从SOD到OOD(HLS生成模块的共性提取)

HLS生成的模块,在BSP中,会生成对应的driver,
在导出HDF后,SDK中,会生成hardware_platform,
之后,在生成的BSP中,会将driver中的src代码合并进BSP中去。

这些HLS生成的模块,都会有一些共性的操作集。
来看看
1)cfginit

int XBayer_photo_accl_CfgInitialize(XBayer_photo_accl *InstancePtr, XBayer_photo_accl_Config *ConfigPtr) {
    Xil_AssertNonvoid(InstancePtr != NULL);
    Xil_AssertNonvoid(ConfigPtr != NULL);

    InstancePtr->Control_bus_BaseAddress = ConfigPtr->Control_bus_BaseAddress;
    InstancePtr->IsReady = XIL_COMPONENT_IS_READY;

    return XST_SUCCESS;
}

int XClahe_accl_CfgInitialize(XClahe_accl *InstancePtr, XClahe_accl_Config *ConfigPtr) {
    Xil_AssertNonvoid(InstancePtr != NULL);
    Xil_AssertNonvoid(ConfigPtr != NULL);

    InstancePtr->Control_bus_BaseAddress = ConfigPtr->Control_bus_BaseAddress;
    InstancePtr->IsReady = XIL_COMPONENT_IS_READY;

    return XST_SUCCESS;
}

这个函数,主要是填充结构体,baseaddress和ready状态。

2)start

void XBayer_photo_accl_Start(XBayer_photo_accl *InstancePtr) {
    u32 Data;

    Xil_AssertVoid(InstancePtr != NULL);
    Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);

    Data = XBayer_photo_accl_ReadReg(InstancePtr->Control_bus_BaseAddress, XBAYER_PHOTO_ACCL_CONTROL_BUS_ADDR_AP_CTRL) & 0x80;
    XBayer_photo_accl_WriteReg(InstancePtr->Control_bus_BaseAddress, XBAYER_PHOTO_ACCL_CONTROL_BUS_ADDR_AP_CTRL, Data | 0x01);
}

void XClahe_accl_Start(XClahe_accl *InstancePtr) {
    u32 Data;

    Xil_AssertVoid(InstancePtr != NULL);
    Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);

    Data = XClahe_accl_ReadReg(InstancePtr->Control_bus_BaseAddress, XCLAHE_ACCL_CONTROL_BUS_ADDR_AP_CTRL) & 0x80;
    XClahe_accl_WriteReg(InstancePtr->Control_bus_BaseAddress, XCLAHE_ACCL_CONTROL_BUS_ADDR_AP_CTRL, Data | 0x01);
}

这个函数,设置模块启动,
首先读取ap_auto_restart状态,
然后写入ap_start位,
具体的寄存器位的含义如下。

// CONTROL_BUS
// 0x00 : Control signals
//        bit 0  - ap_start (Read/Write/COH)
//        bit 1  - ap_done (Read/COR)
//        bit 2  - ap_idle (Read)
//        bit 3  - ap_ready (Read)
//        bit 7  - auto_restart (Read/Write)
//        others - reserved

和0x80相与,提取出ap_auto_restart的状态,
再和0x01相或,设置ap_start的状态。

3)isdone

u32 XBayer_photo_accl_IsDone(XBayer_photo_accl *InstancePtr) {
    u32 Data;

    Xil_AssertNonvoid(InstancePtr != NULL);
    Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);

    Data = XBayer_photo_accl_ReadReg(InstancePtr->Control_bus_BaseAddress, XBAYER_PHOTO_ACCL_CONTROL_BUS_ADDR_AP_CTRL);
    return (Data >> 1) & 0x1;
}
u32 XClahe_accl_IsDone(XClahe_accl *InstancePtr) {
    u32 Data;

    Xil_AssertNonvoid(InstancePtr != NULL);
    Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);

    Data = XClahe_accl_ReadReg(InstancePtr->Control_bus_BaseAddress, XCLAHE_ACCL_CONTROL_BUS_ADDR_AP_CTRL);
    return (Data >> 1) & 0x1;
}

这个函数,读取模块完成状态,
首先读取control寄存器,
然后再右移位到bit0,再和0x01相与,取出ap_done的值,返回。
注意,返回值的bit0携带对应的ap_done的值,其他位全部为0。

4)isidle

u32 XBayer_photo_accl_IsIdle(XBayer_photo_accl *InstancePtr) {
    u32 Data;

    Xil_AssertNonvoid(InstancePtr != NULL);
    Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);

    Data = XBayer_photo_accl_ReadReg(InstancePtr->Control_bus_BaseAddress, XBAYER_PHOTO_ACCL_CONTROL_BUS_ADDR_AP_CTRL);
    return (Data >> 2) & 0x1;
}
u32 XClahe_accl_IsIdle(XClahe_accl *InstancePtr) {
    u32 Data;

    Xil_AssertNonvoid(InstancePtr != NULL);
    Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);

    Data = XClahe_accl_ReadReg(InstancePtr->Control_bus_BaseAddress, XCLAHE_ACCL_CONTROL_BUS_ADDR_AP_CTRL);
    return (Data >> 2) & 0x1;
}

这个函数,读取模块空闲状态,
首先读取control寄存器,
然后再右移位到bit0,再和0x01相与,取出ap_idle的值,返回。
注意,返回值的bit0携带对应的ap_idle的值,其他位全部为0。

5)isready

u32 XBayer_photo_accl_IsReady(XBayer_photo_accl *InstancePtr) {
    u32 Data;

    Xil_AssertNonvoid(InstancePtr != NULL);
    Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);

    Data = XBayer_photo_accl_ReadReg(InstancePtr->Control_bus_BaseAddress, XBAYER_PHOTO_ACCL_CONTROL_BUS_ADDR_AP_CTRL);
    // check ap_start to see if the pcore is ready for next input
    return !(Data & 0x1);
}
u32 XClahe_accl_IsReady(XClahe_accl *InstancePtr) {
    u32 Data;

    Xil_AssertNonvoid(InstancePtr != NULL);
    Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);

    Data = XClahe_accl_ReadReg(InstancePtr->Control_bus_BaseAddress, XCLAHE_ACCL_CONTROL_BUS_ADDR_AP_CTRL);
    // check ap_start to see if the pcore is ready for next input
    return !(Data & 0x1);
}

这个函数,读取模块ready状态,
首先读取control寄存器,
然后再和0x01相与,取出ap_start的值,
然后取反,返回。
注意,返回值的bit0携带对应的ap_start的值的取反值,其他位全部为0。

6)enable_auto_restart

void XBayer_photo_accl_EnableAutoRestart(XBayer_photo_accl *InstancePtr) {
    Xil_AssertVoid(InstancePtr != NULL);
    Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);

    XBayer_photo_accl_WriteReg(InstancePtr->Control_bus_BaseAddress, XBAYER_PHOTO_ACCL_CONTROL_BUS_ADDR_AP_CTRL, 0x80);
}
void XClahe_accl_EnableAutoRestart(XClahe_accl *InstancePtr) {
    Xil_AssertVoid(InstancePtr != NULL);
    Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);

    XClahe_accl_WriteReg(InstancePtr->Control_bus_BaseAddress, XCLAHE_ACCL_CONTROL_BUS_ADDR_AP_CTRL, 0x80);
}

这个函数,设置模块的auto_restart状态,
写入control寄存器中的ap_auto_restart位。

7)disable_auto_restart

void XBayer_photo_accl_DisableAutoRestart(XBayer_photo_accl *InstancePtr) {
    Xil_AssertVoid(InstancePtr != NULL);
    Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);

    XBayer_photo_accl_WriteReg(InstancePtr->Control_bus_BaseAddress, XBAYER_PHOTO_ACCL_CONTROL_BUS_ADDR_AP_CTRL, 0);
}
void XClahe_accl_DisableAutoRestart(XClahe_accl *InstancePtr) {
    Xil_AssertVoid(InstancePtr != NULL);
    Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);

    XClahe_accl_WriteReg(InstancePtr->Control_bus_BaseAddress, XCLAHE_ACCL_CONTROL_BUS_ADDR_AP_CTRL, 0);
}

这个函数,禁止模块的auto_restart状态,
写入control寄存器中的ap_auto_restart位。

8)interrupt_global_enable

void XBayer_photo_accl_InterruptGlobalEnable(XBayer_photo_accl *InstancePtr) {
    Xil_AssertVoid(InstancePtr != NULL);
    Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);

    XBayer_photo_accl_WriteReg(InstancePtr->Control_bus_BaseAddress, XBAYER_PHOTO_ACCL_CONTROL_BUS_ADDR_GIE, 1);
}
void XClahe_accl_InterruptGlobalEnable(XClahe_accl *InstancePtr) {
    Xil_AssertVoid(InstancePtr != NULL);
    Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);

    XClahe_accl_WriteReg(InstancePtr->Control_bus_BaseAddress, XCLAHE_ACCL_CONTROL_BUS_ADDR_GIE, 1);
}

这个函数,使能模块的全局中断。
写入gie寄存器的gie位。

寄存器定义如下:

// 0x04 : Global Interrupt Enable Register
//        bit 0  - Global Interrupt Enable (Read/Write)
//        others - reserved


9)interrupt_global_disable

void XBayer_photo_accl_InterruptGlobalDisable(XBayer_photo_accl *InstancePtr) {
    Xil_AssertVoid(InstancePtr != NULL);
    Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);

    XBayer_photo_accl_WriteReg(InstancePtr->Control_bus_BaseAddress, XBAYER_PHOTO_ACCL_CONTROL_BUS_ADDR_GIE, 0);
}
void XClahe_accl_InterruptGlobalDisable(XClahe_accl *InstancePtr) {
    Xil_AssertVoid(InstancePtr != NULL);
    Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);

    XClahe_accl_WriteReg(InstancePtr->Control_bus_BaseAddress, XCLAHE_ACCL_CONTROL_BUS_ADDR_GIE, 0);
}

这个函数,禁止模块的全局中断。
写入gie寄存器的gie位。

10)interrupt_enable

void XBayer_photo_accl_InterruptEnable(XBayer_photo_accl *InstancePtr, u32 Mask) {
    u32 Register;

    Xil_AssertVoid(InstancePtr != NULL);
    Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);

    Register =  XBayer_photo_accl_ReadReg(InstancePtr->Control_bus_BaseAddress, XBAYER_PHOTO_ACCL_CONTROL_BUS_ADDR_IER);
    XBayer_photo_accl_WriteReg(InstancePtr->Control_bus_BaseAddress, XBAYER_PHOTO_ACCL_CONTROL_BUS_ADDR_IER, Register | Mask);
}
void XClahe_accl_InterruptEnable(XClahe_accl *InstancePtr, u32 Mask) {
    u32 Register;

    Xil_AssertVoid(InstancePtr != NULL);
    Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);

    Register =  XClahe_accl_ReadReg(InstancePtr->Control_bus_BaseAddress, XCLAHE_ACCL_CONTROL_BUS_ADDR_IER);
    XClahe_accl_WriteReg(InstancePtr->Control_bus_BaseAddress, XCLAHE_ACCL_CONTROL_BUS_ADDR_IER, Register | Mask);
}

这个函数,使能模块的各个独立中断源。
首先读出IER寄存器的值,暂存,
然后,根据MASK中提供的bit位,和暂存的原寄存器值相或,写入IER对应的位置。

寄存器定义如下:


// 0x08 : IP Interrupt Enable Register (Read/Write)
//        bit 0  - Channel 0 (ap_done)
//        bit 1  - Channel 1 (ap_ready)
//        others - reserved

有两个可用的中断源 ,ap_done和ap_ready。
当ap_done拉高有效时,模块发出一个中断给CPU,此时CPU可以触发对应的前台ISR来处理,从而实现与模块的交互。
当ap_ready拉高有效时,模块发出一个中断给CPU,此时CPU可以出发对应的前台ISR来处理,从而实现与模块的交互。
从CPU的角度看来,
如果执行进入了前台ISR,那么说明模块产生了对应的event。

11)interrupt_disable

void XBayer_photo_accl_InterruptDisable(XBayer_photo_accl *InstancePtr, u32 Mask) {
    u32 Register;

    Xil_AssertVoid(InstancePtr != NULL);
    Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);

    Register =  XBayer_photo_accl_ReadReg(InstancePtr->Control_bus_BaseAddress, XBAYER_PHOTO_ACCL_CONTROL_BUS_ADDR_IER);
    XBayer_photo_accl_WriteReg(InstancePtr->Control_bus_BaseAddress, XBAYER_PHOTO_ACCL_CONTROL_BUS_ADDR_IER, Register & (~Mask));
}
void XClahe_accl_InterruptDisable(XClahe_accl *InstancePtr, u32 Mask) {
    u32 Register;

    Xil_AssertVoid(InstancePtr != NULL);
    Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);

    Register =  XClahe_accl_ReadReg(InstancePtr->Control_bus_BaseAddress, XCLAHE_ACCL_CONTROL_BUS_ADDR_IER);
    XClahe_accl_WriteReg(InstancePtr->Control_bus_BaseAddress, XCLAHE_ACCL_CONTROL_BUS_ADDR_IER, Register & (~Mask));
}

这个函数,禁止模块的各个独立中断源。
首先读出IER寄存器的值,暂存,
然后,根据MASK中提供的bit位,对MASK取反后,和暂存的原寄存器值相与,写入IER对应的位置。

12)interrupt_get_enable

u32 XBayer_photo_accl_InterruptGetEnabled(XBayer_photo_accl *InstancePtr) {
    Xil_AssertNonvoid(InstancePtr != NULL);
    Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);

    return XBayer_photo_accl_ReadReg(InstancePtr->Control_bus_BaseAddress, XBAYER_PHOTO_ACCL_CONTROL_BUS_ADDR_IER);
}
u32 XClahe_accl_InterruptGetEnabled(XClahe_accl *InstancePtr) {
    Xil_AssertNonvoid(InstancePtr != NULL);
    Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);

    return XClahe_accl_ReadReg(InstancePtr->Control_bus_BaseAddress, XCLAHE_ACCL_CONTROL_BUS_ADDR_IER);
}

这个函数,获取模块的各个独立中断源的使能状态。
读出IER寄存器的值,返回。

13)interrupt_clear

void XBayer_photo_accl_InterruptClear(XBayer_photo_accl *InstancePtr, u32 Mask) {
    Xil_AssertVoid(InstancePtr != NULL);
    Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);

    XBayer_photo_accl_WriteReg(InstancePtr->Control_bus_BaseAddress, XBAYER_PHOTO_ACCL_CONTROL_BUS_ADDR_ISR, Mask);
}
void XClahe_accl_InterruptClear(XClahe_accl *InstancePtr, u32 Mask) {
    Xil_AssertVoid(InstancePtr != NULL);
    Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);

    XClahe_accl_WriteReg(InstancePtr->Control_bus_BaseAddress, XCLAHE_ACCL_CONTROL_BUS_ADDR_ISR, Mask);
}

这个函数,对模块的各个独立中断源的状态清零。
根据MASK中提供的bit位,写入ISR对应的位置。
寄存器定义如下:

// 0x0c : IP Interrupt Status Register (Read/TOW)
//        bit 0  - Channel 0 (ap_done)
//        bit 1  - Channel 1 (ap_ready)
//        others - reserved

注意,CPU中的中断清标,一般都是通过写1来清标的。

14)interrupt_get_status

u32 XBayer_photo_accl_InterruptGetStatus(XBayer_photo_accl *InstancePtr) {
    Xil_AssertNonvoid(InstancePtr != NULL);
    Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);

    return XBayer_photo_accl_ReadReg(InstancePtr->Control_bus_BaseAddress, XBAYER_PHOTO_ACCL_CONTROL_BUS_ADDR_ISR);
}
u32 XClahe_accl_InterruptGetStatus(XClahe_accl *InstancePtr) {
    Xil_AssertNonvoid(InstancePtr != NULL);
    Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);

    return XClahe_accl_ReadReg(InstancePtr->Control_bus_BaseAddress, XCLAHE_ACCL_CONTROL_BUS_ADDR_ISR);
}

这个函数,读取模块的各个独立中断源的状态。

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
这些共性的部分,我们可以封装成一个基类class,名为xhls_accl。

cfginit函数,主要是填充结构体,所以这个函数可以被移植成构建函数,来完成同样的功能。
每个不同的模块,对应一个不同的AXIMM区域,所以,基类可以封装一个io_mem的对象。

这些共性操作集,可以被移植并封装成基类class的成员函数。
如下:

#include "io_mem.h"

//寄存器偏移
#define XHLS_REG_CTRL_START                     BIT(0)
#define XHLS_REG_CTRL_DONE                      BIT(1)
#define XHLS_REG_CTRL_IDLE                      BIT(2)
#define XHLS_REG_CTRL_READY                     BIT(3)
#define XHLS_REG_CTRL_AUTO_RESTART              BIT(7)
#define XHLS_REG_GIE                            0x04
#define XHLS_REG_GIE_GIE                        BIT(0)
#define XHLS_REG_IER                            0x08
#define XHLS_REG_IER_DONE                       BIT(0)
#define XHLS_REG_IER_READY                      BIT(1)
#define XHLS_REG_ISR                            0x0c
#define XHLS_REG_ISR_DONE                       BIT(0)
#define XHLS_REG_ISR_READY                      BIT(1)
#define XHLS_REG_ROWS                           0x10
#define XHLS_REG_COLS                           0x18


//HLS偏移
#define HLS_LOW16_MASK					GENMASK(15, 0)
#define HLS_LOW16_SHIFT					0
#define HLS_HIGH16_MASK					GENMASK(31, 16)
#define HLS_HIGH16_SHIFT				16

#define HLS_LOW8_MASK					GENMASK(7, 0)
#define HLS_LOW8_SHIFT					0
#define HLS_HIGH8_MASK					GENMASK(15, 8)
#define HLS_HIGH8_SHIFT					8

class XhlsAccl
{
public:
	XhlsAccl(u32 phy_base, u32 size) {
		regs_.phy_base_ = phy_base;
		regs_.total_size_ = size;
	}

	void set_ap_start_value(int value) {
		regs_.set_bit_value(0, XHLS_REG_CTRL_START, value);
	}

	void set_ap_auto_restart_value(int value) {
		regs_.set_bit_value(0, XHLS_REG_CTRL_AUTO_RESTART, value);
	}

	void set_gie_gie_value(int value) {
		regs_.set_bit_value(1, XHLS_REG_GIE_GIE, value);
	}

	void set_ier_use_done_value(int value) {
		regs_.set_bit_value(2, XHLS_REG_IER_DONE, value);
	}

	void set_ier_use_ready_value(int value) {
		regs_.set_bit_value(2, XHLS_REG_IER_READY, value);
	}

	void set_isr(u32 value) {
		regs_.set_value(3, value);
	}

	u32 get_ap() {
		return regs_.get_value(0);
	}

	u32 get_isr() {
		return regs_.get_value(3);
	}

	void set_u16_with_en(u32 offset, u32 value, u8 en, int flag = 1) {
		en  = en & 1;
		u32 mask = (en == 0) ? HLS_LOW16_MASK : HLS_HIGH16_MASK;
		u32 shift = (en == 0) ? HLS_LOW16_SHIFT : HLS_HIGH16_SHIFT;

		regs_.set_value(offset, value, mask, shift, flag);
	}

	void set_u8_with_en(u32 offset, u32 value, u8 en, int flag = 1) {
		en  = en & 1;
		u32 mask = (en == 0) ? HLS_LOW8_MASK : HLS_HIGH8_MASK;
		u32 shift = (en == 0) ? HLS_LOW8_SHIFT : HLS_HIGH8_SHIFT;

		regs_.set_value(offset, value, mask, shift, flag);
	}

protected:
	IoMem regs_;
};
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值