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.a / libmi_pspi.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.a / libmi_pspi.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.a / libmi_pspi.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.a / libmi_pspi.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.a / libmi_pspi.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.a / libmi_pspi.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.a / libmi_pspi.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 | 最大时钟频率 | 1000000~54000000 |
| u16DelayCycle | SPI_SSCTL没有设置时,两次传送数据之间的延时 | 0x0000~0xFFFF,单位为时钟周期 |
| u16WaitCycle | SPI_SSCTL有设置时,两次传送数据之间的延时 | 0x0000~0xFFFF,单位为时钟周期 |
| u16PspiMode | PSPI模式配置 | 0:主机模式,MSB,上升沿接收,下降沿发送,片选信号低电平有效,两次数据传送期间片选信号有效。 SPI_CPHA:上升沿发送,下降沿接收 SPI_CPOL:上升沿发送,下降沿接收 SPI_CPHA|SPI_CPOL:上升沿接收,下降沿发送。 SPI_SLAVE:PSPI作为从机 SPI_LSB:PSPI LSB先行 SPI_SSPOL:片选信号极性控制,设置则高电平有效。 SPI_SSCTL:控制PSPI传送两次数据之间片选信号是否继续保持有效。设置则两次数据传送期间片选信号无效。 |
| 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不同,所以要在两者中间串接一个divp模块,divp模块相关配置请参考divp模块文档。)
#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中运行出错 |