Mercurial > ~darius > hgwebdir.cgi > stm32temp
comparison libs/STM32F10x_StdPeriph_Lib_V3.5.0/Utilities/STM32_EVAL/Common/stm32_eval_i2c_ee.c @ 0:c59513fd84fb
Initial commit of STM32 test code.
author | Daniel O'Connor <darius@dons.net.au> |
---|---|
date | Mon, 03 Oct 2011 21:19:15 +1030 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:c59513fd84fb |
---|---|
1 /** | |
2 ****************************************************************************** | |
3 * @file stm32_eval_i2c_ee.c | |
4 * @author MCD Application Team | |
5 * @version V4.5.0 | |
6 * @date 07-March-2011 | |
7 * @brief This file provides a set of functions needed to manage the I2C M24CXX | |
8 * EEPROM memory mounted on STM32xx-EVAL board (refer to stm32_eval.h | |
9 * to know about the boards supporting this memory). | |
10 * | |
11 * =================================================================== | |
12 * Note: This driver is intended for STM32F10x families devices only. | |
13 * =================================================================== | |
14 * | |
15 * It implements a high level communication layer for read and write | |
16 * from/to this memory. The needed STM32 hardware resources (I2C and | |
17 * GPIO) are defined in stm32xx_eval.h file, and the initialization is | |
18 * performed in sEE_LowLevel_Init() function declared in stm32xx_eval.c | |
19 * file. | |
20 * You can easily tailor this driver to any other development board, | |
21 * by just adapting the defines for hardware resources and | |
22 * sEE_LowLevel_Init() function. | |
23 * | |
24 * @note In this driver, basic read and write functions (sEE_ReadBuffer() | |
25 * and sEE_WritePage()) use the DMA to perform the data transfer | |
26 * to/from EEPROM memory (except when number of requested data is | |
27 * equal to 1). Thus, after calling these two functions, user | |
28 * application may perform other tasks while DMA is transferring | |
29 * data. The application should then monitor the variable holding | |
30 * the number of data in order to determine when the transfer is | |
31 * completed (variable decremented to 0). Stopping transfer tasks | |
32 * are performed into DMA interrupt handlers (which are integrated | |
33 * into this driver). | |
34 * | |
35 * +-----------------------------------------------------------------+ | |
36 * | Pin assignment | | |
37 * +---------------------------------------+-----------+-------------+ | |
38 * | STM32 I2C Pins | sEE | Pin | | |
39 * +---------------------------------------+-----------+-------------+ | |
40 * | . | E0(GND) | 1 (0V) | | |
41 * | . | E1(GND) | 2 (0V) | | |
42 * | . | E2(GND) | 3 (0V) | | |
43 * | . | E0(VSS) | 4 (0V) | | |
44 * | sEE_I2C_SDA_PIN/ SDA | SDA | 5 | | |
45 * | sEE_I2C_SCL_PIN/ SCL | SCL | 6 | | |
46 * | . | /WC(VDD)| 7 (3.3V) | | |
47 * | . | VDD | 8 (3.3V) | | |
48 * +---------------------------------------+-----------+-------------+ | |
49 ****************************************************************************** | |
50 * @attention | |
51 * | |
52 * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS | |
53 * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE | |
54 * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY | |
55 * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING | |
56 * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE | |
57 * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. | |
58 * | |
59 * <h2><center>© COPYRIGHT 2011 STMicroelectronics</center></h2> | |
60 ****************************************************************************** | |
61 */ | |
62 | |
63 /* Includes ------------------------------------------------------------------*/ | |
64 #include "stm32_eval_i2c_ee.h" | |
65 | |
66 /** @addtogroup Utilities | |
67 * @{ | |
68 */ | |
69 | |
70 /** @addtogroup STM32_EVAL | |
71 * @{ | |
72 */ | |
73 | |
74 /** @addtogroup Common | |
75 * @{ | |
76 */ | |
77 | |
78 /** @addtogroup STM32_EVAL_I2C_EE | |
79 * @brief This file includes the I2C EEPROM driver of STM32-EVAL boards. | |
80 * @{ | |
81 */ | |
82 | |
83 /** @defgroup STM32_EVAL_I2C_EE_Private_Types | |
84 * @{ | |
85 */ | |
86 /** | |
87 * @} | |
88 */ | |
89 | |
90 | |
91 /** @defgroup STM32_EVAL_I2C_EE_Private_Defines | |
92 * @{ | |
93 */ | |
94 /** | |
95 * @} | |
96 */ | |
97 | |
98 | |
99 /** @defgroup STM32_EVAL_I2C_EE_Private_Macros | |
100 * @{ | |
101 */ | |
102 /** | |
103 * @} | |
104 */ | |
105 | |
106 | |
107 /** @defgroup STM32_EVAL_I2C_EE_Private_Variables | |
108 * @{ | |
109 */ | |
110 __IO uint16_t sEEAddress = 0; | |
111 __IO uint32_t sEETimeout = sEE_LONG_TIMEOUT; | |
112 __IO uint16_t* sEEDataReadPointer; | |
113 __IO uint8_t* sEEDataWritePointer; | |
114 __IO uint8_t sEEDataNum; | |
115 /** | |
116 * @} | |
117 */ | |
118 | |
119 | |
120 /** @defgroup STM32_EVAL_I2C_EE_Private_Function_Prototypes | |
121 * @{ | |
122 */ | |
123 /** | |
124 * @} | |
125 */ | |
126 | |
127 | |
128 /** @defgroup STM32_EVAL_I2C_EE_Private_Functions | |
129 * @{ | |
130 */ | |
131 | |
132 /** | |
133 * @brief DeInitializes peripherals used by the I2C EEPROM driver. | |
134 * @param None | |
135 * @retval None | |
136 */ | |
137 void sEE_DeInit(void) | |
138 { | |
139 sEE_LowLevel_DeInit(); | |
140 } | |
141 | |
142 /** | |
143 * @brief Initializes peripherals used by the I2C EEPROM driver. | |
144 * @param None | |
145 * @retval None | |
146 */ | |
147 void sEE_Init(void) | |
148 { | |
149 I2C_InitTypeDef I2C_InitStructure; | |
150 | |
151 sEE_LowLevel_Init(); | |
152 | |
153 /*!< I2C configuration */ | |
154 /* sEE_I2C configuration */ | |
155 I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; | |
156 I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; | |
157 I2C_InitStructure.I2C_OwnAddress1 = I2C_SLAVE_ADDRESS7; | |
158 I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; | |
159 I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; | |
160 I2C_InitStructure.I2C_ClockSpeed = I2C_SPEED; | |
161 | |
162 /* sEE_I2C Peripheral Enable */ | |
163 I2C_Cmd(sEE_I2C, ENABLE); | |
164 /* Apply sEE_I2C configuration after enabling it */ | |
165 I2C_Init(sEE_I2C, &I2C_InitStructure); | |
166 | |
167 /* Enable the sEE_I2C peripheral DMA requests */ | |
168 I2C_DMACmd(sEE_I2C, ENABLE); | |
169 | |
170 #if defined (sEE_M24C64_32) | |
171 /*!< Select the EEPROM address according to the state of E0, E1, E2 pins */ | |
172 sEEAddress = sEE_HW_ADDRESS; | |
173 #elif defined (sEE_M24C08) | |
174 /*!< depending on the sEE Address selected in the i2c_ee.h file */ | |
175 #ifdef sEE_Block0_ADDRESS | |
176 /*!< Select the sEE Block0 to write on */ | |
177 sEEAddress = sEE_Block0_ADDRESS; | |
178 #endif | |
179 | |
180 #ifdef sEE_Block1_ADDRESS | |
181 /*!< Select the sEE Block1 to write on */ | |
182 sEEAddress = sEE_Block1_ADDRESS; | |
183 #endif | |
184 | |
185 #ifdef sEE_Block2_ADDRESS | |
186 /*!< Select the sEE Block2 to write on */ | |
187 sEEAddress = sEE_Block2_ADDRESS; | |
188 #endif | |
189 | |
190 #ifdef sEE_Block3_ADDRESS | |
191 /*!< Select the sEE Block3 to write on */ | |
192 sEEAddress = sEE_Block3_ADDRESS; | |
193 #endif | |
194 #endif /*!< sEE_M24C64_32 */ | |
195 } | |
196 | |
197 /** | |
198 * @brief Reads a block of data from the EEPROM. | |
199 * @param pBuffer : pointer to the buffer that receives the data read from | |
200 * the EEPROM. | |
201 * @param ReadAddr : EEPROM's internal address to start reading from. | |
202 * @param NumByteToRead : pointer to the variable holding number of bytes to | |
203 * be read from the EEPROM. | |
204 * | |
205 * @note The variable pointed by NumByteToRead is reset to 0 when all the | |
206 * data are read from the EEPROM. Application should monitor this | |
207 * variable in order know when the transfer is complete. | |
208 * | |
209 * @note When number of data to be read is higher than 1, this function just | |
210 * configures the communication and enable the DMA channel to transfer data. | |
211 * Meanwhile, the user application may perform other tasks. | |
212 * When number of data to be read is 1, then the DMA is not used. The byte | |
213 * is read in polling mode. | |
214 * | |
215 * @retval sEE_OK (0) if operation is correctly performed, else return value | |
216 * different from sEE_OK (0) or the timeout user callback. | |
217 */ | |
218 uint32_t sEE_ReadBuffer(uint8_t* pBuffer, uint16_t ReadAddr, uint16_t* NumByteToRead) | |
219 { | |
220 /* Set the pointer to the Number of data to be read. This pointer will be used | |
221 by the DMA Transfer Completer interrupt Handler in order to reset the | |
222 variable to 0. User should check on this variable in order to know if the | |
223 DMA transfer has been complete or not. */ | |
224 sEEDataReadPointer = NumByteToRead; | |
225 | |
226 /*!< While the bus is busy */ | |
227 sEETimeout = sEE_LONG_TIMEOUT; | |
228 while(I2C_GetFlagStatus(sEE_I2C, I2C_FLAG_BUSY)) | |
229 { | |
230 if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback(); | |
231 } | |
232 | |
233 /*!< Send START condition */ | |
234 I2C_GenerateSTART(sEE_I2C, ENABLE); | |
235 | |
236 /*!< Test on EV5 and clear it (cleared by reading SR1 then writing to DR) */ | |
237 sEETimeout = sEE_FLAG_TIMEOUT; | |
238 while(!I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_MODE_SELECT)) | |
239 { | |
240 if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback(); | |
241 } | |
242 | |
243 /*!< Send EEPROM address for write */ | |
244 I2C_Send7bitAddress(sEE_I2C, sEEAddress, I2C_Direction_Transmitter); | |
245 | |
246 /*!< Test on EV6 and clear it */ | |
247 sEETimeout = sEE_FLAG_TIMEOUT; | |
248 while(!I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) | |
249 { | |
250 if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback(); | |
251 } | |
252 | |
253 #ifdef sEE_M24C08 | |
254 | |
255 /*!< Send the EEPROM's internal address to read from: Only one byte address */ | |
256 I2C_SendData(sEE_I2C, ReadAddr); | |
257 | |
258 #elif defined (sEE_M24C64_32) | |
259 | |
260 /*!< Send the EEPROM's internal address to read from: MSB of the address first */ | |
261 I2C_SendData(sEE_I2C, (uint8_t)((ReadAddr & 0xFF00) >> 8)); | |
262 | |
263 /*!< Test on EV8 and clear it */ | |
264 sEETimeout = sEE_FLAG_TIMEOUT; | |
265 while(!I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) | |
266 { | |
267 if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback(); | |
268 } | |
269 | |
270 /*!< Send the EEPROM's internal address to read from: LSB of the address */ | |
271 I2C_SendData(sEE_I2C, (uint8_t)(ReadAddr & 0x00FF)); | |
272 | |
273 #endif /*!< sEE_M24C08 */ | |
274 | |
275 /*!< Test on EV8 and clear it */ | |
276 sEETimeout = sEE_FLAG_TIMEOUT; | |
277 while(I2C_GetFlagStatus(sEE_I2C, I2C_FLAG_BTF) == RESET) | |
278 { | |
279 if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback(); | |
280 } | |
281 | |
282 /*!< Send STRAT condition a second time */ | |
283 I2C_GenerateSTART(sEE_I2C, ENABLE); | |
284 | |
285 /*!< Test on EV5 and clear it (cleared by reading SR1 then writing to DR) */ | |
286 sEETimeout = sEE_FLAG_TIMEOUT; | |
287 while(!I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_MODE_SELECT)) | |
288 { | |
289 if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback(); | |
290 } | |
291 | |
292 /*!< Send EEPROM address for read */ | |
293 I2C_Send7bitAddress(sEE_I2C, sEEAddress, I2C_Direction_Receiver); | |
294 | |
295 /* If number of data to be read is 1, then DMA couldn't be used */ | |
296 /* One Byte Master Reception procedure (POLLING) ---------------------------*/ | |
297 if ((uint16_t)(*NumByteToRead) < 2) | |
298 { | |
299 /* Wait on ADDR flag to be set (ADDR is still not cleared at this level */ | |
300 sEETimeout = sEE_FLAG_TIMEOUT; | |
301 while(I2C_GetFlagStatus(sEE_I2C, I2C_FLAG_ADDR) == RESET) | |
302 { | |
303 if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback(); | |
304 } | |
305 | |
306 /*!< Disable Acknowledgement */ | |
307 I2C_AcknowledgeConfig(sEE_I2C, DISABLE); | |
308 | |
309 /* Call User callback for critical section start (should typically disable interrupts) */ | |
310 sEE_EnterCriticalSection_UserCallback(); | |
311 | |
312 /* Clear ADDR register by reading SR1 then SR2 register (SR1 has already been read) */ | |
313 (void)sEE_I2C->SR2; | |
314 | |
315 /*!< Send STOP Condition */ | |
316 I2C_GenerateSTOP(sEE_I2C, ENABLE); | |
317 | |
318 /* Call User callback for critical section end (should typically re-enable interrupts) */ | |
319 sEE_ExitCriticalSection_UserCallback(); | |
320 | |
321 /* Wait for the byte to be received */ | |
322 sEETimeout = sEE_FLAG_TIMEOUT; | |
323 while(I2C_GetFlagStatus(sEE_I2C, I2C_FLAG_RXNE) == RESET) | |
324 { | |
325 if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback(); | |
326 } | |
327 | |
328 /*!< Read the byte received from the EEPROM */ | |
329 *pBuffer = I2C_ReceiveData(sEE_I2C); | |
330 | |
331 /*!< Decrement the read bytes counter */ | |
332 (uint16_t)(*NumByteToRead)--; | |
333 | |
334 /* Wait to make sure that STOP control bit has been cleared */ | |
335 sEETimeout = sEE_FLAG_TIMEOUT; | |
336 while(sEE_I2C->CR1 & I2C_CR1_STOP) | |
337 { | |
338 if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback(); | |
339 } | |
340 | |
341 /*!< Re-Enable Acknowledgement to be ready for another reception */ | |
342 I2C_AcknowledgeConfig(sEE_I2C, ENABLE); | |
343 } | |
344 else/* More than one Byte Master Reception procedure (DMA) -----------------*/ | |
345 { | |
346 /*!< Test on EV6 and clear it */ | |
347 sEETimeout = sEE_FLAG_TIMEOUT; | |
348 while(!I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)) | |
349 { | |
350 if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback(); | |
351 } | |
352 | |
353 /* Configure the DMA Rx Channel with the buffer address and the buffer size */ | |
354 sEE_LowLevel_DMAConfig((uint32_t)pBuffer, (uint16_t)(*NumByteToRead), sEE_DIRECTION_RX); | |
355 | |
356 /* Inform the DMA that the next End Of Transfer Signal will be the last one */ | |
357 I2C_DMALastTransferCmd(sEE_I2C, ENABLE); | |
358 | |
359 /* Enable the DMA Rx Channel */ | |
360 DMA_Cmd(sEE_I2C_DMA_CHANNEL_RX, ENABLE); | |
361 } | |
362 | |
363 /* If all operations OK, return sEE_OK (0) */ | |
364 return sEE_OK; | |
365 } | |
366 | |
367 /** | |
368 * @brief Writes more than one byte to the EEPROM with a single WRITE cycle. | |
369 * | |
370 * @note The number of bytes (combined to write start address) must not | |
371 * cross the EEPROM page boundary. This function can only write into | |
372 * the boundaries of an EEPROM page. | |
373 * This function doesn't check on boundaries condition (in this driver | |
374 * the function sEE_WriteBuffer() which calls sEE_WritePage() is | |
375 * responsible of checking on Page boundaries). | |
376 * | |
377 * @param pBuffer : pointer to the buffer containing the data to be written to | |
378 * the EEPROM. | |
379 * @param WriteAddr : EEPROM's internal address to write to. | |
380 * @param NumByteToWrite : pointer to the variable holding number of bytes to | |
381 * be written into the EEPROM. | |
382 * | |
383 * @note The variable pointed by NumByteToWrite is reset to 0 when all the | |
384 * data are written to the EEPROM. Application should monitor this | |
385 * variable in order know when the transfer is complete. | |
386 * | |
387 * @note This function just configure the communication and enable the DMA | |
388 * channel to transfer data. Meanwhile, the user application may perform | |
389 * other tasks in parallel. | |
390 * | |
391 * @retval sEE_OK (0) if operation is correctly performed, else return value | |
392 * different from sEE_OK (0) or the timeout user callback. | |
393 */ | |
394 uint32_t sEE_WritePage(uint8_t* pBuffer, uint16_t WriteAddr, uint8_t* NumByteToWrite) | |
395 { | |
396 /* Set the pointer to the Number of data to be written. This pointer will be used | |
397 by the DMA Transfer Completer interrupt Handler in order to reset the | |
398 variable to 0. User should check on this variable in order to know if the | |
399 DMA transfer has been complete or not. */ | |
400 sEEDataWritePointer = NumByteToWrite; | |
401 | |
402 /*!< While the bus is busy */ | |
403 sEETimeout = sEE_LONG_TIMEOUT; | |
404 while(I2C_GetFlagStatus(sEE_I2C, I2C_FLAG_BUSY)) | |
405 { | |
406 if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback(); | |
407 } | |
408 | |
409 /*!< Send START condition */ | |
410 I2C_GenerateSTART(sEE_I2C, ENABLE); | |
411 | |
412 /*!< Test on EV5 and clear it */ | |
413 sEETimeout = sEE_FLAG_TIMEOUT; | |
414 while(!I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_MODE_SELECT)) | |
415 { | |
416 if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback(); | |
417 } | |
418 | |
419 /*!< Send EEPROM address for write */ | |
420 sEETimeout = sEE_FLAG_TIMEOUT; | |
421 I2C_Send7bitAddress(sEE_I2C, sEEAddress, I2C_Direction_Transmitter); | |
422 | |
423 /*!< Test on EV6 and clear it */ | |
424 sEETimeout = sEE_FLAG_TIMEOUT; | |
425 while(!I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) | |
426 { | |
427 if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback(); | |
428 } | |
429 | |
430 #ifdef sEE_M24C08 | |
431 | |
432 /*!< Send the EEPROM's internal address to write to : only one byte Address */ | |
433 I2C_SendData(sEE_I2C, WriteAddr); | |
434 | |
435 #elif defined(sEE_M24C64_32) | |
436 | |
437 /*!< Send the EEPROM's internal address to write to : MSB of the address first */ | |
438 I2C_SendData(sEE_I2C, (uint8_t)((WriteAddr & 0xFF00) >> 8)); | |
439 | |
440 /*!< Test on EV8 and clear it */ | |
441 sEETimeout = sEE_FLAG_TIMEOUT; | |
442 while(!I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) | |
443 { | |
444 if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback(); | |
445 } | |
446 | |
447 /*!< Send the EEPROM's internal address to write to : LSB of the address */ | |
448 I2C_SendData(sEE_I2C, (uint8_t)(WriteAddr & 0x00FF)); | |
449 | |
450 #endif /*!< sEE_M24C08 */ | |
451 | |
452 /*!< Test on EV8 and clear it */ | |
453 sEETimeout = sEE_FLAG_TIMEOUT; | |
454 while(!I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) | |
455 { | |
456 if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback(); | |
457 } | |
458 | |
459 /* Configure the DMA Tx Channel with the buffer address and the buffer size */ | |
460 sEE_LowLevel_DMAConfig((uint32_t)pBuffer, (uint8_t)(*NumByteToWrite), sEE_DIRECTION_TX); | |
461 | |
462 /* Enable the DMA Tx Channel */ | |
463 DMA_Cmd(sEE_I2C_DMA_CHANNEL_TX, ENABLE); | |
464 | |
465 /* If all operations OK, return sEE_OK (0) */ | |
466 return sEE_OK; | |
467 } | |
468 | |
469 /** | |
470 * @brief Writes buffer of data to the I2C EEPROM. | |
471 * @param pBuffer : pointer to the buffer containing the data to be written | |
472 * to the EEPROM. | |
473 * @param WriteAddr : EEPROM's internal address to write to. | |
474 * @param NumByteToWrite : number of bytes to write to the EEPROM. | |
475 * @retval None | |
476 */ | |
477 void sEE_WriteBuffer(uint8_t* pBuffer, uint16_t WriteAddr, uint16_t NumByteToWrite) | |
478 { | |
479 uint8_t NumOfPage = 0, NumOfSingle = 0, count = 0; | |
480 uint16_t Addr = 0; | |
481 | |
482 Addr = WriteAddr % sEE_PAGESIZE; | |
483 count = sEE_PAGESIZE - Addr; | |
484 NumOfPage = NumByteToWrite / sEE_PAGESIZE; | |
485 NumOfSingle = NumByteToWrite % sEE_PAGESIZE; | |
486 | |
487 /*!< If WriteAddr is sEE_PAGESIZE aligned */ | |
488 if(Addr == 0) | |
489 { | |
490 /*!< If NumByteToWrite < sEE_PAGESIZE */ | |
491 if(NumOfPage == 0) | |
492 { | |
493 /* Store the number of data to be written */ | |
494 sEEDataNum = NumOfSingle; | |
495 /* Start writing data */ | |
496 sEE_WritePage(pBuffer, WriteAddr, (uint8_t*)(&sEEDataNum)); | |
497 /* Wait transfer through DMA to be complete */ | |
498 sEETimeout = sEE_LONG_TIMEOUT; | |
499 while (sEEDataNum > 0) | |
500 { | |
501 if((sEETimeout--) == 0) {sEE_TIMEOUT_UserCallback(); return;}; | |
502 } | |
503 sEE_WaitEepromStandbyState(); | |
504 } | |
505 /*!< If NumByteToWrite > sEE_PAGESIZE */ | |
506 else | |
507 { | |
508 while(NumOfPage--) | |
509 { | |
510 /* Store the number of data to be written */ | |
511 sEEDataNum = sEE_PAGESIZE; | |
512 sEE_WritePage(pBuffer, WriteAddr, (uint8_t*)(&sEEDataNum)); | |
513 /* Wait transfer through DMA to be complete */ | |
514 sEETimeout = sEE_LONG_TIMEOUT; | |
515 while (sEEDataNum > 0) | |
516 { | |
517 if((sEETimeout--) == 0) {sEE_TIMEOUT_UserCallback(); return;}; | |
518 } | |
519 sEE_WaitEepromStandbyState(); | |
520 WriteAddr += sEE_PAGESIZE; | |
521 pBuffer += sEE_PAGESIZE; | |
522 } | |
523 | |
524 if(NumOfSingle!=0) | |
525 { | |
526 /* Store the number of data to be written */ | |
527 sEEDataNum = NumOfSingle; | |
528 sEE_WritePage(pBuffer, WriteAddr, (uint8_t*)(&sEEDataNum)); | |
529 /* Wait transfer through DMA to be complete */ | |
530 sEETimeout = sEE_LONG_TIMEOUT; | |
531 while (sEEDataNum > 0) | |
532 { | |
533 if((sEETimeout--) == 0) {sEE_TIMEOUT_UserCallback(); return;}; | |
534 } | |
535 sEE_WaitEepromStandbyState(); | |
536 } | |
537 } | |
538 } | |
539 /*!< If WriteAddr is not sEE_PAGESIZE aligned */ | |
540 else | |
541 { | |
542 /*!< If NumByteToWrite < sEE_PAGESIZE */ | |
543 if(NumOfPage== 0) | |
544 { | |
545 /*!< If the number of data to be written is more than the remaining space | |
546 in the current page: */ | |
547 if (NumByteToWrite > count) | |
548 { | |
549 /* Store the number of data to be written */ | |
550 sEEDataNum = count; | |
551 /*!< Write the data conained in same page */ | |
552 sEE_WritePage(pBuffer, WriteAddr, (uint8_t*)(&sEEDataNum)); | |
553 /* Wait transfer through DMA to be complete */ | |
554 sEETimeout = sEE_LONG_TIMEOUT; | |
555 while (sEEDataNum > 0) | |
556 { | |
557 if((sEETimeout--) == 0) {sEE_TIMEOUT_UserCallback(); return;}; | |
558 } | |
559 sEE_WaitEepromStandbyState(); | |
560 | |
561 /* Store the number of data to be written */ | |
562 sEEDataNum = (NumByteToWrite - count); | |
563 /*!< Write the remaining data in the following page */ | |
564 sEE_WritePage((uint8_t*)(pBuffer + count), (WriteAddr + count), (uint8_t*)(&sEEDataNum)); | |
565 /* Wait transfer through DMA to be complete */ | |
566 sEETimeout = sEE_LONG_TIMEOUT; | |
567 while (sEEDataNum > 0) | |
568 { | |
569 if((sEETimeout--) == 0) {sEE_TIMEOUT_UserCallback(); return;}; | |
570 } | |
571 sEE_WaitEepromStandbyState(); | |
572 } | |
573 else | |
574 { | |
575 /* Store the number of data to be written */ | |
576 sEEDataNum = NumOfSingle; | |
577 sEE_WritePage(pBuffer, WriteAddr, (uint8_t*)(&sEEDataNum)); | |
578 /* Wait transfer through DMA to be complete */ | |
579 sEETimeout = sEE_LONG_TIMEOUT; | |
580 while (sEEDataNum > 0) | |
581 { | |
582 if((sEETimeout--) == 0) {sEE_TIMEOUT_UserCallback(); return;}; | |
583 } | |
584 sEE_WaitEepromStandbyState(); | |
585 } | |
586 } | |
587 /*!< If NumByteToWrite > sEE_PAGESIZE */ | |
588 else | |
589 { | |
590 NumByteToWrite -= count; | |
591 NumOfPage = NumByteToWrite / sEE_PAGESIZE; | |
592 NumOfSingle = NumByteToWrite % sEE_PAGESIZE; | |
593 | |
594 if(count != 0) | |
595 { | |
596 /* Store the number of data to be written */ | |
597 sEEDataNum = count; | |
598 sEE_WritePage(pBuffer, WriteAddr, (uint8_t*)(&sEEDataNum)); | |
599 /* Wait transfer through DMA to be complete */ | |
600 sEETimeout = sEE_LONG_TIMEOUT; | |
601 while (sEEDataNum > 0) | |
602 { | |
603 if((sEETimeout--) == 0) {sEE_TIMEOUT_UserCallback(); return;}; | |
604 } | |
605 sEE_WaitEepromStandbyState(); | |
606 WriteAddr += count; | |
607 pBuffer += count; | |
608 } | |
609 | |
610 while(NumOfPage--) | |
611 { | |
612 /* Store the number of data to be written */ | |
613 sEEDataNum = sEE_PAGESIZE; | |
614 sEE_WritePage(pBuffer, WriteAddr, (uint8_t*)(&sEEDataNum)); | |
615 /* Wait transfer through DMA to be complete */ | |
616 sEETimeout = sEE_LONG_TIMEOUT; | |
617 while (sEEDataNum > 0) | |
618 { | |
619 if((sEETimeout--) == 0) {sEE_TIMEOUT_UserCallback(); return;}; | |
620 } | |
621 sEE_WaitEepromStandbyState(); | |
622 WriteAddr += sEE_PAGESIZE; | |
623 pBuffer += sEE_PAGESIZE; | |
624 } | |
625 if(NumOfSingle != 0) | |
626 { | |
627 /* Store the number of data to be written */ | |
628 sEEDataNum = NumOfSingle; | |
629 sEE_WritePage(pBuffer, WriteAddr, (uint8_t*)(&sEEDataNum)); | |
630 /* Wait transfer through DMA to be complete */ | |
631 sEETimeout = sEE_LONG_TIMEOUT; | |
632 while (sEEDataNum > 0) | |
633 { | |
634 if((sEETimeout--) == 0) {sEE_TIMEOUT_UserCallback(); return;}; | |
635 } | |
636 sEE_WaitEepromStandbyState(); | |
637 } | |
638 } | |
639 } | |
640 } | |
641 | |
642 /** | |
643 * @brief Wait for EEPROM Standby state. | |
644 * | |
645 * @note This function allows to wait and check that EEPROM has finished the | |
646 * last Write operation. It is mostly used after Write operation: after | |
647 * receiving the buffer to be written, the EEPROM may need additional | |
648 * time to actually perform the write operation. During this time, it | |
649 * doesn't answer to I2C packets addressed to it. Once the write operation | |
650 * is complete the EEPROM responds to its address. | |
651 * | |
652 * @note It is not necessary to call this function after sEE_WriteBuffer() | |
653 * function (sEE_WriteBuffer() already calls this function after each | |
654 * write page operation). | |
655 * | |
656 * @param None | |
657 * @retval sEE_OK (0) if operation is correctly performed, else return value | |
658 * different from sEE_OK (0) or the timeout user callback. | |
659 */ | |
660 uint32_t sEE_WaitEepromStandbyState(void) | |
661 { | |
662 __IO uint16_t tmpSR1 = 0; | |
663 __IO uint32_t sEETrials = 0; | |
664 | |
665 /*!< While the bus is busy */ | |
666 sEETimeout = sEE_LONG_TIMEOUT; | |
667 while(I2C_GetFlagStatus(sEE_I2C, I2C_FLAG_BUSY)) | |
668 { | |
669 if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback(); | |
670 } | |
671 | |
672 /* Keep looping till the slave acknowledge his address or maximum number | |
673 of trials is reached (this number is defined by sEE_MAX_TRIALS_NUMBER define | |
674 in stm32_eval_i2c_ee.h file) */ | |
675 while (1) | |
676 { | |
677 /*!< Send START condition */ | |
678 I2C_GenerateSTART(sEE_I2C, ENABLE); | |
679 | |
680 /*!< Test on EV5 and clear it */ | |
681 sEETimeout = sEE_FLAG_TIMEOUT; | |
682 while(!I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_MODE_SELECT)) | |
683 { | |
684 if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback(); | |
685 } | |
686 | |
687 /*!< Send EEPROM address for write */ | |
688 I2C_Send7bitAddress(sEE_I2C, sEEAddress, I2C_Direction_Transmitter); | |
689 | |
690 /* Wait for ADDR flag to be set (Slave acknowledged his address) */ | |
691 sEETimeout = sEE_LONG_TIMEOUT; | |
692 do | |
693 { | |
694 /* Get the current value of the SR1 register */ | |
695 tmpSR1 = sEE_I2C->SR1; | |
696 | |
697 /* Update the timeout value and exit if it reach 0 */ | |
698 if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback(); | |
699 } | |
700 /* Keep looping till the Address is acknowledged or the AF flag is | |
701 set (address not acknowledged at time) */ | |
702 while((tmpSR1 & (I2C_SR1_ADDR | I2C_SR1_AF)) == 0); | |
703 | |
704 /* Check if the ADDR flag has been set */ | |
705 if (tmpSR1 & I2C_SR1_ADDR) | |
706 { | |
707 /* Clear ADDR Flag by reading SR1 then SR2 registers (SR1 have already | |
708 been read) */ | |
709 (void)sEE_I2C->SR2; | |
710 | |
711 /*!< STOP condition */ | |
712 I2C_GenerateSTOP(sEE_I2C, ENABLE); | |
713 | |
714 /* Exit the function */ | |
715 return sEE_OK; | |
716 } | |
717 else | |
718 { | |
719 /*!< Clear AF flag */ | |
720 I2C_ClearFlag(sEE_I2C, I2C_FLAG_AF); | |
721 } | |
722 | |
723 /* Check if the maximum allowed numbe of trials has bee reached */ | |
724 if (sEETrials++ == sEE_MAX_TRIALS_NUMBER) | |
725 { | |
726 /* If the maximum number of trials has been reached, exit the function */ | |
727 return sEE_TIMEOUT_UserCallback(); | |
728 } | |
729 } | |
730 } | |
731 | |
732 /** | |
733 * @brief This function handles the DMA Tx Channel interrupt Handler. | |
734 * @param None | |
735 * @retval None | |
736 */ | |
737 void sEE_I2C_DMA_TX_IRQHandler(void) | |
738 { | |
739 /* Check if the DMA transfer is complete */ | |
740 if(DMA_GetFlagStatus(sEE_I2C_DMA_FLAG_TX_TC) != RESET) | |
741 { | |
742 /* Disable the DMA Tx Channel and Clear all its Flags */ | |
743 DMA_Cmd(sEE_I2C_DMA_CHANNEL_TX, DISABLE); | |
744 DMA_ClearFlag(sEE_I2C_DMA_FLAG_TX_GL); | |
745 | |
746 /*!< Wait till all data have been physically transferred on the bus */ | |
747 sEETimeout = sEE_LONG_TIMEOUT; | |
748 while(!I2C_GetFlagStatus(sEE_I2C, I2C_FLAG_BTF)) | |
749 { | |
750 if((sEETimeout--) == 0) sEE_TIMEOUT_UserCallback(); | |
751 } | |
752 | |
753 /*!< Send STOP condition */ | |
754 I2C_GenerateSTOP(sEE_I2C, ENABLE); | |
755 | |
756 /* Perform a read on SR1 and SR2 register to clear eventualaly pending flags */ | |
757 (void)sEE_I2C->SR1; | |
758 (void)sEE_I2C->SR2; | |
759 | |
760 /* Reset the variable holding the number of data to be written */ | |
761 *sEEDataWritePointer = 0; | |
762 } | |
763 } | |
764 | |
765 /** | |
766 * @brief This function handles the DMA Rx Channel interrupt Handler. | |
767 * @param None | |
768 * @retval None | |
769 */ | |
770 void sEE_I2C_DMA_RX_IRQHandler(void) | |
771 { | |
772 /* Check if the DMA transfer is complete */ | |
773 if(DMA_GetFlagStatus(sEE_I2C_DMA_FLAG_RX_TC) != RESET) | |
774 { | |
775 /*!< Send STOP Condition */ | |
776 I2C_GenerateSTOP(sEE_I2C, ENABLE); | |
777 | |
778 /* Disable the DMA Rx Channel and Clear all its Flags */ | |
779 DMA_Cmd(sEE_I2C_DMA_CHANNEL_RX, DISABLE); | |
780 DMA_ClearFlag(sEE_I2C_DMA_FLAG_RX_GL); | |
781 | |
782 /* Reset the variable holding the number of data to be read */ | |
783 *sEEDataReadPointer = 0; | |
784 } | |
785 } | |
786 | |
787 #ifdef USE_DEFAULT_TIMEOUT_CALLBACK | |
788 /** | |
789 * @brief Basic management of the timeout situation. | |
790 * @param None. | |
791 * @retval None. | |
792 */ | |
793 uint32_t sEE_TIMEOUT_UserCallback(void) | |
794 { | |
795 /* Block communication and all processes */ | |
796 while (1) | |
797 { | |
798 } | |
799 } | |
800 #endif /* USE_DEFAULT_TIMEOUT_CALLBACK */ | |
801 | |
802 #ifdef USE_DEFAULT_CRITICAL_CALLBACK | |
803 /** | |
804 * @brief Start critical section: these callbacks should be typically used | |
805 * to disable interrupts when entering a critical section of I2C communication | |
806 * You may use default callbacks provided into this driver by uncommenting the | |
807 * define USE_DEFAULT_CRITICAL_CALLBACK. | |
808 * Or you can comment that line and implement these callbacks into your | |
809 * application. | |
810 * @param None. | |
811 * @retval None. | |
812 */ | |
813 void sEE_EnterCriticalSection_UserCallback(void) | |
814 { | |
815 __disable_irq(); | |
816 } | |
817 | |
818 /** | |
819 * @brief Start and End of critical section: these callbacks should be typically used | |
820 * to re-enable interrupts when exiting a critical section of I2C communication | |
821 * You may use default callbacks provided into this driver by uncommenting the | |
822 * define USE_DEFAULT_CRITICAL_CALLBACK. | |
823 * Or you can comment that line and implement these callbacks into your | |
824 * application. | |
825 * @param None. | |
826 * @retval None. | |
827 */ | |
828 void sEE_ExitCriticalSection_UserCallback(void) | |
829 { | |
830 __enable_irq(); | |
831 } | |
832 #endif /* USE_DEFAULT_CRITICAL_CALLBACK */ | |
833 | |
834 /** | |
835 * @} | |
836 */ | |
837 | |
838 /** | |
839 * @} | |
840 */ | |
841 | |
842 /** | |
843 * @} | |
844 */ | |
845 | |
846 /** | |
847 * @} | |
848 */ | |
849 | |
850 /** | |
851 * @} | |
852 */ | |
853 | |
854 /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ |