1 /*
2 * Copyright (c) 2006-2023, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2023-03-24 spaceman the first version
9 */
10
11 #include "drv_lcd_spi_ext.h"
12 #include "stm32h7xx_hal.h"
13
14 static SPI_HandleTypeDef* spi_handle;
15
Set_SPI_Handle_Ext(SPI_HandleTypeDef * handle)16 void Set_SPI_Handle_Ext(SPI_HandleTypeDef *handle)
17 {
18 spi_handle = handle;
19 }
20
21 /**
22 * @brief Handle SPI Communication Timeout.
23 * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
24 * the configuration information for SPI module.
25 * @param Flag: SPI flag to check
26 * @param Status: flag state to check
27 * @param Timeout: Timeout duration
28 * @param Tickstart: Tick start value
29 * @retval HAL status
30 */
LCD_SPI_WaitOnFlagUntilTimeout(SPI_HandleTypeDef * hspi,uint32_t Flag,FlagStatus Status,uint32_t Tickstart,uint32_t Timeout)31 HAL_StatusTypeDef LCD_SPI_WaitOnFlagUntilTimeout(SPI_HandleTypeDef *hspi, uint32_t Flag, FlagStatus Status,
32 uint32_t Tickstart, uint32_t Timeout)
33 {
34 /* Wait until flag is set */
35 while ((__HAL_SPI_GET_FLAG(hspi, Flag) ? SET : RESET) == Status) {
36 /* Check for the Timeout */
37 if ((((HAL_GetTick() - Tickstart) >= Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0U)) {
38 return HAL_TIMEOUT;
39 }
40 }
41 return HAL_OK;
42 }
43
44 /**
45 * @brief Close Transfer and clear flags.
46 * @param hspi: pointer to a SPI_HandleTypeDef structure that contains
47 * the configuration information for SPI module.
48 * @retval HAL_ERROR: if any error detected
49 * HAL_OK: if nothing detected
50 */
LCD_SPI_CloseTransfer(SPI_HandleTypeDef * hspi)51 void LCD_SPI_CloseTransfer(SPI_HandleTypeDef *hspi)
52 {
53 uint32_t itflag = hspi->Instance->SR;
54
55 __HAL_SPI_CLEAR_EOTFLAG(hspi);
56 __HAL_SPI_CLEAR_TXTFFLAG(hspi);
57
58 /* Disable SPI peripheral */
59 __HAL_SPI_DISABLE(hspi);
60
61 /* Disable ITs */
62 __HAL_SPI_DISABLE_IT(hspi, (SPI_IT_EOT | SPI_IT_TXP | SPI_IT_RXP | SPI_IT_DXP | SPI_IT_UDR | SPI_IT_OVR | SPI_IT_FRE | SPI_IT_MODF));
63
64 /* Disable Tx DMA Request */
65 CLEAR_BIT(hspi->Instance->CFG1, SPI_CFG1_TXDMAEN | SPI_CFG1_RXDMAEN);
66
67 /* Report UnderRun error for non RX Only communication */
68 if (hspi->State != HAL_SPI_STATE_BUSY_RX) {
69 if ((itflag & SPI_FLAG_UDR) != 0UL) {
70 SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_UDR);
71 __HAL_SPI_CLEAR_UDRFLAG(hspi);
72 }
73 }
74
75 /* Report OverRun error for non TX Only communication */
76 if (hspi->State != HAL_SPI_STATE_BUSY_TX) {
77 if ((itflag & SPI_FLAG_OVR) != 0UL) {
78 SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_OVR);
79 __HAL_SPI_CLEAR_OVRFLAG(hspi);
80 }
81 }
82
83 /* SPI Mode Fault error interrupt occurred -------------------------------*/
84 if ((itflag & SPI_FLAG_MODF) != 0UL) {
85 SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_MODF);
86 __HAL_SPI_CLEAR_MODFFLAG(hspi);
87 }
88
89 /* SPI Frame error interrupt occurred ------------------------------------*/
90 if ((itflag & SPI_FLAG_FRE) != 0UL) {
91 SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FRE);
92 __HAL_SPI_CLEAR_FREFLAG(hspi);
93 }
94
95 hspi->TxXferCount = (uint16_t)0UL;
96 hspi->RxXferCount = (uint16_t)0UL;
97 }
98
99 /**
100 * @brief 专为屏幕清屏而修改,将需要清屏的颜色批量传输
101 * @param pData : 要写入的数据
102 * @param Size : 数据大小
103 * @retval status
104 */
105
SPI_Transmit_Ext(uint16_t pData,uint32_t Size)106 rt_err_t SPI_Transmit_Ext(uint16_t pData, uint32_t Size)
107 {
108 uint32_t tickstart;
109 uint32_t Timeout = 1000; // 超时判断
110 uint32_t LCD_pData_32bit; // 按32位传输时的数据
111 uint32_t LCD_TxDataCount; // 传输计数
112 rt_err_t errorcode = RT_EOK;
113 SPI_HandleTypeDef *hspi = spi_handle;
114
115 /* Check Direction parameter */
116 assert_param(IS_SPI_DIRECTION_2LINES_OR_1LINE_2LINES_TXONLY(hspi->Init.Direction));
117
118 /* Process Locked */
119 __HAL_LOCK(hspi);
120
121 /* Init tickstart for timeout management*/
122 tickstart = HAL_GetTick();
123
124 if (hspi->State != HAL_SPI_STATE_READY) {
125 errorcode = -RT_EBUSY;
126 __HAL_UNLOCK(hspi);
127 return errorcode;
128 }
129
130 if (Size == 0UL) {
131 errorcode = -RT_ERROR;
132 __HAL_UNLOCK(hspi);
133 return errorcode;
134 }
135
136 /* Set the transaction information */
137 hspi->State = HAL_SPI_STATE_BUSY_TX;
138 hspi->ErrorCode = HAL_SPI_ERROR_NONE;
139
140 LCD_TxDataCount = Size; // 传输的数据长度
141 LCD_pData_32bit = (pData << 16) | pData; // 按32位传输时,合并2个像素点的颜色
142
143 /*Init field not used in handle to zero */
144 hspi->pRxBuffPtr = NULL;
145 hspi->RxXferSize = (uint16_t)0UL;
146 hspi->RxXferCount = (uint16_t)0UL;
147 hspi->TxISR = NULL;
148 hspi->RxISR = NULL;
149
150 /* Configure communication direction : 1Line */
151 if (hspi->Init.Direction == SPI_DIRECTION_1LINE) {
152 SPI_1LINE_TX(hspi);
153 }
154
155 // 不使用硬件 TSIZE 控制,此处设置为0,即不限制传输的数据长度
156 MODIFY_REG(hspi->Instance->CR2, SPI_CR2_TSIZE, 0);
157
158 /* Enable SPI peripheral */
159 __HAL_SPI_ENABLE(hspi);
160
161 if (hspi->Init.Mode == SPI_MODE_MASTER) {
162 /* Master transfer start */
163 SET_BIT(hspi->Instance->CR1, SPI_CR1_CSTART);
164 }
165
166 /* Transmit data in 16 Bit mode */
167 while (LCD_TxDataCount > 0UL) {
168 /* Wait until TXP flag is set to send data */
169 if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXP)) {
170 if ((hspi->TxXferCount > 1UL) && (hspi->Init.FifoThreshold > SPI_FIFO_THRESHOLD_01DATA)) {
171 *((__IO uint32_t *)&hspi->Instance->TXDR) = (uint32_t)LCD_pData_32bit;
172 LCD_TxDataCount -= (uint16_t)2UL;
173 } else {
174 *((__IO uint16_t *)&hspi->Instance->TXDR) = (uint16_t)pData;
175 LCD_TxDataCount--;
176 }
177 } else {
178 /* Timeout management */
179 if ((((HAL_GetTick() - tickstart) >= Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0U)) {
180 /* Call standard close procedure with error check */
181 LCD_SPI_CloseTransfer(hspi);
182
183 /* Process Unlocked */
184 __HAL_UNLOCK(hspi);
185
186 SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_TIMEOUT);
187 hspi->State = HAL_SPI_STATE_READY;
188 return -RT_ERROR;
189 }
190 }
191 }
192
193 if (LCD_SPI_WaitOnFlagUntilTimeout(hspi, SPI_SR_TXC, RESET, tickstart, Timeout) != HAL_OK) {
194 SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
195 }
196
197 SET_BIT((hspi)->Instance->CR1, SPI_CR1_CSUSP); // 请求挂起SPI传输
198 /* 等待SPI挂起 */
199 if (LCD_SPI_WaitOnFlagUntilTimeout(hspi, SPI_FLAG_SUSP, RESET, tickstart, Timeout) != HAL_OK) {
200 SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
201 }
202 LCD_SPI_CloseTransfer(hspi); /* Call standard close procedure with error check */
203
204 SET_BIT((hspi)->Instance->IFCR, SPI_IFCR_SUSPC); // 清除挂起标志位
205
206 /* Process Unlocked */
207 __HAL_UNLOCK(hspi);
208
209 hspi->State = HAL_SPI_STATE_READY;
210
211 if (hspi->ErrorCode != HAL_SPI_ERROR_NONE) {
212 return -RT_ERROR;
213 }
214 return errorcode;
215 }
216
217 /**
218 * @brief 专为批量写入数据修改,使之不限长度的传输数据
219 * @param pData : 要写入的数据
220 * @param Size : 数据大小
221 * @retval status
222 */
SPI_TransmitBuffer_Ext(uint16_t * pData,uint32_t Size)223 rt_err_t SPI_TransmitBuffer_Ext(uint16_t *pData, uint32_t Size)
224 {
225 uint32_t tickstart;
226 uint32_t Timeout = 1000; // 超时判断
227 uint32_t LCD_TxDataCount; // 传输计数
228 rt_err_t errorcode = RT_EOK;
229 SPI_HandleTypeDef *hspi = spi_handle;
230
231 /* Check Direction parameter */
232 assert_param(IS_SPI_DIRECTION_2LINES_OR_1LINE_2LINES_TXONLY(hspi->Init.Direction));
233
234 /* Process Locked */
235 __HAL_LOCK(hspi);
236
237 /* Init tickstart for timeout management*/
238 tickstart = HAL_GetTick();
239
240 if (hspi->State != HAL_SPI_STATE_READY) {
241 errorcode = -RT_EBUSY;
242 __HAL_UNLOCK(hspi);
243 return errorcode;
244 }
245
246 if (Size == 0UL) {
247 errorcode = -RT_ERROR;
248 __HAL_UNLOCK(hspi);
249 return errorcode;
250 }
251
252 /* Set the transaction information */
253 hspi->State = HAL_SPI_STATE_BUSY_TX;
254 hspi->ErrorCode = HAL_SPI_ERROR_NONE;
255
256 LCD_TxDataCount = Size; // 传输的数据长度
257
258 /*Init field not used in handle to zero */
259 hspi->pRxBuffPtr = NULL;
260 hspi->RxXferSize = (uint16_t)0UL;
261 hspi->RxXferCount = (uint16_t)0UL;
262 hspi->TxISR = NULL;
263 hspi->RxISR = NULL;
264
265 /* Configure communication direction : 1Line */
266 if (hspi->Init.Direction == SPI_DIRECTION_1LINE) {
267 SPI_1LINE_TX(hspi);
268 }
269
270 // 不使用硬件 TSIZE 控制,此处设置为0,即不限制传输的数据长度
271 MODIFY_REG(hspi->Instance->CR2, SPI_CR2_TSIZE, 0);
272
273 /* Enable SPI peripheral */
274 __HAL_SPI_ENABLE(hspi);
275
276 if (hspi->Init.Mode == SPI_MODE_MASTER) {
277 /* Master transfer start */
278 SET_BIT(hspi->Instance->CR1, SPI_CR1_CSTART);
279 }
280
281 /* Transmit data in 16 Bit mode */
282 while (LCD_TxDataCount > 0UL) {
283 /* Wait until TXP flag is set to send data */
284 if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXP)) {
285 if ((LCD_TxDataCount > 1UL) && (hspi->Init.FifoThreshold > SPI_FIFO_THRESHOLD_01DATA)) {
286 *((__IO uint32_t *)&hspi->Instance->TXDR) = *((uint32_t *)pData);
287 pData += 2;
288 LCD_TxDataCount -= 2;
289 } else {
290 *((__IO uint16_t *)&hspi->Instance->TXDR) = *((uint16_t *)pData);
291 pData += 1;
292 LCD_TxDataCount--;
293 }
294 } else {
295 /* Timeout management */
296 if ((((HAL_GetTick() - tickstart) >= Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0U)) {
297 /* Call standard close procedure with error check */
298 LCD_SPI_CloseTransfer(hspi);
299
300 /* Process Unlocked */
301 __HAL_UNLOCK(hspi);
302
303 SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_TIMEOUT);
304 hspi->State = HAL_SPI_STATE_READY;
305 return -RT_ERROR;
306 }
307 }
308 }
309
310 if (LCD_SPI_WaitOnFlagUntilTimeout(hspi, SPI_SR_TXC, RESET, tickstart, Timeout) != HAL_OK) {
311 SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
312 }
313
314 SET_BIT((hspi)->Instance->CR1, SPI_CR1_CSUSP); // 请求挂起SPI传输
315 /* 等待SPI挂起 */
316 if (LCD_SPI_WaitOnFlagUntilTimeout(hspi, SPI_FLAG_SUSP, RESET, tickstart, Timeout) != HAL_OK) {
317 SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
318 }
319 LCD_SPI_CloseTransfer(hspi); /* Call standard close procedure with error check */
320
321 SET_BIT((hspi)->Instance->IFCR, SPI_IFCR_SUSPC); // 清除挂起标志位
322
323 /* Process Unlocked */
324 __HAL_UNLOCK(hspi);
325
326 hspi->State = HAL_SPI_STATE_READY;
327
328 if (hspi->ErrorCode != HAL_SPI_ERROR_NONE) {
329 return -RT_ERROR;
330 }
331 return errorcode;
332 }
333