Atomic like operation (or disble irq)

tjohansen wrote on Friday, February 24, 2012:

Hi forum

In my case, I have the classic example of task updating variables, that are used in a different task,
I know the variable update is “atomic” if the variable can be updated in one instruction. (8, 16 or 32 bit)

But in my system I do have 16 bit SDRAM interface, so updating a 32 bit variable, would require more then one instruction.
Or am I wrong about that??

I could, of course use the macros portENTER_CRITICAL and  portEXIT_CRITICAL. I would like to avoid this because the variables are written and read often.

When doing the the write and read operation on them I could also disable interrupts. But is that allowed by FreeRTOS? Wouldn’t that make the scheduler run unexpected?

Thomas

davidbrown wrote on Friday, February 24, 2012:

If your cpu is capable of reading and writing 32-bit at a time, then such accesses are atomic - regardless of the width of the memory (unless you have multiple bus masters, and a DRAM controller that splits up such accesses, but that’s highly unlikely).

Remember, of course, that only each read or write of each variable is atomic - read/modify/write operations are not atomic on most cpus (though they /are/ atomic on some CISC cpus), and there is no guarantee of atomicity when accessing multiple variables.

Look at the generated assembly code for the source code in question - then you can easily see what instructions are used.

tjohansen wrote on Friday, February 24, 2012:

Hi

My CPU is 32 bit. Its a ARM Cortex M3,

I could look at the ASM code generated. But if the used instruction doesn’t make the operation atomic?

Also, If need to write variable >32 bit (Could be strings or structs, than I need to do something atomic.

So is using portENTER_CRITICAL and  portEXIT_CRITICAL the only way in FreeRTOS

Im using the LPC1788 CPU

Thomas

davedoors wrote on Friday, February 24, 2012:

If the task is updated in one task, and only used (read, not written) in the other task, then you don’t need any mutual exclusion provided the width of the variable is equal to the natural word size of the CPU. In this case the word size is 32 bits, so if your variable is 32 bits then you should be ok without anything.

davedoors wrote on Friday, February 24, 2012:

Oops. Meant if the **variable ** is updated in one task.

richard_damon wrote on Friday, February 24, 2012:

As it has been said, bus cycle atomisity isn’t needed if you have instruction level atomisity unless you have something else that might access the memory (like a multiprocessor system).

If you have a 32 bit processor, and the memory signals that it is only 16 bits wide, it is quite possible that the processor will do the access atomically.

portENTER/EXIT_CRITICAL is the normal way of doing this and is fairly light weight, but if you need to be even faster you could use an interrupt disable/enable pair (which is similar to what what the CRITICAL macros use) if:

1)  You know you are not inside a CRITICAL section, or you know that your method is not incompatible with nesting with the CRITICAL section macros (they try to only mask interrupt that might interact with FreeRTOS so there MAY be another way to disable interrupts that can nest with the CRITICAL section macros)

2) You disable interrupt time is short enough that you are not going to unacceptably impact interrupts that the critical section macros leave enabled.

Disabling/Enabling the interrupts will not impact the tick interrupt/scheduler any more than the critical section macros will. The impact that is there is the reason you need to keep critical sections short.