mirror of
https://github.com/eddyem/stm32samples.git
synced 2025-12-06 10:45:11 +03:00
fix some bugs
This commit is contained in:
parent
98b61c7e9a
commit
24a270a932
Binary file not shown.
@ -19,6 +19,8 @@
|
|||||||
#include "adc.h"
|
#include "adc.h"
|
||||||
#include "hardware.h" // ADCvals
|
#include "hardware.h" // ADCvals
|
||||||
|
|
||||||
|
#include "usb.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief ADCx_array - arrays for ADC channels with median filtering:
|
* @brief ADCx_array - arrays for ADC channels with median filtering:
|
||||||
* ADC1:
|
* ADC1:
|
||||||
@ -73,6 +75,7 @@ void adc_setup(){
|
|||||||
ADC1->SQR2 = (16<<0);
|
ADC1->SQR2 = (16<<0);
|
||||||
ADC2->SMPR1 = ADC_SMPR1_SMP1;
|
ADC2->SMPR1 = ADC_SMPR1_SMP1;
|
||||||
// configure DMA for ADC
|
// configure DMA for ADC
|
||||||
|
RCC->AHBENR |= RCC_AHBENR_DMA1EN;
|
||||||
ADC1->CFGR = ADC_CFGR_CONT | ADC_CFGR_DMAEN | ADC_CFGR_DMACFG;
|
ADC1->CFGR = ADC_CFGR_CONT | ADC_CFGR_DMAEN | ADC_CFGR_DMACFG;
|
||||||
DMA1_Channel1->CPAR = (uint32_t) (&(ADC1->DR));
|
DMA1_Channel1->CPAR = (uint32_t) (&(ADC1->DR));
|
||||||
DMA1_Channel1->CMAR = (uint32_t)(ADC_array);
|
DMA1_Channel1->CMAR = (uint32_t)(ADC_array);
|
||||||
@ -104,18 +107,19 @@ uint16_t getADCval(int nch){
|
|||||||
PIX_SORT(p[4], p[2]) ;
|
PIX_SORT(p[4], p[2]) ;
|
||||||
#undef PIX_SORT
|
#undef PIX_SORT
|
||||||
#undef PIX_SWAP
|
#undef PIX_SWAP
|
||||||
|
DBG("nch="); printu(nch); USB_sendstr("; data="); printu(p[4]); newline();
|
||||||
return p[4];
|
return p[4];
|
||||||
}
|
}
|
||||||
|
|
||||||
// get voltage @input nch (V)
|
// get voltage @input nch (V)
|
||||||
float getADCvoltage(uint16_t ADCval){
|
float getADCvoltage(int nch){
|
||||||
float v = (float)ADCval * 3.3;
|
float v = getADCval(nch) * 3.3f;
|
||||||
return v/4096.f; // 12bit ADC
|
return v/4096.f; // 12bit ADC
|
||||||
}
|
}
|
||||||
|
|
||||||
// return MCU temperature (degrees of celsius)
|
// return MCU temperature (degrees of celsius)
|
||||||
float getMCUtemp(){
|
float getMCUtemp(){
|
||||||
float temperature = ADC_array[ADC_TSENS] - (float) *TEMP30_CAL_ADDR;
|
float temperature = getADCval(ADC_TSENS) - (float) *TEMP30_CAL_ADDR;
|
||||||
temperature *= (110.f - 30.f);
|
temperature *= (110.f - 30.f);
|
||||||
temperature /= (float)(*TEMP110_CAL_ADDR - *TEMP30_CAL_ADDR);
|
temperature /= (float)(*TEMP110_CAL_ADDR - *TEMP30_CAL_ADDR);
|
||||||
temperature += 30.f;
|
temperature += 30.f;
|
||||||
|
|||||||
@ -33,4 +33,4 @@
|
|||||||
void adc_setup();
|
void adc_setup();
|
||||||
float getMCUtemp();
|
float getMCUtemp();
|
||||||
uint16_t getADCval(int nch);
|
uint16_t getADCval(int nch);
|
||||||
float getADCvoltage(uint16_t ADCval);
|
float getADCvoltage(int nch);
|
||||||
|
|||||||
@ -24,10 +24,16 @@
|
|||||||
#include "strfunc.h"
|
#include "strfunc.h"
|
||||||
#include "usb.h"
|
#include "usb.h"
|
||||||
|
|
||||||
|
#ifdef EBUG
|
||||||
|
#undef EBUG
|
||||||
|
#endif
|
||||||
|
|
||||||
// PD1 - Tx, PD0 - Rx !!!
|
// PD1 - Tx, PD0 - Rx !!!
|
||||||
|
|
||||||
#include <string.h> // memcpy
|
#include <string.h> // memcpy
|
||||||
|
|
||||||
|
uint8_t cansniffer = 0; // 0 - receive only 0 and myID, 1 - receive all
|
||||||
|
|
||||||
// circular buffer for received messages
|
// circular buffer for received messages
|
||||||
static CAN_message messages[CAN_INMESSAGE_SIZE];
|
static CAN_message messages[CAN_INMESSAGE_SIZE];
|
||||||
static uint8_t first_free_idx = 0; // index of first empty cell
|
static uint8_t first_free_idx = 0; // index of first empty cell
|
||||||
@ -45,8 +51,9 @@ static CAN_message loc_flood_msg;
|
|||||||
static CAN_message *flood_msg = NULL; // == loc_flood_msg - to flood
|
static CAN_message *flood_msg = NULL; // == loc_flood_msg - to flood
|
||||||
|
|
||||||
CAN_status CAN_get_status(){
|
CAN_status CAN_get_status(){
|
||||||
int st = can_status;
|
CAN_status st = can_status;
|
||||||
can_status = CAN_OK;
|
//can_status = CAN_OK;
|
||||||
|
if(st == CAN_FIFO_OVERRUN) can_status = CAN_READY;
|
||||||
return st;
|
return st;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,7 +102,7 @@ CAN_message *CAN_messagebuf_pop(){
|
|||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CAN_reinit(uint16_t speed){
|
void CAN_reinit(uint32_t speed){
|
||||||
CAN->TSR |= CAN_TSR_ABRQ0 | CAN_TSR_ABRQ1 | CAN_TSR_ABRQ2;
|
CAN->TSR |= CAN_TSR_ABRQ0 | CAN_TSR_ABRQ1 | CAN_TSR_ABRQ2;
|
||||||
RCC->APB1RSTR |= RCC_APB1RSTR_CANRST;
|
RCC->APB1RSTR |= RCC_APB1RSTR_CANRST;
|
||||||
RCC->APB1RSTR &= ~RCC_APB1RSTR_CANRST;
|
RCC->APB1RSTR &= ~RCC_APB1RSTR_CANRST;
|
||||||
@ -127,8 +134,8 @@ so if TBS1=4 and TBS2=3, sum=8, bit sampling freq is 36/8 = 4.5MHz
|
|||||||
// GPIO configured in hw_setup
|
// GPIO configured in hw_setup
|
||||||
void CAN_setup(uint32_t speed){
|
void CAN_setup(uint32_t speed){
|
||||||
if(speed == 0) speed = oldspeed;
|
if(speed == 0) speed = oldspeed;
|
||||||
else if(speed < 50) speed = 50;
|
else if(speed < CAN_MIN_SPEED) speed = CAN_MIN_SPEED;
|
||||||
else if(speed > 3000) speed = 3000;
|
else if(speed > CAN_MAX_SPEED) speed = CAN_MAX_SPEED;
|
||||||
uint32_t tmout = 10000;
|
uint32_t tmout = 10000;
|
||||||
/* Enable the peripheral clock CAN */
|
/* Enable the peripheral clock CAN */
|
||||||
RCC->APB1ENR |= RCC_APB1ENR_CANEN;
|
RCC->APB1ENR |= RCC_APB1ENR_CANEN;
|
||||||
@ -141,7 +148,7 @@ void CAN_setup(uint32_t speed){
|
|||||||
/* (6) Wait the init mode leaving */
|
/* (6) Wait the init mode leaving */
|
||||||
/* (7) Enter filter init mode, (16-bit + mask, bank 0 for FIFO 0) */
|
/* (7) Enter filter init mode, (16-bit + mask, bank 0 for FIFO 0) */
|
||||||
/* (8) Acivate filter 0 for two IDs */
|
/* (8) Acivate filter 0 for two IDs */
|
||||||
/* (9) Identifier list mode */
|
/* (9) Identifier mode for bank#0, mask mode for #1 */
|
||||||
/* (10) Set the Id list */
|
/* (10) Set the Id list */
|
||||||
/* (12) Leave filter init */
|
/* (12) Leave filter init */
|
||||||
/* (13) Set error interrupts enable (& bus off) */
|
/* (13) Set error interrupts enable (& bus off) */
|
||||||
@ -151,21 +158,28 @@ void CAN_setup(uint32_t speed){
|
|||||||
if(tmout==0){ DBG("timeout!\n");}
|
if(tmout==0){ DBG("timeout!\n");}
|
||||||
CAN->MCR &=~ CAN_MCR_SLEEP; /* (3) */
|
CAN->MCR &=~ CAN_MCR_SLEEP; /* (3) */
|
||||||
CAN->MCR |= CAN_MCR_ABOM; /* allow automatically bus-off */
|
CAN->MCR |= CAN_MCR_ABOM; /* allow automatically bus-off */
|
||||||
|
CAN->BTR = 2 << 20 | 3 << 16 | (((uint32_t)4500000UL)/speed - 1); //| CAN_BTR_SILM | CAN_BTR_LBKM; /* (4) */
|
||||||
CAN->BTR = 2 << 20 | 3 << 16 | (4500000/speed - 1); //| CAN_BTR_SILM | CAN_BTR_LBKM; /* (4) */
|
oldspeed = ((uint32_t)4500000UL)/(uint32_t)((CAN->BTR & CAN_BTR_BRP) + 1);
|
||||||
oldspeed = 4500000/((CAN->BTR & CAN_BTR_BRP) + 1);
|
|
||||||
CAN->MCR &= ~CAN_MCR_INRQ; /* (5) */
|
CAN->MCR &= ~CAN_MCR_INRQ; /* (5) */
|
||||||
tmout = 10000;
|
tmout = 10000;
|
||||||
while(CAN->MSR & CAN_MSR_INAK) /* (6) */
|
while(CAN->MSR & CAN_MSR_INAK) /* (6) */
|
||||||
if(--tmout == 0) break;
|
if(--tmout == 0) break;
|
||||||
if(tmout==0){ DBG("timeout!\n");}
|
if(tmout==0){ DBG("timeout!\n");}
|
||||||
// accept ALL
|
// accept only 0 & ID or ALL depending on `cansniffer` value
|
||||||
CAN->FMR = CAN_FMR_FINIT; /* (7) */
|
CAN->FMR = CAN_FMR_FINIT; /* (7) */
|
||||||
CAN->FA1R = CAN_FA1R_FACT0 | CAN_FA1R_FACT1; /* (8) */
|
CAN->FA1R = CAN_FA1R_FACT0; /* (8) */
|
||||||
// set to 1 all needed bits of CAN->FFA1R to switch given filters to FIFO1
|
CAN->FM1R = CAN_FM1R_FBM0; /* (9) */
|
||||||
CAN->sFilterRegister[0].FR1 = (1<<21)|(1<<5); // all odd IDs
|
// CAN->FSCx = 0 -> dual 16-bit scale configuration
|
||||||
CAN->FFA1R = 2; // filter 1 for FIFO1, filter 0 - for FIFO0
|
// filter 0 for FIFO0
|
||||||
CAN->sFilterRegister[1].FR1 = (1<<21); // all even IDs
|
CAN->sFilterRegister[0].FR1 = the_conf.CANID << 5; // (10) CANID and 0
|
||||||
|
if(cansniffer){ /* (11) */
|
||||||
|
CAN->FA1R |= CAN_FA1R_FACT1; // activate filter1
|
||||||
|
CAN->sFilterRegister[1].FR1 = 0; // all packets
|
||||||
|
// mask mode, all odd and even IDs
|
||||||
|
//CAN->sFilterRegister[1].FR1 = (1<<21)|(1<<5); // all odd IDs, mask mode
|
||||||
|
//CAN->sFilterRegister[1].FR2 = (1<<21)|(0<<5); // all even IDs, mask mode
|
||||||
|
CAN->FFA1R = 2; // filter 1 for FIFO1
|
||||||
|
}
|
||||||
CAN->FMR &= ~CAN_FMR_FINIT; /* (12) */
|
CAN->FMR &= ~CAN_FMR_FINIT; /* (12) */
|
||||||
CAN->IER |= CAN_IER_ERRIE | CAN_IER_FOVIE0 | CAN_IER_FOVIE1 | CAN_IER_BOFIE; /* (13) */
|
CAN->IER |= CAN_IER_ERRIE | CAN_IER_FOVIE0 | CAN_IER_FOVIE1 | CAN_IER_BOFIE; /* (13) */
|
||||||
|
|
||||||
@ -180,6 +194,15 @@ void CAN_setup(uint32_t speed){
|
|||||||
can_status = CAN_READY;
|
can_status = CAN_READY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CAN_sniffer - reconfigure CAN in sniffer or normal mode
|
||||||
|
* @param issniffer - ==0 for normal mode
|
||||||
|
*/
|
||||||
|
void CAN_sniffer(uint8_t issniffer){
|
||||||
|
cansniffer = issniffer;
|
||||||
|
CAN_reinit(0);
|
||||||
|
}
|
||||||
|
|
||||||
void CAN_printerr(){
|
void CAN_printerr(){
|
||||||
if(!last_err_code) last_err_code = CAN->ESR;
|
if(!last_err_code) last_err_code = CAN->ESR;
|
||||||
if(!last_err_code){
|
if(!last_err_code){
|
||||||
@ -228,14 +251,9 @@ void CAN_proc(){
|
|||||||
}
|
}
|
||||||
IWDG->KR = IWDG_REFRESH;
|
IWDG->KR = IWDG_REFRESH;
|
||||||
if(CAN->ESR & (CAN_ESR_BOFF | CAN_ESR_EPVF | CAN_ESR_EWGF)){ // much errors - restart CAN BUS
|
if(CAN->ESR & (CAN_ESR_BOFF | CAN_ESR_EPVF | CAN_ESR_EWGF)){ // much errors - restart CAN BUS
|
||||||
USB_sendstr("\nToo much errors, restarting CAN!\n");
|
USB_sendstr("error=canbuserr\n");
|
||||||
CAN_printerr();
|
CAN_printerr();
|
||||||
// request abort for all mailboxes
|
CAN_reinit(0);
|
||||||
CAN->TSR |= CAN_TSR_ABRQ0 | CAN_TSR_ABRQ1 | CAN_TSR_ABRQ2;
|
|
||||||
// reset CAN bus
|
|
||||||
RCC->APB1RSTR |= RCC_APB1RSTR_CANRST;
|
|
||||||
RCC->APB1RSTR &= ~RCC_APB1RSTR_CANRST;
|
|
||||||
CAN_setup(0);
|
|
||||||
}
|
}
|
||||||
static uint32_t lastFloodTime = 0;
|
static uint32_t lastFloodTime = 0;
|
||||||
static uint32_t incrmessagectr = 0;
|
static uint32_t incrmessagectr = 0;
|
||||||
@ -255,11 +273,17 @@ CAN_status CAN_send(CAN_message *message){
|
|||||||
uint8_t *msg = message->data;
|
uint8_t *msg = message->data;
|
||||||
uint8_t len = message->length;
|
uint8_t len = message->length;
|
||||||
uint16_t target_id = message->ID;
|
uint16_t target_id = message->ID;
|
||||||
uint8_t mailbox = 0;
|
uint8_t mailbox = 0xff;
|
||||||
// check first free mailbox
|
// check first free mailbox
|
||||||
|
uint32_t Tstart = Tms;
|
||||||
|
while(Tms - Tstart < SEND_TIMEOUT_MS/10){
|
||||||
|
IWDG->KR = IWDG_REFRESH;
|
||||||
if(CAN->TSR & (CAN_TSR_TME)){
|
if(CAN->TSR & (CAN_TSR_TME)){
|
||||||
mailbox = (CAN->TSR & CAN_TSR_CODE) >> 24;
|
mailbox = (CAN->TSR & CAN_TSR_CODE) >> 24;
|
||||||
}else{ // no free mailboxes
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(mailbox == 0xff){// no free mailboxes
|
||||||
#ifdef EBUG
|
#ifdef EBUG
|
||||||
USB_sendstr("No free mailboxes\n");
|
USB_sendstr("No free mailboxes\n");
|
||||||
#endif
|
#endif
|
||||||
@ -336,9 +360,13 @@ TRUE_INLINE void parseCANcommand(CAN_message *msg){
|
|||||||
msg->ID = the_conf.CANID; // set own ID for broadcast messages
|
msg->ID = the_conf.CANID; // set own ID for broadcast messages
|
||||||
// check PING
|
// check PING
|
||||||
if(msg->length != 0) run_can_cmd(msg);
|
if(msg->length != 0) run_can_cmd(msg);
|
||||||
int N = 1000;
|
uint32_t Tstart = Tms;
|
||||||
while(CAN_BUSY == CAN_send(msg))
|
while(Tms - Tstart < SEND_TIMEOUT_MS){
|
||||||
if(--N == 0) break;
|
if(CAN_OK == CAN_send(msg)) return;
|
||||||
|
IWDG->KR = IWDG_REFRESH;
|
||||||
|
}
|
||||||
|
// TODO: buzzer error can't send
|
||||||
|
USB_sendstr("error=canbusy\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void can_process_fifo(uint8_t fifo_num){
|
static void can_process_fifo(uint8_t fifo_num){
|
||||||
@ -354,6 +382,7 @@ static void can_process_fifo(uint8_t fifo_num){
|
|||||||
// CAN_RDTxR: (16-31) - timestamp, (8-15) - filter match index, (0-3) - data length
|
// CAN_RDTxR: (16-31) - timestamp, (8-15) - filter match index, (0-3) - data length
|
||||||
/* TODO: check filter match index if more than one ID can receive */
|
/* TODO: check filter match index if more than one ID can receive */
|
||||||
CAN_message msg;
|
CAN_message msg;
|
||||||
|
bzero(&msg, sizeof(msg));
|
||||||
uint8_t *dat = msg.data;
|
uint8_t *dat = msg.data;
|
||||||
uint8_t len = box->RDTR & 0x0f;
|
uint8_t len = box->RDTR & 0x0f;
|
||||||
msg.length = len;
|
msg.length = len;
|
||||||
@ -389,7 +418,7 @@ static void can_process_fifo(uint8_t fifo_num){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(msg.ID == the_conf.CANID || msg.ID == 0) parseCANcommand(&msg);
|
if(msg.ID == the_conf.CANID || msg.ID == 0) parseCANcommand(&msg);
|
||||||
if(CAN_messagebuf_push(&msg)) return; // error: buffer is full, try later
|
if(cansniffer && CAN_messagebuf_push(&msg)) return; // error: buffer is full, try later
|
||||||
*RFxR |= CAN_RF0R_RFOM0; // release fifo for access to next message
|
*RFxR |= CAN_RF0R_RFOM0; // release fifo for access to next message
|
||||||
}
|
}
|
||||||
//if(*RFxR & CAN_RF0R_FULL0) *RFxR &= ~CAN_RF0R_FULL0;
|
//if(*RFxR & CAN_RF0R_FULL0) *RFxR &= ~CAN_RF0R_FULL0;
|
||||||
|
|||||||
@ -20,14 +20,21 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
// min/max speeds in bps
|
||||||
|
#define CAN_MAX_SPEED ((uint32_t)3000000UL)
|
||||||
|
#define CAN_MIN_SPEED ((uint32_t)9600UL)
|
||||||
|
|
||||||
// amount of filter banks in STM32F0
|
// amount of filter banks in STM32F0
|
||||||
#define STM32F0FBANKNO 28
|
#define STM32F0FBANKNO (28)
|
||||||
// flood period in milliseconds
|
// flood period in milliseconds
|
||||||
#define FLOOD_PERIOD_MS 5
|
#define FLOOD_PERIOD_MS (5)
|
||||||
|
// wait to send not more tnah
|
||||||
|
#define SEND_TIMEOUT_MS (100)
|
||||||
|
|
||||||
// incoming message buffer size
|
// incoming message buffer size
|
||||||
#define CAN_INMESSAGE_SIZE (8)
|
#define CAN_INMESSAGE_SIZE (8)
|
||||||
extern uint32_t floodT;
|
extern uint32_t floodT;
|
||||||
|
extern uint8_t cansniffer;
|
||||||
|
|
||||||
// CAN message
|
// CAN message
|
||||||
typedef struct{
|
typedef struct{
|
||||||
@ -47,8 +54,9 @@ typedef enum{
|
|||||||
|
|
||||||
CAN_status CAN_get_status();
|
CAN_status CAN_get_status();
|
||||||
|
|
||||||
void CAN_reinit(uint16_t speed);
|
void CAN_reinit(uint32_t speed);
|
||||||
void CAN_setup(uint32_t speed);
|
void CAN_setup(uint32_t speed);
|
||||||
|
void CAN_sniffer(uint8_t issniffer);
|
||||||
|
|
||||||
CAN_status CAN_send(CAN_message *message);
|
CAN_status CAN_send(CAN_message *message);
|
||||||
void CAN_proc();
|
void CAN_proc();
|
||||||
|
|||||||
@ -49,7 +49,7 @@ static errcodes mcut(CAN_message *msg){
|
|||||||
// get ADC raw values
|
// get ADC raw values
|
||||||
static errcodes adcraw(CAN_message *msg){
|
static errcodes adcraw(CAN_message *msg){
|
||||||
FIXDL(msg);
|
FIXDL(msg);
|
||||||
register uint8_t no = msg->data[2] & ~SETTER_FLAG;
|
uint8_t no = msg->data[2] & ~SETTER_FLAG;
|
||||||
if(no >= NUMBER_OF_ADC_CHANNELS) return ERR_BADPAR;
|
if(no >= NUMBER_OF_ADC_CHANNELS) return ERR_BADPAR;
|
||||||
*(uint32_t*)&msg->data[4] = getADCval(no);
|
*(uint32_t*)&msg->data[4] = getADCval(no);
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
@ -57,7 +57,7 @@ static errcodes adcraw(CAN_message *msg){
|
|||||||
// get ADC voltage
|
// get ADC voltage
|
||||||
static errcodes adcv(CAN_message *msg){
|
static errcodes adcv(CAN_message *msg){
|
||||||
FIXDL(msg);
|
FIXDL(msg);
|
||||||
register uint8_t no = msg->data[2] & ~SETTER_FLAG;
|
uint8_t no = msg->data[2] & ~SETTER_FLAG;
|
||||||
if(no >= ADC_TSENS) return ERR_BADPAR;
|
if(no >= ADC_TSENS) return ERR_BADPAR;
|
||||||
float v = getADCvoltage(no) * the_conf.adcmul[no] * 100.f;
|
float v = getADCvoltage(no) * the_conf.adcmul[no] * 100.f;
|
||||||
*(uint32_t*)&msg->data[4] = (uint32_t) v; // or float??
|
*(uint32_t*)&msg->data[4] = (uint32_t) v; // or float??
|
||||||
@ -67,7 +67,7 @@ static errcodes adcv(CAN_message *msg){
|
|||||||
static errcodes canspeed(CAN_message *msg){
|
static errcodes canspeed(CAN_message *msg){
|
||||||
if(ISSETTER(msg->data)){
|
if(ISSETTER(msg->data)){
|
||||||
uint32_t spd = *(uint32_t*)&msg->data[4];
|
uint32_t spd = *(uint32_t*)&msg->data[4];
|
||||||
CAN_setup(spd);
|
CAN_reinit(spd);
|
||||||
the_conf.CANspeed = CAN_speed();
|
the_conf.CANspeed = CAN_speed();
|
||||||
}else FIXDL(msg);
|
}else FIXDL(msg);
|
||||||
*(uint32_t*)&msg->data[4] = CAN_speed();
|
*(uint32_t*)&msg->data[4] = CAN_speed();
|
||||||
@ -77,7 +77,7 @@ static errcodes canspeed(CAN_message *msg){
|
|||||||
static errcodes canid(CAN_message *msg){
|
static errcodes canid(CAN_message *msg){
|
||||||
if(ISSETTER(msg->data)){
|
if(ISSETTER(msg->data)){
|
||||||
the_conf.CANID = *(uint32_t*)&msg->data[4];
|
the_conf.CANID = *(uint32_t*)&msg->data[4];
|
||||||
// CAN_setup(0); // setup with new ID
|
CAN_reinit(0); // setup with new ID
|
||||||
}else FIXDL(msg);
|
}else FIXDL(msg);
|
||||||
*(uint32_t*)&msg->data[4] = the_conf.CANID;
|
*(uint32_t*)&msg->data[4] = the_conf.CANID;
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
@ -121,7 +121,7 @@ static const commonfunction funclist[CMD_AMOUNT] = {
|
|||||||
[CMD_MCUTEMP] = {mcut, 0, 0, 0},
|
[CMD_MCUTEMP] = {mcut, 0, 0, 0},
|
||||||
[CMD_ADCRAW] = {adcraw, 0, 0, 3}, // need parno: 0..4
|
[CMD_ADCRAW] = {adcraw, 0, 0, 3}, // need parno: 0..4
|
||||||
[CMD_ADCV] = {adcv, 0, 0, 3}, // need parno: 0..3
|
[CMD_ADCV] = {adcv, 0, 0, 3}, // need parno: 0..3
|
||||||
[CMD_CANSPEED] = {canspeed, 50, 3000, 0},
|
[CMD_CANSPEED] = {canspeed, CAN_MIN_SPEED, CAN_MAX_SPEED, 0},
|
||||||
[CMD_CANID] = {canid, 1, 0x7ff, 0},
|
[CMD_CANID] = {canid, 1, 0x7ff, 0},
|
||||||
[CMD_ADCMUL] = {adcmul, 0, 0, 3}, // at least parno
|
[CMD_ADCMUL] = {adcmul, 0, 0, 3}, // at least parno
|
||||||
[CMD_SAVECONF] = {saveconf, 0, 0, 0},
|
[CMD_SAVECONF] = {saveconf, 0, 0, 0},
|
||||||
@ -148,33 +148,39 @@ void run_can_cmd(CAN_message *msg){
|
|||||||
for(int i = 0; i < msg->length; ++i){
|
for(int i = 0; i < msg->length; ++i){
|
||||||
USB_sendstr(uhex2str(msg->data[i])); USB_putbyte(' ');
|
USB_sendstr(uhex2str(msg->data[i])); USB_putbyte(' ');
|
||||||
}
|
}
|
||||||
for(int i = msg->length-1; i < 8; ++i) msg->data[i] = 0;
|
//for(int i = msg->length-1; i < 8; ++i) msg->data[i] = 0;
|
||||||
newline();
|
newline();
|
||||||
#endif
|
#endif
|
||||||
if(datalen < 2){
|
if(datalen < 2){
|
||||||
FORMERR(data, ERR_WRONGLEN);
|
FORMERR(msg, ERR_WRONGLEN);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
uint16_t idx = *(uint16_t*)data;
|
uint16_t idx = *(uint16_t*)data;
|
||||||
if(idx >= CMD_AMOUNT || funclist[idx].fn == NULL){ // bad command index
|
if(idx >= CMD_AMOUNT || funclist[idx].fn == NULL){ // bad command index
|
||||||
FORMERR(data, ERR_BADCMD);
|
FORMERR(msg, ERR_BADCMD); return;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
// check minimal length (2 or 3)
|
// check minimal length (2 or 3)
|
||||||
if(funclist[idx].datalen > datalen){
|
if(funclist[idx].datalen > datalen){
|
||||||
FORMERR(data, ERR_WRONGLEN); return;
|
FORMERR(msg, ERR_WRONGLEN); return;
|
||||||
}
|
}
|
||||||
if(datalen > 3 && (data[2] & SETTER_FLAG)){
|
if(datalen > 3 && (data[2] & SETTER_FLAG)){
|
||||||
// check setter's length
|
// check setter's length
|
||||||
if(datalen != 8){ FORMERR(data, ERR_WRONGLEN); return; }
|
if(datalen != 8){ FORMERR(msg, ERR_WRONGLEN); return; }
|
||||||
// check setter's values
|
// check setter's values
|
||||||
if(funclist[idx].maxval != funclist[idx].minval){
|
if(funclist[idx].maxval != funclist[idx].minval){
|
||||||
int32_t newval = *(int32_t*)&data[4];
|
int32_t newval = *(int32_t*)&data[4];
|
||||||
if(newval < funclist[idx].minval || newval > funclist[idx].maxval){
|
if(newval < funclist[idx].minval || newval > funclist[idx].maxval){
|
||||||
FORMERR(data, ERR_BADVAL); return;
|
FORMERR(msg, ERR_BADVAL); return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
data[3] = funclist[idx].fn(msg); // set error field as result of function
|
data[3] = funclist[idx].fn(msg); // set error field as result of function
|
||||||
data[2] &= ~SETTER_FLAG; // and clear setter flag
|
data[2] &= ~SETTER_FLAG; // and clear setter flag
|
||||||
|
#ifdef EBUG
|
||||||
|
DBG("Return data: ");
|
||||||
|
for(int i = 0; i < msg->length; ++i){
|
||||||
|
USB_sendstr(uhex2str(msg->data[i])); USB_putbyte(' ');
|
||||||
|
}
|
||||||
|
newline();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@ -35,8 +35,8 @@ static uint32_t maxCnum = 1024 / sizeof(user_conf); // can't use blocksize here
|
|||||||
.userconf_sz = sizeof(user_conf) \
|
.userconf_sz = sizeof(user_conf) \
|
||||||
,.CANspeed = 100000 \
|
,.CANspeed = 100000 \
|
||||||
,.CANID = 0xaa \
|
,.CANID = 0xaa \
|
||||||
,.adcmul[0] = 1.f \
|
,.adcmul[0] = 10.930f \
|
||||||
,.adcmul[1] = 1.f \
|
,.adcmul[1] = 2.028f \
|
||||||
,.adcmul[2] = 1.f \
|
,.adcmul[2] = 1.f \
|
||||||
,.adcmul[3] = 1.f \
|
,.adcmul[3] = 1.f \
|
||||||
}
|
}
|
||||||
@ -145,12 +145,11 @@ static int write2flash(const void *start, const void *wrdata, uint32_t stor_size
|
|||||||
// erase Nth page of flash storage (flash should be prepared!)
|
// erase Nth page of flash storage (flash should be prepared!)
|
||||||
static int erase_pageN(int N){
|
static int erase_pageN(int N){
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
#ifdef EBUG
|
|
||||||
USB_sendstr("Erase block #"); printu(N); newline();
|
|
||||||
#endif
|
|
||||||
FLASH->AR = (uint32_t)Flash_Data + N*FLASH_blocksize;
|
FLASH->AR = (uint32_t)Flash_Data + N*FLASH_blocksize;
|
||||||
FLASH->CR |= FLASH_CR_STRT;
|
FLASH->CR |= FLASH_CR_STRT;
|
||||||
while(FLASH->SR & FLASH_SR_BSY) IWDG->KR = IWDG_REFRESH;
|
uint32_t xx = 100000;
|
||||||
|
while((FLASH->SR & FLASH_SR_BSY) && --xx) IWDG->KR = IWDG_REFRESH;
|
||||||
|
if(xx == 0) return 1;
|
||||||
FLASH->SR = FLASH_SR_EOP;
|
FLASH->SR = FLASH_SR_EOP;
|
||||||
if(FLASH->SR & FLASH_SR_WRPERR){ /* Check Write protection error */
|
if(FLASH->SR & FLASH_SR_WRPERR){ /* Check Write protection error */
|
||||||
ret = 1;
|
ret = 1;
|
||||||
@ -167,8 +166,9 @@ int erase_storage(int npage){
|
|||||||
flsz = FLASH_SIZE * 1024; // size in bytes
|
flsz = FLASH_SIZE * 1024; // size in bytes
|
||||||
flsz -= (uint32_t)Flash_Data - FLASH_BASE;
|
flsz -= (uint32_t)Flash_Data - FLASH_BASE;
|
||||||
}
|
}
|
||||||
|
DBG("total free blocks: "); printu(flsz / FLASH_blocksize);
|
||||||
end = flsz / FLASH_blocksize;
|
end = flsz / FLASH_blocksize;
|
||||||
if(end == 0 || end >= FLASH_SIZE) return 1;
|
if(end == 0) return 1;
|
||||||
if(npage > -1){ // erase only one page
|
if(npage > -1){ // erase only one page
|
||||||
if((uint32_t)npage >= end) return 1;
|
if((uint32_t)npage >= end) return 1;
|
||||||
start = npage;
|
start = npage;
|
||||||
@ -184,12 +184,15 @@ int erase_storage(int npage){
|
|||||||
while(FLASH->SR & FLASH_SR_BSY) IWDG->KR = IWDG_REFRESH;
|
while(FLASH->SR & FLASH_SR_BSY) IWDG->KR = IWDG_REFRESH;
|
||||||
FLASH->SR = FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPERR;
|
FLASH->SR = FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPERR;
|
||||||
FLASH->CR |= FLASH_CR_PER;
|
FLASH->CR |= FLASH_CR_PER;
|
||||||
|
__disable_irq();
|
||||||
for(uint32_t i = start; i < end; ++i){
|
for(uint32_t i = start; i < end; ++i){
|
||||||
|
IWDG->KR = IWDG_REFRESH;
|
||||||
if(erase_pageN(i)){
|
if(erase_pageN(i)){
|
||||||
ret = 1;
|
ret = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
__enable_irq();
|
||||||
FLASH->CR &= ~FLASH_CR_PER;
|
FLASH->CR &= ~FLASH_CR_PER;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -33,8 +33,8 @@
|
|||||||
*/
|
*/
|
||||||
typedef struct __attribute__((packed, aligned(4))){
|
typedef struct __attribute__((packed, aligned(4))){
|
||||||
uint16_t userconf_sz; // "magick number"
|
uint16_t userconf_sz; // "magick number"
|
||||||
uint32_t CANspeed; // default CAN speed
|
|
||||||
uint16_t CANID; // identifier
|
uint16_t CANID; // identifier
|
||||||
|
uint32_t CANspeed; // default CAN speed
|
||||||
float adcmul[ADC_TSENS]; // ADC voltage multipliers
|
float adcmul[ADC_TSENS]; // ADC voltage multipliers
|
||||||
} user_conf;
|
} user_conf;
|
||||||
|
|
||||||
|
|||||||
@ -19,13 +19,41 @@
|
|||||||
#include "adc.h"
|
#include "adc.h"
|
||||||
#include "hardware.h"
|
#include "hardware.h"
|
||||||
#include "usart.h"
|
#include "usart.h"
|
||||||
|
#include "usbhw.h"
|
||||||
|
|
||||||
|
#ifndef EBUG
|
||||||
|
TRUE_INLINE void iwdg_setup(){
|
||||||
|
uint32_t tmout = 16000000;
|
||||||
|
/* Enable the peripheral clock RTC */
|
||||||
|
/* (1) Enable the LSI (40kHz) */
|
||||||
|
/* (2) Wait while it is not ready */
|
||||||
|
RCC->CSR |= RCC_CSR_LSION; /* (1) */
|
||||||
|
while((RCC->CSR & RCC_CSR_LSIRDY) != RCC_CSR_LSIRDY){if(--tmout == 0) break;} /* (2) */
|
||||||
|
/* Configure IWDG */
|
||||||
|
/* (1) Activate IWDG (not needed if done in option bytes) */
|
||||||
|
/* (2) Enable write access to IWDG registers */
|
||||||
|
/* (3) Set prescaler by 64 (1.6ms for each tick) */
|
||||||
|
/* (4) Set reload value to have a rollover each 2s */
|
||||||
|
/* (5) Check if flags are reset */
|
||||||
|
/* (6) Refresh counter */
|
||||||
|
IWDG->KR = IWDG_START; /* (1) */
|
||||||
|
IWDG->KR = IWDG_WRITE_ACCESS; /* (2) */
|
||||||
|
IWDG->PR = IWDG_PR_PR_1; /* (3) */
|
||||||
|
IWDG->RLR = 1250; /* (4) */
|
||||||
|
tmout = 16000000;
|
||||||
|
while(IWDG->SR){if(--tmout == 0) break;} /* (5) */
|
||||||
|
IWDG->KR = IWDG_REFRESH; /* (6) */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static inline void gpio_setup(){
|
static inline void gpio_setup(){
|
||||||
RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN | RCC_AHBENR_GPIOCEN;
|
RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN | RCC_AHBENR_GPIOCEN;
|
||||||
// PWM - AF1 @PA7; USB - alternate function 14 @ pins PA11/PA12; USART1 = AF7 @PA9/10; SWD - AF0 @PA13/14
|
// PWM - AF1 @PA7; USB - alternate function 14 @ pins PA11/PA12; USART1 = AF7 @PA9/10; SWD - AF0 @PA13/14
|
||||||
GPIOA->AFR[0] = AFRf(1, 7);
|
GPIOA->AFR[0] = AFRf(1, 7);
|
||||||
GPIOA->AFR[1] = AFRf(7, 9) | AFRf(7, 10) | AFRf(14, 11) | AFRf(14, 12);
|
GPIOA->AFR[1] = AFRf(7, 9) | AFRf(7, 10) | AFRf(14, 11) | AFRf(14, 12);
|
||||||
// USART1: PA10(Rx), PA9(Tx); USB - PA11, PA12; SWDIO - PA13, PA14;
|
// PA4 - din (PU in), USART1: PA10(Rx, pullup), PA9(Tx); USB - PA11, PA12; SWDIO - PA13, PA14; PA8 & PA15 - PU in
|
||||||
|
GPIOA->PUPDR = (GPIOA->PUPDR & PUPD_CLR(4) & PUPD_CLR(8) & PUPD_CLR(10) & PUPD_CLR(15)) |
|
||||||
|
PUPD_PU(4) | PUPD_PU(8) | PUPD_PU(10) | PUPD_PU(15);
|
||||||
GPIOA->MODER = MODER_AI(0) | MODER_AI(1) | MODER_AI(2) | MODER_AI(3) | MODER_I(4) | MODER_O(5) |
|
GPIOA->MODER = MODER_AI(0) | MODER_AI(1) | MODER_AI(2) | MODER_AI(3) | MODER_I(4) | MODER_O(5) |
|
||||||
MODER_O(6) | MODER_AF(7) | MODER_I(8) | MODER_AF(9) | MODER_AF(10) | MODER_AF(11) |
|
MODER_O(6) | MODER_AF(7) | MODER_I(8) | MODER_AF(9) | MODER_AF(10) | MODER_AF(11) |
|
||||||
MODER_AF(12) | MODER_AF(13) | MODER_AF(14) | MODER_I(15);
|
MODER_AF(12) | MODER_AF(13) | MODER_AF(14) | MODER_I(15);
|
||||||
@ -33,6 +61,8 @@ static inline void gpio_setup(){
|
|||||||
// SPI for SSI: AF5 @PB3, PB4; I2C1: AF4 @PB6, PB7; CAN: AF9 @PB8, PB9; SPI2: AF5 @PB12..PB15
|
// SPI for SSI: AF5 @PB3, PB4; I2C1: AF4 @PB6, PB7; CAN: AF9 @PB8, PB9; SPI2: AF5 @PB12..PB15
|
||||||
GPIOB->AFR[0] = AFRf(5, 3) | AFRf(5, 4) | AFRf(4, 6) | AFRf(4, 7);
|
GPIOB->AFR[0] = AFRf(5, 3) | AFRf(5, 4) | AFRf(4, 6) | AFRf(4, 7);
|
||||||
GPIOB->AFR[1] = AFRf(9, 8) | AFRf(9, 9) | AFRf(5, 12) | AFRf(5, 13) | AFRf(5, 14) | AFRf(5, 15);
|
GPIOB->AFR[1] = AFRf(9, 8) | AFRf(9, 9) | AFRf(5, 12) | AFRf(5, 13) | AFRf(5, 14) | AFRf(5, 15);
|
||||||
|
// PB10,11 - PU in
|
||||||
|
GPIOB->PUPDR = PUPD_PU(10) | PUPD_PU(11);
|
||||||
GPIOB->MODER = MODER_O(0) | MODER_O(1) | MODER_O(2) | MODER_AF(3) | MODER_AF(4) | MODER_AF(6) | MODER_AF(7) |
|
GPIOB->MODER = MODER_O(0) | MODER_O(1) | MODER_O(2) | MODER_AF(3) | MODER_AF(4) | MODER_AF(6) | MODER_AF(7) |
|
||||||
MODER_AF(8) | MODER_AF(9) | MODER_I(10) | MODER_I(11) | MODER_AF(12) | MODER_AF(13) |
|
MODER_AF(8) | MODER_AF(9) | MODER_I(10) | MODER_I(11) | MODER_AF(12) | MODER_AF(13) |
|
||||||
MODER_AF(14) | MODER_AF(15);
|
MODER_AF(14) | MODER_AF(15);
|
||||||
@ -44,5 +74,10 @@ static inline void gpio_setup(){
|
|||||||
void hw_setup(){
|
void hw_setup(){
|
||||||
gpio_setup();
|
gpio_setup();
|
||||||
adc_setup();
|
adc_setup();
|
||||||
|
//usart_setup(); - power it on only for encoders on RS-422
|
||||||
|
USB_setup();
|
||||||
|
#ifndef EBUG
|
||||||
|
iwdg_setup();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -31,6 +31,21 @@ void sys_tick_handler(void){
|
|||||||
++Tms;
|
++Tms;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TRUE_INLINE void showCANmessages(){
|
||||||
|
CAN_message *can_mesg = NULL;
|
||||||
|
while((can_mesg = CAN_messagebuf_pop())){
|
||||||
|
IWDG->KR = IWDG_REFRESH;
|
||||||
|
printu(Tms);
|
||||||
|
USB_sendstr(" #");
|
||||||
|
printuhex(can_mesg->ID);
|
||||||
|
for(int ctr = 0; ctr < can_mesg->length; ++ctr){
|
||||||
|
USB_putbyte(' ');
|
||||||
|
printuhex(can_mesg->data[ctr]);
|
||||||
|
}
|
||||||
|
newline();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int main(void){
|
int main(void){
|
||||||
char inbuff[MAXSTRLEN+1];
|
char inbuff[MAXSTRLEN+1];
|
||||||
USBPU_OFF();
|
USBPU_OFF();
|
||||||
@ -42,26 +57,31 @@ int main(void){
|
|||||||
}
|
}
|
||||||
flashstorage_init();
|
flashstorage_init();
|
||||||
hw_setup();
|
hw_setup();
|
||||||
usart_setup();
|
|
||||||
USB_setup();
|
|
||||||
CAN_setup(the_conf.CANspeed);
|
CAN_setup(the_conf.CANspeed);
|
||||||
USBPU_ON();
|
USBPU_ON();
|
||||||
while(1){
|
while(1){
|
||||||
|
IWDG->KR = IWDG_REFRESH;
|
||||||
CAN_proc();
|
CAN_proc();
|
||||||
if(CAN_get_status() == CAN_FIFO_OVERRUN){
|
CAN_status stat = CAN_get_status();
|
||||||
|
if(stat == CAN_FIFO_OVERRUN){
|
||||||
USB_sendstr("CAN bus fifo overrun occured!\n");
|
USB_sendstr("CAN bus fifo overrun occured!\n");
|
||||||
|
// TODO: buzzer short
|
||||||
|
}else if(stat == CAN_ERR){
|
||||||
|
// TODO: buzzer errors
|
||||||
|
CAN_reinit(0);
|
||||||
}
|
}
|
||||||
if(bufovr){
|
if(cansniffer) showCANmessages();
|
||||||
|
/*if(bufovr){
|
||||||
bufovr = 0;
|
bufovr = 0;
|
||||||
usart_send("bufovr\n");
|
USB_sendstr("error=uartoverflow\n");
|
||||||
}
|
}*/
|
||||||
char *txt = NULL;
|
char *txt = NULL;
|
||||||
if(usart_getline(&txt)){
|
if(usart_getline(&txt)){
|
||||||
const char *ans = run_text_cmd(txt);
|
const char *ans = run_text_cmd(txt);
|
||||||
if(ans) usart_send(ans);
|
if(ans) usart_send(ans);
|
||||||
}
|
}
|
||||||
int l = USB_receivestr(inbuff, MAXSTRLEN);
|
int l = USB_receivestr(inbuff, MAXSTRLEN);
|
||||||
if(l < 0) USB_sendstr("error=overflow\n");
|
if(l < 0) USB_sendstr("error=usboverflow\n");
|
||||||
else if(l){
|
else if(l){
|
||||||
const char *ans = run_text_cmd(inbuff);
|
const char *ans = run_text_cmd(inbuff);
|
||||||
if(ans) USB_sendstr(ans);
|
if(ans) USB_sendstr(ans);
|
||||||
|
|||||||
@ -35,7 +35,7 @@
|
|||||||
#define NO_PARNO (0x1f)
|
#define NO_PARNO (0x1f)
|
||||||
|
|
||||||
// make error for CAN answer
|
// make error for CAN answer
|
||||||
#define FORMERR(data, err) do{data[3] = err;}while(0)
|
#define FORMERR(m, err) do{m->data[3] = err; if(m->length < 4) m->length = 4;}while(0)
|
||||||
|
|
||||||
// error codes for answer message
|
// error codes for answer message
|
||||||
typedef enum{
|
typedef enum{
|
||||||
|
|||||||
@ -19,6 +19,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <strings.h>
|
#include <strings.h>
|
||||||
|
|
||||||
|
#include "can.h"
|
||||||
#include "commonfunctions.h"
|
#include "commonfunctions.h"
|
||||||
#include "flash.h"
|
#include "flash.h"
|
||||||
#include "proto.h"
|
#include "proto.h"
|
||||||
@ -32,10 +33,12 @@
|
|||||||
|
|
||||||
// text-only commans indexes (0 is prohibited)
|
// text-only commans indexes (0 is prohibited)
|
||||||
typedef enum{
|
typedef enum{
|
||||||
TCMD_PROHIBITED
|
TCMD_PROHIBITED, // prohibited
|
||||||
,TCMD_WDTEST
|
TCMD_WDTEST, // test watchdog
|
||||||
,TCMD_DUMPCONF
|
TCMD_DUMPCONF, // dump configuration
|
||||||
,TCMD_AMOUNT
|
TCMD_CANSNIF, // CAN sniffer/normal
|
||||||
|
TCMD_CANSEND, // send CAN message
|
||||||
|
TCMD_AMOUNT
|
||||||
} text_cmd;
|
} text_cmd;
|
||||||
|
|
||||||
|
|
||||||
@ -47,15 +50,17 @@ typedef struct{
|
|||||||
|
|
||||||
// list of all text functions; should be sorted and can be grouped
|
// list of all text functions; should be sorted and can be grouped
|
||||||
static const funcdescr funclist[] = {
|
static const funcdescr funclist[] = {
|
||||||
{"adcmul", CMD_ADCMUL, "get/set ADC multipliers 0..4 (*1000)"},
|
{"adcmul", CMD_ADCMUL, "get/set ADC multipliers 0..3 (*1000)"},
|
||||||
{"adcraw", CMD_ADCRAW, "get raw ADC values of channel 0..4"},
|
{"adcraw", CMD_ADCRAW, "get raw ADC values of channel 0..4"},
|
||||||
{"adcv", CMD_ADCV, "get ADC voltage of channel 0..3 (*100V)"},
|
{"adcv", CMD_ADCV, "get ADC voltage of channel 0..3 (*100V)"},
|
||||||
{"canid", CMD_CANID, "get/set CAN ID"},
|
{"canid", CMD_CANID, "get/set CAN ID"},
|
||||||
|
{"cansnif", -TCMD_CANSNIF, "get/change sniffer state (0 - normal, 1 - sniffer)"},
|
||||||
{"canspeed", CMD_CANSPEED, "get/set CAN speed (bps)"},
|
{"canspeed", CMD_CANSPEED, "get/set CAN speed (bps)"},
|
||||||
{"dumpconf", -TCMD_DUMPCONF, "dump current configuration"},
|
{"dumpconf", -TCMD_DUMPCONF, "dump current configuration"},
|
||||||
{"eraseflash", CMD_ERASESTOR, "erase all flash storage"},
|
{"eraseflash", CMD_ERASESTOR, "erase all flash storage"},
|
||||||
{"mcutemp", CMD_MCUTEMP, "get MCU temperature (*10degrC)"},
|
{"mcutemp", CMD_MCUTEMP, "get MCU temperature (*10degrC)"},
|
||||||
{"reset", CMD_RESET, "reset MCU"},
|
{"reset", CMD_RESET, "reset MCU"},
|
||||||
|
{"s", -TCMD_CANSEND, "send CAN message: ID 0..8 data bytes"},
|
||||||
{"saveconf", CMD_SAVECONF, "save configuration"},
|
{"saveconf", CMD_SAVECONF, "save configuration"},
|
||||||
{"time", CMD_TIME, "get/set time (ms)"},
|
{"time", CMD_TIME, "get/set time (ms)"},
|
||||||
{"wdtest", -TCMD_WDTEST, "test watchdog"},
|
{"wdtest", -TCMD_WDTEST, "test watchdog"},
|
||||||
@ -72,9 +77,10 @@ static errcodes wdtest(const char _U_ *str){
|
|||||||
|
|
||||||
static errcodes dumpconf(const char _U_ *str){
|
static errcodes dumpconf(const char _U_ *str){
|
||||||
#ifdef EBUG
|
#ifdef EBUG
|
||||||
USB_sendstr("flashsize="); printu(FLASH_SIZE); USB_putbyte('*');
|
uint32_t sz = FLASH_SIZE*1024;
|
||||||
printu(FLASH_blocksize); USB_putbyte('='); printu(FLASH_SIZE*FLASH_blocksize);
|
USB_sendstr("flashsize="); printu(sz); USB_putbyte('/');
|
||||||
newline();
|
printu(FLASH_blocksize); USB_putbyte('='); printu(sz/FLASH_blocksize);
|
||||||
|
USB_sendstr(" blocks\n");
|
||||||
#endif
|
#endif
|
||||||
USB_sendstr("userconf_addr="); printuhex((uint32_t)Flash_Data);
|
USB_sendstr("userconf_addr="); printuhex((uint32_t)Flash_Data);
|
||||||
USB_sendstr("\nuserconf_idx="); printi(currentconfidx);
|
USB_sendstr("\nuserconf_idx="); printi(currentconfidx);
|
||||||
@ -91,19 +97,75 @@ static errcodes dumpconf(const char _U_ *str){
|
|||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static errcodes cansnif(const char *str){
|
||||||
|
uint32_t U;
|
||||||
|
if(str){
|
||||||
|
if(*str == '=') str = omit_spaces(str + 1);
|
||||||
|
const char *nxt = getnum(str, &U);
|
||||||
|
if(nxt != str){ // setter
|
||||||
|
CAN_sniffer((uint8_t)U);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
USB_sendstr("cansnif="); USB_putbyte('0' + cansniffer); newline();
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static errcodes cansend(const char *txt){
|
||||||
|
CAN_message canmsg;
|
||||||
|
bzero(&canmsg, sizeof(canmsg));
|
||||||
|
int ctr = -1;
|
||||||
|
canmsg.ID = 0xffff;
|
||||||
|
do{
|
||||||
|
txt = omit_spaces(txt);
|
||||||
|
uint32_t N;
|
||||||
|
const char *n = getnum(txt, &N);
|
||||||
|
if(txt == n) break;
|
||||||
|
txt = n;
|
||||||
|
if(ctr == -1){
|
||||||
|
if(N > 0x7ff){
|
||||||
|
return ERR_BADPAR;
|
||||||
|
}
|
||||||
|
canmsg.ID = (uint16_t)(N&0x7ff);
|
||||||
|
ctr = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(ctr > 7){
|
||||||
|
return ERR_WRONGLEN;
|
||||||
|
}
|
||||||
|
if(N > 0xff){
|
||||||
|
return ERR_BADVAL;
|
||||||
|
}
|
||||||
|
canmsg.data[ctr++] = (uint8_t) N;
|
||||||
|
}while(1);
|
||||||
|
if(canmsg.ID == 0xffff){
|
||||||
|
return ERR_BADPAR;
|
||||||
|
}
|
||||||
|
canmsg.length = (uint8_t) ctr;
|
||||||
|
uint32_t Tstart = Tms;
|
||||||
|
while(Tms - Tstart < SEND_TIMEOUT_MS){
|
||||||
|
if(CAN_OK == CAN_send(&canmsg)){
|
||||||
|
USB_sendstr("OK\n");
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ERR_CANTRUN;
|
||||||
|
}
|
||||||
|
|
||||||
/************ END of all common functions list (for `textfunctions`) ************/
|
/************ END of all common functions list (for `textfunctions`) ************/
|
||||||
|
|
||||||
// in `textfn` arg `str` is rest of input string (spaces-omitted) after command
|
// in `textfn` arg `str` is rest of input string (spaces-omitted) after command
|
||||||
typedef errcodes (*textfn)(const char *str);
|
typedef errcodes (*textfn)(const char *str);
|
||||||
// array of text-only functions
|
// array of text-only functions
|
||||||
static textfn textfunctions[TCMD_AMOUNT] = {
|
static textfn textfunctions[TCMD_AMOUNT] = {
|
||||||
[TCMD_PROHIBITED] = NULL
|
[TCMD_PROHIBITED] = NULL,
|
||||||
,[TCMD_WDTEST] = wdtest
|
[TCMD_WDTEST] = wdtest,
|
||||||
,[TCMD_DUMPCONF] = dumpconf
|
[TCMD_DUMPCONF] = dumpconf,
|
||||||
|
[TCMD_CANSNIF] = cansnif,
|
||||||
|
[TCMD_CANSEND] = cansend,
|
||||||
};
|
};
|
||||||
|
|
||||||
static char stbuf[256], *bptr = NULL;
|
static char stbuf[256], *bptr = stbuf;
|
||||||
static int blen = 0;
|
static int blen = 255;
|
||||||
static void initbuf(){bptr = stbuf; blen = 255; *bptr = 0;}
|
static void initbuf(){bptr = stbuf; blen = 255; *bptr = 0;}
|
||||||
static void bufputchar(char c){
|
static void bufputchar(char c){
|
||||||
if(blen == 0) return;
|
if(blen == 0) return;
|
||||||
@ -111,6 +173,7 @@ static void bufputchar(char c){
|
|||||||
*bptr = 0;
|
*bptr = 0;
|
||||||
}
|
}
|
||||||
static void add2buf(const char *s){
|
static void add2buf(const char *s){
|
||||||
|
if(!s) return;
|
||||||
while(blen && *s){
|
while(blen && *s){
|
||||||
*bptr++ = *s++;
|
*bptr++ = *s++;
|
||||||
--blen;
|
--blen;
|
||||||
@ -121,7 +184,7 @@ static void add2buf(const char *s){
|
|||||||
static void printhelp(){
|
static void printhelp(){
|
||||||
const funcdescr *c = funclist;
|
const funcdescr *c = funclist;
|
||||||
USB_sendstr("https://github.com/eddyem/stm32samples/tree/master/F3:F303/CANbus4BTA build#" BUILD_NUMBER " @ " BUILD_DATE "\n");
|
USB_sendstr("https://github.com/eddyem/stm32samples/tree/master/F3:F303/CANbus4BTA build#" BUILD_NUMBER " @ " BUILD_DATE "\n");
|
||||||
USB_sendstr("commands format: parameter[number][=setter]");
|
USB_sendstr("commands format: parameter[number][=setter]\n");
|
||||||
USB_sendstr("parameter [CAN idx] - help\n");
|
USB_sendstr("parameter [CAN idx] - help\n");
|
||||||
USB_sendstr("--------------------------\n");
|
USB_sendstr("--------------------------\n");
|
||||||
while(c->help){
|
while(c->help){
|
||||||
@ -168,9 +231,10 @@ static void errtext(errcodes e){
|
|||||||
* WARNING! Sending help works only for USB!
|
* WARNING! Sending help works only for USB!
|
||||||
*/
|
*/
|
||||||
char *run_text_cmd(const char *str){
|
char *run_text_cmd(const char *str){
|
||||||
|
if(!str || !*str) goto ret;
|
||||||
char cmd[MAXCMDLEN + 1];
|
char cmd[MAXCMDLEN + 1];
|
||||||
errcodes ecode = ERR_BADCMD;
|
errcodes ecode = ERR_BADCMD;
|
||||||
if(!str || !*str) goto ret;
|
initbuf();
|
||||||
int idx = CMD_AMOUNT;
|
int idx = CMD_AMOUNT;
|
||||||
const funcdescr *c = funclist;
|
const funcdescr *c = funclist;
|
||||||
int l = 0;
|
int l = 0;
|
||||||
@ -185,13 +249,13 @@ char *run_text_cmd(const char *str){
|
|||||||
idx = c->idx;
|
idx = c->idx;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
++c;
|
||||||
}
|
}
|
||||||
if(idx == CMD_AMOUNT){ // didn't found
|
if(idx == CMD_AMOUNT){ // didn't found
|
||||||
// send help over USB
|
// send help over USB
|
||||||
printhelp();
|
printhelp();
|
||||||
goto ret;
|
goto ret;
|
||||||
}
|
}
|
||||||
initbuf();
|
|
||||||
str = omit_spaces(ptr);
|
str = omit_spaces(ptr);
|
||||||
if(idx < 0){ // text-only function
|
if(idx < 0){ // text-only function
|
||||||
ecode = textfunctions[-idx](str);
|
ecode = textfunctions[-idx](str);
|
||||||
@ -216,6 +280,7 @@ char *run_text_cmd(const char *str){
|
|||||||
}
|
}
|
||||||
str = omit_spaces(str);
|
str = omit_spaces(str);
|
||||||
if(*str == '='){ // setter
|
if(*str == '='){ // setter
|
||||||
|
++str;
|
||||||
ptr = getint(str, ((int32_t*)&data[4]));
|
ptr = getint(str, ((int32_t*)&data[4]));
|
||||||
if(str == ptr){
|
if(str == ptr){
|
||||||
ecode = ERR_BADVAL;
|
ecode = ERR_BADVAL;
|
||||||
@ -234,7 +299,7 @@ ret:
|
|||||||
if(msg.length != 8){
|
if(msg.length != 8){
|
||||||
return "OK\n"; // non setters/getters will just print "OK" if all OK
|
return "OK\n"; // non setters/getters will just print "OK" if all OK
|
||||||
}else{
|
}else{
|
||||||
add2buf(funclist[idx].cmd);
|
add2buf(cmd);
|
||||||
data[2] &= ~SETTER_FLAG;
|
data[2] &= ~SETTER_FLAG;
|
||||||
if(data[2] != NO_PARNO) add2buf(u2str(data[2]));
|
if(data[2] != NO_PARNO) add2buf(u2str(data[2]));
|
||||||
bufputchar('=');
|
bufputchar('=');
|
||||||
|
|||||||
@ -25,11 +25,11 @@
|
|||||||
static volatile uint8_t usbbuff[USB_TXBUFSZ]; // temporary buffer for sending data
|
static volatile uint8_t usbbuff[USB_TXBUFSZ]; // temporary buffer for sending data
|
||||||
// ring buffers for incoming and outgoing data
|
// ring buffers for incoming and outgoing data
|
||||||
static uint8_t obuf[RBOUTSZ], ibuf[RBINSZ];
|
static uint8_t obuf[RBOUTSZ], ibuf[RBINSZ];
|
||||||
volatile ringbuffer rbout = {.data = obuf, .length = RBOUTSZ, .head = 0, .tail = 0};
|
static volatile ringbuffer rbout = {.data = obuf, .length = RBOUTSZ, .head = 0, .tail = 0};
|
||||||
volatile ringbuffer rbin = {.data = ibuf, .length = RBINSZ, .head = 0, .tail = 0};
|
volatile ringbuffer rbin = {.data = ibuf, .length = RBINSZ, .head = 0, .tail = 0}; // used in usblib.c
|
||||||
// transmission is succesfull
|
// transmission is succesfull
|
||||||
volatile uint8_t bufisempty = 1;
|
static volatile uint8_t bufisempty = 1;
|
||||||
volatile uint8_t bufovrfl = 0;
|
volatile uint8_t bufovrfl = 0; // used in usblib.c
|
||||||
|
|
||||||
void send_next(){
|
void send_next(){
|
||||||
if(bufisempty) return;
|
if(bufisempty) return;
|
||||||
|
|||||||
@ -37,8 +37,8 @@
|
|||||||
#define DBG(str)
|
#define DBG(str)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern volatile ringbuffer rbout, rbin;
|
extern volatile ringbuffer /* rbout, */ rbin;
|
||||||
extern volatile uint8_t bufisempty, bufovrfl;
|
extern volatile uint8_t /* bufisempty, */ bufovrfl;
|
||||||
|
|
||||||
void send_next();
|
void send_next();
|
||||||
int USB_sendall();
|
int USB_sendall();
|
||||||
@ -48,10 +48,8 @@ int USB_sendstr(const char *string);
|
|||||||
int USB_receive(uint8_t *buf, int len);
|
int USB_receive(uint8_t *buf, int len);
|
||||||
int USB_receivestr(char *buf, int len);
|
int USB_receivestr(char *buf, int len);
|
||||||
|
|
||||||
#ifdef EBUG
|
|
||||||
#include "strfunc.h"
|
#include "strfunc.h"
|
||||||
#define printu(x) do{USB_sendstr(u2str(x));}while(0)
|
#define printu(x) do{USB_sendstr(u2str(x));}while(0)
|
||||||
#define printi(x) do{USB_sendstr(i2str(x));}while(0)
|
#define printi(x) do{USB_sendstr(i2str(x));}while(0)
|
||||||
#define printuhex(x) do{USB_sendstr(uhex2str(x));}while(0)
|
#define printuhex(x) do{USB_sendstr(uhex2str(x));}while(0)
|
||||||
#define printf(x) do{USB_sendstr(float2str(x, 2));}while(0)
|
#define printf(x) do{USB_sendstr(float2str(x, 2));}while(0)
|
||||||
#endif
|
|
||||||
|
|||||||
@ -1,2 +1,2 @@
|
|||||||
#define BUILD_NUMBER "22"
|
#define BUILD_NUMBER "56"
|
||||||
#define BUILD_DATE "2024-01-07"
|
#define BUILD_DATE "2024-01-08"
|
||||||
|
|||||||
@ -47,7 +47,7 @@ LIB_DIR := $(INC_DIR)/ld
|
|||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# C flags
|
# C flags
|
||||||
CFLAGS += -O2 -D__thumb2__=1 -MD
|
CFLAGS += -D__thumb2__=1 -MD
|
||||||
CFLAGS += -Wall -Wextra -Wshadow -Wdouble-promotion
|
CFLAGS += -Wall -Wextra -Wshadow -Wdouble-promotion
|
||||||
CFLAGS += -fshort-enums -ffunction-sections -fdata-sections
|
CFLAGS += -fshort-enums -ffunction-sections -fdata-sections
|
||||||
#CFLAGS += -fno-common -fno-stack-protector
|
#CFLAGS += -fno-common -fno-stack-protector
|
||||||
@ -91,12 +91,12 @@ endif
|
|||||||
BUILDDATE := $(shell date +%Y-%m-%d)
|
BUILDDATE := $(shell date +%Y-%m-%d)
|
||||||
|
|
||||||
# release: add LTO
|
# release: add LTO
|
||||||
release: CFLAGS += -flto
|
release: CFLAGS += -O2 -flto
|
||||||
release: LDFLAGS += -flto
|
release: LDFLAGS += -flto
|
||||||
release: $(TARGFILE) bin list size
|
release: $(TARGFILE) bin list size
|
||||||
|
|
||||||
#debug: add debug flags
|
#debug: add debug flags
|
||||||
debug: CFLAGS += -DEBUG -Werror -g3 -gdwarf-2
|
debug: CFLAGS += -O0 -DEBUG -Werror -g3 -gdwarf-2
|
||||||
debug: TARGET := DEBUG
|
debug: TARGET := DEBUG
|
||||||
debug: $(TARGFILE) bin list size
|
debug: $(TARGFILE) bin list size
|
||||||
|
|
||||||
@ -123,6 +123,7 @@ $(VERSION_FILE): *.[ch]
|
|||||||
@[ -f $(VERSION_FILE) ] || echo -e "#define BUILD_NUMBER \"0\"\n#define BUILD_DATE \"none\"" > $(VERSION_FILE)
|
@[ -f $(VERSION_FILE) ] || echo -e "#define BUILD_NUMBER \"0\"\n#define BUILD_DATE \"none\"" > $(VERSION_FILE)
|
||||||
@echo " Generate version: $(NEXTVER) for date $(BUILDDATE)"
|
@echo " Generate version: $(NEXTVER) for date $(BUILDDATE)"
|
||||||
@sed -i "s/#define BUILD_NUMBER.*/#define BUILD_NUMBER \"$(NEXTVER)\"/" $(VERSION_FILE)
|
@sed -i "s/#define BUILD_NUMBER.*/#define BUILD_NUMBER \"$(NEXTVER)\"/" $(VERSION_FILE)
|
||||||
|
@sed -i "s/#define BUILDNO.*/#define BUILDNO $(NEXTVER)/" $(VERSION_FILE)
|
||||||
@sed -i "s/#define BUILD_DATE.*/#define BUILD_DATE \"$(BUILDDATE)\"/" $(VERSION_FILE)
|
@sed -i "s/#define BUILD_DATE.*/#define BUILD_DATE \"$(BUILDDATE)\"/" $(VERSION_FILE)
|
||||||
|
|
||||||
$(OBJDIR)/proto.o: proto.c $(VERSION_FILE)
|
$(OBJDIR)/proto.o: proto.c $(VERSION_FILE)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user