Any interest in cracking the STM32? - Page 1
Forum section: electronics / general

author: Chris Mr
author_rank: Regular Contributor
timestamp: September 12, 2025, 09:21:56 am
content: Hi All,I've had to use STM32s many times in the past (people already using it etc) and ended up writing a program called "Headergen".The program takes two files, "peripherals" and "processors" and writes separate files with all the addresses of all the registers of the peripherals of the processors. It also takes a template of the interrupt table and adds weak interrupt function calls to get things started as well as a list of NVIC interrupt numbers for the peripherals.Here's an example of the CRC peripheral to get the idea..CRCF030DR : 0x0DR[31:0]IDR : 0x4 (byte)IDR[7:0]CR : 0x8RESETREV_IN[6:5]REV_OUTINIT : 0x10F429DR : 0x0DR[31:0]IDR : 0x4 (byte)IDR[7:0]CR : 0x8RESETG030DR : 0x0IDR : 0x4CR : 0x8INIT : 0x10POL : 0x14Please excuse the way it comes out, the original has tabs. The tabs are used to define what's what. Zero tabs before a label means the name of a peripheral, one tab before a label means a type of peripheral, two means a register number followed by a colon and then the register offset address. An extra tab means it's a bit-field which isn't used yet. They are all assumed to be unsigned long pointers and so if you use brackets after the address offset you can set it to another data type.Here's what a processor look lie:STM32F030ADCF030ADC : 0x40012400_ CRCF030CRC : 0x40023000EXTIF030EXTI : 0x400104000_1 2_3 4_15 there are more but that covers what's needed to explain. Zero tab label means the name of a processor, one tab is to the peripheral name, then the type, then what you are to call it with the colon followed by the base address.After that comes the interrupts which is what you want to call it followed by the interrupt number in square brackets.An example not shown of the "what you want to call it" field would be USART1 or USART2 etc, same peripheral, same set of offsets, different interrupt numbers and base address.Here's a snippet of the interrupt table:/*----------External Exceptions---------------------------------------------------------------------------------------------*/WWDG_Interrupt_Handler, /* 0 */0, /* 1 */RTC_Interrupt_Handler, /* 2 */0, /* 3 */RCC_Interrupt_Handler, /* 4 */EXTI_0_1_Interrupt_Handler, /* 5 */EXTI_2_3_Interrupt_Handler, /* 6 */EXTI_4_15_Interrupt_Handler, /* 7 */0, /* 8 */DMA_CH1_Interrupt_Handler, /* 9 */DMA_CH2_3_Interrupt_Handler, /* 10 */DMA_CH4_5_Interrupt_Handler, /* 11 */ADC_Interrupt_Handler, /* 12 */TIM1_BRK_UP_TRG_COM_Interrupt_Handler, /* 13 */and here's the addresses example:#define CRC_DR ( ul *)( ( ul)0x40023000)/* DR[0:31] */#define CRC_IDR ( byte *)( ( ul)0x40023004)/* IDR[0:7] */#define CRC_CR ( ul *)( ( ul)0x40023008)/* RESET *//* REV_IN[5:6] *//* REV_OUT */Once you get a few peripherals and a few processors you start to notice that there is quite a bit of mix and match between peripherals and processors.. which of course ST don't document. For example the CRC shown here appears in lots of processors and you get to find out when entering a new one. You look into the peripherals file and see there is one there already so don't need to enter it, just use the type in the next processor.Given that the peripheral is identified by the name and type you can then write a driver for that peripheral name/type and that means it will work in any processor that has that peripheral.. and the list of where that applies is provided!Now, it might not be a "crack" for the problem but does anyone want to comment / add to the above method or say if there is any interest in doing something like this (or better!) community-wise to reduce (or preferably crack) the problem?

author: hans
author_rank: Super Contributor
timestamp: September 12, 2025, 12:07:59 pm
content: Yes.. I do find it frustrating too they are clearly reusing a lot of their peripheral IP, but not clearly documenting which families are identical, have extensions (such as a FIFO added to SPI) or which are completely refreshed. I'm not sure how many STM32 families there are , but there must be at least as many versions of their HAL with sometimes a few refreshes/redesigns over the years. So much code duplication... especially when I write all my firmware in a BSP so I can reuse and port as much higher level stuff as possible.Personally I've started writing peripheral drivers for STM32 with a common model, e.g. SpiGen1, etc. I've found the Rust crate embassy-stm32 to be useful in this, as they have done a lot of this work, although its still a community project (and so may be incomplete). And I personally still program in C++, so it being in Rust is a bit of a problem...

author: Tation
author_rank: Regular Contributor
timestamp: September 12, 2025, 12:37:07 pm
content: Wouldn't the .svd files contain the same information, with less effort? This is an excerpt from the .svd file for stm32f0x0 chips:Code:<peripheral><name>CRC</name><description>cyclic redundancy check calculation unit</description><groupName>CRC</groupName><baseAddress>0x40023000</baseAddress><addressBlock><offset>0x0</offset><size>0x400</size><usage>registers</usage></addressBlock><registers><register><name>DR</name><displayName>DR</displayName><description>Data register</description><addressOffset>0x0</addressOffset><size>0x20</size><access>read-write</access><resetValue>0xFFFFFFFF</resetValue><fields><field><name>DR</name><description>Data register bits</description><bitOffset>0</bitOffset><bitWidth>32</bitWidth></field></fields></register><register><name>IDR</name>…And so on, for each field, of each register, of each peripheral.Also, the dts files in the zephyr project can give some clues about the degree of compatibility between peripherals from different chips, for example, in file stm32f0.dtsi one finds:Code:usart1: serial@40013800 {compatible = "st,stm32-usart", "st,stm32-uart";reg = <0x40013800 0x400>;clocks = <&rcc STM32_CLOCK(APB2, 14U)>;resets = <&rctl STM32_RESET(APB2, 14U)>;interrupts = <27 0>;status = "disabled";};and in file stm32l4.dtsi:Code:usart1: serial@40013800 {compatible = "st,stm32-usart", "st,stm32-uart";reg = <0x40013800 0x400>;clocks = <&rcc STM32_CLOCK(APB2, 14U)>;resets = <&rctl STM32_RESET(APB2, 14U)>;interrupts = <37 0>;status = "disabled";};Thus, when working with one chip (supposed it is supported by zephyr, as the peripheral of interest) one can look for the driver used (the 'compatible' field above) and look for other chips also compatible. Comparing then their .svd files one can get a more detailed report of differences.

author: kloetpatra
author_rank: Regular Contributor
timestamp: September 12, 2025, 12:44:18 pm
content: so you reinventedhttps://developer.arm.com/documentation/101407/0543/Utilities/System-View-Description-ConverterInstead you could have usedSVDConvwith the corresponding .svd file.https://github.com/modm-io/cmsis-svd-stm32

author: Chris Mr
author_rank: Regular Contributor
timestamp: September 12, 2025, 01:39:41 pm
content: Great replies, thank you.I've committed the mistake of not defining what the problem is I'm trying to solveSimply put, there are ways of doing things that can be followed easily, and ways which are not so easy. If you go the not so easy route then you limit the number of people who can help (or who you could employ to help) by the amount of required information before you can start.I like to follow the maxim of "think about the next person". There's a good example in the plumbing world... If you get a plumber to come to fix a leaking tap, and there's no shut off valve under the sink, then there's going to be a lot of work to get to the point where the tap can be fixed (emptying higher levels by opening taps etc), and so the plumber will fit a shut off valve because they are thinking about the next person (who could well be them).Equally editing a text file is what everyone does in the coding world so getting someone to help (or employ) should be easy.. or rather not limited by the method.I looked at Zephyr, which is awesome, but I couldn't use it following the above maxim.. I doubt we could find anyone locally to help if that was a prerequisite.Ultimately someone has to maintain code. Personally I like to understand what I am doing and do it in a way that the next person has a good chance of understanding too.

author: Siwastaja
author_rank: Super Contributor
timestamp: September 12, 2025, 01:46:51 pm
content: What is wrong with manufacturer-supplied header files?

author: Chris Mr
author_rank: Regular Contributor
timestamp: September 12, 2025, 02:10:43 pm
content: Quote from: Siwastaja on September 12, 2025, 01:46:51 pmA good question.If we start with that they are not always accurate then here's an example I recently reported to ST (but found the header file issue as a side line). In the STM32G431 there is a DMAMUX which has fewer channels that the full thing (G474 for example). In the reference manual it says (for G431 which is category 2)For category 2 devices:• DMAMUX channels 0 to 5 are connected to DMA1 channels 1 to 6• DMAMUX channels 6 to 11 are connected to DMA2 channels 1 to 6It also says in the memory map that the numbering convention is13.6.1 DMAMUX request line multiplexer channel x configuration register(DMAMUX_CxCR)Address offset: 0x000 + 0x04 * x (x = 0 to 15)So in the G431 there are no DMAMUX_C6CR or DMAMUX_C7CR.. but not so in the header files. Whoever wrote the header files increased the offset to make C6CR go to DMA2!Sure, it matches their code, but according to the reference manual that's wrong. It means that code won't work on a different processor that has those registers.There are many more.. I just sent yet another documentation issue to ST.. I do that in the hope that they might improve, but the time constant for that seems quite long!

author: Siwastaja
author_rank: Super Contributor
timestamp: September 12, 2025, 02:52:25 pm
content: Yeah, those headers do have some errors (compared to the reference manual which should be the reference). I have worked around those in case-by-case basis because... it's not much work. Maybe <5% of registers are wrong. You quickly find the correct one from the header file by text search and then use that. (A pragmatic approach.)Or fix the header files as you go.

author: ahsrabrifat
author_rank: Regular Contributor
timestamp: September 12, 2025, 06:12:25 pm
content: Your method separates peripherals from processors, which is excellent.It promotes reusable drivers across many STM32 variants. Tab-based format is simple but hard for tools. YAML or JSON improves readability and validation. CMSIS-SVD already defines peripherals and registers. Supporting SVD files increases compatibility and adoption. Community contributions could build a large database. Your project has real potential for embedded developers.https://arm-software.github.io/CMSIS_5/SVD/html/svd_Format_pg.htmlhttps://github.com/modm-io/cmsis-svd-stm32

author: SiliconWizard
author_rank: Super Contributor
timestamp: September 12, 2025, 08:30:24 pm
content: Almost all manufacturers release SVD files, if one's not satisified with the vendor-provided headers, I would also suggest a tool that converts SVD to definitions that you feel comfortable with / fit your code style.Benefit, if the tool is correctly architectured, you could generate headers/definitions for a number of programming languages.

author: radiolistener
author_rank: Super Contributor
timestamp: September 13, 2025, 03:43:58 pm
content: Quote from: SiliconWizard on September 12, 2025, 08:30:24 pmThe idea is definitely interesting. But what’s not entirely clear is how to set up the configuration — specifically, what should be exported from the SVD. Ideally the generator should be customizable, e.g. only output base register structures and addresses, while including bitfields or more detailed definitions only if needed.

author: Chris Mr
author_rank: Regular Contributor
timestamp: September 14, 2025, 02:09:05 pm
content: The separation of the peripherals is important to me. It's also important that you can see (and therefore compare) peripherals at the same time. So you can say to yourself, Ah, it's like one of those but with an extra register.. and then follow what the register does to change things etc.One of the things which might not be obvious from the explanation is that whilst tab based text file for input isn't great for tools, it is so easy to copy an existing peripheral, add new registers (or remove some) that anyone can do it. I find markup language pretty tedious to check.. JSON isn't too bad but nowhere near as easy as tab based.On a side, but important, note I filed a case at ST due to finding a problem in the reference manual for the STM32U5A5 where it gives the wrong end point number for an address. For anyone interested it's RM0456, page 3381, last item is OTG_DIEPTXF7 at offset 0x120 which should be OTG_DIEPTX8. It's been accepted that is an error and will be dealt with internally.The important point being, how can that be the reference manualthe .SVD file is correct so how did they write thatthere is one possibility (probably more) that the reference manual was written after the .SVD file; in which case what were the people who wrote the .SVD file following?The various people who have suggested using the .SVD file are therefore correct, in that the .SVD file is closer to the "reference" than the reference manual (which sounds like an incredibly daft state of affairs).Without any insights inside ST it looks like they do have better documentation, but for whatever reason it's not what they provide. Instead someone writes the .SVD files, someone writes the reference manual and that's why the information is so incomplete.. the person(s) writing the reference manuals probably filter out IP so no-one else can copy it.. and in that process we lose quite a bit of the understanding we could really do with.

author: Siwastaja
author_rank: Super Contributor
timestamp: September 14, 2025, 03:24:57 pm
content: Quote from: Chris Mr on September 14, 2025, 02:09:05 pmI have filed a few. I think ST hasnever everfixeda single issueinanyof their reference manuals. It just doesn't happen. They don't even version them; they just "are". You caneasilyfind hundreds of errors in them. Maybe <5% of them are mentioned in a separate errata document - even that is a special exception at ST.The process at ST is like this: they first write the reference manual, documenting their internalhopesof what they aim to achieve. Then they publish the HW, which ends up being something different, and that obsolete document at the same time. The end result is not documented, and reference manuals or datasheets are never updated. Whenever backlash becomes excessive, they add an entry to a separate errata document, which is the only revisioned document.

author: bson
author_rank: Unknown
timestamp: September 15, 2025, 08:56:56 pm
content: Quote from: Chris Mr on September 14, 2025, 02:09:05 pm"Inheritance by copy and paste" makes for completely unmaintainable code...