Nios开发--ucos2


文章摘要:
Nios2已经移植好了ucos2的相关代码,只需要进行简单的配置即可使用;


硬件平台:EP4CE6F17C8
开发环境:Quartus II 13.1/Nios II 13.1
参考文档:Nios II Software Developer’s Handbook


添加SysTick定时器
由于ucos2需要一个毫秒级的系统时钟来实现节拍(Time Tick),所以需要创建一个周期为1ms的Interval Timer组件;


创建基于ucos2的BSP
创建基于ucos2的BSP


BSP配置
BSP配置


示例代码:

#include "regs.h"
#include "unistd.h"
#include <os_cfg.h>
#include <ucos_ii.h>
#include <stdio.h>
//----------------------------------
OS_STK LedTaskStk[OS_TASK_TMR_STK_SIZE];
void LedTask(void *pdata)
{
    for(;;)
    {
        rLEDS = 0x55;
        //OSTimeDlyHMSM(0,0,0,100);
        OSTimeDly(500);
        //OSTaskSuspend(OS_PRIO_SELF);
        rLEDS = 0xAA;
        //OSTaskSuspend(OS_PRIO_SELF);
        OSTimeDly(500);
        //OSTimeDlyHMSM(0,0,0,100);
    }
}
//----------------------------------
// 数码管显示表(共阳极显示)
char smg_table[16] = {
    0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
    0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E
};    

OS_STK SmgTaskStk[OS_TASK_TMR_STK_SIZE];
void SmgTask(void *pdata)
{
    int val;
    for(;;)
    {
        val = OSTimeGet();  // 获取tick,并显示
        rSMG0 = (int)smg_table[val%10];
        rSMG1 = (int)smg_table[(val/10)%10];
        rSMG2 = (int)smg_table[(val/100)%10];
        rSMG3 = (int)smg_table[(val/1000)%10];
        rSMG4 = (int)smg_table[(val/10000)%10];
        rSMG5 = (int)smg_table[(val/100000)%10];
        OSTimeDly(50);    
    }
}

//----------------------------------
int main(void)
{
    OSInit();
    rTIMER_CR = 0x07;
    OSTaskCreate(LedTask,0,&LedTaskStk[OS_TASK_TMR_STK_SIZE-1],1);
    OSTaskCreate(SmgTask,0,&SmgTaskStk[OS_TASK_TMR_STK_SIZE-1],2);

    OSStart();

    return 0;
}

- 阅读全文 -

Nios开发--定时器Interval Timer


文章摘要:
本文详细描述了Nios定时器r组件Interval Timer的应用;


硬件平台:EP4CE6F17C8
开发环境:Quartus II 13.1/Nios II 13.1
参考文档:Quartus II Handbook Volume 5: Embedded Peripherals


添加Timer组件

Library -->
    Peripherals -->
        Microcontroller Peripherals -->
            Vectored Interrupt Controller

添加定时器组件

连接clk/rest/s1线, 分配地址,分配IRQ信号;


寄存器说明

寄存器说明

状态寄存器
TO - TimeOut标志,定时器时间到时置位,需要软件清零;
RUN - 运行状态标志,对其写操作无效;

控制寄存器

ITO :中断使能
CONF :重载使能, 1 - 循环计数; 0 - 单次计数
START:启动计时
STOP :停止计时

周期寄存器
两个16位寄存器,用于重载计数值;

计数器快照
两个16位寄存器,用于保存当前计数值;
需要先对快照寄存器进行写操作,才能将计数器当前值保存至快照寄存器;


其他说明
1.定时器采用递减工作模式;
2.重载值计数结果需要减1;


示例代码

#include "regs.h"
#include "sys/alt_irq.h"
#include <unistd.h>

/*
 * 定时器中断服务函数
 */
void isr_timer(void* context)
{
    rTIMER_SR = 0;  // 清除中断标志位
    rLEDS = ~rLEDS;
}

/*
 * 功能描述:定时器初始化函数
 * 参数列表:interval - 定时值(时钟数)
 */
void timer_init(int interval)
{
    rTIMER_CR  = 0x08;      // 设置参数时先停止运行
    rTIMER_PRH = interval >> 16;
    rTIMER_PRL = interval & 0xFFFF;

    // 注册中断
    alt_ic_isr_register(
        TIMER_IRQ_INTERRUPT_CONTROLLER_ID,
        TIMER_IRQ,  // 中断向量
        isr_timer,  // 中断服务函数
        0,      // 参数
        0);     // flag

    // 启动/循环计数/中断使能
    rTIMER_CR = 0x07;
}

int main(void)
{
    int val0,val1;
    timer_init(500000000);
    while(1){

        // 必须经过一个写操作才能生成快照,
        // 数据内容被忽略,不影响计数器值;
        rTIMER_DRL = 0;
        val0 = rTIMER_DRL;
        val1 = rTIMER_DRH;
        usleep(100000);
    }
}

- 阅读全文 -

Niso II开发--代码固化


文章摘要
做为正式的产品发布,是需要将程序代码固化到非易失存储器中的,本文主要说明了将代码固化至片外Flash中的流程;


硬件平台:EP4CE6F17C8
开发环境:Nios II 13.1


1.添加EPCS Flash Controller

2.修改CPU配置项
将CPU的Reset Vector (复位地址)和Exception Vector(中断向量)指向Flash(重要)。
请输入图片描述

Exception Vector指向ram时貌似也能正常工作,待测试。

3.重新生成qsys


4.顶层文件中导出相关引脚(注意引脚方向):

output DCLK;    // 时钟,FPGA-->Flash
output nCSO;    // 片选,FPGA-->Flash
output ASDO;    // 数据输入,FPGA-->Flash
input  DATA;    // 数据输出,Flash-->FPGA

5.重新编译并生成工程


6.重新编译BSP工程及项目工程


下载固化

Niso II --> Flash Programer

File --> New...

请输入图片描述

选择BSP文件(BSP工程)或者sopcinfo文件(SOPC工程),两者只选其一,系统自动会关联;

点击Add添加文件:
一定要先添加sof文件,再添加elf文件,如图所示;
请输入图片描述

点击start进行下载


重新加载配置(重上电)

系统即可正常运行。

- 阅读全文 -

Nios II开发--基于SDRAM存储器运行


文章摘要
由于FPGA片内的RAM资源比较少(相对于嵌入式系统而言),而且由于布线原因,也不能得到完全利用,所以可利用的空间有限,简单的演示程序还可以跑跑,稍大一点的就提示内存不足了,可以让程序运行在外部的SDRAM上,本文主要就是针对外部SDRAM应用的说明;


硬件平台:EP4CE6F17C8
开发环境:Quartus II 13.1/Nios II 13.1


修改Qsys添加SDRAM控制器

Library --> 
    Memories and Memory Controllers -->
        External Memory Interfaces -->
            SDRAM Interfaces -->
                SDRAM Controller

基本参数配置:
请输入图片描述

这里需要根据实际的电路来配置,本例中采用了1片的H57V2562GTR,256Mbit(16Mx16bit),一共4个Bank,13根行地址线,9根列地址线;


时序参数配置:
请输入图片描述
这里需要查看数据手册,进行相关参数填写;

CAS latency cycles:: 数据潜伏期,数据手册规定为3;
Initialization refresh cycles:初始化刷新周期
Issue one refresh command every: 刷新周期 = 64ms / 行数量(8K) = 7.8125us
Delay after powerup, before initialization:
Duration of refresh command(t_rfc):
Duration of precharge command (t_rp):
ACTIVE to READ or WRITE delay(t_rcd):RAS to CAS Delay
Access time(t_ac):
Write recovery time(t_wr,no auto precharge):


Qsys系统配置
1.修改名称为sdram,连接时钟线,复位线,指令总线和数据总线,并导出相关引脚;
2.删除之前的内部存储器(可不删);
3.修改CPU属性,修改复位向量和异常向量为sdram.
4.重新分配地址;
5.重新生成系统;


顶层文件修改
1.修改顶层接口及例化代码,导出SDRAM引脚;
2.将sdram时钟引脚连接至clk(重要),暂时不采用pll倍频;
3.分析综合并分配sdram引脚;
4.全编译;
5.下载至目标板;


修改BSP
1.重新生成BSP(Generate BSP);
2.重新编译BSP工程(Build Project);
3.重新编译应用工程,并下载运行;


下载完成后,系统自动运行,采用delay延时的程序中,可以发现,系统运行比内部ram慢很多,这里由于外部存储器访问模式比较复杂造成的,这就是为什么有的系统中有多级缓存的原因。

- 阅读全文 -

Nios II开发--数码管组件


文章摘要:
本文通过基于Avalon-MM总线设备的数码管显示组件的应用,来说明的组件的添加与应用;


硬件平台:EP4CE6F17C8
开发环境:Quartus II 13.1/Nios II 13.1


创建数码管组件

/*
 *  功能描述:基于Avalon-MM总线的数码管组件
 */
module avalon_mm_smg (
    clk,            // 时钟信号
    rst_n,          // 复位信号
    
    // Avalon-MM接口
    address,        // 地址线(3bit)
    chipselect,     // 片选
    write_n,        // 写使能(低电平有效)
    writedata,      // 写数据
    readdata,       // 读数据
    
    // 硬件接口
    data_pin,       // 数据管段 
    sel_pin         // 数据管位
 );

input         clk;
input         rst_n;
input [ 2: 0] address;
input         chipselect;
input         write_n;
input [31: 0] writedata;
output[31: 0] readdata;

output [7:0] data_pin;
output [5:0] sel_pin;
//-----------------------------------------------   
reg[31: 0] readdata;

// 模块连接线
reg[7:0]segs[5:0];  // 6字节显示数据
//-----------------------------------------------  
// 寄存器读操作
always @(posedge clk or negedge rst_n)begin
  if (rst_n == 0)
      readdata <= 0;
  else if(address < 6)
       readdata <= {32'b0 | segs[address]};
  else
       readdata <= 0; 
end
//----------------------------------------------- 
// 寄存器写操作   
always @(posedge clk or negedge rst_n) begin
    if(~rst_n) begin
        segs[0] <= 0;    
        segs[1] <= 0;
        segs[2] <= 0;
        segs[3] <= 0;
        segs[4] <= 0;
        segs[5] <= 0;
    end  
    
    else if (chipselect && ~write_n) begin 
        if(address < 6) begin
            segs[address] = writedata[7:0];
        end        
    end
end 
//----------------------------------------------- 
// 例化数码管显示模块
smg_scan s0(
    .clk(clk),              // 时钟信号
    .rst_n(rst_n),          // 复位信号
    .data_pin(data_pin),    // 数据引脚,共阳数码管
    .sel_pin(sel_pin),      // 选通信号,低电平导通   
    .seg0(segs[0]),         // 数据
    .seg1(segs[1]),         // 数据
    .seg2(segs[2]),         // 数据
    .seg3(segs[3]),         // 数据
    .seg4(segs[4]),         // 数据
    .seg5(segs[5])          // 数据
);
//----------------------------------------------- 
endmodule

打开Qsys软件

Project --> New Components...


基本信息
请输入图片描述


添加文件
1.添加文件,并指定顶层文件(Top-level File);

添加源文件

2.点击Analyze Synthesis Files,系统将自动分析模块接口,如果后续修改了接口,则需要重新操作;

这里显示的错误是因为信号定义的问题,暂时不用理会,下一步骤中会处理;


信号处理

请输入图片描述


接口定义
点击Remove Interfaces With No Signals删除无用的信号;

请输入图片描述

此时不应该再有任何错误了,点击Finish完成组件创建;


将数码管组件添加至系统中


示例代码:

/*
 *  main.c
 *  Created on: 2017-4-18
 *  Author    : alex.duan
 *  Descript  :
 */
#include "system.h"

// 寄存器定义
#define rSMG0 *((volatile int *)(SMG_BASE + (0 << 2)))
#define rSMG1 *((volatile int *)(SMG_BASE + (1 << 2)))
#define rSMG2 *((volatile int *)(SMG_BASE + (2 << 2)))
#define rSMG3 *((volatile int *)(SMG_BASE + (3 << 2)))
#define rSMG4 *((volatile int *)(SMG_BASE + (4 << 2)))
#define rSMG5 *((volatile int *)(SMG_BASE + (5 << 2)))

// 数码管显示表(共阳极显示)
char smg_table[16] = {
    0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
    0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E
};

// 延时程序
void delay(int n)
{
    while(n--);
}

// 主函数入口
int main(void)
{
    int val = 0x00;
    while(1)
    {
        // 这种数码管的显示方案是不是简单很多
        rSMG0 = (int)smg_table[val%10];
        rSMG1 = (int)smg_table[val/10%10];
        rSMG2 = (int)smg_table[val/100%10];
        rSMG3 = (int)smg_table[val/1000%10];
        rSMG4 = (int)smg_table[val/10000%10];
        rSMG5 = (int)smg_table[val/100000%10];

        delay(1000000); // 延时一会
        val++;
    }

    return 0;
}

- 阅读全文 -


Copyright©2025 春天花会开, All Rights Reserved. Email: webmaster@oroct.com