/*! * \file sysIrqHandlers.c * * \brief Default IRQ handlers * * \copyright Revised BSD License, see section \ref LICENSE. * * \code * ______ _ * / _____) _ | | * ( (____ _____ ____ _| |_ _____ ____| |__ * \____ \| ___ | (_ _) ___ |/ ___) _ \ * _____) ) ____| | | || |_| ____( (___| | | | * (______/|_____)_|_|_| \__)_____)\____)_| |_| * (C)2013-2017 Semtech * * \endcode * * \author Miguel Luis ( Semtech ) * * \author Gregory Cristian ( Semtech ) */ #include #include "stm32l4xx.h" #include "eeprom_emul.h" /*! * \brief This function handles NMI exception. * \param None * \retval None */ void NMI_Handler( void ) { uint32_t corruptedflashaddress; // Check if NMI is due to flash ECCD (error detection) if( __HAL_FLASH_GET_FLAG( FLASH_FLAG_ECCD ) ) { // Compute corrupted flash address corruptedflashaddress = FLASH_BASE + ( FLASH->ECCR & FLASH_ECCR_ADDR_ECC ); #if defined(FLASH_OPTR_BFB2) // Add bank size to corrupteflashaddress if fail bank is bank 2 if( READ_BIT( FLASH->ECCR, FLASH_ECCR_BK_ECC ) == FLASH_ECCR_BK_ECC ) { corruptedflashaddress += FLASH_BANK_SIZE; } #endif // Check if corrupted flash address is in eeprom emulation pages if( ( corruptedflashaddress >= START_PAGE_ADDRESS ) || ( corruptedflashaddress <= END_EEPROM_ADDRESS ) ) { /* Delete the corrupted flash address */ if( EE_DeleteCorruptedFlashAddress( corruptedflashaddress ) == EE_OK ) { // Resume execution if deletion succeeds return; } } } /* Go to infinite loop when NMI occurs in case: - ECCD is raised in eeprom emulation flash pages but corrupted flash address deletion fails - ECCD is raised out of eeprom emulation flash pages - no ECCD is raised */ while( 1 ) { } } /*! * \brief This function handles Hard Fault exception. * \param None * \retval None */ void HardFault_Handler( void ) { //************************************************************************* // When a power down or external reset occurs during a Flash Write operation, // the first line at 0x0 may be corrupted at 0x0 (low occurrence). // In this case the Flash content is restored. // address : flash bank1 base address // data : first flash line (64 bits). This variable must be updated after each build. // sram2address : sram2 start address to copy and restore first flash page //************************************************************************* uint32_t address = FLASH_BASE; uint64_t data = 0x08002df120001bc0; uint32_t sram2address = 0x20030000; uint32_t page = 0; uint32_t banks = FLASH_BANK_1; uint32_t element = 0U; if( ( *( __IO uint32_t* )address == 0x0 ) && ( *( __IO uint32_t* )( address + 4 ) == 0x0 ) ) { // Authorize the FLASH Registers access FLASH->KEYR = FLASH_KEY1; FLASH->KEYR = FLASH_KEY2; // Save first flash page in SRAM2 for( element = 2; element < FLASH_PAGE_SIZE; element++ ) { *( __IO uint32_t* )( sram2address + ( element * 4 ) ) = *( __IO uint32_t* )( address + ( element * 4 ) ); } // Restore the first flash line in SRAM2 to its correct value *( __IO uint32_t* )sram2address = ( uint32_t )data; *( __IO uint32_t* )( sram2address + 4 ) = ( uint32_t )( data >> 32 ); // Clear FLASH all errors __HAL_FLASH_CLEAR_FLAG( FLASH_FLAG_ALL_ERRORS ); // Erase first flash page #if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \ defined (STM32L496xx) || defined (STM32L4A6xx) || \ defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) #if defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx) if( READ_BIT( FLASH->OPTR, FLASH_OPTR_DBANK ) == RESET ) { CLEAR_BIT( FLASH->CR, FLASH_CR_BKER ); } else #endif { if( ( banks & FLASH_BANK_1 ) != RESET ) { CLEAR_BIT( FLASH->CR, FLASH_CR_BKER ); } else { SET_BIT( FLASH->CR, FLASH_CR_BKER ); } } #endif // Proceed to erase the page MODIFY_REG( FLASH->CR, FLASH_CR_PNB, ( page << POSITION_VAL( FLASH_CR_PNB ) ) ); SET_BIT( FLASH->CR, FLASH_CR_PER ); SET_BIT( FLASH->CR, FLASH_CR_STRT ); // Wait for last operation to be completed while( __HAL_FLASH_GET_FLAG( FLASH_FLAG_BSY ) ){ } // If the erase operation is completed, disable the PER Bit CLEAR_BIT( FLASH->CR, ( FLASH_CR_PER | FLASH_CR_PNB ) ); // Restore first flash page in flash from SRAM2 for( element = 0; element < FLASH_PAGE_SIZE; element++ ) { // Wait for last operation to be completed while( __HAL_FLASH_GET_FLAG( FLASH_FLAG_BSY ) ){ } // Set PG bit SET_BIT( FLASH->CR, FLASH_CR_PG ); // Write in flash *( __IO uint32_t* )( address + ( element * 4 ) ) = *( __IO uint32_t* )( sram2address + ( element * 4 ) ); } // System reset NVIC_SystemReset( ); } // Go to infinite loop when Hard Fault exception occurs while( 1 ) { } } /*! * \brief This function handles Memory Manage exception. * \param None * \retval None */ void MemManage_Handler( void ) { /* Go to infinite loop when Memory Manage exception occurs */ while ( 1 ) { } } /*! * \brief This function handles Bus Fault exception. * \param None * \retval None */ void BusFault_Handler( void ) { /* Go to infinite loop when Bus Fault exception occurs */ while ( 1 ) { } } /*! * \brief This function handles Usage Fault exception. * \param None * \retval None */ void UsageFault_Handler( void ) { /* Go to infinite loop when Usage Fault exception occurs */ while ( 1 ) { } } /*! * \brief This function handles Debug Monitor exception. * \param None * \retval None */ void DebugMon_Handler( void ) { } /*! * \brief This function handles Flash interrupt request. * \param None * \retval None */ void FLASH_IRQHandler( void ) { HAL_FLASH_IRQHandler(); } /*! * \brief This function handles PVD interrupt request. * \param None * \retval None */ void PVD_PVM_IRQHandler( void ) { // Loop inside the handler to prevent the Cortex from using the Flash, // allowing the flash interface to finish any ongoing transfer. while( __HAL_PWR_GET_FLAG( PWR_FLAG_PVDO ) != RESET ) { } }