Skip to content

add CAINIAO CNIoT-CORE initial support #8208

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jun 9, 2025

Conversation

retro98boy
Copy link
Contributor

How Has This Been Tested?

build the armbian.img, flash to eMMC/USB drive,then boot and use it

Checklist:

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • My changes generate no new warnings

Hardware

Cainiao Logistics Terminal A311D Edition, detachable into two parts: the main unit and the base.

overview

Main Unit

Amlogic A311D SoC, 2 GB DDR, 16 GB eMMC

No SD card slot, so the A311D can only load FIP from eMMC.

Gigabit Ethernet port and RTL8822CS WiFi/BT.

One USB Type-C port for power and data transfer in USB download mode. When the main unit is used with the base, it is unclear if this Type-C can function as a Host under Linux, as it is obstructed by the base, making it difficult to plug in devices for testing.

Base

The base comes in different models, but the software should be universal.

Equipped with a USB HUB, display (HDMI or VGA), and power supply (USB Type-C or DC).

Debug Points

Debug UART

debug-uart

eMMC Shorting Point

emmc-short

Armbian Peripheral Status

Component Status
GBE Working
WiFi Working
BT Working
PWM Fan Working
eMMC Working
USB Working
HDMI Display Working
HDMI Audio Working
Internal Speaker Not Working
Power Button Working
ADC Key Working
Side Lights? Not Working
Four Dots on Side Not Working (USB? SPI?)

Installing Armbian

The Amlogic USB Burning Tool uses a proprietary firmware format. Although the firmware extension is .img, it is not a disk image file.

There are tools available for unpacking/repacking it:

Amlogic binary only executable

hzyitc/AmlImg

7Ji/ampack

Repacking all system image .img files into USB flashing packages is not cost-effective.

You can pack an FIP with mainline U-Boot into a USB flashing package to restore the device to a state with mainline U-Boot. Mainline U-Boot includes drivers for Ethernet, USB, and eMMC, which is sufficient for many tasks.

An FIP with mainline U-Boot is available here.

Flashing Mainline U-Boot

Using dd Command

If the device has a working system like Android or Linux with root access, you can simply write fip-with-mainline-uboot.bin to the eMMC:

dd if=path-to-fip-with-mainline-uboot.bin of=/dev/mmcblk1 bs=512 seek=1

It is also recommended to flash the FIP to the eMMC boot area, as the A311D will try to load the FIP from the eMMC boot area if it cannot find it in the user area.

On Linux, you can:

# Check if write access to boot area is available
blockdev --getro /dev/mmcblk1boot0
blockdev --getro /dev/mmcblk1boot1

# Unlock write access to boot area
echo 0 | sudo tee /sys/block/mmcblk1boot0/force_ro
echo 0 | sudo tee /sys/block/mmcblk1boot1/force_ro

dd if=path-to-fip-with-mainline-uboot.bin of=/dev/mmcblk1boot0 bs=512 seek=1
dd if=path-to-fip-with-mainline-uboot.bin of=/dev/mmcblk1boot1 bs=512 seek=1

Using USB Download Mode

If you cannot gain root access to the existing system on the device, you can use the Amlogic USB Burning Tool with the prepared USB flashing package fip-with-mainline-uboot.burn.img to directly flash mainline U-Boot to the eMMC. See Flashing eMMC in USB Download Mode for the USB download process.

The Amlogic USB Burning Tool will write the FIP to the eMMC boot area.

Flashing Armbian Image

Flashing Armbian Image to USB Drive

If you frequently test different systems, considering the lifespan of eMMC and convenience, you may prefer booting from a USB drive. Simply flash the .img file to a USB drive, insert it into the device, and power on. The mainline U-Boot on the eMMC will automatically scan devices like eMMC, USB, and Ethernet in sequence to find a suitable boot environment, such as a U-Boot script, extlinux, or TFTP.

If the A311D still boots from eMMC, it means there is a bootable system on the eMMC. To force booting from USB, you need to destroy the system on the eMMC, such as by deleting the MBR partition table. Alternatively, in the U-Boot command line, enter setenv boot_targets usb0 && boot if you have a UART cable connected.

Flashing Armbian Image to eMMC

Method 1

This method requires a USB drive and network access for the device.

First, flash the Armbian system image to a USB drive and boot the device from it. Then, transfer the system image to be installed to the USB drive via the network, and use the dd command to flash it to the eMMC:

dd if=path-to-your-os-img of=/dev/mmcblk1 status=progress

Alternatively, use a trick to avoid transferring the system image to the USB drive.

On the Armbian system booted from the USB drive, install Netcat and run:

nc -l -p 1234 > /dev/mmcblk1

On a Linux PC, install Netcat and run:

nc -w 3 your-cainiao-cniot-core-ip 1234 < path-to-your-os-img

Netcat has two variants: GNU and OpenBSD. If you have GNU Netcat installed on the PC, the command should be:

nc -w 3 -c your-cainiao-cniot-core-ip 1234 < path-to-your-os-img

To install OpenBSD Netcat:

# ArchLinux
sudo pacman -S openbsd-netcat
# Ubuntu/Debian
apt install netcat-openbsd

To install GNU Netcat:

# ArchLinux
sudo pacman -S gnu-netcat
# Ubuntu/Debian
sudo apt install netcat-traditional

Method 2

This method requires connecting the device's UART to a PC and ensuring both the device and PC are on the same LAN via Ethernet.

First, place the system image to be installed on the Linux PC and rename it, e.g., armbian.img.

Split the image on the Linux PC, as the device's memory cannot hold the entire image at once:

split -b 512M armbian.img armbian.img.
# Assume armbian.img is split into armbian.img.aa, armbian.img.ab, armbian.img.ac; note the filenames.

Set up a TFTP server on the PC.

Windows users can use Tftpd64.

On Linux, use a similar tool like puhitaku/tftp-now. Download the binary from Releases, install it to PATH, and run sudo tftp-now serve -root dir-to-armbian.img.aX.

When powering on the device, press the spacebar in the UART session to enter the U-Boot command line.

Configure the device's network:

setenv ipaddr 172.24.0.241
setenv netmask 255.255.252.0
setenv gatewayip 172.24.0.1
setenv serverip 172.24.0.248

The IP 172.24.0.248 is the PC's IP.

Set the RAM address for temporarily storing the image:

setenv loadaddr 0x20000000

Start downloading the image from the PC's TFTP server and write it to the eMMC:

setenv mmcscript 'setenv files "armbian.img.aa armbian.img.ab armbian.img.ac"; setenv offset 0x0; for file in ${files}; do tftpboot ${loadaddr} ${file}; setexpr nblk ${filesize} / 0x200; mmc write ${loadaddr} ${offset} ${nblk}; setexpr offset ${offset} + ${nblk}; done'
mmc dev 1 && run mmcscript

Finally, reboot the device.

Flashing eMMC in USB Download Mode

The USB Type-C port on the main unit is the USB download port.

Shorting the eMMC shorting point and powering on will put the device into USB download mode.

Alternatively, while the device is running, you can erase the header of the eMMC user/boot area and reboot to enter USB download mode. Example commands:

# Under Linux
sudo dd if=/dev/zero of=/dev/mmcblk1 bs=1MiB count=4 status=progress

echo 0 | sudo tee /sys/block/mmcblk1boot0/force_ro
echo 0 | sudo tee /sys/block/mmcblk1boot1/force_ro

sudo dd if=/dev/zero of=/dev/mmcblk1boot0 bs=1MiB count=4 status=progress
sudo dd if=/dev/zero of=/dev/mmcblk1boot1 bs=1MiB count=4 status=progress

# Under U-Boot command line
mmc dev 1
mmc erase 0 8192
mmc partconf 1 1 1 1
mmc erase 0 8192
mmc partconf 1 1 2 2
mmc erase 0 8192

Finally, use Amlogic USB Burning Tool v2.x.x to flash the image.

Copy link
Contributor

coderabbitai bot commented May 19, 2025

Walkthrough

A new board configuration file for the "CAINIAO CNIoT-CORE" device was introduced, detailing board-specific settings and custom build functions for handling firmware integration and tooling. This includes fetching vendor firmware, building a required host tool (gxlimg), and repacking the vendor Firmware Image Package (FIP) with a mainline U-Boot binary. Additionally, the common post-processing logic was updated to recognize this board, delegating its custom post-processing to the new board file. A new ALSA sound state configuration with 49 mixer and PCM controls was also added for the CNIoTCORE audio hardware. No changes were made to exported function signatures outside the new board configuration.

Suggested labels

ready to merge

Suggested reviewers

  • igorpecovnik
  • clee
  • joekhoobyar
  • rpardini

📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0bd2d87 and 8103f79.

⛔ Files ignored due to path filters (5)
  • patch/kernel/archive/meson64-6.12/dt/meson-g12b-a311d-cainiao-cniot-core.dts is excluded by !patch/**
  • patch/kernel/archive/meson64-6.12/meson-g12b-pinctrl-Add-missing-pinmux-for-pwm.patch is excluded by !patch/**
  • patch/kernel/archive/meson64-6.15/dt/meson-g12b-a311d-cainiao-cniot-core.dts is excluded by !patch/**
  • patch/kernel/archive/meson64-6.15/meson-g12b-pinctrl-Add-missing-pinmux-for-pwm.patch is excluded by !patch/**
  • patch/u-boot/v2025.04/board_cainiao-cniot-core/add-board-cainiao-cniot-core.patch is excluded by !patch/**
📒 Files selected for processing (3)
  • config/boards/cainiao-cniot-core.csc (1 hunks)
  • config/sources/families/meson-g12b.conf (1 hunks)
  • packages/blobs/asound.state/asound.state.cainiao-cniot-core (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • packages/blobs/asound.state/asound.state.cainiao-cniot-core
🚧 Files skipped from review as they are similar to previous changes (2)
  • config/sources/families/meson-g12b.conf
  • config/boards/cainiao-cniot-core.csc

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions github-actions bot added size/large PR with 250 lines or more 05 Milestone: Second quarter release Needs review Seeking for review Hardware Hardware related like kernel, U-Boot, ... Patches Patches related to kernel, U-Boot, ... labels May 19, 2025
@coderabbitai coderabbitai bot added the Ready to merge Reviewed, tested and ready for merge label May 19, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (4)
config/sources/families/meson-g12b.conf (1)

27-29: Redundant noop branch can be dropped

The new branch exactly mirrors the preceding VIM3 branch – a simple do-nothing (:) – which is fine, but not strictly necessary.
Removing it would shorten the if-chain without changing behaviour because the board already implements post_uboot_custom_postprocess in its own file.

config/boards/cainiao-cniot-core.conf (3)

8-8: Black-listing simpledrm hides a working fallback console

Disabling simpledrm avoids Panfrost conflicts but also removes the early framebuffer that’s handy for debugging.
An alternative is to leave the module enabled and pass video=efifb:off or drm.debug=0 on the kernel cmdline when Panfrost is loaded.
Consider whether losing the boot logo / early console is acceptable.


13-13: ASOUND_STATE points to a different board

ASOUND_STATE="asound.state.khadas-vim3" may work accidentally but makes the intent unclear and risks mismatched mixer-routing.
Provide a dedicated state file (even if identical) to make future maintenance obvious.


33-45: Installation step should use install(1) and honor $DESTDIR

Copying the binary with cp hard-codes /usr/local/bin. Use install -m 0755 and the build framework’s destination directory instead:

- mkdir -p /usr/local/bin/
- cp gxlimg /usr/local/bin
+ install -Dm0755 gxlimg "${HOST_INSTALL_DIR:-/usr/local}/bin/gxlimg"

This also preserves permissions and works under sudo-less container builds.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d0f708d and 6bc91d0.

⛔ Files ignored due to path filters (3)
  • patch/kernel/archive/meson64-6.12/dt/meson-g12b-a311d-cainiao-cniot-core.dts is excluded by !patch/**
  • patch/kernel/archive/meson64-6.14/dt/meson-g12b-a311d-cainiao-cniot-core.dts is excluded by !patch/**
  • patch/u-boot/v2025.04/board_cainiao-cniot-core/add-board-cainiao-cniot-core.patch is excluded by !patch/**
📒 Files selected for processing (4)
  • config/boards/cainiao-cniot-core.conf (1 hunks)
  • config/kernel/linux-meson64-current.config (1 hunks)
  • config/kernel/linux-meson64-edge.config (1 hunks)
  • config/sources/families/meson-g12b.conf (1 hunks)
🔇 Additional comments (3)
config/kernel/linux-meson64-edge.config (1)

3722-3722: Enable CONFIG_PWM_GPIO as a loadable module
This change mirrors the update in linux-meson64-current.config and makes the PWM_GPIO driver available at runtime without a full rebuild. It’s consistent with the existing CONFIG_PWM=y selection above and should satisfy the new board’s PWM requirements.

config/kernel/linux-meson64-current.config (1)

3717-3722: PWM-GPIO enabled only as module – verify boot-time requirements

CONFIG_PWM_GPIO=m will defer driver availability until after the root FS is mounted.
If the board needs PWM (e.g. fan, back-light) very early in the boot sequence consider compiling it in (=y) instead of a module. Otherwise the change looks good.

config/boards/cainiao-cniot-core.conf (1)

58-60: Missing existence check before mv

mv u-boot.bin raw-u-boot.bin assumes the file is in the current working directory.
To avoid hard-to-diagnose build failures:

[[ -f u-boot.bin ]] || { echo "u-boot.bin not found"; exit 1; }
mv u-boot.bin raw-u-boot.bin

@CT1IQI
Copy link

CT1IQI commented May 19, 2025

Who is (re)selling this product? Tried to find it but it seems a proprietary tool for the Cainiao logistics company. When not a commercial product there is little point in having it as a board in Armbian/build.

@retro98boy
Copy link
Contributor Author

Who is (re)selling this product? Tried to find it but it seems a proprietary tool for the Cainiao logistics company. When not a commercial product there is little point in having it as a board in Armbian/build.

This device is indeed not a product directly aimed at ordinary consumers, but on a famous online second-hand market in China, some merchants are selling it, with prices ranging from $14 to $30. Most people buy it to use as an Android TV Box.

Screenshot_2025-05-19-19-00-53-55_0dff84d2da4d0ad536cbb4d749024dd6

@retro98boy retro98boy force-pushed the cainiao-cniot-core branch from 6bc91d0 to 6e6e585 Compare May 21, 2025 14:08
@github-actions github-actions bot removed the Ready to merge Reviewed, tested and ready for merge label May 21, 2025
@coderabbitai coderabbitai bot added the Ready to merge Reviewed, tested and ready for merge label May 21, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (2)
config/boards/cainiao-cniot-core.csc (2)

4-4: Fill in BOARD_MAINTAINER to avoid “orphan” board definitions

Leaving the maintainer field empty makes it hard for others to know who to ping when this board definition breaks in the future.
Please add at least a GitHub handle or email so issues can be routed quickly.


33-45: Race-proof rebuild guard for gxlimg

  1. git rev-parse @ fails if the repo has no commits (e.g. interrupted clone).
  2. The current logic rebuilds when /usr/local/bin/gxlimg is missing, but never checks whether that binary actually matches the recorded commit.

A safer pattern:

current_sha=$(git rev-parse HEAD)
installed_sha=$(cat /usr/local/bin/.gxlimg_commit 2>/dev/null || echo "none")
if [[ $current_sha != "$installed_sha" ]]; then
    …
    cp gxlimg /usr/local/bin
    echo "$current_sha" >/usr/local/bin/.gxlimg_commit
fi
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6bc91d0 and 6e6e585.

⛔ Files ignored due to path filters (5)
  • patch/kernel/archive/meson64-6.12/dt/meson-g12b-a311d-cainiao-cniot-core.dts is excluded by !patch/**
  • patch/kernel/archive/meson64-6.12/meson-g12b-pinctrl-Add-missing-pinmux-for-pwm.patch is excluded by !patch/**
  • patch/kernel/archive/meson64-6.14/dt/meson-g12b-a311d-cainiao-cniot-core.dts is excluded by !patch/**
  • patch/kernel/archive/meson64-6.14/meson-g12b-pinctrl-Add-missing-pinmux-for-pwm.patch is excluded by !patch/**
  • patch/u-boot/v2025.04/board_cainiao-cniot-core/add-board-cainiao-cniot-core.patch is excluded by !patch/**
📒 Files selected for processing (2)
  • config/boards/cainiao-cniot-core.csc (1 hunks)
  • config/sources/families/meson-g12b.conf (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • config/sources/families/meson-g12b.conf

@igorpecovnik
Copy link
Member

igorpecovnik commented May 29, 2025

Hey! I don't mind merging this, but please check if any of AI suggested changes are valuable. There is also one merge conflict.

@retro98boy retro98boy force-pushed the cainiao-cniot-core branch from 6e6e585 to 0bd2d87 Compare May 31, 2025 15:47
@github-actions github-actions bot removed the Ready to merge Reviewed, tested and ready for merge label May 31, 2025
@coderabbitai coderabbitai bot added the Ready to merge Reviewed, tested and ready for merge label May 31, 2025
@retro98boy
Copy link
Contributor Author

Hey! I don't mind merging this, but please check if any of AI suggested changes are valuable. There is also one merge conflict.

I am very happy that it can be merged into the mainline source code, and I will modify my PR as much as possible to meet the requirements.

@retro98boy
Copy link
Contributor Author

retro98boy commented May 31, 2025

Hey! I don't mind merging this, but please check if any of AI suggested changes are valuable. There is also one merge conflict.

I have submitted a PR to the gxlimg repository about gxlimg incorrectly returning a non-zero value. We can wait for the author of gxlimg to merge it. Then I modified PR again to remove the temporary changes to the gxlimg source code.

There may be errors in gxlimg's handling of bl3x. If I have free time later, I would like to study [angerman/meson64-tools] and try port its bl3x processing code to gxlimg. So this PR can only use amlogic binary only executable for the time being.

@igorpecovnik igorpecovnik added Work in progress Unfinished / work in progress and removed Ready to merge Reviewed, tested and ready for merge labels Jun 3, 2025
@retro98boy retro98boy force-pushed the cainiao-cniot-core branch from 0bd2d87 to 8103f79 Compare June 9, 2025 14:13
@retro98boy retro98boy requested a review from a team as a code owner June 9, 2025 14:13
@github-actions github-actions bot added the BSP Board Support Packages label Jun 9, 2025
@coderabbitai coderabbitai bot added the Ready to merge Reviewed, tested and ready for merge label Jun 9, 2025
@retro98boy
Copy link
Contributor Author

Hey! I don't mind merging this, but please check if any of AI suggested changes are valuable. There is also one merge conflict.

Hi, this PR is ready to be merged. Compared to the last time:

  • FIP packaging now uses pre-extracted blobs.

  • The breathing light on the host's side is now functional, with a user-space demo available here.

  • The internal speaker is now driven and can work alongside HDMI audio without interference.

  • The four contacts on the host's side have been confirmed as USB and are now enabled by default.

@igorpecovnik igorpecovnik merged commit c66fbec into armbian:main Jun 9, 2025
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
05 Milestone: Second quarter release BSP Board Support Packages Hardware Hardware related like kernel, U-Boot, ... Needs review Seeking for review Patches Patches related to kernel, U-Boot, ... Ready to merge Reviewed, tested and ready for merge size/large PR with 250 lines or more Work in progress Unfinished / work in progress
Development

Successfully merging this pull request may close these issues.

3 participants