![]() |
PDL for FM0+
Version1.0
Peripheral Driverl Library for FM0+
|
00001 /******************************************************************************* 00002 * Copyright (C) 2013 Spansion LLC. All Rights Reserved. 00003 * 00004 * This software is owned and published by: 00005 * Spansion LLC, 915 DeGuigne Dr. Sunnyvale, CA 94088-3453 ("Spansion"). 00006 * 00007 * BY DOWNLOADING, INSTALLING OR USING THIS SOFTWARE, YOU AGREE TO BE BOUND 00008 * BY ALL THE TERMS AND CONDITIONS OF THIS AGREEMENT. 00009 * 00010 * This software contains source code for use with Spansion 00011 * components. This software is licensed by Spansion to be adapted only 00012 * for use in systems utilizing Spansion components. Spansion shall not be 00013 * responsible for misuse or illegal use of this software for devices not 00014 * supported herein. Spansion is providing this software "AS IS" and will 00015 * not be responsible for issues arising from incorrect user implementation 00016 * of the software. 00017 * 00018 * SPANSION MAKES NO WARRANTY, EXPRESS OR IMPLIED, ARISING BY LAW OR OTHERWISE, 00019 * REGARDING THE SOFTWARE (INCLUDING ANY ACOOMPANYING WRITTEN MATERIALS), 00020 * ITS PERFORMANCE OR SUITABILITY FOR YOUR INTENDED USE, INCLUDING, 00021 * WITHOUT LIMITATION, THE IMPLIED WARRANTY OF MERCHANTABILITY, THE IMPLIED 00022 * WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE OR USE, AND THE IMPLIED 00023 * WARRANTY OF NONINFRINGEMENT. 00024 * SPANSION SHALL HAVE NO LIABILITY (WHETHER IN CONTRACT, WARRANTY, TORT, 00025 * NEGLIGENCE OR OTHERWISE) FOR ANY DAMAGES WHATSOEVER (INCLUDING, WITHOUT 00026 * LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, 00027 * LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS) ARISING FROM USE OR 00028 * INABILITY TO USE THE SOFTWARE, INCLUDING, WITHOUT LIMITATION, ANY DIRECT, 00029 * INDIRECT, INCIDENTAL, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOSS OF DATA, 00030 * SAVINGS OR PROFITS, 00031 * EVEN IF SPANSION HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 00032 * YOU ASSUME ALL RESPONSIBILITIES FOR SELECTION OF THE SOFTWARE TO ACHIEVE YOUR 00033 * INTENDED RESULTS, AND FOR THE INSTALLATION OF, USE OF, AND RESULTS OBTAINED 00034 * FROM, THE SOFTWARE. 00035 * 00036 * This software may be replicated in part or whole for the licensed use, 00037 * with the restriction that this Disclaimer and Copyright notice must be 00038 * included with each copy of this software, whether used in part or whole, 00039 * at all times. 00040 */ 00041 00042 /******************************************************************************/ 00053 /******************************************************************************/ 00054 /* Include files */ 00055 /******************************************************************************/ 00056 #include "i2c_at24cxx.h" 00057 #include <string.h> 00058 00059 #if (PDL_UTILITY_ENABLE_I2C_INT_AT24CXX == PDL_ON) 00060 00061 /*****************************************************************************/ 00062 /* Local pre-processor symbols/macros ('#define') */ 00063 /*****************************************************************************/ 00064 /*****************************************************************************/ 00065 /* Global variable definitions (declared in header file with 'extern') */ 00066 /*****************************************************************************/ 00067 /*****************************************************************************/ 00068 /* Local type definitions ('typedef') */ 00069 /*****************************************************************************/ 00074 typedef enum en_i2c_rw_mode 00075 { 00076 I2cTxMode = 0, 00077 I2cRxMode, 00078 I2cTxRxMode, 00079 00080 }en_i2c_rw_mode_t; 00081 00086 typedef enum en_i2c_seq 00087 { 00088 I2cSeqStart = 0u, 00089 I2cSeqWrite, 00090 I2cSeqRestart, 00091 I2cSeqRead, 00092 I2cSeqStop, 00093 00094 }en_i2c_seq_t; 00095 00100 typedef struct stc_i2c_info 00101 { 00102 boolean_t bI2cErrorFlag; 00103 uint8_t* pu8TxBuf; 00104 uint32_t u32TxSize; 00105 uint8_t* pu8RxBuf; 00106 uint32_t u32RxSize; 00107 uint32_t u32Count; 00108 en_i2c_seq_t enSequence; 00109 uint8_t u8DevAddr; 00110 en_i2c_rw_mode_t enRwMode; 00111 uint32_t u32TxRxGap; 00112 00113 }stc_i2c_info_t; 00114 00115 /*****************************************************************************/ 00116 /* Local variable definitions ('static') */ 00117 /*****************************************************************************/ 00118 stc_i2c_int_sel_t stcI2cIntSel; 00119 stc_i2c_int_cb_t stcI2cIntCb; 00120 stc_i2c_info_t stcI2cInfo; 00121 00130 static boolean_t I2cCheckErrorStatus(void) 00131 { 00132 if(TRUE == Mfs_I2c_GetStatus(EE_I2C_CH, I2cBusErr)) 00133 { 00134 return TRUE; /* Bus error occurs? */ 00135 } 00136 00137 if(TRUE == Mfs_I2c_GetStatus(EE_I2C_CH, I2cOverrunError)) 00138 { 00139 return TRUE; /* Overrun error occurs? */ 00140 } 00141 00142 return FALSE; 00143 } 00144 00152 static void Delay(uint32_t u32Cnt) 00153 { 00154 for(;u32Cnt;u32Cnt--); 00155 } 00156 00157 00163 static void I2cTxCallback(void) 00164 { 00165 if(stcI2cInfo.enSequence == I2cSeqStart) 00166 { 00167 if((stcI2cInfo.enRwMode == I2cTxMode) || (stcI2cInfo.enRwMode == I2cTxRxMode)) 00168 { 00169 /* Prepare I2C device address with write flag */ 00170 Mfs_I2c_SendData(EE_I2C_CH, ((stcI2cInfo.u8DevAddr<<1)|0u)); 00171 00172 stcI2cInfo.enSequence = I2cSeqWrite; 00173 } 00174 else 00175 { 00176 /* Prepare I2C device address with read flag */ 00177 Mfs_I2c_SendData(EE_I2C_CH, ((stcI2cInfo.u8DevAddr<<1)|1u)); 00178 00179 PDL_ZERO_STRUCT(stcI2cIntSel); 00180 stcI2cIntSel.bTxInt = TRUE; 00181 Mfs_I2c_DisableInt(EE_I2C_CH, &stcI2cIntSel); // Disable TX interrupt when read 00182 } 00183 00184 /* Enable ACK */ 00185 Mfs_I2c_ConfigAck(EE_I2C_CH, I2cAck); 00186 00187 /* Generate I2C start signal */ 00188 if(Ok != Mfs_I2c_GenerateStart(EE_I2C_CH)) 00189 { 00190 stcI2cInfo.bI2cErrorFlag = 1; 00191 return; /* Timeout or other error */ 00192 } 00193 00194 00195 } 00196 else if(stcI2cInfo.enSequence == I2cSeqRestart) 00197 { 00198 /* Sometimes a short time delay is needed before generate restart */ 00199 Delay(stcI2cInfo.u32TxRxGap); 00200 /* Prepare I2C device address */ 00201 Mfs_I2c_SendData(EE_I2C_CH, ((stcI2cInfo.u8DevAddr<<1)|1u)); 00202 00203 /* Enable ACK */ 00204 Mfs_I2c_ConfigAck(EE_I2C_CH, I2cAck); 00205 00206 /* Generate I2C start signal */ 00207 if(Ok != Mfs_I2c_GenerateRestart(EE_I2C_CH)) 00208 { 00209 stcI2cInfo.bI2cErrorFlag = 1; 00210 return ; /* Timeout or other error */ 00211 } 00212 00213 if(stcI2cInfo.enRwMode == I2cTxRxMode) 00214 { 00215 PDL_ZERO_STRUCT(stcI2cIntSel); 00216 stcI2cIntSel.bTxInt = TRUE; 00217 Mfs_I2c_DisableInt(EE_I2C_CH, &stcI2cIntSel); // Disable TX interrupt when read 00218 } 00219 00220 } 00221 else if(stcI2cInfo.enSequence == I2cSeqWrite) 00222 { 00223 if(stcI2cInfo.u32Count == stcI2cInfo.u32TxSize) 00224 { 00225 if(stcI2cInfo.enRwMode != I2cTxRxMode) 00226 { 00227 /* Generate I2C stop signal */ 00228 if(Ok != Mfs_I2c_GenerateStop(EE_I2C_CH)) 00229 { 00230 stcI2cInfo.bI2cErrorFlag = 1; 00231 return; /* Timeout or other error */ 00232 } 00233 } 00234 else // Don't generate stop signal if read continues after write 00235 { 00236 stcI2cInfo.enSequence = I2cSeqRestart; 00237 stcI2cInfo.u32Count = 0; 00238 } 00239 return; 00240 } 00241 00242 Mfs_I2c_SendData(EE_I2C_CH, *stcI2cInfo.pu8TxBuf++); 00243 Mfs_I2c_ClrStatus(EE_I2C_CH, I2cRxTxInt); 00244 00245 stcI2cInfo.u32Count++; 00246 00247 } 00248 } 00249 00255 static void I2cRxCallback(void) 00256 { 00257 if(stcI2cInfo.enSequence == I2cSeqRead) 00258 { 00259 *stcI2cInfo.pu8RxBuf++ = Mfs_I2c_ReceiveData(EE_I2C_CH); 00260 00261 if(stcI2cInfo.u32Count == stcI2cInfo.u32RxSize) 00262 { 00263 // Generate stop signal 00264 if(Ok != Mfs_I2c_GenerateStop(EE_I2C_CH)) 00265 { 00266 stcI2cInfo.bI2cErrorFlag = 1; 00267 return; /* Timeout or other error */ 00268 } 00269 return; 00270 } 00271 00272 if(stcI2cInfo.u32Count == stcI2cInfo.u32RxSize-1) 00273 { 00274 Mfs_I2c_ConfigAck(EE_I2C_CH, I2cNAck); /* Last byte send a NACK */ 00275 } 00276 00277 Mfs_I2c_ClrStatus(EE_I2C_CH, I2cRxTxInt); 00278 00279 stcI2cInfo.u32Count++; 00280 } 00281 } 00282 00288 static void I2cIntCallback(void) 00289 { 00290 if(TRUE == Mfs_I2c_GetStatus(EE_I2C_CH, I2cRxTxInt)) 00291 { 00292 /* Check error status of I2C */ 00293 if(TRUE == I2cCheckErrorStatus()) 00294 { 00295 stcI2cInfo.bI2cErrorFlag = 1; 00296 return; 00297 } 00298 00299 if((stcI2cInfo.enSequence != I2cSeqStart) && (stcI2cInfo.enSequence != I2cSeqRestart)) // In read or write sequence, clear INT at TX/RX callback 00300 { 00301 return; 00302 } 00303 00304 /* Check ACK */ 00305 if(I2cNAck == Mfs_I2c_GetAck(EE_I2C_CH)) 00306 { 00307 stcI2cInfo.bI2cErrorFlag = 1; 00308 return; /* NACK */ 00309 } 00310 00311 if(stcI2cInfo.enSequence == I2cSeqStart) 00312 { 00313 if(stcI2cInfo.enRwMode == I2cRxMode) 00314 { 00315 if(stcI2cInfo.u32Count == stcI2cInfo.u32RxSize-1) 00316 { 00317 Mfs_I2c_ConfigAck(EE_I2C_CH, I2cNAck); /* Last byte send a NACK */ 00318 } 00319 /* Receive first data here and receive following data at RX callback */ 00320 Mfs_I2c_ClrStatus(EE_I2C_CH, I2cRxTxInt); 00321 00322 stcI2cInfo.u32Count++; 00323 00324 stcI2cInfo.enSequence = I2cSeqRead; // Start read data 00325 } 00326 else 00327 { 00328 stcI2cInfo.enSequence = I2cSeqWrite; // Start write data 00329 } 00330 } 00331 00332 if(stcI2cInfo.enSequence == I2cSeqRestart) 00333 { 00334 if(stcI2cInfo.u32Count == stcI2cInfo.u32RxSize-1) 00335 { 00336 Mfs_I2c_ConfigAck(EE_I2C_CH, I2cNAck); /* Last byte send a NACK */ 00337 } 00338 /* Receive first data here and receive following data at RX callback */ 00339 Mfs_I2c_ClrStatus(EE_I2C_CH, I2cRxTxInt); 00340 00341 stcI2cInfo.u32Count++; 00342 00343 stcI2cInfo.enSequence = I2cSeqRead; // Start read data 00344 } 00345 } 00346 } 00347 00353 static void I2cStopDetectCallback(void) 00354 { 00355 if(TRUE == Mfs_I2c_GetStatus(EE_I2C_CH, I2cStopDetect)) 00356 { 00357 Mfs_I2c_ClrStatus(EE_I2C_CH, I2cStopDetect); 00358 Mfs_I2c_ClrStatus(EE_I2C_CH, I2cRxTxInt); 00359 00360 stcI2cInfo.enSequence = I2cSeqStop; 00361 00362 PDL_ZERO_STRUCT(stcI2cIntSel); 00363 stcI2cIntSel.bTxInt = TRUE; 00364 stcI2cIntSel.bRxInt = TRUE; 00365 stcI2cIntSel.bTxRxInt = TRUE; 00366 stcI2cIntSel.bStopDetectInt = TRUE; 00367 00368 Mfs_I2c_DisableInt(EE_I2C_CH, &stcI2cIntSel); // Disable interrupt 00369 } 00370 } 00371 00384 static en_result_t I2cTxData(uint8_t u8DevAddr, uint8_t* pu8Data, uint32_t u32Size) 00385 { 00386 PDL_ZERO_STRUCT(stcI2cIntSel); 00387 PDL_ZERO_STRUCT(stcI2cIntCb); 00388 PDL_ZERO_STRUCT(stcI2cInfo); 00389 00390 stcI2cInfo.enSequence = I2cSeqStart; 00391 stcI2cInfo.enRwMode = I2cTxMode; 00392 stcI2cInfo.u8DevAddr = u8DevAddr; 00393 stcI2cInfo.pu8TxBuf = pu8Data; 00394 stcI2cInfo.u32TxSize = u32Size; 00395 stcI2cInfo.u32Count = 0; 00396 stcI2cInfo.bI2cErrorFlag = 0; 00397 00398 stcI2cIntSel.bTxInt = TRUE; 00399 stcI2cIntSel.bTxRxInt = TRUE; 00400 stcI2cIntSel.bStopDetectInt = TRUE; 00401 00402 stcI2cIntCb.pfnTxIntCb = I2cTxCallback; 00403 stcI2cIntCb.pfnTxRxCb = I2cIntCallback; 00404 stcI2cIntCb.pfnStopDetectCb = I2cStopDetectCallback; 00405 00406 if(Ok != Mfs_I2c_EnableInt(EE_I2C_CH, &stcI2cIntSel, &stcI2cIntCb)) 00407 { 00408 return Error; 00409 } 00410 00411 while(stcI2cInfo.enSequence < I2cSeqStop) 00412 { 00413 if(stcI2cInfo.bI2cErrorFlag == 1) 00414 { 00415 return Error; 00416 } 00417 } 00418 00419 return Ok; 00420 } 00421 00436 static en_result_t I2cTxRxData(uint8_t u8DevAddr, 00437 uint8_t* pu8TxData, 00438 uint32_t u32TxSize, 00439 uint8_t* pu8RxData, 00440 uint32_t u32RxSize) 00441 { 00442 PDL_ZERO_STRUCT(stcI2cIntSel); 00443 PDL_ZERO_STRUCT(stcI2cIntCb); 00444 PDL_ZERO_STRUCT(stcI2cInfo); 00445 00446 stcI2cInfo.enSequence = I2cSeqStart; 00447 stcI2cInfo.enRwMode = I2cTxRxMode; 00448 stcI2cInfo.u8DevAddr = u8DevAddr; 00449 stcI2cInfo.pu8TxBuf = pu8TxData; 00450 stcI2cInfo.u32TxSize = u32TxSize; 00451 stcI2cInfo.pu8RxBuf = pu8RxData; 00452 stcI2cInfo.u32RxSize = u32RxSize; 00453 stcI2cInfo.u32Count = 0; 00454 stcI2cInfo.bI2cErrorFlag = 0; 00455 stcI2cInfo.u32TxRxGap = SystemCoreClock/(160000); 00456 00457 stcI2cIntSel.bTxInt = TRUE; 00458 stcI2cIntSel.bRxInt = TRUE; 00459 stcI2cIntSel.bTxRxInt = TRUE; 00460 stcI2cIntSel.bStopDetectInt = TRUE; 00461 00462 stcI2cIntCb.pfnTxIntCb = I2cTxCallback; 00463 stcI2cIntCb.pfnRxIntCb = I2cRxCallback; 00464 stcI2cIntCb.pfnTxRxCb = I2cIntCallback; 00465 stcI2cIntCb.pfnStopDetectCb = I2cStopDetectCallback; 00466 00467 if(Ok != Mfs_I2c_EnableInt(EE_I2C_CH, &stcI2cIntSel, &stcI2cIntCb)) 00468 { 00469 return Error; 00470 } 00471 00472 while(stcI2cInfo.enSequence < I2cSeqStop) 00473 { 00474 if(stcI2cInfo.bI2cErrorFlag == 1) 00475 { 00476 return Error; 00477 } 00478 } 00479 00480 return Ok; 00481 } 00482 00495 static en_result_t I2cRxData(uint8_t u8DevAddr, uint8_t* pu8RxData, uint32_t u32RxSize) 00496 { 00497 PDL_ZERO_STRUCT(stcI2cIntSel); 00498 PDL_ZERO_STRUCT(stcI2cIntCb); 00499 PDL_ZERO_STRUCT(stcI2cInfo); 00500 00501 stcI2cInfo.enSequence = I2cSeqStart; 00502 stcI2cInfo.enRwMode = I2cRxMode; 00503 stcI2cInfo.u8DevAddr = u8DevAddr; 00504 stcI2cInfo.pu8RxBuf = pu8RxData; 00505 stcI2cInfo.u32RxSize = u32RxSize; 00506 stcI2cInfo.u32Count = 0; 00507 stcI2cInfo.bI2cErrorFlag = 0; 00508 00509 stcI2cIntSel.bTxInt = TRUE; 00510 stcI2cIntSel.bRxInt = TRUE; 00511 stcI2cIntSel.bTxRxInt = TRUE; 00512 stcI2cIntSel.bStopDetectInt = TRUE; 00513 00514 stcI2cIntCb.pfnTxIntCb = I2cTxCallback; 00515 stcI2cIntCb.pfnRxIntCb = I2cRxCallback; 00516 stcI2cIntCb.pfnTxRxCb = I2cIntCallback; 00517 stcI2cIntCb.pfnStopDetectCb = I2cStopDetectCallback; 00518 00519 if(Ok != Mfs_I2c_EnableInt(EE_I2C_CH, &stcI2cIntSel, &stcI2cIntCb)) 00520 { 00521 return Error; 00522 } 00523 00524 while(stcI2cInfo.enSequence < I2cSeqStop) 00525 { 00526 if(stcI2cInfo.bI2cErrorFlag == 1) 00527 { 00528 return Error; 00529 } 00530 } 00531 00532 return Ok; 00533 } 00534 00543 en_result_t At24cxx_Init(void) 00544 { 00545 stc_mfs_i2c_config_t stcI2cConfig; 00546 PDL_ZERO_STRUCT(stcI2cConfig); 00547 00548 InitI2cIo(); 00549 00550 stcI2cConfig.enMsMode = I2cMaster; 00551 stcI2cConfig.u32BaudRate = 100000u; 00552 stcI2cConfig.bWaitSelection = FALSE; 00553 stcI2cConfig.bDmaEnable = FALSE; 00554 stcI2cConfig.bEnableFifo = FALSE; 00555 00556 if(Ok != Mfs_I2c_Init(EE_I2C_CH, &stcI2cConfig)) 00557 { 00558 return Error; 00559 } 00560 00561 return Ok; 00562 } 00563 00576 en_result_t At24cxx_ByteWrite(uint8_t u8DevAddr, uint16_t u16Addr, uint8_t u8Data) 00577 { 00578 uint8_t au8TempData[3]; 00579 00580 /* Send data address */ 00581 if(AT24CXX_ADDR_LENGTH == 1) 00582 { 00583 au8TempData[0] = u16Addr & 0x00FFu; 00584 au8TempData[1] = u8Data; 00585 } 00586 else 00587 { 00588 au8TempData[0] = u16Addr & 0x00FFu; 00589 au8TempData[1] = (u16Addr & 0xFF00u) >> 8; 00590 au8TempData[2] = u8Data; 00591 } 00592 00593 I2cTxData(u8DevAddr, au8TempData, (AT24CXX_ADDR_LENGTH+1)); 00594 00595 return Ok; 00596 } 00597 00598 00612 en_result_t At24cxx_PageWrite(uint8_t u8DevAddr, uint16_t u16PageAddr, uint8_t* pu8Data, uint8_t u8Size) 00613 { 00614 uint8_t au8DataBuf[2+AT24CXX_PAGE_SIZE]; 00615 00616 if(u8Size > AT24CXX_PAGE_SIZE) 00617 { 00618 return ErrorInvalidParameter; 00619 } 00620 00621 if(AT24CXX_ADDR_LENGTH == 1) 00622 { 00623 au8DataBuf[0] = u16PageAddr & 0x00FFu; 00624 memcpy(&au8DataBuf[1], pu8Data, u8Size); 00625 } 00626 else 00627 { 00628 au8DataBuf[0] = u16PageAddr & 0x00FFu; 00629 au8DataBuf[1] = (u16PageAddr & 0xFF00u) >> 8; 00630 memcpy(&au8DataBuf[2], pu8Data, u8Size); 00631 } 00632 00633 if(Ok != I2cTxData(u8DevAddr, au8DataBuf, (AT24CXX_ADDR_LENGTH+u8Size))) 00634 { 00635 return Error; 00636 } 00637 00638 return Ok; 00639 } 00640 00652 en_result_t At24cxx_CurrentAddrRead(uint8_t u8DevAddr, uint8_t* pu8CurData) 00653 { 00654 if(Ok != I2cRxData(u8DevAddr, pu8CurData, 1)) 00655 { 00656 return Error; 00657 } 00658 00659 return Ok; 00660 } 00661 00674 en_result_t At24cxx_RandomRead(uint8_t u8DevAddr, uint16_t u16Addr, uint8_t* pu8Data) 00675 { 00676 uint8_t au8TempData[2]; 00677 00678 /* Send address */ 00679 if(AT24CXX_ADDR_LENGTH == 1) 00680 { 00681 au8TempData[0] = u16Addr & 0x00FFu; 00682 } 00683 else 00684 { 00685 au8TempData[0] = u16Addr & 0x00FFu; 00686 au8TempData[1] = (u16Addr & 0xFF00u) >> 8; 00687 } 00688 00689 I2cTxRxData(u8DevAddr, au8TempData, AT24CXX_ADDR_LENGTH, pu8Data, 1); 00690 00691 return Ok; 00692 } 00693 00706 en_result_t At24cxx_SequentialRead(uint8_t u8DevAddr, uint8_t* pu8Data, uint8_t u8Size) 00707 { 00708 if(Ok != I2cRxData(u8DevAddr, pu8Data, u8Size)) 00709 { 00710 return Error; 00711 } 00712 00713 return Ok; 00714 } 00715 00723 void At24cxx_Delayms(uint32_t u32Cnt) 00724 { 00725 uint32_t u32i; 00726 00727 for(;u32Cnt;u32Cnt--) 00728 for(u32i=SystemCoreClock/12000; u32i; u32i--); 00729 } 00730 00731 00732 #endif // if (PDL_UTILITY_ENABLE_I2C_INT_AT24CXX == PDL_ON) 00733 00734 /******************************************************************************/ 00735 /* EOF (not truncated) */ 00736 /******************************************************************************/