Need advice for ARM programming - Page 1
Forum section: electronics / general

author: pisoiu
author_rank: Regular Contributor
timestamp: October 01, 2020, 12:58:47 pm
content: Hi all,I need a bit of advice for a crash course into embedded C for ARM.My background: I am a lifetime programmer in 8051 asm (15-20 years), mainly on Silabs 8bit mcus. I have designs from 4kb of flash to 128kbytes length of code, I wrote a lot of code for sensors, wireless modules, data analysis, communication, etc. I also wrote an RTOS which is included in almost all my designs.But time to market restrictions forces me to move to next level, 32bit ARM and C. It's a step which I delayed too much due to lack of time, but now it has to be done somehow.I am not lazy to look for information but there is so much available and it would help me to get some 'filtered' advices, focused on my concerns.I do not have a problem strictly with C language, but with understanding the entire workflow.For the beginning I am thinking to play with Silabs ARM cortex M4 series (giant gecko 11 family is close to what I need), another candidate is ST, also M4 series.What I would like to understand as fast as possible:-how the hardware and IDE interacts through BSP, how a BSP is written, is BSP required in all designs, etc.-how to integrate an RTOS into an existing project, is this something which must be done manually, or some IDEs have some templates to do this when starting a project?-how to create libraries which can be used in other projects-how to manipulate firmware images at lower level. Example: my 8051 projects can compile various binary files, some are required for direct cable programming (at prototyping, they include firmware and bootloader), other variations are required to be programmed into a separate device (production programmer) which we use at initial firmware transfer and some are required to assemble upgrade images which are sent over the air. Also, those upgrade images contain some more data, not only firmware, because the boards contains some dataflash SPI memories which must be pre-initialized with some data (AT strings, constants etc). I do not know how that can be handled in the ARM environment.If you have any advice (youtube courses, other type of courses, etc) it would be helpful. Thanks.

author: NivagSwerdna
author_rank: Super Contributor
timestamp: October 01, 2020, 01:18:52 pm
content: Chris of contextual electronics mentioned a good book in the last Amp Hour episode.It's"Hands-On RTOS with Microcontrollers"https://www.packtpub.com/product/hands-on-rtos-with-microcontrollers/9781838826734and it has a suggested play along board...https://www.st.com/en/evaluation-tools/nucleo-f767zi.htmlavailable at DigiKey, Mouser etc for around USD$20It looked quite fun to me... probably add that board in with my next Farnell order and have a play

author: HB9EVI
author_rank: Frequent Contributor
timestamp: October 01, 2020, 01:37:28 pm
content: maybe the biggest thing to get into when switching from older 8bit mcus to ARM is the vast selection of peripherals with dozens of registers each, how to activate them (to not forget to activate the clock for a selected peripheral) and on what IO ports to map them (alternate IO function register and possible collisions with other peripherals).I cannot say about the workflow, since my asm days are already a while over; but still I'd say programming a mcu in C is a different thing than programming software-only applications on an OS, it remains close to the hardware although not as close as in asm.

author: NivagSwerdna
author_rank: Super Contributor
timestamp: October 01, 2020, 01:44:53 pm
content: I should have mentioned.... the board above is Arm Cortex-M7.. so probably in your ballpark if not exactly what you were after.

author: pisoiu
author_rank: Regular Contributor
timestamp: October 01, 2020, 01:47:36 pm
content: It's close and it's helpful, thanks.I also found (based on your recommendation) something interesting on udemy:https://www.udemy.com/course/mastering-rtos-hands-on-with-freertos-arduino-and-stm32fx/Sample videos looks promising.

author: JOEBOBSICLE
author_rank: Regular Contributor
timestamp: October 01, 2020, 07:14:14 pm
content: Buy an ST dev board, open a demo project and try to understand the bring up. There's normally a startup file which you should read and understand first.I would then put down FreeRTOS. Make a task that blinks and then your golden. I think if you've worked with 8 bitters, you'll find arm cortex m a lot easier in the long run.Yes things are more complicated, but MCU companies are now producing high quality HALs.If you need to program ROM then you'll need to write a bootloader or put it in your application code.

author: emece67
author_rank: Frequent Contributor
timestamp: October 01, 2020, 09:07:27 pm
content: .

author: rstofer
author_rank: Super Contributor
timestamp: October 01, 2020, 09:23:20 pm
content: This book will take you from nowhere up through project development including how to install the tools.https://leanpub.com/mastering-stm32As a side issue, look at the PSoC 6 - a dual core (M0 and M4) chip with a great toolchain and a lot of videos. There is a graphical element to programming where you define the IOs and various logic blocks and the tools generate all the code. You include FreeRTOS by clicking a check box. 600 MHz is pretty quick and there are lots of videos on YouTubehttps://www.cypress.com/products/32-bit-arm-cortex-m4-cortex-m0-psoc-6The standard STM32 tools do a similar kind of thing in terms of setting up the IOs.In an NXP chip, I like the Teensy 4.1:https://www.pjrc.com/store/teensy41.htmlIt's a Cortex M7 and it uses the Arduino IDE - which I don't like - and the tools are installed in parallel with the Arduino tools. You can use the tools with a different IDE - perhaps Eclipse. I'm not sure how to get real-time debugging. I tend to use printf() for that kind of thing.I like the 'stamp' board format of the Teensy 4.1 because I can plug it into a daughter card and avoid creating a PCB for the BGA chip. The User Manual is a concise 3437 page epic! NXP documentation is excellent.

author: westfw
author_rank: Super Contributor
timestamp: October 02, 2020, 10:50:40 am
content: QuoteYou wrote an RTOS for 8051 assembly programs?!QuoteSo...ARM-architecture chips divide into two parts. There is the "ARM Core", which was designed by ARM, and is standard across all parts with the same CPU (M0, M3, M4...) The Core includes the CPU, assorted buses, and some common peripherals (a single "tick" timer, an interrupt controller, and standardized debugging access and features.)Then there is "the rest of the chip." Memory and peripherals. These tend to be vendor specific (ie everyone's flash memory is programmed differently, and their UARTs are dissimilar.) (The 8051 derivatives all sort-of have the original standardish UART, Ports, and Timer, right? ARMs may be a rude awakening, in that respect.)ARM has specified a standard STYLE of peripheral access - part of what they call CMSIS - they're all accessed via memory-mapped C structures, like:Code:struct {__io uint32_t ctrl;__i uint32_t stat;__io uint8_t data;} UART0;For the Core, including the Core peripherals, ARM provides standard definitions.For the vendor-specific stuff, there are varying degrees of interpretation of the standard style. But at least they're similar. Ish.This should be similar to vendor-provided include files that you get for your 80051 chips, in principle. As an added bonus, there are many more IDEs that are "popular" for ARMs than there were for 8051, and you may need to get the various include files separately from the IDE, and the IDE separately from the compiler.That's essentially the minimal "Chip level Support."Most vendors have additional tools and libraries for supporting their peripherals. They all suck and everyone hates them, except for peripherals that are actually difficult to write your own code for, like Ethernet or USB. Then everyone still hates them for being bloated, buggy, and not really any easier to understand than the bare hardware, but at least "it's a mostly working example." Except they re-write them in incompatible ways every couple of years. Sigh.(One of the first difficulties that you're likely to run into is that ARM chips seem to have excesively complex clock systems: two crystals and several internall oscillators, DFLLs, DPLLs, and different clock routing, on/of control, and speeds for different peripherals. All documented by a hardware engineer that didn't understand software and was very proud of their hardware! Or you can use the library written by the software intern that didn't understand hardware, which is still obnoxious and might take 1k of code to get your CPU running at it's top speed. Sigh.)Vendor libraries typically provide a layer of abstraction. But there's no commonality between different vendors. ARM made some attempts in CMSIS at vendor-independent abstractions, but they don't seem to be widely adopted.There are some 3rd party libraries. I'm less familiar with them (other than Arduino. Which is a toy. A toy that provides better cross-vendor abstraction than most vendor libraries. Sigh.)QuoteThere are SO MANY RTOSes for ARM. ARM has their own standard in CMSIS for RTOS-related calls; I'm not sure if it's popular, or exactly how much it covers. Vendors have their own RTOSes (TI-RTOS comes to mind.) (I'd probably avoid those, to avoid vendor lock-in.) Free-RTOS is free and seems to have a lot of support. MBedOS is also popular. Some of ARM chips (especially those with wireless networking support) have proprietary code that already uses some OS. (notably Nordic NRFchips have a radio stack based on MBedOS, and Arduino Support for those chips runs ON TOP of MBedOS.)My general impression is that the existing "RTOS" offerings are "excessively complete", and probably a lot more complex than most people need for most things.QuoteCurrent style seems to mostly source-level libraries with conditional compilation for several chips. You either copy or symlink the library source code into your project, compile it with appropriate -Doption=value settings, and link it with the project. You can also have binary libraries, of course, but they tend to be less flexible. You'll get a full-featured C library with all the mixed-precision, floating point, and posix code that you might want. Several of them, in fact. And a very large set of generic C libraries written over the last 50 years that "probably work." Unlike many 8bit microcontrollers, ARMs don't run into show-stoppers like "the stack is only 256 bytes", or "I can't have contiguous arrays longer than 4k", or "I couldn't possible fit dynamic memory allocation in there."QuoteSWD is standard debugging hardware, and there's a standard comm protocol that goes with it. This is more-or-less JTAG, and it gives you the ability to manipulate internal memory and registers of the ARM chips. There are lots of options for doing this sort of base-level access. But this does NOT include programming flash, which usually involves a vendor-specific "non volatile memory controller." Many of the SWD options include flash programming for many chips, usually either by manipulating the NVM controller directly, or by uploading and executing short pieces of code into/from RAM. And there are many bootloaders - nearly all ARM chips can write their own flash. After you have basic code and/or bootloader in the chip, you have the same options for loading "other image-like data" as on any other system. I don't *think* that the JTAG-like properties of SWD extend to boundry-scan-like manipulation of other chips in a chain.QuoteWell, there have been intersting discussions here, and in otehr fora.I rather enjoyed the "Ghetto Style STM32" and "One Dollar One Minute ARM" threads here (and created this:https://github.com/WestfW/Minimal-ARM- it has pointers to the threads.)(and this:https://github.com/WestfW/SAMD10-experiments)I liked the UTEXAS "Embedded System - Shape the World" MOOC (https://courses.edx.org/courses/UTAustinX/UT.6.02x/1T2015/course/), which is probably mostly old-hat for you, but has a good intro to an ARM chip. And it's follow on about RTOS:https://courses.edx.org/courses/course-v1:UTAustinX+UT.RTBN.12.01x+3T2016/course/which specifically talks about RTOS primitives for ARM.)The various Arduino Cores (and libraries) are open-source and "educational" to look at, especially WRT the differences in implementations. (Let's see. Arduino Due was built on top of Atmel's "libsam" vendor library (which has otherwise been wiped from the face of the earth.) SAMD cores are mostly bare-metal. The Maple Arduino core was written on top of one of the old STM vendor libraries, then re-written on bare metal due to performance issues (and perceived licensing problems?) Then it was taken over by others and many chips were added, and most recently (?) ST took control and has put it back on top of a newer vendor library. The Nordic code runs on top of MBedOS, and TI has multitasking version for MPS432 built on top of TI-RTOS.

author: pisoiu
author_rank: Regular Contributor
timestamp: October 02, 2020, 11:31:33 am
content: First of all, many thanks for such detailed reply.Yes I wrote an RTOS for 8051, in ASMMany years ago when I started my business (which is centered around GPS tracking devices for cars, trucks and also peripherals such as sensors, etc) ARM was not really an option for me, I was not educated into this, no tools available or very expensive, etc. 8051 or AVR were the only choices and back at that time, C compilers were not that good (those free) or cheap (those commercial), so... 8051 ASM it is.First devices were rather simple, so a simpler SW architecture based on interrupts did the job of getting some GPS data, store it and relay it with a GSM modem. Those designs fitted into 4kbytes of flash at that time. But over the years, many peripherals were added , accelerometers, ibutton, interfaces to CAN, tachographs, etc and just loops and interrupts were not enough anymore. At that time I was not aware of any RTOS good for me, they were either too expensive or too buggy, and all were in C. Time restrictions also prevented me to move to another architecture and workflow, like C/ARM. So I had to write an RTOS according to my needs. It is not that advanced as freeRTOS but it does the job it suppose to do.

author: Nominal Animal
author_rank: Super Contributor
timestamp: October 02, 2020, 07:08:48 pm
content: Quote from: westfw on October 02, 2020, 10:50:40 amFully agreed.Paul Stoffregenprovides Teensyduino, Arduino-compatible libraries for a couple of different 32-bit ARM microcontrollers (and a couple of older 8-bit AVRs with native USB support) at GitHub. Stuff likeDMA channel supportfor i.MX RT1062 (Teensy 4.x) or theGCC linker fileused should be interesting; at least in the sense of options on how to implement your own.(Teensys are not open source hardware: the exact board files and the bootloader is proprietary, but the general schematics and the bootloader protocol (HalfKay) are documented at pjrc.com, and discussed at forum.pjrc.com. Because the support is via Arduino support library, Teensyduino, the compiler used is the ARM GCC suite, specifically the c++ compiler.)I myself am just a hobbyist, but I've been looking at implementing aSAM D51 "blitter"for small (240×320 or 320×480) display modules using 16-bit or 18-bit parallel bus – basically an Arduino-programmable display module with a framebuffer; one could implement either a 2D blitter, a DCT or perhaps even a full video decoder, etc. – as an OSHW design.(I have both Coldtears and BuyDisplay 240×320 with ILI9341 or similar controllers with IPS panels, which would be excellent for hobbyist use). It's a very straightforward design, really, with ample room, since the displays are over 2" diagonally. The idea is that these are slave processors, doing just the graphics stuff, controlled by a master processor connected via SPI/I2C/UART/etc.Before I commit to a board, I'd like to be sure I can program it. So, I've been looking at existing Arduino core library implementations for Cortex M4F a bit, and I fully agree with westfw. In my opinion, a lot of the Arduino core stuff is kept together with just spit and hope; a lot of it is very poor quality... but since a lot of it works at least, it gives another viewpoint in addition to the datasheets. Useful, informative; not perfect. Basically, I like to keep the datasheet with the register and programming info open in one window, when looking at existing code, and see how well my mental model of how something ought to be done matches the real-world code.

author: emece67
author_rank: Frequent Contributor
timestamp: October 03, 2020, 12:03:12 am
content: .

author: Fire Doger
author_rank: Regular Contributor
timestamp: October 03, 2020, 10:39:45 am
content: you can check the videos herehttps://www.eevblog.com/forum/microcontrollers/free-hitex-training-on-cortex-m/In general the first thing you have to do is "master" c, my suggestion would be to start with simple C on 8bit. This way you will see how your C code compiles in a very familiar result.You will be writing very efficient and bug free C code from the beginning. (don't try floating point or anything extreme. Simple stuff like function calls, pointers, structs, access ram, flash etc..)Then after you learn how to do what you want to do (bit masking, pointers, structs, preprocessor, optimization level etc) you can move on RTOS.I guess you did some amazing tricks in ASM but in C same tricks will look like black magic to you, start simple, understand principles and then move on. It may look huge (and it is) but with your knowledge in asm and how a CPU works it will be very fast and it will save you a lot of time on understanding code from libraries.The second thing to do is to learn to use HAL (hardware abstraction layer), they are huge libraries that helps you configure your peripherals. They will also look like black magic at the beginning because they use a lot the preprocessor (imagine it like script which runs before compile and choose what parts of library code to enable to target the specific mcu).After that you will be able to choose to treat them like black box or see how they are setting up a peripheral and how they interact with it and make your plans.For libraries you can do whatever you want. You include other libraries that you depend on in your libraries and start coding. If you want to use them you include them on your project.The tricky part is to make them compatible, if you use the HAL in your library then it will be compatible with all mcus in your family (that's the point of using HAL) but most likely you will have to use the preprocessor to enable or disable code according to your configuration for each project. For example on one project you need polling on the other interrupt, if you know how preprocessor works and use it in your library the change will be a single line.I have made libraries that are compatible with different core by changing HAL file path with preprocessor, its very useful tool.*off topicThe firmware for 3D printers can compile in STM32, LPC, SAM, ESP32, 8bit AVR and can be configured by people who doesn't know sh*t about mcu. So don't worry about compatibility, many open source projects use tricks to be compatible and you will have a ton of examples to see how they are doing it.In paid libraries I have seen tricks for compatibility among different compilers, same library for mcu and windows appAnd finally FreeRTOS will be very easy for you, you have done it in x1000 harder way. I bet just reading the free pdf from their website will be more than enough.I know for sure that ST HAL you can include it during project configuration and it will autogenerate the code.For your questions:BSP do you mean Board Support Package? They use this term for development boards, it just includes configuration for hardware like on which pin is the LED etc. Not used in custom projects.You create your own configuration according to your schematic.Yes you can definitely manipulate the compiled result, either by simple flags (preprocessor) or by IDE settings or by gcc commands. It depends on your tools and what you want to do.My only advice would be to get comfortable with C, everything else will come into place by itself.And don't fall into the trap to fiddle with peripheral registers, many engineers with 8bit history are trying to do it, start simple with HAL and return when you can make it better.

author: JOEBOBSICLE
author_rank: Regular Contributor
timestamp: October 03, 2020, 11:17:39 am
content: I agree about the HALs, people complain about them but don't appreciate that with the right GCC flags unused functions are thrown away and you end up with small binaries. Not only that, if you don't like them then they're easy to strip out and understand.I have seen opt S take a project from 120k flash down to 50k flash. I would argue that one of the best features of ARM is how good the free compiler is.Other architectures are stuck with GCC from ten years ago. Even though warnings and performance are much better now.I wish preprocessor use was cut down, it's okay in some areas but it's heavily overused.

author: jnz
author_rank: Frequent Contributor
timestamp: October 04, 2020, 04:48:00 pm
content: Quote from: JOEBOBSICLE on October 03, 2020, 11:17:39 amIt’s not the binary size have have a problem with. nordic is a pretty decent Hal, not great but easy enough to follow.The SPI overhead per transaction, 100% longer than it needed to be. 20uS from CS assert to CS deassert, vs 9.5uS just being smarter about the register access. Likewise it’s 50 instructions to flip or read a GPIO. Add another 5uS for ISR to “Event” layer and it’ll creep up on you even if you have performance requirements.

author: westfw
author_rank: Super Contributor
timestamp: October 05, 2020, 02:27:46 am
content: QuoteSome of the more advanced optimizations won't work if your HAL is provided as a library file, rather than as source code. :-((Some vendors have caught on to that, at the expense of bloating the source code included with each "project.")(There was a thread a long time ago where I found an example STM project that shrunk something like 30% just by #include-ing the library source code, rather than compiling is separately (and thus allowing the compiler more options WRT what to inline...)QuoteSubstantially worse than the much-derided Arduino "digitalWrite()" functions. (although, only about 10x what it should take, vs the AVR's 20-30x...)

author: cv007
author_rank: Frequent Contributor
timestamp: October 05, 2020, 03:38:51 am
content: >Likewise it’s 50 instructions to flip or read a GPIOIf you are still talking about nRF, not sure how you can get to 50 instructions. I add my own C++ drivers as needed/wanted simply because I cannot handle typing or reading a handful of underscores embedded in a function name that is a third of a page long (and if real lucky, all chars are uppercase). Or every time you want to figure out what is going on in the source, you have to mentally discard two thirds of it, then decode the remaining one third since defines are probably used to 'help' (and at the end you end up with- 'that's it?').But the nRF gpio driver is all inline, so getting to 50 will be hard to do it seems to me, and example below ends up exactly the same as my c++ driver (I get the better syntax and ease of use, but end up producing mostly the same code)-Code://my c++ version (what is 'on' or 'off already taken care of when pin created)if( board.sw1.isOn() ) board.ledRed.on();//nrf_gpio.h version, typical C code with defines#define SW1 27 //P0_27#define SW1_ONSTATE 0 //low is on#define LEDRED 7 //P0_7#define LEDRED_ONSTATE 1 //high is onif( SW1_ONSTATE == nrf_gpio_pin_read(SW1) ) LEDRED_ONSTATE ? nrf_gpio_pin_set(LEDRED) : nrf_gpio_pin_clear(LEDRED);both versions compile to the same code1c11e:f04f 43a0mov.wr3, #1342177280; 0x500000001c122:f8d3 2510ldr.wr2, [r3, #1296]; 0x5101c126:0112lslsr2, r2, #41c128:bf5cittpl1c12a:2280movplr2, #128; 0x801c12c:f8c3 2508strpl.wr2, [r3, #1288]; 0x508The nRF is a pretty neat family of mcu's, and Nordic has some good ideas. The 'Power management unit' takes care of power and clocks, and you are left with very little to do for clocks and power (in contrast to the normal complex matrix of clock controls and power settings). Getting to lower single digits uA takes little effort. Having the ability for digital peripherals to use any gpio is also nice, so you do not have to play rubik's cube with pin functions. They also have peripherals which the datasheet writer has little trouble communicating how it works (not complex). I can list some more niceties, but I'm not on their payroll so will refrain.

author: S. Petrukhin
author_rank: Super Contributor
timestamp: October 05, 2020, 09:03:40 pm
content: I recommend looking at the IDE of the Serbian company mikroE - mikroPascal or mikroC. Convenient environment, not messed up like others, not sloppy, very similar to old Borland products, simple and convenient. It has an editor, compiler, and step-by-step debugging on a chip. For a person who wrote on asm, this is closer than bulky and opaque other tools that generate a lot of inconspicuous code around the corner from the ticked boxes in the designer.I wrote a lot in x86 assembler - it is simple and clear, even with inconvenient memory segmentation. The Cortex assembler is a nightmare for me.

author: S. Petrukhin
author_rank: Super Contributor
timestamp: October 05, 2020, 09:16:43 pm
content: And I will add: mikroE has a wonderful CodeGrip programmer that can work over WiFi and be powered by a circuit.Very convenient remote debugging, it is very useful to me.

author: jnz
author_rank: Frequent Contributor
timestamp: October 08, 2020, 06:06:38 pm
content: Quote from: cv007 on October 05, 2020, 03:38:51 amYou are free to test it for yourself. I just did and its 47 instructions using nrf vendor library.I call nrf_gpio_pin_clear(my_pin)>>>nrf_gpio_pin_clear(uint32_t pin_number)>>>nrf_gpio_pin_port_decode(&pin_number);nrf_gpio_port_out_clear(reg, 1UL << pin_number);returnsI threw away a few instructions on the call be it was in a ternary in my test. So I didn't even count the call itself. At 64Mhz this should be .8uS, and that's probably close, but in practice I was seeing software SPI with manual chip select / slave select taking about 2uS longer, that's a CLEAR and a SET command following each other. Only one SPIM on the Nordics support hardware CS/SS so that's a dumber but whatever.

author: cv007
author_rank: Frequent Contributor
timestamp: October 08, 2020, 07:50:00 pm
content: >You are free to test it for yourselfI already did, and showed what was produced in the asm for something even more complicated.Here is the actual nrf driver code to clear a pin-https://godbolt.org/z/4s3x5qresult- 3 instructions.Maybe you have optimizations off (-O0), which is about the only way to get to those kind of numbers you have.