MicroMod Beta Testing

@mjs513 sorry I have been a bit distracted today. Still hacking DMA...
Pushed up branch dma_merge_fixes which updated the DMA code not to hang.
Plus added a command 'D' which does like 'd' except displays only one frame.

With Sparkfun it appears to display stuff OK. In continuous mode it gets scrambled.

next up maybe look again what difference are between Sparkfun and non-sparkfun.

Back to playing
 
Just a question.

Before trying to answer, I need to admit two things.

1: I've only read Kurt's code quickly, haven't actually worked with it or analyzed carefully
2: Obviously I don't know everything about FlexIO DMA, since I couldn't get hardware trigger working yet

Looks like Kurt's code is a using separate DMA transfer for each horizontal line. Two buffers and 2 DMA channels seem to be used in a ping-pong style. Actual hardware triggering from PCLK is done by XBAR. Since GPIO only supports 32 bit access, the full 32 bit register is captured into 1296 byte buffers. The DMA interrupt runs after each line, to extract the 324 bytes and set the DMA up again. It really looks like a pretty solid approach.

So far I've not tried to use interrupts at all. Hardly seems worthwhile to add all that until the hardware triggering issue is resolved.

But the general idea is pretty much as AN12686 describes. Rather than an interrupt after each horizontal line, FlexIO is meant to capture the entire image into the frame buffer and give a single interrupt when it's completed.

Kurt's code is using attachInterrupt() on VSYNC to set everything up. AN12686 suggests doing the same. The DMA config I used is meant to work that way. The main point is uses disableOnCompletion() which causes the DMA channel to not be able to work again until you enable it.

That's pretty much the opposite of how we do DMA for audio. For sound, the DMA is configured so it automatically restarts the same transfer all over again as soon as it's finished. The key ingredient to make that work properly is the TCD's SLAST or DLASTSGA setting. After the transfer is complete, the source or destination (whichever was accessing a buffer in memory) will be pointing to just beyond the buffer it used. These settings automatically add a constant to the source or destination pointer when the transfer completes. We use negative numbers, so the pointer goes back to the beginning of the buffer. If the DMA transfer is going to automatically restart, it better do so back at the beginning of the buffer its using!

So I believe those words in AN12686 are trying to say is you don't need to use those automatic adjustments, since the DMA is configured to not auto-restart. The code will just write the buffer address again when the rising edge of VSYNC happens. And if you were going to double buffer, I guess you would set the buffer address differently on each VSYNC rising edge.

Perhaps will try to use DLASTSGA with FlexIO for an auto-restarting transfer that doesn't require anything to be at the VSYNC rising edge? For single buffer, it could reset the destination so the DMA is ready to go for the next use. For double buffer, we could create 2 different DMASettings objects (like a DMAChannel, but only the transfer setup data, not actual hardware) and have each automatically load the other's settings after each transfer completes. If that's confusing, well, the other way to use DLASTSGA is scatter-gather, where a DMA channel can use DMA upon completion to completely replace all its settings. That's why we have a DMASettings class, so you can set up settings for a DMA channel to update itself when it completes. So 2 of those could be used with 1 DMAChannel that doesn't have disableOnCompletion() to create a double buffer approach that automatically restarts itself.

But having the DMAChannel disables on completion and an interrupt on the rising edge of VSYNC which programs the destination buffer and re-enables it is simpler and costs only a brief interrupt on VSYNC. Maybe eventually we'll go with DMA that automatically re-enables itself like we do for audio. But unlike audio, we have a lot of time between the end of a frame and the next VSYNC rising edge.

Hopefully that made some sense? Or at least didn't make it all even more confusing?
 
Paul,

I will read more of your comments in a bit... Other distractions going on.

With VSync - I was wondering if I was starting too late, or maybe VSync interrupt not being serviced fast enough at times.

I am doing to experiment, with changing it from GPIO9 to GIPIO4 and and connect up to use ISR IRQ_GPIO4_0_15

Not sure how much of a difference it will make, but probably easier to control.

But maybe the image moving around on my code is more with other delays.

My DMA is using One DMAChannel, with Two DMASettings, such that I can then process the data when one completes and the other should continue to receive the new data.
Just found it easier. Alternatively could have one buffer with interrupt at end and at center. And yes I start it and stop it between frames.
 
@mjs513 sorry I have been a bit distracted today. Still hacking DMA...
Pushed up branch dma_merge_fixes which updated the DMA code not to hang.
Plus added a command 'D' which does like 'd' except displays only one frame.

With Sparkfun it appears to display stuff OK. In continuous mode it gets scrambled.

next up maybe look again what difference are between Sparkfun and non-sparkfun.

Back to playing

No problem - been doing some other things as well. Just when I get back on I'm on for a while. Been spending time going down the rabbit hole.

Funny that's exactly what I am seeing with FlexIO. With SparkFun/non-sparkfun if you just do a single snapshot everything is working as it should. When you go into continuous it gets out of synch in different ways. But single shot works for FlexIO.

But either way glad you got single shot working. With the way its set up now the 2 should almost be equivalent. I know its that almost that gets you.
 
...

Hopefully that made some sense? Or at least didn't make it all even more confusing?

Seems to be a typically good exposition - Makes sense to me and I haven't even looked in any of those rabbit holes.


And yes the FlexIO single shot works promisingly well! Been videoing my room all day since I left for other things.
 
PaulStoffregen said:
Hopefully that made some sense? Or at least didn't make it all even more confusing?
As usual yes it make sense when you explain it - I just need to do some more homework on the TCD setups. Going to be a long process.
 
Playing a little more, I brought over my Frame info function to get an idea of what maybe is different... Pushed up to my dma_merge_fixes.

Here is information printed when SPARKFUN:
Code:
	converged!
Reading frame
Finished reading frame
*** Frame Capture Data: elapsed Micros: 33213 loops: 651473
   VSync Loops Start: 27558 end: 27556
   href count: 244 pclk ! href count: 1
      0(0) 
    324(0) 324(125) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 
    324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 
    324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 
    324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 
    324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(126) 324(125) 
    324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 
    324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 
    324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 
    324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 
    324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 
    324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 
    324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 
    324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(126) 324(125) 324(125) 324(125) 
    324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 
    324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(126) 324(125) 324(125) 324(125) 324(126) 324(125) 
    324(125) 324(126) 324(125) 324(125)
The numbers at end are how many PCLKS per HREF and delta Micros from previous row...

Actually now showing 'D' command still correctly with similar data.
Code:
Reading frame
Finished reading frame
startReadFrameDMA called buffers 20029ac4 20200000
*** Return from startReadFrameDMA ***
*** Frame Capture Data: elapsed Micros: 32587 loops: 654716
   VSync Loops Start: 55676 end: 55677
   href count: 244 pclk ! href count: 1
      0(0) 
    324(0) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(125) 324(126) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 
    324(125) 324(126) 324(125) 324(126) 324(125) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(126) 324(125) 324(125) 324(126) 
    324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(125) 324(126) 324(125) 324(126) 324(125) 324(125) 324(125) 324(126) 
    324(125) 324(125) 324(126) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 
    324(125) 324(126) 324(125) 324(126) 324(125) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(126) 324(125) 324(125) 324(126) 
    324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(125) 324(126) 324(125) 324(126) 324(125) 324(125) 324(125) 324(126) 
    324(125) 324(125) 324(126) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 
    324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(125) 
    324(126) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(125) 324(126) 324(125) 324(126) 324(125) 324(125) 324(125) 324(126) 
    324(125) 324(125) 324(126) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 
    324(125) 324(126) 324(125) 324(126) 324(125) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(126) 324(125) 324(125) 324(126) 
    324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(125) 324(126) 324(125) 324(126) 324(125) 324(125) 324(125) 324(126) 
    324(125) 324(125) 324(126) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 
    324(125) 324(126) 324(125) 324(126) 324(125) 324(125) 324(125) 324(126) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(125) 
    324(126) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 324(125) 324(126) 324(125) 
    324(125) 324(126) 324(125) 324(125)
The interesting thing is there is almost no time between the VSYNC and the first href... Which may be my issue.
 
@KurtE
That might be why it would work in single frame mode but not continuous - how to do you fix it. Try commenting out the line in the sketch for framesize and uncomment Sparkfun. If you do that it will put it into 5fps mode.
 
@mjs513,
I see a few different options:

a) don't disable the DMA... In theory if I am totally in sink, the next DMA operation (when PCLK) triggers should be at the start of the next frame. May try this to see how it does...

b) Make sure handling of VSYNC is fast... That is why I mentioned maybe have it's own interrupt.

c) not sure if there is something one might do with XBAR? That is it is an XBAR pin,
Looks like there are two IRQs associated with XBAR... But my guess is it is the same XBAR type mapping like using to trigger DMA from the PCLK...
 
@mjs513,
I see a few different options:

a) don't disable the DMA... In theory if I am totally in sink, the next DMA operation (when PCLK) triggers should be at the start of the next frame. May try this to see how it does...

b) Make sure handling of VSYNC is fast... That is why I mentioned maybe have it's own interrupt.

c) not sure if there is something one might do with XBAR? That is it is an XBAR pin,
Looks like there are two IRQs associated with XBAR... But my guess is it is the same XBAR type mapping like using to trigger DMA from the PCLK...

@KurtE
Just did the merge - glad I waited on downloading your branch :)
 
@Paul - Taking a quick look through your FlexIO configuration and DMA. It is kooks like Greek to me :D

The first thing I wonder and may try. It looks like you are using Shifter 3?

Then I believe you need to use a different DMAMUX Source:
I believe you are using:
Code:
	dma_flexio.triggerAtHardwareEvent(DMAMUX_SOURCE_FLEXIO2_REQUEST0);
But I think you may need:
Code:
	dma_flexio.triggerAtHardwareEvent(DMAMUX_SOURCE_FLEXIO2_REQUEST3);

Note: There are only 2 DMAMUX sources per FlexIO1 and FlexIO2 and none for FlexIO3
Code:
#define DMAMUX_SOURCE_FLEXIO2_REQUEST0		1
#define DMAMUX_SOURCE_FLEXIO2_REQUEST1		1

#define DMAMUX_SOURCE_FLEXIO2_REQUEST2		65
#define DMAMUX_SOURCE_FLEXIO2_REQUEST3		65
The DMAMUX ones are shown in PDF page 56

Again not sure if that is it, but will be my first test.
 
Yup, that did the trick. I see where I went wrong. A silly mistake really. Sent a pull request to fix it.
:D looks like you beat me to it! :D

At times still wonder if we should cleanup something like it, sort of like DMAChannel such that sketches who just want to use something like an extra serial TX port can use it and not need to understand what other libraries or the like may be using some of the resources. Sort of dito for XBAR.
 
Yes, I believe your library tries to do the dynamic allocation of FlexIO resources, right?

The camera interface is a bit special through, because only shifters 3 & 7 support receiving parallel signals. The other 6 apparently can only be used with a single input pin. Only shifters 0 & 4 can transmit parallel. Details on page 2894 in the ref manual.

So far I've only been using a single shifter. AN12686 suggests using all 8 of them to capture 32 bytes at a time, which is probably more efficient, especially if using the DMA controller's special 32 byte transfer mode. But with the line having 324 bytes, it's not an integer multiple of anything more than 4 bytes. So even if only a single shifter works this time, a library to manage the resources would probably need an API to request parallel capable shifter resources.

I do like the idea of making your library or something very similar one of the default libraries. Ideally we could then make SoftwareSerial use it automatically, if the pins the user requests are FlexIO capable. Any ideas about adding an API for the camera to allocate parallel-capable resources in the way that can play nice with FlexIO SPI / I2C / Serial?
 
:D looks like you beat me to it! :D

At times still wonder if we should cleanup something like it, sort of like DMAChannel such that sketches who just want to use something like an extra serial TX port can use it and not need to understand what other libraries or the like may be using some of the resources. Sort of dito for XBAR.

Just downloaded and am getting an error message:
Code:
D:\Users\Merli\Documents\Arduino\libraries\TMM-HM01B0\src\HM01B0.cpp: In member function 'bool HM01B0::startReadFrameDMA(bool (*)(void*), uint8_t*, uint8_t*)':
D:\Users\Merli\Documents\Arduino\libraries\TMM-HM01B0\src\HM01B0.cpp:1363:3: error: '_save_IOMUXC_GPR_GPR27' was not declared in this scope
   _save_IOMUXC_GPR_GPR27 = IOMUXC_GPR_GPR27;  // save away the configuration before we change...

EDIT _ never mind - forgot I was compiling something for T4.1
 
@PaulStoffregen - @KurtE - @defragster
Ok finally got sorted out on my end (Past my bed time on the east coast) :)

Anyway just ran the updates using Sparkfun and non-Sparkfun configs at frameRate(30).

DMA single shot works no problem as well as FlexIO single shot.

DMA continuous fails as we already know, and FlexIO works in continuous very nicely. I combined my modified v2 sketch with Kurts to come up with a v3. Attached. Let me know if I missed anything.
 

Attachments

  • hm01b0_testv3.zip
    5.4 KB · Views: 81
@PaulStoffregen - @KurtE - @defragster
Ok finally got sorted out on my end (Past my bed time on the east coast) :)

Anyway just ran the updates using Sparkfun and non-Sparkfun configs at frameRate(30).

DMA single shot works no problem as well as FlexIO single shot.

DMA continuous fails as we already know, and FlexIO works in continuous very nicely. I combined my modified v2 sketch with Kurts to come up with a v3. Attached. Let me know if I missed anything.

That works well as far as tested since downloading @mjs513! Other sketches not so much fun and function.

Glad to see 'F' somewhere - had to turf my github again as the multi crossing pulls confused me and or the Github desktop!

NOTE: on the phone holder the ML+CAMERA are just over the NumPad/Mouse and it catches my had in the lower ~6th of the ILI9341 screen where my fingers are moving:
> I can see TEARING of the image in that lower part of the screen as the 'F' repeats?
So fast movie redraw anywhere of wiggling hand draw clean and smooth - but that lower part of the screen a wiggling hand doesn't have frame to frame continuity - but gets tears across some dozen lines a few lines up from the bottom - the bottom not perfect - but just above that the discontinuity is obvious.
> not sure if this is from the AsyncFrame data - or the FlexIO camera reading?
 
RE: p#421 :: Did some repeat 'f' frames while moving left hand up and down - right hand over numPad hitting Up&Enter to trigger 'f' in TyComm - oh look it is in Selfie/Mirror mode again with left hand on the left.

So this is a static draw of a single 'f' image from FlexIO - where only these bottom rows show this effect. In 'F' movie mode the aberrations are more drastic looking as the scan line is shifting @30 fps, but this shows it on Single Frame.
ProCam07.png
Took the pic of the ILI9341 with phone to record this image.

This is using p#420 code - one mode it to stop "F" with 'f' key and also turn AsyncUpdate(false) - SPARKFUN is OFF and display is 9341

<Edit>: Returned to repeat and now left hand is on the right in Camera not Selfie mode?

Also "F" was running some longer time and hitting "F" then 'f' causes a single bad/DARK shaded image and the T.MM was locked and needed a button press to allow Upload / Reset, i.e. USB was dead.
 
Adding 'z' key to save LAST frameBuffer[] unchanged not taking new image - again seeing Camera mode ( L/R reverse in image facing camera and display )

using 'f' : Not able to recreate the aberrations noted in p#421 & 422 when the display was showing in Selfie Mode. "F" does show those again those same bottom lines out of sync.

Something gets the camera Mode swapped - not seeing how that happens - and that bodes ill it seems ???

Noticed the LED backlight going brighter on the image during SD CARD write.

@KurtE :: Just got the "F" running 'f' to stop ... T.MM locked dead USB and BLUE T.mm light left on. Perhaps the issue is doing tft.useFrameBuffer(false); while tft.updateScreenAsync(); is in progress? If that is what happened it seems the code should prevent that?

Here is that sketch in case I don't make a more worthy update : View attachment hm01b0_testv3.ino
 
Back to running sketch and opps - did a 'z' during 'F' looking at the draw aberrations - and the Frank B Print Hardfaults #535 code gave this error:
Code:
Hardfault.
Return Address: 0x106A
	(IMPRECISERR) Data bus error but address not related to instruction
> On restart repeated 'F' and 'z' and the same fault occurred.
MORE INFO: "F" to start then "F" to stop, got a bad image to 'z' save. FlexIO was stopped, and image was completed { though still tft.useFrameBuffer(true); } and the above Fault 0x106A recurred and the file was opened ( zero size ) but not PC readable as it was not complete when Faulted.

So that was save_image_SD() write during an active tft.updateScreenAsync(); where frameBuffer[] is read but not written to transfer to img[]? Not sure why this would fault unless the DMA Screen Update conflicted with "Data bus error" write to this :: img = (unsigned char *)malloc(3*w*h);

<edit>: The Fault does not occur with 'c' then 'c' and 'z', but doing 'F' then 'F' ( and asyncUpdate(0) ) then 'z' still Faults???

NOTE: rather than Malloc for img[230400] I made a stack var and it is too large it seems Print Hardfault gives this handy message on Restart:
Code:
Hardfault.
Return Address: 0x104A
	(DACCVIOL) Data Access Violation
	(MMARVALID) Accessed Address: 0x20043342 (Stack problem)
	Check for stack overflows, array bounds, etc.
So indeed RAM1 is overallocated and caught at RUN not Compile time (because it is a stack var allocated based on RunTime screen size):
Code:
teensy_size: Memory Usage on Teensy MicroMod:
teensy_size:   FLASH: code:90208, data:15420, headers:7212   free for files:16402232
[B]teensy_size:    RAM1: code:98304 (85384 used), variables:275264   free for local variables:150720[/B]
teensy_size:    RAM2: variables:492640  free for malloc/new:31648

The FAULT DOES NOT HAPPEN with this define for img ???? Even if I hit 'z' DURING 'F'!
Code:
[B]DMAMEM unsigned char img[3 * 320*240];[/B]
That suggests the malloc is the problem? ODD since malloc is also DMAMEM/RAM2? But only after AsyncUpdate and FlexIO have been used.


None of the other recent USB Loss hangs have triggered that 'Print Hardfaults' - so they just hung the MCU, where this Faulted. That is a valuable difference to know Hang/Crash .vs. Fault.

Note: in bad code buff[] manipulations recently I have triggered other faults - That code is Very Handy having Faults Trapped and noted and MCU returns to running versus a blind hang. Unless something better is ready - looking forward to getting the Print Hardfaults PR#535 included in next beta.

Probably one more post with updated code as I didn't add 'z' to the help list, and I pulled a bogus name print in save_image_SD() ...
 
Last edited:
Back
Top