mirror of
https://github.com/eddyem/stm32samples.git
synced 2025-12-06 18:55:13 +03:00
Start with events storage in MCU flash
This commit is contained in:
parent
29d62c26c7
commit
7be1737383
@ -8,8 +8,8 @@ MCU ?= F103x8
|
|||||||
# density (stm32f10x.h, lines 70-84)
|
# density (stm32f10x.h, lines 70-84)
|
||||||
DENSITY ?= MD
|
DENSITY ?= MD
|
||||||
# change this linking script depending on particular MCU model,
|
# change this linking script depending on particular MCU model,
|
||||||
LDSCRIPT ?= stm32f103xB.ld
|
LDSCRIPT ?= stm32F103xB.ld
|
||||||
DEFS = -DVERSION=\"0.0.1\"
|
DEFS = -DVERSION=\"0.0.2\"
|
||||||
# debug
|
# debug
|
||||||
#DEFS += -DEBUG
|
#DEFS += -DEBUG
|
||||||
# proxy GPS output over USART1
|
# proxy GPS output over USART1
|
||||||
@ -66,7 +66,7 @@ CFLAGS += $(ARCH_FLAGS)
|
|||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Linker flags
|
# Linker flags
|
||||||
LDFLAGS += -nostartfiles --static -nostdlibs
|
LDFLAGS += --static -nostartfiles -nostdlibs
|
||||||
LDFLAGS += -L$(LIB_DIR) -L$(TOOLCHLIB)
|
LDFLAGS += -L$(LIB_DIR) -L$(TOOLCHLIB)
|
||||||
LDFLAGS += -T$(LDSCRIPT)
|
LDFLAGS += -T$(LDSCRIPT)
|
||||||
|
|
||||||
@ -114,7 +114,7 @@ $(LIST): $(ELF)
|
|||||||
@echo " OBJDUMP $(LIST)"
|
@echo " OBJDUMP $(LIST)"
|
||||||
$(OBJDUMP) -S $(ELF) > $(LIST)
|
$(OBJDUMP) -S $(ELF) > $(LIST)
|
||||||
|
|
||||||
$(ELF): $(OBJDIR) $(OBJS)
|
$(ELF): $(OBJDIR) $(OBJS) $(LDSCRIPT)
|
||||||
@echo " LD $(ELF)"
|
@echo " LD $(ELF)"
|
||||||
$(LD) $(LDFLAGS) $(OBJS) $(LDLIBS) -o $(ELF)
|
$(LD) $(LDFLAGS) $(OBJS) $(LDLIBS) -o $(ELF)
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
@ -39,117 +39,162 @@
|
|||||||
#include "adc.h"
|
#include "adc.h"
|
||||||
#include "flash.h"
|
#include "flash.h"
|
||||||
#include "lidar.h"
|
#include "lidar.h"
|
||||||
|
#include "str.h"
|
||||||
#include "usart.h" // DBG
|
#include "usart.h" // DBG
|
||||||
|
#include "usb.h" // printout
|
||||||
#include <string.h> // memcpy
|
#include <string.h> // memcpy
|
||||||
|
|
||||||
extern uint32_t _edata, _etext, _sdata;
|
// max amount of records stored: Config & Logs
|
||||||
static int maxnum = FLASH_BLOCK_SIZE / sizeof(user_conf);
|
static int maxCnum = FLASH_BLOCK_SIZE / sizeof(user_conf);
|
||||||
|
static int maxLnum = FLASH_BLOCK_SIZE / sizeof(user_conf);
|
||||||
|
|
||||||
|
// common structure for all datatypes stored
|
||||||
|
/*typedef struct {
|
||||||
|
uint16_t userconf_sz;
|
||||||
|
} flash_storage;*/
|
||||||
|
|
||||||
typedef struct{
|
#define USERCONF_INITIALIZER { \
|
||||||
const user_conf all_stored;
|
/* .magick = 0xAB, */ \
|
||||||
} flash_storage;
|
|
||||||
|
|
||||||
#define USERCONF_INITIALIZER { \
|
|
||||||
.userconf_sz = sizeof(user_conf) \
|
.userconf_sz = sizeof(user_conf) \
|
||||||
,.dist_min = LIDAR_MIN_DIST \
|
,.dist_min = LIDAR_MIN_DIST \
|
||||||
,.dist_max = LIDAR_MAX_DIST \
|
,.dist_max = LIDAR_MAX_DIST \
|
||||||
,.trig_pullups = 0xff \
|
|
||||||
,.trigstate = 0 \
|
,.trigstate = 0 \
|
||||||
,.trigpause = {400, 400, 400, 300, 300} \
|
,.trigpause = {400, 400, 400, 300, 300} \
|
||||||
,.ADC_min = ADC_MIN_VAL \
|
,.ADC_min = ADC_MIN_VAL \
|
||||||
,.ADC_max = ADC_MAX_VAL \
|
,.ADC_max = ADC_MAX_VAL \
|
||||||
|
,.USART_speed = USART1_DEFAULT_SPEED \
|
||||||
|
,.strendRN = 0 \
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((section(".myvars"))) static const flash_storage Flash_Storage = {
|
// change to placement
|
||||||
.all_stored = USERCONF_INITIALIZER
|
/*
|
||||||
};
|
__attribute__ ((section(".logs"))) const uint32_t *logsstart;
|
||||||
|
__attribute__ ((section(".myvars"))) const user_conf *Flash_Data;
|
||||||
|
*/
|
||||||
|
|
||||||
static const user_conf *Flash_Data = &Flash_Storage.all_stored;
|
static int erase_flash(const void*, const void*);
|
||||||
|
static int write2flash(const void*, const void*, int);
|
||||||
|
|
||||||
|
const user_conf *Flash_Data = (const user_conf *)&__varsstart;
|
||||||
|
const event_log *logsstart = (event_log*) &__logsstart;
|
||||||
|
|
||||||
user_conf the_conf = USERCONF_INITIALIZER;
|
user_conf the_conf = USERCONF_INITIALIZER;
|
||||||
|
|
||||||
static int erase_flash();
|
|
||||||
|
|
||||||
static int currentconfidx = -1; // index of current configuration
|
static int currentconfidx = -1; // index of current configuration
|
||||||
|
static int currentlogidx = -1; // index of current logs record
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief binarySearch - binary search in flash for last non-empty cell
|
* @brief binarySearch - binary search in flash for last non-empty cell
|
||||||
|
* any struct searched should have its sizeof() @ the first field!!!
|
||||||
* @param l - left index
|
* @param l - left index
|
||||||
* @param r - right index (should be @1 less than last index!)
|
* @param r - right index (should be @1 less than last index!)
|
||||||
|
* @param start - starting address
|
||||||
|
* @param stor_size - size of structure to search
|
||||||
* @return index of non-empty cell or -1
|
* @return index of non-empty cell or -1
|
||||||
*/
|
*/
|
||||||
static int binarySearch(int l, int r){
|
static int binarySearch(int l, int r, uint8_t *start, int stor_size){
|
||||||
|
/*DBG("start: "); printuhex(1, (uint32_t)start);
|
||||||
|
DBG("\nsizeof: "); printu(1, stor_size);
|
||||||
|
newline();*/
|
||||||
while(r >= l){
|
while(r >= l){
|
||||||
int mid = l + (r - l) / 2;
|
int mid = l + (r - l) / 2;
|
||||||
// If the element is present at the middle
|
uint8_t *s = start + mid * stor_size;
|
||||||
// itself
|
if(*((uint16_t*)s) == stor_size){
|
||||||
uint16_t sz = Flash_Data[mid].userconf_sz;
|
if(*((uint16_t*)(s + stor_size)) == 0xffff){
|
||||||
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;
|
return mid;
|
||||||
}else{ // element is to the right
|
}else{ // element is to the right
|
||||||
l = mid + 1;
|
l = mid + 1;
|
||||||
#if 0
|
|
||||||
SEND("To the right, L="); printu(1, l); newline();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}else{ // element is to the left
|
}else{ // element is to the left
|
||||||
r = mid - 1;
|
r = mid - 1;
|
||||||
#if 0
|
|
||||||
SEND("To the left, R="); printu(1, r); newline();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DBG("Not found!");
|
|
||||||
return -1; // not found
|
return -1; // not found
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_gooddata(){
|
/**
|
||||||
static uint8_t firstrun = 1;
|
* @brief flashstorage_init - initialization of user conf & logs storage
|
||||||
if(firstrun){
|
* run in once @ start
|
||||||
firstrun = 0;
|
*/
|
||||||
if(FLASH_SIZE > 0 && FLASH_SIZE < 20000){
|
void flashstorage_init(){
|
||||||
uint32_t flsz = FLASH_SIZE * 1024; // size in bytes
|
maxCnum = ((uint32_t)&_varslen) / sizeof(user_conf);
|
||||||
flsz -= (uint32_t)Flash_Data - FLASH_BASE;
|
//SEND("maxCnum="); printu(1, maxCnum);
|
||||||
#if 0
|
if(FLASH_SIZE > 0 && FLASH_SIZE < 20000){
|
||||||
SEND("All size: "); printu(1, flsz); newline();
|
uint32_t flsz = FLASH_SIZE * 1024; // size in bytes
|
||||||
#endif
|
flsz -= (uint32_t)logsstart - FLASH_BASE;
|
||||||
uint32_t usz = (sizeof(user_conf) + 1) / 2;
|
maxLnum = flsz / sizeof(event_log);
|
||||||
maxnum = flsz / 2 / usz;
|
//SEND("\nmaxLnum="); printu(1, maxLnum);
|
||||||
#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
|
// -1 if there's no data at all & flash is clear; maxnum-1 if flash is full
|
||||||
}
|
currentconfidx = binarySearch(0, maxCnum-2, (uint8_t*)Flash_Data, sizeof(user_conf));
|
||||||
|
if(currentconfidx > -1){
|
||||||
void get_userconf(){
|
memcpy(&the_conf, &Flash_Data[currentconfidx], sizeof(user_conf));
|
||||||
const user_conf *c = Flash_Data;
|
}
|
||||||
int idx = get_gooddata();
|
currentlogidx = binarySearch(0, maxLnum-2, (uint8_t*)logsstart, sizeof(event_log));
|
||||||
if(idx < 0) return; // no data stored
|
SEND("\ncurrentconfidx="); printu(1, currentconfidx);
|
||||||
currentconfidx = idx;
|
SEND("\ncurrentlogidx="); printu(1, currentlogidx);
|
||||||
memcpy(&the_conf, &c[idx], sizeof(user_conf));
|
newline();
|
||||||
}
|
}
|
||||||
|
|
||||||
// store new configuration
|
// store new configuration
|
||||||
// @return 0 if all OK
|
// @return 0 if all OK
|
||||||
int store_userconf(){
|
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
|
// 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
|
// for binarySearch() checking that there's nothing more after it!
|
||||||
idx = 0;
|
if(currentconfidx > maxCnum - 3){ // there's no more place
|
||||||
|
currentconfidx = 0;
|
||||||
DBG("Need to erase flash!");
|
DBG("Need to erase flash!");
|
||||||
if(erase_flash()) return 1;
|
if(erase_flash(Flash_Data, &__varsend)) return 1;
|
||||||
}else ++idx; // take next data position
|
}else ++currentconfidx; // take next data position (0 - within first run after firmware flashing)
|
||||||
currentconfidx = idx;
|
SEND("store_userconf\n");
|
||||||
|
SEND("\ncurrentconfidx="); printu(1, currentconfidx);
|
||||||
|
newline();
|
||||||
|
return write2flash(&Flash_Data[currentconfidx], &the_conf, sizeof(the_conf));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief store_log - save log record L into flash memory
|
||||||
|
* @param L - event log
|
||||||
|
* @return 0 if all OK
|
||||||
|
*/
|
||||||
|
int store_log(event_log *L){
|
||||||
|
if(currentlogidx > maxLnum - 3){ // there's no more place
|
||||||
|
currentlogidx = 0;
|
||||||
|
DBG("Need to erase flash!");
|
||||||
|
if(erase_flash(logsstart, NULL)) return 1;
|
||||||
|
}else ++currentlogidx; // take next data position (0 - within first run after firmware flashing)
|
||||||
|
SEND("sore_log\n");
|
||||||
|
SEND("\ncurrentlogidx="); printu(1, currentlogidx);
|
||||||
|
newline();
|
||||||
|
return write2flash(&logsstart[currentlogidx], L, sizeof(event_log));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief dump_log - dump N log records
|
||||||
|
* @param start - first record to show (if start<0, then first=last+start)
|
||||||
|
* @param Nlogs - amount of logs to show (if Nlogs<=0, then show all logs)
|
||||||
|
* @return 0 if all OK, 1 if there's no logs in flash
|
||||||
|
*/
|
||||||
|
int dump_log(int start, int Nlogs){
|
||||||
|
if(currentlogidx < 0) return 1;
|
||||||
|
if(start < 0) start += currentlogidx;
|
||||||
|
if(start > currentlogidx) return 1;
|
||||||
|
int nlast;
|
||||||
|
if(Nlogs > 0){
|
||||||
|
nlast = start + Nlogs;
|
||||||
|
if(nlast > currentlogidx) nlast = currentlogidx;
|
||||||
|
}else nlast = currentlogidx;
|
||||||
|
++nlast;
|
||||||
|
const event_log *l = logsstart + start;
|
||||||
|
for(int i = start; i < nlast; ++i, ++l){
|
||||||
|
IWDG->KR = IWDG_REFRESH;
|
||||||
|
USB_send(get_trigger_shot(i, l));
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int write2flash(const void *start, const void *wrdata, int stor_size){
|
||||||
|
int ret = 0;
|
||||||
if (FLASH->CR & FLASH_CR_LOCK){ // unloch flash
|
if (FLASH->CR & FLASH_CR_LOCK){ // unloch flash
|
||||||
FLASH->KEYR = FLASH_KEY1;
|
FLASH->KEYR = FLASH_KEY1;
|
||||||
FLASH->KEYR = FLASH_KEY2;
|
FLASH->KEYR = FLASH_KEY2;
|
||||||
@ -158,10 +203,11 @@ int store_userconf(){
|
|||||||
if(FLASH->SR & FLASH_SR_WRPRTERR) return 1; // write protection
|
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->SR = FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPRTERR; // clear all flags
|
||||||
FLASH->CR |= FLASH_CR_PG;
|
FLASH->CR |= FLASH_CR_PG;
|
||||||
uint16_t *data = (uint16_t*) &the_conf;
|
uint16_t *data = (uint16_t*) wrdata;
|
||||||
uint16_t *address = (uint16_t*) &c[idx];
|
uint16_t *address = (uint16_t*) start;
|
||||||
uint32_t i, count = (sizeof(user_conf) + 1) / 2;
|
uint32_t i, count = (stor_size + 1) / 2;
|
||||||
for (i = 0; i < count; ++i){
|
for (i = 0; i < count; ++i){
|
||||||
|
IWDG->KR = IWDG_REFRESH;
|
||||||
*(volatile uint16_t*)(address + i) = data[i];
|
*(volatile uint16_t*)(address + i) = data[i];
|
||||||
while (FLASH->SR & FLASH_SR_BSY);
|
while (FLASH->SR & FLASH_SR_BSY);
|
||||||
if(FLASH->SR & FLASH_SR_PGERR) ret = 1; // program error - meet not 0xffff
|
if(FLASH->SR & FLASH_SR_PGERR) ret = 1; // program error - meet not 0xffff
|
||||||
@ -172,18 +218,29 @@ int store_userconf(){
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int erase_flash(){
|
/**
|
||||||
|
* @brief erase_flash - erase N pages of flash memory
|
||||||
|
* @param start - first address
|
||||||
|
* @param end - last address (or NULL if need to erase all flash remaining)
|
||||||
|
* @return 0 if succeed
|
||||||
|
*/
|
||||||
|
static int erase_flash(const void *start, const void *end){
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
uint32_t nblocks = 1;
|
uint32_t nblocks = 1, flsz = 0;
|
||||||
if(FLASH_SIZE > 0 && FLASH_SIZE < 20000){
|
if(!end){ // erase all remaining
|
||||||
uint32_t flsz = FLASH_SIZE * 1024; // size in bytes
|
if(FLASH_SIZE > 0 && FLASH_SIZE < 20000){
|
||||||
flsz -= (uint32_t)Flash_Data - FLASH_BASE;
|
flsz = FLASH_SIZE * 1024; // size in bytes
|
||||||
nblocks = flsz / FLASH_BLOCK_SIZE;
|
flsz -= (uint32_t)start - FLASH_BASE;
|
||||||
#if 0
|
}
|
||||||
SEND("N blocks:"); printu(1, nblocks); newline();
|
}else{ // erase a part
|
||||||
#endif
|
flsz = (uint32_t)end - (uint32_t)start;
|
||||||
}
|
}
|
||||||
|
nblocks = flsz / FLASH_BLOCK_SIZE;
|
||||||
|
if(nblocks == 0 || nblocks >= FLASH_SIZE) return 1;
|
||||||
for(uint32_t i = 0; i < nblocks; ++i){
|
for(uint32_t i = 0; i < nblocks; ++i){
|
||||||
|
#ifdef EBUG
|
||||||
|
SEND("Try to erase page #"); printu(1,i); newline();
|
||||||
|
#endif
|
||||||
IWDG->KR = IWDG_REFRESH;
|
IWDG->KR = IWDG_REFRESH;
|
||||||
/* (1) Wait till no operation is on going */
|
/* (1) Wait till no operation is on going */
|
||||||
/* (2) Clear error & EOP bits */
|
/* (2) Clear error & EOP bits */
|
||||||
@ -205,9 +262,6 @@ static int erase_flash(){
|
|||||||
/* (5) Clear EOP flag by software by writing EOP at 1 */
|
/* (5) Clear EOP flag by software by writing EOP at 1 */
|
||||||
/* (6) Reset the PER Bit to disable the page erase */
|
/* (6) Reset the PER Bit to disable the page erase */
|
||||||
FLASH->CR |= FLASH_CR_PER; /* (1) */
|
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->AR = (uint32_t)Flash_Data + i*FLASH_BLOCK_SIZE; /* (2) */
|
||||||
FLASH->CR |= FLASH_CR_STRT; /* (3) */
|
FLASH->CR |= FLASH_CR_STRT; /* (3) */
|
||||||
while(!(FLASH->SR & FLASH_SR_EOP));
|
while(!(FLASH->SR & FLASH_SR_EOP));
|
||||||
@ -228,7 +282,6 @@ void dump_userconf(){
|
|||||||
SEND("userconf_sz="); printu(1, the_conf.userconf_sz);
|
SEND("userconf_sz="); printu(1, the_conf.userconf_sz);
|
||||||
SEND("\ndist_min="); printu(1, the_conf.dist_min);
|
SEND("\ndist_min="); printu(1, the_conf.dist_min);
|
||||||
SEND("\ndist_max="); printu(1, the_conf.dist_max);
|
SEND("\ndist_max="); printu(1, the_conf.dist_max);
|
||||||
SEND("\ntrig_pullups="); printuhex(1, the_conf.trig_pullups);
|
|
||||||
SEND("\ntrigstate="); printuhex(1, the_conf.trigstate);
|
SEND("\ntrigstate="); printuhex(1, the_conf.trigstate);
|
||||||
SEND("\ntrigpause={");
|
SEND("\ntrigpause={");
|
||||||
for(int i = 0; i < TRIGGERS_AMOUNT; ++i){
|
for(int i = 0; i < TRIGGERS_AMOUNT; ++i){
|
||||||
|
|||||||
@ -31,21 +31,45 @@
|
|||||||
#define FLASH_SIZE_REG ((uint32_t)0x1FFFF7E0)
|
#define FLASH_SIZE_REG ((uint32_t)0x1FFFF7E0)
|
||||||
#define FLASH_SIZE *((uint16_t*)FLASH_SIZE_REG)
|
#define FLASH_SIZE *((uint16_t*)FLASH_SIZE_REG)
|
||||||
|
|
||||||
typedef struct __attribute__((packed)){
|
/*
|
||||||
|
* struct to save user configurations
|
||||||
|
*/
|
||||||
|
typedef struct __attribute__((packed, aligned(4))){
|
||||||
uint16_t userconf_sz; // "magick number"
|
uint16_t userconf_sz; // "magick number"
|
||||||
uint32_t dist_min; // minimal distance for LIDAR
|
|
||||||
uint32_t dist_max; // maximal -//-
|
|
||||||
uint8_t trig_pullups; // trigger pullups: each bit ==0 to set OFF, ==1 to set ON pullup with given number
|
|
||||||
uint8_t trigstate; // level in `triggered` state
|
|
||||||
int32_t trigpause[TRIGGERS_AMOUNT]; // pause (ms) for false shots
|
|
||||||
int16_t ADC_min; // min&max values of ADC (shot when ADval > ADC_min && < ADC_max)
|
int16_t ADC_min; // min&max values of ADC (shot when ADval > ADC_min && < ADC_max)
|
||||||
int16_t ADC_max; // !!! BOTH ARE SIGNED! so you can include 0 & 4096
|
int16_t ADC_max; // !!! BOTH ARE SIGNED! so you can include 0 & 4096
|
||||||
|
uint8_t trigstate; // level in `triggered` state
|
||||||
|
uint8_t strendRN; // strings ends with "\r\n" instead of normal "\n"
|
||||||
|
uint8_t defflags; // default flags
|
||||||
|
uint32_t dist_min; // minimal distance for LIDAR
|
||||||
|
uint32_t dist_max; // maximal -//-
|
||||||
|
uint32_t USART_speed; // USART1 speed (115200 by default)
|
||||||
|
int32_t trigpause[TRIGGERS_AMOUNT]; // pause (ms) for false shots
|
||||||
} user_conf;
|
} user_conf;
|
||||||
|
|
||||||
extern user_conf the_conf;
|
// values for user_conf.defflags:
|
||||||
|
#define FLAG_SAVE_EVENTS (1 << 0)
|
||||||
|
|
||||||
void get_userconf();
|
/*
|
||||||
|
* struct to save events logs
|
||||||
|
*/
|
||||||
|
typedef struct __attribute__((packed, aligned(4))){
|
||||||
|
uint16_t elog_sz;
|
||||||
|
uint8_t trigno;
|
||||||
|
trigtime shottime;
|
||||||
|
int16_t triglen;
|
||||||
|
uint16_t lidar_dist;
|
||||||
|
} event_log;
|
||||||
|
|
||||||
|
extern user_conf the_conf;
|
||||||
|
extern const user_conf *Flash_Data;
|
||||||
|
extern const event_log *logsstart;
|
||||||
|
extern uint32_t _varslen, __varsstart, __varsend, __logsstart;
|
||||||
|
|
||||||
|
void flashstorage_init();
|
||||||
int store_userconf();
|
int store_userconf();
|
||||||
|
int store_log(event_log *L);
|
||||||
|
int dump_log(int start, int Nlogs);
|
||||||
|
|
||||||
#ifdef EBUG
|
#ifdef EBUG
|
||||||
void dump_userconf();
|
void dump_userconf();
|
||||||
|
|||||||
@ -80,11 +80,8 @@ static inline void gpio_setup(){
|
|||||||
uint16_t pin = trigpin[i];
|
uint16_t pin = trigpin[i];
|
||||||
// fill trigstate array
|
// fill trigstate array
|
||||||
uint8_t trgs = (the_conf.trigstate & (1<<i)) ? 1 : 0;
|
uint8_t trgs = (the_conf.trigstate & (1<<i)) ? 1 : 0;
|
||||||
#ifdef EBUG
|
|
||||||
trigstate[i] = trgs;
|
trigstate[i] = trgs;
|
||||||
#endif
|
trigport[i]->ODR |= pin; // turn on pullups
|
||||||
// turn on pullups
|
|
||||||
if(the_conf.trig_pullups & (1<<i)) trigport[i]->ODR |= pin;
|
|
||||||
EXTI->IMR |= pin;
|
EXTI->IMR |= pin;
|
||||||
if(trgs){ // triggered @1 -> rising interrupt
|
if(trgs){ // triggered @1 -> rising interrupt
|
||||||
EXTI->RTSR |= pin;
|
EXTI->RTSR |= pin;
|
||||||
@ -172,6 +169,7 @@ void fillunshotms(){
|
|||||||
if(!trigger_shot) return;
|
if(!trigger_shot) return;
|
||||||
uint8_t X = 1;
|
uint8_t X = 1;
|
||||||
for(int i = 0; i < TRIGGERS_AMOUNT; ++i, X<<=1){
|
for(int i = 0; i < TRIGGERS_AMOUNT; ++i, X<<=1){
|
||||||
|
IWDG->KR = IWDG_REFRESH;
|
||||||
// check whether trigger is OFF but shot recently
|
// check whether trigger is OFF but shot recently
|
||||||
if(trigger_shot & X){
|
if(trigger_shot & X){
|
||||||
uint32_t len = Tms - shotms[i];
|
uint32_t len = Tms - shotms[i];
|
||||||
@ -229,15 +227,26 @@ uint8_t gettrig(uint8_t N){
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
void chk_buzzer(){
|
void chk_buzzer(){
|
||||||
if(!trigger_shot && BUZZER_GET()){ // should we turn off buzzer?
|
static uint32_t Ton = 0; // Time of first buzzer check
|
||||||
|
if(!BUZZER_GET()) return; // buzzer if OFF
|
||||||
|
if(!trigger_shot){ // should we turn off buzzer?
|
||||||
uint8_t notrg = 1;
|
uint8_t notrg = 1;
|
||||||
for(int i = 0; i < DIGTRIG_AMOUNT; ++i){
|
for(int i = 0; i < DIGTRIG_AMOUNT; ++i){
|
||||||
uint8_t curval = (trigport[i]->IDR & trigpin[i]) ? 1 : 0;
|
uint8_t curval = (trigport[i]->IDR & trigpin[i]) ? 1 : 0;
|
||||||
if(curval == trigstate[i]){
|
if(curval == trigstate[i]){
|
||||||
notrg = 0;
|
notrg = 0; // cheep while digital trigger is ON
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(notrg) BUZZER_OFF(); // turn off buzzer when there's no trigger events
|
if(notrg){ // turn off buzzer when there's no trigger events & timeout came
|
||||||
|
if(Tms - Ton < BUZZER_CHEEP_TIME) return;
|
||||||
|
Ton = 0;
|
||||||
|
BUZZER_OFF();
|
||||||
|
}
|
||||||
|
}else{ // buzzer is ON - check timer
|
||||||
|
if(Ton == 0){
|
||||||
|
Ton = Tms;
|
||||||
|
if(!Ton) Ton = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,6 +40,8 @@ extern uint8_t buzzer_on;
|
|||||||
#define BUZZER_ON() do{if(buzzer_on)pin_set(BUZZER_port, BUZZER_pin);}while(0)
|
#define BUZZER_ON() do{if(buzzer_on)pin_set(BUZZER_port, BUZZER_pin);}while(0)
|
||||||
#define BUZZER_OFF() pin_clear(BUZZER_port, BUZZER_pin)
|
#define BUZZER_OFF() pin_clear(BUZZER_port, BUZZER_pin)
|
||||||
#define BUZZER_GET() (pin_read(BUZZER_port, BUZZER_pin))
|
#define BUZZER_GET() (pin_read(BUZZER_port, BUZZER_pin))
|
||||||
|
// minimal time to buzzer to cheep (ms)
|
||||||
|
#define BUZZER_CHEEP_TIME (500)
|
||||||
|
|
||||||
// PPS pin - PA1
|
// PPS pin - PA1
|
||||||
#define PPS_port GPIOA
|
#define PPS_port GPIOA
|
||||||
|
|||||||
@ -72,6 +72,7 @@ void iwdg_setup(){
|
|||||||
char *parse_cmd(char *buf){
|
char *parse_cmd(char *buf){
|
||||||
int32_t N;
|
int32_t N;
|
||||||
static char btns[] = "BTN0=0, BTN1=0, BTN2=0, PPS=0\n";
|
static char btns[] = "BTN0=0, BTN1=0, BTN2=0, PPS=0\n";
|
||||||
|
event_log l = {.elog_sz = sizeof(event_log), .trigno = 2};
|
||||||
switch(*buf){
|
switch(*buf){
|
||||||
case '0':
|
case '0':
|
||||||
LED_off(); // LED0 off @dbg
|
LED_off(); // LED0 off @dbg
|
||||||
@ -79,6 +80,14 @@ char *parse_cmd(char *buf){
|
|||||||
case '1':
|
case '1':
|
||||||
LED_on(); // LED0 on @dbg
|
LED_on(); // LED0 on @dbg
|
||||||
break;
|
break;
|
||||||
|
case 'a':
|
||||||
|
l.shottime.Time = current_time;
|
||||||
|
l.shottime.millis = Timer;
|
||||||
|
l.triglen = getADCval(1);
|
||||||
|
if(store_log(&l)) SEND("Error storing");
|
||||||
|
else SEND("Store OK");
|
||||||
|
newline();
|
||||||
|
break;
|
||||||
case 'b':
|
case 'b':
|
||||||
btns[5] = gettrig(0) + '0';
|
btns[5] = gettrig(0) + '0';
|
||||||
btns[13] = gettrig(1) + '0';
|
btns[13] = gettrig(1) + '0';
|
||||||
@ -100,6 +109,9 @@ char *parse_cmd(char *buf){
|
|||||||
case 'd':
|
case 'd':
|
||||||
dump_userconf();
|
dump_userconf();
|
||||||
break;
|
break;
|
||||||
|
case 'D':
|
||||||
|
if(dump_log(0, -1)) DBG("Error dumping log: empty?");
|
||||||
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
pin_toggle(USBPU_port, USBPU_pin);
|
pin_toggle(USBPU_port, USBPU_pin);
|
||||||
SEND("USB pullup is ");
|
SEND("USB pullup is ");
|
||||||
@ -140,9 +152,11 @@ char *parse_cmd(char *buf){
|
|||||||
if(buf[1] != '\n') return buf;
|
if(buf[1] != '\n') return buf;
|
||||||
return
|
return
|
||||||
"0/1 - turn on/off LED1\n"
|
"0/1 - turn on/off LED1\n"
|
||||||
|
"'a' - add test log record\n"
|
||||||
"'b' - get buttons's state\n"
|
"'b' - get buttons's state\n"
|
||||||
"'c' - send cold start\n"
|
"'c' - send cold start\n"
|
||||||
"'d' - dump current user conf\n"
|
"'d' - dump current user conf\n"
|
||||||
|
"'D' - dump log\n"
|
||||||
"'p' - toggle USB pullup\n"
|
"'p' - toggle USB pullup\n"
|
||||||
"'C' - store userconf for N times\n"
|
"'C' - store userconf for N times\n"
|
||||||
"'G' - get last LIDAR distance\n"
|
"'G' - get last LIDAR distance\n"
|
||||||
@ -167,10 +181,15 @@ static char *get_USB(){
|
|||||||
if(!x) return NULL;
|
if(!x) return NULL;
|
||||||
curptr[x] = 0;
|
curptr[x] = 0;
|
||||||
USB_send(curptr); // echo
|
USB_send(curptr); // echo
|
||||||
|
//USB_send("ENDOINPUT\n");
|
||||||
//if(x == 1 && *curptr < 32){USB_send("\n"); USB_send(u2str(*curptr)); USB_send("\n");}
|
//if(x == 1 && *curptr < 32){USB_send("\n"); USB_send(u2str(*curptr)); USB_send("\n");}
|
||||||
if(curptr[x-1] == '\n'){
|
if(curptr[x-1] == '\n' || curptr[x-1] == '\r'){
|
||||||
curptr = tmpbuf;
|
curptr = tmpbuf;
|
||||||
rest = USBBUF;
|
rest = USBBUF;
|
||||||
|
// omit empty lines
|
||||||
|
if(tmpbuf[0] == '\n') return NULL;
|
||||||
|
// and wrong empty lines
|
||||||
|
if(tmpbuf[0] == '\r' && tmpbuf[1] == '\n') return NULL;
|
||||||
return tmpbuf;
|
return tmpbuf;
|
||||||
}
|
}
|
||||||
curptr += x; rest -= x;
|
curptr += x; rest -= x;
|
||||||
@ -190,16 +209,10 @@ void linecoding_handler(usb_LineCoding __attribute__((unused)) *lc){ // get/set
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static uint8_t USBconn = 0;
|
||||||
void clstate_handler(uint16_t __attribute__((unused)) val){ // lesser bits of val: RTS|DTR
|
void clstate_handler(uint16_t __attribute__((unused)) val){ // lesser bits of val: RTS|DTR
|
||||||
static uint32_t Tlast = 0;
|
USBconn = 1;
|
||||||
SEND("Tms/Tlast: ");
|
|
||||||
printu(1, Tms);
|
|
||||||
newline();
|
|
||||||
printu(1, Tlast);
|
|
||||||
newline();
|
|
||||||
if(Tms - Tlast < 500) return;
|
|
||||||
Tlast = Tms;
|
|
||||||
USB_send("Chronometer version " VERSION ".\n");
|
|
||||||
#ifdef EBUG
|
#ifdef EBUG
|
||||||
if(val & 2){
|
if(val & 2){
|
||||||
DBG("RTS set");
|
DBG("RTS set");
|
||||||
@ -225,8 +238,6 @@ int main(void){
|
|||||||
sysreset();
|
sysreset();
|
||||||
StartHSE();
|
StartHSE();
|
||||||
SysTick_Config(SYSTICK_DEFCONF); // function SysTick_Config decrements argument!
|
SysTick_Config(SYSTICK_DEFCONF); // function SysTick_Config decrements argument!
|
||||||
// read data stored in flash
|
|
||||||
get_userconf();
|
|
||||||
// !!! hw_setup() should be the first in setup stage
|
// !!! hw_setup() should be the first in setup stage
|
||||||
hw_setup();
|
hw_setup();
|
||||||
USB_setup();
|
USB_setup();
|
||||||
@ -242,11 +253,17 @@ int main(void){
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
RCC->CSR |= RCC_CSR_RMVF; // remove reset flags
|
RCC->CSR |= RCC_CSR_RMVF; // remove reset flags
|
||||||
|
// read data stored in flash
|
||||||
|
flashstorage_init();
|
||||||
iwdg_setup();
|
iwdg_setup();
|
||||||
|
|
||||||
while (1){
|
while (1){
|
||||||
IWDG->KR = IWDG_REFRESH; // refresh watchdog
|
IWDG->KR = IWDG_REFRESH; // refresh watchdog
|
||||||
if(Timer > 499) LED_on(); // turn ON LED0 over 0.25s after PPS pulse
|
if(Timer > 499) LED_on(); // turn ON LED0 over 0.25s after PPS pulse
|
||||||
|
if(USBconn && Tms > 100){ // USB connection
|
||||||
|
USBconn = 0;
|
||||||
|
USB_send("Chronometer version " VERSION ".\n");
|
||||||
|
}
|
||||||
// check if triggers that was recently shot are off now
|
// check if triggers that was recently shot are off now
|
||||||
fillunshotms();
|
fillunshotms();
|
||||||
if(lastT > Tms || Tms - lastT > 499){
|
if(lastT > Tms || Tms - lastT > 499){
|
||||||
@ -301,17 +318,19 @@ int main(void){
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
//if(trigger_shot) show_trigger_shot(trigger_shot);
|
|
||||||
IWDG->KR = IWDG_REFRESH;
|
IWDG->KR = IWDG_REFRESH;
|
||||||
usb_proc();
|
usb_proc();
|
||||||
IWDG->KR = IWDG_REFRESH;
|
IWDG->KR = IWDG_REFRESH;
|
||||||
int r = 0;
|
int r = 0;
|
||||||
char *txt;
|
char *txt = NULL;
|
||||||
if((txt = get_USB())){
|
if((txt = get_USB())){
|
||||||
DBG("Received data over USB:");
|
DBG("Received data over USB:");
|
||||||
DBG(txt);
|
DBG(txt);
|
||||||
if(parse_USBCMD(txt))
|
if(parse_USBCMD(txt)){
|
||||||
USB_send("Bad command!");
|
USB_send("Bad command: ");
|
||||||
|
USB_send(txt);
|
||||||
|
USB_send("\n");
|
||||||
|
}
|
||||||
IWDG->KR = IWDG_REFRESH;
|
IWDG->KR = IWDG_REFRESH;
|
||||||
}
|
}
|
||||||
#if defined EBUG || defined USART1PROXY
|
#if defined EBUG || defined USART1PROXY
|
||||||
|
|||||||
97
F1-nolib/chronometer/stm32F103xB.ld
Normal file
97
F1-nolib/chronometer/stm32F103xB.ld
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
********************************************************************************
|
||||||
|
* *
|
||||||
|
* Copyright (c) 2017 Andrea Loi *
|
||||||
|
* *
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a *
|
||||||
|
* copy of this software and associated documentation files (the "Software"), *
|
||||||
|
* to deal in the Software without restriction, including without limitation *
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the *
|
||||||
|
* Software is furnished to do so, subject to the following conditions: *
|
||||||
|
* *
|
||||||
|
* The above copyright notice and this permission notice shall be included *
|
||||||
|
* in all copies or substantial portions of the Software. *
|
||||||
|
* *
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *
|
||||||
|
* DEALINGS IN THE SOFTWARE. *
|
||||||
|
* *
|
||||||
|
********************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
MEMORY
|
||||||
|
{
|
||||||
|
rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K
|
||||||
|
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
/* DON'T EDIT THIS FILE UNLESS YOU KNOW WHAT YOU'RE DOING! */
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
/* _isrvectors_tend = 0x00000150; - different for different series */
|
||||||
|
|
||||||
|
ENTRY(reset_handler)
|
||||||
|
|
||||||
|
SECTIONS {
|
||||||
|
.vector_table 0x08000000 :
|
||||||
|
{
|
||||||
|
_sisrvectors = .;
|
||||||
|
KEEP(*(.vector_table))
|
||||||
|
/* ASSERT(. == _isrvectors_tend, "The vector table needs to be 84 elements long!"); */
|
||||||
|
_eisrvectors = .;
|
||||||
|
} >rom
|
||||||
|
|
||||||
|
.text :
|
||||||
|
{
|
||||||
|
. = ALIGN(4);
|
||||||
|
_stext = .;
|
||||||
|
*(.text*)
|
||||||
|
*(.rodata*)
|
||||||
|
. = ALIGN(4);
|
||||||
|
_etext = .;
|
||||||
|
} >rom
|
||||||
|
|
||||||
|
.ARM.extab :
|
||||||
|
{
|
||||||
|
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
||||||
|
} >rom
|
||||||
|
|
||||||
|
.ARM : {
|
||||||
|
*(.ARM.exidx*)
|
||||||
|
} >rom
|
||||||
|
|
||||||
|
.data :
|
||||||
|
{
|
||||||
|
. = ALIGN(4);
|
||||||
|
_sdata = .;
|
||||||
|
*(.data*)
|
||||||
|
. = ALIGN(4);
|
||||||
|
_edata = .;
|
||||||
|
} >ram AT >rom
|
||||||
|
|
||||||
|
.myvars :
|
||||||
|
{
|
||||||
|
. = ALIGN(1024);
|
||||||
|
KEEP(*(.myvars))
|
||||||
|
} > rom
|
||||||
|
|
||||||
|
_ldata = LOADADDR(.data);
|
||||||
|
|
||||||
|
.bss :
|
||||||
|
{
|
||||||
|
. = ALIGN(4);
|
||||||
|
_sbss = .;
|
||||||
|
*(.bss*)
|
||||||
|
*(COMMON)
|
||||||
|
. = ALIGN(4);
|
||||||
|
_ebss = .;
|
||||||
|
} >ram
|
||||||
|
}
|
||||||
|
|
||||||
|
PROVIDE(_stack = ORIGIN(ram) + LENGTH(ram));
|
||||||
@ -17,7 +17,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "adc.h"
|
#include "adc.h"
|
||||||
#include "flash.h"
|
|
||||||
#include "GPS.h"
|
#include "GPS.h"
|
||||||
#include "lidar.h"
|
#include "lidar.h"
|
||||||
#include "str.h"
|
#include "str.h"
|
||||||
@ -74,11 +73,10 @@ static void sendi(int32_t I){
|
|||||||
* @brief showuserconf - show configuration over USB
|
* @brief showuserconf - show configuration over USB
|
||||||
*/
|
*/
|
||||||
static void showuserconf(){
|
static void showuserconf(){
|
||||||
USB_send("\nCONFIG:\nDISTMIN="); sendu(the_conf.dist_min);
|
USB_send("DISTMIN="); sendu(the_conf.dist_min);
|
||||||
USB_send("\nDISTMAX="); sendu(the_conf.dist_max);
|
USB_send("\nDISTMAX="); sendu(the_conf.dist_max);
|
||||||
USB_send("\nADCMIN="); sendi(the_conf.ADC_min);
|
USB_send("\nADCMIN="); sendi(the_conf.ADC_min);
|
||||||
USB_send("\nADCMAX="); sendi(the_conf.ADC_max);
|
USB_send("\nADCMAX="); sendi(the_conf.ADC_max);
|
||||||
USB_send("\nPULLUPS="); sendu(the_conf.trig_pullups);
|
|
||||||
USB_send("\nTRIGLVL="); sendu(the_conf.trigstate);
|
USB_send("\nTRIGLVL="); sendu(the_conf.trigstate);
|
||||||
USB_send("\nTRIGPAUSE={");
|
USB_send("\nTRIGPAUSE={");
|
||||||
for(int i = 0; i < TRIGGERS_AMOUNT; ++i){
|
for(int i = 0; i < TRIGGERS_AMOUNT; ++i){
|
||||||
@ -86,7 +84,15 @@ static void showuserconf(){
|
|||||||
sendu(the_conf.trigpause[i]);
|
sendu(the_conf.trigpause[i]);
|
||||||
}
|
}
|
||||||
USB_send("}");
|
USB_send("}");
|
||||||
USB_send("\nENDCONFIG\n");
|
USB_send("\nUSART1SPD="); sendu(the_conf.USART_speed);
|
||||||
|
USB_send("\nSTREND=");
|
||||||
|
if(the_conf.strendRN) USB_send("RN");
|
||||||
|
else USB_send("N");
|
||||||
|
uint8_t f = the_conf.defflags;
|
||||||
|
USB_send("\nSAVE_EVENTS=");
|
||||||
|
if(f & FLAG_SAVE_EVENTS) USB_send("1");
|
||||||
|
else USB_send("0");
|
||||||
|
USB_send("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -95,7 +101,7 @@ static void showuserconf(){
|
|||||||
* @return 0 if got command, 1 if command not recognized
|
* @return 0 if got command, 1 if command not recognized
|
||||||
*/
|
*/
|
||||||
int parse_USBCMD(char *cmd){
|
int parse_USBCMD(char *cmd){
|
||||||
#define CMP(a,b) cmpstr(a, b, sizeof(b)-1)
|
#define CMP(a,b) cmpstr(a, b, sizeof(b))
|
||||||
#define GETNUM(x) if(getnum(cmd+sizeof(x)-1, &N)) goto bad_number;
|
#define GETNUM(x) if(getnum(cmd+sizeof(x)-1, &N)) goto bad_number;
|
||||||
static uint8_t conf_modified = 0;
|
static uint8_t conf_modified = 0;
|
||||||
uint8_t succeed = 0;
|
uint8_t succeed = 0;
|
||||||
@ -105,23 +111,28 @@ int parse_USBCMD(char *cmd){
|
|||||||
if(*cmd == '?'){ // help
|
if(*cmd == '?'){ // help
|
||||||
USB_send("Commands:\n"
|
USB_send("Commands:\n"
|
||||||
CMD_ADCMAX " - max ADC value treshold for trigger\n"
|
CMD_ADCMAX " - max ADC value treshold for trigger\n"
|
||||||
CMD_ADCMIN " - min -//- (triggered when ADval>min & <max\n"
|
CMD_ADCMIN " - min -//- (triggered when ADval>min & <max)\n"
|
||||||
CMD_GETADCVAL " - get ADC value\n"
|
CMD_GETADCVAL " - get ADC value\n"
|
||||||
CMD_BUZZER "S - turn buzzer ON/OFF\n"
|
CMD_BUZZER "S - turn buzzer ON/OFF\n"
|
||||||
CMD_DISTMIN " - min distance threshold (cm)\n"
|
CMD_DISTMIN " - min distance threshold (cm)\n"
|
||||||
CMD_DISTMAX " - max distance threshold (cm)\n"
|
CMD_DISTMAX " - max distance threshold (cm)\n"
|
||||||
|
CMD_DUMP " - dump stored events\n"
|
||||||
|
CMD_FLASH " - FLASH info\n"
|
||||||
CMD_GPSRESTART " - send Full Cold Restart to GPS\n"
|
CMD_GPSRESTART " - send Full Cold Restart to GPS\n"
|
||||||
CMD_GPSSTAT " - get GPS status\n"
|
CMD_GPSSTAT " - get GPS status\n"
|
||||||
CMD_GPSSTR " - current GPS data string\n"
|
CMD_GPSSTR " - current GPS data string\n"
|
||||||
CMD_LEDS "S - turn leds on/off (1/0)\n"
|
CMD_LEDS "S - turn leds on/off (1/0)\n"
|
||||||
CMD_GETMCUTEMP " - MCU temperature\n"
|
CMD_GETMCUTEMP " - MCU temperature\n"
|
||||||
CMD_PULLUP "NS - triggers pullups state (N - trigger No, S - 0/1 for off/on)\n"
|
|
||||||
CMD_SHOWCONF " - show current configuration\n"
|
CMD_SHOWCONF " - show current configuration\n"
|
||||||
CMD_PRINTTIME " - print time\n"
|
CMD_PRINTTIME " - print time\n"
|
||||||
|
CMD_RESET " - reset MCU\n"
|
||||||
|
CMD_SAVEEVTS "x - save/don't save (1/0) trigger events into flash\n"
|
||||||
CMD_STORECONF " - store new configuration in flash\n"
|
CMD_STORECONF " - store new configuration in flash\n"
|
||||||
|
CMD_STREND "x - string ends with \\n (x=n) or \\r\\n (x=r)\n"
|
||||||
CMD_TRIGLVL "NS - working trigger N level S\n"
|
CMD_TRIGLVL "NS - working trigger N level S\n"
|
||||||
CMD_TRGPAUSE "NP - pause (P, ms) after trigger N shots\n"
|
CMD_TRGPAUSE "NP - pause (P, ms) after trigger N shots\n"
|
||||||
CMD_TRGTIME "N - show last trigger N time\n"
|
CMD_TRGTIME "N - show last trigger N time\n"
|
||||||
|
CMD_USARTSPD "V - set USART1 speed to V\n"
|
||||||
CMD_GETVDD " - Vdd value\n"
|
CMD_GETVDD " - Vdd value\n"
|
||||||
);
|
);
|
||||||
}else if(CMP(cmd, CMD_PRINTTIME) == 0){
|
}else if(CMP(cmd, CMD_PRINTTIME) == 0){
|
||||||
@ -157,7 +168,8 @@ int parse_USBCMD(char *cmd){
|
|||||||
}
|
}
|
||||||
}else if(CMP(cmd, CMD_GPSSTR) == 0){ // show GPS status string
|
}else if(CMP(cmd, CMD_GPSSTR) == 0){ // show GPS status string
|
||||||
showGPSstr = 1;
|
showGPSstr = 1;
|
||||||
}else if(CMP(cmd, CMD_PULLUP) == 0){
|
}/*
|
||||||
|
else if(CMP(cmd, CMD_PULLUP) == 0){
|
||||||
DBG("Pullups");
|
DBG("Pullups");
|
||||||
cmd += sizeof(CMD_PULLUP) - 1;
|
cmd += sizeof(CMD_PULLUP) - 1;
|
||||||
uint8_t Nt = *cmd++ - '0';
|
uint8_t Nt = *cmd++ - '0';
|
||||||
@ -169,7 +181,8 @@ int parse_USBCMD(char *cmd){
|
|||||||
else the_conf.trig_pullups = oldval | (1<<Nt);
|
else the_conf.trig_pullups = oldval | (1<<Nt);
|
||||||
if(oldval != the_conf.trig_pullups) conf_modified = 1;
|
if(oldval != the_conf.trig_pullups) conf_modified = 1;
|
||||||
succeed = 1;
|
succeed = 1;
|
||||||
}else if(CMP(cmd, CMD_TRIGLVL) == 0){
|
} */
|
||||||
|
else if(CMP(cmd, CMD_TRIGLVL) == 0){
|
||||||
DBG("Trig levels");
|
DBG("Trig levels");
|
||||||
cmd += sizeof(CMD_TRIGLVL) - 1;
|
cmd += sizeof(CMD_TRIGLVL) - 1;
|
||||||
uint8_t Nt = *cmd++ - '0';
|
uint8_t Nt = *cmd++ - '0';
|
||||||
@ -288,7 +301,53 @@ int parse_USBCMD(char *cmd){
|
|||||||
USB_send(", PPS working\n");
|
USB_send(", PPS working\n");
|
||||||
else
|
else
|
||||||
USB_send(", no PPS\n");
|
USB_send(", no PPS\n");
|
||||||
|
}else if(CMP(cmd, CMD_USARTSPD) == 0){
|
||||||
|
GETNUM(CMD_USARTSPD);
|
||||||
|
if(N < 400 || N > 3000000) goto bad_number;
|
||||||
|
if(the_conf.USART_speed != (uint32_t)N){
|
||||||
|
the_conf.USART_speed = (uint32_t)N;
|
||||||
|
conf_modified = 1;
|
||||||
|
succeed = 1;
|
||||||
|
}
|
||||||
|
}else if(CMP(cmd, CMD_RESET) == 0){
|
||||||
|
USB_send("Soft reset\n");
|
||||||
|
NVIC_SystemReset();
|
||||||
|
}else if(CMP(cmd, CMD_STREND) == 0){
|
||||||
|
char c = cmd[sizeof(CMD_STREND) - 1];
|
||||||
|
succeed = 1;
|
||||||
|
if(c == 'n' || c == 'N') the_conf.strendRN = 0;
|
||||||
|
else if(c == 'r' || c == 'R') the_conf.strendRN = 1;
|
||||||
|
else{
|
||||||
|
succeed = 0;
|
||||||
|
USB_send("Bad letter, should be 'n' or 'r'\n");
|
||||||
|
}
|
||||||
|
}else if(CMP(cmd, CMD_FLASH) == 0){ // show flash size
|
||||||
|
USB_send("FLASHSIZE=");
|
||||||
|
sendu(FLASH_SIZE);
|
||||||
|
USB_send("kB\nFLASH_BASE=");
|
||||||
|
sendu(FLASH_BASE);
|
||||||
|
USB_send("\nFlash_Data=");
|
||||||
|
sendu((uint32_t)Flash_Data);
|
||||||
|
USB_send("\nvarslen=");
|
||||||
|
sendu((uint32_t)&_varslen);
|
||||||
|
USB_send("\nvarsend=");
|
||||||
|
sendu((uint32_t)&__varsend);
|
||||||
|
USB_send("\nvarsstart=");
|
||||||
|
sendu((uint32_t)&__varsstart);
|
||||||
|
USB_send("\nlogsstart=");
|
||||||
|
sendu((uint32_t)logsstart);
|
||||||
|
USB_send("\n");
|
||||||
|
}else if(CMP(cmd, CMD_SAVEEVTS) == 0){
|
||||||
|
if('0' == cmd[sizeof(CMD_SAVEEVTS) - 1]) the_conf.defflags &= ~FLAG_SAVE_EVENTS;
|
||||||
|
else the_conf.defflags |= FLAG_SAVE_EVENTS;
|
||||||
|
succeed = 1;
|
||||||
|
}else if(CMP(cmd, CMD_DUMP) == 0){
|
||||||
|
if(dump_log(0, -1)) USB_send("Event log empty!\n");
|
||||||
}else return 1;
|
}else return 1;
|
||||||
|
/*else if(CMP(cmd, CMD_) == 0){
|
||||||
|
;
|
||||||
|
}*/
|
||||||
|
|
||||||
IWDG->KR = IWDG_REFRESH;
|
IWDG->KR = IWDG_REFRESH;
|
||||||
if(succeed) USB_send("Success!\n");
|
if(succeed) USB_send("Success!\n");
|
||||||
return 0;
|
return 0;
|
||||||
@ -298,7 +357,38 @@ int parse_USBCMD(char *cmd){
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief show_trigger_shot - print on USB message about last trigger shot time
|
* @brief get_trigger_shot - print on USB message about last trigger shot time
|
||||||
|
* @param number - number of event (if > -1)
|
||||||
|
* @param logdata - record from event log
|
||||||
|
* @return string with data
|
||||||
|
*/
|
||||||
|
char *get_trigger_shot(int number, const event_log *logdata){
|
||||||
|
static char buf[64];
|
||||||
|
char *bptr = buf;
|
||||||
|
if(number > -1){
|
||||||
|
bptr = strcp(bptr, u2str(number));
|
||||||
|
bptr = strcp(bptr, ": ");
|
||||||
|
}
|
||||||
|
if(logdata->trigno == LIDAR_TRIGGER){
|
||||||
|
bptr = strcp(bptr, "LIDAR, dist=");
|
||||||
|
bptr = strcp(bptr, u2str(logdata->lidar_dist));
|
||||||
|
bptr = strcp(bptr, ", TRIG" STR(LIDAR_TRIGGER) "=");
|
||||||
|
}else{
|
||||||
|
bptr = strcp(bptr, "TRIG");
|
||||||
|
*bptr++ = '0' + logdata->trigno;
|
||||||
|
}
|
||||||
|
*bptr++ = '=';
|
||||||
|
IWDG->KR = IWDG_REFRESH;
|
||||||
|
bptr = strcp(bptr, get_time(&logdata->shottime.Time, logdata->shottime.millis));
|
||||||
|
bptr = strcp(bptr, ", len=");
|
||||||
|
if(logdata->triglen < 0) bptr = strcp(bptr, ">1s");
|
||||||
|
else bptr = strcp(bptr, u2str((uint32_t) logdata->triglen));
|
||||||
|
*bptr++ = '\n'; *bptr++ = 0;
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief show_trigger_shot printout @ USB data with all triggers shot recently (+ save it in flash)
|
||||||
* @param tshot - each bit consists information about trigger
|
* @param tshot - each bit consists information about trigger
|
||||||
*/
|
*/
|
||||||
void show_trigger_shot(uint8_t tshot){
|
void show_trigger_shot(uint8_t tshot){
|
||||||
@ -307,20 +397,39 @@ void show_trigger_shot(uint8_t tshot){
|
|||||||
IWDG->KR = IWDG_REFRESH;
|
IWDG->KR = IWDG_REFRESH;
|
||||||
if(tshot & X) tshot &= ~X;
|
if(tshot & X) tshot &= ~X;
|
||||||
else continue;
|
else continue;
|
||||||
if(!triglen[i]) continue; // noice
|
event_log l;
|
||||||
if(i == LIDAR_TRIGGER){
|
l.elog_sz = sizeof(event_log);
|
||||||
USB_send("LIDAR, dist=");
|
l.trigno = i;
|
||||||
sendu(lidar_triggered_dist);
|
if(i == LIDAR_TRIGGER) l.lidar_dist = lidar_triggered_dist;
|
||||||
USB_send(", TRIG=");
|
l.shottime = shottime[i];
|
||||||
}else{
|
l.triglen = triglen[i];
|
||||||
USB_send("TRIG");
|
USB_send(get_trigger_shot(-1, &l));
|
||||||
sendu(i);
|
if(the_conf.defflags & FLAG_SAVE_EVENTS){
|
||||||
|
if(store_log(&l)) USB_send("\n\nError saving event!\n\n");
|
||||||
}
|
}
|
||||||
USB_send("=");
|
|
||||||
USB_send(get_time(&shottime[i].Time, shottime[i].millis));
|
|
||||||
USB_send(", len=");
|
|
||||||
if(triglen[i] < 0) USB_send(">1s");
|
|
||||||
else sendu((uint32_t) triglen[i]);
|
|
||||||
USB_send("\n");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief strln == strlen
|
||||||
|
* @param s - string
|
||||||
|
* @return length
|
||||||
|
*/
|
||||||
|
int strln(const char *s){
|
||||||
|
int i = 0;
|
||||||
|
while(*s++) ++i;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief strcp - strcpy (be carefull: it doesn't checks destination length!)
|
||||||
|
* @param dst - destination
|
||||||
|
* @param src - source
|
||||||
|
* @return pointer to '\0' @ dst`s end
|
||||||
|
*/
|
||||||
|
char *strcp(char* dst, const char *src){
|
||||||
|
int l = strln(src);
|
||||||
|
if(l < 1) return dst;
|
||||||
|
while((*dst++ = *src++));
|
||||||
|
return dst - 1;
|
||||||
|
}
|
||||||
|
|||||||
@ -20,6 +20,7 @@
|
|||||||
#define STR_H__
|
#define STR_H__
|
||||||
|
|
||||||
#include "stm32f1.h"
|
#include "stm32f1.h"
|
||||||
|
#include "flash.h"
|
||||||
#include "hardware.h"
|
#include "hardware.h"
|
||||||
|
|
||||||
// usb commands
|
// usb commands
|
||||||
@ -31,7 +32,6 @@
|
|||||||
#define CMD_PRINTTIME "time"
|
#define CMD_PRINTTIME "time"
|
||||||
#define CMD_STORECONF "store"
|
#define CMD_STORECONF "store"
|
||||||
#define CMD_GPSSTR "gpsstring"
|
#define CMD_GPSSTR "gpsstring"
|
||||||
#define CMD_PULLUP "pullup"
|
|
||||||
#define CMD_SHOWCONF "showconf"
|
#define CMD_SHOWCONF "showconf"
|
||||||
#define CMD_TRIGLVL "triglevel"
|
#define CMD_TRIGLVL "triglevel"
|
||||||
#define CMD_TRGPAUSE "trigpause"
|
#define CMD_TRGPAUSE "trigpause"
|
||||||
@ -43,12 +43,20 @@
|
|||||||
#define CMD_GPSRESTART "gpsrestart"
|
#define CMD_GPSRESTART "gpsrestart"
|
||||||
#define CMD_BUZZER "buzzer"
|
#define CMD_BUZZER "buzzer"
|
||||||
#define CMD_GPSSTAT "gpsstat"
|
#define CMD_GPSSTAT "gpsstat"
|
||||||
|
#define CMD_USARTSPD "usartspd"
|
||||||
|
#define CMD_RESET "reset"
|
||||||
|
#define CMD_STREND "strend"
|
||||||
|
#define CMD_FLASH "flash"
|
||||||
|
#define CMD_SAVEEVTS "saveevt"
|
||||||
|
#define CMD_DUMP "dump"
|
||||||
|
|
||||||
extern uint8_t showGPSstr;
|
extern uint8_t showGPSstr;
|
||||||
|
|
||||||
|
int strln(const char *s);
|
||||||
|
char *strcp(char* dst, const char *src);
|
||||||
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);
|
int parse_USBCMD(char *cmd);
|
||||||
|
char *get_trigger_shot(int number, const event_log *logdata);
|
||||||
void show_trigger_shot(uint8_t trigger_shot);
|
void show_trigger_shot(uint8_t trigger_shot);
|
||||||
|
|
||||||
#endif // STR_H__
|
#endif // STR_H__
|
||||||
|
|||||||
@ -102,7 +102,7 @@ static void ms2str(char **str, uint32_t T){
|
|||||||
/**
|
/**
|
||||||
* print time: Tm - time structure, T - milliseconds
|
* print time: Tm - time structure, T - milliseconds
|
||||||
*/
|
*/
|
||||||
char *get_time(curtime *Tm, uint32_t T){
|
char *get_time(const curtime *Tm, uint32_t T){
|
||||||
static char buf[64];
|
static char buf[64];
|
||||||
char *bstart = &buf[5], *bptr = bstart;
|
char *bstart = &buf[5], *bptr = bstart;
|
||||||
int S = 0;
|
int S = 0;
|
||||||
|
|||||||
@ -53,7 +53,7 @@ extern uint32_t trigger_ms[];
|
|||||||
|
|
||||||
extern volatile int need_sync;
|
extern volatile int need_sync;
|
||||||
|
|
||||||
char *get_time(curtime *T, uint32_t m);
|
char *get_time(const curtime *T, uint32_t m);
|
||||||
void set_time(const char *buf);
|
void set_time(const char *buf);
|
||||||
void time_increment();
|
void time_increment();
|
||||||
void systick_correction();
|
void systick_correction();
|
||||||
|
|||||||
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "stm32f1.h"
|
#include "stm32f1.h"
|
||||||
|
#include "flash.h"
|
||||||
#include "usart.h"
|
#include "usart.h"
|
||||||
#include "lidar.h"
|
#include "lidar.h"
|
||||||
|
|
||||||
@ -169,7 +170,7 @@ static void usart_setup(int n, uint32_t BRR){
|
|||||||
void usarts_setup(){
|
void usarts_setup(){
|
||||||
RCC->AHBENR |= RCC_AHBENR_DMA1EN;
|
RCC->AHBENR |= RCC_AHBENR_DMA1EN;
|
||||||
#if defined EBUG || defined USART1PROXY
|
#if defined EBUG || defined USART1PROXY
|
||||||
usart_setup(1, 72000000 / 115200); // debug console or GPS proxy
|
usart_setup(1, 72000000 / the_conf.USART_speed); // debug console or GPS proxy
|
||||||
#endif
|
#endif
|
||||||
usart_setup(2, 36000000 / 9600); // GPS
|
usart_setup(2, 36000000 / 9600); // GPS
|
||||||
usart_setup(3, 36000000 / 115200); // LIDAR
|
usart_setup(3, 36000000 / 115200); // LIDAR
|
||||||
@ -253,27 +254,20 @@ void usart3_isr(){
|
|||||||
|
|
||||||
// return string buffer with val
|
// return string buffer with val
|
||||||
char *u2str(uint32_t val){
|
char *u2str(uint32_t val){
|
||||||
static char bufa[11];
|
static char buf[11];
|
||||||
char bufb[10];
|
char *bufptr = &buf[10];
|
||||||
int l = 0, bpos = 0;
|
*bufptr = 0;
|
||||||
IWDG->KR = IWDG_REFRESH;
|
|
||||||
if(!val){
|
if(!val){
|
||||||
bufa[0] = '0';
|
*(--bufptr) = '0';
|
||||||
l = 1;
|
|
||||||
}else{
|
}else{
|
||||||
while(val){
|
while(val){
|
||||||
bufb[l++] = val % 10 + '0';
|
*(--bufptr) = val % 10 + '0';
|
||||||
val /= 10;
|
val /= 10;
|
||||||
}
|
}
|
||||||
int i;
|
|
||||||
bpos += l;
|
|
||||||
for(i = 0; i < l; ++i){
|
|
||||||
bufa[--bpos] = bufb[i];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
bufa[l + bpos] = 0;
|
return bufptr;
|
||||||
return bufa;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// print 32bit unsigned int
|
// print 32bit unsigned int
|
||||||
void printu(int n, uint32_t val){
|
void printu(int n, uint32_t val){
|
||||||
usart_send(n, u2str(val));
|
usart_send(n, u2str(val));
|
||||||
|
|||||||
@ -29,6 +29,9 @@
|
|||||||
#define TIMEOUT_MS (1500)
|
#define TIMEOUT_MS (1500)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// USART1 default speed
|
||||||
|
#define USART1_DEFAULT_SPEED (115200)
|
||||||
|
|
||||||
#define STR_HELPER(s) #s
|
#define STR_HELPER(s) #s
|
||||||
#define STR(s) STR_HELPER(s)
|
#define STR(s) STR_HELPER(s)
|
||||||
|
|
||||||
|
|||||||
@ -20,6 +20,7 @@
|
|||||||
* MA 02110-1301, USA.
|
* MA 02110-1301, USA.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
#include "flash.h"
|
||||||
#include "usb.h"
|
#include "usb.h"
|
||||||
#include "usb_lib.h"
|
#include "usb_lib.h"
|
||||||
#include "usart.h"
|
#include "usart.h"
|
||||||
@ -106,17 +107,26 @@ void USB_send(const char *buf){
|
|||||||
DBG("USB not configured");
|
DBG("USB not configured");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
char tmpbuf[USB_TXBUFSZ];
|
||||||
uint16_t l = 0, ctr = 0;
|
uint16_t l = 0, ctr = 0;
|
||||||
const char *p = buf;
|
const char *p = buf;
|
||||||
while(*p++) ++l;
|
while(*p++) ++l;
|
||||||
while(l){
|
while(l){
|
||||||
uint16_t s = (l > USB_TXBUFSZ) ? USB_TXBUFSZ : l;
|
uint16_t proc = 0, s = (l > USB_TXBUFSZ - 1) ? USB_TXBUFSZ - 1: l;
|
||||||
|
for(int i = 0; i < s; ++i, ++proc){
|
||||||
|
char c = buf[ctr+proc];
|
||||||
|
if(c == '\n' && the_conf.strendRN){ // add '\r' before '\n'
|
||||||
|
tmpbuf[i++] = '\r';
|
||||||
|
if(i == s) ++s;
|
||||||
|
}
|
||||||
|
tmpbuf[i] = c;
|
||||||
|
}
|
||||||
tx_succesfull = 0;
|
tx_succesfull = 0;
|
||||||
EP_Write(3, (uint8_t*)&buf[ctr], s);
|
EP_Write(3, (uint8_t*)tmpbuf, s);
|
||||||
uint32_t ctra = 1000000;
|
uint32_t ctra = 1000000;
|
||||||
while(--ctra && tx_succesfull == 0);
|
while(--ctra && tx_succesfull == 0);
|
||||||
l -= s;
|
l -= proc;
|
||||||
ctr += s;
|
ctr += proc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user