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