STM32G4 + Arduino = BRK interrupt issue - Page 1
Forum section: electronics / general

author: Alex-lab
author_rank: Contributor
timestamp: April 06, 2024, 07:48:21 pm
content: Hi,I am trying to use stm32G4 Timer1 Break functionality.Previously the same basic code was working fine on F103, F303 and F411, but with G431 I've got some weird behaviour.The main cycle sequentially triggers TIM1->ADC->DMA->DMA interrupt->serial ... etc. Everything works as expected until the NVIC interrupt for BRK is enabled. After that, the cycle operates ok (serial data is coming), but ADC returns zeros for all three channels.I am using Arduino and register defined peripherals.Example is in attachment, the only difference is in un/commenting of two NVIC related lines.Has anybody experienced similar issue? Any guess?Thank you.

author: pcprogrammer
author_rank: Super Contributor
timestamp: April 07, 2024, 06:48:19 am
content: Better attach you full sketch. The only thing that can be concluded from your picture is that, yes, in the one it gets enabled and in the other it is not.Are you sure timer 1 is not used by the Arduino framework? (I don't use the Arduino environment that much)Give us more to work with, because now it is just a guessing game. Like for instance the board you are using. Is it home made or something from WeAct Studio like thisone.That kind of information allows us to test things ourselves when we have the same stuff.

author: Alex-lab
author_rank: Contributor
timestamp: April 08, 2024, 05:36:43 pm
content: Yes TIM1 is not in use by Arduino. The board is a self-made G431C8T6 adaptation for the blue-pill form-factor. Just Pin to pin traces. 8MHz crystal.In the beginning of the code, ADCres array initiated by certain numbers (100,200,300), which are replaced by zeros, but not by a real ADC conversion result. This means that DMA works correctly, but ADC conversion result is 0x00. If ADC clock had been disabled, conversions would have never ended and DMA would not have triggered the interrupt and data would not have been sent by Serial. But everything is working, except the value of ADC...In the figure above you can see that first value in the line is ADC->DR register which is zero as well. So the problem is somewhere there, but I am unable to imaging how this could be.I suspected that it may be affected by GPIO de-initialisation, but, in that case ADC conversion values are not zeros, just oscillating around 0-2 (tested).TheNVIC_enablefunction do nothing more than just set corresponding ISER bits.Thanks.The sketch:Code:// in file "stm32g4xx_hal_conf_default.h" add #define HSE_VALUE 8000000ULuint32_t u32_ADCres = {100, 200, 300};boolean b_senden = false;HardwareSerial Serial1(PB7, PB6);//HardwareSerial Serial1(PA10, PA9);void setup() {NVIC_SetPriority(DMA1_Channel1_IRQn, 14);NVIC_EnableIRQ(DMA1_Channel1_IRQn);// NVIC_SetPriority(TIM1_BRK_TIM15_IRQn, 15);// NVIC_EnableIRQ(TIM1_BRK_TIM15_IRQn);Serial1.begin(115200);pinMode(PC13, OUTPUT); //ON-OFF LEDpinMode(PB3, OUTPUT);RCC->AHB2ENR = 0xFFFFFFFF; //GPIOs, ADC12ENRCC->AHB1ENR = 0xFFFFFFFF; //DMA1RCC->APB2ENR = 0xFFFFFFFF;RCC->CCIPR |= 0x10000000; //ADC12 clock input selector, PLLP 113.33MHzADC12_COMMON->CCR |= 0x00040000; // ADC divider 1/2 Fadc=56.67MHzADC1->CFGR |= 0x0543; //DMA request enabled, circular mode, TIM1-TRGO2 - start of conversionADC1->SQR1 = 0xC2042; //ch1, once. 0x000C2042; //L=3, (PA0-2 = CH1-3) in a sequence, ADC1.CH0 - is internally connected to VssaADC1->SMPR1 = 0x0049; //6.5 cycles sampling time for ch0-2.ADC1->CR = 0; //Clear DEEPPWDADC1->CR = (1 << 28); //ADVREGEN = 1delayMicroseconds(1000);ADC1->CR |= (1 << 31); //ADCCAL = 1while (ADC1->CR & (1 << 31));ADC1->CR |= 1; //ADEN = 1delayMicroseconds(1000);ADC1->CR |= (1 << 2); //ADSTART = 1, soft start of the conversiondelayMicroseconds(1000);GPIOA->AFR = 0x00000000; //Alternative functions: PA0-2 - ADCGPIOA->AFR = 0x00000666; //Alternative functions: PA8,PA9,PA10 - TIM1GPIOA->MODER = 0x002A0FFF; //Pa8,PA9, PA10 - TIM1 pushpul, Pa0-Pa5 - anaolog inp (PA4-7 are from ADC2)GPIOA->OSPEEDR = 0xFFFFFFFF;GPIOB->AFR = 0x77088000; //Alternative functions: PB6, PB7 - USART1, PB3,PB4 - GPIOGPIOB->AFR = 0x46660000; //Alternative functions: PB12,PB13,PB14,PB15 - TIM1GPIOB->MODER = 0xAA54A544; //PB3,4,5,9 GPIO outGPIOB->OSPEEDR = 0xFFFFFFFF;TIM1->ARR = 850; //PWMARR; //Max value of pWM counterTIM1->CR2 = 0x00500000; //ADC call on Update event - 2TIM1->CCMR1 = 0x3838; //CH1 high out on upconting, low out downcounting, preloadingTIM1->CCMR2 = 0x0038; //CH3 high out on upconting, low out downcounting, preloadingTIM1->CCER = 0x0555; //CH1,3 output, CH2 - no outputTIM1->PSC = 0x0; //Prescaler = 1TIM1->BDTR = 0x80C30; //Dead time 48 tics (667 nS), auto output, uotputs disconnected, BRK filter: 7-444nS, 8-667nS, 9-890nS, A-1112nSTIM1->CCR1 = 0x200; //VAR. PWM width changeable valueTIM1->CCR2 = 0x1; //Start ADC signalTIM1->CCR3 = 0x1; //CONST.TIM1->DIER = 0x0080; //BRK interrupts enabledTIM1->RCR = 0x1; //Only each second (1+1) event causes interruptionTIM1->BDTR |= 0x3000; //Enable break function, active - high levelTIM1->EGR |= TIM_EGR_UG; //Immediate load of registersTIM1->CR1 = 0x0180; //autoreload preload, edge aligned, run disabledTIM1->SR = 0; //reset TIMER1 interrupt flagTIM1->CR1 |= 1; //start TIMTIM1->BDTR |= 0xC000;DMA1_Channel1->CMAR = (uint32_t) & (u32_ADCres); //Starting address of ADC conversion results arrayDMA1_Channel1->CPAR = (uint32_t) & (ADC1->DR); //Address of ADC data registerDMA1_Channel1->CNDTR = 0x0003; //3 words to be movedDMA1_Channel1->CCR = 0b0000101010100010; //MSIZE, PSIZE 32 bits each, mem inc, TCIE interrupt, no enable DMADMA1->IFCR = 0xFFFFFFFF;DMAMUX1_Channel0->CCR |= 0x0005; //ADC1 as DMA request sourceDMA1_Channel1->CCR |= 0x1; // enable DMA__enable_irq();}void loop() {if (b_senden) {Serial1.print("ADC1_DR: ");Serial1.print(ADC1->DR);Serial1.print(" ADC1_PA0: ");Serial1.print(u32_ADCres);Serial1.print(" ADC1_PA1: ");Serial1.print(u32_ADCres);Serial1.print(" ADC1_PA2: ");Serial1.println(u32_ADCres);b_senden = false;}delay(100);digitalWrite(PC13, HIGH);digitalWrite(PB3, HIGH);delay(200);digitalWrite(PC13, LOW);delay(200);digitalWrite(PB3, LOW);}extern "C" void DMA1_Channel1_IRQHandler(void) { //happens when DMA obtain data from ADCb_senden = true;DMA1->IFCR = 0xFFFFFFFF; //Clear interrupt status bit}extern "C" void TIM1_BRK_TIM15_IRQHandler() { //TIM1->BDTR &= ~0xC000; //OFF PWM outputsTIM1->CR1 &= ~0x0001; //Disable counterTIM1->SR = 0x0000;}extern "C" void SystemClock_Config(void) //HSE, Fclk = 170MHz, Fadc = 56.67MHz{RCC_OscInitTypeDef RCC_OscInitStruct = {0};RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};/** Configure the main internal regulator output voltage*/HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1_BOOST);/** Initializes the RCC Oscillators according to the specified parametersin the RCC_OscInitTypeDef structure.*/RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; //RCC_OSCILLATORTYPE_HSI48|RCC_OscInitStruct.HSEState = RCC_HSE_ON;// RCC_OscInitStruct.HSI48State = RCC_HSI48_ON;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV2;RCC_OscInitStruct.PLL.PLLN = 85;RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV3;RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){Error_Handler();}RCC->PLLCFGR |= (1 << 16); //PLLP enable/** Initializes the CPU, AHB and APB buses clocks*/RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK| RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK){Error_Handler();}// HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_SYSCLK, RCC_MCODIV_16); //PA8 - 10.625MHz x16 = 170MHz}

author: Alex-lab
author_rank: Contributor
timestamp: April 08, 2024, 10:04:09 pm
content: Further investigation revealed that the issue comes from the ADC clock settings.In order to get maximum performance, SYSCLK was set to 170MHz. ADC clock Fadc was supplied from PLL P-out (113.33MHz) divided by ADC divider (1/2) yielding ~56MHz (<60 fadc_max).However, this configuration fails when TIM1_BRK IRQ enabled. But, when I switched ADC input to SYSCLK (instead of PLLP) the ADC conversion occurred, even though the Fadc was 170/2 = 85MHz, more than specified maximum of 60MHz!May be I misunderstand the maximum ratings?I have checked MCO frequency of SYSCLK - it's ok, 170M...

author: Atlan
author_rank: Frequent Contributor
timestamp: April 08, 2024, 10:32:45 pm
content: I don't write anything about it in EErdata datasheet?

author: Alex-lab
author_rank: Contributor
timestamp: April 08, 2024, 10:52:29 pm
content: Sorry, it was a stupid mistakeManual says:1. Clear the ADRDY bit in the ADC_ISR register by writing 1.2. Set ADEN.3. Wait until ADRDY = 1I just set ADEN and waited for 1 ms, but this was not enough...