1 /******************************************************************************
2 * Copyright (c) 2022 Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
3 * All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 *****************************************************************************/
18 #include "analog.h"
19 #include "compiler.h"
20 #include "plic.h"
21 #include "stimer.h"
22 /**********************************************************************************************************************
23 * local constants *
24 *********************************************************************************************************************/
25
26 /**********************************************************************************************************************
27 * local macro *
28 *********************************************************************************************************************/
29
30 /**********************************************************************************************************************
31 * local data type *
32 *********************************************************************************************************************/
33
34 /**********************************************************************************************************************
35 * global variable *
36 *********************************************************************************************************************/
37
38 dma_config_t analog_tx_dma_config = {
39 .dst_req_sel = DMA_REQ_ALGM_TX, /* < tx req */
40 .src_req_sel = 0,
41 .dst_addr_ctrl = DMA_ADDR_FIX,
42 .src_addr_ctrl = DMA_ADDR_INCREMENT, /* < increment */
43 .dstmode = DMA_HANDSHAKE_MODE, /* < handshake */
44 .srcmode = DMA_NORMAL_MODE,
45 .dstwidth = DMA_CTR_WORD_WIDTH,
46 .srcwidth = DMA_CTR_WORD_WIDTH,
47 .src_burst_size = 0, /* < must 0 */
48 .read_num_en = 0,
49 .priority = 0,
50 .write_num_en = 0,
51 .auto_en = 0, /* < must 0 */
52 };
53 dma_config_t analog_rx_dma_config = {
54 .dst_req_sel = 0, // tx req
55 .src_req_sel = DMA_REQ_ALGM_RX,
56 .dst_addr_ctrl = DMA_ADDR_INCREMENT,
57 .src_addr_ctrl = DMA_ADDR_FIX,
58 .dstmode = DMA_NORMAL_MODE,
59 .srcmode = DMA_HANDSHAKE_MODE,
60 .dstwidth = DMA_CTR_WORD_WIDTH, /* < must word */
61 .srcwidth = DMA_CTR_WORD_WIDTH, /* < must word */
62 .src_burst_size = 0,
63 .read_num_en = 0,
64 .priority = 0,
65 .write_num_en = 0,
66 .auto_en = 0, // must 0
67 };
68 /**********************************************************************************************************************
69 * local variable *
70 *********************************************************************************************************************/
71 /**********************************************************************************************************************
72 * local function prototype *
73 *********************************************************************************************************************/
74
75 /**
76 * @brief This function serves to judge whether analog write/read is busy .
77 * @return none.
78 */
79 static inline void analog_wait(void);
80 /**********************************************************************************************************************
81 * global function implementation *
82 *********************************************************************************************************************/
83
84 /**
85 * @brief This function serves to analog register read by byte.
86 * @param[in] addr - address need to be read.
87 * @return the result of read.
88 */
analog_read_reg8(unsigned char addr)89 unsigned char analog_read_reg8(unsigned char addr)
90 {
91 unsigned int r = core_interrupt_disable();
92 reg_ana_addr = addr;
93 reg_ana_len = 0x1;
94 reg_ana_ctrl = FLD_ANA_CYC;
95 analog_wait();
96 unsigned char data = reg_ana_data(0);
97 core_restore_interrupt(r);
98 return data;
99 }
100
101 /**
102 * @brief This function serves to analog register write by byte.
103 * @param[in] addr - address need to be write.
104 * @param[in] data - the value need to be write.
105 * @return none.
106 */
analog_write_reg8(unsigned char addr,unsigned char data)107 void analog_write_reg8(unsigned char addr, unsigned char data)
108 {
109 unsigned int r = core_interrupt_disable();
110 reg_ana_addr = addr;
111 reg_ana_data(0) = data;
112 reg_ana_ctrl = (FLD_ANA_CYC | FLD_ANA_RW);
113 analog_wait();
114 reg_ana_ctrl = 0x00;
115 core_restore_interrupt(r);
116 }
117
118 /**
119 * @brief This function serves to analog register write by halfword.
120 * @param[in] addr - address need to be write.
121 * @param[in] data - the value need to be write.
122 * @return none.
123 */
analog_write_reg16(unsigned char addr,unsigned short data)124 void analog_write_reg16(unsigned char addr, unsigned short data)
125 {
126 unsigned int r = core_interrupt_disable();
127 reg_ana_addr = addr;
128 reg_ana_addr_data16 = data;
129 reg_ana_ctrl = (FLD_ANA_CYC | FLD_ANA_RW);
130 analog_wait();
131 core_restore_interrupt(r);
132 }
133
134 /**
135 * @brief This function serves to analog register read by halfword.
136 * @param[in] addr - address need to be read.
137 * @return the result of read.
138 */
analog_read_reg16(unsigned char addr)139 unsigned short analog_read_reg16(unsigned char addr)
140 {
141 unsigned int r = core_interrupt_disable();
142 reg_ana_len = 2;
143 reg_ana_addr = addr;
144 reg_ana_ctrl = FLD_ANA_CYC;
145 analog_wait();
146 unsigned short data = reg_ana_addr_data16;
147 core_restore_interrupt(r);
148 return data;
149 }
150
151 /**
152 * @brief This function serves to analog register read by word.
153 * @param[in] addr - address need to be read.
154 * @return the result of read.
155 */
analog_read_reg32(unsigned char addr)156 unsigned int analog_read_reg32(unsigned char addr)
157 {
158 unsigned int r = core_interrupt_disable();
159 reg_ana_len = 4;
160 reg_ana_addr = addr;
161 reg_ana_ctrl = FLD_ANA_CYC;
162 analog_wait();
163 unsigned int data = reg_ana_addr_data32;
164 core_restore_interrupt(r);
165 return data;
166 }
167
168 /**
169 * @brief This function serves to analog register write by word.
170 * @param[in] addr - address need to be write.
171 * @param[in] data - the value need to be write.
172 * @return none.
173 */
analog_write_reg32(unsigned char addr,unsigned int data)174 void analog_write_reg32(unsigned char addr, unsigned int data)
175 {
176 unsigned int r = core_interrupt_disable();
177 reg_ana_addr = addr;
178 reg_ana_addr_data32 = data;
179 reg_ana_ctrl = (FLD_ANA_CYC | FLD_ANA_RW);
180 analog_wait();
181 core_restore_interrupt(r);
182 }
183
184 /**
185 * @brief This function serves to analog register write by word using dma.
186 * @param[in] chn - the dma channel.
187 * @param[in] addr - address need to be write.
188 * @param[in] pdat - the value need to be write.
189 * @return none.
190 */
analog_read_reg32_dma(dma_chn_e chn,unsigned char addr,void * pdat)191 void analog_read_reg32_dma(dma_chn_e chn, unsigned char addr, void *pdat)
192 {
193 unsigned int r = core_interrupt_disable();
194 reg_ana_len = 0x04;
195 reg_ana_addr = addr;
196 reg_ana_ctrl = FLD_ANA_CYC;
197 reg_dma_src_addr(chn) = 0x80140184;
198 reg_dma_dst_addr(chn) = convert_ram_addr_cpu2bus(pdat);
199 dma_set_size(chn, 4, DMA_WORD_WIDTH);
200 analog_rx_dma_config.dstwidth = DMA_CTR_WORD_WIDTH;
201 analog_rx_dma_config.srcwidth = DMA_CTR_WORD_WIDTH;
202 dma_config(chn, &analog_rx_dma_config);
203 dma_chn_en(chn);
204 analog_wait();
205 core_restore_interrupt(r);
206 }
207
208 /**
209 * @brief This function serves to analog register write by word using dma.
210 * @param[in] chn - the dma channel.
211 * @param[in] addr - address need to be write.
212 * @param[in] data - the value need to be write.
213 * @return none.
214 */
analog_write_reg32_dma(dma_chn_e chn,unsigned char addr,void * pdat)215 void analog_write_reg32_dma(dma_chn_e chn, unsigned char addr, void *pdat)
216 {
217 unsigned int r = core_interrupt_disable();
218 reg_ana_addr = addr;
219 reg_dma_src_addr(chn) = convert_ram_addr_cpu2bus(pdat);
220 reg_dma_dst_addr(chn) = 0x80140184;
221 dma_set_size(chn, 4, DMA_WORD_WIDTH);
222 analog_tx_dma_config.dstwidth = DMA_CTR_WORD_WIDTH;
223 analog_tx_dma_config.srcwidth = DMA_CTR_WORD_WIDTH;
224 dma_config(chn, &analog_tx_dma_config);
225 dma_chn_en(chn);
226 reg_ana_ctrl = FLD_ANA_CYC | FLD_ANA_RW;
227 analog_wait();
228 core_restore_interrupt(r);
229 }
230
231 /**
232 * @brief This function write buffer to analog register.
233 * @param[in] addr - address need to be write.
234 * @param[in] *buff - the buffer need to be write.
235 * @param[in] len - the length of buffer.
236 * @return none.
237 */
analog_write_buff(unsigned char addr,unsigned char * buff,int len)238 _attribute_ram_code_sec_noinline_ void analog_write_buff(unsigned char addr, unsigned char *buff, int len)
239 {
240 unsigned char wr_idx = 0;
241 unsigned char len_t = len;
242 unsigned int r = core_interrupt_disable();
243 reg_ana_len = len;
244 reg_ana_addr = addr;
245
246 if (len_t <= 4) {
247 while (len_t--) {
248 reg_ana_data(wr_idx++) = *(buff++);
249 }
250
251 reg_ana_ctrl = FLD_ANA_CYC | FLD_ANA_RW;
252 } else {
253 len_t = 4;
254 while (len_t--) {
255 reg_ana_data(wr_idx++) = *(buff++);
256 }
257
258 reg_ana_ctrl = FLD_ANA_CYC | FLD_ANA_RW;
259 len_t = len - 4;
260 wr_idx = 0;
261 while (len_t--) {
262 reg_ana_data(wr_idx++) = *(buff++);
263 if (wr_idx == 4) {
264 wr_idx = 0;
265 while ((reg_ana_irq_sta & FLD_ANA_TXBUFF_IRQ) == 0) {
266 }
267 // tx_buf_irq
268 }
269 }
270 }
271 analog_wait(); // busy
272 reg_ana_ctrl = 0x00;
273 core_restore_interrupt(r);
274 }
275
276 /**
277 * @brief This function read data from analog register to buffer.
278 * @param[in] addr - address need to be read from.
279 * @param[in] *buff - the buffer need to be put data.
280 * @param[in] len - the length of read data.
281 * @return none.
282 */
analog_read_buff(unsigned char addr,unsigned char * buff,int len)283 _attribute_ram_code_sec_noinline_ void analog_read_buff(unsigned char addr, unsigned char *buff, int len)
284 {
285 unsigned int r = core_interrupt_disable();
286 unsigned char rd_idx = 0;
287 unsigned char len_t = len;
288 reg_ana_len = len;
289 reg_ana_addr = addr;
290 reg_ana_ctrl = FLD_ANA_CYC;
291 if (len_t > 4) {
292 while ((reg_ana_irq_sta & FLD_ANA_RXBUFF_IRQ) == 0) {
293 }
294 // rx_buf_irq
295 while (len_t--) {
296 (*buff++) = reg_ana_data(rd_idx++);
297 if (rd_idx == 4) {
298 rd_idx = 0;
299 if (len_t <= 4) {
300 break;
301 } else {
302 while ((reg_ana_irq_sta & FLD_ANA_RXBUFF_IRQ) == 0) {
303 }
304 }
305 // rx_buf_irq
306 }
307 }
308 }
309 analog_wait();
310 while (len_t--) {
311 (*buff++) = reg_ana_data(rd_idx++);
312 }
313
314 reg_ana_ctrl = 0x00;
315 core_restore_interrupt(r);
316 }
317
318 /**
319 * @brief This function write buffer to analog register by dma channel.
320 * @param[in] chn - the dma channel.
321 * @param[in] addr - address need to be write.
322 * @param[in] *pdat - the buffer need to be write.
323 * @param[in] len - the length of buffer.
324 * @return none.
325 */
analog_write_buff_dma(dma_chn_e chn,unsigned char addr,unsigned char * pdat,unsigned int len)326 void analog_write_buff_dma(dma_chn_e chn, unsigned char addr, unsigned char *pdat, unsigned int len)
327 {
328 unsigned int r = core_interrupt_disable();
329 reg_ana_addr = addr;
330 reg_dma_src_addr(chn) = convert_ram_addr_cpu2bus(pdat);
331 reg_dma_dst_addr(chn) = 0x80140184;
332 dma_set_size(chn, len, DMA_WORD_WIDTH);
333 analog_tx_dma_config.dstwidth = DMA_CTR_WORD_WIDTH;
334 analog_tx_dma_config.srcwidth = DMA_CTR_WORD_WIDTH;
335 dma_config(chn, &analog_tx_dma_config);
336 dma_chn_en(chn);
337 reg_ana_ctrl = 0x60;
338 analog_wait();
339 core_restore_interrupt(r);
340 }
341
342 /**
343 * @brief This function write buffer to analog register by dma channel.
344 * @param[in] chn - the dma channel.
345 * @param[in] addr - address need to be read from.
346 * @param[in] *pdat - the buffer need to be put data.
347 * note: The size of array pdat must be a multiple of 4.
348 * For example, if you just need read 5 byte by dma, you should
349 * define the size of array pdat to be greater than 8 other than 5.
350 * Because the dma would return 4 byte data every time, 5 byte is
351 * not enough to store them.
352 * @param[in] len - the length of read data.
353 * @return none.
354 */
analog_read_buff_dma(dma_chn_e chn,unsigned char addr,unsigned char * pdat,unsigned int len)355 void analog_read_buff_dma(dma_chn_e chn, unsigned char addr, unsigned char *pdat, unsigned int len)
356 {
357 unsigned int r = core_interrupt_disable();
358 reg_ana_len = len;
359 reg_ana_addr = addr;
360
361 reg_dma_src_addr(chn) = 0x80140184;
362 reg_dma_dst_addr(chn) = convert_ram_addr_cpu2bus(pdat);
363 dma_set_size(chn, len, DMA_WORD_WIDTH);
364 analog_rx_dma_config.dstwidth = DMA_CTR_WORD_WIDTH;
365 analog_rx_dma_config.srcwidth = DMA_CTR_WORD_WIDTH;
366 dma_config(chn, &analog_rx_dma_config);
367 dma_chn_en(chn);
368 reg_ana_ctrl = FLD_ANA_CYC;
369 analog_wait();
370 core_restore_interrupt(r);
371 }
372
373 /**
374 * @brief This function write buffer to analog register by dma channel.
375 * @param[in] chn - the dma channel.
376 * @param[in] pdat - the buffer(addr & data) ptr need to be write,
377 * note: The array pdat should look like this,
378 * | pdat | | |
379 * | :------ | :----------| :---- |
380 * | pdat[0] | address | 0x3a |
381 * | pdat[1] | data | 0x11 |
382 * | pdat[2] | address | 0x3b |
383 * | pdat[3] | data | 0x22 |
384 * | ...... | | |
385 * It means write data 0x11 to address 0x3a,
386 * write data 0x22 to address 0x3b,
387 * ......
388 * @param[in] len - the length of read data.
389 * @return none.
390 */
analog_write_addr_data_dma(dma_chn_e chn,void * pdat,int len)391 void analog_write_addr_data_dma(dma_chn_e chn, void *pdat, int len)
392 {
393 unsigned int r = core_interrupt_disable();
394
395 reg_dma_src_addr(chn) = convert_ram_addr_cpu2bus(pdat);
396 reg_dma_dst_addr(chn) = 0x80140184;
397 dma_set_size(chn, len, DMA_WORD_WIDTH);
398 analog_tx_dma_config.dstwidth = DMA_CTR_WORD_WIDTH;
399 analog_tx_dma_config.srcwidth = DMA_CTR_WORD_WIDTH;
400 dma_config(chn, &analog_tx_dma_config);
401 dma_chn_en(chn);
402 delay_us(1);
403 reg_ana_ctrl = FLD_ANA_RW;
404 reg_ana_dma_ctl = FLD_ANA_CYC1 | FLD_ANA_DMA_EN;
405 delay_us(1);
406 while (!(reg_ana_sta & BIT(3))) {
407 }
408
409 reg_ana_ctrl = 0x00;
410 reg_ana_dma_ctl = 0;
411 core_restore_interrupt(r);
412 }
413
414 /**********************************************************************************************************************
415 * local function implementation *
416 *********************************************************************************************************************/
417 /**
418 * @brief This function serves to judge whether analog write/read is busy .
419 * @return none.
420 */
analog_wait(void)421 static inline void analog_wait(void)
422 {
423 while (reg_ana_ctrl & FLD_ANA_BUSY) {
424 }
425 }
426