第五节定制NiosIIAvalon用户外设利用SOPCBuilder的组件编辑器,可创建和编辑用户的Avalon外设。一个Avalon外设(组件)的典型构成:●硬件描述文件(HDL模块)●软件文件(定义组件寄存器映像的C语言头文件以及相应的驱动程序)●组件描述文件(class.ptf):由组件编辑器自动生成,定义组件的结构,为SOPCBuilder提供系统集成时所需要的信息。例:设计一个Avalon从外设,实现PWM功能。总体设计周期寄存器count占空比寄存器dutyAvalon从端口减1计数器PWM输出控制OUT总线时钟地址片选Avalon从信号数据复位写计数值duty时,输出out为1;计数值≤duty时,输出out为0。VerilogHDL描述QuartusII仿真验证注意:实际计数周期=count+1占空比如何计算?在SOPCBuilder中添加用户IP在已建立的SOPC设计中,添加用户IP。双击进入SOPCBuilder已建立的SOPC系统结构由此进入用户逻辑编辑器若需要,在此添加HAL有关文件。例如:寄存器映射头文件,驱动程序,demo例程等。基于Avalon的用户逻辑(从设备)硬件结构Avalon接口Avalon从信号状态寄存器控制寄存器数据寄存器1数据寄存器2其他寄存器任务逻辑与应用相关的接口信号基于Avalon用户逻辑(从设备)的相关软件设计文件(文件夹)名描述/pwm_hw该文件夹包含硬件描述文件my_pwm.vpwm的VerilogHDL代码/pwm_sw该文件夹包含软件接口的C文件/inc定义底层硬件的C语言头文件avalon_slave_my_pwm_regs.h/HAL包含Nios处理器的HAL驱动文件/inc包含HAL驱动文件的C头文件altera_avalon_my_pwm_routines.h声明访问硬件的函数原型/src包含HAL驱动文件的源代码altera_avalon_my_pwm_routines.c定义访问硬件的函数/test_software包含软、硬件测试例程hello_altera_avalon_my_pwm.c测试程序请同学总结开发Avalon用户从设备(用户IP)的基本步骤参考1《NiosII嵌入式软核SOPC设计原理及应用》P445参考2《SOPC嵌入式系统基础教程》P291第六节NiosII软件开发一、NiosIIIDE为软件开发提供四个主要功能:工程管理器新工程向导软件工程模板软件组件引导建立C/C++应用程序工程和系统库工程软件代码实例HAL系统库、轻量级IPTCP/IP库、uC/OS实时操作系统(RTOS)、Altera压缩文件系统。编辑器和编译器文本编辑器(成熟、全功能)C/C++编译器(GCC)自动生成基于用户特定系统配置(SOPCBuilder生成的PTF文件)的makefile。它自动映射NiosIIIDE中的任何改变。调试器通过JTAG调试模块与目标硬件相连。基本调试功能——运行控制、调用堆栈查看、软件断点、反汇编代码查看、调试信息查看、指令集仿真器。高级调试功能——硬件断点调试ROM或闪存中的代码、数据触发、指令跟踪。闪存编程器●烧写CFI接口的闪存器件●烧写主动串行配置器件EPCS二、硬件抽象层(HAL)系统库当用户在NiosIIIDE中创建一个新的软件工程时,根据与之绑定的NiosII硬件系统(PTF文件),自动生成HAL库。即:NiosIIIDE和SOPCBuilder紧密相关。硬件配置变化→PTF文件自动变化→HAL库自动变化。HAL提供了相关设备的驱动程序,用户只要利用HAL提供的各种函数就可以编写应用程序。HAL应用程序接口(API)与ANSIC标准库综合在一起,可使用printf()、fopen()、fwrite()等类似C语言的库函数来访问硬件设备。用户应用程序C标准库HALAPI设备驱动设备驱动……设备驱动NiosⅡ处理器系统硬件HAL系统库的结构HAL系统库的服务•与标准的C函数库集成;•提供对每一个设备的驱动;•提供一致的、标准的应用程序接口;•系统初始化;•设备初始化。_exit()open()close()opendir()closedir()read()fstat()readdir()getpid()rewinddir()gettimeofday()sdrk()ioctl()settimeofday()isatty()stat()kill()usleep()lseek()wait()write()用户程序访问硬件设备的方法:(1)调用C标准库函数;例如:printf()和fwrite()(2)调用HAL的API函数;(3)调用设备驱动程序;(4)直接访问设备寄存器。例如:write()、usleep()例如:alt_avalon_uart_write()例如:IOWR_ALTERA_AVALON_UART_RXDATA(base,data)HAL为嵌入式系统中最常见外围设备提供了通用的设备模型,它们具有相同的、与硬件细节无关的应用编程接口(API)。通用设备类型对应AlteraNiosII系统字符型设备UART核、JTAG核、LCD16207显示控制器文件子系统只读文档系统DMA设备DMA控制器核定时器设备TIMER定时器核Flash设备通用Flash接口(CFI)芯片控制器主动串行配置芯片EPCS控制器以太网设备uC/OS支持的LAN9111以太网MAC/PHY控制器数据宽度及HAL类型定义ANSIC的数据类型没有非常确切地定义数据宽度,取决于编译器的定义。HAL使用alt_types.h头文件定义了一套支持ANSIC的数据类型。类型说明alt_8有符号8位整数alt_u8无符号8位整数alt_16有符号16位整数alt_u16无符号16位整数alt_32有符号32位整数alt_u32无符号32位整数HAL数据类型定义类型说明char8位short16位long32位int32位对ANSIC数据类型的支持HAL对系统启动的支持启动——系统上电复位后到运行main()函数之前,初始化硬件,构建应用程序运行环境的过程。NiosII的HAL系统库为用户提供了这段代码,如果用户采用链接器(Linker)的默认设置,则自动链入HAL提供的初始化函数,实现系统的启动和初始化过程。启动文件位于“.\altera\kits\nios2\components\altera_nios2\HAL\src\crt0.s”程序入口标号“_reset”,功能:1.初始化指令Cache,然后调用_start;2.初始化数据Cache,把异常向量表装入指令Cache;3.设置堆栈指针(SP)和全局指针(GP)寄存器;4.把全局变量和静态变量区(_bss_start~_bss_end)清零;5.如果没有bootloader,则把可读写数据(.rwdata)、只读数据(.rodata)和异常向量表装入RAM中;6.调用alt_main(),进一步初始化。alt_main()对CPU和外设进行初始化1.若使用操作系统,调用alt_os_init()初始化OS;2.若使用OS,则初始化访问HAL文件系统的信号量;3.初始化中断控制器,开中断;4.调用NiosIIIDE自动创建并管理的alt_sys_init()初始化系统设备及软件模块;5.将标准输入/输出设备(stdin、stdout、stderr)映射到输入/输出通道;6.使用the_do_ctors()函数调用C++的构造器;7.在系统关闭时调用C++解构器;8.调用main()函数;9.调用exit()函数,执行结束代码。HAL与异常处理当异常发生时,跳转到异常处理地址,处理器执行一段由HAL插入的代码。其中包括判断中断源和中断优先级,然后跳转到用户的中断服务子程序(ISR)。即:除了ISR外,保护现场、查找中断源、恢复现场、中断返回等工作均由HAL系统库代码替用户完成。保护现场查中断源调用相应的ISR恢复现场中断返回HAL提供isr_name(void*context,intid){/*用户代码*/}用户编写的中断服务程序为方便用户创建和维护中断服务程序,HAL系统库的alt_irq.h提供中断API函数。如何使用HALAPI函数编写ISR?第一步:参照下列函数原型编写ISRviodisr_name(void*context,alt_u32id)函数名全局变量指针,指向传递给ISR的信息。在system.h中声明的硬件中断号,例如:UART_IRQ第二步:调用下列API函数注册中断服务程序intalt_irq_register(alt_u32id,void*context,void(*isr)(void*,alt_u32))指向ISR的函数指针中断服务程序主要处理一些高优先级、实时性强的操作,所以,ISR中不能有等待或阻塞性操作。1.尽量保持ISR精简;2.无关紧要的事件应在ISR之外处理;3.尽量避免调用C库函数(如:printf());4.尽量避免进行浮点操作;5.很多HALAPI函数不能在ISR中调用。ISR的调试1.在ISR中设断点。当中断发生时,处理器在断点处停下,用户可单步调试ISR代码。但此时忽略了其它硬件中断。2.使用sprintf()函数,把关键数据写到内存,然后触发外部分析程序。三、与目标系统相关的system.h文件第一次编译NiosIIIDE软件工程时,编译工具根据硬件系统文件(.ptf文件)和系统库的配置生成一个system.h头文件。system.h的构成:(1)系统库的设置信息,如果用户选择使用uC/OS支持,还包括uC/OS的配置信息。(2)每个外围设备的详细信息:硬件配置、基地址、中断优先级、设备名称。见一个实例文件