STM32 interrupt source (edit : programmer flakiness) - Page 1
Forum section: electronics / general

author: danmcb
author_rank: Regular Contributor
timestamp: April 19, 2017, 08:42:35 pm
content: so, I have the el-cheapo STM32F334 demo board (amazing value!) and TrueStudio installed, and I am getting myself used to the whole shebang.I have used this Cube business to basically configure the board, and can get a crude blinky up and running, which is a start.What I want to do is implement a simple scheduler, using the SysTick to trigger the scheduler via a flag. So I have added code to the handler for SysTick and the basic code I need in main(). I also tried turning off SysTick until my scheduler is loaded and ready tofly. But then I get an unexpected interrupt - but I don't know from where.How do i check out registers to see where it came from? I am looking at the STM32 programming and hardware manuals, but don't find out how to determine the interrupt source. I guess some generated code somewhere is doing stuff I don't know about - but what?

author: TNorthover
author_rank: Contributor
timestamp: April 19, 2017, 08:58:44 pm
content: I think you should be looking in the ARM Architecture Reference Manual (for v7M). The interrupt controller memory mapping and function is specified there. The NVIC_IABRn registers look particularly interesting (starting at 0xE000E300 accoring to Table B3-35).Edit: link:http://infocenter.arm.com/help/topic/com.arm.doc.ddi0403e.b/index.htmlEdit2: and the value you get looks like it matches up with Table 34 inthe chip manual, which may (or hopefully not) lead you into querying the EXTI configuration if it's an external interrupt.

author: danmcb
author_rank: Regular Contributor
timestamp: April 19, 2017, 09:42:49 pm
content: holy crap. that is a serious reference manual. thank you!

author: danmcb
author_rank: Regular Contributor
timestamp: April 19, 2017, 10:00:01 pm
content: actually I probably asked the wrong question. A better one would be "can I use STMCube to configure the SysTick? if so, how?"

author: andyturk
author_rank: Frequent Contributor
timestamp: April 19, 2017, 10:03:42 pm
content: Somewhere in your build are a bunch of "weak" interrupt handler definitions that map everything you haven't specifically written code for to the same "unhandled" vector. Stick a breakpoint in that unhandled handler so the core stops:Code:void Unhandled_Handler() {asm volatile ("bkpt #1");}... and when you get there, use your debugging environment to examine the IPSR register in the core. In Segger's ozone debugger, it'll look like the attached screen grab.The number in IPSR is the number of the exception that just happened. Since you'll be in an "unhandled" exception, you'll know that's the troublemaker. The first 16 interrupts are standard for all Cortex-M chips. Higher interrupt numbers vary with the chip, so you'll have to look it up.

author: TNorthover
author_rank: Contributor
timestamp: April 19, 2017, 10:39:08 pm
content: Quote from: andyturk on April 19, 2017, 10:03:42 pmNow that's quite a bit simpler than my suggestion! I assume the Table 34 values are the external interrupt numbers so you just add 16 to get the IPSR-reported value?

author: danmcb
author_rank: Regular Contributor
timestamp: April 19, 2017, 11:23:33 pm
content: You guys are great. Thank you. I am really feeling my way with this at the moment.I seem to have some kind of weirdness going on. I am not even convinced that the connection to the debugger is good. It seems flaky.I took out any attempts to disable/enable interrupts, and went into STMCube again and turned off all IOs except the LEDs and switch (all I want now). I also found interrupts were enabled for TIM1, I removed those. now there are only interrupts for things that look important, and SYSTICK.If I load and start and hit main I have this:Code:int main(void){/* USER CODE BEGIN 1 */timer_flag = 0;#define NUM_TASKS 1task tasks;// define taskstasks.elapsedTime = 0;tasks.period = 1000;tasks.TickFct = &T_blink;/* USER CODE END 1 *//* MCU Configuration----------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* Configure the system clock */SystemClock_Config();/* Initialize all configured peripherals */MX_GPIO_Init();/* USER CODE BEGIN 2 *//* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */// Schedulerfor (unsigned char t = 0; t < NUM_TASKS; ++t) {if (tasks.elapsedTime >= tasks.period) { // Readytasks.TickFct(); // Gotasks.elapsedTime = 0;}tasks.elapsedTime++;}timer_flag = 0;while (!timer_flag) {}}/* USER CODE END 3 */}timer_flag is just a global, all the SysTick ISR should do (for now) is set it:Code:/*** @brief This function handles System tick timer.*/void SysTick_Handler(void){/* USER CODE BEGIN SysTick_IRQn 0 *//* USER CODE END SysTick_IRQn 0 */HAL_SYSTICK_IRQHandler();/* USER CODE BEGIN SysTick_IRQn 1 */if (timer_flag){// error! tasks not completed, handle this better later onHAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET); // red light on} else {HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET); // red light off}timer_flag = 1; // must be reset by scheduler/* USER CODE END SysTick_IRQn 1 */}When I step through, my debugger seems to lose it at the end of MX_GPIO_Init()Code:static void MX_GPIO_Init(void){GPIO_InitTypeDef GPIO_InitStruct;/* GPIO Ports Clock Enable */__HAL_RCC_GPIOA_CLK_ENABLE();__HAL_RCC_GPIOB_CLK_ENABLE();/*Configure GPIO pin Output Level */HAL_GPIO_WritePin(GPIOB, LD_U_Pin|LD_D_Pin|LD_L_Pin|LD_R_Pin, GPIO_PIN_RESET);/*Configure GPIO pin : B_USER_Pin */GPIO_InitStruct.Pin = B_USER_Pin;GPIO_InitStruct.Mode = GPIO_MODE_EVT_RISING;GPIO_InitStruct.Pull = GPIO_NOPULL;HAL_GPIO_Init(B_USER_GPIO_Port, &GPIO_InitStruct);/*Configure GPIO pins : LD_U_Pin LD_D_Pin LD_L_Pin LD_R_Pin */GPIO_InitStruct.Pin = LD_U_Pin|LD_D_Pin|LD_L_Pin|LD_R_Pin;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);}When it gets the last instruction, instead of going back to main() it seems to hang. In fact I seem to now end up here:Code:.section.text.Default_Handler,"ax",%progbitsDefault_Handler:Infinite_Loop:bInfinite_Loop.sizeDefault_Handler, .-Default_Handler/******************************************************************************** The minimal vector table for a Cortex-M4. Note that the proper constructs* must be placed on this to ensure that it ends up at physical address* 0x0000.0000.*******************************************************************************/.section.isr_vector,"a",%progbits.typeg_pfnVectors, %object.sizeg_pfnVectors, .-g_pfnVectorswhich I think is the default handler Andy mentioned. but if I break here, and look at registers - no IPSR register ... (see screenshot attached).Meh. this is obviously something silly, but it's late and I am gonna get some sleep. Sorry if this is confused or silly - but if you can give me some pointers, that will be appreciated.cheers!

author: TNorthover
author_rank: Contributor
timestamp: April 20, 2017, 01:06:08 am
content: The xpsr is sensible and seems to contain the IPSR data Andy mentioned. Specifically the low byte is 0x29, which indicates the 0x29 - 16 = 25th external interrupt. Looking at the CPU reference that's a "TIM1" signal, which sounds very plausible given that you've been playing around with that component.So I suspect you may not have quite managed to disable TIM1 everywhere. Unfortunately I'm not familiar enough with the software to tell you how to do it properly. But someone who is might find the "Generate Report" pdf output very useful in telling you where things have gone wrong.

author: danmcb
author_rank: Regular Contributor
timestamp: April 20, 2017, 07:19:45 am
content: OK, that was helpful. Thanks. It turns out that there was in fact a place to set SysTick as the timebase - not TIM1. Once I did that TIM1 ints are gone.But I still have this odd issue that the thing hangs before it gets to my main loop - at the end of the MX_GPIO_Init() call. See screenshot. WHat happens is that it gets to the end of this function, and then loops infinitely on the instruction in the Disassembly pane - ( "b.n ... " etc)What is this and where does it come from?This is the STCube report - I think it is clean now.Code:ConfigurationBlinkySTM32CubeMX4.20.1Date04/20/2017MCUSTM32F334C8TxPERIPHERALSMODESFUNCTIONSPINSSYSSysTickSYS_VS_SystickVP_SYS_VS_SystickPin NbPINsFUNCTIONsLABELs10PA0GPIO_EXTI0B_USER [B1 Blue PushButton]42PB6GPIO_OutputLD_U [LD3 Red Led]43PB7GPIO_OutputLD_D [LD6 Blue Led]45PB8GPIO_OutputLD_L [LD4 Orange Led]46PB9GPIO_OutputLD_R [LD5 Green Led]SOFTWARE PROJECTProject Settings :Project Name : BlinkyProject Folder : C:\STM32\work\blinky\BlinkyToolchain / IDE : TrueSTUDIOFirmware Package Name and Version : STM32Cube FW_F3 V1.7.0Code Generation Settings :STM32Cube Firmware Library Package : Copy only the necessary library filesGenerate peripheral initialization as a pair of '.c/.h' files per peripheral : NoBackup previously generated files when re-generating : NoDelete previously generated files when not re-generated : YesSet all free pins as analog (to optimize the power consumption) : NoToolchains Settings :Compiler Optimizations : Balanced Size/Speed

author: danmcb
author_rank: Regular Contributor
timestamp: April 20, 2017, 07:57:21 am
content: Woah. I fixed it.I went into project settings and TURNED OFF all compiler optimisations (it was set to optimise for size).The thing that made me suspicious was that when I single-stepped - things seemed to be running out of sequence - like jumping three steps ahead, then back two ... then ... and also when I looked at the disassembly, I could see that it seemed to be in-lining things.Turned off the opts altogether, and now the debugger seems to step as I would expect. I though I was losing the plot for a bit there.But -- WTF? what so(u)rcery is this ... ? Is this the fault of attollic or the GNU compiler? this strikes me as very flakey - no? what the hell kind of compiler "optimisation" hangs the chip in an infinite loop at the end of a basic function call?

author: langwadt
author_rank: Super Contributor
timestamp: April 20, 2017, 10:54:35 am
content: Quote from: danmcb on April 20, 2017, 07:57:21 amI'd put GCC or Attollic being at fault very low on the list of probabilities

author: danmcb
author_rank: Regular Contributor
timestamp: April 20, 2017, 11:17:55 am
content: well, it is their code, compiling with their default setup.

author: newbrain
author_rank: Super Contributor
timestamp: April 20, 2017, 11:40:12 am
content: I also estimate the problem to be somewhere else than gcc.Cube MX, possible.User code possible too, especially if it goes away removing optimizations.Can we see the whole thing?To name just one point: there's exchange of information from SysTick ISR and the main loop through flags, have they been declared asvolatile?That's the first thing that bites when switching on optimizations.

author: Jeroen3
author_rank: Super Contributor
timestamp: April 20, 2017, 12:26:01 pm
content: If you lose debug connectivity during initialization of GPIO you're overwriting the default GPIO config of the SWD/JTAG pins in a way that they don't support the debug channel anymore.Also, add this line somewhere early on.Code:CoreDebug->DEMCR |= CoreDebug_DEMCR_VC_HARDERR_Msk;It makes the code throw a breakpoint when entering the hardfault handler. (eg: when you've done something terribly wrong)You can use the following series of if's to know what you did wrong.Code:uint32_t cfsr = SCB->CFSR;if(cfsr & SCB_CFSR_DIVBYZERO )if(cfsr & SCB_CFSR_...)

author: danmcb
author_rank: Regular Contributor
timestamp: April 20, 2017, 12:51:00 pm
content: thank you again, people for the suggestions.Mea culpa - no I didn't declare the flag volatile. I will see if putting the optimisation back in has the same results now, with and without that. But, of course, it should be. Will also post code.I'm a bit sceptical about whether this is it though - the last b jump statement at the end of the GPIO_Init was basically jumping to itself I think (OK, I didn't work out the physical address, but stepping, it was stuck at that location. Never went back to main(). But I will try and see.The debug crash has completely stopped since I took out the optimisation.

author: langwadt
author_rank: Super Contributor
timestamp: April 20, 2017, 01:50:05 pm
content: Quote from: danmcb on April 20, 2017, 12:51:00 pmwith flag not volatile and optimizing the compiler concludes that flag never changes so the codes nothing but init IO and loop foreverseems to be correct and expected

author: danmcb
author_rank: Regular Contributor
timestamp: April 20, 2017, 02:00:29 pm
content: you are absolutely right. With the flag volatile, it works, with optimisation.Mea Culpa, and I hereby apologise to Gnu, Atollic, B. Kernighan and D. Ritchie ;-)Thanks for helping! (It IS good to know the *why* instead of just the *what*.)

author: TNorthover
author_rank: Contributor
timestamp: April 20, 2017, 02:15:04 pm
content: Quote from: danmcb on April 20, 2017, 02:00:29 pmYou might want to consider C11 atomics instead, since this is more of an inter-thread communication issue than what volatile was designed for (memory-mapped IO basically). Volatile is probably safe for what you have so far though.