From 01b811cd8c2452f54e217c5f4420f8d72061bdca Mon Sep 17 00:00:00 2001 From: Nicholas Sherlock Date: Thu, 12 Mar 2015 20:40:40 +1300 Subject: [PATCH] Add support for Winbond 64Mbit SPI flash chip --- docs/Blackbox.md | 14 +++++++--- src/main/drivers/flash.h | 8 +++--- src/main/drivers/flash_m25p16.c | 47 +++++++++++++++++++++------------ 3 files changed, 45 insertions(+), 24 deletions(-) diff --git a/docs/Blackbox.md b/docs/Blackbox.md index 2c4bbd38b..67d70412d 100644 --- a/docs/Blackbox.md +++ b/docs/Blackbox.md @@ -134,9 +134,17 @@ tubing instead. ![OpenLog installed](Wiring/blackbox-installation-1.jpg "OpenLog installed with double-sided tape, SDCard slot pointing outward") ### Onboard dataflash storage -The full version of the Naze32 and the CC3D have an onboard "m25p16" 2 megayte dataflash storage chip which can be used -to store flight logs instead of using an OpenLog. This is a small chip with 8 fat legs, which can be found at the base -of the Naze32's direction arrow. This chip is not present on the "Acro" version of the Naze32. +Some flight controllers have an onboard SPI NOR flash chip which can be used to store flight logs instead of using an +OpenLog. + +The full version of the Naze32 and the CC3D have an onboard "m25p16" 2 megayte dataflash storage chip. This is a small +chip with 8 fat legs, which can be found at the base of the Naze32's direction arrow. This chip is not present on the +"Acro" version of the Naze32. + +These chips are also supported: + +* Micron/ST M25P16 - 16 Mbit +* Winbond W25Q64 - 64 Mbit ## Enabling the Blackbox (CLI) In the [Cleanflight Configurator][] , enter the CLI tab. Enable the Blackbox feature by typing in `feature BLACKBOX` and diff --git a/src/main/drivers/flash.h b/src/main/drivers/flash.h index 6ccba0d7b..10af1c224 100644 --- a/src/main/drivers/flash.h +++ b/src/main/drivers/flash.h @@ -20,12 +20,12 @@ #include typedef struct flashGeometry_t { - uint8_t sectors; + uint8_t sectors; // Count of the number of erasable blocks on the device uint16_t pagesPerSector; - uint16_t pageSize; + uint16_t pageSize; // In bytes - uint32_t sectorSize; + uint32_t sectorSize; // This is just pagesPerSector * pageSize - uint32_t totalSize; + uint32_t totalSize; // This is just sectorSize * sectors } flashGeometry_t; diff --git a/src/main/drivers/flash_m25p16.c b/src/main/drivers/flash_m25p16.c index a6bd7b22f..bf6bc39a7 100644 --- a/src/main/drivers/flash_m25p16.c +++ b/src/main/drivers/flash_m25p16.c @@ -38,6 +38,10 @@ #define M25P16_STATUS_FLAG_WRITE_IN_PROGRESS 0x01 #define M25P16_STATUS_FLAG_WRITE_ENABLED 0x02 +// Format is manufacturer, memory type, then capacity +#define JEDEC_ID_MICRON_M25P16 0x202015 +#define JEDEC_ID_WINBOND_W25Q64 0xEF4017 + #define DISABLE_M25P16 GPIO_SetBits(M25P16_CS_GPIO, M25P16_CS_PIN) #define ENABLE_M25P16 GPIO_ResetBits(M25P16_CS_GPIO, M25P16_CS_PIN) @@ -124,6 +128,7 @@ static bool m25p16_readIdentification() { uint8_t out[] = { M25P16_INSTRUCTION_RDID, 0, 0, 0}; uint8_t in[4]; + uint32_t chipID; delay(50); // short delay required after initialisation of SPI device instance. @@ -139,29 +144,37 @@ static bool m25p16_readIdentification() // Clearing the CS bit terminates the command early so we don't have to read the chip UID: DISABLE_M25P16; - // Check manufacturer, memory type, and capacity - if (in[1] == 0x20 && in[2] == 0x20 && in[3] == 0x15) { - // In the future we can support other chip geometries here: - geometry.sectors = 32; - geometry.pagesPerSector = 256; - geometry.pageSize = 256; + // Manufacturer, memory type, and capacity + chipID = (in[1] << 16) | (in[2] << 8) | (in[3]); - geometry.sectorSize = geometry.pagesPerSector * geometry.pageSize; - geometry.totalSize = geometry.sectorSize * geometry.sectors; + switch (chipID) { + case JEDEC_ID_MICRON_M25P16: + geometry.sectors = 32; + geometry.pagesPerSector = 256; + geometry.pageSize = 256; + break; + case JEDEC_ID_WINBOND_W25Q64: + geometry.sectors = 128; + geometry.pagesPerSector = 256; + geometry.pageSize = 256; + break; + default: + // Unsupported chip or not an SPI NOR flash + geometry.sectors = 0; + geometry.pagesPerSector = 0; + geometry.pageSize = 0; - couldBeBusy = true; // Just for luck we'll assume the chip could be busy even though it isn't specced to be - - return true; + geometry.sectorSize = 0; + geometry.totalSize = 0; + return false; } - geometry.sectors = 0; - geometry.pagesPerSector = 0; - geometry.pageSize = 0; + geometry.sectorSize = geometry.pagesPerSector * geometry.pageSize; + geometry.totalSize = geometry.sectorSize * geometry.sectors; - geometry.sectorSize = 0; - geometry.totalSize = 0; + couldBeBusy = true; // Just for luck we'll assume the chip could be busy even though it isn't specced to be - return false; + return true; } /**