WIFI_API_20150524e
Diff: WIFI_Driver/nordic/spi_flash.c
- Revision:
- 0:a2de37bf5f3d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WIFI_Driver/nordic/spi_flash.c Tue Jun 09 06:04:13 2015 +0000 @@ -0,0 +1,462 @@ +/* + * Generated for windbond flash + */ + +#include <string.h> +#include <spi_flash.h> +//#include "nrf_delay.h" +#include "nrf_gpio.h" +//#include "common.h" +#include "spi_master_config.h" // This file must be in the application folder + +#include "simple_uart.h" + +#include "spi_master.h" + +#include "wait_api.h" + +#if 1 //marcus add for flash read/write +#define MFG_ID_WINBOND (0xEF) +#define DEVICE_ID_WINBOND_8M (0x5014) + +#define CMD_POWER_UP (0xAB) +#define CMD_JEDEC_ID (0x9F) +#define CMD_POWER_DOWN (0xB9) +#define CMD_READ_STATUS (0x05) +#define CMD_WRITE_ENABLE (0x06) +#define CMD_PAGE_PROG (0x02) +#define CMD_READ_DATA (0x03) +#define CMD_ERASE_4K (0x20) +#define CMD_ERASE_64K (0xD8) +#define CMD_DUMMY (0xFF) + +// added by Tsungta +#define CMD_READ_UNIQUE_ID (0x4B) +#define CMD_ERASE_SECU (0x44) +#define CMD_PAGE_PROG_SECU (0x42) +#define CMD_READ_SECU (0x48) + +#define THREE_BYTE_LENGTH 3 +#define WIFIDRI_LENGTH (136568) +#define ERASEWIFI_LENGTH (2696) +#define DEVICE_PAGE_SIZE (256) +#define DEVICE_SECTOR_SIZE (4096) +#define DEVICE_BLOCK_SIZE (65536) +#ifdef WIFI_BOOT_NORDIC +extern const unsigned char wifi_firmware[]; +#endif +#endif + +#if 1 //marcus add for flash read/write +static bool spi_flash_writeOneByte(uint32_t *spi_base_address, uint8_t DataBuffer) +{ + uint8_t rx_data; + uint32_t counter = 0; + /*lint -e{826} //Are too small pointer conversion */ + NRF_SPI_Type *spi_base = (NRF_SPI_Type *)spi_base_address; + + spi_base->TXD = (uint32_t) DataBuffer; + + /* Wait for the transaction complete or timeout (about 10ms - 20 ms) */ + while ((spi_base->EVENTS_READY == 0U) && (counter < TIMEOUT_COUNTER)) + { + counter++; + } + + if (counter == TIMEOUT_COUNTER) + { + /* timed out, disable slave (slave select active low) and return with error */ + return false; + } else { + /* clear the event to be ready to receive next messages */ + spi_base->EVENTS_READY = 0U; + } + + /* Marcus, need to move RXD to get the next transaction*/ + rx_data = (uint8_t)spi_base->RXD; + + return true; +} + +static uint8_t spi_flash_readOneByte(uint32_t *spi_base_address) +{ + uint32_t counter = 0; + /*lint -e{826} //Are too small pointer conversion */ + NRF_SPI_Type *spi_base = (NRF_SPI_Type *)spi_base_address; + + spi_base->TXD = 0xFF; //put dont case data + + /* Wait for the transaction complete or timeout (about 10ms - 20 ms) */ + while ((spi_base->EVENTS_READY == 0U) && (counter < TIMEOUT_COUNTER)) + { + counter++; + } + + if (counter == TIMEOUT_COUNTER) + { + return 0; + } else { + /* clear the event to be ready to receive next messages */ + spi_base->EVENTS_READY = 0U; + } + + return (uint8_t)spi_base->RXD; +} + +//#if !defined(TARGET_DELTA_DFCM_NNN40) +bool spi_flash_init(void) +{ + uint8_t mfgId; + uint16_t deviceID; + + uint32_t * p_spi_base_address = spi_master_init(SPI0, SPI_MODE0, false); + if (p_spi_base_address == NULL) + { + return false; + } + + nrf_gpio_pin_clear(SPI_PSELSS1_flash); + spi_flash_writeOneByte(p_spi_base_address, CMD_POWER_UP); + nrf_gpio_pin_set(SPI_PSELSS1_flash); + + //wait for wake up + wait_us(30);//nrf_delay_us(30); + + nrf_gpio_pin_clear(SPI_PSELSS1_flash); + + spi_flash_writeOneByte(p_spi_base_address, CMD_JEDEC_ID); + + mfgId = spi_flash_readOneByte(p_spi_base_address); + deviceID = (uint16_t)(spi_flash_readOneByte(p_spi_base_address) << 8); + deviceID |= spi_flash_readOneByte(p_spi_base_address); + + nrf_gpio_pin_set(SPI_PSELSS1_flash); + + if (mfgId != MFG_ID_WINBOND || deviceID != DEVICE_ID_WINBOND_8M) { + return false; + } + + return true; +} + +bool spi_flash_powerDown(void) +{ + uint32_t * p_spi_base_address = spi_master_init(SPI0, SPI_MODE0, false); + if (p_spi_base_address == NULL) + { + return false; + } + + nrf_gpio_pin_clear(SPI_PSELSS1_flash); + spi_flash_writeOneByte(p_spi_base_address, CMD_POWER_DOWN); + nrf_gpio_pin_set(SPI_PSELSS1_flash); + + //wait for sleep + wait_us(3);//nrf_delay_us(3); + + return true; +} +//#endif + +bool spi_flash_waitBusy(void) +{ + uint8_t status; + uint32_t * p_spi_base_address = spi_master_init(SPI0, SPI_MODE0, false); + if (p_spi_base_address == NULL) + { + return false; + } + + nrf_gpio_pin_clear(SPI_PSELSS1_flash); + spi_flash_writeOneByte(p_spi_base_address, CMD_READ_STATUS); + status = spi_flash_readOneByte(p_spi_base_address); + nrf_gpio_pin_set(SPI_PSELSS1_flash); + + if ( (status & 0x01) == 0x01 ) + { + return true; + } else { + return false; + } +} + +void spi_flash_setWEL(void) +{ + uint32_t * p_spi_base_address = spi_master_init(SPI0, SPI_MODE0, false); + if (p_spi_base_address == NULL) + { + return; + } + + nrf_gpio_pin_clear(SPI_PSELSS1_flash); + spi_flash_writeOneByte(p_spi_base_address, CMD_WRITE_ENABLE); + nrf_gpio_pin_set(SPI_PSELSS1_flash); +} + +void spi_flash_writePage(uint32_t address, const uint8_t *data, uint16_t len) +{ + //wait busy + while(spi_flash_waitBusy()) {}; + + //setWEL + spi_flash_setWEL(); + + uint32_t * p_spi_base_address = spi_master_init(SPI0, SPI_MODE0, false); + if (p_spi_base_address == NULL) + { + return; + } + + nrf_gpio_pin_clear(SPI_PSELSS1_flash); + + spi_flash_writeOneByte(p_spi_base_address, CMD_PAGE_PROG); + + spi_flash_writeOneByte(p_spi_base_address, ((address >> 16) & 0xFF)); + spi_flash_writeOneByte(p_spi_base_address, ((address >> 8) & 0xFF)); + spi_flash_writeOneByte(p_spi_base_address, (address & 0xFF)); + + /* write data */ + while(len--) { + spi_flash_writeOneByte(p_spi_base_address, *data++); + } + + nrf_gpio_pin_set(SPI_PSELSS1_flash); + + return; +} + +void spi_flash_eraseCmd(uint8_t command, uint32_t address) +{ + uint32_t * p_spi_base_address = spi_master_init(SPI0, SPI_MODE0, false); + if (p_spi_base_address == NULL) + { + return; + } + + nrf_gpio_pin_clear(SPI_PSELSS1_flash); + + spi_flash_writeOneByte(p_spi_base_address, command); + + spi_flash_writeOneByte(p_spi_base_address, ((address >> 16) & 0xFF)); + spi_flash_writeOneByte(p_spi_base_address, ((address >> 8) & 0xFF)); + spi_flash_writeOneByte(p_spi_base_address, (address & 0xFF)); + + nrf_gpio_pin_set(SPI_PSELSS1_flash); +} + +void spi_flash_erase(void) +{ + uint32_t address = 0; + uint32_t totalLength = WIFIDRI_LENGTH + ERASEWIFI_LENGTH; //To map SECTOR size + + //wait busy + while(spi_flash_waitBusy()) {}; + + //setWEL + spi_flash_setWEL(); + + // handle any full blocks + while(totalLength >= DEVICE_BLOCK_SIZE) { + spi_flash_eraseCmd(CMD_ERASE_64K, address); + address += DEVICE_BLOCK_SIZE; + totalLength -= DEVICE_BLOCK_SIZE; + } + + // finally handle any trailing partial blocks + while(totalLength) { + spi_flash_eraseCmd(CMD_ERASE_4K, address); + address += DEVICE_SECTOR_SIZE; + totalLength -= DEVICE_SECTOR_SIZE; + } + + return; +} + +static bool m_spi_result = true; + +void spi_flash_readpage(uint32_t address, uint8_t *data, uint16_t len) +{ + + uint16_t i = 0; + + //wait busy + while(spi_flash_waitBusy()) {}; + + uint32_t * p_spi_base_address = spi_master_init(SPI0, SPI_MODE0, false); + if (p_spi_base_address == NULL) + { + m_spi_result = false; + return; + } + + nrf_gpio_pin_clear(SPI_PSELSS1_flash); + + spi_flash_writeOneByte(p_spi_base_address, CMD_READ_DATA); + + spi_flash_writeOneByte(p_spi_base_address, ((address >> 16) & 0xFF)); + spi_flash_writeOneByte(p_spi_base_address, ((address >> 8) & 0xFF)); + spi_flash_writeOneByte(p_spi_base_address, (address & 0xFF)); + + /* read data */ + + for (i=0; i < len; i++){ // only totalLength bytes (<4096) left + *data++ = spi_flash_readOneByte(p_spi_base_address); + } + + nrf_gpio_pin_set(SPI_PSELSS1_flash); +} + #ifdef WIFI_BOOT_NORDIC +void spi_flash_write(void) +{ + uint32_t totalLength = WIFIDRI_LENGTH; + uint32_t address = 0; + uint16_t len = DEVICE_PAGE_SIZE; + + const uint8_t *data = wifi_firmware; + + + while(totalLength) { + spi_flash_writePage(address, data, len); + totalLength -= len; + address += len; + data += len; + len = (totalLength>DEVICE_PAGE_SIZE)? DEVICE_PAGE_SIZE : totalLength; + } +} +#endif +#endif + +// added by Tsungta +void spi_flash_read_uniqueID(uint8_t *data) +{ + uint8_t dummy_len = 4; + uint8_t id_len = 8; + //wait busy + while(spi_flash_waitBusy()) {}; + + uint32_t * p_spi_base_address = spi_master_init(SPI0, SPI_MODE0, false); + if (p_spi_base_address == NULL) + { + return; + } + + nrf_gpio_pin_clear(SPI_PSELSS1_flash); + + spi_flash_writeOneByte(p_spi_base_address, CMD_READ_UNIQUE_ID); + while(dummy_len--) + spi_flash_readOneByte(p_spi_base_address); // there is four dummy bytes before real data + /* id data */ + while(id_len--) + *data++ = spi_flash_readOneByte(p_spi_base_address); + + nrf_gpio_pin_set(SPI_PSELSS1_flash); +} + +// added by Tsungta +void spi_flash_erase_security(uint32_t address) +{ + //wait busy + while(spi_flash_waitBusy()) {}; + + //setWEL + spi_flash_setWEL(); + + uint32_t * p_spi_base_address = spi_master_init(SPI0, SPI_MODE0, false); + if (p_spi_base_address == NULL) + { + return; + } + + nrf_gpio_pin_clear(SPI_PSELSS1_flash); + + spi_flash_writeOneByte(p_spi_base_address, CMD_ERASE_SECU); + + spi_flash_writeOneByte(p_spi_base_address, ((address >> 16) & 0xFF)); + spi_flash_writeOneByte(p_spi_base_address, ((address >> 8) & 0xFF)); + spi_flash_writeOneByte(p_spi_base_address, (address & 0xFF)); + + nrf_gpio_pin_set(SPI_PSELSS1_flash); +} + +// added by Tsungta +void spi_flash_writePage_security(uint32_t address, const uint8_t *data, uint16_t len) +{ + //wait busy + while(spi_flash_waitBusy()) {}; + + //setWEL + spi_flash_setWEL(); + + uint32_t * p_spi_base_address = spi_master_init(SPI0, SPI_MODE0, false); + if (p_spi_base_address == NULL) + { + return; + } + + nrf_gpio_pin_clear(SPI_PSELSS1_flash); + + spi_flash_writeOneByte(p_spi_base_address, CMD_PAGE_PROG_SECU); + + spi_flash_writeOneByte(p_spi_base_address, ((address >> 16) & 0xFF)); + spi_flash_writeOneByte(p_spi_base_address, ((address >> 8) & 0xFF)); + spi_flash_writeOneByte(p_spi_base_address, (address & 0xFF)); + + /* write data */ + while(len--) { + spi_flash_writeOneByte(p_spi_base_address, *data++); + } + + nrf_gpio_pin_set(SPI_PSELSS1_flash); + + return; +} + +// added by Tsungta +void spi_flash_read_security(uint32_t address, uint8_t *data, uint16_t len) +{ + +#ifdef FLASHDEBUG + uint8_t data = 0; + uint8_t i = 1; +#endif + + //wait busy + while(spi_flash_waitBusy()) {}; + +// //setWEL +// spi_flash_setWEL(); + + uint32_t * p_spi_base_address = spi_master_init(SPI0, SPI_MODE0, false); + if (p_spi_base_address == NULL) + { + return; + } + + nrf_gpio_pin_clear(SPI_PSELSS1_flash); + + spi_flash_writeOneByte(p_spi_base_address, CMD_READ_SECU); + + spi_flash_writeOneByte(p_spi_base_address, ((address >> 16) & 0xFF)); + spi_flash_writeOneByte(p_spi_base_address, ((address >> 8) & 0xFF)); + spi_flash_writeOneByte(p_spi_base_address, (address & 0xFF)); + + spi_flash_readOneByte(p_spi_base_address); // there is a dummy byte before real data + /* read data */ + while(len--) { +#ifdef FLASHDEBUG + data = spi_flash_readOneByte(p_spi_base_address); + uint8_t buf[30]; + sprintf(buf,"0x%02X ",data); + simple_uart_putstring(buf); + if(i == 11) + { + simple_uart_put('\n'); + i = 0; + } + i++; +#else + *data++ = spi_flash_readOneByte(p_spi_base_address); +#endif + } + nrf_gpio_pin_set(SPI_PSELSS1_flash); +}