2015-02-23 08:17:26 +00:00
|
|
|
#include "hal.h"
|
|
|
|
#include "flash_memory.h"
|
|
|
|
|
|
|
|
static const unsigned short _SERIAL_FLASH_CMD_RDID = 0x9F; // 25P80
|
|
|
|
static const unsigned short _SERIAL_FLASH_CMD_READ = 0x03;
|
|
|
|
static const unsigned short _SERIAL_FLASH_CMD_WRITE = 0x02;
|
|
|
|
static const unsigned short _SERIAL_FLASH_CMD_WREN = 0x06;
|
|
|
|
static const unsigned short _SERIAL_FLASH_CMD_RDSR = 0x05;
|
|
|
|
static const unsigned short _SERIAL_FLASH_CMD_ERASE = 0xC7; // 25P80
|
|
|
|
static const unsigned short _SERIAL_FLASH_CMD_EWSR = 0x06; // 25P80
|
|
|
|
static const unsigned short _SERIAL_FLASH_CMD_WRSR = 0x01;
|
|
|
|
static const unsigned short _SERIAL_FLASH_CMD_SER = 0xD8; //25P80
|
|
|
|
|
|
|
|
static const SPIConfig flash_spicfg = {
|
|
|
|
0,
|
|
|
|
GPIOD,
|
|
|
|
GPIOD_FLASH_CS,
|
|
|
|
0
|
|
|
|
};
|
|
|
|
|
|
|
|
bool flash_is_write_busy(void) {
|
2018-11-03 00:51:23 +00:00
|
|
|
static gU8 is_write_busy_cmd[1];
|
2015-02-23 08:17:26 +00:00
|
|
|
is_write_busy_cmd[0] = _SERIAL_FLASH_CMD_RDSR;
|
|
|
|
|
2018-11-03 00:51:23 +00:00
|
|
|
gU8 result[1];
|
2015-02-23 08:17:26 +00:00
|
|
|
|
|
|
|
spiAcquireBus(&SPID3);
|
|
|
|
spiStart(&SPID3, &flash_spicfg);
|
|
|
|
spiSelect(&SPID3);
|
|
|
|
spiSend(&SPID3, sizeof(is_write_busy_cmd), is_write_busy_cmd);
|
|
|
|
spiReceive(&SPID3, sizeof(result), result);
|
|
|
|
spiUnselect(&SPID3);
|
|
|
|
spiReleaseBus(&SPID3);
|
|
|
|
|
|
|
|
return result[0]&0x01;
|
|
|
|
}
|
|
|
|
|
|
|
|
void flash_write_enable(void) {
|
|
|
|
spiAcquireBus(&SPID3);
|
|
|
|
spiStart(&SPID3, &flash_spicfg);
|
|
|
|
spiSelect(&SPID3);
|
|
|
|
spiSend(&SPID3, 1, &_SERIAL_FLASH_CMD_WREN);
|
|
|
|
spiUnselect(&SPID3);
|
|
|
|
spiReleaseBus(&SPID3);
|
|
|
|
}
|
|
|
|
|
2018-11-03 00:51:23 +00:00
|
|
|
void flash_sector_erase(gU32 sector) {
|
2015-02-23 08:17:26 +00:00
|
|
|
flash_write_enable();
|
2018-11-03 00:51:23 +00:00
|
|
|
static gU8 sector_erase_cmd[4];
|
2015-02-23 08:17:26 +00:00
|
|
|
sector_erase_cmd[0] = _SERIAL_FLASH_CMD_SER;
|
|
|
|
sector_erase_cmd[1] = (sector >> 16) & 0xFF;
|
|
|
|
sector_erase_cmd[2] = (sector >> 8) & 0xFF;
|
|
|
|
sector_erase_cmd[3] = sector & 0xFF;
|
|
|
|
|
|
|
|
|
|
|
|
spiAcquireBus(&SPID3);
|
|
|
|
spiStart(&SPID3, &flash_spicfg);
|
|
|
|
spiSelect(&SPID3);
|
|
|
|
spiSend(&SPID3, sizeof(sector_erase_cmd), sector_erase_cmd);
|
|
|
|
spiUnselect(&SPID3);
|
|
|
|
spiReleaseBus(&SPID3);
|
|
|
|
|
|
|
|
/* wait for complete */
|
|
|
|
while(flash_is_write_busy());
|
|
|
|
}
|
|
|
|
|
2018-11-03 00:51:23 +00:00
|
|
|
void flash_read(gU32 address, gMemSize bytes, gU8 *out) {
|
|
|
|
static gU8 sector_read_cmd[4];
|
2015-02-23 08:17:26 +00:00
|
|
|
sector_read_cmd[0] = _SERIAL_FLASH_CMD_READ;
|
|
|
|
sector_read_cmd[1] = (address >> 16) & 0xFF;
|
|
|
|
sector_read_cmd[2] = (address >> 8) & 0xFF;
|
|
|
|
sector_read_cmd[3] = address & 0xFF;
|
|
|
|
|
|
|
|
spiAcquireBus(&SPID3);
|
|
|
|
spiStart(&SPID3, &flash_spicfg);
|
|
|
|
spiSelect(&SPID3);
|
|
|
|
spiSend(&SPID3, sizeof(sector_read_cmd), sector_read_cmd);
|
|
|
|
spiReceive(&SPID3, bytes, out);
|
|
|
|
spiUnselect(&SPID3);
|
|
|
|
spiReleaseBus(&SPID3);
|
|
|
|
}
|
|
|
|
|
2018-11-03 00:51:23 +00:00
|
|
|
void flash_write(gU32 address, gMemSize bytes, const gU8 *data) {
|
|
|
|
static gU8 flash_write_cmd[4];
|
2015-02-23 08:17:26 +00:00
|
|
|
|
|
|
|
flash_write_enable();
|
|
|
|
|
|
|
|
flash_write_cmd[0] = _SERIAL_FLASH_CMD_WRITE;
|
|
|
|
flash_write_cmd[1] = (address >> 16) & 0xFF;
|
|
|
|
flash_write_cmd[2] = (address >> 8) & 0xFF;
|
|
|
|
flash_write_cmd[3] = address & 0xFF;
|
|
|
|
|
|
|
|
spiAcquireBus(&SPID3);
|
|
|
|
spiStart(&SPID3, &flash_spicfg);
|
|
|
|
spiSelect(&SPID3);
|
|
|
|
spiSend(&SPID3, sizeof(flash_write_cmd), flash_write_cmd);
|
|
|
|
spiSend(&SPID3, bytes, data);
|
|
|
|
spiUnselect(&SPID3);
|
|
|
|
spiReleaseBus(&SPID3);
|
|
|
|
|
|
|
|
/* wait for complete */
|
|
|
|
while(flash_is_write_busy());
|
|
|
|
}
|
|
|
|
|
|
|
|
bool flash_tp_calibrated(void) {
|
2018-11-03 00:51:23 +00:00
|
|
|
gU8 out[1];
|
2015-02-23 08:17:26 +00:00
|
|
|
flash_read(0x0F0000, 1, out);
|
|
|
|
|
|
|
|
return (out[0] == 0x01);
|
|
|
|
}
|
|
|
|
|
2018-11-03 00:51:23 +00:00
|
|
|
void flash_tp_calibration_save(gU16 instance, const gU8 *calbuf, gMemSize sz) {
|
2015-02-23 08:17:26 +00:00
|
|
|
if (instance) return;
|
|
|
|
flash_sector_erase(0x0F0000);
|
2018-11-03 00:51:23 +00:00
|
|
|
gU8 calibrated = 0x01;
|
2015-02-23 08:17:26 +00:00
|
|
|
flash_write(0x0F0000, 1, &calibrated);
|
|
|
|
flash_write(0x0F0001, sz, calbuf);
|
|
|
|
}
|
2018-11-03 00:51:23 +00:00
|
|
|
const char *flash_tp_calibration_load(gU16 instance) {
|
|
|
|
static gU8 foo[24];
|
2015-02-23 08:17:26 +00:00
|
|
|
|
|
|
|
if (instance) return 0;
|
|
|
|
if (!flash_tp_calibrated()) return 0;
|
|
|
|
flash_read(0x0F0001, 24, foo);
|
|
|
|
|
|
|
|
return (char *)foo;
|
|
|
|
}
|