Driver for AT25SF041 SPI Flash Memory, just basic operations
at25sf041.cpp@1:e6ad2967ec95, 2015-09-17 (annotated)
- Committer:
- tpadovani
- Date:
- Thu Sep 17 19:53:27 2015 +0000
- Revision:
- 1:e6ad2967ec95
- Parent:
- 0:9225e2aef6b3
Credits header
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
tpadovani | 1:e6ad2967ec95 | 1 | /** |
tpadovani | 1:e6ad2967ec95 | 2 | * AT45DB161D module for arduino (C) Vincent |
tpadovani | 1:e6ad2967ec95 | 3 | * SPI flash memory |
tpadovani | 1:e6ad2967ec95 | 4 | * http://blog.blockos.org/?p=27 |
tpadovani | 1:e6ad2967ec95 | 5 | * |
tpadovani | 1:e6ad2967ec95 | 6 | * bug fix by todotani |
tpadovani | 1:e6ad2967ec95 | 7 | * http://todotani.cocolog-nifty.com/blog/2009/07/arduino-4cf4.html |
tpadovani | 1:e6ad2967ec95 | 8 | * |
tpadovani | 1:e6ad2967ec95 | 9 | * Modified for mbed, 2011 Suga. |
tpadovani | 1:e6ad2967ec95 | 10 | * |
tpadovani | 1:e6ad2967ec95 | 11 | * Adapted for AT25SF041 SPI flash memory, 2015 tpadovani. |
tpadovani | 1:e6ad2967ec95 | 12 | */ |
tpadovani | 1:e6ad2967ec95 | 13 | |
tpadovani | 0:9225e2aef6b3 | 14 | #include "at25sf041.h" |
tpadovani | 0:9225e2aef6b3 | 15 | |
tpadovani | 0:9225e2aef6b3 | 16 | /** CTOR **/ |
tpadovani | 0:9225e2aef6b3 | 17 | AT25SF041::AT25SF041(PinName mosi, PinName miso, PinName sclk, PinName cs) |
tpadovani | 0:9225e2aef6b3 | 18 | : _spi(mosi, miso, sclk), _cs(cs) |
tpadovani | 0:9225e2aef6b3 | 19 | {} |
tpadovani | 0:9225e2aef6b3 | 20 | |
tpadovani | 0:9225e2aef6b3 | 21 | AT25SF041::AT25SF041(SPI &spi, PinName cs) |
tpadovani | 0:9225e2aef6b3 | 22 | : _spi(spi), _cs(cs) |
tpadovani | 0:9225e2aef6b3 | 23 | {} |
tpadovani | 0:9225e2aef6b3 | 24 | |
tpadovani | 0:9225e2aef6b3 | 25 | /** DTOR **/ |
tpadovani | 0:9225e2aef6b3 | 26 | AT25SF041::~AT25SF041() |
tpadovani | 0:9225e2aef6b3 | 27 | {} |
tpadovani | 0:9225e2aef6b3 | 28 | |
tpadovani | 0:9225e2aef6b3 | 29 | /** Setup SPI and pinout **/ |
tpadovani | 0:9225e2aef6b3 | 30 | void AT25SF041::Init() |
tpadovani | 0:9225e2aef6b3 | 31 | { |
tpadovani | 0:9225e2aef6b3 | 32 | /* Disable device */ |
tpadovani | 0:9225e2aef6b3 | 33 | DF_CS_inactive; |
tpadovani | 0:9225e2aef6b3 | 34 | |
tpadovani | 0:9225e2aef6b3 | 35 | /* Setup SPI */ |
tpadovani | 0:9225e2aef6b3 | 36 | _spi.format(8, 0); |
tpadovani | 0:9225e2aef6b3 | 37 | |
tpadovani | 0:9225e2aef6b3 | 38 | } |
tpadovani | 0:9225e2aef6b3 | 39 | |
tpadovani | 0:9225e2aef6b3 | 40 | /** |
tpadovani | 0:9225e2aef6b3 | 41 | * Read status register |
tpadovani | 0:9225e2aef6b3 | 42 | * @return The content of the status register |
tpadovani | 0:9225e2aef6b3 | 43 | **/ |
tpadovani | 0:9225e2aef6b3 | 44 | uint8_t AT25SF041::ReadStatusRegister(int n) |
tpadovani | 0:9225e2aef6b3 | 45 | { |
tpadovani | 0:9225e2aef6b3 | 46 | uint8_t status; |
tpadovani | 0:9225e2aef6b3 | 47 | |
tpadovani | 0:9225e2aef6b3 | 48 | DF_CS_inactive; |
tpadovani | 0:9225e2aef6b3 | 49 | DF_CS_active; |
tpadovani | 0:9225e2aef6b3 | 50 | |
tpadovani | 0:9225e2aef6b3 | 51 | /* Send status read command */ |
tpadovani | 0:9225e2aef6b3 | 52 | if(n == 1){ |
tpadovani | 0:9225e2aef6b3 | 53 | spi_transfer(READ_STATUS_REGISTER_BYTE_1); |
tpadovani | 0:9225e2aef6b3 | 54 | } else{ |
tpadovani | 0:9225e2aef6b3 | 55 | spi_transfer(READ_STATUS_REGISTER_BYTE_2); |
tpadovani | 0:9225e2aef6b3 | 56 | } |
tpadovani | 0:9225e2aef6b3 | 57 | /* Get result with a dummy write */ |
tpadovani | 0:9225e2aef6b3 | 58 | status = spi_transfer(0x00); |
tpadovani | 0:9225e2aef6b3 | 59 | |
tpadovani | 0:9225e2aef6b3 | 60 | DF_CS_inactive; |
tpadovani | 0:9225e2aef6b3 | 61 | |
tpadovani | 0:9225e2aef6b3 | 62 | return status; |
tpadovani | 0:9225e2aef6b3 | 63 | } |
tpadovani | 0:9225e2aef6b3 | 64 | |
tpadovani | 0:9225e2aef6b3 | 65 | void AT25SF041::WriteEnable() |
tpadovani | 0:9225e2aef6b3 | 66 | { |
tpadovani | 0:9225e2aef6b3 | 67 | DF_CS_inactive; |
tpadovani | 0:9225e2aef6b3 | 68 | DF_CS_active; |
tpadovani | 0:9225e2aef6b3 | 69 | |
tpadovani | 0:9225e2aef6b3 | 70 | spi_transfer(WRITE_ENABLE); |
tpadovani | 0:9225e2aef6b3 | 71 | |
tpadovani | 0:9225e2aef6b3 | 72 | DF_CS_inactive; |
tpadovani | 0:9225e2aef6b3 | 73 | } |
tpadovani | 0:9225e2aef6b3 | 74 | |
tpadovani | 0:9225e2aef6b3 | 75 | void AT25SF041::WriteDisable() |
tpadovani | 0:9225e2aef6b3 | 76 | { |
tpadovani | 0:9225e2aef6b3 | 77 | DF_CS_inactive; |
tpadovani | 0:9225e2aef6b3 | 78 | DF_CS_active; |
tpadovani | 0:9225e2aef6b3 | 79 | |
tpadovani | 0:9225e2aef6b3 | 80 | spi_transfer(WRITE_DISABLE); |
tpadovani | 0:9225e2aef6b3 | 81 | |
tpadovani | 0:9225e2aef6b3 | 82 | DF_CS_inactive; |
tpadovani | 0:9225e2aef6b3 | 83 | } |
tpadovani | 0:9225e2aef6b3 | 84 | |
tpadovani | 0:9225e2aef6b3 | 85 | /** |
tpadovani | 0:9225e2aef6b3 | 86 | * Read Manufacturer and Device ID |
tpadovani | 0:9225e2aef6b3 | 87 | * @note if id.extendedInfoLength is not equal to zero, |
tpadovani | 0:9225e2aef6b3 | 88 | * successive calls to spi_transfer(0xff) will return |
tpadovani | 0:9225e2aef6b3 | 89 | * the extended device information string bytes. |
tpadovani | 0:9225e2aef6b3 | 90 | * @param id Pointer to the ID structure to initialize |
tpadovani | 0:9225e2aef6b3 | 91 | **/ |
tpadovani | 0:9225e2aef6b3 | 92 | void AT25SF041::ReadManufacturerAndDeviceID(struct AT25SF041::ID *id) |
tpadovani | 0:9225e2aef6b3 | 93 | { |
tpadovani | 0:9225e2aef6b3 | 94 | |
tpadovani | 0:9225e2aef6b3 | 95 | DF_CS_inactive; /* Make sure to toggle CS signal in order */ |
tpadovani | 0:9225e2aef6b3 | 96 | DF_CS_active; /* to reset Dataflash command decoder */ |
tpadovani | 0:9225e2aef6b3 | 97 | |
tpadovani | 0:9225e2aef6b3 | 98 | /* Send status read command */ |
tpadovani | 0:9225e2aef6b3 | 99 | spi_transfer(READ_MANUFACTURER_AND_DEVICE_ID); |
tpadovani | 0:9225e2aef6b3 | 100 | |
tpadovani | 0:9225e2aef6b3 | 101 | /* Manufacturer ID */ |
tpadovani | 0:9225e2aef6b3 | 102 | id->manufacturer = spi_transfer(0xff); |
tpadovani | 0:9225e2aef6b3 | 103 | /* Device ID (part 1) */ |
tpadovani | 0:9225e2aef6b3 | 104 | id->device[0] = spi_transfer(0xff); |
tpadovani | 0:9225e2aef6b3 | 105 | /* Device ID (part 2) */ |
tpadovani | 0:9225e2aef6b3 | 106 | id->device[1] = spi_transfer(0xff); |
tpadovani | 0:9225e2aef6b3 | 107 | |
tpadovani | 0:9225e2aef6b3 | 108 | DF_CS_inactive; |
tpadovani | 0:9225e2aef6b3 | 109 | } |
tpadovani | 0:9225e2aef6b3 | 110 | |
tpadovani | 0:9225e2aef6b3 | 111 | void AT25SF041::ReadArray(uint32_t address, uint32_t length, uint8_t *buffer) |
tpadovani | 0:9225e2aef6b3 | 112 | { |
tpadovani | 0:9225e2aef6b3 | 113 | DF_CS_inactive; /* Make sure to toggle CS signal in order */ |
tpadovani | 0:9225e2aef6b3 | 114 | DF_CS_active; /* to reset Dataflash command decoder */ |
tpadovani | 0:9225e2aef6b3 | 115 | |
tpadovani | 0:9225e2aef6b3 | 116 | /* Send opcode */ |
tpadovani | 0:9225e2aef6b3 | 117 | spi_transfer(READ_ARRAY_HF); |
tpadovani | 0:9225e2aef6b3 | 118 | |
tpadovani | 0:9225e2aef6b3 | 119 | /* Address (page | offset) */ |
tpadovani | 0:9225e2aef6b3 | 120 | spi_transfer((uint8_t)((address >> 16) & 0xff)); |
tpadovani | 0:9225e2aef6b3 | 121 | spi_transfer((uint8_t)((address >> 8) & 0xff)); |
tpadovani | 0:9225e2aef6b3 | 122 | spi_transfer((uint8_t)(address & 0xff)); |
tpadovani | 0:9225e2aef6b3 | 123 | spi_transfer(0x00); |
tpadovani | 0:9225e2aef6b3 | 124 | |
tpadovani | 0:9225e2aef6b3 | 125 | for(int i=0; i < length; i++){ |
tpadovani | 0:9225e2aef6b3 | 126 | buffer[i] = spi_transfer(0x00); |
tpadovani | 0:9225e2aef6b3 | 127 | } |
tpadovani | 0:9225e2aef6b3 | 128 | |
tpadovani | 0:9225e2aef6b3 | 129 | } |
tpadovani | 0:9225e2aef6b3 | 130 | |
tpadovani | 0:9225e2aef6b3 | 131 | void AT25SF041::WriteArray(uint32_t address, uint32_t length, uint8_t *buffer){ |
tpadovani | 0:9225e2aef6b3 | 132 | DF_CS_inactive; /* Make sure to toggle CS signal in order */ |
tpadovani | 0:9225e2aef6b3 | 133 | DF_CS_active; /* to reset Dataflash command decoder */ |
tpadovani | 0:9225e2aef6b3 | 134 | |
tpadovani | 0:9225e2aef6b3 | 135 | /* Send opcode */ |
tpadovani | 0:9225e2aef6b3 | 136 | spi_transfer(PROGRAM); |
tpadovani | 0:9225e2aef6b3 | 137 | |
tpadovani | 0:9225e2aef6b3 | 138 | /* Address (page | offset) */ |
tpadovani | 0:9225e2aef6b3 | 139 | spi_transfer((uint8_t)((address >> 16) & 0xff)); |
tpadovani | 0:9225e2aef6b3 | 140 | spi_transfer((uint8_t)((address >> 8) & 0xff)); |
tpadovani | 0:9225e2aef6b3 | 141 | spi_transfer((uint8_t)(address & 0xff)); |
tpadovani | 0:9225e2aef6b3 | 142 | |
tpadovani | 0:9225e2aef6b3 | 143 | for(int i=0; i < length; i++){ |
tpadovani | 0:9225e2aef6b3 | 144 | spi_transfer(buffer[i]); |
tpadovani | 0:9225e2aef6b3 | 145 | } |
tpadovani | 0:9225e2aef6b3 | 146 | |
tpadovani | 0:9225e2aef6b3 | 147 | EndAndWait(); |
tpadovani | 0:9225e2aef6b3 | 148 | } |
tpadovani | 0:9225e2aef6b3 | 149 | |
tpadovani | 0:9225e2aef6b3 | 150 | /** |
tpadovani | 0:9225e2aef6b3 | 151 | * Erase the entire chip memory. Sectors proteced or locked down will |
tpadovani | 0:9225e2aef6b3 | 152 | * not be erased. |
tpadovani | 0:9225e2aef6b3 | 153 | **/ |
tpadovani | 0:9225e2aef6b3 | 154 | void AT25SF041::ChipErase() |
tpadovani | 0:9225e2aef6b3 | 155 | { |
tpadovani | 0:9225e2aef6b3 | 156 | WriteEnable(); |
tpadovani | 0:9225e2aef6b3 | 157 | |
tpadovani | 0:9225e2aef6b3 | 158 | DF_CS_inactive; |
tpadovani | 0:9225e2aef6b3 | 159 | DF_CS_active; |
tpadovani | 0:9225e2aef6b3 | 160 | |
tpadovani | 0:9225e2aef6b3 | 161 | spi_transfer(CHIP_ERASE); |
tpadovani | 0:9225e2aef6b3 | 162 | |
tpadovani | 0:9225e2aef6b3 | 163 | EndAndWait(); |
tpadovani | 0:9225e2aef6b3 | 164 | |
tpadovani | 0:9225e2aef6b3 | 165 | WriteDisable(); |
tpadovani | 0:9225e2aef6b3 | 166 | } |
tpadovani | 0:9225e2aef6b3 | 167 | |
tpadovani | 0:9225e2aef6b3 | 168 | /** |
tpadovani | 0:9225e2aef6b3 | 169 | * Perform a low-to-high transition on the CS pin and then poll |
tpadovani | 0:9225e2aef6b3 | 170 | * the status register to check if the dataflash is busy. |
tpadovani | 0:9225e2aef6b3 | 171 | **/ |
tpadovani | 0:9225e2aef6b3 | 172 | void AT25SF041::EndAndWait() |
tpadovani | 0:9225e2aef6b3 | 173 | { |
tpadovani | 0:9225e2aef6b3 | 174 | DF_CS_inactive; /* End current operation */ |
tpadovani | 0:9225e2aef6b3 | 175 | DF_CS_active; /* Some internal operation may occur |
tpadovani | 0:9225e2aef6b3 | 176 | * (buffer to page transfer, page erase, etc... ) */ |
tpadovani | 0:9225e2aef6b3 | 177 | |
tpadovani | 0:9225e2aef6b3 | 178 | /* Wait for the chip to be ready */ |
tpadovani | 0:9225e2aef6b3 | 179 | while((ReadStatusRegister(1) & READY_BUSY) > 0); |
tpadovani | 0:9225e2aef6b3 | 180 | |
tpadovani | 0:9225e2aef6b3 | 181 | DF_CS_inactive; /* Release SPI Bus */ |
tpadovani | 0:9225e2aef6b3 | 182 | } |