Skip to content
View in the app

A better way to browse. Learn more.

Armbian Community Forums

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

ODROID-M1 NPU fully working on Armbian 6.18.x

Featured Replies

Hello Armbian-Community!

 

TL;DR

 

I've successfully enabled the Rockchip RK3568 NPU (0.8 TOPS INT8) on the ODROID-M1 with 8GB RAM running Armbian 6.18.9-current-rockchip64.

 

The only thing needed to make this work for everyone is a 1-line kernel patch in Armbian build that I've already submitted: https://github.com/armbian/build/pull/9403

 

Once this patch is merged into Armbian, the DKMS modules will work out-of-the-box on all RK3568 boards.

 

The Problem

 

1. Hardkernel and Rockchip provide NPU patches for quite old kernel versions:

  • rockchip <= 6.6
  • hardkernel <= 5.10

 

2. IOMMU page table allocation bug — On systems with >4GB RAM, the kernel's IOMMU allocates page tables above 4GB, but the NPU can only access the first 4GB of physical memory, causing DMA mapping failures and inference timeouts

 

The Solution

 

1. Kernel Patch (1 line!)

 

-   .gfp_flags = 0,
+   .gfp_flags = GFP_DMA32,

 

This forces IOMMU page tables to be allocated below 4GB, fixing NPU operation on 8GB boards.

 

2. DKMS Driver Package

 

I've created a complete DKMS package that:

- Includes DT overlays for NPU, IOMMU, power-domain, and clock configuration

- Supports dynamic frequency scaling (100 MHz - 1000 MHz)

- Provides `/dev/dri/renderD129` (DRM/GEM interface) for RKNN Runtime

- Would compile against Armbian's stock kernel headers with the above patch merged

 

The Questions

 

1. What would be the best way to provide those modules for installation in the armbian system?

2. Has someone a 4 GB version of the M1 and could test the modules?

 

Edited by m1zfs

Hello,
 

I believe @m1zfs's work on the DKMS modules is available here:

https://github.com/vitalijborissow/rk3568-npu-ODROID-M1

 

I have spent many hours trying to get the NPU working on my ODROID-M1 (8 GB) running Armbian 26.5.1 with current kernel 6.18.x as well as edge kernels 6.19 and 7.1. I also tried building the latest Armbian image from source (July 19 build including U-Boot 2026.07), but so far I have not been able to get the device tree / overlay and DKMS modules from the repository working on any of these combinations.

 

The system always fails to boot. Fortunately, I can capture the boot process through the serial console and see where it fails.

The log shows a kernel exception related to enabling the RK3568 NPU power domain:

 

rockchip-pm-domain fdd90000.power-management:power-controller:
failed to get ack on domain 'npu', val=0x1ee

platform fde40000.npu: Adding to iommu group 3

Internal error: synchronous external abort
...
Workqueue: pm genpd_power_off_work_fn
...
rockchip_pd_power

 

From the log it appears that the crash occurs before rknpu.ko is loaded. This makes me believe the issue is more likely related to the device tree, overlay, power-domain, regulator, or clock configuration rather than to the DKMS module itself.

 

Has anyone seen a similar issue on recent Armbian kernels, or can suggest a direction for further troubleshooting? I am still willing to spend some time investigating this and would appreciate any ideas or hints.

 

 

Hi,


Finally, I made some good progress.

I updated the DTS by starting with the DTS from Armbian 26.5.1 for current 6.18.x kernels and then merged the missing NPU and Power Domain nodes from the original DTS provided by @m1zfs.
 

While comparing the original DTS with the current Armbian DTS, I also found that one of the phandle references in the NPU power-domain definition needed to be adjusted to match the phandle numbering used in the current Armbian DTS. After fixing that, the system booted successfully and the NPU was detected correctly.

I'm now testing it with rknn_toolkit2 to verify that the NPU is fully functional.

 

root@odroidtest:~# uname -a
Linux odroidtest 6.18.35-current-rockchip64 #2 SMP PREEMPT Tue Jun  9 10:28:53 UTC 2026 aarch64 GNU/Linux
root@odroidtest:~# 
root@odroidtest:~# lsmod | grep -E '^(rknpu|dma32_heap)\b'
rknpu                  94208  0
dma32_heap             12288  0
root@odroidtest:~# 
root@odroidtest:~# ls -l /dev/rknpu /dev/dri/by-path/platform-fde40000.npu-render /dev/dma_heap/system /dev/dma_heap/dma32
crw------- 1 root root 251,   3 Jul 25 21:19 /dev/dma_heap/dma32
lrwxrwxrwx 1 root root       19 Jul 25 21:19 /dev/dma_heap/system -> /dev/dma_heap/dma32
lrwxrwxrwx 1 root root       13 Jul 25 21:19 /dev/dri/by-path/platform-fde40000.npu-render -> ../renderD128
crw------- 1 root root  10, 261 Jul 25 21:19 /dev/rknpu
root@odroidtest:~# 
root@odroidtest:~# dmesg | grep -i rknpu
[    6.108962] [drm] Initialized rknpu 0.9.8 for fde40000.npu on minor 1
[    6.110169] RKNPU fde40000.npu: RKNPU: DKMS: /dev/rknpu registered (DMA-BUF import only)
[    6.132583] RKNPU fde40000.npu: RKNPU: SCMI clock 198 MHz
[    6.133433] RKNPU fde40000.npu: RKNPU: devfreq active (SCMI-only, OPP 200-1000 MHz)
[    6.134599] RKNPU fde40000.npu: RKNPU: thermal throttling enabled
[    6.139965] RKNPU fde40000.npu: RKNPU: sram region: [0x00000000fdcc0000, 0x00000000fdccb000), sram size: 0xb000
root@odroidtest:~# 

 

Hi,
 

As I mentioned earlier, after updating the DTS I was able to get the driver loaded and the NPU detected. I then started testing it using rknn-toolkit2 and a model from rknn_model_zoo.

 

The RKNN runtime was able to load and inspect the model successfully, but the first NPU job submission failed:

 

./rknn_yolov5_demo model/yolov5s_relu.rknn model/bus.jpg
 
...
 
rknn_run
 
E RKNN: failed to submit, op id: 1,
op name: Conv:/model.0/convsp/Conv
 
...
 
rknn_run fail! ret=-1
init_yolov5_model fail! ret=-1

 

After a lot of testing and troubleshooting, I found that the failure appears to be related to the NPU IOMMU path.

 

After disabling the NPU IOMMU in the DTS:

 

iommu@fde4b000 {
	...
	status = "disabled";
	...
};

 

the NPU started working correctly. The demo completed successfully and produced valid object detection results:
 

(base) fero@odroidtest:~/rk356x_linux_aarch64/rknn_yolov5_demo$ ./rknn_yolov5_demo model/yolov5s_relu.rknn model/bus.jpg
load lable ./model/coco_80_labels_list.txt
model input num: 1, output num: 3
input tensors:
  index=0, name=images, n_dims=4, dims=[1, 640, 640, 3], n_elems=1228800, size=1228800, fmt=NHWC, type=INT8, qnt_type=AFFINE, zp=-128, scale=0.003922
output tensors:
  index=0, name=output0, n_dims=4, dims=[1, 255, 80, 80], n_elems=1632000, size=1632000, fmt=NCHW, type=INT8, qnt_type=AFFINE, zp=-128, scale=0.003922
  index=1, name=286, n_dims=4, dims=[1, 255, 40, 40], n_elems=408000, size=408000, fmt=NCHW, type=INT8, qnt_type=AFFINE, zp=-128, scale=0.003922
  index=2, name=288, n_dims=4, dims=[1, 255, 20, 20], n_elems=102000, size=102000, fmt=NCHW, type=INT8, qnt_type=AFFINE, zp=-128, scale=0.003922
model is NHWC input fmt
model input height=640, width=640, channel=3
origin size=640x640 crop size=640x640
input image: 640 x 640, subsampling: 4:2:0, colorspace: YCbCr, orientation: 1
scale=1.000000 dst_box=(0 0 639 639) allow_slight_change=1 _left_offset=0 _top_offset=0 padding_w=0 padding_h=0
convert image use cpu
finish
rknn_run
person @ (209 243 286 510) 0.880
person @ (479 238 560 526) 0.871
person @ (109 238 231 534) 0.840
bus @ (91 129 555 464) 0.692
person @ (79 353 121 517) 0.301
write_image path: out.png width=640 height=640 channel=3 data=0x3d269000

 

The remaining issue is understanding why inference fails when the NPU IOMMU is enabled. Nevertheless, the NPU now appears to be fully usable in non-IOMMU mode. I will continue testing with additional RKNN models and workloads while investigating the underlying IOMMU problem.

Update:
 
I found that the original IOMMU patch (see 1st post) - Armbian PR #9403  was incomplete for my case!

 

I created an updated IOMMU patch based on the original upstream discussion. The important difference is that iommu_data_ops_v2 is forced back to 32-bit DMA addressing and GFP_DMA32 allocations:

 

- .dma_bit_mask = DMA_BIT_MASK(40),
- .gfp_flags = 0,
+ .dma_bit_mask = DMA_BIT_MASK(32),
+ .gfp_flags = GFP_DMA32,

 

After rebuilding the kernel with this updated patch, the NPU now works correctly with the IOMMU enabled.

 

root@odroidtest:~# dmesg | grep -i iommu
[    0.147669] iommu: Default domain type: Translated
[    0.147794] iommu: DMA domain TLB invalidation policy: strict mode
[    2.495423] platform fde40000.npu: Adding to iommu group 0
[    2.498138] platform fdea0000.video-codec: Adding to iommu group 1
[    2.500670] platform fdee0000.video-codec: Adding to iommu group 2
[    2.503131] platform fe040000.vop: Adding to iommu group 3
root@odroidtest:~# 
root@odroidtest:~# dmesg | grep -i rkn
[    6.142497] [drm] Initialized rknpu 0.9.8 for fde40000.npu on minor 1
[    6.143858] RKNPU fde40000.npu: RKNPU: DKMS: /dev/rknpu registered (DMA-BUF import only)
[    6.160736] RKNPU fde40000.npu: RKNPU: SCMI clock 198 MHz
[    6.169001] RKNPU fde40000.npu: RKNPU: devfreq active (SCMI-only, OPP 200-1000 MHz)
[    6.180806] RKNPU fde40000.npu: RKNPU: thermal throttling enabled
[    6.188054] RKNPU fde40000.npu: RKNPU: sram region: [0x00000000fdcc0000, 0x00000000fdccb000), sram size: 0xb000



 

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

Account

Navigation

Search

Search

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.