2025-07-17 5:56 AM - last edited on 2025-07-17 8:08 AM by Mike_ST
I've been working on a project on STM32F746-Discovery with only CMSIS (no other libraries written by not me) on a Windows machine in STM32CubeIDE. I used the default STM startup file (.s with a vector table and a memory initialization), the startup_stm32f746nghx.s. This file, among other things, defines a list of weak IRQ handler hooks with interrupt handler names. So naturally I took the name HASH_RNG_IRQHandler straight from the file. I declared the function extern "C" to prevent name mangling in C++, besides, it's far from the first interrupt handler in the project. All of them work without an issue. When I compiled and ran the project, I found myself hardfaulting. I debugged my way through everything, but everything looked solid. It just suddenly crashed after I enabled the RNG peripheral. I verified everything there was to verify, but found nothing odd, right before RNGEN, the RNG showed no error flags, no seed error, no clock error. My gut feel told me to look at the vector table in the flash memory with the memory inspector - and voila! There is no entry for my interrupt handler, just a weak default handler value. It confused me.
I tried to force-disable mangling differently, so instead of not working (not linking)
extern "C" void HASH_RNG_IRQHandler(){
...
}
I did
void HASH_RNG_IRQHandler() __asm__ ("HASH_RNG_IRQHandler");
void HASH_RNG_IRQHandler(){
...
}
And what do you know, it worked! It linked! Now, everything worked, so I could proceed with the project, but I decided to figure out what was happening. It was bugging me immensely that all other handlers just work with extern "C", but this one specifically doesn't link with extern "C". I couldn't let it go.
I examined the startup file .s up and down, left and right, but found nothing at all. The HASH_RNG_IRQHandler was declared just like any other interrupt, no special conditions, no checks of any defined values or macros, nothing at all. The most regular boring vector table entry.
But then I opened stm32f746.h, and saw this:
/* Aliases for __IRQn */
#define HASH_RNG_IRQn RNG_IRQn
/* Aliases for __IRQHandler */
#define HASH_RNG_IRQHandler RNG_IRQHandler
So instead of mapping just RNG onto HASH_RNG, it goes the other way around and maps HASH_RNG onto just RNG. And the IRQ number for the interrupt is called RNG_IRQn in the table where they are assigned values. And the preprocessor shamelessly replaced my wonderful HASH_RNG_IRQHandler with a miserable RNG_IRQHandler!
I commented out the #define HASH_RNG_IRQHandler RNG_IRQHandler, and what do you know! Everything worked, my vector table has the correct entry at the correct place!
Both of these files were supplied by default with the STM32F746, and in their current state they are mutually exclusive with respect to this interrupt handler.
The file "stm32f746.h" should be fixed in 3 places:
1. The proper name of this interrupt handler is HASH_RNG_IRQHandler, because it handles interrupts from both HASH and RNG peripherals. This is so in .s, but .h redefines it. It should define the other way around and map RNG_IRQHandler name onto the primary HASH_RNG_IRQHandler name.
#define RNG_IRQHandler HASH_RNG_IRQHandler
2. The IRQn number must be defined in the interrupt table not as RNG_IRQn = 80, but as HASH_RNG_IRQn = 80.
DCMI_IRQn = 78, /*!< DCMI global interrupt */
HASH_RNG_IRQn = 80, /*!< HASH and RNG global interrupt */
FPU_IRQn = 81, /*!< FPU global interrupt */
3. The name RNG_IRQn should be mapped onto HASH_RNG_IRQn.
#define RNG_IRQn HASH_RNG_IRQn
In the current state, the .s and .h are in a conflict regarding this interrupt.
Now, just as I was proof-reading this text, I noticed that in the IRQ list, the RNG_IRQn = 80, but the DCMI_IRQn just above has 78. Where is 79? I checked the .s file. It's CRYP peripheral with the according CRYP_IRQHandler! And CRYP_IRQn is clearly missing from the list of IRQns in the stm32f746.h. What's even more interesting is that the letter combination of "CRYP" is nowhere to be found in the entire file stm32f746.h. It's like this peripheral doesn't exist. I verified in the reference manual that the peripheral can emit interrupts, and its total absence from the header file is suspicious.
Please, at least fix the conflicting HASH and RNG handler definitions for this file.
2025-07-17 8:04 AM
Hello,
What version of the firmware package for STM32F7xx are you working on ?
It does look like you're working on old or heavily modified ST code, in that case we can't fix what you're reporting.
The latest firmware package can be found here:
In our latest startup_stm32f746xx.s file, the ISR vector table for the STM32F746 in a gcc env is declared like that:
.word DCMI_IRQHandler /* DCMI */
.word 0 /* Reserved */
.word RNG_IRQHandler /* Rng */
.word 0 is there because the crypto block does not exist on STM32F746
For the STM32F756 you will have that:
.word DCMI_IRQHandler /* DCMI */
.word CRYP_IRQHandler /* Crypto */
.word HASH_RNG_IRQHandler /* Hash and Rng */
2025-07-17 11:42 AM
It was updated a month ago, when I started the current project, I believe. But the point is, I'm talking about broken RNG here first and foremost. The MCU header breaks the startup interrupt handler, it's the most important thing here, the CRYP part is something I noticed while writing this thing. It's completely secondary, and it's good that you clarified things about it.
2025-07-17 1:00 PM
Just get the current version of these CMSIS files from the ST source.
The device .h file is stm32f746xx.h (not stm32f746.h) - and here is defined the IRQ number.
The .s file is startup_stm32f746xx.s and here is the handler. At offset 80.
Nothing looks broken there.
2025-07-17 3:03 PM
Interesting. Your .h is the same as mine, but your .s has the IRQ handler name as just "RNG_IRQHandler" , without HASH part (mine has HASH_RNG_IRQHandler). Which is odd, because HASH peripheral also lands into that handler. I think, whoever fixed it, fixed the wrong thing .It was .s that was correct and .h that was and still is broken because it still has the line
#define HASH_RNG_IRQHandler RNG_IRQHandler
which is an obvious mistake, it has to be the other way around, and the .s should have the IRQ handler name with HASH too, because it's HASH's handler as well. The change to .s made it link correctly, obviously, but it's a fix in the wrong direction. The reality is that that handler handles both HASH and RNG, so the main name of it in the .s should be with HASH and RNG, and just RNG name without HASH should be an alias for it, not the other way around.