最早接触cmem是TI davinci系列中dvsdk有个cmem模块,
主要负责共享音视频数据,以及应用程序(IPNC)的一些消息通信.
后来IPNC要移植到其它系统上,如海思,升迈,安霸.出现了一些错误,
遇到了一些麻烦,虽然是简单的问题,但也走了许多弯路.
现总结一些经常遇到的,方便大家参考,如果有别的问题,也可以留言在后面1,insmod cmemk.ko,提示cmemk: Unknown symbol cpu_cache (err 0)
说明:
这个错误通常是cmemk.ko 跟当前内核(kernel)不匹配造成的,重新编译一下就行.
解决办法:
首先编译内核, 在cmem的Rules.make中设置内核路径,接下来把cmem重新编译一遍,生成cmemk.ko即可
2,insmod cmemk.ko 提示 cmemk: Unknown symbol xx_dma_map_area (err 0)
说明:
xx_dma_map_area中xx表示不同的cpu型号,比如arm926等.
该错误通常出现在kernel版本高于 2.6.34 的时候.
解决办法:
假设是arm926,在src/module/cmemk.c中最后面添加以下定义:
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,34)
/*
* The following assembly functions were taken from
* arch/arm/mm/proc-arm926.S
* Since we can't use the C preprocessor to evaluate #defines, the
* code that was taken is the code encapsulated by
* #ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
* ...
* #endif
* (note that this is #ifndef, i.e., #if !defined)
*/
asm("\n \
.global arm926_dma_map_area\n \
arm926_dma_map_area:\n \
add r1, r1, r0\n \
@ cmp r2, #DMA_TO_DEVICE\n \
cmp r2, #1\n \
beq arm926_dma_clean_range\n \
bcs arm926_dma_inv_range\n \
b arm926_dma_flush_range\n \
");
/*
* the cache line size of the I and D cache
*/
/*
* Leave here for documentation purposes, but we don't use it since
* asm("") statements won't get preprocessed (inside a string).
*/
#define CACHE_DLINESIZE 32
/*
* dma_inv_range(start, end)
*
* Invalidate (discard) the specified virtual address range.
* May not write back any entries. If 'start' or 'end'
* are not cache line aligned, those lines must be written
* back.
*
* - start - virtual start address
* - end - virtual end address
*
* (same as v4wb)
ENTRY(arm926_dma_inv_range)
*/
asm("\n \
.global arm926_dma_inv_range\n \
arm926_dma_inv_range:\n \
@ tst r0, #CACHE_DLINESIZE - 1\n \
tst r0, #32 - 1\n \
mcrne p15, 0, r0, c7, c10, 1 @ clean D entry\n \
@ tst r1, #CACHE_DLINESIZE - 1\n \
tst r1, #32 - 1\n \
mcrne p15, 0, r1, c7, c10, 1 @ clean D entry\n \
@ bic r0, r0, #CACHE_DLINESIZE - 1\n \
bic r0, r0, #32 - 1\n \
1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry\n \
@ add r0, r0, #CACHE_DLINESIZE\n \
add r0, r0, #32\n \
cmp r0, r1\n \
blo 1b\n \
mcr p15, 0, r0, c7, c10, 4 @ drain WB\n \
mov pc, lr\n \
");
/*
* dma_clean_range(start, end)
*
* Clean the specified virtual address range.
*
* - start - virtual start address
* - end - virtual end address
*
* (same as v4wb)
ENTRY(arm926_dma_clean_range)
*/
asm("\n \
.global arm926_dma_clean_range\n \
arm926_dma_clean_range:\n \
@ bic r0, r0, #CACHE_DLINESIZE - 1\n \
bic r0, r0, #32 - 1\n \
1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry\n \
@ add r0, r0, #CACHE_DLINESIZE\n \
add r0, r0, #32\n \
cmp r0, r1\n \
blo 1b\n \
mcr p15, 0, r0, c7, c10, 4 @ drain WB\n \
mov pc, lr\n \
");
/*
* dma_flush_range(start, end)
*
* Clean and invalidate the specified virtual address range.
*
* - start - virtual start address
* - end - virtual end address
ENTRY(arm926_dma_flush_range)
*/
asm("\n \
.global arm926_dma_flush_range\n \
arm926_dma_flush_range:\n \
@ bic r0, r0, #CACHE_DLINESIZE - 1\n \
bic r0, r0, #32 - 1\n \
1:\n \
mcr p15, 0, r0, c7, c14, 1 @ clean+invalidate D entry\n \
@ add r0, r0, #CACHE_DLINESIZE\n \
add r0, r0, #32\n \
cmp r0, r1\n \
blo 1b\n \
mcr p15, 0, r0, c7, c10, 4 @ drain WB\n \
mov pc, lr\n \
");
#endif
如果是别的cpu型号,依然可以从arch/arm/mm/proc-xxxx.S 或者arch/arm/mm/cache-xx.S中找到相应定义.
直接按照上面格式把这几个函数挪过来就行了.注意asm()里面不要有空行,或者每一行都加\n \