123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641 |
- /*
- *********************************************************************************************************
- *
- * 模块名称 : NOR Flash驱动模块
- * 文件名称 : bsp_nor_flash.c
- * 版 本 : V1.0
- * 说 明 : 安富莱STM32-V5开发板标配的NOR Flash 为 S29GL128P10TFI01 容量16M字节,16Bit,100ns速度
- * 物理地址 : 0x6400 0000
- * 修改记录 :
- * 版本号 日期 作者 说明
- * V1.0 2013-02-01 armfly 正式发布
- *
- * Copyright (C), 2013-2014, 安富莱电子 www.armfly.com
- *
- *********************************************************************************************************
- */
- /*
- S29GL128P 内存组织结构: 每个扇区128K字节,一共128个扇区。总容量为 16M字节。按16Bit访问。
- 挂在STM32上,对应的物理地址范围为 : 0x6400 0000 - 0x64FF FFFF. 只能按16Bit模式访问。
- */
- #include "nor_flash.h"
- #include "interface.h"
- #include <inttypes.h>
- #define ADDR_SHIFT(A) (NOR_FLASH_ADDR + (2 * (A)))
- #define NOR_WRITE(Address, Data) (*(__IO uint16_t *)(Address) = (Data))
- /* 判忙时的执行语句循环次数 */
- #define BlockErase_Timeout ((uint32_t)0x00A00000)
- #define ChipErase_Timeout ((uint32_t)0x30000000)
- #define Program_Timeout ((uint32_t)0x00001400)
- /* PD6 是NOR Flash输出到STM32的忙信号, 通过GPIO查询方式判忙 */
- #define NOR_IS_BUSY() (GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_6) == RESET)
- static void NOR_QuitToReadStatus(void);
- static uint8_t NOR_GetStatus(uint32_t Timeout);
- /*
- *********************************************************************************************************
- * 函 数 名: bsp_InitNorFlash
- * 功能说明: 配置连接外部NOR Flash的GPIO和FSMC
- * 形 参: 无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- void nor_flash_init(void)
- {
- FSMC_NORSRAMInitTypeDef FSMC_NORSRAMInitStructure;
- FSMC_NORSRAMTimingInitTypeDef p;
- /* NOR Flash 的 GPIO :
- PD0/FSMC_D2
- PD1/FSMC_D3
- PD4/FSMC_NOE
- PD5/FSMC_NWE
- PD6/FSMC_NWAIT - 忙信号,配置为GPIO,输入模式,通过软件查询方式判忙
- PD8/FSMC_D13
- PD9/FSMC_D14
- PD10/FSMC_D15
- PD11/FSMC_CLE/FSMC_A16
- PD12/FSMC_ALE/FSMC_A17
- PD13/FSMC_A18
- PD14/FSMC_D0
- PD15/FSMC_D1
- PE3/FSMC_A19
- PE4/FSMC_A20
- PE5/FSMC_A21
- PE6/FSMC_A22
- PE7/FSMC_D4
- PE8/FSMC_D5
- PE9/FSMC_D6
- PE10/FSMC_D7
- PE11/FSMC_D8
- PE12/FSMC_D9
- PE13/FSMC_D10
- PE14/FSMC_D11
- PE15/FSMC_D12
- PF0/FSMC_A0
- PF1/FSMC_A1
- PF2/FSMC_A2
- PF3/FSMC_A3
- PF4/FSMC_A4
- PF5/FSMC_A5
- PF12/FSMC_A6
- PF13/FSMC_A7
- PF14/FSMC_A8
- PF15/FSMC_A9
- PG0/FSMC_A10
- PG1/FSMC_A11
- PG2/FSMC_A12
- PG3/FSMC_A13
- PG4/FSMC_A14
- PG5/FSMC_A15
- PG9/FSMC_NE2 - 片选信号
- */
- /*-- FSMC Configuration ------------------------------------------------------*/
- p.FSMC_AddressSetupTime = 0x06; /* 0x05正常, 0x04 出错 */
- p.FSMC_AddressHoldTime = 0x01;
- p.FSMC_DataSetupTime = 0x0C; /* 0x0B正常, 0x0A 出错 */
- p.FSMC_BusTurnAroundDuration = 0x00;
- p.FSMC_CLKDivision = 0x00;
- p.FSMC_DataLatency = 0x00;
- p.FSMC_AccessMode = FSMC_AccessMode_B;
- FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM2;
- FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;
- FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_NOR;
- FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;
- FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable;
- FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable;
- FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
- FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;
- FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;
- FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;
- FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;
- FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable;
- FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;
- FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &p;
- FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &p;
- FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure);
- /*!< Enable FSMC Bank1_SRAM2 Bank */
- FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM2, ENABLE);
- }
- /*
- *********************************************************************************************************
- * 函 数 名: NOR_ReadID
- * 功能说明: 读取NOR Flash的器件ID
- * 形 参: 无
- * 返 回 值: 器件ID,32Bit, 高8bit 是Manufacturer_Code, 低24bit是器件ID
- *********************************************************************************************************
- */
- uint32_t NOR_ReadID(void)
- {
- uint32_t uiID;
- uint8_t id1, id2, id3, id4;
- NOR_WRITE(ADDR_SHIFT(0x0555), 0x00AA);
- NOR_WRITE(ADDR_SHIFT(0x02AA), 0x0055);
- NOR_WRITE(ADDR_SHIFT(0x0555), 0x0090);
- id1 = *(__IO uint16_t *)ADDR_SHIFT(0x0000);
- id2 = *(__IO uint16_t *)ADDR_SHIFT(0x0001);
- id3 = *(__IO uint16_t *)ADDR_SHIFT(0x000E);
- id4 = *(__IO uint16_t *)ADDR_SHIFT(0x000F);
- uiID = ((uint32_t)id1 << 24) | ((uint32_t)id2 << 16) | ((uint32_t)id3 << 8) | id4;
- NOR_WRITE(NOR_FLASH_ADDR, 0x00F0); /* 退出ID模式 */
- return uiID;
- }
- /*
- *********************************************************************************************************
- * 函 数 名: NOR_QuitToReadStatus
- * 功能说明: 复位NOR,退到读状态
- * 形 参: 无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- static void NOR_QuitToReadStatus(void)
- {
- NOR_WRITE(ADDR_SHIFT(0x00555), 0x00AA);
- NOR_WRITE(ADDR_SHIFT(0x002AA), 0x0055);
- NOR_WRITE(NOR_FLASH_ADDR, 0x00F0);
- }
- /*
- *********************************************************************************************************
- * 函 数 名: NOR_GetStatus
- * 功能说明: 读取NOR的操作状态
- * 形 参: 无
- * 返 回 值: 0表示成功. NOR_SUCCESS, NOR_ERROR, NOR_TIMEOUT
- *********************************************************************************************************
- */
- static uint8_t NOR_GetStatus(uint32_t Timeout)
- {
- uint16_t val1 = 0x00;
- uint16_t val2 = 0x00;
- uint8_t status = NOR_ONGOING;
- uint32_t timeout = Timeout;
- /* 等待NOR输出忙信号,高电平时等待。避免NOR的忙信号还未反映过来导致CPU提前认为不忙了 */
- while ((!NOR_IS_BUSY()) && (timeout > 0))
- {
- timeout--;
- }
- /* 等待NOR忙信号结束,低电平时等待 */
- timeout = Timeout;
- while (NOR_IS_BUSY() && (timeout > 0))
- {
- timeout--;
- }
- /*
- - DQ 6 编程时跳变
- - DQ 6 和 DQ 2 在擦除时跳变
- - DQ 2 在擦除挂起时跳变
- - DQ 1 在编程错误时置1
- - DQ 5 在超时时置1
- */
- /* 通过读取DQ6, DQ5 的数据位是否存在翻转现象判断NOR 内部操作是否完成。如果正忙,则第2次读和第1次读的数据不同 */
- while ((Timeout != 0x00) && (status != NOR_SUCCESS))
- {
- Timeout--;
- /* Read DQ6 */
- val1 = *(__IO uint16_t *)(NOR_FLASH_ADDR);
- val2 = *(__IO uint16_t *)(NOR_FLASH_ADDR);
- /* If DQ6 did not toggle between the two reads then return NOR_Success */
- if ((val1 & 0x0040) == (val2 & 0x0040))
- {
- return NOR_SUCCESS;
- }
- /* Read DQ2 */
- if ((val1 & 0x0020) != 0x0020)
- {
- status = NOR_ONGOING;
- }
- val1 = *(__IO uint16_t *)(NOR_FLASH_ADDR);
- val2 = *(__IO uint16_t *)(NOR_FLASH_ADDR);
- if ((val1 & 0x0040) == (val2 & 0x0040))
- {
- return NOR_SUCCESS;
- }
- else if ((val1 & 0x0020) == 0x0020)
- {
- status = NOR_ERROR;
- NOR_QuitToReadStatus();
- }
- }
- if (Timeout == 0x00)
- {
- status = NOR_TIMEOUT;
- NOR_QuitToReadStatus();
- }
- /* 返回操作状态 */
- return (status);
- }
- /*
- *********************************************************************************************************
- * 函 数 名: NOR_EraseChip
- * 功能说明: 擦除NOR Flash整个芯片
- * 形 参: 无
- * 返 回 值: 0表示成功
- *********************************************************************************************************
- */
- uint8_t NOR_EraseChip(void)
- {
- NOR_WRITE(ADDR_SHIFT(0x0555), 0x00AA);
- NOR_WRITE(ADDR_SHIFT(0x02AA), 0x0055);
- NOR_WRITE(ADDR_SHIFT(0x0555), 0x0080);
- NOR_WRITE(ADDR_SHIFT(0x0555), 0x00AA);
- NOR_WRITE(ADDR_SHIFT(0x02AA), 0x0055);
- NOR_WRITE(ADDR_SHIFT(0x0555), 0x0010);
- return (NOR_GetStatus(ChipErase_Timeout));
- }
- /*
- *********************************************************************************************************
- * 函 数 名: NOR_StartEraseChip
- * 功能说明: 开始擦除NOR Flash整个芯片, 不等待结束
- * 形 参: 无
- * 返 回 值: 0表示成功
- *********************************************************************************************************
- */
- void NOR_StartEraseChip(void)
- {
- NOR_WRITE(ADDR_SHIFT(0x0555), 0x00AA);
- NOR_WRITE(ADDR_SHIFT(0x02AA), 0x0055);
- NOR_WRITE(ADDR_SHIFT(0x0555), 0x0080);
- NOR_WRITE(ADDR_SHIFT(0x0555), 0x00AA);
- NOR_WRITE(ADDR_SHIFT(0x02AA), 0x0055);
- NOR_WRITE(ADDR_SHIFT(0x0555), 0x0010);
- NOR_GetStatus(1000);
- }
- /*
- *********************************************************************************************************
- * 函 数 名: NOR_CheckComplete
- * 功能说明: 检测擦除是否完成
- * 形 参: 无
- * 返 回 值: 0表示成功 NOR_SUCCESS, NOR_ERROR, NOR_TIMEOUT
- *********************************************************************************************************
- */
- uint8_t NOR_CheckStatus(void)
- {
- uint16_t val1 = 0x00;
- uint16_t val2 = 0x00;
- uint8_t status = NOR_ONGOING;
- uint32_t timeout = 10;
- /*
- - DQ 6 编程时跳变
- - DQ 6 和 DQ 2 在擦除时跳变
- - DQ 2 在擦除挂起时跳变
- - DQ 1 在编程错误时置1
- - DQ 5 在超时时置1
- */
- /* 通过读取DQ6, DQ5 的数据位是否存在翻转现象判断NOR 内部操作是否完成。如果正忙,则第2次读和第1次读的数据不同 */
- while ((timeout != 0x00) && (status != NOR_SUCCESS))
- {
- timeout--;
- /* Read DQ6 */
- val1 = *(__IO uint16_t *)(NOR_FLASH_ADDR);
- val2 = *(__IO uint16_t *)(NOR_FLASH_ADDR);
- /* If DQ6 did not toggle between the two reads then return NOR_Success */
- if ((val1 & 0x0040) == (val2 & 0x0040))
- {
- return NOR_SUCCESS;
- }
- /* Read DQ2 */
- if ((val1 & 0x0020) != 0x0020)
- {
- status = NOR_ONGOING;
- }
- val1 = *(__IO uint16_t *)(NOR_FLASH_ADDR);
- val2 = *(__IO uint16_t *)(NOR_FLASH_ADDR);
- if ((val1 & 0x0040) == (val2 & 0x0040))
- {
- return NOR_SUCCESS;
- }
- else if ((val1 & 0x0020) == 0x0020)
- {
- status = NOR_ERROR;
- NOR_QuitToReadStatus();
- }
- }
- if (timeout == 0x00)
- {
- status = NOR_TIMEOUT;
- // NOR_QuitToReadStatus();
- }
- /* 返回操作状态 */
- return (status);
- }
- /*
- *********************************************************************************************************
- * 函 数 名: NOR_EraseSector
- * 功能说明: 擦除NOR Flash指定的扇区
- * 形 参: 扇区地址
- * 返 回 值: NOR_SUCCESS, NOR_ERROR, NOR_TIMEOUT
- *********************************************************************************************************
- */
- uint8_t NOR_EraseSector(uint32_t _uiBlockAddr)
- {
- NOR_WRITE(ADDR_SHIFT(0x0555), 0x00AA);
- NOR_WRITE(ADDR_SHIFT(0x02AA), 0x0055);
- NOR_WRITE(ADDR_SHIFT(0x0555), 0x0080);
- NOR_WRITE(ADDR_SHIFT(0x0555), 0x00AA);
- NOR_WRITE(ADDR_SHIFT(0x02AA), 0x0055);
- NOR_WRITE((NOR_FLASH_ADDR + _uiBlockAddr), 0x30);
- return (NOR_GetStatus(BlockErase_Timeout));
- }
- /*
- *********************************************************************************************************
- * 函 数 名: NOR_ReadByte
- * 功能说明: 读取单字节数据
- * 形 参: _uiWriteAddr : 偏移地址[0, 16*1024*1024 - 2]; 编程地址可以为偶数,也可以为奇数。
- * 返 回 值: 读取到的数据
- *********************************************************************************************************
- */
- uint8_t NOR_ReadByte(uint32_t _uiWriteAddr)
- {
- uint16_t usHalfWord;
- if (_uiWriteAddr % 2) /* 奇数地址 */
- {
- usHalfWord = *(uint16_t *)(NOR_FLASH_ADDR + _uiWriteAddr - 1);
- return (usHalfWord >> 8); /* 取高8Bit */
- }
- else /* 偶数地址 */
- {
- usHalfWord = *(uint16_t *)(NOR_FLASH_ADDR + _uiWriteAddr);
- return usHalfWord; /* 取低8Bit */
- }
- }
- /*
- *********************************************************************************************************
- * 函 数 名: NOR_ReadBuffer
- * 功能说明: 连续读取NOR Flash
- * 形 参: _pBuf : 字节型数据缓冲区,用于存放读出的数据
- * _uiWriteAddr : 偏移地址[0, 16*1024*1024 - 2]; 编程地址可以为偶数,也可以为奇数。
- * _uiBytes : 字节大小
- * 返 回 值: 读取到的数据
- *********************************************************************************************************
- */
- void NOR_ReadBuffer(uint8_t *_pBuf, uint32_t _uiWriteAddr, uint32_t _uiBytes)
- {
- uint16_t usHalfWord;
- uint16_t *pNor16;
- uint32_t i;
- uint32_t uiNum;
- uiNum = _uiBytes;
- /* 处理首字节 */
- if (_uiWriteAddr % 2) /* 奇数地址 */
- {
- usHalfWord = *(uint16_t *)(NOR_FLASH_ADDR + _uiWriteAddr - 1);
- *_pBuf++ = (usHalfWord >> 8); /* 取高8Bit */
- uiNum--;
- _uiWriteAddr++; /* 变为偶数 */
- }
- /* 按照双字节模式连续读取NOR数据至缓冲区_pBuf */
- pNor16 = (uint16_t *)(NOR_FLASH_ADDR + _uiWriteAddr);
- for (i = 0; i < uiNum / 2; i++)
- {
- usHalfWord = *pNor16++;
- *_pBuf++ = usHalfWord;
- *_pBuf++ = usHalfWord >> 8;
- uiNum -= 2;
- }
- /* 处理最后1个字节 */
- if (uiNum == 1)
- {
- *_pBuf++ = *pNor16;
- }
- }
- /*
- *********************************************************************************************************
- * 函 数 名: NOR_WriteHalfWord
- * 功能说明: 半字编程. 编程前执行解锁命令序列。编程完毕后,自动退到读取模式。半字编程可以是随机地址。
- * 编程前需要保证存储单元是全0xFF状态。可以重复编程相同的数据。
- * 形 参: _uiWriteAddr : 偏移地址[0, 16*1024*1024 - 2]; 编程地址必须为偶数
- * _usData : 数据 16Bit
- *
- * 返 回 值: NOR_SUCCESS, NOR_ERROR, NOR_TIMEOUT
- *********************************************************************************************************
- */
- uint8_t NOR_WriteHalfWord(uint32_t _uiWriteAddr, uint16_t _usData)
- {
- NOR_WRITE(ADDR_SHIFT(0x0555), 0x00AA);
- NOR_WRITE(ADDR_SHIFT(0x02AA), 0x0055);
- NOR_WRITE(ADDR_SHIFT(0x0555), 0x00A0);
- NOR_WRITE(NOR_FLASH_ADDR + _uiWriteAddr, _usData);
- return (NOR_GetStatus(Program_Timeout));
- }
- /*
- *********************************************************************************************************
- * 函 数 名: NOR_WriteByte
- * 功能说明: 字节编程. 编程前需要保证存储单元是全0xFF状态。可以重复编程相同的数据。
- * 形 参: _uiWriteAddr : 偏移地址[0, 16*1024*1024 - 1]; 编程地址可以为奇数也可以为偶数
- * _usData : 数据 16Bit
- *
- * 返 回 值: NOR_SUCCESS, NOR_ERROR, NOR_TIMEOUT
- *********************************************************************************************************
- */
- uint8_t NOR_WriteByte(uint32_t _uiWriteAddr, uint8_t _ucByte)
- {
- uint16_t usHalfWord;
- if (_uiWriteAddr % 2) /* 奇数地址 */
- {
- /* 读出2字节数据,然后改写高字节,维持以前的低字节数据不变 */
- usHalfWord = *(uint16_t *)(NOR_FLASH_ADDR + _uiWriteAddr - 1);
- usHalfWord &= 0x00FF;
- usHalfWord |= (_ucByte << 8);
- }
- else
- {
- /* 读取NOR原始数据,保留高字节 */
- usHalfWord = *(uint16_t *)(NOR_FLASH_ADDR + _uiWriteAddr);
- usHalfWord &= 0xFF00;
- usHalfWord |= _ucByte;
- }
- return NOR_WriteHalfWord(_uiWriteAddr, usHalfWord);
- }
- /*
- *********************************************************************************************************
- * 函 数 名: NOR_WriteInPage.
- * 功能说明: 页面内编程(64字节一个页面). 编程前需要保证存储单元是全0xFF状态。可以重复编程相同的数据。
- * 形 参: pBuffer : 数据存放在此缓冲区
- * _uiWriteAddr : 偏移地址, 必须是偶数开始
- * _usNumHalfword : 数据格式,双字节为1个单位. 值域: 1-32
- *
- * 返 回 值: NOR_SUCCESS, NOR_ERROR, NOR_TIMEOUT
- *********************************************************************************************************
- */
- uint8_t NOR_WriteInPage(uint16_t *pBuffer, uint32_t _uiWriteAddr, uint16_t _usNumHalfword)
- {
- uint32_t lastloadedaddress;
- uint32_t currentaddress;
- uint32_t endaddress;
- /* pdf 表7.7 写入缓冲器编程
- 写入缓冲器编程允许系统在一个编程操作中写入最多32 个字。与标准的“ 字” 编程算法相比,这可以有效地
- 加快字编程速度。
- */
- if (_usNumHalfword > 32)
- {
- return NOR_ERROR;
- }
- if ((_uiWriteAddr % 2) != 0)
- {
- return NOR_ERROR;
- }
- _uiWriteAddr = _uiWriteAddr / 2;
- currentaddress = _uiWriteAddr;
- endaddress = _uiWriteAddr + _usNumHalfword - 1;
- lastloadedaddress = _uiWriteAddr;
- /* 解锁命令序列 */
- NOR_WRITE(ADDR_SHIFT(0x00555), 0x00AA);
- NOR_WRITE(ADDR_SHIFT(0x02AA), 0x0055);
- /* Write Write Buffer Load Command */
- NOR_WRITE(ADDR_SHIFT(_uiWriteAddr), 0x0025);
- NOR_WRITE(ADDR_SHIFT(_uiWriteAddr), (_usNumHalfword - 1));
- /* Load Data into NOR Buffer */
- while (currentaddress <= endaddress)
- {
- /* Store last loaded address & data value (for polling) */
- lastloadedaddress = currentaddress;
- NOR_WRITE(ADDR_SHIFT(currentaddress), *pBuffer++);
- currentaddress += 1;
- }
- NOR_WRITE(ADDR_SHIFT(lastloadedaddress), 0x29);
- return (NOR_GetStatus(Program_Timeout));
- }
- /*
- *********************************************************************************************************
- * 函 数 名: NOR_WriteBuffer
- * 功能说明: 连续编程操作。采取半字编程模式。
- * S29GL 支持64字节页面大小的连续编程。本函数暂时不支持页面编程。
- * 形 参: _pBuf : 8位数据缓冲区
- * _uiWriteAddr : 写入的存储单元首地址, 必须为偶数
- * _uiBytes : 字节个数
- * 返 回 值: NOR_SUCCESS, NOR_ERROR, NOR_TIMEOUT
- *********************************************************************************************************
- */
- uint8_t NOR_WriteBuffer(uint8_t *_pBuf, uint32_t _uiWriteAddr, uint32_t _uiBytes)
- {
- uint16_t usHalfWord;
- uint32_t i;
- uint32_t uiNum;
- uint8_t ucStatus;
- uiNum = _uiBytes;
- /* 处理首字节 */
- if (_uiWriteAddr % 2) /* 奇数地址 */
- {
- /* 读出2字节数据,然后改写高字节,维持以前的低字节数据不变 */
- usHalfWord = *(uint16_t *)(NOR_FLASH_ADDR + _uiWriteAddr - 1);
- usHalfWord &= 0x00FF;
- usHalfWord |= ((*_pBuf++) << 8);
- ucStatus = NOR_WriteHalfWord(_uiWriteAddr - 1, usHalfWord);
- if (ucStatus != NOR_SUCCESS)
- {
- goto err_quit;
- }
- uiNum--;
- _uiWriteAddr++; /* 变为偶数 */
- }
- /* 按照双字节模式连续编程NOR数据 */
- for (i = 0; i < uiNum / 2; i++)
- {
- usHalfWord = *_pBuf++;
- usHalfWord |= ((*_pBuf++) << 8);
- ucStatus = NOR_WriteHalfWord(_uiWriteAddr, usHalfWord);
- if (ucStatus != NOR_SUCCESS)
- {
- goto err_quit;
- }
- _uiWriteAddr += 2;
- }
- /* 处理最后1个字节 */
- if (uiNum % 2)
- {
- /* 读取NOR原始数据,保留高字节 */
- usHalfWord = *(uint16_t *)(NOR_FLASH_ADDR + _uiWriteAddr);
- usHalfWord &= 0xFF00;
- usHalfWord |= (*_pBuf++);
- ucStatus = NOR_WriteHalfWord(_uiWriteAddr, usHalfWord);
- if (ucStatus != NOR_SUCCESS)
- {
- goto err_quit;
- }
- }
- ucStatus = NOR_SUCCESS;
- err_quit:
- return ucStatus;
- }
- /***************************** 安富莱电子 www.armfly.com (END OF FILE) *********************************/
|