1 /*
2 * Copyright (c) 2022 HPMicro
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8 #ifndef HPM_LINV2_DRV_H
9 #define HPM_LINV2_DRV_H
10
11 #include <math.h>
12 #include "hpm_common.h"
13 #include "hpm_linv2_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 LINV2 driver APIs
23 * @defgroup linv2_interface LINV2 driver APIs
24 * @ingroup linv2_interface
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, dma mode not use this config */
70 uint8_t data_length; /**< used when data_length_from_id is false or dma mode */
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 control and status register value
82 *
83 * @param [in] ptr lin base address
84 * @return uint32_t control and status register value
85 */
lin_get_control_and_status(LINV2_Type * ptr)86 static inline uint32_t lin_get_control_and_status(LINV2_Type *ptr)
87 {
88 return ptr->CONTROL_STATUS;
89 }
90
91 /**
92 * @brief lin reset interrupt
93 *
94 * @param ptr lin base address
95 */
lin_reset_interrupt(LINV2_Type * ptr)96 static inline void lin_reset_interrupt(LINV2_Type *ptr)
97 {
98 ptr->CONTROL_STATUS = ((ptr->CONTROL_STATUS) & ~LINV2_CONTROL_STATUS_SLEEP_MASK) | LINV2_CONTROL_STATUS_RESET_INT_MASK;
99 }
100
101 /**
102 * @brief lin reset error
103 *
104 * @param ptr lin base address
105 */
lin_reset_error(LINV2_Type * ptr)106 static inline void lin_reset_error(LINV2_Type *ptr)
107 {
108 ptr->CONTROL_STATUS = ((ptr->CONTROL_STATUS) & ~LINV2_CONTROL_STATUS_SLEEP_MASK) | LINV2_CONTROL_STATUS_RESET_ERROR_MASK;
109 }
110
111 /**
112 * @brief lin wakeup
113 *
114 * @param ptr lin base address
115 */
lin_wakeup(LINV2_Type * ptr)116 static inline void lin_wakeup(LINV2_Type *ptr)
117 {
118 ptr->CONTROL_STATUS = ((ptr->CONTROL_STATUS) & ~LINV2_CONTROL_STATUS_SLEEP_MASK) | LINV2_CONTROL_STATUS_WAKEUP_REQ_MASK;
119 }
120
121 /**
122 * @brief lin sleep
123 *
124 * @param ptr lin base address
125 */
lin_sleep(LINV2_Type * ptr)126 static inline void lin_sleep(LINV2_Type *ptr)
127 {
128 ptr->CONTROL_STATUS |= LINV2_CONTROL_STATUS_SLEEP_MASK;
129 }
130
131 /**
132 * @brief lin slave stop
133 *
134 * @param ptr lin base address
135 */
lin_slave_stop(LINV2_Type * ptr)136 static inline void lin_slave_stop(LINV2_Type *ptr)
137 {
138 ptr->CONTROL_STATUS = ((ptr->CONTROL_STATUS) & ~LINV2_CONTROL_STATUS_SLEEP_MASK) | LINV2_CONTROL_STATUS_STOP_MASK;
139 }
140
141 /**
142 * @brief lin slave ack
143 *
144 * @param ptr lin base address
145 */
lin_slave_ack(LINV2_Type * ptr)146 static inline void lin_slave_ack(LINV2_Type *ptr)
147 {
148 ptr->CONTROL_STATUS = ((ptr->CONTROL_STATUS) & ~LINV2_CONTROL_STATUS_SLEEP_MASK) | LINV2_CONTROL_STATUS_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(LINV2_Type * ptr,lin_bus_inactivity_time_t time)157 static inline void lin_slave_set_bus_inactivity_time(LINV2_Type *ptr, lin_bus_inactivity_time_t time)
158 {
159 ptr->TIMING_CONTROL = (ptr->TIMING_CONTROL & (~LINV2_TIMING_CONTROL_BUS_INACTIVE_TIME_MASK))
160 | LINV2_TIMING_CONTROL_BUS_INACTIVE_TIME_SET(time);
161 }
162
163 /**
164 * @brief lin slave set wakeup repeat time
165 *
166 * @param ptr lin base address
167 * @param time lin_wakeup_repeat_time_t
168 */
lin_slave_set_wakeup_repeat_time(LINV2_Type * ptr,lin_wakeup_repeat_time_t time)169 static inline void lin_slave_set_wakeup_repeat_time(LINV2_Type *ptr, lin_wakeup_repeat_time_t time)
170 {
171 ptr->TIMING_CONTROL = (ptr->TIMING_CONTROL & (~LINV2_TIMING_CONTROL_WUP_REPEAT_TIME_MASK))
172 | LINV2_TIMING_CONTROL_WUP_REPEAT_TIME_SET(time);
173 }
174
175 /**
176 * @brief lin set mode
177 *
178 * @param ptr lin base address
179 * @param master true for master mode, false for slave mode
180 */
lin_set_mode(LINV2_Type * ptr,bool master)181 static inline void lin_set_mode(LINV2_Type *ptr, bool master)
182 {
183 if (master) {
184 ptr->TIMING_CONTROL |= LINV2_TIMING_CONTROL_MASTER_MODE_MASK;
185 } else {
186 ptr->TIMING_CONTROL &= ~LINV2_TIMING_CONTROL_MASTER_MODE_MASK;
187 }
188 }
189
190 /**
191 * @brief lin set checksum mode
192 *
193 * @param ptr lin base address
194 * @param enhance_check true for enhance checksum mode, false for normal checksum mode
195 */
lin_set_checksum_mode(LINV2_Type * ptr,bool enhance_checksum)196 static inline void lin_set_checksum_mode(LINV2_Type *ptr, bool enhance_checksum)
197 {
198 if (enhance_checksum) {
199 ptr->DATA_LEN_ID |= LINV2_DATA_LEN_ID_ENH_CHECK_MASK;
200 } else {
201 ptr->DATA_LEN_ID &= ~LINV2_DATA_LEN_ID_ENH_CHECK_MASK;
202 }
203 }
204
205 /**
206 * @brief lin get data value in byte
207 *
208 * @param ptr lin base address
209 * @param index byte index
210 * @return uint8_t byte value
211 */
lin_get_data_byte(LINV2_Type * ptr,uint8_t index)212 static inline uint8_t lin_get_data_byte(LINV2_Type *ptr, uint8_t index)
213 {
214 return ptr->DATA_BYTE[index];
215 }
216
217 /**
218 * @brief lin write data value in byte
219 *
220 * @param ptr lin base address
221 * @param index byte index
222 * @param data byte value
223 */
lin_write_data_byte(LINV2_Type * ptr,uint8_t index,uint8_t data)224 static inline void lin_write_data_byte(LINV2_Type *ptr, uint8_t index, uint8_t data)
225 {
226 ptr->DATA_BYTE[index] = data;
227 }
228
229 /**
230 * @brief lin get ID
231 *
232 * @param ptr lin base address
233 * @return uint8_t ID value
234 */
lin_get_id(LINV2_Type * ptr)235 static inline uint8_t lin_get_id(LINV2_Type *ptr)
236 {
237 return (uint8_t)LINV2_DATA_LEN_ID_ID_GET(ptr->DATA_LEN_ID);
238 }
239
240 /**
241 * @brief lin get checksum value
242 *
243 * @param ptr lin base address
244 * @return uint8_t checksum value
245 */
lin_get_checksum(LINV2_Type * ptr)246 static inline uint8_t lin_get_checksum(LINV2_Type *ptr)
247 {
248 return (uint8_t)LINV2_DATA_LEN_ID_CHECKSUM_GET(ptr->DATA_LEN_ID);
249 }
250
251 /**
252 * @brief lin active status
253 *
254 * @param ptr lin base address
255 * @return bool true for active, false for inactive
256 */
lin_is_active(LINV2_Type * ptr)257 static inline uint8_t lin_is_active(LINV2_Type *ptr)
258 {
259 return ((ptr->CONTROL_STATUS & LINV2_CONTROL_STATUS_LIN_ACTIVE_MASK) == LINV2_CONTROL_STATUS_LIN_ACTIVE_MASK) ? true : false;
260 }
261
262 /**
263 * @brief lin complete status
264 *
265 * @param ptr lin base address
266 * @return bool true for complete, false for incomplete
267 */
lin_is_complete(LINV2_Type * ptr)268 static inline uint8_t lin_is_complete(LINV2_Type *ptr)
269 {
270 return ((ptr->CONTROL_STATUS & LINV2_CONTROL_STATUS_COMPLETE_MASK) == LINV2_CONTROL_STATUS_COMPLETE_MASK) ? true : false;
271 }
272
273 /**
274 * @brief lin configure timing on master mode
275 *
276 * @param ptr lin base address
277 * @param timing lin_timing_t
278 * @return hpm_stat_t
279 */
280 hpm_stat_t lin_master_configure_timing(LINV2_Type *ptr, lin_timing_t *timing);
281
282 /**
283 * @brief lin config timing on slave mode
284 *
285 * @param ptr lin base address
286 * @param src_freq_in_hz source frequency
287 * @return hpm_stat_t
288 */
289 hpm_stat_t lin_slave_configure_timing(LINV2_Type *ptr, uint32_t src_freq_in_hz);
290
291 /**
292 * @brief lin transfer on master mode
293 *
294 * @param ptr lin base address
295 * @param config lin_trans_config_t
296 */
297 void lin_master_transfer(LINV2_Type *ptr, lin_trans_config_t *config);
298
299 /**
300 * @brief lin transfer on slave mode
301 *
302 * @note call this function after lin generate data request interrupt
303 *
304 * @param ptr lin base address
305 * @param config lin_trans_config_t
306 */
307 void lin_slave_transfer(LINV2_Type *ptr, lin_trans_config_t *config);
308
309 /**
310 * @brief get data length
311 *
312 * @note data length is determined by DATA_LEN register and ID
313 *
314 * @param ptr lin base address
315 * @return uint8_t data length
316 */
317 uint8_t lin_get_data_length(LINV2_Type *ptr);
318
319 /**
320 * @brief lin send data on master mode
321 *
322 * @param ptr lin base address
323 * @param config lin_trans_config_t
324 * @return status_timeout
325 * @return status_success
326 */
327 hpm_stat_t lin_master_sent(LINV2_Type *ptr, lin_trans_config_t *config);
328
329 /**
330 * @brief lin receive data on master mode
331 *
332 * @param ptr lin base address
333 * @param config lin_trans_config_t
334 * @return status_timeout
335 * @return status_success
336 */
337 hpm_stat_t lin_master_receive(LINV2_Type *ptr, lin_trans_config_t *config);
338
339 /**
340 * @brief lin send data on slave mode
341 *
342 * @param ptr lin base address
343 * @param config lin_trans_config_t
344 * @return status_timeout
345 * @return status_success
346 */
347 hpm_stat_t lin_slave_sent(LINV2_Type *ptr, lin_trans_config_t *config);
348
349 /**
350 * @brief lin receive data on slave mode
351 *
352 * @param ptr lin base address
353 * @param config lin_trans_config_t
354 * @return status_timeout
355 * @return status_success
356 */
357 hpm_stat_t lin_slave_receive(LINV2_Type *ptr, lin_trans_config_t *config);
358
359 /**
360 * @brief lin slave dma transfer
361 *
362 * @param ptr lin base address
363 * @param config lin_trans_config_t
364 */
365 void lin_slave_dma_transfer(LINV2_Type *ptr, lin_trans_config_t *config);
366
367 /**
368 * @}
369 */
370
371 #ifdef __cplusplus
372 }
373 #endif
374
375 #endif /* HPM_LINV2_DRV_H */
376
377