1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
|
/*------------------------------------------------------------------------------------------------*/
/* UNICENS V2.1.0-3491 */
/* Copyright (c) 2017 Microchip Technology Germany II GmbH & Co. KG. */
/* */
/* This program is free software: you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation, either version 2 of the License, or */
/* (at your option) any later version. */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* */
/* You may also obtain this software under a propriety license from Microchip. */
/* Please contact Microchip for further information. */
/*------------------------------------------------------------------------------------------------*/
/*!
* \file
* \brief Implementation of Port Message Protocol
*
* \cond UCS_INTERNAL_DOC
* \addtogroup G_PMH
* @{
*/
/*------------------------------------------------------------------------------------------------*/
/* Includes */
/*------------------------------------------------------------------------------------------------*/
#include "ucs_pmp.h"
#include "ucs_misc.h"
/*------------------------------------------------------------------------------------------------*/
/* PMP Indexes */
/*------------------------------------------------------------------------------------------------*/
#define PMP_IDX_PML_H 0U
#define PMP_IDX_PML_L 1U
#define PMP_IDX_PMHL 2U
#define PMP_IDX_FPH 3U
#define PMP_IDX_SID 4U
#define PMP_IDX_EXT_TYPE 5U
/*------------------------------------------------------------------------------------------------*/
/* Masks and shifts for bit fields */
/*------------------------------------------------------------------------------------------------*/
#define PMP_PMHL_MASK 0x1FU /* 0b00011111 */
#define PMP_VERSION_MASK 0xE0U /* 0b11100000 */
#define PMP_VERSION 0x40U /* Version: "2" */
#define PMP_FPH_TYPE_POS 1U
#define PMP_FPH_TYPE_MASK 0x06U /* 0b00000110 */
#define PMP_FPH_ID_POS 3U
#define PMP_FPH_ID_MASK 0x38U /* 0b00111000 */
#define PMP_FPH_DIR_RX 0x01U /* RX: "1" */
#define PMP_FPH_DIR_MASK 0x01U /* 0b00000001 */
#define PMP_EXT_TYPE_POS 5U
#define PMP_EXT_TYPE_MASK 0xE0U /* 0b11100000 */
#define PMP_EXT_CODE_MASK 0x1FU /* 0b00011111 */
/*------------------------------------------------------------------------------------------------*/
/* PMP Verification */
/*------------------------------------------------------------------------------------------------*/
#define PMP_PML_MAX_SIZE_CTRL 69U
#define PMP_PMHL_MIN_SIZE 3U
#define PMP_PMHL_MAX_SIZE 5U
/*------------------------------------------------------------------------------------------------*/
/* Macro like functions */
/*------------------------------------------------------------------------------------------------*/
/*! \brief Sets the port message length within a given message header
* \param header The message header
* \param length The port message length
*/
void Pmp_SetPml(uint8_t header[], uint8_t length)
{
header[PMP_IDX_PML_H] = 0U;
header[PMP_IDX_PML_L] = length;
}
/*! \brief Sets the port message header length within a given message header
* \param header The message header
* \param length The port message header length. Valid values: 3..5.
* Invalid values will set the PMHL to \c 0.
*/
void Pmp_SetPmhl(uint8_t header[], uint8_t length)
{
if ((length < PMP_PMHL_MIN_SIZE) || (length > PMP_PMHL_MAX_SIZE))
{
length = 0U;
}
header[PMP_IDX_PMHL] = length | PMP_VERSION;
}
/*! \brief Sets the FIFO protocol header within a given message header
* \param header The message header
* \param id The FIFO id
* \param type The port message type
*/
void Pmp_SetFph(uint8_t header[], Pmp_FifoId_t id, Pmp_MsgType_t type)
{
header[PMP_IDX_FPH] = (uint8_t)((uint8_t)type << PMP_FPH_TYPE_POS) | (uint8_t)((uint8_t)id << PMP_FPH_ID_POS) | (uint8_t)PMP_DIR_TX;
}
/*! \brief Sets the field ExtType within a given message header
* \param header The message header
* \param type The command or status type
* \param code The command or status code
*/
void Pmp_SetExtType(uint8_t header[], uint8_t type, uint8_t code)
{
header[PMP_IDX_EXT_TYPE] = (uint8_t)((type << PMP_EXT_TYPE_POS) & PMP_EXT_TYPE_MASK) | (uint8_t)(code & PMP_EXT_CODE_MASK);
}
/*! \brief Sets the sequence id within a given message header
* \param header The message header
* \param sid The sequence id
*/
void Pmp_SetSid(uint8_t header[], uint8_t sid)
{
header[PMP_IDX_SID] = sid;
}
/*! \brief Retrieves the port message length of a given port message buffer
* \param header Data buffer containing the port message.
* The required size of this buffer is 6 bytes.
* \return The port message length in bytes or 0 if the PML is greater than 255.
*/
uint8_t Pmp_GetPml(uint8_t header[])
{
uint8_t pml;
if (header[PMP_IDX_PML_H] != 0U)
{
pml = 0U;
}
else
{
pml = header[PMP_IDX_PML_L];
}
return pml;
}
/*! \brief Retrieves the port message header length of a given port message buffer
* \param header Data buffer containing the port message.
* The required size of this buffer is 6 bytes.
* \return The port message header length in bytes
*/
uint8_t Pmp_GetPmhl(uint8_t header[])
{
return ((uint8_t)(header[PMP_IDX_PMHL] & (uint8_t)PMP_PMHL_MASK));
}
/*! \brief Retrieves the FIFO number of a given port message buffer
* \param header Data buffer containing the port message.
* The required size of this buffer is 6 bytes.
* \return The FIFO number
*/
Pmp_FifoId_t Pmp_GetFifoId(uint8_t header[])
{
return (Pmp_FifoId_t)(((uint8_t)PMP_FPH_ID_MASK & (header)[PMP_IDX_FPH]) >> PMP_FPH_ID_POS);
}
/*! \brief Retrieves the FIFO Type of a given port message buffer
* \param header Data buffer containing the port message.
* The required size of this buffer is 6 bytes.
* \return The FIFO type
*/
Pmp_MsgType_t Pmp_GetMsgType(uint8_t header[])
{
return ((Pmp_MsgType_t)((PMP_FPH_TYPE_MASK & (header)[PMP_IDX_FPH]) >> PMP_FPH_TYPE_POS));
}
/*! \brief Retrieves the SequenceID of a given port message buffer
* \param header Data buffer containing the port message.
* The required size of this buffer is 6 bytes.
* \return The SequenceID
*/
uint8_t Pmp_GetSid(uint8_t header[])
{
return ((header)[PMP_IDX_SID]);
}
/*! \brief Retrieves payload data of a port message
* \param header Data buffer containing the port message.
* The required size of this buffer is 6 bytes.
* \param index The index of the payload byte starting with '0'
* \return The content of a payload data byte
*/
uint8_t Pmp_GetData(uint8_t header[], uint8_t index)
{
return header[Pmp_GetPmhl(header) + 3U + index];
}
/*! \brief Retrieves the payload size of the port message
* \param header Data buffer containing the port message.
* The required size of this buffer is 6 bytes.
* \details The function Pmp_VerifyHeader() must be called before
* to verify that the port message fields are consistent.
* \return The payload size of a port message
*/
uint8_t Pmp_GetDataSize(uint8_t header[])
{
return Pmp_GetPml(header) - (Pmp_GetPmhl(header) + 1U);
}
/*! \brief Checks if header length fields are set to valid values
* \param header Data buffer containing the port message.
* The required size of this buffer is 6 bytes.
* \param buf_len Length of the complete port message in bytes
* \return Returns \c true if the header was checked successfully,
* otherwise \c false.
*/
bool Pmp_VerifyHeader(uint8_t header[], uint8_t buf_len)
{
uint8_t pml = Pmp_GetPml(header);
uint8_t pmhl = Pmp_GetPmhl(header);
bool ok = true;
ok = ((pmhl >= 3U)&&(pmhl <= 5U)) ? ok : false;
ok = ((header[PMP_IDX_PMHL] & PMP_VERSION_MASK) == PMP_VERSION) ? ok : false;
ok = (pml >= (pmhl + 1U)) ? ok : false;
ok = ((pml + 2U) <= buf_len) ? ok : false;
ok = (pml <= PMP_PML_MAX_SIZE_CTRL) ? ok : false;
ok = ((header[PMP_IDX_FPH] & PMP_FPH_DIR_MASK) == PMP_FPH_DIR_RX) ? ok : false;
return ok;
}
/*------------------------------------------------------------------------------------------------*/
/* Implementation */
/*------------------------------------------------------------------------------------------------*/
/*! \brief Creates a Port Message Header instance
* \param self The instance
*/
void Pmh_Ctor(CPmh *self)
{
MISC_MEM_SET(self, 0, sizeof(*self));
}
/*! \brief Inserts a port message header of the specified size into a given buffer
* \param self Header content to be written to the buffer (source)
* \param data Data buffer the header shall be written to (target)
*/
void Pmh_BuildHeader(CPmh *self, uint8_t data[])
{
uint8_t cnt;
data[PMP_IDX_PML_H] = 0U;
data[PMP_IDX_PML_L] = (uint8_t)self->pml;
data[PMP_IDX_PMHL] = (uint8_t)PMP_VERSION | self->pmhl;
data[PMP_IDX_FPH] = (uint8_t)PMP_DIR_TX | ((uint8_t)((self->fifo_id) << PMP_FPH_ID_POS)) |
((uint8_t)((self->msg_type) << PMP_FPH_TYPE_POS));
data[PMP_IDX_SID] = self->sid;
data[PMP_IDX_EXT_TYPE]= self->ext_type;
for (cnt=3U; cnt < self->pmhl; cnt++)
{
data[3U + cnt] = 0U; /* add stuffing bytes */
}
}
/*! \brief Decodes a given data buffer into a provided port message header structure
* \param self Header content structure (target)
* \param data Data buffer containing the port message with a minimum size
* of 6 bytes (source)
*/
void Pmh_DecodeHeader(CPmh *self, uint8_t data[])
{
self->pml = Pmp_GetPml(data);
self->pmhl = data[PMP_IDX_PMHL] & PMP_PMHL_MASK; /* ignore version */
self->fifo_id = Pmp_GetFifoId(data);
self->msg_type = Pmp_GetMsgType(data);
self->sid = data[PMP_IDX_SID];
self->ext_type = data[PMP_IDX_EXT_TYPE];
}
/*! \brief Setter function for FIFO protocol header which contains several subfields
* \details The "retransmitted" flag is currently not supported (always Tx)
* \param self Reference to the PM content structure that shall be modified
* \param fifo_id Id of the PM FIFO
* \param msg_type PM type
*/
void Pmh_SetFph(CPmh *self, Pmp_FifoId_t fifo_id, Pmp_MsgType_t msg_type)
{
self->msg_type = msg_type;
self->fifo_id = fifo_id;
}
/*! \brief Retrieves the ExtType StatusType
* \param self The instance
* \return Returns The Status Type
*/
Pmp_StatusType_t Pmh_GetExtStatusType(CPmh *self)
{
return ((Pmp_StatusType_t)((uint8_t)(PMP_EXT_TYPE_MASK & self->ext_type) >> PMP_EXT_TYPE_POS));
}
/*! \brief Retrieves the ExtType StatusCode
* \param self The instance
* \return Returns The Status Code
*/
Pmp_CommandCode_t Pmh_GetExtCommandCode(CPmh *self)
{
return ((Pmp_CommandCode_t)(uint8_t)(PMP_EXT_CODE_MASK & self->ext_type));
}
/*! \brief Retrieves the ExtType StatusType
* \param self The instance
* \return Returns The Status Type
*/
Pmp_CommandType_t Pmh_GetExtCommandType(CPmh *self)
{
return ((Pmp_CommandType_t)((uint8_t)(PMP_EXT_TYPE_MASK & self->ext_type) >> PMP_EXT_TYPE_POS));
}
/*! \brief Retrieves the ExtType StatusCode
* \param self The instance
* \return Returns The Status Code
*/
Pmp_StatusCode_t Pmh_GetExtStatusCode(CPmh *self)
{
return ((Pmp_StatusCode_t)(uint8_t)(PMP_EXT_CODE_MASK & self->ext_type));
}
/*! \brief Sets the ExtType field by passing the values for type and code
* \details The function is applicable for status and command
* \param self The Instance
* \param type The status or command type
* \param code The status or command code
*/
void Pmh_SetExtType(CPmh *self, uint8_t type, uint8_t code)
{
self->ext_type = (uint8_t)((type << PMP_EXT_TYPE_POS) & PMP_EXT_TYPE_MASK) | (uint8_t)(code & PMP_EXT_CODE_MASK);
}
/*!
* @}
* \endcond
*/
/*------------------------------------------------------------------------------------------------*/
/* End of file */
/*------------------------------------------------------------------------------------------------*/
|