Implementation of Parallel Camera Functionality Using FlexIO on RT1176

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Implementation of Parallel Camera Functionality Using FlexIO on RT1176

Jump to solution
3,502 Views
seobi
Contributor III
 
We are preparing to integrate two cameras with the RT1176.
 
Currently, one camera is successfully operating with the CSI interface.
 
For the additional camera, we are working on implementing the functionality to receive 16-bit parallel camera data using FLEXIO2.
 
Referring to AN12686 and the an-flexio_camera_rt1010 GitHub repository, we attempted to receive 16-bit data. 
 
While the DMA callback is triggered, the received data appears to be incorrect.
 
The HSYNC and PCLK (24MHz) signals are being received correctly.
 
We would appreciate guidance on what additional configurations might be required.
 
Please find the relevant code attached. Your assistance would be greatly appreciated.
 
Best regards,
 
void FLEXIO_CAMERA_Init(FLEXIO_CAMERA_Type *base, const flexio_camera_config_t *config)
{
    assert((base != NULL) && (config != NULL));
    assert(base->shifterCount > 0U);
 
    uint32_t i                   = 0U;
    volatile uint32_t controlVal = 0U;
 
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
    /* Ungate flexio clock. */
    CLOCK_EnableClock(s_flexioClocks[FLEXIO_CAMERA_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
 
    flexio_shifter_config_t shifterConfig;
    flexio_timer_config_t timerConfig;
 
    /* Clear the shifterConfig & timerConfig struct. */
    (void)memset(&shifterConfig, 0, sizeof(shifterConfig));
    (void)memset(&timerConfig, 0, sizeof(timerConfig));
 
    /* Configure flexio camera */
    controlVal = base->flexioBase->CTRL;
    controlVal &=
        ~(FLEXIO_CTRL_DOZEN_MASK | FLEXIO_CTRL_DBGE_MASK | FLEXIO_CTRL_FASTACC_MASK | FLEXIO_CTRL_FLEXEN_MASK);
    controlVal |= (FLEXIO_CTRL_DBGE(config->enableInDebug) | FLEXIO_CTRL_FASTACC(config->enableFastAccess) |
                   FLEXIO_CTRL_FLEXEN(config->enablecamera));
    if (!config->enableInDoze)
    {
        controlVal |= FLEXIO_CTRL_DOZEN_MASK;
    }
    base->flexioBase->CTRL = controlVal;
 
    /* FLEXIO_CAMERA shifter config */
    shifterConfig.timerSelect   = base->timerIdx;
    shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnPositive;
    shifterConfig.pinConfig     = kFLEXIO_PinConfigOutputDisabled;
    shifterConfig.pinSelect     = base->datPinStartIdx;
    shifterConfig.pinPolarity   = kFLEXIO_PinActiveHigh;
    shifterConfig.shifterMode   = kFLEXIO_ShifterModeReceive;
    shifterConfig.parallelWidth = 16 - 1U;
    shifterConfig.inputSource   = kFLEXIO_ShifterInputFromNextShifterOutput;
    shifterConfig.shifterStop   = kFLEXIO_ShifterStopBitDisable;
    shifterConfig.shifterStart  = kFLEXIO_ShifterStartBitDisabledLoadDataOnEnable;
    /* Configure the shifters as FIFO buffer. */
    for (i = base->shifterStartIdx; i < (base->shifterStartIdx + base->shifterCount - 1U); i++)
    {
        FLEXIO_SetShifterConfig(base->flexioBase, (uint8_t)i, &shifterConfig);
    }
    shifterConfig.inputSource = kFLEXIO_ShifterInputFromPin;
    FLEXIO_SetShifterConfig(base->flexioBase, (uint8_t)i, &shifterConfig);
 
    /* FLEXIO_CAMERA timer config, the PCLK's clk is source of timer to drive the shifter, the HREF is the selecting
     * signal for available data. */
    timerConfig.triggerSelect   = FLEXIO_TIMER_TRIGGER_SEL_PININPUT(base->hrefPinIdx);
    timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveHigh;
    timerConfig.triggerSource   = kFLEXIO_TimerTriggerSourceInternal;
    timerConfig.pinConfig       = kFLEXIO_PinConfigOutputDisabled;
    timerConfig.pinSelect       = base->pclkPinIdx;
    timerConfig.pinPolarity     = kFLEXIO_PinActiveHigh;
    timerConfig.timerMode       = kFLEXIO_TimerModeSingle16Bit;
    timerConfig.timerOutput     = kFLEXIO_TimerOutputZeroNotAffectedByReset;
    timerConfig.timerDecrement  = kFLEXIO_TimerDecSrcOnPinInputShiftPinInput;
    timerConfig.timerReset      = kFLEXIO_TimerResetOnTimerTriggerRisingEdge;
    timerConfig.timerDisable    = kFLEXIO_TimerDisableOnTriggerFallingEdge;
    timerConfig.timerEnable     = kFLEXIO_TimerEnableOnTriggerRisingEdge;
    timerConfig.timerStop       = kFLEXIO_TimerStopBitDisabled;
    timerConfig.timerStart      = kFLEXIO_TimerStartBitDisabled;
 
#ifdef __CAMERA_DATA_16BIT__
    timerConfig.timerCompare    = 2*((32*base->shifterCount)/16)-1U;
#else
timerConfig.timerCompare = 8U * base->shifterCount - 1U;
#endif
 
    FLEXIO_SetTimerConfig(base->flexioBase, (uint8_t)base->timerIdx, &timerConfig);
    /* Clear flags. */
    FLEXIO_ClearShifterErrorFlags(base->flexioBase, (((1UL << (base->shifterCount)) - 1U) << (base->shifterStartIdx)));
    FLEXIO_ClearTimerStatusFlags(base->flexioBase, 1UL << (base->timerIdx));
}
 
 
int32_t cameraStartFrame(volatile uint8_t *pDest, const uint32_t numFrames)
{
busy = true;
 
flexio_camera_transfer_t cameraTransfer;
    cameraTransfer.dataAddress = (uint32_t)pDest;
cameraTransfer.dataNum = g_width * g_height * sizeof(uint16_t) * numFrames;
 
frameCounter = 0;
numFramesExpected = numFrames;
 
FLEXIO_CAMERA_ClearStatusFlags(&g_FlexioCameraDevice, kFLEXIO_CAMERA_RxDataRegFullFlag | kFLEXIO_CAMERA_RxErrorFlag);
 
g_cameraEdmaHandle.rxState = 0;
    FLEXIO_CAMERA_TransferReceiveEDMA(&g_FlexioCameraDevice, &g_cameraEdmaHandle, &cameraTransfer);
 
return 0;
}
 
 
int InitParallelCamera(void)
{
edma_config_t edmaConfig;
flexio_camera_config_t cameraConfig;
 
CLOCK_EnableClock(kCLOCK_Flexio2);
    FLEXIO_Reset(FLEXIO2);
/* Configure DMAMUX */
DMAMUX_Init(DMAMUX0);
// DMAMUX_SetSource(DMAMUX0, FLEXIO_CAMERA_DMA_CHN, FLEXIO_CAMERA_DMA_MUX_SRC);
// DMAMUX_SetSource(DMAMUX0, FLEXIO_CAMERA_DMA_CHN, (g_FlexioCameraDevice.shifterStartIdx + 1U));
DMAMUX_EnableAlwaysOn(DMAMUX0, FLEXIO_CAMERA_DMA_CHN, true);
DMAMUX_EnableChannel(DMAMUX0, FLEXIO_CAMERA_DMA_CHN);
 
/* Configure DMA */
EDMA_GetDefaultConfig(&edmaConfig);
    edmaConfig.enableDebugMode = true;
EDMA_Init(DMA0, &edmaConfig);
EDMA_CreateHandle(&g_edmaHandle, DMA0, FLEXIO_CAMERA_DMA_CHN);
 
    FLEXIO_Reset(FLEXIO2);
FLEXIO_CAMERA_GetDefaultConfig(&cameraConfig);
FLEXIO_CAMERA_Init(&g_FlexioCameraDevice, &cameraConfig);
 
/* Clear all the flag. */
FLEXIO_CAMERA_ClearStatusFlags(&g_FlexioCameraDevice, kFLEXIO_CAMERA_RxDataRegFullFlag | kFLEXIO_CAMERA_RxErrorFlag);
FLEXIO_ClearTimerStatusFlags(FLEXIO2, 0xFF);
 
/* Enable FlexIO. */
FLEXIO_CAMERA_Enable(&g_FlexioCameraDevice, true);
 
int32_t status = FLEXIO_CAMERA_TransferCreateHandleEDMA(&g_FlexioCameraDevice, &g_cameraEdmaHandle, FLEXIO_CAMERA_UserCallback, NULL, &g_edmaHandle);
 
PRINTF(">>>> end InitparallelCamera() status = %d\r\n", status);
}
 
0 Kudos
Reply
1 Solution
3,062 Views
seobi
Contributor III

During HSYNC, the bytes received were width x 4 bytes.

An issue occurred with the received frame, causing flexio to not receive all 32 bytes.

Thank you for everything.


BR,
seobi

View solution in original post

0 Kudos
Reply
11 Replies
3,112 Views
seobi
Contributor III

When receiving dma via flexio, frames of 320x240 pixels are received normally.(16bit mode)

However, 316x240 pixels are received abnormally. And 312x240 pixels are received normally again.

Horizontal values that are multiples of 8 are received normally, but multiples of 4 are received abnormally (frames are broken).

DMA is transmitted based on 32 bytes, and flexio uses 8 shifters.

Can you tell me why it's only a multiple of 8?

seobi_0-1737333312038.png

BR.
seobi

0 Kudos
Reply
3,097 Views
EdwinHz
NXP TechSupport
NXP TechSupport

Hi @seobi,

This is due to the nature of the byte sizes for the screen's buffers. They are byte sized, which means that contain 8 bits each.

0 Kudos
Reply
3,084 Views
seobi
Contributor III

Let me explain the problem in more detail.

Even at 316x240 resolution, when drawing pixels directly without using FlexIO and DMA, the display works properly.

However, when using the pixels received through FlexIO and DMA, the display gets corrupted.

It is in 16-bit mode, and 320x240 works fine. 312x240 also works fine (multiples of 8).

However, issues occur at 316x240 and 308x240 resolutions (multiples of 4).

The frame size received through FlexIO and DMA is being affected.

Why does this issue occur?

 

BR,
seobi

0 Kudos
Reply
3,063 Views
seobi
Contributor III

During HSYNC, the bytes received were width x 4 bytes.

An issue occurred with the received frame, causing flexio to not receive all 32 bytes.

Thank you for everything.


BR,
seobi

0 Kudos
Reply
3,313 Views
seobi
Contributor III

The root clock of FlexIO2 on the RT1176 was initially set to 24 MHz.

After replacing the root clock with 120 MHz, it started to normally receive 16 bits.

However, as shown in the picture below, there is an issue.

When counting the pixels, the 31,32nd byte appears abnormal.

The DMA setting of the FLEXIO_CAMERA_TransferReceiveEDMA() function is set to process 32 bytes at a time. Is this related?

I am waiting for your advice.

grayscale.PNG

0 Kudos
Reply
3,302 Views
EdwinHz
NXP TechSupport
NXP TechSupport

Hi @seobi,

Make sure the DMA is running at a proper speed according to the 120MHz of the FlexIO camera, so it has enough time to process the 31st and 32nd bit.

 

0 Kudos
Reply
3,276 Views
seobi
Contributor III

As you can see in the picture below, if flexio misses the 1st pixel, every 32nd pixel in that row is broken.

shift_pixel.PNG

 

I thought it would be enough time for flexio to reset since it starts on the riging edge of HSYNC and kFLEXIO_PinActiveLow is set.

pclk.PNG

Is there a problem with the timing of flexio's timer?

I am waiting for your help.

 

 

0 Kudos
Reply
3,280 Views
seobi
Contributor III

I am using only one edma in this project, which is used by flexio.

I know that edma has default maximum bandwidth.

What can I change to get proper speed?

Tags (1)
0 Kudos
Reply
3,457 Views
EdwinHz
NXP TechSupport
NXP TechSupport

Hi @seobi,

What camera are you using for the FlexIO side? Are you certain you have mirrored the extensive HW configurations that are described on the GitHub - nxp-appcodehub/an-flexio_camera_rt1010

BR,
Edwin.

0 Kudos
Reply
3,444 Views
seobi
Contributor III

My camera is a 13-bit parallel camera.

I used data lines from FlexIO2 pins 1 through 16 sequentially, along with PCLK, VSYNC, and HSYNC.

Additionally, the last 3 bits of the 16 bits, which are unused, have been left as not connected.

It seems that no further hardware handling is necessary.

When reading the data, only specific vertical lines are being read.

Could you review if there are any issues in the attached source code regarding the 16-bit processing?

I'm suspecting the settings of the shifter and timer, but there's not much information on the subject...

I desperately need your help.

 

seobi_0-1733797756913.png

 

0 Kudos
Reply
3,415 Views
seobi
Contributor III

The yellow waveform in the figure below represents the timing when FLEXIO_CAMERA_TransferReceiveEDMA(&g_FlexioCameraDevice, &g_cameraEdmaHandle, &cameraTransfer) is called and the User Callback is invoked.

The green waveform indicates the timing of HSYNC reception.

I understood that, when using FlexIO2 to receive data from a 16-bit parallel camera, HSYNC serves as the trigger.

However, observing the actual waveform, I noticed that as soon as FLEXIO_CAMERA_TransferReceiveEDMA() is called, data starts accumulating.

After receiving the specified amount of data, the User Callback is immediately invoked.

Interestingly, the second yellow waveform appears even before HSYNC is triggered.

Isn't the structure designed to receive data via DMA only during the High period of HSYNC based on "timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveHigh"?

What is the correct method to receive data only during the HSYNC period?

I desperately need your help.

seobi_0-1733894052956.png

 

0 Kudos
Reply