mirror of https://github.com/ARMmbed/mbed-os.git
				
				
				
			Fix bug in MBR for NRF52 series
The MBR VTOR state depends on how the application is booted. This makes it difficult to initialize the MBR correctly since a bug prevents the MBR from being initialized more than once. This commit resets the MBR and SoftDevice to a known state before initializing the MBR and setting the VTOR through the SoftDevice.pull/6798/head
							parent
							
								
									d08c819830
								
							
						
					
					
						commit
						41c1654a49
					
				| 
						 | 
					@ -58,8 +58,8 @@
 | 
				
			||||||
extern uint32_t __Vectors[];
 | 
					extern uint32_t __Vectors[];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define VECTORS_FLASH_START __Vectors
 | 
					#define VECTORS_FLASH_START __Vectors
 | 
				
			||||||
#define UICR_BOOTLOADER_ADDRESS 0x10001014
 | 
					#define MBR_VTOR_ADDRESS 0x20000000
 | 
				
			||||||
#define MBR_ADDRESS 0x0
 | 
					#define SOFTDEVICE_VTOR_ADDRESS 0x20000004
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @brief Function for relocation of the vector to RAM on nRF5x devices.
 | 
					 * @brief Function for relocation of the vector to RAM on nRF5x devices.
 | 
				
			||||||
| 
						 | 
					@ -68,36 +68,42 @@ extern uint32_t __Vectors[];
 | 
				
			||||||
void nrf_reloc_vector_table(void)
 | 
					void nrf_reloc_vector_table(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    // Copy and switch to dynamic vectors
 | 
					    // Copy and switch to dynamic vectors
 | 
				
			||||||
	uint32_t *old_vectors = (uint32_t*)VECTORS_FLASH_START;
 | 
						uint32_t *old_vectors = VECTORS_FLASH_START;
 | 
				
			||||||
	uint32_t i;
 | 
						uint32_t i;
 | 
				
			||||||
	for (i = 0; i< NVIC_NUM_VECTORS; i++) {
 | 
						for (i = 0; i< NVIC_NUM_VECTORS; i++) {
 | 
				
			||||||
		nrf_dispatch_vector[i] = old_vectors[i];
 | 
							nrf_dispatch_vector[i] = old_vectors[i];
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if defined(SOFTDEVICE_PRESENT)
 | 
					#if defined(SOFTDEVICE_PRESENT)
 | 
				
			||||||
    /* Bootloader address is stored in UICR */
 | 
					 | 
				
			||||||
    uint32_t *bootloader = (uint32_t *) UICR_BOOTLOADER_ADDRESS;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Before setting the new vector table address in the SoftDevice the MBR must be initialized.
 | 
					     * Before setting the new vector table address in the SoftDevice the MBR must be initialized.
 | 
				
			||||||
     * If no bootloader is present the MBR will be initialized automatically.
 | 
					     * If no bootloader is present the MBR will be initialized automatically.
 | 
				
			||||||
     * If a bootloader is present nrf_dfu_mbr_init_sd must be called once and only once.
 | 
					     * If a bootloader is present nrf_dfu_mbr_init_sd must be called once and only once.
 | 
				
			||||||
     * 
 | 
					     * 
 | 
				
			||||||
     * This application is a bootloader being booted for the first time if:
 | 
					     * By resetting the MBR and SoftDevice VTOR address first, it becomes safe to initialize
 | 
				
			||||||
     *  1. The application's vector table (VECTORS_FLASH_START) is set in the UICR.
 | 
					     * the MBR again regardless of how the application was started. 
 | 
				
			||||||
     *  2. SCB->VTOR is still pointing to the MBR's vector table (MBR_ADDRESS). 
 | 
					 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    if ((VECTORS_FLASH_START == (uint32_t *) *bootloader) && (SCB->VTOR == MBR_ADDRESS)) {
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* Initialize MBR so SoftDevice service calls are being trapped correctly. */
 | 
					    /* Reset MBR VTOR to original state before calling MBR init. */
 | 
				
			||||||
        nrf_dfu_mbr_init_sd();
 | 
					    uint32_t *mbr_vtor_address = (uint32_t *) MBR_VTOR_ADDRESS;
 | 
				
			||||||
    }
 | 
					    *mbr_vtor_address = (uint32_t) VECTORS_FLASH_START;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Reset SoftDevive VTOR. */
 | 
				
			||||||
 | 
					    uint32_t *softdevice_vtor_address = (uint32_t *) SOFTDEVICE_VTOR_ADDRESS;
 | 
				
			||||||
 | 
					    *softdevice_vtor_address = 0xFFFFFFFF;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Set SCB->VTOR to go through MBR to trap SoftDevice service calls. */
 | 
					    /* Set SCB->VTOR to go through MBR to trap SoftDevice service calls. */
 | 
				
			||||||
    SCB->VTOR = 0x0;
 | 
					    SCB->VTOR = 0x0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Initialize MBR so SoftDevice service calls are being trapped correctly. 
 | 
				
			||||||
 | 
					     * This call sets MBR_VTOR_ADDRESS to point to the SoftDevice's VTOR at address 0x1000.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    nrf_dfu_mbr_init_sd();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Instruct the SoftDevice to forward interrupts to the application's vector table in RAM. */
 | 
					    /* Instruct the SoftDevice to forward interrupts to the application's vector table in RAM. */
 | 
				
			||||||
    sd_softdevice_vector_table_base_set((uint32_t) nrf_dispatch_vector);
 | 
					    sd_softdevice_vector_table_base_set((uint32_t) nrf_dispatch_vector);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* No SoftDevice is present. Set all interrupts to vector table in RAM. */
 | 
					    /* No SoftDevice is present. Set all interrupts to vector table in RAM. */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue