We have been using the new syslink paradigm to talk to the DSP from the ARM core on the OMAP3530. For the most part, getting it to work was pretty straightforward and quick. We do have some questions that we would like to have answered regarding memory mapping and caching. See the questions highlighted in italics.
For a concrete example, let’s use the message queue example (ex02_messageq) memory layout provided for the OMAP3530 in syslink_2_21_01_05:
/* Memory Map for ti.platforms.evm3530
*
* 8000_0000 - 8FFF_FFFF 1000_0000 ( 256 MB) External Memory
* ------------------------------------------------------------------------
* 8000_0000 - 8EEF_FFFF EF0_0000 ( 239 MB) Linux don't care
* 8EF0_0000 - 8EF0_FFFF 1_0000 ( 64 KB) SR_0 no cache
* 8EF1_0000 - 8EF2_FFFF 2_0000 ( 128 KB) SR_1 no cache
* 8EF3_0000 - 8EFF_FFFF D_0000 ( 832 KB) -------- don't care
* 8F00_0000 - 8F7F_FFFF 80_0000 ( 8 MB) DSP_PROG cache enable MARXXX
* 8F80_0000 - 8FFF_FFFF 80_0000 ( 8 MB) -------- cache enable MARXXX
*/
In particular, we want DSP_PROG on the DSP side to use cache, but the shared memory regions SR_0 and SR_1 should not be cacheable on both the ARM and the DSP side.
It seems that the memory layout needs to be reflected in quite a few places (not such a good design) to get this all to work:
- The kernel argument mem needs to be set to 239M in the u-boot parameters.
- In shared/config.bld:
var SR_0 = {
name: "SR_0", space: "data", access: "RWX",
base: 0x8EF00000, len: 0x10000,
comment: "SR#0 Memory (64 KB)"
};
var SR_1 = {
name: "SR_1", space: "data", access: "RWX",
base: 0x8EF10000, len: 0x10000,
comment: "SR#1 Memory (128 KB)"
};
Build.platformTable["ti.platforms.evm3530:dsp"] = {
externalMemoryMap: [
[ SR_0.name, SR_0 ],
[ SR_1.name, SR_1 ],
[ "DSP_PROG", {
name: "DSP_PROG", space: "code/data", access: "RWX",
base: 0x8F000000, len: 0x800000,
comment: "DSP Program Memory (8 MB)"
}]
],
Notice there is no cache configuration given here.
- In dsp/DSP.cfg:
/* shared region configuration */
var SharedRegion = xdc.useModule('ti.sdo.ipc.SharedRegion');
/* configure SharedRegion #0 (IPC) */
var SR0Mem = Program.cpu.memoryMap["SR_0"];
SharedRegion.setEntryMeta(0,
new SharedRegion.Entry({
name: "SR0",
base: SR0Mem.base,
len: SR0Mem.len,
ownerProcId: MultiProc.getIdMeta("HOST"),
cacheEnable: false,
isValid: true
})
);
/* configure SharedRegion #1 (MessageQ Buffers) */
var SR1Mem = Program.cpu.memoryMap["SR_1"];
SharedRegion.setEntryMeta(1,
new SharedRegion.Entry({
name: "MessageQ Buffers",
base: SR1Mem.base,
len: SR1Mem.len,
ownerProcId: MultiProc.getIdMeta("HOST"),
cacheEnable: false,
isValid: true
})
);
Cache = xdc.useModule('ti.sysbios.family.c64p.Cache');
Cache.MAR128_159 = 0x00008000; /* xxxx xxxx xxxx xxxx 10xx xxxx xxxx xxxx */
What takes precedence here the cache setting in the MAR or the cacheEnable in the SharedRegion.Entry? Are both being used?
- In memap.txt (input to slaveloader):
# Format is "procName, slaveVirt, slavePhys, mastPhys, size, mask, cache"
# mask values can be a bitwise OR of these values:
# * 0x1 - MasterKnlVirt
# * 0x2 - MasterUsrVirt
# * 0x4 - SlaveVirt
# DDR - 8MB, MasterKnlVirt | SlaveVirt, noncached
DSP, 0x8F000000, 0x8F000000, 0x8F000000, 0x800000, 0x5, 0
# SR0 - 64kB , MasterKnlVirt | SlaveVirt, noncached
DSP, 0x8EF00000, 0x8EF00000, 0x8EF00000, 0x10000, 0x5, 0
# SR1 - 128kB , MasterKnlVirt | SlaveVirt, noncached
DSP, 0x8EF10000, 0x8EF10000, 0x8EF10000, 0x20000, 0x5, 0
This is really confusing. Is there any documentation about this file? What does the 0x5 mean (SlaveVirt ! MasterKnlVirt)? What do the terms MasterKnlVirt, MasterUsrVirt, SlaveVirt mean? Why is 5 the right value for this field? The last field which is 0 in all cases seems to imply that there is no cache. But I thought that the DSP at 0x8F000000 was to be cached. Do the cache settings here take precedence over the ones in dsp/DSP.cfg?
Finally, how is the non-cacheability of SR_0 and SR_1 memory regions reflected on the ARM side? How is Linux informed not to cache these regions?