diff --git a/meson.build b/meson.build
index cdaeade7..b0d6100e 100644
--- a/meson.build
+++ b/meson.build
@@ -169,6 +169,7 @@ stm32f405_src = ['platform/mcu/STM32F4xx/boot/startup.cpp',
'platform/mcu/STM32F4xx/drivers/rtc.c',
'platform/mcu/STM32F4xx/drivers/SPI2.c',
'platform/mcu/STM32F4xx/drivers/USART3.cpp',
+ 'platform/mcu/STM32F4xx/drivers/flash.c',
'platform/mcu/CMSIS/Device/ST/STM32F4xx/Source/system_stm32f4xx.c']
stm32f405_inc = ['platform/mcu/CMSIS/Include',
diff --git a/openrtx/src/main.c b/openrtx/src/main.c
index 0a9a3838..470026de 100644
--- a/openrtx/src/main.c
+++ b/openrtx/src/main.c
@@ -48,11 +48,14 @@ int main(void)
// Initialize platform drivers
platform_init();
+ // Initialize radio state
+ state_init();
+
// Initialize display and graphics driver
gfx_init();
// Set default contrast
- display_setContrast(default_settings.contrast);
+ display_setContrast(state.settings.contrast);
// Initialize user interface
ui_init();
@@ -63,7 +66,7 @@ int main(void)
// Wait 30ms before turning on backlight to hide random pixels on screen
sleepFor(0u, 30u);
- platform_setBacklightLevel(255);
+ platform_setBacklightLevel(state.settings.brightness);
// Keep the splash screen for 1 second
sleepFor(1u, 0u);
diff --git a/openrtx/src/state.c b/openrtx/src/state.c
index fed01c18..6b0ef7b7 100644
--- a/openrtx/src/state.c
+++ b/openrtx/src/state.c
@@ -34,7 +34,7 @@ void state_init()
* Try loading settings from nonvolatile memory and default to sane values
* in case of failure.
*/
- if(nvm_readSettings(&state.settings) != 0)
+ if(nvm_readSettings(&state.settings) < 0)
{
state.settings = default_settings;
strncpy(state.settings.callsign, "OPNRTX", 10);
@@ -44,7 +44,7 @@ void state_init()
* Try loading VFO configuration from nonvolatile memory and default to sane
* values in case of failure.
*/
- if(nvm_readVFOChannelData(&state.channel) != 0)
+ if(nvm_readVFOChannelData(&state.channel) < 0)
{
state.channel.mode = FM;
state.channel.bandwidth = BW_25;
diff --git a/openrtx/src/threads.c b/openrtx/src/threads.c
index 32f5620d..8e9a27a3 100644
--- a/openrtx/src/threads.c
+++ b/openrtx/src/threads.c
@@ -327,9 +327,6 @@ void create_threads()
// Create UI event queue
queue_init(&ui_queue);
- // State initialization, execute before starting all tasks
- state_init();
-
// Create rtx radio thread
pthread_t rtx_thread;
pthread_attr_t rtx_attr;
diff --git a/platform/drivers/NVM/mcuFlash_MDx.c b/platform/drivers/NVM/mcuFlash_MDx.c
deleted file mode 100644
index 5df510ab..00000000
--- a/platform/drivers/NVM/mcuFlash_MDx.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2021 by Federico Amedeo Izzo IU2NUO, *
- * Niccolò Izzo IU2KIN *
- * Frederik Saraci IU2NRO *
- * Silvano Seva IU2KWO *
- * *
- * This program 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. *
- * *
- * This program 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 this program; if not, see *
- ***************************************************************************/
-
-#include "mcuFlash.h"
-
-inline bool unlock()
-{
- // Flash already unlocked
- if((FLASH->CR & FLASH_CR_LOCK) == 0)
- {
- return true;
- }
-
- FLASH->KEYR = 0x45670123;
- FLASH->KEYR = 0xCDEF89AB;
-
- // Succesful unlock
- if((FLASH->CR & FLASH_CR_LOCK) == 0)
- {
- return true;
- }
-
- return false;
-}
-
-bool mcuFlash_eraseSector(const uint8_t secNum)
-{
- if(secNum > 11) return false;
- if(unlock() == false) return false;
-
- // Flash busy, wait until previous operation finishes
- while((FLASH->SR & FLASH_SR_BSY) != 0) ;
-
- FLASH->CR |= FLASH_CR_PSIZE_1 // 32-bit program parallelism
- | (secNum << 3) // Sector number
- | FLASH_CR_SER // Sector erase
- | FLASH_CR_STRT; // Start erase
-
- // Wait until erase ends
- while((FLASH->SR & FLASH_SR_BSY) != 0) ;
-
- return true;
-}
-
-void mcuFlash_write(const uint32_t address, const void *data, const size_t len)
-{
- if((data == NULL) || (len == 0)) return;
-
- // Flash busy, wait until previous operation finishes
- while((FLASH->SR & FLASH_SR_BSY) != 0) ;
-
- // Request programming with 8-bit parallelism
- FLASH->CR = FLASH_CR_PG;
-
- const uint8_t *buf = ((uint8_t *) data);
- const uint8_t *mem = ((uint8_t *) address);
- for(size_t i = 0; i < len; i++)
- {
- *mem = buf[i];
- mem++;
- }
-
- // Wait until the end of the write operation
- while((FLASH->SR & FLASH_SR_BSY) != 0) ;
-}
\ No newline at end of file
diff --git a/platform/drivers/NVM/nvmem_settings_MDx.c b/platform/drivers/NVM/nvmem_settings_MDx.c
index 4c78fabc..a830b62f 100644
--- a/platform/drivers/NVM/nvmem_settings_MDx.c
+++ b/platform/drivers/NVM/nvmem_settings_MDx.c
@@ -21,18 +21,112 @@
#include
#include
#include
+#include "flash.h"
-int nvm_readSettings(settings_t *settings)
+
+typedef struct
{
- return -1;
+ uint32_t magic;
+ uint32_t flags[64];
+ struct dataBlock
+ {
+ settings_t settings;
+ channel_t vfoData;
+ }
+ data[2048];
}
+__attribute__((packed)) memory_t;
+
+static const uint32_t validMagic = 0x5854524F; // "ORTX"
+static const uint32_t baseAddress = 0x080E0000;
+memory_t *memory = ((memory_t *) baseAddress);
+
+
+/**
+ * \internal
+ * Utility function to find the currently active data block inside memory, that
+ * is the one containing the last saved settings.
+ *
+ * @return number currently active data block or -1 if memory data is invalid.
+ */
+int findActiveBlock()
+{
+ if(memory->magic != validMagic) return -1;
+
+ uint16_t block = 0;
+ for(; block < 64; block++)
+ {
+ if(memory->flags[block] != 0x00000000)
+ {
+ break;
+ }
+ }
+
+ uint16_t bit = 0;
+ for(; bit < 32; bit++)
+ {
+ if((memory->flags[block] & (1 << bit)) != 0)
+ {
+ break;
+ }
+ }
+
+ block = (block * 32) + bit;
+ return block - 1;
+}
+
+
int nvm_readVFOChannelData(channel_t *channel)
{
- return -1;
+ int block = findActiveBlock();
+ if(block < 0) return -1;
+ memcpy(channel, &(memory->data[block].vfoData), sizeof(channel_t));
+ return 0;
+}
+
+int nvm_readSettings(settings_t *settings)
+{
+ int block = findActiveBlock();
+ if(block < 0) return -1;
+ memcpy(settings, &(memory->data[block].settings), sizeof(settings_t));
+ return 0;
}
int nvm_writeSettingsAndVfo(const settings_t *settings, const channel_t *vfo)
{
- return -1;
+ uint32_t addr = 0;
+ int block = findActiveBlock();
+
+ /*
+ * Memory never initialised or save space finished: erase all the sector.
+ * On STM32F405 the settings are saved in sector 11, starting at address
+ * 0x08060000.
+ */
+ if((block < 0) || (block >= 2047))
+ {
+ flash_eraseSector(11);
+ addr = ((uint32_t) &(memory->magic));
+ flash_write(addr, &validMagic, sizeof(validMagic));
+ block = 0;
+ }
+ else
+ {
+ block += 1;
+ }
+
+ // Save settings
+ addr = ((uint32_t) &(memory->data[block].settings));
+ flash_write(addr, settings, sizeof(settings_t));
+
+ // Save VFO configuration
+ addr = ((uint32_t) &(memory->data[block].vfoData));
+ flash_write(addr, vfo, sizeof(channel_t));
+
+ // Update the flags marking used data blocks
+ uint32_t flag = ~(1 << (block % 32));
+ addr = ((uint32_t) &(memory->flags[block / 32]));
+ flash_write(addr, &flag, sizeof(uint32_t));
+
+ return 0;
}
diff --git a/platform/mcu/STM32F4xx/drivers/flash.c b/platform/mcu/STM32F4xx/drivers/flash.c
new file mode 100644
index 00000000..c05326c7
--- /dev/null
+++ b/platform/mcu/STM32F4xx/drivers/flash.c
@@ -0,0 +1,94 @@
+/***************************************************************************
+ * Copyright (C) 2021 by Federico Amedeo Izzo IU2NUO, *
+ * Niccolò Izzo IU2KIN *
+ * Frederik Saraci IU2NRO *
+ * Silvano Seva IU2KWO *
+ * *
+ * This program 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. *
+ * *
+ * This program 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 this program; if not, see *
+ ***************************************************************************/
+
+#include
+#include
+#include "flash.h"
+
+/**
+ * \internal
+ * Utility function performing unlock of flash erase and write access.
+ *
+ * @true on success, false on failure.
+ */
+static inline bool unlock()
+{
+ // Flash already unlocked
+ if((FLASH->CR & FLASH_CR_LOCK) == 0)
+ {
+ return true;
+ }
+
+ FLASH->KEYR = 0x45670123;
+ FLASH->KEYR = 0xCDEF89AB;
+
+ // Succesful unlock
+ if((FLASH->CR & FLASH_CR_LOCK) == 0)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+
+
+bool flash_eraseSector(const uint8_t secNum)
+{
+ if(secNum > 11) return false;
+ if(unlock() == false) return false;
+
+ // Flash busy, wait until previous operation finishes
+ while((FLASH->SR & FLASH_SR_BSY) != 0) ;
+
+ FLASH->CR |= FLASH_CR_PSIZE_1 // 32-bit program parallelism
+ | (secNum << 3) // Sector number
+ | FLASH_CR_SER // Sector erase
+ | FLASH_CR_STRT; // Start erase
+
+ // Wait until erase ends
+ while((FLASH->SR & FLASH_SR_BSY) != 0) ;
+
+ return true;
+}
+
+void flash_write(const uint32_t address, const void *data, const size_t len)
+{
+ if(unlock() == false) return;
+ if((data == NULL) || (len == 0)) return;
+
+ // Flash busy, wait until previous operation finishes
+ while((FLASH->SR & FLASH_SR_BSY) != 0) ;
+
+ // Request programming with 8-bit parallelism
+ FLASH->CR = FLASH_CR_PG;
+
+ // Write data to memory
+ const uint8_t *buf = ((uint8_t *) data);
+ uint8_t *mem = ((uint8_t *) address);
+ for(size_t i = 0; i < len; i++)
+ {
+ *mem = buf[i];
+ mem++;
+ }
+
+ // Wait until the end of the write operation
+ while((FLASH->SR & FLASH_SR_BSY) != 0) ;
+}
diff --git a/platform/drivers/NVM/mcuFlash.h b/platform/mcu/STM32F4xx/drivers/flash.h
similarity index 88%
rename from platform/drivers/NVM/mcuFlash.h
rename to platform/mcu/STM32F4xx/drivers/flash.h
index fbfceefe..b63e1149 100644
--- a/platform/drivers/NVM/mcuFlash.h
+++ b/platform/mcu/STM32F4xx/drivers/flash.h
@@ -1,49 +1,57 @@
-/***************************************************************************
- * Copyright (C) 2021 by Federico Amedeo Izzo IU2NUO, *
- * Niccolò Izzo IU2KIN *
- * Frederik Saraci IU2NRO *
- * Silvano Seva IU2KWO *
- * *
- * This program 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. *
- * *
- * This program 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 this program; if not, see *
- ***************************************************************************/
-
-#ifndef MCUFLASH_H
-#define MCUFLASH_H
-
-#include
-#include
-
-/**
- * Driver for MCU's internal flash management, allowing for sector erase and data
- * writing.
- */
-
-/**
- * Erase one sector of the MCU flash memory.
- *
- * @param secNum: sector number.
- * @return true for successful erase, false otherwise.
- */
-bool mcuFlash_eraseSector(const uint8_t secNum);
-
-/**
- * Write data to the MCU flash memory.
- *
- * @param address: starting address for the write operation.
- * @param data: data to be written.
- * @param len: data length.
- */
-void mcuFlash_write(const uint32_t address, const void *data, const size_t len);
-
-#endif /* MCUFLASH_H */
\ No newline at end of file
+/***************************************************************************
+ * Copyright (C) 2021 by Federico Amedeo Izzo IU2NUO, *
+ * Niccolò Izzo IU2KIN *
+ * Frederik Saraci IU2NRO *
+ * Silvano Seva IU2KWO *
+ * *
+ * This program 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. *
+ * *
+ * This program 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 this program; if not, see *
+ ***************************************************************************/
+
+#ifndef FLASH_H
+#define FLASH_H
+
+#include
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Driver for MCU's internal flash management, allowing for sector erase and data
+ * writing.
+ */
+
+/**
+ * Erase one sector of the MCU flash memory.
+ *
+ * @param secNum: sector number.
+ * @return true for successful erase, false otherwise.
+ */
+bool flash_eraseSector(const uint8_t secNum);
+
+/**
+ * Write data to the MCU flash memory.
+ *
+ * @param address: starting address for the write operation.
+ * @param data: data to be written.
+ * @param len: data length.
+ */
+void flash_write(const uint32_t address, const void *data, const size_t len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FLASH_H */
diff --git a/platform/mcu/STM32F4xx/linker_script.ld b/platform/mcu/STM32F4xx/linker_script.ld
index 5520da0a..598d8724 100644
--- a/platform/mcu/STM32F4xx/linker_script.ld
+++ b/platform/mcu/STM32F4xx/linker_script.ld
@@ -59,7 +59,8 @@ ENTRY(_Z13Reset_Handlerv)
/* specify the memory areas */
MEMORY
{
- flash(rx) : ORIGIN = 0x0800C000, LENGTH = 1M - 48K
+ /* Reserve space for bootloader and settings */
+ flash(rx) : ORIGIN = 0x0800C000, LENGTH = 1M - 48K - 128K
/*
* Note, the small ram starts at 0x10000000 but it is necessary to add the
* size of the main stack, so it is 0x10000200.
diff --git a/platform/targets/MD-3x0/platform.c b/platform/targets/MD-3x0/platform.c
index f6596e5c..aeb12fec 100644
--- a/platform/targets/MD-3x0/platform.c
+++ b/platform/targets/MD-3x0/platform.c
@@ -38,9 +38,6 @@ void platform_init()
gpio_setMode(GREEN_LED, OUTPUT);
gpio_setMode(RED_LED, OUTPUT);
- gpio_setMode(LCD_BKLIGHT, ALTERNATE);
- gpio_setAlternateFunction(LCD_BKLIGHT, 3);
-
gpio_setMode(CH_SELECTOR_0, INPUT);
gpio_setMode(CH_SELECTOR_1, INPUT);
gpio_setMode(CH_SELECTOR_2, INPUT);
@@ -50,6 +47,7 @@ void platform_init()
gpio_setMode(PTT_EXT, INPUT);
gpio_setMode(PWR_SW, OUTPUT);
+ gpio_setPin(PWR_SW);
/*
* Initialise ADC1, for vbat, RSSI, ...
@@ -146,7 +144,7 @@ bool platform_pwrButtonStatus()
* is always a bit of noise in the ADC measurement making the returned
* voltage not to be exactly zero.
*/
- return (platform_getVbat() > 1.0f) ? true : false;
+ return (platform_getVbat() > 1000) ? true : false;
}
void platform_ledOn(led_t led)
diff --git a/platform/targets/MD-UV3x0/platform.c b/platform/targets/MD-UV3x0/platform.c
index d1cd9d64..0f704948 100644
--- a/platform/targets/MD-UV3x0/platform.c
+++ b/platform/targets/MD-UV3x0/platform.c
@@ -45,6 +45,9 @@ void platform_init()
gpio_setMode(PTT_SW, INPUT_PULL_UP);
gpio_setMode(PTT_EXT, INPUT_PULL_UP);
+ gpio_setMode(PWR_SW, OUTPUT);
+ gpio_setPin(PWR_SW);
+
/*
* Initialise ADC1, for vbat, RSSI, ...
* Configuration of corresponding GPIOs in analog input mode is done inside
@@ -141,7 +144,7 @@ bool platform_pwrButtonStatus()
* is always a bit of noise in the ADC measurement making the returned
* voltage not to be exactly zero.
*/
- return (platform_getVbat() > 1.0f) ? true : false;
+ return (platform_getVbat() > 1000) ? true : false;
}
void platform_ledOn(led_t led)