I am reading S32K-RM rev 13 on FlexCAN and the BUSY bit.
Section 55.5.6.1 "Move-in" mentions the BUSY bit (bit 0 of CODE) is set whilst the move-in process is taking place (move Rx SMB to the MB) so the CPU should not read the MB until BUSY is clear. This will be a wait loop in my code and so I need a timeout to protect it. I could not find any mention of the time taken for the move-in process.
Section 55.5.6.2 "Move-out" does not mention the BUSY bit. Is it set whilst the move-out happens? I am thinking the BUSY bit would then indicate FlexCAN is reading out the data from the MB into the Tx SMB so CPU should not update the MB data. If the BUSY bit is set in this case then the reference manual needs updating to say so (or please point me to the section that does explain this).
Questions
Thanks
Darren
Hi,
Tables 55-11 and 55-12 shows possible CODE field values for RX and TX MBs.
For TX MBs a CODE[0] has different meaning and is only considered if abort mechanism is enabled and MB aborted. See more in chapter 55.5.7.1 Transmission abort mechanism.
1),2) timing for BUSY bit and move-in/-out is not specified, but chapter 55.5.9.8 Arbitration and matching timing shows duration of move-in/-out window, which is 2 CAN bits
3) move-out is not indicated to user. Once TX MB is prepared for transmission (CODE field written) it participates in the arbitration process and is eventually transmitted according to its priority. At the end of the successful transmission CODE field is updated accordingly and MB flag is set. So you should use MB flag as indication new message can be prepared for transmission.
BR, Petr
Thanks for the quick reply and the timeout references in 55.5.9.8, that's great.
I am reusing the same MB to send TX messages and send remote frame requests to a device (I talk to many devices at the same time [subject to message-ID priority], so I can only use 1 MB per device, i.e. 2 MBs per device exceeds the maximum number of MBs).
We are reusing MBs throughout our minor frame to send/receive CAN messages. I am trying to reconfigure the MB in a graceful way, which is why I set MCR.AEN=1 to allow the ABORT mechanism on TX MBs and for RX MBs the only option is the inactivation mechanism.
Since I am using the same MB for both RX and TX (at different times) I keep an internal record of what the MB was last used for (RX or TX) so I know whether to use the ABORT or RX inactivation on the next configure MB.
As I see it, the RX inactivation "suffers" from potential loss of a message if the "arbitration/move-in" has decided to use this MB being reconfigured. I don't consider this a big loss since we are going to be re-configuring the MB anyway so any previous RX message has already been handled. Also I am not expecting any incoming RX at that time.
Re-reading 55.5.7.1 and 55.5.1 I am a bit confused over the ABORT mechanism.
55.5.1 step 1 Why check IFLAG1 bit is set if we are going to clear it - by writing a 1? Why not just write the 1?
55.5.1 step 3 Again, is the "wait timeout" another 2 CAN bit times like the others? I would expect this to allow "move-out" from MB to Tx SMB. Once in the Tx SMB it will be transmitted on the bus (since it is consistent data). I am correct thinking there is only one Tx SMB (next message to be transmitted) but one Rx SMB per MB?
55.5.7.1 paragraph 3 onwards. Once this TX MB has been arbitrated/decided to be the one that is next to be transmitted the move-out copies the MB data to Tx SMB and starts transmitting on the bus. If the CPU writes ABORT to CODE before the start of the move-out then the abort will succeed, but once the move-out has started or data is being transmitted, then the "point of no return" has been reached and so the CPU writing ABORT to CODE does not work. In both cases IFLAG1 bit is set either after the transmission on the bus (not just when written to the Tx SMB) or when the abort has been accepted/worked. Reading the CODE field and getting ABORT shows the abort worked and getting any other value indicates the abort failed and the message was transmitted. In either case this MB is now no longer in any arbitration processing since it aborted or transmitted its data and so the CPU is free to update the MB. Is this all correct?
55.5.7.1 list of conditions - I am confused over the "kept pending until one of the following" and paragraph a bit later where the "frame is not transmitted" if "only one of the above conditions is reached". Am I over-thinking this all?
Is my code really just....
IFLAG1 bit = 1 (forces HW to set bit to 0)
CODE = ABORT
while IFLAG1 bit == 0 or 2 CAN bit timeout
{ /* wait */ }
if CODE == ABORT then aborted else transmitted /* do I care? */
IFLAG1 bit = 1 (acknowledge the abort/transmission)
Now I am free to update the MB and then finally set CODE to the new required setting
Thanks
Darren
Hi,
step1) MB flag is indication of successful transmission/reception, so commonly it is checked and if set you can clear it (have to if AEN is set) and you can skip steps 2-5 as abort is not needed if previously prepared message was send successfully
step3) a time will vary and can be up to full CAN frame long. If MB was not selected as winner during arbitration, so still not moved-out into TX SMB, a ABORT is immediately done I think. If written after message was already loaded into the Tx SMB for transmission, a message can be fully transmitted so flag will be set after that.
There is no SMBs per each MBs, module includes one TX SMB and 2 RX SMBs.
pargraf 3 onwards) yes, you are right
list of conditions) those five conditions lists a situation when pending abort request is acknowledged/performed. In fact message is not successfully transmitted for any of those conditions.
So if none of condition happens a message is successfully transmitted on the bus, MB flag set and CODE field changes to INACTIVE (DATA->INACTIVE)
If any condition is reached, a frame is not successfully transmitted on the bus, MB flag is set, CODE changed to ABORT.
BR, Petr
Sorry for the long delay. A few more questions.
For remote frame requests does reading the CODE/STATUS register and getting RANSWER lock the mailbox (like FULL/OVERRUN do)? I have IRMQ = 0. Section 55.5.7.3 "Mailbox lock mechanism" NOTE implies Rx MB is locked if it reads back INACTIVE or EMPTY (footnote says EMPTY locks because I have IRMQ = 0, also I am not using the FIFO). This implies RANSWER will lock the mailbox, however, the first paragraph of this section talks about locking only on "FULL or OVERRUN". Which is it?
I am asking since I want to know when it is safe to update the mailbox data on the slave. If I read CODE/STATUS and get RANSWER I know that the slave is waiting for the RFR from the master. If the mailbox is locked on reading RANSWER then I can safely update the data before unlocking it to restore normal operation. If I read CODE/STATUS and get TANSWER I know the slave is queued up to send the slave data. Therefore, I can try and abort the transmission, if that works then I can update the mailbox data and reset the CODE/STATUS back to TANSWER.
Is this the preferred way of updating slave data?
One of my concerns is that if I read CODE/STATUS and then say it is RANSWER and the mailbox is NOT locked then how do I synchronise with the FLEXCAN? It can change the CODE/STATUS at any time so if I read it and then take action on the result the CODE/STATUS could have changed to the other option (RANSWER <--> TANSWER) within that small window and then I am updating based on the wrong situation.
Thanks
Hi,
MB with RANSWER code is not locked when reading it. But you are right with synchronization to incoming messages. I think you can reuse MB flag for that, this will be set once remote response is transmitted.
BR, Petr
We are converting an old project (non-Arm chip) to use the S32K146 chip
I have done some more testing on remote frames and found some weird effects that I need help understanding
Setup
-----
Here are (what I think) are the relevant CAN settings that I am using
CTRL1.LBUF=0 - Tx highest priority (lowest ID) message (and MCR.LPRIOEN=0)
CTRL1.LOM=0 - Tx allowed
MCR.RFEN=0 - no Rx FIFO
MCR.SRXDIS=0 - allow Rx of my own Tx'd messages (but I don't use it)
MCR.IMRQ=0 - our old project used a global mask
- I have set all 3 masks RXFGMASK, RX14MASK and RX15MASK
- to the same value, although we don't use mailboxes 14 or 15)
MCR.LPRIOEN=0 - Tx highest priority (lowest ID) message (and CTRL1.LBUF=0)
MCR.AEN=1 - the reference manual says this is a cleaner way of dealing
- with TXs (especially a standard TX, i.e. CODE = DATA, RTR = 0)
MCR.FDEN=0 - standard CAN2.0B 29-bit IDs (and RAMn.IDE=1)
CTRL2.RRS=0 - FLEXCAN automatically sends the remote frame response
CTRL2.EACEN=0 - Ignore RTR bit in ID matching
For the remote frame responses (my problem mailboxes)
RAMn[mb + 0].SRR=0 - compulsory for 29-bit IDs
RAMn[mb + 0].IDE=1 - standard CAN2.0B 29-bit ID (and MCR.FDEN=0)
RAMn[mb + 0].RTR=0 - send data frame as the remote frame response (see table 55-12 TANSWER)
Other key parts that I found in the reference manual
55.5.7.2 "Mailbox inactivation"
Inactivation of transmission mailboxes must be performed just when MCR[AEN] is
deasserted.
I configure the mailbox once (as a remote frame response - RANSWER) in RAMn[mb+0] and RAMn[mb+1]
Every minor frame (20ms) I want to update the message data dword1 (RAMn[mb+2]) and dword2 (RAMn[mb+3])
If I just update message data dword1 and dword2 I sometimes get messages with dword1 from one message and dword2 from a different message (one old dword, one new dword)
For example, several frames updating dword1=0x11, dword2=0x11
dword1=0x22, dword2=0x22
dword1=0x33, dword2=0x33
dword1=0x44, dword2=0x44
sometimes CAN will transmit 0x33,0x22 (new,old) - or it might have been 0x22, 0x33 (I can't remember)
This is clearly unacceptable to have, effectively, corrupted messages so I added protection around the updates
First I tried to read CODE to determine RANSWER or TANSWER
In TANSWER (like a standard TX DATA+RTR=0) there are 3 options
I can ABORT the mb as it is a Tx MB (is this true?)
In tests I found that if the mb is in option
In all 3 options I concluded that 4us after the ABORT the RAMn[mb+2 and +3] are free for the CPU to access
Therefore, I can safely update the RAMn[mb+2 and +3] words
After the update I will need to set CODE back to TANSWER
This will cause a second transmission if TANSWER switched to RANSWER (during dword1/2 update and before I set CODE to TANSWER)
If I simply read CODE=RANSWER (or IFLAG1 bit set) I could not write CODE=TANSWER to avoid this
However, that also means if I read CODE != RANSWER (should be ABORT or TANSWER) then proceeded to write CODE = TANSWER
there is a (very tiny) small window where CODE could switch to RANSWER between the read and the write
Therefore, it is not impossible to prevent a 2nd transmission (although it would be extremely unlikely)
Because of this tiny window I decided to simply INACTIVATE the mb and simply accept the warnings in the manual...
Because you will not be able to synchronize the CODE field update with the FlexCAN
internal processes, an inactivation can have the following consequences:
• A frame in the bus that matches the filtering of the inactivated Rx mailbox may be
lost without notice, even if there are other mailboxes with the same filter.
• A frame containing the message within the inactivated Tx mailbox may be
transmitted without setting the respective IFLAG
In RANSWER there are 2 options (?)
So again reading CODE = RANSWER it is possible that it switches to TANSWER before we try and process the RANSWER state
It is not possible to lock the mb when reading RANSWER (reference manual states EMPTY[since IRMQ=0], FULL or OVERRUN)
Therefore, I need to INACTIVATE the mb when I read CODE = RANSWER to allow "safe" updating of the message data
After the update I need to set CODE back to RANSWER
This means that if the RFR from the master comes in whilst the mb is INACTIVE I will lose the request and so won't send the response
This is not the end of the world as I am hoping we won't always be updating the message data when the RFR comes in
During further testing I found that I could not write to the mb RAMn area if IFLAG1 was set so I had to clear it first
So my final code for updating mb data looked like this
cs_reg = CAN0.RAMn[mb+0]; // read CODE/STATUS
CAN0.IFLAG1 = 1 << mb; // clear previous updates
if CAN0.RAMn[mb+0] CODE == TANSWER
{
CAN0.RAMn[mb+0] = INACTIVE
CAN0.RAMn[mb+2] = dword1
CAN0.RAMn[mb+3] = dword2
CAN0.RAMn[mb+0] = cs_reg (but CODE=TANSWER)
}
else // RANSWER
{
CAN0.RAMn[mb+0] = INACTIVE
CAN0.RAMn[mb+2] = dword1
CAN0.RAMn[mb+3] = dword2
CAN0.RAMn[mb+0] = cs_reg (but CODE=RANSWER) // RANSWER not TANSWER
}
When I ran this I found that after a while (minutes or seconds) my CAN remote frame responses stopped being sent
Debugging I found that after writing "CAN0.RAMn[mb+0] = INACTIVE" in the TANSWER block no further writes to RAMn worked!
I then set IFLAG1 bit (before each write) but that still didn't let me write to RAMn
I also read the free running TIMER in case it thought it was locked
Do you know why this is?
Have I made a glaring mistake?
It seems that the CPU cannot synchronise access protection on RANSWER/TANSWER since they can change at any time.
My next line of thought is to try and set AEN=0 but this will mean my standard TX processing (elsewhere) will no longer have the clean approach but the dirty INACTIVE approach. With AEN=0 I am hoping to avoid the warning mentioned earlier in this post about 55.5.7.2 "Mailbox inactivation"
If this AEN=0 does not work (I can test it next week) then I am thinking possibly setting RRS=1 so the RFR is stored in the mailbox and turning on the IRQ for this mb. I can then use an IRQ handler to turn the mb into a TX mb and send the data. This will allow me to synchronise between my background "message update" function and the IRQ to allow data-coherent access to the dword1/2 which seems to not be possible between the CPU and FLEXCAN. Your thoughts on this approach would be useful.
Thanks for reading this far
Hi,
quite long description...my feedback will be much shorter
- If AEN is set then, if MB flag is set, writing to MB is blocked. The CPU is not able to update it until the MB flag is negated by the CPU.
- if RRS=0, it is not recommended to update MB data the way you tried. There can be safe time after response is send and so the MB flag set. Update must be done before new remote request is sent by other node.
- using RRS=1 would be best option, I think. As you wrote, RFR is stored in MB and then you can send remote response as you want/need.
BR, Petr