kopia lustrzana https://github.com/DL7AD/pecanpico10
Changes:
- Fix bug in flash sector allocation for F413. - Fix bug in rxafsk releasing object FIFO.Development
rodzic
61188565ab
commit
a6e0c85e4d
|
@ -209,7 +209,7 @@ const SerialConfig debug_config = {
|
|||
/*===========================================================================*/
|
||||
|
||||
void pktConfigSerialDiag(void) {
|
||||
#if ENABLE_EXTERNAL_I2C == FALSE
|
||||
#if ENABLE_EXTERNAL_I2C == FALSE && ENABLE_SERIAL_DEBUG == TRUE
|
||||
/* USART3 TX. */
|
||||
palSetLineMode(LINE_USART3_TX, PAL_MODE_ALTERNATE(7));
|
||||
/* USART3 RX. */
|
||||
|
@ -234,7 +234,7 @@ uint8_t pktReadIOlines() {
|
|||
void pktSerialStart(void) {
|
||||
#if ENABLE_SERIAL_DEBUG == TRUE
|
||||
pktConfigSerialDiag();
|
||||
sdStart(SERIAL_CFG_DEBUG_DRIVER, &debug_config);
|
||||
sdStart(&SERIAL_CFG_DEBUG_DRIVER, &debug_config);
|
||||
#endif
|
||||
/* Setup diagnostic resource access semaphore. */
|
||||
//extern binary_semaphore_t debug_out_sem;
|
||||
|
@ -244,7 +244,7 @@ void pktSerialStart(void) {
|
|||
void dbgWrite(uint8_t level, uint8_t *buf, uint32_t len) {
|
||||
(void)level;
|
||||
#if ENABLE_SERIAL_DEBUG == TRUE
|
||||
chnWrite((BaseSequentialStream*)SERIAL_CFG_DEBUG_DRIVER, buf, len);
|
||||
chnWrite((BaseSequentialStream*)&SERIAL_CFG_DEBUG_DRIVER, buf, len);
|
||||
#else
|
||||
(void)buf;
|
||||
(void)len;
|
||||
|
@ -270,7 +270,7 @@ int dbgPrintf(uint8_t level, const char *format, ...) {
|
|||
|
||||
void pktWrite(uint8_t *buf, uint32_t len) {
|
||||
#if ENABLE_SERIAL_DEBUG == TRUE
|
||||
chnWrite((BaseSequentialStream*)SERIAL_CFG_DEBUG_DRIVER, buf, len);
|
||||
chnWrite((BaseSequentialStream*)&SERIAL_CFG_DEBUG_DRIVER, buf, len);
|
||||
#else
|
||||
(void)buf;
|
||||
(void)len;
|
||||
|
|
|
@ -161,7 +161,7 @@
|
|||
//#define LINE_UART4_RX PAL_LINE(GPIOA, 11U)
|
||||
|
||||
/* The external port can be used for bit bang I2C. */
|
||||
#define ENABLE_EXTERNAL_I2C TRUE
|
||||
#define ENABLE_EXTERNAL_I2C FALSE
|
||||
|
||||
#define EI2C_SCL LINE_IO_TXD /* SCL */
|
||||
#define EI2C_SDA LINE_IO_RXD /* SDA */
|
||||
|
|
|
@ -239,9 +239,6 @@
|
|||
#define GPIOK_PIN14 14U
|
||||
#define GPIOK_PIN15 15U
|
||||
|
||||
/*
|
||||
* IO lines assignments.
|
||||
*/
|
||||
|
||||
/* For enabling TCXO. Done in early_init. */
|
||||
#define LINE_TCXO_EN PAL_LINE(GPIOC, 13U)
|
||||
|
|
|
@ -214,16 +214,6 @@ void pktConfigSerialDiag(void) {
|
|||
palSetLineMode(LINE_USART3_RX, PAL_MODE_ALTERNATE(7));
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Move this into pktradio.c or make it an Si446x function in si446x.c
|
||||
* The GPIO assignments per radio should be in the radio record.
|
||||
*/
|
||||
/*ioline_t pktSetLineModeICU(const radio_unit_t radio) {
|
||||
(void)radio;
|
||||
palSetLineMode(LINE_ICU, PAL_MODE_INPUT | PAL_MODE_ALTERNATE(2));
|
||||
return LINE_ICU;
|
||||
}*/
|
||||
|
||||
/*
|
||||
* Read GPIO that are used for:
|
||||
* a) general use
|
||||
|
|
|
@ -29,7 +29,7 @@ const conf_t conf_flash_default = {
|
|||
.cca = 0x5F,
|
||||
},
|
||||
// App identity
|
||||
.call = "VK2GJ-6",
|
||||
.call = "VK2GJ-5",
|
||||
.path = "WIDE1-1",
|
||||
.symbol = SYM_DIGIPEATER,
|
||||
.aprs_msg = false, // Enable APRS message reception on this app
|
||||
|
@ -141,8 +141,8 @@ const conf_t conf_flash_default = {
|
|||
// If duration is TIME_INFINITE then the radio stays active while the thread waits forever.
|
||||
.active = true,
|
||||
.init_delay = TIME_S2I(20),
|
||||
.cycle = CYCLE_CONTINUOUSLY,
|
||||
.interval = 0
|
||||
.cycle = TIME_S2I(60),
|
||||
.interval = TIME_S2I(45)
|
||||
},
|
||||
// Receive radio configuration
|
||||
.radio_conf = {
|
||||
|
@ -165,7 +165,7 @@ const conf_t conf_flash_default = {
|
|||
.cca = 0x5F
|
||||
},
|
||||
// Digipeat transmission identity
|
||||
.call = "VK2GJ-6",
|
||||
.call = "VK2GJ-5",
|
||||
.path = "WIDE2-1",
|
||||
.symbol = SYM_DIGIPEATER,
|
||||
// A digipeater beacon can be added using one of the POS apps
|
||||
|
|
|
@ -248,16 +248,16 @@ THD_FUNCTION(pktConsole, arg) {
|
|||
event_listener_t shell_el;
|
||||
|
||||
/*Wait for start permission. */
|
||||
thread_t *initiator = chMsgWait();
|
||||
(void)chMsgGet(initiator);
|
||||
//thread_t *initiator = chMsgWait();
|
||||
//(void)chMsgGet(initiator);
|
||||
|
||||
console_state = CON_CHN_INIT;
|
||||
|
||||
/* Signal that basic init is done. */
|
||||
chMsgRelease(initiator, MSG_OK);
|
||||
//chMsgRelease(initiator, MSG_OK);
|
||||
|
||||
/* Wait for serial channel to be started for us. */
|
||||
initiator = chMsgWait();
|
||||
thread_t *initiator = chMsgWait();
|
||||
(void)chMsgGet(initiator);
|
||||
|
||||
/* Attach event listener to serial channel. */
|
||||
|
@ -273,6 +273,9 @@ THD_FUNCTION(pktConsole, arg) {
|
|||
NULL
|
||||
};
|
||||
|
||||
(void)chEvtGetAndClearEvents(CONSOLE_CHANNEL_EVT);
|
||||
(void)chEvtGetAndClearFlags(&con_el);
|
||||
|
||||
/* Flag that channel setup is done. */
|
||||
chMsgRelease(initiator, MSG_OK);
|
||||
|
||||
|
@ -334,7 +337,7 @@ THD_FUNCTION(pktConsole, arg) {
|
|||
console_state = CON_CHN_SHELL;
|
||||
/* Wait for next event. */
|
||||
continue;
|
||||
} /* End case CON_CHN_CONNECT or CON_CHN_WAIT. */
|
||||
} /* End case CON_CHN_CONNECT, CON_CHN_WAIT or CON_CHN_FLUSH. */
|
||||
|
||||
default:
|
||||
/* Check if there was a shell event. */
|
||||
|
@ -404,7 +407,7 @@ msg_t pktStartConsole(BaseAsynchronousChannel *ser) {
|
|||
msg_t smsg = chMsgSend(con_thd, MSG_OK);
|
||||
|
||||
/* Signal thread to enter trace output and shell request monitoring. */
|
||||
smsg = chMsgSend(con_thd, MSG_OK);
|
||||
//smsg = chMsgSend(con_thd, MSG_OK);
|
||||
|
||||
return smsg;
|
||||
}
|
||||
|
|
|
@ -111,7 +111,7 @@ void debug_print(char *type, char* filename, uint32_t line, char* format, ...)
|
|||
chvprintf((BaseSequentialStream*)&SERIAL_DEBUG_DRIVER, format, args);
|
||||
va_end(args);
|
||||
chprintf((BaseSequentialStream*)&SERIAL_DEBUG_DRIVER, "\r\n");
|
||||
#endif
|
||||
#endif /* ENABLE_SERIAL_DEBUG == TRUE */
|
||||
|
||||
chMtxUnlock(&debug_mtx);
|
||||
}
|
||||
|
|
|
@ -1,278 +1,280 @@
|
|||
/**
|
||||
* Flash driver
|
||||
* The driver code origin is
|
||||
* https://github.com/mabl/ARMCM3-STM32F107-BOOTLOADER/tree/master/ARMCM3-STM32F107-BOOTLOADER/flash
|
||||
* https://github.com/tegesoft/flash-stm32f407/tree/master/flash
|
||||
*/
|
||||
|
||||
#include "flash.h"
|
||||
#include <string.h>
|
||||
|
||||
size_t flashSectorSize(flashsector_t sector)
|
||||
{
|
||||
if (sector <= 3)
|
||||
return 16 * 1024;
|
||||
else if (sector == 4)
|
||||
return 64 * 1024;
|
||||
else if (sector >= 5 && sector <= 11)
|
||||
return 128 * 1024;
|
||||
return 0;
|
||||
}
|
||||
|
||||
flashaddr_t flashSectorBegin(flashsector_t sector)
|
||||
{
|
||||
flashaddr_t address = FLASH_BASE;
|
||||
while (sector > 0)
|
||||
{
|
||||
--sector;
|
||||
address += flashSectorSize(sector);
|
||||
}
|
||||
return address;
|
||||
}
|
||||
|
||||
flashaddr_t flashSectorEnd(flashsector_t sector)
|
||||
{
|
||||
return flashSectorBegin(sector + 1);
|
||||
}
|
||||
|
||||
flashsector_t flashSectorAt(flashaddr_t address)
|
||||
{
|
||||
flashsector_t sector = 0;
|
||||
while (address >= flashSectorEnd(sector))
|
||||
++sector;
|
||||
return sector;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Wait for the flash operation to finish.
|
||||
*/
|
||||
#define flashWaitWhileBusy() { while (FLASH->SR & FLASH_SR_BSY) {} }
|
||||
|
||||
/**
|
||||
* @brief Unlock the flash memory for write access.
|
||||
* @return TRUE Unlock was successful.
|
||||
* @return FALSE Unlock failed.
|
||||
*/
|
||||
static bool flashUnlock(void)
|
||||
{
|
||||
/* Check if unlock is really needed */
|
||||
if (!(FLASH->CR & FLASH_CR_LOCK))
|
||||
return TRUE;
|
||||
|
||||
/* Write magic unlock sequence */
|
||||
FLASH->KEYR = 0x45670123;
|
||||
FLASH->KEYR = 0xCDEF89AB;
|
||||
|
||||
/* Check if unlock was successful */
|
||||
if (FLASH->CR & FLASH_CR_LOCK)
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Lock the flash memory for write access.
|
||||
*/
|
||||
#define flashLock() { FLASH->CR |= FLASH_CR_LOCK; }
|
||||
|
||||
int flashSectorErase(flashsector_t sector)
|
||||
{
|
||||
/* Unlock flash for write access */
|
||||
if(flashUnlock() == FALSE)
|
||||
return FLASH_RETURN_NO_PERMISSION;
|
||||
|
||||
/* Wait for any busy flags. */
|
||||
flashWaitWhileBusy();
|
||||
|
||||
/* Setup parallelism before any program/erase */
|
||||
FLASH->CR &= ~FLASH_CR_PSIZE_MASK;
|
||||
FLASH->CR |= FLASH_CR_PSIZE_VALUE;
|
||||
|
||||
/* Start deletion of sector.
|
||||
* SNB(3:1) is defined as:
|
||||
* 0000 sector 0
|
||||
* 0001 sector 1
|
||||
* ...
|
||||
* 1011 sector 11
|
||||
* others not allowed */
|
||||
FLASH->CR &= ~(FLASH_CR_SNB_0 | FLASH_CR_SNB_1 | FLASH_CR_SNB_2 | FLASH_CR_SNB_3);
|
||||
if (sector & 0x1) FLASH->CR |= FLASH_CR_SNB_0;
|
||||
if (sector & 0x2) FLASH->CR |= FLASH_CR_SNB_1;
|
||||
if (sector & 0x4) FLASH->CR |= FLASH_CR_SNB_2;
|
||||
if (sector & 0x8) FLASH->CR |= FLASH_CR_SNB_3;
|
||||
FLASH->CR |= FLASH_CR_SER;
|
||||
FLASH->CR |= FLASH_CR_STRT;
|
||||
|
||||
/* Wait until it's finished. */
|
||||
flashWaitWhileBusy();
|
||||
|
||||
/* Sector erase flag does not clear automatically. */
|
||||
FLASH->CR &= ~FLASH_CR_SER;
|
||||
|
||||
/* Lock flash again */
|
||||
flashLock();
|
||||
|
||||
/* Check deleted sector for errors */
|
||||
if (flashIsErased(flashSectorBegin(sector), flashSectorSize(sector)) == FALSE)
|
||||
return FLASH_RETURN_BAD_FLASH; /* Sector is not empty despite the erase cycle! */
|
||||
|
||||
/* Successfully deleted sector */
|
||||
return FLASH_RETURN_SUCCESS;
|
||||
}
|
||||
|
||||
int flashErase(flashaddr_t address, size_t size)
|
||||
{
|
||||
while (size > 0)
|
||||
{
|
||||
flashsector_t sector = flashSectorAt(address);
|
||||
int err = flashSectorErase(sector);
|
||||
if (err != FLASH_RETURN_SUCCESS)
|
||||
return err;
|
||||
address = flashSectorEnd(sector);
|
||||
size_t sector_size = flashSectorSize(sector);
|
||||
if (sector_size >= size)
|
||||
break;
|
||||
else
|
||||
size -= sector_size;
|
||||
}
|
||||
|
||||
return FLASH_RETURN_SUCCESS;
|
||||
}
|
||||
|
||||
bool flashIsErased(flashaddr_t address, size_t size)
|
||||
{
|
||||
/* Check for default set bits in the flash memory
|
||||
* For efficiency, compare flashdata_t values as much as possible,
|
||||
* then, fallback to byte per byte comparison. */
|
||||
while (size >= sizeof(flashdata_t))
|
||||
{
|
||||
if (*(volatile flashdata_t*)address != (flashdata_t)(-1)) // flashdata_t being unsigned, -1 is 0xFF..FF
|
||||
return FALSE;
|
||||
address += sizeof(flashdata_t);
|
||||
size -= sizeof(flashdata_t);
|
||||
}
|
||||
while (size > 0)
|
||||
{
|
||||
if (*(char*)address != 0xff)
|
||||
return FALSE;
|
||||
++address;
|
||||
--size;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool flashCompare(flashaddr_t address, const char* buffer, size_t size)
|
||||
{
|
||||
/* For efficiency, compare flashdata_t values as much as possible,
|
||||
* then, fallback to byte per byte comparison. */
|
||||
while (size >= sizeof(flashdata_t))
|
||||
{
|
||||
if (*(volatile flashdata_t*)address != *(flashdata_t*)buffer)
|
||||
return FALSE;
|
||||
address += sizeof(flashdata_t);
|
||||
buffer += sizeof(flashdata_t);
|
||||
size -= sizeof(flashdata_t);
|
||||
}
|
||||
while (size > 0)
|
||||
{
|
||||
if (*(volatile char*)address != *buffer)
|
||||
return FALSE;
|
||||
++address;
|
||||
++buffer;
|
||||
--size;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int flashRead(flashaddr_t address, char* buffer, size_t size)
|
||||
{
|
||||
memcpy(buffer, (char*)address, size);
|
||||
return FLASH_RETURN_SUCCESS;
|
||||
}
|
||||
|
||||
static void flashWriteData(flashaddr_t address, const flashdata_t data)
|
||||
{
|
||||
/* Enter flash programming mode */
|
||||
FLASH->CR |= FLASH_CR_PG;
|
||||
|
||||
/* Write the data */
|
||||
*(flashdata_t*)address = data;
|
||||
|
||||
/* Wait for completion */
|
||||
flashWaitWhileBusy();
|
||||
|
||||
/* Exit flash programming mode */
|
||||
FLASH->CR &= ~FLASH_CR_PG;
|
||||
}
|
||||
|
||||
int flashWrite(flashaddr_t address, const char* buffer, size_t size)
|
||||
{
|
||||
/* Unlock flash for write access */
|
||||
if(flashUnlock() == FALSE)
|
||||
return FLASH_RETURN_NO_PERMISSION;
|
||||
|
||||
/* Wait for any busy flags */
|
||||
flashWaitWhileBusy();
|
||||
|
||||
/* Setup parallelism before any program/erase */
|
||||
FLASH->CR &= ~FLASH_CR_PSIZE_MASK;
|
||||
FLASH->CR |= FLASH_CR_PSIZE_VALUE;
|
||||
|
||||
/* Check if the flash address is correctly aligned */
|
||||
size_t alignOffset = address % sizeof(flashdata_t);
|
||||
if (alignOffset != 0)
|
||||
{
|
||||
/* Not aligned, thus we have to read the data in flash already present
|
||||
* and update them with buffer's data */
|
||||
|
||||
/* Align the flash address correctly */
|
||||
flashaddr_t alignedFlashAddress = address - alignOffset;
|
||||
|
||||
/* Read already present data */
|
||||
flashdata_t tmp = *(volatile flashdata_t*)alignedFlashAddress;
|
||||
|
||||
/* Compute how much bytes one must update in the data read */
|
||||
size_t chunkSize = sizeof(flashdata_t) - alignOffset;
|
||||
if (chunkSize > size)
|
||||
chunkSize = size; // this happens when both address and address + size are not aligned
|
||||
|
||||
/* Update the read data with buffer's data */
|
||||
memcpy((char*)&tmp + alignOffset, buffer, chunkSize);
|
||||
|
||||
/* Write the new data in flash */
|
||||
flashWriteData(alignedFlashAddress, tmp);
|
||||
|
||||
/* Advance */
|
||||
address += chunkSize;
|
||||
buffer += chunkSize;
|
||||
size -= chunkSize;
|
||||
}
|
||||
|
||||
/* Now, address is correctly aligned. One can copy data directly from
|
||||
* buffer's data to flash memory until the size of the data remaining to be
|
||||
* copied requires special treatment. */
|
||||
while (size >= sizeof(flashdata_t))
|
||||
{
|
||||
flashWriteData(address, *(const flashdata_t*)buffer);
|
||||
address += sizeof(flashdata_t);
|
||||
buffer += sizeof(flashdata_t);
|
||||
size -= sizeof(flashdata_t);
|
||||
}
|
||||
|
||||
/* Now, address is correctly aligned, but the remaining data are to
|
||||
* small to fill a entier flashdata_t. Thus, one must read data already
|
||||
* in flash and update them with buffer's data before writing an entire
|
||||
* flashdata_t to flash memory. */
|
||||
if (size > 0)
|
||||
{
|
||||
flashdata_t tmp = *(volatile flashdata_t*)address;
|
||||
memcpy(&tmp, buffer, size);
|
||||
flashWriteData(address, tmp);
|
||||
}
|
||||
|
||||
/* Lock flash again */
|
||||
flashLock();
|
||||
|
||||
return FLASH_RETURN_SUCCESS;
|
||||
}
|
||||
/**
|
||||
* Flash driver
|
||||
* The driver code origin is
|
||||
* https://github.com/mabl/ARMCM3-STM32F107-BOOTLOADER/tree/master/ARMCM3-STM32F107-BOOTLOADER/flash
|
||||
* https://github.com/tegesoft/flash-stm32f407/tree/master/flash
|
||||
*/
|
||||
|
||||
#include "flash.h"
|
||||
#include <string.h>
|
||||
|
||||
/* TODO: The flash driver needs to be dynamically defined based on MCU. */
|
||||
size_t flashSectorSize(flashsector_t sector)
|
||||
{
|
||||
if (sector <= 3)
|
||||
return 16 * 1024;
|
||||
else if (sector == 4)
|
||||
return 64 * 1024;
|
||||
else if (sector >= 5 && sector < FLASH_SECTOR_COUNT)
|
||||
return 128 * 1024;
|
||||
return 0;
|
||||
}
|
||||
|
||||
flashaddr_t flashSectorBegin(flashsector_t sector)
|
||||
{
|
||||
flashaddr_t address = FLASH_BASE;
|
||||
chDbgAssert(sector < FLASH_SECTOR_COUNT, "Invalid flash sector index");
|
||||
while (sector > 0)
|
||||
{
|
||||
--sector;
|
||||
address += flashSectorSize(sector);
|
||||
}
|
||||
return address;
|
||||
}
|
||||
|
||||
flashaddr_t flashSectorEnd(flashsector_t sector)
|
||||
{
|
||||
return flashSectorBegin(sector + 1);
|
||||
}
|
||||
|
||||
flashsector_t flashSectorAt(flashaddr_t address)
|
||||
{
|
||||
flashsector_t sector = 0;
|
||||
while (address >= flashSectorEnd(sector))
|
||||
++sector;
|
||||
return sector;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Wait for the flash operation to finish.
|
||||
*/
|
||||
#define flashWaitWhileBusy() { while (FLASH->SR & FLASH_SR_BSY) {} }
|
||||
|
||||
/**
|
||||
* @brief Unlock the flash memory for write access.
|
||||
* @return TRUE Unlock was successful.
|
||||
* @return FALSE Unlock failed.
|
||||
*/
|
||||
static bool flashUnlock(void)
|
||||
{
|
||||
/* Check if unlock is really needed */
|
||||
if (!(FLASH->CR & FLASH_CR_LOCK))
|
||||
return TRUE;
|
||||
|
||||
/* Write magic unlock sequence */
|
||||
FLASH->KEYR = 0x45670123;
|
||||
FLASH->KEYR = 0xCDEF89AB;
|
||||
|
||||
/* Check if unlock was successful */
|
||||
if (FLASH->CR & FLASH_CR_LOCK)
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Lock the flash memory for write access.
|
||||
*/
|
||||
#define flashLock() { FLASH->CR |= FLASH_CR_LOCK; }
|
||||
|
||||
int flashSectorErase(flashsector_t sector)
|
||||
{
|
||||
/* Unlock flash for write access */
|
||||
if(flashUnlock() == FALSE)
|
||||
return FLASH_RETURN_NO_PERMISSION;
|
||||
|
||||
/* Wait for any busy flags. */
|
||||
flashWaitWhileBusy();
|
||||
|
||||
/* Setup parallelism before any program/erase */
|
||||
FLASH->CR &= ~FLASH_CR_PSIZE_MASK;
|
||||
FLASH->CR |= FLASH_CR_PSIZE_VALUE;
|
||||
|
||||
/* Start deletion of sector.
|
||||
* SNB(3:1) is defined as:
|
||||
* 0000 sector 0
|
||||
* 0001 sector 1
|
||||
* ...
|
||||
* 1011 sector 11
|
||||
* others not allowed */
|
||||
FLASH->CR &= ~(FLASH_CR_SNB_0 | FLASH_CR_SNB_1 | FLASH_CR_SNB_2 | FLASH_CR_SNB_3);
|
||||
if (sector & 0x1) FLASH->CR |= FLASH_CR_SNB_0;
|
||||
if (sector & 0x2) FLASH->CR |= FLASH_CR_SNB_1;
|
||||
if (sector & 0x4) FLASH->CR |= FLASH_CR_SNB_2;
|
||||
if (sector & 0x8) FLASH->CR |= FLASH_CR_SNB_3;
|
||||
FLASH->CR |= FLASH_CR_SER;
|
||||
FLASH->CR |= FLASH_CR_STRT;
|
||||
|
||||
/* Wait until it's finished. */
|
||||
flashWaitWhileBusy();
|
||||
|
||||
/* Sector erase flag does not clear automatically. */
|
||||
FLASH->CR &= ~FLASH_CR_SER;
|
||||
|
||||
/* Lock flash again */
|
||||
flashLock();
|
||||
|
||||
/* Check deleted sector for errors */
|
||||
if (flashIsErased(flashSectorBegin(sector), flashSectorSize(sector)) == FALSE)
|
||||
return FLASH_RETURN_BAD_FLASH; /* Sector is not empty despite the erase cycle! */
|
||||
|
||||
/* Successfully deleted sector */
|
||||
return FLASH_RETURN_SUCCESS;
|
||||
}
|
||||
|
||||
int flashErase(flashaddr_t address, size_t size)
|
||||
{
|
||||
while (size > 0)
|
||||
{
|
||||
flashsector_t sector = flashSectorAt(address);
|
||||
int err = flashSectorErase(sector);
|
||||
if (err != FLASH_RETURN_SUCCESS)
|
||||
return err;
|
||||
address = flashSectorEnd(sector);
|
||||
size_t sector_size = flashSectorSize(sector);
|
||||
if (sector_size >= size)
|
||||
break;
|
||||
else
|
||||
size -= sector_size;
|
||||
}
|
||||
|
||||
return FLASH_RETURN_SUCCESS;
|
||||
}
|
||||
|
||||
bool flashIsErased(flashaddr_t address, size_t size)
|
||||
{
|
||||
/* Check for default set bits in the flash memory
|
||||
* For efficiency, compare flashdata_t values as much as possible,
|
||||
* then, fallback to byte per byte comparison. */
|
||||
while (size >= sizeof(flashdata_t))
|
||||
{
|
||||
if (*(volatile flashdata_t*)address != (flashdata_t)(-1)) // flashdata_t being unsigned, -1 is 0xFF..FF
|
||||
return FALSE;
|
||||
address += sizeof(flashdata_t);
|
||||
size -= sizeof(flashdata_t);
|
||||
}
|
||||
while (size > 0)
|
||||
{
|
||||
if (*(char*)address != 0xff)
|
||||
return FALSE;
|
||||
++address;
|
||||
--size;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool flashCompare(flashaddr_t address, const char* buffer, size_t size)
|
||||
{
|
||||
/* For efficiency, compare flashdata_t values as much as possible,
|
||||
* then, fallback to byte per byte comparison. */
|
||||
while (size >= sizeof(flashdata_t))
|
||||
{
|
||||
if (*(volatile flashdata_t*)address != *(flashdata_t*)buffer)
|
||||
return FALSE;
|
||||
address += sizeof(flashdata_t);
|
||||
buffer += sizeof(flashdata_t);
|
||||
size -= sizeof(flashdata_t);
|
||||
}
|
||||
while (size > 0)
|
||||
{
|
||||
if (*(volatile char*)address != *buffer)
|
||||
return FALSE;
|
||||
++address;
|
||||
++buffer;
|
||||
--size;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int flashRead(flashaddr_t address, char* buffer, size_t size)
|
||||
{
|
||||
memcpy(buffer, (char*)address, size);
|
||||
return FLASH_RETURN_SUCCESS;
|
||||
}
|
||||
|
||||
static void flashWriteData(flashaddr_t address, const flashdata_t data)
|
||||
{
|
||||
/* Enter flash programming mode */
|
||||
FLASH->CR |= FLASH_CR_PG;
|
||||
|
||||
/* Write the data */
|
||||
*(flashdata_t*)address = data;
|
||||
|
||||
/* Wait for completion */
|
||||
flashWaitWhileBusy();
|
||||
|
||||
/* Exit flash programming mode */
|
||||
FLASH->CR &= ~FLASH_CR_PG;
|
||||
}
|
||||
|
||||
int flashWrite(flashaddr_t address, const char* buffer, size_t size)
|
||||
{
|
||||
/* Unlock flash for write access */
|
||||
if(flashUnlock() == FALSE)
|
||||
return FLASH_RETURN_NO_PERMISSION;
|
||||
|
||||
/* Wait for any busy flags */
|
||||
flashWaitWhileBusy();
|
||||
|
||||
/* Setup parallelism before any program/erase */
|
||||
FLASH->CR &= ~FLASH_CR_PSIZE_MASK;
|
||||
FLASH->CR |= FLASH_CR_PSIZE_VALUE;
|
||||
|
||||
/* Check if the flash address is correctly aligned */
|
||||
size_t alignOffset = address % sizeof(flashdata_t);
|
||||
if (alignOffset != 0)
|
||||
{
|
||||
/* Not aligned, thus we have to read the data in flash already present
|
||||
* and update them with buffer's data */
|
||||
|
||||
/* Align the flash address correctly */
|
||||
flashaddr_t alignedFlashAddress = address - alignOffset;
|
||||
|
||||
/* Read already present data */
|
||||
flashdata_t tmp = *(volatile flashdata_t*)alignedFlashAddress;
|
||||
|
||||
/* Compute how much bytes one must update in the data read */
|
||||
size_t chunkSize = sizeof(flashdata_t) - alignOffset;
|
||||
if (chunkSize > size)
|
||||
chunkSize = size; // this happens when both address and address + size are not aligned
|
||||
|
||||
/* Update the read data with buffer's data */
|
||||
memcpy((char*)&tmp + alignOffset, buffer, chunkSize);
|
||||
|
||||
/* Write the new data in flash */
|
||||
flashWriteData(alignedFlashAddress, tmp);
|
||||
|
||||
/* Advance */
|
||||
address += chunkSize;
|
||||
buffer += chunkSize;
|
||||
size -= chunkSize;
|
||||
}
|
||||
|
||||
/* Now, address is correctly aligned. One can copy data directly from
|
||||
* buffer's data to flash memory until the size of the data remaining to be
|
||||
* copied requires special treatment. */
|
||||
while (size >= sizeof(flashdata_t))
|
||||
{
|
||||
flashWriteData(address, *(const flashdata_t*)buffer);
|
||||
address += sizeof(flashdata_t);
|
||||
buffer += sizeof(flashdata_t);
|
||||
size -= sizeof(flashdata_t);
|
||||
}
|
||||
|
||||
/* Now, address is correctly aligned, but the remaining data are to
|
||||
* small to fill a entier flashdata_t. Thus, one must read data already
|
||||
* in flash and update them with buffer's data before writing an entire
|
||||
* flashdata_t to flash memory. */
|
||||
if (size > 0)
|
||||
{
|
||||
flashdata_t tmp = *(volatile flashdata_t*)address;
|
||||
memcpy(&tmp, buffer, size);
|
||||
flashWriteData(address, tmp);
|
||||
}
|
||||
|
||||
/* Lock flash again */
|
||||
flashLock();
|
||||
|
||||
return FLASH_RETURN_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -1,177 +1,178 @@
|
|||
/**
|
||||
* Flash driver
|
||||
* The driver code origin is
|
||||
* https://github.com/mabl/ARMCM3-STM32F107-BOOTLOADER/tree/master/ARMCM3-STM32F107-BOOTLOADER/flash
|
||||
* https://github.com/tegesoft/flash-stm32f407/tree/master/flash
|
||||
*/
|
||||
|
||||
#ifndef FLASH_H
|
||||
#define FLASH_H
|
||||
|
||||
#include <ch.h>
|
||||
#include <hal.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* @brief Number of sectors in the flash memory.
|
||||
*/
|
||||
#if !defined(FLASH_SECTOR_COUNT) || defined(__DOXYGEN__)
|
||||
#define FLASH_SECTOR_COUNT 12
|
||||
#endif
|
||||
|
||||
/* Error codes */
|
||||
|
||||
/** @brief Flash operation successful */
|
||||
#define FLASH_RETURN_SUCCESS TRUE
|
||||
|
||||
/** @brief Flash operation error because of denied access, corrupted memory.*/
|
||||
#define FLASH_RETURN_NO_PERMISSION -1
|
||||
|
||||
/** @brief Flash operation error because of bad flash, corrupted memory */
|
||||
#define FLASH_RETURN_BAD_FLASH -11
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Maximum program/erase parallelism
|
||||
*
|
||||
* FLASH_CR_PSIZE_MASK is the mask to configure the parallelism value.
|
||||
* FLASH_CR_PSIZE_VALUE is the parallelism value suitable for the voltage range.
|
||||
*
|
||||
* PSIZE(1:0) is defined as:
|
||||
* 00 to program 8 bits per step
|
||||
* 01 to program 16 bits per step
|
||||
* 10 to program 32 bits per step
|
||||
* 11 to program 64 bits per step
|
||||
*/
|
||||
// Warning, flashdata_t must be unsigned!!!
|
||||
#if defined(STM32F4XX) || defined(__DOXYGEN__)
|
||||
#define FLASH_CR_PSIZE_MASK FLASH_CR_PSIZE_0 | FLASH_CR_PSIZE_1
|
||||
#if ((STM32_VDD >= 270) && (STM32_VDD <= 360)) || defined(__DOXYGEN__)
|
||||
#define FLASH_CR_PSIZE_VALUE FLASH_CR_PSIZE_1
|
||||
typedef uint32_t flashdata_t;
|
||||
#elif (STM32_VDD >= 240) && (STM32_VDD < 270)
|
||||
#define FLASH_CR_PSIZE_VALUE FLASH_CR_PSIZE_0
|
||||
typedef uint16_t flashdata_t;
|
||||
#elif (STM32_VDD >= 210) && (STM32_VDD < 240)
|
||||
#define FLASH_CR_PSIZE_VALUE FLASH_CR_PSIZE_0
|
||||
typedef uint16_t flashdata_t;
|
||||
#elif (STM32_VDD >= 180) && (STM32_VDD < 210)
|
||||
#define FLASH_CR_PSIZE_VALUE ((uint32_t)0x00000000)
|
||||
typedef uint8_t flashdata_t;
|
||||
#else
|
||||
#error "invalid VDD voltage specified"
|
||||
#endif
|
||||
#endif /* defined(STM32F4XX) */
|
||||
|
||||
/** @brief Address in the flash memory */
|
||||
typedef uintptr_t flashaddr_t;
|
||||
|
||||
/** @brief Index of a sector */
|
||||
typedef uint8_t flashsector_t;
|
||||
|
||||
/**
|
||||
* @brief Get the size of @p sector.
|
||||
* @return @p sector size in bytes.
|
||||
*/
|
||||
size_t flashSectorSize(flashsector_t sector);
|
||||
|
||||
/**
|
||||
* @brief Get the beginning address of @p sector.
|
||||
* @param sector Sector to retrieve the beginning address of.
|
||||
* @return First address (inclusive) of @p sector.
|
||||
*/
|
||||
flashaddr_t flashSectorBegin(flashsector_t sector);
|
||||
|
||||
/**
|
||||
* @brief Get the end address of @p sector.
|
||||
* @param sector Sector to retrieve the end address of.
|
||||
* @return End address (exclusive) of @p sector (i.e. beginning address of the next sector).
|
||||
*/
|
||||
flashaddr_t flashSectorEnd(flashsector_t sector);
|
||||
|
||||
/**
|
||||
* @brief Get the sector containing @p address.
|
||||
* @warning @p address must be in the flash addresses range.
|
||||
* @param address Address to be searched for.
|
||||
* @return Sector containing @p address.
|
||||
*/
|
||||
flashsector_t flashSectorAt(flashaddr_t address);
|
||||
|
||||
/**
|
||||
* @brief Erase the flash @p sector.
|
||||
* @details The sector is checked for errors after erase.
|
||||
* @note The sector is deleted regardless of its current state.
|
||||
*
|
||||
* @param sector Sector which is going to be erased.
|
||||
* @return FLASH_RETURN_SUCCESS No error erasing the sector.
|
||||
* @return FLASH_RETURN_BAD_FLASH Flash cell error.
|
||||
* @return FLASH_RETURN_NO_PERMISSION Access denied.
|
||||
*/
|
||||
int flashSectorErase(flashsector_t sector);
|
||||
|
||||
/**
|
||||
* @brief Erase the sectors containing the span of @p size bytes starting at @p address.
|
||||
*
|
||||
* @warning If @p address doesn't match the beginning of a sector, the
|
||||
* data contained between the beginning of the sector and @p address will
|
||||
* be erased too. The same applies for data contained at @p address + @p size
|
||||
* up to the end of the sector.
|
||||
*
|
||||
* @param address Starting address of the span in flash memory.
|
||||
* @param size Size of the span in bytes.
|
||||
* @return FLASH_RETURN_SUCCESS No error erasing the flash memory.
|
||||
* @return FLASH_RETURN_BAD_FLASH Flash cell error.
|
||||
* @return FLASH_RETURN_NO_PERMISSION Access denied.
|
||||
*/
|
||||
int flashErase(flashaddr_t address, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Check if the @p size bytes of flash memory starting at @p address are erased.
|
||||
* @note If the memory is erased, one can write data into it safely.
|
||||
* @param address First address in flash memory to be checked.
|
||||
* @param size Size of the memory space to be checked in bytes.
|
||||
* @return TRUE Memory is already erased.
|
||||
* @return FALSE Memory is not erased.
|
||||
*/
|
||||
bool flashIsErased(flashaddr_t address, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Check if the data in @p buffer are identical to the one in flash memory.
|
||||
* @param address First address in flash memory to be checked.
|
||||
* @param buffer Buffer containing the data to compare.
|
||||
* @param size Size of @p buffer in bytes.
|
||||
* @return TRUE if the flash memory and the buffer contain identical data.
|
||||
* @return FALSE if the flash memory and the buffer don't contain identical data.
|
||||
*/
|
||||
bool flashCompare(flashaddr_t address, const char* buffer, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Copy data from the flash memory to a @p buffer.
|
||||
* @warning The @p buffer must be at least @p size bytes long.
|
||||
* @param address First address of the flash memory to be copied.
|
||||
* @param buffer Buffer to copy to.
|
||||
* @param size Size of the data to be copied in bytes.
|
||||
* @return FLASH_RETURN_SUCCESS if successfully copied.
|
||||
*/
|
||||
int flashRead(flashaddr_t address, char* buffer, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Copy data from a @p buffer to the flash memory.
|
||||
* @warning The flash memory area receiving the data must be erased.
|
||||
* @warning The @p buffer must be at least @p size bytes long.
|
||||
* @param address First address in the flash memory where to copy the data to.
|
||||
* @param buffer Buffer containing the data to copy.
|
||||
* @param size Size of the data to be copied in bytes.
|
||||
* @return FLASH_RETURN_SUCCESS No error.
|
||||
* @return FLASH_RETURN_NO_PERMISSION Access denied.
|
||||
*/
|
||||
int flashWrite(flashaddr_t address, const char* buffer, size_t size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* FLASH_H */
|
||||
/**
|
||||
* Flash driver
|
||||
* The driver code origin is
|
||||
* https://github.com/mabl/ARMCM3-STM32F107-BOOTLOADER/tree/master/ARMCM3-STM32F107-BOOTLOADER/flash
|
||||
* https://github.com/tegesoft/flash-stm32f407/tree/master/flash
|
||||
*/
|
||||
|
||||
#ifndef FLASH_H
|
||||
#define FLASH_H
|
||||
|
||||
#include <ch.h>
|
||||
#include <hal.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* @brief Number of sectors in the flash memory.
|
||||
* TODO: The flash driver needs to be dynamically defined based on MCU.
|
||||
*/
|
||||
#if !defined(FLASH_SECTOR_COUNT) || defined(__DOXYGEN__)
|
||||
#define FLASH_SECTOR_COUNT 16
|
||||
#endif
|
||||
|
||||
/* Error codes */
|
||||
|
||||
/** @brief Flash operation successful */
|
||||
#define FLASH_RETURN_SUCCESS TRUE
|
||||
|
||||
/** @brief Flash operation error because of denied access, corrupted memory.*/
|
||||
#define FLASH_RETURN_NO_PERMISSION -1
|
||||
|
||||
/** @brief Flash operation error because of bad flash, corrupted memory */
|
||||
#define FLASH_RETURN_BAD_FLASH -11
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Maximum program/erase parallelism
|
||||
*
|
||||
* FLASH_CR_PSIZE_MASK is the mask to configure the parallelism value.
|
||||
* FLASH_CR_PSIZE_VALUE is the parallelism value suitable for the voltage range.
|
||||
*
|
||||
* PSIZE(1:0) is defined as:
|
||||
* 00 to program 8 bits per step
|
||||
* 01 to program 16 bits per step
|
||||
* 10 to program 32 bits per step
|
||||
* 11 to program 64 bits per step
|
||||
*/
|
||||
// Warning, flashdata_t must be unsigned!!!
|
||||
#if defined(STM32F4XX) || defined(__DOXYGEN__)
|
||||
#define FLASH_CR_PSIZE_MASK FLASH_CR_PSIZE_0 | FLASH_CR_PSIZE_1
|
||||
#if ((STM32_VDD >= 270) && (STM32_VDD <= 360)) || defined(__DOXYGEN__)
|
||||
#define FLASH_CR_PSIZE_VALUE FLASH_CR_PSIZE_1
|
||||
typedef uint32_t flashdata_t;
|
||||
#elif (STM32_VDD >= 240) && (STM32_VDD < 270)
|
||||
#define FLASH_CR_PSIZE_VALUE FLASH_CR_PSIZE_0
|
||||
typedef uint16_t flashdata_t;
|
||||
#elif (STM32_VDD >= 210) && (STM32_VDD < 240)
|
||||
#define FLASH_CR_PSIZE_VALUE FLASH_CR_PSIZE_0
|
||||
typedef uint16_t flashdata_t;
|
||||
#elif (STM32_VDD >= 180) && (STM32_VDD < 210)
|
||||
#define FLASH_CR_PSIZE_VALUE ((uint32_t)0x00000000)
|
||||
typedef uint8_t flashdata_t;
|
||||
#else
|
||||
#error "invalid VDD voltage specified"
|
||||
#endif
|
||||
#endif /* defined(STM32F4XX) */
|
||||
|
||||
/** @brief Address in the flash memory */
|
||||
typedef uintptr_t flashaddr_t;
|
||||
|
||||
/** @brief Index of a sector */
|
||||
typedef uint8_t flashsector_t;
|
||||
|
||||
/**
|
||||
* @brief Get the size of @p sector.
|
||||
* @return @p sector size in bytes.
|
||||
*/
|
||||
size_t flashSectorSize(flashsector_t sector);
|
||||
|
||||
/**
|
||||
* @brief Get the beginning address of @p sector.
|
||||
* @param sector Sector to retrieve the beginning address of.
|
||||
* @return First address (inclusive) of @p sector.
|
||||
*/
|
||||
flashaddr_t flashSectorBegin(flashsector_t sector);
|
||||
|
||||
/**
|
||||
* @brief Get the end address of @p sector.
|
||||
* @param sector Sector to retrieve the end address of.
|
||||
* @return End address (exclusive) of @p sector (i.e. beginning address of the next sector).
|
||||
*/
|
||||
flashaddr_t flashSectorEnd(flashsector_t sector);
|
||||
|
||||
/**
|
||||
* @brief Get the sector containing @p address.
|
||||
* @warning @p address must be in the flash addresses range.
|
||||
* @param address Address to be searched for.
|
||||
* @return Sector containing @p address.
|
||||
*/
|
||||
flashsector_t flashSectorAt(flashaddr_t address);
|
||||
|
||||
/**
|
||||
* @brief Erase the flash @p sector.
|
||||
* @details The sector is checked for errors after erase.
|
||||
* @note The sector is deleted regardless of its current state.
|
||||
*
|
||||
* @param sector Sector which is going to be erased.
|
||||
* @return FLASH_RETURN_SUCCESS No error erasing the sector.
|
||||
* @return FLASH_RETURN_BAD_FLASH Flash cell error.
|
||||
* @return FLASH_RETURN_NO_PERMISSION Access denied.
|
||||
*/
|
||||
int flashSectorErase(flashsector_t sector);
|
||||
|
||||
/**
|
||||
* @brief Erase the sectors containing the span of @p size bytes starting at @p address.
|
||||
*
|
||||
* @warning If @p address doesn't match the beginning of a sector, the
|
||||
* data contained between the beginning of the sector and @p address will
|
||||
* be erased too. The same applies for data contained at @p address + @p size
|
||||
* up to the end of the sector.
|
||||
*
|
||||
* @param address Starting address of the span in flash memory.
|
||||
* @param size Size of the span in bytes.
|
||||
* @return FLASH_RETURN_SUCCESS No error erasing the flash memory.
|
||||
* @return FLASH_RETURN_BAD_FLASH Flash cell error.
|
||||
* @return FLASH_RETURN_NO_PERMISSION Access denied.
|
||||
*/
|
||||
int flashErase(flashaddr_t address, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Check if the @p size bytes of flash memory starting at @p address are erased.
|
||||
* @note If the memory is erased, one can write data into it safely.
|
||||
* @param address First address in flash memory to be checked.
|
||||
* @param size Size of the memory space to be checked in bytes.
|
||||
* @return TRUE Memory is already erased.
|
||||
* @return FALSE Memory is not erased.
|
||||
*/
|
||||
bool flashIsErased(flashaddr_t address, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Check if the data in @p buffer are identical to the one in flash memory.
|
||||
* @param address First address in flash memory to be checked.
|
||||
* @param buffer Buffer containing the data to compare.
|
||||
* @param size Size of @p buffer in bytes.
|
||||
* @return TRUE if the flash memory and the buffer contain identical data.
|
||||
* @return FALSE if the flash memory and the buffer don't contain identical data.
|
||||
*/
|
||||
bool flashCompare(flashaddr_t address, const char* buffer, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Copy data from the flash memory to a @p buffer.
|
||||
* @warning The @p buffer must be at least @p size bytes long.
|
||||
* @param address First address of the flash memory to be copied.
|
||||
* @param buffer Buffer to copy to.
|
||||
* @param size Size of the data to be copied in bytes.
|
||||
* @return FLASH_RETURN_SUCCESS if successfully copied.
|
||||
*/
|
||||
int flashRead(flashaddr_t address, char* buffer, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Copy data from a @p buffer to the flash memory.
|
||||
* @warning The flash memory area receiving the data must be erased.
|
||||
* @warning The @p buffer must be at least @p size bytes long.
|
||||
* @param address First address in the flash memory where to copy the data to.
|
||||
* @param buffer Buffer containing the data to copy.
|
||||
* @param size Size of the data to be copied in bytes.
|
||||
* @return FLASH_RETURN_SUCCESS No error.
|
||||
* @return FLASH_RETURN_NO_PERMISSION Access denied.
|
||||
*/
|
||||
int flashWrite(flashaddr_t address, const char* buffer, size_t size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* FLASH_H */
|
||||
|
|
|
@ -4,8 +4,11 @@
|
|||
|
||||
dataPoint_t* flash_getLogBuffer(uint16_t id)
|
||||
{
|
||||
uint32_t addr = LOG_FLASH_ADDR + LOG_SECTOR_ID(id) * LOG_SECTOR_SIZE + LOG_POS_IN_SECTOR(id) * sizeof(dataPoint_t);
|
||||
if(addr >= LOG_FLASH_ADDR && addr <= LOG_FLASH_ADDR+LOG_FLASH_SIZE-sizeof(dataPoint_t))
|
||||
uint32_t addr = LOG_FLASH_ADDR
|
||||
+ (LOG_SECTOR_ID(id) * LOG_SECTOR_SIZE)
|
||||
+ (LOG_POS_IN_SECTOR(id) * sizeof(dataPoint_t));
|
||||
if(addr >= LOG_FLASH_ADDR
|
||||
&& addr <= (LOG_FLASH_ADDR + LOG_FLASH_SIZE - sizeof(dataPoint_t)))
|
||||
return (dataPoint_t*)addr;
|
||||
else
|
||||
return NULL; // Outside of memory address allocation
|
||||
|
@ -95,7 +98,7 @@ void flash_writeLogDataPoint(dataPoint_t* tp)
|
|||
{
|
||||
// Get address to write on
|
||||
dataPoint_t* address = flash_getNextFreeLogAddress();
|
||||
if(address == NULL) // Memory completly used, erase oldest data
|
||||
if(address == NULL) // Memory completely used, erase oldest data
|
||||
{
|
||||
flash_eraseOldestLogData();
|
||||
address = flash_getNextFreeLogAddress();
|
||||
|
|
|
@ -543,6 +543,7 @@ THD_FUNCTION(pktAFSKDecoder, arg) {
|
|||
AFSKDemodDriver *myDriver = arg;
|
||||
packet_svc_t *myHandler = myDriver->packet_handler;
|
||||
radio_unit_t radio = myHandler->radio;
|
||||
tprio_t decoder_idle_priority;
|
||||
|
||||
/* No active packet object. */
|
||||
myHandler->active_packet_object = NULL;
|
||||
|
@ -577,7 +578,7 @@ THD_FUNCTION(pktAFSKDecoder, arg) {
|
|||
}
|
||||
|
||||
/* Save the priority that calling thread gave us. */
|
||||
tprio_t decoder_idle_priority = chThdGetPriorityX();
|
||||
decoder_idle_priority = chThdGetPriorityX();
|
||||
|
||||
/* Setup LED for decoder blinker. */
|
||||
pktLLDradioConfigIndicator(radio, PKT_INDICATOR_DECODE);
|
||||
|
@ -608,7 +609,7 @@ THD_FUNCTION(pktAFSKDecoder, arg) {
|
|||
pktAddEventFlags(myDriver, DEC_CLOSE_EXEC);
|
||||
pktReleaseAFSKDecoder(myDriver);
|
||||
myDriver->decoder_state = DECODER_TERMINATED;
|
||||
pktWriteGPIOline(LINE_DECODER_LED, PAL_LOW);
|
||||
pktLLDradioUpdateIndicator(radio, PKT_INDICATOR_DECODE, PAL_LOW);
|
||||
chThdExit(MSG_OK);
|
||||
/* Something went wrong if we arrive here. */
|
||||
chSysHalt("ThdExit");
|
||||
|
@ -670,18 +671,24 @@ THD_FUNCTION(pktAFSKDecoder, arg) {
|
|||
/* Check if prior packet buffer released. */
|
||||
chDbgCheck(myHandler->active_packet_object == NULL);
|
||||
|
||||
/* Get a packet buffer. */
|
||||
/*
|
||||
* Get a reference to the packet management FIFO.
|
||||
* The factory reference count is increased when found.
|
||||
*/
|
||||
dyn_objects_fifo_t *pkt_fifo =
|
||||
chFactoryFindObjectsFIFO(myHandler->pbuff_name);
|
||||
chDbgAssert(pkt_fifo != NULL, "unable to find packet fifo");
|
||||
|
||||
/* The factory reference count is increased. */
|
||||
objects_fifo_t *pkt_buffer_pool = chFactoryGetObjectsFIFO(pkt_fifo);
|
||||
chDbgAssert(pkt_buffer_pool != NULL, "no packet fifo list");
|
||||
/*
|
||||
* Packet management FIFO found.
|
||||
* Now get reference to inner FIFO allocator.
|
||||
*/
|
||||
objects_fifo_t *pkt_object_pool = chFactoryGetObjectsFIFO(pkt_fifo);
|
||||
chDbgAssert(pkt_object_pool != NULL, "no packet fifo list");
|
||||
|
||||
/* Get a buffer and have it initialized ready for use. */
|
||||
/* Get a packet management object and assign a data buffer. */
|
||||
pkt_data_object_t *myPktBuffer = pktTakeDataBuffer(myHandler,
|
||||
pkt_buffer_pool,
|
||||
pkt_object_pool,
|
||||
TIME_MS2I(100));
|
||||
#if AFSK_DEBUG_TYPE == AFSK_PWM_DATA_CAPTURE_DEBUG
|
||||
char buf[80];
|
||||
|
@ -690,9 +697,9 @@ THD_FUNCTION(pktAFSKDecoder, arg) {
|
|||
pktWrite( (uint8_t *)buf, out);
|
||||
#endif
|
||||
|
||||
/* If no buffer is available the handler pointer is also set to NULL. */
|
||||
/* If no management object or data buffer is available get NULL. */
|
||||
if(myPktBuffer == NULL) {
|
||||
/* Decrease ref count on AX25 FIFO. */
|
||||
/* Decrease ref count on packet management object FIFO. */
|
||||
chFactoryReleaseObjectsFIFO(pkt_fifo);
|
||||
pktAddEventFlags(myHandler, EVT_PKT_NO_BUFFER);
|
||||
myDriver->active_demod_stream->status |= STA_PKT_NO_BUFFER;
|
||||
|
@ -702,7 +709,7 @@ THD_FUNCTION(pktAFSKDecoder, arg) {
|
|||
|
||||
|
||||
/* Increase thread priority. */
|
||||
(void)chThdSetPriority(DECODER_RUN_PRIORITY);
|
||||
decoder_idle_priority = chThdSetPriority(DECODER_RUN_PRIORITY);
|
||||
|
||||
/* Enable processing of incoming PWM stream. */
|
||||
myDriver->decoder_state = DECODER_ACTIVE;
|
||||
|
@ -745,7 +752,10 @@ THD_FUNCTION(pktAFSKDecoder, arg) {
|
|||
/* Timeout calculated as SYMBOL time x 8 x 20. */
|
||||
|
||||
if(n != sizeof(packed_pwm_counts_t)) {
|
||||
/* PWM stream wait timeout. */
|
||||
/*
|
||||
* PWM stream wait timeout.
|
||||
* No in-band close or abort in stream.
|
||||
*/
|
||||
pktAddEventFlags(myHandler, EVT_PWM_STREAM_TIMEOUT);
|
||||
myFIFO->status |= STA_PWM_STREAM_TIMEOUT;
|
||||
myDriver->decoder_state = DECODER_RESET;
|
||||
|
@ -819,7 +829,7 @@ THD_FUNCTION(pktAFSKDecoder, arg) {
|
|||
|
||||
/* This is a debug error.
|
||||
* CCA is validated but a PWM is still active.
|
||||
* The PWM side has already posted a PWM_FIFO_REMNANT event.
|
||||
* The PWM side has already posted a PWM_FIFO_ORDER event.
|
||||
*/
|
||||
case PWM_TERM_QUEUE_ERR:
|
||||
|
||||
|
@ -912,10 +922,34 @@ THD_FUNCTION(pktAFSKDecoder, arg) {
|
|||
myDriver->decoder_state = DECODER_DISPATCH;
|
||||
continue; /* From this case. */
|
||||
}
|
||||
} /* End switch. */
|
||||
} /* End switch on frame_state. */
|
||||
break; /* Keep GCC 7 happy. */
|
||||
} /* End case DECODER_ACTIVE. */
|
||||
|
||||
case DECODER_DISPATCH: {
|
||||
if(myHandler->active_packet_object != NULL) {
|
||||
|
||||
/*
|
||||
* Indicate AFSK decode done.
|
||||
* PWM handler will terminate capture session if still active.
|
||||
*/
|
||||
myDriver->active_demod_stream->status |= STA_AFSK_DECODE_DONE;
|
||||
|
||||
/* Copy latest status into packet buffer object. */
|
||||
myHandler->active_packet_object->status =
|
||||
myDriver->active_demod_stream->status;
|
||||
|
||||
/* Set AX25 status and dispatch the packet buffer object. */
|
||||
pktDispatchReceivedBuffer(myHandler->active_packet_object);
|
||||
|
||||
/* Packet object has been handed over. Remove our reference. */
|
||||
myHandler->active_packet_object = NULL;
|
||||
} /* Active packet object != NULL. */
|
||||
/* Release PWM buffers and reset decoder in RESET state. */
|
||||
myDriver->decoder_state = DECODER_RESET;
|
||||
break;
|
||||
} /* End case DECODER_DISPATCH. */
|
||||
|
||||
/*
|
||||
* RESET readies the decoder for the next session.
|
||||
* It frees any held buffers/objects.
|
||||
|
@ -955,10 +989,10 @@ THD_FUNCTION(pktAFSKDecoder, arg) {
|
|||
#if USE_CCM_BASED_PWM_HEAP == TRUE
|
||||
pktAssertCCMdynamicCheck(myHandler->active_packet_object->buffer);
|
||||
#endif
|
||||
/* Free the packet buffer referenced in the packet object. */
|
||||
/* Free the data buffer referenced in the packet object. */
|
||||
chHeapFree(myHandler->active_packet_object->buffer);
|
||||
#endif
|
||||
/* Release the AX25 receive packet buffer management object. */
|
||||
/* Release the receive packet buffer management object. */
|
||||
objects_fifo_t *pkt_fifo =
|
||||
chFactoryGetObjectsFIFO(myHandler->active_packet_object->pkt_factory);
|
||||
|
||||
|
@ -1020,30 +1054,6 @@ THD_FUNCTION(pktAFSKDecoder, arg) {
|
|||
myDriver->decoder_state = DECODER_IDLE;
|
||||
break;
|
||||
} /* End case DECODER_RESET. */
|
||||
|
||||
case DECODER_DISPATCH: {
|
||||
if(myHandler->active_packet_object != NULL) {
|
||||
|
||||
/*
|
||||
* Indicate AFSK decode done.
|
||||
* PWM handler will terminate capture session if still active.
|
||||
*/
|
||||
myDriver->active_demod_stream->status |= STA_AFSK_DECODE_DONE;
|
||||
|
||||
/* Copy latest status into packet buffer object. */
|
||||
myHandler->active_packet_object->status =
|
||||
myDriver->active_demod_stream->status;
|
||||
|
||||
/* Set AX25 status and dispatch the packet buffer object. */
|
||||
pktDispatchReceivedBuffer(myHandler->active_packet_object);
|
||||
|
||||
/* Packet object has been handed over. Remove our reference. */
|
||||
myHandler->active_packet_object = NULL;
|
||||
} /* Active packet object != NULL. */
|
||||
/* Release PWM buffers and reset decoder in RESET state. */
|
||||
myDriver->decoder_state = DECODER_RESET;
|
||||
break;
|
||||
} /* End case DECODER_DISPATCH. */
|
||||
} /* End switch on decoder state. */
|
||||
} /* End thread while(true). */
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
#define AFSK_DSP_QCORR_DECODE 1
|
||||
#define AFSK_DSP_FCORR_DECODE 2 /* Currently under test. */
|
||||
|
||||
#define AFSK_DECODE_TYPE AFSK_DSP_QCORR_DECODE
|
||||
#define AFSK_DECODE_TYPE AFSK_DSP_FCORR_DECODE
|
||||
#if !defined(AFSK_DECODE_TYPE)
|
||||
#error "AFSK decoder not specified"
|
||||
#endif
|
||||
|
|
|
@ -427,7 +427,7 @@ void pktOpenPWMChannelI(ICUDriver *myICU, eventflags_t evt) {
|
|||
* Shouldn't happen unless CCA has not triggered an EXTI trailing edge.
|
||||
* For now just flag that an error condition happened.
|
||||
*/
|
||||
pktClosePWMchannelI(myICU, EVT_PWM_FIFO_REMNANT, PWM_TERM_QUEUE_ERR);
|
||||
pktClosePWMchannelI(myICU, PWM_FIFO_ORDER, PWM_TERM_QUEUE_ERR);
|
||||
return;
|
||||
}
|
||||
/* Normal CCA handling. */
|
||||
|
|
|
@ -381,53 +381,54 @@ extern "C" {
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief Fetches a buffer from the packet buffer free pool.
|
||||
* @brief Gets an sets up a packet management object.
|
||||
* @notes Fetches a management object from the FIFO pool.
|
||||
* @notes A packet buffer is then obtained and assigned to the object.
|
||||
* @details This function is called from thread level to obtain a buffer
|
||||
* to write AX25 data into.
|
||||
*
|
||||
* @param[in] handler pointer to a @p packet service object
|
||||
* @param[in] fifo pointer to a @p objects FIFO
|
||||
* @paream[in] timeout Allowable wait for a free buffer
|
||||
* @paream[in] timeout Allowable wait for a free data buffer
|
||||
*
|
||||
* @return pointer to packet buffer object.
|
||||
* @retval NULL if no buffer object available.
|
||||
* @return pointer to packet management object.
|
||||
* @retval NULL if no management object or buffer available.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
static inline pkt_data_object_t *pktTakeDataBuffer(packet_svc_t *handler,
|
||||
objects_fifo_t *fifo,
|
||||
sysinterval_t timeout) {
|
||||
/* Get a management object from the FIFO pool. */
|
||||
pkt_data_object_t *pkt_buffer = chFifoTakeObjectTimeout(fifo, timeout);
|
||||
handler->active_packet_object = pkt_buffer;
|
||||
if(pkt_buffer != NULL) {
|
||||
|
||||
/*
|
||||
* Packet buffer available.
|
||||
* Packet management object available.
|
||||
* Initialize the object fields.
|
||||
*/
|
||||
//handler->active_packet_object = pkt_buffer;
|
||||
|
||||
/* Initialize the object fields. */
|
||||
pkt_buffer->handler = handler;
|
||||
pkt_buffer->status = EVT_STATUS_CLEAR;
|
||||
pkt_buffer->packet_size = 0;
|
||||
pkt_buffer->buffer_size = PKT_RX_BUFFER_SIZE;
|
||||
pkt_buffer->cb_func = handler->usr_callback;
|
||||
|
||||
/* Save the pointer to the packet factory for use when releasing object. */
|
||||
/* Save the pointer to the object factory for use when releasing object. */
|
||||
pkt_buffer->pkt_factory = handler->the_packet_fifo;
|
||||
#if USE_CCM_HEAP_RX_BUFFERS == TRUE
|
||||
extern memory_heap_t *ccm_heap;
|
||||
pkt_buffer->buffer = chHeapAlloc(ccm_heap, PKT_RX_BUFFER_SIZE);
|
||||
if(pkt_buffer->buffer == NULL) {
|
||||
/* No heap available. */
|
||||
/* Return packet buffer object to free list. */
|
||||
/* No heap available for data buffer. */
|
||||
/* Return management object to free list. */
|
||||
chFifoReturnObject(fifo, (pkt_data_object_t *)pkt_buffer);
|
||||
|
||||
/*
|
||||
* Decrease FIFO reference counter (increased by decoder).
|
||||
* FIFO will be destroyed when all references are released.
|
||||
*/
|
||||
chFactoryReleaseObjectsFIFO(pkt_buffer->pkt_factory);
|
||||
/*chFactoryReleaseObjectsFIFO(pkt_buffer->pkt_factory);*/
|
||||
pkt_buffer = NULL;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -81,7 +81,7 @@
|
|||
#define EVT_PWM_BUFFER_FAIL EVENT_MASK(EVT_PRIORITY_BASE + 15)
|
||||
|
||||
#define EVT_RAD_STREAM_OPEN EVENT_MASK(EVT_PRIORITY_BASE + 16)
|
||||
#define EVT_PWM_FIFO_REMNANT EVENT_MASK(EVT_PRIORITY_BASE + 17)
|
||||
#define PWM_FIFO_ORDER EVENT_MASK(EVT_PRIORITY_BASE + 17)
|
||||
#define EVT_RAD_STREAM_CLOSE EVENT_MASK(EVT_PRIORITY_BASE + 18)
|
||||
//#define STA_PKT_INVALID_FRAME EVENT_MASK(EVT_PRIORITY_BASE + 19)
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue