嵌入式系统中的CACHE问题
3 解决的方法
根据上面的分析和讨论,可见问题正是由数据CACHE / RAM的不一致性引起的。虽然关掉CACHE就可以解决一致性的问题,并且能够减小程序开发的复杂度。但是一个高性能的系统是需要CACHE的,关掉CACHE会大大降低系统的性能。因此,本文仅讨论在程序中加入代码来克服一致性问题的方法。
可以采用以下几种加入代码的方法来解决一致性的问题本文使用WIND RIVER公司的嵌入式实时多任务操作系统VxWORKS,下面的函数都是VxWORKS提供的:
(1)对于时间上不是那么关键的程序段,可以先用下面的代码维护数据CACHE的一致性。
cacheInvalidate DATA_CACHE address bytes
/ 输入缓冲区/
...
cacheFlush DATA_CACHE address bytes
/输出缓冲区/
(2)对于时间上比较关键的程序段采用如下原则:在每次使用输出缓冲区前将其更新;在每次使用输入缓冲区前使其无效。
将缓冲区标示为“non-cacheable”可以防止一致性问题,这需要MMU支持。在分配缓冲区时,将其标示为“non-cacheable”即可。然而,动态缓冲区在释放时要标为“cacheable”,否则内存总会产生大量的缓冲区碎片。
下面给出一个高性能的驱动程序例子,它把更新/无效的概念进行了扩展。不是对整个CACHE系统,而是对每一个缓冲区都这样做。即通过分配对CACHE安全的缓冲区,在一个缓冲区的基础上操作,从而防止了不需要的更新/无效操作。在这个例子中使用了CACHE库中的函数cacheDMAMalloc ,宏CACHE_DMA_INVALIDATE和CACHE_DMA_FLUSH实现一致性。在第4行调用函数cacheDMAMalloc 后,如果指针返回为非空,则说明分配到了一块对于一致性问题来说是安全的缓冲区。
第7行驱动程序在缓冲区中写入要传给外部设备的数据,在第9行准备传给外设之前,驱动程序必须更新数据CACHE以保证要传的数据是在内存中,而不是在CACHE中。
当驱动程序准备读外设传给内存的数据,在第13行驱动程序处理这些数据之前,必须使数据CACHE中对应于输入缓冲区的那部分无效以消除这些包含过时内容的条目。之后,驱动程序才能安全地处理从内存中取来的输入数据。
1: STATUS drvExample pBuf
2: void pBuf / 缓冲区指针 /
3: { /*
4: pBuf = cacheDMAMalloc BUF_SIZE
5: if pBuf == NULL
6: return ERROR /内存分配失败/
7: /其它初始化代码和向发送缓冲区填数据/
8: CACHE_DMA_FLUSH pBuf BUF_SIZE
9: drvWrite pBuf /向外设发送数据/
10: …… / 其它代码 /
11: drvWait /等待外设来的数据/
12: CACHE_DMA_INVALIDATE pBuf BUF_SIZE
13: / 处理外设来的数据 /
14: cacheDMAFree pBuf /释放内存 /
15: return OK
16:}