# Bugs, Pitfalls, and Pain ###### tags: `firmware_hardware` `electrical_system` `NTURT` Most tutorials and documentations tell us how to make a thing work, but they don't tell us how to make a thing not work. So, this page is for making notes for what makes things not work. In general, 4 different things are to be blamed when stuff goes down if we are not using any 3rd party software or hardware: 1. We do some bad stuff 2. ST software did some bad stuff 3. ST firmware did some bad stuff 4. ST silicon did some bad stuff In most cases, the cause is #1. But sometimes, #2 and #3 can happen as well. These can be rare and hard to track down but sometimes we can find the answers in google or ST's forum, where some other engineers are already complaining at. This page mostly documents these 3 types of errors #4 is the rarest error, but also the hardest to track down. The info about these errors is written in each chip's **errata sheet**. It is always on ST's website along with the datasheet and reference manual. Be sure to check it out whenever you are starting working on a new MCU or are fighting a really confusing problem. Please come help extend this page if you also encounter anything painful. ## General ### Enabling NVIC remember to enable the NVIC interrupt in MX when you want to use anything with interrupts. ### English folders EVERY folder in your directory tree have to have English names, otherwise the compiler might freak out. ### Keep MX from deleting your code when you regenerate code from the ioc file, CubeMX will rewrite everything that is both 1. in the files generated automatically (such as main.c) 2. not bounded by the`/*USER CODE BEGIN*/` and`/*USER CODE END*/` tags. Be sure to put your code between the BEGIN and END tags. For example: ```cpp= /* USER CODE BEGIN WHILE */ while(1) { /* USER CODE END WHILE*/ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ ``` It's a trap. Don't put your code on line 4. Create a new line after line 2 or line 5 instead. Alternatively, you can put the code that you want to write in a seperate custom file instead. For example, do this in main.c: ```cpp= /*write this somewhere safe above*/ #include "user_main.h"; /* USER CODE BEGIN WHILE */ user_main(); while(1) { /* USER CODE END WHILE*/ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ ``` then make 2 more file at Inc/user_main.h and Src/user_main.c: ```cpp= #ifndef USER_MAIN_H #define USER_MAIN_H void user_main(); #endif //USER_MAIN_H ``` ```cpp= #include "user_main.h" #include "main.h" void user_main(){ // I can do anything here for(;;){ HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13); HAL_Delay(1000); } } ``` ### pin not responding on Nucleo Nucleo board has some board pins shared by 2 different microcontroller pins. Or, have 1 pin do 2 different functions. In these cases, there would be solder jumpers on the Nucleo that enable us to choose between connections. The solder jumper would have a default connection, so 1 of the solder jumper would be opened and the microcontroller pin would not be exposed. To know if a pin is not exposed by default, go to the user manual of a Nucleo board and Ctrl-F the pin name.(e.g. PA2) If there is a solder jumper between the pin and the board connector, we should be able to find it in the solder jumper section. To avoid some headaches, it is possible to initilize a C project in CubeIDE(or CubeMX)by using templates for Nucleo boards instead of the bare chip. This way, some pins having default functions(such as the debug ports and XTAL) would be activated accordingly by default. ![image](https://hackmd.io/_uploads/SJmciHnhT.png) ### ST account and disappearing code For some reason, newer CubeIDE requires the user to log into an ST account to use, while older versions only require us to input an email when we are downloading the software. When you first open up CubeIDE, make sure to make an account and log in when it ask you to. Otherwise the program will not generate the Cube firmware. ST takes forever to process their account email, so be sure do it early. I am not sure from which version did this became a thing. Currently tested versions include: 1. 1.0.9 -> not required 2. 1.0.15 -> login required If you know which version did ST started doing this awful thing, please write it here. Thank you.:heart: If you don't need the newer features, using older versions might be a useful workaround. ## Compilation ### Mac crash There was a case where compiling code using an i7 mac with newest CubeIDE would make it crash. Changing to an older version(1.0.9) made it work. If use use CubeIDE on a mac and stuff starts breaking, maybe swapping to an older version would work. ## Flashing Programs ### Fake and Evil Hardware Some of the BluePills and STLink found online contain fake or cloned ST chips. If you see a chip that does not say "STM32F103C8T6" then it is a clone chip, but even if the chip says "STM32F103C8T6", it might be a fake. current symptoms include: 1. CubeIDE throwing an unknown ID error when programming. Using CubeProgrammer can bypass this restriction, but debugging would still be impossible. Methods for bypassing ID checks is still being studied. 2. to be continued... STLinks can be fake as well. From our personal experience, the same vendor can have STLinks that packs genuine chips and non-ST chips in the same batch because they are essentially the same unless you plug them into a PC or remove their the casing. Clone or fake chips might still work if they contain the correct firmware, but oftentimes they don't. symptoms of a bad STLink include: 1. Showing a strange serial number when read by STM32CubeProgrammer 2. not being able to update its firmware 3. Having a central chip inside the casing that is not an ST chip. You can strip away the casing to check. 4. To be continued... We have not figured out a way to make the fake and evil STLinks to work(it might be possible to overwrite its firmware), so the current best way might simply be to buy from a reputable buyer that tests their product beforehand and avoid those that had give you evil STLinks before. ### Flashing BluePill - Serial Wire dubugging remember to enable your debug peripheral in the CubeMX, otherwise you will not be able to debug or flash any programs when the device is booted from flash. ### Flashing BluePill - BOOT Jumper jumpers on the blue pill board determine which memory is chosen when booting up, so make sure it is correctly placed when doing anything. ### No debug probe connected This can be of serveral different reasons. Currently known answers include: 1. USB port has a bad contact with PC. Try unplugging and plugging and tweaking the connector. 2. to be continued... (hopefully not) ## UART ### printf() function the std library on MCUs are a bit different than that run on PCs, and different dev environments use different std library. In Keil MDK, enable "use microlib", otherwise your program will get stuck in the init functions if you use ``#include "stdio.h".`` ## DMA ### DMA NVIC settings CubeMX enables DMA interrupts on default whenever you turn the DMA functionality on. However, we have had some trouble with DMA NVIC before as the program keeps freezing at startup for some misterious reason as long as we leave the DMA on. If your program also freezes after enabling DMA, try turning off DMA NVIC if you don't need the DMA interrupts. DMA NVIC can't be turned off directly at the DMA tab in each peripherals. You have to go to the NVIC tab under "System Core" and untick the "force DMA interrupt" box first. ### Initialization order [Blog post of this problem on ST forem](https://community.st.com/s/question/0D50X0000Bmob3uSQA/dma-not-working-in-cubemx-generated-code-order-of-initialization) There is a bug in STM32CubeMX that messes up the order in which hardware is initialized. ```MX_DMA_Init()``` should be called before any other peripheral that uses DMA. If that is not the case, the chance is high that MX messed up the order of the functions, which caused DMA to stop working. When the hardware is initialzed, ```MX_DMA_Init()``` should be called before any other peripheral that uses the DMA. This is because DMA's clock needs to be enabled in order for the registers to be writable. When HAL tries to write to the DMA's config registers before its clock is enabled in ```MX_DMA_Init()```, the registers would simply ignore the attempt and stay in its reset state. So, you can check the config register(e.g. CCR) of your DMA to see if this is the cause. If the config register of your DMA channel looks odd and doesn't match what you have set up in CubeMX, it might be that it was not correctly initialized. The fix for this is very simple. A temporary fix that should work before the next time you use CubeMX is to move ```MX_DMA_Init``` above all other peripherals except GPIO, and the problem should be eliminated. ST have said that newer versions of CubeMX should have this fixed, so checking for updates might be a good idea. ## CAN ### baud ## FreeRTOS ### Stack OverFlow Default stack size in CubeMX is 128 bytes. This is enough for most small tasks. But It can be used up pretty quickly.(especially if you're using stdlib or other libraries.) Stack Overflow have some unclear symptoms so it can be hard to diagnose. If you have any weird problems, always remembers to check the stack size. FreeRTOS has a built in function that returns the high water mark of stack memory for some task. ```c uxTaskGetStackHighWaterMark(xTask) ``` Acording to freertos.org: :::info Parameter: xTask: The handle of the task being queried. A task may query its own high water mark by passing NULL as the xTask parameter. Return Value: The value returned is the high water mark in words (for example, on a 32 bit machine a return value of 1 would indicate that 4 bytes of stack were unused). If the return value is zero then the task has likely overflowed its stack. If the return value is close to zero then the task has come close to overflowing its stack. ::: Alternatively, if you want to view the stats in CubeIDE in debug mode: https://stm32world.com/wiki/STM32_FreeRTOS_Statistics