blob: f4b3fb0a59a972be439423e734d46ccf76e6b3ef [file] [log] [blame]
/*
* This is a modified version of the file printf.c, which was distributed
* by Motorola as part of the M5407C3BOOT.zip package used to initialize
* the M5407C3 evaluation board.
*
* Copyright:
* 1999-2000 MOTOROLA, INC. All Rights Reserved.
* You are hereby granted a copyright license to use, modify, and
* distribute the SOFTWARE so long as this entire notice is
* retained without alteration in any modified and/or redistributed
* versions, and that such modified versions are clearly identified
* as such. No licenses are granted by implication, estoppel or
* otherwise under any patents or trademarks of Motorola, Inc. This
* software is provided on an "AS IS" basis and without warranty.
*
* To the maximum extent permitted by applicable law, MOTOROLA
* DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, INCLUDING
* IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR
* PURPOSE AND ANY WARRANTY AGAINST INFRINGEMENT WITH REGARD TO THE
* SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF) AND ANY
* ACCOMPANYING WRITTEN MATERIALS.
*
* To the maximum extent permitted by applicable law, IN NO EVENT
* SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER (INCLUDING
* WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS
* INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY
* LOSS) ARISING OF THE USE OR INABILITY TO USE THE SOFTWARE.
*
* Motorola assumes no responsibility for the maintenance and support
* of this software
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdarg.h>
#include <stdlib.h>
#if defined(__CC_ARM)
#include <stdio.h>
#endif
#include "fsl_debug_console.h"
#include "fsl_debug_console_conf.h"
#include "fsl_log.h"
#include "fsl_str.h"
#if defined(__riscv)
#include <sys/stat.h>
#include <sys/types.h>
#endif
/*******************************************************************************
* Definitions
******************************************************************************/
/*******************************************************************************
* Variables
******************************************************************************/
/*******************************************************************************
* Prototypes
******************************************************************************/
/*!
* @brief This is a printf call back function which is used to relocate the log to buffer
* or print the log immediately when the local buffer is full.
*
* @param[in] buf Buffer to store log.
* @param[in] indicator Buffer index.
* @param[in] val Target character to store.
* @param[in] len length of the character
*
*/
#if SDK_DEBUGCONSOLE
static void DbgConsole_RelocateLog(char *buf, int32_t *indicator, char val, int len);
#endif
/*******************************************************************************
* Code
******************************************************************************/
/*************Code for DbgConsole Init, Deinit, Printf, Scanf *******************************/
/* See fsl_debug_console.h for documentation of this function. */
status_t DbgConsole_Init(uint32_t baseAddr, uint32_t baudRate, uint8_t device, uint32_t clkSrcFreq)
{
assert(device != DEBUG_CONSOLE_DEVICE_TYPE_NONE);
return LOG_Init(baseAddr, device, baudRate, clkSrcFreq);
}
/* See fsl_debug_console.h for documentation of this function. */
status_t DbgConsole_Deinit(void)
{
/* LOG deinit */
LOG_Deinit();
return kStatus_Success;
}
status_t DbgConsole_Flush(void)
{
/* wait log and io idle */
return LOG_WaitIdle();
}
#if SDK_DEBUGCONSOLE
/* See fsl_debug_console.h for documentation of this function. */
int DbgConsole_Printf(const char *fmt_s, ...)
{
va_list ap;
int logLength = 0U, result = 0U;
char printBuf[DEBUG_CONSOLE_PRINTF_MAX_LOG_LEN] = {0U};
va_start(ap, fmt_s);
/* format print log first */
logLength = StrFormatPrintf(fmt_s, ap, printBuf, DbgConsole_RelocateLog);
/* print log */
result = LOG_Push((uint8_t *)printBuf, logLength);
va_end(ap);
return result;
}
/* See fsl_debug_console.h for documentation of this function. */
int DbgConsole_Putchar(int ch)
{
/* print char */
return LOG_Push((uint8_t *)&ch, 1U);
}
/* See fsl_debug_console.h for documentation of this function. */
int DbgConsole_Scanf(char *fmt_ptr, ...)
{
va_list ap;
int result;
char scanfBuf[DEBUG_CONSOLE_SCANF_MAX_LOG_LEN + 1U] = {0U};
/* scanf log */
LOG_ReadLine((uint8_t *)scanfBuf, DEBUG_CONSOLE_SCANF_MAX_LOG_LEN);
/* get va_list */
va_start(ap, fmt_ptr);
/* format scanf log */
result = StrFormatScanf(scanfBuf, fmt_ptr, ap);
va_end(ap);
return result;
}
/* See fsl_debug_console.h for documentation of this function. */
int DbgConsole_Getchar(void)
{
uint8_t ch;
/* Get char */
LOG_ReadCharacter(&ch);
return ch;
}
static void DbgConsole_RelocateLog(char *buf, int32_t *indicator, char val, int len)
{
int i = 0;
for (i = 0; i < len; i++)
{
if ((*indicator + 1) >= DEBUG_CONSOLE_PRINTF_MAX_LOG_LEN)
{
LOG_Push((uint8_t *)buf, *indicator);
*indicator = 0U;
}
buf[*indicator] = val;
(*indicator)++;
}
}
#endif /* SDK_DEBUGCONSOLE */
/*************Code to support toolchain's printf, scanf *******************************/
/* These function __write and __read is used to support IAR toolchain to printf and scanf*/
#if (defined(__ICCARM__))
#pragma weak __write
size_t __write(int handle, const unsigned char *buffer, size_t size)
{
if (buffer == 0)
{
/*
* This means that we should flush internal buffers. Since we don't we just return.
* (Remember, "handle" == -1 means that all handles should be flushed.)
*/
return 0;
}
/* This function only writes to "standard out" and "standard err" for all other file handles it returns failure. */
if ((handle != 1) && (handle != 2))
{
return ((size_t)-1);
}
/* Send data. */
LOG_Push((uint8_t *)buffer, 1U);
return size;
}
#pragma weak __read
size_t __read(int handle, unsigned char *buffer, size_t size)
{
/* This function only reads from "standard in", for all other file handles it returns failure. */
if (handle != 0)
{
return ((size_t)-1);
}
/* Receive data.*/
LOG_ReadLine(buffer, size);
return size;
}
/* support LPC Xpresso with RedLib */
#elif(defined(__REDLIB__))
#if (!SDK_DEBUGCONSOLE) && (defined(SDK_DEBUGCONSOLE_UART))
int __attribute__((weak)) __sys_write(int handle, char *buffer, int size)
{
if (buffer == 0)
{
/* return -1 if error. */
return -1;
}
/* This function only writes to "standard out" and "standard err" for all other file handles it returns failure. */
if ((handle != 1) && (handle != 2))
{
return -1;
}
/* Send data. */
LOG_Push((uint8_t *)buffer, size);
return 0;
}
int __attribute__((weak)) __sys_readc(void)
{
char tmp;
/* Receive data. */
LOG_ReadCharacter((uint8_t *)&tmp);
return tmp;
}
#endif
/* These function __write and __read is used to support ARM_GCC, KDS, Atollic toolchains to printf and scanf*/
#elif(defined(__GNUC__))
#if ((defined(__GNUC__) && (!defined(__MCUXPRESSO))) || \
(defined(__MCUXPRESSO) && (!SDK_DEBUGCONSOLE) && (defined(SDK_DEBUGCONSOLE_UART))))
int __attribute__((weak)) _write(int handle, char *buffer, int size)
{
if (buffer == 0)
{
/* return -1 if error. */
return -1;
}
/* This function only writes to "standard out" and "standard err" for all other file handles it returns failure. */
if ((handle != 1) && (handle != 2))
{
return -1;
}
/* Send data. */
LOG_Push((uint8_t *)buffer, size);
return size;
}
int __attribute__((weak)) _read(int handle, char *buffer, int size)
{
/* This function only reads from "standard in", for all other file handles it returns failure. */
if (handle != 0)
{
return -1;
}
/* Receive data. */
return LOG_ReadLine((uint8_t *)buffer, size);
}
#endif
/* These function fputc and fgetc is used to support KEIL toolchain to printf and scanf*/
#elif defined(__CC_ARM)
struct __FILE
{
int handle;
/*
* Whatever you require here. If the only file you are using is standard output using printf() for debugging,
* no file handling is required.
*/
};
/* FILE is typedef in stdio.h. */
#pragma weak __stdout
#pragma weak __stdin
FILE __stdout;
FILE __stdin;
#pragma weak fputc
int fputc(int ch, FILE *f)
{
/* Send data. */
return LOG_Push((uint8_t *)(&ch), 1);
}
#pragma weak fgetc
int fgetc(FILE *f)
{
char ch;
/* Receive data. */
LOG_ReadCharacter((uint8_t *)&ch);
return ch;
}
#endif /* __ICCARM__ */
#if defined(__riscv)
int isatty(int fd)
{
return 1;
}
int fstat(int fd, struct stat *st)
{
st->st_mode = S_IFCHR;
return 0;
}
int lseek(int fd, off_t ptr, int dir)
{
return 0;
}
int close(int fd)
{
return -1;
}
int read(int fd, void* ptr, size_t len)
{
/* This function only reads from "standard in", for all other file handles it returns failure. */
if (fd != 0)
{
return -1;
}
/* Receive data. */
return LOG_ReadLine((uint8_t *)ptr, len);
}
int write(int fd, const void* ptr, size_t len)
{
if (ptr == 0)
{
/* return -1 if error. */
return -1;
}
/* This function only writes to "standard out" and "standard err" for all other file handles it returns failure. */
if ((fd != 1) && (fd != 2))
{
return -1;
}
/* Send data. */
LOG_Push((uint8_t *)ptr, len);
return len;
}
#endif