diff --git a/flight/CopterControl/System/inc/pios_config.h b/flight/CopterControl/System/inc/pios_config.h index 1f6f3917d..a13a8fce7 100644 --- a/flight/CopterControl/System/inc/pios_config.h +++ b/flight/CopterControl/System/inc/pios_config.h @@ -59,6 +59,7 @@ #define PIOS_INCLUDE_I2C_ESC #define PIOS_INCLUDE_ADXL345 +#define PIOS_INCLUDE_FLASH /* Defaults for Logging */ #define LOG_FILENAME "PIOS.LOG" diff --git a/flight/PiOS/Boards/STM32103CB_CC_Rev1.h b/flight/PiOS/Boards/STM32103CB_CC_Rev1.h index d9321f99a..695e044ba 100644 --- a/flight/PiOS/Boards/STM32103CB_CC_Rev1.h +++ b/flight/PiOS/Boards/STM32103CB_CC_Rev1.h @@ -249,6 +249,7 @@ TIM4 | RC In 1 | Servo 3 | Servo 2 | Servo 1 #define PIOS_GPIO_CLKS { PIOS_GPIO_1_GPIO_CLK } #define PIOS_GPIO_NUM 1 +#define PIOS_FLASH_CS_PIN 0 #define PIOS_FLASH_ENABLE PIOS_GPIO_On(0) #define PIOS_FLASH_DISABLE PIOS_GPIO_Off(0) #define PIOS_ADXL_ENABLE PIOS_SPI_RC_PinSet(PIOS_SPI_ACCEL,0) diff --git a/flight/PiOS/Common/pios_flash_w25x.c b/flight/PiOS/Common/pios_flash_w25x.c index 85e75ad52..ecb8120e7 100644 --- a/flight/PiOS/Common/pios_flash_w25x.c +++ b/flight/PiOS/Common/pios_flash_w25x.c @@ -11,57 +11,201 @@ #include "pios_flash_w25x.h" #include "pios_adxl345.h" -void PIOS_FLASH_W25X_ClaimBus() +#define W25X_WRITE_ENABLE 0x06 +#define W25X_WRITE_DISABLE 0x04 +#define W25X_READ_STATUS 0x05 +#define W25X_WRITE_STATUS 0x01 +#define W25X_READ_DATA 0x03 +#define W25X_FAST_READ 0x0b +#define W25X_DEVICE_ID 0x90 +#define W25X_SECTOR_ERASE 0x20 +#define W25X_PAGE_WRITE 0x02 + +#define W25X_STATUS_BUSY 0x01 +#define W25X_STATUS_WRITEPROTECT 0x02 +#define W25X_STATUS_BP0 0x04 +#define W25X_STATUS_BP1 0x08 +#define W25X_STATUS_BP2 0x10 +#define W25X_STATUS_TP 0x20 +#define W25X_STATUS_SEC 0x40 +#define W25X_STATUS_SRP0 0x80 + +static uint8_t device_type; + +//! Private functions +static int8_t PIOS_Flash_W25X_ClaimBus(); +static void PIOS_Flash_W25X_ReleaseBus(); +static uint8_t PIOS_Flash_W25X_WriteEnable(); +static uint8_t PIOS_Flash_W25X_Busy() ; + +/** + * @brief Claim the SPI bus for flash use and assert CS pin + * @return 0 for sucess, -1 for failure to get semaphore + */ +static int8_t PIOS_Flash_W25X_ClaimBus() { - PIOS_SPI_ClaimBus(PIOS_SPI_FLASH); - PIOS_ADXL_DISABLE; + int8_t ret = PIOS_SPI_ClaimBus(PIOS_SPI_FLASH); PIOS_FLASH_ENABLE; - PIOS_DELAY_WaituS(1); + return (ret == 0) ? 0 : -1; } -void PIOS_FLASH_W25X_ReleaseBus() +/** + * @brief Release the SPI bus sempahore and ensure flash chip not using bus + */ +static void PIOS_Flash_W25X_ReleaseBus() { - PIOS_ADXL_DISABLE; PIOS_FLASH_DISABLE; PIOS_SPI_ReleaseBus(PIOS_SPI_FLASH); } -void PIOS_FLASH_W25X_Init() -{ - PIOS_FLASH_W25X_ClaimBus(); - PIOS_FLASH_W25X_ReleaseBus(); +/** + * @brief Returns if the flash chip is busy + */ +static uint8_t PIOS_Flash_W25X_Busy() +{ + return PIOS_Flash_W25X_ReadStatus() & W25X_STATUS_BUSY; } +/** + * @brief Execute the write enable instruction and returns the status + * @returns 0 if successful, -1 if unable to claim bus + */ +static uint8_t PIOS_Flash_W25X_WriteEnable() +{ + uint8_t out[] = {W25X_WRITE_ENABLE}; + if(PIOS_Flash_W25X_ClaimBus() != 0) + return -1; + PIOS_SPI_TransferBlock(PIOS_SPI_FLASH,out,NULL,sizeof(out),NULL); + PIOS_Flash_W25X_ReleaseBus(); + return 0; +} + +/** + * @brief Initialize the flash device and enable write access + */ +int8_t PIOS_Flash_W25X_Init() +{ + PIOS_GPIO_Enable(PIOS_FLASH_CS_PIN); + device_type = PIOS_Flash_W25X_ReadID(); + PIOS_Flash_W25X_WriteEnable(); + return 0; +} + + /** * @brief Read the status register from flash chip and return it */ -uint8_t PIOS_FLASH_ReadStatus() +uint8_t PIOS_Flash_W25X_ReadStatus() { - PIOS_FLASH_W25X_ClaimBus(); uint8_t out[2] = {W25X_READ_STATUS, 0}; uint8_t in[2] = {0,0}; + PIOS_Flash_W25X_ClaimBus(); PIOS_SPI_TransferBlock(PIOS_SPI_FLASH,out,in,sizeof(out),NULL); - PIOS_FLASH_W25X_ReleaseBus(); + PIOS_Flash_W25X_ReleaseBus(); return in[1]; } /** * @brief Read the status register from flash chip and return it */ -uint8_t PIOS_FLASH_ReadID() +uint8_t PIOS_Flash_W25X_ReadID() { - PIOS_FLASH_W25X_ClaimBus(); uint8_t out[] = {W25X_DEVICE_ID, 0, 0, 0, 0, 0}; uint8_t in[6]; + PIOS_Flash_W25X_ClaimBus(); PIOS_SPI_TransferBlock(PIOS_SPI_FLASH,out,in,sizeof(out),NULL); - PIOS_FLASH_W25X_ReleaseBus(); + PIOS_Flash_W25X_ReleaseBus(); return in[5]; } -void PIOS_FLASH_W25X_WriteData(uint32_t addr, uint8_t * data, uint16_t len) +/** + * @brief Erase a sector on the flash chip + * @param[in] add Address of flash to erase + * @returns 0 if successful + * @retval -1 if unable to claim bus + * @retval + */ +int8_t PIOS_Flash_W25X_EraseSector(uint32_t addr) { + uint8_t ret; + uint8_t out[] = {W25X_SECTOR_ERASE, (addr >> 16) && 0xff, (addr >> 8) && 0xff , addr && 0xff}; + + if((ret = PIOS_Flash_W25X_WriteEnable()) != 0) + return ret; + + if(PIOS_Flash_W25X_ClaimBus() != 0) + return -1; + PIOS_SPI_TransferBlock(PIOS_SPI_FLASH,out,NULL,sizeof(out),NULL); + PIOS_Flash_W25X_ReleaseBus(); + + while(PIOS_Flash_W25X_Busy()) { + //TODO: Fail on timeout +#if defined(PIOS_INCLUDE_FREERTOS) + vTaskDelay(1); +#endif + } + + return 0; } -void PIOS_FLASH_W25X_ReadData(uint32_t addr, uint8_t * data, uint16_t len) +/** + * @brief Write one page of data (up to 256 bytes) aligned to a page start + * @param[in] addr Address in flash to write to + * @param[in] data Pointer to data to write to flash + * @param[in] len Length of data to write (max 256 bytes) + * @return Zero if success or error code + * @retval -1 Unable to claim SPI bus + * @retval -2 Size exceeds 256 bytes + * @retval -3 Length to write would wrap around page boundary + */ +int8_t PIOS_Flash_W25X_WriteData(uint32_t addr, uint8_t * data, uint16_t len) { + uint8_t ret; + + /* Can only write one page at a time */ + if(len > 0x100) + return -2; + + /* Ensure number of bytes fits after starting address before end of page */ + if(((addr & 0xff) + len) > 0x100) + return -3; + + if((ret = PIOS_Flash_W25X_WriteEnable()) != 0) + return ret; + + /* Execute write page command and clock in address. Keep CS asserted */ + if(PIOS_Flash_W25X_ClaimBus() != 0) + return -1; + uint8_t out[] = {W25X_PAGE_WRITE, (addr >> 16) && 0xff, (addr >> 8) && 0xff , addr && 0xff}; + PIOS_SPI_TransferBlock(PIOS_SPI_FLASH,out,NULL,sizeof(out),NULL); + + /* Clock out data to flash */ + PIOS_SPI_TransferBlock(PIOS_SPI_FLASH,data,NULL,len,NULL); + + PIOS_Flash_W25X_ReleaseBus(); + + while(PIOS_Flash_W25X_Busy()) { +#if defined(PIOS_INCLUDE_FREERTOS) + vTaskDelay(1); +#endif + } + + return 0; +} + +int8_t PIOS_Flash_W25X_ReadData(uint32_t addr, uint8_t * data, uint16_t len) +{ + if(PIOS_Flash_W25X_ClaimBus() == -1) + return -1; + + /* Execute read command and clock in address. Keep CS asserted */ + uint8_t out[] = {W25X_READ_DATA, (addr >> 16) && 0xff, (addr >> 8) && 0xff , addr && 0xff}; + PIOS_SPI_TransferBlock(PIOS_SPI_FLASH,out,NULL,sizeof(out),NULL); + + /* Copy the transfer data to the buffer */ + PIOS_SPI_TransferBlock(PIOS_SPI_FLASH,NULL,data,len,NULL); + + PIOS_Flash_W25X_ReleaseBus(); + + return 0; } \ No newline at end of file diff --git a/flight/PiOS/inc/pios_flash_w25x.h b/flight/PiOS/inc/pios_flash_w25x.h index dfe243521..e9a8715be 100644 --- a/flight/PiOS/inc/pios_flash_w25x.h +++ b/flight/PiOS/inc/pios_flash_w25x.h @@ -7,16 +7,9 @@ * */ -#define W25X_WRITE_ENABLE 0x06 -#define W25X_WRITE_DISABLE 0x04 -#define W25X_READ_STATUS 0x05 -#define W25X_WRITE_STATUS 0x01 -#define W25X_READ_DATA 0x03 -#define W25X_FAST_READ 0x0b -#define W25X_DEVICE_ID 0x90 - -void PIOS_FLASH_W25X_Init(); -uint8_t PIOS_FLASH_ReadStatus(); -uint8_t PIOS_FLASH_ReadID(); -void PIOS_FLASH_W25X_WriteData(uint32_t addr, uint8_t * data, uint16_t len); -void PIOS_FLASH_W25X_ReadData(uint32_t addr, uint8_t * data, uint16_t len); +int8_t PIOS_Flash_W25X_Init(); +uint8_t PIOS_Flash_W25X_ReadStatus(); +uint8_t PIOS_Flash_W25X_ReadID(); +int8_t PIOS_Flash_W25X_EraseSector(uint32_t add); +int8_t PIOS_Flash_W25X_WriteData(uint32_t addr, uint8_t * data, uint16_t len); +int8_t PIOS_Flash_W25X_ReadData(uint32_t addr, uint8_t * data, uint16_t len); diff --git a/flight/PiOS/pios.h b/flight/PiOS/pios.h index 88a5631c6..7f5c08daa 100644 --- a/flight/PiOS/pios.h +++ b/flight/PiOS/pios.h @@ -107,6 +107,10 @@ #include #endif +#if defined(PIOS_INCLUDE_FLASH) +#include +#endif + #if defined(PIOS_INCLUDE_BL_HELPER) #include #endif