From ec871b0ef13545688ddd140520bb49baacb4283a Mon Sep 17 00:00:00 2001 From: Giovanni Di Sirio Date: Sat, 4 Jun 2016 12:29:54 +0000 Subject: M25Q driver works over QSPI. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@9568 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/lib/peripherals/flash/hal_jesd216_flash.c | 277 +++++++++++++++++++++++ os/hal/lib/peripherals/flash/hal_jesd216_flash.h | 113 +++++++-- 2 files changed, 375 insertions(+), 15 deletions(-) (limited to 'os/hal/lib/peripherals') diff --git a/os/hal/lib/peripherals/flash/hal_jesd216_flash.c b/os/hal/lib/peripherals/flash/hal_jesd216_flash.c index 7687a4aa7..07d4aad80 100644 --- a/os/hal/lib/peripherals/flash/hal_jesd216_flash.c +++ b/os/hal/lib/peripherals/flash/hal_jesd216_flash.c @@ -46,4 +46,281 @@ /* Driver exported functions. */ /*===========================================================================*/ +void jesd216_cmd(BUSDriver *busp, uint8_t cmd) { +#if JESD216_BUS_MODE != JESD216_BUS_MODE_SPI + qspi_command_t mode; + + mode.cfg = QSPI_CFG_CMD(cmd) | +#if JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI1L + QSPI_CFG_CMD_MODE_ONE_LINE; +#elif JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI2L + QSPI_CFG_CMD_MODE_TWO_LINES; +#else + QSPI_CFG_CMD_MODE_FOUR_LINES; +#endif + mode.addr = 0U; + mode.alt = 0U; + qspiCommand(busp, &mode); +#else + uint8_t buf[1]; + + spiSelect(busp); + buf[0] = cmd; + spiSend(busp, 1, buf); + spiUnselect(busp); +#endif +} + +void jesd216_cmd_receive(BUSDriver *busp, + uint8_t cmd, + size_t n, + uint8_t *p) { +#if JESD216_BUS_MODE != JESD216_BUS_MODE_SPI + qspi_command_t mode; + + mode.cfg = QSPI_CFG_CMD(cmd) | +#if JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI1L + QSPI_CFG_CMD_MODE_ONE_LINE | + QSPI_CFG_DATA_MODE_ONE_LINE; +#elif JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI2L + QSPI_CFG_CMD_MODE_TWO_LINES | + QSPI_CFG_DATA_MODE_TWO_LINES; +#else + QSPI_CFG_CMD_MODE_FOUR_LINES | + QSPI_CFG_DATA_MODE_FOUR_LINES; + +#endif + mode.addr = 0U; + mode.alt = 0U; + qspiReceive(busp, &mode, n, p); +#else + uint8_t buf[1]; + + spiSelect(busp); + buf[0] = cmd; + spiSend(busp, 1, buf); + spiReceive(busp, n, p); + spiUnselect(busp); +#endif +} + +void jesd216_cmd_send(BUSDriver *busp, + uint8_t cmd, + size_t n, + const uint8_t *p) { +#if JESD216_BUS_MODE != JESD216_BUS_MODE_SPI + qspi_command_t mode; + + mode.cfg = QSPI_CFG_CMD(cmd) | +#if JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI1L + QSPI_CFG_CMD_MODE_ONE_LINE | + QSPI_CFG_DATA_MODE_ONE_LINE; +#elif JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI2L + QSPI_CFG_CMD_MODE_TWO_LINES | + QSPI_CFG_DATA_MODE_TWO_LINES; +#else + QSPI_CFG_CMD_MODE_FOUR_LINES | + QSPI_CFG_DATA_MODE_FOUR_LINES; + +#endif + mode.addr = 0U; + mode.alt = 0U; + qspiSend(busp, &mode, n, p); +#else + uint8_t buf[1]; + + spiSelect(busp); + buf[0] = cmd; + spiSend(busp, 1, buf); + spiSend(busp, n, p); + spiUnselect(busp); +#endif +} + +void jesd216_cmd_addr(BUSDriver *busp, + uint8_t cmd, + flash_address_t addr) { +#if JESD216_BUS_MODE != JESD216_BUS_MODE_SPI + qspi_command_t mode; + + mode.cfg = QSPI_CFG_CMD(cmd) | +#if JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI1L + QSPI_CFG_CMD_MODE_ONE_LINE | + QSPI_CFG_ADDR_MODE_ONE_LINE | + QSPI_CFG_ADDR_SIZE_24; +#elif JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI2L + QSPI_CFG_CMD_MODE_TWO_LINES | + QSPI_CFG_ADDR_MODE_TWO_LINES | + QSPI_CFG_ADDR_SIZE_24; +#else + QSPI_CFG_CMD_MODE_FOUR_LINES | + QSPI_CFG_ADDR_MODE_FOUR_LINES | + QSPI_CFG_ADDR_SIZE_24; + +#endif + mode.addr = addr; + mode.alt = 0U; + qspiCommand(busp, &mode); +#else + uint8_t buf[4]; + + spiSelect(busp); + buf[0] = cmd; + buf[1] = (uint8_t)(addr >> 16); + buf[2] = (uint8_t)(addr >> 8); + buf[3] = (uint8_t)(addr >> 0); + spiSend(busp, 4, buf); + spiUnselect(busp); +#endif +} + +void jesd216_cmd_addr_send(BUSDriver *busp, + uint8_t cmd, + flash_address_t addr, + size_t n, + const uint8_t *p) { +#if JESD216_BUS_MODE != JESD216_BUS_MODE_SPI + qspi_command_t mode; + + mode.cfg = QSPI_CFG_CMD(cmd) | +#if JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI1L + QSPI_CFG_CMD_MODE_ONE_LINE | + QSPI_CFG_ADDR_MODE_ONE_LINE | + QSPI_CFG_ADDR_SIZE_24 | + QSPI_CFG_DATA_MODE_ONE_LINE; +#elif JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI2L + QSPI_CFG_CMD_MODE_TWO_LINES | + QSPI_CFG_ADDR_MODE_TWO_LINES | + QSPI_CFG_ADDR_SIZE_24 | + QSPI_CFG_DATA_MODE_TWO_LINES; +#else + QSPI_CFG_CMD_MODE_FOUR_LINES | + QSPI_CFG_ADDR_MODE_FOUR_LINES | + QSPI_CFG_ADDR_SIZE_24 | + QSPI_CFG_DATA_MODE_FOUR_LINES; + +#endif + mode.addr = addr; + mode.alt = 0U; + qspiSend(busp, &mode, n, p); +#else + uint8_t buf[4]; + + spiSelect(busp); + buf[0] = cmd; + buf[1] = (uint8_t)(addr >> 16); + buf[2] = (uint8_t)(addr >> 8); + buf[3] = (uint8_t)(addr >> 0); + spiSend(busp, 4, buf); + spiSend(busp, n, p); + spiUnselect(busp); +#endif +} + +void jesd216_cmd_addr_receive(BUSDriver *busp, + uint8_t cmd, + flash_address_t addr, + size_t n, + uint8_t *p) { +#if JESD216_BUS_MODE != JESD216_BUS_MODE_SPI + qspi_command_t mode; + + mode.cfg = QSPI_CFG_CMD(cmd) | +#if JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI1L + QSPI_CFG_CMD_MODE_ONE_LINE | + QSPI_CFG_ADDR_MODE_ONE_LINE | + QSPI_CFG_ADDR_SIZE_24 | + QSPI_CFG_DATA_MODE_ONE_LINE; +#elif JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI2L + QSPI_CFG_CMD_MODE_TWO_LINES | + QSPI_CFG_ADDR_MODE_TWO_LINES | + QSPI_CFG_ADDR_SIZE_24 | + QSPI_CFG_DATA_MODE_TWO_LINES; +#else + QSPI_CFG_CMD_MODE_FOUR_LINES | + QSPI_CFG_ADDR_MODE_FOUR_LINES | + QSPI_CFG_ADDR_SIZE_24 | + QSPI_CFG_DATA_MODE_FOUR_LINES; + +#endif + mode.addr = addr; + mode.alt = 0U; + qspiReceive(busp, &mode, n, p); +#else + uint8_t buf[4]; + + spiSelect(busp); + buf[0] = cmd; + buf[1] = (uint8_t)(addr >> 16); + buf[2] = (uint8_t)(addr >> 8); + buf[3] = (uint8_t)(addr >> 0); + spiSend(busp, 4, buf); + spiReceive(busp, n, p); + spiUnselect(busp); +#endif +} + +#if (JESD216_BUS_MODE != JESD216_BUS_MODE_SPI) || defined(__DOXYGEN__) +void jesd216_cmd_addr_dummy_receive(BUSDriver *busp, + uint8_t cmd, + flash_address_t addr, + uint8_t dummy, + size_t n, + uint8_t *p) { + qspi_command_t mode; + + mode.cfg = QSPI_CFG_CMD(cmd) | +#if JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI1L + QSPI_CFG_CMD_MODE_ONE_LINE | + QSPI_CFG_ADDR_MODE_ONE_LINE | + QSPI_CFG_ADDR_SIZE_24 | + QSPI_CFG_DUMMY_CYCLES(dummy) | + QSPI_CFG_DATA_MODE_ONE_LINE; +#elif JESD216_BUS_MODE == JESD216_BUS_MODE_QSPI2L + QSPI_CFG_CMD_MODE_TWO_LINES | + QSPI_CFG_ADDR_MODE_TWO_LINES | + QSPI_CFG_ADDR_SIZE_24 | + QSPI_CFG_DUMMY_CYCLES(dummy) | + QSPI_CFG_DATA_MODE_TWO_LINES; +#else + QSPI_CFG_CMD_MODE_FOUR_LINES | + QSPI_CFG_ADDR_MODE_FOUR_LINES | + QSPI_CFG_ADDR_SIZE_24 | + QSPI_CFG_DUMMY_CYCLES(dummy) | + QSPI_CFG_DATA_MODE_FOUR_LINES; +#endif + mode.addr = addr; + mode.alt = 0U; + qspiReceive(busp, &mode, n, p); +} +#endif /* JESD216_BUS_MODE != JESD216_BUS_MODE_SPI */ + +#if ((JESD216_BUS_MODE != JESD216_BUS_MODE_SPI) && \ + (JESD216_SHARED_BUS == TRUE)) || defined(__DOXYGEN__) +void jesd216_bus_acquire(BUSDriver *busp) { + + qspiAcquireBus(busp); +} + +void jesd216_bus_release(BUSDriver *busp) { + + qspiReleaseBus(busp); +} +#elif (JESD216_BUS_MODE == JESD216_BUS_MODE_SPI) && \ + (JESD216_SHARED_BUS == TRUE) +static void jesd216_bus_acquire(BUSDriver *busp) { + + spiAcquireBus(busp); + spiStart(busp, busp->config->spicfg); +} + +static void jesd216_bus_release(BUSDriver *busp) { + + spiReleaseBus(busp); +} +#else +#define jesd216_bus_acquire(busp) +#define jesd216_bus_release(busp) +#endif + /** @} */ diff --git a/os/hal/lib/peripherals/flash/hal_jesd216_flash.h b/os/hal/lib/peripherals/flash/hal_jesd216_flash.h index 8e46f71e8..69d8a8533 100644 --- a/os/hal/lib/peripherals/flash/hal_jesd216_flash.h +++ b/os/hal/lib/peripherals/flash/hal_jesd216_flash.h @@ -35,40 +35,108 @@ * @name Common command codes * @{ */ -#define JESD216_CMD_READ_ID 0x9F -#define JESD216_CMD_READ 0x03 -#define JESD216_CMD_WRITE_ENABLE 0x06 -#define JESD216_CMD_WRITE_DISABLE 0x04 -#define JESD216_CMD_READ_STATUS_REGISTER 0x05 -#define JESD216_CMD_WRITE_STATUS_REGISTER 0x01 -#define JESD216_CMD_PAGE_PROGRAM 0x02 -#define JESD216_CMD_ERASE_4K 0x20 -#define JESD216_CMD_ERASE_BULK 0xC7 -#define JESD216_CMD_PROGRAM_ERASE_RESUME 0x7A -#define JESD216_CMD_PROGRAM_ERASE_SUSPEND 0x75 -#define JESD216_CMD_READ_OTP_ARRAY 0x4B -#define JESD216_CMD_PROGRAM_OTP_ARRAY 0x42 +#define JESD216_CMD_READ_ID 0x9F +#define JESD216_CMD_READ 0x03 +#define JESD216_CMD_WRITE_ENABLE 0x06 +#define JESD216_CMD_WRITE_DISABLE 0x04 +#define JESD216_CMD_READ_STATUS_REGISTER 0x05 +#define JESD216_CMD_WRITE_STATUS_REGISTER 0x01 +#define JESD216_CMD_PAGE_PROGRAM 0x02 +#define JESD216_CMD_ERASE_4K 0x20 +#define JESD216_CMD_ERASE_BULK 0xC7 +#define JESD216_CMD_PROGRAM_ERASE_RESUME 0x7A +#define JESD216_CMD_PROGRAM_ERASE_SUSPEND 0x75 +#define JESD216_CMD_READ_OTP_ARRAY 0x4B +#define JESD216_CMD_PROGRAM_OTP_ARRAY 0x42 +/** @} */ + +/** + * @name Bus interface. + * @{ + */ +#define JESD216_BUS_MODE_SPI 0 +#define JESD216_BUS_MODE_QSPI1L 1 +#define JESD216_BUS_MODE_QSPI2L 2 +#define JESD216_BUS_MODE_QSPI4L 4 /** @} */ /*===========================================================================*/ /* Driver pre-compile time settings. */ /*===========================================================================*/ +/** + * @name Configuration options + * @{ + */ +/** + * @brief Physical transport interface. + */ +#if !defined(JESD216_USE_SPI) || defined(__DOXYGEN__) +#define JESD216_BUS_MODE JESD216_BUS_MODE_QSPI4L +#endif + +/** + * @brief Shared bus switch. + * @details If set to @p TRUE the device acquires bus ownership + * on each transaction. + * @note Requires @p SPI_USE_MUTUAL_EXCLUSION or + * @p SPI_USE_MUTUAL_EXCLUSION. + */ +#if !defined(JESD216_SHARED_BUS) || defined(__DOXYGEN__) +#define JESD216_SHARED_BUS TRUE +#endif +/** @} */ + /*===========================================================================*/ /* Derived constants and error checks. */ /*===========================================================================*/ +#if (JESD216_BUS_MODE == JESD216_BUS_MODE_SPI) && (HAL_USE_SPI == FALSE) +#error "JESD216_BUS_MODE_SPI requires HAL_USE_SPI" +#endif + +#if (JESD216_BUS_MODE != JESD216_BUS_MODE_SPI) && (HAL_USE_QSPI == FALSE) +#error "JESD216_BUS_MODE_QSPIxL requires HAL_USE_QSPI" +#endif + +#if (JESD216_BUS_MODE == JESD216_BUS_MODE_SPI) && \ + (JESD216_SHARED_SPI == TRUE) && \ + (SPI_USE_MUTUAL_EXCLUSION == FALSE) +#error "JESD216_SHARED_SPI requires SPI_USE_MUTUAL_EXCLUSION" +#endif + +#if (JESD216_BUS_MODE != JESD216_BUS_MODE_SPI) && \ + (JESD216_BUS_MODE != JESD216_BUS_MODE_QSPI1L) && \ + (JESD216_BUS_MODE != JESD216_BUS_MODE_QSPI2L) && \ + (JESD216_BUS_MODE != JESD216_BUS_MODE_QSPI4L) +#error "invalid JESD216_BUS_MODE selected" +#endif + /*===========================================================================*/ /* Driver data structures and types. */ /*===========================================================================*/ +#if (JESD216_BUS_MODE != JESD216_BUS_MODE_SPI) || defined(__DOXYGEN__) +#define BUSConfig QSPIConfig +#define BUSDriver QSPIDriver +#else +#define BUSConfig SPIConfig +#define BUSDriver SPIDriver +#endif + +#define _jesd216_config \ + BUSDriver *busp; \ + const BUSConfig *buscfg; + /** * @brief @p JESD215Flash specific methods. * @note No methods so far, just a common ancestor interface. */ #define _jesd216_flash_methods_alone \ /* Read SFDP.*/ \ - flash_error_t (*read_id)(void *instance, uint8_t *rp, size_t max); + flash_error_t (*read_sfdp)(void *instance, uint8_t *rp, \ + flash_address_t addr, \ + size_t n); /** * @brief @p JESD215Flash specific methods with inherited ones. @@ -116,7 +184,22 @@ typedef struct { #ifdef __cplusplus extern "C" { #endif - + void jesd216_cmd(BUSDriver *busp, uint8_t cmd); + void jesd216_cmd_receive(BUSDriver *busp, uint8_t cmd, size_t n, uint8_t *p); + void jesd216_cmd_send(BUSDriver *busp, uint8_t cmd, size_t n, const uint8_t *p); + void jesd216_cmd_addr(BUSDriver *busp, uint8_t cmd, flash_address_t addr); + void jesd216_cmd_addr_send(BUSDriver *busp, uint8_t cmd, flash_address_t addr, + size_t n, const uint8_t *p); + void jesd216_cmd_addr_receive(BUSDriver *busp, uint8_t cmd, flash_address_t addr, + size_t n, uint8_t *p); +#if JESD216_BUS_MODE != JESD216_BUS_MODE_SPI + void jesd216_cmd_addr_dummy_receive(BUSDriver *busp, uint8_t cmd, flash_address_t addr, + uint8_t dummy, size_t n, uint8_t *p); +#endif /* JESD216_BUS_MODE != JESD216_BUS_MODE_SPI */ +#if JESD216_SHARED_BUS == TRUE + void jesd216_bus_acquire(BUSDriver *busp); + void jesd216_bus_release(BUSDriver *busp); +#endif #ifdef __cplusplus } #endif -- cgit v1.2.3