1 /*
2 * Copyright (c) 2022 HPMicro
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8 #ifndef HPM_LIN_DRV_H
9 #define HPM_LIN_DRV_H
10
11 #include <math.h>
12 #include "hpm_common.h"
13 #include "hpm_lin_regs.h"
14 #include "hpm_soc_feature.h"
15
16 /** bit4 and bit5 encode data length in ID */
17 #define LIN_ID_DATA_LEN_SHIFT 4U
18 #define LIN_ID_DATA_LEN_MASK 0x30U
19 #define LIN_ID_DATA_LEN_GET(x) (((uint8_t)(x) & LIN_ID_DATA_LEN_MASK) >> LIN_ID_DATA_LEN_SHIFT)
20
21 /**
22 * @brief LIN driver APIs
23 * @defgroup lin_interface LIN driver APIs
24 * @ingroup io_interfaces
25 * @{
26 */
27
28 /**
29 * @brief data length in ID bit4 and bit5
30 */
31 typedef enum {
32 id_data_length_2bytes,
33 id_data_length_2bytes_2, /**< both 0 and 1 represent 2 bytes */
34 id_data_length_4bytes,
35 id_data_length_8bytes
36 } lin_id_data_length_t;
37
38 /**
39 * @brief bus inactivity tome to go to sleep
40 */
41 typedef enum {
42 bus_inactivity_time_4s,
43 bus_inactivity_time_6s,
44 bus_inactivity_time_8s,
45 bus_inactivity_time_10s
46 } lin_bus_inactivity_time_t;
47
48 /**
49 * @brief wakeup repeat time
50 */
51 typedef enum {
52 wakeup_repeat_time_180ms,
53 wakeup_repeat_time_200ms,
54 wakeup_repeat_time_220ms,
55 wakeup_repeat_time_240ms
56 } lin_wakeup_repeat_time_t;
57
58 typedef struct {
59 uint32_t src_freq_in_hz; /**< Source clock frequency in Hz */
60 uint32_t baudrate; /**< Baudrate */
61 } lin_timing_t;
62
63 /**
64 * @brief LIN config
65 */
66 typedef struct {
67 uint8_t id; /**< ID */
68 uint8_t *data_buff; /**< data buff */
69 bool data_length_from_id; /**< data length should be decoded from the identifier or not) */
70 uint8_t data_length; /**< used when data_length_from_id is false */
71 bool enhanced_checksum; /**< true for enhanced checksum; false for classic checksum */
72 bool transmit; /**< true for transmit operation; false for receive operation */
73 /* bool start; */ /**< true for start operation; false for only configuration */
74 } lin_trans_config_t;
75
76 #ifdef __cplusplus
77 extern "C" {
78 #endif
79
80 /**
81 * @brief lin get STATE register value
82 *
83 * @param [in] ptr lin base address
84 * @return uint8_t STATE register value
85 */
lin_get_status(LIN_Type * ptr)86 static inline uint8_t lin_get_status(LIN_Type *ptr)
87 {
88 return ptr->STATE;
89 }
90
91 /**
92 * @brief lin reset interrupt
93 *
94 * @param ptr lin base address
95 */
lin_reset_interrupt(LIN_Type * ptr)96 static inline void lin_reset_interrupt(LIN_Type *ptr)
97 {
98 ptr->CONTROL |= LIN_CONTROL_RESET_INT_MASK;
99 }
100
101 /**
102 * @brief lin reset error
103 *
104 * @param ptr lin base address
105 */
lin_reset_error(LIN_Type * ptr)106 static inline void lin_reset_error(LIN_Type *ptr)
107 {
108 ptr->CONTROL |= LIN_CONTROL_RESET_ERROR_MASK;
109 }
110
111 /**
112 * @brief lin wakeup
113 *
114 * @param ptr lin base address
115 */
lin_wakeup(LIN_Type * ptr)116 static inline void lin_wakeup(LIN_Type *ptr)
117 {
118 ptr->CONTROL |= LIN_CONTROL_WAKEUP_REQ_MASK;
119 }
120
121 /**
122 * @brief lin sleep
123 *
124 * @param ptr lin base address
125 */
lin_sleep(LIN_Type * ptr)126 static inline void lin_sleep(LIN_Type *ptr)
127 {
128 ptr->CONTROL |= LIN_CONTROL_SLEEP_MASK;
129 }
130
131 /**
132 * @brief lin slave stop
133 *
134 * @param ptr lin base address
135 */
lin_slave_stop(LIN_Type * ptr)136 static inline void lin_slave_stop(LIN_Type *ptr)
137 {
138 ptr->CONTROL |= LIN_CONTROL_STOP_MASK;
139 }
140
141 /**
142 * @brief lin slave ack
143 *
144 * @param ptr lin base address
145 */
lin_slave_ack(LIN_Type * ptr)146 static inline void lin_slave_ack(LIN_Type *ptr)
147 {
148 ptr->CONTROL |= LIN_CONTROL_DATA_ACK_MASK;
149 }
150
151 /**
152 * @brief lin slave set bus inactivity time
153 *
154 * @param ptr lin base address
155 * @param time lin_bus_inactivity_time_t
156 */
lin_slave_set_bus_inactivity_time(LIN_Type * ptr,lin_bus_inactivity_time_t time)157 static inline void lin_slave_set_bus_inactivity_time(LIN_Type *ptr, lin_bus_inactivity_time_t time)
158 {
159 ptr->TV |= LIN_TV_BUS_INACTIVITY_TIME_SET(time);
160 }
161
162 /**
163 * @brief lin slave set wakeup repeat time
164 *
165 * @param ptr lin base address
166 * @param time lin_wakeup_repeat_time_t
167 */
lin_slave_set_wakeup_repeat_time(LIN_Type * ptr,lin_wakeup_repeat_time_t time)168 static inline void lin_slave_set_wakeup_repeat_time(LIN_Type *ptr, lin_wakeup_repeat_time_t time)
169 {
170 ptr->TV |= LIN_TV_WUP_REPEAT_TIME_SET(time);
171 }
172
173 /**
174 * @brief lin set mode
175 *
176 * @param ptr lin base address
177 * @param master true for master mode, false for slave mode
178 */
lin_set_mode(LIN_Type * ptr,bool master)179 static inline void lin_set_mode(LIN_Type *ptr, bool master)
180 {
181 if (master) {
182 ptr->TV |= LIN_TV_MASTER_MODE_MASK;
183 } else {
184 ptr->TV &= ~LIN_TV_MASTER_MODE_MASK;
185 }
186 }
187
188 /**
189 * @brief lin get data value in byte
190 *
191 * @param ptr lin base address
192 * @param index byte index
193 * @return uint8_t byte value
194 */
lin_get_data_byte(LIN_Type * ptr,uint8_t index)195 static inline uint8_t lin_get_data_byte(LIN_Type *ptr, uint8_t index)
196 {
197 return ptr->DATABYTE[index];
198 }
199
200 /**
201 * @brief lin write data value in byte
202 *
203 * @param ptr lin base address
204 * @param index byte index
205 * @param data byte value
206 */
lin_write_data_byte(LIN_Type * ptr,uint8_t index,uint8_t data)207 static inline void lin_write_data_byte(LIN_Type *ptr, uint8_t index, uint8_t data)
208 {
209 ptr->DATABYTE[index] = data;
210 }
211
212 /**
213 * @brief lin active status
214 *
215 * @param ptr lin base address
216 * @return bool true for active, false for inactive
217 */
lin_is_active(LIN_Type * ptr)218 static inline bool lin_is_active(LIN_Type *ptr)
219 {
220 return ((ptr->STATE & LIN_STATE_LIN_ACTIVE_MASK) == LIN_STATE_LIN_ACTIVE_MASK) ? true : false;
221 }
222
223 /**
224 * @brief lin complete status
225 *
226 * @param ptr lin base address
227 * @return bool true for complete, false for incomplete
228 */
lin_is_complete(LIN_Type * ptr)229 static inline bool lin_is_complete(LIN_Type *ptr)
230 {
231 return ((ptr->STATE & LIN_STATE_COMPLETE_MASK) == LIN_STATE_COMPLETE_MASK) ? true : false;
232 }
233
234 /**
235 * @brief lin get ID
236 *
237 * @param ptr lin base address
238 * @return uint8_t ID value
239 */
lin_get_id(LIN_Type * ptr)240 static inline uint8_t lin_get_id(LIN_Type *ptr)
241 {
242 return ptr->ID;
243 }
244
245 /**
246 * @brief lin configure timing on master mode
247 *
248 * @param ptr lin base address
249 * @param timing lin_timing_t
250 * @return hpm_stat_t
251 */
252 hpm_stat_t lin_master_configure_timing(LIN_Type *ptr, lin_timing_t *timing);
253
254 /**
255 * @brief lin config timing on slave mode
256 *
257 * @param ptr lin base address
258 * @param src_freq_in_hz source frequency
259 * @return hpm_stat_t
260 */
261 hpm_stat_t lin_slave_configure_timing(LIN_Type *ptr, uint32_t src_freq_in_hz);
262
263 /**
264 * @brief lin transfer on master mode
265 *
266 * @param ptr lin base address
267 * @param config lin_trans_config_t
268 */
269 void lin_master_transfer(LIN_Type *ptr, lin_trans_config_t *config);
270
271 /**
272 * @brief lin transfer on slave mode
273 *
274 * @note call this function after lin generate data request interrupt
275 *
276 * @param ptr lin base address
277 * @param config lin_trans_config_t
278 */
279 void lin_slave_transfer(LIN_Type *ptr, lin_trans_config_t *config);
280
281 /**
282 * @brief get data length
283 *
284 * @note data length is determined by DATA_LEN register and ID
285 *
286 * @param ptr lin base address
287 * @return uint8_t data length
288 */
289 uint8_t lin_get_data_length(LIN_Type *ptr);
290
291 /**
292 * @brief lin send data on master mode
293 *
294 * @param ptr lin base address
295 * @param config lin_trans_config_t
296 * @return status_timeout
297 * @return status_success
298 */
299 hpm_stat_t lin_master_sent(LIN_Type *ptr, lin_trans_config_t *config);
300
301 /**
302 * @brief lin receive data on master mode
303 *
304 * @param ptr lin base address
305 * @param config lin_trans_config_t
306 * @return status_timeout
307 * @return status_success
308 */
309 hpm_stat_t lin_master_receive(LIN_Type *ptr, lin_trans_config_t *config);
310
311 /**
312 * @brief lin send data on slave mode
313 *
314 * @param ptr lin base address
315 * @param config lin_trans_config_t
316 * @return status_timeout
317 * @return status_success
318 */
319 hpm_stat_t lin_slave_sent(LIN_Type *ptr, lin_trans_config_t *config);
320
321 /**
322 * @brief lin receive data on slave mode
323 *
324 * @param ptr lin base address
325 * @param config lin_trans_config_t
326 * @return status_timeout
327 * @return status_success
328 */
329 hpm_stat_t lin_slave_receive(LIN_Type *ptr, lin_trans_config_t *config);
330
331 /**
332 * @}
333 */
334
335 #ifdef __cplusplus
336 }
337 #endif
338
339 #endif /* HPM_LIN_DRV_H */
340
341