MI PSPI API


REVISION HISTORY

Revision No.
Description
Date
1.00
  • Initial release
  • 09/25/2020

    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);
      
    • 参数

      参数名称 描述 输入/输出
      PspiDev PSPI具体设备 输入
      pstPspiParam 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);
      
    • 参数

      参数名称 描述 输入/输出
      PspiDev 需要销毁的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)
      
    • 参数

      参数名称 描述 输入/输出
      PspiDev PSPI具体设备 输入
      pstMsg 发送给从机设备的具体参数 输入
    • 返回值

      • 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);
      
    • 参数

      参数名称 描述 输入/输出
      PspiDev PSPI具体设备 输入
      pstPspiParam 即将要进行配置的具体属性 输入
    • 返回值

      • 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);
      
    • 参数

      参数名称 描述 输入/输出
      pstOutputAttr 即将要进行配置的属性 输入
    • 返回值

      • 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);
      
    • 参数

      参数名称 描述 输入/输出
      PspiDev 要启用的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);
      
    • 参数

      参数名称 描述 输入/输出
      PspiDev 要禁用的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] 接收数据缓冲区
    • 相关数据类型及接口

      MI_PSPI_Transfer

    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_PSPI_SetOutputAttr

    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发送数据时的格式和数据线条数 RGB_SINGLE:RGB格式,单线发送
      RGB_DUAL:RGB格式,双线发送
      BGR_SINGLE:BGR格式,单线发送
      BGR_DUAL:BGR格式,双向发送
      注意:需要同步配置data_lane
      u8TeMode 是否使用TE模式 1:使用TE模式;0:不使用TE模式
      u8ChipSelect PSPI片选信号 MI_PSPI_SELECT_0; MI_PSPI_SELECT_1
    • 相关数据类型及接口

      MI_PSPI_CreateDevice

      MI_PSPI_SetDevAttr

    3.5. MI_PSPI_DEV

    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中运行出错