W tym poście chciałbym opisać uruchomienie oraz sposób działania układu BOR w mikrokontrolerach STM32.
[Źródło: http://www.st.com/en/evaluation-tools/stm32f4discovery.html]
Brownout Reset (BOR):
Układ ten pozwala na utrzymanie mikrokontrolera w stanie resetu, aż nie pojawi się napięcie wyższe od zadanego progu. Dodatkowo pozwala on na programowanie progu zadziałania. Dostępne są trzy granice do ustawienia:
- VBOR3
- VBOR2
- VBOR1
Konfiguracja układu dostępna jest przez modyfikację tzw. Option Bytes.
Tutaj w przypadku modyfikacji wartości umieszczonych w tych bitach należy pamiętać, że modyfikacja bitów RDP a dokładniej ustawienia ich na Level 2. Gdy ten poziom zabezpieczeń zostanie ustawiony nie ma możliwości aby został on zmniejszony ([1] str. 93).
Dane wprowadzane są do rejestru FLASH_OPTCR (Flash option control register):
Dane do modyfikacji rejestrów umieszczone są w strukturze FLASH_OBProgramInitTypeDef (stm32f4xx_hal_flash_ex.h).
- typedef struct
- {
- uint32_t OptionType; /*!< Option byte to be configured.
- This parameter can be a value of @ref FLASHEx_Option_Type */
- uint32_t WRPState; /*!< Write protection activation or deactivation.
- This parameter can be a value of @ref FLASHEx_WRP_State */
- uint32_t WRPSector; /*!< Specifies the sector(s) to be write protected.
- The value of this parameter depend on device used within the same series */
- uint32_t Banks; /*!< Select banks for WRP activation/deactivation of all sectors.
- This parameter must be a value of @ref FLASHEx_Banks */
- uint32_t RDPLevel; /*!< Set the read protection level.
- This parameter can be a value of @ref FLASHEx_Option_Bytes_Read_Protection */
- uint32_t BORLevel; /*!< Set the BOR Level.
- This parameter can be a value of @ref FLASHEx_BOR_Reset_Level */
- uint8_t USERConfig; /*!< Program the FLASH User Option Byte: IWDG_SW / RST_STOP / RST_STDBY. */
- } FLASH_OBProgramInitTypeDef;
Odczytanie ustawionego poziomu BOR można wykonać za pomocą funkcji.
- void HAL_FLASHEx_OBGetConfig(FLASH_OBProgramInitTypeDef *pOBInit)
- {
- pOBInit->OptionType = OPTIONBYTE_WRP | OPTIONBYTE_RDP | OPTIONBYTE_USER | OPTIONBYTE_BOR;
- /*Get WRP*/
- pOBInit->WRPSector = (uint32_t)FLASH_OB_GetWRP();
- /*Get RDP Level*/
- pOBInit->RDPLevel = (uint32_t)FLASH_OB_GetRDP();
- /*Get USER*/
- pOBInit->USERConfig = (uint8_t)FLASH_OB_GetUser();
- /*Get BOR Level*/
- pOBInit->BORLevel = (uint32_t)FLASH_OB_GetBOR();
- }
Funkcja w bibliotece pozwalająca na modyfikacje aktualnego poziomu BOR.
- BOR_Result_t BOR_SetLevel(BOR_Level_t BORNewLevelValue)
- {
- HAL_StatusTypeDef status;
- FLASH_OBProgramInitTypeDef FLASH_OBProgramHandle;
- HAL_FLASHEx_OBGetConfig(&FLASH_OBProgramHandle);
- BOR_Level_t BorSetLevelValue = (BOR_Level_t)FLASH_OBProgramHandle.BORLevel;
- if (BorSetLevelValue != BORNewLevelValue)
- {
- FLASH_OBProgramHandle.BORLevel = (uint32_t)BORNewLevelValue;
- FLASH_OBProgramHandle.OptionType = OPTIONBYTE_BOR;
- HAL_FLASH_OB_Unlock();
- HAL_FLASHEx_OBProgram(&FLASH_OBProgramHandle);
- status = HAL_FLASH_OB_Launch();
- HAL_FLASH_OB_Lock();
- if (status != HAL_OK) {
- return BOR_Result_Error;
- }
- }
- return BOR_Result_Ok;
- }
Na samym początku następuje sprawdzenie aktualnego poziomu BOR. Jeśli jest on inny niż nowa wprowadzana wartość. To następuje wprowadzenie danych do zmiennej w typie struktury FLASH_OBProgramInitTypeDef. Następnie w celu modyfikacji opisanych danych należy odblokować modyfikacje danych w rejestrze. Dalej dane zostają modyfikowane i ustawione. Ostatnim elementem jest ponowne zablokowanie bitów operacji.