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

sd_flash_write implementation without Softdevice

Hello,

I am starting to create a bootloader and I want it to be independant of the SoftDevice. Is there any open source implementation of a flash_write function that I could use? I've noticed that the official bootloader is using sd_mbr_command to initiate the copy process with the help of the softdevice. How is this copy process implemented?

  • Does it begin from the lowest page of the source and does it copy pagewise? E.g. what happens when the image starts at page 100, is 50 pages long and should be moved to page 80.

Thanks, Marius

Parents
  • Here's my code that I wrote based on @Vidar's Response:

    void eraseFlashPage(u32 pageNumber, u32 numPages){
    
    	// Turn on flash erase enable and wait until the NVMC is ready:
    	NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Een << NVMC_CONFIG_WEN_Pos);
    
    	//Wait until the Non volatile memory controller is ready for erasing
    	while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
    
    	while(numPages > 0){
    
    		NRF_NVMC->ERASEPAGE = (uint32_t)((pageNumber+numPages-1) * NRF_FICR->CODEPAGESIZE);
    
    		//Wait until ready
    		while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
    
    		numPages--;
    	}
    
    	//Turn of flash erase
    	NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos);
    
    	//Wait until ready
    	while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
    }
    
    void copyFlashData(u32* destinationAddress, u32* sourceAddress, u32 size)
    {
        static u32 buffer  __attribute__((aligned (4)));
        uint8_t cnt = 0;
    
        // Turn on flash write enable and wait until the NVMC is ready:
        NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos);
    
        while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
    
        //Copy all data
        for(u32 i=0; i < size/4; i++){
        	buffer = *(sourceAddress + i);
    
        	*(destinationAddress + i) = buffer;
    
        	while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
    
        }
    
        // Turn off flash write enable and wait until the NVMC is ready:
        NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos);
    
    	while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
    }
    
Reply
  • Here's my code that I wrote based on @Vidar's Response:

    void eraseFlashPage(u32 pageNumber, u32 numPages){
    
    	// Turn on flash erase enable and wait until the NVMC is ready:
    	NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Een << NVMC_CONFIG_WEN_Pos);
    
    	//Wait until the Non volatile memory controller is ready for erasing
    	while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
    
    	while(numPages > 0){
    
    		NRF_NVMC->ERASEPAGE = (uint32_t)((pageNumber+numPages-1) * NRF_FICR->CODEPAGESIZE);
    
    		//Wait until ready
    		while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
    
    		numPages--;
    	}
    
    	//Turn of flash erase
    	NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos);
    
    	//Wait until ready
    	while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
    }
    
    void copyFlashData(u32* destinationAddress, u32* sourceAddress, u32 size)
    {
        static u32 buffer  __attribute__((aligned (4)));
        uint8_t cnt = 0;
    
        // Turn on flash write enable and wait until the NVMC is ready:
        NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos);
    
        while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
    
        //Copy all data
        for(u32 i=0; i < size/4; i++){
        	buffer = *(sourceAddress + i);
    
        	*(destinationAddress + i) = buffer;
    
        	while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
    
        }
    
        // Turn off flash write enable and wait until the NVMC is ready:
        NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos);
    
    	while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
    }
    
Children
  • Hi Marius, Hi Vidar, I've just read reference manual and now I wonder, if / how the CPU could see the READY register in an other state than ready, if the CPU is halted during the write of the NVM?

  • Hello Marius. This post suits perfectly my new bootloader. However I am having difficulties in understanding the parameters of your functions. Which value is for pagenumber? is this the page address of MBR + SD Size? Number of pages is the size of new firmware divided by the CODE_PAGE_SIZE? Destination address is MBR + SD Size? sourceAddress is the SPI flash address? I would appreciate very much your help. Best regards

  • Hi, page number for the nRF51 is simply from 0 to 256. Each oage has 1024 bytes (this value is saved in NRF_FICR->CODEPAGESIZE). If you want to get the address of your application, you have to find out the starting address of your application first which is done via the MBR command:

    softdeviceAddress = MBR_SIZE;
    appAddress = SD_SIZE_GET(MBR_SIZE);
    

    Then you have to calculate the page where wour app starts.

    source and destination address are simply the addresses in your flash memory that you want to copy. These have to be a multiple of 4 bytes, the size also has to be a multiple of 4.

Related