2017-04-04 3 views
3

J'essaye d'initialiser le RTC sur une carte STM32F469I-DISCO. Depuis que j'apprends encore, j'ai essayé de jouer avec l'API HAL qui me permet de réaliser quelques projets jusqu'au jour où j'aurai assez de compréhension de ce microcontrôleur pour jouer directement avec les registres. Quoi qu'il en soit, mon code utilise le template STM32F469I-DISCO de CubeF4 qui permet de charger directement la couche HAL et l'horloge système (180 MHz via l'oscillateur HSE 8 MHz).Timeout STM32 RTC pendant l'initialisation

Afin d'initialiser le RTC, j'ai suivi les instructions données dans le UM1725 : Description of STM32F4 HAL and LL drivers. Page 715, Section 55.2.4 vous avez des instructions pour utiliser l'API HAL_RTC.

Et le premier point dit qu'il est nécessaire d'activer "l'accès au domaine RTC". Ce point est expliqué dans la section ci-dessus (55.2.3, même page).

Et j'ai fait ce qu'on m'a demandé de faire. Voici mon code (simplifié, je ne laisse la partie RTC Init et configuration horloge système):

#include "main.h" 

RTC_HandleTypeDef rtcHandle; 
RTC_InitTypeDef rtcInit; 
RTC_TimeTypeDef rtcTime; 
RTC_DateTypeDef rtcDate; 

static void SystemClock_Config(void); 
static void Error_Handler(void); 


int main(void) 
{ 
    HAL_Init(); 
    SystemClock_Config(); 

    ////////////////// RTC 

    HAL_PWR_EnableBkUpAccess(); 
    __HAL_RCC_RTC_CONFIG(RCC_RTCCLKSOURCE_LSE); 
    __HAL_RCC_RTC_ENABLE(); 

    rtcInit.HourFormat = RTC_HOURFORMAT_24; 
    rtcInit.AsynchPrediv = 0x7F; 
    rtcInit.SynchPrediv = 0xFF; 
    rtcInit.OutPut = RTC_OUTPUT_DISABLE; 
    rtcInit.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH; 
    rtcInit.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN; 

    rtcHandle.Instance = RTC; 
    rtcHandle.Init = rtcInit; 

    HAL_RTC_Init(&rtcHandle); 

    rtcTime.Hours = 12; 
    rtcTime.Minutes = 30; 
    rtcTime.Seconds = 40; 

    rtcDate.WeekDay = RTC_WEEKDAY_WEDNESDAY; 
    rtcDate.Month = RTC_MONTH_APRIL; 
    rtcDate.Date = 4; 
    rtcDate.Year= 17; 


    HAL_RTC_SetTime(&rtcHandle, &rtcTime, RTC_FORMAT_BCD); 

    while (1) 
    { 

    } 
} 

static void SystemClock_Config(void) 
{ 
    RCC_ClkInitTypeDef RCC_ClkInitStruct; 
    RCC_OscInitTypeDef RCC_OscInitStruct; 

    /* Enable Power Control clock */ 
    __HAL_RCC_PWR_CLK_ENABLE(); 

    __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); 

    /* Enable HSE Oscillator and activate PLL with HSE as source */ 
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; 
    RCC_OscInitStruct.HSEState = RCC_HSE_ON; 
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; 
    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; 
#if defined(USE_STM32469I_DISCO_REVA) 
    RCC_OscInitStruct.PLL.PLLM = 25; 
#else 
    RCC_OscInitStruct.PLL.PLLM = 8; 
#endif /* USE_STM32469I_DISCO_REVA */ 
    RCC_OscInitStruct.PLL.PLLN = 360; 
    RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; 
    RCC_OscInitStruct.PLL.PLLQ = 7; 
    RCC_OscInitStruct.PLL.PLLR = 6; 

    if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) 
    { 
    Error_Handler(); 
    } 
    /* Enable the OverDrive to reach the 180 Mhz Frequency */ 
    if(HAL_PWREx_EnableOverDrive() != HAL_OK) 
    { 
    Error_Handler(); 
    } 

    RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2); 
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; 
    RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; 
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; 
    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; 
    if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) 
    { 
    Error_Handler(); 
    } 
} 

/** 
    * @brief This function is executed in case of error occurrence. 
    * @param None 
    * @retval None 
    */ 
static void Error_Handler(void) 
{ 
    /* User may add here some code to deal with this error */ 
    while(1) 
    { 
    } 
} 

#ifdef USE_FULL_ASSERT 

/** 
    * @brief Reports the name of the source file and the source line number 
    *   where the assert_param error has occurred. 
    * @param file: pointer to the source file name 
    * @param line: assert_param error line source number 
    * @retval None 
    */ 
void assert_failed(uint8_t* file, uint32_t line) 
{ 
    /* User can add his own implementation to report the file name and line number, 
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ 

    /* Infinite loop */ 
    while (1) 
    { 
    } 
} 
#endif 

Et il ne fonctionne pas. Après avoir creusé dans la couche inférieure, j'ai réussi à trouver où cela ne fonctionne pas. Je ne sais pas pourquoi.

L'appel HAL_RTC_Init() renvoie un état HAL_ERROR. Cette HAL_ERROR apparaît parce que HAL_RTC_Init() appelle RTC_EnterInitMode() et renvoie un état HAL_TIMEOUT car une condition n'est pas atteinte pendant le temps prévu. Voici les fonctions:

HAL_StatusTypeDef HAL_RTC_Init(RTC_HandleTypeDef *hrtc) 
{ 
    /* Check the RTC peripheral state */ 
    if(hrtc == NULL) 
    { 
    return HAL_ERROR; 
    } 

    /* Check the parameters */ 
    assert_param(IS_RTC_HOUR_FORMAT(hrtc->Init.HourFormat)); 
    assert_param(IS_RTC_ASYNCH_PREDIV(hrtc->Init.AsynchPrediv)); 
    assert_param(IS_RTC_SYNCH_PREDIV(hrtc->Init.SynchPrediv)); 
    assert_param (IS_RTC_OUTPUT(hrtc->Init.OutPut)); 
    assert_param (IS_RTC_OUTPUT_POL(hrtc->Init.OutPutPolarity)); 
    assert_param(IS_RTC_OUTPUT_TYPE(hrtc->Init.OutPutType)); 

    if(hrtc->State == HAL_RTC_STATE_RESET) 
    { 
    /* Allocate lock resource and initialize it */ 
    hrtc->Lock = HAL_UNLOCKED; 
    /* Initialize RTC MSP */ 
    HAL_RTC_MspInit(hrtc); 
    } 

    /* Set RTC state */ 
    hrtc->State = HAL_RTC_STATE_BUSY; 

    /* Disable the write protection for RTC registers */ 
    __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); 

    /* Set Initialization mode */ 
    if(RTC_EnterInitMode(hrtc) != HAL_OK) 
    { 
    /* Enable the write protection for RTC registers */ 
    __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); 
    /* Set RTC state */ 
    hrtc->State = HAL_RTC_STATE_ERROR; 

    return HAL_ERROR; 
    } 
    else 
    { 
    /* Clear RTC_CR FMT, OSEL and POL Bits */ 
    hrtc->Instance->CR &= ((uint32_t)~(RTC_CR_FMT | RTC_CR_OSEL | RTC_CR_POL)); 
    /* Set RTC_CR register */ 
    hrtc->Instance->CR |= (uint32_t)(hrtc->Init.HourFormat | hrtc->Init.OutPut | hrtc->Init.OutPutPolarity); 

    /* Configure the RTC PRER */ 
    hrtc->Instance->PRER = (uint32_t)(hrtc->Init.SynchPrediv); 
    hrtc->Instance->PRER |= (uint32_t)(hrtc->Init.AsynchPrediv << 16U); 

    /* Exit Initialization mode */ 
    hrtc->Instance->ISR &= (uint32_t)~RTC_ISR_INIT; 

    hrtc->Instance->TAFCR &= (uint32_t)~RTC_TAFCR_ALARMOUTTYPE; 
    hrtc->Instance->TAFCR |= (uint32_t)(hrtc->Init.OutPutType); 

    /* Enable the write protection for RTC registers */ 
    __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); 

    /* Set RTC state */ 
    hrtc->State = HAL_RTC_STATE_READY; 

    return HAL_OK; 
    } 
} 

et:

HAL_StatusTypeDef RTC_EnterInitMode(RTC_HandleTypeDef* hrtc) 
{ 
    uint32_t tickstart = 0U; 

    /* Check if the Initialization mode is set */ 
    if((hrtc->Instance->ISR & RTC_ISR_INITF) == (uint32_t)RESET) 
    { 
    /* Set the Initialization mode */ 
    hrtc->Instance->ISR = (uint32_t)RTC_INIT_MASK; 

    /* Get tick */ 
    tickstart = HAL_GetTick(); 

    /* Wait till RTC is in INIT state and if Time out is reached exit */ 
    while((hrtc->Instance->ISR & RTC_ISR_INITF) == (uint32_t)RESET) 
    { 
     if((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE) 
     { 
     return HAL_TIMEOUT; 
     } 
    } 
    } 

    return HAL_OK; 
} 

Donc, si je bien étudié, la question est que la condition: hrtc-> instance-> ISR & RTC_ISR_INITF == (uint32_t) RESET est vrai tout le temps (puisque la condition TIMEOUT est augmentée). Le ting que je ne comprends pas est selon la fonction ci-dessus (EnterInitMode), les variables RTC_ISR_INITF et ISR semblent être clairement définies et ainsi, la valeur de l'opération au niveau du bit n'est pas 0 (RESET).

Le "ISR" est définie dans la fonction directement et est RTC_INIT_MASK (#define avec la valeur 0xFFFFFFFF dans stm32f4xx_hal_rtc.h)

Le "RTC_ISR_INITF" est une macro: (0x1U < < RTC_ISR_INITF_Pos) où RTC_ISR_INITF_Pos est 6U (#define) défini dans stm32f469xx.h

Ai-je tort si je dis que l'opération "&" n'est pas 0?

Avez-vous une idée de la raison pour laquelle cette condition TIMEOUT a été déclenchée?

Merci d'avance!

Répondre

3

J'ai résolu mon problème après une bonne nuit. J'ai oublié d'initialiser l'horloge LSE dans ma routine SystemClock_Config() ... J'ai simplement ajouté le code suivant dans SystemClock_Config(). J'ai ensuite testé avec STM Studio pour visualiser l'évolution de mes variables. Et cela a bien fonctionné (ce n'était pas le cas auparavant).

Désolé pour le dérangement.