STM32 CAN library improvement: addition of TX mailboxes (#508)
* CAN-bus library for STM32 This adds CAN-bus library for STM32. Mainly for STM32F4, but others can be added later. * CAN2 and F446 support added for STM32 CAN library Adds support for second can interface and F446 bit timings. * Fix STM32 CAN pin selection and STM32F1 support The previous way to select CAN pins wasn't actually working, so this fixes that problem and also the F1 support too. * Fix building for Mega/Teensy * Update cancomms.ino * Update speeduino.ino * STM32 CAN library fixes * TX mailbox addition Co-authored-by: Pasi Kemppainen <pazi88@users.noreply.github.com> Co-authored-by: Josh Stewart <josh@noisymime.org>
This commit is contained in:
parent
941da74154
commit
3b46db4ca2
|
@ -124,7 +124,7 @@ void STM32_CAN::begin()
|
|||
#endif
|
||||
}
|
||||
|
||||
int STM32_CAN::write(CAN_message_t &CAN_tx_msg)
|
||||
void STM32_CAN::writeTxMailbox(uint8_t mb_num, CAN_message_t &CAN_tx_msg)
|
||||
{
|
||||
uint32_t out = 0;
|
||||
if (CAN_tx_msg.flags.extended == true) { // Extended frame format
|
||||
|
@ -140,50 +140,97 @@ int STM32_CAN::write(CAN_message_t &CAN_tx_msg)
|
|||
|
||||
if (_channel == _CAN1)
|
||||
{
|
||||
// Check if the mailbox is empty
|
||||
if (CAN1->sTxMailBox[0].TIR & 0x1UL) {
|
||||
//Serial.println("transmit Fail");
|
||||
return -1; // transmit of the previous message has failed
|
||||
}
|
||||
else { // mailbox is empty, so it's ok to send new message
|
||||
CAN1->sTxMailBox[0].TDTR &= ~(0xF);
|
||||
CAN1->sTxMailBox[0].TDTR |= CAN_tx_msg.len & 0xFUL;
|
||||
CAN1->sTxMailBox[0].TDLR = (((uint32_t) CAN_tx_msg.buf[3] << 24) |
|
||||
((uint32_t) CAN_tx_msg.buf[2] << 16) |
|
||||
((uint32_t) CAN_tx_msg.buf[1] << 8) |
|
||||
((uint32_t) CAN_tx_msg.buf[0] ));
|
||||
CAN1->sTxMailBox[0].TDHR = (((uint32_t) CAN_tx_msg.buf[7] << 24) |
|
||||
((uint32_t) CAN_tx_msg.buf[6] << 16) |
|
||||
((uint32_t) CAN_tx_msg.buf[5] << 8) |
|
||||
((uint32_t) CAN_tx_msg.buf[4] ));
|
||||
CAN1->sTxMailBox[mb_num].TDTR &= ~(0xF);
|
||||
CAN1->sTxMailBox[mb_num].TDTR |= CAN_tx_msg.len & 0xFUL;
|
||||
CAN1->sTxMailBox[mb_num].TDLR = (((uint32_t) CAN_tx_msg.buf[3] << 24) |
|
||||
((uint32_t) CAN_tx_msg.buf[2] << 16) |
|
||||
((uint32_t) CAN_tx_msg.buf[1] << 8) |
|
||||
((uint32_t) CAN_tx_msg.buf[0] ));
|
||||
CAN1->sTxMailBox[mb_num].TDHR = (((uint32_t) CAN_tx_msg.buf[7] << 24) |
|
||||
((uint32_t) CAN_tx_msg.buf[6] << 16) |
|
||||
((uint32_t) CAN_tx_msg.buf[5] << 8) |
|
||||
((uint32_t) CAN_tx_msg.buf[4] ));
|
||||
|
||||
// Send Go
|
||||
CAN1->sTxMailBox[0].TIR = out | STM32_CAN_TIR_TXRQ;
|
||||
return 1; // transmit done
|
||||
// Send Go
|
||||
CAN1->sTxMailBox[mb_num].TIR = out | STM32_CAN_TIR_TXRQ;
|
||||
}
|
||||
#if defined(CAN2)
|
||||
if (_channel == _CAN2)
|
||||
{
|
||||
CAN2->sTxMailBox[mb_num].TDTR &= ~(0xF);
|
||||
CAN2->sTxMailBox[mb_num].TDTR |= CAN_tx_msg.len & 0xFUL;
|
||||
CAN2->sTxMailBox[mb_num].TDLR = (((uint32_t) CAN_tx_msg.buf[3] << 24) |
|
||||
((uint32_t) CAN_tx_msg.buf[2] << 16) |
|
||||
((uint32_t) CAN_tx_msg.buf[1] << 8) |
|
||||
((uint32_t) CAN_tx_msg.buf[0] ));
|
||||
CAN2->sTxMailBox[mb_num].TDHR = (((uint32_t) CAN_tx_msg.buf[7] << 24) |
|
||||
((uint32_t) CAN_tx_msg.buf[6] << 16) |
|
||||
((uint32_t) CAN_tx_msg.buf[5] << 8) |
|
||||
((uint32_t) CAN_tx_msg.buf[4] ));
|
||||
// Send Go
|
||||
CAN2->sTxMailBox[mb_num].TIR = out | STM32_CAN_TIR_TXRQ;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int STM32_CAN::write(CAN_message_t &CAN_tx_msg)
|
||||
{
|
||||
volatile int mailbox = 0;
|
||||
|
||||
if (_channel == _CAN1)
|
||||
{
|
||||
// Check if one of the three mailboxes is empty
|
||||
while(CAN1->sTxMailBox[mailbox].TIR & 0x1UL && mailbox++ < 3);
|
||||
|
||||
if (mailbox >= 3) {
|
||||
//Serial.println("transmit Fail");
|
||||
return -1; // transmit failed, no mailboxes available
|
||||
}
|
||||
else { // empty mailbox found, so it's ok to send new message
|
||||
writeTxMailbox(mailbox, CAN_tx_msg);
|
||||
return 1; // transmit done
|
||||
}
|
||||
}
|
||||
#if defined(CAN2)
|
||||
if (_channel == _CAN2)
|
||||
{
|
||||
// Check if the mailbox is empty
|
||||
if (CAN2->sTxMailBox[0].TIR & 0x1UL) {
|
||||
//Serial.println("transmit Fail");
|
||||
return -1; // transmit of the previous message has failed
|
||||
}
|
||||
else { // mailbox is empty, so it's ok to send new message
|
||||
CAN2->sTxMailBox[0].TDTR &= ~(0xF);
|
||||
CAN2->sTxMailBox[0].TDTR |= CAN_tx_msg.len & 0xFUL;
|
||||
CAN2->sTxMailBox[0].TDLR = (((uint32_t) CAN_tx_msg.buf[3] << 24) |
|
||||
((uint32_t) CAN_tx_msg.buf[2] << 16) |
|
||||
((uint32_t) CAN_tx_msg.buf[1] << 8) |
|
||||
((uint32_t) CAN_tx_msg.buf[0] ));
|
||||
CAN2->sTxMailBox[0].TDHR = (((uint32_t) CAN_tx_msg.buf[7] << 24) |
|
||||
((uint32_t) CAN_tx_msg.buf[6] << 16) |
|
||||
((uint32_t) CAN_tx_msg.buf[5] << 8) |
|
||||
((uint32_t) CAN_tx_msg.buf[4] ));
|
||||
// Check if one of the three mailboxes is empty
|
||||
while(CAN2->sTxMailBox[mailbox].TIR & 0x1UL && mailbox++ < 3);
|
||||
|
||||
// Send Go
|
||||
CAN2->sTxMailBox[0].TIR = out | STM32_CAN_TIR_TXRQ;
|
||||
if (mailbox >= 3) {
|
||||
//Serial.println("transmit Fail");
|
||||
return -1; // transmit failed, no mailboxes available
|
||||
}
|
||||
else { // empty mailbox found, so it's ok to send new message
|
||||
writeTxMailbox(mailbox, CAN_tx_msg);
|
||||
return 1; // transmit done
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int STM32_CAN::write(CAN_MAILBOX mb_num, CAN_message_t &CAN_tx_msg)
|
||||
{
|
||||
if (_channel == _CAN1)
|
||||
{
|
||||
if (CAN1->sTxMailBox[mb_num].TIR & 0x1UL) {
|
||||
//Serial.println("transmit Fail");
|
||||
return -1; // transmit failed, mailbox was not empty
|
||||
}
|
||||
else { // mailbox was empty, so it's ok to send new message
|
||||
writeTxMailbox(mb_num, CAN_tx_msg);
|
||||
return 1; // transmit done
|
||||
}
|
||||
}
|
||||
#if defined(CAN2)
|
||||
if (_channel == _CAN2)
|
||||
{
|
||||
if (CAN2->sTxMailBox[mb_num].TIR & 0x1UL) {
|
||||
//Serial.println("transmit Fail");
|
||||
return -1; // transmit failed, mailbox was not empty
|
||||
}
|
||||
else { // mailbox was empty, so it's ok to send new message
|
||||
writeTxMailbox(mb_num, CAN_tx_msg);
|
||||
return 1; // transmit done
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,6 +50,13 @@ typedef const struct
|
|||
|
||||
typedef enum CAN_PINS {DEF, ALT, ALT2,} CAN_PINS;
|
||||
|
||||
//STM32 has only 3 TX mailboxes
|
||||
typedef enum CAN_MAILBOX {
|
||||
MB0 = 0,
|
||||
MB1 = 1,
|
||||
MB2 = 2
|
||||
} CAN_MAILBOX;
|
||||
|
||||
#ifndef CAN2
|
||||
typedef enum CAN_CHANNEL {_CAN1,} CAN_CHANNEL;
|
||||
#elif defined CAN2
|
||||
|
@ -76,6 +83,7 @@ class STM32_CAN {
|
|||
private:
|
||||
void CANSetGpio(GPIO_TypeDef * addr, uint8_t index, uint8_t speed = 3);
|
||||
void CANSetFilter(uint8_t index, uint8_t scale, uint8_t mode, uint8_t fifo, uint32_t bank1, uint32_t bank2);
|
||||
void writeTxMailbox(uint8_t mb_num, CAN_message_t &CAN_tx_msg);
|
||||
uint8_t CANMsgAvail();
|
||||
void SetTXRX();
|
||||
|
||||
|
@ -83,7 +91,8 @@ class STM32_CAN {
|
|||
STM32_CAN(const CAN_CHANNEL channel, CAN_PINS pins) : _channel (channel), _pins (pins) { };
|
||||
void begin();
|
||||
void setBaudRate(uint32_t baud);
|
||||
int write(CAN_message_t &CAN_tx_msg);
|
||||
int write(CAN_message_t &CAN_tx_msg); // use any available mailbox for transmitting
|
||||
int write(CAN_MAILBOX mb_num, CAN_message_t &CAN_tx_msg); // use a single mailbox for transmitting
|
||||
int read(CAN_message_t &CAN_rx_msg);
|
||||
void enableFIFO(bool status = 1);
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue