The MCUXpresso SDK provides a driver for the CMOS Sensor Interface (CSI)
The CSI enables the chip to connect directly to external CMOS image sensors. The CSI driver provides functional APIs and transactional APIs for the CSI module. The functional APIs implement the basic functions, so the user can construct them for a special use case. The transactional APIs provide a queue mechanism in order for the user to submit an empty frame buffer and get a fully-filled frame buffer easily.
Frame Buffer Queue
The CSI transactional functions maintain a frame buffer queue. The queue size is defined by the macro CSI_DRIVER_QUEUE_SIZE. The queue size is 4 by default, but the user can override it by redefining the macro value in the project setting.
To use transactional APIs, first call CSI_TransferCreateHandle to create a handle to save the CSI driver state. This function initializes the frame buffer queue to empty status.
After the handle is created, the function CSI_TransferSubmitEmptyBuffer can be used to submit the empty frame buffer to the queue. If the queue does not have room to save the new empty frame buffers, this function returns with an error. It is not necessary to check the queue rooms before submitting an empty frame buffer. After this step, the application can call CSI_TransferStart to start the transfer. There must be at least two empty buffers in the queue, otherwise this function returns an error. The incoming frames are saved to the empty buffers one by one, and a callback is provided when every frame completed. To get the fully-filled frame buffer, call the function CSI_TransferGetFullBuffer. This function returns an error if the frame buffer queue does not have full buffers. Therefore, it is not necessary to check the full buffer number in the queue before this function.
To stop the transfer, call the function CSI_TransferStop at anytime. If the queue has some full frame buffers, the application can still read them out after this stop function.
Once the transfer is started by calling CSI_TransferStart, the CSI device starts to receive frames and save into buffer. The CSI devices does not stop until CSI_TransferStop is called. If application does not submit empty buffer to CSI driver, the CSI driver always writes to the last submited empty buffer, this buffer will never be sent into full buffer queue until new empty buffer submited. In other words, one frame buffer is reserved by CSI driver, if application submits N empty buffers, it could get (N-1) full buffers.
Fragment Mode
The frame buffer queue mechanism needs large memory, it is not suitable for some special case, for example, no SDRAM used. Fragment mode is designed for this purpose, it needs two types of buffers:
- DMA buffer. It could be as small as (camera frame width x 2 x 2) bytes, CSI DMA writes the input data to this buffer.
- Frame buffer. The input data is copied to this buffer at last. What is more, user could define a window (in other words, region of interest), only image in this window will be copied to the frame buffer. If input data is YUV422 format, user can only save Y component optionally.
Limitations:
- Fragment mode could not be used together with frame buffer queue mode.
- In fragment mode, user should pay attention to the system payload. When the payload is high, the image capture might be broken.
Typical use case
Refer to the driver examples codes located at <SDK_ROOT>/boards/<BOARD>/driver_examples/csi
|
enum | {
kStatus_CSI_NoEmptyBuffer = MAKE_STATUS(kStatusGroup_CSI, 0),
kStatus_CSI_NoFullBuffer = MAKE_STATUS(kStatusGroup_CSI, 1),
kStatus_CSI_QueueFull = MAKE_STATUS(kStatusGroup_CSI, 2),
kStatus_CSI_FrameDone = MAKE_STATUS(kStatusGroup_CSI, 3)
} |
| Error codes for the CSI driver. More...
|
|
enum | csi_work_mode_t {
kCSI_GatedClockMode = CSI_CSICR1_GCLK_MODE(1U),
kCSI_NonGatedClockMode = 0U,
kCSI_CCIR656ProgressiveMode = CSI_CSICR1_CCIR_EN(1U)
} |
| CSI work mode. More...
|
|
enum | csi_data_bus_t {
kCSI_DataBus8Bit,
kCSI_DataBus16Bit,
kCSI_DataBus24Bit
} |
| CSI data bus witdh. More...
|
|
enum | _csi_polarity_flags {
kCSI_HsyncActiveLow = 0U,
kCSI_HsyncActiveHigh = CSI_CSICR1_HSYNC_POL_MASK,
kCSI_DataLatchOnRisingEdge = CSI_CSICR1_REDGE_MASK,
kCSI_DataLatchOnFallingEdge = 0U,
kCSI_VsyncActiveHigh = 0U,
kCSI_VsyncActiveLow = CSI_CSICR1_SOF_POL_MASK
} |
| CSI signal polarity. More...
|
|
enum | csi_fifo_t {
kCSI_RxFifo = (1U << 0U),
kCSI_StatFifo = (1U << 1U),
kCSI_AllFifo = 0x01 | 0x02
} |
| The CSI FIFO, used for FIFO operation. More...
|
|
enum | _csi_interrupt_enable {
kCSI_EndOfFrameInterruptEnable = CSI_CSICR1_EOF_INT_EN_MASK,
kCSI_ChangeOfFieldInterruptEnable = CSI_CSICR1_COF_INT_EN_MASK,
kCSI_StatFifoOverrunInterruptEnable = CSI_CSICR1_SF_OR_INTEN_MASK,
kCSI_RxFifoOverrunInterruptEnable = CSI_CSICR1_RF_OR_INTEN_MASK,
kCSI_StatFifoDmaDoneInterruptEnable,
kCSI_StatFifoFullInterruptEnable = CSI_CSICR1_STATFF_INTEN_MASK,
kCSI_RxBuffer1DmaDoneInterruptEnable,
kCSI_RxBuffer0DmaDoneInterruptEnable,
kCSI_RxFifoFullInterruptEnable = CSI_CSICR1_RXFF_INTEN_MASK,
kCSI_StartOfFrameInterruptEnable = CSI_CSICR1_SOF_INTEN_MASK,
kCSI_EccErrorInterruptEnable = CSI_CSICR3_ECC_INT_EN_MASK,
kCSI_AhbResErrorInterruptEnable = CSI_CSICR3_HRESP_ERR_EN_MASK,
kCSI_BaseAddrChangeErrorInterruptEnable,
kCSI_Field0DoneInterruptEnable = CSI_CSICR18_FIELD0_DONE_IE_MASK << 6U,
kCSI_Field1DoneInterruptEnable = CSI_CSICR18_DMA_FIELD1_DONE_IE_MASK << 6U
} |
| CSI feature interrupt source. More...
|
|
enum | _csi_flags {
kCSI_RxFifoDataReadyFlag = CSI_CSISR_DRDY_MASK,
kCSI_EccErrorFlag = CSI_CSISR_ECC_INT_MASK,
kCSI_AhbResErrorFlag = CSI_CSISR_HRESP_ERR_INT_MASK,
kCSI_ChangeOfFieldFlag = CSI_CSISR_COF_INT_MASK,
kCSI_Field0PresentFlag = CSI_CSISR_F1_INT_MASK,
kCSI_Field1PresentFlag = CSI_CSISR_F2_INT_MASK,
kCSI_StartOfFrameFlag = CSI_CSISR_SOF_INT_MASK,
kCSI_EndOfFrameFlag = CSI_CSISR_EOF_INT_MASK,
kCSI_RxFifoFullFlag = CSI_CSISR_RxFF_INT_MASK,
kCSI_RxBuffer1DmaDoneFlag = CSI_CSISR_DMA_TSF_DONE_FB2_MASK,
kCSI_RxBuffer0DmaDoneFlag = CSI_CSISR_DMA_TSF_DONE_FB1_MASK,
kCSI_StatFifoFullFlag = CSI_CSISR_STATFF_INT_MASK,
kCSI_StatFifoDmaDoneFlag = CSI_CSISR_DMA_TSF_DONE_SFF_MASK,
kCSI_StatFifoOverrunFlag = CSI_CSISR_SF_OR_INT_MASK,
kCSI_RxFifoOverrunFlag = CSI_CSISR_RF_OR_INT_MASK,
kCSI_Field0DoneFlag = CSI_CSISR_DMA_FIELD0_DONE_MASK,
kCSI_Field1DoneFlag = CSI_CSISR_DMA_FIELD1_DONE_MASK,
kCSI_BaseAddrChangeErrorFlag = CSI_CSISR_BASEADDR_CHHANGE_ERROR_MASK
} |
| CSI status flags. More...
|
|
|
status_t | CSI_TransferCreateHandle (CSI_Type *base, csi_handle_t *handle, csi_transfer_callback_t callback, void *userData) |
| Initializes the CSI handle. More...
|
|
status_t | CSI_TransferStart (CSI_Type *base, csi_handle_t *handle) |
| Start the transfer using transactional functions. More...
|
|
status_t | CSI_TransferStop (CSI_Type *base, csi_handle_t *handle) |
| Stop the transfer using transactional functions. More...
|
|
status_t | CSI_TransferSubmitEmptyBuffer (CSI_Type *base, csi_handle_t *handle, uint32_t frameBuffer) |
| Submit empty frame buffer to queue. More...
|
|
status_t | CSI_TransferGetFullBuffer (CSI_Type *base, csi_handle_t *handle, uint32_t *frameBuffer) |
| Get one full frame buffer from queue. More...
|
|
void | CSI_TransferHandleIRQ (CSI_Type *base, csi_handle_t *handle) |
| CSI IRQ handle function. More...
|
|
uint16_t csi_config_t::width |
uint16_t csi_config_t::height |
uint32_t csi_config_t::polarityFlags |
uint8_t csi_config_t::bytesPerPixel |
- 2: Used for RGB565, YUV422, and so on.
- 4: Used for XRGB8888, XYUV444, and so on.
uint16_t csi_config_t::linePitch_Bytes |
bool csi_config_t::useExtVsync |
Please see the user guide for the details of the CSI driver queue mechanism.
uint32_t csi_handle_t::frameBufferQueue[CSI_DRIVER_ACTUAL_QUEUE_SIZE] |
volatile uint8_t csi_handle_t::queueWriteIdx |
volatile uint8_t csi_handle_t::queueReadIdx |
void* volatile csi_handle_t::emptyBuffer |
volatile uint8_t csi_handle_t::emptyBufferCnt |
volatile uint8_t csi_handle_t::activeBufferNum |
volatile bool csi_handle_t::transferStarted |
void* csi_handle_t::userData |
#define CSI_DRIVER_QUEUE_SIZE 4U |
#define CSI_DRIVER_FRAG_MODE 0U |
typedef void(* csi_transfer_callback_t)(CSI_Type *base, csi_handle_t *handle, status_t status, void *userData) |
When a new frame is received and saved to the frame buffer queue, the callback is called and the pass the status kStatus_CSI_FrameDone to upper layer.
Enumerator |
---|
kStatus_CSI_NoEmptyBuffer |
No empty frame buffer in queue to load to CSI.
|
kStatus_CSI_NoFullBuffer |
No full frame buffer in queue to read out.
|
kStatus_CSI_QueueFull |
Queue is full, no room to save new empty buffer.
|
kStatus_CSI_FrameDone |
New frame received and saved to queue.
|
The CCIR656 interlace mode is not supported currently.
Enumerator |
---|
kCSI_GatedClockMode |
HSYNC, VSYNC, and PIXCLK signals are used.
|
kCSI_NonGatedClockMode |
VSYNC, and PIXCLK signals are used.
|
kCSI_CCIR656ProgressiveMode |
CCIR656 progressive mode.
|
Enumerator |
---|
kCSI_DataBus8Bit |
8-bit data bus.
|
kCSI_DataBus16Bit |
16-bit data bus.
|
kCSI_DataBus24Bit |
24-bit data bus.
|
Enumerator |
---|
kCSI_HsyncActiveLow |
HSYNC is active low.
|
kCSI_HsyncActiveHigh |
HSYNC is active high.
|
kCSI_DataLatchOnRisingEdge |
Pixel data latched at rising edge of pixel clock.
|
kCSI_DataLatchOnFallingEdge |
Pixel data latched at falling edge of pixel clock.
|
kCSI_VsyncActiveHigh |
VSYNC is active high.
|
kCSI_VsyncActiveLow |
VSYNC is active low.
|
Enumerator |
---|
kCSI_RxFifo |
RXFIFO.
|
kCSI_StatFifo |
STAT FIFO.
|
kCSI_AllFifo |
Both RXFIFO and STAT FIFO.
|
Enumerator |
---|
kCSI_EndOfFrameInterruptEnable |
End of frame interrupt enable.
|
kCSI_ChangeOfFieldInterruptEnable |
Change of field interrupt enable.
|
kCSI_StatFifoOverrunInterruptEnable |
STAT FIFO overrun interrupt enable.
|
kCSI_RxFifoOverrunInterruptEnable |
RXFIFO overrun interrupt enable.
|
kCSI_StatFifoDmaDoneInterruptEnable |
STAT FIFO DMA done interrupt enable.
|
kCSI_StatFifoFullInterruptEnable |
STAT FIFO full interrupt enable.
|
kCSI_RxBuffer1DmaDoneInterruptEnable |
RX frame buffer 1 DMA transfer done.
|
kCSI_RxBuffer0DmaDoneInterruptEnable |
RX frame buffer 0 DMA transfer done.
|
kCSI_RxFifoFullInterruptEnable |
RXFIFO full interrupt enable.
|
kCSI_StartOfFrameInterruptEnable |
Start of frame (SOF) interrupt enable.
|
kCSI_EccErrorInterruptEnable |
ECC error detection interrupt enable.
|
kCSI_AhbResErrorInterruptEnable |
AHB response Error interrupt enable.
|
kCSI_BaseAddrChangeErrorInterruptEnable |
The DMA output buffer base address changes before DMA completed.
|
kCSI_Field0DoneInterruptEnable |
Field 0 done interrupt enable.
|
kCSI_Field1DoneInterruptEnable |
Field 1 done interrupt enable.
|
The following status register flags can be cleared:
- kCSI_EccErrorFlag
- kCSI_AhbResErrorFlag
- kCSI_ChangeOfFieldFlag
- kCSI_StartOfFrameFlag
- kCSI_EndOfFrameFlag
- kCSI_RxBuffer1DmaDoneFlag
- kCSI_RxBuffer0DmaDoneFlag
- kCSI_StatFifoDmaDoneFlag
- kCSI_StatFifoOverrunFlag
- kCSI_RxFifoOverrunFlag
- kCSI_Field0DoneFlag
- kCSI_Field1DoneFlag
- kCSI_BaseAddrChangeErrorFlag
Enumerator |
---|
kCSI_RxFifoDataReadyFlag |
RXFIFO data ready.
|
kCSI_EccErrorFlag |
ECC error detected.
|
kCSI_AhbResErrorFlag |
Hresponse (AHB bus response) Error.
|
kCSI_ChangeOfFieldFlag |
Change of field.
|
kCSI_Field0PresentFlag |
Field 0 present in CCIR mode.
|
kCSI_Field1PresentFlag |
Field 1 present in CCIR mode.
|
kCSI_StartOfFrameFlag |
Start of frame (SOF) detected.
|
kCSI_EndOfFrameFlag |
End of frame (EOF) detected.
|
kCSI_RxFifoFullFlag |
RXFIFO full (Number of data reaches trigger level).
|
kCSI_RxBuffer1DmaDoneFlag |
RX frame buffer 1 DMA transfer done.
|
kCSI_RxBuffer0DmaDoneFlag |
RX frame buffer 0 DMA transfer done.
|
kCSI_StatFifoFullFlag |
STAT FIFO full (Reach trigger level).
|
kCSI_StatFifoDmaDoneFlag |
STAT FIFO DMA transfer done.
|
kCSI_StatFifoOverrunFlag |
STAT FIFO overrun.
|
kCSI_RxFifoOverrunFlag |
RXFIFO overrun.
|
kCSI_Field0DoneFlag |
Field 0 transfer done.
|
kCSI_Field1DoneFlag |
Field 1 transfer done.
|
kCSI_BaseAddrChangeErrorFlag |
The DMA output buffer base address changes before DMA completed.
|
This function enables the CSI peripheral clock, and resets the CSI registers.
- Parameters
-
base | CSI peripheral base address. |
config | Pointer to the configuration structure. |
- Return values
-
kStatus_Success | Initialize successfully. |
kStatus_InvalidArgument | Initialize failed because of invalid argument. |
void CSI_Deinit |
( |
CSI_Type * |
base | ) |
|
This function disables the CSI peripheral clock.
- Parameters
-
base | CSI peripheral base address. |
void CSI_Reset |
( |
CSI_Type * |
base | ) |
|
This function resets the CSI peripheral registers to default status.
- Parameters
-
base | CSI peripheral base address. |
The default configuration value is:
config->width = 320U;
config->height = 240U;
config->bytesPerPixel = 2U;
config->linePitch_Bytes = 320U * 2U;
config->useExtVsync = true;
- Parameters
-
config | Pointer to the CSI configuration. |
void CSI_ClearFifo |
( |
CSI_Type * |
base, |
|
|
csi_fifo_t |
fifo |
|
) |
| |
This function clears the CSI FIFO.
- Parameters
-
base | CSI peripheral base address. |
fifo | The FIFO to clear. |
void CSI_ReflashFifoDma |
( |
CSI_Type * |
base, |
|
|
csi_fifo_t |
fifo |
|
) |
| |
This function reflashes the CSI FIFO DMA.
For RXFIFO, there are two frame buffers. When the CSI module started, it saves the frames to frame buffer 0 then frame buffer 1, the two buffers will be written by turns. After reflash DMA using this function, the CSI is reset to save frame to buffer 0.
- Parameters
-
base | CSI peripheral base address. |
fifo | The FIFO DMA to reflash. |
void CSI_EnableFifoDmaRequest |
( |
CSI_Type * |
base, |
|
|
csi_fifo_t |
fifo, |
|
|
bool |
enable |
|
) |
| |
- Parameters
-
base | CSI peripheral base address. |
fifo | The FIFO DMA reques to enable or disable. |
enable | True to enable, false to disable. |
static void CSI_Start |
( |
CSI_Type * |
base | ) |
|
|
inlinestatic |
- Parameters
-
base | CSI peripheral base address. |
static void CSI_Stop |
( |
CSI_Type * |
base | ) |
|
|
inlinestatic |
- Parameters
-
base | CSI peripheral base address. |
void CSI_SetRxBufferAddr |
( |
CSI_Type * |
base, |
|
|
uint8_t |
index, |
|
|
uint32_t |
addr |
|
) |
| |
- Parameters
-
base | CSI peripheral base address. |
index | Buffer index. |
addr | Frame buffer address to set. |
void CSI_EnableInterrupts |
( |
CSI_Type * |
base, |
|
|
uint32_t |
mask |
|
) |
| |
- Parameters
-
base | CSI peripheral base address. |
mask | The interrupts to enable, pass in as OR'ed value of _csi_interrupt_enable. |
void CSI_DisableInterrupts |
( |
CSI_Type * |
base, |
|
|
uint32_t |
mask |
|
) |
| |
- Parameters
-
base | CSI peripheral base address. |
mask | The interrupts to disable, pass in as OR'ed value of _csi_interrupt_enable. |
static uint32_t CSI_GetStatusFlags |
( |
CSI_Type * |
base | ) |
|
|
inlinestatic |
- Parameters
-
base | CSI peripheral base address. |
- Returns
- status flag, it is OR'ed value of _csi_flags.
static void CSI_ClearStatusFlags |
( |
CSI_Type * |
base, |
|
|
uint32_t |
statusMask |
|
) |
| |
|
inlinestatic |
The flags to clear are passed in as OR'ed value of _csi_flags. The following flags are cleared automatically by hardware:
- Parameters
-
base | CSI peripheral base address. |
statusMask | The status flags mask, OR'ed value of _csi_flags. |
This function initializes CSI handle, it should be called before any other CSI transactional functions.
- Parameters
-
base | CSI peripheral base address. |
handle | Pointer to the handle structure. |
callback | Callback function for CSI transfer. |
userData | Callback function parameter. |
- Return values
-
kStatus_Success | Handle created successfully. |
status_t CSI_TransferStart |
( |
CSI_Type * |
base, |
|
|
csi_handle_t * |
handle |
|
) |
| |
When the empty frame buffers have been submit to CSI driver using function CSI_TransferSubmitEmptyBuffer, user could call this function to start the transfer. The incoming frame will be saved to the empty frame buffer, and user could be optionally notified through callback function.
- Parameters
-
base | CSI peripheral base address. |
handle | Pointer to the handle structure. |
- Return values
-
kStatus_Success | Started successfully. |
kStatus_CSI_NoEmptyBuffer | Could not start because no empty frame buffer in queue. |
status_t CSI_TransferStop |
( |
CSI_Type * |
base, |
|
|
csi_handle_t * |
handle |
|
) |
| |
The driver does not clean the full frame buffers in queue. In other words, after calling this function, user still could get the full frame buffers in queue using function CSI_TransferGetFullBuffer.
- Parameters
-
base | CSI peripheral base address. |
handle | Pointer to the handle structure. |
- Return values
-
kStatus_Success | Stoped successfully. |
status_t CSI_TransferSubmitEmptyBuffer |
( |
CSI_Type * |
base, |
|
|
csi_handle_t * |
handle, |
|
|
uint32_t |
frameBuffer |
|
) |
| |
This function could be called before CSI_TransferStart or after CSI_TransferStart. If there is no room in queue to store the empty frame buffer, this function returns error.
- Parameters
-
base | CSI peripheral base address. |
handle | Pointer to the handle structure. |
frameBuffer | Empty frame buffer to submit. |
- Return values
-
kStatus_Success | Started successfully. |
kStatus_CSI_QueueFull | Could not submit because there is no room in queue. |
status_t CSI_TransferGetFullBuffer |
( |
CSI_Type * |
base, |
|
|
csi_handle_t * |
handle, |
|
|
uint32_t * |
frameBuffer |
|
) |
| |
After the transfer started using function CSI_TransferStart, the incoming frames will be saved to the empty frame buffers in queue. This function gets the full-filled frame buffer from the queue. If there is no full frame buffer in queue, this function returns error.
- Parameters
-
base | CSI peripheral base address. |
handle | Pointer to the handle structure. |
frameBuffer | Full frame buffer. |
- Return values
-
kStatus_Success | Started successfully. |
kStatus_CSI_NoFullBuffer | There is no full frame buffer in queue. |
void CSI_TransferHandleIRQ |
( |
CSI_Type * |
base, |
|
|
csi_handle_t * |
handle |
|
) |
| |
This function handles the CSI IRQ request to work with CSI driver transactional APIs.
- Parameters
-
base | CSI peripheral base address. |
handle | CSI handle pointer. |