HELP! RE-ENTRANT CAN API

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

HELP! RE-ENTRANT CAN API

1,779 Views
DETP
Contributor I
Hi,

I am writing a CAN API which can be called by two or more threads. This can be achieved if the interfaces provided are re-entrant. The single interface that need to be re-entrant is CanSend() which takes in two field- pointer to CAN FRAME and priority of the CAN MESSAGE for arbitration internal to node (i.e if previously message with priority low is loaded but now another message with priority high has come, and low priority message is not yet transmitted so abort it and transmit current high priority message.). The problem is how can i make a CanSend() re-entrant as the data copy of CAN FRAME to CAN REGISTERS (arbitration field, control field, 8 bytes data etc) cannot be an atomic operation unless i disable interrupts! Blocking a thread on calling this function is not allowed, so semaphore to indicate resource been aquired is ruled out! Also if another thread(say T2) pre-empts the current thread (say T1) which has finished copying 50% of CAN FRAME to CAN REGISTERS, then the T2 copies all CAN FRAME data to h/w registers and transmits.... then gives control back to T1, T1 now assumes 50% copy is over so resumes copy from 50% which results in bad FRAME, as first half had been overwritten by T2! Also I need to take care that HIGH PRIORITY messages are transmitted first. There can be N number of threads pre-emting each other.....life becomes miserable. CAN somebody help me out on this?

Regards,
DETP
Labels (1)
0 Kudos
1 Reply

283 Views
rhinoceroshead
Contributor I
Why can't you use a flag to indicate when to abort?  Before CanSend() starts running, you can look at a flag (global variable) to see the resource's availability and set the flag to show the priority of the current frame to transmit.  If your priority is higher than what's already being copied, then change the flag to show your priority and start copying data to registers.  During the frame-copy loop of CanSend() you can keep checking that flag to see if it has changed to a higher priority, ie another thread took over, and if so, break from the loop and then have CanSend() return a 1 to indicate unsuccessfull transmisison.  Then when the function completes a transmisison, have it clear the flag and return a 0 for successful transmission.  Then when you call CanSend(), make it repeat the call if it wasn't successfull:  while(CanSend(dataStart, priority));  That way it will start from the beginning.
 
One thing to add.  If you're allowing other threads to interrupt the data copy portion, then you're already stalling on high priority frames.  You might actually get better performance if you make the frame arbitration occur before you start copying data into the CAN registers and then disable interrupts once you've started.

Message Edited by rhinoceroshead on 04-30-200612:04 PM

0 Kudos