noc 片上网络

目录

一,NOC理论基础

[1. 多层多通道的互连结构](#1. 多层多通道的互连结构)

[2. 服务质量保证](#2. 服务质量保证)

[3. 专用带宽通道](#3. 专用带宽通道)

[4. 与DDR控制器的紧密耦合](#4. 与DDR控制器的紧密耦合)

二,rk3288的NOC寄存器

1,QoS优先级寄存器组(0x0800-0x08FF)

2,带宽控制寄存器组(0x0900-0x09FF)

3,性能计数器寄存器组(0x0A00-0x0AFF)

4,状态和错误寄存器组(0x0C00-0x0CFF)

三,典型使用场景

[1 .U-Boot初始化配置](#1 .U-Boot初始化配置)

[2. 多媒体场景优化](#2. 多媒体场景优化)

3,寄存器操作封装函数

四,调试和诊断

1.读取总线状态

2.性能监控

五,注意事项


一,NOC理论基础

在传统的SoC设计中,各个IP核(如CPU、GPU、VPU、内存控制器等)通常通过共享总线(如AMBA AXI)进行通信。但随着芯片内模块增多、数据流复杂化,总线容易成为性能瓶颈。

NOC 可以理解为 芯片内部的"高速公路网"或"交换网络"。它将多个并行的数据通道和交换节点集成在片上,允许多个主设备(如CPU、GPU)和从设备(如DDR、外部接口)之间同时进行高速、低延迟的数据传输,极大提升了内部带宽和效率。

1. 多层多通道的互连结构

NOC不是一个单一总线,而是一个分层、分区的交换网络。它通常包含:

  • 多个主端口:连接不同的主设备(CPU簇、GPU、视频处理单元VPU、显示处理器VOP、各种DMA控制器等)。

  • 多个从端口 :主要连接到双通道DDR内存控制器,也连接到一些高速配置总线。

  • 内部的交叉开关:用于路由数据包,允许多个传输同时进行。

2. 服务质量保证

这是NOC最关键的特性。NOC实现了QoS机制

  • 带宽分配:可以为不同的主设备或数据流(如显示输出、视频解码、GPU渲染)设置不同的带宽权重或上限。

  • 优先级控制:高优先级的请求(如显示实时读取帧缓冲)会被优先处理和响应,确保画面不卡顿。

  • 仲裁策略:智能的仲裁器根据配置的QoS规则,决定多个并发请求的响应顺序。

3. 专用带宽通道

对于最关键的子系统使用专用数据通路来绕过公共部分的竞争:

  • 显示路径:从内存到显示控制器(VOP)的读请求具有极高优先级和专用通道,这是保证UI流畅和视频播放不掉帧的基石。

  • 视频编解码路径:VPU与内存之间的数据通道也经过特别优化,保证大块视频码流输入和输出帧的稳定传输。

4. 与DDR控制器的紧密耦合

NOC直接与高效的双通道32位DDR3/LPDDR2/LPDDR3内存控制器对接。NOC负责将内部多路请求,高效地调度并转换为对DDR物理层的访问命令,最大化利用DDR带宽。

二,rk3288的NOC寄存器

|---------------|---------------|------------|-------------|--------------|
| 地址偏移 | 寄存器名称 | 大小 | 复位值 | 功能描述 |
| 0x0000-0x07FF | 保留 | - | - | 保留区域 |
| 0x0800-0x08FF | QoS优先级控制 | 4字节 | 0x00000000 | 主设备优先级设置 |
| 0x0900-0x09FF | 带宽控制 | 4字节 | 0x00000000 | 带宽限制和分配 |
| 0x0A00-0x0AFF | 性能计数器 | 4字节 | 0x00000000 | 监控总线性能 |
| 0x0B00-0x0BFF | 仲裁控制 | 4字节 | 0x00000000 | 仲裁算法配置 |
| 0x0C00-0x0CFF | 状态寄存器 | 4字节 | 0x00000000 | 总线状态和错误 |
| 0x0D00-0x1FFF | 保留 | - | - | 保留区域 |

1,QoS优先级寄存器组(0x0800-0x08FF)

主设备优先级寄存器 (每个主设备32位)

typedef union {

struct {

uint32_t priority : 4; // [3:0] 优先级 (0-15)

uint32_t urgent_level : 4; // [7:4] 紧急级别

uint32_t timeout_val : 8; // [15:8] 超时值

uint32_t reserved : 12; // [27:16] 保留

uint32_t enable : 1; // [28] QoS使能

uint32_t lock : 1; // [29] 配置锁定

uint32_t bypass : 2; // [31:30] 旁路模式

} bits;

uint32_t value;} noc_qos_priority_t;

具体寄存器偏移

|----------------|----------------|------------|-------------|
| 偏移 | 主设备 | 描述 | 建议值 |
| 0x0800 | CPU0 | CPU0读优先级 | 0xF (最高) |
| 0x0804 | CPU1 | CPU1读优先级 | 0xF |
| 0x0808 | CPU2 | CPU2读优先级 | 0xF |
| 0x080C | CPU3 | CPU3读优先级 | 0xF |
| 0x0810 | GPU | GPU读/写优先级 | 0x8-0xC |
| 0x0814 | VCODEC | 视频编解码器优先级 | 0x8-0xA |
| 0x0818 | VOP | 显示控制器优先级 | 0xA-0xD |
| 0x081C | ISP | 图像处理器优先级 | 0x6-0x8 |
| 0x0820 | EDP | eDP接口优先级 | 0x7-0x9 |
| 0x0824 | HDMI | HDMI接口优先级 | 0x7-0x9 |
| 0x0828 | USB | USB控制器优先级 | 0x5-0x7 |
| 0x082C | SDMMC | SD/MMC卡优先级 | 0x4-0x6 |
| 0x0830 | GMAC | 以太网优先级 | 0x5-0x7 |

举例说明

2,带宽控制寄存器组(0x0900-0x09FF)

带宽限制寄存器格式

typedef union {

struct {

uint32_t bandwidth_limit : 10; // [9:0] 带宽限制值 (单位: 16MB/s)

uint32_t burst_limit : 6; // [15:10] 突发限制

uint32_t reserved1 : 8; // [23:16] 保留

uint32_t window_size : 4; // [27:24] 监控窗口大小

uint32_t reserved2 : 3; // [30:28] 保留

uint32_t enable : 1; // [31] 使能位

} bits;

uint32_t value;} noc_bandwidth_ctrl_t;

带宽分配寄存器

|----------------|-------------------------|--------------|
| 偏移 | 寄存器名称 | 功能描述 |
| 0x0900 | BW_LIMIT_CPU | CPU带宽限制 |
| 0x0904 | BW_LIMIT_GPU | GPU带宽限制 |
| 0x0908 | BW_LIMIT_VCODEC | 视频编解码器带宽 |
| 0x090C | BW_LIMIT_VOP | 显示控制器带宽 |
| 0x0910 | BW_LIMIT_ISP | ISP带宽限制 |
| 0x0914 | BW_LIMIT_USB | USB带宽限制 |
| 0x0918 | BW_LIMIT_SDMMC | SD/MMC带宽限制 |
| 0x091C | BW_LIMIT_DDR | DDR访问总带宽限制 |

计算示例

// 设置GPU带宽为800MB/s

// 800MB/s ÷ 16MB/s/单位 = 50 (0x32)

uint32_t gpu_bw = (50 & 0x3FF) | (1 << 31); // 使能带宽限制

writel(gpu_bw, NOC_BASE + 0x0904);

3,性能计数器寄存器组(0x0A00-0x0AFF)

性能监控寄存器

|----------------|---------------------|--------------|
| 偏移 | 寄存器名称 | 功能描述 |
| 0x0A00 | PERF_CTRL | 性能计数器控制 |
| 0x0A04 | PERF_EVENT_SEL | 事件选择 |
| 0x0A08 | PERF_COUNT0 | 计数器0值 |
| 0x0A0C | PERF_COUNT1 | 计数器1值 |
| 0x0A10 | PERF_COUNT2 | 计数器2值 |
| 0x0A14 | PERF_COUNT3 | 计数器3值 |
| 0x0A18 | PERF_LATENCY_MIN | 最小延迟 |
| 0x0A1C | PERF_LATENCY_MAX | 最大延迟 |
| 0x0A20 | PERF_LATENCY_AVG | 平均延迟 |

性能计数器控制寄存器

// PERF_CTRL (0x0A00)

#define PERF_ENABLE (1 << 0) // 使能所有计数器

#define PERF_RESET (1 << 1) // 复位所有计数器

#define PERF_INTERRUPT_EN (1 << 2) // 中断使能

#define PERF_WINDOW_MASK 0xFFFF0000 // 监控窗口掩码

// 支持监控的事件类型

enum noc_perf_event {

PERF_EVENT_READ_BYTES = 0x01, // 读取字节数

PERF_EVENT_WRITE_BYTES = 0x02, // 写入字节数

PERF_EVENT_READ_OPS = 0x03, // 读操作次数

PERF_EVENT_WRITE_OPS = 0x04, // 写操作次数

PERF_EVENT_LATENCY = 0x05, // 延迟

PERF_EVENT_CONGESTION = 0x06, // 拥塞周期

PERF_EVENT_TIMEOUT = 0x07, // 超时次数 };

4,仲裁控制寄存器组(0x0B00-0x0BFF)

|----------------|-------------------|--------------|
| 偏移 | 寄存器名称 | 功能描述 |
| 0x0B00 | ARB_CTRL | 仲裁器控制 |
| 0x0B04 | ARB_WEIGHT_CPU | CPU权重设置 |
| 0x0B08 | ARB_WEIGHT_GPU | GPU权重设置 |
| 0x0B0C | ARB_WEIGHT_VCODEC | 视频编解码器权重 |
| 0x0B10 | ARB_WEIGHT_VOP | 显示控制器权重 |
| 0x0B14 | ARB_ALGORITHM | 仲裁算法选择 |

仲裁算法配置

// ARB_CTRL (0x0B00)

#define ARB_ENABLE (1 << 0) // 仲裁器使能

#define ARB_MODE_MASK (3 << 1) // 仲裁模式

#define ARB_MODE_FIXED (0 << 1) // 固定优先级

#define ARB_MODE_ROUND_ROBIN (1 << 1) // 轮询

#define ARB_MODE_WEIGHTED (2 << 1) // 权重轮询

#define ARB_MODE_ADAPTIVE (3 << 1) // 自适应

#define ARB_LOCK (1 << 3) // 配置锁定

权重寄存器格式

typedef union {

struct {

uint32_t read_weight : 8; // [7:0] 读操作权重

uint32_t write_weight : 8; // [15:8] 写操作权重

uint32_t reserved : 16; // [31:16] 保留

} bits;

uint32_t value;} noc_arb_weight_t;

4,状态和错误寄存器组(0x0C00-0x0CFF)

|----------------|-------------------|--------------|
| 偏移 | 寄存器名称 | 功能描述 |
| 0x0C00 | STATUS | 总体状态 |
| 0x0C04 | ERROR_STATUS | 错误状态 |
| 0x0C08 | TIMEOUT_COUNTER | 超时计数器 |
| 0x0C0C | CONGESTION_STATUS | 拥塞状态 |
| 0x0C10 | BUS_UTILIZATION | 总线利用率 |
| 0x0C14 | SLICE_ACTIVE | 激活的主设备 |
| 0x0C18 | LATENCY_STATUS | 当前延迟 |
| 0x0C1C | DEBUG_INFO | 调试信息 |

状态寄存器位定义

// STATUS (0x0C00)

#define STAT_BUS_BUSY (1 << 0) // 总线忙

#define STAT_CONGESTED (1 << 1) // 总线拥塞

#define STAT_TIMEOUT_OCCUR (1 << 2) // 发生超时

#define STAT_ERROR_OCCUR (1 << 3) // 发生错误

#define STAT_QOS_ACTIVE (1 << 4) // QoS激活

#define STAT_ARB_ACTIVE (1 << 5) // 仲裁器激活

#define STAT_PERF_ACTIVE (1 << 6) // 性能监控激活

错误状态寄存器

// ERROR_STATUS (0x0C04)

#define ERR_ILLEGAL_ADDR (1 << 0) // 非法地址访问

#define ERR_SECURITY_VIOL (1 << 1) // 安全违规

#define ERR_PROTOCOL (1 << 2) // 协议错误

#define ERR_DATA_PARITY (1 << 3) // 数据奇偶校验错

#define ERR_ADDR_PARITY (1 << 4) // 地址奇偶校验错

#define ERR_TIMEOUT (1 << 5) // 访问超时

#define ERR_SLAVE_BUSY (1 << 6) // 从设备忙

#define ERR_MASTER_ABORT (1 << 7) // 主设备中止

举例说明:

三,典型使用场景

1 .U-Boot初始化配置

void rk3288_noc_init(void){

volatile uint32_t *noc_base = (uint32_t *)0xFFAC0000;

/* 1. 设置CPU最高优先级 */

noc_base[0x0800/4] = 0xF000000F; // CPU0

noc_base[0x0804/4] = 0xF000000F; // CPU1

noc_base[0x0808/4] = 0xF000000F; // CPU2

noc_base[0x080C/4] = 0xF000000F; // CPU3

/* 2. 设置GPU优先级和带宽 */

// 优先级: 0xB, 带宽: 400MB/s

noc_base[0x0810/4] = 0xB000000B; // GPU优先级

noc_base[0x0904/4] = (25 << 0) | (1 << 31); // 带宽限制

/* 3. 设置视频编解码器 */

noc_base[0x0814/4] = 0xA000000A; // VCODEC优先级

noc_base[0x0908/4] = (50 << 0) | (1 << 31); // 800MB/s

/* 4. 设置显示控制器 */

noc_base[0x0818/4] = 0xC000000C; // VOP优先级

noc_base[0x090C/4] = (63 << 0) | (1 << 31); // 1GB/s

/* 5. 配置仲裁器 */

noc_base[0x0B00/4] = ARB_ENABLE | ARB_MODE_WEIGHTED;

noc_base[0x0B04/4] = 0x20202020; // CPU权重

noc_base[0x0B08/4] = 0x10101010; // GPU权重

/* 6. 总带宽限制 */

noc_base[0x091C/4] = (400 << 0) | (1 << 31); // 6.4GB/s总限

/* 7. 启用性能监控 */

noc_base[0x0A00/4] = PERF_ENABLE | (0x1000 << 16); // 窗口大小 }

2. 多媒体场景优化

void setup_noc_for_4k_video_playback(void){

uint32_t *noc = (uint32_t *)0xFFAC0000;

/* 视频播放时GPU和VCODEC需要高带宽 */

// GPU: 优先级12,带宽600MB/s

noc[0x0810/4] = 0xC000000C;

noc[0x0904/4] = (37 << 0) | (1 << 31);

// VCODEC: 优先级13,带宽800MB/s

noc[0x0814/4] = 0xD000000D;

noc[0x0908/4] = (50 << 0) | (1 << 31);

// VOP: 优先级14,带宽400MB/s

noc[0x0818/4] = 0xE000000E;

noc[0x090C/4] = (25 << 0) | (1 << 31);

// 降低其他设备优先级

noc[0x0820/4] = 0x50000005; // USB降为5

noc[0x0824/4] = 0x40000004; // SDMMC降为4 }

3,寄存器操作封装函数

void noc_set_priority(uint32_t master_id, uint32_t priority) {

uint32_t reg = 0x0800 + (master_id * 4);

uint32_t val = (priority & 0xF) | (0xF0000000) | (1 << 28);

writel(val, NOC_BASE + reg);}

void noc_set_bandwidth(uint32_t master_id, uint32_t mbps) {

uint32_t reg = 0x0900 + (master_id * 4);

uint32_t val = ((mbps / 16) & 0x3FF) | (1 << 31);

writel(val, NOC_BASE + reg);}

uint32_t noc_get_utilization(void) {

return readl(NOC_BASE + 0x0C10) & 0xFF;}

四,调试和诊断

1.读取总线状态

uint32_t get_noc_status(void){

uint32_t *noc = (uint32_t *)0xFFAC0000;

uint32_t status = noc[0x0C00/4];

uint32_t errors = noc[0x0C04/4];

uint32_t utilization = noc[0x0C10/4];

printf("NOC Status: 0x%08X\n", status);

printf("Errors: 0x%08X\n", errors);

printf("Utilization: %d%%\n", (utilization & 0xFF));

return status;}

2.性能监控

void monitor_noc_performance(void){

uint32_t *noc = (uint32_t *)0xFFAC0000;

// 选择监控事件:读取字节数

noc[0x0A04/4] = PERF_EVENT_READ_BYTES;

// 启动监控

noc[0x0A00/4] = PERF_ENABLE;

// 延时一段时间

udelay(1000000); // 1秒

// 读取计数器值

uint32_t read_bytes = noc[0x0A08/4];

printf("Read bandwidth: %u MB/s\n", read_bytes / (1024*1024));}

五,注意事项

配置顺序 :先配置优先级,再配置带宽,最后启用仲裁器

时钟要求 :NOC模块需要PCLK和ACLK时钟

复位影响 :软复位不会清除NOC寄存器,需要手动复位

性能影响 :不正确的QoS配置可能导致系统性能下降

安全限制 :某些安全区域配置需要TrustZone权限

相关推荐
日更嵌入式的打工仔3 小时前
RS-485通讯协议
笔记·嵌入式硬件
蓝桥_吹雪3 小时前
HAL库深入了解--STM32与GPIO
单片机·嵌入式硬件
不能跑的代码不是好代码3 小时前
STM32:LED共阴/共阳连接与GPIO控制逻辑的关系,如何实现电平转换
stm32·单片机·嵌入式硬件
持续学习的程序员+14 小时前
强化学习Actor/Learner框架介绍(lerobot版)
arm开发
颜子鱼4 小时前
Linux驱动-INPUT子系统
linux·c语言·驱动开发
Lueeee.4 小时前
llseek 定位设备驱动实验
linux·驱动开发
Jason_zhao_MR4 小时前
YOLO5目标检测方案-基于米尔RK3576开发板
linux·人工智能·嵌入式硬件·目标检测·计算机视觉·目标跟踪·嵌入式
小小程序媛(*^▽^*)4 小时前
Claude Code 新手保姆级安装与使用指南 (ZCF 版)
linux·编辑器·vim
鱼香rose__5 小时前
管道、环境变量与常用命令
linux