Forums » Software Development »
Write to SharedMem from DSP and read it from ARM
Added by stefan nielsen almost 10 years ago
Hi im trying to write to some shared memory from the DSP and read it back from the ARM. Ive expanded the HelloWorldDSP project, so memory is mapped as in that project. I tried on 4 different memory areas.
DSP code:
#define SHARED_MEM_BASE 0x80000000 #define IRAM_MEM_BASE 0x11800000 #define POOL_MEM_BASE 0xC6830000 #define DSP_MEM_BASE 0xC6000080 unsigned int volatile * const port_shared = (unsigned int *) SHARED_MEM_BASE; unsigned int volatile * const port_iram = (unsigned int *) IRAM_MEM_BASE; unsigned int volatile * const port_pool = (unsigned int *) POOL_MEM_BASE; unsigned int volatile * const port_dsp = (unsigned int *) DSP_MEM_BASE; unsigned int value = 1; char tmp[80]; sprintf(tmp,"********** Log Test trying to write Shared Mem to adr: %#010x, value %d ******* \n",SHARED_MEM_BASE,value); debugPrint(tmp); *port_shared = value; // write to port / value = *port_shared; // read from port / sprintf(tmp,"********** Log Test read from Shared Mem adr: %#010x, value read: %d ******* \n",SHARED_MEM_BASE,value); debugPrint(tmp);
This seems to work for the DSP and all read back values are okay, using similar printouts.
ARM code:
#define SHARED_MEM_BASE 0x80000000 #define POOL_MEM_BASE 0xC6830000 #define IRAM_MEM_BASE 0x11800000 #define DSP_MEM_BASE 0xC6000080 unsigned int volatile * const port_pool = (unsigned int *) POOL_MEM_BASE; unsigned int volatile * const port_shared = (unsigned int *) SHARED_MEM_BASE; unsigned int volatile * const port_iram = (unsigned int *) IRAM_MEM_BASE; unsigned int volatile * const port_dsp = (unsigned int *) DSP_MEM_BASE; char tmp[80]; int value_pool = *port_pool; // read from port / int value_iram = *port_iram; // read from port / int value_shared = *port_shared; // read from port / int value_dsp = *port_dsp; // read from port / sprintf(tmp,"*** Log Test read from adr: %#010x, value:%d, adr: %#010x, value:%d, adr: %#010x, value:%d, adr: %#010x, value:%d ******* \n" ,POOL_MEM_BASE ,value_pool ,IRAM_MEM_BASE ,value_iram ,SHARED_MEM_BASE ,value_shared ,DSP_MEM_BASE ,value_dsp); printf(tmp);
This makes the ARM give up. Below is the response seen in the consol.
Unable to handle kernel paging request at virtual address c6b7300c pgd = c52d0000 [c6b7300c] *pgd=c4493811, *pte=00000000, *ppte=00000000 Internal error: Oops: 807 [#1] PREEMPT Modules linked in: dsplinkk(O) ipv6 CPU: 0 Tainted: G O (3.2.0 #1) PC is at remove_wait_queue+0x24/0x70 LR is at remove_wait_queue+0x1c/0x70 pc : [<c00366bc>] lr : [<c00366b4>] psr: 80000093 sp : c5173e50 ip : c5a84044 fp : 00000000 r10: 00000001 r9 : 80040800 r8 : c6b73008 r7 : 000003e8 r6 : c5172000 r5 : 00000013 r4 : c5173e64 r3 : c6b73008 r2 : c6b73008 r1 : 00000000 r0 : 00000001 Flags: Nzcv IRQs off FIQs on Mode SVC_32 ISA ARM Segment user Control: 0005317f Table: c52d0000 DAC: 00000015 Process KK_Converter (pid: 2390, stack limit = 0xc5172270) Stack: (0xc5173e50 to 0xc5174000) 3e40: c6b73000 fffffe00 c5172000 bf0a6ffc 3e60: 80000013 00000001 c52b0c20 c0016fa0 c6b73008 c6b73008 00000001 000003e8 3e80: 00008000 c5173f04 c6b6f000 bf0ad600 80008051 bf09d668 00000029 41da6d64 3ea0: c018e03a 41da6d64 c44a6648 c0009524 c5172000 00000000 41da6d4c bf0a9d38 3ec0: a0000013 c018954c c51188cc c00366e0 c5118800 00000000 00000000 60000013 3ee0: c5172000 c05caed0 00000000 00008000 c8000200 00010000 000003e8 00000000 3f00: 41da6da4 00000000 a0000093 c505a3e0 41da6d64 41da6d64 c44a6648 c0009524 3f20: 00000000 c0091300 c0161818 00000030 00000000 febfd000 c5173f9c 80000010 3f40: c056a484 00000030 41da6d4c c0022958 41da6d4c c0009c88 00000001 c505a3e0 3f60: 00000000 c5318180 c5173f8c c505a3e0 41da6d64 c018e03a 00000003 c0009524 3f80: c5172000 c00913b8 00000003 00000001 41da6d64 00021158 00000080 00000000 3fa0: 00000036 c00093a0 00021158 00000080 00000003 c018e03a 41da6d64 00000003 3fc0: 00021158 00000080 00000000 00000036 00000000 41da6fa0 401448ac 41da6d4c 3fe0: 00000152 41da6c40 0000ab48 4038519c 80000010 00000003 018c0265 e0800000 [<c00366bc>] (remove_wait_queue+0x24/0x70) from [<bf0a6ffc>] (SYNC_WaitSEM+0x254/0x290 [dsplinkk]) [<bf0a6ffc>] (SYNC_WaitSEM+0x254/0x290 [dsplinkk]) from [<bf09d668>] (LDRV_MSGQ_get+0x84/0xc0 [dsplinkk]) [<bf09d668>] (LDRV_MSGQ_get+0x84/0xc0 [dsplinkk]) from [<bf0a9d38>] (DRV_Ioctl+0x1d0/0x778 [dsplinkk]) [<bf0a9d38>] (DRV_Ioctl+0x1d0/0x778 [dsplinkk]) from [<c0091300>] (do_vfs_ioctl+0x500/0x584) [<c0091300>] (do_vfs_ioctl+0x500/0x584) from [<c00913b8>] (sys_ioctl+0x34/0x54) [<c00913b8>] (sys_ioctl+0x34/0x54) from [<c00093a0>] (ret_fast_syscall+0x0/0x2c) Code: e3a00001 ebff7d25 e5943010 e594200c (e5823004) ---[ end trace 0b3ac9a59b6033d9 ]--- note: KK_Converter[2390] exited with preempt_count 1 Unable to handle kernel paging request at virtual address c6c2800c pgd = c52d0000 [c6c2800c] *pgd=c52ee811, *pte=00000000, *ppte=00000000 Internal error: Oops: 807 [#2] PREEMPT Modules linked in: dsplinkk(O) ipv6 CPU: 0 Tainted: G D O (3.2.0 #1) PC is at remove_wait_queue+0x24/0x70 LR is at remove_wait_queue+0x1c/0x70 pc : [<c00366bc>] lr : [<c00366b4>] psr: 20000093 sp : c51ede50 ip : c50f6044 fp : 00000000 r10: 00000001 r9 : 80040800 r8 : c6c28008 r7 : 000003e8 r6 : c51ec000 r5 : 20000013 r4 : c51ede64 r3 : c6c28008 r2 : c6c28008 r1 : 00000000 r0 : 00000001 Flags: nzCv IRQs off FIQs on Mode SVC_32 ISA ARM Segment user Control: 0005317f Table: c52d0000 DAC: 00000015 Process KK_Converter (pid: 2391, stack limit = 0xc51ec270) Stack: (0xc51ede50 to 0xc51ee000) de40: c6c28000 fffffe00 c51ec000 bf0a6ffc de60: 000003e8 00000001 c52b19e0 c0016fa0 c6c28008 c6c28008 80008051 000003e8 de80: 00008000 c51edf04 c6c24000 bf0ad600 80008051 bf09d668 00000029 425abd64 dea0: c018e03a 425abd64 c44a6648 c0009524 c51ec000 00000000 425abd4c bf0a9d38 dec0: 00000001 c00543b4 c05644b4 c52942a0 00000000 c00562c4 00002000 c0053c40 dee0: febfd000 c0161898 c0161818 00008000 c8000000 00010001 000003e8 00000000 df00: 425abda4 00000000 425abd4c c505a3e0 425abd64 425abd64 c44a6648 c0009524 df20: 00000000 c0091300 00000003 c51edf8c 00000020 c53181b0 c505a3e0 00000000 df40: c5318180 c51edf8c c0009524 c51ec000 00000000 425abd4c 00000001 c505a3e0 df60: 00000000 c5318180 c51edf8c c505a3e0 425abd64 c018e03a 00000003 c0009524 df80: c51ec000 c00913b8 00000003 00000001 425abd64 00009630 00000080 00000000 dfa0: 00000036 c00093a0 00009630 00000080 00000003 c018e03a 425abd64 00000003 dfc0: 00009630 00000080 00000000 00000036 00000000 425abfa0 401448ac 425abd4c dfe0: 00000152 425abc40 0000ab48 4038519c 80000010 00000003 018ca264 00006000 [<c00366bc>] (remove_wait_queue+0x24/0x70) from [<bf0a6ffc>] (SYNC_WaitSEM+0x254/0x290 [dsplinkk]) [<bf0a6ffc>] (SYNC_WaitSEM+0x254/0x290 [dsplinkk]) from [<bf09d668>] (LDRV_MSGQ_get+0x84/0xc0 [dsplinkk]) [<bf09d668>] (LDRV_MSGQ_get+0x84/0xc0 [dsplinkk]) from [<bf0a9d38>] (DRV_Ioctl+0x1d0/0x778 [dsplinkk]) [<bf0a9d38>] (DRV_Ioctl+0x1d0/0x778 [dsplinkk]) from [<c0091300>] (do_vfs_ioctl+0x500/0x584) [<c0091300>] (do_vfs_ioctl+0x500/0x584) from [<c00913b8>] (sys_ioctl+0x34/0x54) [<c00913b8>] (sys_ioctl+0x34/0x54) from [<c00093a0>] (ret_fast_syscall+0x0/0x2c) Code: e3a00001 ebff7d25 e5943010 e594200c (e5823004) ---[ end trace 0b3ac9a59b6033da ]--- note: KK_Converter[2391] exited with preempt_count 1
I also tried
unsigned int NumOfBytes = 4; static unsigned int res[4] = {0,0,0,0}; lpDspApp->ReadMemory((void*)IRAM_MEM_BASE, 4, &res[0]); sprintf(tmp,"*** Log Test read from adr: %#010x, value read[0]:%d,read[1]:%d,read[2]:%d,read[3]:%d ******* \n",IRAM_MEM_BASE,res[0],res[1],res[2],res[3]); printf(tmp);
but no luck and similar response as above.
Anybody has any idea as to what im duing wrong ?
thanks in advance
/stefan
Replies (11)
RE: Write to SharedMem from DSP and read it from ARM - Added by Michael Williamson almost 10 years ago
The linux OS uses virtual memory addresses. You can't access RAM by physical address in the normal case.
You need to use /dev/mem and mmap in the memory you want to access (though it will not be cacheable with this technique). See the examples folder in the MDK or trying searching / googling for linux memory map and /dev/mem for example code. Or you need to use the DSPLINK API for memory access.
Otherwise, you'll need to write a linux kernel module in order to get direct access to memory.
Sorry.
-Mike
RE: Write to SharedMem from DSP and read it from ARM - Added by stefan nielsen almost 10 years ago
Hi thanks for the quick reply. I found some stuff of how to do it on the ARM side, following the example you pointed out. On the DSP is it okay to write to memory as showed above ?
RE: Write to SharedMem from DSP and read it from ARM - Added by Michael Williamson almost 10 years ago
DSP code is OK, though if you have the caches enabled for the regions of SRAM or RAM you may need to add a cache write back call to ensure the data is moved to external memory for the ARM to pick up.
-Mike
RE: Write to SharedMem from DSP and read it from ARM - Added by Jonathan Cormier almost 10 years ago
You may find this post helpful for transmitting non-string data using dsplink. https://support.criticallink.com/redmine/boards/10/topics/4178?r=4179#message-4179
Note that the tsData::data_ptr requires tcDspApp::ReadMemory() on the ARM side to copy the memory into ARM space.
RE: Write to SharedMem from DSP and read it from ARM - Added by stefan nielsen almost 10 years ago
Hi thanks for the help, I still got some problems with reading on the ARM.
ARM code:
const char memDevice[] = "/dev/mem"; int *map = NULL; int _fdmem; /* open /dev/mem and error checking */ _fdmem = open( memDevice, O_RDWR | O_SYNC ); if (_fdmem < 0){ printf("Failed to open the /dev/mem !\n"); return 0; } else{ printf("open /dev/mem successfully !\n"); } /* mmap() the opened /dev/mem */ map= (int *)(mmap(0,MAPPED_SIZE,PROT_READ|PROT_WRITE,MAP_SHARED,_fdmem,DDR_RAM_PHYS));
And then i read like this:
// use 'map' pointer to access the mapped area! for (int i=0;i<10;i++) printf("content: 0x%x\n",*(map+i));
This gets me the values i wrote from the DSP, but the ARM side just doesnt continuing running my app.
Then tried this as suggested.
int res[10]; char tmp[80]; lpDspApp->ReadMemory((void*)map, 4, &res[0]); sprintf(tmp,"*** Log Test value read[0]:%d,read[1]:%d,read[2]:%d,read[3]:%d ******* \n",res[0],res[1],res[2],res[3]); printf(tmp);
but his does not give me the correct values written from the DSP. Any ideas what im missing ?
Thanks Stefan
RE: Write to SharedMem from DSP and read it from ARM - Added by stefan nielsen almost 10 years ago
Hi
do i need to use
int tcDspApp::SetSharedMemCfg(tsSharedMemCfg* pConfig)
or
int tcDspApp::SetPoolCfg(uint32_t anNumBufPools, uint32_t *apBufSizes,
uint32_t *apNumBuf, bool abExactMatch)
to use the Iram at 0x11802000 on the DSP ?
RE: Write to SharedMem from DSP and read it from ARM - Added by Michael Williamson almost 10 years ago
No you don't need ot use SetSharedMemCfg() or SetPoolCfg() if you are not using the tcDspInbound and tcDspOutbound message passing frameworks.
If you look at the dspapp.cpp file in the MDK, you will see the following parameters:
/** * Read a section of DSP memory. This is a light wrapper for the PROC_read() * call. * * \param DspAddr Physical Memory pointer of source data * * \param NumBytes number of bytes to transfer * * \param DestAddr Virtual Address of destination * * \return non-zero on error. */ int tcDspApp::ReadMemory(void* DspAddr, unsigned int NumBytes, void* DestAddr)
The ReadMemory call, I believe, takes a DSP physical address as the source not a memory mapped address. I don't think you want to call it with the map variable.
-Mike
RE: Write to SharedMem from DSP and read it from ARM - Added by stefan nielsen almost 10 years ago
Hi mike
your are rigth. I tried it before the
map= (int *)(mmap(0,MAPPED_SIZE,PROT_READ|PROT_WRITE,MAP_SHARED,_fdmem,DDR_RAM_PHYS));
and forgot to correct it back.. Its working now, thanks alot..
RE: Write to SharedMem from DSP and read it from ARM - Added by Frank C almost 10 years ago
Hi,
I am trying to get the shared memory working as well (by writing from DSP side and reading back from ARM side) using the HelloWorld as a basis. But ARM side doesn't read back correct values. I am using the same stuff from here. It seems I don't need to use /dev/mmap if I use ReadMemory call
Could you take a look at it and see what I am missing? Thanks
DSP side write value 1
#define SHARED_MEM_BASE 0xC6800000 unsigned int volatile * const port_shared = (unsigned int *) SHARED_MEM_BASE; ... value = 1; sprintf(tmp,"DSP... Writing to addr %#010x: %d\n",port_shared, value); debugPrint(tmp); *(port_shared) = value;
ARM side read
#define SHARED_MEM_BASE 0xC6800000 ... tcDspApp* lpDspApp = NULL; lpDspApp = new tcDspApp(); ... lpDspApp->ReadMemory((void*)SHARED_MEM_BASE, 4, &res[0]); sprintf(tmp,"ARM... Reading from address %#010x:%d\t%d\t%d\t%d\n",SHARED_MEM_BASE, res[0],res[1],res[2],res[3]); printf(tmp); }
dspapp.h has the memory addresses as:
SharedMemCfg() : RESETCTRLADDR (0xC6000000) , RESETCTRLSIZE (0x80) , CODEMEMORYADDR (0xC6000080) , CODEMEMORYSIZE (0x007FFF80) , SHAREDMEMORYADDR0(0xC6800000) , SHAREDMEMORYSIZE0(0x00005000) , SHAREDMEMORYADDR1(0xC6805000) , SHAREDMEMORYSIZE1(0x0002B000) , POOLMEMORYADDR (0xC6830000) , POOLMEMORYSIZE (0x00800000)
Thanks,
-Frank
RE: Write to SharedMem from DSP and read it from ARM - Added by Jonathan Cormier almost 10 years ago
Pretty sure you have to flush the DSP cache after changing values.
RE: Write to SharedMem from DSP and read it from ARM - Added by Frank C almost 10 years ago
Thanks for the cache info. Completely missed that part.
I reverted to the original code, and I've added BCACHE_wb() call after I write to memory on the DSP side, but I still have a problem somewhere.
I changed the SHARED_MEM_BASE to 0x80000000
and when I read from the ARM side, it just spits out some random data, and StopApp() call gives
ERROR: DSP_EWRONGSTATE StopApp - Error in PROC_stop [0x8000801b]
and it just hangs there.
Is there anything else I am missing here?
Thanks!