Update RTC module

Removed_REF_marker
DiSlord 5 years ago committed by erikkaashoek
parent 53a8601399
commit 6eff8ca5ee

@ -75,8 +75,6 @@ static volatile vna_shellcmd_t shell_function = 0;
//#define ENABLED_DUMP //#define ENABLED_DUMP
// Allow get threads debug info // Allow get threads debug info
#define ENABLE_THREADS_COMMAND #define ENABLE_THREADS_COMMAND
// RTC time not used
//#define ENABLE_TIME_COMMAND
// Enable vbat_offset command, allow change battery voltage correction in config // Enable vbat_offset command, allow change battery voltage correction in config
#define ENABLE_VBAT_OFFSET_COMMAND #define ENABLE_VBAT_OFFSET_COMMAND
// Info about NanoVNA, need fore soft // Info about NanoVNA, need fore soft
@ -620,17 +618,35 @@ VNA_SHELL_FUNCTION(cmd_power)
} }
#endif #endif
#ifdef ENABLE_TIME_COMMAND #ifdef __USE_RTC__
#if HAL_USE_RTC == FALSE
#error "Error cmd_time require define HAL_USE_RTC = TRUE in halconf.h"
#endif
VNA_SHELL_FUNCTION(cmd_time) VNA_SHELL_FUNCTION(cmd_time)
{ {
RTCDateTime timespec;
(void)argc; (void)argc;
(void)argv; (void)argv;
rtcGetTime(&RTCD1, &timespec); uint32_t dt_buf[2];
shell_printf("%d/%d/%d %d\r\n", timespec.year+1980, timespec.month, timespec.day, timespec.millisecond); dt_buf[0] = rtc_get_tr_bcd(); // TR should be read first for sync
dt_buf[1] = rtc_get_dr_bcd(); // DR should be read second
static const uint8_t idx_to_time[] = {6,5,4,2, 1, 0};
static const char time_cmd[] = "y|m|d|h|min|sec";
// 0 1 2 4 5 6
// time[] ={sec, min, hr, 0, day, month, year, 0}
uint8_t *time = (uint8_t*)dt_buf;
if (argc == 3 && get_str_index(argv[0], "b") == 0){
rtc_set_time(my_atoui(argv[1]), my_atoui(argv[2]));
return;
}
if (argc!=2) goto usage;
int idx = get_str_index(argv[0], time_cmd);
uint32_t val = my_atoui(argv[1]);
if (idx < 0 || val > 99)
goto usage;
// Write byte value in struct
time[idx_to_time[idx]] = ((val/10)<<4)|(val%10); // value in bcd format
rtc_set_time(dt_buf[1], dt_buf[0]);
return;
usage:
shell_printf("20%02X/%02X/%02X %02X:%02X:%02X\r\n"\
"usage: time {[%s] 0-99} or {b 0xYYMMDD 0xHHMMSS}\r\n", time[6], time[5], time[4], time[2], time[1], time[0], time_cmd);
} }
#endif #endif
@ -2429,7 +2445,7 @@ static const VNAShellCommand commands[] =
#ifdef __VNA__ #ifdef __VNA__
{"offset" , cmd_offset , 0}, {"offset" , cmd_offset , 0},
#endif #endif
#ifdef ENABLE_TIME_COMMAND #ifdef __USE_RTC__
{"time" , cmd_time , 0}, {"time" , cmd_time , 0},
#endif #endif
{"dac" , cmd_dac , 0}, {"dac" , cmd_dac , 0},

177
rtc.c

@ -56,90 +56,119 @@ uint32_t rtc_get_FAT(void) {
return fattime; return fattime;
} }
void rtc_set_time(uint32_t dr, uint32_t tr) { // Finish of configuration procedure.
// Beginning of configuration procedure. static void rtc_exit_init(void) {
RTC->ISR |= RTC_ISR_INIT;
while ((RTC->ISR & RTC_ISR_INITF) == 0)
;
// Writing the registers.
RTC->TR = tr;
RTC->DR = dr;
RTC->ISR &= ~RTC_ISR_INIT; RTC->ISR &= ~RTC_ISR_INIT;
} }
#define RTC_PRER(a, s) ((((a) - 1) << 16) | ((s) - 1)) // Beginning of configuration procedure.
static bool rtc_enter_init(void){
RTC->ISR |= RTC_ISR_INIT;
uint32_t count = 4*65536;
while (--count)
if (RTC->ISR & RTC_ISR_INITF)
return true;
return false;
}
void rtc_set_time(uint32_t dr, uint32_t tr) {
if (rtc_enter_init()){
RTC->TR = tr; // Write TR register
RTC->DR = dr; // Write TD register
}
rtc_exit_init();
}
#ifdef VNA_AUTO_SELECT_RTC_SOURCE
// Enable LSE bypass if need
#if defined(STM32_LSE_BYPASS)
#define STM32_LSE_BYPASS RCC_BDCR_LSEBYP
#else
#define STM32_LSE_BYPASS 0
#endif
// Startup LSE or if not work, LSI generator
static void rtc_start_source(void){
// LSE already work (enabled and ready)
if ((RCC->BDCR & (RCC_BDCR_LSEON|RCC_BDCR_LSERDY|STM32_LSE_BYPASS)) == (RCC_BDCR_LSEON|RCC_BDCR_LSERDY|STM32_LSE_BYPASS))
return;
// If LSE not enabled, try startup
RCC->BDCR |= STM32_LSEDRV | STM32_LSE_BYPASS | RCC_BDCR_LSEON;
// Waits until LSE is stable (need ~150ms for startup).
chThdSleepMilliseconds(200);
if (RCC->BDCR & RCC_BDCR_LSERDY) return;
// Startup LSI if not allow start LSE
RCC->CSR |= RCC_CSR_LSION;
while ((RCC->CSR & RCC_CSR_LSIRDY) == 0);
}
static void resetBCDR(uint32_t rtc_drv){
// Backup domain reset, for change source.
RCC->BDCR = RCC_BDCR_BDRST;
RCC->BDCR = 0;
// Startup again source generator
rtc_start_source();
// Select new clock source. And enable
RCC->BDCR|= rtc_drv;
}
// Initiate RTC clock, LSE or LSI generators initiate by ChibiOS !!! void auto_backup_domain_init(void){
// Init Backup domain, RTC clock source
uint32_t rtc_drv;
// Backup domain access enabled and left open.
PWR->CR |= PWR_CR_DBP;
// Start/check source
rtc_start_source();
// Check LSE ready, if ok, select as source
rtc_drv = RCC->BDCR & RCC_BDCR_LSERDY ? STM32_RTCSEL_LSE|RCC_BDCR_RTCEN : // Select LSE as source
STM32_RTCSEL_LSI|RCC_BDCR_RTCEN; // Select LSI as source
// If the backup domain hasn't been initialized yet or work on different source, then proceed with initialization
if ((RCC->BDCR & (STM32_RTCSEL_MASK|RCC_BDCR_RTCEN)) != rtc_drv)
resetBCDR(rtc_drv);
/*
// Check RTC clock, and reset backup domain to LSI if clock not start
if (rtc_enter_init())
rtc_exit_init();
else
resetBCDR(STM32_RTCSEL_LSI|RCC_BDCR_RTCEN);
*/
}
#endif
// Initiate RTC clock
void rtc_init(void){ void rtc_init(void){
#ifdef VNA_AUTO_SELECT_RTC_SOURCE
// Auto start LSE or LSI source for RTC
auto_backup_domain_init();
#else
// ChibiOS init BDCR LSE or LSI source by self from user defined in mcuconf.h source
// For add auto select RTC source need rewrite it
// see hal_lld_backup_domain_init() in hal_lld.c for every CPU
// Default RTC clock is LSE, but it possible not launch if no quartz installed
#endif
uint32_t src = RCC->BDCR & STM32_RTCSEL_MASK;
if (src == STM32_RTCSEL_NOCLOCK) return;
// If calendar has not been initialized yet or different PRER settings then proceed with the initial setup.
// Disable write protection. // Disable write protection.
RTC->WPR = 0xCA; RTC->WPR = 0xCA;
RTC->WPR = 0x53; RTC->WPR = 0x53;
uint32_t rtc_prer = (src == STM32_RTCSEL_LSE) ? STM32_RTC_LSE_PRER :
STM32_RTC_LSI_PRER;
// If calendar has not been initialized yet then proceed with the initial setup. // If calendar has not been initialized yet then proceed with the initial setup.
if (!(RTC->ISR & RTC_ISR_INITS)) { if ((RTC->ISR & RTC_ISR_INITS) == 0 || RTC->PRER != rtc_prer) {
// Beginning of configuration procedure. if (rtc_enter_init()){
RTC->ISR |= RTC_ISR_INIT; RTC->CR = 0;
while ((RTC->ISR & RTC_ISR_INITF) == 0) RTC->ISR = RTC_ISR_INIT; // Clearing all but RTC_ISR_INIT.
; RTC->PRER = rtc_prer; // Prescaler value loaded in registers 2 times
RTC->CR = 0; RTC->PRER = rtc_prer;
RTC->ISR = RTC_ISR_INIT; // Clearing all but RTC_ISR_INIT. }
RTC->PRER = RTC_PRER(STM32_RTC_PRESA_VALUE, STM32_RTC_PRESS_VALUE); // Finalizing of configuration procedure.
RTC->PRER = RTC_PRER(STM32_RTC_PRESA_VALUE, STM32_RTC_PRESS_VALUE); rtc_exit_init();
RTC->ISR &= ~RTC_ISR_INIT;
} }
else else
RTC->ISR &= ~RTC_ISR_RSF; RTC->ISR &= ~RTC_ISR_RSF;
#if 0
// ChibiOS init BDCR by self!!
// For add auto select RTC source need rewrite it
// see hal_lld_backup_domain_init() in hal_lld.c for every CPU
// Default RTC clock is LSE, but it possible not launch if no quartz installed
uint32_t rtc_drv = STM32_RTCSEL_LSI;
uint32_t rtc_prer = RTC_PRER(40, 1000);
// If LSE off try launch it
if ((RCC->BDCR & RCC_BDCR_LSEON) == 0){
// Try start LSE
RCC->BDCR |= STM32_LSEDRV | RCC_BDCR_LSEON;
uint32_t count = 65535;
do{
if (RCC->BDCR & RCC_BDCR_LSERDY) break;
}while (--count);// Waits until LSE is stable. or count == 0
}
// Check, if LSE ready, then prepare it data
if (RCC->BDCR & RCC_BDCR_LSERDY){
rtc_drv = STM32_RTCSEL_LSE;
rtc_prer = RTC_PRER(32, 1024);
} else{
// Try start LSI
RCC->CSR |= RCC_CSR_LSION;
while ((RCC->CSR & RCC_CSR_LSIRDY) == 0)
;
}
PWR->CR |= PWR_CR_DBP;
// If the backup domain hasn't been initialized yet then proceed with initialization or source different
if ((RCC->BDCR & RCC_BDCR_RTCEN) == 0 || (RCC->BDCR & STM32_RTCSEL_MASK)!=rtc_drv) {
// Backup domain reset.
RCC->BDCR = RCC_BDCR_BDRST;
RCC->BDCR = 0;
// Selects clock source.
RCC->BDCR |= rtc_drv;
// Disable write protection.
RTC->WPR = 0xCA;
RTC->WPR = 0x53;
// Beginning of configuration procedure.
RTC->ISR |= RTC_ISR_INIT;
while ((RTC->ISR & RTC_ISR_INITF) == 0)
;
// Prescaler value loaded in registers.
RTC->CR = 0;
RTC->ISR = RTC_ISR_INIT; // Clearing all but RTC_ISR_INIT.
RTC->PRER = rtc_prer;
RTC->PRER = rtc_prer;
// Finalizing of configuration procedure.
RTC->ISR &= ~RTC_ISR_INIT;
RCC->BDCR |= RCC_BDCR_RTCEN; // RTC clock enabled.
}
#endif
} }
#endif #endif // __USE_RTC__

24
ui.c

@ -474,8 +474,8 @@ show_version(void)
do {shift>>=1; y+=5;} while (shift&1); do {shift>>=1; y+=5;} while (shift&1);
ili9341_drawstring(info_about[i++], x, y+=5); ili9341_drawstring(info_about[i++], x, y+=5);
} }
char buf[96];
#ifdef TINYSA4 #ifdef TINYSA4
static char buf[96];
extern const char *states[]; extern const char *states[];
#define ENABLE_THREADS_COMMAND #define ENABLE_THREADS_COMMAND
@ -501,14 +501,34 @@ extern const char *states[];
} while (tp != NULL); } while (tp != NULL);
#endif #endif
#endif // TINYSA4 #endif // TINYSA4
uint16_t cnt = 0;
while (true) { while (true) {
if (touch_check() == EVT_TOUCH_PRESSED) if (touch_check() == EVT_TOUCH_PRESSED)
break; break;
if (btn_check() & EVT_BUTTON_SINGLE_CLICK) if (btn_check() & EVT_BUTTON_SINGLE_CLICK)
break; break;
chThdSleepMilliseconds(40);
if ((cnt++)&0x07) continue; // Not update time so fast
#ifdef __USE_RTC__
uint32_t tr = rtc_get_tr_bin(); // TR read first
uint32_t dr = rtc_get_dr_bin(); // DR read second
plot_printf(buf, sizeof(buf), "Time: 20%02d/%02d/%02d %02d:%02d:%02d" " (LS%c)",
RTC_DR_YEAR(dr),
RTC_DR_MONTH(dr),
RTC_DR_DAY(dr),
RTC_TR_HOUR(dr),
RTC_TR_MIN(dr),
RTC_TR_SEC(dr),
(RCC->BDCR & STM32_RTCSEL_MASK) == STM32_RTCSEL_LSE ? 'E' : 'I');
ili9341_drawstring(buffer, x, y);
#endif
#if 1
uint32_t vbat=adc_vbat_read();
plot_printf(buf, sizeof(buf), "Batt: %d.%03dV", vbat/1000, vbat%1000);
ili9341_drawstring(buf, x, y + FONT_STR_HEIGHT + 2);
#endif
} }
touch_start_watchdog(); touch_start_watchdog();

Loading…
Cancel
Save

Powered by TurnKey Linux.