Kinetis SDK v.1.3 API Reference Manual  Rev. 0
Freescale Semiconductor, Inc.
 All Data Structures Functions Variables Typedefs Enumerations Enumerator Groups Pages

This section describes the programming interface of the FlexIO Camera HAL driver.

FlexIO Camera HAL description

The FlexIO Camera HAL supports the general 8-bit Camera Parallel Interface (CPI) for camera devices, such as the OV7670.

The FlexIO Camera Interface is simulated from the FlexIO basic HAL driver using one timer, multiple shifters (typically 8 count, such as the data buffer) and ten pins (eight pins for data D[0..7], one pin for PCLK, and one pin for HREF). The HREF pin signal triggers the timer. The PCLK pin signal drives the timer's counter and the shifter. Finally, the data pin signals are shifted into the shifter's chain buffer, where each shifter is connected to one another. Multiple transfers from the buffer to the indicated memory can be supported using the external DMA controller.

Note that the FlexIO Camera driver covers the data bus interface. Additionally, to connect the driver to the camera, the SCCB bus and a VSYNC signal need to be implemented in the application. The SCCB bus is compatible with I2C hardware. The VSYNC signal can be implemented using the GPIO's IRQ, which is more flexible for the application.

Usage of FlexIO Camera HAL

This is an example that shows how to use the FlexIO Camera Interface to capture the image data from an OV7670 camera and display it to an LCD module with FlexBus interface. The triggers for Camera DMA and LCD DMA are generated by the buffer full event.

#include "fsl_flexio_hal.h"
#include "fsl_flexio_camera.h"
#include "fsl_edma_hal.h"
// FlexIO configuration structures.
flexio_camera_dev_t gFlexioCameraDevStruct =
{
.flexioBase = FLEXIO0,
.datPinStartIdx = 24U, // fxio_pin 24 -31 is used.
.pclkPinIdx = 1U, // fxio_pin 1 is used as PCLK pin.
.hrefPinIdx = 18U, // flexio_pin 18 is used as HREF pin.
.shifterStartIdx = 0U, // Shifter 0 - 7 is used.
.shifterCount = 8U,
.timerIdx = 0U
};
static volatile uint16_t u16CameraFrameBuffer[OV7670_FRAME_PIXELS];
//------------------------------------------------------------------------------
//DMA0 channel 16 configuration structure.
// details This DMA channel ensures 16-bit (2 bytes) data transfers from the
// camera frame buffer to flexbus (LCD SSD1289), which means
// 4800 (major loop) x 16 x 16-bit data transfers (32 bytes minor loops).
// These transfers ensure frame display.
// Data is transferred based on the shifter 0 status flag
// (all shifters are filled by appropriate data).
//------------------------------------------------------------------------------
#define eDMA16_CONFIG \
{ \
.srcAddr = (uint32_t)u16CameraFrameBuffer, \
.destAddr = (uint32_t)FLEX_BASE_ADDRESS, \
.srcTransferSize = kEDMATransferSize_2Bytes, \
.destTransferSize = kEDMATransferSize_2Bytes, \
.srcOffset = 2, \
.destOffset = 0, \
.srcLastAddrAdjust = -((sizeof(u16CameraFrameBuffer))), \
.destLastAddrAdjust = 0, \
.srcModulo = kEDMAModuloDisable, \
.destModulo = kEDMAModuloDisable, \
.minorLoopCount = 32, \
.majorLoopCount = ((sizeof(u16CameraFrameBuffer)>>5)), \
}
//------------------------------------------------------------------------------
// DMA0 channel 17 configuration structure.
// details This DMA channel ensures 32 bytes data transfers (burns) from
// shifter 0-7 buffer to the one frame data circular buffer (150 kB), which
// means 4800 (major loop) x 32-bytes (minor loop)
// transfers. Data is transferred based on the shifter 0 status flag
// (all shifters are filled by appropriate data).
//------------------------------------------------------------------------------
#define eDMA17_CONFIG \
{ \
.srcAddr = 0U, /* Dummy. \
.destAddr = (uint32_t)u16CameraFrameBuffer, \
.srcTransferSize = kEDMATransferSize_32Bytes, \
.destTransferSize = kEDMATransferSize_32Bytes, \
.srcOffset = 0, \
.destOffset = 32, \
.srcLastAddrAdjust = 0, \
.destLastAddrAdjust = -((sizeof(u16CameraFrameBuffer))), \
.srcModulo = kEDMAModuloDisable, \
.destModulo = kEDMAModuloDisable, \
.minorLoopCount = 32, \
.majorLoopCount = ((sizeof(u16CameraFrameBuffer)>>5)), \
}
// eDMA configuration structures.
static edma_transfer_config_t edma16_transfer_config = eDMA16_CONFIG;
static edma_transfer_config_t edma17_transfer_config = eDMA17_CONFIG;
static void FlexIO_Init(void);
static void eDma_Init(edma_channel_indicator_t channel, uint8_t source, edma_transfer_config_t *edma_config);
static void eDma_Reset(edma_channel_indicator_t channel, edma_transfer_config_t *edma_config);
static void porta_callback(uint32_t pin);
int main(void)
{
//...
// Initialize the LCD (SSD1289) and the Camera (OV7670)
// Initialize the FlexIO (OV7670 CPI).
FlexIO_Init();
// Initialize the eDMA for moving data.
DMAMUX_HAL_Init(DMAMUX);
EDMA_HAL_Init(DMA0);
// Because the function call is not allowed in constant expression,
// the API that get the buffer's address is called by the application.
edma17_transfer_config.srcAddr = FLEXIO_Camera_HAL_GetRxBufferAddr(&gFlexioCameraDevStruct),
eDma_Init(kEDMAChannel16, // DMA Channel 16 is bound to the threshold event which is one item left to the full buffer.
gFlexioCameraDevStruct.shifterStartIdx + 2U, &edma16_transfer_config);
eDma_Init(kEDMAChannel17, // DMA channel 17 is bound to the bull buffer event.
gFlexioCameraDevStruct.shifterStartIdx + 1U, &edma17_transfer_config);
PORTA_InstallCallback(1, porta_callback); // vsync pin in PTA13 with priority value 1.
configure_app_gpio_pins(); // Enable the interrupt of OV7670's vsync pins.
while(1) {}
}
static void FlexIO_Init(void)
{
// Configure the FlexIO as camera.
FLEXIO_Camera_HAL_Configure(&gFlexioCameraDevStruct);
// Clear all flags.
FLEXIO_Camera_HAL_ClearRxBufferFullFlag(&gFlexioCameraDevStruct);
FLEXIO_HAL_ClearShifterErrorFlags(FLEXIO0, 0xFF);
FLEXIO_HAL_ClearTimerStatusFlags(FLEXIO0, 0xFF);
FLEXIO_Camera_HAL_SetRxBufferDmaCmd(&gFlexioCameraDevStruct, 0x03, true);
// Configure the FlexIO common function.
FLEXIO_HAL_SetFastAccessCmd(FLEXIO0, true);
FLEXIO_HAL_SetFlexioEnableCmd(FLEXIO0, true);
}
static void eDma_Init(
edma_channel_indicator_t channel, // eDMA channel.
uint8_t source, // Trigger source.
edma_transfer_config_t *edma_config // Transfer parameter.
)
{
// DMA MUX initialization.
DMAMUX_HAL_SetChannelCmd(DMAMUX, channel, false);
DMAMUX_HAL_SetTriggerSource(DMAMUX, channel, source);
// eDMA initialization.
EDMA_HAL_SetChannelArbitrationMode(DMA0, kEDMAChnArbitrationRoundrobin);
EDMA_HAL_SetGroupPriority(DMA0, kEDMAGroup0PriorityLowGroup1PriorityHigh);
EDMA_HAL_SetGroupArbitrationMode(DMA0, kEDMAGroupArbitrationRoundrobin);
EDMA_HAL_HTCDSetSrcAddr(DMA0, channel, edma_config->srcAddr);
EDMA_HAL_HTCDSetSrcOffset(DMA0, channel, edma_config->srcOffset);
EDMA_HAL_HTCDSetSrcLastAdjust(DMA0, channel, edma_config->srcLastAddrAdjust);
EDMA_HAL_HTCDSetDestAddr(DMA0, channel, edma_config->destAddr);
EDMA_HAL_HTCDSetDestOffset(DMA0, channel, edma_config->destOffset);
EDMA_HAL_HTCDSetDestLastAdjust(DMA0, channel, edma_config->destLastAddrAdjust);
EDMA_HAL_HTCDSetNbytes(DMA0, channel, edma_config->minorLoopCount);
EDMA_HAL_HTCDSetMajorCount(DMA0, channel, edma_config->majorLoopCount );
EDMA_HAL_HTCDSetAttribute(DMA0, channel, edma_config->srcModulo,
edma_config->destModulo,
edma_config->srcTransferSize,
edma_config->destTransferSize);
// Clear all the flags.
EDMA_HAL_ClearDoneStatusFlag(DMA0, channel);
EDMA_HAL_HTCDSetDisableDmaRequestAfterTCDDoneCmd(DMA0, channel, false);
EDMA_HAL_SetAsyncRequestInStopModeCmd(DMA0, channel, true); // The DMA can work in CPU stop mode.
EDMA_HAL_SetDmaRequestCmd(DMA0, channel, true);
DMAMUX_HAL_SetChannelCmd(DMAMUX, channel, true);
}
static void eDma_Reset(edma_channel_indicator_t channel, edma_transfer_config_t *edma_config)
{
EDMA_HAL_HTCDSetSrcAddr(DMA0, channel, edma_config->srcAddr);
EDMA_HAL_HTCDSetDestAddr(DMA0, channel, edma_config->destAddr);
EDMA_HAL_HTCDSetMajorCount(DMA0, channel, edma_config->majorLoopCount);
}
static void porta_callback(uint32_t pin)
{
if (pin == (1<<13)) // vsyhc pin.
{
// Resets the transfer of the flexio_camera to the buffer, and the buffer to the LCD.
eDma_Reset(kEDMAChannel16, &edma16_transfer_config); // buffer to LCD.
eDma_Reset(kEDMAChannel17, &edma17_transfer_config); // flexio_camera to buffer.
// Reset the LCD.
// ...
}
}