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

nRF52840 does not enumerate as USB CDC unless power cycled after download and run from IAR Workbench but works correctly when using Ozone

Hi,

We have a custom board that uses an nRF52840.  All our development is done on Win 10 based PCs.  Our custom board is connected to our Win 10 based PC via USB and when everything is working then we get a virtual COM port connection to our board. Our normal build and debug environment is the IAR Workbench.  We use both the latest 8.42.2 version and older versions and we have the same problem.  We use J-Link SWD adapters to attach to our board. The J-Link FW is updated to the latest version that was released on 2020Jan07. The reset line from the J-Link is connected to the nRF but it makes no difference for the problem described below if the rest line is or is not connected.  We do not provide power to our board from the J-Link.  The J-Link is connected to VTREF and the J-Link is always able to see the correct voltage on VTREF.

Our normal workflow is to compile, download and debug, then run (i.e. press F5) from within the IAR Workbench.  However when we do this the nRF is not enumerated on the USB bus.  The nRF starts running and the code is executed but the USB driver from the SDK is stuck in an error loop showing a USB Event is not ready error. (Note: I will try to get the exact error and add it to this posting later.)   We have to power cycle our board in order for it to be enumerated and detected by the PC.  Power cycling is done with the J-Link connected.  After we power cycle then we attach the IAR debugger to a running application and we can debug without any issues.

When we use the Segger Ozone debugger (V3.10d and also an older version) then we can take the same exact .hex or .out files and select "Download & Reset".  Then when we select run from the debugger our device is enumerated on the USB bus without any problem.  We do not have to add the additional step of power cycling our board.

This leads me to believe that the problem is due to the way that IAR is resetting or more correctly not resetting the nRF after it downloads and programs the binary into flash.

In the IAR Debugger "Setup" tab we have "Run to main" selected. We tried disabling this option and we still have the same problem.  The "Download" tab has "Use flash loader(s)" selected. 

Looking for some help to resolve this IAR configuration problem because it is impacting our workflow and causing extra delays every time we download new code to the nRF.

Thanks,

Raz

Parents
  • Hi Hakon,

    Yes, we route the nRESET pin to the SWD connector.  Yesterday our oscilloscope was busy but today I'm going to check if the nRESET pin is toggled or not toggled by the two different debuggers.  Yesterday I already tried different Reset options in the J-Link Setup tab but today I will do a more thorough test with the oscilloscope on the nRESET line.

    We are not loading Softdevice but we still have the extra option you show below.  Should we remove this option when Softdevice is not loaded?

    Raz

  • Hi Hakon,

    Some additional information.  I checked the nRESET line behavior with an oscilloscope.  Both Segger Ozone and IAR do not toggle the nRESET and yet when using Ozone everything works just fine.  I configured IAR to toggle the nRESET line and it still did not solve the problem. I tried disabling the "Extra Option" in IAR and it did not make any difference.

    This screen shot shows the location where the error occurs:

    I don't know if you can see the above so hopefully this one is more clear:

    Below are screen captures of the nRF52840 registers as they are initialized by Ozone and below that by IAR immediately after downloading the binary into the nRF.  The big difference is in the cycle count.  I don't know what Ozone is doing differently than IAR on startup but it is executing a lot more code.  And again, just to be clear I use the exact same .out file with Ozone and with IAR.  I build the code only in IAR Workbench.

    From Ozone

    From IAR

    Based on some comments that I saw on the IAR website I also tried to disable the "Use flash loader(s)" option but that did not help.

    Any recommendations how I should attempt to debug this?  Do you have an IAR project with USB that I can try to run on my board?  I would need the project file which I think includes all the settings for Workbench.

    BTW, I also tried to use an IAR I-jet adapter instead of a J-Link and I get the exact same problem with the IAR Workbench.  I cannot run Segger Ozone on the I-jet to compare but I think it is quite clear now that the problem is due to something in the IAR configuration.

    Thanks,

    Raz

Reply
  • Hi Hakon,

    Some additional information.  I checked the nRESET line behavior with an oscilloscope.  Both Segger Ozone and IAR do not toggle the nRESET and yet when using Ozone everything works just fine.  I configured IAR to toggle the nRESET line and it still did not solve the problem. I tried disabling the "Extra Option" in IAR and it did not make any difference.

    This screen shot shows the location where the error occurs:

    I don't know if you can see the above so hopefully this one is more clear:

    Below are screen captures of the nRF52840 registers as they are initialized by Ozone and below that by IAR immediately after downloading the binary into the nRF.  The big difference is in the cycle count.  I don't know what Ozone is doing differently than IAR on startup but it is executing a lot more code.  And again, just to be clear I use the exact same .out file with Ozone and with IAR.  I build the code only in IAR Workbench.

    From Ozone

    From IAR

    Based on some comments that I saw on the IAR website I also tried to disable the "Use flash loader(s)" option but that did not help.

    Any recommendations how I should attempt to debug this?  Do you have an IAR project with USB that I can try to run on my board?  I would need the project file which I think includes all the settings for Workbench.

    BTW, I also tried to use an IAR I-jet adapter instead of a J-Link and I get the exact same problem with the IAR Workbench.  I cannot run Segger Ozone on the I-jet to compare but I think it is quite clear now that the problem is due to something in the IAR configuration.

    Thanks,

    Raz

Children
  • Hi Raz,

     

    It looks like you are using an older version of the SDK, and running into this errata:

    https://infocenter.nordicsemi.com/topic/errata_nRF52840_Rev2/ERR/nRF52840/Rev2/latest/anomaly_840_187.html?cp=4_0_1_0_1_21

    This errata workaround has been implemented in SDK v15 and newer.

    Could you try manually implementing this workaround and see if the issue disappears?

     

    Kind regards,

    Håkon

  • Hi Hakon,

    This solved the problem.  We use SDK 15 which has the 187 errata code in there:


    void nrf_drv_usbd_enable(void)
    {
    ASSERT(m_drv_state == NRFX_DRV_STATE_INITIALIZED);

    /* Prepare for READY event receiving */
    nrf_usbd_eventcause_clear(NRF_USBD_EVENTCAUSE_READY_MASK);

    // if (nrf_drv_usbd_errata_187()) // RZD force execution of 187 based on the recommendation from Nordic even though this function indicates that 187 is not needed when running with IAR
    if (1)
    {
    CRITICAL_REGION_ENTER();
    if (*((volatile uint32_t *)(0x4006EC00)) == 0x00000000)
    {
    *((volatile uint32_t *)(0x4006EC00)) = 0x00009375;
    *((volatile uint32_t *)(0x4006ED14)) = 0x00000003;
    *((volatile uint32_t *)(0x4006EC00)) = 0x00009375;
    }
    else
    {
    *((volatile uint32_t *)(0x4006ED14)) = 0x00000003;
    }
    CRITICAL_REGION_EXIT();
    }

    . . . . . .

    When I trace through the code I see the following:

    static inline bool nrf_drv_usbd_errata_type_52840_proto1(void)       <------- this function returns (1)
    {
    return ( nrf_drv_usbd_errata_type_52840() &&
    ( ((*(uint32_t *)0xF0000FE8) & 0xF0) == 0x00 ) &&
    ( ((*(uint32_t *)0xF0000FEC) & 0xF0) == 0x00 ) );
    }

    /**
    * @brief Internal auxiliary function to check if the program is running on first final product of
    * NRF52840 chip
    * @retval true It is NRF52480 chip and it is first final product
    * @retval false It is other chip
    */
    static inline bool nrf_drv_usbd_errata_type_52840_fp1(void) <--- this function fails
    {
    return ( nrf_drv_usbd_errata_type_52840() &&
    ( ((*(uint32_t *)0xF0000FE8) & 0xF0) == 0x10 ) &&  <---- fails, 0xF0000FE8 has a value of 0x2C
    ( ((*(uint32_t *)0xF0000FEC) & 0xF0) == 0x00 ) );
    }

    Memory dump:

    Any ideas what could be going on?

    Thanks,

    Raz

  • Hi Raz,

     

    rzd said:
    Any ideas what could be going on?

    My apologies. The older SDK checked for a specific revision (rev 1) and didn't account for a future revision, which the newer SDKs have in place.

    Here's the implementation in SDK v16, \modules\nrfx\drivers\src\nrfx_usbd_erratas.h, as an example:

    static inline bool nrfx_usbd_errata_type_52840_eng_b_or_later(void)
    {
        return (nrfx_usbd_errata_type_52840() && (*(uint32_t const *)0x10000134UL >= 0x1UL));
    }
    
    static inline bool nrfx_usbd_errata_187(void)
    {
        return (NRFX_USBD_ERRATA_ENABLE && (nrfx_usbd_errata_type_52840_eng_b_or_later()
                                            || nrfx_usbd_errata_type_52833()));
    }
     

     

    Kind regards,

    Håkon

  • Hi Hakon,

    I downloaded the SDK 16 code after I sent my comments above and I saw the new code.  I was wondering about the reason for the big difference so thank you for clearing this up.  It seems like there were a lot of changes made when going from version 15 to 16 so we will need to carefully evaluate how we migrate to version 16.

    BTW, one thing that is strange is the fact that the old code ran correctly when I used the Segger Ozone.  I wonder what Segger do in their init code that made the SDK 15 code work.  In any case we already modified the code and now everything is stable.

    Thanks again for the great support.

    Raz

  • Hi Hakon,

    How do I mark this problem as resolved and close the issue in your system?

    Thanks,

    Raz

Related