KurtE
Senior Member+
As @mjs513 mentioned in another thread, we have been playing around with the OV7670 camera using FlexIO, preferably with DMA
We have had it working on T4.1 using CSI and Micromod using DMA from GPIO pins, but thought it would be fun to get it working properly using
DMA and FlexIO.
We are using the Micromod pins. I had it sort of working with Flexio using just one Shifter, but some of the data was being corrupted. and noticed that the RM for FlexIO Camera example is using 4 shifters and another version we saw was setup to use all 8... So currently trying to use all 8.
Currently with the 4 and 8 setup a read from the camera, dies with either timeout or DMA Error.
Short version question: Has anyone tried FlexIO where you are chaining shift registers to each other so for example with:
4 of them we have 128 bits of data and likewise all 8 256 bits.
If so how have you used DMA to read in the data from the SHIFTBUF[0-7] to be stored out for memory... (Or likewise for something like a display be able to load up all of the Shift buffer registers. with DMA?
Note: the NXP Shifter option has code to configure DMA like:
Their 4 shifter version was similar:
With the 4 one I think it is setup to have inner DMA loop that cycled over the 4 buffers, and then used the Source Mask and the like,
to have the registers work like a circular buffer, so after it reads all 4 (or 8) it recycles back to the first one.
Has anyone tried something like this?
=====
Longer version: More to be filled in tomorrow...
It sort of follows the information within the RM
The code was more or less a conversion of the 1050 NXP example code.
IO pins:
The flexIO is setup to hopefully chain all 8 Shift buffers to each other: The settings for the FlexIO registers:
At startup the FlexIO registers are:
In this run I had a DMA Timeout
I know that the Camera is generating data and that we are seeing some of it. For example in the below Logic Analyzer capture, the last line is where we detect the start of a new frame and the start to capture data.
More tomorrow after I reread some of the sections again on how the chaining works in FlexIO and likewise:
inner and outer loops.
But suggestions would be appreciated!
We have had it working on T4.1 using CSI and Micromod using DMA from GPIO pins, but thought it would be fun to get it working properly using
DMA and FlexIO.
We are using the Micromod pins. I had it sort of working with Flexio using just one Shifter, but some of the data was being corrupted. and noticed that the RM for FlexIO Camera example is using 4 shifters and another version we saw was setup to use all 8... So currently trying to use all 8.
Currently with the 4 and 8 setup a read from the camera, dies with either timeout or DMA Error.
Short version question: Has anyone tried FlexIO where you are chaining shift registers to each other so for example with:
4 of them we have 128 bits of data and likewise all 8 256 bits.
If so how have you used DMA to read in the data from the SHIFTBUF[0-7] to be stored out for memory... (Or likewise for something like a display be able to load up all of the Shift buffer registers. with DMA?
Note: the NXP Shifter option has code to configure DMA like:
Code:
/* Configure DMA TCD */
DMA0->TCD[FLEXIO_CAMERA_DMA_CHN].SADDR = FLEXIO_CAMERA_GetRxBufferAddress(&s_FlexioCameraDevice);
DMA0->TCD[FLEXIO_CAMERA_DMA_CHN].SOFF = 0u;
DMA0->TCD[FLEXIO_CAMERA_DMA_CHN].ATTR = DMA_ATTR_SMOD(0u) |
DMA_ATTR_SSIZE(5u) |
DMA_ATTR_DMOD(0u) |
DMA_ATTR_DSIZE(5u);
DMA0->TCD[FLEXIO_CAMERA_DMA_CHN].NBYTES_MLNO = 32u;
DMA0->TCD[FLEXIO_CAMERA_DMA_CHN].SLAST = 0u;
DMA0->TCD[FLEXIO_CAMERA_DMA_CHN].DADDR = (uint32_t)(*pFlexioCameraFrameBuffer);
DMA0->TCD[FLEXIO_CAMERA_DMA_CHN].DOFF = 32u;
DMA0->TCD[FLEXIO_CAMERA_DMA_CHN].CITER_ELINKNO = (OV7670_FRAME_BYTES / 32u);
DMA0->TCD[FLEXIO_CAMERA_DMA_CHN].DLAST_SGA = 0;
DMA0->TCD[FLEXIO_CAMERA_DMA_CHN].CSR = 0u;
DMA0->TCD[FLEXIO_CAMERA_DMA_CHN].CSR |= DMA_CSR_DREQ_MASK;
DMA0->TCD[FLEXIO_CAMERA_DMA_CHN].BITER_ELINKNO = (OV7670_FRAME_BYTES / 32u);
/* Configure DMA MUX Source */
DMAMUX->CHCFG[FLEXIO_CAMERA_DMA_CHN] = DMAMUX->CHCFG[FLEXIO_CAMERA_DMA_CHN] &
(~DMAMUX_CHCFG_SOURCE_MASK) |
DMAMUX_CHCFG_SOURCE(FLEXIO_CAMERA_DMA_MUX_SRC);
/* Enable DMA channel. */
DMAMUX->CHCFG[FLEXIO_CAMERA_DMA_CHN] |= DMAMUX_CHCFG_ENBL_MASK;
}
Code:
static void configDMA(void)
{
uint32_t soff, smod = 0u, size=0u;
while(1u << size < DMA_TRSF_SIZE) /* size = log2(DMA_TRSF_SIZE) */
{
size++;
}
if(DMA_TRSF_SIZE == DMA_MINOR_LOOP_SIZE)
{
soff = 0u;
}
else
{
soff = DMA_TRSF_SIZE;
while(1u << smod < DMA_MINOR_LOOP_SIZE) /* smod = log2(DMA_MINOR_LOOP_SIZE) */
{
smod++;
}
}
/* Configure DMA TCD */
DMA0->TCD[FLEXIO_CAMERA_DMA_CHN].SADDR = FLEXIO_CAMERA_GetRxBufferAddress(&s_FlexioCameraDevice);
DMA0->TCD[FLEXIO_CAMERA_DMA_CHN].SOFF = soff;
DMA0->TCD[FLEXIO_CAMERA_DMA_CHN].ATTR = DMA_ATTR_SMOD(smod) |
DMA_ATTR_SSIZE(size) |
DMA_ATTR_DMOD(0u) |
DMA_ATTR_DSIZE(size);
DMA0->TCD[FLEXIO_CAMERA_DMA_CHN].NBYTES_MLNO = DMA_MINOR_LOOP_SIZE;
DMA0->TCD[FLEXIO_CAMERA_DMA_CHN].SLAST = 0u;
DMA0->TCD[FLEXIO_CAMERA_DMA_CHN].DADDR = (uint32_t)(*pFlexioCameraFrameBuffer);
DMA0->TCD[FLEXIO_CAMERA_DMA_CHN].DOFF = DMA_TRSF_SIZE;
DMA0->TCD[FLEXIO_CAMERA_DMA_CHN].CITER_ELINKNO = DMA_MAJOR_LOOP_SIZE;
DMA0->TCD[FLEXIO_CAMERA_DMA_CHN].DLAST_SGA = -OV7670_FRAME_BYTES;
DMA0->TCD[FLEXIO_CAMERA_DMA_CHN].CSR = 0u;
DMA0->TCD[FLEXIO_CAMERA_DMA_CHN].CSR |= DMA_CSR_DREQ_MASK;
DMA0->TCD[FLEXIO_CAMERA_DMA_CHN].BITER_ELINKNO = DMA_MAJOR_LOOP_SIZE;
/* Configure DMA MUX Source */
DMAMUX->CHCFG[FLEXIO_CAMERA_DMA_CHN] = DMAMUX->CHCFG[FLEXIO_CAMERA_DMA_CHN] &
(~DMAMUX_CHCFG_SOURCE_MASK) |
DMAMUX_CHCFG_SOURCE(FLEXIO_CAMERA_DMA_MUX_SRC);
/* Enable DMA channel. */
DMAMUX->CHCFG[FLEXIO_CAMERA_DMA_CHN] |= DMAMUX_CHCFG_ENBL_MASK;
}
With the 4 one I think it is setup to have inner DMA loop that cycled over the 4 buffers, and then used the Source Mask and the like,
to have the registers work like a circular buffer, so after it reads all 4 (or 8) it recycles back to the first one.
Has anyone tried something like this?
=====
Longer version: More to be filled in tomorrow...
It sort of follows the information within the RM
The code was more or less a conversion of the 1050 NXP example code.
IO pins:
Code:
#ifdef ARDUINO_TEENSY_MICROMOD
/*
HM01B0 pin pin# NXP Usage
---------- ---- --- -----
FVLD/VSYNC 33 EMC_07 GPIO
LVLD/HSYNC 32 B0_12 FlexIO2:12
MCLK 7 B1_01 PWM
PCLK 8 B1_00 FlexIO2:16
D0 40 B0_04 FlexIO2:4
D1 41 B0_05 FlexIO2:5
D2 42 B0_06 FlexIO2:6
D3 43 B0_07 FlexIO2:7
D4 44 B0_08 FlexIO2:8 - probably not needed, use 4 bit mode
D5 45 B0_09 FlexIO2:9 - probably not needed, use 4 bit mode
D6 6 B0_10 FlexIO2:10 - probably not needed, use 4 bit mode
D7 9 B0_11 FlexIO2:11 - probably not needed, use 4 bit mode
TRIG 5 EMC_08 ???
INT 29 EMC_31 ???
SCL 19 AD_B1_0 I2C
SDA 18 AD_B1_1 I2C
*/
#define OV7670_PLK 8 //8 B1_00 FlexIO2:16
#define OV7670_XCLK 7 //7 B1_01 PWM
#define OV7670_HREF 46 //32 B0_12 FlexIO2:12
#define OV7670_VSYNC 21 //33 EMC_07 GPIO
#define OV7670_RST 255 // reset pin
#define OV7670_D0 40 //40 B0_04 FlexIO2:4
#define OV7670_D1 41 //41 B0_05 FlexIO2:5
#define OV7670_D2 42 //42 B0_06 FlexIO2:6
#define OV7670_D3 43 //43 B0_07 FlexIO2:7
#define OV7670_D4 44 //44 B0_08 FlexIO2:8 - probably not needed, use 4 bit mode
#define OV7670_D5 45 //45 B0_09 FlexIO2:9 - probably not needed, use 4 bit mode
#define OV7670_D6 6 //6 B0_10 FlexIO2:10 - probably not needed, use 4 bit mode
#define OV7670_D7 9 //9 B0_11 FlexIO2:11 - probably not needed, use 4 bit mode
The flexIO is setup to hopefully chain all 8 Shift buffers to each other: The settings for the FlexIO registers:
At startup the FlexIO registers are:
Code:
FlexIO Configure
CCM_CSCMR2 = 13192F06
div1 = 2, div2 = 2
FlexIO2 Frequency = 120.00 MHz
CCM_CCGR3 = F00FF333
FLEXIO2_CTRL = 00000000
FlexIO2 Config, param=02200808
8Bit FlexIO
FLEXIO:1 Shifter:0 Timer:0
SHIFTCFG = 00070100 00070100 00070100 00070100 00070100 00070100 00070100 00070000
SHIFTCTL = 00000401 00000401 00000401 00000401 00000401 00000401 00000401 00000401
TIMCMP = 0000003F
TIMCFG = 01206600
TIMCTL = 00000401
I2C Write: reg: 0x11(CLKRC), value = 0x0f
I2C Write: reg: 0x6b(DBLV), value = 0x4a
Camera settings:
width = 320
height = 240
bits per pixel = 16
Code:
Reading frame
Buffer: 0x20017d2c halfway: 0x2002a92c end:0x2003d52c
DMA CR: 00000482 Channel: 1 80000041
CH: 2000449c 400e9020: SA:401b0200 SO:0 AT:505 (SM:0 SS:5 DM:0 DS:5) NB:20 SL:0 DA:20017d2c DO: 32 CI:12c0 DL:-153600 CS:a BI:12c0
Flexio DMA: length: 153600
Timeout waiting for DMA
SHIFTSTAT bit was set (000000FF)
DMA channel #1
DMAMUX = 80000041
FLEXIO2_SHIFTSDEN = 01
TCD CITER = 4800
TCD CSR = 0000000A
CM: 2000449c 400e9020: SA:401b0200 SO:0 AT:505 (SM:0 SS:5 DM:0 DS:5) NB:20 SL:0 DA:20017d2c DO: 32 CI:12c0 DL:-153600 CS:a BI:12c0
Finished reading frame
More tomorrow after I reread some of the sections again on how the chaining works in FlexIO and likewise:
inner and outer loops.
But suggestions would be appreciated!