mirror of
https://github.com/eddyem/stm32samples.git
synced 2025-12-06 10:45:11 +03:00
fixed some bugs in canUART for F103, add some features to usbcan_ringbuffer for F0
This commit is contained in:
parent
cfff079dba
commit
59fb731725
@ -8,6 +8,7 @@ FAMILY ?= F0
|
|||||||
MCU ?= F042x6
|
MCU ?= F042x6
|
||||||
# change this linking script depending on particular MCU model,
|
# change this linking script depending on particular MCU model,
|
||||||
LDSCRIPT ?= stm32f042x6.ld
|
LDSCRIPT ?= stm32f042x6.ld
|
||||||
|
#DEFS = -DEBUG
|
||||||
|
|
||||||
# autoincremental version & build date
|
# autoincremental version & build date
|
||||||
VERSION_FILE = version.inc
|
VERSION_FILE = version.inc
|
||||||
|
|||||||
@ -21,17 +21,14 @@
|
|||||||
#include "proto.h"
|
#include "proto.h"
|
||||||
#include "usb.h"
|
#include "usb.h"
|
||||||
|
|
||||||
#include <string.h> // memcpy
|
|
||||||
|
|
||||||
// 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
|
||||||
static int8_t first_nonfree_idx = -1; // index of first data cell
|
static int8_t first_nonfree_idx = -1; // index of first data cell
|
||||||
static uint16_t oldspeed = 100; // speed of last init
|
static uint16_t oldspeed = 100; // speed of last init
|
||||||
|
uint32_t floodT = FLOOD_PERIOD_MS-1; // flood period in ms
|
||||||
|
|
||||||
#ifdef EBUG
|
|
||||||
static uint32_t last_err_code = 0;
|
static uint32_t last_err_code = 0;
|
||||||
#endif
|
|
||||||
static CAN_status can_status = CAN_STOP;
|
static CAN_status can_status = CAN_STOP;
|
||||||
|
|
||||||
static void can_process_fifo(uint8_t fifo_num);
|
static void can_process_fifo(uint8_t fifo_num);
|
||||||
@ -65,7 +62,7 @@ static int CAN_messagebuf_push(CAN_message *msg){
|
|||||||
return 1; // no free space
|
return 1; // no free space
|
||||||
}
|
}
|
||||||
if(first_nonfree_idx < 0) first_nonfree_idx = 0; // first message in empty buffer
|
if(first_nonfree_idx < 0) first_nonfree_idx = 0; // first message in empty buffer
|
||||||
memcpy(&messages[first_free_idx++], msg, sizeof(CAN_message));
|
messages[first_free_idx++] = *msg;
|
||||||
// need to roll?
|
// need to roll?
|
||||||
if(first_free_idx == CAN_INMESSAGE_SIZE) first_free_idx = 0;
|
if(first_free_idx == CAN_INMESSAGE_SIZE) first_free_idx = 0;
|
||||||
return 0;
|
return 0;
|
||||||
@ -146,9 +143,7 @@ void CAN_setup(uint16_t speed){
|
|||||||
/* (13) Set error interrupts enable */
|
/* (13) Set error interrupts enable */
|
||||||
CAN->MCR |= CAN_MCR_INRQ; /* (1) */
|
CAN->MCR |= CAN_MCR_INRQ; /* (1) */
|
||||||
while((CAN->MSR & CAN_MSR_INAK)!=CAN_MSR_INAK) /* (2) */
|
while((CAN->MSR & CAN_MSR_INAK)!=CAN_MSR_INAK) /* (2) */
|
||||||
{
|
|
||||||
if(--tmout == 0) break;
|
if(--tmout == 0) break;
|
||||||
}
|
|
||||||
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 */
|
||||||
|
|
||||||
@ -174,6 +169,36 @@ void CAN_setup(uint16_t speed){
|
|||||||
can_status = CAN_READY;
|
can_status = CAN_READY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void printCANerr(){
|
||||||
|
if(!last_err_code) last_err_code = CAN->ESR;
|
||||||
|
if(!last_err_code){
|
||||||
|
USB_sendstr("No errors\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
USB_sendstr("Receive error counter: ");
|
||||||
|
printu((last_err_code & CAN_ESR_REC)>>24);
|
||||||
|
USB_sendstr("\nTransmit error counter: ");
|
||||||
|
printu((last_err_code & CAN_ESR_TEC)>>16);
|
||||||
|
USB_sendstr("\nLast error code: ");
|
||||||
|
int lec = (last_err_code & CAN_ESR_LEC) >> 4;
|
||||||
|
const char *errmsg = "No";
|
||||||
|
switch(lec){
|
||||||
|
case 1: errmsg = "Stuff"; break;
|
||||||
|
case 2: errmsg = "Form"; break;
|
||||||
|
case 3: errmsg = "Ack"; break;
|
||||||
|
case 4: errmsg = "Bit recessive"; break;
|
||||||
|
case 5: errmsg = "Bit dominant"; break;
|
||||||
|
case 6: errmsg = "CRC"; break;
|
||||||
|
case 7: errmsg = "(set by software)"; break;
|
||||||
|
}
|
||||||
|
USB_sendstr(errmsg); USB_sendstr(" error\n");
|
||||||
|
if(last_err_code & CAN_ESR_BOFF) USB_sendstr("Bus off ");
|
||||||
|
if(last_err_code & CAN_ESR_EPVF) USB_sendstr("Passive error limit ");
|
||||||
|
if(last_err_code & CAN_ESR_EWGF) USB_sendstr("Error counter limit");
|
||||||
|
last_err_code = 0;
|
||||||
|
USB_putbyte('\n');
|
||||||
|
}
|
||||||
|
|
||||||
void can_proc(){
|
void can_proc(){
|
||||||
#ifdef EBUG
|
#ifdef EBUG
|
||||||
if(last_err_code){
|
if(last_err_code){
|
||||||
@ -193,27 +218,7 @@ 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("\nToo much errors, restarting CAN!\n");
|
||||||
USB_sendstr("Receive error counter: ");
|
printCANerr();
|
||||||
printu((CAN->ESR & CAN_ESR_REC)>>24);
|
|
||||||
USB_sendstr("\nTransmit error counter: ");
|
|
||||||
printu((CAN->ESR & CAN_ESR_TEC)>>16);
|
|
||||||
USB_sendstr("\nLast error code: ");
|
|
||||||
int lec = (CAN->ESR & CAN_ESR_LEC) >> 4;
|
|
||||||
const char *errmsg = "No";
|
|
||||||
switch(lec){
|
|
||||||
case 1: errmsg = "Stuff"; break;
|
|
||||||
case 2: errmsg = "Form"; break;
|
|
||||||
case 3: errmsg = "Ack"; break;
|
|
||||||
case 4: errmsg = "Bit recessive"; break;
|
|
||||||
case 5: errmsg = "Bit dominant"; break;
|
|
||||||
case 6: errmsg = "CRC"; break;
|
|
||||||
case 7: errmsg = "(set by software)"; break;
|
|
||||||
}
|
|
||||||
USB_sendstr(errmsg); USB_sendstr(" error\n");
|
|
||||||
if(CAN->ESR & CAN_ESR_BOFF) USB_sendstr("Bus off ");
|
|
||||||
if(CAN->ESR & CAN_ESR_EPVF) USB_sendstr("Passive error limit ");
|
|
||||||
if(CAN->ESR & CAN_ESR_EWGF) USB_sendstr("Error counter limit");
|
|
||||||
USB_putbyte('\n');
|
|
||||||
// request abort for all mailboxes
|
// request abort for all mailboxes
|
||||||
CAN->TSR |= CAN_TSR_ABRQ0 | CAN_TSR_ABRQ1 | CAN_TSR_ABRQ2;
|
CAN->TSR |= CAN_TSR_ABRQ0 | CAN_TSR_ABRQ1 | CAN_TSR_ABRQ2;
|
||||||
// reset CAN bus
|
// reset CAN bus
|
||||||
@ -222,7 +227,7 @@ void can_proc(){
|
|||||||
CAN_setup(0);
|
CAN_setup(0);
|
||||||
}
|
}
|
||||||
static uint32_t lastFloodTime = 0;
|
static uint32_t lastFloodTime = 0;
|
||||||
if(flood_msg && (Tms - lastFloodTime) > (FLOOD_PERIOD_MS-1)){ // flood every ~5ms
|
if(flood_msg && (Tms - lastFloodTime) > (floodT)){ // flood every ~5ms
|
||||||
lastFloodTime = Tms;
|
lastFloodTime = Tms;
|
||||||
can_send(flood_msg->data, flood_msg->length, flood_msg->ID);
|
can_send(flood_msg->data, flood_msg->length, flood_msg->ID);
|
||||||
}
|
}
|
||||||
@ -285,7 +290,21 @@ CAN_status can_send(uint8_t *msg, uint8_t len, uint16_t target_id){
|
|||||||
void set_flood(CAN_message *msg){
|
void set_flood(CAN_message *msg){
|
||||||
if(!msg) flood_msg = NULL;
|
if(!msg) flood_msg = NULL;
|
||||||
else{
|
else{
|
||||||
memcpy(&loc_flood_msg, msg, sizeof(CAN_message));
|
#ifdef EBUG
|
||||||
|
USB_sendstr("flood msg: #");
|
||||||
|
printuhex(msg->ID);
|
||||||
|
for(uint8_t ctr = 0; ctr < msg->length; ++ctr){
|
||||||
|
USB_putbyte(' ');
|
||||||
|
printuhex(msg->data[ctr]);
|
||||||
|
}
|
||||||
|
USB_putbyte('\n');
|
||||||
|
#endif
|
||||||
|
// I meet strange problems with `loc_flood_msg = *msg` and system memcpy, so..
|
||||||
|
loc_flood_msg.ID = msg->ID;
|
||||||
|
loc_flood_msg.length = msg->length;
|
||||||
|
*((uint32_t*)loc_flood_msg.data) = *((uint32_t*)msg->data);
|
||||||
|
if(loc_flood_msg.length > 4)
|
||||||
|
*((uint32_t*)&loc_flood_msg.data[4]) = *((uint32_t*)&msg->data[4]);
|
||||||
flood_msg = &loc_flood_msg;
|
flood_msg = &loc_flood_msg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -364,3 +383,4 @@ void cec_can_isr(){
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "hardware.h"
|
#include <stdint.h>
|
||||||
|
|
||||||
// amount of filter banks in STM32F0
|
// amount of filter banks in STM32F0
|
||||||
#define STM32F0FBANKNO 28
|
#define STM32F0FBANKNO 28
|
||||||
@ -28,6 +28,8 @@
|
|||||||
// incoming message buffer size
|
// incoming message buffer size
|
||||||
#define CAN_INMESSAGE_SIZE (8)
|
#define CAN_INMESSAGE_SIZE (8)
|
||||||
|
|
||||||
|
extern uint32_t floodT;
|
||||||
|
|
||||||
// CAN message
|
// CAN message
|
||||||
typedef struct{
|
typedef struct{
|
||||||
uint8_t data[8]; // up to 8 bytes of data
|
uint8_t data[8]; // up to 8 bytes of data
|
||||||
@ -50,6 +52,7 @@ void CAN_setup(uint16_t speed);
|
|||||||
|
|
||||||
CAN_status can_send(uint8_t *msg, uint8_t len, uint16_t target_id);
|
CAN_status can_send(uint8_t *msg, uint8_t len, uint16_t target_id);
|
||||||
void can_proc();
|
void can_proc();
|
||||||
|
void printCANerr();
|
||||||
|
|
||||||
CAN_message *CAN_messagebuf_pop();
|
CAN_message *CAN_messagebuf_pop();
|
||||||
|
|
||||||
|
|||||||
@ -68,7 +68,7 @@ int main(void){
|
|||||||
USB_sendstr(" #");
|
USB_sendstr(" #");
|
||||||
printuhex(can_mesg->ID);
|
printuhex(can_mesg->ID);
|
||||||
for(uint8_t ctr = 0; ctr < len; ++ctr){
|
for(uint8_t ctr = 0; ctr < len; ++ctr){
|
||||||
USB_putbyte('\n');
|
USB_putbyte(' ');
|
||||||
printuhex(can_mesg->data[ctr]);
|
printuhex(can_mesg->data[ctr]);
|
||||||
}
|
}
|
||||||
USB_putbyte('\n');
|
USB_putbyte('\n');
|
||||||
|
|||||||
@ -137,6 +137,7 @@ static char *getbin(const char *buf, uint32_t *N){
|
|||||||
char *getnum(const char *txt, uint32_t *N){
|
char *getnum(const char *txt, uint32_t *N){
|
||||||
char *nxt = NULL;
|
char *nxt = NULL;
|
||||||
char *s = omit_spaces(txt);
|
char *s = omit_spaces(txt);
|
||||||
|
if(!*s) return (char*)txt;
|
||||||
if(*s == '0'){ // hex, oct or 0
|
if(*s == '0'){ // hex, oct or 0
|
||||||
if(s[1] == 'x' || s[1] == 'X'){ // hex
|
if(s[1] == 'x' || s[1] == 'X'){ // hex
|
||||||
nxt = gethex(s+2, N);
|
nxt = gethex(s+2, N);
|
||||||
@ -166,7 +167,6 @@ static CAN_message *parseCANmsg(char *txt){
|
|||||||
int ctr = -1;
|
int ctr = -1;
|
||||||
canmsg.ID = 0xffff;
|
canmsg.ID = 0xffff;
|
||||||
do{
|
do{
|
||||||
txt = omit_spaces(txt);
|
|
||||||
n = getnum(txt, &N);
|
n = getnum(txt, &N);
|
||||||
if(txt == n) break;
|
if(txt == n) break;
|
||||||
txt = n;
|
txt = n;
|
||||||
@ -200,16 +200,19 @@ static CAN_message *parseCANmsg(char *txt){
|
|||||||
|
|
||||||
// USB_sendstr command, format: ID (hex/bin/dec) data bytes (up to 8 bytes, space-delimeted)
|
// USB_sendstr command, format: ID (hex/bin/dec) data bytes (up to 8 bytes, space-delimeted)
|
||||||
TRUE_INLINE void USB_sendstrCANcommand(char *txt){
|
TRUE_INLINE void USB_sendstrCANcommand(char *txt){
|
||||||
|
if(CAN->MSR & CAN_MSR_INAK){
|
||||||
|
USB_sendstr("CAN bus is off, try to restart it\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
CAN_message *msg = parseCANmsg(txt);
|
CAN_message *msg = parseCANmsg(txt);
|
||||||
if(!msg) return;
|
if(!msg) return;
|
||||||
uint32_t N = 1000000;
|
uint32_t N = 5;
|
||||||
while(CAN_BUSY == can_send(msg->data, msg->length, msg->ID)){
|
while(CAN_BUSY == can_send(msg->data, msg->length, msg->ID)){
|
||||||
if(--N == 0) break;
|
if(--N == 0) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TRUE_INLINE void CANini(char *txt){
|
TRUE_INLINE void CANini(char *txt){
|
||||||
txt = omit_spaces(txt);
|
|
||||||
uint32_t N;
|
uint32_t N;
|
||||||
char *n = getnum(txt, &N);
|
char *n = getnum(txt, &N);
|
||||||
if(txt == n){
|
if(txt == n){
|
||||||
@ -318,6 +321,17 @@ TRUE_INLINE void list_filters(){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TRUE_INLINE void setfloodt(char *s){
|
||||||
|
uint32_t N;
|
||||||
|
s = omit_spaces(s);
|
||||||
|
char *n = getnum(s, &N);
|
||||||
|
if(s == n || N == 0){
|
||||||
|
USB_sendstr("t="); printu(floodT); USB_putbyte('\n');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
floodT = N - 1;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief add_filter - add/modify filter
|
* @brief add_filter - add/modify filter
|
||||||
* @param str - string in format "bank# FIFO# mode num0 .. num3"
|
* @param str - string in format "bank# FIFO# mode num0 .. num3"
|
||||||
@ -414,10 +428,12 @@ const char *helpmsg =
|
|||||||
"https://github.com/eddyem/stm32samples/tree/master/F0-nolib/usbcan_ringbuffer build#" BUILD_NUMBER " @ " BUILD_DATE "\n"
|
"https://github.com/eddyem/stm32samples/tree/master/F0-nolib/usbcan_ringbuffer build#" BUILD_NUMBER " @ " BUILD_DATE "\n"
|
||||||
"'a' - add ID to ignore list (max 10 IDs)\n"
|
"'a' - add ID to ignore list (max 10 IDs)\n"
|
||||||
"'b' - reinit CAN with given baudrate\n"
|
"'b' - reinit CAN with given baudrate\n"
|
||||||
|
"'c' - get CAN status\n"
|
||||||
"'d' - delete ignore list\n"
|
"'d' - delete ignore list\n"
|
||||||
"'D' - activate DFU mode\n"
|
"'D' - activate DFU mode\n"
|
||||||
|
"'e' - get CAN errcodes\n"
|
||||||
"'f' - add/delete filter, format: bank# FIFO# mode(M/I) num0 [num1 [num2 [num3]]]\n"
|
"'f' - add/delete filter, format: bank# FIFO# mode(M/I) num0 [num1 [num2 [num3]]]\n"
|
||||||
"'F' - USB_sendstr/clear flood message: F ID byte0 ... byteN\n"
|
"'F' - send/clear flood message: F ID byte0 ... byteN\n"
|
||||||
"'I' - reinit CAN\n"
|
"'I' - reinit CAN\n"
|
||||||
"'l' - list all active filters\n"
|
"'l' - list all active filters\n"
|
||||||
"'o' - turn LEDs OFF\n"
|
"'o' - turn LEDs OFF\n"
|
||||||
@ -425,10 +441,22 @@ const char *helpmsg =
|
|||||||
"'p' - print ignore buffer\n"
|
"'p' - print ignore buffer\n"
|
||||||
"'P' - pause/resume in packets displaying\n"
|
"'P' - pause/resume in packets displaying\n"
|
||||||
"'R' - software reset\n"
|
"'R' - software reset\n"
|
||||||
"'s/S' - USB_sendstr data over CAN: s ID byte0 .. byteN\n"
|
"'s/S' - send data over CAN: s ID byte0 .. byteN\n"
|
||||||
|
"'t' - change flood period (>=1ms)\n"
|
||||||
"'T' - get time from start (ms)\n"
|
"'T' - get time from start (ms)\n"
|
||||||
;
|
;
|
||||||
|
|
||||||
|
TRUE_INLINE void getcanstat(){
|
||||||
|
USB_sendstr("CAN_MSR=");
|
||||||
|
printuhex(CAN->MSR);
|
||||||
|
USB_sendstr("\nCAN_TSR=");
|
||||||
|
printuhex(CAN->TSR);
|
||||||
|
USB_sendstr("\nCAN_RF0R=");
|
||||||
|
printuhex(CAN->RF0R);
|
||||||
|
USB_sendstr("\nCAN_RF1R=");
|
||||||
|
printuhex(CAN->RF1R);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief cmd_parser - command parsing
|
* @brief cmd_parser - command parsing
|
||||||
* @param txt - buffer with commands & data
|
* @param txt - buffer with commands & data
|
||||||
@ -436,37 +464,48 @@ const char *helpmsg =
|
|||||||
*/
|
*/
|
||||||
void cmd_parser(char *txt){
|
void cmd_parser(char *txt){
|
||||||
char _1st = txt[0];
|
char _1st = txt[0];
|
||||||
|
++txt;
|
||||||
/*
|
/*
|
||||||
* parse long commands here
|
* parse long commands here
|
||||||
*/
|
*/
|
||||||
switch(_1st){
|
switch(_1st){
|
||||||
case 'a':
|
case 'a':
|
||||||
addIGN(txt + 1);
|
addIGN(txt);
|
||||||
goto eof;
|
goto eof;
|
||||||
break;
|
break;
|
||||||
case 'b':
|
case 'b':
|
||||||
CANini(txt + 1);
|
CANini(txt);
|
||||||
goto eof;
|
goto eof;
|
||||||
break;
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
add_filter(txt + 1);
|
add_filter(txt);
|
||||||
goto eof;
|
goto eof;
|
||||||
break;
|
break;
|
||||||
case 'F':
|
case 'F':
|
||||||
set_flood(parseCANmsg(txt + 1));
|
set_flood(parseCANmsg(txt));
|
||||||
goto eof;
|
goto eof;
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
case 'S':
|
case 'S':
|
||||||
USB_sendstrCANcommand(txt + 1);
|
USB_sendstrCANcommand(txt);
|
||||||
|
goto eof;
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
setfloodt(txt);
|
||||||
goto eof;
|
goto eof;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(txt[1] != '\n') *txt = '?'; // help for wrong message length
|
if(*txt != '\n') _1st = '?'; // help for wrong message length
|
||||||
switch(_1st){
|
switch(_1st){
|
||||||
|
case 'c':
|
||||||
|
getcanstat();
|
||||||
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
IgnSz = 0;
|
IgnSz = 0;
|
||||||
break;
|
break;
|
||||||
|
case 'e':
|
||||||
|
printCANerr();
|
||||||
|
break;
|
||||||
case 'D':
|
case 'D':
|
||||||
USB_sendstr("Go into DFU mode\n");
|
USB_sendstr("Go into DFU mode\n");
|
||||||
USB_sendall();
|
USB_sendall();
|
||||||
|
|||||||
Binary file not shown.
1
F0:F030,F042,F072/usbcan_ringbuffer/usbcanrb.cflags
Normal file
1
F0:F030,F042,F072/usbcan_ringbuffer/usbcanrb.cflags
Normal file
@ -0,0 +1 @@
|
|||||||
|
-std=c17
|
||||||
5
F0:F030,F042,F072/usbcan_ringbuffer/usbcanrb.config
Normal file
5
F0:F030,F042,F072/usbcan_ringbuffer/usbcanrb.config
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
// Add predefined macros for your project here. For example:
|
||||||
|
// #define THE_ANSWER 42
|
||||||
|
#define EBUG
|
||||||
|
#define STM32F0
|
||||||
|
#define STM32F042x6
|
||||||
1
F0:F030,F042,F072/usbcan_ringbuffer/usbcanrb.creator
Normal file
1
F0:F030,F042,F072/usbcan_ringbuffer/usbcanrb.creator
Normal file
@ -0,0 +1 @@
|
|||||||
|
[General]
|
||||||
160
F0:F030,F042,F072/usbcan_ringbuffer/usbcanrb.creator.user
Normal file
160
F0:F030,F042,F072/usbcan_ringbuffer/usbcanrb.creator.user
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE QtCreatorProject>
|
||||||
|
<!-- Written by QtCreator 6.0.0, 2022-10-28T17:08:49. -->
|
||||||
|
<qtcreator>
|
||||||
|
<data>
|
||||||
|
<variable>EnvironmentId</variable>
|
||||||
|
<value type="QByteArray">{cf63021e-ef53-49b0-b03b-2f2570cdf3b6}</value>
|
||||||
|
</data>
|
||||||
|
<data>
|
||||||
|
<variable>ProjectExplorer.Project.ActiveTarget</variable>
|
||||||
|
<value type="int">0</value>
|
||||||
|
</data>
|
||||||
|
<data>
|
||||||
|
<variable>ProjectExplorer.Project.EditorSettings</variable>
|
||||||
|
<valuemap type="QVariantMap">
|
||||||
|
<value type="bool" key="EditorConfiguration.AutoIndent">true</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
|
||||||
|
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
|
||||||
|
<value type="QString" key="language">Cpp</value>
|
||||||
|
<valuemap type="QVariantMap" key="value">
|
||||||
|
<value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
|
||||||
|
</valuemap>
|
||||||
|
</valuemap>
|
||||||
|
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
|
||||||
|
<value type="QString" key="language">QmlJS</value>
|
||||||
|
<valuemap type="QVariantMap" key="value">
|
||||||
|
<value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
|
||||||
|
</valuemap>
|
||||||
|
</valuemap>
|
||||||
|
<value type="int" key="EditorConfiguration.CodeStyle.Count">2</value>
|
||||||
|
<value type="QByteArray" key="EditorConfiguration.Codec">KOI8-R</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
|
||||||
|
<value type="int" key="EditorConfiguration.IndentSize">4</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
|
||||||
|
<value type="int" key="EditorConfiguration.MarginColumn">80</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.MouseHiding">true</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
|
||||||
|
<value type="int" key="EditorConfiguration.PaddingMode">1</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.PreferSingleLineComments">false</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">false</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.ShowMargin">false</value>
|
||||||
|
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">1</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
|
||||||
|
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
|
||||||
|
<value type="int" key="EditorConfiguration.TabSize">8</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.UseGlobal">true</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.UseIndenter">false</value>
|
||||||
|
<value type="int" key="EditorConfiguration.Utf8BomBehavior">2</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
|
||||||
|
<value type="QString" key="EditorConfiguration.ignoreFileTypes">*.md, *.MD, Makefile</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.inEntireDocument">true</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.skipTrailingWhitespace">true</value>
|
||||||
|
</valuemap>
|
||||||
|
</data>
|
||||||
|
<data>
|
||||||
|
<variable>ProjectExplorer.Project.PluginSettings</variable>
|
||||||
|
<valuemap type="QVariantMap">
|
||||||
|
<valuemap type="QVariantMap" key="ClangTools">
|
||||||
|
<value type="bool" key="ClangTools.AnalyzeOpenFiles">true</value>
|
||||||
|
<value type="bool" key="ClangTools.BuildBeforeAnalysis">true</value>
|
||||||
|
<value type="QString" key="ClangTools.DiagnosticConfig">Builtin.DefaultTidyAndClazy</value>
|
||||||
|
<value type="int" key="ClangTools.ParallelJobs">4</value>
|
||||||
|
<valuelist type="QVariantList" key="ClangTools.SelectedDirs"/>
|
||||||
|
<valuelist type="QVariantList" key="ClangTools.SelectedFiles"/>
|
||||||
|
<valuelist type="QVariantList" key="ClangTools.SuppressedDiagnostics"/>
|
||||||
|
<value type="bool" key="ClangTools.UseGlobalSettings">true</value>
|
||||||
|
</valuemap>
|
||||||
|
</valuemap>
|
||||||
|
</data>
|
||||||
|
<data>
|
||||||
|
<variable>ProjectExplorer.Project.Target.0</variable>
|
||||||
|
<valuemap type="QVariantMap">
|
||||||
|
<value type="QString" key="DeviceType">Desktop</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{91347f2c-5221-46a7-80b1-0a054ca02f79}</value>
|
||||||
|
<value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
|
||||||
|
<value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
|
||||||
|
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
|
||||||
|
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/eddy/Docs/SAO/ELECTRONICS/STM32/F0-srcs/usbcan_ringbuffer</value>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||||
|
<valuelist type="QVariantList" key="GenericProjectManager.GenericMakeStep.BuildTargets">
|
||||||
|
<value type="QString">all</value>
|
||||||
|
</valuelist>
|
||||||
|
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">GenericProjectManager.GenericMakeStep</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Сборка</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Сборка</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||||
|
</valuemap>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||||
|
<valuelist type="QVariantList" key="GenericProjectManager.GenericMakeStep.BuildTargets">
|
||||||
|
<value type="QString">clean</value>
|
||||||
|
</valuelist>
|
||||||
|
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">GenericProjectManager.GenericMakeStep</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Очистка</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Очистка</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||||
|
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||||
|
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
|
||||||
|
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
|
||||||
|
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">По умолчанию</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">GenericProjectManager.GenericBuildConfiguration</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">1</value>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||||
|
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Развёртывание</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Развёртывание</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
|
||||||
|
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
|
||||||
|
<valuelist type="QVariantList" key="CustomOutputParsers"/>
|
||||||
|
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||||
|
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.CustomExecutableRunConfiguration</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey"></value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
|
||||||
|
</valuemap>
|
||||||
|
</data>
|
||||||
|
<data>
|
||||||
|
<variable>ProjectExplorer.Project.TargetCount</variable>
|
||||||
|
<value type="int">1</value>
|
||||||
|
</data>
|
||||||
|
<data>
|
||||||
|
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>
|
||||||
|
<value type="int">22</value>
|
||||||
|
</data>
|
||||||
|
<data>
|
||||||
|
<variable>Version</variable>
|
||||||
|
<value type="int">22</value>
|
||||||
|
</data>
|
||||||
|
</qtcreator>
|
||||||
1
F0:F030,F042,F072/usbcan_ringbuffer/usbcanrb.cxxflags
Normal file
1
F0:F030,F042,F072/usbcan_ringbuffer/usbcanrb.cxxflags
Normal file
@ -0,0 +1 @@
|
|||||||
|
-std=c++17
|
||||||
16
F0:F030,F042,F072/usbcan_ringbuffer/usbcanrb.files
Normal file
16
F0:F030,F042,F072/usbcan_ringbuffer/usbcanrb.files
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
can.c
|
||||||
|
can.h
|
||||||
|
hardware.c
|
||||||
|
hardware.h
|
||||||
|
main.c
|
||||||
|
proto.c
|
||||||
|
proto.h
|
||||||
|
ringbuffer.c
|
||||||
|
ringbuffer.h
|
||||||
|
usb.c
|
||||||
|
usb.h
|
||||||
|
usb_defs.h
|
||||||
|
usb_lib.c
|
||||||
|
usb_lib.h
|
||||||
|
usbhw.c
|
||||||
|
usbhw.h
|
||||||
6
F0:F030,F042,F072/usbcan_ringbuffer/usbcanrb.includes
Normal file
6
F0:F030,F042,F072/usbcan_ringbuffer/usbcanrb.includes
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
.
|
||||||
|
../inc
|
||||||
|
../inc/Fx
|
||||||
|
../inc/cm
|
||||||
|
../inc/ld
|
||||||
|
../inc/startup
|
||||||
@ -1,2 +1,2 @@
|
|||||||
#define BUILD_NUMBER "1"
|
#define BUILD_NUMBER "23"
|
||||||
#define BUILD_DATE "2022-10-28"
|
#define BUILD_DATE "2022-12-05"
|
||||||
|
|||||||
Binary file not shown.
@ -157,6 +157,6 @@ dfuboot: $(BIN)
|
|||||||
openocd:
|
openocd:
|
||||||
openocd -f openocd.cfg
|
openocd -f openocd.cfg
|
||||||
dbg:
|
dbg:
|
||||||
arm-none-eabi-gdb $(ELF) -ex 'target remote localhost:3333' -ex 'monitor reset halt'
|
arm-none-eabi-gdb $(ELF) -ex 'target extended-remote localhost:3333' -ex 'monitor reset halt'
|
||||||
|
|
||||||
.PHONY: size clean flash boot dfuboot openocd dbg
|
.PHONY: size clean flash boot dfuboot openocd dbg
|
||||||
|
|||||||
@ -1,2 +1,4 @@
|
|||||||
CAN bus (PB8/PB9) <> UART1 (PA9/PA10)
|
CAN bus (PB8/PB9) <> UART1 (PA9/PA10)
|
||||||
The same thing as canusb for STM32F0x2
|
The same thing as canusb for STM32F0x2
|
||||||
|
|
||||||
|
Baudrate - 921600
|
||||||
|
|||||||
@ -30,6 +30,7 @@ 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
|
||||||
static int8_t first_nonfree_idx = -1; // index of first data cell
|
static int8_t first_nonfree_idx = -1; // index of first data cell
|
||||||
static uint16_t oldspeed = 100; // speed of last init
|
static uint16_t oldspeed = 100; // speed of last init
|
||||||
|
uint32_t floodT = FLOOD_PERIOD_MS-1; // flood period in ms
|
||||||
|
|
||||||
static uint32_t last_err_code = 0;
|
static uint32_t last_err_code = 0;
|
||||||
static CAN_status can_status = CAN_STOP;
|
static CAN_status can_status = CAN_STOP;
|
||||||
@ -229,7 +230,7 @@ void can_proc(){
|
|||||||
CAN_setup(0);
|
CAN_setup(0);
|
||||||
}
|
}
|
||||||
static uint32_t lastFloodTime = 0;
|
static uint32_t lastFloodTime = 0;
|
||||||
if(flood_msg && (Tms - lastFloodTime) > (FLOOD_PERIOD_MS-1)){ // flood every ~5ms
|
if(flood_msg && (Tms - lastFloodTime) > (floodT)){ // flood every ~5ms
|
||||||
lastFloodTime = Tms;
|
lastFloodTime = Tms;
|
||||||
can_send(flood_msg->data, flood_msg->length, flood_msg->ID);
|
can_send(flood_msg->data, flood_msg->length, flood_msg->ID);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
// incoming message buffer size
|
// incoming message buffer size
|
||||||
#define CAN_INMESSAGE_SIZE (8)
|
#define CAN_INMESSAGE_SIZE (8)
|
||||||
|
extern uint32_t floodT;
|
||||||
|
|
||||||
// CAN message
|
// CAN message
|
||||||
typedef struct{
|
typedef struct{
|
||||||
|
|||||||
@ -30,9 +30,7 @@ void sys_tick_handler(void){
|
|||||||
|
|
||||||
int main(void){
|
int main(void){
|
||||||
uint32_t lastT = 0;
|
uint32_t lastT = 0;
|
||||||
#ifdef BLUEPILL
|
|
||||||
uint32_t bplastT = 0;
|
uint32_t bplastT = 0;
|
||||||
#endif
|
|
||||||
CAN_message *can_mesg;
|
CAN_message *can_mesg;
|
||||||
StartHSE();
|
StartHSE();
|
||||||
SysTick_Config(72000);
|
SysTick_Config(72000);
|
||||||
@ -50,12 +48,13 @@ int main(void){
|
|||||||
LED_off(LED0);
|
LED_off(LED0);
|
||||||
lastT = 0;
|
lastT = 0;
|
||||||
}
|
}
|
||||||
#ifdef BLUEPILL
|
|
||||||
if(Tms - bplastT > 499){
|
if(Tms - bplastT > 499){
|
||||||
|
usart_transmit();
|
||||||
|
#ifdef BLUEPILL
|
||||||
pin_toggle(LEDB_port, LEDB_pin);
|
pin_toggle(LEDB_port, LEDB_pin);
|
||||||
|
#endif
|
||||||
bplastT = Tms;
|
bplastT = Tms;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
can_proc();
|
can_proc();
|
||||||
CAN_status st = CAN_get_status();
|
CAN_status st = CAN_get_status();
|
||||||
if(st == CAN_FIFO_OVERRUN){
|
if(st == CAN_FIFO_OVERRUN){
|
||||||
@ -63,30 +62,34 @@ int main(void){
|
|||||||
}else if(st == CAN_ERR){
|
}else if(st == CAN_ERR){
|
||||||
usart_send("Some CAN error occured\n");
|
usart_send("Some CAN error occured\n");
|
||||||
}
|
}
|
||||||
|
int errflag = 0;
|
||||||
while((can_mesg = CAN_messagebuf_pop())){
|
while((can_mesg = CAN_messagebuf_pop())){
|
||||||
|
IWDG->KR = IWDG_REFRESH;
|
||||||
if(can_mesg && isgood(can_mesg->ID)){
|
if(can_mesg && isgood(can_mesg->ID)){
|
||||||
LED_on(LED0);
|
LED_on(LED0);
|
||||||
lastT = Tms;
|
lastT = Tms;
|
||||||
if(!lastT) lastT = 1;
|
if(!lastT) lastT = 1;
|
||||||
if(ShowMsgs){ // new data in buff
|
if(ShowMsgs){ // new data in buff
|
||||||
IWDG->KR = IWDG_REFRESH;
|
|
||||||
uint8_t len = can_mesg->length;
|
uint8_t len = can_mesg->length;
|
||||||
printu(Tms);
|
printu(Tms);
|
||||||
usart_send(" #");
|
if(!usart_send(" #")) errflag = 1;
|
||||||
printuhex(can_mesg->ID);
|
printuhex(can_mesg->ID);
|
||||||
for(uint8_t ctr = 0; ctr < len; ++ctr){
|
for(uint8_t ctr = 0; ctr < len; ++ctr){
|
||||||
usart_putchar(' ');
|
if(!usart_putchar(' ')) errflag = 1;
|
||||||
printuhex(can_mesg->data[ctr]);
|
printuhex(can_mesg->data[ctr]);
|
||||||
}
|
}
|
||||||
usart_putchar('\n');
|
if(!usart_putchar('\n')) errflag = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
char *str;
|
char *str;
|
||||||
int g = usart_getline(&str);
|
int g = usart_getline(&str);
|
||||||
if(g < 0) usart_send("USART buffer overflow!\n");
|
if(g < 0) usart_send("USART IN buffer overflow!\n");
|
||||||
else if(g > 0) cmd_parser(str);
|
else if(g > 0) cmd_parser(str);
|
||||||
usart_transmit();
|
if(errflag){
|
||||||
|
while(!usart_txrdy) IWDG->KR = IWDG_REFRESH;
|
||||||
|
usart_send("USART OUT buffer overflow!\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -137,6 +137,7 @@ static char *getbin(const char *buf, uint32_t *N){
|
|||||||
char *getnum(const char *txt, uint32_t *N){
|
char *getnum(const char *txt, uint32_t *N){
|
||||||
char *nxt = NULL;
|
char *nxt = NULL;
|
||||||
char *s = omit_spaces(txt);
|
char *s = omit_spaces(txt);
|
||||||
|
if(!*s) return (char*)txt;
|
||||||
if(*s == '0'){ // hex, oct or 0
|
if(*s == '0'){ // hex, oct or 0
|
||||||
if(s[1] == 'x' || s[1] == 'X'){ // hex
|
if(s[1] == 'x' || s[1] == 'X'){ // hex
|
||||||
nxt = gethex(s+2, N);
|
nxt = gethex(s+2, N);
|
||||||
@ -166,7 +167,6 @@ static CAN_message *parseCANmsg(char *txt){
|
|||||||
int ctr = -1;
|
int ctr = -1;
|
||||||
canmsg.ID = 0xffff;
|
canmsg.ID = 0xffff;
|
||||||
do{
|
do{
|
||||||
txt = omit_spaces(txt);
|
|
||||||
n = getnum(txt, &N);
|
n = getnum(txt, &N);
|
||||||
if(txt == n) break;
|
if(txt == n) break;
|
||||||
txt = n;
|
txt = n;
|
||||||
@ -206,14 +206,13 @@ TRUE_INLINE void usart_sendCANcommand(char *txt){
|
|||||||
}
|
}
|
||||||
CAN_message *msg = parseCANmsg(txt);
|
CAN_message *msg = parseCANmsg(txt);
|
||||||
if(!msg) return;
|
if(!msg) return;
|
||||||
uint32_t N = 3;
|
uint32_t N = 5;
|
||||||
while(CAN_BUSY == can_send(msg->data, msg->length, msg->ID)){
|
while(CAN_BUSY == can_send(msg->data, msg->length, msg->ID)){
|
||||||
if(--N == 0) break;
|
if(--N == 0) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TRUE_INLINE void CANini(char *txt){
|
TRUE_INLINE void CANini(char *txt){
|
||||||
txt = omit_spaces(txt);
|
|
||||||
uint32_t N;
|
uint32_t N;
|
||||||
char *n = getnum(txt, &N);
|
char *n = getnum(txt, &N);
|
||||||
if(txt == n){
|
if(txt == n){
|
||||||
@ -237,7 +236,6 @@ TRUE_INLINE void addIGN(char *txt){
|
|||||||
usart_send("Ignore buffer is full");
|
usart_send("Ignore buffer is full");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
txt = omit_spaces(txt);
|
|
||||||
uint32_t N;
|
uint32_t N;
|
||||||
char *n = getnum(txt, &N);
|
char *n = getnum(txt, &N);
|
||||||
if(txt == n){
|
if(txt == n){
|
||||||
@ -333,7 +331,6 @@ TRUE_INLINE void list_filters(){
|
|||||||
*/
|
*/
|
||||||
static void add_filter(char *str){
|
static void add_filter(char *str){
|
||||||
uint32_t N;
|
uint32_t N;
|
||||||
str = omit_spaces(str);
|
|
||||||
char *n = getnum(str, &N);
|
char *n = getnum(str, &N);
|
||||||
if(n == str){
|
if(n == str){
|
||||||
usart_send("No bank# given");
|
usart_send("No bank# given");
|
||||||
@ -431,6 +428,7 @@ const char *helpmsg =
|
|||||||
"'P' - pause/resume in packets displaying\n"
|
"'P' - pause/resume in packets displaying\n"
|
||||||
"'R' - software reset\n"
|
"'R' - software reset\n"
|
||||||
"'s/S' - usart_send data over CAN: s ID byte0 .. byteN\n"
|
"'s/S' - usart_send data over CAN: s ID byte0 .. byteN\n"
|
||||||
|
"'t' - change flood period (>=1ms)\n"
|
||||||
"'T' - get time from start (ms)\n"
|
"'T' - get time from start (ms)\n"
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -445,39 +443,54 @@ TRUE_INLINE void getcanstat(){
|
|||||||
printuhex(CAN1->RF1R);
|
printuhex(CAN1->RF1R);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TRUE_INLINE void setfloodt(char *s){
|
||||||
|
uint32_t N;
|
||||||
|
char *n = getnum(s, &N);
|
||||||
|
if(s == n || N == 0){
|
||||||
|
usart_send("t="); printu(floodT); usart_putchar('\n');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
floodT = N - 1;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief cmd_parser - command parsing
|
* @brief cmd_parser - command parsing
|
||||||
* @param txt - buffer with commands & data
|
* @param txt - buffer with commands & data
|
||||||
*/
|
*/
|
||||||
void cmd_parser(char *txt){
|
void cmd_parser(char *txt){
|
||||||
char _1st = txt[0];
|
char _1st = txt[0];
|
||||||
|
++txt;
|
||||||
/*
|
/*
|
||||||
* parse long commands here
|
* parse long commands here
|
||||||
*/
|
*/
|
||||||
switch(_1st){
|
switch(_1st){
|
||||||
case 'a':
|
case 'a':
|
||||||
addIGN(txt + 1);
|
addIGN(txt);
|
||||||
goto eof;
|
goto eof;
|
||||||
break;
|
break;
|
||||||
case 'b':
|
case 'b':
|
||||||
CANini(txt + 1);
|
CANini(txt);
|
||||||
goto eof;
|
goto eof;
|
||||||
break;
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
add_filter(txt + 1);
|
add_filter(txt);
|
||||||
goto eof;
|
goto eof;
|
||||||
break;
|
break;
|
||||||
case 'F':
|
case 'F':
|
||||||
set_flood(parseCANmsg(txt + 1));
|
set_flood(parseCANmsg(txt));
|
||||||
goto eof;
|
goto eof;
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
case 'S':
|
case 'S':
|
||||||
usart_sendCANcommand(txt + 1);
|
usart_sendCANcommand(txt);
|
||||||
|
goto eof;
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
setfloodt(txt);
|
||||||
goto eof;
|
goto eof;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(txt[1] != '\n') *txt = '?'; // help for wrong message length
|
if(txt[1] != 0) _1st = '?'; // help for wrong message length
|
||||||
switch(_1st){
|
switch(_1st){
|
||||||
case 'c':
|
case 'c':
|
||||||
getcanstat();
|
getcanstat();
|
||||||
|
|||||||
@ -53,11 +53,18 @@ int usart_getline(char **line){
|
|||||||
}
|
}
|
||||||
|
|
||||||
// transmit current tbuf and swap buffers
|
// transmit current tbuf and swap buffers
|
||||||
void usart_transmit(){
|
int usart_transmit(){
|
||||||
register int l = odatalen[tbufno];
|
register int l = odatalen[tbufno];
|
||||||
if(!l) return;
|
if(!l) return 0;
|
||||||
uint32_t tmout = 16000000;
|
uint32_t tmout = 1600000;
|
||||||
while(!usart_txrdy){if(--tmout == 0) return;}; // wait for previos buffer transmission
|
/*tbuf[tbufno][0] = '*';
|
||||||
|
tbuf[tbufno][1] = '0' + tbufno;
|
||||||
|
tbuf[tbufno][l-1] = '*';
|
||||||
|
tbuf[tbufno][l-2] = '0' + tbufno;*/
|
||||||
|
while(!usart_txrdy){
|
||||||
|
IWDG->KR = IWDG_REFRESH;
|
||||||
|
if(--tmout == 0) return 0;
|
||||||
|
}; // wait for previos buffer transmission
|
||||||
usart_txrdy = 0;
|
usart_txrdy = 0;
|
||||||
odatalen[tbufno] = 0;
|
odatalen[tbufno] = 0;
|
||||||
DMA1_Channel4->CCR &= ~DMA_CCR_EN;
|
DMA1_Channel4->CCR &= ~DMA_CCR_EN;
|
||||||
@ -65,18 +72,27 @@ void usart_transmit(){
|
|||||||
DMA1_Channel4->CNDTR = l;
|
DMA1_Channel4->CNDTR = l;
|
||||||
DMA1_Channel4->CCR |= DMA_CCR_EN;
|
DMA1_Channel4->CCR |= DMA_CCR_EN;
|
||||||
tbufno = !tbufno;
|
tbufno = !tbufno;
|
||||||
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
void usart_putchar(const char ch){
|
int usart_putchar(const char ch){
|
||||||
if(odatalen[tbufno] == UARTBUFSZO) usart_transmit();
|
if(odatalen[tbufno] == UARTBUFSZO){
|
||||||
|
if(!usart_transmit()) return 0;
|
||||||
|
}
|
||||||
tbuf[tbufno][odatalen[tbufno]++] = ch;
|
tbuf[tbufno][odatalen[tbufno]++] = ch;
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void usart_send(const char *str){
|
int usart_send(const char *str){
|
||||||
|
int l = 0;
|
||||||
while(*str){
|
while(*str){
|
||||||
if(odatalen[tbufno] == UARTBUFSZO) usart_transmit();
|
if(odatalen[tbufno] == UARTBUFSZO){
|
||||||
tbuf[tbufno][odatalen[tbufno]++] = *str++;
|
if(!usart_transmit()) return 0;
|
||||||
}
|
}
|
||||||
|
tbuf[tbufno][odatalen[tbufno]++] = *str++;
|
||||||
|
++l;
|
||||||
|
}
|
||||||
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -102,7 +118,7 @@ void usart_setup(){
|
|||||||
NVIC_EnableIRQ(DMA1_Channel4_IRQn);
|
NVIC_EnableIRQ(DMA1_Channel4_IRQn);
|
||||||
NVIC_SetPriority(USART1_IRQn, 0);
|
NVIC_SetPriority(USART1_IRQn, 0);
|
||||||
// setup usart1
|
// setup usart1
|
||||||
USART1->BRR = 72000000 / 115200;
|
USART1->BRR = 72000000 / 921600;
|
||||||
USART1->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_UE; // 1start,8data,nstop; enable Rx,Tx,USART
|
USART1->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_UE; // 1start,8data,nstop; enable Rx,Tx,USART
|
||||||
while(!(USART1->SR & USART_SR_TC)){if(--tmout == 0) break;} // polling idle frame Transmission
|
while(!(USART1->SR & USART_SR_TC)){if(--tmout == 0) break;} // polling idle frame Transmission
|
||||||
USART1->SR = 0; // clear flags
|
USART1->SR = 0; // clear flags
|
||||||
@ -116,15 +132,15 @@ void usart1_isr(){
|
|||||||
if(USART1->SR & USART_SR_RXNE){ // RX not emty - receive next char
|
if(USART1->SR & USART_SR_RXNE){ // RX not emty - receive next char
|
||||||
uint8_t rb = USART1->DR;
|
uint8_t rb = USART1->DR;
|
||||||
if(idatalen[rbufno] < UARTBUFSZI){ // put next char into buf
|
if(idatalen[rbufno] < UARTBUFSZI){ // put next char into buf
|
||||||
rbuf[rbufno][idatalen[rbufno]++] = rb;
|
|
||||||
if(rb == '\n'){ // got newline - line ready
|
if(rb == '\n'){ // got newline - line ready
|
||||||
|
rbuf[rbufno][idatalen[rbufno]] = 0;
|
||||||
usart_linerdy = 1;
|
usart_linerdy = 1;
|
||||||
dlen = idatalen[rbufno];
|
dlen = idatalen[rbufno];
|
||||||
recvdata = rbuf[rbufno];
|
recvdata = rbuf[rbufno];
|
||||||
// prepare other buffer
|
// prepare other buffer
|
||||||
rbufno = !rbufno;
|
rbufno = !rbufno;
|
||||||
idatalen[rbufno] = 0;
|
idatalen[rbufno] = 0;
|
||||||
}
|
}else rbuf[rbufno][idatalen[rbufno]++] = rb;
|
||||||
}else{ // buffer overrun
|
}else{ // buffer overrun
|
||||||
usart_bufovr = 1;
|
usart_bufovr = 1;
|
||||||
idatalen[rbufno] = 0;
|
idatalen[rbufno] = 0;
|
||||||
|
|||||||
@ -19,16 +19,16 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// input and output buffers size
|
// input and output buffers size
|
||||||
#define UARTBUFSZI (128)
|
#define UARTBUFSZI (256)
|
||||||
#define UARTBUFSZO (128)
|
#define UARTBUFSZO (1024)
|
||||||
|
|
||||||
#define usartrx() (usart_linerdy)
|
#define usartrx() (usart_linerdy)
|
||||||
#define usartovr() (usart_bufovr)
|
#define usartovr() (usart_bufovr)
|
||||||
|
|
||||||
extern volatile int usart_txrdy;
|
extern volatile int usart_txrdy;
|
||||||
|
|
||||||
void usart_transmit();
|
int usart_transmit();
|
||||||
void usart_setup();
|
void usart_setup();
|
||||||
int usart_getline(char **line);
|
int usart_getline(char **line);
|
||||||
void usart_send(const char *str);
|
int usart_send(const char *str);
|
||||||
void usart_putchar(const char ch);
|
int usart_putchar(const char ch);
|
||||||
|
|||||||
@ -1,2 +1,2 @@
|
|||||||
#define BUILD_NUMBER "64"
|
#define BUILD_NUMBER "98"
|
||||||
#define BUILD_DATE "2022-12-05"
|
#define BUILD_DATE "2022-12-05"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user