1 /*------------------------------------------------------------------------------------------------*/
2 /* UNICENS V2.1.0-3491 */
3 /* Copyright (c) 2017 Microchip Technology Germany II GmbH & Co. KG. */
5 /* This program is free software: you can redistribute it and/or modify */
6 /* it under the terms of the GNU General Public License as published by */
7 /* the Free Software Foundation, either version 2 of the License, or */
8 /* (at your option) any later version. */
10 /* This program is distributed in the hope that it will be useful, */
11 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
12 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
13 /* GNU General Public License for more details. */
15 /* You should have received a copy of the GNU General Public License */
16 /* along with this program. If not, see <http://www.gnu.org/licenses/>. */
18 /* You may also obtain this software under a propriety license from Microchip. */
19 /* Please contact Microchip for further information. */
20 /*------------------------------------------------------------------------------------------------*/
24 * \brief Implementation of Port Message Protocol
26 * \cond UCS_INTERNAL_DOC
31 /*------------------------------------------------------------------------------------------------*/
33 /*------------------------------------------------------------------------------------------------*/
37 /*------------------------------------------------------------------------------------------------*/
39 /*------------------------------------------------------------------------------------------------*/
40 #define PMP_IDX_PML_H 0U
41 #define PMP_IDX_PML_L 1U
42 #define PMP_IDX_PMHL 2U
43 #define PMP_IDX_FPH 3U
44 #define PMP_IDX_SID 4U
45 #define PMP_IDX_EXT_TYPE 5U
47 /*------------------------------------------------------------------------------------------------*/
48 /* Masks and shifts for bit fields */
49 /*------------------------------------------------------------------------------------------------*/
50 #define PMP_PMHL_MASK 0x1FU /* 0b00011111 */
51 #define PMP_VERSION_MASK 0xE0U /* 0b11100000 */
52 #define PMP_VERSION 0x40U /* Version: "2" */
53 #define PMP_FPH_TYPE_POS 1U
54 #define PMP_FPH_TYPE_MASK 0x06U /* 0b00000110 */
55 #define PMP_FPH_ID_POS 3U
56 #define PMP_FPH_ID_MASK 0x38U /* 0b00111000 */
57 #define PMP_FPH_DIR_RX 0x01U /* RX: "1" */
58 #define PMP_FPH_DIR_MASK 0x01U /* 0b00000001 */
59 #define PMP_EXT_TYPE_POS 5U
60 #define PMP_EXT_TYPE_MASK 0xE0U /* 0b11100000 */
61 #define PMP_EXT_CODE_MASK 0x1FU /* 0b00011111 */
63 /*------------------------------------------------------------------------------------------------*/
64 /* PMP Verification */
65 /*------------------------------------------------------------------------------------------------*/
66 #define PMP_PML_MAX_SIZE_CTRL 69U
67 #define PMP_PMHL_MIN_SIZE 3U
68 #define PMP_PMHL_MAX_SIZE 5U
70 /*------------------------------------------------------------------------------------------------*/
71 /* Macro like functions */
72 /*------------------------------------------------------------------------------------------------*/
73 /*! \brief Sets the port message length within a given message header
74 * \param header The message header
75 * \param length The port message length
77 void Pmp_SetPml(uint8_t header[], uint8_t length)
79 header[PMP_IDX_PML_H] = 0U;
80 header[PMP_IDX_PML_L] = length;
83 /*! \brief Sets the port message header length within a given message header
84 * \param header The message header
85 * \param length The port message header length. Valid values: 3..5.
86 * Invalid values will set the PMHL to \c 0.
88 void Pmp_SetPmhl(uint8_t header[], uint8_t length)
90 if ((length < PMP_PMHL_MIN_SIZE) || (length > PMP_PMHL_MAX_SIZE))
95 header[PMP_IDX_PMHL] = length | PMP_VERSION;
98 /*! \brief Sets the FIFO protocol header within a given message header
99 * \param header The message header
100 * \param id The FIFO id
101 * \param type The port message type
103 void Pmp_SetFph(uint8_t header[], Pmp_FifoId_t id, Pmp_MsgType_t type)
105 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;
108 /*! \brief Sets the field ExtType within a given message header
109 * \param header The message header
110 * \param type The command or status type
111 * \param code The command or status code
113 void Pmp_SetExtType(uint8_t header[], uint8_t type, uint8_t code)
115 header[PMP_IDX_EXT_TYPE] = (uint8_t)((type << PMP_EXT_TYPE_POS) & PMP_EXT_TYPE_MASK) | (uint8_t)(code & PMP_EXT_CODE_MASK);
118 /*! \brief Sets the sequence id within a given message header
119 * \param header The message header
120 * \param sid The sequence id
122 void Pmp_SetSid(uint8_t header[], uint8_t sid)
124 header[PMP_IDX_SID] = sid;
127 /*! \brief Retrieves the port message length of a given port message buffer
128 * \param header Data buffer containing the port message.
129 * The required size of this buffer is 6 bytes.
130 * \return The port message length in bytes or 0 if the PML is greater than 255.
132 uint8_t Pmp_GetPml(uint8_t header[])
135 if (header[PMP_IDX_PML_H] != 0U)
141 pml = header[PMP_IDX_PML_L];
147 /*! \brief Retrieves the port message header length of a given port message buffer
148 * \param header Data buffer containing the port message.
149 * The required size of this buffer is 6 bytes.
150 * \return The port message header length in bytes
152 uint8_t Pmp_GetPmhl(uint8_t header[])
154 return ((uint8_t)(header[PMP_IDX_PMHL] & (uint8_t)PMP_PMHL_MASK));
157 /*! \brief Retrieves the FIFO number of a given port message buffer
158 * \param header Data buffer containing the port message.
159 * The required size of this buffer is 6 bytes.
160 * \return The FIFO number
162 Pmp_FifoId_t Pmp_GetFifoId(uint8_t header[])
164 return (Pmp_FifoId_t)(((uint8_t)PMP_FPH_ID_MASK & (header)[PMP_IDX_FPH]) >> PMP_FPH_ID_POS);
167 /*! \brief Retrieves the FIFO Type of a given port message buffer
168 * \param header Data buffer containing the port message.
169 * The required size of this buffer is 6 bytes.
170 * \return The FIFO type
172 Pmp_MsgType_t Pmp_GetMsgType(uint8_t header[])
174 return ((Pmp_MsgType_t)((PMP_FPH_TYPE_MASK & (header)[PMP_IDX_FPH]) >> PMP_FPH_TYPE_POS));
177 /*! \brief Retrieves the SequenceID of a given port message buffer
178 * \param header Data buffer containing the port message.
179 * The required size of this buffer is 6 bytes.
180 * \return The SequenceID
182 uint8_t Pmp_GetSid(uint8_t header[])
184 return ((header)[PMP_IDX_SID]);
187 /*! \brief Retrieves payload data of a port message
188 * \param header Data buffer containing the port message.
189 * The required size of this buffer is 6 bytes.
190 * \param index The index of the payload byte starting with '0'
191 * \return The content of a payload data byte
193 uint8_t Pmp_GetData(uint8_t header[], uint8_t index)
195 return header[Pmp_GetPmhl(header) + 3U + index];
198 /*! \brief Retrieves the payload size of the port message
199 * \param header Data buffer containing the port message.
200 * The required size of this buffer is 6 bytes.
201 * \details The function Pmp_VerifyHeader() must be called before
202 * to verify that the port message fields are consistent.
203 * \return The payload size of a port message
205 uint8_t Pmp_GetDataSize(uint8_t header[])
207 return Pmp_GetPml(header) - (Pmp_GetPmhl(header) + 1U);
210 /*! \brief Checks if header length fields are set to valid values
211 * \param header Data buffer containing the port message.
212 * The required size of this buffer is 6 bytes.
213 * \param buf_len Length of the complete port message in bytes
214 * \return Returns \c true if the header was checked successfully,
215 * otherwise \c false.
217 bool Pmp_VerifyHeader(uint8_t header[], uint8_t buf_len)
219 uint8_t pml = Pmp_GetPml(header);
220 uint8_t pmhl = Pmp_GetPmhl(header);
223 ok = ((pmhl >= 3U)&&(pmhl <= 5U)) ? ok : false;
224 ok = ((header[PMP_IDX_PMHL] & PMP_VERSION_MASK) == PMP_VERSION) ? ok : false;
225 ok = (pml >= (pmhl + 1U)) ? ok : false;
226 ok = ((pml + 2U) <= buf_len) ? ok : false;
227 ok = (pml <= PMP_PML_MAX_SIZE_CTRL) ? ok : false;
228 ok = ((header[PMP_IDX_FPH] & PMP_FPH_DIR_MASK) == PMP_FPH_DIR_RX) ? ok : false;
233 /*------------------------------------------------------------------------------------------------*/
235 /*------------------------------------------------------------------------------------------------*/
236 /*! \brief Creates a Port Message Header instance
237 * \param self The instance
239 void Pmh_Ctor(CPmh *self)
241 MISC_MEM_SET(self, 0, sizeof(*self));
244 /*! \brief Inserts a port message header of the specified size into a given buffer
245 * \param self Header content to be written to the buffer (source)
246 * \param data Data buffer the header shall be written to (target)
248 void Pmh_BuildHeader(CPmh *self, uint8_t data[])
252 data[PMP_IDX_PML_H] = 0U;
253 data[PMP_IDX_PML_L] = (uint8_t)self->pml;
254 data[PMP_IDX_PMHL] = (uint8_t)PMP_VERSION | self->pmhl;
255 data[PMP_IDX_FPH] = (uint8_t)PMP_DIR_TX | ((uint8_t)((self->fifo_id) << PMP_FPH_ID_POS)) |
256 ((uint8_t)((self->msg_type) << PMP_FPH_TYPE_POS));
258 data[PMP_IDX_SID] = self->sid;
259 data[PMP_IDX_EXT_TYPE]= self->ext_type;
261 for (cnt=3U; cnt < self->pmhl; cnt++)
263 data[3U + cnt] = 0U; /* add stuffing bytes */
267 /*! \brief Decodes a given data buffer into a provided port message header structure
268 * \param self Header content structure (target)
269 * \param data Data buffer containing the port message with a minimum size
270 * of 6 bytes (source)
272 void Pmh_DecodeHeader(CPmh *self, uint8_t data[])
274 self->pml = Pmp_GetPml(data);
275 self->pmhl = data[PMP_IDX_PMHL] & PMP_PMHL_MASK; /* ignore version */
277 self->fifo_id = Pmp_GetFifoId(data);
278 self->msg_type = Pmp_GetMsgType(data);
279 self->sid = data[PMP_IDX_SID];
280 self->ext_type = data[PMP_IDX_EXT_TYPE];
283 /*! \brief Setter function for FIFO protocol header which contains several subfields
284 * \details The "retransmitted" flag is currently not supported (always Tx)
285 * \param self Reference to the PM content structure that shall be modified
286 * \param fifo_id Id of the PM FIFO
287 * \param msg_type PM type
289 void Pmh_SetFph(CPmh *self, Pmp_FifoId_t fifo_id, Pmp_MsgType_t msg_type)
291 self->msg_type = msg_type;
292 self->fifo_id = fifo_id;
295 /*! \brief Retrieves the ExtType StatusType
296 * \param self The instance
297 * \return Returns The Status Type
299 Pmp_StatusType_t Pmh_GetExtStatusType(CPmh *self)
301 return ((Pmp_StatusType_t)((uint8_t)(PMP_EXT_TYPE_MASK & self->ext_type) >> PMP_EXT_TYPE_POS));
304 /*! \brief Retrieves the ExtType StatusCode
305 * \param self The instance
306 * \return Returns The Status Code
308 Pmp_CommandCode_t Pmh_GetExtCommandCode(CPmh *self)
310 return ((Pmp_CommandCode_t)(uint8_t)(PMP_EXT_CODE_MASK & self->ext_type));
313 /*! \brief Retrieves the ExtType StatusType
314 * \param self The instance
315 * \return Returns The Status Type
317 Pmp_CommandType_t Pmh_GetExtCommandType(CPmh *self)
319 return ((Pmp_CommandType_t)((uint8_t)(PMP_EXT_TYPE_MASK & self->ext_type) >> PMP_EXT_TYPE_POS));
322 /*! \brief Retrieves the ExtType StatusCode
323 * \param self The instance
324 * \return Returns The Status Code
326 Pmp_StatusCode_t Pmh_GetExtStatusCode(CPmh *self)
328 return ((Pmp_StatusCode_t)(uint8_t)(PMP_EXT_CODE_MASK & self->ext_type));
331 /*! \brief Sets the ExtType field by passing the values for type and code
332 * \details The function is applicable for status and command
333 * \param self The Instance
334 * \param type The status or command type
335 * \param code The status or command code
337 void Pmh_SetExtType(CPmh *self, uint8_t type, uint8_t code)
339 self->ext_type = (uint8_t)((type << PMP_EXT_TYPE_POS) & PMP_EXT_TYPE_MASK) | (uint8_t)(code & PMP_EXT_CODE_MASK);
347 /*------------------------------------------------------------------------------------------------*/
349 /*------------------------------------------------------------------------------------------------*/