• 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_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