Author Topic: STM32G4 + Arduino = BRK interrupt issue  (Read 839 times)

0 Members and 1 Guest are viewing this topic.

Offline Alex-labTopic starter

  • Contributor
  • Posts: 12
  • Country: gb
STM32G4 + Arduino = BRK interrupt issue
« on: April 06, 2024, 07:48:21 pm »
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.
« Last Edit: April 06, 2024, 07:58:48 pm by Alex-lab »
 

Offline pcprogrammer

  • Super Contributor
  • ***
  • Posts: 3718
  • Country: nl
Re: STM32G4 + Arduino = BRK interrupt issue
« Reply #1 on: April 07, 2024, 06:48:19 am »
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 this one.

That kind of information allows us to test things ourselves when we have the same stuff.

Offline Alex-labTopic starter

  • Contributor
  • Posts: 12
  • Country: gb
Re: STM32G4 + Arduino = BRK interrupt issue
« Reply #2 on: April 08, 2024, 05:36:43 pm »
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).
The NVIC_enable function do nothing more than just set corresponding ISER bits.
Thanks.

The sketch:
Code: [Select]
// in file "stm32g4xx_hal_conf_default.h" add #define HSE_VALUE 8000000UL

uint32_t u32_ADCres[3] = {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 LED
  pinMode(PB3, OUTPUT);
     
  RCC->AHB2ENR = 0xFFFFFFFF;  //GPIOs, ADC12EN
  RCC->AHB1ENR = 0xFFFFFFFF;  //DMA1
  RCC->APB2ENR = 0xFFFFFFFF;
  RCC->CCIPR |=  0x10000000;  //ADC12 clock input selector, PLLP 113.33MHz

  ADC12_COMMON->CCR |= 0x00040000;   // ADC divider 1/2 Fadc=56.67MHz
  ADC1->CFGR |= 0x0543;        //DMA request enabled, circular mode, TIM1-TRGO2 - start of conversion
  ADC1->SQR1 = 0xC2042;         //ch1, once.   0x000C2042;  //L=3, (PA0-2 = CH1-3) in a sequence, ADC1.CH0 - is internally connected to Vssa
  ADC1->SMPR1 = 0x0049;     //6.5 cycles sampling time for ch0-2.

  ADC1->CR = 0;               //Clear DEEPPWD
  ADC1->CR = (1 << 28);       //ADVREGEN = 1
  delayMicroseconds(1000);
  ADC1->CR |= (1 << 31);      //ADCCAL = 1
  while (ADC1->CR & (1 << 31));
  ADC1->CR |= 1;              //ADEN = 1
  delayMicroseconds(1000);
  ADC1->CR |= (1 << 2);       //ADSTART = 1, soft start of the conversion
  delayMicroseconds(1000);

  GPIOA->AFR[0]   = 0x00000000;           //Alternative functions: PA0-2 - ADC
  GPIOA->AFR[1]   = 0x00000666;           //Alternative functions: PA8,PA9,PA10 - TIM1
  GPIOA->MODER    = 0x002A0FFF;           //Pa8,PA9, PA10 - TIM1 pushpul, Pa0-Pa5 - anaolog inp (PA4-7 are from ADC2)
  GPIOA->OSPEEDR  = 0xFFFFFFFF;

  GPIOB->AFR[0]   = 0x77088000;               //Alternative functions: PB6, PB7 - USART1, PB3,PB4 - GPIO
  GPIOB->AFR[1]   = 0x46660000;               //Alternative functions: PB12,PB13,PB14,PB15 - TIM1
  GPIOB->MODER    = 0xAA54A544;               //PB3,4,5,9 GPIO out
  GPIOB->OSPEEDR  = 0xFFFFFFFF;


  TIM1->ARR    = 850; //PWMARR;                  //Max value of pWM counter
  TIM1->CR2    = 0x00500000;              //ADC  call on Update event - 2
  TIM1->CCMR1  = 0x3838;                  //CH1 high out on upconting, low out downcounting, preloading
  TIM1->CCMR2  = 0x0038;                  //CH3 high out on upconting, low out downcounting, preloading
  TIM1->CCER   = 0x0555;                  //CH1,3 output, CH2 - no output
  TIM1->PSC    = 0x0;                     //Prescaler = 1
  TIM1->BDTR   = 0x80C30;                 //Dead time 48 tics (667 nS), auto output, uotputs disconnected, BRK filter: 7-444nS, 8-667nS, 9-890nS, A-1112nS
  TIM1->CCR1   = 0x200;                   //VAR. PWM width changeable value
  TIM1->CCR2   = 0x1;                     //Start ADC signal
  TIM1->CCR3   = 0x1;                     //CONST.
  TIM1->DIER   = 0x0080;                  //BRK interrupts enabled
  TIM1->RCR    = 0x1;                     //Only each second (1+1) event causes interruption
  TIM1->BDTR  |= 0x3000;                  //Enable break function, active - high level
  TIM1->EGR   |= TIM_EGR_UG;              //Immediate load of registers
  TIM1->CR1    = 0x0180;                  //autoreload preload, edge aligned, run disabled
  TIM1->SR     = 0;                       //reset TIMER1 interrupt flag
  TIM1->CR1   |= 1;                       //start TIM
  TIM1->BDTR  |= 0xC000;
   
  DMA1_Channel1->CMAR = (uint32_t) & (u32_ADCres); //Starting address of ADC conversion results array
  DMA1_Channel1->CPAR = (uint32_t) & (ADC1->DR);   //Address of ADC data register
  DMA1_Channel1->CNDTR = 0x0003;                   //3 words to be moved
  DMA1_Channel1->CCR = 0b0000101010100010;         //MSIZE, PSIZE 32 bits each, mem inc, TCIE interrupt, no enable DMA
  DMA1->IFCR = 0xFFFFFFFF;
  DMAMUX1_Channel0->CCR |= 0x0005;     //ADC1 as DMA request source
  DMA1_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[0]);
    Serial1.print("  ADC1_PA1: ");
    Serial1.print(u32_ADCres[1]);
    Serial1.print("  ADC1_PA2: ");
    Serial1.println(u32_ADCres[2]);
    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 ADC
  b_senden = true;
  DMA1->IFCR = 0xFFFFFFFF;                      //Clear interrupt status bit
}

extern "C" void TIM1_BRK_TIM15_IRQHandler() {      //
  TIM1->BDTR &= ~0xC000;                  //OFF PWM outputs
  TIM1->CR1 &= ~0x0001;                   //Disable counter
  TIM1->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 parameters
    in 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
}
 

Offline Alex-labTopic starter

  • Contributor
  • Posts: 12
  • Country: gb
Re: STM32G4 + Arduino = BRK interrupt issue
« Reply #3 on: April 08, 2024, 10:04:09 pm »
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...


 

Offline Atlan

  • Frequent Contributor
  • **
  • Posts: 334
  • Country: sk
Re: STM32G4 + Arduino = BRK interrupt issue
« Reply #4 on: April 08, 2024, 10:32:45 pm »
I don't write anything about it in EErdata datasheet?
FNIRSI 1013D Always provide a picture or video with the problem where the parameters of the oscilloscope are visible, and a picture of the diagnostic screen with the values.
 

Offline Alex-labTopic starter

  • Contributor
  • Posts: 12
  • Country: gb
Re: STM32G4 + Arduino = BRK interrupt issue
« Reply #5 on: April 08, 2024, 10:52:29 pm »
Sorry, it was a stupid mistake |O

Manual says:
1. Clear the ADRDY bit in the ADC_ISR register by writing 1.
2.  Set ADEN.
3.  Wait until ADRDY = 1

I just set ADEN and waited for 1 ms, but this was not enough...
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf