外部記憶體管理
最近在研究CC2541,
希望能記錄一些連結記錄,
本來在內部設定一個陣列,
旦發現只要CC2541裝置一斷線資料就全清空了,
所以想存在外部記憶體,
因為希望每個來拜訪的主機都能分別記錄並抓取、修改資料,
所以需要每次都能依不同的主機去分辨並正確的從指定的位址開始撈取資料,
但本身完全沒有學過記憶體管理相關課程,
聽說要利用I2C來把資料傳到外部記憶體並用FAT表來管理?
有人能告訴我需要從哪個方向或是從哪些資料開始研究呢?
一時間不知道從哪開始下手,
謝謝。
首先2541有闪存控制器,你可以把数据直接记录在flash中,然后如果你的数据量比较大的话,可以外挂一个I2C接口的EEPROM。至于FAT,虽然我也不太懂,但我觉得没有必要。
請問要如何存取flash?
因為每次連結需要更動記憶體中某一部分資料,
要如何指定存取範圍?
osal提供了一些已经定义的flash空间和读写API,调用就可以了,具体请看osal的api文档。也可以研究cc2541数据手册中的闪存控制器章节,学习flash空间的编址方式,再根据代码的flash占用量,就可以知道哪些地址是可以使用的了。
謝謝,我查了一下API,找到下列關於FLASH的函數
void HalFlashRead(uint8 pg, uint16 offset, uint8 *buf, uint16 cnt);
void HalFlashWrite(uint16 addr, uint8 *buf, uint16 cnt);
void HalFlashErase(uint8 pg);
我想請問一下為什麼READ要寫入頁碼,WRITE卻不用呢?
那我怎麼知道我到底寫到哪?讀的時候又怎麼知道要從哪一頁讀取?
是这样的,物理上,flash分为8个bank区(bank0~bank7),每个区32KB,code空间同时只能映射两个区(64K)。闪存控制器把flash用18位编址(256K),并分为128个页面,每个页面2048字节,每个bank区有16个页面。闪存控制器可对flash进行erase和write的操作。当执行erase时,只能通过页面寻址,一次擦除全部2048字节。当执行write操作时,只能使用18位地址的高16位进行寻址,一次寻址四个字节(32位字)。至于读flash,则需要将你要读的flash地址所在的bank区映射到xdata空间的高32kb上, HalFlashRead(uint8 pg, uint16 offset, uint8 *buf, uint16 cnt)页码参数就是为了确定在哪个区以便映射。当然,通过16位的地址也可以知道所在的区,但是osal并不支持这样做。这么说你明白了吗
FLASH的128頁面中,是否有些頁面是保留的?哪些頁面是空的?
我的是板子CC2541,
如果沒用過初始值是0X00嗎?還是0XFF?
flash擦除后的值为0xFF,最后一个页面似乎有一些固有的信息,不允许读写,建议你根据自己代码量的大小,在自己代码结束的下一个页面进行存取。
我後來試出0X4A似乎整頁是0XFF,所以就利用那夜去做讀寫,
但我發現第一次讀取正常,但如果我想把某一段覆寫,那段值就全部變成0X00,
請問這是什麼原因?
寫入的值就不能修改只能HalFlashErase整頁在重寫嗎?
Flash的特点就是页写,即使你只写一个字节,那一整页都会被重新写一遍空字节。目前没有接触过具有字节写功能的flash,所以你要修改某一段,最好是读——改——写三个步骤,才能保证原来的数据不被破坏。
可是我在寫的時候我分開寫正常,
如果我只寫
HalFlashWrite(0x9400, TEST1, 2);
HalFlashWrite(0x9402, TEST2, 2);
這樣HalFlashRead(0x4A, 0x0000, RESULT, 16);讀出來的結果是
9400的值跟9402的值都正常是TEST1跟TEST2。
但是如果我9402寫第二次,
HalFlashWrite(0x9400, TEST1, 2);
HalFlashWrite(0x9402, TEST2, 2);
HalFlashWrite(0x9402, TEST3, 2);
這樣HalFlashRead(0x4A, 0x0000, RESULT, 16);讀出來的結果是
9400的值正常是TEST1,9402的值既不是TEST2也不是TEST3而是0X00。
所以好像不是頁寫?HalFlashWrite(0x9402, TEST2, 2);不是指定絕對位址嗎?
那我就不清楚了,从硬件上来说,flash应该是不支持字节写的,我还是建议先把这一页所有的有效数据读出来,修改相应的字节,再重新写。
謝謝,確實我把該頁資料抓出來後整個ERASE掉,
再重新寫入就正常了~~感謝。