Andes D1088 在汽车ADAS之应用

沈智明,资深经理,晶心科技股份有限公司

先进驾驶辅助系统(Advanced Driver Assistance Systems;ADAS)为现今 IT 产业发展之重要方向,是将来可以达到无人驾驶智慧车辆的技术进阶过程。ADAS 的主要功能并不是控制汽车,而是为驾驶人提供车内的工作情况与车外环境变化等相关信息进行分析,提供预先警告可能的危险状况,让驾驶人提早采取因应措施,避免交通意外发生。晶心科技的产品 D1088 具数字信号处理器(digital signal processor,DSP)指令,除了一般 CPU 指令外还多了 SIMD instructions 来加速ADAS 系统的演算,增加 ADAS 产品之性能,也因此获得客户的认同使用晶心科技 D1088 开发 ADAS 产品。使用 D1088 开发的 ADAS 产品包括盲点侦测(Blind-Spot Detection, BSD),前车碰撞警示(Forward-Collision Warning, FCW),车道偏移警示(Lane-Departure Warning, LDW),移动物侦测(Motion-Object Detection, MOD),倒车碰撞警示(Rear-Collision Warning, RCW),行人碰撞警示(Pedestrian-Collision Warning, PCW)及行车纪录器。

车 用 电 子 须 通 过 AEC-Q100(Automotive Electronics Council – Failure Mechanism Based Stress Test Qualification For Integrated Circuits)的认证,要求有别于一般消费性电子产品,本文之目的除了告诉我们的客户(IC设计业者)D1088的优势,也与我们的客户一起探讨车用电子与消费性电子产品间差异。希望在车用电子领域,晶心科技与我们的客户携手同行从今日开发ADAS芯片到未来的无人车自动驾驶。

1. D1088 应用于 ADAS 的优势
生活环境中都是模拟讯号,声音是模拟讯号,影像是模拟讯号,汽车碰撞的压力值还是模拟讯号,汽车在行进中,感知器将量测数值传送进 ADAS 控制器,经过 ADC 转换后得到数字讯号﹐车内外环境中充满了干扰与噪声,滤波器可以滤掉噪声与干扰,大大提升讯号正确性与可靠度,还原事物的原貌。文中以数字滤波器 FIR (Finite Impulse Response)为例,比较使用一般 CPU 指令与D1088 提供的 DSP 指令在实践 FIR 时的差异,说明 D1088 的优势与特性。

1.1 使用Fir_q15 函数验证
以 ADAS 中车道偏移警示系统会用到的 FIR 数字滤波器,使用 Fir_q15[1]
函数 C 语言实作如下所示:
     void nds32_fir_q15(const nds32_fir_q15_t *instance,q15_t *src, q15_t *dst, uint32_t size)

  此 FIR 数字滤波器函数,其中函数的自变量:*instance 此是指向 FIR 结构的指针,数字滤波器参数特性定义在此。输入*src 与输出*dst 是以 Q15 的数据格式来呈现,size 是此函数一次处理的取样数目,本实验的取样数目是 1024。
  在使用此函数时,设计两种定义,一种是全部使用 Andes baseline 指令, 另一种使用 DSP 指令,D1088 除了具备一般 CPU 功能外,增加超过 130 DSP 相关指令。在此函数中除了运用 DSP Q 指令外也使用了DSP 中的saturation 运算, 当数字讯号运算后产生 overflow 或 underflow 时,没有使用 saturation 运算会产生错误且离谱的结果,Andes saturation 指令可以大大提升效能。
  在 Fir_q15 函数在 D1088 上做验证函数的取样数目为 1024,在全部使用baseline 指令运算所得的 cycle 数除以取样数目 1024 得到每一笔 DSP 讯号所需要的 cycle 数是 210,如果使用 DSP 指令,处理每一笔 DSP 指令只需要的是 41 cycles。从 Fir_q15 函数运算结果得知 DSP 指令对比 baseline 指令运算效能提升5.12 倍。

1.2 DSP Benchmark 数值
下图[2]是依各类测试群组得到 D1088 与 Baseline CPU 的 benchmark 数据,总体 benchmark 的平均值 D1088/N1068 有 64%的性能提升:

图 1. DSP Library 效能图

2. 车用电子产品需要通过之认证
  近几年随着汽车市场逐步走向车联网、电动车领域,需要更多驾驶信息辅助整合系统,也让IC设计业者找到一个好的发展方向与新的产品市场。很明显, 车用电子要求有别于一般消费性产品,分别在产品的寿命,温度的范围,可靠度等级与安全性的要求等皆远高于消费性电子产品,车用电子需要经过ISO 26262 与AEC-Q100认证。晶心科技是CPU IP 的供货商,提供CPU IP给IC设计业者。从AEC-Q100的验证流程中,了解IC设计业在车用电子所在的角色,也可以得知CPU与IC设计业者在车用电子中的位置与关系。

2.1 车用IC规范AEC-Q100验证流程
  图2为AEC-Q100规范中的验证流程[3],此图是以Die Design→Wafer Fab.→ PKG Assembly→Testing的制造流程来绘制,各群组的关联性须要参考图中的箭头符号,本文重点着重在IC设计业者(Design House),所以仅标示AEC-Q100中Design House与 Design Verification 相关测试项目。

图 2. AEC-Q100 验证流程

2.2 IC设计业者进行AEC-Q100验证
  在AEC-Q100建议中,IC设计业者需要依据IC芯片在汽车中使用位置区分为引擎区与乘坐区两部份,其基本工作环境要求不同,故对于测试温度,可靠度, 安全性的建议规格也不同。由于IC芯片种类繁多,因此在试验条件上,AEC-Q100 已进行分门别类,亦即依照属性设定建议的试验条件,当IC芯片设计测试规范订定后依据图2 AEC-Q100验证流程图,IC设计业者需完成红框的验证项目,当Wafer Foundry也通过需做测项后,AEC-Q100验证项目皆完成后,就可说此IC芯片完成AEC-Q100的验证。

3. 车用电子产品需要通过之认证
  除了 ADAS 本身须具备之功能与通过 AEC-Q100 认证外,也需有额外设计才能符合在汽车的应用环境下的需求,下列几个实例说明在车用 ADAS 中增加的设计,有别于一般消费性电子产品。

3.1 CRC checksum 安全验证
  在车用 ADAS 设计实例中,考虑到汽车环境中干扰严重且需要高可靠度。ADAS 程序在刻录进 ADAS 产品的 NOR-Flash 时, 将欲刻录程序经由CRC32-CCIR 演算后得到 32bits 结果一并写在 NOR-Flash 上。在车上当 ADAS 产品开机后,NOR-Flash 上的程序搬到 RAM 后,在 RAM 的程序也一样经过CRC32-CCIR 演算后得到的结果与程序后面 32bit checksum 演算结果做比对,如果 RAM 端与 NOR-Flash 数值一致表示通过 CRC checksum 安全验证,如果数值不一致代表 RAM 上的程序在过程中被干扰须采取对应的措施。增加 CRC checksum 安全验证可以知道车用 ADAS 对安全与可靠度要求远高于一般消费性电子产品。

3.2 程序启动前先行验证 CPU 周边
  有别于一般消费性产品,车用电子产品在程序启动前需验证 CPU 周边device 本身之正确性,以 ADAS 实例来说明需要验证 cache 与 RAM。在 ADAS 程序执行前,提供晶心科技自定义指令集 CCTL (Cache Control)指令做 cache 的验证。将 CCTL 指令以 intrinsic 函数方式(如下所示)[4]提供给客户使用:

Unsigned   int   __nds32 cctlidx_read     (const   enum   nds32_cctl_idxread subtype, unsigned int idx)
void __nds32 cctlidx_write (const enum nds32_cctl_idxwrite subtype, unsigned int b, unsigned int idxw)

  开发 ADAS 客户使用晶心科技提供 nds32 cctlidx_write 函数写入 再用 _nds32 cctlidx_read 函數讀出來驗證整個 cache device。
  RAM 在使用前也需要做 RAM device 的验证,进行 RAM device 验证需要验证程序结合 RAM 测试 pattern。晶心科技使用程序编写的技巧提供 ADAS 开发业者不需要用到RAM 的验证程序结合ADAS 开发业者使用March C Algorithm 做为的 RAM device 的验证 pattern。

  在 ADAS 开机时使用 March C Algorithm 来做 RAM 的 BIST 好处是快速, 产品开机时所需的等待时间对于车用产品极为重要,也是车用产品优劣的重要评判准则,March C Algorithm 除了简单快速外,还有 fault coverage 高的特性。受到广泛的应用,将 March C Algorithm 的 pseudo code 详列如下[5]:

//for writing 0s in block 1 and writing 1s in block 2, let n and m are rows and columns for(i=0;i<(n-1)/2;i=i+1)
          begin
               for(j=0;j<(m-1);j=j+1)
                    mem[i][j]=0; //write 0 in m1
          end
   for(i=(n-1)/2;i<(n-1);i=i+1)
          begin
                  for(j=0;j<(m-1);j=j+1)
                            mem[i][j]=1; //write 1 in m2
          end
//for reading background and for writing alternate
                  for(i=0;i<(n-1)/2;i=i+1)
                           begin
                                  for(j=0;j<(m-1);j=j+1)
                                          begin
                                                  if(mem[i][j]==0)
                                                           mem[i][j]=1;
                                                  else return;
                                          end
                            end
for(i=(n-1)/2;i<(n-1);i=i+1)
         begin
                for(j=0;j<(m-1);j=j+1) 
                          begin
                                  if(mem[i][j]==1)
                                          mem[i][j]=0;
                                  else return;
                           end
          end

4. 结语
  D1088 具 DSP 指令适合应用在于先进驾驶辅助系统。晶心科技提供高效能符合车用的 CPU 给 IC 设计业者,在 IC 设计业者开发车用 ADAS 产品时,晶心科技提供适当的支持协助 IC 设计业者开发具竞争力且符合车规之 ADAS 芯片与系统,衷心感谢伟诠公司顾朝奇博士与陈文庆先生的协助,才能完成此技术文章。
  电子产业各项领域中,不论是 MCU,触控周边,IoT 与本文探讨之车用 ADAS, 晶心科技皆已取得不错的成效,也期望在未来趋势 ADAS 与车联网产业中晶心科技与我们的客户 IC 设计业者紧密的合作,开发出具竞争力的芯片与系统,达到双赢的目的。

参考文件
[1] Andes Fir_q15 Program “nds32_fir_q15.c”
[2] Andes Company Profile July 2016 page 28
[3] 新通讯 2016 年 4 月号 182 期《 技术前瞻 》
[4] Andes Programming Guide for ISA-V3 page 104
[5] Muddapu Parvathi , N. Vasantha, K. Satya Parasad, “Modified March C – Algorithm for Embedded Memory Testing” International Journal of Electrical and Computer Engineering (IJECE) Vol. 2, No.5, October 2012, pp. 571~576 ISSN: 2088-8708

Continue ReadingAndes D1088 在汽车ADAS之应用

在晶心平台运行具OSC的FreeRTOS

沈智明,资深经理,晶心科技股份有限公司

  晶心科技所设计 IP 的目的,是满足客户实际需求,提供低成本高效率的产品给客户,让客户可以做出极具竞争力的SoC,达到客户与晶心科技双赢的目的, 本文介绍的具 OSC 的 FreeRTOS 产品,巧妙的与 AndesCore™结合,客户导入产品后,具竞争力与实用性,本文的目的期望能够让更多的读者清楚这个产品的特性与优势进而使用此产品。

  某些电子产品的应用是不同的时间需要运行不同的功能,这时需要大空间的ROM 与 RAM 来存放与运行时会用到的各式各样的功能。因为 CPU 同时间只会运行一种功能。所以在务实与经济的考虑下可以使用 overlay 的方式来满足此类型产品的需求, 不但大幅降低 RAM 空间的使用,也达成硬件成本降低,使得产品竞争力大大的提升。达成 overlay 的方式有两种,纯软件 overlay 与硬件加速 overlay。纯软件的 overlay 不须增加硬件,但软件工程师写程序时需自己配置functions 摆放的位置,容易出错;呼叫 functions 时需要经过额外的处理,降低程序效能。因此纯软件的方法多用于只需偶而更换 overlay 的应用。例如 audio player,一条歌播完下一条开始前才需要检查是否要用不同 decoder。我们有另一篇文章针对软件 overlay 做介绍,本文不多加探讨。

  硬件加速的 overlay 使用少许硬件 gate count < 2K (OSC, Overlay SRAM Controller),提供软件透明的 overlay 处理。软件工程师写程序时,可以假设有一个很大的连续程序空间,完全不需配置 functions 摆放的位置,这大大增加开发程序的效率;同时,呼叫 functions 时完全没有任何纯软件方式的 overhead。上述之 OSC 优点可以符合客户之需求,如果客户系统复杂,要做的事比较多,需要用到多任务(Multi-tasking),则晶心科技「支持 OSC 的 FreeRTOS 产品」就是最佳解方案。

1. Andes OSC 工作原理
  先设定AndesCore™ NCEOSC100 IP中缓存器,再与运行软件做整合搭配, 即可执行OSC的功能。

1.1 设定 OSC IP 的缓存器与动作解说
  • OSC Control Register, OSCCTRL (+0x00)
             • OVL_SZ: 3’h4 (16KB) RO/WI
             • OVL_VALID: 0
  • Fixed Region Size Register, OVLFS (+0x04)
             • OVL_FSZ: 8’h18 (96KB)            RW
  • Overlay Region Base Register, OVLBASE (+0x08)
  • Overlay Region End Register, OVLEND (+0x0C)

  在OSC设计中SRAM分为两个区域一个是”fixed region” 另一个是 “overlay region”,fixed region 为低地址的 SRAM ,其大小由OVLFS 缓存器设定。overlay region 是一个动态的区域,其地址由OVLBASE缓存器设定,大小由OVL_SZ 设定。当CPU运行时存取地址落在缓存器 OVLBASE与OVLEND之间时OSC将自动转址到SRAM的overlay region内,如图1所示。
  因应实际需求设定多个Overlay 区域,当发生 ”Overlay Miss” 时,经由Overlay Exception的机制与软件的搭配,可以将storage 中的 overlay page N 复制到 SRAM 中的Overlay Region,如图1所示。关于overlay page 置换的工作原理将于下两个章节中做说明。

图 1. Overlay 范例说明

  CPU运行时存取地址不在fixed region 或是当时有效的 overlay page 时,会发生Overlay Miss。当o Miss 发生时OSC会产生illegal instruction (32’hcoddcodd) 造成general exception。因为也有其他原因也会产生general exception,如何区分出overlay miss 与其他general exception于下个章节说明。

1.2 Overlay Exception 侦测
   当进入 general exception 时可透过软件检验下列程序来判断是否为overlay miss:
  Step 1 如果 interrupt level 已经到达最大值 (PSW.INTL == Max INTL) ,这是 fetal error 不是overlay miss。
  Step 2 必须是ITYPE.EYPE==1,才有机会是overlay miss。
  Step 3 检查IPC值,如果是落在fixed region 或是当时有效的 overlay page 时这是真正的 illegal exception case. 如果不是在这两个区域则是overlay miss。

  经过前面3步骤验证,如果确定是overlay miss ,则可进行Overlay exception handling 的动作。

1.3 执行 Overlay Exception Handling 的动作
  确定 overlay miss 后,做更新overlay region的动作。
  Step 1 得到新的overlay region 地址:
              – 从IPC得到更新overlay page的起始位置。
              – 更新OVLBASE 缓存器。
  Step 2 更新的overlay page内容复制到 SRAM 中的overlay region
  Step 3 最后执行iret返回overlay miss发生时的地址。

2. 具 OSC 的 FreeRTOS 介绍
 Andes 结合OSC 与 FreeRTOS设计出具 OSC的FreeRTOS ,OSC的功能与原理已经介绍于上个章节,本章节将说明具 OSC的FreeRTOS与一般的FreeRTOS 的差异处,并列举范例程序的运行展现OSC与FreeRTOS的功能。

2.1 具OSC的FreeRTOS内存配置
  具OSC的FreeRTOS的内存配置如图2 , 范例程序的linker script设定了LMA(系统image)的内存配置模式,其中overlay0, overlay1 与 overlay2是仿真storage 的地址。linker script 设定VMA(系统执行时)的内存配置模式,当系统运行进入overlay1,2.. 时产生overlay miss 触发 exception 将overlayN 内的数据复制到 overlay region 中,这样的设计达到一份Overlay Region 的SRAM空间可以在不同时间执行对应不同的overlayN程序代码的目的。

图 2.具 OSC 的 FreeRTOS 内存配置图

2.2 osc_hisr task
  从图2的overlay0,1,2 中可以发现系统会运行task1与task2。说明FreeRTOS 做overlay region置换时也会执行scheduler 做置换task 的工作。本范例程序设计是在standard FreeRTOS 中增加一个 osc_hisr task 做overlay region 置换与管理的工作。如何达到OSC 与 osc_hisr task的结合需从Overlay Exception Handling的动作开始研讨:
• 当 overlay exception 被触发时,送 message 给 queue 启动 osc_hisr task。
• 因为 osc_hisr task 做 overlay region 资料的置换,所以 osc_hisr task 尚未执行完成前,不可以执行Overlay Exception Handling 的 iret.

osc_hisr task 的主要工作在:
• Map overlay region
• overlay region 数据的复制

osc_hisr task  设计的原则:
• 此 task 必须是最高 priority task.
• 此 task 必须放在 fixed region.

2.3 范例程序运行
  具 OSC 的 FreeRTOS 在 Andes EVB 上直接运行得到的结果如图 3,范例程序中键入 3 时,是进行 task 转换,因为不同 task 运行相对应的 overlay function 从console task 转成task1 再转成task2 也会产生相对应的page fault 执行osc_hisr task。图 3 红色箭头与数字转变可以得知 task 转换启动 function overlay 运作,从此范例程序中可同时验证 OSC 与 FreeRTOS 两者的功能。

图 3.范例程序执行结果

3. 结语
  本文第一章说明 Andes OSC 的工作原理与功能,第二章说明 FreeRTOS 如何与 Andes OSC 整合运作,在 OSC 的 FreeROTS 中也增加一个最高 priority task “osc_hisr” 来执行 OSC 相对应的功能,进而说明了具 OSC 的 FreeRTOS 需注意的设计原则,具 OSC 之 FreeRTOS 是由软件与硬件单元所组成,兼具硬件的效能与软件的弹性。
  已经有业界客户取得 Andes 的具 OSC 之 FreeRTOS 开发出具竞争力产品在市面上销售,由此可知具 OSC 之 FreeRTOS 具有经济实用的价值,可以协助客户在使用 AndesCore™时,设计出具有弹性且高附加价值之产品。

Continue Reading在晶心平台运行具OSC的FreeRTOS

8051与AndesCore™的软件差异与移植

1. 8051 与 AndesCore™
  本文将介绍使用 8051 与 AndesCore™差异事项,并对两种 CPU 系统相关事项做说明,后面再介绍从 8051 移植到 AndesCore™上注意事项,举中断向量表及异常处理函数的例子说明差异及移植,最后简要介绍 AndesCore™在 MCU 应用的三款 CPU: N705,N801 和 N968A。

2. 8051 与 AndesCore™ 常見差異事項
 2.1. 位宽的差异
  位宽是指处理器一次执行指令的数据带宽。8051 是 8 位宽的处理器, 而AndesCore™是 32 位宽的处理器,支持 32 位与 16 位的混合指令集,位数越宽,在数据的处理方面就更有效率。

 2.2. 指令差异
  8051 汇编语言共有 111 条指令集,AndeStar™的 V3m 指令集有 157 条, AndeStar™的 V3 指令集有 200 多条,两种 CPU 的指令集大概可以分为以下几类:算术运算,如加,减,乘,除等操作;数据传送,如数据在缓存器与内存间的传送,赋值等;逻辑跳转,如函数呼叫,无条件跳转,条件跳转,中断返回等;在AndesCore™中还有特权模式的指令部分,关于两种指令集的具体差别, 可以分别参考对应的指令集介绍文档。

 2.3. 地址空间映射差异
  AndesCore™使用 memory map 方式映射地址空间,主要有两种,内存的空间映射,如其中的 RAM 或 ROM 地址,它们用于存放程序运行时的代码和数据,在 AndesCore™上代码在 link 后,程序运行的代码和数据地址会最终确定, Andes 提供了一个简便的 link script 工具 SaG,可以很方便的对系统中可用的内存空间进行分配设定。

  另一个是外围所对应的地址空间,可以通过查看 SoC 对应的手册了解对应的外围映射的空间范围及相应的使用方法。

 2.4. 堆栈设置差异
  8051 的堆栈的起始位置是固定的(部分衍生 8051 可以做程序设定),它通常固定在芯片内的 RAM 中,8051 内存空间有限,非常小,程序中所使用的变量存放于特定的数据空间中,并不会放在堆栈空间,所以在 8051 中所需要的堆栈空间很小。而对于AndesCore™来说,堆栈可以设置在任意合适的RAM 上。程序运行时所有的局部变量都存放在堆栈中,只需要确保在设计系统的时候有足够的堆栈空间。在 AndesCore™中有$sp 寄存器记录堆栈位置,这需要在系统上电或者是系统 reset 后初始化时进行设置。

 2.5. 代码和资料的存储差异
  在 8051 系列单片机中,数据存储区可以分为内部数据存储区以及外部数据存储区。

   内部数据存储区有几个区别:data,bdata,idata。
   data : 片内 RAM 直接寻址区。bdata: 片内 RAM 位寻址区。idata: 片内 RAM间接寻址区。

  外部数据存储区又有:xdata,pdata。
   xdata 和 pdata:是外部存储区,有些芯片会带有 XRAM。

  在有些开发工具中,如 Keil,可以通过设置存储模式来处理,存储模式决定了默认的内存类型,此内存类型将应用于函数参数,局部变量和定义时未包含内存类型的变量。

SMALL 所有的变量存放在片内 RAM(data 区间)
COMPACT 所有的变量存放在外部存储区 (pdata 区间) 
LARGE 所有的变量存放在外部存储区(xdata 区间)

  AndesCore™以内存映射的方式,内存空间不会有特别的限制,就是说不会像 8051 那样需放在某处区间,这样的设计更方便灵活,允许程序代码和数据在可用的空间里自由放置。

  有时候需要将某段代码或者数据存放在指定的位置上,在 8051 中,可以在代码中使用”at”关键词,但该关键词是 8051 中所特有的,会造成可移植性和维护的问题,在 AndesCore™上,提供了一种简便的 link script 工具,如上所提到的SaG 工具,在 C 代码中使用 GNU 标准的语法格式,在 link 之后相应的代码和数据将存放于指定的位置,这样可以避免在代码中使用”at”该平台相关的属性设置。

 2.6. 数据类型及对齐差异
  8051 和AndesCore™是不同类型的CPU,它们所使用的数据类型所对应的宽度也不同,如下表所示:

   在链接完成后数据通常都会按照本身的属性对齐,比如 int 类型则会 4 bytes 对齐,short 则会 2 bytes 对齐。这样的存放方式可以提高 CPU 对数据读取时的效率。虽然 AndesCore™是 32bit 的 CPU, 在只需要 8bit 和 16bit 的数据时能节省存储空间,但在处理 16bit 和 32bit 的资料上则有更高效。

  在 8051 中有 sbit 关键词用于设置对特殊功能缓存器 SFR 的直接 access, 8051 的特殊功能缓存器分布在内存地址 0x80 到 0xFF 处,如下表:

  sbit 是 8051 扩展的变量类型,非标准 C 语法,移植的时候需要将其修改成标准 C 操作语法,另外在 AndesCore™中,所有的缓存器都是单独存在的,不会占用内存的空间。

 2.7. 指標使用差異
   8051 中兩種類型的指標,分別是記憶體指標和通用指標,通用指標由 3 個位元組組成,第一個位元組用來指明對應的記憶體類型,所以這種類型的指標類型佔用空間更大也更慢,記憶體指標只能用來訪問指定類型的記憶體空間。

而在 AndesCore™上指标不会有这方面的限制,它是一个 32bit 的数据,普通的缓存器就可以存放指针内容,可以访问到系统 4G 范围内的空间
(N705,N801 地址空间只有 16M,N968A 以上的 CPU 地址空间可达 4G)。

  2.8. 函数声明差异
   在 8051 中由于堆栈空间有限,如果有函数是可重入的,需要在函数声明的时候用关键词 reentrant 做说明。8051 的中断处理函数则需要使用关键词interrupt 声明,中断处理函数有时也需要用 using 关键词指明哪一缓存器组会被使用到。

  在 AndesCore™中,都采用标准的 C 语法,在声明函数时并不需要这些附加的声明。AndesCore™遵行底层的 ABI 机制,编译程序处理底层的缓存器及堆栈相关机制。对于上层用户来说是透明的。

3. 系统相关事项说明
 3.1. 操作模式
  8051 只有一种 mode,AndesCore™有两种 mode,分别是 superuser mode 和 user mode,当系统上电启动时是在 superuser mode,或者当系统进入到中断或者异常时也进入到 superuser mode,当从中断或者是异常返回后,会返回到 user mode。由于 8051 没有mode 切换的问题,所以在移植的时候只需要理解 AndesCore™在 mode 方面的机制就可以。

 3.2. 系统的启动
  8051 和AndesCore™的系统启动过程类似,通常在 0 地址存放中断向量表, 第一个向量表是 reset,当系统上电或者是 reset 后,经过该向量会跳转到一个启动函数中,该启动函数会完成系统启动所必要的步骤,比如设置 CPU,初始化 SoC,清理内存,初始化 C 运行环境等, 最后完成所有的准备后跳转到 main 函数。

 3.3. 中断处理
  8051 有 5 个中断源,通常中断向量表只是一个跳转,会跳到真正的中断处理函数,8051 只能设置成两级的中断优先级。

  AndesCore™包含了 9 个内部异常,中断向量号对应于从 0 到 8, 9 之后对应于外部中断,在 Internal Vector Interrupt Controller (IVIC)mode 时可支持 32 个外部中断,

  当 External Vector Interrupt Controller(EVIC) mode 时由外部中断控制器决定,最多有 64 个。

  中断的处理由以下几部分组成:
    1. 实现中断处理函数
可以用汇编语言实现 8051 的中断处理函数,也可以用 C 来实现,在 8051 中 C 实现的中断处理函数会有一个”interrupt”的关键词,如果有缓存器 bank 被使用到,还要加上”using”关键词。如果要将中断处理函数固定在特定位置还需要使用”at”关键词,而 AndesCore™使用的是标准的 C 语法,不需要为中断处理函数做这些设置。

   2. 中断向量表的产生
  8051 中断向量表摆放在 0 开始的位置,在 AndesCore™中硬件可以设
定启动地址,通常设为 0 地址,也可以是非 0 地址,中断向量表存放在对应系统启动地址处。在程序编写过程中可以通过标准的 gnu 语法再加上 link script 的 SaG 工具,以使产生的中断向量表在连结的时候存放于特定的位置。

    3. 中断配置
在 8051 中,需要做以下设置
1. IE 寄存器中Individual Interrupt Enable 位设 1
2. IE 寄存器中 EA(Enable All)位设 1
3. 当是外部中断时,配置相关的 pin 为输入,并设置对应的触发属性为 edge 或 level 触发。

而在 AndesCore™中需要做以下設置:
1.设置 CPU IVIC 或者 EVIC mode
2.设置INT_MASK 位
3. 设置中断的优先级
4. 关于异常处理差异
在8051 中没有异常处理向量,所以在8051 中并没有这部分的处理函数, 在 AndesCore™中有一些系统的异常处理向量,比如 Machine Error, General Exception, 建议在 AndesCore™上实现对应的处理函数,当发生这类异常时做一些基本的处理。

 3.4. 时序和延迟
  在 8051 中可以采用 NOP 指令来延迟,在 AndesCore™中也有 NOP 指令来达到类似目的。

 3.5. 电源管理
  8051 单芯片中有两种省电方式,分别是空闲方式和掉电模式,单芯片处于空闲工作方式时,CPU 处于睡眠状态,它的芯片内其它部件还是会继续工作,芯片内 RAM 的内容和所有专用缓存器的内容在空闲方式期间都被保存下来了, 可以通过中断或者硬件复位来终止空闲工作方式。单芯片处于掉电工作方式时,芯片内的振荡器停止了工作,因此它的一切都被迫停止了。但芯片内 RAM 的内容和专用缓存器的内容一直保持到掉电方式结束为止。掉电方式的唤醒方式只有一种,就是硬件复位。

  在AndesCore™上,可以通过软件 standby 指令使 CPU 进入到低功耗模式, 通常标准 c 代码并不能直接控制硬件,Andes 的 compiler 提供了 intrinsic 函数来做到这点。分别是: nds32_standby_no_wake_grant(), nds32_standby_wake_grant(), nds32_standby_wait_done().指定系统进 入低功耗模式时被唤醒的方式,分别是外部中断的中断唤醒,电源管理模块唤醒, 和中断配合电源管理模块唤醒,可以根据系统需要分别设计。

4. 从 8051 移植到 AndesCore™ 上注意事项
从一个 8051 工程,当移植到 AndesCore™上时有以下注意事项:
     1.内存映射,代码和数据摆放位置相关的设置。
     2.可以不必考虑变量数目,或者是函数的 overlay, 因为在 32bit 的 AndesCore™上开发时内存空间通常不会像 8051 那样小。
     3. 如果空间允许,在 AndesCore™上尽量使用 32bit 的数据类型,这样效率会更高。
     4. 在 8051 上用于表示内存区域属性的标志如(idata, xdata, bdata, pdata等)在 AndesCore™上可以移除。
     5. 在 8051 上不需要设置内存区块模式,比如:small, compact, large 等。
     6. 在 8051 上用于表示对象远近的属性”near” 和”far”, 都可以移除,AndesCore™上的指标的访问可以达到所有地址空间。
     7. 在中断处理函数中不需要像 8051 那样指定哪块缓存器块会被用到的关键词”using”。
     8. 在 8051 上中断处理函数就和普通的函数一样,不需要设置其它的关键词, 如 interrupt。
     9. 如果有 8051 汇编部分移植到 AndesCore™,需要重新实现,尽可能的用 c 来实现,便于维护和调试。
     10. 在 8051 中使用到的#progma 相关部分需要删除。
     11. 在 AndesCore™中函數不需要声明为”reentrant”属性。
     12. 如果使用了数学运算,在 8051 中默认是使用 32bit 单精度浮点,如果要保持和 8051 中相同的精度,需要将函数名做一些调整,如将 sin()改成sinf()。

5. 中断向量及异常处理函数例子
以中断向量及中断处理函数的例子说明差异及移植。

 5.1. 汇编实现中断向量表
   [8051]
该例子显示怎样用汇编设置 8051 的中断向量和中断处理函数,在 8051 汇编中 ORG 指定了后面汇编代码的位置,后面的中断向量通常是一个跳转语句。如下例第一个向量跳到主函数 MAIN 函数中,另外一个外部中断1,也是一个跳转指令:LJMP INT 到后面的用汇编实现的中断处理函数 INT 中。

   [AndesCore™]
该例子显示怎样用汇编设置AndesCore™的中断向量表和中断处理函数, 该例子中 exception_vector 是中断向量表的 label, 后面分别表示第 0,1,2,3…个中断向量,它们只是简单的跳转指令,跳到具体的执行实体中去,如 vector 0 跳到_start,做系统相关的初始化操作,_start 是系统启动代码,用汇编语言来实现。vector 9 后面对应的是外部中断,中断处理函数如 OS_Trap_Interrupt_HW0, OS_Trap_Interrupt_HW1… 它通常用 C 来实现,可以参考后面 5.2 章节的AndesCore™中断处理函数范例。

  在上面用汇编设置 AndesCore™的中断向量表的例子中,我们需要将中断向量表最终设定在 0 地址处,可以通过 section 语法配合 SaG 工具实现,例子中我们设定该段的 section 名为.vector, 所以在 SaG 中,我们自定义一个USER_SECTION 为.vector,并将.vector 放在 0 开始的地方并作为第一个section。

通过上面的 SaG 语法,并使用 Andes 提供的 SaG 转 ld 的工具,可以产生类似以下的 ld,在工程进行链接的时候选择该 ld 时就能确保 .vector 链接的地址位于 0 处。

 5.2. 中断处理函数的 C 实现
   [8051]
怎样用 C 写 8051 的中断处理函数范例 

[AndesCore™]
怎样用 C 写 AndesCore™的中断处理函数范例   

6. 适用于 MCU 的 Andes CPUs
  Andes 有三款非常适用于 MCU 应用的 CPU,分别是:N705,N801,N968A,如下图所列:

  N705 和 N801 分别采用了两级和三级流水线,都具有很低的功耗和很好的性能,当应用需要的频率较低时,使用两级流水线的 N705 能发挥出更好的性能和更低功耗的特性,相比于 8051,两级流水线的 N705 在频率方面高出许多,比如在 TSMC 40nm LP 工艺下能跑到超过 240MHz,所以完全能胜任 8051 的应用需求。N968A 使用了五级的流水线,同样有低功耗的特性和很好的性能,同时该款 CPU 具有很强的可配置性,如支持多种总线接口,还支持了专门为audio 的加速指令,N968A 是一个性能好,功耗低,又具备强大的可配置特性, 适合于多种应用。

7. 总结
  AndesCore™使用标准的 C 语法开发,方便快捷,同时作为 32 位 RISC(精简指令集)架构的 CPU,AndesCore™有多款适用于 MCU 应用的 CPU,相对于8051 具有功耗,性能方面优势。

Continue Reading8051与AndesCore™的软件差异与移植

中断处理固定优先级与可编程优先级的差别

王胜雯,经理,晶心科技股份有限公司

  在现今 SOC 设计中,当周边设备(Peripheral IP)想要和中央处理器(CPU)沟通时,最常使用的机制则是透过中断(Interrupt)。由周边设备触发中断给中央处理器,当中央处理器接收到中断后,则可判断是由哪个周边设备触发中断,接着处理相对应的中断处理程序(ISR,Interrupt Service Routine),藉此达到彼此沟通的目的。但在同时间若有多个周边设备同时触发中断给中央处理器时,优先级别处理就成为了非常重要的一环。

  AndesCore™在中断优先级处理方面,共支持两种模式:固定中断优先级(Fixed Priority)和可编程中断优先级(Programmable Priority)。当配置为固定中断优先级时,中断处理优先级会依照中断输入脚位的顺序来决定优先处理权,脚位数字越小其优先权越高(Low Interrupt Input Number High Priority),而配置在可编程中断优先级时,可将所有中断输入设置成四个层级的优先处理权,中央处理器在同时发生触发中断时会依照其设置的层级来决定优先处理权,若发生层级相同时则再以中断输入脚位的顺序来决定优先处理级。固定中断优先级比较简单,闸门数也稍少;而可编程中断优先级则较有弹性,芯片完成后软件仍然可以根据不同应用更改中断优先级别。

   而在中央处理器进入中断处理程序后,倘若希望能让其他优先级较高的中断触发中央处理器进而处理该中断处理程序,在软件部分又应该怎么设置来达到嵌套中断的结构?我们将在本文介绍给使用者参考,期望能对使用者有所帮助,也希望读者不吝指教提供您宝贵的意见。

1. 中断优先级介绍
AndesCore™共支持两种中断优先级处理模式:固定优先级模式(Fixed Priority)与可编程优先级模式(Programmable Priority)。前者是 AndeStar 架构 V1 及V2 定义的; AndeStar V3/V3m 架构除保留前者的选项以维持向后兼容(backward-compatibility)之外,也加入更有彈性的后者选项。以下的介绍将基于V3m AndesCore™ N801-S 这颗中央处理器。带领使用者循序渐进地了解这两种中断优先级处理模式的差异。

1.1. Definition
AndesCore™ N801-S支持两种中断优先级模式,在硬件配置时就需要先决定中断优先级的模式,如图1的硬件配置窗口所示,首先,我们先介绍关于这两种模式的定义。

图1. 硬件配置窗口

1.1.1 Fixed Priority Mode 
  在AndesCore™ N801-S硬件配置时,若配置在中断固定优先级模式下,中央处理器在多个触发中断同时发生时,则依照中断输入脚位来决定处理顺序,请参考表1。

表1. Fixed Priority Mode 触发中断处理优先级

1.1.2 Programmable Priority Mode
  在AndesCore™ N801-S硬件配置时,若配置在中断可编程优先级模式下,中央处理器在多个触发中断同时发生时,则依照每个中断输入设置的优先层级来决定处理顺序,请参考表2。而在可编程优先级模式下,每个中断输入都有四个优先层级可以让使用者编写软件时设置,用户也可以透过系统寄存器(PPL2FIX_EN) 将模式从可编程优先级模式切换至固定优先级模式。

表2. Programmable Priority Mode 触发中断处理优先级

1.2. System Register
  关于上述两种中断优先级模式,在可编程优先级模式下用户可透过设置AndesCore™ N801-S内部的system register来设置每个中断优先权层级,以及将可程序化优先权模式切换回固定优先级模式。

  设置优先级的system register为INT_PRI(ir18)与INT_PRI2(ir28),每个中断输入都有四个层级让使用者规划,其格式如图2与图3的寄存器配置,而设定值的优先权可参考表3的解释。

图2. Format of Interrupt Priority Register (HW_INT0~HW_INT15)

图3. Format of Interrupt Priority Register2 (HW_INT16~HW_INT31)

  在硬件配 置成可 编程优先级模式下时 ,有一个system register 为INT_CTRL(ir19)。透过设置INT_CTRL.0,用户在硬件配置成可编程优先级模式下切换回固定优先级模式。其格式如图4的缓存器配置,而内容值的意义可参考表4的解释。当PPL2FIX_EN=1时,CPU处理中断的方式则会与硬件配置成固定优先权模式的情况一样,CPU只根据中断输入的号码大小来决定处理顺序。

  控制中断输入 on/off 的 system register 为 INT_MASK2(ir26),用户可以透过设定该寄存器来决定各中断输入是否开启,其各相关描述可参考图 5 与表 5。

图 5. Format of Interruption Masking Register 2

  与中断控制还有一个很重要的System register就是Processor Status Word Register(PSW),其中PSW.GIE(Global Interrupt Enable)是用来控制中断程序致能, PSW.INTL(Interruption Stack Level) 是纪录 CPU 当前中 断层 级的数据 , PSW.CPL(Current Priority Level)则是纪录当前中断优先级数据,其各相关描述可参考图6与表6~表8。

1.3. Nested Interrupt
  在中断处理程序中,最常用到的就是嵌套中断(Nested Interrupt) 的应用,在这个章节将介绍 AndesCore™如何实现嵌套中断处理程序。

当CPU发生中断进入中断处理程序时,硬件会关闭中断致能(PSW.GIE),并将中断层级(PSW.INTL)加一,在离开中断程序后硬件会将中断层级减一,再重新开启中断致能。以AndesCore™ N801-S为例,PSW.INTL可支持至2 Level(01),若要实现嵌套中断的应用,CPU在进入中断处理程序后,需要先将中断层级进行降级(PSW.INTL-1),避免嵌套中断的发生造成中断层级溢位(overflow)而让CPU 进入exception interrupt,降级后再开启中断致能(PSW.GIE),CPU就可以实现嵌套中断程序,可参考图7的流程图说明。发生嵌套中断程序时,CPU硬件会比对当前中断优先级(PSW.CPL),来决定是否让CPU处理该嵌套中断,另外CPU在处理嵌套中断程序时,必须由软件来备份通用寄存器與内容, 用户可以参考AndeSight™中提供的相关demo code。

2. 非嵌套中断优先级处理程序介绍
在介绍完中断处理模式相关定义之后,本章节提供在非嵌套中断 (Non-nested Interrupt)实际开发与应用上的范例,让用户可更了解在不同中断处理模式下的差异。

2.1. Multi-Interrupts at Fixed Priority Mode
  本章节介绍当硬件配置在固定中断优先级模式下时,发生多个中断时,CPU在处理的程序。

图 8 中,表示同时发生 HW_INT1、HW_INT28 与 HW_INT30 三个中断源, 此时 CPU 会依照中断输入号码大小(号码越小优先权越高)来决定处理优先级,所以 CPU 依序先处理 HW_INT1,然后再接着处理 HW_INT28,最后再处理HW_INT30。

图 8. 固定中断优先级 CPU 处理程序(一)

图 9 中,表示同时发生 HW_INT1 与 HW_INT30 两个中断源,在 CPU 处理完 HW_INT1 后应该接着处理 HW_INT30,但在处理 HW_INT1 的同时,外部中断源又接着发生 HW_INT28,所以在 CPU 在处理完 HW_INT1 后会优先处理HW_INT28,然后最后才处理 HW_INT30。

图 9. 固定中断优先级 CPU 处理程序(二)

  图 10 中,表示同时发生 HW_INT28 与 HW_INT30 两个中断源,在 CPU 处理完 HW_INT28 后接着处理 HW_INT30,此时外部发生了 HW_INT1,在没有使用嵌套中断的情况下,此时 CPU 已经在处理 HW_INT30,所以并不会因为HW_INT1 的中断优先权大于 HW_INT30 而去处理 HW_INT1 ,必须等到HW_INT30 处理完毕,最后才处理 HW_INT1。

图 10. 固定中断优先级 CPU 处理程序(三)

2.2. Multi-Interrupts at Programmable Priority Mode
  本章节介绍当硬件配置在可编程中断优先级模式下时,发生多个中断时,CPU 在处理的程序。

  图 11 中,表示同时发生 HW_INT1(PPL=2) 、 HW_INT28(PPL=0) 与HW_INT30(PPL=1)三个中断源,此时 CPU 会依照中断优先权大小(PPL 值越小优先权越高)来决定处理优先级,所以 CPU 依序先处理 HW_INT28(PPL=0),然后再接着处理 HW_INT30(PPL=1),最后再处理 HW_INT1(PPL=2)。

图 11. 可编程中断优先级 CPU 处理程序(一)

图 12 中, 表示同时发生 HW_INT1(PPL=1) 、 HW_INT28(PPL=0) 与HW_INT30(PPL=1)三个中断源,此时 CPU 会依照中断优先级大小来决定处理优先级,而发生中断优先权大小相同时,则再依照中断号码大小(号码越小优先权越高) 来决定处理优先级。 CPU 依序先处理 HW_INT28(PPL=0) , 此时HW_INT1(PPL=1)与 HW_INT30(PPL=1)的 PPL 相同,CPU 则依照中断输入号码大小来决定优先级,所以先接着处理 HW_INT1(PPL=1) , 最后再处理HW_INT30(PPL=1)。

图 12. 可编程中断优先级 CPU 处理程序(二)

图 13 中,表示同时发生 HW_INT28(PPL=0)与 HW_INT30(PPL=1)两个中断源,此时 CPU 会依照中断优先级大小来决定处理优先级,所以 CPU 先处理HW_INT28(PPL=0),但在处理 HW_INT28(PPL=0)的同时,外部中断源又接着发生 HW_INT1(PPL=0),所以 CPU 在处理完 HW_INT28(PPL=0)后会优先处理HW_INT1(PPL=0),最后再处理 HW_INT30(PPL=1)。

图 13. 可编程中断优先级 CPU 处理程序(三)

图 14 中,表示同时发生 HW_INT28(PPL=1)与 HW_INT30(PPL=2)两个中断源,此时 CPU 会依照中断优先权大小来决定处理优先级,所以 CPU 先处理HW_INT28(PPL=1) ,然后接着处理 HW_INT30(PPL=2) ,但在处理HW_INT30(PPL=2)的同时,外部中断源又接着发生 HW_INT1(PPL=0),在没有使用嵌套中断的情况下,此时 CPU已经在处理 HW_INT30(PPL=2),所以 CPU 并不会因为 HW_INT1(PPL=0) 的优先权大于 HW_INT30(PPL=2) 而去处理HW_INT1(PPL=0) , 必须等到 HW_INT30(PPL=2) 处理完毕, 最后才处理HW_INT1(PPL=0)。

图 14. 可编程中断优先级 CPU 处理程序(四)

3. 嵌套中断优先级处理程序介绍
  本章节将介绍嵌套中断(Nested Interrupts)实际开发与应用上的范例,让用户可以更快速了解嵌套中断处理程序的实现。因为固定优先权模式先天逻辑简化后的限制,处理嵌套中断没有可编程优先权模式简捷有效率。如果必需使用嵌套中断,建议硬件配置在可编程优先权模式(Programmable Priority)。下面介绍在此模式下,如何实现嵌套中断处理程序,以下范例中在进入每个中断处理程序后也都已经先完成嵌套中断的软件降级程序。

图 15 中,表示当 CPU 正在处理 HW_INT1(PPL=1)中断源时,若发生嵌套中断 HW_INT30(PPL=1),CPU 并不会进入 HW_INT30(PPL=1)的嵌套中断处理程序中,等到 HW_INT1(PPL=1) 中断处理程序结束后, CPU 才会进入HW_INT30(PPL=1)的中断处理程序中。

图 16 中,表示当 CPU 正在处理 HW_INT1(PPL=1)中断源时,若发生嵌套中断 HW_INT30(PPL=2),CPU 并不会进入 HW_INT30(PPL=2)的嵌套中断处理程序中,倘若此时又再发生嵌套中断 HW_INT28(PPL=0) 时, CPU 则进入HW_INT28(PPL=0)的嵌套中断处理程序中,等到 HW_INT28(PPL=0)中断处理程序结束后回到 HW_INT1(PPL=1)的中断处理程序中,等到 HW_INT1(PPL=1)中断处理程序结束后,CPU 才会进入 HW_INT30(PPL=2)的中断处理程序中。

4. 結語
  在 AndesCore™所提供的两种中断优先级模式里,都可以实现嵌套中断(Nested Interrupt)的处理,透过上述的几种多个中断源发生时,在 AndesCore™ N801-S 处理程序上的范例,相信各位对于嵌套中断与非嵌套中断的实现有了更进一步的了解,对于在中断源的配置上就能依照电路需要来规划输入脚位以及灵活运用可编程优先级中断的功能。在 AndeSight™软件整合开发环境中也提供关于中断处理程序的软件范例,让用户在程序开发过程更为简单与快速。

Continue Reading中断处理固定优先级与可编程优先级的差别

Andes SAG 应用实例

  在嵌入式开发中,系统软件设计特别是各种存储器的规划是必不可少的一个环节,它也直接体现在链接脚本的撰写上。 因链接脚本的语法相对复杂和篇幅较大,前期撰写和后期维护对工程师来讲难度都很大, 但对使用 AndesCore 做开发的工程师来讲,Andes SAG 是一大福音,它提供简单直观的描述语言替代了复杂的链接脚本。我们收到的反馈也证明,越来越多的工程师开始采用 Andes SAG 替代 linker,之前我们有一篇技术文章对 SAG 的语法格式做了介绍并说明如何使用,本文将展示四个实际工程开发的例子,以帮助广大开发者更好的熟悉和理解Andes SAG,同时可以作为开发时的参考。

1. 将函数和变量指定到特定地址
  第一个例子是如何将函数和变量的地址指定到一个特定的地址,例子中的地址指运行地址——VMA。有这样要求的原因有很多,诸如 SOC 的运行地址空间不连续,或者需要高效使用某一块效率很高的存储器等情况。解法分为两步:一, 在SAG 文件中添加自定义的section,将此 section 的 VMA 设定到指定地址;二,在 C 语言中,将需要改变的函数和变量用特定的语法放在自定义的 section。

  图表 1 是在SAG 中自定义 section 的例子。第 1 行关键词 USER_SECTIONS 表示后面接的这几个 sections 都是由使用者自定义的 sections。

图表 1. Samp1.sag 文件

  图表 1 中,第 4 行至 8 行表示从 0x0 开始的区域是只读区,包含程序代码(.text section)及只读数据段(.rodata section)。第 9 行,MYRAM0 部分表示.mysection0 的 VMA 从 0x00014000 开始。以此类推,MYRAM1 和 MYRAM2 部分各自表示mysection1 和.mysection2 的 VMA 起始位置。第 21 行的 RAM1 里放的是.data 及.bss sections,执行时期会从 0x00010000 开始,源代码中须做到将 data 的 LMA 地址 copy 至 VMA 位置,可以使用 data_lmastart 与 data_start 来寻址。

  指定函数放在自定义 section 里,在源代码的对应处要使用 attribute ((section(“.mysection0”)))语法,完整写法请参考图表 2a。图表 2b 是另外一种写法。

图表 2a. 指定函数放在自定义 section

图表 2b. 指定函数放在自定义 section 的另一种写法

  指定全局变量 gdata1 放在自定义 section .mysection1 里,在源代码的对应处要使用 attribute ((section(“.mysection1”)))语法,完整语法请参考图表 3。

图表 3. 指定变量放在自定义 section

  将函数和变量这样指定后,编译后的 adx(elf)文档可以清晰看到对应 Section 的 LMA 与 VMA 如图表 4.

图表 4. ELF Header

2. 实现 IVB 在运行时切换
  有一个客户需要系统在开机与正常运行时能有不同的 ISR,即是同一个中断的服务函数在开机和正常运行时会不一样。对于这个问题的解法有很多,我们今天介绍是其中一种解决方法:设置一个新的 Vector Table,新的 Vector Table 会跳到新的 ISR;通过 SAG 将新的 Vector Table 指定到一个特定地址上;当程序开机完成,需要正常运行时,只需要去修改 IVBASE (ir3)这个寄存器。
  所以完成这个例子的重点是如何在汇编代码中建一个新的 vector table 并指定到自定义的 section 中。表5是实例的写法:

图表 5  指定 Vector table 到自定义 section

  图表 5 重点是是第一行,.section 是用来定义非标准的section,.nds32_aa 即为非标准 section 的名称,”a”表示 allocable, “x”表示 executable. 因为 Andes 的标准vector table 一般会放在.nds32_init section,所以新的 vector table 放.nds32_aa 里,名称不一样能区别就好。接下来是让新的自定义 section .nds32_aa 运行在特定地址上,如图表 6 所示。

图表 6 指定自定义 section 到特定地址

  这样新的 vector table 的首地址会被固定到 0x10000 的位置,当程序开机完成,只需要将 IVBASE 设定到这个地址,那么当有中断进来,就会跳到新的 Vector Table 中。

3. 指定一个或几个 C 档的所有 section 到指定地址
  上两个例子有共同点是通过编程将某一段程序放到自定义 section,区别在于一个是指定 C 语言函数和变量到自定义 section,一个指定汇编函数到指定的section,都需要改动源代码。然而对于一些应用场景,比如不提供源代码只有编译好的.o 或者.a 文件,如果想将.o 档里的 section 指定到特定地址运行,这个时候该如何做呢?请参考图表 7A 的写法,这表示我们要将 hello.o 的只读区,包含程序代码(.text section)及只读数据段(.rodata section)放在 LMA 及 VMA 在0x10000 的地址上。

图表 7A 指定自定义 section 到特定地址

  在整个 project 中如果将每个.o 档都列出来,那么整个 SAG 文档将变得难以阅读,而且在给后期维护带来麻烦,这种解法不好。如果使用者只需要排除几个.o 檔,对于熟悉 GNU linker 的读者会想到 “EXCLUDE_FILE”这一语法,让使用者可以很方便地在 Linker 中实现这一需求。Andes SAG 也与时俱进地引入这一语法。图表 7B 正是这样一个例子,它将 uart.o 中所有的 section 都放到一个特定位址去运行,而其它的保持不变。

图表 7B 支持“EXCULDE_FILE”

4. 如何避免 LMA 或 VMA 的偏差
  在前三个例子中,都是举例去说明如何实现将程序的某一部分的 LMA 或者VMA 固定在某一个特定地址上,这是对链接这一动作的基本要求。嵌入式软件工程师需要知道,当某一 section 的 LMA 与 VMA 不相等时,那么在程序初始化时需要将这一 section 从 LMA 的地址拷贝到 VMA 的地址。初始化做拷贝时,这些 section 的 LMA 和 VMA 都是在链接脚本中赋值的,代码中只是去做引用。 
  Andes SAG 同样可以给变量赋值 LMA 和 VMA,但如何赋值呢,是不是一个一个紧凑地排列下来?答案很显然是不。很多工程师都知道,数据存放有Alignment 的要求,比如 4 Byte 的 Word 其存放的首地址需要是 4 Byte Align;程序呢,因为优化的需要,比如在 Andes 编译器在-Os 等级下,函数的首地址同样强制 4 Byte Align。既然有对齐的要求,就必然有 gap 存在,当然这里举出的对齐因素只是让读者了解到链接器对某一section 的 LMA 或 VMA 的数值确定不只是单纯累加,Andes SAG 能自动处理好大部分对齐状况。但在一些较复杂的例子中,需要给 Andes SAG 更多指示,让它工作正确。
   首先,我们来看图表 7 所举出的例子,这一行“LOADADDR NEXT
uart_lmastart”,有一个关键字“NEXT”。它的作用就是让 SAG 知道,这个变量的取值是下一个 Section 的开始,而不是上一个 Section 的结束。为了让读者更明白所表示的含义,我们首先来看依照图表 7 的SAG 编译出的 elf (adx)档 header信息,如图表 8:

图表 8      adx header

  可以看到.text_*uart.o 的 LMA 应该是 0x1c60, 上一个 section(.bss)的 LMA 结束地址应为:0x1c48+0x10=0x1c58,所以为了清晰地让SAG 知道 uart_lmastart 代表.text_*uart.o 的 LMA 开始而不是.bss 的 LMA 结束,我们应该用 NEXT 去修饰它。

  然后,我们再来看图表 9 的例子,这个例子中,使用“LMA_FORCE_ALIGN” 的原因是因为可能某一个 section 的 size 只有 2 Byte(不是 4 Byte 的整数倍), 但下一个 section 的 VMA 起始地址需要 4 Byte Align,这时就会出现冲突,为解 决冲突,Andes SAG 引入这一关键字“LMA_FORCE_ALIGN”,强制让 LMA与 VMA 用同一个值去做 Align。

图表 9 “LMA_FORCE_ALIGN”example

我们用图表 9 的 SAG 例子去编译对应的 project,可以看到图表 10 中section .sbss_b 的 LMA 已经被从 0x1d42 调整到 0x1d44。

图表 10 “LMA_FORCE_ALIGN”的效果

5. 结语
  Andes 提供通俗易用的 SAG 工具帮助工程师替代了复杂的链接脚本,可以大大提高在 Andes core 平台上的软件开发效率。本文从实际例子出发,介绍了Andes SAG 工具如何快速解决工程实际问题,说明了 Andes SAG 强大而且容易上手。然而工具的功能越强大,也就需要工程师多加深入了解功能设计的缘由, 这也正是最后一个例子展现出来的道理,即是透彻了解就可以熟能生巧。希望广大读者能熟练掌握 Andes SAG 这样一把利器,在软件开发中发挥四两拨千斤的作用。

参考文档:
 1: BSP321 programming guide link generator
 2: The GNU Linker Manual

Continue ReadingAndes SAG 应用实例

软件Overlay:程序编写与调试

赖歆雅,技术经理,晶心科技股份有限公司

  近几年来,SOC 为了支持更大的硬件资源,及更精确的算法,很多应用中的软件程序代码越来越大,但是售价却要越来越便宜。各家厂商无不绞尽脑汁寻找降低成本的方法。
  SRAM 在 SOC 上,是一个快速但单位面积较大的组件,而单位面积较大代表成本较高。有一个降低成本的方法,是将程序代码放在较慢但单位面积较小的 flash 或 ROM 上,当系统需要执行里面的某些程序代码时,才加载到内存里执行。
  如果用商店来比喻的话,有一个小店租在都市里的黄金店面里,小店的展示柜很小,当客人想要看架上没有的商品时,店员才从后面较大的仓库里,把商品拿出来放到展示柜上。这里的展示柜就像 SRAM,昂贵但是有效率,仓库就像 flash,便宜容积大但是存取较麻烦。
  本文介绍的是软件 overlay 的技术。除此之外,晶心科技也发展了硬件overlay 的技术,使得 overlay 执行更快,操作更为简单。期望本文章能对使用者有所帮助,也希望读者不吝指教提供您宝贵的意见。

1. 软件 Overlay 技术介绍及操作
  我们举一个实际例子作为说明,比方说程序代码的大小为 210KB,RAM 只有 64KB,我们把 RAM 规划成一格一格的大小,比方说每 4KB 切成一块。每4KB 的大小可以在不同时间,更换成不同的程序代码,可以重复利用 RAM 的空间。程序代码储存在 ROM 或flash 里,只有在执行之前会将函数从 ROM 或flash 里动态加载 SRAM 里。当这个函数执行完成,下一个函数要执行前,再加载下一个函数。
  值得注意的是,每一格 SRAM 里可加载的程序代码是互斥的,比方说有些不会同时使用的功能可以放在同一格里,比方说 mp3 播放器,录音和播放不会同时使用,就可以规划重复利用同一格 SRAM。

1.1 系统架构
  请参考图表 1,右边长方形是 flash 的内容。0x0 起 1MB 的空间,flash 里存放了程序代码和.data,及各个即将要被 overlay 的 sections。
  图表1的左边长方形是SRAM规划,地址从0x10000000开始,我们切出三格提供overlay的SRAM,分别是0x10800000, 0x10804000及0x10808000。Overlay要规划成几格,或者每一格要切成多大块,都是由使用者规划。这里的SRAM与flash的地址是以通用型Andes FPGA开发板作例子。读者设计SOC时,可以根据实际需求定义合理的地址。
  程序执行时,0x10800000可以加载.ovly0或是.ovly1。0x10804000可以加载.ovly3或是.ovly2。0x10808000可以加载.ovly4或是.ovly5。

图表1. 系统架构图

1.2 overlay 的 sag 文件编写
  图表 2 是范例 sag 文件。Sag 文件是 Andes linker script generator 所需要的输入文件,执行linker script generator 后,输出会产生GNU linker 需要的linker script。详细语法说明可以参考 Andes BSP v3.2.0 User manual 第 12 章。
  我们简单介绍图表 2 的语法。第 1 行关键词 USER_SECTIONS 表示后面接的这几个 sections 都是由使用者自定义的 sections。在后面的章节,笔者会介绍如何把函数指定为这些自定义 sections。

图表2. sw-ovly.sag文件

  图表2中,第4行表示从0x0开始的区域是只读区,包含程序代码(.text section) 及只读数据段(.rodata section)。第9行,OVLY0从0x10800000开始,里面有2 个sections可overlay,一个是.overlay0,另一个是.overlay1。以此类推,在OVLY1 和OVLY2都各有2个sections可以overlay。第24行的RAM1里放的是.data及.bss sections,执行时期会从0x10000000开始。

1.3 sag 文件转成 linker script
   如图表3,在cygwin下执行nds_ldsag软件,将sw-ovly.sag转成sw-nds32.ld 文件。参数-o sw-nds32.ld为指定输出文件名。nds_ldsag软件可以在AndeSight 2.0.1 MCU或是BSP v3.2.0里取得。

图表3. Sag文件转换

1.4 程序里指定函数或变量放在自定义的 sections
  GNU ld (linker)可连结目标文件为可执行文件,排列上的最小单位是section, 基本的sections为.text,.data及.bss这3个sections。为了达成分区overlay的功能,必须指定函数或是变量在自定义的sections上。在前一节里我们介绍了我们切出 3个区域可以做overlay,分别是OVLY0(从0x10800000起),OVLY1(从0x10804000起)及OVLY2(从0x10808000起)三个区域。指定函数overlay0放在自 定义section .overlay0里,要使用 __attribute__ ((section(“.overlay0”)))语法, 完整写法请参考图表4a。图表4b.是另外一种写法。

指定全局变量gdata1放在自定义section .overlay4里,要使用 attribute ((section(“.overlay4”)))语法,完整写法请参考图表5。

图表5. 指定变量放在自定义section

1.5 各 sections 的 LMA 与 VMA
  图表6,是各个section的LMA和VMA。在这个表上,可以看.andes32_init 到.sdata_w的LMA从0x0~0x29dc,这些section的LMA是连续的。.overlay0 与.overlay1做overlay,所以有共同的VMA 0x10800000。同样的,.overlay2 和.overlay3,具有共同的VMA 0x10804000。.Overlay4和.overlay5,也有同样的VMA 0x18008000。

图表6. 各sections的LMA和VMA

1.6 overlay 程序的加载
  前面已经介绍overlay section的sag文件写法。那么如何加载用户想要用的overlay程序呢?
  请看图表7,这是overlay的执行程序代码。第5行OverlayLoad(0)表示載入section .overlay0。第6行OverlayLoad(4)表示载入section .overlay4。第7行在.overlay0被加载后,执行overlay0(),可以正常工作。

图表7. Overlay sections的使用方法

  再来我们介绍一下Overlay manager的程序运作,Overlay manager即为图表7中的函数OverlayLoad。图表8列出Overlay manager代码段,主要做了两件事。一,修改mapped table _ovly_table,标示overlay section是mapped或是unmapped。_ovly_table的用途是让gdb知道目前加载的是哪一个section,使得gdb在debug时,能自动切换为正确的调试信息。
  二,在程序执行时期将函数加载,函数ovly_copy是一个memcpy函数,将函数从LMA复制到VMA上。当OverlayLoad(0)执行完后,overlay0函数主体便存在于VMA上,可正确的执行。

图表8. Overlay manager代码段

  图表9为_ovly_table的内容,要标示每一个overlay section的vma, size, lma, 和是否mapped。必须要注意的一点,_ovly_table要位在一个lma等于vma的区域里。

图表9. _ovly_table的内容

2. 调试 Overlay 的程序
  开启自动overlay调试功能的gdb命令是overlay auto。当overlay auto开启后, 对于使用者来说,与一般程序的调试方法相同。
  图表8的最后一行_ovly_debug_event()的用途是让gdb能把断点加在正确的地址上,这一行要写在OverlayLoad的后面。必须要有这一行,gdb的自动overlay调试才能正常。
  当用户加一个断点在被overlay的区域,gdb会在函数被加载之后(即为执行完OverlayLoad),遇到_ovly_debug_event时,自动的把断点加到overlay的地址上。

3. 参考数据
  Overlay Commands
https://sourceware.org/gdb/onlinedocs/gdb/Overlay-Commands.html

Automatic Overlay Debugging https://sourceware.org/gdb/onlinedocs/gdb/Automatic-Overlay-Debugging.html#Auto matic-Overlay-Debugging

Debugging Programs That Use Overlays http://davis.lbl.gov/Manuals/GDB/gdb_11.html

Andes BSP v3.2.0 User Manual
Chapter 12 “Linker Script Generation”

4. 结语
  善用 overlay 技术可以更有效率地使用快速但昂贵的 SRAM,在执行时,容纳比 SRAM 实际大小更大的程序,设计出高效率小面积的 IC。

Continue Reading软件Overlay:程序编写与调试

中断处理模式:外部中断处理和内部中断处理的差异性

江继尧,资深工程师,晶心科技股份有限公司

  在现今 SOC 设计中,当周边装置(Peripheral IP)想要和中央处理器(CPU) 沟通时,最常使用的机制是透过中断(Interrupt)。周边装置可触发中断给中央处理器,当中央处理器接收到中断后,则可判断是由那个周边装置触发些中断, 接着处理相对应的中断处理程序(ISR,Interrupt Service Routine),藉此达到彼此沟通的目的。
  而 AndesCore™在中断处理方面,共支持两种模式:内部中断处理器(IVIC Mode,Internal Vector Interrupt Controller)和外部中断处理器(EVIC Mode, External Vector Interrupt Controller)。其中最大的差异性,即是中断控制器所存在的位置。在内部中断处理模式下,AndesCore™本身即设置了一个中断控制器存在于 CPU 内部,经由此中断控制器来处理相关中断的工作。而在外部中断处理模式下,用户必须在 CPU 外部实做一个中断控制器来处理相关中断工作。
  除了上述的差异性之外,在硬件方面的整合和软件方面的应用,也存在些许差异性。本文之目的除了介绍这些差异性外,也提供一个简单的设计平台供使用者参考。期望能对使用者有所帮助,也希望读者不吝指教提供您宝贵的意见。

1. 中断处理模式介绍
  AndesCore™共支持两种中断处理模式:内部中断处理器(IVIC Mode, Internal Vector Interrupt Controller)和外部中断处理器(EVIC Mode,External Vector Interrupt Controller)。以下的介绍将架构于 AndesCore™ N968A-S 这颗中央处理器。带领使用者循序渐进地,了解这两种中断处理模式的差异。

1.1 Definition
  AndesCore™ N968A-S支持两种中断处理模式,首先,我们先介绍关于这两种模式的定义。

1.1.1 IVIC Mode
  AndesCore™ N968A-S内部设计了一个中断控制器,所支持的中断来源数目可透过配置来决定。目前最大可支持16个中断来源,但可扩充至32个。请参考图表 1。若使用这存在于CPU内部的中断控制器来处理相关中断工作时,则为IVIC模式。假若SOC的中断来源大于32个时,使用者还是可以使用IVIC模式, 但是需要将多个中断来源合为一个中断讯号线(ex: OR function),且中断处理程序(ISR)在该中断讯号线触发时,需要去判断是由那个中断来源所触发。在N968A-S的IVIC mode之下,每个中断来源可以选定值为0~3的优先权 (priority). 优先权高的中断来源可以打断优先权低的中断来源。

1.1.2 EVIC Mode
  假若IVIC模式不符合用户所设计的系统,用户就需要选用EVIC模式。在此模式下,用户需要额外设计一个中断控制器,用来处理周边装置和中央处理器之间相关中断的工作,作为两者间沟通的桥梁。

图表 1. AndesCore™ N968A-S 所支持中断来源数目

1.1.3 Interruption Vector Entry Points
  为了加速中断处理的时间,AndesCore™ N968A-S内部实做了一个Interruption Vector Table。将不同的中断事件分别对应到不同的Vector Entry, 当中断发生时,CPU即可判断中断是由那个周边装置所触发,并跳到该中断所对应的Vector Entry,进而执行相关的中断处理程序(ISR)。
  在前面章节有介绍AndesCore™ N968A-S支持两种不同的中断处理模式。因此,在不同的中断处理模式下,也对应了不同的Interruption Vector Table。

1.1.3.1 Interruption Vector Table of IVIC Mode
  在IVIC模式下,所支持的中断来源可由用户来配置,支持的数目由2个到32 个。Interruption Vector Table相关信息如下:
 • 41 entry points (9 exceptions + 32 interrupts)
 • Address = IVB.IVBASE + (entry number) * IVB.ESZ (VEP: Vector Entry Point)

图表2. Interruption Vector Table of IVIC Mode

1.1.3.2 Interruption Vector Table of EVIC Mode
  在EVIC模式下,所支持的中断来源数目可达到64个中断。Interruption Vector Table相关信息如下:
 • 73 entry points (9 exceptions + 64 interrupts)
 • Address = IVB.IVBASE + (entry number) * IVB.ESZ

图表3. Interruption Vector Table of EVIC Mode

1.2 Signal Descriptions
  AndesCore™ N968A-S 提供相关中断讯号线,使得 CPU 可与周边装置或是外部中断控制器沟通。在 EVIC 模式下,除了中断来源讯号线之外,还包含了和外部中断控制器相互沟通的讯号线,详细讯号线叙述如下:

图表4. 中断相关讯号

  其中,evic_ireqval 和 evic_ireqack 这两个讯号线用来和外部中断控制器沟通。在 IVIC 模式下,周边装置的中断讯号可和 int_req[N:0]直接整合。当周边装置触发中断时,相对应的 int_req 讯号会拉起,告知 CPU 该周边装置触发了中断,CPU 即会跳到所对应的 Vector Entry 来执行相关的中断处理程序。
  而在 EVIC 模式下,外部中断控制器会负责处理周边装置的中断讯号。当周边装置触发中断时,外部中断处理器会负责和周边装置沟通,并将相对应的中断讯号(int_req)和中断需求讯号(evic_ireqval)发给 CPU,当 CPU 接收到中断时, 会将中断接收讯号(evic_ireqack)拉起,告知外部中断处理器收到中断,并去处理相关中断处理程序。
  相关处理程序可参考图表 5。在 ARC a 时,当 ireqack 讯号为 low 时,CPU 可等待周边装置触发中断。当周边装置触发中断,外部中断控制器将相对应中断讯号 int_req 和 ireqval 拉起,告知 CPU 有中断发生。在 ARC b 时,当 CPU 收到中断,则将 ireqack 讯号拉起,告知外部中断控制器已收到中断。在 ARC c 时,外部中断控制器将 ireqval 讯号拉下,并等待 CPU 将 ireqack 讯号拉下(在ARC d 时),表示 CPU 可接收新的中断触发。

图表5. EVIC Interrupt Request Level Transfer Sequence

1.3 System Register Setting
  关于上述两种中断模式的选择,用户可透过设定 AndesCore™ N968A-S 内部的一个 system register 来达到目的。
  该 system register 为 Interruption Vector Base Register(ir3)。其中的第 13个 bit 决定不同的中断模式。其格式如下:

2. Reference Design Architecture
在介绍完中断处理模式相关定义之后,本章节提供在实际整合与应用上的范例,让用户可更了解在不同中断处理模式下的差异。

2.1 主要架构
  本次所实作的 Reference Design 主要是架构在 Andes mini-platform 上,搭配 AndesCore™ N968A-S 为主要 CPU 来控制相关周边装置。其主要架构如下图:

图表 8. Architecture of Reference Design

将 AndesCore™ N968A-S 整合在 AHB-Lite Bus 上,藉由 APB Bridge 和 APB Bus 沟通,而相关的周边装置则整合在 APB Bus 上。在本次范例中,主要会用到GPIO 和INTC(中断控制器)这两个周边装置,在不同的中断模式下,利用GPIO 来触发中断,再透过 INTC 与 CPU 沟通,观察不同中断模式下中断的处理方式。

2.1.1 Design Scenario in IVIC
  在 IVIC 模式下,由 GPIO 触发中断(gpio_int signal),直接将中断传递给CPU(int_req signal)。当 CPU 接收到中断时,即可去处理相关的中断处理程序。相关装置之间的整合如下图所示:

图表 9. Design Scenario in IVIC

2.1.2 Design Scenario in EVIC
  在 EVIC 模式下,由 GPIO 触发中断(gpio_int signal),INTC 收到中断后, 会将中断讯号和相关沟通讯号传递给CPU(int_req signal & evic_ireqval signal)。当 CPU 接收到中断时,会将响应讯号拉起(evic_ireqack signal),告知 INTC 收到该中断,并去处理相关的中断处理程序。相关装置之间的整合如下图所示:

图表 10. Design Scenario in EVIC

2.2 Example Code
  以下将 Reference Design 中,就本次中断处理模式相关的整合程序部分和测试程序部分,摘要出来说明。

2.2.1 整合程序部分
  在系统整合部分,包含 AndesCore™ N968A-S 和 INTC 在不同的模式下, 整合相关的讯号线,其中透过 EVIC_MODE 参数来进行不同模式间的切换。

AndesCore™ N968A-S 相关 RTL 片断:
evic_ireqval 讯号在 EVIC 模式下由 INTC 触发给 CPU,在 IVIC 下可直接给予 0 值。int_req 由 INTC 或中断来源传递给 CPU,告知 CPU 中断产生。evic_ireqack 在 EVIC 模式下由 CPU 触发给 INTC,告知 INTC 收到中断。

INTC 相关 RTL 片断:
  此中断控制器可透过 evic_mode 这个输入讯号,来决定该装置是处于 IVIC 模式或是 EVIC 模式,因此,在 EVIC 模式下,给予 1 值,设定为 EVIC 模式, 在 IVIC 下,给予 0 值,设定为 IVIC 模式。ireqack 讯号在 EVIC 模式下由 CPU 触发给 INTC,告知 INTC 已收到中断,在 IVIC 模式下则给予 0 值。

2.2.2 测试程序部分
  在测试验证部分,包含 AndesCore™ N968A-S 在不同中断模式下的设置、INTC 相关中断状态的设置和 GPIO 触发中断的设置。

AndesCore™ N968A-S 相关程序片断:
  AndesCore™ N968A-S 支持两种中断处理模式,透过 CPU 内部的 system register 来设置。主要为设置 Interruption Vector Base Register,该 register 的第 13 个 bit 用来定义 CPU 处在何种中断处理模式。在 EVIC 模式下,需将该 bit 设置为 1,在 IVIC 模式下,则将该 bit 设置为 0。

INTC 相关程序片断:
  INTC 通常支持不同的中断触发方式,包含 Interrupt Masking、Interrupt Trigger Mode、Interrupt Trigger Level …等。在开始使用每个中断来源之前,这些控制选项都必须在 INTC 上设定正确。

 

3. 模拟结果
  将上述的 Reference Design 整合完成后,搭配测试程序进行仿真,并藉由波形图来观察不同中断模式下,相关中断讯号线的变化。

3.1 IVIC 模拟结果
在 IVIC 仿真环境中,主要测试程序如下:
 • 由 GPIO 触发一中断,并将中断传递给 給 CPU 
 • CPU 接收到中断后,执行相对应的中断处理程序
仿真结果如图表 11 所示,当 GPIO 触发中断后,将中断直接传递给 CPU,在CPU 端的 int_req 讯号线会触发,表示有中断发生。当 CPU 收到中断讯号后, 接着会处理相对应的中断处理程序。

图表 11.Simulation Waveform of IVIC

3.2 EVIC 模拟结果
在 EVIC 仿真环境中,主要测试程序如下:
 • 由 GPIO 触发一中断
 • 此时 INTC 设罝为 EVIC 模式,并将中断讯号和相关沟通讯号传递给CPU
 • CPU 接收到中断后,会将响应讯号拉起,告知 INTC 收到该中断,并执行相对应的中断处理程序

  仿真结果如图表 12 所示,当 GPIO 触发中断后,INTC 将中断和相关沟通讯号(ireqval)传递给 CPU,在 CPU 端的 int_req 讯号线和 evic_ireqval 讯号线会触发,表示有中断发生。当 CPU 收到中断讯号后,会将 evic_ireqack 讯号线拉起,告知 INTC 收到中断。仿真结果如同章节 1.2 和图表 5 所论述。

图表 12. Simulation Waveform of EVIC

结语
在 AndesCore™ N968A-S 所提供的两种中断模式里,其中的 IVIC 模式使用CPU 内的中断控制器来处理中断,此模式对用户来说,只要将中断来源和CPU 端的中断讯号连接即可,相当容易整合。若用户所设计的系统里,中断来源数目超过 IVIC 模式所支持,或者系统需要更复杂的优先权选择时,则可选用 EVIC 模式。在 EVIC 模式下,用户需额外设计外部中断控制器,并整合相关沟通讯号。因此,用户可根据本身系统的复杂度和整合的难易度,来选择适合的中断处理模式。

Continue Reading中断处理模式:外部中断处理和内部中断处理的差异性

如何应用AndesCore™ EDM 安全访问机制

沈永胜,技术副哩,晶心科技股份有限公司

EDM 安全存取是 AndesCoreTM 内建的功能(option),应用在安全存取的控管。EDM 安全存取有二种的控管方式:debug access indication 和 EDM access restriction。第一种控管方式(debug access indication)提供了一个 sideband signal 用于指示从调试器(Debug host)的请求。第二种控管方式, 控制AndesCoreTM 的 input port(edm_restrict_access )达到 EDM 存取的限制。更详细的内容在后续章节会有更深入的介绍。

1. EDM功能介绍
  一个 debug system 包含一个 debug host 和一个 target system。EDM 主要的功能就是 translate debug host 发出的 TAP 指令來存取系统 memory 或是 CPU。图表 1 为基本的 debug 系统方块图:

图表 1 基本的 debug 系统方块图

图表 2 說明 TAP 指令的种類:

图表 2 TAP 指令的种類

2. 控制EDM存取的限制
  使用 EDM 的访问方式会被一个 sideband signal (edm_restrict_access) 所影响。当这个 signal 值是 high,仅仅只能对 EDM MISC registers 做讀取的动作。而想要存取CPU/System Bus/Local Memory 的动作将会被封锁住并且会得到下面的结果:

  •  讀为零写忽略
  • 不正确的 JTAG instruction(JTAG ICE debugger 会 timeout)

图表 3 說明 EDM 限制存取方块:

图表 3 EDM 限制存取方块图

在启用存取限制功能后,图表 4 說明出每个 TAP 指令的行为:

图表 4 TAP 指令的行为

如何实现 EDM 存取限制,在系统设计上有很多种实现方法,以控制 edm restrict access 的 signal。兩种基本的设计方案說明如下:

  • eFUSE 方式使用 Chip 重新编程管理控制
  • SOC 方式使用软件管理控制

图表 5 所示为 hardware 实现控制 edm_restrict_access 的示意图如下:

图表 5   Hardware 实现控制 edm_restrict_access 的示意图

software 实现控制 edm_restrict_access的例子如下:

  • sethi $r2,#0x80000
  • ori $r2,$r2,#0x8c
  • sethi $r3,#0x04030
  • ori $r3,$r3,#0x201
  • swi $r3,[$r2+#0]

3. EDM 存取指示
  AndesCoreTM 增加一个额外的 sideband signal,xdebug_access(active-high),根据此 sideband signal 來决定 request 的 host 是否为 EDM。而 device 就能根据此 sideband signal 决定是否要把 request 的 data 内容传回到host。

sideband signal 的名称根据 bus interface 的類型而有所不同。对于AndesCoreTM 处理器,基本的信号名称如下所示:
• AHB/AHB-Lite => hdebug_access
• APB => pdebug_access
• EILM => eilm_debug_access
• EDLM => edlm_debug_access

3.1. debug 存取識别信号控制
  当 debug exception 发生后,CPU 将进入debug mode。然后 CPU 将会留在 debug access mode 直到CPU 执行到 IRET instruction 并且 trusted_debug_exit 是处于high 后CPU 将離开 debug access mode,反之 trusted_debug_exit 如果是low, CPU 将会保留在debug access mode。
实现控制 trusted_debug_exit 信号,有二种可供选择的方式如下:
• trusted_debug_exit 信号总是给 high
增加一个权限管理邏辑去控制trusted_debug_exit 信号是high 或是 low 权限管理邏辑方块图如图表 6 所示:

图表 6 权限管理邏辑方块图

如何控制 trusted_debug_exit 信号时序图如图表 7 所示:

图表 7   如何控制 trusted_debug_exit 信号时序图

如下例子說明了如何产生 trusted_debug_exit 控制信号的verilog code:

  • The code example (Verilog) of trusted_debug_exit generation is described below:
  • //
  • //— Utilize passcode to generate trusted_debug_exit in AHB Bus Controller
  • //* assume zero-wait-state AHB access
  • parameter AUTH_CODE = 32’h0a0b0c0d;
  • always @(posedge hclk or negedge hreset_n) begin
  • if (!hreset_n) begin
  • passcode_reg <= 32’d0;
  • end
  • else if (passcode_wen) begin //debugger enters passcode through debug access
  • passcode_reg <= hwdata[31:0];
  • end
  • end
  • //validate passcode to generate trusted_debug_exit
  • assign trusted_debug_exit = (passcode_reg == AUTH_CODE);

3.2. debug 存取指示应用
图表 8 說明 AHB bus 如何使用 hdebug_access 和验证邏辑來防止惡意的 debug存取

图表 8   AHB bus 如何使用hdebug_access 和验证邏辑來防止惡意的 debug 存取

如下 verilog code 說明了如何使用 hdebug_access 信号:

  • //— Use hdebug_access to prevent malicious debug access in AHB Bus Controller
  • //* assume zero-wait-state AHB access
  • parameter IRRELEVANT_DATA = 32’hcafe0001;
  • parameter AUTH_CODE = 32’h01020304;
  • always @(posedge hclk or negedge hreset_n) begin
  • if (!hreset_n) begin
  • dbg_acc_d1 <= 1’b0;
  • end
  • else begin // data phase indication of debug access
  • dbg_acc_d1 <= hdebug_access;
  • end
  • end
  • always @(posedge hclk or negedge hreset_n) begin
  • if (!hreset_n) begin
  • passcode_reg <= 32’d0;
  • end
  • else if (passcode_wen) begin //debugger enters passcode through debug access
  • passcode_reg <= hwdata[31:0];
  • end
  • end
  • //validate passcode to check authentication
  • assign auth_check_fail = (passcode_reg != AUTH_CODE);
  • //return irrelevant data if the authentication check of debug access fails
  • assign hrdata_out = {32{data_read_en}} &
  • ((dbg_acc_d1 & auth_check_fail) ? IRRELEVANT_DATA : normal_data_out);

4. 实际的应用
  使用者经由上面的介绍完成了权限管理邏辑后,并且挂在 AndesCoreTMAHB bus 上,再经由仿真器(Cadence)仿真此权限管理邏辑的行为,如下面几张图所示:

• edm_restrict_access 信号控制
图表 9 說明由 sw code 把 edm_restrict_access signal disable

图表 9   由 sw code 把 edm_restrict_access signal disable

• trusted_debug_exit 信号控制

图表 10   经由 debug access 把 trusted_debug_exit signal 设定成high

• debug_access 信号
图表 11 說明经由 debug host 來做存取时,debug_access signal 会从 low 变成 high:

图表 11   经由 debug host 來做存取时,debug_access signal 会从 low 变成 high

图表 12 說明经由执行 IRTE instruction 时,debug_access signal 会从 high 变成 low:

图表 12   经由执行 IRTE instruction 时,debug_access signal 会从high 变成 low

5. 结语
EDM 安全存取是 AndesCoreTM 保护周边装置内容不被窃取的功能,也因为越來越多客户使用到此功能,所以撰写此技术文章让客户更能进一步了解到此功能的用途,让客户能够很快速的上手,并且使用晶心开发的 EDM 安全存取是一件愉快与简单的工作。

Continue Reading如何应用AndesCore™ EDM 安全访问机制

当高速AndesCore™遇上低速 Embedded Flash的晶片效能提升方法

陈群旻,技术副理,晶心科技股份有限公司

  AndesCore™除提供 AHP,APB ,HSMP 接口外,亦可透过 EILM 接口与内存整合,使 AndesCore™可以不透过 AMBA BUS 直接透过 EILM 接口撷取指令。然而嵌入式 Flash 的执行速度目前,并不能赶及 AndesCore™的工作频率, AndesCore™的执行效能将受限于嵌入式 Flash 的执行速度。此时可透过在 AndesCore™与 Flash 间的 EILM 接口之间加入一个预取模块,减少 AndesCore™因为 Flash throughput 跟不上 AndesCore™ 效能,使执行效能下降的影响。文章中所提供的参考预取模块,以 data width 32 bits 的 Flash 为操作对象,预取 buffer size 为两道 Instructions(32bits*2)提供一预取机制的设计参考。
  本文之目的在提供与介绍一个预取模块的参考设计作为用户设计预取模块的参考。期望能对使用者有所帮助,也希望读者不吝指教提供您宝贵的意见。

1. Prefetch design 界面介绍
  AndesCore™透过 EILM 接口可与外部 external local memory 整合,为了透过 Prefetch 模块根据前一道指令撷取时的地址,以 AndesCore™将循序撷取指令为预测逻辑来预取下道指令,并储存该指令内容于 Prefetch 模块,供 AndesCore™循序撷取指令时使用,我们将原本 AndesCore™与 EILM 的整合方式(如图一所示),改为在 AndesCore™与 EILM 之间加入 Prefetch 模块的整合方式(如图一所示)。
  AndesCore™透过 EILM 接口跟 Prefetch 模块提交 request,Prefetch 模块透过 eilm_wait 告知 AndesCore™该 request 执行是否需要 wait,并在对应的时序提供 AndesCore™欲撷取的指令内容。
  Prefetch 模块另有接口与 memory (Flash or ROM)整合,透过该接口进行对 memory 的读取。由于坊间 Flash or ROM 有各种 protocol,Andes 提供的 Prefetch reference design 主要专注于提供 prefetch 机制的参考设计,memory 接口以一 pseudo Flash 接口为设计对象,用户后续可根据所使用的 memory 的 protocol 进行调整设计。

1.1 Block Diagram  

1.2 Signal Descriptions
Prefetch 模块的 clock 与 reset,与 AndesCore™使用相同的 clock,reset 讯号源作设计,此外有一 input 讯号”ratio”用以设定 AndesCore™与 memory 工作频率倍率关系。其余讯号,我们分作两个群组”EILM”与”MEM”分别说明。

  1.2.1. Global signals

  1.2.2. EILM
  Prefetch 模块透过 EILM 接口与 AndesCore™整合,依循 AndeStar 所定义的 protocol 与 AndesCore™沟通。

以下时序图说明 EILM 接口 Read/Write 时的讯号

1.2.3. 本次仿真使用的 Flash 接口的讯号
  Prefetch 模块的 memory 接口以一 pseudo Flash 接口为设计对象。并以此 memory 的 behavior module 与 Prefetch 模块整合后仿真。以下图表介绍此 pseudo Flash 之讯号与工作之时序。

图表 8 Pseudo Flash Timing Diagram
图表 9 Pseudo Flash AC Characteristics

2. Prefetch 模块的主要功能介绍
  透过 Prefetch 模块来提升 AndesCore EILM 撷取指令时的效率,减少 AndesCore 提出指令 request 后,等待 read data 自 Flash 回复有效值的等待时间,来增加 AndesCore 的执行效能。
  实现方式是以前次 AndesCore 提出指令 request 时,所发出的 address 来预测后续 AndesCore 提出指令 request 的 address 为递增方式,在 AndesCore 提出指令 request 前,Prefetch 模块先将该递增 address 的指令内容由 Flash 取回并储存于 Prefetch 模块中,当 AndesCore 提出指令 request 的 address 确为递增方式,且指令内容已在 Prefetch 模块中,AndesCore 将不需 wait,可在下一时序即可自 Prefetch 模块撷取指令内容。
  若 AndesCore 提出指令 request 的 address 为非递增方式,或是 AndesCore 提出指令 request 的频率高过 Prefetch 模块预取数据的频率,Prefetch 模块中已无事先预取的指令内容时,则依然透过 wait 讯号来延迟 AndesCore 撷取指令内容。

2.1 预取功能说明
  图表 10 所示为 Prefetch 模块自 Flash 撷取指令内容的 function 示意图

图表 10 Prefetch 模块自 Flash 撷取指令内容的 function 示意图

Reset 后, Prefetch 模块内并无预取的指令内容,于是执行 general prefetch function,后续当 AndesCore 提出指令 request 为递增方式,若指令已预取完成,则将指令内容传给 AndesCore,若指令预取未完成则拉 wait 讯号来延迟 AndesCore 撷取指令内容。再以目前 request 的 address 递增来预取指令。当 AndesCore 提出指令 request 不为递增方式(本文后续称为 branch),则拉 wait 讯号来延迟 AndesCore 撷取指令内容,同时 Prefetch 模块自 Flash 撷取该指令,当 Prefetch 模块得到有效数据时,撤回 wait 讯号,并将有效数据传给 AndesCore。再以目前 request 的 address 递增来预取指令。

2.2 主要程序说明
以下我们剪辑 Prefetch 模块 RTL 程序中几个重要部分来做说明

  2.2.1 branch 判断:
  当一个 AndesCore™ request (instruction fetch)被 Prefetch 模块接受时,若此 时的 address 不等于预设的递增 address,表示一个 branch 发生,Prefetch 模块将跟据 branch 时应有的动作来对 Flash 读取指令,使用 wait 讯号来延迟 AndesCore,选择 read data 等。


相关程序片断:
assign    branch= eilm_read_req_valid&((lastest_eilm_ifetch_addr_inc1!=eilm_addr)|eilm_ifetch_n);

  2.2.2 prefetch 判断:
  当 Prefetch 模块处于 idle 状态时,若需要被预取的指令内容,未储存于 Prefetch 模块,则进行 prefetch 的动作,对 Flash 读取指令,并存放至 Prefetch 模块。 Prefetch 模块预取深度我们设计为 2,故我们会预取下一道 (lastest_eilm_ifetch_addr_inc1)及下下一道(lastest_eilm_ifetch_addr_inc2)指令。

相关程序片断:
assign     prefetch_next1= (state_cnt==4’h0)& (~wait_for_write)&
                                                              (~((lastest_eilm_ifetch_addr_inc1==addr0)&addr0_valid )&
                                                                 ~((lastest_eilm_ifetch_addr_inc1==addr1)&addr1_valid ));
  assign      prefetch_next2= (state_cnt==4’h0)& (~wait_for_write)&
                                                                  (~((lastest_eilm_ifetch_addr_inc2==addr0)&addr0_valid )&
                                                                      ~((lastest_eilm_ifetch_addr_inc2==addr1)&addr1_valid ));

  2.2.3选择执行branch, prefetch 或 idle
  当 Branch 发生时,不论需要被预取的指令内容是否已储存于 Prefetch 模块,执行 branch 时应有的动作,若有 prefetch 的动作执行中则放弃。
当Branch 未发生时,需要被预取的指令内容未储存于 Prefetch 模块,执行 prefetch时应有的动作,若需要被预取的指令内容已储存于 Prefetch 模块,Prefetch 模块处于 idle。

相关程序片断:

 

 

 

 

 

 

 

 

 

2.2.4 选择 read data:
  若 Prefetch 模块处在执行 branch 时应有 function 的动作,自 Flash 于数据有效时撤回wait 讯号,选择 DO (Flash read data)作为响应给AndesCore 的read data。若 AndesCore 提出指令 request 为递增方式,则以预取的指令内容,作为响应给 AndesCore 的 read data。

相关程序片断:

 

 

 

 

2.2.5 储存预取的指令内容:
  当进行 prefetch 的动作完成时,更新预取的指令内容。
A_latch 为进行 prefetch 的动作发 request 给 Flash 时所发出的 address,我们以 A_latch 最后一个位选择要储存于两个 buffer 中的哪一个。

相关程序片断:

 

 

 

 

 

 

 

 

 

 

 

 

2.3 波形圖說明
 
以下小节,为 After Reset, Branch, Sequential 三种状况下的波形图以及说明。

 

 2.3.1. After Reset

图表 11 After reset 波形图

波形图说明:


 

 

 

 

2.3.2. Branch fetch
 

图表 12 branch fetch 波形图

波形图说明:

 

 

 

 

 

 

2.3.3. Sequential fetch

图表 13 sequential fetch 波形图

波形图说明:

 

 

 

 

 

 

 

 

 

3. Instruction fetch效能改善
   
由于参考模块,以 32 bits Flash 为设计对象,默认 AndesCore™ frequency 与 Flash frequency 为 n:1 (n≧2),Instruction fetch performance 受限 Flash 输出频率,故未能有明显提升。
 
当Flash 扩充带宽为64 bits,使Flash 输出及上AndesCore™指令消耗速度后, Instruction fetch performance 将会有明显提升。
 
Andes 已有客戶參考此設計,並加以修改,使之支援頻寬為 64 bits之Flash。以 AndesCore™ frequency 與 Flash frequency 為 2:1 下,由原本 fetch 一道指令平均需要兩 cycle 增進為 fetch 一道指令平均需要 1.1cycle。Instruction fetch 效能改善 80%左右。

  Instruction fetch 效能改善可透过下列公式计算。
Instruction fetch performance improvement = ( 2/(1+ branch instruction ratio)
-1)*100%
(当branch 发生时,由于欲 fetch 的指令不在prefetch 内,此时仍需花费 2cycle fetch 该指令。)

4. 结语
   
AndesCore™所提供的 EILM 接口相当方便客户与 Flash 或 ROM 整合,然而 Flash 或 ROM 目前最高速 access time 目前不能与AndesCore™所能实现的最高工作频率相同。AndesCore™的执行效能将受限于 Flash 或 ROM 目前最高速 access time。Prefetch 模块提供一预取的机制来增加 AndesCore™与 Flash 或 ROM 整合时的执行效能。文章中所提供的参考预取模块,以 data width 32 bits 的 Flash 为操作对象,提供一预取机制的设计参考。使用者可参考此设计概念,将 data width 32 bits 的 Flash 为操作对象改为 data width 64 bits 的 Flash,在增加此设计后, Instruction fetch performance 将可得到符合使用者期待的效果。

Continue Reading当高速AndesCore™遇上低速 Embedded Flash的晶片效能提升方法

如何在晶心平台实作ROM patch

赖歆雅,技术经理,晶心科技股份有限公司

笔者曾协助多家公司工程师,在 AndesCore™上发展 firmware。我们发现,当客户开发 Non-OS 的程序代码,最常遇到的问题在于开发者不知如何撰写 linker script。网络上有 GNU ld 的使用文件,但是 linker script 的范例太少,尤其开发者需要撰写进阶的 linker script,常常不知如何下手。

本篇文章我们分享如何实作 ROM patch。使用晶心 CPU 建构的 embedded system,一般具有 CPU、外围 IP 及 RAM、ROM。部份客户使用 ROM code开机,程序代码放在 ROM 内,data section 放在 SRAM 里。ROM code 的特性是成本低,跟着 IC 光罩一起生产,当 IC 制作完成即不可修改,若有制作上的错误或是程序代码逻辑上的错误,只能用 ROM patch 的方式修补。也就是将需要修补的程序代码放到小容量的 flash 里。这就是我们今天要分享的技术。

1. 主程序架构
  首先介绍主程序的架构。IC主的程M序emory layout 如下图。

图表1  主程序的 memory layout 图

红色框线的部份,为主程序编译的范围。主程序 main 会呼叫到 func1、func2
和 func3 这 3 个 function。

在上图中,黄色区域是 IC 的 ROM,这部份的程序是 IC 制作出来即不可以改变。绿色部份是 flash。在图中,flash 分成 2 区,一个是 jump_table,存放 func1~func3的地址。剩余的空间 FUNC_PATCH,预留给 patch 使用。

为了要修补 ROM 内的 function,所以规划出 jump_table 区域,原本都是指向 ROM 的 function。如果 ROM 里的部份 function 损坏或是需要改写,就把 jump_table 改为指向 FUNC_PATCH 里新建的 function。

   1.1 源代码
  主程序的程序代码如下:(main.c)

 1.2 主程序 linker script (仅列需要修改的部份)

Flash 的地址由 0x510000 起,将 FUNC_TABLE 固定在 flash 的最开头,语法如上。

   1.3 主程序执行结果

2. 经过Patch之后的架构图
假设ROM里的func2 损坏,要改用flash里的func2。需要更改指向func2的指标,及func2的内容。如下图:

图表2 ROM patch 的 memory layout 图

用红色框线标起来的地方,表示为 patch 编译的范围。其中 jump table 在这里重新编译,指向新的地址。

   2.1 实作方法
  (1) 导出主程序的 symbol table。
在主程序的 Linker flags 加上-Wl,–mgen-symbol-ld-script=export.txt ,ld 会产生 export.txt 这个档案, 这个档案包含了一个 SECTION block 以及许多变数的地址。如下图所示。

图表 3 主程序的 symbol

Linker script 在 import Main program 的 symbols 时,除了需要修改的 func2不要 import 之外,其他的 symbols 全部要 import 进来。(将 export.txt 删去这一行: func2 = 0x005001c4; /* ./main.o */)


   (2) patch 在编译之前,先汇入主程序的 symbol table。(将 export.txt 档案放在一起编译)。Patch 的 linker script 要汇入主程序的 symbol,写法如下面红色字体。

   (3) patch 的程序代码里如下,没有 main function,也不要加入 startup files。改写 func2。func2 放在 flash 的 FUNC_PATCH section。并且将 jump_table里的 func2,改成指向新的 func2。

   (4) patch 的 linker script,加入 FUNC_PATH 在 jump_table 之后。

3. 如何除错
首先,将程序代码存放在 IC 的 ROM 及 flash 里。(本文为了示范,我们的做法是在 AndeShape™ ADP-XC5 的 FPGA 板上,用 RAM 模拟 ROM 及 flash,分别将主程序和 patch 的 bin 文件 restore 到板子上。)

当 gdb debug 时,载入 patch 的 symbol。以下节录 gdb 指令。

上面过程中,先加载 main 的 symbol,再加载 patch 的 symbol 及 debug information。”add-symbol-file patch.adx 0x500000 -s FUNC_TABLE 0x510000 -s FUNC_PATCH 0x510020″是将 patch section 的symbol 及 debug information 也载入 gdb 以 debug。读者可以在 gdb 里,打”help add-symbol-file”查阅 add-symbol-file 的用法。

   3.1 主程序 patch 后的执行结果

4. 结语
目前晶心科技使用GNU的toolchain,其功能非常强大。读者可多动手试试不同的linker script写法,使得开发firmware更有弹性及效率。

5. 参考数据
gnu linker ld manual
http://sourceware.org/binutils/docs-2.22/ld/index.html

6. 作者简历
赖歆雅,女,台湾省新竹县人。1977 年出生,2002 年毕业于台灣成功大学电机研究所 VLSI/CAD 组硕士班。
2002~2005 年就读台灣成功大学电机研究所 VLSI/CAD 组博士班(肄业)。
2005~2010 年任职于工业技术研究院,担任副工程师,负责 Linux 上的软件开发。
2010~2012 年任职于晶心科技,担任技术经理,负责客户的技术支持。

Continue Reading如何在晶心平台实作ROM patch