整板硬件初始化相关。
1)构建函数
SystemManager::SystemManager() :
xcmos_(&cam_uart_, &sys_timer_),
xmotor_(&mcu_uart_, this),
xhost_(&host_uart_, this),
xaf_(this),
xaec_(this),
xin_(SYS_IN_0_REGS_ADDR, 0x1000),
xout_(SYS_OUT_0_REGS_ADDR, 0x1000),
xbayer_write_(BAYER_IP_REGS_ADDR, 0x1000),
xbayer_video_(VIDEO_IP_REGS_ADDR, 0x1000),
xbayer_photo_(PHOTO_IP_REGS_ADDR, 0x1000),
xcrop_(CROP_ACCL_REGS_ADDR, 0x1000),
xaf_accl_(AUTO_FOCUS_REGS_ADDR, 0x1000),
// xinfo_(RGB_INFO_REGS_ADDR, 0x1000),
xclahe_(CLAHE_ACCL_REGS_ADDR, 0x1000),
boot_state_(0),
state_timestamp_(0),
debug_mode_(0)
{
max_dzoom_scale_ = 2.581;
min_dzoom_scale_ = 1.0;
video_frame_count_ = 0;
sensor_frame_count_ = 0;
focus_motor_reach_ = 0;
photo_stamp_ = 0;
photo_over_mode_ = 0;
zoom_speed_ = 1;
dehazing_mode_ = 0;
hdr_mode_ = 0;
zoom_status_ = 0;
brightness_mode_ = 0;
brightness_value_ = 0;
contrast_mode_ = 0;
contrast_value_ = 0;
saturation_mode_ = 1;
saturation_value_ = 22000;
awb_mode_ = 0;
focus_radio_ = 1024;
}
构建函数,负责填充各个成员数据。
2)INTC初始化
int SystemManager::intc_init()
{
int ret;
XIntc* intc = &intc_;
/*
* Initialize the interrupt controller driver so that it is ready to
* use.
*/
ret = XIntc_Initialize(intc, 0);
if (ret != XST_SUCCESS) {
return -1;
}
/*
* Connect a device driver handler that will be called when an interrupt
* for the device occurs, the device driver handler performs the
* specific interrupt processing for the device.
*/
ret = XIntc_Connect(intc, HOST_UART_IRQ_ID, (XInterruptHandler)uart_lite_isr_handle, (void *)&host_uart_);
if (ret != XST_SUCCESS) {
return -1;
}
ret = XIntc_Connect(intc, MCU_UART_IRQ_ID, (XInterruptHandler)uart_lite_isr_handle, (void *)&mcu_uart_);
if (ret != XST_SUCCESS) {
return -1;
}
ret = XIntc_Connect(intc, CAM_UART_IRQ_ID, (XInterruptHandler)uart_lite_isr_handle, (void *)&cam_uart_);
if (ret != XST_SUCCESS) {
return -1;
}
ret = XIntc_Connect(intc, SYS_FLASH_IRQ_ID, (XInterruptHandler)XSpi_InterruptHandler, (void *)&sys_flash_.spi);
if (ret != XST_SUCCESS) {
return -1;
}
ret = XIntc_Connect(intc, FOCUS_MOTOR_IRQ_ID, (XInterruptHandler)focus_motor_isr_handle, (void *)this);
if (ret != XST_SUCCESS) {
return -1;
}
ret = XIntc_Connect(intc, RGB_INFO_IRQ_ID, (XInterruptHandler)video_isr_handle, (void *)this);
if (ret != XST_SUCCESS) {
return -1;
}
ret = XIntc_Connect(intc, SENSOR_TRIGGER_IRQ_ID, (XInterruptHandler)trigger_isr_handle, (void *)this);
if (ret != XST_SUCCESS) {
return -1;
}
ret = XIntc_Connect(intc, TIME_LOOP_IRQ_ID, (XInterruptHandler)time_loop_isr_handle, (void *)this);
if (ret != XST_SUCCESS) {
return -1;
}
/*
* Start the interrupt controller such that interrupts are enabled for
* all devices that cause interrupts, specific real mode so that
* the UartLite can cause interrupts through the interrupt controller.
*/
ret = XIntc_Start(intc, XIN_REAL_MODE);
if (ret != XST_SUCCESS) {
return -1;
}
/*
* Enable the interrupt for the UartLite device.
*/
XIntc_Enable(intc, HOST_UART_IRQ_ID);
XIntc_Enable(intc, MCU_UART_IRQ_ID);
XIntc_Enable(intc, CAM_UART_IRQ_ID);
XIntc_Enable(intc, SYS_FLASH_IRQ_ID);
XIntc_Enable(intc, FOCUS_MOTOR_IRQ_ID);
XIntc_Enable(intc, SENSOR_TRIGGER_IRQ_ID);
XIntc_Enable(intc, TIME_LOOP_IRQ_ID);
/*
* Initialize the exception table.
*/
Xil_ExceptionInit();
/*
* Register the interrupt controller handler with the exception table.
*/
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, (Xil_ExceptionHandler)XIntc_InterruptHandler, intc);
/*
* #define XIL_EXCEPTION_ID_UNALIGNED_ACCESS 1U
#define XIL_EXCEPTION_ID_ILLEGAL_OPCODE 2U
#define XIL_EXCEPTION_ID_M_AXI_I_EXCEPTION 3U
#define XIL_EXCEPTION_ID_IPLB_EXCEPTION 3U
#define XIL_EXCEPTION_ID_M_AXI_D_EXCEPTION 4U
#define XIL_EXCEPTION_ID_DPLB_EXCEPTION 4U
#define XIL_EXCEPTION_ID_DIV_BY_ZERO 5U
#define XIL_EXCEPTION_ID_FPU 6U
#define XIL_EXCEPTION_ID_STACK_VIOLATION 7U
*/
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_UNALIGNED_ACCESS, (Xil_ExceptionHandler)exception_unaligned_access_handle, (void *)this);
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_ILLEGAL_OPCODE, (Xil_ExceptionHandler)exception_illegal_opcode_handle, (void *)this);
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_M_AXI_D_EXCEPTION, (Xil_ExceptionHandler)exception_M_AXI_D_handle, (void *)this);
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_DIV_BY_ZERO, (Xil_ExceptionHandler)exception_div_by_zero_handle, (void *)this);
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_FPU, (Xil_ExceptionHandler)exception_fpu_handle, (void *)this);
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_STACK_VIOLATION, (Xil_ExceptionHandler)exception_stack_violation_handle, (void *)this);
/*
* Enable exceptions.
*/
Xil_ExceptionEnable();
return 0;
}
整个INTC的初始化过程,可以参考BSP中提供的各个example中提供的代码。
这里需要注意的就是,根据我们整板上的中断的配置,进行多个xintc_connect操作。
也可以根据需要,进行多个exception的register操作。
对于xinc_connect相关的interrupt handler,如下:
void focus_motor_isr_handle(SystemManager* sys)
{
XIntc* xintc = &sys->intc_;
//关闭中断
XIntc_Disable(xintc, FOCUS_MOTOR_IRQ_ID);
if (sys->boot_state_) {
//读取标志
sys->focus_motor_reach_ = 1;
}
//打开中断
XIntc_Enable(xintc, FOCUS_MOTOR_IRQ_ID);
}
void video_isr_handle(SystemManager* sys)
{
static u32 count = 0;
XIntc* xintc = &sys->intc_;
AxiLiteIn* xin = &sys->xin_;
AutoExpGain* xaec = &sys->xaec_;
AutoFocus* xaf = &sys->xaf_;
AutoFocusAccl* xaf_accl = &sys->xaf_accl_;
//关闭中断
XIntc_Disable(xintc, RGB_INFO_IRQ_ID);
if (sys->boot_state_) {
//读取清晰度评价
xaf->current_clarity_ = xaf_accl->get_clarity_value();
//帧计数
sys->video_frame_count_++;
//读取RGB分块均值数据
xin->get_rgb_win_sum(xaec->win_sum_);
u32 lum_level = xaec->calc_lum_level();
//防止亮度震荡
const u32 scale = 900;
xaec->lum_level_ = lum_level;//(scale * lum_level + (1024 - scale) * xaec->lum_level_) / 1024;
count++;
if (count >= 3) {
count = 0;
}
}
//打开中断
XIntc_Enable(xintc, RGB_INFO_IRQ_ID);
}
void trigger_isr_handle(SystemManager* sys)
{
XIntc* xintc = &sys->intc_;
AxiLiteIn* xin = &sys->xin_;
AutoExpGain* xaec = &sys->xaec_;
AutoFocus* xaf = &sys->xaf_;
AutoFocusAccl* xaf_accl = &sys->xaf_accl_;
//关闭中断
XIntc_Disable(xintc, SENSOR_TRIGGER_IRQ_ID);
if (sys->boot_state_) {
//设置数字增益
sys->xcmos_.set_digital_gain(sys->xaec_.gain_, 0);
//读取亮度均值
u32 bayer_sum = xin->get_bayer_sum();
u32 bayer_cnt = xin->get_bayer_cnt();
u32 bayer_aver = (bayer_cnt == 0) ? 0 : (bayer_sum / bayer_cnt);
xaec->lum_level_ = bayer_aver;
//读取清晰度评价
xaf->current_clarity_ = xaf_accl->get_clarity_value();
//帧计数
sys->sensor_frame_count_++;
}
//打开中断
XIntc_Enable(xintc, SENSOR_TRIGGER_IRQ_ID);
}
void sensor_isr_handle(SystemManager* sys)
{
XIntc* xintc = &sys->intc_;
AxiLiteIn* xin = &sys->xin_;
AutoExpGain* xaec = &sys->xaec_;
//关闭中断
XIntc_Disable(xintc, SENSOR_TRIGGER_IRQ_ID);
if (sys->boot_state_) {
//读取亮度均值
u32 bayer_sum = xin->get_bayer_sum();
u32 bayer_cnt = xin->get_bayer_cnt();
u32 bayer_aver = (bayer_cnt == 0) ? 0 : (bayer_sum / bayer_cnt);
xaec->lum_level_ = bayer_aver;
//帧计数
sys->sensor_frame_count_++;
}
//打开中断
XIntc_Enable(xintc, SENSOR_TRIGGER_IRQ_ID);
}
void time_loop_isr_handle(SystemManager* sys)
{
XIntc* xintc = &sys->intc_;
//关闭中断
XIntc_Disable(xintc, TIME_LOOP_IRQ_ID);
if (sys->boot_state_) {
//检查系统定时器
u32 now_timestamp = sys->get_timestamp();
if ((sys->state_timestamp_ != 0) && (sys->state_timestamp_ == now_timestamp)) {
syslog("system timer is stop: timestamp=%u!!!!\r\n", now_timestamp);
}
sys->state_timestamp_ = now_timestamp;
}
//打开中断
XIntc_Enable(xintc, TIME_LOOP_IRQ_ID);
}
这些callback,传入的参数callbackref,都是一个systemmanager对象,它是拥有最大索引范围的对象,以它为callbackref,是最合适的。
对于exception_register相关的exceptionhandler,如下:
void exception_unaligned_access_handle(void *arg)
{
syslog("exception_unaligned_access_handle\r\n");
}
void exception_illegal_opcode_handle(void *arg)
{
syslog("exception_illegal_opcode_handle\r\n");
}
void exception_M_AXI_D_handle(void *arg)
{
syslog("exception_M_AXI_D_handle\r\n");
}
void exception_div_by_zero_handle(void *arg)
{
syslog("exception_div_by_zero_handle\r\n");
}
void exception_fpu_handle(void *arg)
{
syslog("exception_fpu_handle\r\n");
}
void exception_stack_violation_handle(void *arg)
{
syslog("exception_stack_violation_handle\r\n");
}
3)sensor_init
void SystemManager::sensor_init()
{
u32 value;
xcmos_.set_aoi_hsize(sensor_width_);
xcmos_.set_aoi_vsize(sensor_height_);
xcmos_.set_aoi_hoff(0);
xcmos_.set_aoi_voff(480);
xcmos_.set_pixel_clock_rate(110);
xcmos_.set_fixed_frame_period(33333);
xcmos_.set_fixed_frame_period_en(1);
//最大增益
xcmos_.set_digital_gain(1024);
xcmos_.set_anglog_gain(1);
#if SENSOR_TRIGGER_ENABLE
xcmos_.set_ignore_next_trigger(1);
xcmos_.set_trigger_edge_selector(0);
xcmos_.set_trigger_input(2);
xcmos_.set_trigger_enable(1);
xcmos_.set_exposure_mode(1);
xout_.set_exposure_time(15000);
#else
xcmos_.set_trigger_enable(0);
xcmos_.set_exposure_mode(2);
xcmos_.set_exposure_time(15000);
#endif
//打开自动曝光
xcmos_.set_aec_en(0);
//打开自动增益
xcmos_.set_agc_en(0);
u32 current_hsize = 0, current_vsize = 0;
u32 max_hsize = 0, max_vsize = 0;
}
这里主要是调用xcmos_成员对象的操作集完成需要的操作。
关于xcmos这个类,后面再讲。
4)fpga_isp_init
void SystemManager::fpga_isp_init()
{
xout_.set_ccm_mode(1);
xout_.set_awb_mode(1);
xout_.set_awb_Auto_en(1);
xout_.set_awb_TL84_en(0);
xout_.set_awb_CWF_en(0);
xout_.set_awb_A_light_en(0);
xout_.set_brightness_mode(brightness_mode_);
xout_.set_brightness_value((u16)brightness_value_);
xout_.set_contrast_mode(contrast_mode_);
xout_.set_contrast_value((u16)contrast_value_);
xout_.set_saturation_mode(saturation_mode_);
xout_.set_saturation_value((u16)saturation_value_);
xout_.set_sharpness_mode(0);
xout_.set_sharp_shold(800);
xout_.set_sharpness_k1(2);
xout_.set_sharpness_k2(2);
set_cursor_x(video_width_ / 2);
set_cursor_y(video_height_ / 2);
xout_.set_rgbyuv_sw(1);
xout_.set_yuv_mode(0);
xout_.set_color_mode(0);
//测试图像
xout_.set_tpg_en(0);
xout_.set_tpg_mode(1);
xout_.set_photo_cmd(0);
xout_.set_photo_hcnt_max(1);
xout_.set_photo_vcnt_max(100000000);
xout_.set_photo_mode(0);
usleep(1000);
xout_.set_photo_mode(1);
}
这里主要是调用xout_对象的操作集,完成需要的操作。
AXILITE_OUT这个类,如前所述。
其中有几个函数需要特别说明,
set_cursor_x,set_cursor_y,这两个函数,是为了进一步封装操作,而设计的成员函数,所以这里看到,其调用形式,并不是“对象名索引成员函数名”的形式,形如xout_.xxx()的形式,由成员索引操作符(.)来连接左侧的对象名和右侧的成员函数名。
在书写上,没有前缀对象名,而是函数直接调用的形式。
而usleep,这个函数,是BSP提供的函数,这是全局函数,并不属于某个特定的类对象,所以,也是传统的函数直接调用的形式。
void SystemManager::set_cursor_x(int value) {
const int w = 40;
const int minx = w;
const int maxx = video_width_ - w;
value = (value < minx) ? minx : ((value > maxx) ? maxx : value);
cursor_x_ = value;
xout_.set_cursor_x(cursor_x_);
xout_.set_cursor_en(1);
usleep(10);
xout_.set_cursor_en(0);
}
void SystemManager::set_cursor_y(int value) {
const int h = 40;
const int miny = h;
const int maxy = video_height_ - h;
value = (value < miny) ? miny : ((value > maxy) ? maxy : value);
cursor_y_ = value;
xout_.set_cursor_y(cursor_y_);
xout_.set_cursor_en(1);
usleep(10);
xout_.set_cursor_en(0);
}
可以看出,这两个成员函数,是为了增强可读性,提供更好的封装,将一些操作进行了封装。
5)hls_isp_init
void SystemManager::hls_isp_init()
{
xbayer_write_.set_ddr_base(ddr_base_);
xbayer_write_.set_width(sensor_width_);
xbayer_write_.set_height(sensor_height_);
xbayer_write_.set_param(0, 0, sensor_width_, sensor_height_);
xbayer_video_.set_ddr_base(ddr_base_);
xbayer_video_.set_sensor_width(sensor_width_);
xbayer_video_.set_sensor_height(sensor_height_);
xbayer_video_.set_delay_frame(2);
xbayer_video_.set_param(0, 0, 0, sensor_width_, sensor_height_, 3, video_align_width_, video_align_height_);
set_dzoom_scale(max_dzoom_scale_);
set_flip_mode(0);
xbayer_photo_.set_ddr_base(ddr_base_);
xbayer_photo_.set_width(sensor_width_);
xbayer_photo_.set_height(sensor_height_);
xbayer_photo_.set_param(photo_width_, photo_height_, sensor_width_, sensor_height_);
xclahe_.set_width(video_align_width_);
xclahe_.set_height(video_align_height_);
xclahe_.set_limit_th(80);
xclahe_.set_scale_th(2);
xclahe_.set_mode(1);
xcrop_.set_crop_x((video_align_width_ - video_width_) / 2);
xcrop_.set_crop_y((video_align_height_ - video_height_) / 2);
xcrop_.set_crop_width(video_width_);
xcrop_.set_crop_height(video_height_);
xcrop_.set_width(video_align_width_);
xcrop_.set_height(video_align_height_);
int af_roi_width = 1024;
int af_roi_height = 512;
int af_roi_x = (video_align_width_ - af_roi_width) / 2;
int af_roi_y = (video_align_height_ - af_roi_height) / 2;
xaf_accl_.set_roi_x(af_roi_x);
xaf_accl_.set_roi_y(af_roi_y);
xaf_accl_.set_roi_width(af_roi_width);
xaf_accl_.set_roi_height(af_roi_height);
xaf_accl_.set_width(video_align_width_);
xaf_accl_.set_height(video_align_height_);
}
这里主要是调用各个类对象中定义的操作集,完成需要的操作。
这几个类,如前所述。
其中有几个函数需要特别说明,
set_dzoom_scale,set_flip_mode,这两个函数,是为了进一步封装操作,而设计的成员函数,所以这里看到,其调用形式,并不是“对象名索引成员函数名”的形式,形如xclahe_.xxx()的形式,由成员索引操作符(.)来连接左侧的对象名和右侧的成员函数名。
在书写上,没有前缀对象名,而是函数直接调用的形式。
而usleep,这个函数,是BSP提供的函数,这是全局函数,并不属于某个特定的类对象,所以,也是传统的函数直接调用的形式。
void SystemManager::set_dzoom_scale(float value) {
dzoom_scale_ = value;
u32 align_width = (u32)((video_align_width_ / video_align_wsize_ / 2) * dzoom_scale_) * video_align_wsize_ * 2;
if (align_width > sensor_width_) {
align_width = sensor_width_;
}
float align_scale = align_width / ((float)video_align_width_);
u32 crop_width = xbayer_video_.check_width(align_width);
u32 crop_height = xbayer_video_.check_height(video_align_height_ * align_scale);
u32 crop_x = xbayer_video_.check_x((sensor_width_ - crop_width) / 2);
u32 crop_y = xbayer_video_.check_y((sensor_height_ - crop_height) / 2);
xbayer_video_.set_param(flip_mode_, crop_x, crop_y, crop_width, crop_height, bayer_mode_, video_align_width_, video_align_height_);
}
void SystemManager::set_flip_mode(int value) {
switch(value)
{
case 0://正常显示
{
flip_mode_ = 0;
bayer_mode_ = 3;
xbayer_video_.set_param(flip_mode_, xbayer_video_.crop_x_, xbayer_video_.crop_y_, xbayer_video_.crop_width_, xbayer_video_.crop_height_, bayer_mode_, xbayer_video_.dst_width_, xbayer_video_.dst_height_);
}break;
case 1://上下翻转
{
flip_mode_ = 1;
bayer_mode_ = 1;
xbayer_video_.set_param(flip_mode_, xbayer_video_.crop_x_, xbayer_video_.crop_y_, xbayer_video_.crop_width_, xbayer_video_.crop_height_, bayer_mode_, xbayer_video_.dst_width_, xbayer_video_.dst_height_);
}break;
case 2://左右翻转
{
flip_mode_ = 2;
bayer_mode_ = 3;
xbayer_video_.set_param(flip_mode_, xbayer_video_.crop_x_, xbayer_video_.crop_y_, xbayer_video_.crop_width_, xbayer_video_.crop_height_, bayer_mode_, xbayer_video_.dst_width_, xbayer_video_.dst_height_);
}break;
case 3://上下左右翻转
{
flip_mode_ = 3;
bayer_mode_ = 1;
xbayer_video_.set_param(flip_mode_, xbayer_video_.crop_x_, xbayer_video_.crop_y_, xbayer_video_.crop_width_, xbayer_video_.crop_height_, bayer_mode_, xbayer_video_.dst_width_, xbayer_video_.dst_height_);
}break;
default:
break;
}
}
可以看出,这两个成员函数,是为了增强可读性,提供更好的封装,将一些操作进行了封装。
6)hls_isp_start
void SystemManager::hls_isp_start()
{
xbayer_write_.set_ap_auto_restart_value(1);
xbayer_write_.set_ap_start_value(1);
xbayer_video_.set_ap_auto_restart_value(1);
xbayer_video_.set_ap_start_value(1);
xbayer_photo_.set_ap_auto_restart_value(1);
xbayer_photo_.set_ap_start_value(1);
xclahe_.set_ap_auto_restart_value(1);
xclahe_.set_ap_start_value(1);
xcrop_.set_ap_auto_restart_value(1);
xcrop_.set_ap_start_value(1);
xaf_accl_.set_ap_auto_restart_value(1);
xaf_accl_.set_ap_start_value(1);
}
7)vtc_start
void SystemManager::vtc_start()
{
//video_crop
xout_.set_video_align_width(video_align_width_);
xout_.set_video_align_height(video_align_height_);
xout_.set_video_width(video_width_);
xout_.set_video_height(video_height_);
xout_.set_video_crop_x((video_align_width_ - video_width_) / 2);
xout_.set_video_crop_y((video_align_height_ - video_height_) / 2);
// vtc0
xout_.set_vtc0_reset(1);
xout_.set_vtc0_mode(1);
xout_.set_vtc0_active_hsize(video_width_);
xout_.set_vtc0_active_vsize(video_height_);
xout_.set_vtc0_frame_hsize(2200);
xout_.set_vtc0_frame_vsize(1125);
xout_.set_vtc0_hvalid_start(16);
xout_.set_vtc0_vvalid_start(4);
xout_.set_vtc0_hsync_start(8);
xout_.set_vtc0_hsync_end(2052);
xout_.set_vtc0_vsync_hstart(0);
xout_.set_vtc0_vsync_hend(0);
xout_.set_vtc0_vsync_vstart(3);
xout_.set_vtc0_vsync_vend(1092);
xout_.set_sdi_rst_vcnt_num(1);
xout_.set_sdi_sync_vcnt_num(35);
xout_.set_sdi_start_vcnt_num(41);
xout_.set_sdi_end_vcnt_num(1121);
usleep(2000);
xout_.set_vtc0_reset(0);
//vtc1
xout_.set_vtc1_reset(1);
xout_.set_vtc1_mode(1);
xout_.set_vtc1_active_hsize(photo_width_);
xout_.set_vtc1_active_vsize(photo_height_);
xout_.set_vtc1_frame_hsize(5620);
xout_.set_vtc1_frame_vsize(4102);
xout_.set_vtc1_hvalid_start(250);
xout_.set_vtc1_vvalid_start(3);
xout_.set_vtc1_hsync_start(200);
xout_.set_vtc1_hsync_end(250 + photo_width_ + 50);
xout_.set_vtc1_vsync_hstart(0);
xout_.set_vtc1_vsync_hend(0);
xout_.set_vtc1_vsync_vstart(3);
xout_.set_vtc1_vsync_vend(3 + photo_height_);
usleep(2000);
xout_.set_vtc1_reset(0);
//等待photo流初始化
sleep(3);
}
其中的usleep和sleep函数,都是BSP提供的函数,位于sleep.h文件中。
8)GPIO的初始化
int SystemManager::isp_gpio_init(XGpio* instance, u16 dev_id)
{
int ret;
ret = XGpio_Initialize(instance, dev_id);
if (ret != XST_SUCCESS)
return -1;
XGpio_SetDataDirection(instance, 1, 0);
return 0;
}
这里参考了BSP中提供的GPIO的example的例子,封装了gpio_init函数。
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
下面补充一个关于reset操作的函数,一并视为初始化相关
9)fpga_reset
void SystemManager::fpga_reset()
{
xout_.set_ap_reset(1);
xout_.set_st_reset(1);
usleep(1000);
xout_.set_ap_reset(0);
xout_.set_st_reset(0);
usleep(1000);
isp_ap_reset(&isp_gpio_);
}
利用set操作配合以sleep操作,完成内部signal的时序控制。
10)isp_ap_reset
void SystemManager::isp_ap_reset(XGpio* instance)
{
XGpio_DiscreteWrite(instance, 1, 3);
usleep(1000);
XGpio_DiscreteWrite(instance, 1, 0);
usleep(1000);
}
利用XGpio_DiscreteWrite配合以sleep操作,完成AXI_GPIO的时序控制。
11)isp_ap_set_reset
void SystemManager::isp_ap_set_reset(XGpio* instance, u32 value)
{
XGpio_DiscreteWrite(instance, 1, value);
usleep(1000);
}
利用XGpio_DiscreteWrite配合以sleep操作,完成AXI_GPIO的时序控制。