2026-05-24 4:23 AM
I am writing code for a system where a STM32F1 communicates with the 8-bit data bus of another CPU (a 65C816). The STM32's GPIO pins are presented to this CPU as memory-mapped registers via a set of latches and bus transceivers. When the CPU attempts to read or write these addresses, a signal will be sent to PD0 or PD1, which are configured as EXTI pins.
In my STM32 subroutines for reading and writing data, I clear the EXTI_PR and then immediately execute a WFI or WFE instruction. Is a my understanding that on the Cortex-M3, a STR Rx,[Ry,#imm] store takes 2 cycles, but that the 2nd cycle overlaps with the execution of the following instruction, as per section 3.3.2 of the ARM Cortex-M3 TRM. As this cycle would overlap the execution of the WFI or WFE, is a NOP or DSB required in this case to prevent the wait being skipped as a interrupt/event could still be pending at the time of the wait instruction?
// R11 is globally reserved: EXTI_BASE
PORT_READ = GPIOx_IDR + (PORTA_BASE - EXTI_BASE)
PORT_WRITE = GPIOx_ODR + (PORTB_BASE - EXTI_BASE)
// Read logic:
// STM32 clears pending register
// STM32 enters wait
// 65C816 finishes writing data: STM32 interrupt triggered
// STM32 reads data
// repeat for N bytes
// R2 is expected to be 0xFF before call
ReadU16:
STR.W R2,[R11,#EXTI_PR] // clear pending register
WFI // wait for 65C816 to finish write
LDRB.W R0,[R11,#PORT_READ] // read low byte
STR.W R2,[R11,#EXTI_PR] // clear pending register
WFI // wait for 65C816 to finish write
LDRB.W R12,[R11,#PORT_READ] // read high byte
ORRS.W R0,R0,R12,LSL #8 // combine data
BX LR
// Write logic:
// STM32 clears pending register
// STM32 enters wait
// 65C816 starts reading data(*): STM32 event triggered
// STM32 writes data before 65C816 samples bus
// repeat for N bytes
// (*)65C816 only samples data at end of read
// R2 is expected to be 0xFF before call
WriteU16:
STR.W R2,[R11,#EXTI_PR] // clear pending register
WFE // wait for 65C816 to start read
STRB.W R0,[R11,#PORT_WRITE] // write low byte
STR.W R2,[R11,#EXTI_PR] // clear pending register
LSRS R0,#8 // shift high byte
WFE // wait for 65C816 to start read
STRB.W R0,[R11,#PORT_WRITE] // write high byte
BX LR