Bare metal zig code on raspberry pico 2

Hi,

I’m having some trouble getting a raspberry pico 2 to run bare metal zig code (code available here ) and I’m hoping to get some help from the community.

I’m trying to do the basic embedded hello world to blink the on board LED, but i can’t get my code to run. The pico just reboots in usb flash mode immediately after i flash the uf2 file to it.

This is what i get when generating the uf2 file with picotool:

read_ph ph offset 52 #entries 4
read_sh sh offset 65860 #entries 7
Detected FLASH binary
Mapped segment 10000000->10000028 (10000000->10000028)
Mapped segment 10000028->10000060 (10000028->10000060)
Page 0 / 1 10000000

And here is the structure of the ELF file:

zig-out/bin/blink:     file format elf32-littlearm

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .vector_table 00000008  10000000  10000000  00010000  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  1 .ARM.exidx    00000020  10000008  10000008  00010008  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  2 .text         00000038  10000028  10000028  00010028  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  3 .ARM.attributes 00000034  00000000  00000000  00010060  2**0
                  CONTENTS, READONLY
  4 .comment      0000006d  00000000  00000000  00010094  2**0
                  CONTENTS, READONLY

I have tried looking at example projects available online, but most of it is in C or python using complex full featured SDKs that make it hard to understand at a basic level what i need to do at the linking and building stages for my code to run.

I tried following the microzig getting started guide from scratch in a new project, but i get a similar result as with my own code: the compilation and uf2 generation complete without errors but the code doesn’t do anything and the chip reboots right away.

I don’t think anything is wrong with the chip itself because the pre-compiled uf2 blink example from the official docs runs as expected.

I guess the problem is related to the initial stack pointer and/or reset handler either not being at the right memory addresses or not pointing to the right addresses, but i’m not sure how to set that up properly.

If someone has managed to run some basic zig code on the pico 2 i would very much appreciate some help to understand how to set up the binary correctly so the chip can run it.

2 Likes

Hi ! I can’t say for sure, but is the code compiled in debug mode ? there’s been some regression lately with the new Io interface in binary size, and you might be blowing up the stack because of it :slight_smile:

1 Like

I’m sorry I can’t provide direct code assistance, but section 5.9.5.1. Minimum Arm IMAGE_DEF of this document might be helpful.

1 Like

I was able to get the microzig getting started example to work on the pico2 by changing the firmware target board to mb.ports.rp2xxx.boards.raspberrypi.pico2_arm.

2 Likes

I was initially compiling with -Doptimize=ReleaseSmall option, but apparently this was part of my problem. I got the code to work correctly now, but only when compiling in debug mode.

When i compile in ReleaseSmall mode, the code runs and the LED turns on, but then it doesn’t blink, as if some part of the main loop was bugged or missing. I also get some weird “undefined” and “unpredictable” comments in the ELF output:

1000003c <.text>:
1000003c:       21004806        tstcs   r0, r6, lsl #16
10000040:       48066001        stmdami r6, {r0, sp, lr}
10000044:       60012105        andvs   r2, r1, r5, lsl #2
10000048:       f04f4805                        ; <UNDEFINED> instruction: 0xf04f4805
1000004c:       62017100        andvs   r7, r1, #0, 2
10000050:       60816001        addvs   r6, r1, r1
10000054:       bf00e7fc        svclt   0x0000e7fc
10000058:       40038068        andmi   r8, r3, r8, rrx
1000005c:       400280cc        andmi   r8, r2, ip, asr #1
10000060:       d0000018        andle   r0, r0, r8, lsl r0
10000064:       f7ffb580                        ; <UNDEFINED> instruction: 0xf7ffb580
10000068:       4770ffe9        ldrbmi  pc, [r0, -r9, ror #31]! ; <UNPREDICTABLE>

I get the same behavior with ReleaseFast and ReleaseSafe compilation modes. I only get the expected behavior of blinking the LED when compiling in Debug mode.

Thank you, i didn’t realize i needed to manually include that in my code, i assumed it would be provided for me automatically by the ELF to UF2 conversion tool.

Part of getting the code the work was defining this magic boot block as a data structure in the code and forcing the linker to include it in the ELF output.

I also looked at this repo for a very minimal pico 2 example written in C, which helped a lot.

2 Likes