Question thread: Develop DSP device driver for Gumstix OMAP3530


thinair89

Still Fresh
Joined
Dec 6, 2013
Messages
4
Hi bsp,

I was developing a minimum "DSPLink" as well but for Gumstix Overo (OMAP3530) to use DSP to do extensive computation. It seems like what you've done is exactly what I plan to do. I'm not very experienced in this but I did read a lot of reference manuals and have some knowledge of general kernel stuff. 

Currently I encounter some problems. I tried to load boot table (I convert .out to a boot table.h and put it into the kernel module) into DSP L2 RAM (currently don't want to mess up with DSP MMU). And all of a sudden, I cannot use devmem2 to access DSP subsystem memory space (I was able to before). Kernel panic and hangs. No luck after reboot. I'm kinda stuck on this now.

On TI forum, someone suggests this might due to Memory Overlapping. But I'm not sure how to check/change configuration of this. Do you have any suggestions?
 
Hi thinair89,

 IIRC, powering on the L2, and configuring it for bypass mode should do the trick (see XMC L2CFG register, p.1931/1932 in the TRM) (=> all 64k available as shared/flat memory instead of cache).

 at least that's what I did in c64_tools and it is working fine.

 I'd suggest that instead of writing your own DSP driver (which really is just boring and hard work and, as you can see, took quite a bit longer than expected -- 2 months instead of 2 weeks..), you'd simply compile c64_tools for your Gumstix device. It should work out of the box.

 If the kernel you are using does not support CMA (contiguous memory allocator) resp. you don't want to merge the c64_tools related patches (just a few lines of code in arch/arm/mach-omap2/board-omap3pandora.c, though. see http://git.openpandora.org/cgi-bin/gitweb.cgi?p=pandora-kernel.git;a=blob;f=arch/arm/mach-omap2/board-omap3pandora.c;h=6f98ba0835c411df72e8e420c0c86d334bed5e69;hb=pandora-3.2 ), you can comment out the line #define USE_CMA_FOR_POOLS in dev.c. You will then need to setup a memory hole for the DSP using the linux boot args (mem=..). By default, the driver expects a memory hole @0x86000000..0x88000000 (4MB for the DSP text/data/bss + 28MB for shared memory).

 Last but not least, I'd also suggest to use the L2 for data instead of code, and place performance-critical DSP loops in the L1 (or execute it from RAM and let the cache logic pull it into L1P automatically).

 If you need further help with getting this to work on your Gumstix Overo, please open a new thread in this subforum.

Greetings,
Bastian
 
Hi all,

First I wanna thank Bastian for answering my questions. Actually, I'm writing this DSP driver just for fun (to run computation is not my main purpose). My purpose, for this "hello world" stage, is just to learn the basic kernel stuff and low level device driver experience.

So I was panic when the kernel panic...It turns out that because I forgot DSP was kept under reset and not powered on, that why I lost all the access to DSP subsystem registers when I did not load my module. Really feel dumb for this....

After a quick fix and load my module, I was able to access DSP L2RAM from ARM side. And confirmed with memset 0x0f to L2RAM area. (L1DRAM is also accessble from devmem2 tool ) 

So what I am trying to do now, is to use CCSv5 to compile a simple program: 

 

#define REG(x)              *((volatile unsigned int *) (x))

#define MAILBOX_BASE           0x48094000

#define MAILBOX_MESSAGE_0_OFFSET      0x40

#define MAILBOX_MESSAGE_1_OFFSET      0x44

#define L1DRAM_BASE 0x00F04000

#define L2RAM_BASE 0x007F8000

#define L2RAM_TEST_LOC 0x007FF000

int main(void) {

 

REG(L1DRAM_BASE) = 0xABABCDCD;

REG(L2RAM_TEST_LOC)= 0xCAFEF00D;

REG(MAILBOX_BASE+MAILBOX_MESSAGE_0_OFFSET) = 0xF00DCAFE;

return 0;

}

 

I found a tool on TI website, called Dspboot assist tool (comes with sprab60), which convert the .out to a .bin or .h (bootTable) that should be copied to DSP memory, in my case, L2RAM. I've attached my link cmd file and my source code below. 

 

I then find out the entry_point of the program manually, and code it into the BOOTADDR. The entry_point is aligned with 1KB as TRM said. However, what happens is, Linux hangs. The breathing LED no longer blinks. 

 

i'm thinking that maybe it's my kernel module memory issue. I do ioremap_nocache on L2RAM (according to L3 address, global view), and use the return pointer as the base. Extract section address from the bootTable.h, OFFSET = section address - L2RAM_base(address is according to DSP view, different from L3 view) and copy data to the ioremap_return_address + OFFSET.

I assume this is the correct physical location and continuous?

 

To sum up: 

1. I assume I copied the correct binary data to the correct memory location and set the correct entry_point to BOOTADDR(BOOTMOD=0).

Why does the Linux hang and die ? I think two cores are operating independently, why DSP can kill Linux?

 

2. When I write the DSP test code and compile with ccs, did I use DSPBIOS or SYSBIOS library? If any lib is used, it should be static linking right?  So it should execute without any pre-stored library data.

3. When I "return 0", where does the PC of DSP go? DSP is actually bare-metal with no OS...What would happen if the program is executed correctly? (Mailbox should not work, I saw TI guys said DSP was blind to global address if MMU is disabled. I expect to see value changes in those RAM locations though.)

 

4. I want to configure DSP internal memory using XMC registers, however, it gives me error:


root@overo:~/dspdd/transfer# ../../devmem2/devmem2 0x5e840000

/dev/mem opened.[10665.960113] Unhandled fault: external abort on non-linefetch (0x1018) at 0xb6f43000

[10665.969329] In-band Error seen by MPU  at address 0

Memory mapped at address 0xb6f43000.

Bus error

 

Maybe the MMU power/clock is not on?? ...I'm kinda tired on opening 4 copies of TRM and look around for registers....


 

Sorry for this lengthy post...Just like Bastian, I don't have JTAG,.And I can totally feel the pain when he was developing the c64_tool.

 

Somehow I cannot upload any of the code, so I pasted it here.

 

--Thanks everyone for reading it till here....Airie

 

My code: dsp side test program

#define REG(x)              *((volatile unsigned int *) (x))

#define MAILBOX_BASE           0x48094000

#define MAILBOX_MESSAGE_0_OFFSET      0x40

#define MAILBOX_MESSAGE_1_OFFSET      0x44

#define L1DRAM_BASE 0x00F04000

#define L2RAM_BASE 0x007F8000

#define L2RAM_TEST_LOC 0x007FF000

int main(void) {

 

REG(L1DRAM_BASE) = 0xABABCDCD;

REG(L2RAM_TEST_LOC)= 0xCAFEF00D;

REG(MAILBOX_BASE+MAILBOX_MESSAGE_0_OFFSET) = 0xF00DCAFE;

return 0;

}

 

My Linker cmd file:


-c

-a

-heap  0x2000

-stack 0x2000

 

MEMORY

{

RAM: o = 0x007F8000 l = 0x00007000 /* Currently use L2RAM */

}

 

SECTIONS

{

boot > RAM

{

    -l  rts64plus.lib<boot.obj>(.text)

}

.text : palign(1024)         >  RAM

.stack : palign(8)       >  RAM (HIGH)

.bss :  palign(8)          >  RAM

.cio   : palign(8)       >  RAM

.const  : palign(8)       >  RAM

.data   : palign(8)       >  RAM

.sysmem  : palign(8)       >  RAM

.far     : palign(8)       >  RAM

  .args      : palign(8)     >  RAM

.ppinfo   : palign(8)      >  RAM

.ppdata    : palign(8)     >  RAM

 

  /* TI-ABI sections */

.pinit    : palign(8)      >  RAM

.cinit    : palign(8)      >  RAM

 

  /* EABI sections */

  .binit       : palign(8)   >  RAM

.init_array:  palign(8)  >  RAM

  .neardata     : palign(8)  >  RAM

.fardata     : palign(8)   >  RAM

.rodata      : palign(8)   >  RAM

.c6xabi.exidx : palign(8)  >  RAM

.c6xabi.extab  : palign(8) >  RAM

}
 
Last edited by a moderator:
So what I am trying to do now, is to use CCSv5 to compile a simple program: [...]

Your code accesses the mailbox, have you powered it on ?


I'd suggest to remove the mailbox code (for now), and replace the 'return 0;' with an infinite loop (main() is not supposed to return).

The entry_point is aligned with 1KB as TRM said

Actually the TRM says it has to be aligned to a 4k page. Should not be an issue, though, since you shouldn't set BOOTADDR to the entry point but to some short (assembly) program that jumps to the actual entry point. For example, c64_tools sets BOOTADDR to 0x86000000 (reset_vector), then generates a short boot code, depending on the actual entry point, before releasing the DSP from reset.

i'm thinking that maybe it's my kernel module memory issue. I do ioremap_nocache on L2RAM (according to L3 address, global view), and use the return pointer as the base. Extract section address from the bootTable.h, OFFSET = section address - L2RAM_base(address is according to DSP view, different from L3 view) and copy data to the ioremap_return_address + OFFSET.
I assume this is the correct physical location and continuous?

That sounds OK. I assume you have verified that the target addresses are correct ?

1. I assume I copied the correct binary data to the correct memory location and set the correct entry_point to BOOTADDR(BOOTMOD=0).
Why does the Linux hang and die ? I think two cores are operating independently, why DSP can kill Linux?

I presume you meant that you copied the data, set the entry point (resp. generated the boot code, see above), released the DSP from reset, then it crashes ?


Why the DSP can kill the entire system cannot be answered easily but I've seen it _a lot_ of times even when I totally did not expect it (usually the system simply resets).

2. When I write the DSP test code and compile with ccs, did I use DSPBIOS or SYSBIOS library? If any lib is used, it should be static linking right?  So it should execute without any pre-stored library data.

Well, you don't have to use DSPBIOS but it contains a couple of useful routines that you'd have to re-invent otherwise (e.g. HWI dispatching, cache control).

For a simple DSP test program you don't need these so you should be able to work w/o DSPBIOS.


And yeah, it's all linked statically. As for pre-stored library data, the "Dspboot assist tool" you're using (which I'm totally unfamiliar with) hopefully takes care of cinit, otherwise you cannot use global variable initializers. Not relevant to your test-program, though (for now).

3. When I "return 0", where does the PC of DSP go? DSP is actually bare-metal with no OS...What would happen if the program is executed correctly? (Mailbox should not work, I saw TI guys said DSP was blind to global address if MMU is disabled. I expect to see value changes in those RAM locations though.)

See above. Replace the "return 0;" with an infinite loop to be on the safe side.


If you haven't configured the MMU, you can only access memory within the local interconnect (i.e. DSP internal regs, L1/L2).

4. I want to configure DSP internal memory using XMC registers, however, it gives me error:
root@overo:~/dspdd/transfer# ../../devmem2/devmem2 0x5e840000


/dev/mem opened.[10665.960113] Unhandled fault: external abort on non-linefetch (0x1018) at 0xb6f43000


[10665.969329] In-band Error seen by MPU  at address 0


Memory mapped at address 0xb6f43000.


Bus error


Maybe the MMU power/clock is not on?? ...I'm kinda tired on opening 4 copies of TRM and look around for registers....

Hmm.. hard to say why that happens. You did not post the ARM side code. My guess is that the DSP is not powered on when you try to access its regs using your "devmem2" tool ?!

Sorry for this lengthy post...Just like Bastian, I don't have JTAG,.And I can totally feel the pain when he was developing the c64_tool.

yep, w/o JTAG this was a real PITA. You really picked a "fun" topic to learn kernel/embedded development and if you want to see this through, be ready to lose a hair or two over this one..


On the upside, you can always look into the c64_tools source code. Some of the code lines in there took me hours, sometimes days to figure out.


Still, if I were you I'd pick a more accessible platform (with a proper debugger!) to learn about embedded development (e.g. how to develop your own RTOS, how to use interrupts handlers, DMA, ADC/DAC, GPIOs, ..).


Last but not least, your questions are clearly TI forum material but I have seen that, unfortunately, many questions there simply do not get answered (it's usually the high level questions about codec engine etc. that are), and there are hardly any alternatives, so feel free to keep on posting ;)


Next time you'd post your entire source, though. You can "tar"/"zip" it and attach it to your posts in this forum (if you have javascript enabled), or you can upload it to one of the many one-click hosters and post the link.
 
I can't help but burst into tears today....Yes, finally, DSP executed my program and ARM doesn't hang !!!!!!!!!!!!!!!!!!!! 

No change on ARM side module, mailbox is properly initialized according to TI' DSPLink code(but not useful for now).

I used while(1) and remove the mailbox operation from my test program. A million thanks to Bastian !

Also I asked my Professor about this "return"  issue, I posted the email here in case anyone is interested.

Question:

If I have a computer with no OS. When I boot it up, it just jump to an address I specified and start executing. When I have a C code which ends with return 0 (converted to binary, and entry_point is the boot address, think about general C toolchain and static linking), what would possibly happen to this return statement?

Where would the PC go? Back to its entry point? Will it stop?

I doubt since there is no HALT (like LC3), something bad happens...

My Professor's reply:

When you call return, it sets PC to the address that was current prior to call of your program.  What is that address?  It was not set.  In fact, there is probably no valid activation record for main with this address set.  So, PC is set to some value that happened to be in the expected location in the activation record on the run-time stack, but that location is not properly initialized.

My thought:

Now I recall I have a while(1) in every program I wrote when I use MSP430 and other development boards as well.......T_T

//**********************************************************************************************************

Output:


root@overo:~/devmem2# ./devmem2 0x5cf04000

/dev/mem opened.

Memory mapped at address 0xb6f58000.

Value at address 0x5CF04000 (0xb6f58000): 0xABABCDCD

 

root@overo:~/devmem2# ./devmem2 0x5c7ff000

/dev/mem opened.

Memory mapped at address 0xb6fbe000.

Value at address 0x5C7FF000 (0xb6fbe000): 0xCAFEF00D

//**********************************************************************************


Anyway, I'm still so excited about this result... I'll continue developing my stuff (kind of falling into a new stage of DSP RTOS dev now..). Gumstix seems to have a JTAG support, but not many people use it. I plan to ask other experts around me to help set up a JTAG debugger next semester, or I may buy a OMAP3530 BeagleBoard (better JTAG support and more popular). 
 
hehe, glad to hear it's working now :)

regarding JTAG: From what I know, JTAG emulators for the TI C64+ DSP (14 pin header) don't come cheap (650$+) (unlike 2 pin ARM serial wire debug (SWD) adapters, which you can buy for ~30$ or less).

If you somehow manage to find a low cost solution, please post it here!

..and yes, you really should think about getting a Pandora. Unlike a mere devboard, it comes with a nice display (50 and 60Hz), very good audio output, a lot of controls, and you can easily take it with you and show your "hacks" around :)
 
Hello bsp,

Here I am again. I finished my Coff Parser, and now I can use my User program to load bin file to DSP (mmap, but still map to L2RAM...). Much better than recompile every time...

I tried to toggle an LED using GPIO, I did see LED blinking. But I keep get kernel warnings:

In-band Error seen by IVA_SS  at address 0

It just keep printing on the screen but kernel does not hang, I can stop this by reset DSP from my User program.

TI forum points me to a possibility that it is due to access the register/module before its clock is enabled. But this is not the case for GPIO (  I enabled clock ).

I'm not sure if that related with L3 firewall settings.. That part of the TRM is totally confusing..

Have you seen this error before ?

This is my TI threads, which has my little program for LED blinking...

http://e2e.ti.com/support/dsp/omap_applications_processors/f/447/t/328175.aspx

Thanks,

Airie
 
Back
Top