cancel
Showing results for 
Search instead for 
Did you mean: 

Is a delay required between a write to EXTI_PR and a WFI or WFE instruction?

Haruki
Associate

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
0 REPLIES 0