1. xloader 中除了把log输出到串口外,还备份存放在 &__LOG_START --- &__LOG_END中
void puts(char *buf)
{
uart_register_t *pUartRegs = (uart_register_t *) UART1_REG_START_ADDR;
while (*buf)
{
while (IsTxfifoFull());
*logBuffer++ = *buf;
//备份到SRAM中
if (logBuffer >= &__LOG_END)
logBuffer = &__LOG_START;
//输出到串口
pUartRegs->DATA.Data = *buf++;
}
*logBuffer = 0;
}
logbuffer 的定义与初始化:
static char *logBuffer;
uart_error_t UART_Init(uart_baudrate_t baudrate, uart_parity_bit_t parity_bit,
uart_stop_bits_t stop_bits, uart_data_bits_t data_bits)
{
/* Variable to flush Rx fifo */
volatile uint32_t dataflushed;
uart_register_t *pUartRegs = (uart_register_t *) UART1_REG_START_ADDR;
gpio_register_t *pGpio0Regs = (gpio_register_t *) GPIO0_REG_START_ADDR;
//logBuffer在 UART_Init()中初始化
logBuffer = &__LOG_START;
memset(logBuffer, 0, &__LOG_END - logBuffer);
__LOG_START 和 __LOG_END 在default.dld 链接文件中定义:
/* The sizes of the stacks used by the application. NOTE: you need to adjust */
//LOG buffer的大小
LOG_SIZE = 2048;
GROUP : {
__LOG_START = .;
. += LOG_SIZE;
__LOG_END = .;
2. 内核中,把bootlog 通过/sys 接口导出来:
/*
* =============================================================================
* Cartesio Bootloader Log Access
* =============================================================================
*/
#ifdef CONFIG_SYSFS
static ssize_t bootlog_show(struct kobject *kobj, struct kobj_attribute *a, char *buf)
{
//锁定地址
const u32 __base = IO_ADDRESS(CARTESIO_ESRAM_BASE) + 0x3800;
u32 *b32 = (u32 *)buf;
int i;
//读2048个字节
for(i = 0; i < 2048; i += 4)
*b32++ = readl(__base + i);
return 2048;
}
//创建只读文件 bootlog
static struct kobj_attribute bootlog_attr = __ATTR_RO(bootlog);
static struct attribute *st_attrs[] = {
&bootlog_attr.attr,
NULL,
};
static struct attribute_group st_attr_group = {
.attrs = st_attrs,
//group 表示会建立出 stmicro 目录,里面会有 bootlog选项
.name = "stmicro",
};
#endif /* CONFIG_SYSFS */
这里通过 sys_create_group(kernel_kobj, &st_attr_group) 导出:
sys_create_group(kernel_kobj, ) 会在 /sys/kernel/ 下建立出stmicro 目录,stmicro 目录想会有一个bootlog文件,是只读的.
static int __init cartesio_core_late_init(void)
{
/*
* Register core-specific platform devices depending on board devices
*/
platform_add_devices(core_late_devices, ARRAY_SIZE(core_late_devices));
#ifdef CONFIG_SYSFS
sysfs_create_group(kernel_kobj, &st_attr_group);
#endif
return 0;
}
3. 用户空间读取bootlog:
int getlog()
{
char *log = harAPI_getLog();
printf("x-loader logs :\n");
while (*log)
{
printf("%s\n", log);
log += strlen(log) + 1;
}
return 0;
}
char *harAPI_getLog()
{
int fd;
char logbuf[LOG_BUF_SIZE];
char *buf;
FILE *log;
buf = logbuf;
//打开bootlog文件
log = fopen(BOOTLOG, "r");
if(!log){
printf("Open bootlog failed\n");
return 0;
}
//读取文件到buf, 大小为2048
if (fread(buf, LOG_BUF_SIZE, 1, log) != 1) {
puts("Read bootlog failed");
}
fclose(log);
return buf;
}
#define LOG_BUF_SIZE 2048
#define BOOTLOG "/sys/kernel/stmicro/bootlog"
这样就实现了bootloader log 从用户空间读取出来的功能。