9 years, 8 months ago.

GCC for ARM Offline Toolchain won't Compile asm instructions

I am using the following library: https://developer.mbed.org/users/bridadan/code/WS2812/ and wanted to build it using the gcc for ARM compiler offline. When I run the makefile it throws an error saying "error: 'nop' was not declared in this scope".

I read that .s files are not exported for the offline compiler. However, it is necessary that I have the nop functionality working due to timing constraints. Could someone suggest how using assembly files can be achieved?

2 Answers

9 years, 8 months ago.

Hello,

I am getting errors that nop is not defined, as it's true for GCC ARM. It's valid for ARMCC http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0491c/CJABCDAD.html

If you replace those __nop() by __NOP(), then it compiles.

I tried this but it doesn't seem to be using the nop. I'm thinking the compiler optimizes this instruction and neglects it.

posted by Naren Vasanad 16 Apr 2015

I exported for LPC1768, gcc arm, had not problems building the example in the page you provided above.

posted by Martin Kojtal 16 Apr 2015

I was compiling for the K64F. It compiles ok for me too. However, when loaded onto the K64F, the code doesn't seem to work. All the LEDs on the strip light up. This leads me to believe that there is some timing issue and that the nop didn't take effect.

posted by Naren Vasanad 16 Apr 2015
9 years, 7 months ago.

Hello,

I managed to hack together a solution for the K64F. I think it has something to do with optimization in the offline compiler. I took a scope to it and changed the iterations on constructor:

WS2812 ws(D9, WS2812_BUF, 0, 5, 5, 0);

I changed the 5's to different numbers, but nothing happened in the timing. If we take a look at the following function in WS2812.cpp:

void WS2812::write_offsets (int buf[],int r_offset, int g_offset, int b_offset)

I changed the variables "i" and "j" to be volatile, and this seemed to have some effect on the timing, but it took way to long.

Ultamately what I did, in the makefile for the library, change the optimization from "Os" to "O2", and the function I mentioned to:

hacked WS2812 solution

void WS2812::write_offsets (int buf[],int r_offset, int g_offset, int b_offset) {
    volatile int i;
    int totalSize = FRAME_SIZE * __size;
    
    // Load the transmit buffer
    __loadBuf(buf, r_offset, g_offset, b_offset);

    // Entering timing critical section, so disabling interrupts
    __disable_irq();
    
    // Begin bit-banging
    for (i = 0; i < totalSize; i++) {
        if (__transmitBuf[i]){
            __gpo = 1;
            __NOP();
            __NOP();
            __NOP();
            __NOP();
            __NOP();
            __NOP();
            __NOP();
            __NOP();
            __NOP();
            __NOP();
            __NOP();
            __NOP();
            __NOP();
            __NOP();
            __NOP();
            __NOP();
            __NOP();
            __NOP();
            __NOP();
            __NOP();
            __NOP();
            __NOP();
            __NOP();
            __NOP();
            __NOP();
            __NOP();
            __NOP();
            __NOP();
            __NOP();
            __NOP();
            __NOP();
            __NOP();
            __NOP();
            __NOP();
            __NOP();
            __NOP();
            __NOP();
            __NOP();
            __NOP();
            __NOP();
            __gpo = 0;
            __NOP();
            __NOP();
        } else {
            __gpo = 1;
            __NOP();
            __NOP();
            __gpo = 0;
            __NOP();
            __NOP();
            __NOP();
            __NOP();
            __NOP();
        }
    }
    
    // Exiting timing critical section, so enabling interrutps
    __enable_irq();
}

The timing with the solution is not perfect (neither was the original really), but it works mostly. There is probably a better solution code wise. Ultimately, it is best to take out the scope and make sure the timing following the timing here.

Hope this helps someone.