一、序
写这篇文章的目的是今天偶来间看到了 开源库https://github.com/armink/SFUD.git ,遥想起当年入职时的前几个任务就是针对自家的spi flash controller 写一个driver来驱动外置的flash,因为code 固化在rom 中,所以尽量需要兼容不同厂家的flash型号,当时也是折腾了很久。今天有幸看到这份源码,还是满满的回忆。
二. 源码剖析
2.1 初始化
初始化的核心函数在hardware_init中,也体现了识别板载flash型号的核心策略:
首先读取 JEDEC ID,其中包含了manufacturer ID, memory type ID 和flash capacity ID;
然后判断当前flash是否支持SFDP。SFDP标准是JEDEC (固态技术协会)制定的串行 Flash 功能的参数表标准,最新版 V1.6B ([点击这里查看](https://www.jedec.org/standards-documents/docs/jesd216b))。该标准规定了,每个 Flash 中会存在一个参数表,该表中会存放 Flash 容量、写粒度、擦除命令、地址模式等 Flash 规格参数。目前,除了部分厂家旧款 Flash 型号会不支持该标准,其他绝大多数新出厂的 Flash 均已支持 SFDP 标准。所以该库在初始化时会优先读取 SFDP 表参数。
如果该 Flash 不支持 SFDP 标准,SFUD 会查询配置文件 中提供的 Flash 参数信息表 中是否支持该款 Flash。如果不支持,则可以在配置文件中添加该款 Flash 的参数信息。获取到了 Flash 的规格参数后,就可以实现对 Flash 的全部操作。
/**
* hardware initialize
*/
static sfud_err hardware_init(sfud_flash *flash) {
extern sfud_err sfud_spi_port_init(sfud_flash * flash);
sfud_err result = SFUD_SUCCESS;
size_t i;
result = sfud_spi_port_init(flash);
if (result != SFUD_SUCCESS) {
return result;
}
/* if the user don't configure flash chip information then using SFDP parameter or static flash parameter table */
if (flash->chip.capacity == 0 || flash->chip.write_mode == 0 || flash->chip.erase_gran == 0
|| flash->chip.erase_gran_cmd == 0) {
/* read JEDEC ID include manufacturer ID, memory type ID and flash capacity ID */
result = read_jedec_id(flash);
if (result != SFUD_SUCCESS) {
return result;
}
#ifdef SFUD_USING_SFDP
extern bool sfud_read_sfdp(sfud_flash *flash);
/* read SFDP parameters */
if (sfud_read_sfdp(flash)) {
flash->chip.name = NULL;
flash->chip.capacity = flash->sfdp.capacity;
/* only 1 byte or 256 bytes write mode for SFDP */
if (flash->sfdp.write_gran == 1) {
flash->chip.write_mode = SFUD_WM_BYTE;
} else {
flash->chip.write_mode = SFUD_WM_PAGE_256B;
}
/* find the the smallest erase sector size for eraser. then will use this size for erase granularity */
flash->chip.erase_gran = flash->sfdp.eraser[0].size;
flash->chip.erase_gran_cmd = flash->sfdp.eraser[0].cmd;
for (i = 1; i < SFUD_SFDP_ERASE_TYPE_MAX_NUM; i++) {
if (flash->sfdp.eraser[i].size != 0 && flash->chip.erase_gran > flash->sfdp.eraser[i].size) {
flash-&