• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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