csi_bus.c File Reference

Implementation of hardware independent serial driver for CSI. More...

#include "csi_bus.h"
#include <string.h>
#include "csi_hwserial.h"
#include "csi_const.h"
#include "csi_crc.h"
#include "csi_types.h"
+ Include dependency graph for csi_bus.c:

Macros

#define CSI_ACK_ERR   'F'
 negative acknowledge
 
#define CSI_ACK_OK   'O'
 positive acknowledge
 
#define CSI_CMD_ANSWER   0x00
 answer from device
 
#define CSI_CMD_DATA_READ   0x10
 read up to 4 bytes of data
 
#define CSI_CMD_DATA_WRITE   0x11
 write up to 4 bytes of data
 
#define CSI_CMD_SEG_READ   0x14
 read segment
 
#define CSI_CMD_SEG_READ_INIT   0x12
 start read of segmented data
 
#define CSI_CMD_SEG_WRITE   0x15
 write segment
 
#define CSI_CMD_SEG_WRITE_INIT   0x13
 initialize segmented write
 
#define CSI_COMM_TIMEOUT_MS   500
 default timeout
 
#define WORDSIZE_CRC_1   1
 
#define WORDSIZE_DATA_BYTES_2   2
 
#define WORDSIZE_ERR_CODE_2   2
 
#define WORDSIZE_EXPEDITED_DATA_2   2
 
#define WORDSIZE_HEADER_1   1
 
#define WORDSIZE_INDEX_1   1
 
#define WORDSIZE_INDEX_SUB_2   2
 
#define WORDSIZE_OBJECT_LEN_2   2
 
#define WORDSIZE_OPCODE_LEN_1   1
 
#define WORDSIZE_SEG_CONTROL_BYTE_1   1
 
#define WORDSIZE_SUB_AND_NODE_ID_1   1
 

Enumerations

enum  eAccess { WRITE_ACCESS = 1, READ_ACCESS = 0 }
 
enum  eCtrlByteBits { TOGGLE_BIT = 0x40, MORE_SEGMENTS_BIT = 0x80 }
 
enum  eOpcodeV2 {
  OpcodeResponse = 0x00, OpcodeReadObject = 0x60, OpcodeInitiateSegementedRead = 0x61, OpcodeSegmentRead = 0x62,
  OpcodeWriteObject = 0x68, OpcodeInitiateSegmentedWrite = 0x69, OpcodeSegmentWrite = 0x6A
}
 

Functions

static int Csi_CreateByteStreamV2 (TCsiFrameBuf *Frame, TCsiFrameBuf *ByteStream)
 
static void Csi_MemcpySwap (void *pDestBuf, const void *pSrcBuf, uint32_t dwDataSize)
 
static uint16_t Csi_PrepareFrameHeader (struct CsiBus *pBus, uint8_t NodeId, uint16_t ObjDicIdx, uint8_t ObjDicSub, uint8_t Command, uint8_t DataAndCrcWordSize, uint16_t *CRC)
 
static void Csi_PrepareTxFrameV2 (TCsiFrameBuf *TxFrame, uint8_t NodeId, uint16_t ObjDicIdx, uint8_t ObjDicSub, uint32_t *pTransfDWord, uint8_t Write)
 
static void Csi_StoreCrcIntoFrame (struct CsiBus *pBus, uint8_t DataAndCrcWordSize, uint16_t *CRC)
 
static uint16_t Csi_StoreIntoFrame (uint16_t *TxFrame, const void *pWordData, uint16_t Bytes, uint16_t *CRC)
 
static uint16_t Csi_StoreWordIntoFrame (uint16_t *TxFrame, uint16_t Data, uint16_t *CRC)
 
static void Csi_StoreWordIntoFrameV2 (uint8_t *TxFrame, uint16_t Data)
 
static long CsiBus_ExecuteSingleTransfer (struct CsiBus *pBus, uint8_t DataAndCrcWordSize, uint8_t RxWordsMinus1)
 
static long CsiBus_ReceiveResponseV2 (struct CsiBus *pBus, TCsiFrameBuf *RxFrame)
 
static long CsiBus_SendAckn (struct CsiBus *pBus)
 
static long CsiBus_TransfData (struct CsiBus *pBus, uint8_t NodeId, uint16_t ObjDicIdx, uint8_t ObjDicSub, uint32_t *pTransfDWord, uint8_t bWrite)
 
long CsiBus_TransfDataV2 (struct CsiBus *pBus, uint8_t NodeId, uint16_t ObjDicIdx, uint8_t ObjDicSub, uint32_t *pTransfDWord, uint8_t Write)
 
static long CsiBus_WaitForAckn (struct CsiBus *pBus)
 
static long CsiBus_WaitForChar (struct CsiBus *pBus, uint8_t WaitChar)
 
long CsiBusClose (struct CsiBus *pBus)
 Close connection. More...
 
long CsiBusOpen (struct CsiBus *pBus)
 This function initializes connection to CSI bus. More...
 
long CsiBusReadData (struct CsiBus *pBus, uint8_t NodeId, uint16_t ObjDicIdx, uint8_t ObjDicSub, uint32_t *pRxDWord)
 This function reads up to 4 bytes of data from device object dictionary. More...
 
long CsiBusReadDataV2 (struct CsiBus *pBus, uint8_t NodeId, uint16_t ObjDicIdx, uint8_t ObjDicSub, uint32_t *pRxDWord)
 This function reads up to 4 bytes of data from device object dictionary using the new serial protocol version V2. More...
 
long CsiBusReadLargeData (struct CsiBus *pBus, uint8_t NodeId, uint16_t ObjDicIdx, uint8_t ObjDicSub, uint8_t *pDataBuffer, uint16_t BufferSize)
 Use this function if you need to read more than 4 bytes of data. More...
 
long CsiBusWriteData (struct CsiBus *pBus, uint8_t NodeId, uint16_t ObjDicIdx, uint8_t ObjDicSub, uint32_t TxDWord)
 This function writes up to 4 bytes of data into device object dictionary. More...
 
long CsiBusWriteDataV2 (struct CsiBus *pBus, uint8_t NodeId, uint16_t ObjDicIdx, uint8_t ObjDicSub, uint32_t TxDWord)
 This function writes up to 4 bytes of data into device object dictionary using the new serial protocol version V2. More...
 
long CsiBusWriteLargeData (struct CsiBus *pBus, uint8_t NodeId, uint16_t ObjDicIdx, uint8_t ObjDicSub, uint8_t *pDataBuffer, uint32_t DataSize, CsiDataTransferCallback Callback)
 Use this function if you need to write more than 4 bytes of data. More...
 

Variables

static const uint8_t DLE = 0x90
 
static const uint8_t STX = 0x02
 

Detailed Description

Implementation of hardware independent serial driver for CSI.

Author
Uwe Kindler (UK)
Date
2009/09/08

Function Documentation

long CsiBusClose ( struct CsiBus pBus)

Close connection.

Parameters
[in]pBusBus object to finish communication
Returns
Error code - ERR_NOERR indicates success

Referenced by CsiClose().

110 {
111  return CsiHwSerCloseChannel(&pBus->SerChannel);
112 }
CSI_API long CsiHwSerCloseChannel(struct CsiSerChannel *pChan)
Closes serial connection.
struct CsiSerChannel SerChannel
serial channel data for connection
Definition: csi_types.h:79

+ Here is the call graph for this function:

long CsiBusOpen ( struct CsiBus pBus)

This function initializes connection to CSI bus.

Parameters
[in]pBusBus object with properly set timeout value and configured serial channel data
Returns
Error code - ERR_NOERR indicates success

Referenced by CsiConnectToDevice(), and CsiOpen().

93 {
94  long Result;
95 
96  Result = CsiHwSerOpenChannel(&pBus->SerChannel);
97  if (Result != ERR_NOERR)
98  {
99  return Result;
100  }
101 
102  return ERR_NOERR;
103 }
#define ERR_NOERR
No error.
Definition: err_codes.h:102
CSI_API long CsiHwSerOpenChannel(struct CsiSerChannel *pChan)
Initializes serial channel configuration data and opens serial connection.
struct CsiSerChannel SerChannel
serial channel data for connection
Definition: csi_types.h:79

+ Here is the call graph for this function:

long CsiBusReadData ( struct CsiBus pBus,
uint8_t  NodeId,
uint16_t  ObjDicIdx,
uint8_t  ObjDicSub,
uint32_t *  pRxDWord 
)

This function reads up to 4 bytes of data from device object dictionary.

Parameters
[in]pBusBus object the device is attached to
[in]NodeIdNodeId (1 - 30) of device to read from
[in]ObjDicIdxIndex into device object dictionary
[in]ObjDicSubSub entry of object dictionary entry
[in]pRxDWordPoints to DWord buffer for storage of received data
Returns
Error code - ERR_NOERR indicates success

Referenced by CsiDevReadObject().

607 {
608  return CsiBus_TransfData(pBus, NodeId, ObjDicIdx, ObjDicSub, pRxDWord, 0);
609 }
uint8_t NodeId
the node identifier for this device
Definition: csi_types.h:91
long CsiBusReadDataV2 ( struct CsiBus pBus,
uint8_t  NodeId,
uint16_t  ObjDicIdx,
uint8_t  ObjDicSub,
uint32_t *  pRxDWord 
)

This function reads up to 4 bytes of data from device object dictionary using the new serial protocol version V2.

Use this function if you work with devices like Nemesys M and S that have a controller with this new protocol

Parameters
[in]pBusBus object the device is attached to
[in]NodeIdNodeId (1 - 30) of device to read from
[in]ObjDicIdxIndex into device object dictionary
[in]ObjDicSubSub entry of object dictionary entry
[in]pRxDWordPoints to DWord buffer for storage of received data
Returns
Error code - ERR_NOERR indicates success

Referenced by CsiDevReadObject().

901 {
902  return CsiBus_TransfDataV2(pBus, NodeId, ObjDicIdx, ObjDicSub, pRxDWord, 0);
903 }
uint8_t NodeId
the node identifier for this device
Definition: csi_types.h:91
long CsiBusReadLargeData ( struct CsiBus pBus,
uint8_t  NodeId,
uint16_t  ObjDicIdx,
uint8_t  ObjDicSub,
uint8_t *  pDataBuffer,
uint16_t  BufferSize 
)

Use this function if you need to read more than 4 bytes of data.

If data size is <=4, this function falls back to CsiBusReadData()

Parameters
[in]pBusBus object the device is attached to
[in]NodeIdNodeId (1 - 30) of device to read from
[in]ObjDicIdxIndex into device object dictionary
[in]ObjDicSubSub entry of object dictionary entry
[in]pDataBufferPoints to buffer that stores data
[in]BufferSizeSize of the buffer given in pDataBuffer
Return values
>=0 Number of received bytes in pDataBuffer
<0Error code

Referenced by CsiDevReadLargeObject().

454 {
455  long Result; // function return value
456  uint8_t DataAndCrcWordSize;
457  uint8_t RxWordsMinus1;
458  uint16_t CRC = 0;
459  TCsiFrameBuf *pTxBuf = &pBus->BufTx; // receive frame buffer
460  TCsiFrameBuf *pRxBuf = &pBus->BufRx; // transmit frame buffer
461 
462  // if we have small data, then we can do an expedited transfer
463  if (BufferSize <= 4)
464  {
465  uint32_t DataWord;
466  Result = CsiBus_TransfData(pBus, NodeId, ObjDicIdx, ObjDicSub, &DataWord,
467  READ_ACCESS);
468  if (Result != ERR_NOERR)
469  {
470  return Result;
471  }
472  memcpy(pDataBuffer, &DataWord, BufferSize);
473  return BufferSize;
474  }
475 
476  //
477  // Initialize segmented read
478  //
479  DataAndCrcWordSize = WORDSIZE_INDEX_SUB_2 + WORDSIZE_CRC_1;
480  RxWordsMinus1 = WORDSIZE_ERR_CODE_2 - 1;
481  Csi_PrepareFrameHeader(pBus, NodeId, ObjDicIdx, ObjDicSub,
482  CSI_CMD_SEG_READ_INIT, DataAndCrcWordSize, &CRC);
483  Csi_StoreCrcIntoFrame(pBus, DataAndCrcWordSize, &CRC);
484  // Execute the frame transfer
485  Result = CsiBus_ExecuteSingleTransfer(pBus, DataAndCrcWordSize, RxWordsMinus1);
486  CSI_RETURN_ON_ERROR(Result);
487 
488  uint16_t TxControlByte = 0;
489  uint8_t RxControlByte;
490  uint16_t StoredBytes = 0;
491  do
492  {
493  CRC = 0;
494  DataAndCrcWordSize = WORDSIZE_SEG_CONTROL_BYTE_1 + WORDSIZE_CRC_1;
495  RxWordsMinus1 = WORDSIZE_ERR_CODE_2 - 1;
496 
497  // Build frame
498  Csi_StoreWordIntoFrame(&pTxBuf->Words[0], (CSI_CMD_SEG_READ << 8) | (DataAndCrcWordSize - 2), &CRC);
499  Csi_StoreWordIntoFrame(&pTxBuf->Words[1], TxControlByte, &CRC);
500  Csi_StoreCrcIntoFrame(pBus, DataAndCrcWordSize, &CRC);
501 
502  // Execute the frame transfer
503  Result = CsiBus_ExecuteSingleTransfer(pBus, DataAndCrcWordSize, RxWordsMinus1);
504  CSI_RETURN_ON_ERROR(Result);
505  TxControlByte ^= TOGGLE_BIT;
506  RxControlByte = pRxBuf->Bytes[6];
507  uint8_t DataBytes = RxControlByte & 0x3F;
508  if ((StoredBytes + DataBytes) > BufferSize)
509  {
510  return -ERR_NOBUFS;
511  }
512  memcpy(&pDataBuffer[StoredBytes], &pRxBuf->Bytes[7], DataBytes);
513  StoredBytes += DataBytes;
514  }
515  while (RxControlByte & MORE_SEGMENTS_BIT);
516 
517  return StoredBytes;
518 }
TCsiFrameBuf BufTx
buffer for sending frames to device
Definition: csi_types.h:80
#define CSI_CMD_SEG_READ_INIT
start read of segmented data
Definition: csi_bus.c:30
uint16_t Words[40]
word access
Definition: csi_types.h:69
TCsiFrameBuf BufRx
buffer for reception of frames from device
Definition: csi_types.h:81
uint8_t Bytes[80]
byte access
Definition: csi_types.h:68
#define ERR_NOBUFS
No buffer space available.
Definition: err_codes.h:153
#define ERR_NOERR
No error.
Definition: err_codes.h:102
#define CSI_CMD_SEG_READ
read segment
Definition: csi_bus.c:31
A CSI frame buffer for reception / transmission of frames.
Definition: csi_types.h:66
uint8_t NodeId
the node identifier for this device
Definition: csi_types.h:91
long CsiBusWriteData ( struct CsiBus pBus,
uint8_t  NodeId,
uint16_t  ObjDicIdx,
uint8_t  ObjDicSub,
uint32_t  TxDWord 
)

This function writes up to 4 bytes of data into device object dictionary.

Parameters
[in]pBusBus object the device is attached to
[in]NodeIdNodeId (1 - 30) of CSI device to write to
[in]ObjDicIdxIndex into device object dictionary
[in]ObjDicSubSub entry of object dictionary entry
[in]TxDWordPoints to DWord that contains data to write
Returns
Error code - ERR_NOERR indicates success

Referenced by CsiDevWriteObject().

620 {
621  return CsiBus_TransfData(pBus, NodeId, ObjDicIdx, ObjDicSub, &TxDWord, 1);
622 }
uint8_t NodeId
the node identifier for this device
Definition: csi_types.h:91
long CsiBusWriteDataV2 ( struct CsiBus pBus,
uint8_t  NodeId,
uint16_t  ObjDicIdx,
uint8_t  ObjDicSub,
uint32_t  TxDWord 
)

This function writes up to 4 bytes of data into device object dictionary using the new serial protocol version V2.

Use this function if you work with devices like Nemesys M and S that have a controller with this new protocol.

Parameters
[in]pBusBus object the device is attached to
[in]NodeIdNodeId (1 - 30) of CSI device to write to
[in]ObjDicIdxIndex into device object dictionary
[in]ObjDicSubSub entry of object dictionary entry
[in]TxDWordPoints to DWord that contains data to write
Returns
Error code - ERR_NOERR indicates success

Referenced by CsiDevWriteObject().

914 {
915  return CsiBus_TransfDataV2(pBus, NodeId, ObjDicIdx, ObjDicSub, &TxDWord, 1);
916 }
uint8_t NodeId
the node identifier for this device
Definition: csi_types.h:91
long CsiBusWriteLargeData ( struct CsiBus pBus,
uint8_t  NodeId,
uint16_t  ObjDicIdx,
uint8_t  ObjDicSub,
uint8_t *  pDataBuffer,
uint32_t  DataSize,
CsiDataTransferCallback  Callback 
)

Use this function if you need to write more than 4 bytes of data.

If data size is <=4, this function falls back to CsiBusWriteData()

Parameters
[in]pBusBus object the device is attached to
[in]NodeIdNodeId (1 - 30) of CSI device to write to
[in]ObjDicIdxIndex into device object dictionary
[in]ObjDicSubSub entry of object dictionary entry
[in]pDataBufferPoints to buffer that stores data
[in]DataSizeSize of the buffer given in pDataBuffer
[in]CallbackCallback function that will be called after each data packet that has been sent (e.g. to show a progress bar)
Returns
Error code - ERR_NOERR indicates success

Referenced by CsiDevWriteLargeObject().

530 {
531  long Result; // function return value
532  uint8_t DataAndCrcWordSize;
533  uint8_t RxWordsMinus1;
534  uint16_t CRC = 0;
535  TCsiFrameBuf *pTxBuf = &pBus->BufTx; // receive frame buffer
536 
537  // if we have small data, then we can do an expedited transfer
538  if (DataSize <= 4)
539  {
540  uint32_t DataWord = 0;
541  memcpy(&DataWord, pDataBuffer, DataSize);
542  Result = CsiBus_TransfData(pBus, NodeId, ObjDicIdx, ObjDicSub, &DataWord,
543  WRITE_ACCESS);
544  if (Result != ERR_NOERR)
545  {
546  return Result;
547  }
548  return DataSize;
549  }
550 
551  //
552  // Initialize segmented write
553  //
554  DataAndCrcWordSize = WORDSIZE_INDEX_SUB_2 + WORDSIZE_OBJECT_LEN_2 + WORDSIZE_CRC_1;
555  RxWordsMinus1 = WORDSIZE_ERR_CODE_2 - 1;
556  Csi_PrepareFrameHeader(pBus, NodeId, ObjDicIdx, ObjDicSub,
557  CSI_CMD_SEG_WRITE_INIT, DataAndCrcWordSize, &CRC);
558  Csi_StoreIntoFrame(&pTxBuf->Words[3], &DataSize, sizeof(DataSize), &CRC);
559  Csi_StoreCrcIntoFrame(pBus, DataAndCrcWordSize, &CRC);
560  // Execute the frame transfer
561  Result = CsiBus_ExecuteSingleTransfer(pBus, DataAndCrcWordSize, RxWordsMinus1);
562  CSI_RETURN_ON_ERROR(Result);
563 
564  uint16_t SentBytes = 0;
565  uint8_t TxControlByte = 0;
566  do
567  {
568  uint32_t BytesToSend = DataSize - SentBytes;
569  uint8_t DataBytes = (BytesToSend) > 63 ? 63 : BytesToSend;
570  TxControlByte = (TxControlByte & ~0x3F) | (DataBytes & 0x3F);
571  pTxBuf->Bytes[2] = TxControlByte;
572  TxControlByte ^= TOGGLE_BIT;
573  memset(&pTxBuf->Bytes[3], 0, 63);// clear buffer
574  memcpy(&pTxBuf->Bytes[3], &pDataBuffer[SentBytes], DataBytes);
575  SentBytes += DataBytes;
576  uint8_t DataWords = (DataBytes + 2) >> 1;// + 2 because of TxControlByte + 1 byte for word calculation
577 
578  CRC = 0;
579  RxWordsMinus1 = WORDSIZE_ERR_CODE_2 + WORDSIZE_SEG_CONTROL_BYTE_1 - 1;
580  DataAndCrcWordSize = DataWords + WORDSIZE_CRC_1;
581  Csi_StoreWordIntoFrame(&pTxBuf->Words[0], (CSI_CMD_SEG_WRITE << 8) | (DataAndCrcWordSize - 2), &CRC);
582  CRC = CsiCrcCalcIncremental(&pTxBuf->Words[1], DataWords, CRC);
583  Csi_StoreCrcIntoFrame(pBus, DataAndCrcWordSize, &CRC);
584 
585  // Execute the frame transfer
586  Result = CsiBus_ExecuteSingleTransfer(pBus, DataAndCrcWordSize, RxWordsMinus1);
587  CSI_RETURN_ON_ERROR(Result);
588  if (Callback)
589  {
590  Callback(SentBytes);
591  }
592  }
593  while (SentBytes < DataSize);
594 
595  return SentBytes;
596 }
TCsiFrameBuf BufTx
buffer for sending frames to device
Definition: csi_types.h:80
uint16_t CsiCrcCalcIncremental(const uint16_t *pWordArray, uint16_t NumberOfWords, uint16_t CRC)
Calculate CRC-field for CSI protocol.
Definition: csi_crc.c:18
uint16_t Words[40]
word access
Definition: csi_types.h:69
#define CSI_CMD_SEG_WRITE
write segment
Definition: csi_bus.c:34
uint8_t Bytes[80]
byte access
Definition: csi_types.h:68
#define ERR_NOERR
No error.
Definition: err_codes.h:102
#define CSI_CMD_SEG_WRITE_INIT
initialize segmented write
Definition: csi_bus.c:33
A CSI frame buffer for reception / transmission of frames.
Definition: csi_types.h:66
uint8_t NodeId
the node identifier for this device
Definition: csi_types.h:91

+ Here is the call graph for this function: