Reading FICR through SWD on nRF52832

Hello,

I am working on a SWD flasher for nRF52 chips. I try to perform basic commands like flashing a firmware or reading flash content. I wanted to use FICR informations such as "Codepage size" or "Codesize" to calculate the size of the firmware loaded on the chip for the read command. How ever, I struggle to read the content of these registers. I managed to write to the NVMC config register for example but reading the FICR registers always returns me a 0. I also received 0 for the Flash Variant. I checked the implementation made on this Github project (https://github.com/atc1441/ESP32_nRF52_SWD) and I have similar implementation regarding the writing and the reading of these register. Though I do not understand why they are reading twice the RDBUFF Debug Port to get the return value of their AP Read nor why they check RDBUFF after AP write in this example. The ARM Debug Interface v5 Architecture Specification do not mention reading twice RDBUFF in their paragraph regarding " Posted Read Accesses to the AP" (https://developer.arm.com/documentation/ihi0031/a/The-Serial-Wire-Debug-Port--SW-DP-/Protocol-description/The-OK-response?lang=en).

Is there something I need to do to unlock access to this specific register (like halting the chip or writing to some specific register maybe)? If so, how can I perform these steps?

Parents
  • Hi Fabien

    What SDK are you using for development here, the nRF5 SDK or the nRF Connect SDK? What revision of the nRF52832 are you using? there was an issue with revision 1 with reading the FICR, but not that these should return 0: https://infocenter.nordicsemi.com/index.jsp?topic=%2Ferrata_nRF52832_Rev1%2FERR%2FnRF52832%2FRev1%2Flatest%2Fanomaly_832_163.html 

    This could also be readback/access port protection being enabled, and if so, you'd need to recover the device with nrfjprog --recover, but I don't think that's it since you're able to read the NVMC...

    Can you share a code snippet of how you're reading these registers exactly on your end?

    Best regards,

    Simon

  • Hello Simon,

    I am using nRF Connect SDK v2.5.1 to build the firmware I try to flash through SWD but I do not use any SDK for the SWD flasher itself.

    Here is the function I am using to perform the read:

    int read_nrf_register(uint32_t addr, uint32_t* value){
        int err;
    
        err = swd_packet_write_AP(AP_TAR, addr);
        if (err){
            printf("ERROR: Cannot write to AP TAR\n");
            return -1;
        }
    
        err = swd_packet_read_AP(AP_DRW, value);
        if (err){
            printf("ERROR: Cannot read to AP DRW\n");
            return -1;
        }
    
        err = swd_packet_read_DP(DP_RDBUFF, value);
        if (err){
            printf("ERROR: Cannot read/clear DP RDBUFF\n");
            return -1;
        }
    
        err = swd_packet_read_DP(DP_RDBUFF, value);
        if (err){
            printf("ERROR: Cannot read/clear DP RDBUFF\n");
            return -1;
        }
    
        return 0;
    }

    The "swd_packet_*" functions generates the Host command byte, do a turnaround phase, receive the ACK and if he is OK, read data or turnaround and send data, and handle the parity bit. They should be working correctly since I am able to perform an ERASEALL through the custom CTRL-AP register for example.

    When I plug a Jlink probe, I am able to perform a nrfjprog --readcode without having to do a recover.

    Regards,
    Fabien

  • Okay, and what function here is it that returns just 0s? Are you able to see what registers it is that you're reading exactly? 

    Best regards,

    Simon

  • Calls to that function like these :

    read_nrf_register(NRF_REG_FICR_INFOFLASH, &(nrf_info.flash_specs));
    read_nrf_register(NRF_REG_FICR_CODEPAGESIZE, &codepage_size);
    read_nrf_register(NRF_REG_FICR_CODESIZE, &code_size);

    With "NRF_REG_FICR_*" equal to the 0x10000*** addresses. They all end up reading 0 in the last RDBUFF DP read and populates the 2nd argument of the function with it.

    I would at least expect to have the reset value for CODESIZE or CODEPAGESIZE which is 0xFFFFFFFF.

    Regards,
    Fabien

Reply
  • Calls to that function like these :

    read_nrf_register(NRF_REG_FICR_INFOFLASH, &(nrf_info.flash_specs));
    read_nrf_register(NRF_REG_FICR_CODEPAGESIZE, &codepage_size);
    read_nrf_register(NRF_REG_FICR_CODESIZE, &code_size);

    With "NRF_REG_FICR_*" equal to the 0x10000*** addresses. They all end up reading 0 in the last RDBUFF DP read and populates the 2nd argument of the function with it.

    I would at least expect to have the reset value for CODESIZE or CODEPAGESIZE which is 0xFFFFFFFF.

    Regards,
    Fabien

Children
No Data
Related