Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
abcc_par30_drv.c
00001 /******************************************************************************* 00002 ******************************************************************************** 00003 ** ** 00004 ** ABCC Driver version 4.01.01 (2015-12-14) ** 00005 ** ** 00006 ** Delivered with: ** 00007 ** ABP 7.16.01 (2015-10-14) ** 00008 ** */ 00009 /******************************************************************************* 00010 ******************************************************************************** 00011 ** COPYRIGHT NOTIFICATION (c) 2013 HMS Industrial Networks AB ** 00012 ** ** 00013 ** This code is the property of HMS Industrial Networks AB. ** 00014 ** The source code may not be reproduced, distributed, or used without ** 00015 ** permission. When used together with a product from HMS, permission is ** 00016 ** granted to modify, reproduce and distribute the code in binary form ** 00017 ** without any restrictions. ** 00018 ** ** 00019 ** THE CODE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. HMS DOES NOT ** 00020 ** WARRANT THAT THE FUNCTIONS OF THE CODE WILL MEET YOUR REQUIREMENTS, OR ** 00021 ** THAT THE OPERATION OF THE CODE WILL BE UNINTERRUPTED OR ERROR-FREE, OR ** 00022 ** THAT DEFECTS IN IT CAN BE CORRECTED. ** 00023 ******************************************************************************** 00024 ******************************************************************************** 00025 ** File Description: 00026 ** Parallel (PARI) driver implementation. 00027 ******************************************************************************** 00028 ******************************************************************************** 00029 */ 00030 #include "abcc_drv_cfg.h" 00031 00032 #if( ABCC_CFG_DRV_PARALLEL_30 ) 00033 00034 #include "abcc_td.h" 00035 #include "../abcc_debug_err.h" 00036 #include "abcc_sys_adapt.h" 00037 #include "../abcc_timer.h" 00038 #include "../abcc_drv_if.h" 00039 #include "../abcc_mem.h" 00040 #include "abp.h" 00041 #include "abcc_sys_adapt_par.h" 00042 #include "abcc_port.h" 00043 00044 /******************************************************************************* 00045 ** Constants 00046 ******************************************************************************** 00047 */ 00048 00049 /******************************************************************************* 00050 ** Typedefs 00051 ******************************************************************************** 00052 */ 00053 00054 typedef enum ABCC_DrvPar30State 00055 { 00056 SM_RDY_TO_PING, 00057 SM_WAITING_FOR_PONG, 00058 SM_SER_INIT 00059 } 00060 ABCC_DrvPar30StateType; 00061 00062 /******************************************************************************* 00063 ** Private Globals 00064 ******************************************************************************** 00065 */ 00066 00067 static ABP_MsgType* par_drv_pbReadMessageData; 00068 static UINT8* par_drv_pbRdPdBuffer; 00069 00070 static UINT16 par_drv_iSizeOfReadPd; 00071 static UINT16 par_drv_iSizeOfWritePd; 00072 00073 static UINT8 par_drv_bNbrOfCmds; /* Number of commands supported by the application. */ 00074 static ABCC_TimerHandle xWdTmoHandle; 00075 static BOOL fWdTmo; /* Current wd timeout status */ 00076 static BOOL drv_fLegacy; /* USe legacy format */ 00077 00078 /* 00079 ** Working copies of the status and control registers 00080 */ 00081 static volatile UINT8 bControlReg = ABP_CTRL_R_BIT; 00082 static volatile UINT8 bStatusReg = 0x80; 00083 static volatile ABCC_DrvPar30StateType eState = SM_SER_INIT; 00084 00085 00086 00087 /******************************************************************************* 00088 ** Private forward declarations 00089 ******************************************************************************** 00090 */ 00091 00092 00093 /******************************************************************************* 00094 ** Private Services 00095 ******************************************************************************** 00096 */ 00097 /* 00098 ** Converting to/from legacy message format. 00099 ** 00100 ** ABCC40 msg header Leagcy msg header 00101 ** -------------------- 00102 ** | UINT16 iDataSize | 00103 ** -------------------- 00104 ** | UINT16 iReserved | 00105 ** -------------------- -------------------- 00106 ** | UINT8 bSourceId | | UINT8 bSourceId | 00107 ** -------------------- -------------------- 00108 ** | UINT8 bDestObj | | UINT8 bDestObj | 00109 ** -------------------- -------------------- 00110 ** | UINT8 bSourceId | | UINT8 bSourceId | 00111 ** -------------------- -------------------- 00112 ** | UINT16 iInstance | | UINT16 iInstance | 00113 ** -------------------- -------------------- 00114 ** | UINT8 bReserved | | UINT8 bDataSize | 00115 ** -------------------- -------------------- 00116 ** | UINT8 bCmdExt0 | | UINT8 bCmdExt0 | 00117 ** -------------------- -------------------- 00118 ** | UINT8 bCmdExt1 | | UINT8 bCmdExt1 | 00119 ** -------------------- -------------------- 00120 ** 00121 ** The last 8 bytes in the new message format 00122 ** structured the same way as the legacy message format 00123 ** except for bReserved which is placed on the legacy 00124 ** bDataSize position. 00125 ** 00126 ** This means that the conversion from "new" meessage format 00127 ** to legacy format 00128 ** is simply done by copying the iDataSize to the bReserved 00129 ** filed and the message is sent from the bsourceId address position. 00130 ** 00131 ** 00132 ** Read message are converted the same way. The data from 00133 ** ACI are copied to the bSourceId address position. The bReserved 00134 ** field are copied to the iDataSize filed. 00135 ** 00136 ** Note that the iDataSize need to be converted to/from little endian. 00137 ** 00138 */ 00139 static void drv_DoMsgWrite( ABP_MsgType* psMsg ) 00140 { 00141 /* 00142 ** First Calculate total message size 00143 */ 00144 UINT16 iMsgSize = iLeTOi( psMsg->sHeader.iDataSize ); 00145 00146 ABCC_ASSERT( iMsgSize < ABP_MAX_MSG_DATA_BYTES ); 00147 iMsgSize += sizeof( ABP_MsgHeaderType ); 00148 00149 ABCC_DrvParallelWrite( ABP_WRMSG_ADR_OFFSET, (UINT8*)psMsg, iMsgSize ); 00150 } 00151 00152 00153 static void drv_DoLegacyMsgWrite( ABP_MsgType* psMsg ) 00154 { 00155 UINT16 iMsgSize = iLeTOi( psMsg->sHeader.iDataSize ); 00156 00157 ABCC_ASSERT( iMsgSize <= ABP_MAX_MSG_255_DATA_BYTES ); 00158 iMsgSize += sizeof( ABP_Msg255HeaderType ); 00159 psMsg->sHeader.bReserved = (UINT8)psMsg->sHeader.iDataSize; 00160 ABCC_DrvParallelWrite( ABP_WRMSG_LEGACY_ADR_OFFSET, (UINT8*)&psMsg->sHeader.bSourceId, iMsgSize ); 00161 } 00162 00163 static void drv_DoMsgRead( ABP_MsgType* psMsg ) 00164 { 00165 UINT16 iMsgSize; 00166 00167 ABCC_DrvParallelRead( ABP_RDMSG_ADR_OFFSET, (UINT8*)psMsg, sizeof( ABP_MsgHeaderType ) ); 00168 00169 iMsgSize = iLeTOi( psMsg->sHeader.iDataSize ); 00170 00171 if( iMsgSize > ABCC_CFG_MAX_MSG_SIZE ) 00172 { 00173 /* 00174 ** Message size exceeds buffer. 00175 */ 00176 ABCC_ERROR( ABCC_SEV_FATAL, ABCC_EC_RDMSG_SIZE_ERR, 0 ); 00177 00178 return; 00179 } 00180 00181 /* 00182 ** Continue reading data area if > 0. 00183 */ 00184 if ( iMsgSize > 0 ) 00185 { 00186 ABCC_DrvParallelRead( ABP_RDMSG_ADR_OFFSET + sizeof( ABP_MsgHeaderType ), 00187 psMsg->abData, 00188 iMsgSize ); 00189 } 00190 } 00191 00192 00193 void drv_DoLegacyMsgRead( ABP_MsgType* psMsg ) 00194 { 00195 UINT16 iMsgSize; 00196 00197 ABCC_DrvParallelRead( ABP_RDMSG_LEGACY_ADR_OFFSET, (UINT8*)&psMsg->sHeader.bSourceId, sizeof( ABP_Msg255HeaderType ) ); 00198 00199 iMsgSize = (UINT16)( psMsg->sHeader.bReserved ); 00200 00201 if( ( iMsgSize > ABP_MAX_MSG_255_DATA_BYTES ) || 00202 ( iMsgSize > ABCC_CFG_MAX_MSG_SIZE ) ) 00203 { 00204 /* 00205 ** Message size exceeds buffer. 00206 */ 00207 ABCC_ERROR( ABCC_SEV_FATAL, ABCC_EC_RDMSG_SIZE_ERR, 0 ); 00208 00209 return; 00210 } 00211 00212 psMsg->sHeader.iDataSize = iTOiLe( iMsgSize ); 00213 00214 /* 00215 ** Continue reading data area if > 0. 00216 */ 00217 if( iMsgSize > 0 ) 00218 { 00219 ABCC_DrvParallelRead( ABP_RDMSG_LEGACY_ADR_OFFSET + sizeof( ABP_Msg255HeaderType ), 00220 psMsg->abData, 00221 iMsgSize ); 00222 } 00223 } 00224 00225 00226 static void drv_WdTimeoutHandler( void ) 00227 { 00228 fWdTmo = TRUE; 00229 ABCC_CbfWdTimeout(); 00230 } 00231 00232 /******************************************************************************* 00233 ** Public Services 00234 ******************************************************************************** 00235 */ 00236 void ABCC_DrvPar30Init( UINT8 bOpmode ) 00237 { 00238 /* 00239 ** Initialize privates and states. 00240 */ 00241 ABCC_ASSERT_ERR( bOpmode == 8 , ABCC_SEV_FATAL, ABCC_EC_INCORRECT_OPERATING_MODE, (UINT32)bOpmode ); 00242 00243 par_drv_iSizeOfReadPd = 0; 00244 par_drv_iSizeOfWritePd = 0; 00245 par_drv_bNbrOfCmds = 0; 00246 par_drv_pbRdPdBuffer = ABCC_DrvParallelGetRdPdBuffer(); 00247 bControlReg = ABP_CTRL_R_BIT | ABP_CTRL_T_BIT; 00248 bStatusReg = 0; 00249 eState = SM_SER_INIT; 00250 xWdTmoHandle = ABCC_TimerCreate( drv_WdTimeoutHandler ); 00251 fWdTmo = FALSE; 00252 00253 /* If an ABCC40 is attached then use big messages */ 00254 if ( ABCC_ReadModuleId() == ABP_MODULE_ID_ACTIVE_ABCC40 ) 00255 { 00256 drv_fLegacy = FALSE; 00257 } 00258 else 00259 { 00260 drv_fLegacy = TRUE; 00261 } 00262 } 00263 00264 void ABCC_DrvPar30SetIntMask( const UINT16 iIntMask ) 00265 { 00266 /* 00267 ** Not possible to set interrupt mask. 00268 */ 00269 (void)iIntMask; 00270 } 00271 00272 #if( ABCC_CFG_INT_ENABLED ) 00273 UINT16 ABCC_DrvPar30ISR( void ) 00274 { 00275 /* 00276 ** Interrupt is acknowledged when status register is read 00277 */ 00278 ABCC_DrvRead8( ABP_STATUS_ADR_OFFSET ); 00279 00280 return 0; 00281 } 00282 #else 00283 UINT16 ABCC_DrvPar30ISR( void ) 00284 { 00285 ABCC_ERROR( ABCC_SEV_WARNING, ABCC_EC_INTERNAL_ERROR, 0); 00286 return 0; 00287 } 00288 #endif 00289 00290 00291 ABP_MsgType* ABCC_DrvPar30RunDriverRx( void ) 00292 { 00293 UINT8 bNewStatusReg1; 00294 UINT8 bNewStatusReg2; 00295 00296 if ( eState == SM_WAITING_FOR_PONG ) 00297 { 00298 00299 do 00300 { 00301 bNewStatusReg1 = ABCC_DrvRead8( ABP_STATUS_ADR_OFFSET ); 00302 bNewStatusReg2 = ABCC_DrvRead8( ABP_STATUS_ADR_OFFSET ); 00303 } while ( bNewStatusReg1 != bNewStatusReg2 ); 00304 00305 00306 if( ( bNewStatusReg1 & ABP_STAT_T_BIT ) != ( bStatusReg & ABP_STAT_T_BIT ) ) 00307 { 00308 bStatusReg = bNewStatusReg1; 00309 bControlReg &= ~ABP_CTRL_M_BIT; 00310 bControlReg ^= ABP_CTRL_T_BIT; 00311 00312 ABCC_TimerStop( xWdTmoHandle ); 00313 /* 00314 ** Check if timeout has occurred. 00315 */ 00316 if( fWdTmo == TRUE ) 00317 { 00318 ABCC_CbfWdTimeoutRecovered(); 00319 } 00320 fWdTmo = FALSE; 00321 eState = SM_RDY_TO_PING; 00322 } 00323 } 00324 else if ( eState == SM_SER_INIT ) 00325 { 00326 eState = SM_RDY_TO_PING; 00327 } 00328 00329 return NULL; 00330 } 00331 00332 00333 void ABCC_DrvPar30RunDriverTx( void ) 00334 { 00335 if(eState == SM_RDY_TO_PING ) 00336 { 00337 ABCC_DrvWrite8( ABP_CONTROL_ADR_OFFSET, bControlReg ); 00338 /* 00339 ** Start WD timer 00340 */ 00341 ABCC_TimerStart(xWdTmoHandle, ABCC_CFG_WD_TIMEOUT_MS ); 00342 eState = SM_WAITING_FOR_PONG; 00343 } 00344 } 00345 00346 00347 00348 00349 BOOL ABCC_DrvPar30WriteMessage( ABP_MsgType* psWriteMsg ) 00350 { 00351 ABCC_ASSERT( psWriteMsg ); 00352 00353 if( drv_fLegacy ) 00354 { 00355 drv_DoLegacyMsgWrite( psWriteMsg ); 00356 } 00357 else 00358 { 00359 drv_DoMsgWrite( psWriteMsg ); 00360 } 00361 00362 bControlReg |= ABP_CTRL_M_BIT; 00363 00364 /* 00365 ** Determine if command messages (instead of response messages) can be sent. 00366 */ 00367 if( !( psWriteMsg->sHeader.bCmd & ABP_MSG_HEADER_C_BIT ) ) 00368 { 00369 /* 00370 ** A command message has been received by the host application and a 00371 ** response message (not a command message) will be sent back to the 00372 ** Anybus. The number of commands the host application can receive 00373 ** shall be increased by one, as a previous received command is now 00374 ** handled. 00375 */ 00376 par_drv_bNbrOfCmds++; 00377 00378 /* 00379 ** When a change of the number of commands which the host application 00380 ** can receive is made from 0 to 1, it means that we can set the APPRF 00381 ** flag again to indicate for the Anybus that the host is now ready to 00382 ** receive a new command. 00383 */ 00384 bControlReg |= ABP_CTRL_R_BIT;; 00385 } 00386 00387 /* 00388 ** Update the buffer control register. 00389 */ 00390 return( TRUE); 00391 } 00392 00393 00394 void ABCC_DrvPar30WriteProcessData( void* pxProcessData ) 00395 { 00396 00397 if( par_drv_iSizeOfWritePd ) 00398 { 00399 /* 00400 ** Write process data. 00401 */ 00402 ABCC_DrvWriteWrPd(pxProcessData, par_drv_iSizeOfWritePd ); 00403 } 00404 } 00405 00406 00407 BOOL ABCC_DrvPar30IsReadyForWriteMessage( void ) 00408 { 00409 BOOL fRdyForCmd = FALSE; 00410 00411 if( eState == SM_RDY_TO_PING ) 00412 { 00413 if( !( bControlReg & ABP_CTRL_M_BIT ) ) 00414 { 00415 fRdyForCmd = TRUE; 00416 } 00417 } 00418 return fRdyForCmd; 00419 } 00420 00421 00422 BOOL ABCC_DrvPar30IsReadyForCmd( void ) 00423 { 00424 BOOL fRdyForCmd = FALSE; 00425 00426 if( eState == SM_RDY_TO_PING ) 00427 { 00428 if( ( bStatusReg & ABP_STAT_R_BIT ) && !( bControlReg & ABP_CTRL_M_BIT ) ) 00429 { 00430 fRdyForCmd = TRUE; 00431 } 00432 } 00433 00434 return fRdyForCmd; 00435 } 00436 00437 00438 void ABCC_DrvPar30SetNbrOfCmds( UINT8 bNbrOfCmds ) 00439 { 00440 par_drv_bNbrOfCmds = bNbrOfCmds; 00441 00442 /* 00443 ** Acknowledge that we are ready to accept the first command message. 00444 */ 00445 bControlReg |= ABP_CTRL_R_BIT; 00446 } 00447 00448 00449 void ABCC_DrvPar30SetAppStatus( ABP_AppStatusType eAppStatus ) 00450 { 00451 (void)eAppStatus; 00452 } 00453 00454 void ABCC_DrvPar30SetPdSize( const UINT16 iReadPdSize, const UINT16 iWritePdSize ) 00455 { 00456 par_drv_iSizeOfReadPd = iReadPdSize; 00457 par_drv_iSizeOfWritePd = iWritePdSize; 00458 } 00459 00460 00461 static void DrvPar30SetMsgReceiverBuffer( ABP_MsgType* const psReadMsg ) 00462 { 00463 /* 00464 ** The buffer can be NULL if we are out of msg resources. 00465 ** We can not start a new ping-pong before this is resolved. 00466 */ 00467 par_drv_pbReadMessageData = psReadMsg; 00468 } 00469 00470 00471 UINT16 ABCC_DrvPar30GetIntStatus( void ) 00472 { 00473 return 0; 00474 } 00475 00476 UINT8 ABCC_DrvPar30GetAnybusState( void ) 00477 { 00478 /* 00479 ** The Anybus state is stored in bits 0-2 of the status register. 00480 */ 00481 return( bStatusReg & 0x07 ); 00482 } 00483 00484 00485 void* ABCC_DrvPar30ReadProcessData( void ) 00486 { 00487 /* 00488 ** TODO Check valid data 00489 */ 00490 00491 if ( ( par_drv_iSizeOfReadPd == 0) || ( eState == SM_WAITING_FOR_PONG ) ) 00492 { 00493 return NULL; 00494 } 00495 00496 ABCC_DrvReadRdPd( par_drv_pbRdPdBuffer, par_drv_iSizeOfReadPd ); 00497 return( par_drv_pbRdPdBuffer ); 00498 } 00499 00500 ABP_MsgType* ABCC_DrvPar30ReadMessage( void ) 00501 { 00502 if( eState == SM_RDY_TO_PING ) 00503 { 00504 if( bStatusReg & ABP_STAT_M_BIT ) 00505 { 00506 DrvPar30SetMsgReceiverBuffer( ABCC_MemAlloc() ); 00507 00508 if( par_drv_pbReadMessageData == NULL ) 00509 { 00510 ABCC_ERROR( ABCC_SEV_WARNING, ABCC_EC_OUT_OF_MSG_BUFFERS, 0 ); 00511 return( NULL ); 00512 } 00513 00514 if( drv_fLegacy ) 00515 { 00516 drv_DoLegacyMsgRead( par_drv_pbReadMessageData ); 00517 } 00518 else 00519 { 00520 drv_DoMsgRead( par_drv_pbReadMessageData ); 00521 } 00522 00523 /* 00524 ** Determine if command messages (instead of response messages) can be read. 00525 */ 00526 if( par_drv_pbReadMessageData->sHeader.bCmd & ABP_MSG_HEADER_C_BIT ) 00527 { 00528 /* 00529 ** A command messages has been sent by the Anybus and it has been read 00530 ** by the host application. The number of commands allowed by the host 00531 ** application must be decreased by one. 00532 */ 00533 par_drv_bNbrOfCmds--; 00534 00535 /* 00536 ** Indicates that the host application is not ready to receive a new 00537 ** command from the Anybus. Writing to this register must only be done 00538 ** when the RDMSG bit is set to 1. A check is not required however, 00539 ** since the RDMSG bit is set to 1 a few lines higher up in the code. 00540 */ 00541 if( par_drv_bNbrOfCmds == 0 ) 00542 { 00543 /* 00544 ** Update the buffer control register. 00545 */ 00546 bControlReg &= ~ABP_CTRL_R_BIT; 00547 } 00548 } 00549 00550 return( par_drv_pbReadMessageData ); 00551 } 00552 } 00553 return( NULL ); 00554 } 00555 00556 BOOL ABCC_DrvPar30IsReadyForWrPd( void ) 00557 { 00558 if ( eState == SM_RDY_TO_PING ) 00559 { 00560 return TRUE; 00561 } 00562 00563 return FALSE; 00564 } 00565 00566 UINT8* ABCC_DrvPar30GetWrPdBuffer( void ) 00567 { 00568 return ABCC_DrvParallelGetWrPdBuffer(); 00569 } 00570 00571 00572 UINT16 ABCC_DrvPar30GetModCap( void ) 00573 { 00574 return 0xFFFF; 00575 } 00576 00577 UINT16 ABCC_DrvPar30GetLedStatus( void ) 00578 { 00579 return 0; 00580 } 00581 00582 BOOL ABCC_DrvPar30IsSupervised( void ) 00583 { 00584 /* 00585 ** The Anybus supervision bis is stored in bit 3 00586 */ 00587 return( ( bStatusReg >> 3 ) & 1 ); 00588 } 00589 00590 UINT8 ABCC_DrvPar30GetAnbStatus( void ) 00591 { 00592 return bStatusReg & 0xf ; 00593 } 00594 00595 00596 00597 #endif 00598 /******************************************************************************* 00599 ** End of par_drv.c 00600 ******************************************************************************** 00601 */
Generated on Tue Jul 12 2022 15:51:56 by
