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
|
#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;
|
uint32_t out = 0;
|
||||||
if (CAN_tx_msg.flags.extended == true) { // Extended frame format
|
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)
|
if (_channel == _CAN1)
|
||||||
{
|
{
|
||||||
// Check if the mailbox is empty
|
CAN1->sTxMailBox[mb_num].TDTR &= ~(0xF);
|
||||||
if (CAN1->sTxMailBox[0].TIR & 0x1UL) {
|
CAN1->sTxMailBox[mb_num].TDTR |= CAN_tx_msg.len & 0xFUL;
|
||||||
//Serial.println("transmit Fail");
|
CAN1->sTxMailBox[mb_num].TDLR = (((uint32_t) CAN_tx_msg.buf[3] << 24) |
|
||||||
return -1; // transmit of the previous message has failed
|
((uint32_t) CAN_tx_msg.buf[2] << 16) |
|
||||||
}
|
((uint32_t) CAN_tx_msg.buf[1] << 8) |
|
||||||
else { // mailbox is empty, so it's ok to send new message
|
((uint32_t) CAN_tx_msg.buf[0] ));
|
||||||
CAN1->sTxMailBox[0].TDTR &= ~(0xF);
|
CAN1->sTxMailBox[mb_num].TDHR = (((uint32_t) CAN_tx_msg.buf[7] << 24) |
|
||||||
CAN1->sTxMailBox[0].TDTR |= CAN_tx_msg.len & 0xFUL;
|
((uint32_t) CAN_tx_msg.buf[6] << 16) |
|
||||||
CAN1->sTxMailBox[0].TDLR = (((uint32_t) CAN_tx_msg.buf[3] << 24) |
|
((uint32_t) CAN_tx_msg.buf[5] << 8) |
|
||||||
((uint32_t) CAN_tx_msg.buf[2] << 16) |
|
((uint32_t) CAN_tx_msg.buf[4] ));
|
||||||
((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] ));
|
|
||||||
|
|
||||||
// Send Go
|
// Send Go
|
||||||
CAN1->sTxMailBox[0].TIR = out | STM32_CAN_TIR_TXRQ;
|
CAN1->sTxMailBox[mb_num].TIR = out | STM32_CAN_TIR_TXRQ;
|
||||||
return 1; // transmit done
|
}
|
||||||
|
#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 defined(CAN2)
|
||||||
if (_channel == _CAN2)
|
if (_channel == _CAN2)
|
||||||
{
|
{
|
||||||
// Check if the mailbox is empty
|
// Check if one of the three mailboxes is empty
|
||||||
if (CAN2->sTxMailBox[0].TIR & 0x1UL) {
|
while(CAN2->sTxMailBox[mailbox].TIR & 0x1UL && mailbox++ < 3);
|
||||||
//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] ));
|
|
||||||
|
|
||||||
// Send Go
|
if (mailbox >= 3) {
|
||||||
CAN2->sTxMailBox[0].TIR = out | STM32_CAN_TIR_TXRQ;
|
//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
|
return 1; // transmit done
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,6 +50,13 @@ typedef const struct
|
||||||
|
|
||||||
typedef enum CAN_PINS {DEF, ALT, ALT2,} CAN_PINS;
|
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
|
#ifndef CAN2
|
||||||
typedef enum CAN_CHANNEL {_CAN1,} CAN_CHANNEL;
|
typedef enum CAN_CHANNEL {_CAN1,} CAN_CHANNEL;
|
||||||
#elif defined CAN2
|
#elif defined CAN2
|
||||||
|
@ -76,6 +83,7 @@ class STM32_CAN {
|
||||||
private:
|
private:
|
||||||
void CANSetGpio(GPIO_TypeDef * addr, uint8_t index, uint8_t speed = 3);
|
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 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();
|
uint8_t CANMsgAvail();
|
||||||
void SetTXRX();
|
void SetTXRX();
|
||||||
|
|
||||||
|
@ -83,7 +91,8 @@ class STM32_CAN {
|
||||||
STM32_CAN(const CAN_CHANNEL channel, CAN_PINS pins) : _channel (channel), _pins (pins) { };
|
STM32_CAN(const CAN_CHANNEL channel, CAN_PINS pins) : _channel (channel), _pins (pins) { };
|
||||||
void begin();
|
void begin();
|
||||||
void setBaudRate(uint32_t baud);
|
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);
|
int read(CAN_message_t &CAN_rx_msg);
|
||||||
void enableFIFO(bool status = 1);
|
void enableFIFO(bool status = 1);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue