设计要点
数据读写时启用
SPI NAND / SPI NOR 驱动通过发送命令的方式与 SPI NAND / SPI NOR 器件进行交互,从而实现数据的读写。 在使能 SPI_ENC 之后,SPI NAND / SPI NOR 驱动需要进行区分:
-
非存储数据的 SPI 传输,不启动 SPI_ENC,按照原有驱动的流程执行
-
存储数据的 SPI 传输,启动 SPI_ENC 进行加密或者解密
因此 SPI NAND / SPI NOR 驱动需要做一些改动,在对存储数据进行读写时,使用 Crypto API 启动 SPI_ENC。
以 SPI NAND 为例:
spinand_flash_init(); |-> drv_spienc_init()
spinand_read_page(); |-> SPINAND_FLASH_OPS->read_dataload(); |-> cpos = 1 + 2 + (SPINAND_FLASH_DUMMYBYTE * 8); /* cpos = cmd.nbyte + addr.nbyte + dummy.nbyte */ |-> drv_spienc_set_cfg(0, page * SPINAND_FLASH_PAGE_SIZE, cpos, data_len); /* 配置本次加密数据信息 */ |-> drv_spienc_start(); /* 启动 SPI_ENC */ |-> SPINAND_FLASH_OPS->read_quadoutput(qspi, 0, buf, data_len); /* 调用标准 SPI API 进行数据传输 */ |-> drv_spienc_stop(); /* 停止 SPI_ENC */ |-> drv_spienc_check_empty() /* 检查是否为空 page */
spinand_write_page(); |-> SPINAND_FLASH_OPS->program_dataload(); |-> cpos = 1 + 2 + (SPINAND_FLASH_DUMMYBYTE * 8); /* cpos = cmd.nbyte + addr.nbyte + dummy.nbyte */ |-> drv_spienc_set_cfg(0, page * SPINAND_FLASH_PAGE_SIZE, cpos, data_len); /* 配置本次加密数据信息 */ |-> drv_spienc_start(); /* 启动 SPI_ENC */ |-> SPINAND_FLASH_OPS->program_dataload(); /* 调用标准 SPI API 进行数据传输 */ |-> drv_spienc_stop(); /* 停止 SPI_ENC */ |-> SPINAND_FLASH_OPS->program_execute();
空数据块的检测
SPI NAND / SPI NOR 在执行了擦除之后,存储单元上的数据被认为是空的,值都是 0xFF
。
但是在使用过程中,读取程序并不一定知道所读取的区域是否是被擦除过,因此在使能了 SPI_ENC 之后, 通过 SPI 读取回来该区域的数据都是被 SPI_ENC
解密后的数据。原本是被擦除后的 0xFF
, 读回来的却是其他数据。
带来的问题:
有些程序,如文件系统,会判断读回来的数据是否都为 0xFF
,如果是,则认为是未使用的块,做特殊处理。
现在读回来的数据却被改变了,会导致原来的处理逻辑全部失效。
为了解决上述问题,SPI_ENC 提供了一个空块检测功能。如下图所示:
-
首先按照正常的流程读取一块数据
-
传输完成之后,检查 SPI_ENC 的状态,如果提示解密前的所有数据都是
0xFF
,则软件将读取的结果全部置为0xFF

相关的软件操作,在 spinand_enc_read()
和 spi_nor_enc_read()
中完成。