This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Image processing on DM642



Hi all, I'm trying to do some simple image processing using DM642 EVM. Starting from the examples given in the CD, I now have: 

while(1){/* loop forever */

   /* copy data from capture buffer to array to display buffer */

   for(i = 0; i < numLines; i++) {
      DAT_copy(capFrameBuf->frame.iFrm.y1 + i * capLinePitch, Array1, disLinePitch);
      /* IMG_thr_gt2max: pixels greater than threshold are set to 255 */
      IMG_thr_gt2max(Array1, Array2, cols, rows, threshold);
      DAT_copy(Array1, disFrameBuf->frame.rpFrm.buf + i * disLinePitch, disLinePitch);
   }

   FVID_exchange(capChan, &capFrameBuf);
   FVID_exchange(disChan, &disFrameBuf);
   frames ++;
}

What I'm trying to do is a thresholding procedure. The image from camera is stored in capFrameBuf and whatever in disFrameBuf is sent to the display. I introduced Array1 & Array2 (decalared as: unsigned char Array1[640 * 480], Array2[640 * 480];) to enable me to do some processing. The program compiles ok, but when I run it, nothing show up (the screen is blank). Can anyone help? Thanks. Hanief

  • Assuming you are working with L2 Cache enabled you may need to add in some cache invalidate/write-back calls to this code to ensure cache coherency. Whenever the EDMA copies new data into the external memory the cache is unaware of the updated data externally so a cache invalidate is necessary. You might want to try something like this:

    Hanief said:
    while(1){/* loop forever */

       /* copy data from capture buffer to array to display buffer */

       for(i = 0; i < numLines; i++) {
          DAT_copy(capFrameBuf->frame.iFrm.y1 + i * capLinePitch, Array1, disLinePitch);
          CACHE_wbInvAllL2(CACHE_WAIT);
          /* IMG_thr_gt2max: pixels greater than threshold are set to 255 */
          IMG_thr_gt2max(Array1, Array2, cols, rows, threshold); 
          CACHE_wbInvAllL2(CACHE_WAIT);
          DAT_copy(Array1, disFrameBuf->frame.rpFrm.buf + i * disLinePitch, disLinePitch); 
       }

       FVID_exchange(capChan, &capFrameBuf);
       FVID_exchange(disChan, &disFrameBuf);
       frames ++;
    }


    This should help ensure that what is located in your external memory matches what is stored inside the L2 cache.

  • Hi TimHarron,
    Unfortunately that doesn't seem to work, or do anything different for that matter. I forgot to mention yesterday that the program (both original & modified) runs for only a few seconds. It then halts with the message: s/w breakpoint. Another thing is that, sometimes, when I load my program to the EVM, I get these messages (or something similar):

    Trouble Removing Breakpoint with the Action "Process CIO" at 0x810182e0: Error 0x00000008/-1066 Error during: Break Point, Cannot set/verify breakpoint at 0x810182E0
    Trouble Removing Breakpoint with the Action "Terminate Program Execution" at 0x81019740: Error 0x00000008/-1066 Error during: Break Point, Cannot set/verify breakpoint at 0x81019740

    It doesn't happen every time though. Would that shed more light for you?
    Thanks. Hanief
    p/s: Err.. do I have to manually add HTML tags?
  • As it is crashing like this, it could be that your stack or heap sizes are too small, particularly if you are allocating additional large arrays beyond what the driver is allocating. I would make sure that the arrays you are processing are declared as global so they can be statically allocated, if they are local they would be placed on the stack which would be enough to overflow the stack if left at the default value, alternatively you could increase the size of the stack though for these relatively large buffers it is better practice to just declare them globally (more efficient and less chance of stack issues).

  • I agree with Bernie -- it sounds like your software is not stable.  The stack is a common cause of these problems and a good place to look is the DSP/BIOS Kernel Object Viewer (under the DSP/BIOS menu in CCS).  It allows you to see the system stack and how much has been used as well as the individual task stacks and their respective usage.

  • Hi guys
    I tried declaring the arrays as global as suggested. It works in that I can see the thresholding is taking place. It also doesn't halt prematurely. However, it is very slow. Maybe 2, 3 seconds lag. Why is that?

    I also looked at the DSP/BIOS Kernel Object Viewer as suggested. I see 'KNL Stack Full' and 'SDRAM Memory Heap Full', so that must be the problem. How do I increase the size of the stacks?

    Thanks
    Hanief

  • I am glad to hear that making the arrays global fixed the crashing issue. As to being slow do you mean just the lag as in a delay/latency from the video input to the video output or do you mean that you are dropping frames? In either case it is possible that you are reaching performance limits of the device, you can probably improve performance a bit by organizing your memory map such that code and data that is accessed most often is stored internally, though since these buffers do not fit in internal memory there will always be a bit of slowdown as the current data being worked on is cached. As to the latency I would expect some due to the buffering being done in the drivers as well as perhaps some latency added by the processing buffering, though this should only be a matter of a few frame delays, a fraction of a second. If the delay is more than a second than you may want to look at your buffering scheme and see if it can be modified to improve the latency (such as avoiding unnecessary data copies).

    The stack and heap sizes can be set within your DSP/BIOS configuration file (cdb or tcf depending on your version), there are controls within the memory section manager for this.

  • Make sure the cache is enabled.  This article was written for 64x+ though the procedure is nearly identical when configuring through BIOS:

    http://wiki.davincidsp.com/index.php?title=Enabling_64x%2B_Cache

    Once cache is properly configured then you will need to concern yourself with cache coherence.  This article describes that process:

    http://wiki.davincidsp.com/index.php?title=Cache_Management

    Brad

  • By slow I mean that when I put my hand in front of the camera, there is a 2,3-second delay before it is displayed. And I guess there are also lost frames, as my hand seems to 'magically' appear in front of the camera. I hope I'm not reaching the performance limit of the DM642, this is just (relatively) simple image processing. I have never work with a DSP/BIOS configuration file before, so I have to do some reading before I can tinker with it. Btw, I seem to have both the video.cdb & video.tcf in my project, how do I tell which one is being used?

    As for the cache, I'll also have to read up on that. I hope I can find something more specific in spru610 & spru656 in addition to those articles.

    Thanks.
    Hanief

  • I think something must fundamentally be misconfigured based on the poor performance you are reporting.  I recommend checking the tcf to make sure the proper MAR bits are set as discussed in the wiki article I pointed you to before.

    Ignore the cdb file.  It's auto-generated based on your tcf.  You should include the tcf file in your project and all your changes should be on the tcf not the cdb.

    Brad

  • To dig into the performance issue a bit more you may want to try out some of the profiling capabilities of CCS, there are tutorials under the help meny to get you started with the profiler, it should help to tell you where your code is spending the most time to narrow down why it is going so slowly. Additionally BIOS also offers tools to measure performance such as the statistics view under the BIOS menu of CCS, this can give you performance information at a task level.

  • I'm using the tcf file as supplied, so I don't know if something is fundamentally misconfigured. I haven't made any changes to it, until now that is. Anyway, the only tab configurable in the Global Settings is 641x. I believe the cache is enabled. I tried playing around with the MAR bits, specifically MAR128-142, as it controls the EMIFA CE0 space (SDRAM), but there doesn't seem to be any difference. Am I doing it right?

    As for stack and heap sizes, the only thing I can find in MEM are "argument buffer size" and "stack size (MAUs)". Is that what you are referring to. Fyi, the default values are 0x0004 and 0x1000 respectively

    I haven't tried profiling yet. I guess that's next.

    Thanks,
    Hanief

  • If you've set the MAR bits and enabled the cache inside the Global Settings area then it should be turned on (assuming there is not code somewhere turning it back off!).  Another "big one" to check is your compiler settings.  Make sure the optimizer is turned on.

    Brad

  • It sounds like you are set for the MAR bits, they determine what external memory is cachable.

    For the stack size you found that already, but the heap size is specific to each memory region you have defined in your BIOS configuration file (you can have multiple heaps with BIOS). For example see the attached screen shot.

  • I tried all Opt Level (-o0 to -o3), but again there doesn't seem to be any difference.

    As for the stack size and heap size, I tried several values. There's some improvement in that with certain values, it doesn't halt prematurely. However, it still displays nothing. The "Trouble Removing Breakpoint" messages are also still there, along with "Trouble Setting Breakpoint".

    Thanks
    Hanief

  • Send your tcf to support@ti.com so we can have a look.  If changing the optimization level in the compiler didn't help then it sounds like perhaps you still have an issue with the cache/MAR settings.

  • For the purposes of this discussion it may be easier to post the content of your TCF file in the thread (it is just text after all). The TI support system is regionalized, so if you emailed in your TCF file to support@ti.com (I normally suggest http://support.ti.com to speed the process) it would end up being routed to your local support group which may not be aware of this thread.

  • environment["ti.bios.oldMemoryNames"] = true;

    /* loading the generic platform */
    var params = {};
    params.clockRate = 720.000000;
    params.deviceName = "DM642";
    params.catalogName = "ti.catalog.c6000";
    params.regs = {};
    params.regs.l2Mode = "4-way cache (0k)";
    utils.loadPlatform("ti.platforms.generic", params);

    /* enabling DSP/BIOS components */
    bios.GBL.ENABLEINST = true;
    bios.MEM.NOMEMORYHEAPS = false;
    bios.RTDX.ENABLERTDX = true;
    bios.HST.HOSTLINKTYPE = "RTDX";
    bios.TSK.ENABLETSK = true;
    bios.GBL.ENABLEALLTRC = true;
    bios.GBL.ENDIANMODE = "little";
    bios.GBL.C641XCONFIGUREL2 = true;
    bios.ISRAM.createHeap = true;
    bios.ISRAM.heapSize = 0x8000;
    bios.MEM.BIOSOBJSEG = prog.get("ISRAM");
    bios.MEM.MALLOCSEG = prog.get("ISRAM");
    bios.TSK.STACKSEG = prog.get("ISRAM");

    /* applying user changes */
    bios.SDRAM = bios.MEM.create("SDRAM");
    bios.SDRAM.comment = "This object defines space for the DSP's off-chip memory";
    bios.SDRAM.base = 0x80000000;
    bios.SDRAM.len = 0x2000000;
    bios.SDRAM.heapSize = 0x1000000;
    bios.SDRAM.enableHeapLabel = 1;
    bios.SDRAM.heapLabel = prog.extern("EXTERNALHEAP");
    bios.SDRAM.space = "code/data";
    bios.tskLoopback = bios.TSK.create("tskLoopback");
    bios.trace = bios.LOG.create("trace");
    bios.VP0CAPTURE = bios.UDEV.create("VP0CAPTURE");
    bios.VP1CAPTURE = bios.UDEV.create("VP1CAPTURE");
    bios.VP2DISPLAY = bios.UDEV.create("VP2DISPLAY");
    bios.RTA_fromHost.bufSeg = prog.get("SDRAM");
    bios.RTA_toHost.bufSeg = prog.get("SDRAM");
    bios.TSK_idle.stackMemSeg = prog.get("SDRAM");
    bios.LOG_system.bufSeg = prog.get("SDRAM");
    bios.LOG_system.bufLen = 0x400;
    bios.MEM.ARGSSEG = prog.get("SDRAM");
    bios.MEM.BIOSSEG = prog.get("SDRAM");
    bios.MEM.STACKSIZE = 0x1000;
    bios.MEM.STACKSEG = prog.get("SDRAM");
    bios.MEM.SYSINITSEG = prog.get("SDRAM");
    bios.MEM.GBLINITSEG = prog.get("SDRAM");
    bios.MEM.TRCDATASEG = prog.get("SDRAM");
    bios.MEM.SYSDATASEG = prog.get("SDRAM");
    bios.MEM.OBJSEG = prog.get("SDRAM");
    bios.MEM.BIOSOBJSEG = prog.get("SDRAM");
    bios.MEM.MALLOCSEG = prog.get("SDRAM");
    bios.MEM.TEXTSEG = prog.get("SDRAM");
    bios.MEM.SWITCHSEG = prog.get("SDRAM");
    bios.MEM.BSSSEG = prog.get("SDRAM");
    bios.MEM.FARSEG = prog.get("SDRAM");
    bios.MEM.CINITSEG = prog.get("SDRAM");
    bios.MEM.PINITSEG = prog.get("SDRAM");
    bios.MEM.CONSTSEG = prog.get("SDRAM");
    bios.MEM.DATASEG = prog.get("SDRAM");
    bios.MEM.CIOSEG = prog.get("SDRAM");
    bios.MEM.SYSMEMSEG = prog.get("SDRAM");
    bios.MEM.HWISEG = prog.get("SDRAM");
    bios.MEM.HWIVECSEG = prog.get("SDRAM");
    bios.MEM.RTDXTEXTSEG = prog.get("SDRAM");
    bios.GBL.CALLUSERINITFXN = 1;
    bios.BUF.OBJMEMSEG = prog.get("SDRAM");
    bios.PRD.OBJMEMSEG = prog.get("SDRAM");
    bios.HST.OBJMEMSEG = prog.get("SDRAM");
    bios.TSK.OBJMEMSEG = prog.get("SDRAM");
    bios.TSK.STACKSEG = prog.get("SDRAM");
    bios.tskLoopback.comment = "Loopback Task";
    bios.tskLoopback.fxn = prog.extern("tskVideoLoopback");
    bios.tskLoopback.stackMemSeg = prog.get("SDRAM");
    bios.IDL.OBJMEMSEG = prog.get("SDRAM");
    bios.LOG.OBJMEMSEG = prog.get("SDRAM");
    bios.trace.bufSeg = prog.get("SDRAM");
    bios.trace.bufLen = 0x400;
    bios.PIP.OBJMEMSEG = prog.get("SDRAM");
    bios.SEM.OBJMEMSEG = prog.get("SDRAM");
    bios.MBX.OBJMEMSEG = prog.get("SDRAM");
    bios.QUE.OBJMEMSEG = prog.get("SDRAM");
    bios.LCK.OBJMEMSEG = prog.get("SDRAM");
    bios.SIO.OBJMEMSEG = prog.get("SDRAM");
    bios.STS.OBJMEMSEG = prog.get("SDRAM");
    bios.SYS.TRACESEG = prog.get("SDRAM");
    bios.GIO.ENABLEGIO = 1;
    bios.VP0CAPTURE.fxnTable = prog.extern("VPORTCAP_Fxns");
    bios.VP0CAPTURE.fxnTableType = "IOM_Fxns";
    bios.VP0CAPTURE.params = prog.extern("EVMDM642_vCapParamsPort");
    bios.VP1CAPTURE.fxnTable = prog.extern("VPORTCAP_Fxns");
    bios.VP1CAPTURE.fxnTableType = "IOM_Fxns";
    bios.VP1CAPTURE.deviceId = 1;
    bios.VP1CAPTURE.params = prog.extern("EVMDM642_vCapParamsPort");
    bios.VP2DISPLAY.fxnTable = prog.extern("VPORTDIS_Fxns");
    bios.VP2DISPLAY.fxnTableType = "IOM_Fxns";
    bios.VP2DISPLAY.deviceId = 0x2;
    bios.VP2DISPLAY.params = prog.extern("EVMDM642_vDisParamsPort");
    bios.DHL.OBJMEMSEG = prog.get("SDRAM");
    bios.DIO.OBJMEMSEG = prog.get("SDRAM");
    bios.GBL.USERINITFXN = prog.extern("EVMDM642_init");
    bios.CLK.OBJMEMSEG = prog.get("SDRAM");
    bios.RTDX.RTDXDATASEG = prog.get("SDRAM");
    bios.SWI.OBJMEMSEG = prog.get("SDRAM");
    bios.ISRAM.len = 0x20000;
    bios.ISRAM.createHeap = 0;
    bios.GBL.C641XCCFGL2MODE = "4-way cache (32k)";
    bios.GBL.C641XCCFGL2MODE = "4-way cache (256k)";
    bios.GBL.C641XCCFGL2MODE = "4-way cache (128k)";
    bios.GBL.C641XMARCE0 = 0x000f;
    bios.GBL.C641XMARCE0 = 0x0f00;
    bios.GBL.C641XCONFIGUREL2 = 1;
    bios.GBL.C641XCCFGL2MODE = "4-way cache (0k)";
    bios.GBL.C641XMARCE0 = 0xf000;
    bios.GBL.C641XMARCE0 = 0x000f;
    bios.GBL.C641XCCFGL2MODE = "4-way cache (128k)";
    bios.MEM.instance("SDRAM").heapSize = 0x02000000;
    bios.MEM.instance("SDRAM").len = 0x01000000;
    bios.MEM.instance("SDRAM").heapSize = 0x01000000;
    bios.MEM.instance("SDRAM").len = 0x02000000;
    bios.MEM.instance("SDRAM").heapSize = 0x01100000;
    bios.MEM.instance("SDRAM").heapSize = 0x01000000;
    bios.MEM.STACKSIZE = 0x2000;
    bios.MEM.STACKSIZE = 0x3000;
    bios.MEM.STACKSIZE = 0x4000;
    bios.MEM.STACKSIZE = 0x3000;
    bios.MEM.instance("SDRAM").heapSize = 0x01100000;

    // !GRAPHICAL_CONFIG_TOOL_SCRIPT_INSERT_POINT!
    if (config.hasReportedError == false) {
    prog.gen();
    }
  • First off I suggest taking a second look at the MAR registers. Looking through the history of your changes I see you flipping on different MAR bits seemingly at random. Note that each of these bits will enable cache for specific memory ranges - see pages 10-11 of the device datasheet.

    Make sure the correct MAR register(s) are activated for the important memory ranges.

    *edit* For example, if you are using CE0 and wish to cache 32MB of external memory both MAR128 and MAR129 must be set. (bios.GBL.C641XMARCE0 = 0x0003;).

  • Oh, I didn't realize that tcf stores previous changes to itself. As I've said before, the board is using CE0 for SDRAM, and is thus my focus. I don't quite get why 0x0003 equals setting MAR128 & 129 though. The datasheet doesn't make it clear. So if I want to cache half the SDRAM i.e. 128M, how do I translate that to MAR bits?

  • Hanief said:
    Oh, I didn't realize that tcf stores previous changes to itself. As I've said before, the board is using CE0 for SDRAM, and is thus my focus. I don't quite get why 0x0003 equals setting MAR128 & 129 though. The datasheet doesn't make it clear. So if I want to cache half the SDRAM i.e. 128M, how do I translate that to MAR bits?


    I mentioned where you can find this in my other post (datasheet pages 10-11). Each MAR register uses a single bit to turn a range on or off, and that range for each is covered in this chart.

    MAR128 covers 0x80000000 - 0x80FFFFFF and MAR129 covers 0x81000000 - 0x81FFFFFF which, combined, covers the first 32MB of CE0.

  • Ok, if you can check whether I get it correctly, 128MB requires MAR128 - MAR 135. So that means bios.GBL.C641XMARCE0 = 0x00ff, right? Well, the result is still the same as before. It doesn't halt prematurely, but it still displays nothing. "Trouble Removing Breakpoint" & "Trouble Setting Breakpoint" messages are also still there

    Thanks,
    Hanief

  • Hanief said:
    Ok, if you can check whether I get it correctly, 128MB requires MAR128 - MAR 135. So that means bios.GBL.C641XMARCE0 = 0x00ff, right?

    Yes, this is correct.

    Hanief said:
    Well, the result is still the same as before. It doesn't halt prematurely, but it still displays nothing. "Trouble Removing Breakpoint" & "Trouble Setting Breakpoint" messages are also still there
    This behavior sounds like at some point the CPU begins running invalid code and trashes the system. If you are able to load the program and start stepping through see if you can step through all of the initialization properly and find where the code starts causing those messages.

  • Sorry for the 'late reply'. I just realized that my post the other day didn't get through.

    Anyway, I can only do Assembly-Single Step. Not much help to me (I can't really read assembly codes). The other buttons are greyed out.

    Hanief