1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
|
#include "main.h"
#define BUFFERSIZE 4096
ESMC_HandleTypeDef hesmc;
ESMC_InitTypeDef ESMC_initTypeDef;
uint8_t aRxBuffer[BUFFERSIZE];
uint8_t aTxBuffer[BUFFERSIZE];
uint8_t flashStatus;
/* 函数声明 */
static void APP_EsmcInit(void);
static void APP_WriteEnable(void);
static void APP_EraseSector(uint32_t address);
static void APP_PageProgram(uint8_t *pdata, uint32_t addr, uint32_t Nbytes);
static void APP_DataRead(uint8_t *pData, uint32_t address, uint32_t nBytes);
static HAL_StatusTypeDef APP_DataCheck(uint8_t *pSrc, uint8_t *pDst, uint32_t length);
static void APP_SetFlashStatus(uint8_t status, uint8_t comm);
static uint8_t APP_GetFlashStatus(uint8_t comm);
int main(void)
{
uint32_t i = 0, cnt = 0, progAddr = 0;
uint8_t *pData = NULL;
uint32_t address = 0;
HAL_Init();
BSP_LED_Init(LED_GREEN);
/* 准备测试数据 0,1,2,...,255 循环 */
for (i = 0; i < BUFFERSIZE; i++) aTxBuffer[i] = i % 256;
APP_EsmcInit(); /* 1. ESMC 初始化 */
APP_WriteEnable(); /* 2. 写使能 */
while (APP_GetFlashStatus(0x05) & 0x01) {} /* 等 BUSY 清 */
APP_EraseSector(address); /* 3. 扇区擦除(4KB)*/
while (APP_GetFlashStatus(P25Q64_READ_STATUS_REG_CMD) & 0x01) {}
/* 4. 开启 QE 位(状态寄存器1 的 bit1)*/
flashStatus = APP_GetFlashStatus(P25Q64_READ_STATUS_REG_1_CMD);
flashStatus |= 0x02;
APP_WriteEnable();
while (APP_GetFlashStatus(0x05) & 0x01) {}
APP_SetFlashStatus(flashStatus, P25Q64_WRITE_STATUS_REG_1_CMD);
while (APP_GetFlashStatus(P25Q64_READ_STATUS_REG_CMD) & 0x01) {}
/* 5. 分页编程(每页 256 字节)*/
cnt = BUFFERSIZE; progAddr = address; pData = aTxBuffer;
while (cnt / P25Q64_PAGE_SIZE > 0)
{
APP_PageProgram(pData, progAddr, P25Q64_PAGE_SIZE);
while (APP_GetFlashStatus(P25Q64_READ_STATUS_REG_CMD) & 0x01) {}
cnt -= P25Q64_PAGE_SIZE;
progAddr += P25Q64_PAGE_SIZE;
pData += P25Q64_PAGE_SIZE;
}
if (cnt > 0) {
APP_PageProgram(pData, progAddr, cnt);
while (APP_GetFlashStatus(P25Q64_READ_STATUS_REG_CMD) & 0x01) {}
}
/* 6. 读回并校验 */
APP_DataRead(aRxBuffer, address, BUFFERSIZE);
if (HAL_OK != APP_DataCheck(aRxBuffer, aTxBuffer, BUFFERSIZE))
{
BSP_LED_Off(LED_GREEN);
APP_ErrorHandler();
}
BSP_LED_On(LED_GREEN); /* 成功亮灯 */
while (1) {}
}
/* ---------- ESMC 初始化 ---------- */
static void APP_EsmcInit(void)
{
__HAL_RCC_ESMC_CLK_ENABLE();
hesmc.Instance = ESMC;
ESMC_initTypeDef.ClockPrescaler = 0x8; /* 时钟分频(决定 QSPI 速率)*/
ESMC_initTypeDef.ClockMode = ESMC_CLOCK_MODE_0; /* CPOL=0, CPHA=0 */
ESMC_initTypeDef.DualFlash = ESMC_DUALFLASH_DISABLE;
hesmc.Init = ESMC_initTypeDef;
HAL_ESMC_Init(&hesmc);
}
/* ---------- 读状态寄存器 ---------- */
static uint8_t APP_GetFlashStatus(uint8_t command)
{
ESMC_CommandTypeDef cmdStc = {0};
uint8_t status;
cmdStc.TransferFormat = ESMC_TRANSFER_FORMAT_SINGLE;
cmdStc.InstructionMode = ESMC_INSTRUCTION_SINGLE_LINE;
cmdStc.Instruction = command; /* 如 0x05 读状态 */
cmdStc.AddressMode = ESMC_ADDRESS_NONE;
cmdStc.DummyCycles = 0x0;
cmdStc.DdrMode = ESMC_DDR_DISABLE;
cmdStc.DataMode = ESMC_DATA_READ;
cmdStc.NbData = 1;
cmdStc.CSPinSel = ESMC_SELECT_PIN_CS0; /* 选 CS0(PA2) */
HAL_ESMC_Command(&hesmc, &cmdStc, 0x0000FFFF);
HAL_ESMC_Receive(&hesmc, &status, 0x0000FFFF);
return status;
}
/* ---------- 写状态寄存器 ---------- */
static void APP_SetFlashStatus(uint8_t status, uint8_t command)
{
ESMC_CommandTypeDef cmdStc = {0};
cmdStc.TransferFormat = ESMC_TRANSFER_FORMAT_SINGLE;
cmdStc.InstructionMode = ESMC_INSTRUCTION_SINGLE_LINE;
cmdStc.Instruction = command; /* 如 0x31 写状态1 */
cmdStc.AddressMode = ESMC_ADDRESS_NONE;
cmdStc.DataMode = ESMC_DATA_WRITE;
cmdStc.NbData = 1;
cmdStc.CSPinSel = ESMC_SELECT_PIN_CS0;
HAL_ESMC_Command(&hesmc, &cmdStc, 0x0000FFFF);
HAL_ESMC_Transmit(&hesmc, &status, 0x0000FFFF);
}
/* ---------- 写使能(06h)---------- */
static void APP_WriteEnable(void)
{
ESMC_CommandTypeDef commandStc = {0};
commandStc.TransferFormat = ESMC_TRANSFER_FORMAT_SINGLE;
commandStc.InstructionMode = ESMC_INSTRUCTION_SINGLE_LINE;
commandStc.Instruction = P25Q64_WRITE_ENABLE_CMD; /* 0x06 */
commandStc.AddressMode = ESMC_ADDRESS_NONE;
commandStc.DataMode = ESMC_DATA_NONE;
commandStc.CSPinSel = ESMC_SELECT_PIN_CS0;
HAL_ESMC_Command(&hesmc, &commandStc, 0x0000FFFF);
}
/* ---------- 扇区擦除(20h,4KB)---------- */
static void APP_EraseSector(uint32_t address)
{
ESMC_CommandTypeDef cmdStc = {0};
APP_WriteEnable();
cmdStc.TransferFormat = ESMC_TRANSFER_FORMAT_SINGLE;
cmdStc.InstructionMode = ESMC_INSTRUCTION_SINGLE_LINE;
cmdStc.Instruction = P25Q64_SECTOR_ERASE_4K_CMD; /* 0x20 */
cmdStc.AddressMode = ESMC_ADDRESS_SINGLE_LINE;
cmdStc.AddressSize = ESMC_ADDRESS_24_BITS;
cmdStc.Address = address;
cmdStc.DataMode = ESMC_DATA_NONE;
cmdStc.CSPinSel = ESMC_SELECT_PIN_CS0;
HAL_ESMC_Command(&hesmc, &cmdStc, 0x0000FFFF);
}
/* ---------- 四线页编程(32h)---------- */
static void APP_PageProgram(uint8_t *pData, uint32_t addr, uint32_t nBytes)
{
ESMC_CommandTypeDef cmdStc = {0};
APP_WriteEnable();
cmdStc.TransferFormat = ESMC_TRANSFER_FORMAT_QUAD; /* 四线传输数据 */
cmdStc.InstructionMode = ESMC_INSTRUCTION_SINGLE_LINE;/* 指令仍单线 */
cmdStc.Instruction = P25Q64_QUAD_INPUT_PAGE_PROG_CMD; /* 0x32 */
cmdStc.AddressMode = ESMC_ADDRESS_SINGLE_LINE;
cmdStc.AddressSize = ESMC_ADDRESS_24_BITS;
cmdStc.Address = addr;
cmdStc.DummyCycles = 0x0;
cmdStc.DataMode = ESMC_DATA_WRITE;
cmdStc.NbData = nBytes;
cmdStc.CSPinSel = ESMC_SELECT_PIN_CS0;
HAL_ESMC_Command(&hesmc, &cmdStc, 0x0000FFFF);
HAL_ESMC_Transmit(&hesmc, pData, 0x0000FFFF);
}
/* ---------- 四线快读(6Bh)---------- */
static void APP_DataRead(uint8_t *pData, uint32_t address, uint32_t nBytes)
{
ESMC_CommandTypeDef cmdStc = {0};
cmdStc.TransferFormat = ESMC_TRANSFER_FORMAT_QUAD; /* 四线读数据 */
cmdStc.InstructionMode = ESMC_INSTRUCTION_SINGLE_LINE;
cmdStc.Instruction = P25Q64_1I4O_FAST_READ_CMD; /* 0x6B:指令单线,数据四线 */
cmdStc.AddressMode = ESMC_ADDRESS_SINGLE_LINE;
cmdStc.AddressSize = ESMC_ADDRESS_24_BITS;
cmdStc.Address = address;
cmdStc.DummyCycles = DUMMY_CLOCK_CYCLES_READ; /* 8 个哑周期 */
cmdStc.DataMode = ESMC_DATA_READ;
cmdStc.NbData = nBytes;
cmdStc.CSPinSel = ESMC_SELECT_PIN_CS0;
HAL_ESMC_Command(&hesmc, &cmdStc, 0x00FFFFFF);
HAL_ESMC_Receive(&hesmc, pData, 0x00FFFFFF);
}
/* ---------- 数据比对 ---------- */
static HAL_StatusTypeDef APP_DataCheck(uint8_t *pSrc, uint8_t *pDst, uint32_t length)
{
for (uint32_t i = 0; i < length; i++)
if (pSrc[i] != pDst[i]) return HAL_ERROR;
return HAL_OK;
}
void APP_ErrorHandler(void) { while (1) {} }
|