从SOD到OOD(iomem模块)

IOMEM模块是定义的一个AXI总线上的一块Memory Map的资源,所以它有一个base,有一个size。
如果不定义具体的操作函数,那么对IOMEM的操作,就只能用最基本的“=”操作,配合volatile指针,将常数地址进行强制转换来完成,这并不符合C++的接口封装的设计思想。
为了增强可读性,需要为IOMEM设计一系列配套的操作函数。
这里,将IOMEM封装为class,而不是struct。

class IoMem
{
public:
	IoMem() {}
	IoMem(u32 phy_base, u32 size);

	void set_value(u32 offset, u32 value, int flag = 1);
	void set_value(u32 offset, int value, int flag = 1);
	void set_value(u32 offset, float value, int flag = 1);
	void set_value(u32 offset, u32 value, u32 mask, u32 shift, int flag = 1);


	u32 get_value(u32 offset, int flag = 1);
	int get_value_as_int(u32 offset, int flag = 1);
	float get_value_as_float(u32 offset, int flag = 1);

	void set_bits_value(u32 offset, u32 mask, u32 shift, int value, int flag = 1);
	void set_bit_value(u32 offset, u32 mask, int value, int flag = 1);
	
	void set_bit(u32 offset, u32 mask, int flag = 1);
	void clr_bit(u32 offset, u32 mask, int flag = 1);

	u32 float_to_u32(float value);
	float u32_to_float(u32 value);

public:
	u32 phy_base_;
	u32 total_size_;
};

#define BIT(nr)			(1 << (nr))
#define GENMASK(h, l)   ((((1) << ((h) - (l) + 1)) - 1) << (l))

在操作集中,我们看到,
set_value被重载了4次,
这是为了适应不同的输入参数,
但是其他的函数,并没有重载,是为了增强可读性,
而且,返回值的类型,并不能判决重载。

来看CPP文件中的定义,

void IoMem::set_value(u32 offset, u32 value, int flag)
{
	u32 addr = phy_base_ + offset * 4;
	Xil_Out32(addr, value);
	if (flag) {
		plog("set value: 0x%08x 0x%08x\r\n", addr, value);
	}
}

这个是最基础的set_value函数,其他函数都要调用它的服务,或者说,其他函数是对它的封装。
注意,AXI总线地址是BYTE地址,所以u32占4个BYTE,这里给出的offset,是以REG为单位给出的,即u32,所以在用AXI总线去传输的时候,地址要左移两位,即乘以4。

void IoMem::set_value(u32 offset, int value, int flag)
{
	set_value(offset, (u32)value, flag);
}

void IoMem::set_value(u32 offset, float value, int flag)
{
	set_value(offset, float_to_u32(value), flag);
}

void IoMem::set_value(u32 offset, u32 value, u32 mask, u32 shift, int flag)
{
	u32 result = get_value(offset, flag);
	result &= (~mask);
	result |= value << shift;
	set_value(offset, result, flag);
}

再来看看get_value系列,

u32 IoMem::get_value(u32 offset, int flag)
{
	u32 addr = phy_base_ + offset * 4;
	u32 result = Xil_In32(addr);
	if (flag) {
		plog("get value: 0x%08x 0x%08x\r\n", addr, result);
	}
	return result;
}

int IoMem::get_value_as_int(u32 offset, int flag)
{
	u32 result = get_value(offset, flag);
	return (int)result;
}

float IoMem::get_value_as_float(u32 offset, int flag)
{
	u32 result = get_value(offset, flag);
	return u32_to_float(result);
}

再来看看BIT操作系列,

void IoMem::set_bit(u32 offset, u32 mask, int flag)
{
	u32 result = get_value(offset, flag);
	result |= mask;
	set_value(offset, result, flag);
}

void IoMem::clr_bit(u32 offset, u32 mask, int flag)
{
	u32 result = get_value(offset, flag);
	result &= (~mask);
	set_value(offset, result, flag);
}

void IoMem::set_bit_value(u32 offset, u32 mask, int value, int flag)
{
	if (value)
		set_bit(offset, mask, flag);
	else
		clr_bit(offset, mask, flag);
}

void IoMem::set_bits_value(u32 offset, u32 mask, u32 shift, int value, int flag)
{
	u32 result = get_value(offset, flag);
	result &= ~mask;
	result |= value << shift;
	set_value(offset, result, flag);
}

再来看看类型转换操作系列,

u32 IoMem::float_to_u32(float value)
{
	u32 tmp;
	tmp = (U32)value;
	return tmp;
}


float IoMem::u32_to_float(u32 value)
{
	float tmp;
	tmp = (float)value;
	return tmp;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值