kopia lustrzana https://github.com/OpenRTX/OpenRTX
Implemented load/save of settings and VFO configuration for MDx devices
rodzic
756812ca31
commit
691b388228
|
@ -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',
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 <http://www.gnu.org/licenses/> *
|
||||
***************************************************************************/
|
||||
|
||||
#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) ;
|
||||
}
|
|
@ -21,18 +21,112 @@
|
|||
#include <string.h>
|
||||
#include <interfaces/nvmem.h>
|
||||
#include <cps.h>
|
||||
#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;
|
||||
}
|
||||
|
|
|
@ -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 <http://www.gnu.org/licenses/> *
|
||||
***************************************************************************/
|
||||
|
||||
#include <stm32f4xx.h>
|
||||
#include <stddef.h>
|
||||
#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) ;
|
||||
}
|
|
@ -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 <http://www.gnu.org/licenses/> *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MCUFLASH_H
|
||||
#define MCUFLASH_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/**
|
||||
* 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 */
|
||||
/***************************************************************************
|
||||
* 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 <http://www.gnu.org/licenses/> *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef FLASH_H
|
||||
#define FLASH_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#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 */
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
Ładowanie…
Reference in New Issue