mirror of
https://github.com/betaflight/betaflight.git
synced 2025-07-16 04:45:24 +03:00
Prepare flash code for multiple device type support (#5683)
* Prepare flash drivers for multiple device type support * Add static assertions on device page and flashfs alloc sizes.
This commit is contained in:
parent
4a5e79a534
commit
864dba98c1
13 changed files with 387 additions and 187 deletions
153
src/main/drivers/flash.c
Normal file
153
src/main/drivers/flash.c
Normal file
|
@ -0,0 +1,153 @@
|
|||
/*
|
||||
* This file is part of Betaflight/Cleanflight.
|
||||
*
|
||||
* Betaflight/Cleanflight is free software: you can redistribute it
|
||||
* and/or modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* Betaflight/Cleanflight is distributed in the hope that it will be
|
||||
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Betaflight/Cleanflight. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "platform.h"
|
||||
|
||||
#include "build/debug.h"
|
||||
|
||||
#ifdef USE_FLASH
|
||||
|
||||
#include "flash.h"
|
||||
#include "flash_impl.h"
|
||||
#include "flash_m25p16.h"
|
||||
#include "drivers/bus_spi.h"
|
||||
#include "drivers/io.h"
|
||||
#include "drivers/time.h"
|
||||
|
||||
static busDevice_t busInstance;
|
||||
static busDevice_t *busdev;
|
||||
|
||||
static flashDevice_t flashDevice;
|
||||
|
||||
// Read chip identification and send it to device detect
|
||||
|
||||
bool flashInit(const flashConfig_t *flashConfig)
|
||||
{
|
||||
busdev = &busInstance;
|
||||
busdev->bustype = BUSTYPE_SPI;
|
||||
spiBusSetInstance(busdev, spiInstanceByDevice(SPI_CFG_TO_DEV(flashConfig->spiDevice)));
|
||||
if (flashConfig->csTag) {
|
||||
busdev->busdev_u.spi.csnPin = IOGetByTag(flashConfig->csTag);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
IOInit(busdev->busdev_u.spi.csnPin, OWNER_FLASH_CS, 0);
|
||||
IOConfigGPIO(busdev->busdev_u.spi.csnPin, SPI_IO_CS_CFG);
|
||||
IOHi(busdev->busdev_u.spi.csnPin);
|
||||
|
||||
#ifndef M25P16_SPI_SHARED
|
||||
//Maximum speed for standard READ command is 20mHz, other commands tolerate 25mHz
|
||||
//spiSetDivisor(busdev->busdev_u.spi.instance, SPI_CLOCK_FAST);
|
||||
spiSetDivisor(busdev->busdev_u.spi.instance, SPI_CLOCK_STANDARD*2);
|
||||
#endif
|
||||
|
||||
flashDevice.busdev = busdev;
|
||||
|
||||
const uint8_t out[] = { SPIFLASH_INSTRUCTION_RDID, 0, 0, 0 };
|
||||
|
||||
delay(50); // short delay required after initialisation of SPI device instance.
|
||||
|
||||
/* Just in case transfer fails and writes nothing, so we don't try to verify the ID against random garbage
|
||||
* from the stack:
|
||||
*/
|
||||
uint8_t in[4];
|
||||
in[1] = 0;
|
||||
|
||||
// Clearing the CS bit terminates the command early so we don't have to read the chip UID:
|
||||
spiBusTransfer(busdev, out, in, sizeof(out));
|
||||
|
||||
// Manufacturer, memory type, and capacity
|
||||
uint32_t chipID = (in[1] << 16) | (in[2] << 8) | (in[3]);
|
||||
|
||||
#ifdef USE_FLASH_M25P16
|
||||
if (m25p16_detect(&flashDevice, chipID)) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
spiPreInitCs(flashConfig->csTag);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool flashIsReady(void)
|
||||
{
|
||||
return flashDevice.vTable->isReady(&flashDevice);
|
||||
}
|
||||
|
||||
bool flashWaitForReady(uint32_t timeoutMillis)
|
||||
{
|
||||
return flashDevice.vTable->waitForReady(&flashDevice, timeoutMillis);
|
||||
}
|
||||
|
||||
void flashEraseSector(uint32_t address)
|
||||
{
|
||||
flashDevice.vTable->eraseSector(&flashDevice, address);
|
||||
}
|
||||
|
||||
void flashEraseCompletely(void)
|
||||
{
|
||||
flashDevice.vTable->eraseCompletely(&flashDevice);
|
||||
}
|
||||
|
||||
void flashPageProgramBegin(uint32_t address)
|
||||
{
|
||||
flashDevice.vTable->pageProgramBegin(&flashDevice, address);
|
||||
}
|
||||
|
||||
void flashPageProgramContinue(const uint8_t *data, int length)
|
||||
{
|
||||
flashDevice.vTable->pageProgramContinue(&flashDevice, data, length);
|
||||
}
|
||||
|
||||
void flashPageProgramFinish(void)
|
||||
{
|
||||
flashDevice.vTable->pageProgramFinish(&flashDevice);
|
||||
}
|
||||
|
||||
void flashPageProgram(uint32_t address, const uint8_t *data, int length)
|
||||
{
|
||||
flashDevice.vTable->pageProgram(&flashDevice, address, data, length);
|
||||
}
|
||||
|
||||
int flashReadBytes(uint32_t address, uint8_t *buffer, int length)
|
||||
{
|
||||
return flashDevice.vTable->readBytes(&flashDevice, address, buffer, length);
|
||||
}
|
||||
|
||||
void flashFlush(void)
|
||||
{
|
||||
flashDevice.vTable->flush(&flashDevice);
|
||||
}
|
||||
|
||||
static const flashGeometry_t noFlashGeometry = {
|
||||
.totalSize = 0,
|
||||
};
|
||||
|
||||
const flashGeometry_t *flashGetGeometry(void)
|
||||
{
|
||||
if (flashDevice.vTable && flashDevice.vTable->getGeometry) {
|
||||
return flashDevice.vTable->getGeometry(&flashDevice);
|
||||
}
|
||||
|
||||
return &noFlashGeometry;
|
||||
}
|
||||
#endif // USE_FLASH
|
Loading…
Add table
Add a link
Reference in a new issue