1 /**
2  * Copyright (c) 2015, Realsil Semiconductor Corporation. All rights reserved.
3  *
4  */
5 
6 #include <stdio.h>
7 #include <stdarg.h>
8 #include "trace_uart.h"
9 #include "bt_board.h"
10 
11 extern uint8_t  hci_tp_lgc_efuse[];
12 
13 typedef struct _TraceUartBuffer
14 {
15     uint8_t  *tx_buffer;
16     uint16_t tx_len;
17     uint8_t  tx_busy;
18     UART_TX_CB  tx_cb;
19 
20     bool     tx_switch;
21     GDMA_InitTypeDef    UARTTxGdmaInitStruct;
22 } TRACE_UART_INFO;
23 
24 TRACE_UART_INFO   g_uart_obj;
25 
26 #ifdef TRACE_UART_TX_IRQ
traceuart_stop_tx(TRACE_UART_INFO * trace_pointer)27 static inline void traceuart_stop_tx(TRACE_UART_INFO *trace_pointer)
28 {
29     if (trace_pointer->tx_busy)
30     {
31         trace_pointer->tx_busy = 0;
32         UART_INTConfig(TRACE_UART_DEV, RUART_IER_ETBEI, DISABLE);
33     }
34 }
35 
transmit_log(TRACE_UART_INFO * trace_pointer)36 static inline void transmit_log(TRACE_UART_INFO *trace_pointer)
37 {
38     int count;
39     if (trace_pointer->tx_len == 0)
40     {
41         traceuart_stop_tx(trace_pointer);
42         if(trace_pointer->tx_cb)
43             trace_pointer->tx_cb();
44         return;
45     }
46 
47     count = TRACE_COUNT;
48     do
49     {
50         UART_CharPut(TRACE_UART_DEV,*trace_pointer->tx_buffer);
51         trace_pointer->tx_buffer++;
52         trace_pointer->tx_len--;
53     }
54     while (--count > 0 && trace_pointer->tx_len > 0);
55 }
56 
traceuart_irq(void * data)57 uint32_t traceuart_irq(void *data)
58 {
59     volatile uint8_t reg_iir;
60     uint8_t int_id;
61     uint32_t reg_val;
62     TRACE_UART_INFO *trace_pointer = (TRACE_UART_INFO *) data;
63 
64     reg_iir = UART_IntStatus(TRACE_UART_DEV);
65     if ((reg_iir & RUART_IIR_INT_PEND) != 0)
66     {
67         /* No pending IRQ */
68         return 0;
69     }
70 
71     int_id = (reg_iir & RUART_IIR_INT_ID) >> 1;
72 
73     switch (int_id)
74     {
75         case RUART_TX_FIFO_EMPTY:
76             transmit_log(trace_pointer);
77             break;
78         case RUART_RECEIVE_LINE_STATUS:
79             reg_val = (UART_LineStatusGet(TRACE_UART_DEV));
80             platform_debug("traceuart_irq: LSR interrupt, reg_val=%x\r\n",reg_val);
81             break;
82         default:
83             platform_debug("traceuart_irq: Unknown interrupt type %x", int_id);
84             break;
85     }
86 
87     return 0;
88 }
89 #endif
90 
trace_uart_init(void)91 bool trace_uart_init(void)
92 {
93     if(!CHECK_SW(EFUSE_SW_TRACE_SWITCH))
94     {
95         //0
96     platform_debug("trace_uart_init:  TRACE OPEN");
97     g_uart_obj.tx_switch = true;
98 
99     //gloabal_init
100     g_uart_obj.tx_busy = 0;
101 
102     Pinmux_Config(TRACE_UART_TX, PINMUX_FUNCTION_UART);
103     //  Pinmux_Config(TRACE_UART_RX, PINMUX_FUNCTION_UART)
104 
105     PAD_PullCtrl(TRACE_UART_TX, GPIO_PuPd_UP);
106     // PAD_PullCtrl(TRACE_UART_RX, GPIO_PuPd_UP);
107 
108     UART_InitTypeDef    UARTStruct;
109     UART_InitTypeDef    *pUARTStruct = &UARTStruct;
110 
111     UART_StructInit(pUARTStruct);
112     pUARTStruct->WordLen = RUART_WLS_8BITS;
113     pUARTStruct->StopBit = RUART_STOP_BIT_1;
114     pUARTStruct->Parity = RUART_PARITY_DISABLE;
115     pUARTStruct->ParityType = RUART_EVEN_PARITY;
116     pUARTStruct->StickParity = RUART_STICK_PARITY_DISABLE;
117 
118     UART_Init(TRACE_UART_DEV, pUARTStruct);
119     UART_SetBaud(TRACE_UART_DEV, TRACE_UART_BAUDRATE);
120     UART_RxCmd(TRACE_UART_DEV, DISABLE);
121 
122 
123 #ifdef TRACE_UART_TX_IRQ
124     InterruptDis(TRACE_UART_IRQ);
125     InterruptUnRegister(TRACE_UART_IRQ);
126     InterruptRegister((IRQ_FUN)traceuart_irq,
127             TRACE_UART_IRQ, (uint32_t)&g_uart_obj,
128             TRACEUART_IRQ_PRIO);
129     InterruptEn(TRACE_UART_IRQ, TRACEUART_IRQ_PRIO);
130 #endif
131     }
132     else
133     {
134         //default 1 close
135         g_uart_obj.tx_switch = false;
136     }
137 
138     return true;
139 }
140 
trace_uart_deinit(void)141 bool trace_uart_deinit(void)
142 {
143 
144     if(!CHECK_SW(EFUSE_SW_TRACE_SWITCH))
145     {
146         if (g_uart_obj.tx_switch == true) {
147             //has already close
148             UART_DeInit(TRACE_UART_DEV);
149 #ifdef TRACE_UART_TX_IRQ
150             InterruptDis(TRACE_UART_IRQ);
151             InterruptUnRegister(TRACE_UART_IRQ);
152 #endif
153             g_uart_obj.tx_switch = false;
154             return true;
155         }
156         else {
157             hci_board_debug("\r\n:trace_uart_deinit: no need\r\n");
158             return false;
159         }
160     }
161     return true;
162 }
163 
164 
165 
166 #ifdef TRACE_UART_DMA
traceuart_dma_tx_complete(void * data)167 static uint32_t traceuart_dma_tx_complete(void *data)
168 {
169     TRACE_UART_INFO *t = (TRACE_UART_INFO *)data;
170     PGDMA_InitTypeDef GDMA_InitStruct;
171     uint8_t  IsrTypeMap;
172 
173     platform_debug("TRACE DMA Tx complete ISR");
174 
175     GDMA_InitStruct = &t->UARTTxGdmaInitStruct;
176 
177     GDMA_Cmd(GDMA_InitStruct->GDMA_Index, GDMA_InitStruct->GDMA_ChNum, DISABLE);
178     IsrTypeMap = GDMA_ClearINT(GDMA_InitStruct->GDMA_Index, GDMA_InitStruct->GDMA_ChNum);
179     GDMA_ChnlFree(GDMA_InitStruct->GDMA_Index, GDMA_InitStruct->GDMA_ChNum);
180     UART_TXDMACmd(TRACE_UART_DEV, DISABLE);
181     UART_RXDMACmd(TRACE_UART_DEV, DISABLE);
182     /* Wake task to continue tx */
183     t->tx_busy = 0;
184     if(t->tx_cb)
185         t->tx_cb();
186     return 0;
187 }
188 #endif
trace_uart_tx(uint8_t * pstr,uint16_t len,UART_TX_CB tx_cb)189 bool trace_uart_tx(uint8_t *pstr,uint16_t len, UART_TX_CB tx_cb)
190 {
191     if(g_uart_obj.tx_switch == false)
192     {
193         //printf("\r\n trace_uart_deinit has been called please call init \r\n");
194         if(tx_cb)
195             tx_cb();
196         return true;
197     }
198 
199 #ifdef TRACE_UART_TX_WHILE
200     UART_SendData(TRACE_UART_DEV, pstr, len);
201     if(tx_cb)
202         tx_cb();
203 #else
204 
205     TRACE_UART_INFO   *p_uart_obj= &g_uart_obj;
206 
207     if (!(p_uart_obj->tx_busy))
208     {
209         p_uart_obj->tx_busy = 1;
210 #ifdef TRACE_UART_TX_IRQ
211         p_uart_obj->tx_buffer = pstr;
212         p_uart_obj->tx_len  = len;
213         p_uart_obj->tx_cb   = tx_cb;
214         UART_INTConfig(TRACE_UART_DEV, RUART_IER_ETBEI, ENABLE);
215 #endif
216 
217 #ifdef TRACE_UART_DMA
218         int ret;
219         UART_TXDMAConfig(TRACE_UART_DEV, 8);
220         UART_TXDMACmd(TRACE_UART_DEV, ENABLE);
221         ret = UART_TXGDMA_Init(TRACE_UART_INDEX, &p_uart_obj->UARTTxGdmaInitStruct,(void *) p_uart_obj, traceuart_dma_tx_complete,pstr,len);
222         NVIC_SetPriority(GDMA_GetIrqNum(0, p_uart_obj->UARTTxGdmaInitStruct.GDMA_ChNum), TRACEUART_DMA_PRIO);
223 
224         if (!ret ) {
225             platform_debug("%s Error(%d)\n", __FUNCTION__, ret);
226             p_uart_obj->tx_busy = 0;
227         }
228 
229 #endif
230     }
231     else
232     {
233         platform_debug("!!!TX not finished, can't send");
234         return false;
235     }
236 
237 #endif
238     return true;
239 }
240 
bt_trace_set_switch(bool flag)241 void bt_trace_set_switch(bool flag)
242 {
243     g_uart_obj.tx_switch = flag;
244 }
245 
246 
247