kernel_liteos_a1/platform/uart/dw-3.0.8a/uart.c

216 lines
6.1 KiB
C

/*
* Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020, Huawei Device 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 the copyright holder 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 HOLDER 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 "los_event.h"
#include "hisoc/uart.h"
EVENT_CB_S g_uartEvent;
#ifdef LOSCFG_PLATFORM_UART_WITHOUT_VFS
#ifdef LOSCFG_SHELL
#define UART_BUF 128
static UINT8 g_uart_buf[UART_BUF];
extern void shellCmdLineParse(CHAR c, pf_OUTPUT pf_put);
#endif
#endif
UINT8 uart_getc(void)
{
UINT8 ch = 0;
while (!(GET_UINT32(UART_REG_BASE + UART_USR) & 0x08)) { /*lint !e40*/
LOS_Msleep(100);
}
/* receive one char */
READ_UINT8(ch, UART_REG_BASE + UART_DR);
return ch;
}
#if defined(LOSCFG_COREDUMP) || defined(LOSCFG_LLTSER)
UINT8 uart_getc_interrupt(void)
{
UINT8 ch = 0;
while (!(GET_UINT32(UART_REG_BASE + UART_USR) & 0x08)) { /*lint !e40*/
}
/* receive one char */
READ_UINT8(ch, UART_REG_BASE + UART_DR);
return ch;
}
#endif
/* send */
char uart_putc (char c)
{
/* Wait until THRE is empyt */
while (!(GET_UINT32(UART_REG_BASE + UART_USR) & 0x02)); /*lint !e40*/
/* send one char */
WRITE_UINT8(c, UART_REG_BASE + UART_DR);
return c;
}
unsigned int g_uart_fputc_en __attribute__ ((section(".data"))) = 1;
char uart_fputc(char c, void *f)
{
if (g_uart_fputc_en == 1) {
if (c == '\n') {
uart_putc('\r'); /*lint !e534*/
}
return (uart_putc(c));
} else {
return 0;
}
}
#ifdef LOSCFG_PLATFORM_UART_WITHOUT_VFS
#ifdef LOSCFG_SHELL
static void uart_notice_adapt(void)
{
LOS_EventWrite(&g_uartEvent, 0x112);
}
void uart_get_raw(void)
{
UINT8 ch;
static int cnt_ii = 0;
if (cnt_ii == 0) {
(VOID)memset_s(g_uart_buf, UART_BUF, 0, UART_BUF);
}
ch = uart_getc();
g_uart_buf[cnt_ii] = ch;
cnt_ii++;
switch (cnt_ii) {
case 1: // only one char
if (ch != 27) { // un special
uart_notice_adapt();
cnt_ii = 0;
}
break;
case 2:
if (ch != 91) {
uart_notice_adapt();
cnt_ii = 0;
}
break;
case 3:
switch (ch) {
default:
case 'A':
case 'B':
case 'C':
case 'D':
{
uart_notice_adapt();
cnt_ii = 0;
}
break;
case 51:
case 49:
case 52:
break;
}
break;
case 4:
{
uart_notice_adapt();
cnt_ii = 0;
}
break;
default:
{
uart_notice_adapt();
cnt_ii = 0;
}
break;
}
}
extern void dprintf(const char *fmt, ...);
static void uart_irqhandle(void)
{
UINT8 ch;
shellCmdLineParse(0, dprintf);
}
int uart_hwiCreate(void)
{
UINT32 uwRet = 0;
if (uwRet != LOS_HwiCreate(NUM_HAL_INTERRUPT_UART, 0xa0, 0, uart_irqhandle, 0)) {
return uwRet;
}
uart_interrupt_unmask();
return 0;
}
#endif
#endif
void uart_init()
{
unsigned int temp;
unsigned int divider;
unsigned char dividerH, dividerL;
/* disable UART1 FIFO */
WRITE_UINT32(0, UART_REG_BASE + UART_FCR); /*lint !e40*/
/* reset and enable UART1 FIFO */
WRITE_UINT32(0x7, UART_REG_BASE + UART_FCR); /*lint !e40*/
/* disable UART1 interrupt */
WRITE_UINT32(0, UART_REG_BASE + UART_IER); /*lint !e40*/
/* enable DLL and DLH */
WRITE_UINT32(0x80, UART_REG_BASE + UART_LCR); /*lint !e40*/
/* Caculate devide */
temp = 16 * CONSOLE_UART_BAUDRATE;
divider = CONFIG_UART_CLK_INPUT / temp;
dividerH = ((divider) & 0xff00) >> 8;
dividerL = ((divider) & 0x00ff);
/* configure DLL and DLH */
WRITE_UINT32(dividerL, UART_REG_BASE + UART_DLL); /*lint !e40*/
WRITE_UINT32(dividerH, UART_REG_BASE + UART_DLH); /*lint !e40*/
/* disable DLL and DLH */
WRITE_UINT32(0x0, UART_REG_BASE + UART_LCR); /*lint !e40*/
/* 8bit data, 1bit stop,even parity */
WRITE_UINT32(0x1b, UART_REG_BASE + UART_LCR); /*lint !e40*/
/* enable UART1 */
WRITE_UINT32(0x1, UART_REG_BASE + UART_IER); /*lint !e40*/
(VOID)LOS_EventInit(&g_uartEvent);
}
void uart_interrupt_unmask(void)
{
HalIrqUnmask(NUM_HAL_INTERRUPT_UART);
}