This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Flash protection nrf52840 SDK: 14.0.0

I am trying to implement a bootloader with rewrite protection on nrf52840 with SDK: 14.0.0. But it seems that there is no flash write protection registers in nrf52840. So is there a way to implement a flash rewrite protection?

Thanks.

Parents
  • Hi,

    The BPROT peripheral that is found in the nRF52832, has been replaced with the ACL peripheral on the nRF52840. ACL works similar to the BPROT(erase/write protection), but also adds support for protection against reading the flash.

    You can find more information about the ACL here.

  • Are you testing this in an active debug session? I think the current implementation of ACL is that erase/write is allowed while debugging.

    Here is the code I used to test this. LED3 will light if the data is successfully deleted, and re-written. If tested in non-debug mode session, the LED3 and LED4 will not light, indicating that the device hardfaults because there is an attempt to erase/write to protected flash.

    #include <stdbool.h>
    #include <stdint.h>
    
    #include "boards.h"
    #include "nordic_common.h"
    #include "nrf.h"
    #include "nrf_nvmc.h"
    
    #define LED_PIN1 13 // Pin P0.13
    #define LED_PIN2 14 // Pin P0.14
    #define LED_PIN3 15 // Pin P0.15
    #define LED_PIN4 16 // Pin P0.16
    
    #define PAGE_SIZE 4096
    
    #define REGION1_START 0xF0000  //0xF0000 
    #define REGION1_SIZE PAGE_SIZE*10 //PAGE_SIZE*10
    
    
    
    
    
    void led_off(uint8_t led)
    {
        NRF_GPIO->OUTSET = (1UL << led);
    }
    
    void led_on(uint8_t led)
    {
        NRF_GPIO->OUTCLR = (1UL << led);
    }
    
    void configure_leds(void)
    {
        uint8_t led_pins[4] = {LED_PIN1, LED_PIN2, LED_PIN3, LED_PIN4};
        for (int i = 0; i < sizeof(led_pins); i++)
        {
            // setup led gpio in output mode
            led_off(led_pins[i]);
            NRF_GPIO->PIN_CNF[led_pins[i]] = (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos) | (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos) | (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos) | (GPIO_PIN_CNF_INPUT_Disconnect << GPIO_PIN_CNF_INPUT_Pos) | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos);
        }
    }
    
    int test_writeProtect(void)
    {
        uint32_t errcode = 0;
    
        // Start by erasing region 1
        nrf_nvmc_page_erase(REGION1_START);
    
        //Writing to region 1
        nrf_nvmc_write_word(REGION1_START, 0xABBA1234);
    
        // Read before ACL region is configured
        uint32_t orig_data = 0;
        orig_data          = *((uint32_t *)REGION1_START);
    
        // Disable write/erase for region 1 with ACL
        NRF_ACL->ACL[0].ADDR = REGION1_START;
        NRF_ACL->ACL[0].SIZE = REGION1_SIZE;
        NRF_ACL->ACL[0].PERM = ACL_ACL_PERM_WRITE_Disable << ACL_ACL_PERM_WRITE_Pos;
    
        
        //Try to erase region 1
        nrf_nvmc_page_erase(REGION1_START);
    
        // Write to region 1
        nrf_nvmc_write_word(REGION1_START, 0xABBADEAD);
    
        // Try to read from region using CPU
        uint32_t new_data = 0;
        new_data          = *((uint32_t *)REGION1_START);
    
        if (new_data == 0xABBADEAD) // data successfully deleted, and re-written
        { 
            errcode = 1;
            led_on(LED_PIN3);
        }
        return errcode;
    }
    
    int main(void)
    {
        configure_leds();
        led_on(LED_PIN1); // Start
    
        test_writeProtect();
        
        led_on(LED_PIN4);
    
        while (true)
        {
            // Do nothing.
        }
    }
    /** @} */
    
Reply
  • Are you testing this in an active debug session? I think the current implementation of ACL is that erase/write is allowed while debugging.

    Here is the code I used to test this. LED3 will light if the data is successfully deleted, and re-written. If tested in non-debug mode session, the LED3 and LED4 will not light, indicating that the device hardfaults because there is an attempt to erase/write to protected flash.

    #include <stdbool.h>
    #include <stdint.h>
    
    #include "boards.h"
    #include "nordic_common.h"
    #include "nrf.h"
    #include "nrf_nvmc.h"
    
    #define LED_PIN1 13 // Pin P0.13
    #define LED_PIN2 14 // Pin P0.14
    #define LED_PIN3 15 // Pin P0.15
    #define LED_PIN4 16 // Pin P0.16
    
    #define PAGE_SIZE 4096
    
    #define REGION1_START 0xF0000  //0xF0000 
    #define REGION1_SIZE PAGE_SIZE*10 //PAGE_SIZE*10
    
    
    
    
    
    void led_off(uint8_t led)
    {
        NRF_GPIO->OUTSET = (1UL << led);
    }
    
    void led_on(uint8_t led)
    {
        NRF_GPIO->OUTCLR = (1UL << led);
    }
    
    void configure_leds(void)
    {
        uint8_t led_pins[4] = {LED_PIN1, LED_PIN2, LED_PIN3, LED_PIN4};
        for (int i = 0; i < sizeof(led_pins); i++)
        {
            // setup led gpio in output mode
            led_off(led_pins[i]);
            NRF_GPIO->PIN_CNF[led_pins[i]] = (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos) | (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos) | (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos) | (GPIO_PIN_CNF_INPUT_Disconnect << GPIO_PIN_CNF_INPUT_Pos) | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos);
        }
    }
    
    int test_writeProtect(void)
    {
        uint32_t errcode = 0;
    
        // Start by erasing region 1
        nrf_nvmc_page_erase(REGION1_START);
    
        //Writing to region 1
        nrf_nvmc_write_word(REGION1_START, 0xABBA1234);
    
        // Read before ACL region is configured
        uint32_t orig_data = 0;
        orig_data          = *((uint32_t *)REGION1_START);
    
        // Disable write/erase for region 1 with ACL
        NRF_ACL->ACL[0].ADDR = REGION1_START;
        NRF_ACL->ACL[0].SIZE = REGION1_SIZE;
        NRF_ACL->ACL[0].PERM = ACL_ACL_PERM_WRITE_Disable << ACL_ACL_PERM_WRITE_Pos;
    
        
        //Try to erase region 1
        nrf_nvmc_page_erase(REGION1_START);
    
        // Write to region 1
        nrf_nvmc_write_word(REGION1_START, 0xABBADEAD);
    
        // Try to read from region using CPU
        uint32_t new_data = 0;
        new_data          = *((uint32_t *)REGION1_START);
    
        if (new_data == 0xABBADEAD) // data successfully deleted, and re-written
        { 
            errcode = 1;
            led_on(LED_PIN3);
        }
        return errcode;
    }
    
    int main(void)
    {
        configure_leds();
        led_on(LED_PIN1); // Start
    
        test_writeProtect();
        
        led_on(LED_PIN4);
    
        while (true)
        {
            // Do nothing.
        }
    }
    /** @} */
    
Children
No Data
Related