Arduino-STM32-CAN icon indicating copy to clipboard operation
Arduino-STM32-CAN copied to clipboard

feature request: support multiple transmit mailboxes

Open i-make-robots opened this issue 2 years ago • 12 comments

Currently sTxMailBox array appears to be hard coded to use box 0, tho (on the STM32F405) there are at least 3. I'd love to see some code that identifies an available mailbox and uses that, or warns if there are none available.

i-make-robots avatar Aug 25 '23 01:08 i-make-robots

Advanced use of BxCan

Skip if you don't need advanced usage.
Advanced usage has different purposes depending on the requirements of the application.
So I can't give you a concrete code example.

About transmission

STM32 has three transmit(TX) mailboxes.
Three TX mailboxes are provided to the software for setting up messages.
This sample code uses only the first TX mailbox and blocks the application until the send is successfully completed.
There are two ways to know if the send was successful without blocking.
Read the reference manual carefully and modify the source code as needed.

  • Uses a transmission completion interrupt
    You need to set the CAN interrupt enable register (CAN_IER) appropriately.

  • Check TX mailbox space before sending
    An application can store transmission requests in three TX mailboxes simultaneously.
    When there are requests for multiple TX mailboxes, the transmission scheduler decides which mailbox has to be transmitted first.
    You can specify which mailbox has priority using the CAN Master Control Register (CAN_MCR).
    You can tell if a mailbox is free using the CAN Transmit Status Register (CAN_TSR).
    When all three TX mailboxes are pending, no new messages can be sent until the transmit is canceled or completed.
    When all three TX mailboxes are pending, you can choose to cancel the pending transmission, wait until the transmission is complete, or give up on the new transmission.
    This choice depends on your application requirements.
    When all three TX mailboxes are pending for a long time, it could be a transmission error.
    CAN Error Status Register (CAN_ESR) should be checked.

About reception

STM32 has two receive(RX) mailboxes.
Each RX Mailbox allows access to a 3-level depth FIFO, the access being offered only to the oldest received message in the FIFO.
This sample code uses only the first RX mailbox.
The RX mailbox is closely related to the receive filter settings.
By properly setting the receive filter, you can sort the received messages into two RX Mailboxes.
For example, high priority messages can be stored in the first RX MailBox and low priority messages can be stored in the second RX MailBox.
Read the reference manual carefully and modify the source code as needed.

nopnop2002 avatar Aug 25 '23 05:08 nopnop2002

Thank you! That seems to match what I read and gives me confidence to proceed.

i-make-robots avatar Aug 25 '23 16:08 i-make-robots

I've had much success now. Thank you for your help.

I've been reading the RM0090 manual for the STM32F405 as you suggested. One thing still eludes me - how do I create an interrupt for bxCAN? I want to catch arriving messages before the three mailboxes overflow. ChatGPT only tells me how to interrupt on a pin change :( I'm sorry to take up your valuable time. Is there an example in the files that I missed?

i-make-robots avatar Sep 18 '23 16:09 i-make-robots

First of all, to write a conclusion, you cannot use bxCan interrupts with Arduino core support for STM32.

The following steps should get the transmit interrupt working, but then it stops.

Add this in CANInit()

  CAN1->IER  |=   0x1UL;                // Set to Transmit mailbox empty interrupt enable

Add this in Setup()

  NVIC_SetPriority(CAN1_TX_IRQn, 1);
  NVIC_EnableIRQ(CAN1_TX_IRQn);

Transmit interrupts are now enabled.

STM32F4 Interrupt handlers are defined with the following names.

  .word     CAN1_TX_IRQHandler                /* CAN1 TX                      */
  .word     CAN1_RX0_IRQHandler               /* CAN1 RX0                     */
  .word     CAN1_RX1_IRQHandler               /* CAN1 RX1                     */
  .word     CAN1_SCE_IRQHandler               /* CAN1 SCE                     */


  .word     CAN2_TX_IRQHandler                /* CAN2 TX                      */
  .word     CAN2_RX0_IRQHandler               /* CAN2 RX0                     */
  .word     CAN2_RX1_IRQHandler               /* CAN2 RX1                     */
  .word     CAN2_SCE_IRQHandler               /* CAN2 SCE                     */

This is a week function, so you can replace it.

extern "C" void CAN1_TX_IRQHandler (void)
{
  Serial.println("CAN1_TX_IRQHandler");  
}

This interrupt function is called when transmission is completed, but when this function ends, it becomes HALT.

You can use a debugger with Arduino IDE 2.x.

You can see that this function is called by setting BreakPoint to this function.

It crashes when I proceed with StepOver. It has been reported to STM, but no countermeasures have been taken yet.

nopnop2002 avatar Sep 18 '23 23:09 nopnop2002

Interesting! Here's what I did https://github.com/MarginallyClever/Daisy-Driver-2.0-firmware/commit/465ec3dbeb831ee2f49fd6a6648da8fd7377a56a

in Arduino 2.2.1 with https://github.com/stm32duino/BoardManagerFiles/raw/master/package_stmicroelectronics_index.json

void CANInit() {
  // ...

  // attach message pending interrupt method
  NVIC_SetPriority(CAN1_RX_IRQn, 1);
  NVIC_EnableIRQ(CAN1_RX_IRQn);

  // Enable FIFO Message Pending Interrupt 
  CAN1->IER |= CAN_IER_FMPIE0 | CAN_IER_FMPIE1;
  DEBUGLN("CAN1 interrupt enabled.");

  return true;
}

int CANstate2,CANstate1;
void CAN1_RX0_IRQHandler(void) {
  light.setColor(0,CANstate1,CANstate2);
  CANstate2 = (CANstate2==0? 255 : 0);
  CAN1->RF0R |= CAN_RF0R_RFOM0;  // release FIFO
  CAN1->IER |= CAN_IER_FMPIE0;  // enable interrupt
}

void CAN1_RX1_IRQHandler(void) {
  light.setColor(0,CANstate2,CANstate2);
  CANstate1 = (CANstate1==0? 255 : 0);
  CAN1->RF1R |= CAN_RF1R_RFOM1;  // release FIFO
  CAN1->IER |= CAN_IER_FMPIE1;  // enable interrupt
}

I confirm this problem case. No response from STM tells me nobody write the firmware this way because a) stm32cubeide is what most people use or b) polling should be enough or c) almost nobody writes CAN stuff for this board.

i-make-robots avatar Sep 19 '23 23:09 i-make-robots

Does light.setColor() run correctly?

nopnop2002 avatar Sep 19 '23 23:09 nopnop2002

on it's own, sure. it's just banging the pins.

void LED::setColor(uint8_t r,uint8_t g,uint8_t b) {
  analogWrite(PIN_PWM_RGB_R,r);
  analogWrite(PIN_PWM_RGB_G,g);
  analogWrite(PIN_PWM_RGB_B,b);
}

in the interrupt? no. the light turns on once and then stays there.

i-make-robots avatar Sep 20 '23 15:09 i-make-robots

CAN1_RX0_IRQHandler is a C language function. When using in C++, You need to change:

//void CAN1_RX0_IRQHandler(void) {
extern "C" void CAN1_RX0_IRQHandler(void) {
  digitalWrite(LED, HIGH);
}

LED will turn on. But HALT occurs when exiting from an interrupt function.

nopnop2002 avatar Sep 20 '23 23:09 nopnop2002

It hated external “c”Sent from my iPhoneOn Sep 20, 2023, at 4:44 PM, nopnop2002 @.***> wrote: You need to change: //void CAN1_RX0_IRQHandler(void) { extern "C" void CAN1_RX0_IRQHandler(void) { But don't work.

—Reply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you authored the thread.Message ID: @.***>

i-make-robots avatar Sep 21 '23 02:09 i-make-robots

Any idea why HALT occurs?

i-make-robots avatar Oct 02 '23 22:10 i-make-robots

Probably the default Week function implementation included in the core library is incomplete.

I think the problem can be solved by changing the interrupt vector and using your own interrupt function will solve the problem, but I don't know how to change the interrupt vector from default.

STM is not proactive in resolving this issue. I have asked STM to suggest a solution, but have not received any response. Please Ask STM to suggest a solution.

nopnop2002 avatar Oct 02 '23 23:10 nopnop2002

I have. https://community.st.com/t5/stm32-mcus-products/stm32f405-can-rx-interrupt-halts/m-p/592491

i-make-robots avatar Oct 03 '23 17:10 i-make-robots