• 前言
  • NIOS II项目搭建
  • Hello World on Nios ii
  • 点亮LED
  • 快速的开发:使用C++的类

前言

在上一篇文章中博主介绍了如何让nios ii跑在板子自带的SDRAM里,这样大家伙就不用担心小的可怜的FPGA内部的memory(当然用着几万块开发板的土豪除外)。对于要用FPGA做开发的盆友来说,花费少量的资源跑一个简单的软核还是非常方便的,特别是对于一些速度要求不是很高的处理,像是跑个小型的GUI之类的,nios ii无疑是个很棒的选择。

在很多的教程中,开发NIOS II总是给人一个非常不好的印象:晦涩难懂的函数,复杂的调用,还有一些莫名其妙的问题,这无疑给开发带来了很大的难度。

这十年来,开源硬件越来越流行,从最初的Arduino到后来的树莓派,都是以一种相对平易近人的姿态面向电子爱好者和广大学生或是从业者们,其简易的开发方式大大缩短了编程难度,让我们真正的拜托硬件平台的限制,把目光从如何使用一款硬件转移到如何开发一套优良的算法。这几年ARM公司的Mbed给了Cortex-M系列处理器前所未有的支持,从STM32到LPC一系列微控制器都允许使用Mbed开发,进一步降低了设计难度。由于Mbed良好的移植特性,我们可以轻易地将官方未宣布支持的Cortex-M控制器一直上Mbed,经过简易的测试就可以顺利跑起来。

Mbed是基于C++语言开发的平台,其优雅的代码形式还是很受博主欣赏的呢!

#include "mbed.h"
DigitalOut myled(LED1);
int main()
{// check that myled object is initialized and connected to a pinif(myled.is_connected()) {printf("myled is initialized and connected!\n\r");}// Blink LEDwhile(1) {myled = 1;          // set LED1 pin to highprintf("myled = %d \n\r", (uint8_t)myled );wait(0.5);myled.write(0);     // set LED1 pin to lowprintf("myled = %d \n\r",myled.read() );wait(0.5);}
}

这是官网给出来的一段blinking led的代码样例,使用DigitalOut,在这篇博客中,博主希望能够以一种这样的方式开发NIOS II。

SunZhenyu,

于 台州学院 电力电子实验室


NIOS II工程搭建

接着上一次的教程,创建完成一个nios ii软核与pll核,正确分配引脚并编译成功以后,下载到目标板上后,FPGA内部就已经有一个可用的nios处理器了。

注意:如果生成的sof文件后缀为time limited,应该考虑一下是否购买了正版的Quartus^_ ^或者正确地 破解 您的软件??

博主使用Quartus Prime 18.0,这款软件有一个lite版本可以尝尝鲜,是不需要license的,但是使用nios ii会有时间限制(限制为无限时间),也就是time limited…因此不可以转化为jic文件烧录到配置芯片中,不过学学nios应该也够用了,学会了记得忽悠导师买正版啊!


选择Nios ii Software Build Tool for Eclipse
注意NIOS ii的开发平台是基于大名鼎鼎的Eclipse的,博主希望充分发挥Eclipse的优势。

选择软件工程存放位置

载入SOPC文件,注意SOPC文件的路径
工程模板我们就选择一个空模板就好了。

点击Finish以后就可以载入一个工程。

注意nios_on_sdram这个是我们的工程,而nios_on_sdram_bsp则是系统自动建立的bsp模板。

新建一个源代码文件


注意文件的扩展名!
因为博主希望使用C++开发,因此后缀选择了CPP
至此项目框架搭建完毕!


Hello World on Nios ii

使用C++语言的优势就在于可以方便而灵活的使用面向对象的特点,利用类简化一些操作。 为了测试SOPC是否顺利跑起来,我们还是写一个Hello World试一下。

/** main.cpp**  Created on: Sep 23, 2019*      Author: Sunzh*/#include <iostream>int main()
{std::cout<<"Hello World on Nios ii"<<std::endl;return 0;
}


如果没毛病的话,经过短暂的构建编译以后就可以看到控制台输出了一段

Hello World on Nios ii

这证明我们的程序跑起来了!
那么这个小小的Hello World有多大呢?我们看一下控制台的下载过程

Using cable "USB-Blaster [USB-0]", device 1, instance 0x00
Pausing target processor: OK
Initializing CPU cache (if present)
OKDownloading 02000000 ( 0%)
Downloading 02010000 ( 8%)
Downloading 02020000 (16%)
Downloading 02030000 (24%)
Downloading 02040000 (32%)
Downloading 02050000 (40%)
Downloading 02060000 (48%)
Downloading 02070000 (56%)
Downloading 02080000 (65%)
Downloading 02090000 (73%)
Downloading 020A0000 (81%)
Downloading 020B0000 (89%)
Downloading 020C0000 (97%)
Downloading 020C4AE4 (99%)
Downloaded 787KB in 7.8s (100.8KB/s)Verifying 02000000 ( 0%)
Verifying 02010000 ( 8%)
Verifying 02020000 (16%)
Verifying 02030000 (24%)
Verifying 02040000 (32%)
Verifying 02050000 (40%)
Verifying 02060000 (48%)
Verifying 02070000 (56%)
Verifying 02080000 (65%)
Verifying 02090000 (73%)
Verifying 020A0000 (81%)
Verifying 020B0000 (89%)
Verifying 020C0000 (97%)
Verifying 020C4AE4 (99%)
Verified OK
Starting processor at address 0x02000244

神特么的一个小小的Hello World有787KB?!
其实不用这么紧张,如果我们不用C++的输入输出流,这个代码可能很短。

点亮LED

在设计SOPC的时候,博主加上一个PIO的模块,这个模块被映射为一个真实的IO口,与开发板上的一个LED相连。

在system.h中我们可以看到IO口的基地址。在BSP中Altera为我们编写好了一系列的HAL库供我们调用,就像STM32开发一样。当然这些库有的晦涩难懂,需要翻阅手册才能使用。这里博主简单介绍一个函数。
直接HAL库操作IO的方法是IOWR(),声明在io.h中

#define IOWR(BASE, REGNUM, DATA) \__builtin_stwio (__IO_CALC_ADDRESS_NATIVE ((BASE), (REGNUM)), (DATA))

这是一个带参数的宏定义,其包含三个参数BASE,REGNUM,DATA
BASE参数就是我们PIO模块的基地址,在博主搭建的SOPC上是0x4001010,第二个参数是寄存器号
通常我们使用如下这两个
寄存器0:数据寄存器,为PIO写入或读取的数据
寄存器1:为方向寄存器,定义0为输入1为输出
DATA是要写入的内容
例如我们要使一个16位的PIO中第5管脚设置为输出,其余管脚设置为输入,只需要对1寄存器写入0x0010

IOWR(PIO_BASE, 1, 0x0010);
//0x00=(0000 0000 0001 0000)b

要是第五管脚输出一个高电平,只需要对0寄存器写入0x0010

IOWR(PIO_BASE, 0, 0x0010);
//0x00=(0000 0000 0001 0000)b

注意对方向寄存器设置为输入的管脚写入数据是无效的。
利用这个函数就足够让小灯闪烁了。
博主的PIO为16位,其中小灯接在第2个IO。

/** main.cpp**  Created on: Sep 23, 2019*      Author: Sunzh*/#include <io.h>
#include <unistd.h>
#include <system.h>
int main()
{IOWR(PIO_BASE,1,0x0002);while(true){IOWR(PIO_BASE,0,0x0002);  usleep(500000);  //延时函数,包含在unistd.h中IOWR(PIO_BASE,0,0x0000);usleep(500000);}return 0;
}

当控制台闪过这样一段文字的时候

Using cable "USB-Blaster [USB-0]", device 1, instance 0x00
Pausing target processor: OK
Initializing CPU cache (if present)
OKDownloading 02000000 ( 0%)
Downloading 02003EB8 (64%)
Downloaded 16KB in 0.1s        Verifying 02000000 ( 0%)
Verifying 02003EB8 (64%)
Verified OK
Starting processor at address 0x02000244

值得注意的是这段代码仅有16KB大小。
是的,现在小灯已经在以1秒钟1次的速度闪烁了。
但是现在有一个不小的问题,每一次这么操作实在是太麻烦了,点亮一个LED尚可,若点亮一块SPI接口的OLED屏幕呢?
算了算了还是静静吧。


快速开发:使用C++的类

如果我们将每一个IO封装为一个类,这个类通过IOWR的方式操作PIO,这样估计就能一劳永逸了。 Mbed为我们提供了一个绝佳的典范!

博主定义了一个DigitalOut类

#ifndef DRIVERS_DIGITALOUT_H_
#define DRIVERS_DIGITALOUT_H_
#include "inc.h"
class DigitalOut
{private:PinName pin;bool data;public:DigitalOut(PinName);void operator=(const bool);operator int();
};
#endif

实现如下

#include "inc.h"extern uint16_t PIO_DATA;
extern uint16_t PIO_DIR;void DigitalOut::operator=(bool data)
{this->data = data;if(((PIO_DIR&(1<<pin))!=0)!=_DigitalOutDir){PIO_DIR |= (1 << pin);IOWR(_DigitalOut_IO_BASE, DIR_REG, PIO_DIR);}PIO_DATA &= (~(1 << pin));PIO_DATA |= (data << pin);IOWR(_DigitalOut_IO_BASE, DATA_REG, PIO_DATA);
}
DigitalOut::DigitalOut(PinName Name)
{pin = Name;operator=(0);
}
DigitalOut::operator int()
{return data;
}

博主这里使用了几个重载,尤其注意转换函数int()重载用于实现类似a=!a的操作
其中PinName是一个枚举类型,定义如下

#ifndef DRIVERS_PINNAME_H_
#define DRIVERS_PINNAME_H_
enum PinName
{D0 = 0,D1,D2,D3,D4,D5,D6,D7,D8,D9,D10,D11,D12,D13,D14,D15
};
#endif

同时博主对usleep也做了一点小小的改动,以求更加方便

#ifndef _WAIT_H_
#define _WAIT_H_
#define wait_ms(x) usleep((x)*1000)
#define wait(x) usleep((x)*1000000)
#define wait_us usleep((x))#endif

现在是否能更加优雅的点灯了呢?

/** main.cpp**  Created on: Sep 23, 2019*      Author: Sunzh*/#include "Drivers/inc.h"
int main()
{DigitalOut led(D1);while(true){led=!led;wait_ms(500);}return 0;
}

我们还可以定义一个DigitalIn类型,完成按键的输入,就像这个样子

/** main.cpp**  Created on: Sep 23, 2019*      Author: Sunzh*/#include "Drivers/inc.h"
int main()
{DigitalOut led(D1);DigitalIn key(D0);while(true){if(key==0){wait_ms(25);while(key==0);led=!led;}}return 0;
}

至此,所有关于IO的基本操作我们都实现了,利用DigitalIn,DigitalOut还有wait,我们能完成几乎所有的I2C SPI等的访问,驱动各种传感器,代码也会简洁地令人耳目一新。

稍后博主会放上一些代码和模板工程。
博主会利用学业的空闲时间一点一点地将Mbed-NIOS完善起来,加油!

FPGA学习[2]——致敬Mbed!使用C++开发NIOS II相关推荐

  1. FPGA 之 SOPC 系列(六)Nios II 程序开发 II

    FPGA 之 SOPC 系列(六)Nios II 程序开发 II 今天给大侠带来今天带来FPGA 之 SOPC 系列第六篇,Nios II 程序开发 II,希望对各位大侠的学习有参考价值,话不多说,上 ...

  2. FPGA学习之 状态机实现数码管的数字时钟

    FPGA学习之 状态机实现数字时钟 开发板型号:EP4CE6F17C8 六位数码管原理图: 由图可知,数码管段选和片选均为低电平有效. 由于人眼的视觉残留,我们控制一定频率对每一位数码管进行刷新,就能 ...

  3. FPGA 之 SOPC 系列(四)NIOS II 外围设备--标准系统搭建

    FPGA 之 SOPC 系列(四)NIOS II 外围设备--标准系统搭建 今天给大侠带来今天带来FPGA 之 SOPC 系列第四篇,NIOS II 外围设备--标准系统搭建,希望对各位大侠的学习有参 ...

  4. 【FPGA入门教程】(二)FPGA学习路线及开发流程

    一.FPGA学习路线 工具使用 -> 语法学习 -> 逻辑设计 -> IP使用 ->接口设计 -> 时序分析 -> 片上系统 1.工具使用 Altera:Quart ...

  5. 小梅哥FPGA学习笔记——开发流程及仿真示例

    开发流程及仿真示例 FPGA整体设计开发流程 1. 设计定义 2. 设计输入(Quartus II) 3. 分析和综合(Quartus II) 4. 功能仿真(modelsim-altera/mode ...

  6. FPGA学习及设计中的注意事项

    为什么80%的码农都做不了架构师?>>>    FPGA学习及设计中的注意事项 1.基础问题 FPGA的基础就是数字电路和HDL语言,想学好FPGA的人,建议床头都有一本数字电路的书 ...

  7. FPGA学习笔记之Altera FPGA使用JIC文件配置固化教程

    FPGA学习笔记之Altera FPGA使用JIC文件配置固化教程 很多做过单片机的朋友都知 道,我们在对MCU烧写完程序固件后,那么该程序固件就存储在了该MCU内部.即使MCU断电了再重新上电,程序 ...

  8. FPGA学习之路—接口(2)—I2C协议详解+Verilog源码分析

    FPGA学习之路--I2C协议详解+Verilog源码分析 定义 I2C Bus(Inter-Integrated Circuit Bus) 最早是由Philips半导体(现被NXP收购)开发的两线时 ...

  9. FPGA学习—数码管显示

    FPGA学习--数码管显示 文章目录 FPGA学习--数码管显示 结构框架 一.硬件设计 二.verilog编写 1.计数器 2.译码模块 3.数码管扫描模块 4.顶层模块 实验结果 结构框架 数码管 ...

最新文章

  1. 【iOS学习笔记】IOS开发中设置applicationIconBadgeNumber和消息推送
  2. 如何从文件内容创建Java字符串?
  3. MATLAB从入门到精通-MATLAB2021版类似excel的坐标轴标签自动缩放布局
  4. music算法_Elasticsearch系列---相关性评分算法及正排索引
  5. 【CodeForces - 501C】Misha and Forest (思维构造,树,数学异或)
  6. spike 序列matlab,SPKtool1.0.1 神经信号spike 分类及处理 工具包 matlab 238万源代码下载- www.pudn.com...
  7. Java Spring-Bean
  8. WEBPACK+ES6+REACT入门(1/7)-创建webpack4.x项目
  9. mysql修复表命令_mysql命令修复数据库表
  10. 企业信息化到底是不是一把手工程
  11. SEGGER Embedded Studio 搭建开发环境
  12. 一个简单的HTML5后台登陆界面及登录实现
  13. 主板声卡坏了会不会有电流声_不要小瞧十几块钱的USB声卡!
  14. argc,argv,argv[0]用法详解
  15. 自定义treeview控件,实现右键菜单编辑功能
  16. 【机器学习】之 主成分分析PCA
  17. 两分钟快速理解成本函数(cost function)
  18. OpenCV Error: Unspecified error (could not find a writer for the specified extension) in imwrite
  19. 北京市计算机工业学校吧 03413,2014年广东省中职学校“创新杯”教师信息化教学设计和说课大赛通知“创新杯”说课大赛可参考使用的数字化教学资源.doc...
  20. java条码扫描_Java上的条形码扫描仪实现

热门文章

  1. PUTT(psftp)文件上传下载
  2. 传感器精度和分辨率的区别
  3. 前端经典面试500题【上】
  4. 【Linux】揭露定时任务真相
  5. 4K壁纸批量采集,张张精品,全程自动化
  6. 汇编语言知识点总结之五:第五章《[bx]和loop指令》
  7. 深度学习笔记(18)- 深度终端之一
  8. 爬取国家药品监督管理局详情页面信息
  9. 中国石油大学《政治学原理》第一次在线作业
  10. 使用spring data JPA,or跟and的合并使用语句拼凑or跟and的合并使用需要密切注意