[announce] c64_tools (DSP loader and IPC)


That CMA test works for me after adding MISC_DYNAMIC_MINOR like you said.

Code:
root@notaz-openpandora2:/var/volatile/tmp# insmod cma_test.ko 
[3239137.864410] misc cma_test: registered.
root@notaz-openpandora2:/var/volatile/tmp# ls /dev/cma_test 
/dev/cma_test
root@notaz-openpandora2:/var/volatile/tmp# echo 1024 > /dev/cma_test 
[3239161.339996] misc cma_test: alloc: virt: df400000 dma: 9f400000 size: 1024K
root@notaz-openpandora2:/var/volatile/tmp# cat /dev/cma_test         
[3239171.307281] misc cma_test: free: CM virt: df400000 dma: 9f400000 size:1024K
Passing NULL dev to dma_alloc_coherent() should be ok, that's what dspbridge currently does and it works.
 
Last edited by a moderator:
hmm. interesting. on the stock SZ1.55 kernel the "misc device" cma test caused a crash here. maybe you already have a newer kernel ?

but well, I do not really care, all that matters to me is that the CMA works and this is not a showstopper.

For the not-so-technically-inclined readers: "CMA" means that there's no need to reserve a dedicated shared memory area for the DSP, except for a few (probably 4) MBytes for the DSP OS/Firmware. If the shared memory is not needed for DSP things it can be used by regular ARM applications. Cool!
 
hmm. interesting. on the stock SZ1.55 kernel the "misc device" cma test caused a crash here. maybe you already have a newer kernel ?
Linux notaz-openpandora2 3.2.45 #894 Sat Jul 6 17:22:45 EEST 2013 armv7l GNU/Linux

Even if this isn't exact SZ1.55 kernel, the changes should be minor. From your logs it looks like there was some corruption inside the kernel, perhaps caused by some other module earlier, try it on fresh boot next time when you have such problems.
 
*shrug* minor changes can break things. fresh boots are standard procedure (I reboot after almost every test run just to be sure, sometimes I even plug out the battery when things do not seem to make sense). Nevertheless, thank's for trying it out!

minor breakthrough here, btw: L1DSRAM cache access is working now, from both GPP and DSP sides.

two things were preventing this: 1) the initial DSP register / memory protection configuration did not even allow the DSP to access its own L1DSRAM (got DSP crashes when trying to read/write it). Added some register setup magic which fixed that. 2) my own stupidity: on the OMAP3, the GPP/ARM sees the DSP caches at different addresses than the DSP.

Now that the SRAM access is working, superfast RPC can be implemented (I just dug out an old proposal / ref. implementation I sent to TI in 2008 that had some benchmark figures: 0.000940ms per roundtrip should be doable (that's over a million RPCs per second). The IRQ variant (on QNX) took 0.023ms per roundtrip, btw. However: On Linux there's the added overhead of the read/write file ops, so 0.0733ms is still quite good. I'll keep you posted.

EDIT: [22:05] rewrote IPC to use the L1DSRAM, gave a nice speed improvement (had quite a struggle with some c6x related quirks regarding SRAM access..accessing it via *(volatile sU32*) (ADDR) freezes the DSP. via an array that's linked into the SRAM via .section works fine. W.T.H. seriously.)


pandora:/home/bsp# ./go64.sh

go64.sh: ARGS="" DSPIMAGE="./c64p_simple_dm3730.out"
[...] loading DSP image from "./c64p_simple_dm3730.out"
[dbg] coff_open: file size=209838 (0x000333ae)
[...] reading 52 section headers....................................................
[...] initializing DSP memory and copying sections..
[...] text=0x00005fa0 data=0x000012df bss=0x00704388
[...] DSP image loaded successfully. starting DSP..
[dbg] waiting for DSP startup..
[...] DSP is up and running!
pandora:/home/bsp# ./test_hello q l; dmesg -c
[dbg] DSP numRead=4, debug=0x07000002
[...] loc_shm_alloc: ioctl() succeeded.
[...] starting calibration
[...] write testmsg: 4 bytes written.
[dbg] DSP numRead=4, debug=0x37010007
[...] write testmsg: 4 bytes written.
[dbg] DSP numRead=4, debug=0x37010007
[...] starting benchmark
[...] benchmark finished. => 100000 iterations in 4270 millisecs.
[...] loc_shm_free: ioctl() succeeded.
[ 996.354400] c64: init ok. module build date: Sep 17 2013


Configuration:

[ ] flush_cache_all()
[x] DSP L1D
[ ] DSP L2D
[x] use L1DSRAM for IRQ-driven IPC


==> 0.0427 millisec messaging overhead per roundtrip/RPC.
==> 23419.2037471 roundtrips/RPCs per second.

==> ~16.39 times faster than DspLink (based on M-HT's measurement, i.e. ~0.7ms/roundtrip)
==> ~ 1.72 times faster than c64_tools-15Sep2013

(yep, how boring, I know, I know. But that's the kind of boring thing that needs to be done before the real fun can begin ;) My goal is to make the IPC fast enough for ARM apps to be able to utilize the DSP even for smaller subroutines, not just for decoding/processing huge chunks of data.)

p.s.: I also just tested the multi-process / multi-client feature: works fine (ran 4 benchmarks/stresstests in parallel).

EDIT: [sep18, 15:40]: CMA seems to work fine. The kernel module now supports mmap() so the shared memory can be accessed in userspace. I also implemented GPP-side cache wb/inv/wbinv ioctls.

There's also a new test component (demo_checksum) on the DSP-side that builds a checksum for a given memory range -- that's to verify that the whole thing really works.

Currently working on a new release that should contain everything developers need to get started with DSP programming (but first of all: lunch time.).
 
Last edited by a moderator:
Ok guys'n'gals,

 here is an update of the "c64_tools" package (see attachment).

 Changes compared to the 15-Sep-2013 release:

   - Source clean up

   - Support for Linux CMA (contiguous memory allocator) (for dynamic GPP/DSP shared memory allocation)

   - Reduced memory reserved for DSP from 32 MBytes to 4 MBytes

   - ARM cache writeback/invalidate support / utility functions

   - IPC / messaging speed improved by factor 1.72

   - lots of new API functions (see "include/dsp.h")

   - a "readme.txt", you should, well, read.

Cheers,

Bastian

p.s.: the package includes precompiled binaries, too. Pandora boot scripts can be found in "scripts/".

c64_tools-18Sep2013_dist.tar.gz
 

Attachments

  • c64_tools-18Sep2013_dist.tar.gz
    536.1 KB · Views: 483
Last edited by a moderator:
@milkshape: it's as good as finished. I'll add a couple of convenience stuff, like a memory manager for the shared memory (in userspace, could as well be done by the application.). Plus I'll add access to L1DSRAM, but that's for expert devs (DspLink does not have that). In its current state, it's good enough for using the DSP to play MP3s, softsynths (hey Torpor!), ... The L1DSRAM will be especially interesting for push-it-to-the-limit apps like emulators, I guess.

@Linux-SWAT: thanks! In the end (almost the end), it again turned out to be much more work than initially expected but I really hope it will have been worth it.

I'd really appreciate if everyone could test this on their Pandoras (CC/Rebirth/1Ghz) to see if there are any compatibility issues (I do not expect any but you never know).

p.s.: you currently need to be root to run the "c64_tc" example application but that's a minor mistake on my side that took 2 minutes to be fixed.
 
Last edited by a moderator:
Sweet :) go go power ptitSeb / bsp.

I'm rather surprised that even after all these years the pandora is getting newer ways to tap into previously untapped resources.

Long live the pandora :)
 
@notaz:

That's the classic hen-and-egg problem. as long as this is not going to be in the standard firmware, ppl will hesitate to use it. Also: you have >=65 MBytes of Python stuff sitting in the firmware. Is this really necessary ?

I mean, this thing is a "whopping" 400 KBytes in size. Would it really hurt that much ?

EDIT: IMHO, it's not about finding a suitable task for the DSP (there's plenty), it's more about getting devs out of their comfort zone and encouraging them to optimize for a fixed-hardware platform, like any good console-dev would do.

@milkshake:

We haven't even scratched the surface ;) (the biggest challenge still is to write good software. Look at e.g. Nintendo and how much they get from "inferior" hardware. Or the c64 demoscene (all hail to the 6581/8550 :D ).

(ok that sounded a bit pretentious and there is some really good SW for the Pandora but IMHO software in general is still the biggest challenge nowadays)
 
Last edited by a moderator:
Well somebody could have used dspbridge for something already, it's not useless and it's in firmware for over a year, but nobody did.

The main problem with your solution is the need of custom boot scripts, not size. We'd have to add 2 additional options to boot menu, and the user would have to select the right one or things would go wrong (and yes we need to get rid of the old boot-with-dsp-mem option, ugh).

Quite a lot users boot from SD card with their own boot scripts too, everyone of them would have to be told to put the correct memory hole bootarg depending on the unit they have (the boot SD is usually created with an app from the repo). It would be better to find a solution where it just works without special setup.

I might be remembering wrong but I think I've seen some way to use CMA to reserve fixed physical memory location without wastage. If we could use that to eliminate need that memory hole in bootargs, I would have no problem pulling this in.
 
Last edited by a moderator:
For a start, a mediaplayer that can decode mp3 and h264 on it would be great. With a memorysplit of 4MB it could be the standard boot method as 4MB can be easily sacrificed even on 256MB Pandoras imho.
 
@Notaz:
You are right, the boot scripts would be the major obstacle. A "boot with 4MB cut for DSP" boot option, with the ability to select that as a default in U-Boot, could solve that issue.

Users that have their own boot scripts hopefully know what they are doing and would need to add the required options themselves. Since they've already figured out how to use custom boot scripts in the first place, that should not be an issue (it's a very simple modification, after all).

After reading that you might have seen something that would allow for such a fixed-address mapping, I took another look at "dma-mapping.h" and "dma-coherent.c". There is a function called "dma_declare_coherent_memory()" which looks like it could be used for this purpose. I tried it out, but it always results in a kernel oops (17) / "kernel NULL pointer dereference at virtual address 00000114". I tried the following: Passing NULL as device pointer (the "workaround" for the dma_alloc_coherent() call), Passing the actual struct device* (c64_device), passing 0 as bus address (does not make much sense, I know). All attempts resulted in a kernel crash.

Like mcobit said, sacrificing the 4 MBytes is probably hardly noticable and it is also the most realistic solution for now (unless someone volunteers to investigate why the kernel call mentioned above crashes and if it is even allowed to be called after the system has started up).

These 4 MBytes would not be lost after all: If the DSP is not used, the memory could still be used for applications, although there would be some special handling required (an extra mmap() call in the app., I could add that to the kernel module so the app. does not require root privileges).

Another idea, which would involve a bit more effort than just sacrificing the DSP memory, would be to use the 4 MBytes for the DSS framebuffers.
I.e. when the memory is needed for the DSP, the whole system would need to be locked, the page entries that refer to the old framebuffer address(es) would need to be updated, the current framebuffer contents would need to be copied to the new (physical) address, and finally the DSS registers would need to be updated accordingly. Again, I'm not sure that's worth the effort for just 4 MBytes.


@mcobit/all:
Regarding DSP codecs: ED told me that they are freely available from TI but cannot be included in the firmware because of patent issues (a well known problem that's not DSP specific). Maybe we could workaround that by adding a feature to the COFF loader (my task) that allows to load single code sections. In the long run, assuming that people will code for the DSP, it might be useful to have a standard/base DSP image in the firmware, which could then be extended by loading additional code sections (i.e. an additional DSP "overlay" image).

The TI codecs, last time I've seen them (but haven't done much with them except verifying that the MP4 codec works alongside the DSP code the company I'm working for created), are standard "XDAIS" algorithms. XDAIS is a rather lightweight interface that allows DSP software to specify their resource requirements (memory blocks, DMA, L1DSRAM, ..) and, in general, offers a "standard" interface to use the algorithm. In order to use an XDAIS algorithm, you have to query its resource requirements, allocate the resources, initialize the algorithm, and then you're ready to call its "process" function (or what it was called).

Since the gstreamer framework is built upon the CodecEngine framework, which is built upon DspLink, and, on the DSP-side, finally XDAIS, I do not think it's possible to use gstreamer (without modifications) with a "c64_tools" DSP image.

Therefore, someone with more intimite knowledge of video codecs and e.g. mplayer/VLC would be required to make this happen.


Regarding example code: The .tar.gz I released yesterday contains an example DSP project that can be openend and build with CodeComposerStudio.

This example project contains two example "components" -- A simple calculator ("demo_calc"), and a memory-checksum component ("demo_checksum").

While that's only a few lines of code, I think this should be enough to give devs an idea how to add their own components.

On the ARM side there is a test application ("c64_tc") which shows how to use aforementioned DSP components.

ah, and another thing: For some reason that I have not figured out, yet, it is necessary to reboot the Pandora when the DSP image has changed (loading the same DSP image multiple times works fine, though). It looks as if the DSP reset code (very similar to what Dsplink does, btw), does not work as expected and maybe the DSP is still executing code while the ARM updates the code sections.

Once I've added the "load overlay" (and "unload") feature to "c64_load", this issue can be worked-around by making sure that the DSP sits in its main dispatch loop while the code memory is being updated. For binary compatibility's sake I will also move the DSP-side component_register() function to its own section that will be located at a fixed size address.

p.s.: sorry for posting such a long message :)
 
Last edited by a moderator:
Back
Top