STM32G0 freezes over time - Page 1
Forum section: electronics / general

author: Veketti
author_rank: Regular Contributor
timestamp: December 21, 2023, 05:14:37 pm
content: Dear All,So I'm developing to myself accurate CO meter which uses Winsen ZE07-CO sensor and STM32G050F6 uC. Current operation is so that it will read the ZE07 through UART and if the reading is below 1ppm it will shut down the power supply to connected 4 bit parallel character display and go to stop mode1. Then through RTC LSI 32kHz every five seconds wake up and read again. This is in while loop to happen forever. If CO value is over 1ppm, then it won’t go to sleep and read the sensor every one second as well as turn on the display. This all works like it should for a good period of time. However, the next day it won’t wake up anymore. I’m stumbled and don’t know how could I troubleshoot this kind of issue which take several hours until it happens. Could it be like some sort of memory leak which eventually freeze the MCU? How could I possibly find out where the problem is? It froze before I implemented the stop mode as well so that most likely is not the culprit.Thank you in advance

author: eutectique
author_rank: Frequent Contributor
timestamp: December 21, 2023, 05:26:21 pm
content: Quote from: Veketti on December 21, 2023, 05:14:37 pmIs this time-to-fail more or less constant? Could be related to an overrun counter.You could possibly make it sleep 1 second instead of 5, thus (potentially) speeding up the failure.Do you have a spare UART? You could dump some variables to the port.Also, the first link brought by google is this:https://community.st.com/t5/stm32-mcus-embedded-software/stm32g030-sometimes-not-waking-up-from-stop-1-mode/td-p/604906

author: ataradov
author_rank: Super Contributor
timestamp: December 21, 2023, 05:26:50 pm
content: Attach the debugger and check the state of the device Just knowing the program counter value and matching that to the map listing may give you a good idea of what went wrong.If you think that actual sleep does not matter for the reproduction, disable it for debugging. It will make debugging easier.

author: cv007
author_rank: Frequent Contributor
timestamp: December 21, 2023, 11:31:17 pm
content: Since you already have a display in use, skip powering it off and use it to show debug info.init_stuf();unsigned count = 0;while(1){wfi(); //wait for rtc wakeup timer (set to 1 second, never changed)//if stuck here, display will show last readingdisplay("reading co...");int v = read_co(); //if stuck here, display will show reading co...display("[0x%08X] co: %d"); //  co: 5//if display is corrupt, incomplete, blank, then maybe display functions have a problem}The setting of rtc between 5 sec and 1 sec is eliminated, which could be a potential problem, display is not turned off so display initialization is eliminated (except for initial init), no low power mode, you will be able to see whether rtc wakeup is working, or if stuck in the read_co() function.A debugger is a better alternative, but a simple lcd display already in use can be quite helpful (and a uart is even better as you can dump more info and have a record of it).

author: Veketti
author_rank: Regular Contributor
timestamp: December 22, 2023, 01:02:56 pm
content: I haven't been able to yet see whether it always freezes after the same period of time. But what I found out was that it's not the display or the ZE07. I scoped the serial line to the ZE07 and the uC had stopped sending the value request message. Right after I power cycle the device it starts communicating with the sensor again. It has poll the sensor now already over five hours and still continue, so lets see how many hours until it freezes again.I haven't played with watchdog before, but could that be utilized to reboot the device for example every hour? Of course it would be just a band aid, but better than manual power cycle. Maybe it's not a good idea when thinking of how important role this whole meter is playing..

author: SiliconWizard
author_rank: Super Contributor
timestamp: December 22, 2023, 11:20:19 pm
content: You should enable the watchdog IMO, but as you said, not as a band-aid. As a last resort thing, just in case.The additional benefit of the watchdog is that it will make it obvious when the MCU is blocked somewhere (it will reset), rather than having to guess just because it "looks" frozen.You can catch that the reset cause was a watchdog timeout reading a register. So you can detect it happened.It's impossible to tell what the cause is without the full code and context. It may be an infinite loop somewhere in your code, or it may be a hard fauit exception, for instance. One thing to do to debug it is to find out if a hard fault occurs.Either use a debugger and place a breakpoint in the hard fault handler (which with "standard" STM32 HAL code, executes just an infinite loop), or if you don't want to use a debugger, you can toggle a GPIO in the hard fault handler, something like this. Could just be turning a LED on. That way, you can leave the device running and when it eventually freezes, if the LED is on, you know it was due to a hard fault (for this debugging test, don't turn on the watchdog).

author: DavidAlfa
author_rank: Super Contributor
timestamp: December 23, 2023, 07:53:42 am
content: Hard to know, could be a million things, maybe something as simple as your code stuck in a while() loop with no timeout control where you didn't expect something to fail.You definitely need a debugger, you can easilyattach it to a running systemand see what it's doing.

author: Veketti
author_rank: Regular Contributor
timestamp: December 23, 2023, 07:54:25 am
content: Before I went to bed last night, it was still running so it was ok for almost 9 hours. This morning when I woke up it was dead. So it froze after running 9 to 18 hours. Don’t have any counters which aren’t bulletproof for zeroing. Also I’m thinking as the time it freezes is so long, all the programming errors should be due very much earlier? Maybe I’ve managed to ESD damage it, even though I’ve been extra cautious with it.One thing that makes me doubt is the HAL serial functions that could it somehow in long run fill some buffer and cause failure? With PIC mcu’s I used to do “while (Uart1_Data_Ready()) trash = Uart1_Read(); // Clear the uart buffer” to clear the buffer and never had issues.Do you see issue with this Uart code that I’m using, maybe this will eventually overrun some buffer or something?Code:// in main while loopif ( (readCOSensor) || (GoToSleep) ){readCOSensor = false;HAL_UART_Transmit_IT(&huart1, question, sizeof(question)); // Request data from ZE07HAL_UART_Receive_IT(&huart1, answer_data, 9);// receive data from ZE07HAL_Delay(100); // Wait for the IT to trigger. Serial data should be ready after this if ever.}if ( (data_ready) && CheckSumCalculate() ){data_ready = false;.....}else if (data_ready) // Checksum didn't match. Don't go to sleep, need new value read{data_ready = false;GoToSleep = false;}else GoToSleep = false; // Don't go to sleep as we haven't had sensible values from ZE07// Serial interrupt, when data readyvoid HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){data_ready = true;}

author: DavidAlfa
author_rank: Super Contributor
timestamp: December 23, 2023, 08:18:19 am
content: You aren't checking the return value of HAL functions, always do it, should be HAL_OK.Return values can be HAL_OK, HAL_ERROR, HAL_BUSY, HAL_TIMEOUT.IT functions are non-blocking, so:Code:HAL_UART_Transmit_IT(&huart1, question, sizeof(question)); // This won't wait until sent, so instantly proceed withHAL_UART_Receive_IT(&huart1, answer_data, 9);// With thisIt should work, as the device won't start sending anything until he gets the command, but it might be causing some conflict in HAL or whatever.Also, using IT to later wait in a loop is silly and won't provide any benefit, just do non-IT, removing possible sources of trouble:Code:HAL_UART_Transmit(&huart1, question, sizeof(question), 100); // 100m timeoutHAL_UART_Receive(&huart1, answer_data, 9, 100);// 100ms timeoutTX failing would be rare as it only depends on the uart interface, will send the data no matter who is listening at the other side.But RX fully depends on the external device, if for whatever module doesn't answer back you'll get a timeout.Never asume it'll always work when working with external peripherals.Code:HAL_StatusTypeDef status;status = HAL_UART_Receive(&huart1, answer_data, 9, 100);if (status!=HAL_OK){// check if it's error, timeout, busy...}

author: Veketti
author_rank: Regular Contributor
timestamp: December 23, 2023, 11:51:30 am
content: Sorry, maybe stupid question. I'm not sure what happened but the debuggin does now fail at the last line of following code with "target is not responding":Code:/*Configure GPIO pins : PA8 PA12 PA13 PA14PA15 */GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;GPIO_InitStruct.Pull = GPIO_NOPULL;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);I haven't done any changes to these so that makes me wonder. Those pins include the SWDIO, SWCLK and reset, so maybe they are wrongly declared?

author: DavidAlfa
author_rank: Super Contributor
timestamp: December 23, 2023, 12:58:15 pm
content: Because you're screwing it up when setting SWD pins to analog (PA13 & PA14), leave them untouched.SWD pins are set to Alternate (AF) on power-on / system reset, but analog mode turns everything off, it's only done to reduce power consumtion on unused pins.Code:GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_12|GPIO_PIN_15;

author: Veketti
author_rank: Regular Contributor
timestamp: December 23, 2023, 05:08:20 pm
content: Thank you so much. Having ability to actually debug makes life so much easier. One more question this time on IWDG. I'm having hard time understanding ST'sdocumenton IWDG. Through CubeMX I generated the IWDG init and I calculated that with prescaler_256 and Reload = 1249 I should have 10 seconds time to refresh the IWDG, before reset. But the documentation is confusing on how to disable the window, as I don't want any refresh window. Document states: "Otherwise, refresh the counter by a writing 0x0000_AAAA in the Key register to disable the window option." Does it mean writing hiwdg.Init.Window = 0xAAAA;? That cubemx created intialization function doesn't have same keywords than the ST's document so I'm really stumbled. Here's the init function where I added correct prescaler and Reload for 10 seconds:Code:static void MX_IWDG_Init(void){/* USER CODE BEGIN IWDG_Init 0 *//* USER CODE END IWDG_Init 0 *//* USER CODE BEGIN IWDG_Init 1 *//* USER CODE END IWDG_Init 1 */hiwdg.Instance = IWDG;hiwdg.Init.Prescaler = IWDG_PRESCALER_256;hiwdg.Init.Window = 0; // how to disable window?hiwdg.Init.Reload = 1249;if (HAL_IWDG_Init(&hiwdg) != HAL_OK){Error_Handler();}/* USER CODE BEGIN IWDG_Init 2 *//* USER CODE END IWDG_Init 2 */}Sorry for my ignorance.

author: DavidAlfa
author_rank: Super Contributor
timestamp: December 23, 2023, 05:48:37 pm
content: Did you read the reference manual? I think you're mixing up WWDG and IWDG.WWDG is the one with the refresh window, not IWDG.IWDG is just a free-running counter, refresh anytime, the system will reset if reaching 0.https://www.eevblog.com/forum/microcontrollers/production-loading-of-code-into-a-st-32f417/msg5062525/#msg5062525Just use HAL_IWDG_Refresh(&hiwdg); (But indeed, it does IWDG->KR = 0xAAAA;)Yes, Prescaler_256 and Reload = 1249 should make 10 seconds @ 32KHZ LSI.But I wouldn't use IWDG for development stage, you'll have nasty resets here and there while trying things.One your code is working, proceed with the IWDG, but still, not very useful as it'll reset the system and you'll have a hard time finding out why.It's better to just let it hang/frezze somewhere, then attach the debugger and see where is it stalled at. "Ahh this while() is stuck!"

author: Veketti
author_rank: Regular Contributor
timestamp: December 23, 2023, 06:08:25 pm
content: Yes I read that document that I linked and it mentions about the window as well. And the MXCube generated that window line as well when I selected the IWDG. No I'm not confusing to the WWDG, it seems this G0 series has that window in IWDG as well. I found this:https://community.st.com/t5/stm32-mcus-products/stm32g0-iwdg/td-p/195232and set:Code:hiwdg.Init.Window = IWDG_WINDOW_DISABLE;and now it works.Beats me why isn't that document telling that to disable the window use "hiwdg.Init.Window = IWDG_WINDOW_DISABLE;", but instead it tells cryptic "Window option disabled: Refresh counter value with IWDG_RLR by writing 0x0000_AAAA in register IWDG_KR"

author: SiliconWizard
author_rank: Super Contributor
timestamp: December 23, 2023, 07:45:21 pm
content: The HAL documentation is lackluster, and if you're using it, I highly recommend 1/ reading the reference manual and the datasheet to understand the peripherals you're using, then the HAL parameters will make a bit more sense, and 2/ looking at the source code of the HAL function/type definition you're wondering about, it helps a lot figuring things out. The source code for the HAL is fully available.

author: DavidAlfa
author_rank: Super Contributor
timestamp: December 23, 2023, 07:56:42 pm
content: The documentation is the HAL itself, every function explains the arguments and everything.

author: 8goran8
author_rank: Contributor
timestamp: December 23, 2023, 11:43:37 pm
content: What will happen in your main loop if STM does not receive any response within 100ms?Code:data_ready = false;readCOSensor = false;GoToSleep = false;If I see the code correctly, it will remain stuck in the main loop.

author: DavidAlfa
author_rank: Super Contributor
timestamp: December 24, 2023, 10:11:34 am
content: Following the documentation rant, it's not that hard.The examples are for G4 but applies in the same way.Every source file has plenty of info at the beginning, likestm32g4xx_hal_iwdg.c.Then each function has a "pre-comment" explaining a bit what it does, likeHAL_IWDG_Init.Most HAL functions uses specific typedefs, like xxx_InitTypedef structure.To see the arguments they take, simply go to their declaration (Control+click in cubeIDE), this works for variables, functions...For example,IWDG_InitTypeDef.Code:typedef struct{uint32_t Prescaler; /*!< Select the prescaler of the IWDG.This parameter can be a value of @ref IWDG_Prescaler */uint32_t Reload; /*!< Specifies the IWDG down-counter reload value.This parameter must be a number between Min_Data = 0 and Max_Data = 0x0FFF */uint32_t Window; /*!< Specifies the window value to be compared to the down-counter.This parameter must be a number between Min_Data = 0 and Max_Data = 0x0FFF */} IWDG_InitTypeDef;See how each parameter explains itself, also showing the argument type they take, for example the prescaler:Code:This parameter can be a value of @ref IWDG_PrescalerFinddefgroup IWDG_Prescaler, there you'll get all the possible arguments:Code:/** @defgroup IWDG_Prescaler IWDG Prescaler* @{*/#define IWDG_PRESCALER_4 0x00000000u /*!< IWDG prescaler set to 4 */#define IWDG_PRESCALER_8 IWDG_PR_PR_0 /*!< IWDG prescaler set to 8 */#define IWDG_PRESCALER_16 IWDG_PR_PR_1 /*!< IWDG prescaler set to 16 */#define IWDG_PRESCALER_32 (IWDG_PR_PR_1 | IWDG_PR_PR_0) /*!< IWDG prescaler set to 32 */#define IWDG_PRESCALER_64 IWDG_PR_PR_2 /*!< IWDG prescaler set to 64 */#define IWDG_PRESCALER_128 (IWDG_PR_PR_2 | IWDG_PR_PR_0) /*!< IWDG prescaler set to 128 */#define IWDG_PRESCALER_256And that's pretty much it!

author: Veketti
author_rank: Regular Contributor
timestamp: December 24, 2023, 10:46:23 am
content: Sorry to still continue this. Not trying to argue, just trying to learn. But still reading the HAL comments and explanations, I still can't seem to find clear description of disabling the window. Only this:Code:#define IWDG_WINDOW_DISABLE IWDG_WINR_WINand then the ST community post where someone used like:Code:hiwdg.Init.Window = IWDG_WINDOW_DISABLE;, which did resolve my reset issue. Where is the usage of this described, or how should I conclude how it works?@8goran8 ReadCOSensor is set by timer6 every one second, so it shouldn't get stuck in the loop. And if it's set to sleep/RTC wakeup, GoToSleep is set.

author: Siwastaja
author_rank: Super Contributor
timestamp: December 24, 2023, 10:59:38 am
content: Quote from: Veketti on December 24, 2023, 10:46:23 amIt's all in the reference manual. Just read the manual, not library documentation or Google. But this is the usual issue with libraries: you have to spend twice the effort, learning both the library and the actual hardware. You tried to use the library, now you hit the wall, and have to start again from the actual source of information anyway; next time you know to start from there.In general, for mysterious hangs, a debugger would be a handy tool; attach it to the target and read out the program counter to see where it is stuck. You can then also examine state of peripherals, your own state variables etc. An alternative, if you do not have physical access to the device, is to use watchdog as described but write a high-priority watchdog handler which (hopefully) is able to pre-empt any other stuck interrupt or whatever is causing the issue. In that watchdog handler, dump interesting information (internal variable values, PC value, stack dump)... somewhere. One option is a region in RAM which is not cleared by boot code, which you can then dump out to your display after a reset.

author: DavidAlfa
author_rank: Super Contributor
timestamp: December 24, 2023, 11:05:08 am
content: It only needs a bit of reading tofind it out, it's not very well explained, but the true details are in theRM, 28.3.2:Quote

author: Veketti
author_rank: Regular Contributor
timestamp: December 24, 2023, 11:56:19 am
content: Wonderful, thanks.For these mysterious hangs, do I need to leave the debugger connected and cubeIde running to be able to see where it stuck, or is it possible to attach the device afterwards once it's hang and see where it hung? If it's possible to afterwards diagnose, what would be good documentation/instructions how to do this?

author: DavidAlfa
author_rank: Super Contributor
timestamp: December 24, 2023, 12:03:34 pm
content: You can leave it running without the debugger and attach it later, see my first posts, I linked a message showing how to do this.Edit:here.

author: nctnico
author_rank: Super Contributor
timestamp: December 28, 2023, 03:57:11 am
content: How is the layout? Especially where it comes to power supply decoupling?

author: temperance
author_rank: Super Contributor
timestamp: December 28, 2023, 03:38:18 pm
content: QuoteIs it not waking up after power on or after a while? If it happens after power on, the reset line might be floating. Also check the CLK line of the debug interface.

author: DavidAlfa
author_rank: Super Contributor
timestamp: December 28, 2023, 05:22:34 pm
content: Toggle a LED in the SysTick ISR, another in the main loop.If both stop completely it probably got a Hardfault, but if the systick led keeps working it's probably caused by you code being stuck somewhere by something you didn't account for.In any case the debugger will show it instantly.

author: Siwastaja
author_rank: Super Contributor
timestamp: December 28, 2023, 05:41:21 pm
content: Quote from: DavidAlfa on December 28, 2023, 05:22:34 pmI always write a hardfault handler (and busfault, and the others) so that I don't need to guess. Something as simple as blinking an LED for 3 times for hardfault, 4 times for busfault, 5 times for "invalid handler" (to which all interrupt vectors are initialized to by default), instead of the "silent" while(1) loop. Doesn't take many minutes to write and you can reuse them across projects.

author: DavidAlfa
author_rank: Super Contributor
timestamp: December 28, 2023, 06:14:40 pm
content: That's also a very simple yet efficient approach, but my money is in a while(not_done) for the reasons I said earlier.99.99% something is wrong around the UART code!

author: Veketti
author_rank: Regular Contributor
timestamp: December 29, 2023, 07:54:19 am
content: @ntnicoMuch has happened in the meantime. I revised the power supply layout according toArdWar’s comments. However there was no mention about issues with decoupling so didn’t touch that side.@temperanceGood point. I noticed I missed the 100nF capacitor from the NRST pin which should filter out EMC resets. However any layout I’ve found does not include external pullup/pulldown resistors for NRST, SWDIO & SWCLK. It’s confusing, do they need or not?@EveryoneI basically redesigned the PCB with the improvements I mentioned above. Also changed the display type from HD44780 parallel to SSD1306 and added HM-10 BTLE and noticed I ran out of flash & pins so I upgraded the MCU to STM32G070CBT6 which I recently ordered plenty of. I also added led to the new design so I could use that to indicate any error handler faults etc.I also changed the uart communication from interrupt to direct and added the IWDG with 10 seconds timeout. Device goes to sleep in case no CO detected for five seconds and takes read and goes back to sleep. Now it has kept running for several days without freeze. Wakes up every day, when I burn some wood in the stove (commercial meters don’t even react yet). I don’t know whether it was the uart IT which was causing the freeze or what.I’ve been also thinking my head around to save the energy on this. Now it draws 7.5mA with the display turned off which with AA batteries will last bit over a week. ZE07 sensor has heating time of 60 seconds so I cannot power it off every five seconds and have a read. It draws 4.5mA just doing nothing. I think I have no other possibility than add manual switch and power it on when I decide to burn some wood in the stove. Other times keep it turned off. The other approach I’ve been thinking is big LiPo battery and USB C charging module and plug it in every other week or so..Sorry to ask again stupid questions, most likely this is also mentioned in some documentation which I haven’t found but do I need to declare these SWDIO and SWCLK pins like this or leave them at reset state? Before they were left to reset state and the debugging and programming worked ok. Maybe this way I don't need to remove the analog declaration each time I generate the code from these pins? What else might it do?

author: DavidAlfa
author_rank: Super Contributor
timestamp: December 29, 2023, 11:30:10 am
content: By default they're set to SWD but HAL might change them if Serial Wire isn't enabled under SYS tab.Only required if you want to attach a debugger.nRST has an internal pullup, read the RM.A failure here would reset your system, not freeze it.If you have to wait 60 seconds for the sensor, set LSI, start a low power timer and go to sleep, let the timer wake the system when it's over.Are you enabling compiler optimizations? Set it to size optimization and you'll see a huge gain.Are you using u8g2 for the oled?If so and you're using large fonts, there're tools to make your own fonts, adding only the required chars, this saves a lot of memory, seethis.

author: Veketti
author_rank: Regular Contributor
timestamp: December 29, 2023, 11:52:58 am
content: I enabled the "optimize for size" like you earlier suggested and it helped a lot. Otherwise I would have ran out of flash way earlier..For the SSD1306 I'm usinghttps://github.com/afiskon/stm32-ssd1306library which is based on 4ilo's library.

author: DavidAlfa
author_rank: Super Contributor
timestamp: December 29, 2023, 12:12:13 pm
content: Also your code seems to be pretty simple, maybe go LL and save more space?Is it a commercial project or just for your own? That mcu might have double the flash like so many stm32.The STM32G050F6 has DIE456, which means it's very much the same as all these, 99.99% it has 64Kb flash and can be unlocked, seethis.Quote

author: Veketti
author_rank: Regular Contributor
timestamp: December 29, 2023, 12:37:13 pm
content: Hmm, interesting, 64kB would be plenty. Maybe I'll test that some time. However I accidentally while back ordered 40 pcs of the 128kB STM32G070CBT6 from LCSC due to first time ordering there and not checking how they multiply strangely the amount, so I think those will last for my personal projects for the rest of my life.This is just my hobby, I used to challenge myself to do the devices I can't find exactly what I'm looking for, so nothing commercial here.

author: DavidAlfa
author_rank: Super Contributor
timestamp: December 29, 2023, 12:46:38 pm
content: So hobby & hacking it is!Try u8g2, you might be surprised. Also I recall the font structure having some kind of data compression? Not sure!I'm using it in a project with the HK32F030, also LL libs, it's only using 13KB of flash.Though I'm using only one small font (u8g2_font_6x12_tr), a 0.91" 128x32 display can't display much.

author: DavidAlfa
author_rank: Super Contributor
timestamp: December 29, 2023, 04:25:18 pm
content: I ported the custom LCD lib (Using u8g2) I was using for HK32/PY32 to STM32G0.Works in my STM32G030.Using LL, everything takes less than 8KB, including initialization, drawing routines, 9x15 font, test program...1KB RAM is used for the local oled buffer (It's much better this way).u8g2 is huge, so the files are too large to post here (10MB), uploaded to myGoogle drive.(Oops minor bug in the example, updating screen twice, so it reported half the speed. Ensure your file timestamp is 18:12 or download again).As you'll see I do my own OLED initialization instead using some existing u8g2 profile, I prefer it like that to make it easier to modify, also u8g2 has a thousand profiles I don't feel like trying until finding the correct one.I just copied the display test from the STM32 soldering FW and modified it slightly.PB0 is a led, will blink slowly is ok, fast if the display was not detected.The good about CubeMX is you can remap any pin easily, just choose any other pin and name it "LED".Other pins are mostly explained in display.h.It uses Fast Mode (400KHz), this gives about 35FPS, you can try setting it to Fast Mode Plus (1MHz) for about 80FPS.Worked for me but will heavily depend on the display, wires/traces and pullup resistors (If not working, replace the default 10K with 2K2 or 1K).

author: Veketti
author_rank: Regular Contributor
timestamp: December 29, 2023, 10:10:26 pm
content: Quote from: DavidAlfa on December 29, 2023, 04:25:18 pmThank you so much, I'll try that.Quote from: Siwastaja on December 28, 2023, 05:41:21 pmThis is interesting, I'd like to try similar approach. Would you mind opening bit, how did you do that? Is it using timers for the LED blink? Like in error handler case for different HAL statuses and then call separate function for led blink and pass the times to it and start timer and blink the amount? Or in error handler just Hal_Delay_ms() and toggle pin state? Or something else? As I'm not sure what works in the fault state..

author: DavidAlfa
author_rank: Super Contributor
timestamp: December 29, 2023, 11:14:18 pm
content: A hard fault is a terminal, top priority interrupt, no other interrupts are allowed, so normally you'll make a software delay based in a for() loop or similar.However you can still poll the SysTick timer, as it will keep running in the background:Code:void HardFault_Handler(void) {while (1) {LED_GPIO_Port->ODR ^= LED_Pin;LL_mDelay(20);}}From LL libs (Cleaned up):Code:#define LL_MAX_DELAY 0xFFFFFFFFU /* Max delay can be used in LL_mDelay */void LL_mDelay(uint32_t Delay){SysTick->CTRL; /* Clear the COUNTFLAG first */if (Delay < LL_MAX_DELAY) /* Add a period to guaranty minimum wait */Delay ++;while (Delay != 0U) {if ((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) != 0U)Delay --;}}

author: Siwastaja
author_rank: Super Contributor
timestamp: December 30, 2023, 08:47:19 am
content: Quote from: Veketti on December 29, 2023, 10:10:26 pmJust something super simple like this:Code:void hardfault_handler(){RCC->... // enable GPIO ports, in case some other code disabled them or hardfault triggered before initGPIO->... // configure LED pin as output, for the same reasonwhile(1){for(int cnt=0; cnt<5; cnt++){GPIO->BSRR = ... // turn LED ondelay_simple(1000);GPIO->BSRR = ... // turn LED offdelay_simple(1000);}delay_simple(2000);}}Code:static void delay_simple(uint32_t i){i *= 1024; // some random multiplier you experimentally find so that delay is suitable for the intended purpose, for the eye.// depending on what the clock configuration registers happen to be at the time of fault, it might blink faster or slower,// but will be visiblewhile(i--)__asm__ __volatile__ ("nop");}Hardfault handler by definition cannot be pre-empted by any other interrupt source, but if you use same kind of terminal led blinker functions for other purposes, then you might want to make them disable the interrupts as the first thing.

author: Veketti
author_rank: Regular Contributor
timestamp: January 10, 2024, 03:15:31 pm
content: Update to this. I got new pcb's where I implemented led and added Error_Handler and HardFault_Handler led control. It seems it gets to the HardFault_Handler. Now even more, when the display is changed to be i2c ssd1306 variant. Sometimes it works and sometimes not. I need to study how to find out how can I see what was the command that caused the hardfault..

author: newbrain
author_rank: Super Contributor
timestamp: January 10, 2024, 03:42:53 pm
content: Quote from: Veketti on January 10, 2024, 03:15:31 pmFollow ataradov's advice in Reply #2: attach a debugger and look at the stack trace.The trace will tell you where the hard fault was generated and any decent IDE will bring to the exact spot in the code.But the same advice was repeated many times in the thread, is there a reason this is not possible?

author: Siwastaja
author_rank: Super Contributor
timestamp: January 10, 2024, 04:53:31 pm
content: With a debugger, you would look at Hardfault Status Register and others. If there is some actual reason not to use a debugger, you can just print those interesting registers to UART as well in your hardfault handler (make it an infinite loop which prints every second so that you don't miss the printout when it happens). You want to look at the content of HFSR, which reveals if this was an actual hardfault, or some other fault escalating into hardfault. You can usually find the address where the problem occurred in, and then, for example using arm-none-eabi-objdump list the symbols to find the function name this piece of code resides in, or disassemble (still with objdump) the code to find the exact instruction. All of this is of course somewhat quicker in an IDE&debugger once you have it set up.Read this great tutorial:https://interrupt.memfault.com/blog/cortex-m-hardfault-debug

author: Veketti
author_rank: Regular Contributor
timestamp: January 10, 2024, 07:08:33 pm
content: Odd thing is that this seem to cause hardfault:HAL_GPIO_WritePin(DISP_PW_O_GPIO_Port, DISP_PW_O_Pin, GPIO_PIN_RESET);But this doesn't:HAL_GPIO_WritePin(GPIOB, 13, GPIO_PIN_RESET);

author: ataradov
author_rank: Super Contributor
timestamp: January 10, 2024, 07:21:31 pm
content: How are DISP_PW_O_GPIO_Port and DISP_PW_O_Pin defined?Also, disassemble both versions of the code and see what is the difference. It is possible that HF is not related to that code specifically, but the change in size moves something else in the address space.Get a debugger and read the top 8 words of the stack when HF happens, it will tell you the exact PC value at the time of fault.

author: newbrain
author_rank: Super Contributor
timestamp: January 11, 2024, 08:37:20 am
content: Quote from: Siwastaja on January 10, 2024, 04:53:31 pmThe STM32G0 series is a Cortex M0+, so the exception model ismuchsimpler than the one in M3..7: there is only Hard Fault, and no detail registers, no cases where the (hard) fault is "imprecise", AFAIR.It should be much easier to debug as the stack trace is more or less the only valuable piece of information, and the debugger/IDE can easily unravel it, though one lacks the details available with the more advance cores.If the OP is using an RTOS, they should be aware of the MSP/PSP distinction, good IDE and debug servers are RTOS aware.

author: cv007
author_rank: Frequent Contributor
timestamp: January 11, 2024, 09:02:36 am
content: If your DISP_PW_O_GPIO_Port is something like-#define DISP_PW_O_GPIO_Port GPIOBthen there is really nothing that could cause a hard fault using the same port (address).The other two arguments could literally be anything, and the worse that can happen is you get the wrong bitmask and/or apply it to the wrong register (but still bsrr or brr), not a hard fault.If your define is something else, then all bets are off. The function takes a GPIO_TypeDef*, and if not actually a gpio port address, then you will be writing somewhere not intended (for some reason the stm32 hal does not assert_param the port parameter, which is the most important thing to check in this function). You also have to enable the port in RCC, so if you somehow missed that you would get a fault of some kind, although if you were using the same define to init its pins you would run into a problem there first if the define was wrong.How about telling this thread what you have available for debugging? If you do not have a debugger, at least no one has to repeatedly suggest using the debugger to help with your problem(s). There are ways to do without, but if you are already in an ide and are already using a programmer/debugger then its just a matter of learning how to use it.I have a stm32 nucleo with g031 using command line only (not using gdb either), and have a small chunk of ram set aside in the linker script to store debug data. The startup file has an error function that runs for all unhandled exceptions, in which it stores the 8 words of stack data and any other useful info, then resets. When problems arise, the main function can check for sw reset, and dump out the 'debug' ram to the uart in use. Most problems seem to be beginner mistakes, and once you get familiar with the mcu you start to figure out what makes things break.edit- I forgot to add, other mcu's I have using an ide w/ programmer/debugger are usually simpler/faster when odd problems arise, so although doing without is workable its not ideal.

author: Veketti
author_rank: Regular Contributor
timestamp: January 11, 2024, 02:13:47 pm
content: Definition for the DISP_PW_O is as follows from gpio.c:Code:/*Configure GPIO pin : PtPin */GPIO_InitStruct.Pin = DISP_PW_O_Pin;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(DISP_PW_O_GPIO_Port, &GPIO_InitStruct);I'm starting to think that there is something very badly wrong with this setup. Could it be that the project has corrupted in cubeIDE? One thing fixed another mess up and causes hardfault. Now HAL_Delay causes hardfault and gets stuck in following:Code:__weak uint32_t HAL_GetTick(void){return uwTick; <- Stuck here}Or could the mcu be bad? Maybe I'll start new fresh project and copy the code between /*user code*/ from this and see whether that works. And maybe solder another pcb if the mcu is bad..

author: DavidAlfa
author_rank: Super Contributor
timestamp: January 11, 2024, 02:29:13 pm
content: I don't think so. Those are not the definitions, cubeMX places then in main.h.

author: Veketti
author_rank: Regular Contributor
timestamp: January 11, 2024, 04:23:19 pm
content: Yes, sorry. From main.h#define DISP_PW_O_GPIO_Port GPIOBI've been using that DISP_PW_O in other parts of the code as well. For example just before that pin write I check whether the pin is set or not:Code:if ( (HAL_GPIO_ReadPin(DISP_PW_O_GPIO_Port, DISP_PW_O_Pin)) == 1 )And, sorry I missed to tell that I have the ST Link/V2 as a debugger connected to the board.Does the following picture tell that what went wrong?

author: ataradov
author_rank: Super Contributor
timestamp: January 11, 2024, 05:12:03 pm
content: Your screenshots show LED_GPIO_Port, not DISP_PW_O_GPIO_Port.You need to find out the value of SP at the time of fault and then read the memory contents at that address. No idea how to do that with GDB.Then 7th word from the top of the stack would contain the program counter of the instruction that caused this fault. Then you look at the disassembly and check what is at that address. Then you will know what other things to check.Full stack would contain: r0, r1, r2, r3, r12, lr, pc, psr. Since you are stopped at the beginning of the HF handler, you can do a sanity check and verify that r0-r3 in the CPU registers and on the stack are the same. This will verify that you have the correct stack location.Don't trust any symbolic names IDE tells you. Read the values from the registers and verify independently with the disassembly/map file. IDEs are easily confused when things go wrong.When IDE tells you that you have a hard fault, verify that PC is at the location of the HF handler.

author: Veketti
author_rank: Regular Contributor
timestamp: January 11, 2024, 05:18:33 pm
content: I updated the previous post. I added also led on and breakpoint to NMI_Handler. It seems to go sometimes to the NMI as well. I added also picture of that.When I press the button "View Disassembly...", nothing happens. Any idea why is it so?That LED_GPIO_Port is from the fault handler where I lit up the led if it goes there.

author: ataradov
author_rank: Super Contributor
timestamp: January 11, 2024, 05:21:21 pm
content: Take the ELF file and run "arm-none-eabi-objdump -d file.elf > file.txt" This will give you the disassembly.IDEs suck.

author: newbrain
author_rank: Super Contributor
timestamp: January 11, 2024, 06:30:33 pm
content: Quote from: Veketti on January 11, 2024, 04:23:19 pmThe address 0x40012C00 is the start of TIM1 register: it should not appear in the shown stack trace!Of course, you'll find no code there.The address below could be legit (as 0x00000000 is an alias for the flash at 0x08000000 in normal boot mode).Moreover, the "Signal Handler called at 0xFFFFFFF1" is quite suspect: the value of 0xFFFFFFF1 is an EXCEPTION_RETURN (loaded in LR when entering exceptions) and means that the CPU was already in handler mode when fault hit, i.e., already in an interrupt servicing routineor in a fault handler.In the second case the processor enters lockup (only reset and NMI accepted) and the stack unwinding in gdb gets very confused (at least it used to - not sure this is still the case, but it looks like).You might need to follow ataradov's instructions to unwind the stack manually.

author: nctnico
author_rank: Super Contributor
timestamp: January 11, 2024, 06:44:00 pm
content: Quote from: Siwastaja on January 10, 2024, 04:53:31 pmI second the suggestion to print a stack trace when a hard fault occurs. In my own code I print the last 16 words (32 bit) on the stack from the hardfault handler using a piece of code that takes over a UART and controls it directly to output characters. From there I pick values that point to flash or RAM to pinpoint which function the processor was executing. A map file is required for this. This has helped me to solve pointer corruption problems quite a few times. Using a debuggen has proven to be less helpfull in these cases because the debugger tries to interpret a stack frame that is in an interrupt context.Also, given the erratic behaviour I'm not ruling out the OP has a hardware problem so it would be good if the OP can share the processor part of the schematics and the board layout.

author: DavidAlfa
author_rank: Super Contributor
timestamp: January 11, 2024, 06:53:45 pm
content: View disassembly is to be used only in a live debugging session.Open project properties, select All configurations, go to C build options:- MCU post build options, tick Generate list file.- MCU GCC compiler, debugging, set debug level to max.That's it, after building you'll have a .list file with the asm.I like IDEs

author: Veketti
author_rank: Regular Contributor
timestamp: January 11, 2024, 08:07:03 pm
content: Quote from: newbrain on January 11, 2024, 06:30:33 pmInteresting, I don't use TIM1 at all. Only TIM6 & 7. I've got the list file like DavidAlfa suggested. I looked for the TIM1 register 40012C00 and found three occurences.Code:/* Change the htim state */htim->State = HAL_TIM_STATE_READY;8004968:2301movsr3, #1__HAL_UNLOCK(htim);800496a:2000movsr0, #0htim->State = HAL_TIM_STATE_READY;800496c:702bstrbr3, [r5, #0]__HAL_UNLOCK(htim);800496e:7020strbr0, [r4, #0]return HAL_OK;}8004970:bdf0pop{r4, r5, r6, r7, pc}8004972:46c0nop; (mov r8, r8)8004974:40012c00.word0x40012c008004978:ff0fffff.word0xff0fffff800497c:40000400.word0x400004008004980:40014000.word0x4001400008004984 <HAL_TIMEx_CommutCallback>:8004984:4770bxlr08004986 <HAL_TIMEx_BreakCallback>:8004986:4770bxlrCode:/* Check if the update flag is set after the Update Generation, if so clear the UIF flag */if (HAL_IS_BIT_SET(TIMx->SR, TIM_FLAG_UPDATE))800489a:6903ldrr3, [r0, #16]800489c:4213tstr3, r2800489e:d002beq.n80048a6 <TIM_Base_SetConfig+0x7e>{/* Clear the update flag */CLEAR_BIT(TIMx->SR, TIM_FLAG_UPDATE);80048a0:6903ldrr3, [r0, #16]80048a2:4393bicsr3, r280048a4:6103strr3, [r0, #16]}}80048a6:bd10pop{r4, pc}80048a8:40012c00.word0x40012c0080048ac:40000400.word0x4000040080048b0:40002000.word0x4000200080048b4:40014000.word0x4001400080048b8:40014400.word0x4001440080048bc:40014800.word0x4001480080048c0:fffffcff.word0xfffffcff080048c4 <HAL_TIM_Base_Init>:{80048c4:b570push{r4, r5, r6, lr}80048c6:0004movsr4, r0return HAL_ERROR;80048c8:2001movsr0, #1if (htim == NULL)80048ca:2c00cmpr4, #080048cc:d023beq.n8004916 <HAL_TIM_Base_Init+0x52>if (htim->State == HAL_TIM_STATE_RESET)Code:800466e:4770bxlr__HAL_TIM_ENABLE(htim);8004670:681aldrr2, [r3, #0]8004672:4302orrsr2, r08004674:601astrr2, [r3, #0]return HAL_OK;8004676:2000movsr0, #08004678:e7f9b.n800466e <HAL_TIM_Base_Start_IT+0x46>800467a:46c0nop; (mov r8, r8)800467c:40012c00.word0x40012c008004680:40000400.word0x400004008004684:40014000.word0x400140008004688:00010007.word0x000100070800468c <HAL_TIM_Base_Stop_IT>:{/* Check the parameters */assert_param(IS_TIM_INSTANCE(htim->Instance));/* Disable the TIM Update interrupt */__HAL_TIM_DISABLE_IT(htim, TIM_IT_UPDATE);800468c:2101movsr1, #1800468e:6803ldrr3, [r0, #0]Is there anything suspicious here?

author: ataradov
author_rank: Super Contributor
timestamp: January 11, 2024, 08:51:37 pm
content: If you look at the stack as I described, you will know where it failed and why. Then you can look at the specific piece of code instead of guessing which one may be wrong.There is not likely to be a mistake in the compiler generated code, so looking at those specific fragments is pointless. You may have some out of bounds access and it just happens to fetch a random value from the memory. That memory is not at fault here.

author: DavidAlfa
author_rank: Super Contributor
timestamp: January 12, 2024, 11:53:17 pm
content: I guess DISP_PW pin is controlling the power to the display.Might it be crashing due a VDD trasient? Since the display has its own caps, the initial inrush current might be able to cause a voltage glitch.Put a 10uF electrolytic cap just before the switching device (In the STM32 side) and check if still happening.Also since this is a personal project, consider attaching the schematic and CubeIDE project, will be much easier to find any design/program flaw.

author: Veketti
author_rank: Regular Contributor
timestamp: January 14, 2024, 10:06:49 am
content: This is now solved and it was indeed hardware issue. 1.54" Oled display HS154L03B2C01 took so big current spike that when MCU switched P-Fet on it crashed the MCU. Even afterwards added 10uf cap didn't fix it. Power supply for the display changed from 3.3V to 5V and 10uf cap added to the supply now.Thank you all for being so helpful and special thanks to DavidAlfa for debugging.. Fantastic that there are so many kind people willing to help when someone is banging their head on the wall for weeks not figuring it out by theirselves.

author: Siwastaja
author_rank: Super Contributor
timestamp: January 14, 2024, 11:04:26 am
content: BTW, do you have Brown-Out Detector enabled? It's usually a good idea to enable it and setup it with highest voltage (closest to supply rail) possible, e.g. 3.0V for a 3.3V rail - I don't know what settings are available for STM32G0, though. This way, you (usually) get a clean reset instead of the microcontroller doing some random and hard-to-debug shit.Non-current-limited, hard-on P-channel MOSFETs are quite problematic if the load has almost any capacitance (beyond some trivially small value like 0.1µF). Think about it - even if you add 10 times the capacitance before the switch, the charge divider formed by the two capacitors would still cause a 10% voltage dip. If you have a spare IO pin, you can use it to do a precharge step, using another switch but with series resistance. Best option is a high-side load switch IC with built-in inrush current limitation.

author: SiliconWizard
author_rank: Super Contributor
timestamp: January 14, 2024, 08:53:01 pm
content: OLED displays require a boost converter, so if you use a ready-made module and unless they have implemented some soft-start, the current peak when powering them on can be quite high.

author: DavidAlfa
author_rank: Super Contributor
timestamp: January 14, 2024, 08:53:59 pm
content: Yeah, the oled made a nasty vdd glitch.I suggested making the fet switch slowly with 10-22K Rgate + 100nF, that way it would take 5-10ms to switch.But the display had its own LDO, so in the end the "fix" was to connect it to 5V directly, avoiding disturbing the 3.3v rail.Any small spike won't get through the 3.3V LDO and reset the STM32.Still, I would make the fet switch slower, voltage glitches are never good.

author: Siwastaja
author_rank: Super Contributor
timestamp: January 15, 2024, 08:32:51 am
content: Quote from: DavidAlfa on January 14, 2024, 08:53:59 pmThis is OK, but it's a good idea to do at least a napkin calculation on SOA. For small MOSFETs (those rated to say 1-2A) and large capacitances (maybe 100µF or so), the power dissipated in the MOSFET is too much for the tiny die, and kills the MOSFET. It's pretty simple to approximate switching time from I_gate * t_sw = Qg_tot + Q_external, and then look at the SOA curves if the MOSFET can take this I_gate for t_sw; if not, pick a larger MOSFET.

author: DavidAlfa
author_rank: Super Contributor
timestamp: January 15, 2024, 09:37:31 am
content: That's why I suggested this, 100ma, 5-10ms shouldn't cause any issue.If It was 100amps I wouldn't!

author: Veketti
author_rank: Regular Contributor
timestamp: January 17, 2024, 04:58:39 pm
content: Dear All,So I felt to this same trap twice now.I also had active 5V buzzer on the board, controlled by low side N-Fet AO3400A. Had 620r series resistor between gate and mcu pin and 100k pull down on mcu pin. Odd behavior that debugger disconnected sometimes and second counter got crazy values whenever it didn’t completely crash. Changed from the buzzer control to the onboard led and it worked like it should. Buzzer is rated for <30mA. I’m bit stumbled how even that is causing the MCU to go crazy. I got the manual recommended 4.7u and 0.1u caps right next to VDD/VDDA pin, 0.1u cap shared on VREF+ and VBAT pins and all these connected to 3.3V net. I got the exact same layout and setup (except the vref and vbat as they were missing) on the STM32G050 and it drove that buzzer with no issues. Could it be that this STM32G070CBT6 is somehow more sensitive or something? Should I in the future always include RC delay on every STM32 design which drives FET? Or add more capacitance to the MCP16251 step up converter output? Now 10uf like suggested in datasheet and 4.7uf in battery input side.Actually the pcb is bit different on this new design. It’s six layer pcb, with following layer stack up. But should this basically be even better?signalgnd3.3 VDC5 VDCgndsignalOn older design had four layers.signalgnd5 VDCsignalThank you in advance

author: Siwastaja
author_rank: Super Contributor
timestamp: January 17, 2024, 06:44:10 pm
content: At this point, it would be easier to see if you just post the full schematic (and picture of layout).

author: nctnico
author_rank: Super Contributor
timestamp: January 17, 2024, 06:47:23 pm
content: Agreed. And using 6 layers seems excessive for this design; it is not going to solve any of the problems. I second the suggestion others made to use current limited load switches instead of MOSFETs.

author: DavidAlfa
author_rank: Super Contributor
timestamp: January 17, 2024, 08:03:26 pm
content: Probably lacking capacitance in the 3.3V rail? 10uf + 100nF at the LDO + 100nF on every device.You said there was 300mA at the LDO output, which might be close to the limit for a lot of regulators, so any extra current spike will result I current limitation and voltage drop.Yeah you should post the schematics once for all instead telling "I'm having a strange issue".Also, making a new pcb each time is just wasting money, make any required modifications in the current board, like adding caps, cutting traces, adding wires... It's fine!When you get it working, then order the new pcb!

author: nctnico
author_rank: Super Contributor
timestamp: January 18, 2024, 12:27:13 pm
content: Extra capacitance is not going to help. Charging a 1uf cap from a 10uf cap gives you a 10% voltage drop. But chances are the capacitance is much higher on the device that gets turned on. Like 10uf or tens of uf. You'd need to have 1000uf to 10,000uf on the board to prevent excessive (>1%) drooping of the rails. A load switch with soft-start / current limiting is the way to go.

author: Veketti
author_rank: Regular Contributor
timestamp: January 18, 2024, 06:08:43 pm
content: Ok, sorry. Here's the schematics and picture of the pcb. Display portion is bit changed according to the comments, but I haven't yet received the PCB yet which is according to the new schematic..

author: DavidAlfa
author_rank: Super Contributor
timestamp: January 19, 2024, 01:59:35 am
content: Just make fets switch slowly!

author: Veketti
author_rank: Regular Contributor
timestamp: January 19, 2024, 03:21:45 pm
content: Was just wondering, were the schema and layout otherwise ok? I'd appreciate to hear some feedback to further learn...Did I understood correctly the delayed switching, whether below is correct?

author: DavidAlfa
author_rank: Super Contributor
timestamp: January 19, 2024, 03:44:29 pm
content: 15K or even higher might be required if the loading device has a large capacitance.If the cost of the extra resistor+cap gets close to a current-limited switch, it's no brainer here!But did even a buzzer reset your system?You induced a problem by choosing fets conducting extremely well at low VGS (24 mOhm at 2.5V).Do you need such low RDS to power a oled screen? I don't think so.The problem? It will conduct so fast and so much, the charging current will be huge, causing all the issues you're having.Did you measure the current at VDD rail? Was it 300mA? Well, the STLQ015 LDO is rated for 150mA!Internally limited to 250-350mA, so you might be in the limit, any extra load causes voltage drop and it won't be able to respond properly to any small current surge.As the OLED screens ususally carry their own LDO, just power it from 5V directly (As already talked).Do you have oscilloscope?If so, make a single run triggered by the gpio, second channel connected to VDD.You'll see how VDD reacts to the load, if the voltage drop is still too large, increase the resistor.Was that 10uf cap you used ceramic or electrolytic?Ceramics have extremely low esr, so the current spike can be short and huge, beyond what most electrolytics can filter.Try adding several 1uF ceramics here and there!Also: Learn about filtering chokes / ferrite beads. Adding a 1K+ @ 100MHz choke will help filtering any fast trasients.But can be like opening a can of worms, adding big ceramic caps to them or certain current patterns can make them oscillate!https://www.mouser.com/ProductDetail/Fair-Rite/2508052026Y1?qs=sGAEpiMZZMt1hubY80%2Fs8OaNS%2FJrXGrqqm6ynnsmRzk%3Dhttps://www.mouser.com/ProductDetail/Murata-Electronics/BLM21HE472SN1L?qs=sGAEpiMZZMt1hubY80%2Fs8KH3ycnB7WcGvEtoVdG6EB4g77W1AEfufA%3D%3Dhttps://www.mouser.com/ProductDetail/Murata-Electronics/BLM31KN102SH1L?qs=sGAEpiMZZMt1hubY80%2Fs8DE23zOR%2FvJ90O%2Fye4ApNH4cE%252BJSpGa1AA%3D%3D

author: Veketti
author_rank: Regular Contributor
timestamp: January 19, 2024, 06:52:52 pm
content: Indeed the buzzer does also reset or cause havoc on the system. That’s what I tried to say that this thing got me twice (on post #63) and that’s why I was wondering that is there some other detrimental flaw in my design or is it just cursed? Ruling out any code related issue, changing the output to the led cured the issue with the buzzer.Quote from: DavidAlfa on January 19, 2024, 03:44:29 pmInteresting.. Well, to be true, I've searched the smallest RDSon fet's available and invested on them. Due to my ignorance it seems it bite me. Still it beats me why the buzzer work with the G05 and with G07 it doesn't?Quote from: DavidAlfaNo I haven't measured that. I can only see that the whole system draw bit over 10mA max. seen from the lab power connected to the J4 battery connector. That 300 mA was what I remembered that this STLQ015 had max output, but you're right it's only 150mA. Still it should be plenty when both 5V and 3.3V net combined draw decade less. However, I'm not able to see the sudden current spikes. Lab power is quite slow to react.Quote from: DavidAlfaI do have. On G070 datasheet it says "Voltage range: 2.0V to 3.6V". So voltage drop not exceeding 1.3V on 3.3V rail is acceptable?Quote from: DavidAlfaThe one I added to the OLED output was electrolytic and it didn't cure the problem on display turning on.What comes to the current limiting fet's. I’m not sure have I searched with wrong keywords but current limiting FET’s eg. 8 pin soic MAX890L cost over 3€ so it’s pretty steep compared to any fet+res+cap combination… And that still needs one extra resistor which dictates the current limit. Any suggested parts for current limiting N and P fets?

author: DavidAlfa
author_rank: Super Contributor
timestamp: January 19, 2024, 07:33:28 pm
content: Still, a buzzer shouldn't reset your system so easily.How about 100uF electrolytic after the LDO?

author: Siwastaja
author_rank: Super Contributor
timestamp: January 20, 2024, 03:53:56 pm
content: Buzzer isn't a large capacitive load. Something else must be going on.

author: Veketti
author_rank: Regular Contributor
timestamp: January 21, 2024, 07:29:36 am
content: My mistake, the buzzer didn't crash it, it was consequence of issues with the debugging that I didn't notice the error in the code. Now I'll go to the shame corner... Sorry. Buzzer works fine as is. I scoped the buzzer and there were negligible effect on 3.3V nor the 5V net. However, noticed one funny thing. The buzzer control fet on output side had terrible ringing when fet turned off. I screwed up the screen capture, so no picture of it unfortunately. I googled about it and found information that it cannot be avoided or it is due to bad layout. Should I worry about it?I found some reasonably priced current limited load switches. Would this be ok for the display side:TPS22942DCKR?It limits to 100mA and the 3.3V regulator is up to 150mA so my understanding is that it would be ok.And for the ferrite bead, would below circuit be correct application? My understanding was to have it on output side on series and 100nf cap after. Should it be on the 3.3V net instead? I could always replace it with jumper, if it causes oscillation..

author: DavidAlfa
author_rank: Super Contributor
timestamp: January 21, 2024, 07:44:38 am
content: The converter looks fine to me.Maybe another 10uF electrolytic after the coil to compensate for fast current surges.And another 100nF before the coild to filter HF armonics coming from the output.And couldn't you simply capture a new picture?Was it an ultra-high-energy particle captured once every 30 years like theOMG Particleor theAmaratsu Particle?The buzzers are normally piezolectric or inductive, and can generate a bit of back-EMF when turned off.Add a small 1N4148 diode in parallel with the buzzer:You can skip D1 here:

author: Veketti
author_rank: Regular Contributor
timestamp: January 21, 2024, 08:40:17 am
content: Quote from: DavidAlfa on January 21, 2024, 07:44:38 amHaha.I took zillion screenshots but you know, not doing it everyday and the not so intuitive Rigol interface, they were all .stp (setup files), not the screen captures. Didn't have enough motivation after that to do that all over again. That ringing however was suppressed effectively to 5V by that D1, or at least I think that's what helped. Makes sense if the ringing was the back emf..Quote from: DavidAlfa on January 21, 2024, 07:44:38 amI recall some time ago Siwastaja mentioned inthispost that the suppress diode/tvs should be close to the fet and not on the load so I've been following that and that's why I put that tvs across fet drain and source. Hope I got that right... Maybe in this case it doesn't matter as the wires between load and fet are short so both approaches are ok.

author: DavidAlfa
author_rank: Super Contributor
timestamp: January 21, 2024, 08:48:01 am
content: The backemf would be completely negligible, the inductance of a 3" trace is nH and the current of the buzzer small.The problem here is not the placement, but the diode, a TVS acts similar of a zener, only clamping excessive voltage.But below the clamping threshold, the backemf won't have a current path, so the energy has nowhere to go and cause the oscillation anyways.You might add a small RC snubber to reduce this oscillation.

author: Siwastaja
author_rank: Super Contributor
timestamp: January 21, 2024, 11:29:35 am
content: Quote from: Veketti on January 21, 2024, 08:40:17 amIt's still in the wrong place, in the schematic. It needs to be in parallel with load, not parallel with the MOSFET; the post you refer to talks aboutlayout; it should be close to the MOSFET. Placement and circuit are two different things. Paralleling a freewheeling diode with the MOSFET does not do much because the MOSFET already has built-in parasitic body diode. You want to provide a path for the current which still goes through the load after the MOSFET goes open-circuit, and the only place to offer this path is in parallel with the load.If the load (in this case, piezo) is driven such that off-time is always significant, then any diode type is OK (forward recovery time matters; but it's good enough with nearly any diode type). On the other hand, if you drive the MOSFET back on quickly (e.g., because you do PWM), then you need to use a diode type with fast reverse recovery, or no reverse recovery at all, schottky is the usual choice then. A "normal" slow Si diode would be still conducting due to slow reverse recovery and cause significant short-circuit current through the diode+MOSFET series connection.#1 for even slightly inductive loads is to add the freewheeling diode, and having it physically close to the MOSFET is right because it then also freewheels the parasitic inductance from the wiring going to the load. Always try this first, remove the problem where it's generated. After that, if you still have ringing, which is now caused by the parasitic inductance of your switching loop (loop formed by your closest DC bus capacitor, MOSFET and the freewheeling diode all in series) forming a "tank" circuit with Cds of the MOSFET (or C of the diode), then you can add RC snubber(s), across the MOSFET and across the diode.

author: DavidAlfa
author_rank: Super Contributor
timestamp: January 21, 2024, 11:34:04 am
content: The effect will be similar (Clamping against VDD or to GND) but the oscillation would still happen with the TVS if there's no snubber.The only real difference will be dumping the energy into VDD, making it a bit more efficient?

author: Veketti
author_rank: Regular Contributor
timestamp: January 21, 2024, 12:36:12 pm
content: Now my head is spinning. Bear with me, please. So did I understood correctly that this is what you meant Siwastaja?If so then it is physically close to the load, not the transistor. Let's say there is two meters wires between the load and transistor. For dummies, please. What does this mean:QuoteHow can it at the same time be physically close to transistor and parallel with load? Sketch or someting?

author: DavidAlfa
author_rank: Super Contributor
timestamp: January 21, 2024, 01:46:25 pm
content: Regarding the LDO decoupling, I just rememberedthis threadand updated it.

author: Veketti
author_rank: Regular Contributor
timestamp: January 21, 2024, 02:05:04 pm
content: I soldered the 1n4148 to the buzzer legs and results below. Sorry, not enough hands to get both channels at once, but it shouldn't matter. I still have the D1, should I unsolder it, whether it messes this up?

author: DavidAlfa
author_rank: Super Contributor
timestamp: January 21, 2024, 02:08:51 pm
content: Don't you have probe clips?You can solder small wires to the testing points, sometimes is safer than acrobatic probing, risking the probe slipping and causing all kind of mess, like shorting 12Vin -> 3Vout in a regulator!Why is the buzzer turning off when the gate is high? Your schematic shows a N-fet but this behaviour is for P-fet.Or you just captured the wrong edge of the gate signal?

author: Veketti
author_rank: Regular Contributor
timestamp: January 21, 2024, 02:25:53 pm
content: I got the wrong edge, I forgot to change it. Updated the image on previous post. Those very small glitches which are barely visible on gate seem to be 371us apart and ~470mv high..

author: DavidAlfa
author_rank: Super Contributor
timestamp: January 21, 2024, 02:36:27 pm
content: Are you using the probe in 10X mode? Otherwise it'll add a lot of capacitance to the circuit and cause strange effects/issues.Looks like if nothing was connected at all, show the updated schematic?The PESD5V0 is rated for 5V, not 5.5 or 6V, but exactly 5V, and you're feeding 5V to it, so you're at the very limit.You only want to protect the Fet from excessive voltages, if the fet tolerates 20V, clamping to 6-10V would be ok, but not so extremely close to VDD.That TVS would be ok for example for a MCU input.And yeah try removing D1.

author: Veketti
author_rank: Regular Contributor
timestamp: January 21, 2024, 02:45:52 pm
content: Here's the updated schematic.Update. Added also zoom image of the gate glitches..Update2. Added also picture of the drain, when D1 removed. So only 4148 present. Yes, I'm using 10x mode.Update3. To rule out the 4148 was faulty, I replaced it with über-fast BYV27 diode and still the same ringing...