From 1482439bbe32520bfed93946580a0f5699926aa2 Mon Sep 17 00:00:00 2001 From: Martin Budden Date: Fri, 17 Nov 2017 09:15:19 +0000 Subject: [PATCH] Improve bus usage in M25P16 flash --- src/main/drivers/flash_m25p16.c | 75 ++++++++++++++++++--------------- 1 file changed, 40 insertions(+), 35 deletions(-) diff --git a/src/main/drivers/flash_m25p16.c b/src/main/drivers/flash_m25p16.c index 5a9455549..6969977a8 100644 --- a/src/main/drivers/flash_m25p16.c +++ b/src/main/drivers/flash_m25p16.c @@ -55,9 +55,6 @@ #define JEDEC_ID_WINBOND_W25Q128 0xEF4018 #define JEDEC_ID_WINBOND_W25Q256 0xEF4019 -#define DISABLE_M25P16 IOHi(bus->busdev_u.spi.csnPin); __NOP() -#define ENABLE_M25P16 __NOP(); IOLo(bus->busdev_u.spi.csnPin) - static busDevice_t busInstance; static busDevice_t *bus; static bool isLargeFlash = false; @@ -78,40 +75,56 @@ static flashGeometry_t geometry = {.pageSize = M25P16_PAGESIZE}; */ static bool couldBeBusy = false; + +static void m25p16_disable(busDevice_t *bus) +{ + IOHi(bus->busdev_u.spi.csnPin); + __NOP(); +} + +static void m25p16_enable(busDevice_t *bus) +{ + __NOP(); + IOLo(bus->busdev_u.spi.csnPin); +} + +static void m25p16_transfer(busDevice_t *bus, const uint8_t *txData, uint8_t *rxData, int len) +{ + m25p16_enable(bus); + spiTransfer(bus->busdev_u.spi.instance, txData, rxData, len); + m25p16_disable(bus); +} + /** * Send the given command byte to the device. */ -static void m25p16_performOneByteCommand(uint8_t command) +static void m25p16_performOneByteCommand(busDevice_t *bus, uint8_t command) { - ENABLE_M25P16; + m25p16_enable(bus); spiTransferByte(bus->busdev_u.spi.instance, command); - DISABLE_M25P16; + m25p16_disable(bus); } /** * The flash requires this write enable command to be sent before commands that would cause * a write like program and erase. */ -static void m25p16_writeEnable(void) +static void m25p16_writeEnable(busDevice_t *bus) { - m25p16_performOneByteCommand(M25P16_INSTRUCTION_WRITE_ENABLE); + m25p16_performOneByteCommand(bus, M25P16_INSTRUCTION_WRITE_ENABLE); // Assume that we're about to do some writing, so the device is just about to become busy couldBeBusy = true; } -static uint8_t m25p16_readStatus(void) +static uint8_t m25p16_readStatus(busDevice_t *bus) { const uint8_t command[2] = { M25P16_INSTRUCTION_READ_STATUS_REG, 0 }; uint8_t in[2]; - ENABLE_M25P16; - - spiTransfer(bus->busdev_u.spi.instance, command, in, sizeof(command)); - - DISABLE_M25P16; + m25p16_transfer(bus, command, in, sizeof(command)); return in[1]; } @@ -119,7 +132,7 @@ static uint8_t m25p16_readStatus(void) bool m25p16_isReady(void) { // If couldBeBusy is false, don't bother to poll the flash chip for its status - couldBeBusy = couldBeBusy && ((m25p16_readStatus() & M25P16_STATUS_FLAG_WRITE_IN_PROGRESS) != 0); + couldBeBusy = couldBeBusy && ((m25p16_readStatus(bus) & M25P16_STATUS_FLAG_WRITE_IN_PROGRESS) != 0); return !couldBeBusy; } @@ -153,12 +166,8 @@ static bool m25p16_readIdentification(void) uint8_t in[4]; in[1] = 0; - ENABLE_M25P16; - - spiTransfer(bus->busdev_u.spi.instance, out, in, sizeof(out)); - // Clearing the CS bit terminates the command early so we don't have to read the chip UID: - DISABLE_M25P16; + m25p16_transfer(bus, out, in, sizeof(out)); // Manufacturer, memory type, and capacity const uint32_t chipID = (in[1] << 16) | (in[2] << 8) | (in[3]); @@ -206,7 +215,7 @@ static bool m25p16_readIdentification(void) if (geometry.totalSize > 16 * 1024 * 1024) { isLargeFlash = true; - m25p16_performOneByteCommand(W25Q256_INSTRUCTION_ENTER_4BYTE_ADDRESS_MODE); + m25p16_performOneByteCommand(bus, W25Q256_INSTRUCTION_ENTER_4BYTE_ADDRESS_MODE); } couldBeBusy = true; // Just for luck we'll assume the chip could be busy even though it isn't specced to be @@ -241,7 +250,7 @@ bool m25p16_init(const flashConfig_t *flashConfig) IOInit(bus->busdev_u.spi.csnPin, OWNER_FLASH_CS, 0); IOConfigGPIO(bus->busdev_u.spi.csnPin, SPI_IO_CS_CFG); - DISABLE_M25P16; + m25p16_disable(bus); #ifndef M25P16_SPI_SHARED //Maximum speed for standard READ command is 20mHz, other commands tolerate 25mHz @@ -272,22 +281,18 @@ void m25p16_eraseSector(uint32_t address) m25p16_waitForReady(SECTOR_ERASE_TIMEOUT_MILLIS); - m25p16_writeEnable(); + m25p16_writeEnable(bus); - ENABLE_M25P16; - - spiTransfer(bus->busdev_u.spi.instance, out, NULL, isLargeFlash ? 5 : 4); - - DISABLE_M25P16; + m25p16_transfer(bus, out, NULL, sizeof(out)); } void m25p16_eraseCompletely(void) { m25p16_waitForReady(BULK_ERASE_TIMEOUT_MILLIS); - m25p16_writeEnable(); + m25p16_writeEnable(bus); - m25p16_performOneByteCommand(M25P16_INSTRUCTION_BULK_ERASE); + m25p16_performOneByteCommand(bus, M25P16_INSTRUCTION_BULK_ERASE); } void m25p16_pageProgramBegin(uint32_t address) @@ -298,9 +303,9 @@ void m25p16_pageProgramBegin(uint32_t address) m25p16_waitForReady(DEFAULT_TIMEOUT_MILLIS); - m25p16_writeEnable(); + m25p16_writeEnable(bus); - ENABLE_M25P16; + m25p16_enable(bus); spiTransfer(bus->busdev_u.spi.instance, command, NULL, isLargeFlash ? 5 : 4); } @@ -312,7 +317,7 @@ void m25p16_pageProgramContinue(const uint8_t *data, int length) void m25p16_pageProgramFinish(void) { - DISABLE_M25P16; + m25p16_disable(bus); } /** @@ -357,12 +362,12 @@ int m25p16_readBytes(uint32_t address, uint8_t *buffer, int length) return 0; } - ENABLE_M25P16; + m25p16_enable(bus); spiTransfer(bus->busdev_u.spi.instance, command, NULL, isLargeFlash ? 5 : 4); spiTransfer(bus->busdev_u.spi.instance, NULL, buffer, length); - DISABLE_M25P16; + m25p16_disable(bus); return length; }