先看看效果
比如我们现在要实现点亮一个灯的操作,采用了C++进行封装之后,在主程序中就会非常的简洁。
main.cpp
GNios::Gpio Led(LED_BASE);
int main() {
//Hello world to jtag
printf("Hello from Nios II!\n");
//led
int i;
while (1)
{
for (i = 0; i < 4; i++)
{
//IOWR_ALTERA_AVALON_PIO_DATA(LED_BASE, 1<<i);
Led.WriteData(1<<i);
usleep(100000);
}
}
}
return 0;
}
自定义类型
在实际开始写之前,将一些类型名称进行个性化的定制,这样保持整个工程中的不同长度大小的类型定义不混乱。
gnios_types.h
#ifndef GNIOS_TYPES_H_
#define GNIOS_TYPES_H_
#include "system.h"
typedef alt_8 int8; //有符号8位整数
typedef alt_u8 uint8; //无符号8位整数
typedef alt_16 int16; //有符号16位整数
typedef alt_u16 uint16; //无符号16位整数
typedef alt_32 int32;
typedef alt_u32 uint32;
typedef alt_64 int64;
typedef alt_u64 uint64;
typedef void(*gnios_func)(void* context); //定义一个通用的函数指针类型gnios_func,返回类型为void,参数为void* context
//定义一个泛型类(模板类?),以便之后规范数据传输。
template<class T>
class EventArgs
{
public:
T Content;
EventArgs(T content)
{
this->Content=content;
}
};
#endif /* GNIOS_TYPES_H_ */
GPIO
gnios_gpio.h
#ifndef GNIOS_GPIO_H_
#define GNIOS_GPIO_H_
#include "system.h"
#include "altera_avalon_pio_regs.h"
#include "gnios_types.h"
#define GpioInput 0
#define GpioOutput 1
//PIO核支持最多32个IO,这里都定义出来
#define GpioPin0 ((uint32)0x00000001)
#define GpioPin1 ((uint32)0x00000002)
#define GpioPin2 ((uint32)0x00000004)
#define GpioPin3 ((uint32)0x00000008)
#define GpioPin4 ((uint32)0x00000010)
#define GpioPin5 ((uint32)0x00000020)
#define GpioPin6 ((uint32)0x00000040)
#define GpioPin7 ((uint32)0x00000080)
#define GpioPin8 ((uint32)0x00000100)
#define GpioPin9 ((uint32)0x00000200)
#define GpioPin10 ((uint32)0x00000400)
#define GpioPin11 ((uint32)0x00000800)
#define GpioPin12 ((uint32)0x00001000)
#define GpioPin13 ((uint32)0x00002000)
#define GpioPin14 ((uint32)0x00004000)
#define GpioPin15 ((uint32)0x00008000)
#define GpioPin16 ((uint32)0x00010000)
#define GpioPin17 ((uint32)0x00020000)
#define GpioPin18 ((uint32)0x00040000)
#define GpioPin19 ((uint32)0x00080000)
#define GpioPin20 ((uint32)0x00100000)
#define GpioPin21 ((uint32)0x00200000)
#define GpioPin22 ((uint32)0x00400000)
#define GpioPin23 ((uint32)0x00800000)
#define GpioPin24 ((uint32)0x01000000)
#define GpioPin25 ((uint32)0x02000000)
#define GpioPin26 ((uint32)0x04000000)
#define GpioPin27 ((uint32)0x08000000)
#define GpioPin28 ((uint32)0x10000000)
#define GpioPin29 ((uint32)0x20000000)
#define GpioPin30 ((uint32)0x40000000)
#define GpioPin31 ((uint32)0x80000000)
#define GpioPinAll ((uint32)0xFFFFFFFF)
namespace GNios
{
class Gpio
{
protected:
/* GPIO register PIO核的寄存器映射*/
typedef struct RegStruct
{
volatile uint32 DATA;
volatile uint32 DIRECTION;
volatile uint32 INTERRUPT_MASK;
volatile uint32 EDGE_CAPTURE;
}RegStruct;
/* GPIO Arguments*/
typedef struct GpioArgs
{
RegStruct* Reg; //寄存器映射
uint32 base; //PIO核的基地址
}GpioArgs;
GpioArgs Instance; //GPIO核实例
public:
Gpio(uint32 base); //使用基地址实例化
uint32 ReadData();
void WriteData(uint32 data);
uint32 ReadDirection();
void WriteDirection(uint32 data);
uint32 ReadIrqMask();
void WriteIrqMask(uint32 data);
uint32 ReadEdgeCapture();
void WriteEdggeCapture(uint32 data);
uint32 ReadSetBits();
void WriteSetBits(uint32 data);
uint32 ReadClearBits();
void WriteClearBits(uint32 data);
~Gpio();
};
}
#endif /* GNIOS_GPIO_H_ */
这里要说明一下,虽然这里使用了寄存器映射的办法将IP核的寄存器映射到了RegStruct
上,但是实际使用的时候,并不推荐使用寄存器赋值的办法来做,还是推荐使用API来操作。具体原因是采用API的话,调用的是内建的函数,而使用寄存器赋值,在NiosII的F核情况下就会遇到DataCache的问题。所以寄存器赋值的定义那里置位了第31位,第31位是DataCache bypassing位
gnios_gpio.cpp
#include "../inc/gnios_gpio.h"
namespace GNios
{
Gpio::Gpio(uint32 base)
{
Instance.Reg=((RegStruct*)(base|(1<<31)));
Instance.base=base;
}
uint32 Gpio::ReadData()
{
return (uint32)IORD_ALTERA_AVALON_PIO_DATA(Instance.base);
}
void Gpio::WriteData(uint32 data)
{
//Reg->DATA=data; //using Register
IOWR_ALTERA_AVALON_PIO_DATA(Instance.base, data); //using api
}
uint32 Gpio::ReadDirection()
{
return (uint32)IORD_ALTERA_AVALON_PIO_DIRECTION(Instance.base);
}
void Gpio::WriteDirection(uint32 data)
{
IOWR_ALTERA_AVALON_PIO_DIRECTION(Instance.base,data);
}
uint32 Gpio::ReadIrqMask()
{
return (uint32)IORD_ALTERA_AVALON_PIO_IRQ_MASK(Instance.base);
}
void Gpio::WriteIrqMask(uint32 data)
{
IOWR_ALTERA_AVALON_PIO_IRQ_MASK(Instance.base,data);
}
uint32 Gpio::ReadEdgeCapture()
{
return (uint32)IORD_ALTERA_AVALON_PIO_EDGE_CAP(Instance.base);
}
void Gpio::WriteEdggeCapture(uint32 data)
{
IOWR_ALTERA_AVALON_PIO_EDGE_CAP(Instance.base,data);
}
uint32 Gpio::ReadSetBits()
{
return (uint32)IORD_ALTERA_AVALON_PIO_SET_BITS(Instance.base);
}
void Gpio::WriteSetBits(uint32 data)
{
IOWR_ALTERA_AVALON_PIO_SET_BITS(Instance.base,data);
}
uint32 Gpio::ReadClearBits()
{
return (uint32)IORD_ALTERA_AVALON_PIO_CLEAR_BITS(Instance.base);
}
void Gpio::WriteClearBits(uint32 data)
{
IOWR_ALTERA_AVALON_PIO_CLEAR_BITS(Instance.base,data);
}
Gpio::~Gpio()
{
}
}