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.

Code runs fine in SARAM, but not in Flash

Other Parts Discussed in Thread: TMS320F28335

I spent a couple of weeks troubleshooting my algorithm on a TMS320F28335 using CCS v6.1.  I'm a seasoned analog engineer who is new to programming, digital control, etc. but I found CCS an intuitive environment where troubleshooting went surprisingly smoothly.

We're supposed to ship in two days (actually ON TIME), but now that I try and load the code into Flash, it doesn't work properly.  I get the "I'm erasing flash"  and "I'm loading" messages when I load the code by selecting Debug, but when I reset the power to my control board, the code doesn't operate quite right.  The little hearbeat LED on the board blinks at 2Hz, so the timer interrupt is functioning at the right frequency.  When I hit the ON button for the system it locks up in the turn on mode and doesn't proceed to the next mode.  The heartbeat LED blinks at 2Hz, but nothing else happens.  I can hit my OFF button and the system will go to off.

 My limited understanding of the digital control world is based on the TMS320F28335 tutorial available on CD ROM that's broken up into 19 chapter or "modules".  Chapter 14 provides details for loading the code into Flash.  It essentially tells you to add these lines in main after the InitSysCtrl() function call:

memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, &RamfuncsLoadEnd - &RamfuncsLoadStart);

InitFlash(); // call InitFlash in RAM (SARAM - L0)

Also, declare the symbols used in memcpy() before main

extern unsigned int RamfuncsLoadStart;
extern unsigned int RamfuncsLoadEnd;
extern unsigned int RamfuncsRunStart;

Obviously, include a function prototype for InitFlash().

Also, exclude the 28335_RAM_lnk.cmd from the build and instead include F28335.cmd.  In the Project -> Properties -> Debug -> F28335 Flash Settings, I set the OSCCLK to 20 since I'm using a 20 MHz crystal.  After I complete the build, everything in the .map file is exactly what they describe in chapter 14 of the tutorial.

Since the tutorial is based on CCS 4, there may be some instructions for CCS v6.1 that have been left out.

Please, please do not tell me to read SPRA958L.  I'm reading it now and it's not helping me much.  Please let me know if you can help.

Thanks,

Tom

  • Hi Tom,

    Can you check the BOOT MODE pin setting on the board. These pins should be set to "Jump to Flash" as mentioned in table below.

    Regards,

    Vivek Singh

  • Look like the table I was referring in last post did not get attached properly.

    Following is the table, I was referring.

    Regards,

    Vivek Singh

  • Yes. These 4 inputs are pulled high via resistors at all times.
  • Vivek,

    The code will run in stand alone mode with the debugger connected. So while troubleshooting, I noticed that one of my A to D values reads 0 when it is not 0. The other 6 values are correct. While triggering the scope all of a sudden I noticed that the A to D values were all correct and the code was operating properly. This has now happened with 2 different control boards so it is most likely not a hardware issue.

    Any thoughts?
  • Hi Tom,

    I'll have our ADC expert look into your query related to A to D values.

    Regards,

    Vivek Singh

  • Thanks Vivek. Please let your ADC guy know a couple of things.

    The A to D value that I kept getting the incorrect result was the 7th conversion in a cascade of 7. It is also the only input that does't come from an OP AMP buffer with a 1K resistor in series with it and a 47pF capacitor right next to the analog input pin. The analog input with the error is connected to the wiper of an on board pot. This input has a .1uF capacitor across it located about 1" from the analog input pin.

    I actually just got it to run in stand alone mode when I changed ACQ_PS from 7 to 15. I felt pretty good until I changed ACQ_PS to 1, expecting it to not work, but it worked. So now, regardless of the value of ACQ_PS, it works.

    Perhaps I changed something else that I'm not recalling. I would appreciate it if you still run this issue by the ADC expert, maybe he'll have some insight.

    BTW. I did change the cap across the A to D with the problem from .1uF to 47pF, but that didn't seem to help until I started playing with ACQ_PS.
  • Hi Tom,

    I don't think the external circuitry is the problem; if the cap is too far away, too large or small, or the resistance is too high for a given ACQPS setting, then the previous signal will bleed into the current signal. This is very unlikely to force the conversion result to 0.

    How many times does the 0 appear? For a given run of the code, is it always 0 measured multiple times, 0 one time (but you didn't or can't check subsequent conversions), or only 0 every once in awhile even for the same run of the code?

    If it is intermittent in the same run, this suggests a variable timing error with the code. There may be some jitter in a calculation or ISR that causes the ADC to never reach the read to the last ADC result, but only sometimes.

    Something similar, but code build-to-build, could also suggest that you are running out of time somewhere. Slightly adjusting the code and then re-building could put you over/under the limit. You could try adding no-ops to some of the critical code sections to see if you can push it over the edge consistently.

    Overall it is pretty hard to say what the issue is if you can't reproduce it consistently. If you can get a clear set of cases where it works/doesn't work we will probably have a better chance of drilling right down to the issue.
  • Devin,

    Thanks for the response.  I didn't have a lot of hope that changing the cap would help since the problem wasn't really intermittent and the ADC input was from an on board pot.  When the problem occurred, it happened at startup and the seventh A to D input out of seven in the sequence remained at 0 for several minutes until it started reading the correct value.  The problem did not seem to always fix itself, but when it did it ran correctly for several more minutes.

    After playing with the ACQPS value it works every time (at least 50 in a row), but I don't understand why.  I'm not an experienced "coder" so I don't understand what you mean when you say "you are running out of time. You could try adding no-ops to some of the critical code sections to see if you can push it over the edge consistently."  Does this mean that the A to D only performs the 6 conversions and then is inadvertently forced to do something else?  I'll read through the ADC information again and hopefully I'll see something.

    As I troubleshoot my code I have to remind myself that when I see hoof prints that I need to look for horses and not zebras.  To this point it has been horses, but since this issue never occurred when the code ran in SARAM, only when it was loaded in flash, I fear the solution may require a more thorough understanding than I currently have.  The code runs now, but I really don't think I've seen the last of this issue.

  • Hi Tom,

    Could you please post the linker flags? (Properties --> Build --> C2000 Linker --> Summary of flags set:)

    Thanks,
    Janos
  • Hi Tom,

    The ADC HW should always finish its conversions and put something into the result registers, unless it is forcibly issued a sequencer reset command or the whole module is reset. I was thinking more along the lines of the ADC ISR/sample collection code getting starved by a higher priority interrupt - the code runs, but gets preempted periodically before the final conversion result can be read.

    How are you observing the ADC output when running from flash? Are you still connected via JTAG, or are you scanning data out via some interface (e.g. SCI)? If JTAG, it would be interesting to see if the ADCRESULT register is 0 compared with wherever you are recording and using the ADC data. If a comms interface, you could try alternating between sending out the recorded data, vs copying the data to be sent from the ADCRESULT register directly.
  • Sure.  Here they are:

    -v28 -ml -mt --float_support=fpu32 -g --diag_warning=225 --display_error_number --diag_wrap=off -z -m"UAS_HBridge.map" --stack_size=0x400 --warn_sections -i"C:/ti/ccsv6/tools/compiler/ti-cgt-c2000_6.4.3/lib" -i"C:/ti/ccsv6/tools/compiler/ti-cgt-c2000_6.4.3/include" --reread_libs --display_error_number --diag_wrap=off --xml_link_info="UAS_HBridge_linkInfo.xml" --rom_model

    I would certainly appreciate a brief explanation.

  • Well, you might have accidentally switched the linker to RAM model (the debugger initializes the RAM instead of code in flash) which can cause weird errors. It was at best a long shot, since doing this by mistake would be weird itself. This setting is pretty deep in the menu. You are using ROM model indicated by the --rom_model flag.

    Too small stack size (--stack_size=) can also be an issue, since the RAM and the Flash linker script might place the stack at different locations. You are not guaranteed to notice a stack overflow if the memory map is laid out in a certain way. A stack overflow can easily cause the program to behave exactly like you described in your first post.

    There is a way to find the problematic code in your project:

    1. At the beginning of the main func you copy almost everything in RAM. This should be possible since you developed the whole app in RAM, so it should fit in nicely. The necessary framework is already in place for the ramfuncs section. After this step, the code should run just like before, the only difference being the init is done by your code and not by the debugger.
    2. Function by function (or lib by lib) you place things back in flash and wait for things to go south. This should narrow it down where to look for the bug.

    If you send me the two linker scripts and your map file I can help you with the above procedure.

    BR,

    Janos

  • Closing the thread. If your issue is not resolved please reopen the same or start a new post.