Changing MCs after 10 years from PIC to STMicro - Page 1
Forum section: electronics / general

author: merelyuseful
author_rank: Newbie
timestamp: January 11, 2025, 07:21:38 pm
content: I decided today to abandon my self-imposed masochism and abandon PIC programming. I’ve been putting up with ICDs and PicKits of various flavours stopping at random and requiring a machine reboot before they reconnect, inconsitsent PIM pin mappings on dev boards, DMA peripheral to peripheral random failures and differencs across dsPICs that use different memory models inexplicably and other forms of modern torture. The thing is though that I like coding in C but I don’t want to use a RTOS so I’ve always been a bit put off by STMs since all the demos I saw used FreeRTOS.I downloaded STCube and loaded some examples and they all use FreeRTOS. Before I dive in and blow a few hundred hours on mastering a new platform does anyone here use “direct" C programming on ST MCs? If so, how straightforward is STCube for this and how reliable are the programming / debugging tools? I prefer to use MacOS if I can. I gave up even trying on the Mac with PICs because the ICDs and PicKits were even worse than they are on Windows.I am very comfortable with gcc and gdb so my ideal setup would be to use them direct if that’s possible.

author: Slh
author_rank: Regular Contributor
timestamp: January 11, 2025, 08:03:26 pm
content: I just started playing with bare metal stms. My previous experience was mostly msp430s and minor hacks on C2000s. There's no need to use a RTOS.I decided to ignore the HAL and just use CMSIS and cmake on STcube so that I'm not tied to it if I decide to use something else.The user manual for the chips is as easy to follow as the MSP430s but peripherals are generally more complicated so take a little more fettling. CMSIS took a bit of getting used to but I got the hang of it after setting up a couple of peripherals and I'm quite happy with it now.I don't know if it's the right approach but I created HAL projects for the chip that I'm using and then copied the CMSIS and linker scripts to a separate cmake project.I've got a cheap knock off stlink V2 which seems to work perfectly for programming and debugging.I can't comment on Mac, I'm using Linux and haven't had any problems.

author: shtirka
author_rank: Contributor
timestamp: January 11, 2025, 08:17:27 pm
content: Hello,Relatively recently (in the past 3-6months) I also made a similar choice to shift from the microcontrollers I was programming (Atmel/later Microchip) to learn STM32 programming by grabbing a few STM32 based boards from Weact Studio - I also have their mini-debugger/mini-programmer which I can highly recommend (at least to begin with). So I guess my experience may well be helpful to you (we may even end up on joining forces on learning lol). I will also say (as a disclaimer) that I am using Linux in the form of Opensuse Tumbleweed 15.6 so most of my experience should be applicable to you and MacOS (considering it is BSD based nowdays).1. I am using both RTOS and direct C/C++ approach - here it will be more of a personal preference for you. But personally I found the ST documents describing the HAL and low level api documentation very helpful (just be aware there is quite a bit of it so a steep learning curve is in order) - you look for the Description of STM32_"family" HAL and low-layer drivers documents on st.com.2. So far the STM32cube ide and STM32programmer software have been alright - the one thing that took me a bit of time to figure out the beginning of my learning curve is that graphical interface of setting up the microcontroller (since theres quite a few settings). But thats actually pretty easy and it does make certain sense once you get the logic of it. But I also find myself doing things in a text editor and command line (I think I also have links to relatively low level libraries for STM32F1 and F4 families before HAL became the big thing - if you wish I will either post the links themselves or the code archives, whichever is permitted by the forum)3. The best tutorials for STM32 I found so far is by @deepbluembedded on YT - I think the guy also published the libs for that course on his github too, will see if I can dig out that link too for yaThat hopefully helps to at least get started//IlyaQuote from: merelyuseful on January 11, 2025, 07:21:38 pm

author: hans
author_rank: Super Contributor
timestamp: January 12, 2025, 08:33:20 am
content: I'm doing embedded development on a Mac with Intel silicon, and you shouldn't expect issues. With brew you can install the same Linux tools such as the GCC compiler, GDB, CMake, and OpenOCD as a JTAG/SWD dongle and GDB server bridge. I haven't tried my JLink on Mac, but they have Mac builds so I would expect it to work too. I use these tools with VSCode (PlatformIO for RPi Pico's) and Jetbrains CLion (STM32, EFR32, AVR, etc.).Or you use ST's own IDE (STMCubeIDE). If you didn't say you have experience with GCC/GDB, I imagine this is the easiest route as it takes care of project files and makefiles and has tighter integration with STMCubeMX. STMCubeMX is an useful planning tool for pin allocations and initialization code.It's very common to program these chips without FreeRTOS though. I haven't used FreeRTOS in many years. It is not a requirement, however, it can be convenient if you're dealing with protocols such as ethernet or USB that must preempt other tasks or is bound to async delays from other devices (which can be a long time)One thing to be cautious with ST micro's is to read the datasheet and also peek at the user manual. These chips can be complex and some functions are not as generic as can be. For example, the DMA channels on most ST MCUs have a predefined matrix which particular streams each channel will support. E.g. you cannot map random particular SPI TX/RX DMA stream to a random DMA channel: it has to be a specific one that ST has designed in the part. It would be a pity if it turns out that both SPI and ADC conflict after you have committed to building a PCB.Another example could be cases where timers generate trigger signals for each other (as a master / slave combination), and the signal routing is limited to a specific few timers. This could be important if you want to align PWMs etc.And the biggest step when going from PICs to ARM devices in general is to always keep an eye if you've set up the clocks and reset configuration correctly (in STM32 that's the RCC peripheral). If you use ST's code they should handle this for you, but when I first started I was confused for a few hours why my UART initalization code looked fine but nothing worked.. until I turned on the clock enable bit in the RCC..

author: shtirka
author_rank: Contributor
timestamp: January 12, 2025, 10:12:44 am
content: Quote from: hans on January 12, 2025, 08:33:20 amAh yea thats one of many gotchas that got me at the start of my personal learning curve!Ilya

author: pcprogrammer
author_rank: Super Contributor
timestamp: January 12, 2025, 01:14:29 pm
content: I'm quite pleased with the STM32 MCU's and only do full bare metal on these. Tried the ST tools at first but found them to be crap and the HAL in my opinion is awful.I don't even use the cube stuff to setup my projects. I just use the datasheet and reference manual to lookup what is needed to make it work.There are a few pitfalls, where the enabling of the peripheral clocks is one of them. Another one is the pins used for JTAG that need the JTAG interface to be disabled when you want to use these pins yourself for other peripherals or just plain GPIO.Some of my earlier work is in my github repository, like this one:https://github.com/pecostm32/STM32F303_Sine_Square_GeneratorMy new method of working with them is to not even use CMSIS, but search for the header files ST packs with their ST tools and dismantle them to separate files per peripheral. Is a bit of work, but makes life simpler in the long run. I can do this because I'm retired and it is just hobby.At the moment I'm working on a project with the STM32F411 and for each peripheral I start to use I create a new header file and when needed also a code file.No idea what it will do on the MAC, but as long as the arm compilers are available on it you will be fine without any of the ST tools. I myself use netbeans 8.2, just because I'm used to it and it works fine for me. Yes I'm a dinosaur.For loading my programs to FLASH I use a cheap ST-Link clone in combination with openocd. One can find plenty of those cheap St-Links on Aliexpress.At first you might find the documentation a bit crappy, but with some experience you will get things working in no time.There are some differences in peripherals between the different series of STM32's but there are a lot of similarities too. Differences are mainly in the clock and the GPIO setup, for what I have seen of it.

author: AVI-crak
author_rank: Regular Contributor
timestamp: January 12, 2025, 04:00:57 pm
content: Quote from: merelyuseful on January 11, 2025, 07:21:38 pmA good reason to give up the main problem - the heroic overcoming of crazy tasks. To give up, for a more comfortable life and work.WCH - chips with ready-made peripheral code, programming at the level of ready-made code blocks/libraries. No need to dig in low level, just copy what's already ready.Also, WCH is insanely cheap, practically like sand.

author: voltsandjolts
author_rank: Unknown
timestamp: January 12, 2025, 06:56:21 pm
content: Quote from: merelyuseful on January 11, 2025, 07:21:38 pmI too use bare metal, although mostly on STML0/F0 (CM0) which are much simpler than the CM3/4 varieties, but principles are the same.Perhaps useful links:https://github.com/ataradov/mcu-starter-projectshttps://github.com/cpq/bare-metal-programming-guide

author: westfw
author_rank: Super Contributor
timestamp: January 12, 2025, 11:10:38 pm
content: QuoteThere's a company (guy?) that offers a bunch of classes that mostly focus on lower-level programming of STM32F microcontrollers. The classes themselves are for-fee (not too unreasonable; I don't think I've seen a class more than $100), but they offer enough free "teaser" downloads and blog posts and such that I consider it a useful resource.Sign up to receive one of the free downloads, and you'll start getting a somewhat annoying quantity of emails advertising new classes and resources and such (use a categorizable email address, and I suppose it depends on how you feel about filtering emails.)Site ishttps://embeddedexpert.io/Here's some sample content:Bare Metal Mini CookbookSetting up Cube IDE for Bare-Metal ProgrammingWorking with STM32 and display: Nokia 5110 Graphic LCDFWIW, I've watched several people on various forums voice their confusion as they move from 8 bit PIC or AVR chips to newer ARM chips (and my own experiences), and the main problems seem to be:C structures as a way to access peripheral registers, and the associated "pointers" that they've never had to use before.Peripherals are more complex, having "many" registers compare to 8bit chips.In particular, setting up the CPU and peripheral clocks, which is one of the first things you need to do, can involve a bewildering amount of configuration as you deal with multiple clock sources (including FLLs and PLLs) and destinations (clocks for each peripheral, clocks for intermediate bus controllers, etc.) Documentation of this tends to be particularly obscure (IMO), and vendor-provided libraries bloated and also obscure.Low-level operation isn't particularly well documented. You probably won't find the nice table of all the CPU instructions and how many cycles they take that you see in 8bit documentation. Especially once (slow) Flash memory and (probably) its associated "accelerator" are considered. It's assumed that you'll be programming in C, and that the CPU is "fast enough."Documentation is ... diffuse. "Datasheets" probably are essentially feature lists and electrical specs; you'll also need the "family reference manual" (1000+ pages.) And that won't include the pieces that are part of the ARM core (SysTick Timer, NVIC, etc), so you'll also need to find the ARM documentation, which might be in a manual that documents a superset of what you have available. Grr.

author: Georgy.Moshkin
author_rank: Frequent Contributor
timestamp: January 13, 2025, 01:28:16 am
content: STM32 HAL is good, portability is pretty good. I use HAL and signal processing using integers all the time (for speed). DMA is more straightforward than on PIC32MK. For example l, you have half-complete DMA interrupt for everything. On PIC32MK there is some additional double-buffer registers (ADC? don't remember) for some peripheral which I didn't like. BTW, If someone from Microchip reading this, you rejected my job application.

author: pcprogrammer
author_rank: Super Contributor
timestamp: January 13, 2025, 07:34:17 am
content: Quote from: Georgy.Moshkin on January 13, 2025, 01:28:16 amMaybe it has improved in the last 5 or 6 years, but when I started with the STM32F103 (Bluepill) I tried some examples using HAL and I could not get them to work. Particularly USB failed to do what I wanted. Trying to read the code to get to the nitty gritty was not so simple due to all the bloated include files and structures used to make it kind of object oriented.I ended up writing my own bare metal USB driver and never looked back on HAL.In my opinion learning all the aspects of the HAL setup takes just as much time as learning how to use the peripherals bare metal, and when there is an issue with something not working it is, again in my opinion, easier to resolve in bare metal mode than in HAL mode.And yes I know there is also the LL mode one can use, but for me it is just the easiest to do bare metal.About portability, when you structure your own bare metal setup in a good way, most of the code will be reusable. When moving to a faster MCU you will have to tweak the clock settings either way.

author: AVI-crak
author_rank: Regular Contributor
timestamp: January 13, 2025, 04:14:04 pm
content: Quote from: westfw on January 12, 2025, 11:10:38 pmThe problem is inattention, laziness, and accumulated experience. Modern documentation is very concise, every letter, term, and order of information is important. There is no superfluous entertaining information, no attention-grabbing embellishments, and no ready-to-copy product. It is literally an information tool.But almost every programming genius manages to read the documentation diagonally (a quick read of familiar symbols). Ticktock Generation.Translated with DeepL.com (free version)

author: wek
author_rank: Frequent Contributor
timestamp: January 13, 2025, 04:45:02 pm
content: My take.JW

author: mjs
author_rank: Regular Contributor
timestamp: January 14, 2025, 06:53:04 am
content: Bare metal is certainly very doable on STM32 and many of the simpler examples do not use RTOS.Peripherals can be complex to set up correctly, maybe try out the HAL examples and if something does not work, check each and every bit in configuration registers.Get some Nucleo boards, they're great value and contain integrated debugging probe that works great with IDE and GBD. Debugger can access the peripheral registers and step through HAL code, which is great in learning and debugging the peripherals.If using IDE, organize your code according to marked places in generated code or separate files. This way you can safely change peripheral configuration ande regenerate HAL code.For production code, I usually end up doing direct register configurations and build system that works with both IDE and dockerized compile environment for repeatable builds.

author: peter-h
author_rank: Super Contributor
timestamp: January 14, 2025, 07:13:07 am
content: For most nontrivial products, an RTOS makes life much easier, not harder.From my POV, "HAL" is just code generated by Cube MX, which is STM's "code generator". You draw a pic of the CPU chip, allocate pins, etc, and drag in various functional blocks. So you can get a blinking LED running quickly and impress the bossThe detail takes a lot longer, but it always does.So you get functions like thisCode:/*** @brief Sets or clears the selected data port bit.** @note This function uses GPIOx_BSRR register to allow atomic read/modify* accesses. In this way, there is no risk of an IRQ occurring between* the read and the modify access.** @param GPIOx where x can be (A..K) to select the GPIO peripheral for STM32F429X device or* x can be (A..I) to select the GPIO peripheral for STM32F40XX and STM32F427X devices.* @param GPIO_Pin specifies the port bit to be written.* This parameter can be one of GPIO_PIN_x where x can be (0..15).* @param PinState specifies the value to be written to the selected bit.* This parameter can be one of the GPIO_PinState enum values:* @arg GPIO_PIN_RESET: to clear the port pin* @arg GPIO_PIN_SET: to set the port pin* @retval None*/void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState){if(PinState != GPIO_PIN_RESET){GPIOx->BSRR = GPIO_Pin;}else{GPIOx->BSRR = (uint32_t)GPIO_Pin << 16U;}}and then you get more complicated ones like this, which are useful guides but you will probably strip them down to what you actually needCode:/*** @brief Sends an amount of data in blocking mode.* @param huart pointer to a UART_HandleTypeDef structure that contains* the configuration information for the specified UART module.* @param pData Pointer to data buffer* @param Size Amount of data to be sent* @param Timeout Timeout duration* @retval HAL status*/HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout){uint16_t* tmp;uint32_t tickstart = 0U;/* Check that a Tx process is not already ongoing */if(huart->gState == HAL_UART_STATE_READY){if((pData == NULL ) || (Size == 0)){return HAL_ERROR;}/* Process Locked */__HAL_LOCK(huart);huart->ErrorCode = HAL_UART_ERROR_NONE;huart->gState = HAL_UART_STATE_BUSY_TX;/* Init tickstart for timeout managment */tickstart = HAL_GetTick();huart->TxXferSize = Size;huart->TxXferCount = Size;while(huart->TxXferCount > 0U){huart->TxXferCount--;if(huart->Init.WordLength == UART_WORDLENGTH_9B){if(UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK){return HAL_TIMEOUT;}tmp = (uint16_t*) pData;huart->Instance->DR = (*tmp & (uint16_t)0x01FF);if(huart->Init.Parity == UART_PARITY_NONE){pData +=2U;}else{pData +=1U;}}else{if(UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK){return HAL_TIMEOUT;}huart->Instance->DR = (*pData++ & (uint8_t)0xFF);}}if(UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TC, RESET, tickstart, Timeout) != HAL_OK){return HAL_TIMEOUT;}/* At end of Tx process, restore huart->gState to Ready */huart->gState = HAL_UART_STATE_READY;/* Process Unlocked */__HAL_UNLOCK(huart);return HAL_OK;}else{return HAL_BUSY;}}

author: NorthGuy
author_rank: Super Contributor
timestamp: January 16, 2025, 06:13:47 pm
content: Quote from: westfw on January 12, 2025, 11:10:38 pmThe ISA (a set of CPU commands) is well documented and can be found on the ARM's Web site. I found their docs very good.Since it's a load-store architecture, the most difference in timing is produced by memory accesses which are not really a part of CPU, and therefore access times cannot be listed, and in some cases cannot be predicted at all. The majority of non-memory-access instructions execute in one cycle. This is the whole different approach to CPU design - let's make commands simple and fast, and when it comes to memory accesses - try to decouple them from the rest of CPU. Hence they can increase frequency by a lot, but memory accesses will be slow (relative to the CPU speed) and unpredictable.For comparison, Microchip CPUs are built on memory accesses - CPU has read and write phases which ensure fully predictable memory (and hardware register) access. Hence, the CPU frequency is limited by the memory access speed, but everything is fully predictable. It is easy to document the instruction speed by publishing instruction tables with execution times.