port log.c log.h for fusee-primary

refactor printing
remove lib/printk as it is replaced with log
remove lib/driver_utils.h
added log levels as they seem right, might need adjustments
This commit is contained in:
Resaec 2018-09-26 02:18:50 +02:00
parent d67a7c0a87
commit 81355415d0
No known key found for this signature in database
GPG key ID: 5E890BD898EA9064
12 changed files with 212 additions and 135 deletions

View file

@ -17,9 +17,8 @@
#include <inttypes.h>
#include "exception_handlers.h"
#include "lib/driver_utils.h"
#include "utils.h"
#include "display/video_fb.h"
#include "lib/log.h"
#define CODE_DUMP_SIZE 0x30
#define STACK_DUMP_SIZE 0x60
@ -55,26 +54,28 @@ void exception_handler_main(uint32_t *registers, unsigned int exception_type) {
uint32_t instr_addr = pc + ((cpsr & 0x20) ? 2 : 4) - CODE_DUMP_SIZE;
printk("\nSomething went wrong...\n");
print(SCREEN_LOG_LEVEL_ERROR, "\nSomething went wrong...\n");
code_dump_size = safecpy(code_dump, (const void *)instr_addr, CODE_DUMP_SIZE);
stack_dump_size = safecpy(stack_dump, (const void *)registers[13], STACK_DUMP_SIZE);
printk("\nException type: %s\n", exception_names[exception_type]);
printk("\nRegisters:\n\n");
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nException type: %s\n",
exception_names[exception_type]);
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nRegisters:\n\n");
/* Print r0 to pc. */
for (int i = 0; i < 16; i += 2) {
printk("%-7s%08"PRIX32" %-7s%08"PRIX32"\n", register_names[i], registers[i], register_names[i+1], registers[i+1]);
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "%-7s%08"PRIX32" %-7s%08"PRIX32"\n",
register_names[i], registers[i], register_names[i+1], registers[i+1]);
}
/* Print cpsr. */
printk("%-7s%08"PRIX32"\n", register_names[16], registers[16]);
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "%-7s%08"PRIX32"\n", register_names[16], registers[16]);
printk("\nCode dump:\n");
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nCode dump:\n");
hexdump(code_dump, code_dump_size, instr_addr);
printk("\nStack dump:\n");
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nStack dump:\n");
hexdump(stack_dump, stack_dump_size, registers[13]);
printk("\n");
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\n");
fatal_error("An exception occured!\n");
}

View file

@ -13,11 +13,11 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "fs_utils.h"
#include "mc.h"
#include "lib/printk.h"
#include "lib/fatfs/ff.h"
#include "lib/log.h"
FATFS sd_fs;
static bool g_sd_mounted = false;
@ -44,7 +44,7 @@ bool mount_sd(void)
/* Mount SD. */
if (f_mount(&sd_fs, "", 1) == FR_OK) {
printk("Mounted SD card!\n");
print(SCREEN_LOG_LEVEL_INFO, "Mounted SD card!\n");
g_sd_mounted = true;
}
}

View file

@ -1,23 +0,0 @@
/*
* Copyright (c) 2018 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef FUSEE_DRIVER_UTILS_H
#define FUSEE_DRIVER_UTILS_H
#include "vsprintf.h"
#include "printk.h"
#endif

View file

@ -0,0 +1,120 @@
/*
* Copyright (c) 2018 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "log.h"
#include "../display/video_fb.h"
#include "vsprintf.h"
/* default log level for screen output */
ScreenLogLevel g_screen_log_level = SCREEN_LOG_LEVEL_MANDATORY;
void log_set_log_level(ScreenLogLevel log_level) {
g_screen_log_level = log_level;
}
void log_to_uart(const char *message) {
/* TODO: add UART logging */
}
void print_to_screen(ScreenLogLevel screen_log_level, char *message) {
/* don't print to screen if below log level */
if(screen_log_level > g_screen_log_level) return;
video_puts(message);
}
/**
* vprintk - logs a message and prints it to screen based on its screen_log_level
*
* If the level is below g_screen_log_level it will not be shown but logged to UART
* This text will not be colored or prefixed
* UART is TODO
*/
void vprint(ScreenLogLevel screen_log_level, const char *fmt, va_list args)
{
char buf[PRINT_MESSAGE_MAX_LENGTH];
vsnprintf(buf, PRINT_MESSAGE_MAX_LENGTH, fmt, args);
/* log to UART */
log_to_uart(buf);
print_to_screen(screen_log_level, buf);
}
void add_prefix(ScreenLogLevel screen_log_level, const char *fmt, char *buf) {
char typebuf[] = "[%s] %s";
/* apply prefix and append message format */
/* TODO: add coloring to the output */
switch(screen_log_level)
{
case SCREEN_LOG_LEVEL_ERROR:
snprintf(buf, PRINT_MESSAGE_MAX_LENGTH, typebuf, "ERROR", fmt);
break;
case SCREEN_LOG_LEVEL_WARNING:
snprintf(buf, PRINT_MESSAGE_MAX_LENGTH, typebuf, "WARNING", fmt);
break;
case SCREEN_LOG_LEVEL_MANDATORY:
snprintf(buf, PRINT_MESSAGE_MAX_LENGTH, "%s", fmt);
break;
case SCREEN_LOG_LEVEL_INFO:
snprintf(buf, PRINT_MESSAGE_MAX_LENGTH, typebuf, "INFO", fmt);
break;
case SCREEN_LOG_LEVEL_DEBUG:
snprintf(buf, PRINT_MESSAGE_MAX_LENGTH, typebuf, "DEBUG", fmt);
break;
default:
break;
}
}
/**
* print - logs a message and prints it to screen based on its screen_log_level
*
* If the level is below g_screen_log_level it will not be shown but logged to UART
* Use SCREEN_LOG_LEVEL_NO_PREFIX if you don't want a prefix to be added
* UART is TODO
*/
void print(ScreenLogLevel screen_log_level, const char * fmt, ...)
{
char buf[PRINT_MESSAGE_MAX_LENGTH] = {};
char message[PRINT_MESSAGE_MAX_LENGTH] = {};
/* TODO: make splash disappear if level > MANDATORY */
/* make prefix free messages with log_level possible */
if(screen_log_level & SCREEN_LOG_LEVEL_NO_PREFIX) {
/* remove the NO_PREFIX flag so the enum can be recognized later on */
screen_log_level &= ~SCREEN_LOG_LEVEL_NO_PREFIX;
snprintf(buf, PRINT_MESSAGE_MAX_LENGTH, "%s", fmt);
}
else {
add_prefix(screen_log_level, fmt, buf);
}
/* input arguments */
va_list args;
va_start(args, fmt);
vsnprintf(message, PRINT_MESSAGE_MAX_LENGTH, buf, args);
va_end(args);
/* log to UART */
log_to_uart(message);
print_to_screen(screen_log_level, message);
}

View file

@ -0,0 +1,43 @@
/*
* Copyright (c) 2018 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef FUSEE_PRIMARY_PRINT_H
#define FUSEE_PRIMARY_PRINT_H
#define PRINT_MESSAGE_MAX_LENGTH 512
#include <stdarg.h>
typedef enum {
SCREEN_LOG_LEVEL_NONE = 0,
SCREEN_LOG_LEVEL_ERROR = 1,
SCREEN_LOG_LEVEL_WARNING = 2,
SCREEN_LOG_LEVEL_MANDATORY = 3, /* no log prefix */
SCREEN_LOG_LEVEL_INFO = 4,
SCREEN_LOG_LEVEL_DEBUG = 5,
SCREEN_LOG_LEVEL_NO_PREFIX = 0x100 /* OR this to your LOG_LEVEL to prevent prefix creation */
} ScreenLogLevel;
/* TODO: make this configurable by BCT.ini */
extern ScreenLogLevel g_screen_log_level;
void log_set_log_level(ScreenLogLevel screen_log_level);
void log_to_uart(const char *message);
void vprint(ScreenLogLevel screen_log_level, const char *fmt, va_list args);
void print(ScreenLogLevel screen_log_level, const char* fmt, ...);
#endif

View file

@ -1,42 +0,0 @@
/*
* Copyright (c) 2018 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "printk.h"
#include "vsprintf.h"
#include "../display/video_fb.h"
/**
* Temporary stand-in main printk.
*
* TODO: This should print via UART, console framebuffer, and to a ring for
* consumption by Horizon
*/
void printk(const char *fmt, ...)
{
va_list list;
va_start(list, fmt);
vprintk(fmt, list);
va_end(list);
}
void vprintk(const char *fmt, va_list args)
{
char buf[512];
vsnprintf(buf, sizeof(buf), fmt, args);
video_puts(buf);
}

View file

@ -1,25 +0,0 @@
/*
* Copyright (c) 2018 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __PRINTK_H__
#define __PRINTK_H__
#include <stdarg.h>
void printk(const char *fmt, ...);
void vprintk(const char *fmt, va_list args);
#endif

View file

@ -25,7 +25,7 @@
#include "chainloader.h"
#include "sdmmc/sdmmc.h"
#include "lib/fatfs/ff.h"
#include "lib/printk.h"
#include "lib/log.h"
#include "display/video_fb.h"
extern void (*__program_exit_callback)(int rc);
@ -42,8 +42,8 @@ static char g_bct0_buffer[BCTO_MAX_SIZE];
static const char *load_config(void) {
if (!read_from_file(g_bct0_buffer, BCTO_MAX_SIZE, "BCT.ini")) {
printk("Failed to read BCT0 from SD!\n");
printk("[DEBUG] Using default BCT0!\n");
print(SCREEN_LOG_LEVEL_DEBUG, "Failed to read BCT0 from SD!\n");
print(SCREEN_LOG_LEVEL_DEBUG, "Using default BCT0!\n");
memcpy(g_bct0_buffer, DEFAULT_BCT0_FOR_DEBUG, sizeof(DEFAULT_BCT0_FOR_DEBUG));
/* TODO: Stop using default. */
/* printk("Error: Failed to load BCT.ini!\n");
@ -119,8 +119,8 @@ int main(void) {
setup_env();
/* Say hello. */
printk("Welcome to Atmosph\xe8re Fus\xe9" "e!\n");
printk("Using color linear framebuffer at 0x%p!\n", g_framebuffer);
print(SCREEN_LOG_LEVEL_MANDATORY, "Welcome to Atmosph\xe8re Fus\xe9" "e!\n");
print(SCREEN_LOG_LEVEL_DEBUG, "Using color linear framebuffer at 0x%p!\n", g_framebuffer);
/* Load the BCT0 configuration ini off of the SD. */
bct0 = load_config();

View file

@ -26,7 +26,6 @@
#include "mmc.h"
#include "sd.h"
#include "../timers.h"
#include "../lib/driver_utils.h"
#define UNSTUFF_BITS(resp,start,size) \
({ \

View file

@ -30,7 +30,7 @@
#include "../gpio.h"
#include "../pmc.h"
#include "../max7762x.h"
#include "../lib/driver_utils.h"
#include "../lib/log.h"
static SdmmcLogLevel g_sdmmc_log_level = SDMMC_LOG_NONE;
@ -43,26 +43,30 @@ static void sdmmc_print(sdmmc_t *sdmmc, SdmmcLogLevel log_level, char *fmt, va_l
{
if (log_level > g_sdmmc_log_level)
return;
char sdmmc_fmt[] = "%s: ";
ScreenLogLevel screen_log_level = SCREEN_LOG_LEVEL_ERROR;
switch (log_level) {
case SDMMC_LOG_ERROR:
printk("%s [ERROR]: ", sdmmc->name);
screen_log_level = SCREEN_LOG_LEVEL_ERROR;
break;
case SDMMC_LOG_WARN:
printk("%s [WARN]: ", sdmmc->name);
screen_log_level = SCREEN_LOG_LEVEL_WARNING;
break;
case SDMMC_LOG_INFO:
printk("%s [INFO]: ", sdmmc->name);
screen_log_level = SCREEN_LOG_LEVEL_DEBUG;
break;
case SDMMC_LOG_DEBUG:
printk("%s [DEBUG]: ", sdmmc->name);
screen_log_level = SCREEN_LOG_LEVEL_DEBUG;
break;
default:
break;
}
vprintk(fmt, list);
printk("\n");
print(screen_log_level, sdmmc_fmt, sdmmc->name);
vprint(screen_log_level, fmt, list);
print(screen_log_level | SCREEN_LOG_LEVEL_NO_PREFIX, "\n");
}
void sdmmc_error(sdmmc_t *sdmmc, char *fmt, ...)

View file

@ -21,7 +21,7 @@
#include "fs_utils.h"
#include "stage2.h"
#include "chainloader.h"
#include "lib/printk.h"
#include "lib/log.h"
#include "lib/vsprintf.h"
#include "lib/ini.h"
#include "lib/fatfs/ff.h"
@ -74,7 +74,7 @@ void load_stage2(const char *bct0) {
}
if (strlen(config.path) + 1 + sizeof(stage2_args_t) > CHAINLOADER_ARG_DATA_MAX_SIZE) {
printk("Error: Stage2's path name is too big!\n");
print(SCREEN_LOG_LEVEL_ERROR, "Stage2's path name is too big!\n");
}
if (!check_32bit_address_loadable(config.entrypoint)) {
@ -85,10 +85,10 @@ void load_stage2(const char *bct0) {
fatal_error("Stage2's load address is invalid!\n");
}
printk("[DEBUG] Stage 2 Config:\n");
printk(" File Path: %s\n", config.path);
printk(" Load Address: 0x%08x\n", config.load_address);
printk(" Entrypoint: 0x%p\n", config.entrypoint);
print(SCREEN_LOG_LEVEL_DEBUG, "Stage 2 Config:\n");
print(SCREEN_LOG_LEVEL_DEBUG | SCREEN_LOG_LEVEL_NO_PREFIX, " File Path: %s\n", config.path);
print(SCREEN_LOG_LEVEL_DEBUG | SCREEN_LOG_LEVEL_NO_PREFIX, " Load Address: 0x%08x\n", config.load_address);
print(SCREEN_LOG_LEVEL_DEBUG | SCREEN_LOG_LEVEL_NO_PREFIX, " Entrypoint: 0x%p\n", config.entrypoint);
if (f_stat(config.path, &info) != FR_OK) {
fatal_error("Failed to stat stage2 (%s)!\n", config.path);

View file

@ -25,7 +25,7 @@
#include "car.h"
#include "btn.h"
#include "lib/printk.h"
#include "lib/log.h"
#include <inttypes.h>
@ -84,11 +84,11 @@ __attribute__ ((noreturn)) void generic_panic(void) {
__attribute__((noreturn)) void fatal_error(const char *fmt, ...) {
va_list args;
printk("Fatal error: ");
print(SCREEN_LOG_LEVEL_ERROR, "Fatal error: ");
va_start(args, fmt);
vprintk(fmt, args);
vprint(SCREEN_LOG_LEVEL_ERROR, fmt, args);
va_end(args);
printk("\nPress POWER to reboot\n");
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX,"\nPress POWER to reboot\n");
wait_for_button_and_reboot();
}
@ -109,27 +109,27 @@ void hexdump(const void* data, size_t size, uintptr_t addrbase) {
for (size_t i = 0; i < size; i++) {
if (i % 16 == 0) {
printk("%0*" PRIXPTR ": | ", 2 * sizeof(addrbase), addrbase + i);
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "%0*" PRIXPTR ": | ", 2 * sizeof(addrbase), addrbase + i);
}
printk("%02X ", d[i]);
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "%02X ", d[i]);
if (d[i] >= ' ' && d[i] <= '~') {
ascii[i % 16] = d[i];
} else {
ascii[i % 16] = '.';
}
if ((i+1) % 8 == 0 || i+1 == size) {
printk(" ");
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, " ");
if ((i+1) % 16 == 0) {
printk("| %s \n", ascii);
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "| %s \n", ascii);
} else if (i+1 == size) {
ascii[(i+1) % 16] = '\0';
if ((i+1) % 16 <= 8) {
printk(" ");
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, " ");
}
for (size_t j = (i+1) % 16; j < 16; j++) {
printk(" ");
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, " ");
}
printk("| %s \n", ascii);
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "| %s \n", ascii);
}
}
}