Arduino support for YuzukiHD boards: write .ino sketches against the Arduino API and upload them from the
Arduino IDE or arduino-cli. Underneath runs Zephyr, in a prebuilt image that the sketch is linked against
with plain gcc, so using it needs only the Arduino IDE (or arduino-cli), a RISC-V GCC and xfel.
Supported boards: the Allwinner F101 based boards (the F101 EVB, YuzukiNeko). More boards and SoCs are added as
a cores/<soc> / variants/<board> pair.
cores/f101/ Arduino.h, Print/Stream/String, HardwareSerial (headers) and the sketch entry
src/core/ implementation of the core, part of the prebuilt core
libraries/<n>/ public headers of the libraries (src/), f101.conf + f101.overlay of their hardware
libsrc/<n>/ implementation of the libraries, part of the prebuilt core
variants/evb/ pin names, devicetree overlay, Kconfig fragment
prebuilt/ core.elf/.bin/.flash, the loader (boot.img), headers and linker script for sketches
tools/ upload.sh, upload.cmd (used by the IDE), build-core (rebuilds prebuilt/, maintainers)
boards.txt, platform.txt, programmers.txt the Arduino platform
examples/ one folder per example sketch
- A YuzukiHD board (YuzukiNeko, or the F101 EVB).
- A USB cable from the PC to the board's USB port (it is also the download port) and a USB-serial adapter on the
console UART of the board (115200 baud) to see
Serialoutput, if the board has no adapter on board. - Arduino IDE 2.x (https://www.arduino.cc/en/software) or
arduino-cli. Windows 10/11 and Linux x86_64.
You do not download this repository: the IDE fetches everything (platform, RISC-V GCC, xfel, about 85 MB).
-
Open File > Preferences (Arduino > Settings on macOS-style menus), and paste this into Additional boards manager URLs:
https://github.com/YuzukiHD/Arduino/releases/latest/download/package_yuzukihd_index.json -
Open the Boards Manager (left bar, or Tools > Board > Boards Manager), search for YuzukiHD Boards and click Install.
-
Select the board: Tools > Board > YuzukiHD Boards and pick yours (YuzukiNeko, or Allwinner F101 EVB).
-
Select the programmer: Tools > Programmer > xfel (USB FEL). The board has no serial bootloader, so the normal Upload arrow cannot be used; it is the programmer upload that works (see below). The choice is remembered.
With arduino-cli:
arduino-cli config add board_manager.additional_urls https://github.com/YuzukiHD/Arduino/releases/latest/download/package_yuzukihd_index.json
arduino-cli core update-index
arduino-cli core install yuzuki:f101
(The index only exists once a release has been published; until then use the release assets or build it, see "Build the release".)
The board is flashed over USB while it is in its boot ROM download mode, called FEL.
-
Windows: install the WinUSB driver once. Hold the board's FEL key, power the board (or plug the USB cable), open https://zadig.akeo.ie, choose the device
USB Device (VID_1f3a PID_efe8), driver WinUSB, Install Driver. -
Linux: install
libusb-1.0(sudo apt install libusb-1.0-0) and allow access without root:echo 'SUBSYSTEM=="usb", ATTR{idVendor}=="1f3a", ATTR{idProduct}=="efe8", MODE="0666"' | sudo tee /etc/udev/rules.d/50-allwinner-fel.rules sudo udevadm control --reload
- File > Examples, scroll to the examples of YuzukiHD Boards (Blink, SelfTest, SDInfo, DisplayBasics, ...),
open Blink. (They are also in
Documents/Arduino/hardware/yuzuki/f101/examplesif the menu does not show them.) - Click Verify (the check mark). It compiles in a few seconds.
- Put the board in FEL mode: hold the FEL key, power the board on (or reset it), then release.
- Sketch > Upload Using Programmer (Ctrl+Shift+U). It writes the loader, the core and your sketch to the board's flash and starts it. A few seconds for a small sketch.
- Open a serial terminal on the board's console at 115200 baud (the Arduino Serial Monitor on the adapter's COM port):
you should see
F101 Arduino: Blinkandon/offevery half second. The LED is on pinPA0(the EVB has no user LED: wire one there).
From now on the board runs the sketch by itself at every power up. To upload again, put it in FEL mode again (hold FEL, power up): a board that runs from flash does not enter FEL by itself.
If the upload says no board in FEL mode, the board is not in FEL: repeat step 3 and check the USB driver (section 3).
Choosing Upload instead of Upload Using Programmer, or no programmer in the Tools menu, fails with
Request 'upload' failed.
It is the usual Arduino API: pinMode, digitalWrite, analogRead, analogWrite, Serial, Wire, SPI,
String, millis, delay, ... Pins are named PA0 ... PF31 (bank letter + number) and A0..A11 for the
analog inputs. Serial.begin(115200) is all the setup the console needs; other UARTs are Serial1..Serial5
(Serial1.setPins(rx, tx) to choose pins; the pins of the console come from the board and are not re-routed).
The tables below list what is supported and which pins are used.
Peripherals come as libraries, include what you use: #include <SD.h>, <Display.h>, <Audio.h>, <MP4Player.h>, ...
The examples show each of them; the list is in "Libraries for the on-chip peripherals". Two things to know:
DisplayandDBIuse the same pins (PD0..PD5): one of them per sketch.- A sketch is limited to 2 MiB of code and data; the system (Zephyr, drivers, all libraries, ~0.9 MB) is part of the prebuilt core and is not counted. The size the IDE prints is only your sketch, so it is small (hundreds of bytes).
Download yuzukihd-f101-<version>.zip from the Releases page (https://github.com/YuzukiHD/Arduino/releases), unpack
it as <sketchbook>/hardware/yuzuki/f101 (the sketchbook is Documents/Arduino), install riscv-gcc and xfel from
the same page under <Arduino15>/packages/yuzuki/tools/<name>/<version> (Arduino15 is
%LOCALAPPDATA%\Arduino15 on Windows, ~/.arduino15 on Linux), and restart the IDE.
GitHub Actions (.github/workflows/build.yml) does it: it builds the core with the xPack GCC, packages it, installs the
package with arduino-cli and compiles every example, and a tag v<platform version> publishes the files as a release.
The same by hand: CROSS_COMPILE=<xPack>/bin/riscv-none-elf- tools/build-core then tools/package --out dist.
SPI NOR 0x000000 loader (SyterKit, 3 copies at 64 KiB intervals): brings up the PSRAM
0x200000 core header page + core image (Zephyr, drivers, libraries; linked at 0x40000000)
0x400000 sketch image (linked for the window at 0x40e00000)
At power up the BROM starts the loader, which copies the core and the sketch into PSRAM and starts
the core; the core calls setup() and loop() of the sketch. The sketch is compiled and linked by
plain gcc against prebuilt/core/core.elf (platform.txt); the headers it needs are in prebuilt/.
Upload (IDE: "Upload Using Programmer" with xfel, which needs no serial port): hold the FEL key,
power the board, upload. xfel writes loader, core and sketch to the flash and starts the loader. A board
that runs from flash does not enter FEL without the key. The loader is an application of SyterKit
(boards/yuzukineko/app_sram/flash-boot, GPL-2.0).
Rebuild the core (maintainers, needs the west workspace this directory lives in): tools/build-core.
| Arduino API | Implementation |
|---|---|
pinMode/digitalWrite/digitalRead |
Zephyr GPIO, pin number = bank*32 + pin, names PA0..PF31 |
attachInterrupt/detachInterrupt |
GPIO callbacks (RISING/FALLING/CHANGE/ONHIGH/ONLOW) |
analogRead(A0..A11) |
GPADC, 12 bit scaled by analogReadResolution() (default 10) |
analogWrite, tone, analogWriteFrequency |
PWM0, pins PD6 PD7 PD8 PB3 (500 Hz default) |
Serial |
the console UART of the board (its pins come from the board file), with an RX ring buffer, begin(baud, SERIAL_8N1...) |
Serial1..Serial5 |
UART5, UART2, UART1, UART0, UART4 |
setPins(rx, tx), begin(baud, cfg, rx, tx) |
pins are routed at run time (no devicetree edit): UART0 PF4/PF2, UART1 PF1/PF0 or PB1/PB0, UART2 PF5/PF4, UART3 PE9/PE8 or PE1/PE0, UART4 PE3/PE2, UART5 PE5/PE4 (RX/TX). Other pins are refused. The first pair is the default (Serial2..Serial4 default onto the SD card pins PF0..PF5) |
Wire |
I2C1 on PE0 (SCL) / PE1 (SDA), controller mode only |
SPI |
SPI0 on PC0 (SCK) / PC4 (MOSI) / PC2 (MISO); chip select is up to the sketch |
millis/micros/delay/delayMicroseconds |
kernel clock, 24 MHz cycle counter |
String, Print, Stream, F(), printf |
own implementation, Serial.printf() supported |
| math | toolchain libm (sin, pow, ...) |
setup() and loop() run in Zephyr's main thread (16 KiB stack); new/malloc
use all RAM above the image.
Every library is part of the prebuilt core; a sketch just includes it. Devices that own pins or power
are started by the library in begin(), not at boot.
| Library | Hardware | Notes |
|---|---|---|
Display |
DE + TCON + RGB panel | ARGB8888 buffer, drawing/text, show(), video plane (showYuv), backlight. Uses PD0..PD22, PE6/7, PB0..PB3 once Display.begin() ran (LVGL is not part of the core: point the LVGL Arduino library at Display.buffer()) |
G2D |
2D engine | fill, blit (convert/scale), blend; rotate/flip must keep format and size |
DBI |
MIPI DBI (PD0..PD5) | exclusive with Display: both use PD0..PD5, including both is an #error |
Audio |
on-chip codec | PCM out, mic in, tone, volume, speaker PA (PE10) |
I2S, SPDIF |
I2S0, OWA | I2S0 has no pins on the EVB (internal loopback); S/PDIF RX DMA unresolved |
SD |
SMHC0 (PF0..PF6) | Arduino SD API, File is a Stream; also the USBDrive volume |
USBDevice |
CherryUSB device | USBSerial (CDC ACM) |
USBHost |
CherryUSB host | USBHostMSC (+FAT mount as USBDrive), USBHostSerial; one USB role per sketch |
VideoDecoder |
VE | hardware JPEG/PNG, H.264 stream |
MP4, AACDecoder, MP4Player |
demuxer, AAC, full player | player needs Display, SD and codec |
Watchdog |
WDT | begin(ms), reset(), end() |
Status on the EVB (serial-verifiable results only; picture and sound are not judged):
verified I2S loopback (180k frames, 0 mismatches), SD (mkdir/read/seek/rename/remove),
Watchdog (CPU reset), G2D (all calls return 0), VideoDecoder JPEG (320x240 in 4 ms).
Built but not run yet: Display, DBI, Audio, SPDIF, USBDevice, USBHost, MP4*, H.264, PNG.
Pins that the EVB's LCD and backlight use (PD0..PD22, PB0..PB3) are only claimed once Display (or DBI)
is started; PWM and UART pins are routed when first used. The EVB has no documented user LED:
LED_BUILTIN is PA0, wire an LED there. PE2 is the USB VBUS switch and PF0..PF5 the SD card, avoid them.
A new board is a new directory in variants/<name>/ with pins_arduino.h, <name>.overlay and
<name>.conf.
Wire.endTransmission(false)(repeated start) still ends with a STOP; there is no peripheral mode.Serial.printis synchronous (polled TX) and the shell/log are disabled so thatSerialowns the console UART.analogWriteon a pin without PWM does a digital 50 % threshold.- No
Servo,EEPROM,WiFilibraries yet.
SelfTest (String, timing, math, GPIO, ADC, PWM, Wire, SPI, Serial RX echo), AnalogSerial, DisplayBasics
on the single core, flash boot at power up, upload.cmd from Windows with xfel; earlier on a per-peripheral
core: I2S loopback, SD, Watchdog, G2D, VideoDecoder JPEG. Not run on the current core:
DBI, G2D, VideoDecoder, Audio, SPDIF, USBDevice, USBHost, MP4*, H.264, PNG.