time sync (not tested)

This commit is contained in:
eddyem 2019-07-11 23:31:01 +03:00
parent 7ac9d908fa
commit 20728db47f
8 changed files with 132 additions and 93 deletions

Binary file not shown.

View File

@ -89,8 +89,8 @@ void hw_setup(){
} }
void exti1_isr(){ // PPS - PA1 void exti1_isr(){ // PPS - PA1
DBG("exti1");
systick_correction(); systick_correction();
DBG("exti1");
EXTI->PR = EXTI_PR_PR1; EXTI->PR = EXTI_PR_PR1;
} }

View File

@ -26,17 +26,6 @@
#include "stm32f1.h" #include "stm32f1.h"
// usb commands
// lower and upper limits to capture
#define CMD_DISTMIN "distmin"
#define CMD_DISTMAX "distmax"
#define CMD_ADC1MIN "adc1min"
#define CMD_ADC2MIN "adc2min"
#define CMD_ADC1MAX "adc1max"
#define CMD_ADC2MAX "adc2max"
#define CMD_PRINTTIME "time"
#define CMD_STORECONF "store"
// onboard LEDs - PB8/PB9 // onboard LEDs - PB8/PB9
#define LED0_port GPIOB #define LED0_port GPIOB
#define LED0_pin (1<<8) #define LED0_pin (1<<8)

View File

@ -39,8 +39,10 @@ volatile uint32_t Tms = 0;
/* Called when systick fires */ /* Called when systick fires */
void sys_tick_handler(void){ void sys_tick_handler(void){
++Tms; ++Tms; // increment pseudo-milliseconds counter
increment_timer(); if(++Timer == 1000){ // increment milliseconds counter
time_increment();
}
} }
void iwdg_setup(){ void iwdg_setup(){
@ -171,57 +173,6 @@ static char *get_USB(){
return NULL; return NULL;
} }
static void parse_USBCMD(char *cmd){
#define CMP(a,b) cmpstr(a, b, sizeof(b)-1)
#define GETNUM(x) if(getnum(cmd+sizeof(x)-1, &N)) goto bad_number;
static uint8_t conf_modified = 0;
uint8_t succeed = 0;
int32_t N;
if(!cmd || !*cmd) return;
if(*cmd == '?'){ // help
USB_send("Commands:\n"
CMD_DISTMIN " - min distance threshold (cm)\n"
CMD_DISTMAX " - max distance threshold (cm)\n"
CMD_PRINTTIME " - print time\n"
CMD_STORECONF " - store new configuration in flash\n"
);
}else if(CMP(cmd, CMD_PRINTTIME) == 0){
USB_send(get_time(&current_time, get_millis()));
}else if(CMP(cmd, CMD_DISTMIN) == 0){ // set low limit
DBG("CMD_DISTMIN");
GETNUM(CMD_DISTMIN);
if(N < 0 || N > 0xffff) goto bad_number;
if(the_conf.dist_min != (uint16_t)N){
conf_modified = 1;
the_conf.dist_min = (uint16_t) N;
succeed = 1;
}
}else if(CMP(cmd, CMD_DISTMAX) == 0){ // set low limit
DBG("CMD_DISTMAX");
GETNUM(CMD_DISTMAX);
if(N < 0 || N > 0xffff) goto bad_number;
if(the_conf.dist_max != (uint16_t)N){
conf_modified = 1;
the_conf.dist_max = (uint16_t) N;
succeed = 1;
}
}else if(CMP(cmd, CMD_STORECONF) == 0){ // store everything
DBG("Store");
if(conf_modified){
if(store_userconf()){
USB_send("Error: can't save data!\n");
}else{
conf_modified = 0;
succeed = 1;
}
}
}
if(succeed) USB_send("Success!\n");
return;
bad_number:
USB_send("Error: bad number!\n");
}
int main(void){ int main(void){
uint32_t lastT = 0; uint32_t lastT = 0;
sysreset(); sysreset();
@ -230,7 +181,7 @@ int main(void){
LED1_off(); LED1_off();
USBPU_OFF(); USBPU_OFF();
usarts_setup(); usarts_setup();
SysTick_Config(SYSTICK_DEFLOAD); SysTick_Config(SYSTICK_DEFCONF); // function SysTick_Config decrements argument!
SEND("Chronometer version " VERSION ".\n"); SEND("Chronometer version " VERSION ".\n");
if(RCC->CSR & RCC_CSR_IWDGRSTF){ // watchdog reset occured if(RCC->CSR & RCC_CSR_IWDGRSTF){ // watchdog reset occured
SEND("WDGRESET=1\n"); SEND("WDGRESET=1\n");
@ -280,10 +231,10 @@ int main(void){
int r = 0; int r = 0;
char *txt; char *txt;
if((txt = get_USB())){ if((txt = get_USB())){
parse_USBCMD(txt);
DBG("Received data over USB:"); DBG("Received data over USB:");
DBG(txt); DBG(txt);
USB_send(txt); // echo all back if(parse_USBCMD(txt))
USB_send(txt); // echo back non-commands data
} }
#if defined EBUG || defined USART1PROXY #if defined EBUG || defined USART1PROXY
if(usartrx(1)){ // usart1 received data, store in in buffer if(usartrx(1)){ // usart1 received data, store in in buffer

View File

@ -16,8 +16,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "flash.h"
#include "str.h" #include "str.h"
#include "time.h"
#include "usart.h" #include "usart.h"
#include "usb.h"
/** /**
* @brief cmpstr - the same as strncmp * @brief cmpstr - the same as strncmp
* @param s1,s2 - strings to compare * @param s1,s2 - strings to compare
@ -44,3 +48,60 @@ char *getchr(const char *str, char symbol){
}while(*(++str)); }while(*(++str));
return NULL; return NULL;
} }
/**
* @brief parse_USBCMD - parsing of string buffer got by USB
* @param cmd - buffer with commands
* @return 0 if got command, 1 if command not recognized
*/
int parse_USBCMD(char *cmd){
#define CMP(a,b) cmpstr(a, b, sizeof(b)-1)
#define GETNUM(x) if(getnum(cmd+sizeof(x)-1, &N)) goto bad_number;
static uint8_t conf_modified = 0;
uint8_t succeed = 0;
int32_t N;
if(!cmd || !*cmd) return 0;
if(*cmd == '?'){ // help
USB_send("Commands:\n"
CMD_DISTMIN " - min distance threshold (cm)\n"
CMD_DISTMAX " - max distance threshold (cm)\n"
CMD_PRINTTIME " - print time\n"
CMD_STORECONF " - store new configuration in flash\n"
);
}else if(CMP(cmd, CMD_PRINTTIME) == 0){
USB_send(get_time(&current_time, get_millis()));
}else if(CMP(cmd, CMD_DISTMIN) == 0){ // set low limit
DBG("CMD_DISTMIN");
GETNUM(CMD_DISTMIN);
if(N < 0 || N > 0xffff) goto bad_number;
if(the_conf.dist_min != (uint16_t)N){
conf_modified = 1;
the_conf.dist_min = (uint16_t) N;
succeed = 1;
}
}else if(CMP(cmd, CMD_DISTMAX) == 0){ // set low limit
DBG("CMD_DISTMAX");
GETNUM(CMD_DISTMAX);
if(N < 0 || N > 0xffff) goto bad_number;
if(the_conf.dist_max != (uint16_t)N){
conf_modified = 1;
the_conf.dist_max = (uint16_t) N;
succeed = 1;
}
}else if(CMP(cmd, CMD_STORECONF) == 0){ // store everything
DBG("Store");
if(conf_modified){
if(store_userconf()){
USB_send("Error: can't save data!\n");
}else{
conf_modified = 0;
succeed = 1;
}
}
}else return 1;
if(succeed) USB_send("Success!\n");
return 0;
bad_number:
USB_send("Error: bad number!\n");
return 0;
}

View File

@ -19,7 +19,18 @@
#ifndef STR_H__ #ifndef STR_H__
#define STR_H__ #define STR_H__
// usb commands
// lower and upper limits to capture
#define CMD_DISTMIN "distmin"
#define CMD_DISTMAX "distmax"
#define CMD_ADC1MIN "adc1min"
#define CMD_ADC2MIN "adc2min"
#define CMD_ADC1MAX "adc1max"
#define CMD_ADC2MAX "adc2max"
#define CMD_PRINTTIME "time"
#define CMD_STORECONF "store"
int cmpstr(const char *s1, const char *s2, int n); int cmpstr(const char *s1, const char *s2, int n);
char *getchr(const char *str, char symbol); char *getchr(const char *str, char symbol);
int parse_USBCMD(char *cmd);
#endif // STR_H__ #endif // STR_H__

View File

@ -18,20 +18,26 @@
#include "GPS.h" #include "GPS.h"
#include "time.h" #include "time.h"
#ifdef EBUG
#include "usart.h"
#endif
#include "usb.h" #include "usb.h"
#include <string.h> #include <string.h>
volatile uint32_t Timer; // milliseconds counter volatile uint32_t Timer; // milliseconds counter
curtime current_time = TMNOTINI; curtime current_time = TMNOTINI;
volatile int need_sync = 1;
// SysTick->LOAD values for all milliseconds (RVR0) and last millisecond (RVR1) // ms counter in last correction by PPS
static uint32_t RVR0 = SYSTICK_DEFLOAD, RVR1 = SYSTICK_DEFLOAD; static uint32_t last_corr_time = 0;
static inline uint8_t atou(const char *b){ static inline uint8_t atou(const char *b){
return (b[0]-'0')*10 + b[1]-'0'; return (b[0]-'0')*10 + b[1]-'0';
} }
/**
* @brief set_time - set current time from GPS data
* @param buf - buffer with time data (HHMMSS)
*/
void set_time(const char *buf){ void set_time(const char *buf){
uint8_t H = atou(buf) + TIMEZONE_GMT_PLUS; uint8_t H = atou(buf) + TIMEZONE_GMT_PLUS;
if(H > 23) H -= 24; if(H > 23) H -= 24;
@ -54,6 +60,10 @@ void time_increment(){
current_time.H = 0; current_time.H = 0;
} }
} }
#ifdef EBUG
SEND("time_increment(): ");
SEND(get_time(&current_time, 0));
#endif
} }
/** /**
@ -93,9 +103,9 @@ char *get_time(curtime *Tm, uint32_t T){
strcpy(bptr, " (not valid)"); strcpy(bptr, " (not valid)");
bptr += 12; bptr += 12;
} }
if(need_sync){ if(Tms - last_corr_time > 1000){
strcpy(bptr, " need synchronisation"); strcpy(bptr, " need PPS sync");
bptr += 21; bptr += 14;
} }
*bptr++ = '\n'; *bptr++ = '\n';
*bptr = 0; *bptr = 0;
@ -103,15 +113,39 @@ char *get_time(curtime *Tm, uint32_t T){
} }
/** /**
* @brief get_millis - calculate milliseconds due to global fix parameter * @brief systick_correction
* @return milliseconds value * Makes correction of system timer
* The default frequency of timer is 1kHz - 72000 clocks per interrupt
* So we check how much ticks there was for last one second - between PPS interrupts
* Their amount equal to M = `Timer` value x (SysTick->LOAD+1) + (SysTick->LOAD+1 - SysTick->VAL)
* if `Timer` is very small, add 1000 to its value.
* We need 1000xN ticks instead of M
* if L = LOAD+1, then
* M = Timer*L + L - VAL; newL = L + D = M/1000
* 1000*D = M - 1000*L = L(Timer+1-1000) - VAL ->
* D = [L*(Timer-999) - VAL]/1000
* So correction equal to
* [ (SysTick->LOAD + 1) * (Timer - 999) - SysTick->VAL ] / 1000
*/ */
uint32_t get_millis(){
// TODO: calculate right millis
return Tms % 1000; // temporary gag
}
void systick_correction(){ void systick_correction(){
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; // stop systick for a while
int32_t systick_val = SysTick->VAL, L = SysTick->LOAD + 1, timer_val = Timer;
SysTick->VAL = SysTick->LOAD;
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; // start it again
Timer = 0;
if(Tms - last_corr_time < 2000){ // calculate corrections only if Timer was zeroed last time
if(timer_val < 500) timer_val += 1000; // timer already incremented in SysTick interrupt
else time_increment(); // counter less than 1000 -> need to increment time
int32_t D = L * (timer_val - 999) - systick_val;
D /= 1000;
#ifdef EBUG
SEND("Delta: "); if(D < 0){usart_putchar(1, '-'); printu(1, -D);} else printu(1, D); newline();
SEND(get_time(&current_time, 0));
#endif
SysTick->LOAD += D;
}
last_corr_time = Tms;
#if 0
uint32_t t = 0, ticks; uint32_t t = 0, ticks;
static uint32_t ticksavr = 0, N = 0, last_corr_time = 0; static uint32_t ticksavr = 0, N = 0, last_corr_time = 0;
// correct // correct
@ -150,14 +184,6 @@ void systick_correction(){
} }
theend: theend:
last_corr_time = t; last_corr_time = t;
#endif
} }
void increment_timer(){
++Timer;
if(Timer == 999){
SysTick->LOAD = RVR1;
}else if(Timer == 1000){
SysTick->LOAD = RVR0;
time_increment();
}
}

View File

@ -34,6 +34,9 @@
#define TMNOTINI {25,61,61} #define TMNOTINI {25,61,61}
// current milliseconds
#define get_millis() (Timer)
typedef struct{ typedef struct{
uint8_t H; uint8_t H;
uint8_t M; uint8_t M;
@ -51,9 +54,7 @@ extern volatile int need_sync;
char *get_time(curtime *T, uint32_t m); char *get_time(curtime *T, uint32_t m);
void set_time(const char *buf); void set_time(const char *buf);
uint32_t get_millis(); // current milliseconds
void time_increment(); void time_increment();
void systick_correction(); void systick_correction();
void increment_timer();
#endif // TIME_H__ #endif // TIME_H__