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: Write the desired peripheral register Read the peripheral register that was just written 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: Write the desired peripheral register Read the peripheral register that was just written Continue with the subsequent operations Following these steps, you will be guaranteed that peripheral configurations have taken effect before continuing with the application.
View full article