Nios® V/II Embedded Design Suite (EDS)
Support for Embedded Development Tools, Processors (SoCs and Nios® V/II processor), Embedded Development Suites (EDSs), Boot and Configuration, Operating Systems, C and C++
12691 Discussions

Synchronizing between ISR and main code

Altera_Forum
Honored Contributor II
2,862 Views

Hello all, 

 

What is the best way to ensure safe access to shared data between an ISR and the main code ? 

 

In my application, the ISR reads a packet from the FIFO of a custom UART and saves it in a buffer provided to it upon registration. It then asserts a "ready" flag on the data. The main code polls for this flag and processes the data when it's ready. How can I ensure that during the main code's processing the data the ISR won't jump again and override it ? It may cause corrupted data. Say the main code has read 5 out of 10 bytes and then the ISR has overwritten them. When the main code resumes it will read the remaining 5 bytes from the new message. 

 

Is disabling interrupts during the main's code reading of the data the best option ?  

What are the common guideline when dealing with data synchronization in ISRs for Nios ? 

 

Thanks in advance 

http://forum.niosforum.com/work2/style_emoticons/<#EMO_DIR#>/cool.gif
0 Kudos
3 Replies
Altera_Forum
Honored Contributor II
1,801 Views

Hi eliben, 

 

> What is the best way to ensure safe access to shared data between an 

> ISR and the main code ? 

 

That depends on what you are trying to do -- there&#39;s usually not a single "best way". 

 

> Is disabling interrupts during the main&#39;s code reading of the data the best option ? 

 

In most cases, no. This usually leads to those "mysterious" bugs that show up when 

baud rates, cpu clocks, etc. change. 

 

> What are the common guideline when dealing with data synchronization 

> in ISRs for Nios ? 

 

Here&#39;s a good reference: http://www.xml.com/ldd/chapter/book/ch09.html#t8 (http://www.xml.com/ldd/chapter/book/ch09.html#t8

 

A very simple and common technique is to use a circular buffer. The size of the buffer can 

be adjusted to meet your requirements ... provided you have adequate memory resources.  

 

Here&#39;s a basic overview: 

 

1. The isr reads a "put" pointer, and writes its data. Then updates the put pointer. 

2. The app compares the put pointer to a "get" pointer, when unequal, there is data. 

3. The app reads (copies, consumes, whatever) the data, then updates the get pointer. 

 

Regards, 

--Scott
0 Kudos
Altera_Forum
Honored Contributor II
1,801 Views

The circular buffer is indeed useful, implementing a FIFO in software. I wanted, however, to avoid it and use something simpler, as I don&#39;t need a FIFO. I can, however, use a "trivial" FIFO which has depth 1 and "loses" all subsequent packets until the old ones has been read. 

 

Which brings me to the question - are variable assignment and test atomic in Nios ? What I mean is: 

 

int ready; // is this atomic ? ready = 1; // and is this atomic if (ready == 1) { ... } 

 

I ask because I can make my main code "deassert" the &#39;ready&#39; flag when it finished reading the packet, and the ISR to ignore a new packet if &#39;ready&#39; is still asserted. This way no stomping occurs (overflow messages are lost, which is acceptable). So I wonder whether it&#39;s possible for the ISR to run in the middle of asserting &#39;ready&#39; ? If "ready = 1" is atomic, it certainly can&#39;t.
0 Kudos
Altera_Forum
Honored Contributor II
1,801 Views

Don&#39;t forget to specify variables as "volatile" to prevent them being optimised out. 

 

Sometimes I do tricks such as implementing S/R Flip Flops or counters in hardware, with different memory addresses to set/reset increment/decrement/read them. 

 

For simple FIFO buffers I&#39;ll do e.g. "ISR owns write pointer", "main thread owns read pointer" as Scott says. 

 

I will also use a "main thread is using this" flag as you&#39;ve suggested. So 

//shared volatile int MT_Access; //main thread MT_Access = 1; <do something> MT_Access = 0; //ISR if (0 == MT_Access) { <update something> }
0 Kudos
Reply