sdk-hwV1.3/lichee/xr806/appos/project/common/startup/gcc/retarget_stdout.c

293 lines
6.4 KiB
C
Executable File

/*
* Copyright (C) 2017 XRADIO TECHNOLOGY CO., LTD. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
* 3. Neither the name of XRADIO TECHNOLOGY CO., LTD. nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include "common/board/board.h"
#include "pm/pm.h"
#include "driver/chip/hal_util.h"
/*
* retarget for standard output/error
*/
#if PRJCONF_UART_EN
#define STDOUT_WAIT_UART_TX_DONE 1
#if STDOUT_WAIT_UART_TX_DONE
#define STDOUT_WAIT_UART_TX_TIME 100 /* wait uart tx done, 100 us for baudrate 115200 */
#else
#define STDOUT_WAIT_UART_TX_TIME 0
#endif
static uint8_t g_stdout_enable = 1;
static UART_ID g_stdout_uart_id = UART_NUM;
#ifdef CONFIG_PM
#include <string.h>
#include <stdlib.h>
static uint32_t pm_print_index;
static uint32_t pm_print_len;
static char *pm_print_buf;
static int8_t g_stdio_suspending = 0;
__nonxip_text
static int stdio_suspend(struct soc_device *dev, enum suspend_state_t state)
{
g_stdio_suspending = 1;
#if STDOUT_WAIT_UART_TX_DONE
if (g_stdout_enable && g_stdout_uart_id < UART_NUM) {
UART_T *uart = HAL_UART_GetInstance(g_stdout_uart_id);
while (!HAL_UART_IsTxEmpty(uart)) { }
HAL_UDelay(STDOUT_WAIT_UART_TX_TIME); /* wait tx done */
}
#endif
switch (state) {
case PM_MODE_SLEEP:
case PM_MODE_STANDBY:
case PM_MODE_HIBERNATION:
printf("a%s ok\n", __func__);
break;
default:
break;
}
return 0;
}
/* BESURE app cpu has run now for nuart use app gpio */
__nonxip_text
static int stdio_resume(struct soc_device *dev, enum suspend_state_t state)
{
switch (state) {
case PM_MODE_SLEEP:
case PM_MODE_STANDBY:
case PM_MODE_HIBERNATION:
printf("a%s ok\n", __func__);
break;
default:
break;
}
g_stdio_suspending = 0;
if (pm_print_len > 0 && pm_print_index > 0) {
pm_print_buf[pm_print_index] = '\0';
puts(pm_print_buf);
pm_print_index = 0;
}
return 0;
}
static const struct soc_device_driver stdio_drv = {
.name = "astdio",
.suspend_noirq = stdio_suspend,
.resume_noirq = stdio_resume,
.enter_latency = STDOUT_WAIT_UART_TX_TIME + 2, /* at CPU 160MHz */
.exit_latency = 1, /* at CPU 160MHz */
};
static struct soc_device stdio_dev = {
.name = "astdio",
.driver = &stdio_drv,
};
#define STDIO_DEV (&stdio_dev)
void uart_set_suspend_record(unsigned int len)
{
char *buf;
if (pm_print_len == len) {
return;
}
if (pm_print_len > 0) {
buf = pm_print_buf;
pm_print_len = 0;
pm_print_buf = NULL;
free(buf);
}
if (len > 0) {
buf = malloc(len);
if (buf) {
pm_print_buf = buf;
pm_print_len = len;
}
}
pm_print_index = 0;
}
#endif /* CONFIG_PM */
void stdout_enable(uint8_t en)
{
g_stdout_enable = en;
}
static int stdout_write(const char *buf, int len)
{
if (!g_stdout_enable || g_stdout_uart_id >= UART_NUM || len <= 0) {
return 0;
}
#ifdef CONFIG_PM
if (g_stdio_suspending) {
if (pm_print_len > 0 && pm_print_index + len < (pm_print_len - 1)) {
memcpy(pm_print_buf + pm_print_index, buf, len);
pm_print_index += len;
return len;
} else {
return 0;
}
}
#endif
return board_uart_write(g_stdout_uart_id, buf, len);
}
int stdout_init(void)
{
if (g_stdout_uart_id < UART_NUM) {
return 0;
}
if (board_uart_init(BOARD_MAIN_UART_ID) == HAL_OK) {
g_stdout_uart_id = BOARD_MAIN_UART_ID;
#ifdef CONFIG_LIBC_WRAP_STDIO
stdio_set_write(stdout_write);
#endif
#ifdef CONFIG_PM
if (!g_stdio_suspending) {
pm_register_ops(STDIO_DEV);
}
#endif
#ifdef CONFIG_TRUSTZONE
TZ_StdoutInit_NSC(BOARD_MAIN_UART_ID);
#endif
return 0;
}
return -1;
}
int stdout_deinit(void)
{
if (g_stdout_uart_id >= UART_NUM) {
return 0;
}
#ifdef CONFIG_PM
if (!g_stdio_suspending) {
pm_unregister_ops(STDIO_DEV);
}
#endif
if (board_uart_deinit(g_stdout_uart_id) == HAL_OK) {
g_stdout_uart_id = UART_NUM;
#ifdef CONFIG_LIBC_WRAP_STDIO
stdio_set_write(NULL);
#endif
return 0;
}
return -1;
}
#ifndef CONFIG_LIBC_WRAP_STDIO
#include <sys/unistd.h> /* for STDOUT_FILENO and STDERR_FILENO */
#include "compiler.h"
#include "driver/chip/hal_cmsis.h"
#include "kernel/os/os_mutex.h"
static OS_Mutex_t g_stdout_mutex;
/* case of critical context
* - IRQ disabled
* - FIQ disabled
* - Execute in ISR context
* - Scheduler is not running
*/
static int stdout_is_critical_context(void)
{
return (__get_PRIMASK() ||
__get_FAULTMASK() ||
__get_IPSR() ||
!OS_ThreadIsSchedulerRunning());
}
static void stdout_mutex_lock(void)
{
if (stdout_is_critical_context()) {
return;
}
if (!OS_MutexIsValid(&g_stdout_mutex)) {
OS_RecursiveMutexCreate(&g_stdout_mutex);
}
OS_RecursiveMutexLock(&g_stdout_mutex, OS_WAIT_FOREVER);
}
static void stdout_mutex_unlock(void)
{
if (stdout_is_critical_context()) {
return;
}
if (OS_MutexIsValid(&g_stdout_mutex)) {
OS_RecursiveMutexUnlock(&g_stdout_mutex);
}
}
int _write(int fd, const char *buf, int len)
{
int ret;
if (fd != STDOUT_FILENO && fd != STDERR_FILENO) {
return -1;
}
stdout_mutex_lock();
ret = stdout_write(buf, len);
stdout_mutex_unlock();
return ret;
}
#endif /* CONFIG_LIBC_WRAP_STDIO */
#endif /* PRJCONF_UART_EN */