mirror of
https://github.com/eddyem/stm32samples.git
synced 2025-12-06 18:55:13 +03:00
add better version of EEPROM emulation in flash (for now - only in chronometer)
This commit is contained in:
parent
3a5ef823db
commit
7ac9d908fa
@ -149,7 +149,9 @@ void GPS_send_start_seq(){
|
|||||||
*/
|
*/
|
||||||
void GPS_parse_answer(const char *buf){
|
void GPS_parse_answer(const char *buf){
|
||||||
char *ptr;
|
char *ptr;
|
||||||
DBG(buf);
|
#if defined USART1PROXY
|
||||||
|
usart_send(1, buf); newline();
|
||||||
|
#endif
|
||||||
if(buf[1] == 'P') return; // answers to proprietary messages
|
if(buf[1] == 'P') return; // answers to proprietary messages
|
||||||
if(cmpstr(buf+3, "RMC", 3)){ // not RMC message
|
if(cmpstr(buf+3, "RMC", 3)){ // not RMC message
|
||||||
need2startseq = 1;
|
need2startseq = 1;
|
||||||
|
|||||||
@ -12,6 +12,8 @@ LDSCRIPT ?= stm32f103x8.ld
|
|||||||
DEFS = -DVERSION=\"0.0.1\"
|
DEFS = -DVERSION=\"0.0.1\"
|
||||||
# debug
|
# debug
|
||||||
DEFS += -DEBUG
|
DEFS += -DEBUG
|
||||||
|
# proxy GPS output over USART1
|
||||||
|
DEFS += -DUSART1PROXY
|
||||||
|
|
||||||
INDEPENDENT_HEADERS=
|
INDEPENDENT_HEADERS=
|
||||||
|
|
||||||
|
|||||||
@ -11,7 +11,7 @@ Chronometer for downhill competitions
|
|||||||
|
|
||||||
- PB8, PB9 - onboard LEDs
|
- PB8, PB9 - onboard LEDs
|
||||||
|
|
||||||
- PA4 - TRIG2 - 12V trigger (EXTI)
|
- PA4 - TRIG2 - 12V trigger (EXTI) -- not implemented yet
|
||||||
- PA13 - TRIG0 - button0 (EXTI)
|
- PA13 - TRIG0 - button0 (EXTI)
|
||||||
- PA14 - TRIG1 - button1/laser/etc (EXTI)
|
- PA14 - TRIG1 - button1/laser/etc (EXTI)
|
||||||
- PA15 - USB pullup
|
- PA15 - USB pullup
|
||||||
|
|||||||
Binary file not shown.
240
F1-nolib/chronometer/flash.c
Normal file
240
F1-nolib/chronometer/flash.c
Normal 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
|
||||||
48
F1-nolib/chronometer/flash.h
Normal file
48
F1-nolib/chronometer/flash.h
Normal 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__
|
||||||
@ -23,6 +23,7 @@
|
|||||||
|
|
||||||
#include "adc.h"
|
#include "adc.h"
|
||||||
#include "hardware.h"
|
#include "hardware.h"
|
||||||
|
#include "time.h"
|
||||||
#include "usart.h"
|
#include "usart.h"
|
||||||
|
|
||||||
static inline void gpio_setup(){
|
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;
|
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | RCC_APB2ENR_IOPCEN | RCC_APB2ENR_AFIOEN;
|
||||||
// turn off SWJ/JTAG
|
// turn off SWJ/JTAG
|
||||||
AFIO->MAPR = AFIO_MAPR_SWJ_CFG_DISABLE;
|
AFIO->MAPR = AFIO_MAPR_SWJ_CFG_DISABLE;
|
||||||
// pullups
|
// pullups: PA1 - PPS, PA13/PA14 - buttons
|
||||||
GPIOA->ODR = (1<<12)|(1<<13)|(1<<14);
|
GPIOA->ODR = (1<<12)|(1<<13)|(1<<14)|(1<<15);
|
||||||
// Set led (PB8) as opendrain output
|
// Set leds (PB8) as opendrain output
|
||||||
GPIOB->CRH = CRH(8, CNF_ODOUTPUT|MODE_SLOW);
|
GPIOB->CRH = CRH(8, CNF_ODOUTPUT|MODE_SLOW) | CRH(9, CNF_ODOUTPUT|MODE_SLOW);
|
||||||
// PPS pin (PA1) - input with weak pullup
|
// PPS pin (PA1) - input with weak pullup
|
||||||
GPIOA->CRL = CRL(1, CNF_PUDINPUT|MODE_INPUT);
|
GPIOA->CRL = CRL(1, CNF_PUDINPUT|MODE_INPUT);
|
||||||
// Set buttons (PA13/14) as inputs with weak pullups, USB pullup (PA15) - opendrain output
|
// 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
|
void exti1_isr(){ // PPS - PA1
|
||||||
/*
|
|
||||||
if(trigger_ms[2] == DIDNT_TRIGGERED){ // prevent bounce
|
|
||||||
trigger_ms[2] = Timer;
|
|
||||||
memcpy(&trigger_time[2], ¤t_time, sizeof(curtime));
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
DBG("exti1");
|
DBG("exti1");
|
||||||
|
systick_correction();
|
||||||
EXTI->PR = EXTI_PR_PR1;
|
EXTI->PR = EXTI_PR_PR1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -35,10 +35,13 @@
|
|||||||
#define CMD_ADC1MAX "adc1max"
|
#define CMD_ADC1MAX "adc1max"
|
||||||
#define CMD_ADC2MAX "adc2max"
|
#define CMD_ADC2MAX "adc2max"
|
||||||
#define CMD_PRINTTIME "time"
|
#define CMD_PRINTTIME "time"
|
||||||
|
#define CMD_STORECONF "store"
|
||||||
|
|
||||||
// onboard LED - PB8
|
// onboard LEDs - PB8/PB9
|
||||||
#define LED_port GPIOB
|
#define LED0_port GPIOB
|
||||||
#define LED_pin (1<<8)
|
#define LED0_pin (1<<8)
|
||||||
|
#define LED1_port GPIOB
|
||||||
|
#define LED1_pin (1<<9)
|
||||||
|
|
||||||
// PPS pin - PA1
|
// PPS pin - PA1
|
||||||
#define PPS_port GPIOA
|
#define PPS_port GPIOA
|
||||||
@ -55,9 +58,12 @@
|
|||||||
#define USBPU_ON() pin_clear(USBPU_port, USBPU_pin)
|
#define USBPU_ON() pin_clear(USBPU_port, USBPU_pin)
|
||||||
#define USBPU_OFF() pin_set(USBPU_port, USBPU_pin)
|
#define USBPU_OFF() pin_set(USBPU_port, USBPU_pin)
|
||||||
|
|
||||||
#define LED_blink() pin_toggle(LED_port, LED_pin)
|
#define LED_blink() pin_toggle(LED0_port, LED0_pin)
|
||||||
#define LED_on() pin_clear(LED_port, LED_pin)
|
#define LED_on() pin_clear(LED0_port, LED0_pin)
|
||||||
#define LED_off() pin_set(LED_port, LED_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
|
// GPS USART == USART2, LIDAR USART == USART3
|
||||||
#define GPS_USART (2)
|
#define GPS_USART (2)
|
||||||
|
|||||||
@ -16,11 +16,10 @@
|
|||||||
* 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 "lidar.h"
|
#include "lidar.h"
|
||||||
#include "usart.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_dist = 0;
|
||||||
uint16_t last_lidar_stren = 0;
|
uint16_t last_lidar_stren = 0;
|
||||||
uint16_t lidar_triggered_dist = 0;
|
uint16_t lidar_triggered_dist = 0;
|
||||||
@ -35,7 +34,7 @@ void parse_lidar_data(char *txt){
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(triggered){ // check if body gone
|
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;
|
triggered = 0;
|
||||||
#ifdef EBUG
|
#ifdef EBUG
|
||||||
SEND("Untriggered! distance=");
|
SEND("Untriggered! distance=");
|
||||||
@ -46,7 +45,7 @@ void parse_lidar_data(char *txt){
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}else{
|
}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;
|
triggered = 1;
|
||||||
lidar_triggered_dist = last_lidar_dist;
|
lidar_triggered_dist = last_lidar_dist;
|
||||||
#ifdef EBUG
|
#ifdef EBUG
|
||||||
|
|||||||
@ -27,6 +27,9 @@
|
|||||||
#define LIDAR_LOWER_STREN (10)
|
#define LIDAR_LOWER_STREN (10)
|
||||||
// triggered distance threshold - 1 meter
|
// triggered distance threshold - 1 meter
|
||||||
#define LIDAR_DIST_THRES (100)
|
#define LIDAR_DIST_THRES (100)
|
||||||
|
#define LIDAR_MIN_DIST (50)
|
||||||
|
#define LIDAR_MAX_DIST (1000)
|
||||||
|
|
||||||
extern uint16_t last_lidar_dist;
|
extern uint16_t last_lidar_dist;
|
||||||
extern uint16_t lidar_triggered_dist;
|
extern uint16_t lidar_triggered_dist;
|
||||||
extern uint16_t last_lidar_stren;
|
extern uint16_t last_lidar_stren;
|
||||||
|
|||||||
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
//#include "adc.h"
|
//#include "adc.h"
|
||||||
#include "GPS.h"
|
#include "GPS.h"
|
||||||
|
#include "flash.h"
|
||||||
#include "hardware.h"
|
#include "hardware.h"
|
||||||
#include "lidar.h"
|
#include "lidar.h"
|
||||||
#include "str.h"
|
#include "str.h"
|
||||||
@ -33,11 +34,13 @@
|
|||||||
#define VERSION "0.0.0"
|
#define VERSION "0.0.0"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// global pseudo-milliseconds counter
|
||||||
volatile uint32_t Tms = 0;
|
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_timer();
|
||||||
}
|
}
|
||||||
|
|
||||||
void iwdg_setup(){
|
void iwdg_setup(){
|
||||||
@ -65,8 +68,8 @@ void iwdg_setup(){
|
|||||||
|
|
||||||
#ifdef EBUG
|
#ifdef EBUG
|
||||||
char *parse_cmd(char *buf){
|
char *parse_cmd(char *buf){
|
||||||
|
int32_t N;
|
||||||
static char btns[] = "BTN0=0, BTN1=0, PPS=0\n";
|
static char btns[] = "BTN0=0, BTN1=0, PPS=0\n";
|
||||||
if(buf[1] != '\n') return buf;
|
|
||||||
switch(*buf){
|
switch(*buf){
|
||||||
case '0':
|
case '0':
|
||||||
LED_off();
|
LED_off();
|
||||||
@ -80,6 +83,16 @@ char *parse_cmd(char *buf){
|
|||||||
btns[20] = GET_PPS() + '0';
|
btns[20] = GET_PPS() + '0';
|
||||||
return btns;
|
return btns;
|
||||||
break;
|
break;
|
||||||
|
case 'C':
|
||||||
|
if(getnum(&buf[1], &N)){
|
||||||
|
SEND("Need a number!\n");
|
||||||
|
}else{
|
||||||
|
addNrecs(N);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
dump_userconf();
|
||||||
|
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 ");
|
||||||
@ -117,10 +130,13 @@ char *parse_cmd(char *buf){
|
|||||||
while(1){nop();};
|
while(1){nop();};
|
||||||
break;
|
break;
|
||||||
default: // help
|
default: // help
|
||||||
|
if(buf[1] != '\n') return buf;
|
||||||
return
|
return
|
||||||
"0/1 - turn on/off LED1\n"
|
"0/1 - turn on/off LED1\n"
|
||||||
"'b' - get buttons's state\n"
|
"'b' - get buttons's state\n"
|
||||||
|
"'d' - dump current user conf\n"
|
||||||
"'p' - toggle USB pullup\n"
|
"'p' - toggle USB pullup\n"
|
||||||
|
"'C' - store userconf for N times\n"
|
||||||
"'G' - get last LIDAR distance\n"
|
"'G' - get last LIDAR distance\n"
|
||||||
"'L' - send long string over USB\n"
|
"'L' - send long string over USB\n"
|
||||||
"'R' - software reset\n"
|
"'R' - software reset\n"
|
||||||
@ -155,22 +171,55 @@ static char *get_USB(){
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CMP(a,b) cmpstr(a, b, sizeof(b)-1)
|
|
||||||
static void parse_USBCMD(char *cmd){
|
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 || !*cmd) return;
|
||||||
if(*cmd == '?'){ // help
|
if(*cmd == '?'){ // help
|
||||||
USB_send("Commands:\n"
|
USB_send("Commands:\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_PRINTTIME " - print time\n"
|
CMD_PRINTTIME " - print time\n"
|
||||||
|
CMD_STORECONF " - store new configuration in flash\n"
|
||||||
);
|
);
|
||||||
}else if(CMP(cmd, CMD_PRINTTIME) == 0){
|
}else if(CMP(cmd, CMD_PRINTTIME) == 0){
|
||||||
USB_send(get_time(¤t_time, get_millis()));
|
USB_send(get_time(¤t_time, get_millis()));
|
||||||
}else if(CMP(cmd, CMD_DISTMIN) == 0){ // set low limit
|
}else if(CMP(cmd, CMD_DISTMIN) == 0){ // set low limit
|
||||||
DBG("CMD_DISTMIN");
|
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
|
}else if(CMP(cmd, CMD_DISTMAX) == 0){ // set low limit
|
||||||
DBG("CMD_DISTMAX");
|
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){
|
||||||
@ -178,9 +227,10 @@ int main(void){
|
|||||||
sysreset();
|
sysreset();
|
||||||
StartHSE();
|
StartHSE();
|
||||||
hw_setup();
|
hw_setup();
|
||||||
|
LED1_off();
|
||||||
USBPU_OFF();
|
USBPU_OFF();
|
||||||
usarts_setup();
|
usarts_setup();
|
||||||
SysTick_Config(72000);
|
SysTick_Config(SYSTICK_DEFLOAD);
|
||||||
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");
|
||||||
@ -191,14 +241,27 @@ int main(void){
|
|||||||
RCC->CSR |= RCC_CSR_RMVF; // remove reset flags
|
RCC->CSR |= RCC_CSR_RMVF; // remove reset flags
|
||||||
|
|
||||||
USB_setup();
|
USB_setup();
|
||||||
//iwdg_setup();
|
iwdg_setup();
|
||||||
USBPU_ON();
|
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){
|
while (1){
|
||||||
IWDG->KR = IWDG_REFRESH; // refresh watchdog
|
IWDG->KR = IWDG_REFRESH; // refresh watchdog
|
||||||
if(lastT > Tms || Tms - lastT > 499){
|
if(lastT > Tms || Tms - lastT > 499){
|
||||||
if(need2startseq) GPS_send_start_seq();
|
if(need2startseq) GPS_send_start_seq();
|
||||||
LED_blink();
|
LED_blink();
|
||||||
|
if(GPS_status != GPS_VALID) LED1_blink();
|
||||||
|
else LED1_on();
|
||||||
lastT = Tms;
|
lastT = Tms;
|
||||||
if(usartrx(LIDAR_USART)){
|
if(usartrx(LIDAR_USART)){
|
||||||
char *txt;
|
char *txt;
|
||||||
@ -207,7 +270,7 @@ int main(void){
|
|||||||
DBG(txt);
|
DBG(txt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef EBUG
|
#if defined EBUG || defined USART1PROXY
|
||||||
transmit_tbuf(1); // non-blocking transmission of data from UART buffer every 0.5s
|
transmit_tbuf(1); // non-blocking transmission of data from UART buffer every 0.5s
|
||||||
#endif
|
#endif
|
||||||
transmit_tbuf(GPS_USART);
|
transmit_tbuf(GPS_USART);
|
||||||
@ -215,23 +278,28 @@ int main(void){
|
|||||||
}
|
}
|
||||||
usb_proc();
|
usb_proc();
|
||||||
int r = 0;
|
int r = 0;
|
||||||
char *txt, *ans;
|
char *txt;
|
||||||
if((txt = get_USB())){
|
if((txt = get_USB())){
|
||||||
parse_USBCMD(txt);
|
parse_USBCMD(txt);
|
||||||
DBG("Received data over USB:");
|
DBG("Received data over USB:");
|
||||||
DBG(txt);
|
DBG(txt);
|
||||||
USB_send(txt); // echo all back
|
USB_send(txt); // echo all back
|
||||||
}
|
}
|
||||||
#ifdef EBUG
|
#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
|
||||||
r = usart_getline(1, &txt);
|
r = usart_getline(1, &txt);
|
||||||
if(r){
|
if(r){
|
||||||
txt[r] = 0;
|
txt[r] = 0;
|
||||||
ans = parse_cmd(txt);
|
#ifdef EBUG
|
||||||
|
char *ans = parse_cmd(txt);
|
||||||
if(ans){
|
if(ans){
|
||||||
|
transmit_tbuf(1);
|
||||||
usart_send(1, ans);
|
usart_send(1, ans);
|
||||||
transmit_tbuf(1);
|
transmit_tbuf(1);
|
||||||
}
|
}
|
||||||
|
#else // USART1PROXY - send received data to GPS
|
||||||
|
usart_send(GPS_USART, txt);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -251,4 +319,3 @@ int main(void){
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -21,9 +21,13 @@
|
|||||||
#include "usb.h"
|
#include "usb.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
volatile uint32_t Timer; // milliseconds counter
|
||||||
curtime current_time = TMNOTINI;
|
curtime current_time = TMNOTINI;
|
||||||
volatile int need_sync = 1;
|
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){
|
static inline uint8_t atou(const char *b){
|
||||||
return (b[0]-'0')*10 + b[1]-'0';
|
return (b[0]-'0')*10 + b[1]-'0';
|
||||||
}
|
}
|
||||||
@ -36,6 +40,22 @@ void set_time(const char *buf){
|
|||||||
current_time.S = atou(&buf[4]);
|
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
|
* print time: Tm - time structure, T - milliseconds
|
||||||
*/
|
*/
|
||||||
@ -90,3 +110,54 @@ uint32_t get_millis(){
|
|||||||
// TODO: calculate right millis
|
// TODO: calculate right millis
|
||||||
return Tms % 1000; // temporary gag
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -21,7 +21,10 @@
|
|||||||
|
|
||||||
#include <stm32f1.h>
|
#include <stm32f1.h>
|
||||||
|
|
||||||
#define STK_RVR_DEFAULT_VAL (8999)
|
// 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 TIMEZONE_GMT_PLUS (3)
|
||||||
|
|
||||||
#define DIDNT_TRIGGERED (2000)
|
#define DIDNT_TRIGGERED (2000)
|
||||||
@ -38,6 +41,7 @@ typedef struct{
|
|||||||
} curtime;
|
} curtime;
|
||||||
|
|
||||||
extern volatile uint32_t Tms;
|
extern volatile uint32_t Tms;
|
||||||
|
extern volatile uint32_t Timer;
|
||||||
extern curtime current_time;
|
extern curtime current_time;
|
||||||
|
|
||||||
extern curtime trigger_time[];
|
extern curtime trigger_time[];
|
||||||
@ -48,5 +52,8 @@ 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
|
uint32_t get_millis(); // current milliseconds
|
||||||
|
void time_increment();
|
||||||
|
void systick_correction();
|
||||||
|
void increment_timer();
|
||||||
|
|
||||||
#endif // TIME_H__
|
#endif // TIME_H__
|
||||||
|
|||||||
@ -94,7 +94,7 @@ void usart_send(int n, const char *str){
|
|||||||
tbuf[n][tbufno[n]][odatalen[n][tbufno[n]]++] = *str++;
|
tbuf[n][tbufno[n]][odatalen[n][tbufno[n]]++] = *str++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef EBUG
|
#if defined EBUG || defined USART1PROXY
|
||||||
// only for USART1
|
// only for USART1
|
||||||
void newline(){
|
void newline(){
|
||||||
usart_putchar(1, '\n');
|
usart_putchar(1, '\n');
|
||||||
@ -168,8 +168,8 @@ 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;
|
||||||
#ifdef EBUG
|
#if defined EBUG || defined USART1PROXY
|
||||||
usart_setup(1, 72000000 / 115200); // debug console
|
usart_setup(1, 72000000 / 115200); // 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
|
||||||
@ -215,7 +215,7 @@ void usart_isr(int n, USART_TypeDef *USART){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef EBUG
|
#if defined EBUG || defined USART1PROXY
|
||||||
void usart1_isr(){
|
void usart1_isr(){
|
||||||
usart_isr(1, USART1);
|
usart_isr(1, USART1);
|
||||||
}
|
}
|
||||||
@ -310,7 +310,7 @@ void hexdump(uint8_t *arr, uint16_t len){
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef EBUG
|
#if defined EBUG || defined USART1PROXY
|
||||||
void dma1_channel4_isr(){ // USART1
|
void dma1_channel4_isr(){ // USART1
|
||||||
if(DMA1->ISR & DMA_ISR_TCIF4){ // Tx
|
if(DMA1->ISR & DMA_ISR_TCIF4){ // Tx
|
||||||
DMA1->IFCR = DMA_IFCR_CTCIF4; // clear TC flag
|
DMA1->IFCR = DMA_IFCR_CTCIF4; // clear TC flag
|
||||||
@ -332,3 +332,34 @@ void dma1_channel2_isr(){ // USART3
|
|||||||
txrdy[3] = 1;
|
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;
|
||||||
|
}
|
||||||
|
|||||||
@ -55,13 +55,13 @@ void usart_putchar(int n, char ch);
|
|||||||
char *u2str(uint32_t val);
|
char *u2str(uint32_t val);
|
||||||
void printu(int n, uint32_t val);
|
void printu(int n, uint32_t val);
|
||||||
void printuhex(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();
|
void newline();
|
||||||
|
#endif
|
||||||
|
#ifdef EBUG
|
||||||
void hexdump(uint8_t *arr, uint16_t len);
|
void hexdump(uint8_t *arr, uint16_t len);
|
||||||
#endif
|
#endif
|
||||||
/*
|
|
||||||
void hexdump16(uint16_t *arr, uint16_t len);
|
|
||||||
void hexdump32(uint32_t *arr, uint16_t len);
|
|
||||||
*/
|
|
||||||
#endif // __USART_H__
|
#endif // __USART_H__
|
||||||
|
|||||||
@ -102,6 +102,10 @@ void usb_proc(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void USB_send(char *buf){
|
void USB_send(char *buf){
|
||||||
|
if(!USB_configured()){
|
||||||
|
DBG("USB not configured");
|
||||||
|
return;
|
||||||
|
}
|
||||||
uint16_t l = 0, ctr = 0;
|
uint16_t l = 0, ctr = 0;
|
||||||
char *p = buf;
|
char *p = buf;
|
||||||
while(*p++) ++l;
|
while(*p++) ++l;
|
||||||
|
|||||||
@ -71,6 +71,12 @@ SECTIONS {
|
|||||||
_edata = .;
|
_edata = .;
|
||||||
} >ram AT >rom
|
} >ram AT >rom
|
||||||
|
|
||||||
|
.myvars :
|
||||||
|
{
|
||||||
|
. = ALIGN(1024);
|
||||||
|
KEEP(*(.myvars))
|
||||||
|
} > rom
|
||||||
|
|
||||||
_ldata = LOADADDR(.data);
|
_ldata = LOADADDR(.data);
|
||||||
|
|
||||||
.bss :
|
.bss :
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user