Important changes to forums and questions
All forums and questions are now archived. To start a new conversation or read the latest updates go to forums.mbed.com.
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.
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.