SCOM Serial Communication Protocol  0.5.2
scom_service.c
Go to the documentation of this file.
1 
10 #define HAL_LOG_CHANNEL SCOM
11 #define HAL_LOG_SUBCHANNEL SERVICE
12 
13 #include "hal.h"
14 #include "scom_service.h"
15 #include "scom_service_filter.h"
16 #include "scom_frame.h"
17 #include <string.h>
18 
19 // -----------------------------------------------------------------------------
20 // SCOM_SendServiceFrame
21 // -----------------------------------------------------------------------------
22 SCOMResult SCOM_SendServiceFrame(SCOMDataLink scom, uint8_t framePriority, uint8_t serviceID, uint8_t primitiveID, const void* frameData, uint8_t frameDataSize) {
23  HAL_ASSERT_AND_EXECUTE(NULL != scom) {
24  HAL_ASSERT_AND_EXECUTE(NULL != scom->frameBuffer) {
25  // Find empty frame
27  if(NULL != frameQueueItem) {
28  SCOMFrame* const frame = &frameQueueItem->frame;
29  *frame = (SCOMFrame ) {
31  .type = serviceID,
32  .null = 0,
33  .size = frameDataSize + 1,
34  .payload = { .serviceframe.primitive_id = primitiveID }
35  };
36  SCOMFrame_SetPriority(frame, framePriority);
37  if(frameDataSize > 0) { // fixme check if the size doesn't exceed the buffer size
38  memcpy(frame->payload.serviceframe.data, frameData, frameDataSize);
39  }
40  frameQueueItem->state = SCOM_FRAME_TX_READY_FOR_SEND;
41  if(true == SCOMFrameQueue_Insert(&scom->frameBuffer->txFrameQueue, frameQueueItem)) {
42  return SCOM_RESULT_OK;
43  }
44  } else {
45  // Report overload error
46  //SCOM_REPORT_ERROR(SCOM_ERR__TX_OVERLOAD);
48  }
49  }
50  }
51  return SCOM_ERROR;
52 
53 } /* SCOM_SendServiceFrame */
54 
55 
56 // -----------------------------------------------------------------------------
57 // SCOM_SendServiceMultiFrame
58 // -----------------------------------------------------------------------------
59 SCOMResult SCOM_SendServiceMultiFrame(SCOMDataLink scom, uint8_t framePriority, uint8_t serviceID, uint8_t primitiveID,
60  const void* frameData, uint32_t frameDataSize, SCOMMultiFrameDesc* multiFrameDesc)
61 {
62  SCOMResult result = SCOM_ERROR;
63  SCOMFrameQueueItem *frameQueueItem;
64  SCOMFrame *frame;
65  size_t frameCount;
66 
67  HAL_ASSERT_AND_EXECUTE(NULL != scom) {
68  HAL_ASSERT_AND_EXECUTE(NULL != scom->frameBuffer) {
69  HAL_ASSERT_AND_EXECUTE(NULL != multiFrameDesc) {
70  // search for free slot in TX buffer
71  frameQueueItem = SCOMFrameQueue_Lock(&scom->frameBuffer->txFrameQueue);
72 
73  if (frameQueueItem) {
74  frame = &frameQueueItem->frame;
75 
76  frame->sof = SCOM_SOF_CHARACTER;
77  frame->type = serviceID;
78  frame->null = 0;
79  //clear old settings and set multiframe id bit
81  SCOMFrame_SetPriority(frame, framePriority);
82  // calculate how many frame will be within the multi-frame
83  frameCount = frameDataSize / SCOMFrame_GetMaxServiceMultiframePayloadSize();
84  if (frameDataSize % SCOMFrame_GetMaxServiceMultiframePayloadSize()) {
85  frameCount++;
86  }
87  frame->payload.servicemultiframe.offset = multiFrameDesc->progress;
88  // each frame adds one extra byte for primitiveID
89  frame->payload.servicemultiframe.total_size = frameDataSize + frameCount;
90  frame->payload.servicemultiframe.primitive_id = primitiveID;
91 
92  if (0 == multiFrameDesc->multi_id) {
93  // this is the first frame of the new multiframe, increase the multi counter
94  scom->multiCounter++;
95  // make sure the counter is not 0 (it is used as an non-zero id)
96  if (0 == scom->multiCounter) {
97  scom->multiCounter = 1;
98  }
99  // assign id to the frame
100  frame->payload.servicemultiframe.multi_id = scom->multiCounter;
101  // save id in a multiFrameDesc descriptor
102  multiFrameDesc->multi_id = scom->multiCounter;
103  } else {
104  // multi id already assigned
105  frame->payload.servicemultiframe.multi_id = multiFrameDesc->multi_id;
106  }
107 
108  if ((frameData) && (frameDataSize)) {
109  // calculate data size for this part
110  uint32_t size = frameDataSize - multiFrameDesc->progress;
111  if (size > SCOMFrame_GetMaxServiceMultiframePayloadSize()) {
112  size = SCOMFrame_GetMaxServiceMultiframePayloadSize();
113  }
114 
115  frame->size = (uint8_t)size+1;
116  memcpy(frame->payload.servicemultiframe.data, ((uint8_t *)frameData) + multiFrameDesc->progress, size);
117 
118  // update progress
119  multiFrameDesc->progress += size;
120  }
121 
122  // mark that the frame is ready to be sent
123  frameQueueItem->state = SCOM_FRAME_TX_READY_FOR_SEND;
124 
125  if(true == SCOMFrameQueue_Insert(&scom->frameBuffer->txFrameQueue, frameQueueItem)) {
126  result= SCOM_RESULT_OK;
127  }
128  } else {
129  // no free frame available at this moment
131  }
132  }
133  }
134  }
135 
136  return result;
137 
138 } /* SCOM_SendServiceMultiFrame */
139 
140 // -----------------------------------------------------------------------------
141 // SCOM_ServiceTransaction
142 // -----------------------------------------------------------------------------
143 SCOMResult SCOM_ServiceTransaction(SCOMDataLink scom, const uint8_t framePriority, const uint8_t serviceID, const uint8_t primitiveID, const void* const txData, const uint8_t txDataSize, void* rxData, const size_t rxDataSize) {
144  SCOMResult result = SCOM_ERROR;
145  HAL_ASSERT_AND_EXECUTE(NULL != scom) {
146  SCOMServiceMatchFilter filter;
147  if(SCOM_RESULT_OK == SCOM_InitializeServiceMatchFilter(&filter, rxData, rxDataSize)) { // Initialize the filter
148  if(SCOM_RESULT_OK == SCOM_SetupServiceMatchFilter(&filter, serviceID, primitiveID)) { // Setup frame-type matching SCOM filter to catch confirmation
149  result = SCOM_InsertFilter(scom, &filter.filter); // Insert filter into SCOM
150  if(SCOM_RESULT_OK == result) {
151  result = SCOM_SendServiceFrame(scom, framePriority, serviceID, primitiveID, txData, txDataSize);
152  if(SCOM_RESULT_OK == result) {
153  result = SCOM_WaitForServiceFilter(&filter, 3000);
154  SCOM_RemoveFilter(scom, &filter.filter); // remove filter
155  }
156  }
157  }
158  SCOM_DeinitializeServiceMatchFilter(&filter); // Deinitialize the filter
159  }
160  }
161  return result;
162 } /* SCOM_ServiceTransaction */
Definition of multiframe descriptor structure.
Definition: scom.h:247
SCOMResult SCOM_DeinitializeServiceMatchFilter(SCOMServiceMatchFilter *serviceMatchFilter)
uint32_t multi_id
Definition: scom.h:248
Service utilities.
uint8_t null
TODO: XOR from sof, ctrl, type, size.
Definition: scom_frame.h:61
SCOMFrameQueue txFrameQueue
descriptor of the frame queue used for sending
Definition: scom.h:65
struct HAL_PACKED::@1::@4 serviceframe
payload definition for service frame
SCOM version record.
Definition: scom.h:81
SCOMResult SCOM_WaitForServiceFilter(SCOMServiceMatchFilter *serviceMatchFilter, OSTime timeout)
SCOMResult SCOM_SetupServiceMatchFilter(SCOMServiceMatchFilter *serviceMatchFilter, uint8_t serviceID, uint8_t primitiveID)
uint32_t progress
multiframe id
Definition: scom.h:249
Service filters.
SCOMResult SCOM_ServiceTransaction(SCOMDataLink scom, const uint8_t framePriority, const uint8_t serviceID, const uint8_t primitiveID, const void *const txData, const uint8_t txDataSize, void *rxData, const size_t rxDataSize)
Definition: scom_service.c:143
bool SCOMFrame_SetPriority(SCOMFrame *const frame, const uint8_t priority)
Definition: scom_frame.c:67
Definition of a single SCOM frame queue item.
SCOMResult SCOM_RemoveFilter(SCOMDataLink scom, SCOMFilter filter)
SCOMResult SCOM_InitializeServiceMatchFilter(SCOMServiceMatchFilter *serviceMatchFilter, void *data, size_t max_data_size)
uint8_t type
frame type field
#define SCOM_FRAME_CTRL_MULTI_ID_MASK
Definition: scom_frame.h:42
#define SCOM_SOF_CHARACTER
Definition: scom_frame.h:38
uint8_t size
frame type field
Definition: scom_frame.h:59
SCOMResult
Definition: scom.h:211
SCOMFilterDesc filter
Native SCOM filter descriptor.
SCOMResult SCOM_InsertFilter(SCOMDataLink scom, SCOMFilter filter)
SCOMResult SCOM_SendServiceFrame(SCOMDataLink scom, uint8_t framePriority, uint8_t serviceID, uint8_t primitiveID, const void *frameData, uint8_t frameDataSize)
Definition: scom_service.c:22
uint8_t ctrl
frame control field
SCOMFrameState state
SCOM frame state.
SCOMFrameQueueItem * SCOMFrameQueue_Lock(SCOMFrameQueue *frameQueue)
union HAL_PACKED::@1 payload
payload field
struct HAL_PACKED SCOMFrame
Definition of an SCOM frame.
uint8_t sof
synchronization field: always 0xFF
Definition: scom_frame.h:56
SCOM frame definition.
SCOMFrame frame
SCOM frame.
struct HAL_PACKED::@1::@5 servicemultiframe
payload definition for a service multi frame
SCOMResult SCOM_SendServiceMultiFrame(SCOMDataLink scom, uint8_t framePriority, uint8_t serviceID, uint8_t primitiveID, const void *frameData, uint32_t frameDataSize, SCOMMultiFrameDesc *multiFrameDesc)
Definition: scom_service.c:59
bool SCOMFrameQueue_Insert(SCOMFrameQueue *frameQueue, SCOMFrameQueueItem *frame)