MI PSPI API
1. 概述¶
1.1. 模块说明¶
通过PSPI从sensor获取图像数据,或将图像数据通过PSPI传输到panel。
注意:目前sensor只能接PSPI0,panel只能接PSPI1。
1.2. 流程框图¶
芯片可以将PSPI0设置为从机,然后通过PSPI从sensor获取数据,同时搭配有一个BDMA用来将获取到的数据写入内存;
芯片可以将PSPI1设置为主机,然后通过PSPI将数据发送到panel,内部搭配有一个BDMA用来读取内存中的数据。
2. API 参考¶
2.1. API功能模块¶
API名 | 功能 |
---|---|
MI_PSPI_CreateDevice | 创建PSPI设备并配置PSPI属性 |
MI_PSPI_DestroyDevice | 销毁PSPI设备 |
MI_PSPI_Transfer | 给PSPI设备发送参数信息,对外部所接设备的参数进行配置 |
MI_PSPI_SetDevAttr | 设置PSPI属性 |
MI_PSPI_SetOutputAttr | 设置PSPI输出端口属性 |
MI_PSPI_Enable | 启用PSPI设备 |
MI_PSPI_Disable | 禁用PSPI设备 |
2.2. MI_PSPI_CreateDevice¶
-
描述
创建PSPI设备并配置其属性。
-
语法
MI_S32 MI_PSPI_CreateDevice (MI_PSPI_DEV PspiDev, MI_PSPI_Param_t * pstPspiParam);
-
参数
参数名称 描述 输入/输出 MI_PSPI_DEV PSPI具体设备 输入 MI_PSPI_Param_t PSPI设备的具体属性 输入 -
返回值
-
MI_PSPI_SUCCESS 成功。
-
非MI_PSPI_SUCCESS 失败,具体见错误码。
-
-
需求
-
头文件:mi_pspi.h mi_pspi_datatype.h
-
库文件:libmi_pspi_user.a/libmi_pspi_user.so
-
-
注意
同一PSPI设备不能连续创建两次,如果要再修改PSPI的属性,可以通过MI_PSPI_SetDevAttr进行修改
2.3. MI_PSPI_DestroyDevice¶
-
描述
销毁PSPI设备。
-
语法
MI_S32 MI_PSPI_DestroyDevice(MI_PSPI_DEV PspiDev) ;
-
参数
参数名称 描述 输入/输出 MI_PSPI_DEV 需要销毁的PSPI设备。 输入 -
返回值
-
MI_PSPI_SUCCESS 成功。
-
非MI_PSPI_SUCCESS 失败,具体见错误码。
-
-
需求
-
头文件:mi_pspi.h mi_pspi_datatype.h
-
库文件:libmi_pspi_user.a/libmi_pspi_user.so
-
2.4. MI_PSPI_Transfer¶
-
描述
给PSPI外部所接设备发送参数信息,对外部所接设备的参数进行配置。
-
语法
MI_S32 MI_PSPI_Transfer(MI_PSPI_DEV PspiDev, MI_PSPI_Msg_t *pstMsg)
-
参数
参数名称 描述 输入/输出 MI_PSPI_DEV PSPI具体设备 输入 MI_PSPI_Msg_t 发送给从机设备的具体参数 输入 -
返回值
-
MI_PSPI_SUCCESS 成功。
-
非MI_PSPI_SUCCESS 失败,具体见错误码。
-
-
需求
-
头文件:mi_pspi.h mi_pspi_datatype.h
-
库文件:libmi_pspi_user.a/libmi_pspi_user.so
-
-
注意
这个函数是用来通过PSPI向从机发送数据来控制从机的,如使用PSPI点亮panel时,在向panel发送具体的图像数据前需要对panel发送一些控制参数,这些控制参数就可以通过这个函数进行发送。一次性发送参数的数量可以由mi_pspi_datatype.h 中的 PSPI_ PARAM_BUFF_SIZE 宏来进行控制
2.5. MI_PSPI_SetDevAttr¶
-
描述
配置PSPI属性。
-
语法
MI_S32 MI_PSPI_SetDevAttr(MI_PSPI_DEV PspiDev, MI_PSPI_Param_t * pstPspiParam);
-
参数
参数名称 描述 输入/输出 MI_PSPI_DEV PSPI具体设备 输入 MI_PSPI_Param_t 即将要进行配置的具体属性 输入 -
返回值
-
MI_PSPI_SUCCESS 成功。
-
非MI_PSPI_SUCCESS 失败,具体见错误码。
-
-
需求
-
头文件:mi_pspi.h mi_pspi_datatype.h
-
库文件:libmi_pspi_user.a/libmi_pspi_user.so
-
-
注意
这个函数是用来对PSPI的属性进行修改,如果不需要修改,可不调用。
2.6. MI_PSPI_SetOutputAttr¶
-
描述
设置PSPI输出端口的属性。
-
语法
MI_S32 MI_PSPI_SetOutputAttr(MI_PSPI_OutputAttr_t * pstOutputAttr);
-
参数
参数名称 描述 输入/输出 MI_PSPI_OutAttr_t 即将要进行配置的属性 输入 -
返回值
-
MI_PSPI_SUCCESS 成功。
-
非MI_PSPI_SUCCESS 失败,具体见错误码。
-
-
需求
-
头文件:mi_pspi.h mi_pspi_datatype.h
-
库文件:libmi_pspi_user.a/libmi_pspi_user.so
-
-
注意
这个函数是用来对存储sensor 数据的buffer 属性进行设置,在接panel时这个函数无作用。其中sensor的输出通道的默认属性为640 * 480, YUV 422 格式。
2.7. MI_PSPI_Enable¶
-
描述
启用PSPI设备。
-
语法
MI_S32 MI_PSPI_Enable(MI_PSPI_DEV PspiDev );
-
参数
参数名称 描述 输入/输出 MI_PSPI_DEV 要启用的PSPI设备 输入 -
返回值
-
MI_PSPI_SUCCESS 成功。
-
非MI_PSPI_SUCCESS 失败,具体见错误码。
-
-
需求
-
头文件:mi_pspi.h mi_pspi_datatype.h
-
库文件:libmi_pspi_user.a/libmi_pspi_user.so
-
-
注意
在使用mi_sys的相关接口操作PSPI前,必须调用这个函数进行使能。
2.8. MI_PSPI_Disable¶
-
描述
禁用PSPI设备。
-
语法
MI_S32 MI_PSPI_Disable(MI_PSPI_DEV PspiDev );
-
参数
参数名称 描述 输入/输出 MI_PSPI_DEV 要禁用的PSPI设备 输入 -
返回值
-
MI_PSPI_SUCCESS 成功。
-
非MI_PSPI_SUCCESS 失败,具体见错误码。
-
-
需求
-
头文件:mi_pspi.h mi_pspi_datatype.h
-
库文件:libmi_pspi_user.a/libmi_pspi_user.so
-
-
注意
在不需要再使用PSPI时,必须调用这个函数禁用PSPI。
3. PSPI 数据类型¶
3.1. 模块相关数据类型定义¶
数据类型 | 定义 |
---|---|
MI_PSPI_Msg_t | 定义传输给外部连接的PSPI设备参数的数据帧 |
MI_PSPI_OutputAttr_t | 定义PSPI输出端口属性 |
MI_PSPI_Param_t | 定义PSPI属性 |
MI_PSPI_DEV | 定义PSPI的设备编号 |
3.2. MI_PSPI_Msg_t¶
-
说明
定义使用PSPI向外部设备传输参数时的数据帧。
-
定义
typedef struct{ MI_U16 u16TxSize; MI_U16 u16RxSize; MI_U8 u8TxBitCount; MI_U8 u8RxBitCount; MI_U16 au16TxBuf[PSPI_PARAM_BUFF_SIZE]; MI_U16 au16RxBuf[PSPI_PARAM_BUFF_SIZE]; } MI_PSPI_Msg_t ;
-
注意事项
每次传输的最大数据个数是由宏 PSPI_PARAM_BUFF_SIZE 来控制的
-
成员
成员名称 描述 u16TxSize 发送数据数目(MI_U16类型大小) u16RxSize 接收数据数目(MI_U16类型大小) u8TxBitCount 发送时一次传输的bit数目 u8RxBitCount 接收时一次传输的bit数目 au16TxBuf[PSPI_PARAM_BUFF_SIZE] 发送数据缓冲区 au16RxBuf[PSPI_PARAM_BUFF_SIZE] 接收数据缓冲区 -
相关数据类型及接口
PSPI_PARAM_BUFF_SIZE
MI_S32 MI_PSPI_Transfer(MI_PSPI_DEV PspiDev, MI_PSPI_Msg_t *pstMsg)
3.3. MI_PSPI_OutputAttr_t¶
-
说明
定义PSPI输出端口属性。由于只有当PSPI接sensor时才有输出端口,所以这个目前是用来描述所接sensor的属性。
-
定义
typedef struct { MI_SYS_PixelFormat_e ePixelFormat; MI_U16 u16Width; MI_U16 u16Height; }MI_PSPI_OutputAttr_t;
-
成员
成员名称 描述 ePixelFormat 定义sensor输入数据的格式 u16Width 定义sensor输入图像数据的宽 u16Height 定义sensor输入图像数据的高 -
相关数据类型及接口
MI_S32 MI_PSPI_SetOutputAttr(MI_PSPI_OutputAttr_t * pstOutputAttr);
3.4. MI_PSPI_Param_t¶
-
说明
定义PSPI属性
-
定义
typedef struct { MI_U32 u32MaxSpeedHz; MI_U16 u16DelayCycle; MI_U16 u16WaitCycle; MI_U16 u16PspiMode; MI_U8 u8DataLane; MI_U8 u8BitsPerWord; MI_U8 u8RgbSwap; MI_U8 u8TeMode; MI_U8 u8ChipSelect; }MI_PSPI_Param_t;
-
成员
成员名称 | 描述 | 可选值 |
---|---|---|
u32MaxSpeedHz | 最大时钟频率 | |
u16DelayCycle | ||
u16WaitCycle | ||
u16PspiMode | PSPI模式配置 | 0:主机模式,MSB,上升沿接收,下降沿发送,片选信号低电平有效 SPI_CPHA:上升沿发送,下降沿接收 SPI_CPOL:上升沿发送,下降沿接收 SPI_CPHA|SPI_CPOL: 上升沿接收,下降沿发送。 SPI_SLAVE:PSPI作为从机 SPI_LSB: PSPI LSB先行 SPI_SSPOL:片选信号极性控制,设置则高电平有效。 |
u8DataLane | 发送时的数据线条数 | DATA_SINGLE:单线 DATA_DUAL :双线 DATA_QUAD :四线 |
u8BitsPerWord | 每次发送的bit数 | 可以配置为3~32 |
u8RgbSwap | 给panel发送数据时的格式和数据线条数 | 需要同步配置data_lane |
u8TeMode | 是否使用TE模式 | 1:使用TE模式; 0:不使用TE模式 |
u8ChipSelect | PSPI片选信号 | MI_PSPI_SELECT_0 MI_PSPI_SELECT_1 |
-
相关数据类型及接口
MI_S32 MI_PSPI_CreateDevice(MI_PSPI_DEV PspiDev, MI_PSPI_Param_t * pstPspiParam);
MI_S32 MI_PSPI_SetDevAttr(MI_PSPI_DEV PspiDev, MI_PSPI_Param_t * pstPspiParam);
3.5. MI_PSPI_DEV¶
-
说明
定义芯片内部的PSPI编号。
-
定义
typedef MI_S32 MI_PSPI_DEV;
-
注意事项
这个参数的值可设置为0或1,分别代表芯片内部的PSPI0和PSPI1。其中PSPI0用来代表接收(RX),PSPI1代表发送(RX)。
-
相关数据类型及接口
MI_S32 MI_PSPI_CreateDevice(MI_PSPI_DEV PspiDev, MI_PSPI_Param_t * pstPspiParam);
MI_S32 MI_PSPI_DestroyDevice(MI_PSPI_DEV PspiDev);
MI_S32 MI_PSPI_Transfer(MI_PSPI_DEV PspiDev, MI_PSPI_Msg_t * pstMsg );
MI_S32 MI_PSPI_SetDevAttr(MI_PSPI_DEV PspiDev, MI_PSPI_Param_t * pstPspiParam);
MI_S32 MI_PSPI_Disable(MI_PSPI_DEV PspiDev);
MI_S32 MI_PSPI_Enable(MI_PSPI_DEV PspiDev);
4. 程序例程¶
4.1. Sensor例程¶
int main(int argc, char *argv[]) { int fd = 0 MI_PSPI_DEV pspi_dev = 0; MI_PSPI_Param_t pspi_para; MI_PSPI_OutputAttr_t stOutputAttr; MI_SYS_ChnPort_t stChnPort; MI_SYS_BufInfo_t stBufInfo; MI_SYS_BUF_HANDLE hSysBuf; memset(&stChnPort, 0x0, sizeof(MI_SYS_ChnPort_t)); memset(&stBufInfo, 0x0, sizeof(MI_SYS_BufInfo_t)); memset(&hSysBuf, 0x0, sizeof(MI_SYS_BUF_HANDLE)); memset(&pspi_para, 0x0, sizeof(MI_PSPI_SpiParam_t)); stChnPort.eModId = E_MI_MODULE_ID_PSPI; stChnPort.u32DevId = 0; stChnPort.u32ChnId = 0; stChnPort.u32PortId = 0; stOutputAttr.u16Width = 1920; stOutputAttr.u16Width = 1080; stOutputAttr.ePixelFormat = E_MI_SYS_PIXEL_FRAME_YUV_SEMIPLANAR_420; pspi_para.u8BitsPerWord = 8; pspi_para.u8DataLane = DATA_DUAL; pspi_para.u16DelayCycle = 0; pspi_para.u16WaitCycle = 0; pspi_para.u8RgbSwap = 0; pspi_para.u32MaxSpeedHz = 1000000; pspi_para.u16PspiMode = SPI_SLAVE; pspi_para.u8ChipSelect = MI_PSPI_SELECT_0; /*** 通过I2C等手段向sensor发送命令 ***/ MI_SYS_Init(); MI_PSPI_CreateDevice(pspi_dev, &pspi_para); MI_PSPI_SetOutputAttr(&stOutputAttr); //修改sensor输入图像的属性 MI_PSPI_Enable(pspi_dev);//为了减小篇幅去掉了对函数调用的返回值进行判断 MI_SYS_SetChnOutputPortDepth(&stChnPort,3,4); GET_OUT_BUF: if (MI_SUCCESS != MI_SYS_ChnOutputPortGetBuf(&stChnPort, &stBufInfo, &hSysBuf)) { goto GET_OUT_BUF; } fd = open(“picture”, O_RDWR|O_CREAT|O_TRUNC, 0777); write(fd, tBufInfo.stFrameData.pVirAddr[0], stBufInfo.stFrameData.u32BufSize)); sync(); close(fd); PUT_OUT_BUF: if (MI_SUCCESS != MI_SYS_ChnOutputPortPutBuf(hSysBuf)) { goto PUT_OUT_BUF; } MI_SYS_SetChnOutputPortDepth(&stChnPort,0,3); MI_PSPI_Disable(pspi_dev); MI_PSPI_DestroyDevice(pspi_dev); MI_SYS_Exit(); Return 0; }
4.2. Panel例程¶
int main(int argc, char *argv[]) { MI_S32 s32Ret = 0; MI_U16 * buff = NULL; MI_U32 size = 0; MI_PSPI_Msg_t pspi_msg; MI_PSPI_Param_t pspi_para; MI_PSPI_DEV pspi_dev = 1; MI_SYS_ChnPort_t stChnPort; MI_SYS_BUF_HANDLE stHandle; MI_SYS_BufInfo_t stBufInfo; MI_SYS_BufConf_t stBufConf; pspi_para.u8BitsPerWord = 9; pspi_para.u8DataLane = DATA_SINGLE; pspi_para.u16DelayCycle = 2; pspi_para.u16WaitCycle = 2; pspi_para.u8RgbSwap = 0; pspi_para.u32MaxSpeedHz = 1000000; pspi_para.u16PspiMode = 0; pspi_para.u8ChipSelect = MI_PSPI_SELECT_0; pspi_para.u8TeMode = 0; MI_PSPI_CreateDevice(pspi_dev, &pspi_para);//为了减小篇幅去掉了对函数调用的返回值进行判断 memset(&pspi_msg, 0 ,sizeof(MI_PSPI_Msg_t)); pspi_msg.u8TxBitCount = 9;//可根据panel的不同选择不同的数值 pspi_msg.u8RxBitCount = 8; pspi_msg.u8TxSize = 1; //0xDA //根据panel的型号发送对应的控制命令,视panel型号而定 pspi_msg.au16TxBuf[0] = 0xDA; MI_PSPI_Transfer(pspi_dev, & pspi_msg); /**** 向panel发送命令 *****/ memset(&stChnPort, 0, sizeof(MI_SYS_ChnPort_t)); memset(&stBufConf, 0, sizeof(MI_SYS_BufConf_t)); memset(&stBufInfo, 0, sizeof(MI_SYS_BufInfo_t)); memset(&stHandle, 0, sizeof(MI_SYS_BUF_HANDLE)); stChnPort.eModId = E_MI_MODULE_ID_PSPI; stChnPort.u32DevId = 1; stChnPort.u32ChnId = 0; stChnPort.u32PortId = 0; stBufConf.eBufType = E_MI_SYS_BUFDATA_FRAME; stBufConf.stFrameCfg.u16Height = 240; stBufConf.stFrameCfg.u16Width = 320;//这些参数视情况而定 stBufConf.stFrameCfg.eFrameScanMode = E_MI_SYS_FRAME_SCAN_MODE_PROGRESSIVE; stBufConf.stFrameCfg.eFormat = E_MI_SYS_PIXEL_FRAME_RGB565; MI_PSPI_Enable(pspi_dev); while(1) { getBuff1: if(MI_SYS_ChnInputPortGetBuf(&stChnPort,&stBufConf,&stBufInfo,&stHandle,4000)!= MI_SUCCESS) { printf("get input port buf red failed\n"); goto getBuff1; } else { printf("MI_SYS_ChnInputPortGetBuf success 1\n"); buff = (MI_U16 *)stBufInfo.stFrameData.pVirAddr[0]; size = stBufInfo.stFrameData.u32BufSize/2; for(i = 0; i < size ; i++) { buff[i] = 0xf800; } putbuff1: if(MI_SYS_ChnInputPortPutBuf(stHandle, &stBufInfo, FALSE) != MI_SUCCESS) { printf("writter frame err 1\n"); goto putbuff1; } else printf("written a frame red to screen success\n"); } }
4.3. Sensor图像由Panel显示例程¶
(由于当前使用的sensor图像的像素和格式与panel不同,所以要在两者中间串接一个vpe模块,vpe模块相关配置请参考vpe模块文档。)
#define FRAME_RATE 30 int main(int argc, char *argv[]) { MI_S32 s32Ret = 0; MI_SYS_ChnPort_t stSensorChnPort; MI_SYS_ChnPort_t stPanelChnPort; MI_SYS_ChnPort_t stDivpChnPort; MI_SYS_BindType_e eBindType; MI_U32 u32BindParam; MI_SYS_Init(); /*sensor 初始化并使能,参考4.1例程*/ /*panel 初始化并使能,参考4.2例程*/ //vpe初始化 MI_DIVP_ChnAttr_t stAttr; MI_DIVP_OutputPortAttr_t stOutputPortAttr; memset(&stAttr, 0, sizeof(stAttr)); stAttr.bHorMirror = false; stAttr.bVerMirror = false; stAttr.eDiType = E_MI_DIVP_DI_TYPE_OFF; stAttr.eRotateType = E_MI_SYS_ROTATE_NONE; stAttr.eTnrLevel = E_MI_DIVP_TNR_LEVEL_OFF; stAttr.stCropRect.u16X = 0; stAttr.stCropRect.u16Y = 0; stAttr.stCropRect.u16Width = 640; stAttr.stCropRect.u16Height = 480; stAttr.u32MaxWidth = 640; stAttr.u32MaxHeight = 480; s32Ret = MI_DIVP_CreateChn(0, &stAttr); stOutputPortAttr.eCompMode = E_MI_SYS_COMPRESS_MODE_NONE; stOutputPortAttr.ePixelFormat = E_MI_SYS_PIXEL_FRAME_RGB565; stOutputPortAttr.u32Width = 240; stOutputPortAttr.u32Height = 320; s32Ret = MI_DIVP_SetOutputPortAttr(0, &stOutputPortAttr); s32Ret = MI_DIVP_StartChn(0); stSensorChnPort.eModId = E_MI_MODULE_ID_PSPI; stSensorChnPort.u32DevId = 0; stSensorChnPort.u32ChnId = 0; stSensorChnPort.u32PortId = 0; stDivpInputChnPort.eModId = E_MI_MODULE_ID_DIVP; stDivpInputChnPort.u32DevId = 0; stDivpInputChnPort.u32ChnId = 0; stDivpInputChnPort.u32PortId = 0; stPanelChnPort.eModId = E_MI_MODULE_ID_PSPI; stPanelChnPort.u32DevId = 1; stPanelChnPort.u32ChnId = 0; stPanelChnPort.u32PortId = 0; eBindType = E_MI_SYS_BIND_TYPE_FRAME_BASE; u32BindParam = 0; MI_SYS_SetChnOutputPortDepth(&stSensorChnPort,3,6); MI_SYS_BindChnPort2(&stSensorChnPort, &stDivpChnPort, FRAME_RATE, FRAME_RATE, eBindType, u32BindParam); MI_SYS_BindChnPort2(&stDivpChnPort, &stPanelChnPort, FRAME_RATE, FRAME_RATE, eBindType, u32BindParam); While(1) { sleep(10); } MI_PSPI_Disable(0); MI_PSPI_Disable(1); MI_PSPI_DestroyDevice(0); MI_PSPI_DestroyDevice(1); return 0; }
5. 错误码¶
PSPI API 错误码如下表所示:
错误代码 | 宏定义 | 描述 |
---|---|---|
0 | MI_PSPI_SUCCESS | 函数运行成功 |
-1 | MI_PSPI_FAIL | 函数运行失败 |
-2 | MI_ERR_PSPI_NULL_PTR | 传入空指针 |
-3 | MI_ERR_PSPI_NO_MEM | 没有内存 |
-4 | MI_ERR_PSPI_ILLEGAL_PARAM | 传入非法的、不恰当的参数 |
-5 | MI_ERR_PSPI_DEV_NOT_INIT | PSPI设备没有初始化 |
-6 | MI_ERR_PSPI_ENABLE_CHN_FAILED | 使能通道失败 |
-7 | MI_ERR_PSPI_ENABLE_PORT_FAILED | 使能端口失败 |
-8 | MI_ERR_PSPI_DISABLE_CHN_FAILED | 禁用通道失败 |
-9 | MI_ERR_PSPI_DISABLE_PORT_FAILED | 禁用端口失败 |
-10 | MI_ERR_PSPI_DEV_HAVE_INITED | PSPI设备已经初始化 |
-11 | MI_ERR_PSPI_FAILED_IN_MHAL | 在MHAL中运行出错 |