No support for Raspberry Pi Picoprobe (CMSIS-DAP)

Comments

21 comments

  • Avatar
    Jon Elliott

    Set the USB > Interface Mode target property to CMSIS-DAP v2 (Bulk/WinUsb).

    0
    Comment actions Permalink
  • Avatar
    EZ

    I've done that and if I leave the target on maximum speed I still get a "debug register" error.

    When I lower the target speed to 1MHz then it seems to work (at least the erase does) but then

    Executing match part name script
    Completed

    Loading target script file RP2040_Target.js
    Working

    Preparing target for download
    Completed

    Downloading 'RP2040_Loader.elfâ to CMSIS-DAP
    Download successful

    Verifying "RP2040_Loader.elf on CMSIS-DAP
    Verity successful

    Erasing 'Blinky.elf on CMSIS-DAP
    Erase successful

    Downloading 'Blinky.elf to CMSIS-DAP
    Download successful

    Verifying "Blinky.elf on CMSIS-DAP
    Verify failed

    Uploading Blinky.elf from CMSIS-DAP
    Upload successful

    it fails on verify and the flash is all FFs.

                       Blinky.elf                                               RP2040 MO 0 - CMSIS-DAP

    10000000: 00 B5 32 45 21 20 58 60 98 68 02 21 88 43 98 60  10000000: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
    10000010: D8 60 18 61 58 61 2E 4B 00 21 99 60 04 21 59 61  10000010: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 
    0
    Comment actions Permalink
  • Avatar
    Michael Johnson

    Works on my desk at 8Mhz, which target board are you using?

    0
    Comment actions Permalink
  • Avatar
    EZ

    Thanks for that Michael.

    I was using a chinese RP2040 board. When I switched to an official RPico board I was able to program and

    debug the board from within crossworks studio

    openocd is able to program both boards though with the following command:

    openocd -f interface/cmsis-dap.cfg -f target/rp2040.cfg -c "adapter speed 5000" -c "program Blinky.elf verify reset exit"

    If I program the chinese board with openocd and then verify it from within crossworks I get no error.

    So the only problem is programing the flash (which is bigger on the chinese board).

    Bellow is the difference from the openocd output for the 2 boards:

    -Info : Found flash device 'win w25q16jv' (ID 0x001540ef)
    -Info : RP2040 B0 Flash Probe: 2097152 bytes @0x10000000, in 32 sectors
    +Info : Found flash device 'win w25q128fv/jv' (ID 0x001840ef)
    +Info : RP2040 B0 Flash Probe: 16777216 bytes @0x10000000, in 256 sectors

    -Info : Padding image section 0 at 0x100007f8 with 8 bytes (bank write end alignment)

     

    0
    Comment actions Permalink
  • Avatar
    Michael Johnson

    Okay - could you be more specific regarding the board. We'll get one so we can reproduce.

    0
    Comment actions Permalink
  • Avatar
    EZ

    I've got it from Aliexpress:

    https://www.aliexpress.com/item/1005003371056277.html  version "With LED 16M"

    0
    Comment actions Permalink
  • Avatar
    Michael Johnson

    Okay thanks.

    0
    Comment actions Permalink
  • Avatar
    EZ

    I've also tried to set boot2 stage to GENERIC_03 and AT25SF128A but it still doesn't program.

    I think the problem is in your Loader.elf which relies on rp2040 internal_flash_driver which is stored in ROM and it might not have support for every SPI flash.

    I have also found some more bugs:

    - boot_stage2 in .hzp is inconsistent; if you change it you might end up with conflicting values:

    $rg boot_stage2
    Pico_Timer.hzp:23:      boot_stage2="Winbond W25Q080"
    Pico_Timer.hzp:76:          c_user_include_directories="$(TargetsDir)/RP2040/pico-sdk/src/rp2_common/boot_stage2/asminclude"
    Pico_Timer.hzp:93:    <configuration Name="Debug" boot_stage2="None" />

    This should be a global value, I had to either edit the hzp file to remove that property or change it again twice.

    - setting VECTORS_IN_RAM is broken because the boot2 code is executed first and the exit_from_boot2.S from pico-sdk will load a wrong start address. This also means that one cannot use the 'irq_set_exclusive_handler' function (with a previous call to 'spin_locks_reset') from the sdk because it will try to modify an address in the XIP region and will have no effect. In Crossstudio all interrupt handlers must be fixed at compile time.

    0
    Comment actions Permalink
  • Avatar
    Michael Johnson

    We've ordered the board in question.

    Yes the rp2040 loader uses rp2040 ROM API functions. Which SPI flash is on the board? Does the BOOTSEL drag and drop loader work?

    We'll address the other points in the next CPU support package release.

    0
    Comment actions Permalink
  • Avatar
    Jon Elliott

    - boot_stage2 in .hzp is inconsistent; if you change it you might end up with conflicting values:

    $rg boot_stage2
    Pico_Timer.hzp:23:      boot_stage2="Winbond W25Q080"
    Pico_Timer.hzp:76:          c_user_include_directories="$(TargetsDir)/RP2040/pico-sdk/src/rp2_common/boot_stage2/asminclude"
    Pico_Timer.hzp:93:    <configuration Name="Debug" boot_stage2="None" />

    This should be a global value, I had to either edit the hzp file to remove that property or change it again twice.

    boot_stage2 is a property group which appears as the project property Code > Build > Second Stage Bootloader. Changing this property from within the IDE defines the appropriate C preprocessor definition used in RP2040/Source/RP2040_Boot.s file and is intended as a single point of change for selecting the second stage bootloader.

    The Code > Build > Second Stage Bootloader property is described in "RP2040 Project Properties" section of the "RP2040 CPU Support Package Guide" guide which can be found by clicking Tools > Show Installed Packages then clicking the "Raspberry Pi Foundation RP2040 CPU Support Package" link followed by one of the "RP2040 CPU Support Package Guide" links.

    The boot_stage2 property group is defined as follows in the current version of the support package:

      <group short="Second Stage Bootloader" group="Build Options" long="Select a set of options based on section placement." name="boot_sttage2" default="Winbond W25Q080">
        <groupEntry name="Adesto AT25SF128A">
          <cdefine name="BOOT_STAGE2_ADESTO_AT25SF128A" value="1" />
        </groupEntry>
        <groupEntry name="Generic 03h">
          <cdefine name="BOOT_STAGE2_GENERIC_03" value="1" />
        </groupEntry>
        <groupEntry name="ISSI IS25LP080D">
          <cdefine name="BOOT_STAGE2_ISSI_IS25LP080D" value="1" />
        </groupEntry>
        <groupEntry name="Winbond W25Q080">
          <cdefine name="BOOT_STAGE2_WINBOND_W25Q080" value="1" />
        </groupEntry>
        <groupEntry name="Winbond W25X10CL">
          <cdefine name="BOOT_STAGE2_WINBOND_W25X10CL" value="1" />
        </groupEntry>
        <groupEntry name="None">
          <cdefine name="BOOT_STAGE2_NONE" value="1" />
        </groupEntry>
      </group>
    0
    Comment actions Permalink
  • Avatar
    EZ

    I was confused about the boot_stage2 property; you can only alter it while 'Project' is active, it is not visible under Solution (Debug or Release) but then on 'Project' you have to select between Private and Public configurations and Common is over-ruled by Debug. I guess it functions as intended but you have to be careful what you select.

    0
    Comment actions Permalink
  • Avatar
    EZ

    The chinese board has a 2MB Winbond flash on it W25Q128FV.

    The boot-sel and drop an uf2 has always worked - so this means the flash is supported in ROM.

    I've run the following program from RAM:

    int res;
    libmem_driver_handle_t fl;
    uint8_t *erase_start;
    size_t erase_size;

    res = libmem_rp2040_register_internal_flash_driver(&fl);
    res = libmem_erase_impl(&fl, (uint8_t *)0x10010000, 0x800, &erase_start, &erase_size);
    memset(buf, 0x55, 0x800 );
    res = libmem_write_impl(&fl, (uint8_t *)0x10010000, buf, 0x800 );
    memcpy(buf, (uint8_t *)0x10010000, 0x800 );

    For the normal board with the W25Q16JV the correct value of 0x55 is read back while for the larger flash the read back value is 0xff.

    There is no error reported while running it and all libmem functions return 1 (success). All ROM functions are properly detected in the register_internal_flash_driver function.

    The erase works (it overwrites previous content with 0xff, the read works but the
    flash program fails.

    While doing these tests I've found a method to 'brick' both boards: just erase the start of flash and reset the board.
    In this case the pico-probe cannot connect anymore to either board. The only way to recover them is via UF2 drop. I guess there is nothing which can be done for this because there is no reset line accessible for the CMSIS-DAP interface.

    0
    Comment actions Permalink
  • Avatar
    EZ

    I strongly suggest the inclusion of these 2 lines:

    reset_block(~(RESETS_RESET_IO_QSPI_BITS | RESETS_RESET_PADS_QSPI_BITS |    RESETS_RESET_PLL_USB_BITS | RESETS_RESET_USBCTRL_BITS | RESETS_RESET_SYSCFG_BITS |  RESETS_RESET_PLL_SYS_BITS  ));
    unreset_block_wait(RESETS_RESET_BITS & ~( RESETS_RESET_ADC_BITS | RESETS_RESET_RTC_BITS |  RESETS_RESET_SPI0_BITS |  RESETS_RESET_SPI1_BITS | RESETS_RESET_UART0_BITS | RESETS_RESET_UART1_BITS |  RESETS_RESET_USBCTRL_BITS ));

    before the 'clocks_init' call in the 'SystemInit' function.
    These will put the CPU in a known state.
    These are the first 2 lines from the 'runtime_init' SDK function, a function which cannot be called from a crossworks program because it doesn't link (and also expects the vectors in RAM).

    I've spent a few hours trying to debug the PWM peripheral; I was calling 'reset_block' followed by 'unreset_block_wait' but only with a RESETS_RESET_PWM parameter.
    The result was the PWM block was counting, even generating interrupts, other IO was working fine but the PWM was not producing any output until I've added the above two lines.

     

     

    0
    Comment actions Permalink
  • Avatar
    Michael Johnson

    The boot_stage2 property is property group so can only be defined on the project level. The "Common" configuration is inherited by "Debug" and "Release" configurations - usually "Common" is the configuration to set properties in.

    I have found a board with the W25Q128Mb

    https://www.sparkfun.com/products/17745

    which works okay.

    The reset line is on the debug header - if this isn't connected on the chinese board you have (our order won't appear till year end) this may explain problems you are seeing.

    0
    Comment actions Permalink
  • Avatar
    EZ

    I was only mentioning the reset line because other CPUs include it on the SwD connector.

    The original Pico board only has 3 pins on the debug port: Gnd, SwDIO, SwClk. The chinese board has an extra 3V power pin. Both boards have reset connected on pin30 (they have identical pin layout) but the picoprobe programming dongle doesn't have nor support a hardware reset pin.

    When the serial flash is filled with 0xFFs the RP2040 tries to execute that code and somehow disables the SwD interface completely. To restore the target connection you have to press BootSel and reset (maually) so that the CPU stays and executes ROM code and then your SwD interface is accessible again.

    0
    Comment actions Permalink
  • Avatar
    EZ

    So what's your opinion on why my board is not working? I can only see the culprit as the 'RP2040_Loader.elf' program (I've used the original and I've also compiled it myself). Could this be a timing issue?

    So to resume the W25Q128 board can be programmed by UF2 drop, by openocd and can be debugged by crossworks if previously programmed by the 2 mentioned methods. It cannot be programmed by the crossworks loader program (no error, just silent fail).

    0
    Comment actions Permalink
  • Avatar
    Michael Johnson

    The reset script (in RP2040_Target.js) does a System Reset (chip dependent) using the AIRCR and then clears the CLK_SYS_CTRL and uses the RESETS register to put the peripherals into reset.

    From your previous message could this is the problem with your PWM program i.e. the PWM is held in reset?

    The SPI programming could also be affected by the (lack of) reset however I would expect the erase not to work if this is the case.

    If you add _vectors to the "Keep Symbols" property then "Flash Vectors in RAM" should work.

    0
    Comment actions Permalink
  • Avatar
    EZ

    It was exactly as I said: the write fails, the erase worked.

    I've rewritten the loader so it won't use the 'libmem_driver_paged_write', the interaction of that function with the static 'flash_write_page' is somehow broken.

     

    So now I finally got a working loader for both boards:

    https://uglyduck.vajn.icu/libmem_rp2040_internal_flash_driver.c 

    0
    Comment actions Permalink
  • Avatar
    Jon Elliott

    So what's your opinion on why my board is not working? I can only see the culprit as the 'RP2040_Loader.elf' program (I've used the original and I've also compiled it myself). Could this be a timing issue?

    The loader could be running out of stack when calling the functions in ROM - try increasing the stack size from the default of 512 bytes. Note that the loader's stack size is specified in the RP2040 configuration rather than the Common configuration - the easiest way to change this is to modify the arm_linker_stack_size="512" attribute definition in the Loader.hzp file and then reload the project.

    0
    Comment actions Permalink
  • Avatar
    Jon Elliott

    Version 4.3 of the RP2030 support package has just been released ( https://www.rowleydownload.co.uk/arm/packages/index.htm#RP2040 ). This version includes a fix a to the loader that could well be the cause of the problem you are seeing. Please could you try upgrading to this version and see whether is solves the problem.

    Thanks,

    Jon

    0
    Comment actions Permalink
  • Avatar
    EZ

    Yes, the new version solved the problem, thanks.

    0
    Comment actions Permalink

Please sign in to leave a comment.