mirror of
https://github.com/eddyem/stm32samples.git
synced 2025-12-06 18:55:13 +03:00
add more universal functions for reading/writing CAN
This commit is contained in:
parent
9d9536eb2b
commit
c40e239b19
@ -8,7 +8,7 @@ MCU = F042x6
|
|||||||
# hardware definitions
|
# hardware definitions
|
||||||
DEFS += -DUSARTNUM=1
|
DEFS += -DUSARTNUM=1
|
||||||
#DEFS += -DCHECK_TMOUT
|
#DEFS += -DCHECK_TMOUT
|
||||||
#DEFS += -DEBUG
|
DEFS += -DEBUG
|
||||||
# change this linking script depending on particular MCU model,
|
# change this linking script depending on particular MCU model,
|
||||||
# for example, if you have STM32F103VBT6, you should write:
|
# for example, if you have STM32F103VBT6, you should write:
|
||||||
LDSCRIPT = ld/stm32f042k.ld
|
LDSCRIPT = ld/stm32f042k.ld
|
||||||
@ -55,7 +55,7 @@ LIB_DIR := $(INC_DIR)/ld
|
|||||||
###############################################################################
|
###############################################################################
|
||||||
# C flags
|
# C flags
|
||||||
CFLAGS += -O2 -g -MD -D__thumb2__=1
|
CFLAGS += -O2 -g -MD -D__thumb2__=1
|
||||||
CFLAGS += -Wall -Wextra -Wshadow -Wimplicit-function-declaration
|
CFLAGS += -Wall -Werror -Wextra -Wshadow -Wimplicit-function-declaration
|
||||||
CFLAGS += -Wredundant-decls $(INCLUDE)
|
CFLAGS += -Wredundant-decls $(INCLUDE)
|
||||||
# -Wmissing-prototypes -Wstrict-prototypes
|
# -Wmissing-prototypes -Wstrict-prototypes
|
||||||
CFLAGS += -fno-common -ffunction-sections -fdata-sections
|
CFLAGS += -fno-common -ffunction-sections -fdata-sections
|
||||||
|
|||||||
@ -20,32 +20,91 @@
|
|||||||
* MA 02110-1301, USA.
|
* MA 02110-1301, USA.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
#include <string.h> // memcpy
|
||||||
#include "can.h"
|
#include "can.h"
|
||||||
#include "hardware.h"
|
#include "hardware.h"
|
||||||
#include "usart.h"
|
#include "usart.h"
|
||||||
|
|
||||||
#define CMD_TOGGLE (0xDA)
|
#define CMD_TOGGLE (0xDA)
|
||||||
#define CAN_ID_MASK (0xFF70U)
|
#define CAN_ID_MASK (0x7F8)
|
||||||
#define CAN_ID1 (0x651U)
|
#define CAN_ID_PREFIX (0xAAA)
|
||||||
#define CAN_ID2 (0x652U)
|
#define TARG_ID (CAN_ID_PREFIX & CAN_ID_MASK)
|
||||||
#define FILTER_LIST (0) /* 0: filter mode = identifier mask, 1: filter mode = identifier list */
|
|
||||||
|
|
||||||
#define CAN_FLAG_GOTDUMMY (1)
|
#define CAN_FLAG_GOTDUMMY (1)
|
||||||
static uint8_t CAN_addr = 255;
|
// incoming message buffer size
|
||||||
|
#define CAN_INMESSAGE_SIZE (6)
|
||||||
|
|
||||||
|
extern volatile uint32_t Tms;
|
||||||
|
|
||||||
|
// circular buffer for received messages
|
||||||
|
static CAN_message messages[CAN_INMESSAGE_SIZE];
|
||||||
|
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 uint16_t CANID = 0xFFFF;
|
||||||
static uint8_t CAN_flags = 0;
|
static uint8_t CAN_flags = 0;
|
||||||
|
static uint32_t last_err_code = 0;
|
||||||
|
static CAN_status can_status = CAN_STOP;
|
||||||
|
|
||||||
// get CAN address data from GPIO pins
|
static void can_process_fifo(uint8_t fifo_num);
|
||||||
void readCANaddr(){
|
|
||||||
CAN_addr = READ_CAN_INV_ADDR();
|
CAN_status CAN_get_status(){
|
||||||
CAN_addr = ~CAN_addr & 0x7;
|
CAN_status st = can_status;
|
||||||
|
// give overrun message only once
|
||||||
|
if(st == CAN_FIFO_OVERRUN) can_status = CAN_READY;
|
||||||
|
return st;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t getCANaddr(){
|
// push next message into buffer; return 1 if buffer overfull
|
||||||
return CAN_addr;
|
static int CAN_messagebuf_push(CAN_message *msg){
|
||||||
|
MSG("Try to push\n");
|
||||||
|
if(first_free_idx == first_nonfree_idx) return 1; // no free space
|
||||||
|
memcpy(&messages[first_free_idx++], msg, sizeof(CAN_message));
|
||||||
|
// need to roll?
|
||||||
|
if(first_free_idx == CAN_INMESSAGE_SIZE) first_free_idx = 0;
|
||||||
|
#ifdef EBUG
|
||||||
|
MSG("1st free: "); usart_putchar('0' + first_free_idx); newline();
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// pop message from buffer
|
||||||
|
CAN_message *CAN_messagebuf_pop(){
|
||||||
|
if(first_nonfree_idx < 0) return NULL;
|
||||||
|
#ifdef EBUG
|
||||||
|
MSG("read from idx "); usart_putchar('0' + first_nonfree_idx); newline();
|
||||||
|
#endif
|
||||||
|
CAN_message *msg = &messages[first_nonfree_idx++];
|
||||||
|
if(first_nonfree_idx == CAN_INMESSAGE_SIZE) first_nonfree_idx = 0;
|
||||||
|
if(first_nonfree_idx == first_free_idx){ // buffer is empty - refresh it
|
||||||
|
first_nonfree_idx = -1;
|
||||||
|
first_free_idx = 0;
|
||||||
|
MSG("refresh buffer\n");
|
||||||
|
}
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get CAN address data from GPIO pins
|
||||||
|
void readCANID(){
|
||||||
|
uint8_t CAN_addr = READ_CAN_INV_ADDR();
|
||||||
|
CAN_addr = ~CAN_addr & 0x7;
|
||||||
|
CANID = (CAN_ID_PREFIX & CAN_ID_MASK) | CAN_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t getCANID(){
|
||||||
|
return CANID;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAN_reinit(){
|
||||||
|
readCANID();
|
||||||
|
CAN->TSR |= CAN_TSR_ABRQ0 | CAN_TSR_ABRQ1 | CAN_TSR_ABRQ2;
|
||||||
|
RCC->APB1RSTR |= RCC_APB1RSTR_CANRST;
|
||||||
|
RCC->APB1RSTR &= ~RCC_APB1RSTR_CANRST;
|
||||||
|
CAN_setup();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CAN_setup(){
|
void CAN_setup(){
|
||||||
if(CAN_addr == 255) readCANaddr();
|
if(CANID == 0xFFFF) readCANID();
|
||||||
// Configure GPIO: PB8 - CAN_Rx, PB9 - CAN_Tx
|
// Configure GPIO: PB8 - CAN_Rx, PB9 - CAN_Tx
|
||||||
/* (1) Select AF mode (10) on PB8 and PB9 */
|
/* (1) Select AF mode (10) on PB8 and PB9 */
|
||||||
/* (2) AF4 for CAN signals */
|
/* (2) AF4 for CAN signals */
|
||||||
@ -59,23 +118,24 @@ void CAN_setup(){
|
|||||||
/* (1) Enter CAN init mode to write the configuration */
|
/* (1) Enter CAN init mode to write the configuration */
|
||||||
/* (2) Wait the init mode entering */
|
/* (2) Wait the init mode entering */
|
||||||
/* (3) Exit sleep mode */
|
/* (3) Exit sleep mode */
|
||||||
/* (4) Loopback mode, set timing to 1Mb/s: BS1 = 4, BS2 = 3, prescaler = 6 */
|
/* (4) Loopback mode, set timing to 100kb/s: BS1 = 4, BS2 = 3, prescaler = 60 */
|
||||||
/* (5) Leave init mode */
|
/* (5) Leave init mode */
|
||||||
/* (6) Wait the init mode leaving */
|
/* (6) Wait the init mode leaving */
|
||||||
/* (7) Enter filter init mode, (16-bit + mask, filter 0 for FIFO 0) */
|
/* (7) Enter filter init mode, (16-bit + mask, filter 0 for FIFO 0) */
|
||||||
/* (8) Acivate filter 0 */
|
/* (8) Acivate filter 0 */
|
||||||
/* (9) Identifier list mode */
|
/* (9) Identifier list mode */
|
||||||
/* (11) Set the Id list */
|
/* (10) Set the Id list */
|
||||||
/* (12) Set the Id + mask (all bits of standard id will care) */
|
/* (12) Leave filter init */
|
||||||
/* (13) Leave filter init */
|
/* (13) Set error interrupts enable */
|
||||||
/* (14) Set FIFO0 message pending IT 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) */
|
||||||
{
|
{
|
||||||
/* add time out here for a robust application */
|
/* add time out here for a robust application */
|
||||||
}
|
}
|
||||||
CAN->MCR &=~ CAN_MCR_SLEEP; /* (3) */
|
CAN->MCR &=~ CAN_MCR_SLEEP; /* (3) */
|
||||||
CAN->BTR |= CAN_BTR_LBKM | 2 << 20 | 3 << 16 | 5 << 0; /* (4) */
|
CAN->MCR |= CAN_MCR_ABOM;
|
||||||
|
|
||||||
|
CAN->BTR |= 2 << 20 | 3 << 16 | 59 << 0; /* (4) */
|
||||||
CAN->MCR &=~ CAN_MCR_INRQ; /* (5) */
|
CAN->MCR &=~ CAN_MCR_INRQ; /* (5) */
|
||||||
while((CAN->MSR & CAN_MSR_INAK)==CAN_MSR_INAK) /* (6) */
|
while((CAN->MSR & CAN_MSR_INAK)==CAN_MSR_INAK) /* (6) */
|
||||||
{
|
{
|
||||||
@ -83,49 +143,191 @@ void CAN_setup(){
|
|||||||
}
|
}
|
||||||
CAN->FMR = CAN_FMR_FINIT; /* (7) */
|
CAN->FMR = CAN_FMR_FINIT; /* (7) */
|
||||||
CAN->FA1R = CAN_FA1R_FACT0; /* (8) */
|
CAN->FA1R = CAN_FA1R_FACT0; /* (8) */
|
||||||
#if (FILTER_LIST)
|
|
||||||
CAN->FM1R = CAN_FM1R_FBM0; /* (9) */
|
CAN->FM1R = CAN_FM1R_FBM0; /* (9) */
|
||||||
CAN->sFilterRegister[0].FR1 = CAN_ID2 << 5 | CAN_ID1 << (16+5); /* (10) */
|
CAN->sFilterRegister[0].FR1 = CANID << 5; /* (10) */
|
||||||
#else
|
|
||||||
CAN->sFilterRegister[0].FR1 = CAN_ID1 << 5 | CAN_ID_MASK << 16; /* (11) */
|
|
||||||
#endif /* FILTER_LIST */
|
|
||||||
|
|
||||||
CAN->FMR &=~ CAN_FMR_FINIT; /* (12) */
|
CAN->FMR &=~ CAN_FMR_FINIT; /* (12) */
|
||||||
CAN->IER |= CAN_IER_FMPIE0; /* (13) */
|
CAN->IER |= CAN_IER_ERRIE | CAN_IER_FOVIE0 | CAN_IER_FOVIE1; /* (13) */
|
||||||
|
|
||||||
/* Configure IT */
|
/* Configure IT */
|
||||||
/* (14) Set priority for CAN_IRQn */
|
/* (14) Set priority for CAN_IRQn */
|
||||||
/* (15) Enable CAN_IRQn */
|
/* (15) Enable CAN_IRQn */
|
||||||
NVIC_SetPriority(CEC_CAN_IRQn, 0); /* (16) */
|
NVIC_SetPriority(CEC_CAN_IRQn, 0); /* (14) */
|
||||||
NVIC_EnableIRQ(CEC_CAN_IRQn); /* (17) */
|
NVIC_EnableIRQ(CEC_CAN_IRQn); /* (15) */
|
||||||
|
can_status = CAN_READY;
|
||||||
}
|
}
|
||||||
|
|
||||||
void can_proc(){
|
void can_proc(){
|
||||||
|
if(last_err_code){
|
||||||
|
#ifdef EBUG
|
||||||
|
MSG("Error, ESR=");
|
||||||
|
printu(last_err_code);
|
||||||
|
newline();
|
||||||
|
#endif
|
||||||
|
last_err_code = 0;
|
||||||
|
}
|
||||||
|
// check for messages in FIFO0 & FIFO1
|
||||||
|
if(CAN->RF0R & CAN_RF0R_FMP0){
|
||||||
|
can_process_fifo(0);
|
||||||
|
}
|
||||||
|
if(CAN->RF1R & CAN_RF1R_FMP1){
|
||||||
|
can_process_fifo(1);
|
||||||
|
}
|
||||||
|
if(CAN->ESR & (CAN_ESR_BOFF | CAN_ESR_EPVF | CAN_ESR_EWGF)){ // much errors - restart CAN BUS
|
||||||
|
MSG("bus-off, restarting\n");
|
||||||
|
// request abort for all mailboxes
|
||||||
|
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();
|
||||||
|
}
|
||||||
if(CAN_flags){
|
if(CAN_flags){
|
||||||
if(CAN_flags & CAN_FLAG_GOTDUMMY){
|
if(CAN_flags & CAN_FLAG_GOTDUMMY){
|
||||||
SEND("Got dummy message\n");
|
SEND("Got dummy message\n");
|
||||||
}
|
}
|
||||||
CAN_flags = 0;
|
CAN_flags = 0;
|
||||||
}
|
}
|
||||||
|
LED_off(LED1);
|
||||||
|
#ifdef EBUG
|
||||||
|
static uint32_t esr, msr, tsr;
|
||||||
|
uint32_t msr_now = CAN->MSR & 0xf;
|
||||||
|
if(esr != CAN->ESR || msr != msr_now || tsr != CAN->TSR){
|
||||||
|
MSG("Timestamp: ");
|
||||||
|
printu(Tms);
|
||||||
|
newline();
|
||||||
|
}
|
||||||
|
if((CAN->ESR) != esr){
|
||||||
|
usart_putchar(((CAN->ESR & CAN_ESR_BOFF) != 0) + '0');
|
||||||
|
esr = CAN->ESR;
|
||||||
|
MSG("CAN->ESR: ");
|
||||||
|
printuhex(esr); newline();
|
||||||
|
}
|
||||||
|
if(msr_now != msr){
|
||||||
|
msr = msr_now;
|
||||||
|
MSG("CAN->MSR & 0xf: ");
|
||||||
|
printuhex(msr); newline();
|
||||||
|
}
|
||||||
|
if(CAN->TSR != tsr){
|
||||||
|
tsr = CAN->TSR;
|
||||||
|
MSG("CAN->TSR: ");
|
||||||
|
printuhex(tsr); newline();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
CAN_status can_send(uint8_t *msg, uint8_t len, uint16_t target_id){
|
||||||
|
uint8_t mailbox = 0;
|
||||||
|
// check first free mailbox
|
||||||
|
if(CAN->TSR & (CAN_TSR_TME)){
|
||||||
|
mailbox = (CAN->TSR & CAN_TSR_CODE) >> 24;
|
||||||
|
#ifdef EBUG
|
||||||
|
MSG("select "); usart_putchar('0'+mailbox); SEND(" mailbox\n");
|
||||||
|
#endif
|
||||||
|
}else{ // no free mailboxes
|
||||||
|
return CAN_BUSY;
|
||||||
|
}
|
||||||
|
CAN_TxMailBox_TypeDef *box = &CAN->sTxMailBox[mailbox];
|
||||||
|
uint32_t lb = 0, hb = 0;
|
||||||
|
switch(len){
|
||||||
|
case 8:
|
||||||
|
hb |= (uint32_t)msg[7] << 24;
|
||||||
|
case 7:
|
||||||
|
hb |= (uint32_t)msg[6] << 16;
|
||||||
|
case 6:
|
||||||
|
hb |= (uint32_t)msg[5] << 8;
|
||||||
|
case 5:
|
||||||
|
hb |= (uint32_t)msg[4];
|
||||||
|
case 4:
|
||||||
|
lb |= (uint32_t)msg[3] << 24;
|
||||||
|
case 3:
|
||||||
|
lb |= (uint32_t)msg[2] << 16;
|
||||||
|
case 2:
|
||||||
|
lb |= (uint32_t)msg[1] << 8;
|
||||||
|
default:
|
||||||
|
lb |= (uint32_t)msg[0];
|
||||||
|
}
|
||||||
|
box->TDLR = lb;
|
||||||
|
box->TDHR = hb;
|
||||||
|
box->TDTR = len;
|
||||||
|
box->TIR = (target_id & 0x7FF) << 21 | CAN_TI0R_TXRQ;
|
||||||
|
return CAN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void can_send_dummy(){
|
void can_send_dummy(){
|
||||||
if((CAN->TSR & CAN_TSR_TME0) == CAN_TSR_TME0){ /* check mailbox 0 is empty */
|
uint8_t msg = CMD_TOGGLE;
|
||||||
CAN->sTxMailBox[0].TDTR = 1; /* fill data length = 1 */
|
if(CAN_OK != can_send(&msg, 1, TARG_ID)) SEND("Bus busy!\n");
|
||||||
CAN->sTxMailBox[0].TDLR = CMD_TOGGLE; /* fill 8-bit data */
|
MSG("CAN->MSR: ");
|
||||||
CAN->sTxMailBox[0].TIR = (uint32_t)(CAN_ID1 << 21 | CAN_TI0R_TXRQ); /* fill Id field and request a transmission */
|
printuhex(CAN->MSR); newline();
|
||||||
|
MSG("CAN->TSR: ");
|
||||||
|
printuhex(CAN->TSR); newline();
|
||||||
|
MSG("CAN->ESR: ");
|
||||||
|
printuhex(CAN->ESR); newline();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void can_process_fifo(uint8_t fifo_num){
|
||||||
|
if(fifo_num > 1) return;
|
||||||
|
LED_on(LED1); // Toggle LED1
|
||||||
|
CAN_FIFOMailBox_TypeDef *box = &CAN->sFIFOMailBox[fifo_num];
|
||||||
|
volatile uint32_t *RFxR = (fifo_num) ? &CAN->RF1R : &CAN->RF0R;
|
||||||
|
MSG("Receive, RDTR=");
|
||||||
|
#ifdef EBUG
|
||||||
|
printuhex(box->RDTR);
|
||||||
|
newline();
|
||||||
|
#endif
|
||||||
|
// read all
|
||||||
|
while(*RFxR & CAN_RF0R_FMP0){ // amount of messages pending
|
||||||
|
// 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 */
|
||||||
|
CAN_message msg;
|
||||||
|
uint8_t *dat = msg.data;
|
||||||
|
uint8_t len = box->RDTR & 0x7;
|
||||||
|
msg.length = len;
|
||||||
|
if(len){ // message can be without data
|
||||||
|
uint32_t hb = box->RDHR, lb = box->RDLR;
|
||||||
|
switch(len){
|
||||||
|
case 8:
|
||||||
|
dat[7] = hb>>24;
|
||||||
|
case 7:
|
||||||
|
dat[6] = (hb>>16) & 0xff;
|
||||||
|
case 6:
|
||||||
|
dat[5] = (hb>>8) & 0xff;
|
||||||
|
case 5:
|
||||||
|
dat[4] = hb & 0xff;
|
||||||
|
case 4:
|
||||||
|
dat[3] = lb>>24;
|
||||||
|
case 3:
|
||||||
|
dat[2] = (lb>>16) & 0xff;
|
||||||
|
case 2:
|
||||||
|
dat[1] = (lb>>8) & 0xff;
|
||||||
|
case 1:
|
||||||
|
dat[0] = lb & 0xff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(CAN_messagebuf_push(&msg)) return; // error: buffer is full, try later
|
||||||
|
*RFxR |= CAN_RF0R_RFOM0; // release fifo for access to next message
|
||||||
}
|
}
|
||||||
|
if(*RFxR & CAN_RF0R_FULL0) *RFxR &= ~CAN_RF0R_FULL0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cec_can_isr(){
|
void cec_can_isr(){
|
||||||
uint32_t CAN_ReceiveMessage = 0;
|
if(CAN->RF0R & CAN_RF0R_FOVR0){ // FIFO overrun
|
||||||
|
CAN->RF0R &= ~CAN_RF0R_FOVR0;
|
||||||
if(CAN->RF0R & CAN_RF0R_FMP0){ /* check if a message is filtered and received by FIFO 0 */
|
can_status = CAN_FIFO_OVERRUN;
|
||||||
LED_blink(LED1); /* Toggle LED1 */
|
}
|
||||||
CAN_ReceiveMessage = CAN->sFIFOMailBox[0].RDLR; /* read data */
|
if(CAN->RF1R & CAN_RF1R_FOVR1){
|
||||||
CAN->RF0R |= CAN_RF0R_RFOM0; /* release FIFO */
|
CAN->RF1R &= ~CAN_RF1R_FOVR1;
|
||||||
if((CAN_ReceiveMessage & 0xFF) == CMD_TOGGLE){
|
can_status = CAN_FIFO_OVERRUN;
|
||||||
CAN_flags |= CAN_FLAG_GOTDUMMY;
|
}
|
||||||
}
|
#ifdef EBUG
|
||||||
|
if(can_status == CAN_FIFO_OVERRUN) MSG("fifo 0 overrun\n");
|
||||||
|
#endif
|
||||||
|
if(CAN->MSR & CAN_MSR_ERRI){ // Error
|
||||||
|
CAN->MSR &= ~CAN_MSR_ERRI;
|
||||||
|
// request abort for problem mailbox
|
||||||
|
if(CAN->TSR & CAN_TSR_TERR0) CAN->TSR |= CAN_TSR_ABRQ0;
|
||||||
|
if(CAN->TSR & CAN_TSR_TERR1) CAN->TSR |= CAN_TSR_ABRQ1;
|
||||||
|
if(CAN->TSR & CAN_TSR_TERR2) CAN->TSR |= CAN_TSR_ABRQ2;
|
||||||
|
last_err_code = CAN->ESR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,12 +26,30 @@
|
|||||||
|
|
||||||
#include "hardware.h"
|
#include "hardware.h"
|
||||||
|
|
||||||
void readCANaddr();
|
typedef struct{
|
||||||
uint8_t getCANaddr();
|
uint8_t data[8];
|
||||||
|
uint8_t length;
|
||||||
|
} CAN_message;
|
||||||
|
|
||||||
|
typedef enum{
|
||||||
|
CAN_STOP,
|
||||||
|
CAN_READY,
|
||||||
|
CAN_BUSY,
|
||||||
|
CAN_OK,
|
||||||
|
CAN_FIFO_OVERRUN
|
||||||
|
} CAN_status;
|
||||||
|
|
||||||
|
CAN_status CAN_get_status();
|
||||||
|
|
||||||
|
void readCANID();
|
||||||
|
uint16_t getCANID();
|
||||||
|
|
||||||
|
void CAN_reinit();
|
||||||
void CAN_setup();
|
void CAN_setup();
|
||||||
|
|
||||||
void can_send_dummy();
|
void can_send_dummy();
|
||||||
void can_proc();
|
void can_proc();
|
||||||
|
|
||||||
|
CAN_message *CAN_messagebuf_pop();
|
||||||
|
|
||||||
#endif // __CAN_H__
|
#endif // __CAN_H__
|
||||||
|
|||||||
Binary file not shown.
@ -41,7 +41,9 @@
|
|||||||
#define LED1_port GPIOC
|
#define LED1_port GPIOC
|
||||||
#define LED1_pin (1<<14)
|
#define LED1_pin (1<<14)
|
||||||
|
|
||||||
#define LED_blink(x) pin_toggle(x ## _port, x ## _pin)
|
#define LED_blink(x) pin_toggle(x ## _port, x ## _pin)
|
||||||
|
#define LED_on(x) pin_clear(x ## _port, x ## _pin)
|
||||||
|
#define LED_off(x) pin_set(x ## _port, x ## _pin)
|
||||||
|
|
||||||
|
|
||||||
// CAN address - PB14(0), PB15(1), PA8(2)
|
// CAN address - PB14(0), PB15(1), PA8(2)
|
||||||
|
|||||||
@ -53,6 +53,8 @@ void iwdg_setup(){
|
|||||||
|
|
||||||
int main(void){
|
int main(void){
|
||||||
uint32_t lastT = 0;
|
uint32_t lastT = 0;
|
||||||
|
uint8_t ctr, len;
|
||||||
|
CAN_message *can_mesg;
|
||||||
int L;
|
int L;
|
||||||
char *txt;
|
char *txt;
|
||||||
sysreset();
|
sysreset();
|
||||||
@ -60,12 +62,13 @@ int main(void){
|
|||||||
gpio_setup();
|
gpio_setup();
|
||||||
usart_setup();
|
usart_setup();
|
||||||
iwdg_setup();
|
iwdg_setup();
|
||||||
readCANaddr();
|
readCANID();
|
||||||
CAN_setup();
|
CAN_setup();
|
||||||
|
|
||||||
SEND("Greetings! My address is ");
|
SEND("Greetings! My address is ");
|
||||||
printu(getCANaddr());
|
printuhex(getCANID());
|
||||||
newline();
|
newline();
|
||||||
|
|
||||||
if(RCC->CSR & RCC_CSR_IWDGRSTF){ // watchdog reset occured
|
if(RCC->CSR & RCC_CSR_IWDGRSTF){ // watchdog reset occured
|
||||||
SEND("WDGRESET=1\n");
|
SEND("WDGRESET=1\n");
|
||||||
}
|
}
|
||||||
@ -81,6 +84,20 @@ int main(void){
|
|||||||
lastT = Tms;
|
lastT = Tms;
|
||||||
}
|
}
|
||||||
can_proc();
|
can_proc();
|
||||||
|
if(CAN_get_status() == CAN_FIFO_OVERRUN){
|
||||||
|
SEND("CAN bus fifo overrun occured!\n");
|
||||||
|
}
|
||||||
|
can_mesg = CAN_messagebuf_pop();
|
||||||
|
if(can_mesg){ // new data in buff
|
||||||
|
len = can_mesg->length;
|
||||||
|
SEND("got message, len: "); usart_putchar('0' + len);
|
||||||
|
SEND(", data: ");
|
||||||
|
for(ctr = 0; ctr < len; ++ctr){
|
||||||
|
printuhex(can_mesg->data[ctr]);
|
||||||
|
usart_putchar(' ');
|
||||||
|
}
|
||||||
|
newline();
|
||||||
|
}
|
||||||
if(usartrx()){ // usart1 received data, store in in buffer
|
if(usartrx()){ // usart1 received data, store in in buffer
|
||||||
L = usart_getline(&txt);
|
L = usart_getline(&txt);
|
||||||
char _1st = txt[0];
|
char _1st = txt[0];
|
||||||
@ -92,12 +109,19 @@ int main(void){
|
|||||||
break;
|
break;
|
||||||
case 'G':
|
case 'G':
|
||||||
SEND("Can address: ");
|
SEND("Can address: ");
|
||||||
printu(getCANaddr());
|
printuhex(getCANID());
|
||||||
newline();
|
newline();
|
||||||
break;
|
break;
|
||||||
case 'R':
|
case 'R':
|
||||||
|
SEND("Soft reset\n");
|
||||||
NVIC_SystemReset();
|
NVIC_SystemReset();
|
||||||
break;
|
break;
|
||||||
|
case 'S':
|
||||||
|
CAN_reinit();
|
||||||
|
SEND("Can address: ");
|
||||||
|
printuhex(getCANID());
|
||||||
|
newline();
|
||||||
|
break;
|
||||||
case 'W':
|
case 'W':
|
||||||
SEND("Wait for reboot\n");
|
SEND("Wait for reboot\n");
|
||||||
while(1){nop();};
|
while(1){nop();};
|
||||||
@ -107,6 +131,7 @@ int main(void){
|
|||||||
"'C' - send dummy byte over CAN\n"
|
"'C' - send dummy byte over CAN\n"
|
||||||
"'G' - get CAN address\n"
|
"'G' - get CAN address\n"
|
||||||
"'R' - software reset\n"
|
"'R' - software reset\n"
|
||||||
|
"'S' - reinit CAN (with new address)\n"
|
||||||
"'W' - test watchdog\n"
|
"'W' - test watchdog\n"
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -218,6 +218,20 @@ void printu(uint32_t val){
|
|||||||
while(LINE_BUSY == usart_send_blocking(bufa, l+bpos));
|
while(LINE_BUSY == usart_send_blocking(bufa, l+bpos));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// print 32bit unsigned int as hex
|
||||||
|
void printuhex(uint32_t val){
|
||||||
|
SEND("0x");
|
||||||
|
uint8_t *ptr = (uint8_t*)&val + 3;
|
||||||
|
int i, j;
|
||||||
|
for(i = 0; i < 4; ++i, --ptr){
|
||||||
|
for(j = 1; j > -1; --j){
|
||||||
|
uint8_t half = (*ptr >> (4*j)) & 0x0f;
|
||||||
|
if(half < 10) usart_putchar(half + '0');
|
||||||
|
else usart_putchar(half - 10 + 'a');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if USARTNUM == 2
|
#if USARTNUM == 2
|
||||||
void dma1_channel4_5_isr(){
|
void dma1_channel4_5_isr(){
|
||||||
if(DMA1->ISR & DMA_ISR_TCIF4){ // Tx
|
if(DMA1->ISR & DMA_ISR_TCIF4){ // Tx
|
||||||
|
|||||||
@ -56,5 +56,6 @@ TXstatus usart_send_blocking(const char *str, int len);
|
|||||||
void newline();
|
void newline();
|
||||||
void usart_putchar(const char ch);
|
void usart_putchar(const char ch);
|
||||||
void printu(uint32_t val);
|
void printu(uint32_t val);
|
||||||
|
void printuhex(uint32_t val);
|
||||||
|
|
||||||
#endif // __USART_H__
|
#endif // __USART_H__
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user