nRF52 twi and easy-dma - Page 1
Forum section: electronics / general

author: cv007
author_rank: Frequent Contributor
timestamp: August 29, 2020, 01:19:01 pm
content: condensed version-nRF52 and twi dma, or any mcu with dma-if you give the compiler information about the buffer you use for dma, in certain conditions it may think it knows all about that buffer-bool isReady(){uint8_t buffer = { 0,0 }; //init buffer for some reasontwi.read(buffer); //twi uses dma, blocking call (and compiler inlined this code)return (buffer & 0x20); //return a status bit}//compiler 'knows' buffer is 0, so probably optimizes away parts of it like the bit testbool isReady(){uint8_t buffer; //do not init buffer (contents unknown)twi.read(buffer); //twi uses dma, blocking callreturn (buffer & 0x20); //return a status bit}//compiler does not know what buffer contains, so the code is used as expectedbool isReady(){volatile uint8_t buffer = { 0,0 }; //init buffer for some reasontwi.read(buffer); //twi uses dma, blocking callreturn (buffer & 0x20); //return a status bit}// volatile prevents the compiler from optimizing away the bit test, since it is required to read bufferI was doing the first version, and it was acting like the buffer was unused, but only in some optimizations. Adding a simple asm("nop") anywhere in that sequence made the compiler 'forget' what it knew about buffer and then the code would work. Making the buffer volatile works, or simply not initializing the buffer also works. Probably not a typical use of dma- a small buffer that is init, then used in the same function where the compiler then can optimize away its use, but its possible. So, just like isr's where it requires thought when using vars from outside the isr, dma also requires some thought even if its to a lesser extent.I now use the second version, as I really didn't need to init the buffer. It was initially init so I could see if the buffer was changing during debugging, but didn't realize it was then the cause of problems.

author: eutectique
author_rank: Frequent Contributor
timestamp: August 30, 2020, 09:44:43 am
content: Your buffer shall be declared volatile. This is the way to instruct the compiler not to make any assumptions about the nature of the data.You can compile to assembly and inspect the generated code to see what happens to the buffer.

author: cv007
author_rank: Frequent Contributor
timestamp: August 30, 2020, 10:35:09 am
content: >Your buffer shall be declared volatile. This is the way to instruct the compiler not to make any assumptions about the nature of the data.That was the conclusion I made in my original post (before I compressed it). I think that is the wrong conclusion though, although it is an option. In the second version, since the data was not initialized the compiler cannot know what is in the buffer, so is not optimized. I think that is just as valid.It seems it doesn't take much to get the compiler past the point where it no longer attempts to figure things out-https://godbolt.org/z/P8EPP6when you go from a 3 to a 4 byte buffer (in this case, for these compiler settings, on this day of the month, ...), then the optimizer 'gives up'.So turning a tiny buffer into volatile, if you are setting the initial values, is the option to use. If there is no need to initialize the buffer, then the compiler cannot know the buffer contents so no need for volatile. If you have a 1k buffer and do not initialize, the compiler cannot know what is in the buffer, or if initialized (memset) the compiler does not appear to attempt to know beyond some point. Its probably a strange thing to init a dma buffer used for incoming data, as there is likely little reason to do so. Making every dma buffer volatile would seem to not be a good idea, since now you could have a large buffer where every read access after its filled will require re-reading, and at that point it is no longer volatile so you lose out on compiler optimization while working with the buffer.>You can compile to assembly and inspect the generated code to see what happens to the buffer.Yes, you can. The higher you go up the mcu ladder the harder it gets. If the compiler is inlining various things as it sees fit, it can sometimes be a little hard to pick out where your data is used (or optimized away). The objdump -S option does not help much, either (or just makes it harder). Once you understand what is going on and where, then it is easy to see.

author: eutectique
author_rank: Frequent Contributor
timestamp: August 30, 2020, 05:52:53 pm
content: Quote from: cv007 on August 30, 2020, 10:35:09 am> arm-none-eabi-gcc -S file.c> arm-none-eabi-gcc -c -save-temps -o file.o file.c

author: Adityaraj Bhatt
author_rank: Newbie
timestamp: November 17, 2020, 06:00:18 am
content: Hey,I was going through all the threads to find out a suitable one to post this on, our team developed a code generator tool for nRF52xx series MCUs, here's the link:https://vicara.co/nrf52-code-generator, could you please try it out, maybe it helps and makes things easier for you.Since the project is in development phase could you please share your feedback too?, that would help us a lot.