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.

Porting FreeRTOS to OMAP-L138 - ARM9 CCS4 debug

Other Parts Discussed in Thread: OMAP-L138, OMAP-L137, OMAPL138

First of all: our product code will be using FreeRTOS, not ***ux.  Before that happens, we need to verify
that our CCS4 development environment works reliably.

We are trying to bring up the L138 Experimenter's kit to execute the I2C LED test code on the ARM9 core.

The example for flashing the I2C0 LEDs using the DSP works without problem, every time.

We do have an XDS100v2 emulator, and the ARM code downloads and runs to main repeatedly with no problem.
DIP switches are set to Emulator boot.

The problem arises when writing the i2C0 data byte to the peripheral register.   About 95%  of the time, the
I2C transmit status register stays busy, and the test application fails.  The frustration comes from the 5% of
iterations that work, and NOT repeatably.

While I am suspicious of the Emulation Suspend implementation for the I2C,  I'm also purely speculating that there may be
DSP interference with this as well.

If someone could provide direction on how to boot from bare metal into ARM9 code, with the DSP under control, such that
we can reliably debug peripheral driver code,  I'd be very grateful.   Obviously, the L___x platform does so, but I have not seen
any information on how to duplcate that. If someone has done a FreeRTOS port to L138 ARM, and is willing to share,
that would be fantastic.  If it's a matter of RTFM, and someone can point to T appropriate FM, that's helpful too.

-- TIA - Regards,
Joe Curren

 

  • Check out this wiki page for info and test code on how to boot an image using the ARM to flash the LEDs. The DSP remains asleep the entire time:

    http://processors.wiki.ti.com/index.php/Boot_Images_for_OMAP-L138

    Jeff

  • Joe,

    When the ARM boots from its ROM, it disables the DSP.  Unless your application code is waking the DSP again, it should not be able to interfere with anything.

    -Tommy

  • Tommy- thanks for the info; that's what I'd hoped.  So it must be something specifically in the access to the I2C peripheral regs that is *different* between the DSP and the ARM builds of the test app.  I'll look at Jeff's suggestion on using AIS to make a bootable flash image of the code, and not pursue the DSP angle.

     

  • Joe,

    A good reference manual for ARM 9 code is located here: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0100i/index.html

    "While I am suspicious of the Emulation Suspend implementation for the I2C,  I'm also purely speculating that there may be
    DSP interference with this as well."

    If the Emulation Suspend register does not appear to be modified to ARM for the I2C peripheral, this may be due to the current mode of the ARM. You can verify the the current mode of the ARM by viewing the CPSR register in the "Core Registers". If 'M' is set to 0x10, you will not be able to modify the SYSCFG registers.

    - Kevin

  • Thanks for the pointer, Jeff:  I'll give this a try immediately. 
    That prompts the question, though:  If the "LEDs will not flash when the ARM application file is loaded through CCS", does that mean CCS debugging of other peripherals won't work?   I'm struggling to get my head around the interdependencies of boot layers, and who has control at what point, and where the emulator has visibiility/ control of what's executing.  If ARM access to peripherals can only be done with the presence of AIS at boot time, does that imply a build/burn/hope-it-works development cycle?
    I'd rather not go back to 1988....!

    Edit:
    After checking the code, Obvious: The code in the example, as stated in the wiki, doesn't do pinmux.  Without AIS, of course the LEDs won't blink.  Not back in 1988 yet.

  • Kevin-- Thanks for the ARM ref link: will take a look at possible snags there, and verify CPSR M field when the reg access takes place.

  • Have you tried this?

    http://e2e.ti.com/support/dsp/omap_applications_processors/f/42/p/29869/151582.aspx#151582

  • Sorry the wiki was not clear on that point. Ive added some text to make it clear that it is only in this example that the AIS sets up the pinmux. The reason for this is that the code must be run in supervisor mode in order to change the pinmux settings, and the code to enter this mode was more complex than the project itself.

    Jeff

  • Jeff -- Actually, I was being facetious, but thanks for clarifying that point.

    ======================================================================================

    I'm back on the DSP angle again: from 'Using the OMAP-L1x8 Bootloader' (sprab41c):

    The emulation debug boot powers on the device, but does not load or execute any application code.
    Instead, the ARM falls into an idle loop immediately after the device powers on. An emulation connection
    (i.e., JTAG) must then be established to load program data or perform any other operations.
    The bootloader powers the DSP on before idling the ARM. This allows emulators to connect to the DSP
    core immediately after boot as well.
    ....
    _____________________________________

    ... and from http://processors.wiki.ti.com/index.php/GSG:_OMAP-L138_DVEVM_Additional_Procedures#Flashing_images

    in the section:
    DA850/OMAP-L138/AM18xx
    On the OMAP-L138 (or AM18xx) SoC, the ARM boots first. On boot-up, the ARM runs the ARM UBL in AIS file format. The purpose of the ARM UBL is to initialize the PLLs, mDDR, and other hardware. Once done, it copies the U-Boot into mDDR and starts it.
    ......
    ___________________________________

    Then, in section
    DA830/OMAP-L137
    On the OMAP-L137 and DA830 SoCs, the DSP boots first, on boot-up, the DSP runs the DSP UBL in AIS file format. The purpose of the DSP UBL is to wake up the ARM and start the ARM UBL which is present in raw binary form. The purpose of the ARM UBL is to initialize the PLLs, SDRAM, and other hardware.
    ..............
    ____________________________________

    I still do not have a clear picture of what happens between release of hardware reset and the entry to main().
    A graphic representation of the dependencies and branches would be very helpful at this point.
    Essentially, we don't even have the hardware equivalent of 'hello world'  operating.

    I have intentionally obscured references to L__x, because I do not want to hear things like
    "
     But I have never heard of anyone using OMAPL138 without running Linux on the ARM.  While I don't know, I just want to point out the possibility that you have stumbled into a unsupported combination".

    If there is something magical in the L___x HAL that  permits its device drivers to work,
    as in example
    http://e2e.ti.com/support/dsp/omap_applications_processors/f/42/p/29281/127959.aspx#127959
    that would be very useful to we poor saps who want to work from bare metal.
    A port of that example to bare metal, that can be loaded through emulation boot (with a GEL, if possible, to perform the ugly initialization to which Jeff is referring)
    would save many hours of fruitless hacking.

    /Rant

    Truly, thanks for all of your comments and suggestions: this is a complex device, and all input is appreciated.


    [Edit]

    Post-Facto:  No magic:  The HAL is simply built to execute in Supervisor mode.

     

  • Thanks Sergey -- That is probably the best bare-metal demo app for us to try:  I'd put off testing that code until more basic stuff was verified, but that might actually be the best test code available.  Good suggestion, will give it a shot.

  • Joe,

    As Jeff pointed out, the pin multiplexing cannot be accomplished unless the ARM is in a priviledged mode. The document that I previously referred you to contains details on the different ARM modes (see page 41).

    In SPNU151E (ARM Optimizing Compiler v4.6), you will read in Section 4.4.2 - (Run-Time Init) that the _c_int00 function puts the ARM in "user" mode. Thus, you will have to call a software interrupt _call_swi() and switch to a priviledged mode (system mode would work best if using the RTS library). You will also have to add the necessary code to set up the additional stacks you will need. Then, you should be able to modify the Emulation Suspend register as desired.

    - Kevin

  • Joe,

    Another solution is to modify the SUSPSRC directly in your GEL file to assign the I2C0 peripheral to the ARM.

    You can do this with the following code:

    Define this value at the top of your GEL file.
    #define SYSCFG_SUSPSRC *(unsigned int*)(0x01C14170)

    Add this line of code to one of your GEL functions to modify I2C to ARM.
    SYSCFG_SUSPSRC &= 0xFFFEFFFF;

    Hope this helps.

    -Kevin

     

  • Man, this is an eye opener.   My paradigm has been from MCU development, where supervisor mode is the default, and tasks are relegated to user mode if your architecture uses an OS.   As an application processor, there is an implicit assumption of an existing OS (L___x, e.g.) for which developers build applications. 
    Hardware manipulation is through OS calls, which employ driver code and supervisor mode HAL access to registers. 
    Thanks to Jeff and Kevin for getting this through my density in recognizing this.

    At startup in main, yes, the CPSR is showing User mode.  Of course the I2C0 writes won't work.
    Simply going through the emulator, at the entry to main(), and setting two bits (for Supervisor mode (M= 0x13),  the test application works perfectly.

    The $64 question:  is there a runtime available that does NOT set user mode after init?  CCS4 provides a RAM and ROM init, but I'm not sure where (or if) the source is.

    [Edit]
    Thanks for the SYSCFG_SUSPSRC suggestion Kevin, but I think I'm looking for the sledgehammer:  to at least start devt in Supervisor mode.  To answer the next question, we have several aspects that require microsecond timing, so building the system for L__x and its limited timing resolution is not an option.   Now, if someone is willing to share a kernel that coordinates a high-res timer with the kernel scheduler, I'm all ears.

  • SOLUTION:
    1.  Extract boot.asm from source, located at workstation CCS4 directory    ProgramFiles\TI\ccsv4\tools\compiler\TMS470\lib\rtssrc.zip.
    2.  This contains _c_int00.  Change the line with comment  ; SET USER MODE to use 0x13, not 0x10.
    3.  Add this file to CCS4 project.
    4.  Clean/Build.
    5.  Connect and download.   Entry to main() is now at M= 0x13.
    6.  Application can manipulate hardware as needed.


    Thanks to all for your suggestions: you all got me thinking in the right direction.  Onward!

     

  • Joe,

    Glad the inputs helped.  Thanks for sharing your solution.  I'm sure that others will also put it to good use!

    -Tommy

  • Joe,

    Thanks so much for helping clarify this. TI's lack of comprehensive documentation continues to confound me...

    I have successfully manually changed the value of CPSR.M when stopped at main(), then running the demo successfully. However, when I try to follow your "SOLUTION" above, the value of CPSR.M is still equal to 0x10 when I start my debug session. Perhaps I am not following your instructions correctly. Could you elaboarte a bit on "Add this file to CCS4 project".

    FYI, I have successfully extracted boot.asm from rtssrc.zip, modified SET USER MODE to 0x13, saved the modified boot.asm file, then added it (boot.asm) to my project folder. After a clean build, then starting a new debug session, halting at main() and reading the value of CPSR.M, the value is still 0x10 and the demo fails as before. Perhaps I have not fully understood what you mean by "Add this file to CCS4 project"...?

    Again, thanks for your help.

    MikeH

     

  • Mike--

    I just copied the extracted file to the project source directory, then right-clicked on the project and 'Added' to project.
    Then, the following modification:
    There are two sections of boot.asm that do init tasks; the first is conditional on ARMv7 target; we want to change the ARM mode code:

    ..... starting at line 159, the initializer _c_int00 starts:

    _______________________________________________

         .else           ; !.TMS470_16BIS

    ;****************************************************************************
    ;*  32 BIT STATE BOOT ROUTINE                                               *
    ;****************************************************************************

     .global __stack
    ;***************************************************************
    ;* DEFINE THE USER MODE STACK (DEFAULT SIZE IS 512)           
    ;***************************************************************
    __stack:.usect ".stack", 0, 4

     .global _c_int00
    ;***************************************************************
    ;* FUNCTION DEF: _c_int00                                     
    ;***************************************************************
    _c_int00: .asmfunc

     . . . . . .

    _____________________________________________________________________

    and, at line 197, we make the change:

            ;*-----------------------------------------------------
     ;* SET TO USER MODE XXX SUPERVISOR MODE XXX
            ;*------------------------------------------------------
            MRS     r0, cpsr
            BIC     r0, r0, #0x1F  ; CLEAR MODES
         ;   ORR     r0, r0, #0x10  ; SET USER MODE
            ORR     r0, r0, #0x13  ; SET SUPERVISOR MODE
            MSR     cpsr_cf, r0

    ................

    ___________________________________________________________

    The linker found the _c_int00 symbol locally and used the code without any project changes as far as I can recall;
    you might try forcing the issue by renaming the routine (in code and the export at top of file), and setting the project
    entry point to the newly named function (project propeties, TMS470Linker, Symbol Management, Entry Point .)
    You will get a warning that you aren't using the default-named  entry point, but the linker correctly finds the symbol and uses your code.


    Good luck! -- JLC

  • Joe,

    Thanks for the update. I had modified the 16-bit code instead of (line 197) 32-bit code. Works now. THANKS!

    MikeH