• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  * Description:   LOG UART MODULE
15  * Author:
16  * Create:
17  */
18 #if defined USE_CMSIS_OS
19 #include <string.h>
20 #ifdef USE_OSAL_INSTEAD_CMSIS
21 #include "soc_osal.h"
22 #include "los_sched_pri.h"
23 #else
24 #include "cmsis_os2.h"
25 #endif
26 #include "core.h"
27 #if CORE == MASTER_BY_ALL
28 #include "stdio.h"
29 #if (CORE_NUMS  > 1)
30 #include "watchdog.h"
31 #endif
32 #include "hal_uart.h"
33 #endif
34 #ifdef TEST_SUITE
35 #include "test_suite_uart.h"
36 #endif
37 #include "log_panic.h"
38 #include "log_buffer.h"
39 #include "log_buffer_reader.h"
40 #include "log_trigger.h"
41 #include "panic.h"
42 #include "non_os.h"
43 #ifdef SUPPORT_IPC
44 #include "ipc.h"
45 #endif
46 
47 #include "uart.h"
48 #if defined(CONFIG_UART_SUPPORT_DMA)
49 #include "dma.h"
50 #endif  /* CONFIG_UART_SUPPORT_DMA */
51 #include "log_uart_porting.h"
52 #include "log_uart.h"
53 #ifdef HSO_SUPPORT
54 #include "securec.h"
55 #include "diag_adapt_sdt.h"
56 #endif
57 #ifdef IPC_NEW
58 #include "ipc.h"
59 #include "ipc_porting.h"
60 #endif
61 #include "diag_log.h"
62 #include "dfx_adapt_layer.h"
63 
64 /**
65  * Security core logging watermark level.
66  * When the level is under the watermark and the Security core goes to sleep the log will stop until retriggered. */
67 static uint16_t g_log_uart_security_log_watermark = LOG_UART_LOG_WATERMARK_VALUE_ON_INIT;
68 
69 /** Time(ms) of the oldest message left in the logging buffer. */
70 #define OLDEST_MESSAGE_IN_BUFFER 1000
71 
72 static uint8_t g_uart_log_rx_buffer_test[LOG_UART_RX_MAX_BUFFER_SIZE];
73 #ifdef SW_UART_DEBUG
74 #ifndef SW_UART_BAUDRATE
75 #define SW_UART_BAUDRATE 115200UL
76 #endif
77 #endif
78 
79 /** UART Settings. Define these in the C file to avoid pulling in the UART header in the header file. */
80 #define LOG_UART_BAUD_RATE 115200
81 #define LOG_UART_DATA_BITS UART_DATA_BIT_8
82 #define LOG_UART_STOP_BITS UART_STOP_BIT_1
83 #define LOG_UART_PARITY    UART_PARITY_NONE
84 
85 /** Number of milliseconds to delay the trigger of a new UART write in case the UART is busy */
86 #define LOG_UART_DELAY_ON_UART_BUSY 1
87 #if CORE == MASTER_BY_ALL
88 
89 /** Mutex protecting accesses to the circular buffer. */
90 #ifdef USE_OSAL_INSTEAD_CMSIS
91 static osal_semaphore g_semaphore_uart = { NULL };
92 static osal_semaphore g_semaphore_logs = { NULL };
93 #else
94 static osSemaphoreId_t g_semaphore_uart = NULL;
95 static osSemaphoreId_t g_semaphore_logs = NULL;
96 #endif
97 
98 /** UART Handle */
99 static uart_bus_t g_log_uart = LOG_UART_BUS;
100 
101 #if defined(CONFIG_UART_SUPPORT_DMA)
102 #define DMA_UART_TRANSFER_WIDTH_WORD        4
103 #define DMA_UART_TRANSFER_WIDTH_HALF_WORD   2
104 #define DMA_UART_TRANSFER_WIDTH_8           0
105 #define DMA_UART_TRANSFER_WIDTH_16          1
106 #define DMA_UART_TRANSFER_WIDTH_32          2
107 #define DMA_UART_BURST_TRANSACTION_LENGTH_8 2
108 #endif  /* CONFIG_UART_SUPPORT_DMA */
109 
110 /* Local function prototypes. */
111 static void log_uart_tx_isr_callback(const void *buffer, uint32_t length, const void *params);
112 
113 /**
114  * This handler gets called when one of the cores wants to trigger the log reader
115  * @param message   The IPC message
116  * @param payload_p The payload, contains the reset reason
117  * @param src       The core who has just started
118  * @param id        The message ID (should always be 0 - the first message after starting)
119  * @return
120  */
121 #if (CORE_NUMS  > 1) && defined(IPC_NEW)
log_reader_info_action_handler(uint8_t * payload_addr,uint32_t payload_len)122 static void log_reader_info_action_handler(uint8_t *payload_addr, uint32_t payload_len)
123 {
124     unused(payload_addr);
125     unused(payload_len);
126     log_uart_trigger();
127 }
128 #elif (CORE_NUMS > 1) && (defined CONFIG_DFX_SUPPORT_CUSTOM_LOG) && (CONFIG_DFX_SUPPORT_CUSTOM_LOG == DFX_YES)
log_reader_info_action_handler(void)129 void log_reader_info_action_handler(void)
130 {
131     dfx_log_reader_irq_clr();      /* Clear Software interrupt. */
132     log_uart_trigger();
133 }
134 
135 #elif (CORE_NUMS  > 1)
log_reader_info_action_handler(ipc_action_t message,const volatile ipc_payload * payload_p,cores_t src,uint32_t id)136 static bool log_reader_info_action_handler(ipc_action_t message,
137                                            const volatile ipc_payload *payload_p, cores_t src, uint32_t id)
138 {
139     unused(message);
140     unused(id);
141     unused(payload_p);
142     unused(src);
143     log_uart_trigger();
144     return true;
145 }
146 #endif
147 
148 /* Initialise the UART and open it at the specified speed! */
log_uart_init(void)149 void log_uart_init(void)
150 {
151 #if (CORE_NUMS > 1)
152     unused(log_reader_info_action_handler);
153 #endif
154 
155     /* Configure and open the UART port for use. */
156     uart_pin_config_t log_uart_pins = {
157         .tx_pin = CODELOADER_UART_TX_PIN, /* TEST_SUITE_UART_TX_PIN */
158         .rx_pin = CODELOADER_UART_RX_PIN, /* TEST_SUITE_UART_RX_PIN */
159         .cts_pin = PIN_NONE,
160         .rts_pin = PIN_NONE
161     };
162 
163     uart_attr_t uart_line_config = {
164         .baud_rate = LOG_UART_BAUD_RATE,
165         .data_bits = LOG_UART_DATA_BITS,
166         .stop_bits = LOG_UART_STOP_BITS,
167         .parity = LOG_UART_PARITY
168     };
169     uart_buffer_config_t uart_buffer_config;
170 
171     uart_buffer_config.rx_buffer_size = LOG_UART_RX_MAX_BUFFER_SIZE;
172     uart_buffer_config.rx_buffer = g_uart_log_rx_buffer_test;
173 
174     /* Open and configure the UART */
175     g_log_uart = LOG_UART_BUS;
176 #if defined(CONFIG_UART_SUPPORT_DMA)
177     uart_extra_attr_t extra_attr = {
178         .tx_dma_enable = 1,
179         .tx_int_threshold = 0,
180         .rx_dma_enable = 1,
181         .rx_int_threshold = 0
182     };
183 
184     uapi_dma_init();
185     uapi_dma_open();
186     (void)uapi_uart_init(LOG_UART_BUS, &log_uart_pins, &uart_line_config, &extra_attr, &uart_buffer_config);
187 #else
188     (void)uapi_uart_init(LOG_UART_BUS, &log_uart_pins, &uart_line_config, NULL, &uart_buffer_config);
189 #endif  /* CONFIG_UART_SUPPORT_DMA */
190 
191 #if SYS_DEBUG_MODE_ENABLE == YES
192     uapi_uart_register_rx_callback(LOG_UART_BUS, UART_RX_CONDITION_FULL_OR_SUFFICIENT_DATA_OR_IDLE,
193                                    LOG_UART_RX_MAX_BUFFER_SIZE, log_uart_rx_callback);
194 #endif
195 }
196 
log_uart_send_buffer(const uint8_t * buffer,uint16_t length)197 void log_uart_send_buffer(const uint8_t *buffer, uint16_t length)
198 {
199     uapi_uart_write(g_log_uart, (const void *)buffer, length, 0);
200 }
201 
log_uart_update_watermark_level(log_memory_region_section_t log_mem_region,uint16_t new_watermark_val)202 void log_uart_update_watermark_level(log_memory_region_section_t log_mem_region, uint16_t new_watermark_val)
203 {
204 #if CORE_NUMS > 1
205     if (log_mem_region == LOG_MEMORY_REGION_SECTION_1) {
206         g_log_uart_security_log_watermark = new_watermark_val;
207     }
208 #else
209     if (log_mem_region == LOG_MEMORY_REGION_SECTION_0) {
210         g_log_uart_security_log_watermark = new_watermark_val;
211     }
212 #endif
213 }
214 
215 /* Initialises the UART when RTOS functions are available. This should be called before the RTOS scheduler starts,
216  * but when we can create the mutex.
217  */
218 // Run after OS, but before threads are started, so in a single thread.
log_uart_init_after_rtos(void)219 void log_uart_init_after_rtos(void)
220 {
221     /* Create the mutex used to control logs written to . */
222 #ifdef USE_OSAL_INSTEAD_CMSIS
223     osal_sem_binary_sem_init(&g_semaphore_logs, 1);
224     if (g_semaphore_logs.sem == NULL) {
225 #else
226     g_semaphore_logs = osSemaphoreNew(1, 0, NULL);
227     if (!g_semaphore_logs) {
228 #endif
229         panic(PANIC_LOG, LOG_PANIC_MUTEX_NOT_READY);
230         return;
231     }
232     register_log_trigger(log_uart_trigger);
233 
234 #ifdef USE_OSAL_INSTEAD_CMSIS
235     osal_sem_binary_sem_init(&g_semaphore_uart, 1);
236     if (g_semaphore_uart.sem == NULL) {
237 #else
238     g_semaphore_uart = osSemaphoreNew(1, 0, NULL);
239     if (!g_semaphore_uart) {
240 #endif
241 
242         panic(PANIC_LOG, LOG_PANIC_MUTEX_NOT_READY);
243         return;
244     }
245 
246     log_reader_ret_t lret = log_buffer_reader_init();
247     if (lret != LOG_READER_RET_OK) {
248         panic(PANIC_LOG, __LINE__);
249         return;
250     }
251 
252     // Register IPC handler to handle log trigger notifications from other cores
253 #if (CORE_NUMS > 1) && defined(IPC_NEW)
254     if (non_os_is_driver_initialised(DRIVER_INIT_IPC) == false) {
255         uapi_ipc_init();
256     }
257     ipc_rx_handler_info_t handler_info;
258     handler_info.msg_id = IPC_MSG_LOG_INFO;
259     handler_info.cb = log_reader_info_action_handler;
260     (void)uapi_ipc_register_rx_handler(&handler_info);
261 #elif (CORE_NUMS > 1) && (defined CONFIG_DFX_SUPPORT_CUSTOM_LOG) && (CONFIG_DFX_SUPPORT_CUSTOM_LOG == DFX_YES)
262     dfx_log_read_info_init();
263 #elif (CORE_NUMS > 1)
264     if (non_os_is_driver_initialised(DRIVER_INIT_IPC) == false) {
265         ipc_init();
266     }
267 
268     ipc_register_handler(IPC_ACTION_LOG_INFO, log_reader_info_action_handler);
269 #endif
270 }
271 
272 /*
273  * UART has trasnmitted some data. Call in interrupt context,
274  * simply schedule the read index update and additional data check.
275  */
276 static void log_uart_tx_isr_callback(const void *buffer, uint32_t length, const void *params)
277 {
278     unused(buffer);
279     unused(params);
280     unused(length);
281 
282     /* Pass the amount of data actually transmitted, so we can update the read pointer. */
283 #ifdef USE_OSAL_INSTEAD_CMSIS
284     osal_sem_up(&g_semaphore_uart);
285 #else
286     (void)osSemaphoreRelease(g_semaphore_uart);
287 #endif
288 }
289 
290 void log_uart_trigger(void)
291 {
292     /* Give the semaphore to ensure the main logging task will be active */
293 #ifdef USE_OSAL_INSTEAD_CMSIS
294     osal_sem_up(&g_semaphore_logs);
295 #else
296     (void)osSemaphoreRelease(g_semaphore_logs);
297 #endif
298 }
299 
300 #if defined(CONFIG_UART_SUPPORT_DMA)
301 static inline bool uart_dma_align_check_word(uint32_t data_buf, uint32_t data_len, uint32_t align_data)
302 {
303     bool ret1 = (data_buf % align_data) == 0 ? true : false;
304     bool ret2 = (data_len % align_data) == 0 ? true : false;
305     return ret1 && ret2;
306 }
307 
308 static uint8_t uart_dma_get_mem_width(uint32_t buff, uint32_t bytes)
309 {
310     if (uart_dma_align_check_word(buff, bytes, (uint32_t)DMA_UART_TRANSFER_WIDTH_WORD)) {
311         return DMA_UART_TRANSFER_WIDTH_32;
312     }
313     if (uart_dma_align_check_word(buff, bytes, (uint32_t)DMA_UART_TRANSFER_WIDTH_HALF_WORD)) {
314         return DMA_UART_TRANSFER_WIDTH_16;
315     }
316     return DMA_UART_TRANSFER_WIDTH_8;
317 }
318 
319 static uart_write_dma_config_t dma_cfg = { 0 };
320 static void log_uart_write_blocking_dma(const void *buf, uint32_t len)
321 {
322     dma_cfg.src_width = uart_dma_get_mem_width((uint32_t)(uintptr_t)buf, len);
323     dma_cfg.dest_width = DMA_UART_TRANSFER_WIDTH_8;
324     dma_cfg.burst_length = DMA_UART_BURST_TRANSACTION_LENGTH_8;
325     if (uapi_uart_write_by_dma(g_log_uart, buf, (uint16_t)len, &dma_cfg) != (int32_t)len) {
326         return;
327     }
328     while (uapi_uart_has_pending_transmissions(g_log_uart)) {};
329 }
330 #endif  /* CONFIG_UART_SUPPORT_DMA */
331 
332 static void log_uart_write_blocking_int(const void *buf, uint32_t len)
333 {
334     // Write The buffer to the uart
335     while (uapi_uart_write_int(g_log_uart, buf, (uint16_t)len, NULL, log_uart_tx_isr_callback) != ERRCODE_SUCC) {
336         // If it was unsuccessful try again after some ticks
337 #ifdef USE_OSAL_INSTEAD_CMSIS
338         if (OS_SCHEDULER_ALL_ACTIVE) {
339             (void)osal_msleep(LOG_UART_DELAY_ON_UART_BUSY);
340         }
341 #else
342         if (osKernelGetState() == osKernelRunning) {
343             (void)osDelay(LOG_UART_DELAY_ON_UART_BUSY);
344         }
345 #endif
346     }
347 
348     // Wait until the uart write has been completed
349 #ifdef USE_OSAL_INSTEAD_CMSIS
350     if (OS_SCHEDULER_ALL_ACTIVE && osal_sem_down(&g_semaphore_uart) != osOK) {
351         panic(PANIC_LOG, LOG_PANIC_MUTEX_NOT_READY);
352         return;
353     }
354 #else
355     if (osKernelGetState() == osKernelRunning && osSemaphoreAcquire(g_semaphore_uart, osWaitForever) != osOK) {
356         panic(PANIC_LOG, LOG_PANIC_MUTEX_NOT_READY);
357         return;
358     }
359 #endif
360     else {
361         while (uapi_uart_has_pending_transmissions(g_log_uart)) {};
362     }
363 }
364 
365 void log_uart_write_blocking(const void *buf, uint32_t len)
366 {
367 #if defined(CONFIG_UART_SUPPORT_DMA)
368     if (len <= CONFIG_UART_FIFO_DEPTH) {
369         log_uart_write_blocking_int(buf, len);
370     } else {
371         log_uart_write_blocking_dma(buf, len);
372     }
373 #else
374     log_uart_write_blocking_int(buf, len);
375 #endif  /* CONFIG_UART_SUPPORT_DMA */
376 }
377 
378 #define IBRD_NEED_BAUD_OFFSET_NUM      3
379 #define REMAINDER_NEED_BAUD_OFFSET_NUM 3
380 #define FBRD_NEED_REMAINDER_OFFSET_NUM 4
381 
382 static void log_uart_set_baud_rate(uart_bus_t bus, uint32_t baud)
383 {
384     uart_attr_t uart_line_config = {
385         .baud_rate = baud,
386         .data_bits = LOG_UART_DATA_BITS,
387         .stop_bits = LOG_UART_STOP_BITS,
388         .parity = LOG_UART_PARITY
389     };
390     uapi_uart_set_attr(bus, &uart_line_config);
391 }
392 
393 void log_uart_reset_baud_rate(void)
394 {
395     log_uart_set_baud_rate(LOG_UART_BUS, LOG_UART_BAUD_RATE);
396 
397 #ifdef SW_UART_DEBUG
398     log_uart_set_baud_rate(SW_DEBUG_UART_BUS, SW_UART_BAUDRATE);
399 #endif
400 #ifdef TEST_SUITE
401     log_uart_set_baud_rate(TEST_SUITE_UART_BUS, TEST_SUITE_UART_BAUD_RATE);
402 #endif
403 }
404 
405 void log_main(const void *unused_p)
406 {
407     unused(unused_p);
408 
409     log_reader_ret_t lr_ret;
410     log_memory_region_section_t lregion;
411     log_buffer_header_t lb_header = { 0 };
412     uint8_t *b1 = NULL;
413     uint32_t l1 = 0;
414     uint8_t *b2 = NULL;
415     uint32_t l2 = 0;
416 
417     for (;;) {
418         // Check if there are messages
419         while (log_buffer_reader_lock_next(&lregion, &lb_header) == LOG_READER_RET_OK) {
420             // Claim the message available
421             lr_ret = log_buffer_reader_claim_next(lregion, &b1, &l1, &b2, &l2);
422             // we are sure there is a new message
423             if ((lr_ret != LOG_READER_RET_OK) || ((lb_header.length - sizeof(lb_header)) != (l1 + l2))) {
424                 uapi_diag_error_log(0, "[log_uart]data error, r1=0x%x, len1=0x%x, r2=0x%x, len2=0x%x",
425                     (uintptr_t)b1, l1, (uintptr_t)b2, l2);
426                 log_buffer_reader_error_recovery(lregion);
427                 break;
428             }
429 #ifdef HSO_SUPPORT
430             zdiag_adapt_sdt_msg_proc(b1, l1, b2, l2);
431 #else
432             /* Copy SYNC, TIME, SEQUENCE and MSG to circular buffer. */
433             if ((g_log_uart != UART_BUS_NONE) && (l1 > 0)) {
434                 log_uart_write_blocking((const void *)b1, l1);
435             }
436             if ((g_log_uart != UART_BUS_NONE) && (l2 > 0)) {
437                 log_uart_write_blocking((const void *)b2, l2);
438             }
439 #endif
440             log_buffer_reader_discard(lregion);
441             dfx_watchdog_kick();
442         }
443         // If there has been log indicator get run again
444 #ifdef USE_OSAL_INSTEAD_CMSIS
445         if (OS_SCHEDULER_ALL_ACTIVE && osal_sem_down(&g_semaphore_logs) != OSAL_SUCCESS) {
446             panic(PANIC_LOG, LOG_PANIC_MUTEX_NOT_READY);
447         }
448 #else
449         if (osKernelGetState() == osKernelRunning && osSemaphoreAcquire(g_semaphore_logs, osWaitForever) != osOK) {
450             panic(PANIC_LOG, LOG_PANIC_MUTEX_NOT_READY);
451         }
452 #endif
453     }
454 }
455 #endif
456 
457 #endif  // defined USE_CMSIS_OS
458