nopnop2002 / Arduino-STM32-CAN

Can Example for Arduino Core STM32
205 stars 51 forks source link

feature request: support multiple transmit mailboxes #60

Open i-make-robots opened 1 year ago

i-make-robots commented 1 year ago

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.

nopnop2002 commented 1 year ago

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.

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.

i-make-robots commented 1 year ago

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

i-make-robots commented 1 year ago

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?

nopnop2002 commented 1 year ago

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.

i-make-robots commented 1 year ago

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.

nopnop2002 commented 1 year ago

Does light.setColor() run correctly?

i-make-robots commented 1 year ago

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.

nopnop2002 commented 1 year ago

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.

i-make-robots commented 1 year ago

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 commented 1 year ago

Any idea why HALT occurs?

nopnop2002 commented 1 year ago

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.

i-make-robots commented 1 year ago

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