TRC 630401
at45db161e.cpp@0:0b6c94a21953, 2020-04-02 (annotated)
- Committer:
- supawat
- Date:
- Thu Apr 02 03:41:57 2020 +0000
- Revision:
- 0:0b6c94a21953
VMS3GTRC vers. 630401
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
supawat | 0:0b6c94a21953 | 1 | #include "at45db161e.h" |
supawat | 0:0b6c94a21953 | 2 | |
supawat | 0:0b6c94a21953 | 3 | //extern Serial debug_pc; |
supawat | 0:0b6c94a21953 | 4 | |
supawat | 0:0b6c94a21953 | 5 | ATD45DB161E::ATD45DB161E(PinName mosi, PinName miso, PinName clk, PinName cs) |
supawat | 0:0b6c94a21953 | 6 | : _spi(mosi, miso, clk), _cs(cs) {} |
supawat | 0:0b6c94a21953 | 7 | |
supawat | 0:0b6c94a21953 | 8 | ATD45DB161E::ATD45DB161E(SPI &spi, PinName cs) |
supawat | 0:0b6c94a21953 | 9 | : _spi(spi), _cs(cs) {} |
supawat | 0:0b6c94a21953 | 10 | /** Setup SPI **/ |
supawat | 0:0b6c94a21953 | 11 | void ATD45DB161E::initial_chip(void) |
supawat | 0:0b6c94a21953 | 12 | { |
supawat | 0:0b6c94a21953 | 13 | _spi.format(8,0); |
supawat | 0:0b6c94a21953 | 14 | _spi.frequency(16000000); |
supawat | 0:0b6c94a21953 | 15 | _set_pageszie_to_binary(); |
supawat | 0:0b6c94a21953 | 16 | _wake_flag = true; |
supawat | 0:0b6c94a21953 | 17 | _deepsleep_flag = false; |
supawat | 0:0b6c94a21953 | 18 | _udeepsleep_flag = false; |
supawat | 0:0b6c94a21953 | 19 | } |
supawat | 0:0b6c94a21953 | 20 | |
supawat | 0:0b6c94a21953 | 21 | void ATD45DB161E::_select() { |
supawat | 0:0b6c94a21953 | 22 | // ensure that the SPI port is set up correctly still |
supawat | 0:0b6c94a21953 | 23 | // This allows SPI channel sharing |
supawat | 0:0b6c94a21953 | 24 | _spi.format(8,0); |
supawat | 0:0b6c94a21953 | 25 | _spi.frequency(16000000); |
supawat | 0:0b6c94a21953 | 26 | _cs = 0; |
supawat | 0:0b6c94a21953 | 27 | } |
supawat | 0:0b6c94a21953 | 28 | |
supawat | 0:0b6c94a21953 | 29 | /* |
supawat | 0:0b6c94a21953 | 30 | * Deselect simply returns nCS to high |
supawat | 0:0b6c94a21953 | 31 | */ |
supawat | 0:0b6c94a21953 | 32 | void ATD45DB161E::_deselect() { |
supawat | 0:0b6c94a21953 | 33 | _cs = 1; |
supawat | 0:0b6c94a21953 | 34 | } |
supawat | 0:0b6c94a21953 | 35 | |
supawat | 0:0b6c94a21953 | 36 | /* |
supawat | 0:0b6c94a21953 | 37 | * Sends the three lest significant bytes of the supplied address |
supawat | 0:0b6c94a21953 | 38 | */ |
supawat | 0:0b6c94a21953 | 39 | |
supawat | 0:0b6c94a21953 | 40 | void ATD45DB161E::_sendaddr (unsigned int address) { |
supawat | 0:0b6c94a21953 | 41 | _spi.write(address >> 16); |
supawat | 0:0b6c94a21953 | 42 | _spi.write(address >> 8); |
supawat | 0:0b6c94a21953 | 43 | _spi.write(address); |
supawat | 0:0b6c94a21953 | 44 | } |
supawat | 0:0b6c94a21953 | 45 | |
supawat | 0:0b6c94a21953 | 46 | /** |
supawat | 0:0b6c94a21953 | 47 | * Set page size of the flash chip into deep power down mode. |
supawat | 0:0b6c94a21953 | 48 | **/ |
supawat | 0:0b6c94a21953 | 49 | void ATD45DB161E::_set_pageszie_to_binary(void) |
supawat | 0:0b6c94a21953 | 50 | { |
supawat | 0:0b6c94a21953 | 51 | _pollbusy(); // make sure flash isn't already in busy. |
supawat | 0:0b6c94a21953 | 52 | _select(); |
supawat | 0:0b6c94a21953 | 53 | _spi.write(0x3d); |
supawat | 0:0b6c94a21953 | 54 | _spi.write(0x2a); |
supawat | 0:0b6c94a21953 | 55 | _spi.write(0x80); |
supawat | 0:0b6c94a21953 | 56 | _spi.write(0xa6); |
supawat | 0:0b6c94a21953 | 57 | _deselect(); |
supawat | 0:0b6c94a21953 | 58 | _pollbusy(); // waitting for the operation complete. |
supawat | 0:0b6c94a21953 | 59 | } |
supawat | 0:0b6c94a21953 | 60 | |
supawat | 0:0b6c94a21953 | 61 | |
supawat | 0:0b6c94a21953 | 62 | /* |
supawat | 0:0b6c94a21953 | 63 | * return the Status |
supawat | 0:0b6c94a21953 | 64 | */ |
supawat | 0:0b6c94a21953 | 65 | |
supawat | 0:0b6c94a21953 | 66 | int ATD45DB161E::ReadStatusRegister(void) { |
supawat | 0:0b6c94a21953 | 67 | int status = 0; |
supawat | 0:0b6c94a21953 | 68 | _select(); |
supawat | 0:0b6c94a21953 | 69 | _spi.write(0xd7); |
supawat | 0:0b6c94a21953 | 70 | status = _spi.write(0x00); |
supawat | 0:0b6c94a21953 | 71 | _deselect(); |
supawat | 0:0b6c94a21953 | 72 | return status; |
supawat | 0:0b6c94a21953 | 73 | } |
supawat | 0:0b6c94a21953 | 74 | |
supawat | 0:0b6c94a21953 | 75 | /* |
supawat | 0:0b6c94a21953 | 76 | * Make sure the Flash isnt already doing something |
supawat | 0:0b6c94a21953 | 77 | */ |
supawat | 0:0b6c94a21953 | 78 | void ATD45DB161E::_pollbusy() { |
supawat | 0:0b6c94a21953 | 79 | volatile int busy = 1; |
supawat | 0:0b6c94a21953 | 80 | while (busy) { |
supawat | 0:0b6c94a21953 | 81 | if(!_wake_flag) |
supawat | 0:0b6c94a21953 | 82 | { |
supawat | 0:0b6c94a21953 | 83 | if(_deepsleep_flag) DeepPowerDown(false); |
supawat | 0:0b6c94a21953 | 84 | else if(_udeepsleep_flag) UltraDeepPowerDown(false); |
supawat | 0:0b6c94a21953 | 85 | } |
supawat | 0:0b6c94a21953 | 86 | // if bit 7 is set, we can proceed |
supawat | 0:0b6c94a21953 | 87 | if ( ReadStatusRegister() & 0x80 ) { |
supawat | 0:0b6c94a21953 | 88 | busy = 0;} |
supawat | 0:0b6c94a21953 | 89 | } |
supawat | 0:0b6c94a21953 | 90 | } |
supawat | 0:0b6c94a21953 | 91 | |
supawat | 0:0b6c94a21953 | 92 | void ATD45DB161E::pollbusy() { |
supawat | 0:0b6c94a21953 | 93 | _pollbusy(); |
supawat | 0:0b6c94a21953 | 94 | } |
supawat | 0:0b6c94a21953 | 95 | |
supawat | 0:0b6c94a21953 | 96 | /** |
supawat | 0:0b6c94a21953 | 97 | * Read Manufacturer and Device ID |
supawat | 0:0b6c94a21953 | 98 | * @note if id.extendedInfoLength is not equal to zero, |
supawat | 0:0b6c94a21953 | 99 | * successive calls to spi_transfer(0xff) will return |
supawat | 0:0b6c94a21953 | 100 | * the extended device information string bytes. |
supawat | 0:0b6c94a21953 | 101 | * @param id Pointer to the ID structure to initialize |
supawat | 0:0b6c94a21953 | 102 | **/ |
supawat | 0:0b6c94a21953 | 103 | void ATD45DB161E::ReadManufacturerAndDeviceID(struct flash_id *id) |
supawat | 0:0b6c94a21953 | 104 | { |
supawat | 0:0b6c94a21953 | 105 | _pollbusy(); // make sure flash isn't already in busy. |
supawat | 0:0b6c94a21953 | 106 | _select(); |
supawat | 0:0b6c94a21953 | 107 | /* Send status read command */ |
supawat | 0:0b6c94a21953 | 108 | _spi.write(0x9f); |
supawat | 0:0b6c94a21953 | 109 | /* Manufacturer ID */ |
supawat | 0:0b6c94a21953 | 110 | id->manufacturer = _spi.write(0x00); |
supawat | 0:0b6c94a21953 | 111 | /* Device ID (part 1) */ |
supawat | 0:0b6c94a21953 | 112 | id->device[0] = _spi.write(0x00); |
supawat | 0:0b6c94a21953 | 113 | /* Device ID (part 2) */ |
supawat | 0:0b6c94a21953 | 114 | id->device[1] = _spi.write(0x00); |
supawat | 0:0b6c94a21953 | 115 | /* Extended Device Information String Length */ |
supawat | 0:0b6c94a21953 | 116 | id->extendedInfoLength = _spi.write(0x00); |
supawat | 0:0b6c94a21953 | 117 | _deselect(); |
supawat | 0:0b6c94a21953 | 118 | } |
supawat | 0:0b6c94a21953 | 119 | |
supawat | 0:0b6c94a21953 | 120 | /** |
supawat | 0:0b6c94a21953 | 121 | * Main Memory Page Read. |
supawat | 0:0b6c94a21953 | 122 | * A main memory page read allows the user to read data directly from |
supawat | 0:0b6c94a21953 | 123 | * any one of the 4096 pages in the main memory, bypassing both of the |
supawat | 0:0b6c94a21953 | 124 | * data buffers and leaving the contents of the buffers unchanged. |
supawat | 0:0b6c94a21953 | 125 | * |
supawat | 0:0b6c94a21953 | 126 | * @param page: Page of the main memory to read |
supawat | 0:0b6c94a21953 | 127 | * @param offset: Starting byte address within the page |
supawat | 0:0b6c94a21953 | 128 | * @param *data: Data buffer to be return the value in flash memory |
supawat | 0:0b6c94a21953 | 129 | * @param len: Lenght of data that you want to read |
supawat | 0:0b6c94a21953 | 130 | * Note: When the end of a page in main memory is reached, |
supawat | 0:0b6c94a21953 | 131 | the device will continue reading back at the beginning |
supawat | 0:0b6c94a21953 | 132 | of the same page. |
supawat | 0:0b6c94a21953 | 133 | **/ |
supawat | 0:0b6c94a21953 | 134 | void ATD45DB161E::PageRead(unsigned int page,unsigned int offset,unsigned char *data,unsigned int len) |
supawat | 0:0b6c94a21953 | 135 | { |
supawat | 0:0b6c94a21953 | 136 | unsigned int address,i; |
supawat | 0:0b6c94a21953 | 137 | |
supawat | 0:0b6c94a21953 | 138 | address = (page<<9)|offset; |
supawat | 0:0b6c94a21953 | 139 | |
supawat | 0:0b6c94a21953 | 140 | _pollbusy(); // make sure flash isn't already in busy. |
supawat | 0:0b6c94a21953 | 141 | _select(); |
supawat | 0:0b6c94a21953 | 142 | |
supawat | 0:0b6c94a21953 | 143 | /* Send opcode */ |
supawat | 0:0b6c94a21953 | 144 | _spi.write(0xd2); |
supawat | 0:0b6c94a21953 | 145 | |
supawat | 0:0b6c94a21953 | 146 | _sendaddr(address); // send three address byte |
supawat | 0:0b6c94a21953 | 147 | |
supawat | 0:0b6c94a21953 | 148 | /* 4 "don't care" bytes */ |
supawat | 0:0b6c94a21953 | 149 | _spi.write(0x00); |
supawat | 0:0b6c94a21953 | 150 | _spi.write(0x00); |
supawat | 0:0b6c94a21953 | 151 | _spi.write(0x00); |
supawat | 0:0b6c94a21953 | 152 | _spi.write(0x00); |
supawat | 0:0b6c94a21953 | 153 | |
supawat | 0:0b6c94a21953 | 154 | for(i=0;i<len;i++) |
supawat | 0:0b6c94a21953 | 155 | { |
supawat | 0:0b6c94a21953 | 156 | *data++ = _spi.write(0x00); |
supawat | 0:0b6c94a21953 | 157 | } |
supawat | 0:0b6c94a21953 | 158 | _deselect(); |
supawat | 0:0b6c94a21953 | 159 | } |
supawat | 0:0b6c94a21953 | 160 | |
supawat | 0:0b6c94a21953 | 161 | /** |
supawat | 0:0b6c94a21953 | 162 | * Continuous Array Read in low power mode. |
supawat | 0:0b6c94a21953 | 163 | * Continuous Array Read in low power mode allows the user to read data |
supawat | 0:0b6c94a21953 | 164 | * directly from any address in the main memory, bypassing both of the |
supawat | 0:0b6c94a21953 | 165 | * data buffers and leaving the contents of the buffers unchanged. |
supawat | 0:0b6c94a21953 | 166 | * |
supawat | 0:0b6c94a21953 | 167 | * @param page: Page of the main memory to read |
supawat | 0:0b6c94a21953 | 168 | * @param addr_st: Starting byte address within the main memory |
supawat | 0:0b6c94a21953 | 169 | * @param *data: Data buffer to be return the value in flash memory |
supawat | 0:0b6c94a21953 | 170 | * @param len: Lenght of data that you want to read |
supawat | 0:0b6c94a21953 | 171 | * Note: When the end of a page in main memory is reached, the device will |
supawat | 0:0b6c94a21953 | 172 | continue reading at the beginning of the next page with no delays |
supawat | 0:0b6c94a21953 | 173 | incurred during the page boundary crossover. |
supawat | 0:0b6c94a21953 | 174 | **/ |
supawat | 0:0b6c94a21953 | 175 | void ATD45DB161E::ContinuousArrayRead(unsigned int addr_st,unsigned char *data,unsigned int len) |
supawat | 0:0b6c94a21953 | 176 | { |
supawat | 0:0b6c94a21953 | 177 | unsigned int i; |
supawat | 0:0b6c94a21953 | 178 | |
supawat | 0:0b6c94a21953 | 179 | _pollbusy(); // make sure flash isn't already in busy. |
supawat | 0:0b6c94a21953 | 180 | _select(); |
supawat | 0:0b6c94a21953 | 181 | |
supawat | 0:0b6c94a21953 | 182 | /* Send opcode */ |
supawat | 0:0b6c94a21953 | 183 | _spi.write(0x01); |
supawat | 0:0b6c94a21953 | 184 | |
supawat | 0:0b6c94a21953 | 185 | _sendaddr(addr_st); // send three address byte |
supawat | 0:0b6c94a21953 | 186 | |
supawat | 0:0b6c94a21953 | 187 | for(i=0;i<len;i++) |
supawat | 0:0b6c94a21953 | 188 | { |
supawat | 0:0b6c94a21953 | 189 | *data++ = _spi.write(0x00); |
supawat | 0:0b6c94a21953 | 190 | } |
supawat | 0:0b6c94a21953 | 191 | _deselect(); |
supawat | 0:0b6c94a21953 | 192 | } |
supawat | 0:0b6c94a21953 | 193 | |
supawat | 0:0b6c94a21953 | 194 | /** |
supawat | 0:0b6c94a21953 | 195 | * Erase the entire chip memory. Sectors proteced or locked down will |
supawat | 0:0b6c94a21953 | 196 | * not be erased. |
supawat | 0:0b6c94a21953 | 197 | **/ |
supawat | 0:0b6c94a21953 | 198 | void ATD45DB161E::ChipErase(void) |
supawat | 0:0b6c94a21953 | 199 | { |
supawat | 0:0b6c94a21953 | 200 | _pollbusy(); // make sure flash isn't already in busy. |
supawat | 0:0b6c94a21953 | 201 | |
supawat | 0:0b6c94a21953 | 202 | // There are errata on this. For now, do itthe long way :-( |
supawat | 0:0b6c94a21953 | 203 | _select(); |
supawat | 0:0b6c94a21953 | 204 | // 4 byte command sequence |
supawat | 0:0b6c94a21953 | 205 | _spi.write(0xc7); |
supawat | 0:0b6c94a21953 | 206 | _spi.write(0x94); |
supawat | 0:0b6c94a21953 | 207 | _spi.write(0x80); |
supawat | 0:0b6c94a21953 | 208 | _spi.write(0x9a); |
supawat | 0:0b6c94a21953 | 209 | _deselect(); |
supawat | 0:0b6c94a21953 | 210 | |
supawat | 0:0b6c94a21953 | 211 | _pollbusy(); // waiting for chip erase |
supawat | 0:0b6c94a21953 | 212 | } |
supawat | 0:0b6c94a21953 | 213 | |
supawat | 0:0b6c94a21953 | 214 | /** |
supawat | 0:0b6c94a21953 | 215 | * Erase a page in the main memory array. |
supawat | 0:0b6c94a21953 | 216 | * @param page: Number of page that you want to erase |
supawat | 0:0b6c94a21953 | 217 | **/ |
supawat | 0:0b6c94a21953 | 218 | void ATD45DB161E::PageErase(unsigned int page) |
supawat | 0:0b6c94a21953 | 219 | { |
supawat | 0:0b6c94a21953 | 220 | unsigned int address; |
supawat | 0:0b6c94a21953 | 221 | |
supawat | 0:0b6c94a21953 | 222 | address = page<<9; |
supawat | 0:0b6c94a21953 | 223 | |
supawat | 0:0b6c94a21953 | 224 | _pollbusy(); // make sure flash isn't already in busy. |
supawat | 0:0b6c94a21953 | 225 | |
supawat | 0:0b6c94a21953 | 226 | // There are errata on this. For now, do itthe long way :-( |
supawat | 0:0b6c94a21953 | 227 | _select(); |
supawat | 0:0b6c94a21953 | 228 | _spi.write(0x81); // Command for page erase |
supawat | 0:0b6c94a21953 | 229 | _sendaddr(address); // Send 3 address bytes |
supawat | 0:0b6c94a21953 | 230 | _deselect(); |
supawat | 0:0b6c94a21953 | 231 | |
supawat | 0:0b6c94a21953 | 232 | _pollbusy(); // waiting for page erase |
supawat | 0:0b6c94a21953 | 233 | } |
supawat | 0:0b6c94a21953 | 234 | |
supawat | 0:0b6c94a21953 | 235 | /** |
supawat | 0:0b6c94a21953 | 236 | * This is a combination of Buffer Write and Buffer to Page with |
supawat | 0:0b6c94a21953 | 237 | * Built-in Erase. |
supawat | 0:0b6c94a21953 | 238 | * @param page Page where the content of the buffer will transfered |
supawat | 0:0b6c94a21953 | 239 | * @param offset Starting byte address within the buffer |
supawat | 0:0b6c94a21953 | 240 | * @param bufferNum Buffer to use (1 or 2) |
supawat | 0:0b6c94a21953 | 241 | * @param *data: Data that you want to write into flash memory |
supawat | 0:0b6c94a21953 | 242 | * @param len: Lenght of data that you want to write |
supawat | 0:0b6c94a21953 | 243 | * Note: If the end of the buffer is reached, the device will |
supawat | 0:0b6c94a21953 | 244 | wrap around back to the beginning of the buffer. |
supawat | 0:0b6c94a21953 | 245 | **/ |
supawat | 0:0b6c94a21953 | 246 | void ATD45DB161E::PageWriteThroughBuffer(unsigned int page, unsigned int offset, unsigned char bufferNum,unsigned char *data,unsigned int len) |
supawat | 0:0b6c94a21953 | 247 | { |
supawat | 0:0b6c94a21953 | 248 | unsigned int address,i; |
supawat | 0:0b6c94a21953 | 249 | unsigned char opcode; |
supawat | 0:0b6c94a21953 | 250 | |
supawat | 0:0b6c94a21953 | 251 | address = (page<<9)|offset; |
supawat | 0:0b6c94a21953 | 252 | // select opcode which buffer have been used |
supawat | 0:0b6c94a21953 | 253 | if (bufferNum == 1) |
supawat | 0:0b6c94a21953 | 254 | opcode = 0x82; |
supawat | 0:0b6c94a21953 | 255 | else |
supawat | 0:0b6c94a21953 | 256 | opcode = 0x85; |
supawat | 0:0b6c94a21953 | 257 | |
supawat | 0:0b6c94a21953 | 258 | _pollbusy(); // make sure flash isn't already in busy. |
supawat | 0:0b6c94a21953 | 259 | _select(); |
supawat | 0:0b6c94a21953 | 260 | |
supawat | 0:0b6c94a21953 | 261 | /* Send opcode */ |
supawat | 0:0b6c94a21953 | 262 | _spi.write(opcode); |
supawat | 0:0b6c94a21953 | 263 | |
supawat | 0:0b6c94a21953 | 264 | /* Address */ |
supawat | 0:0b6c94a21953 | 265 | _sendaddr(address); // send three address byte |
supawat | 0:0b6c94a21953 | 266 | for(i=0;i<len;i++) |
supawat | 0:0b6c94a21953 | 267 | { |
supawat | 0:0b6c94a21953 | 268 | _spi.write(*data++); |
supawat | 0:0b6c94a21953 | 269 | } |
supawat | 0:0b6c94a21953 | 270 | _deselect(); |
supawat | 0:0b6c94a21953 | 271 | _pollbusy(); // waiting for programming from buffer into main memory |
supawat | 0:0b6c94a21953 | 272 | } |
supawat | 0:0b6c94a21953 | 273 | |
supawat | 0:0b6c94a21953 | 274 | /** |
supawat | 0:0b6c94a21953 | 275 | * This is a combination of the Main Memory Page to Buffer Transfer, Buffer Write, |
supawat | 0:0b6c94a21953 | 276 | * and Buffer to Main Memory Page Program with Built-in Erase commands. |
supawat | 0:0b6c94a21953 | 277 | * @param addr_st Starting byte address of the flash chip |
supawat | 0:0b6c94a21953 | 278 | * @param bufferNum Buffer to use (1 or 2) |
supawat | 0:0b6c94a21953 | 279 | * @param *data: Data that you want to write into flash memory |
supawat | 0:0b6c94a21953 | 280 | * @param len: Lenght of data that you want to write |
supawat | 0:0b6c94a21953 | 281 | * Note: If the end of the buffer is reached, the device will |
supawat | 0:0b6c94a21953 | 282 | wrap around back to the beginning of the buffer. |
supawat | 0:0b6c94a21953 | 283 | **/ |
supawat | 0:0b6c94a21953 | 284 | void ATD45DB161E::ContinuousWriteThroughBuffer(unsigned int addr_st, unsigned char bufferNum,unsigned char *data,unsigned int len) |
supawat | 0:0b6c94a21953 | 285 | { |
supawat | 0:0b6c94a21953 | 286 | unsigned int i,data_len; |
supawat | 0:0b6c94a21953 | 287 | unsigned int page_start,page_end; |
supawat | 0:0b6c94a21953 | 288 | unsigned int page_count,dif_page; |
supawat | 0:0b6c94a21953 | 289 | unsigned char opcode; |
supawat | 0:0b6c94a21953 | 290 | |
supawat | 0:0b6c94a21953 | 291 | page_start = addr_st>>9; |
supawat | 0:0b6c94a21953 | 292 | page_end = (addr_st+len)>>9; |
supawat | 0:0b6c94a21953 | 293 | dif_page = page_end - page_start; |
supawat | 0:0b6c94a21953 | 294 | |
supawat | 0:0b6c94a21953 | 295 | // select opcode which buffer have been used |
supawat | 0:0b6c94a21953 | 296 | if (bufferNum == 1) |
supawat | 0:0b6c94a21953 | 297 | opcode = 0x58; |
supawat | 0:0b6c94a21953 | 298 | else |
supawat | 0:0b6c94a21953 | 299 | opcode = 0x59; |
supawat | 0:0b6c94a21953 | 300 | |
supawat | 0:0b6c94a21953 | 301 | for(page_count=0;page_count<=dif_page;page_count++) |
supawat | 0:0b6c94a21953 | 302 | { |
supawat | 0:0b6c94a21953 | 303 | if(512-(addr_st&0x1ff)<len) data_len = 512-(addr_st&0x1ff); |
supawat | 0:0b6c94a21953 | 304 | else data_len = len; |
supawat | 0:0b6c94a21953 | 305 | _pollbusy(); // make sure flash isn't already in busy. |
supawat | 0:0b6c94a21953 | 306 | _select(); |
supawat | 0:0b6c94a21953 | 307 | _spi.write(opcode); /* Send opcode */ |
supawat | 0:0b6c94a21953 | 308 | _sendaddr(addr_st); // send three address byte |
supawat | 0:0b6c94a21953 | 309 | for(i=0;i<data_len;i++) |
supawat | 0:0b6c94a21953 | 310 | { |
supawat | 0:0b6c94a21953 | 311 | _spi.write(*data++); |
supawat | 0:0b6c94a21953 | 312 | } |
supawat | 0:0b6c94a21953 | 313 | _deselect(); |
supawat | 0:0b6c94a21953 | 314 | _pollbusy(); // waiting for programming from buffer into main memory |
supawat | 0:0b6c94a21953 | 315 | addr_st = addr_st + data_len; |
supawat | 0:0b6c94a21953 | 316 | len = len - data_len; |
supawat | 0:0b6c94a21953 | 317 | } |
supawat | 0:0b6c94a21953 | 318 | } |
supawat | 0:0b6c94a21953 | 319 | |
supawat | 0:0b6c94a21953 | 320 | /** |
supawat | 0:0b6c94a21953 | 321 | * Read the content of one of the SRAM data buffers (in low or high speed mode). |
supawat | 0:0b6c94a21953 | 322 | * @param bufferNum Buffer to read (1 or 2) |
supawat | 0:0b6c94a21953 | 323 | * @param offset Starting byte within the buffer |
supawat | 0:0b6c94a21953 | 324 | * @param low If true the read operation will be performed in low speed mode (and in high speed mode if it's false). |
supawat | 0:0b6c94a21953 | 325 | * @param *data: Data that you want to read from flash memory |
supawat | 0:0b6c94a21953 | 326 | * @param len: Lenght of data that you want to read |
supawat | 0:0b6c94a21953 | 327 | **/ |
supawat | 0:0b6c94a21953 | 328 | void ATD45DB161E::BufferRead(unsigned char bufferNum, unsigned int offset, unsigned char low,unsigned char *data,unsigned int len) |
supawat | 0:0b6c94a21953 | 329 | { |
supawat | 0:0b6c94a21953 | 330 | unsigned int i; |
supawat | 0:0b6c94a21953 | 331 | unsigned char opcode; |
supawat | 0:0b6c94a21953 | 332 | |
supawat | 0:0b6c94a21953 | 333 | /* Send opcode */ |
supawat | 0:0b6c94a21953 | 334 | if(bufferNum == 1) |
supawat | 0:0b6c94a21953 | 335 | { |
supawat | 0:0b6c94a21953 | 336 | if(low) |
supawat | 0:0b6c94a21953 | 337 | opcode = 0xd1; // opcode for read buffer 1 in low speed |
supawat | 0:0b6c94a21953 | 338 | else |
supawat | 0:0b6c94a21953 | 339 | opcode = 0xd4; // opcode for read buffer 1 |
supawat | 0:0b6c94a21953 | 340 | } |
supawat | 0:0b6c94a21953 | 341 | else |
supawat | 0:0b6c94a21953 | 342 | { |
supawat | 0:0b6c94a21953 | 343 | if(low) |
supawat | 0:0b6c94a21953 | 344 | opcode = 0xd3; // opcode for read buffer 1 in low speed |
supawat | 0:0b6c94a21953 | 345 | else |
supawat | 0:0b6c94a21953 | 346 | opcode = 0xd6; // opcode for read buffer 2 |
supawat | 0:0b6c94a21953 | 347 | } |
supawat | 0:0b6c94a21953 | 348 | _pollbusy(); // make sure flash isn't already in busy. |
supawat | 0:0b6c94a21953 | 349 | _select(); |
supawat | 0:0b6c94a21953 | 350 | /* Send opcode */ |
supawat | 0:0b6c94a21953 | 351 | _spi.write(opcode); |
supawat | 0:0b6c94a21953 | 352 | _sendaddr(offset); // send three address byte |
supawat | 0:0b6c94a21953 | 353 | if(!low) |
supawat | 0:0b6c94a21953 | 354 | _spi.write(0x00); // send dummy byte |
supawat | 0:0b6c94a21953 | 355 | for(i=0;i<len;i++) |
supawat | 0:0b6c94a21953 | 356 | { |
supawat | 0:0b6c94a21953 | 357 | *data++ = _spi.write(0x00); |
supawat | 0:0b6c94a21953 | 358 | } |
supawat | 0:0b6c94a21953 | 359 | _deselect(); |
supawat | 0:0b6c94a21953 | 360 | } |
supawat | 0:0b6c94a21953 | 361 | |
supawat | 0:0b6c94a21953 | 362 | /** |
supawat | 0:0b6c94a21953 | 363 | * Write data to one of the SRAM data buffers. Any further call to |
supawat | 0:0b6c94a21953 | 364 | * spi_tranfer will return bytes contained in the data buffer until |
supawat | 0:0b6c94a21953 | 365 | * a low-to-high transition is detected on the CS pin. If the end of |
supawat | 0:0b6c94a21953 | 366 | * the data buffer is reached, the device will wrap around back to the |
supawat | 0:0b6c94a21953 | 367 | * beginning of the buffer. |
supawat | 0:0b6c94a21953 | 368 | * @param bufferNum Buffer to read (1 or 2) |
supawat | 0:0b6c94a21953 | 369 | * @param offset Starting byte within the buffer |
supawat | 0:0b6c94a21953 | 370 | * @param *data: Data that you want to write into flash memory |
supawat | 0:0b6c94a21953 | 371 | * @param len: Lenght of data that you want to write |
supawat | 0:0b6c94a21953 | 372 | **/ |
supawat | 0:0b6c94a21953 | 373 | void ATD45DB161E::BufferWrite(unsigned char bufferNum, unsigned int offset,unsigned char *data,unsigned int len) |
supawat | 0:0b6c94a21953 | 374 | { |
supawat | 0:0b6c94a21953 | 375 | unsigned int i; |
supawat | 0:0b6c94a21953 | 376 | unsigned char opcode; |
supawat | 0:0b6c94a21953 | 377 | |
supawat | 0:0b6c94a21953 | 378 | if (bufferNum == 1) |
supawat | 0:0b6c94a21953 | 379 | opcode = 0x84; |
supawat | 0:0b6c94a21953 | 380 | else |
supawat | 0:0b6c94a21953 | 381 | opcode = 0x87; |
supawat | 0:0b6c94a21953 | 382 | _pollbusy(); // make sure flash isn't already in busy. |
supawat | 0:0b6c94a21953 | 383 | _select(); |
supawat | 0:0b6c94a21953 | 384 | |
supawat | 0:0b6c94a21953 | 385 | /* Send opcode */ |
supawat | 0:0b6c94a21953 | 386 | _spi.write(opcode); |
supawat | 0:0b6c94a21953 | 387 | _sendaddr(offset); // send three address byte |
supawat | 0:0b6c94a21953 | 388 | for(i=0;i<len;i++) |
supawat | 0:0b6c94a21953 | 389 | { |
supawat | 0:0b6c94a21953 | 390 | _spi.write(*data++); |
supawat | 0:0b6c94a21953 | 391 | } |
supawat | 0:0b6c94a21953 | 392 | _deselect(); |
supawat | 0:0b6c94a21953 | 393 | _pollbusy(); // waiting for operation complete. |
supawat | 0:0b6c94a21953 | 394 | } |
supawat | 0:0b6c94a21953 | 395 | |
supawat | 0:0b6c94a21953 | 396 | /** |
supawat | 0:0b6c94a21953 | 397 | * Transfer data from buffer 1 or 2 to main memory page. |
supawat | 0:0b6c94a21953 | 398 | * @param bufferNum Buffer to use (1 or 2) |
supawat | 0:0b6c94a21953 | 399 | * @param page Page where the content of the buffer will transfered |
supawat | 0:0b6c94a21953 | 400 | * @param erase If set the page will be first erased before the buffer transfer. |
supawat | 0:0b6c94a21953 | 401 | * @note If erase is equal to zero, the page must have been previously erased using one of the erase command (Page or Block Erase). |
supawat | 0:0b6c94a21953 | 402 | **/ |
supawat | 0:0b6c94a21953 | 403 | void ATD45DB161E::BufferToPage(unsigned char bufferNum, unsigned int page, unsigned char erase) |
supawat | 0:0b6c94a21953 | 404 | { |
supawat | 0:0b6c94a21953 | 405 | unsigned int address; |
supawat | 0:0b6c94a21953 | 406 | unsigned char opcode; |
supawat | 0:0b6c94a21953 | 407 | |
supawat | 0:0b6c94a21953 | 408 | address = page<<9; |
supawat | 0:0b6c94a21953 | 409 | if(erase) |
supawat | 0:0b6c94a21953 | 410 | { |
supawat | 0:0b6c94a21953 | 411 | if (bufferNum == 1) |
supawat | 0:0b6c94a21953 | 412 | opcode = 0x83; |
supawat | 0:0b6c94a21953 | 413 | else |
supawat | 0:0b6c94a21953 | 414 | opcode = 0x86; |
supawat | 0:0b6c94a21953 | 415 | } |
supawat | 0:0b6c94a21953 | 416 | else |
supawat | 0:0b6c94a21953 | 417 | { |
supawat | 0:0b6c94a21953 | 418 | if (bufferNum == 1) |
supawat | 0:0b6c94a21953 | 419 | opcode = 0x88; |
supawat | 0:0b6c94a21953 | 420 | else |
supawat | 0:0b6c94a21953 | 421 | opcode = 0x89; |
supawat | 0:0b6c94a21953 | 422 | } |
supawat | 0:0b6c94a21953 | 423 | |
supawat | 0:0b6c94a21953 | 424 | _pollbusy(); // make sure flash isn't already in busy. |
supawat | 0:0b6c94a21953 | 425 | _select(); |
supawat | 0:0b6c94a21953 | 426 | |
supawat | 0:0b6c94a21953 | 427 | /* Send opcode */ |
supawat | 0:0b6c94a21953 | 428 | _spi.write(opcode); |
supawat | 0:0b6c94a21953 | 429 | _sendaddr(address); // send three address byte |
supawat | 0:0b6c94a21953 | 430 | _deselect(); |
supawat | 0:0b6c94a21953 | 431 | |
supawat | 0:0b6c94a21953 | 432 | _pollbusy(); // Wait for buffer write to main memory page |
supawat | 0:0b6c94a21953 | 433 | } |
supawat | 0:0b6c94a21953 | 434 | |
supawat | 0:0b6c94a21953 | 435 | /** |
supawat | 0:0b6c94a21953 | 436 | * Transfer data from main memory page to buffer 1 or 2. |
supawat | 0:0b6c94a21953 | 437 | * @param page Page where the content of the main memory page will transfered |
supawat | 0:0b6c94a21953 | 438 | * @param bufferNum Buffer to use (1 or 2) |
supawat | 0:0b6c94a21953 | 439 | **/ |
supawat | 0:0b6c94a21953 | 440 | void ATD45DB161E::PageToBuffer(unsigned int page, unsigned char bufferNum) |
supawat | 0:0b6c94a21953 | 441 | { |
supawat | 0:0b6c94a21953 | 442 | unsigned int address; |
supawat | 0:0b6c94a21953 | 443 | unsigned char opcode; |
supawat | 0:0b6c94a21953 | 444 | |
supawat | 0:0b6c94a21953 | 445 | address = page<<9; |
supawat | 0:0b6c94a21953 | 446 | |
supawat | 0:0b6c94a21953 | 447 | if (bufferNum == 1) opcode = 0x53; |
supawat | 0:0b6c94a21953 | 448 | else opcode = 0x55; |
supawat | 0:0b6c94a21953 | 449 | |
supawat | 0:0b6c94a21953 | 450 | _pollbusy(); // make sure flash isn't already in busy. |
supawat | 0:0b6c94a21953 | 451 | _select(); |
supawat | 0:0b6c94a21953 | 452 | |
supawat | 0:0b6c94a21953 | 453 | /* Send opcode */ |
supawat | 0:0b6c94a21953 | 454 | _spi.write(opcode); |
supawat | 0:0b6c94a21953 | 455 | _sendaddr(address); // send three address byte |
supawat | 0:0b6c94a21953 | 456 | _deselect(); |
supawat | 0:0b6c94a21953 | 457 | |
supawat | 0:0b6c94a21953 | 458 | _pollbusy(); // Wait for buffer write to main memory page |
supawat | 0:0b6c94a21953 | 459 | } |
supawat | 0:0b6c94a21953 | 460 | |
supawat | 0:0b6c94a21953 | 461 | /** |
supawat | 0:0b6c94a21953 | 462 | * Enter the chip into deep power down mode. |
supawat | 0:0b6c94a21953 | 463 | * @param deep_down_onoff: If set the chip will be entered into deep power down mode. Otherwise, wake up command will be sent to the chip. |
supawat | 0:0b6c94a21953 | 464 | **/ |
supawat | 0:0b6c94a21953 | 465 | void ATD45DB161E::DeepPowerDown(unsigned char deep_down_onoff) |
supawat | 0:0b6c94a21953 | 466 | { |
supawat | 0:0b6c94a21953 | 467 | if(deep_down_onoff) |
supawat | 0:0b6c94a21953 | 468 | { |
supawat | 0:0b6c94a21953 | 469 | _pollbusy(); // make sure flash isn't already in busy. |
supawat | 0:0b6c94a21953 | 470 | _select(); |
supawat | 0:0b6c94a21953 | 471 | _spi.write(0xb9); |
supawat | 0:0b6c94a21953 | 472 | _deselect(); |
supawat | 0:0b6c94a21953 | 473 | _wake_flag = false; |
supawat | 0:0b6c94a21953 | 474 | _deepsleep_flag = true; |
supawat | 0:0b6c94a21953 | 475 | wait_us(2); |
supawat | 0:0b6c94a21953 | 476 | } |
supawat | 0:0b6c94a21953 | 477 | else |
supawat | 0:0b6c94a21953 | 478 | { |
supawat | 0:0b6c94a21953 | 479 | _select(); |
supawat | 0:0b6c94a21953 | 480 | _spi.write(0xab); |
supawat | 0:0b6c94a21953 | 481 | _deselect(); |
supawat | 0:0b6c94a21953 | 482 | _wake_flag = true; |
supawat | 0:0b6c94a21953 | 483 | _deepsleep_flag = false; |
supawat | 0:0b6c94a21953 | 484 | wait_us(35); |
supawat | 0:0b6c94a21953 | 485 | } |
supawat | 0:0b6c94a21953 | 486 | } |
supawat | 0:0b6c94a21953 | 487 | |
supawat | 0:0b6c94a21953 | 488 | /** |
supawat | 0:0b6c94a21953 | 489 | * Enter the chip into ultra deep power down mode. |
supawat | 0:0b6c94a21953 | 490 | * @param ultra_deep_down_onoff: If set the chip will be entered into ultra deep power down mode. Otherwise, CS pin will be asseeted for wake up the chip. |
supawat | 0:0b6c94a21953 | 491 | **/ |
supawat | 0:0b6c94a21953 | 492 | void ATD45DB161E::UltraDeepPowerDown(unsigned char ultra_deep_down_onoff) |
supawat | 0:0b6c94a21953 | 493 | { |
supawat | 0:0b6c94a21953 | 494 | if(ultra_deep_down_onoff) |
supawat | 0:0b6c94a21953 | 495 | { |
supawat | 0:0b6c94a21953 | 496 | _pollbusy(); // make sure flash isn't already in busy. |
supawat | 0:0b6c94a21953 | 497 | _select(); |
supawat | 0:0b6c94a21953 | 498 | _spi.write(0x79); |
supawat | 0:0b6c94a21953 | 499 | _deselect(); |
supawat | 0:0b6c94a21953 | 500 | _wake_flag = false; |
supawat | 0:0b6c94a21953 | 501 | _udeepsleep_flag = true; |
supawat | 0:0b6c94a21953 | 502 | wait_us(4); |
supawat | 0:0b6c94a21953 | 503 | } |
supawat | 0:0b6c94a21953 | 504 | else |
supawat | 0:0b6c94a21953 | 505 | { |
supawat | 0:0b6c94a21953 | 506 | _select(); |
supawat | 0:0b6c94a21953 | 507 | wait_us(1); |
supawat | 0:0b6c94a21953 | 508 | _deselect(); |
supawat | 0:0b6c94a21953 | 509 | wait_us(180); |
supawat | 0:0b6c94a21953 | 510 | _wake_flag = true; |
supawat | 0:0b6c94a21953 | 511 | _udeepsleep_flag = false; |
supawat | 0:0b6c94a21953 | 512 | } |
supawat | 0:0b6c94a21953 | 513 | } |
supawat | 0:0b6c94a21953 | 514 | |
supawat | 0:0b6c94a21953 | 515 | /** |
supawat | 0:0b6c94a21953 | 516 | * Check the chip is wake up. |
supawat | 0:0b6c94a21953 | 517 | * Return true if the chip is wake up. Otherwise, the chip is entered in deep power down or ultra deep power down mode mode. |
supawat | 0:0b6c94a21953 | 518 | **/ |
supawat | 0:0b6c94a21953 | 519 | bool ATD45DB161E::is_it_awake(void) |
supawat | 0:0b6c94a21953 | 520 | { |
supawat | 0:0b6c94a21953 | 521 | return _wake_flag; |
supawat | 0:0b6c94a21953 | 522 | } |