I have a function that sets up a DMA transfer and starts it. Then it blocks using a semaphore until the interrupt handler indicating that the DMA transfer has completed unblocks the semaphore.
When I enter the blocking semaphore the core appears to stop executing code and within a second the RGB led goes white and then flashes blue, cyan to breathing cyan. However I am unable to reconnect to the serial port to determine if the core is still running or if it has hung.
I am very confused by inline assembly. I have read this thread -
and it looks like a mixture of AT&T and Intel format. The registers are prefixed with %
but the source and destination registers are reversed.
I'm trying to implement a semaphore to act as a messaging system allowing a blocked function to continue from an interrupt handler.
Here is the ARM assembly code on page 19 from ARM Synchronization Primitives
; sem_dec
; Declare for use from C as extern void sem_dec(void * semaphore);
EXPORT sem_dec
sem_dec PROC
1 LDREX r1, [r0]
CMP r1, #0 ; Test if semaphore holds the value 0
BEQ %f2 ; If it does, block before retryingARM Synchronization Primitives
SUB r1, #1 ; If not, decrement temporary copy
STREX r2, r1, [r0] ; Attempt Store-Exclusive
CMP r2, #0 ; Check if Store-Exclusive succeeded
BNE %b1 ; If Store-Exclusive failed, retry from start
DMB ; Required before accessing protected resource
BX lr
2 ; Take appropriate action while waiting for semaphore to be incremented
WAIT_FOR_UPDATE ; Wait for signal to retry
B %b1
ENDP
; sem_inc
; Declare for use from C as extern void sem_inc(void * semaphore);
EXPORT sem_inc
sem_inc PROC
1 LDREX r1, [r0]
ADD r1, #1 ; Increment temporary copy
STREX r2, r1, [r0] ; Attempt Store-Exclusive
CMP r2, #0 ; Check if Store-Exclusive succeeded
BNE %b1 ; Store failed - retry immediately
CMP r0, #1 ; Store successful - test if incremented from zero
DMB ; Required before releasing protected resource
BGE %f2 ; If initial value was 0, signal update
BX lr
2 ; Signal waiting processors or processes
SIGNAL_UPDATE
BX lr
ENDP
Here is my inline assembly code
// sem_dec
// Declare for use from C as extern void sem_dec(void * semaphore);
void sem_dec(volatile uint32_t *semaphore) {
asm volatile ("@sem_dec \n"
"1: LDREX r1, [r0] \n"
" CMP r1, #0 \n" // ; Test if semaphore holds the value 0
" BEQ 2f \n" // ; If it does, block before retrying
" SUB r1, #1 \n" // ; If not, decrement temporary copy
" STREX r2, r1, [r0] \n" // ; Attempt Store-Exclusive
" CMP r2, #0 \n" // ; Check if Store-Exclusive succeeded
" BNE 1b \n" // ; If Store-Exclusive failed, retry from start
" DMB \n" // ; Required before accessing protected resource
" BX lr \n"
"2: \n" // ; Take appropriate action while waiting for semaphore to be incremented
" WAIT_FOR_UPDATE \n" // ; Wait for signal to retry
" B 1b \n"
: [r0] "=r" (semaphore));
}
// sem_inc
// Declare for use from C as extern void sem_inc(void * semaphore);
void sem_inc(volatile uint32_t *semaphore) {
asm volatile ("@sem_inc \n"
"1: LDREX r1, [r0] \n"
" ADD r1, #1 \n" // ; Increment temporary copy
" STREX r2, r1, [r0] \n" // ; Attempt Store-Exclusive
" CMP r2, #0 \n" // ; Check if Store-Exclusive succeeded
" BNE %b1 \n" // ; Store failed - retry immediately
" CMP r0, #1 \n" // ; Store successful - test if incremented from zero
" DMB \n" // ; Required before releasing protected resource
" BGE %f2 \n" // ; If initial value was 0, signal update
" BX lr \n"
"2: \n" // ; Signal waiting processors or processes
" SIGNAL_UPDATE \n"
" BX lr \n"
: [r0] "=r" (semaphore): );
}
I'm a bit confused as to if I have the assembly correct. I don't have a debugging environment setup yet so it's very difficult to determine what the assembly language is doing.