mirror of
https://github.com/eddyem/stm32samples.git
synced 2026-02-28 03:44:30 +03:00
ringbuffer and device detection to USB-CAN-relay
This commit is contained in:
@@ -22,6 +22,7 @@
|
||||
#include "hardware.h"
|
||||
#include "proto.h"
|
||||
#include "usb.h"
|
||||
#include "version.inc"
|
||||
|
||||
#include <string.h> // strlen
|
||||
|
||||
@@ -30,30 +31,6 @@ extern volatile uint8_t canerror;
|
||||
uint8_t ShowMsgs = 0;
|
||||
uint16_t Ignore_IDs[IGN_SIZE];
|
||||
uint8_t IgnSz = 0;
|
||||
static char buff[BUFSZ+1], *bptr = buff;
|
||||
static uint8_t blen = 0;
|
||||
|
||||
void sendbuf(){
|
||||
IWDG->KR = IWDG_REFRESH;
|
||||
if(blen == 0) return;
|
||||
*bptr = 0;
|
||||
USB_sendstr(buff);
|
||||
bptr = buff;
|
||||
blen = 0;
|
||||
}
|
||||
|
||||
void bufputchar(char ch){
|
||||
if(blen > BUFSZ-1){
|
||||
sendbuf();
|
||||
}
|
||||
*bptr++ = ch;
|
||||
++blen;
|
||||
}
|
||||
|
||||
void addtobuf(const char *txt){
|
||||
IWDG->KR = IWDG_REFRESH;
|
||||
while(*txt) bufputchar(*txt++);
|
||||
}
|
||||
|
||||
char *omit_spaces(const char *buf){
|
||||
while(*buf){
|
||||
@@ -148,7 +125,7 @@ static CAN_message *parseCANmsg(char *txt){
|
||||
txt = n;
|
||||
if(ctr == -1){
|
||||
if(N > 0x7ff){
|
||||
SEND("ID should be 11-bit number!\n");
|
||||
USND("ID should be 11-bit number!");
|
||||
return NULL;
|
||||
}
|
||||
canmsg.ID = (uint16_t)(N&0x7ff);
|
||||
@@ -157,21 +134,20 @@ static CAN_message *parseCANmsg(char *txt){
|
||||
continue;
|
||||
}
|
||||
if(ctr > 7){
|
||||
SEND("ONLY 8 data bytes allowed!\n");
|
||||
USND("ONLY 8 data bytes allowed!");
|
||||
return NULL;
|
||||
}
|
||||
if(N > 0xff){
|
||||
SEND("Every data portion is a byte!\n");
|
||||
USND("Every data portion is a byte!");
|
||||
return NULL;
|
||||
}
|
||||
canmsg.data[ctr++] = (uint8_t)(N&0xff);
|
||||
}while(1);
|
||||
if(canmsg.ID == 0xffff){
|
||||
SEND("NO ID given, send nothing!\n");
|
||||
USND("NO ID given, send nothing!");
|
||||
return NULL;
|
||||
}
|
||||
SEND("Message parsed OK\n");
|
||||
sendbuf();
|
||||
USND("Message parsed OK");
|
||||
canmsg.length = (uint8_t) ctr;
|
||||
return &canmsg;
|
||||
}
|
||||
@@ -191,55 +167,55 @@ TRUE_INLINE void CANini(char *txt){
|
||||
uint32_t N;
|
||||
char *n = getnum(txt, &N);
|
||||
if(txt == n){
|
||||
SEND("No speed given");
|
||||
USND("No speed given");
|
||||
return;
|
||||
}
|
||||
if(N < 50){
|
||||
SEND("Lowest speed is 50kbps");
|
||||
USND("Lowest speed is 50kbps");
|
||||
return;
|
||||
}else if(N > 3000){
|
||||
SEND("Highest speed is 3000kbps");
|
||||
USND("Highest speed is 3000kbps");
|
||||
return;
|
||||
}
|
||||
CAN_reinit((uint16_t)N);
|
||||
SEND("Reinit CAN bus with speed ");
|
||||
printu(N); SEND("kbps");
|
||||
USB_sendstr("Reinit CAN bus with speed ");
|
||||
printu(N); USND("kbps");
|
||||
}
|
||||
|
||||
TRUE_INLINE void addIGN(char *txt){
|
||||
if(IgnSz == IGN_SIZE){
|
||||
MSG("Ignore buffer is full");
|
||||
DBG("Ignore buffer is full");
|
||||
return;
|
||||
}
|
||||
txt = omit_spaces(txt);
|
||||
uint32_t N;
|
||||
char *n = getnum(txt, &N);
|
||||
if(txt == n){
|
||||
SEND("No ID given");
|
||||
USND("No ID given");
|
||||
return;
|
||||
}
|
||||
if(N == CANID){
|
||||
SEND("You can't ignore self ID!");
|
||||
USND("You can't ignore self ID!");
|
||||
return;
|
||||
}
|
||||
if(N > 0x7ff){
|
||||
SEND("ID should be 11-bit number!");
|
||||
USND("ID should be 11-bit number!");
|
||||
return;
|
||||
}
|
||||
Ignore_IDs[IgnSz++] = (uint16_t)(N & 0x7ff);
|
||||
SEND("Added ID "); printu(N);
|
||||
SEND("\nIgn buffer size: "); printu(IgnSz);
|
||||
USB_sendstr("Added ID "); printu(N);
|
||||
USB_sendstr("\nIgn buffer size: "); printu(IgnSz); newline();
|
||||
}
|
||||
|
||||
TRUE_INLINE void print_ign_buf(){
|
||||
if(IgnSz == 0){
|
||||
SEND("Ignore buffer is empty");
|
||||
USND("Ignore buffer is empty");
|
||||
return;
|
||||
}
|
||||
SEND("Ignored IDs:\n");
|
||||
USND("Ignored IDs:");
|
||||
for(int i = 0; i < IgnSz; ++i){
|
||||
printu(i);
|
||||
SEND(": ");
|
||||
USB_sendstr(": ");
|
||||
printuhex(Ignore_IDs[i]);
|
||||
newline();
|
||||
}
|
||||
@@ -267,29 +243,29 @@ TRUE_INLINE void list_filters(){
|
||||
uint32_t fa = CAN->FA1R, ctr = 0, mask = 1;
|
||||
while(fa){
|
||||
if(fa & 1){
|
||||
SEND("Filter "); printu(ctr); SEND(", FIFO");
|
||||
if(CAN->FFA1R & mask) SEND("1");
|
||||
else SEND("0");
|
||||
SEND(" in ");
|
||||
USB_sendstr("Filter "); printu(ctr); USB_sendstr(", FIFO");
|
||||
if(CAN->FFA1R & mask) USB_putbyte('1');
|
||||
else USB_putbyte('0');
|
||||
USB_sendstr(" in ");
|
||||
if(CAN->FM1R & mask){ // up to 4 filters in LIST mode
|
||||
SEND("LIST mode, IDs: ");
|
||||
USB_sendstr("LIST mode, IDs: ");
|
||||
printID(CAN->sFilterRegister[ctr].FR1 & 0xffff);
|
||||
SEND(" ");
|
||||
USB_sendstr(" ");
|
||||
printID(CAN->sFilterRegister[ctr].FR1 >> 16);
|
||||
SEND(" ");
|
||||
USB_sendstr(" ");
|
||||
printID(CAN->sFilterRegister[ctr].FR2 & 0xffff);
|
||||
SEND(" ");
|
||||
USB_sendstr(" ");
|
||||
printID(CAN->sFilterRegister[ctr].FR2 >> 16);
|
||||
}else{ // up to 2 filters in MASK mode
|
||||
SEND("MASK mode: ");
|
||||
USB_sendstr("MASK mode: ");
|
||||
if(!(CAN->sFilterRegister[ctr].FR1&0x1f)){
|
||||
SEND("ID="); printID(CAN->sFilterRegister[ctr].FR1 & 0xffff);
|
||||
SEND(", MASK="); printID(CAN->sFilterRegister[ctr].FR1 >> 16);
|
||||
SEND(" ");
|
||||
USB_sendstr("ID="); printID(CAN->sFilterRegister[ctr].FR1 & 0xffff);
|
||||
USB_sendstr(", MASK="); printID(CAN->sFilterRegister[ctr].FR1 >> 16);
|
||||
USB_sendstr(" ");
|
||||
}
|
||||
if(!(CAN->sFilterRegister[ctr].FR2&0x1f)){
|
||||
SEND("ID="); printID(CAN->sFilterRegister[ctr].FR2 & 0xffff);
|
||||
SEND(", MASK="); printID(CAN->sFilterRegister[ctr].FR2 >> 16);
|
||||
USB_sendstr("ID="); printID(CAN->sFilterRegister[ctr].FR2 & 0xffff);
|
||||
USB_sendstr(", MASK="); printID(CAN->sFilterRegister[ctr].FR2 >> 16);
|
||||
}
|
||||
}
|
||||
newline();
|
||||
@@ -298,7 +274,6 @@ TRUE_INLINE void list_filters(){
|
||||
++ctr;
|
||||
mask <<= 1;
|
||||
}
|
||||
sendbuf();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -315,18 +290,19 @@ static void add_filter(char *str){
|
||||
str = omit_spaces(str);
|
||||
char *n = getnum(str, &N);
|
||||
if(n == str){
|
||||
SEND("No bank# given");
|
||||
USND("No bank# given");
|
||||
return;
|
||||
}
|
||||
if(N == 0 || N > STM32F0FBANKNO-1){
|
||||
SEND("0 (reserved for self) < bank# < 28 (max bank# is 27)!!!");
|
||||
USND("0 (reserved for self) < bank# < 28 (max bank# is 27)!!!");
|
||||
return;
|
||||
}
|
||||
uint8_t bankno = (uint8_t)N;
|
||||
str = omit_spaces(n);
|
||||
if(!*str){ // deactivate filter
|
||||
SEND("Deactivate filters in bank ");
|
||||
USB_sendstr("Deactivate filters in bank ");
|
||||
printu(bankno);
|
||||
newline();
|
||||
CAN->FMR = CAN_FMR_FINIT;
|
||||
CAN->FA1R &= ~(1<<bankno);
|
||||
CAN->FMR &=~ CAN_FMR_FINIT;
|
||||
@@ -335,7 +311,7 @@ static void add_filter(char *str){
|
||||
uint8_t fifono = 0;
|
||||
if(*str == '1') fifono = 1;
|
||||
else if(*str != '0'){
|
||||
SEND("FIFO# is 0 or 1");
|
||||
USND("FIFO# is 0 or 1");
|
||||
return;
|
||||
}
|
||||
str = omit_spaces(str + 1);
|
||||
@@ -343,7 +319,7 @@ static void add_filter(char *str){
|
||||
uint8_t mode = 0; // ID
|
||||
if(c == 'M' || c == 'm') mode = 1;
|
||||
else if(c != 'I' && c != 'i'){
|
||||
SEND("mode is 'M/m' for MASK and 'I/i' for IDLIST");
|
||||
USND("mode is 'M/m' for MASK and 'I/i' for IDLIST");
|
||||
return;
|
||||
}
|
||||
str = omit_spaces(str + 1);
|
||||
@@ -356,11 +332,11 @@ static void add_filter(char *str){
|
||||
str = omit_spaces(n);
|
||||
}
|
||||
if(nfilt == 0){
|
||||
SEND("You should add at least one filter!");
|
||||
USND("You should add at least one filter!");
|
||||
return;
|
||||
}
|
||||
if(mode && (nfilt&1)){
|
||||
SEND("In MASK mode you should point pairs of ID/MASK");
|
||||
USND("In MASK mode you should point pairs of ID/MASK");
|
||||
return;
|
||||
}
|
||||
CAN->FMR = CAN_FMR_FINIT;
|
||||
@@ -389,8 +365,8 @@ static void add_filter(char *str){
|
||||
CAN->sFilterRegister[bankno].FR1 = (F1 & 0xffff0000) | (filters[0] << 5);
|
||||
}
|
||||
CAN->FMR &=~ CAN_FMR_FINIT;
|
||||
SEND("Added filter with ");
|
||||
printu(nfilt); SEND(" parameters");
|
||||
USB_sendstr("Added filter with ");
|
||||
printu(nfilt); USND(" parameters");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -402,13 +378,13 @@ static void ledsOp(const char *str, uint8_t state){
|
||||
uint32_t N;
|
||||
char *x = getnum(str, &N);
|
||||
if(!x || x == str || N > LEDSNO - 1){
|
||||
SEND("Wrong LED number\n");
|
||||
USND("Wrong LED number\n");
|
||||
return;
|
||||
}
|
||||
if(state) LED_on(N);
|
||||
else LED_off(N);
|
||||
SEND("LED"); printu(N); SEND(" is ");
|
||||
if(state) SEND("on"); else SEND("off");
|
||||
USB_sendstr("LED"); printu(N); USB_sendstr(" is ");
|
||||
if(state) USND("on"); else USND("off");
|
||||
}
|
||||
|
||||
// print current buttons state
|
||||
@@ -418,9 +394,9 @@ TRUE_INLINE void getBtnState(){
|
||||
uint32_t T;
|
||||
keyevent e = keystate(i, &T);
|
||||
if(e != EVT_NONE){
|
||||
SEND("The key "); printu(i);
|
||||
SEND(" is "); addtobuf(states[e]); SEND(" at ");
|
||||
printu(T); NL();
|
||||
USB_sendstr("The key "); printu(i);
|
||||
USB_sendstr(" is "); USB_sendstr(states[e]); USB_sendstr(" at ");
|
||||
printu(T); newline();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -428,13 +404,12 @@ TRUE_INLINE void getBtnState(){
|
||||
TRUE_INLINE void getPWM(){
|
||||
volatile uint32_t *reg = &TIM1->CCR1;
|
||||
for(int n = 0; n < 3; ++n){
|
||||
SEND("PWM");
|
||||
bufputchar('0' + n);
|
||||
bufputchar('=');
|
||||
USB_sendstr("PWM");
|
||||
USB_putbyte('0' + n);
|
||||
USB_putbyte('=');
|
||||
printu(*reg++);
|
||||
bufputchar('\n');
|
||||
newline();
|
||||
}
|
||||
sendbuf();
|
||||
}
|
||||
|
||||
TRUE_INLINE void changePWM(char *str){
|
||||
@@ -442,34 +417,33 @@ TRUE_INLINE void changePWM(char *str){
|
||||
uint32_t N, pwm;
|
||||
char *nxt = getnum(str, &N);
|
||||
if(nxt == str || N > 2){
|
||||
SEND("Nch = 0..2");
|
||||
USND("Nch = 0..2");
|
||||
return;
|
||||
}
|
||||
str = omit_spaces(nxt);
|
||||
nxt = getnum(str, &pwm);
|
||||
if(nxt == str || pwm > 255){
|
||||
SEND("PWM should be from 0 to 255");
|
||||
USND("PWM should be from 0 to 255");
|
||||
return;
|
||||
}
|
||||
volatile uint32_t *reg = &TIM1->CCR1;
|
||||
reg[N] = pwm;
|
||||
SEND("OK, changed");
|
||||
USND("OK, changed");
|
||||
}
|
||||
|
||||
TRUE_INLINE void printADC(){ // show all 4 channels ADC
|
||||
for(int i = 0; i < NUMBER_OF_ADC_CHANNELS; ++i){
|
||||
SEND("ADC"); bufputchar('0' + i); bufputchar('=');
|
||||
printu(getADCval(i)); bufputchar('\n');
|
||||
USB_sendstr("ADC"); USB_putbyte('0' + i); USB_putbyte('=');
|
||||
printu(getADCval(i)); newline();
|
||||
}
|
||||
sendbuf();
|
||||
}
|
||||
|
||||
TRUE_INLINE void printVT(){ // show T and Vdd
|
||||
int32_t t = getMCUtemp();
|
||||
SEND("T=");
|
||||
if(t < 0){ bufputchar('-'); t = -t; }
|
||||
printu(t); SEND("/10degC\nVDD=");
|
||||
printu(getVdd()); SEND("/100V");
|
||||
USB_sendstr("T=");
|
||||
if(t < 0){ USB_putbyte('-'); t = -t; }
|
||||
printu(t); USB_sendstr("/10degC\nVDD=");
|
||||
printu(getVdd()); USND("/100V");
|
||||
}
|
||||
|
||||
// set or check relay(N) state
|
||||
@@ -481,10 +455,36 @@ TRUE_INLINE void relayX(uint8_t N, const char *txt){
|
||||
if(b && b != txt && sr < 2){
|
||||
if(sr) Relay_ON(N); else Relay_OFF(N);
|
||||
}
|
||||
SEND("Relay"); bufputchar('0'+N); bufputchar('=');
|
||||
bufputchar('0' + Relay_chk(N));
|
||||
USB_sendstr("Relay"); USB_putbyte('0'+N); USB_putbyte('=');
|
||||
USB_putbyte('0' + Relay_chk(N)); newline();
|
||||
}
|
||||
|
||||
static const char *helpmsg =
|
||||
"https://github.com/eddyem/stm32samples/tree/master/F0-nolib/usbcan_relay build#" BUILD_NUMBER " @ " BUILD_DATE "\n"
|
||||
"'0' - turn relay0 on(1) or off(0)\n"
|
||||
"'1' - turn relay1 on(1) or off(0)\n"
|
||||
"'a' - add ID to ignore list (max 10 IDs)\n"
|
||||
"'A' - get ADC values @ all 4 channels\n"
|
||||
"'b' - get buttons' state\n"
|
||||
"'C' - reinit CAN with given baudrate\n"
|
||||
"'d' - delete ignore list\n"
|
||||
"'D' - activate DFU mode\n"
|
||||
"'f' - add/delete filter, format: bank# FIFO# mode(M/I) num0 [num1 [num2 [num3]]]\n"
|
||||
"'F' - send/clear flood message: F ID byte0 ... byteN\n"
|
||||
"'I' - read CAN ID\n"
|
||||
"'l' - list all active filters\n"
|
||||
"'m' - get MCU temp & Vdd\n"
|
||||
"'o' - turn nth LED OFF\n"
|
||||
"'O' - turn nth LED ON\n"
|
||||
"'p' - print ignore buffer\n"
|
||||
"'P' - pause/resume in packets displaying\n"
|
||||
"'R' - software reset\n"
|
||||
"'s/S' - send data over CAN: s ID byte0 .. byteN\n"
|
||||
"'T' - get time from start (ms)\n"
|
||||
"'w' - get PWM settings\n"
|
||||
"'W' - set PWM @nth channel (ch: 0..2, PWM: 0..255)\n"
|
||||
;
|
||||
|
||||
/**
|
||||
* @brief cmd_parser - command parsing
|
||||
* @param txt - buffer with commands & data
|
||||
@@ -550,15 +550,13 @@ void cmd_parser(char *txt){
|
||||
case 'd':
|
||||
IgnSz = 0;
|
||||
break;
|
||||
#ifdef EBUG
|
||||
case 'D':
|
||||
SEND("Go into DFU mode\n");
|
||||
sendbuf();
|
||||
USND("Go into DFU mode\n");
|
||||
USB_sendall();
|
||||
Jump2Boot();
|
||||
break;
|
||||
#endif
|
||||
case 'I':
|
||||
SEND("CAN ID: "); printuhex(CANID);
|
||||
USB_sendstr("CAN ID: "); printuhex(CANID);
|
||||
break;
|
||||
case 'l':
|
||||
list_filters();
|
||||
@@ -571,17 +569,17 @@ void cmd_parser(char *txt){
|
||||
break;
|
||||
case 'P':
|
||||
ShowMsgs = !ShowMsgs;
|
||||
if(ShowMsgs) SEND("Resume\n");
|
||||
else SEND("Pause\n");
|
||||
if(ShowMsgs) USND("Resume");
|
||||
else USND("Pause");
|
||||
break;
|
||||
case 'R':
|
||||
SEND("Soft reset\n");
|
||||
sendbuf();
|
||||
USND("Soft reset");
|
||||
USB_sendall();
|
||||
pause_ms(5); // a little pause to transmit data
|
||||
NVIC_SystemReset();
|
||||
break;
|
||||
case 'T':
|
||||
SEND("Time (ms): ");
|
||||
USB_sendstr("Time (ms): ");
|
||||
printu(Tms);
|
||||
break;
|
||||
case 'w':
|
||||
@@ -589,37 +587,11 @@ void cmd_parser(char *txt){
|
||||
return;
|
||||
break;
|
||||
default: // help
|
||||
SEND(
|
||||
"'0' - turn relay0 on(1) or off(0)\n"
|
||||
"'1' - turn relay1 on(1) or off(0)\n"
|
||||
"'a' - add ID to ignore list (max 10 IDs)\n"
|
||||
"'A' - get ADC values @ all 4 channels\n"
|
||||
"'b' - get buttons' state\n"
|
||||
"'C' - reinit CAN with given baudrate\n"
|
||||
"'d' - delete ignore list\n"
|
||||
#ifdef EBUG
|
||||
"'D' - activate DFU mode\n"
|
||||
#endif
|
||||
"'f' - add/delete filter, format: bank# FIFO# mode(M/I) num0 [num1 [num2 [num3]]]\n"
|
||||
"'F' - send/clear flood message: F ID byte0 ... byteN\n"
|
||||
"'I' - read CAN ID\n"
|
||||
"'l' - list all active filters\n"
|
||||
"'m' - get MCU temp & Vdd\n"
|
||||
"'o' - turn nth LED OFF\n"
|
||||
"'O' - turn nth LED ON\n"
|
||||
"'p' - print ignore buffer\n"
|
||||
"'P' - pause/resume in packets displaying\n"
|
||||
"'R' - software reset\n"
|
||||
"'s/S' - send data over CAN: s ID byte0 .. byteN\n"
|
||||
"'T' - get time from start (ms)\n"
|
||||
"'w' - get PWM settings\n"
|
||||
"'W' - set PWM @nth channel (ch: 0..2, PWM: 0..255)\n"
|
||||
);
|
||||
USND(helpmsg);
|
||||
break;
|
||||
}
|
||||
eof:
|
||||
newline();
|
||||
sendbuf();
|
||||
}
|
||||
|
||||
// print 32bit unsigned int
|
||||
@@ -634,12 +606,12 @@ void printu(uint32_t val){
|
||||
val /= 10;
|
||||
}
|
||||
}
|
||||
addtobuf(bufptr);
|
||||
USB_sendstr(bufptr);
|
||||
}
|
||||
|
||||
// print 32bit unsigned int as hex
|
||||
void printuhex(uint32_t val){
|
||||
addtobuf("0x");
|
||||
USB_sendstr("0x");
|
||||
uint8_t *ptr = (uint8_t*)&val + 3;
|
||||
int8_t i, j, z=1;
|
||||
for(i = 0; i < 4; ++i, --ptr){
|
||||
@@ -650,8 +622,8 @@ void printuhex(uint32_t val){
|
||||
else z = 0;
|
||||
for(j = 1; j > -1; --j){
|
||||
uint8_t half = (*ptr >> (4*j)) & 0x0f;
|
||||
if(half < 10) bufputchar(half + '0');
|
||||
else bufputchar(half - 10 + 'a');
|
||||
if(half < 10) USB_putbyte(half + '0');
|
||||
else USB_putbyte(half - 10 + 'a');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user