add better version of EEPROM emulation in flash (for now - only in chronometer)

This commit is contained in:
eddyem 2019-07-10 23:38:56 +03:00
parent 3a5ef823db
commit 7ac9d908fa
17 changed files with 529 additions and 47 deletions

View File

@ -149,7 +149,9 @@ void GPS_send_start_seq(){
*/
void GPS_parse_answer(const char *buf){
char *ptr;
DBG(buf);
#if defined USART1PROXY
usart_send(1, buf); newline();
#endif
if(buf[1] == 'P') return; // answers to proprietary messages
if(cmpstr(buf+3, "RMC", 3)){ // not RMC message
need2startseq = 1;

View File

@ -12,6 +12,8 @@ LDSCRIPT ?= stm32f103x8.ld
DEFS = -DVERSION=\"0.0.1\"
# debug
DEFS += -DEBUG
# proxy GPS output over USART1
DEFS += -DUSART1PROXY
INDEPENDENT_HEADERS=

View File

@ -11,7 +11,7 @@ Chronometer for downhill competitions
- PB8, PB9 - onboard LEDs
- PA4 - TRIG2 - 12V trigger (EXTI)
- PA4 - TRIG2 - 12V trigger (EXTI) -- not implemented yet
- PA13 - TRIG0 - button0 (EXTI)
- PA14 - TRIG1 - button1/laser/etc (EXTI)
- PA15 - USB pullup

Binary file not shown.

View File

@ -0,0 +1,240 @@
/*
* geany_encoding=koi8-r
* flash.c
*
* Copyright 2017 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
*/
/**
ATTENTION!!
This things works only if you will add next section:
.myvars :
{
. = ALIGN(1024);
KEEP(*(.myvars))
} > rom
after section .data
*/
#include "stm32f1.h"
#include <string.h> // memcpy
#include "flash.h"
#include "lidar.h"
#ifdef EBUG
#include "usart.h"
#endif
extern uint32_t _edata, _etext, _sdata;
static int maxnum = FLASH_BLOCK_SIZE / sizeof(user_conf);
typedef struct{
const user_conf all_stored;
} flash_storage;
#define USERCONF_INITIALIZER { \
.userconf_sz = sizeof(user_conf) \
,.dist_min = LIDAR_MIN_DIST \
,.dist_max = LIDAR_MAX_DIST \
}
__attribute__((section(".myvars"))) static const flash_storage Flash_Storage = {
.all_stored = USERCONF_INITIALIZER
};
static const user_conf *Flash_Data = &Flash_Storage.all_stored;
user_conf the_conf = USERCONF_INITIALIZER;
static int erase_flash();
static int currentconfidx = -1; // index of current configuration
/**
* @brief binarySearch - binary search in flash for last non-empty cell
* @param l - left index
* @param r - right index (should be @1 less than last index!)
* @return index of non-empty cell or -1
*/
static int binarySearch(int l, int r){
while(r >= l){
int mid = l + (r - l) / 2;
// If the element is present at the middle
// itself
uint16_t sz = Flash_Data[mid].userconf_sz;
if(sz == sizeof(user_conf)){
if(Flash_Data[mid+1].userconf_sz == 0xffff){
#if 0
SEND("Found at "); printu(1, mid); newline();
#endif
return mid;
}else{ // element is to the right
l = mid + 1;
#if 0
SEND("To the right, L="); printu(1, l); newline();
#endif
}
}else{ // element is to the left
r = mid - 1;
#if 0
SEND("To the left, R="); printu(1, r); newline();
#endif
}
}
DBG("Not found!");
return -1; // not found
}
static int get_gooddata(){
static uint8_t firstrun = 1;
if(firstrun){
firstrun = 0;
if(FLASH_SIZE > 0 && FLASH_SIZE < 20000){
uint32_t flsz = FLASH_SIZE * 1024; // size in bytes
flsz -= (uint32_t)Flash_Data - FLASH_BASE;
#if 0
SEND("All size: "); printu(1, flsz); newline();
#endif
uint32_t usz = (sizeof(user_conf) + 1) / 2;
maxnum = flsz / 2 / usz;
#if 0
SEND("Maxnum: "); printu(1, maxnum); newline();
#endif
}
}
return binarySearch(0, maxnum-2); // -1 if there's no data at all & flash is clear; maxnum-1 if flash is full
}
void get_userconf(){
const user_conf *c = Flash_Data;
int idx = get_gooddata();
if(idx < 0) return; // no data stored
currentconfidx = idx;
memcpy(&the_conf, &c[idx], sizeof(user_conf));
}
// store new configuration
// @return 0 if all OK
int store_userconf(){
IWDG->KR = IWDG_REFRESH;
int ret = 0;
const user_conf *c = Flash_Data;
int idx = currentconfidx;
// maxnum - 3 means that there always should be at least one empty record after last data
if(idx < 0 || idx > maxnum - 3){ // data corruption or there's no more place
idx = 0;
DBG("Need to erase flash!");
if(erase_flash()) return 1;
}else ++idx; // take next data position
currentconfidx = idx;
if (FLASH->CR & FLASH_CR_LOCK){ // unloch flash
FLASH->KEYR = FLASH_KEY1;
FLASH->KEYR = FLASH_KEY2;
}
while (FLASH->SR & FLASH_SR_BSY);
if(FLASH->SR & FLASH_SR_WRPRTERR) return 1; // write protection
FLASH->SR = FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPRTERR; // clear all flags
FLASH->CR |= FLASH_CR_PG;
uint16_t *data = (uint16_t*) &the_conf;
uint16_t *address = (uint16_t*) &c[idx];
uint32_t i, count = (sizeof(user_conf) + 1) / 2;
for (i = 0; i < count; ++i){
*(volatile uint16_t*)(address + i) = data[i];
while (FLASH->SR & FLASH_SR_BSY);
if(FLASH->SR & FLASH_SR_PGERR) ret = 1; // program error - meet not 0xffff
else while (!(FLASH->SR & FLASH_SR_EOP));
FLASH->SR = FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPRTERR;
}
FLASH->CR &= ~(FLASH_CR_PG);
return ret;
}
static int erase_flash(){
int ret = 0;
uint32_t nblocks = 1;
if(FLASH_SIZE > 0 && FLASH_SIZE < 20000){
uint32_t flsz = FLASH_SIZE * 1024; // size in bytes
flsz -= (uint32_t)Flash_Data - FLASH_BASE;
nblocks = flsz / FLASH_BLOCK_SIZE;
#if 0
SEND("N blocks:"); printu(1, nblocks); newline();
#endif
}
for(uint32_t i = 0; i < nblocks; ++i){
IWDG->KR = IWDG_REFRESH;
/* (1) Wait till no operation is on going */
/* (2) Clear error & EOP bits */
/* (3) Check that the Flash is unlocked */
/* (4) Perform unlock sequence */
while ((FLASH->SR & FLASH_SR_BSY) != 0){} /* (1) */
FLASH->SR = FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPRTERR; /* (2) */
/* if (FLASH->SR & FLASH_SR_EOP){
FLASH->SR |= FLASH_SR_EOP;
}*/
if ((FLASH->CR & FLASH_CR_LOCK) != 0){ /* (3) */
FLASH->KEYR = FLASH_KEY1; /* (4) */
FLASH->KEYR = FLASH_KEY2;
}
/* (1) Set the PER bit in the FLASH_CR register to enable page erasing */
/* (2) Program the FLASH_AR register to select a page to erase */
/* (3) Set the STRT bit in the FLASH_CR register to start the erasing */
/* (4) Wait until the EOP flag in the FLASH_SR register set */
/* (5) Clear EOP flag by software by writing EOP at 1 */
/* (6) Reset the PER Bit to disable the page erase */
FLASH->CR |= FLASH_CR_PER; /* (1) */
#if 0
SEND("Delete block number "); printu(1, i); newline();
#endif
FLASH->AR = (uint32_t)Flash_Data + i*FLASH_BLOCK_SIZE; /* (2) */
FLASH->CR |= FLASH_CR_STRT; /* (3) */
while(!(FLASH->SR & FLASH_SR_EOP));
FLASH->SR |= FLASH_SR_EOP; /* (5)*/
if(FLASH->SR & FLASH_SR_WRPRTERR){ /* Check Write protection error */
ret = 1;
DBG("Write protection error!");
FLASH->SR |= FLASH_SR_WRPRTERR; /* Clear the flag by software by writing it at 1*/
break;
}
FLASH->CR &= ~FLASH_CR_PER; /* (6) */
}
return ret;
}
#ifdef EBUG
void dump_userconf(){
SEND("userconf_sz="); printu(1, the_conf.userconf_sz); newline();
SEND("dist_min="); printu(1, the_conf.dist_min); newline();
SEND("dist_max="); printu(1, the_conf.dist_max); newline();
}
void addNrecs(int N){
SEND("Try to store userconf for "); printu(1, N); SEND(" times\n");
for(int i = 0; i < N; ++i){
if(store_userconf()){
SEND("Error @ "); printu(1, i); newline();
return;
}
}
SEND("Curr idx: "); printu(1, currentconfidx); newline();
}
#endif

View File

@ -0,0 +1,48 @@
/*
* flash.h
*
* Copyright 2017 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
*/
#pragma once
#ifndef __FLASH_H__
#define __FLASH_H__
#include <stm32f1.h>
#define FLASH_BLOCK_SIZE (1024)
#define FLASH_SIZE_REG ((uint32_t)0x1FFFF7E0)
#define FLASH_SIZE *((uint16_t*)FLASH_SIZE_REG)
typedef struct{
uint16_t userconf_sz; // "magick number"
uint32_t dist_min; // minimal distance for LIDAR
uint32_t dist_max; // maximal -//-
} user_conf;
extern user_conf the_conf;
void get_userconf();
int store_userconf();
#ifdef EBUG
void dump_userconf();
void addNrecs(int N);
#endif
#endif // __FLASH_H__

View File

@ -23,6 +23,7 @@
#include "adc.h"
#include "hardware.h"
#include "time.h"
#include "usart.h"
static inline void gpio_setup(){
@ -30,10 +31,10 @@ static inline void gpio_setup(){
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | RCC_APB2ENR_IOPCEN | RCC_APB2ENR_AFIOEN;
// turn off SWJ/JTAG
AFIO->MAPR = AFIO_MAPR_SWJ_CFG_DISABLE;
// pullups
GPIOA->ODR = (1<<12)|(1<<13)|(1<<14);
// Set led (PB8) as opendrain output
GPIOB->CRH = CRH(8, CNF_ODOUTPUT|MODE_SLOW);
// pullups: PA1 - PPS, PA13/PA14 - buttons
GPIOA->ODR = (1<<12)|(1<<13)|(1<<14)|(1<<15);
// Set leds (PB8) as opendrain output
GPIOB->CRH = CRH(8, CNF_ODOUTPUT|MODE_SLOW) | CRH(9, CNF_ODOUTPUT|MODE_SLOW);
// PPS pin (PA1) - input with weak pullup
GPIOA->CRL = CRL(1, CNF_PUDINPUT|MODE_INPUT);
// Set buttons (PA13/14) as inputs with weak pullups, USB pullup (PA15) - opendrain output
@ -88,13 +89,8 @@ void hw_setup(){
}
void exti1_isr(){ // PPS - PA1
/*
if(trigger_ms[2] == DIDNT_TRIGGERED){ // prevent bounce
trigger_ms[2] = Timer;
memcpy(&trigger_time[2], &current_time, sizeof(curtime));
}
*/
DBG("exti1");
systick_correction();
EXTI->PR = EXTI_PR_PR1;
}

View File

@ -35,10 +35,13 @@
#define CMD_ADC1MAX "adc1max"
#define CMD_ADC2MAX "adc2max"
#define CMD_PRINTTIME "time"
#define CMD_STORECONF "store"
// onboard LED - PB8
#define LED_port GPIOB
#define LED_pin (1<<8)
// onboard LEDs - PB8/PB9
#define LED0_port GPIOB
#define LED0_pin (1<<8)
#define LED1_port GPIOB
#define LED1_pin (1<<9)
// PPS pin - PA1
#define PPS_port GPIOA
@ -55,9 +58,12 @@
#define USBPU_ON() pin_clear(USBPU_port, USBPU_pin)
#define USBPU_OFF() pin_set(USBPU_port, USBPU_pin)
#define LED_blink() pin_toggle(LED_port, LED_pin)
#define LED_on() pin_clear(LED_port, LED_pin)
#define LED_off() pin_set(LED_port, LED_pin)
#define LED_blink() pin_toggle(LED0_port, LED0_pin)
#define LED_on() pin_clear(LED0_port, LED0_pin)
#define LED_off() pin_set(LED0_port, LED0_pin)
#define LED1_blink() pin_toggle(LED1_port, LED1_pin)
#define LED1_on() pin_clear(LED1_port, LED1_pin)
#define LED1_off() pin_set(LED1_port, LED1_pin)
// GPS USART == USART2, LIDAR USART == USART3
#define GPS_USART (2)

View File

@ -16,11 +16,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "flash.h"
#include "lidar.h"
#include "usart.h"
uint16_t lidar_max_dist = 100;
uint16_t lidar_min_dist = 50;
uint16_t last_lidar_dist = 0;
uint16_t last_lidar_stren = 0;
uint16_t lidar_triggered_dist = 0;
@ -35,7 +34,7 @@ void parse_lidar_data(char *txt){
return;
}
if(triggered){ // check if body gone
if(last_lidar_dist < lidar_min_dist || last_lidar_dist > lidar_max_dist || last_lidar_dist > lidar_triggered_dist + LIDAR_DIST_THRES){
if(last_lidar_dist < the_conf.dist_min || last_lidar_dist > the_conf.dist_max || last_lidar_dist > lidar_triggered_dist + LIDAR_DIST_THRES){
triggered = 0;
#ifdef EBUG
SEND("Untriggered! distance=");
@ -46,7 +45,7 @@ void parse_lidar_data(char *txt){
#endif
}
}else{
if(last_lidar_dist > lidar_min_dist && last_lidar_dist < lidar_max_dist){
if(last_lidar_dist > the_conf.dist_min && last_lidar_dist < the_conf.dist_max){
triggered = 1;
lidar_triggered_dist = last_lidar_dist;
#ifdef EBUG

View File

@ -27,6 +27,9 @@
#define LIDAR_LOWER_STREN (10)
// triggered distance threshold - 1 meter
#define LIDAR_DIST_THRES (100)
#define LIDAR_MIN_DIST (50)
#define LIDAR_MAX_DIST (1000)
extern uint16_t last_lidar_dist;
extern uint16_t lidar_triggered_dist;
extern uint16_t last_lidar_stren;

View File

@ -21,6 +21,7 @@
//#include "adc.h"
#include "GPS.h"
#include "flash.h"
#include "hardware.h"
#include "lidar.h"
#include "str.h"
@ -33,11 +34,13 @@
#define VERSION "0.0.0"
#endif
// global pseudo-milliseconds counter
volatile uint32_t Tms = 0;
/* Called when systick fires */
void sys_tick_handler(void){
++Tms;
increment_timer();
}
void iwdg_setup(){
@ -65,8 +68,8 @@ void iwdg_setup(){
#ifdef EBUG
char *parse_cmd(char *buf){
int32_t N;
static char btns[] = "BTN0=0, BTN1=0, PPS=0\n";
if(buf[1] != '\n') return buf;
switch(*buf){
case '0':
LED_off();
@ -80,6 +83,16 @@ char *parse_cmd(char *buf){
btns[20] = GET_PPS() + '0';
return btns;
break;
case 'C':
if(getnum(&buf[1], &N)){
SEND("Need a number!\n");
}else{
addNrecs(N);
}
break;
case 'd':
dump_userconf();
break;
case 'p':
pin_toggle(USBPU_port, USBPU_pin);
SEND("USB pullup is ");
@ -117,10 +130,13 @@ char *parse_cmd(char *buf){
while(1){nop();};
break;
default: // help
if(buf[1] != '\n') return buf;
return
"0/1 - turn on/off LED1\n"
"'b' - get buttons's state\n"
"'d' - dump current user conf\n"
"'p' - toggle USB pullup\n"
"'C' - store userconf for N times\n"
"'G' - get last LIDAR distance\n"
"'L' - send long string over USB\n"
"'R' - software reset\n"
@ -155,22 +171,55 @@ static char *get_USB(){
return NULL;
}
#define CMP(a,b) cmpstr(a, b, sizeof(b)-1)
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_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){
@ -178,9 +227,10 @@ int main(void){
sysreset();
StartHSE();
hw_setup();
LED1_off();
USBPU_OFF();
usarts_setup();
SysTick_Config(72000);
SysTick_Config(SYSTICK_DEFLOAD);
SEND("Chronometer version " VERSION ".\n");
if(RCC->CSR & RCC_CSR_IWDGRSTF){ // watchdog reset occured
SEND("WDGRESET=1\n");
@ -191,14 +241,27 @@ int main(void){
RCC->CSR |= RCC_CSR_RMVF; // remove reset flags
USB_setup();
//iwdg_setup();
iwdg_setup();
USBPU_ON();
// read data stored in flash
#ifdef EBUG
SEND("Old config:\n");
dump_userconf();
#endif
//writeatend();
get_userconf();
#ifdef EBUG
SEND("New config:\n");
dump_userconf();
#endif
while (1){
IWDG->KR = IWDG_REFRESH; // refresh watchdog
if(lastT > Tms || Tms - lastT > 499){
if(need2startseq) GPS_send_start_seq();
LED_blink();
if(GPS_status != GPS_VALID) LED1_blink();
else LED1_on();
lastT = Tms;
if(usartrx(LIDAR_USART)){
char *txt;
@ -207,7 +270,7 @@ int main(void){
DBG(txt);
}
}
#ifdef EBUG
#if defined EBUG || defined USART1PROXY
transmit_tbuf(1); // non-blocking transmission of data from UART buffer every 0.5s
#endif
transmit_tbuf(GPS_USART);
@ -215,23 +278,28 @@ int main(void){
}
usb_proc();
int r = 0;
char *txt, *ans;
char *txt;
if((txt = get_USB())){
parse_USBCMD(txt);
DBG("Received data over USB:");
DBG(txt);
USB_send(txt); // echo all back
}
#ifdef EBUG
#if defined EBUG || defined USART1PROXY
if(usartrx(1)){ // usart1 received data, store in in buffer
r = usart_getline(1, &txt);
if(r){
txt[r] = 0;
ans = parse_cmd(txt);
#ifdef EBUG
char *ans = parse_cmd(txt);
if(ans){
transmit_tbuf(1);
usart_send(1, ans);
transmit_tbuf(1);
}
#else // USART1PROXY - send received data to GPS
usart_send(GPS_USART, txt);
#endif
}
}
#endif
@ -251,4 +319,3 @@ int main(void){
}
return 0;
}

View File

@ -21,9 +21,13 @@
#include "usb.h"
#include <string.h>
volatile uint32_t Timer; // milliseconds counter
curtime current_time = TMNOTINI;
volatile int need_sync = 1;
// SysTick->LOAD values for all milliseconds (RVR0) and last millisecond (RVR1)
static uint32_t RVR0 = SYSTICK_DEFLOAD, RVR1 = SYSTICK_DEFLOAD;
static inline uint8_t atou(const char *b){
return (b[0]-'0')*10 + b[1]-'0';
}
@ -36,6 +40,22 @@ void set_time(const char *buf){
current_time.S = atou(&buf[4]);
}
/**
* @brief time_increment - increment system timer by systick
*/
void time_increment(){
Timer = 0;
if(current_time.H == 25) return; // Time not initialized
if(++current_time.S == 60){
current_time.S = 0;
if(++current_time.M == 60){
current_time.M = 0;
if(++current_time.H == 24)
current_time.H = 0;
}
}
}
/**
* print time: Tm - time structure, T - milliseconds
*/
@ -90,3 +110,54 @@ uint32_t get_millis(){
// TODO: calculate right millis
return Tms % 1000; // temporary gag
}
void systick_correction(){
uint32_t t = 0, ticks;
static uint32_t ticksavr = 0, N = 0, last_corr_time = 0;
// correct
int32_t systick_val = SysTick->VAL;
// SysTick->LOAD values for all milliseconds (RVR0) and last millisecond (RVR1)
SysTick->VAL = RVR0;
int32_t timer_val = Timer;
Timer = 0;
// RVR -> SysTick->LOAD
systick_val = SysTick->LOAD + 1 - systick_val; // Systick counts down!
if(timer_val < 10) timer_val += 1000; // our closks go faster than real
else if(timer_val < 990){ // something wrong
RVR0 = RVR1 = SYSTICK_DEFLOAD;
SysTick->LOAD = RVR0;
need_sync = 1;
goto theend;
}else
time_increment(); // ms counter less than 1000 - we need to increment time
t = current_time.H * 3600 + current_time.M * 60 + current_time.S;
if(t - last_corr_time == 1){ // PPS interval == 1s
ticks = systick_val + (timer_val-1)*(RVR0 + 1) + RVR1 + 1;
++N;
ticksavr += ticks;
if(N > 20){
ticks = ticksavr / N;
RVR0 = ticks / 1000 - 1; // main RVR value
SysTick->LOAD = RVR0;
RVR1 = RVR0 + ticks % 1000; // last millisecond RVR value (with fine correction)
N = 0;
ticksavr = 0;
need_sync = 0;
}
}else{
N = 0;
ticksavr = 0;
}
theend:
last_corr_time = t;
}
void increment_timer(){
++Timer;
if(Timer == 999){
SysTick->LOAD = RVR1;
}else if(Timer == 1000){
SysTick->LOAD = RVR0;
time_increment();
}
}

View File

@ -21,8 +21,11 @@
#include <stm32f1.h>
#define STK_RVR_DEFAULT_VAL (8999)
#define TIMEZONE_GMT_PLUS (3)
// default value for systick_config
#define SYSTICK_DEFCONF (72000)
// defaul for systick->load
#define SYSTICK_DEFLOAD (SYSTICK_DEFCONF - 1)
#define TIMEZONE_GMT_PLUS (3)
#define DIDNT_TRIGGERED (2000)
@ -38,6 +41,7 @@ typedef struct{
} curtime;
extern volatile uint32_t Tms;
extern volatile uint32_t Timer;
extern curtime current_time;
extern curtime trigger_time[];
@ -48,5 +52,8 @@ extern volatile int need_sync;
char *get_time(curtime *T, uint32_t m);
void set_time(const char *buf);
uint32_t get_millis(); // current milliseconds
void time_increment();
void systick_correction();
void increment_timer();
#endif // TIME_H__

View File

@ -94,7 +94,7 @@ void usart_send(int n, const char *str){
tbuf[n][tbufno[n]][odatalen[n][tbufno[n]]++] = *str++;
}
}
#ifdef EBUG
#if defined EBUG || defined USART1PROXY
// only for USART1
void newline(){
usart_putchar(1, '\n');
@ -168,8 +168,8 @@ static void usart_setup(int n, uint32_t BRR){
void usarts_setup(){
RCC->AHBENR |= RCC_AHBENR_DMA1EN;
#ifdef EBUG
usart_setup(1, 72000000 / 115200); // debug console
#if defined EBUG || defined USART1PROXY
usart_setup(1, 72000000 / 115200); // debug console or GPS proxy
#endif
usart_setup(2, 36000000 / 9600); // GPS
usart_setup(3, 36000000 / 115200); // LIDAR
@ -215,7 +215,7 @@ void usart_isr(int n, USART_TypeDef *USART){
}
}
#ifdef EBUG
#if defined EBUG || defined USART1PROXY
void usart1_isr(){
usart_isr(1, USART1);
}
@ -310,7 +310,7 @@ void hexdump(uint8_t *arr, uint16_t len){
}
#endif
#ifdef EBUG
#if defined EBUG || defined USART1PROXY
void dma1_channel4_isr(){ // USART1
if(DMA1->ISR & DMA_ISR_TCIF4){ // Tx
DMA1->IFCR = DMA_IFCR_CTCIF4; // clear TC flag
@ -332,3 +332,34 @@ void dma1_channel2_isr(){ // USART3
txrdy[3] = 1;
}
}
// read `buf` and get first integer `N` in it
// @return 0 if all OK or 1 if there's not a number; omit spaces and '='
int getnum(const char *buf, int32_t *N){
char c;
int positive = -1;
int32_t val = 0;
while((c = *buf++)){
if(c == '\t' || c == ' ' || c == '='){
if(positive < 0) continue; // beginning spaces
else break; // spaces after number
}
if(c == '-'){
if(positive < 0){
positive = 0;
continue;
}else break; // there already was `-` or number
}
if(c < '0' || c > '9') break;
if(positive < 0) positive = 1;
val = val * 10 + (int32_t)(c - '0');
}
if(positive != -1){
if(positive == 0){
if(val == 0) return 1; // single '-'
val = -val;
}
*N = val;
}else return 1;
return 0;
}

View File

@ -55,13 +55,13 @@ void usart_putchar(int n, char ch);
char *u2str(uint32_t val);
void printu(int n, uint32_t val);
void printuhex(int n, uint32_t val);
int getnum(const char *buf, int32_t *N);
#ifdef EBUG
#if defined EBUG || defined USART1PROXY
void newline();
#endif
#ifdef EBUG
void hexdump(uint8_t *arr, uint16_t len);
#endif
/*
void hexdump16(uint16_t *arr, uint16_t len);
void hexdump32(uint32_t *arr, uint16_t len);
*/
#endif // __USART_H__

View File

@ -102,6 +102,10 @@ void usb_proc(){
}
void USB_send(char *buf){
if(!USB_configured()){
DBG("USB not configured");
return;
}
uint16_t l = 0, ctr = 0;
char *p = buf;
while(*p++) ++l;

View File

@ -52,7 +52,7 @@ SECTIONS {
. = ALIGN(4);
_etext = .;
} >rom
.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
@ -71,6 +71,12 @@ SECTIONS {
_edata = .;
} >ram AT >rom
.myvars :
{
. = ALIGN(1024);
KEEP(*(.myvars))
} > rom
_ldata = LOADADDR(.data);
.bss :
@ -84,4 +90,4 @@ SECTIONS {
} >ram
}
PROVIDE(_stack = ORIGIN(ram) + LENGTH(ram));
PROVIDE(_stack = ORIGIN(ram) + LENGTH(ram));