2024-07-02 07:47 AM - edited 2024-07-02 07:50 AM
I am making this code which, on an interrupt, is supposed to wake the system from STOP mode, put it into low powered run mode, and run LPTIM1 for 1 minute before triggering a flag and going back into STOP mode. I have PSC as 128 and ARR as 60962, so Fout = Fosc / ((PSC + 1) * (ARR + 1)) = 0.1667 Hz, which is 59.99 seconds period. however, in my program, the HAL function HAL_LPTIM_AutoReloadMatchCallback() gets called after exactly 30 seconds. why is that? did i set up something wrong? Relevant code:
LPTIM1 setup and ISR callback:
static void MX_LPTIM1_Init(void)
{
/* USER CODE BEGIN LPTIM1_Init 0 */
/* USER CODE END LPTIM1_Init 0 */
/* USER CODE BEGIN LPTIM1_Init 1 */
/* USER CODE END LPTIM1_Init 1 */
hlptim1.Instance = LPTIM1;
hlptim1.Init.Clock.Source = LPTIM_CLOCKSOURCE_APBCLOCK_LPOSC;
hlptim1.Init.Clock.Prescaler = LPTIM_PRESCALER_DIV128;
hlptim1.Init.Trigger.Source = LPTIM_TRIGSOURCE_SOFTWARE;
hlptim1.Init.OutputPolarity = LPTIM_OUTPUTPOLARITY_HIGH;
hlptim1.Init.UpdateMode = LPTIM_UPDATE_IMMEDIATE;
hlptim1.Init.CounterSource = LPTIM_COUNTERSOURCE_INTERNAL;
if (HAL_LPTIM_Init(&hlptim1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN LPTIM1_Init 2 */
__HAL_LPTIM_AUTORELOAD_SET(&hlptim1, 60962);
//hlptim1.Instance->ARR = 1016;
/* USER CODE END LPTIM1_Init 2 */
}
//this function is called when the LP timer's CNT register = ARR
void HAL_LPTIM_AutoReloadMatchCallback(LPTIM_HandleTypeDef *hlptim)
{
HAL_GPIO_WritePin(GPIO_PULSE_PORT, GPIO_PULSE_PIN, GPIO_PIN_SET); //turn on the blue LED
//HAL_GPIO_TogglePin(GPIO_PULSE_PORT, GPIO_PULSE_PIN); //turn off the LED when the timer is finished
RxTimerDone = 1;
}
//this function is called on every external interrupt. In this case,
//when the user PB is pressed on the dev board.
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == GPIO_PIN_2) //if the input pin matches what it is supposed to be.
{
pulseCount++; //increment the number of pulses to send
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_6);
}
}
Clock config (Fosc = 131.072 kHz)
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
/** Configure the main internal regulator output voltage
*/
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
RCC_OscInitStruct.MSIState = RCC_MSI_ON;
RCC_OscInitStruct.MSICalibrationValue = 0;
RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_1;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** 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_MSI;
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_0) != HAL_OK)
{
Error_Handler();
}
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_LPTIM1;
PeriphClkInit.LptimClockSelection = RCC_LPTIM1CLKSOURCE_PCLK;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
}
and main():
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_SPI1_Init();
MX_LPTIM1_Init();
/* USER CODE BEGIN 2 */
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
//lp timer -> 1 minute period for lora pulses
//TIM2 -> pulse output
//
if((pulseCount > 0) && (processStarted == 0))
{
SystemClock_Config();//STOP mode turns off all system clocks; this command resets them
enter_LPRun(); //enter low power mode
HAL_LPTIM_PWM_Start_IT(&hlptim1, LPTIMER_PERIOD, LPTIMER_PULSE); //begin the timer for the pulse output in interrupt mode
processStarted = 1;
}
if(pulseCount <= 0 && (processStarted == 1) && (RxTimerDone == 1))
{
RxTimerDone = 0;
HAL_LPTIM_PWM_Stop_IT(&hlptim1); //stop the LP timer
processStarted = 0; //clear the flag bit to indicate that process is not ongoing
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU); //this bit has to be cleared before entering stop mode
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI); //enter STOP mode
}
//HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
}
/* USER CODE END 3 */
}
enter_LPRun():
void enter_LPRun(void)
{
/* 1. Each digital IP clock must be enabled or disabled by using the
RCC_APBxENR and RCC_AHBENR registers */
RCC->APB1ENR |= RCC_APB1ENR_PWREN;
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
/* 2. The frequency of the system clock must be decreased to not exceed the
frequency of f_MSI range1. */
// Reinitialize peripherals dependent on clock speed
//no peripherals to initialize
/* 3. The regulator is forced in low-power mode by software
(LPRUN and LPSDSR bits set ) */
PWR->CR &= ~PWR_CR_LPRUN; // Be sure LPRUN is cleared!
PWR->CR |= PWR_CR_LPSDSR; // must be set before LPRUN
PWR->CR |= PWR_CR_LPRUN; // enter low power run mode
}