Serialization of memory operations and events

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

Serialization of memory operations and events

Serialization of memory operations and events

Introduction


This document is being written to communicate the need for serialization of memory operations and events in an end application.  In addition, directions will be provided to properly serialize memory operations in the end application.  Memory operations and event serialization applies to all Kinetis devices but is only necessary in specific scenarios. These scenarios include memory writes and reads, clearing status flags, and changing mode control operations.


Serialization of memory operations

Serialization of memory operations or events is the action of guaranteeing that said memory operations or events are executed in a specific order.  This action is required when making a change to a peripheral module when that change must complete before continuing with program execution.  Users often make the mistake of assuming that since a peripheral register has been written to, the change is in effect immediately.  However, this is not always the case.  The Kinetis series devices implement a crossbar and peripheral bridge interface system that allows masters (the CPU, DMA, etc.) to interface with the peripherals.  The crossbar allows multiple masters to access the individual peripherals on the bus, and the peripheral bridge functions as a bus protocol translator between the crossbar switch and the slave peripheral bus.  Wait states can be inserted at either stage of the communication channel (crossbar or peripheral bridge).  When a master attempts to access a slave and another master is already accessing this slave or the slave is busy, wait states will be inserted.  If the access is a write, then the master's write is simply pushed to the peripheral bus and the master continues.  However, if the access is a read, the master must wait for a response from the slave.  The slave may insert wait states in this communication as it must finish any commands (or writes) it was previously given before responding.   


Peripheral module changes that require serialization actions include clearing interrupt service flags, changing power modes (of the module or the SOC as a whole), or software triggering a hardware event.  If the events or memory operations are not serialized in these situations, the CPU could go on to execute code with undesired effects.


When do I need to serialize my memory operations and events?

Memory operations and events require serialization anytime the program needs to guarantee that a peripheral access happens before code execution continues.  Examples of these situations includes:

  • Exiting an interrupt service routine (ISR)
  • Changing a clock mode or power mode
  • Configuring a function
  • Configuring a hardware change
  • Software triggering a hardware event



How do I serialize my memory operations and events?

Memory operations are serialized by performing the following operations:

  1. Write the desired peripheral register
  2. Read the peripheral register that was just written
  3. Continue with the subsequent operations

By simply reading the register that was just written, the core is forced to wait for a response from the peripheral module that was written before code execution can continue.   In this manner, it is guaranteed that the peripheral module will have completed the desired operations.


Example event serialization

The following is an example of a function that services the LPTMR ISR flag and implements the event serialization discussed in this document. 


void lptmr_isr(void)

{

  // Declare dummy variable to store the read of the LPTMR0_CSR register

volatile int dummy_var;

/****   STEP #1  ****/

  // Clear the flag; enable interrupts; enable the timer

  LPTMR0_CSR = ( LPTMR_CSR_TEN_MASK | LPTMR_CSR_TIE_MASK | LPTMR_CSR_TCF_MASK  );

  /****  STEP #2  ****/

   // Store CSR register in dummy_var to serialize the clearing of the TCF flag

  dummy_var = LPTMR0_CSR;

}


Conclusion

In conclusion, there are situations where code execution can continue before a peripheral change has taken effect. These situations include clearing interrupt service flags, changing power modes (of the module or the SOC as a whole), or software triggering a hardware event.  Sometimes these events can cause unexpected results or even cause your application to crash.  These situations call for the serialization of memory operations and events, which is simply the act of guaranteeing that events and code are executed in a specific order.  To serialize memory operations, simply follow these directions:

  1. Write the desired peripheral register
  2. Read the peripheral register that was just written
  3. Continue with the subsequent operations

Following these steps, you will be guaranteed that peripheral configurations have taken effect before continuing with the application. 


Comments

good to know. Thanks apps_man.

Hi Chris Brown ,

It is nice documentation , you described this "Serialization of Memory" in very simple way, which i was searching on net far few days.

I really understood this theory in very easy way, but i have one doubt in its implementation point of view.

My doubt in "void lptmr_isr(void)" , in step-1 : we are writing to the peripheral register LPTMR0_CSR ,

to ensure that LPTMR0_CSR register has been written successfully , how the next statement , means

in step -2:dummy_var = LPTMR0_CSR;

is ensuring that the desired value has been written successfully.

are we performing the read operation just for "to elapsed some time? i mean its a dummy instruction ,which only aim to pass some 

time (means wait) so that "write operation"  done during the execution of this instruction.

Please clear my doubt and if possible please give one more example for one of these  :

  • Changing a clock mode or power mode
  • Configuring a function
  • Configuring a hardware change
  • Software triggering a hardware event

Thankyou very much !

Hi DSPIC MIC,

So, no, reading the register back is not just about waiting some amount of time.  When a peripheral is given two commands to perform, it performs them in the order they are received. So let's say for instance we want to write 0x80 to a control register and then 0x12 to a data register.  If the core sends them in that order, the peripheral will register those two writes in that order (0x80 to the control register first, and then 0x12 to the data register next).  And let's say that the core is operating 4 times as fast as the peripheral.  In this case, the core would be able to already have written both values and execute up to 6 more commands (assuming we're only talking about single cycle commands) before the peripheral is done accepting and processing the commands given to it.  

Now, let's say instead, the core is writing to the control register and reading the data register.  And the core is still operating 4 times as fast as the peripheral.  The peripheral would then get the control register write and the data register read.  It (the peripheral) then has to accept and process the control register write before responding to the data register read.  So we are guaranteed that the control register write took place when the core receives the data register read from the peripheral because the peripheral had to accept and process the control register write before even responding to the data register read command. In addition, the core had to stall waiting on the peripheral to respond.  But the biggest and main idea here is that the peripheral had to process the write command before the read command.  

Now, I'll take your suggestion of adding examples to this document but that will not happen soon.  But I do appreciate the feedback. 

Thanks!

Chris  

Hi Chris ,

Thanks for this quick reply , It means that due to "READ after WRITE " core is waiting and not executing any instruction and is on hold (as peripheral is busy from t1 to t4 to write CONTROL register and then from  t5 to t8 to read CONTROL register ). So core have CONTROL  byte on t9 and instructions-3 (INST3 ), INST4 ,INST5 will start executing from at10 onwards.

When writing  to the CONTROL register, READ of control instruction ensure that new configuration written to CONTROL register and could be used in subsequent instructions(INST3 to INST8)’ operations. as i have shown in below figure ( according to may understanding may be not true ). 

  Each commands have single cycle (T) to Fetch -Read-ALU Operaton-Write . 

  T on Peripheral time line  = 4 times of T on Core time line  (as assuming the core is operating 4 times as fast as the peripheral )

pastedImage_8.png 

thankyou!

Hi DSPIC MIC,

Yes. Your diagrams are a good representation of what I was describing.  

Regards,

Chris 

Hi DSPIC MIC,

I'm not following your question.  Could you state it more simply or perhaps in just a different way?

Thanks,

Chris 

Hi Chris,

I am updating this question ,so i have following question.

1. Can we use asm("isb") instruction in place of " read after write " for the serialization of peripheral access.

    means can we use just asm("isb"), in place of  reading dummy_var = LPTMR0_CSR in step 2.

2. Could you please elaborate the differences among DMB,ISB,DSB barrier instruction.

    means i should use DMB, ISB and DSB .

Thanks !

No ratings
Version history
Last update:
‎07-23-2013 02:55 PM
Updated by: