GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)

This commit is contained in:
lai
2026-09-06 03:52:57 +08:00
commit b1928b41c0
21813 changed files with 4413081 additions and 0 deletions
+166
View File
@@ -0,0 +1,166 @@
CROSS_COMPILE ?= riscv64-unknown-elf-
O ?= $(shell pwd)/out
ARCH ?= riscv
CONFIG_INC := $(O)/include/autoconf.h
CONFIG_MAKE := $(O)/.makefile
CONFIG_FILE := $(O)/.config
export CONFIG_FILE CONFIG_INC
sinclude $(CONFIG_FILE)
TOPDIR := $(shell pwd)
export TOPDIR
CC := $(CROSS_COMPILE)gcc
AR := $(CROSS_COMPILE)ar
LD := $(CROSS_COMPILE)ld
OBJCOPY := $(CROSS_COMPILE)objcopy
SIZE := $(CROSS_COMPILE)size
STRIP := $(CROSS_COMPILE)strip
OBJDUMP := $(CROSS_COMPILE)objdump
RM := $(shell if [ -x "/bin/rm" ]; then echo /bin/rm; else type -P rm; fi)
LS := $(shell if [ -x "/bin/ls" ]; then echo /bin/ls; else type -P ls; fi)
MCU := mcu
RM := $(RM) -f
export CC AR LD OBJCOPY RM TOPDIR MCU SIZE STRIP LS
include $(TOPDIR)/scripts/Makefile.define
V ?= 0
ifeq ($(V),1)
Q :=
QUIET :=
else
Q := @
QUIET := -s
endif
MKFLAGS := $(QUIET) -f $(TOPDIR)/scripts/Makefile.build
CLFLAGS := $(QUIET) -f $(TOPDIR)/scripts/Makefile.clean
export MKFLAGS CLFLAGS Q QUIET
MKDEP := .mkdep
export MKDEP
ARFLAGS += rcs
LDFLAGS +=
CFLAGS += -fno-builtin -fno-common -ffreestanding -nostdinc \
-I$(shell pwd)/include -I$(O)/include -I$(TOPDIR) -pipe -g -gdwarf-4 -Wall -Werror \
-DCONFIG_$(strip $(call upper, $(ARCH)))_ARCH
GC_ENABLE ?= y
CFLAGS += $(if $(GC_ENABLE),-fdata-sections -ffunction-sections)
CFLAGS += $(shell echo $(CONFIG_CFLAGS))
LDFLAGS += $(shell echo $(CONFIG_LDFLAGS))
ARCH_DIR := $(ARCH)/
CFLAGS += -I$(TOPDIR)/$(ARCH_DIR)include
ASFLAGS += $(CFLAGS) -D__ASSEMBLY__
export ARFLAGS LDFLAGS CFLAGS ASFLAGS
LIB_DIRS := init/ libs/ drivers/ common/
ifdef CONFIG_MEDIA_SUPPORT
MEDIA = $(if $(wildcard $(TOPDIR)/media/Makefile),y,)
endif
LIB_DIRS-stage2 += $(call is_enabled, MEDIA,media/,)
CFLAGS += $(call is_enabled, MEDIA,-I$(TOPDIR)/media/include,)
ifeq ($(strip $(CONFIG_UT_ENABLE)),y)
LIB_DIRS-stage2 += test/
endif
LIBS := $(foreach LIB,$(LIB_DIRS),$(LIB)lib$(LIB:/=).a)
LIBS-stage2 := $(foreach LIB,$(LIB_DIRS-stage2),$(LIB)lib$(LIB:/=).a)
################################################################################
sinclude $(CONFIG_MAKE)
PHONYS += help
help:
@echo "Usage: make [config]"
@echo " make clean"
@echo " make distclean"
@echo " make help"
@echo " make"
@echo " support configs:"
@for ix in $(notdir $(wildcard $(TOPDIR)/configs/*)); do ( \
echo " $${ix}"; \
) done
@echo;
PHONYS += $(MCU).bin
$(MCU).bin: $(MCU).elf
$(call show_cmd,OBJCOPY,$@)
$(Q)$(OBJCOPY) -R .comment --gap-fill=0xff -O binary $(O)/$< $(O)/$@
$(call show_cmd,MCU,$@)
$(Q)$(OBJDUMP) -D $(O)/$(MCU).elf > $(O)/mcu.asm
@echo "Config File: $(CONFIG_PLATFORM)_defconfig"
@echo "Entry Point: $(CONFIG_TEXT_BASE)"
@MSG=$$(cd $(O); $(LS) -gG --time-style=long-iso $@); \
echo "Image Size: $$(echo $${MSG} | awk '{print $$3}') Bytes"; \
echo "Create: $$(echo $${MSG} | awk '{print $$4" "$$5}')"
@echo "Output Path: $(O)"
@echo " Image $(@) is ready"
PHONYS += $(MCU).bin
$(MCU).elf: $(LIBS) $(LIBS-stage2)
$(Q)$(MAKE) $(MKFLAGS) SRCDIR="$(ARCH_DIR)" LIBS="$(LIBS)" LIBS-stage2="$(LIBS-stage2)" O="$(O)/" $(@)
PHONYS += $(LIBS) $(LIBS-stage2)
$(LIBS): $(O)/$(MKDEP) force
@touch init/main.c
$(Q)$(MAKE) $(MKFLAGS) -C $(TOPDIR)/$(@D)/ SRCDIR="$(@D)/" O="$(O)/" $(@F)
$(LIBS-stage2): $(O)/$(MKDEP) force
$(Q)$(MAKE) $(MKFLAGS) -C $(TOPDIR)/$(@D)/ SRCDIR="$(@D)/" O="$(O)/" $(@F)
%: $(TOPDIR)/configs/%
$(call show_cmd,GEN,$(notdir $(CONFIG_MAKE)))
$(call checkdir,$(dir $(CONFIG_MAKE)))
$(Q)(echo "# auto produce, don't modify this ") > $(CONFIG_MAKE)
$(Q)(echo "all: $(MCU).bin";) >> $(CONFIG_MAKE)
$(call show_cmd,GEN,$(notdir $(CONFIG_FILE)))
$(call checkdir,$(dir $(CONFIG_FILE)))
$(Q)cp "$<" "$(CONFIG_FILE)"
$(call show_cmd,GEN,$(notdir $(CONFIG_INC)))
$(call checkdir,$(dir $(CONFIG_INC)))
$(Q)(echo "/* auto produce, don't modify this */") > $(CONFIG_INC)
$(Q)set -e; cat $(CONFIG_FILE) | sed -n -f $(TOPDIR)/scripts/env2inc.sed >> $(CONFIG_INC)
force:;
$(O)/$(MKDEP): $(TOPDIR)/Makefile
@touch $@
PHONYS += clean
clean: $(addsuffix .clean,$(LIBS) $(ARCH_DIR))
$(Q)$(RM) -f $(O)/{$(MCU).bin,$(MCU).elf,$(MCU).map,$(MKDEP)}
$(addsuffix .clean,$(LIBS) $(ARCH_DIR)):
$(call show_cmd,ENTRY,$(TOPDIR)/$(@D))
$(Q)$(MAKE) $(CLFLAGS) SRCDIR="$(@D)/" O="$(O)/" clean
PHONYS += distclean
distclean:
$(Q)$(RM) -rf $(O)
$(Q)$(RM) -rf cscope.files cscope.in.out cscope.out cscope.po.out tags
PHONYS += cscope
cscope:
$(Q)find -name "*.S" -o -name "*.c" -o -name "*.h" -o -name "*.s" >cscope.files
$(Q)cscope -bkq -i ./cscope.files
$(Q)ctags -R
################################################################################
.PHONY: $(PHONYS)
################################################################################
+10
View File
@@ -0,0 +1,10 @@
CFLAGS_start += -DTEXT_BASE=$(CONFIG_TEXT_BASE)
CFLAGS_start += -DSTACK_TOP=$(CONFIG_STACK_TOP)
CFLAGS += -DSTACK_TOP=$(CONFIG_STACK_TOP)
ASFLAGS += -DSTACK_TOP=$(CONFIG_STACK_TOP)
LINKLDS := firmware.lds
START = start.S
TAIL = tail.S
SRCS-y += chip.c
+4
View File
@@ -0,0 +1,4 @@
void reset_cpu(void)
{
}
+45
View File
@@ -0,0 +1,45 @@
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
#include <config.h>
ENTRY(_start)
SECTIONS
{
. = CONFIG_TEXT_BASE;
. = ALIGN(4);
.text : {
. = ALIGN(4);
__text_start = .;
start.o (.text)
*(.text)
__text_end = .;
}
. = ALIGN(4);
.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
. = ALIGN(4);
.data : {
__data_start = .;
*(.data)
__data_end = .;
}
.tail : {
tail.o(.tail)
}
. = ALIGN(4);
.bss : {
__bss_start = .;
*(.bss)
__bss_end = .;
ASSERT(((__bss_end - __bss_start) == 0), "All global and static
variables MUST be initialized with non-zero value!");
}
_end = .;
}
+15
View File
@@ -0,0 +1,15 @@
#ifndef __BARRIERS_H__
#define __BARRIERS_H__
#ifndef __ASSEMBLY__
#define ISB asm volatile ("isb sy" : : : "memory")
#define DSB asm volatile ("dsb sy" : : : "memory")
#define DMB asm volatile ("dmb sy" : : : "memory")
#define isb() ISB
#define dsb() DSB
#define dmb() DMB
#endif /* __ASSEMBLY__ */
#endif /* __BARRIERS_H__ */
+24
View File
@@ -0,0 +1,24 @@
#ifndef __ASM_ARM_IO_H
#define __ASM_ARM_IO_H
#include <sys/types.h>
#include <barriers.h>
#define __arch_getl(a) (*(volatile unsigned int *)(a))
#define __arch_putl(v,a) (*(volatile unsigned int *)(a) = (v))
#define mb() dsb()
#define __iormb() dmb()
#define __iowmb() dmb()
#ifdef REG_IORW_DEBUG
#include <serial.h>
#define writel(v,c) ({ u32 __v = v; __iowmb(); serial_puts("REG W: 0x"); serial_put_hex(c); serial_puts(", 0x"); serial_put_hex(__v); serial_puts("\n"); __arch_putl(__v,c); __v; })
#define readl(c) ({ u32 __v; serial_puts("REG R: 0x"); serial_put_hex(c); __v = __arch_getl(c); __iormb(); serial_puts(", 0x"); serial_put_hex(__v); serial_puts("\n"); __v; })
#else
#define writel(v,c) ({ u32 __v = v; __iowmb(); __arch_putl(__v,c); __v; })
#define readl(c) ({ u32 __v = __arch_getl(c); __iormb(); __v; })
#endif
#endif /* __ASM_ARM_IO_H */
+113
View File
@@ -0,0 +1,113 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#ifndef __CHIP_REGS_H__
#define __CHIP_REGS_H__
#define BIT(nr) (1 << (nr))
#define RAM_START_ADRS 0x04010500
#define STACK_TRAINING 0x04018000
#define DDR_DDRT_REG_BASE 0x11330000
#define TIMER0_REG_BASE 0x12000000
#define TIMER1_REG_BASE 0x12000020
#define TIMER2_REG_BASE 0x12001000
#define TIMER3_REG_BASE 0x12001020
#define REG_TIMER_RELOAD 0x0
#define REG_TIMER_VALUE 0x4
#define REG_TIMER_CONTROL 0x8
#define CRG_REG_BASE 0x12010000
#define SYS_CTRL_REG_BASE 0x12020000
#define REG_BASE_SCTL SYS_CTRL_REG_BASE
#define REG_SC_CTRL 0
#define REMAPCLEAR BIT(8)
#define REMAPCLEAR_SHIFT 8
#define TIME0_CLK_SEL BIT(16)
#define TIME0_CLK_SEL_SHIFT 16
#define TIME0_CLK_SEL_3M 0x0
#define TIME0_CLK_SEL_APB 0x1
#define REG_SC_SYSRES 0x8
#define REG_SYSSTAT 0x008C
#define REG_OTP_PO_BIT2 0x88
/* Generic register */
#define REG_SC_DDRT0 0x90
#define REG_SC_DDRT1 0x94
#define REG_SC_DDRT2 0x98
#define REG_SC_DDRT3 0x9c
#define REG_SC_DDRT4 0xa0
#define REG_SC_DDRT5 0xa4
#define REG_SC_DDRT6 0xa8
#define REG_SC_DDRT7 0xac
#define REG_SC_DDRT8 0xb0
#define REG_SC_DDRT9 0xb4
#define REG_SC_DDRT10 0xb8
#define REG_SC_DDRT11 0xbc
#define REG_SC_DDRT12 0xc0
#define REG_SC_DDRT13 0xc4
#define REG_SC_DDRT14 0xc8
#define REG_SC_DDRT15 0xcc
#define REG_SC_SYSBOOT0 0x130
#define REG_SC_SYSBOOT1 0x134
#define REG_SC_SYSBOOT2 0x138
#define REG_SC_SYSBOOT3 0x13c
#define REG_SC_SYSBOOT4 0x140
#define REG_SC_SYSBOOT5 0x144
#define REG_SC_SYSBOOT6 0x148
#define REG_SC_SYSBOOT7 0x14c
#define REG_SC_SYSBOOT8 0x150
#define REG_SC_SYSBOOT9 0x154
#define REG_SC_SYSBOOT10 0x158
#define REG_SC_SYSBOOT11 0x15c
#define REG_SC_SYSBOOT12 0x160
#define REG_SC_SYSBOOT13 0x164
#define REG_SC_SYSBOOT14 0x168
#define REG_SC_SYSBOOT15 0x16c
#define DDRCA_UPDATE (SYS_CTRL_REG_BASE + 0x8034)
#define DDRCA_RANDOM0 (SYS_CTRL_REG_BASE + 0x8600)
#define DDRCA_RANDOM1 (SYS_CTRL_REG_BASE + 0x8604)
#define DDRCA_RANDOM2 (SYS_CTRL_REG_BASE + 0x8608)
#define DDRCA_RANDOM3 (SYS_CTRL_REG_BASE + 0x860c)
#define MISC_REG_BASE 0x12028000
#define DDRC0_REG_BASE 0x11330000
#define UART0_REG_BASE 0x12040000
#define FMC_MEM_BASE 0x14000000
#define DDR_MEM_BASE 0x40000000
#define TIMER0_BASE 0x12000000
#define SERIAL_BASE UART0_REG_BASE
#define UART_PL01x_DR 0x00
#define UART_PL01x_RSR 0x04
#define UART_PL01x_ECR 0x04
#define UART_PL01x_FR 0x18
#define UART_PL01x_FR_TXFE 0x80
#define UART_PL01x_FR_RXFF 0x40
#define UART_PL01x_FR_TXFF 0x20
#define UART_PL01x_FR_RXFE 0x10
#define UART_PL01x_FR_BUSY 0x08
#define UART_PL01x_FR_TMSK (UART_PL01x_FR_TXFF + UART_PL01x_FR_BUSY)
#define START_MAGIC 0x444f574e
#define SUCCESS 0
#define FAILURE -1
#define REG_OTP_PO_BIT0 0x12020080
/* i2c0 reg */
#define REG_I2C_BASE (0x12060000)
/* clk reg control */
#define CRG_I2C (CRG_REG_BASE + 0x1B8)
#define I2C_CKEN BIT(16)
#define I2C_SRST BIT(24)
#endif
+19
View File
@@ -0,0 +1,19 @@
#include <platform.h>
.arm
.globl _start
_start:
push {r4-r11, lr}
bl main
pop {r4-r11, pc}
nop
nop
nop
nop
nop
nop
nop
nop
b . /* bug here */
+6
View File
@@ -0,0 +1,6 @@
#include <platform.h>
.section .tail,#alloc
.fill 0x200,1,0
+1
View File
@@ -0,0 +1 @@
SRCS-y += common.c
+46
View File
@@ -0,0 +1,46 @@
#include <stddef.h>
#include <common.h>
#include <time.h>
void wait_stage2_ready(void)
{
int c = 0;
while (readl(REG_SC_SYSBOOT7) != 0xbeef0001) {
udelay(1);
if (c > 0 && (c % (1000 * 1000 * 2)) == 0) {
puts("Waiting firmware ready!\n");
}
c++;
}
}
int run_stage2_func(int (*func)(void))
{
int ret;
__DSB();
__ISB();
puts("Check firmware...\n");
wait_stage2_ready();
rv32_dcache_disable();
rv32_icache_disable();
if (readl((ulong *)__bin_end_pad) != CONFIG_BIN_END_PAD) {
puts("Firmware ERROR!\n");
return -1;
}
rv32_icache_enable();
rv32_dcache_enable();
puts("Run 0x");puthex((u32)func);puts("\n");
ret = func();
return ret;
}
+30
View File
@@ -0,0 +1,30 @@
CONFIG_PLATFORM = xmfalcon
CONFIG_PLATFORM_XMFALCON = y
CONFIG_CFLAGS = "-march=rv32imafc -mabi=ilp32f -mtune=e906 -Wall -Os"
CONFIG_LDFLAGS = "--oformat=elf32-littleriscv -lm -L$(shell $(CC) -print-sysroot)/lib/rv32imafc/ilp32f/ -lgcc -L$(dir $(shell $(CC) $(CFLAGS) -print-libgcc-file-name))"
CONFIG_PRINT = y
#CONFIG_PRINTF = y
#CONFIG_SERIAL_DISABLE = y
#CONFIG_DEBUG_INFO = y
CONFIG_MALLOC = y
CONFIG_MCU_FW_MAGIC = 0x57465652
CONFIG_MCU_FW_VERSION = 1
CONFIG_MCU_SRAM_SIZE = 256*1024
CONFIG_MCU_HEAD_SIZE = 64
CONFIG_TEXT_BASE = 0x4020000
CONFIG_STAGE2_START = 0x4028000
CONFIG_STACK_SIZE = 8192
CONFIG_PARAM_MEM_SIZE = 4096
CONFIG_RESERVED_MEM_SIZE = (1 * 1024 * 1024)
CONFIG_FPGA = y
CONFIG_I2C = y
CONFIG_BIN_END_PAD = 0xdeadbeef
CONFIG_PWM = y
#CONFIG_SIMPILE_SHELL = y
##CONFIG_UT_ENABLE = y
#CONFIG_XTHEAD_ISA_EXT = y
CONFIG_MEDIA_SUPPORT = y
CONFIG_MEDIA_PIPE_NUM = 1
#CONFIG_MEDIA_SAMPLE_AOV = y
#CONFIG_MEDIA_SAMPLE_QUICKSTART = y
+30
View File
@@ -0,0 +1,30 @@
CONFIG_PLATFORM = xmorca
CONFIG_PLATFORM_XMORCA = y
CONFIG_CFLAGS = "-march=rv32imafc -mabi=ilp32f -mtune=e906 -Wall -Os"
CONFIG_LDFLAGS = "--oformat=elf32-littleriscv -lm -L$(shell $(CC) -print-sysroot)/lib/rv32imafc/ilp32f/ -lgcc -L$(dir $(shell $(CC) $(CFLAGS) -print-libgcc-file-name))"
CONFIG_PRINT = y
#CONFIG_PRINTF = y
#CONFIG_SERIAL_DISABLE = y
#CONFIG_DEBUG_INFO = y
CONFIG_MALLOC = y
CONFIG_MCU_FW_MAGIC = 0x57465652
CONFIG_MCU_FW_VERSION = 1
CONFIG_MCU_SRAM_SIZE = 208*1024
CONFIG_MCU_HEAD_SIZE = 64
CONFIG_TEXT_BASE = 0x401C000
CONFIG_STAGE2_START = 0x4028000
CONFIG_STACK_SIZE = 8192
CONFIG_PARAM_MEM_SIZE = 4096
CONFIG_RESERVED_MEM_SIZE = (1 * 1024 * 1024)
#CONFIG_FPGA = y
CONFIG_I2C = y
CONFIG_BIN_END_PAD = 0xdeadbeef
CONFIG_PWM = y
#CONFIG_SIMPILE_SHELL = y
##CONFIG_UT_ENABLE = y
#CONFIG_XTHEAD_ISA_EXT = y
CONFIG_MEDIA_SUPPORT = y
#CONFIG_STOPWATCH_SUPPORT = y
CONFIG_MEDIA_PIPE_NUM = 1
#CONFIG_MEDIA_SAMPLE_QUICKSTART = y
+7
View File
@@ -0,0 +1,7 @@
SRCS-y += timer/
SRCS-y += serial/
SRCS-y += gpio/
SRCS-y += stopwatch/
SRCS-$(CONFIG_I2C) += i2c/
SRCS-$(CONFIG_PWM) += pwm/
+1
View File
@@ -0,0 +1 @@
SRCS-y += gpio.c
+26
View File
@@ -0,0 +1,26 @@
/* #define REG_IORW_DEBUG */
#include <io.h>
#include <platform.h>
unsigned long get_gpio_base(int group)
{
return GPIO0_BASE + (group << 12);
}
void gpio_set_dir(int group, int bit, int dir)
{
unsigned long base = get_gpio_base(group);
unsigned int v = readl(base + GPIO_DIR);
v &= ~(1 << bit);
v |= dir << bit;
writel(v, base + GPIO_DIR);
}
void gpio_set_data(int group, int bit, int data)
{
unsigned long base = get_gpio_base(group);
unsigned long data_addr = (base + (1 << (bit + 2)));
writel(data << bit, data_addr);
}
+1
View File
@@ -0,0 +1 @@
SRCS-y += i2c.c
+600
View File
@@ -0,0 +1,600 @@
#include <io.h>
#include <timer.h>
#include "i2c.h"
struct platform_i2c {
unsigned int msg_buf_ptr;
int status;
#define I2C_WAIT_RESPOND (1 << 0)
};
struct i2c_platform_data {
unsigned int freq;
unsigned int clk;
};
struct i2c_msg {
unsigned short addr; /* slave address */
unsigned short flags;
#define I2C_M_TEN 0x0010
#define I2C_M_RD 0x0001
#define I2C_M_STOP 0x8000
#define I2C_M_NOSTART 0x4000
#define I2C_M_REV_DIR_ADDR 0x2000
#define I2C_M_IGNORE_NAK 0x1000
#define I2C_M_NO_RD_ACK 0x0800
#define I2C_M_RECV_LEN 0x0400
#define I2C_M_16BIT_DATA 0x0008
#define I2C_M_16BIT_REG 0x0002
unsigned short len; /* msg length */
unsigned char *buf; /* pointer to msg data */
};
struct i2c_driver_data {
unsigned int reg_base;
unsigned int freq;
unsigned int irq;
unsigned int clk;
struct i2c_msg *msgs;
unsigned int msg_num;
unsigned int msg_idx;
unsigned int lock;
void *private;
};
#ifdef CONFIG_LOTUS_FPGA
#define CLK_LIMIT_DEFAULT 40000
#else
#define CLK_LIMIT_DEFAULT 400000
#endif
#define write_reg_bit(value, offset, addr) ({ \
unsigned long t, mask; \
mask = 1 << (offset); \
t = readl(addr); \
t &= ~mask; \
t |= (value << (offset)) & mask; \
writel(t, addr); \
})
#define I2C_WAIT_TIMEOUT (100 * 3)
#define I2C_TIMEOUT_COUNT 0x10000
#define I2C_BUF_SIZE 8
#define I2C_INTERRUPT_NUM 0
#if defined(CONFIG_PLATFORM_XMFALCON) || defined(CONFIG_PLATFORM_XMORCA)
#ifdef CONFIG_LOTUS_FPGA
#define get_bus_clk() 25000000
#else
#define get_bus_clk() 50000000
#endif
#define get_host_clock(i2c_num) ({ get_bus_clk(); })
static struct platform_i2c g_i2c_platform_data[I2C_NUM] = {0};
static int g_i2c_host_cfg[I2C_NUM] = {0, 1, 2, 3, 4, 5, 6, 7}; /* i2c index */
static struct i2c_driver_data g_i2c_data[I2C_NUM] = {
{I2C0_REG_BASE, CLK_LIMIT_DEFAULT, I2C_INTERRUPT_NUM},
{I2C1_REG_BASE, CLK_LIMIT_DEFAULT, I2C_INTERRUPT_NUM},
{I2C2_REG_BASE, CLK_LIMIT_DEFAULT, I2C_INTERRUPT_NUM},
{I2C3_REG_BASE, CLK_LIMIT_DEFAULT, I2C_INTERRUPT_NUM},
{I2C4_REG_BASE, CLK_LIMIT_DEFAULT, I2C_INTERRUPT_NUM},
{I2C5_REG_BASE, CLK_LIMIT_DEFAULT, I2C_INTERRUPT_NUM},
{I2C6_REG_BASE, CLK_LIMIT_DEFAULT, I2C_INTERRUPT_NUM},
{I2C7_REG_BASE, CLK_LIMIT_DEFAULT, I2C_INTERRUPT_NUM},
};
#elif defined(CONFIG_TARGET_XM720XXX)
#define get_bus_clk() 50000000
#define get_host_clock(i2c_num) ({ get_bus_clk(); })
static struct platform_i2c g_i2c_platform_data[I2C_NUM] = {0};
static int g_i2c_host_cfg[I2C_NUM] = {0, 1, 2}; /* 0,1,2: i2c index */
static struct i2c_driver_data g_i2c_data[I2C_NUM] = {
{I2C0_REG_BASE, CLK_LIMIT_DEFAULT, I2C_INTERRUPT_NUM},
{I2C1_REG_BASE, CLK_LIMIT_DEFAULT, I2C_INTERRUPT_NUM},
{I2C2_REG_BASE, CLK_LIMIT_DEFAULT, I2C_INTERRUPT_NUM},
};
#endif
static void i2c_disable(const struct i2c_driver_data *i2c);
static void i2c_cfg_irq(const struct i2c_driver_data *i2c, unsigned int flag);
static unsigned int i2c_clr_irq(const struct i2c_driver_data *i2c);
static void i2c_rescue(const struct i2c_driver_data *i2c)
{
i2c_disable(i2c);
i2c_cfg_irq(i2c, 0);
i2c_clr_irq(i2c);
unsigned int val = (0x1 << GPIO_MODE_SHIFT) | (0x1 << FORCE_SCL_OEN_SHIFT) |
(0x1 << FORCE_SDA_OEN_SHIFT);
writel(val, i2c->reg_base + I2C_CTRL2);
unsigned int time_cnt = 0;
do {
for (int index = 0; index < 9; index++) { /* shift:9 */
val = (0x1 << GPIO_MODE_SHIFT) | 0x1;
writel(val, i2c->reg_base + I2C_CTRL2);
udelay(5); /* delay: 5 us */
val = (0x1 << GPIO_MODE_SHIFT) |
(0x1 << FORCE_SCL_OEN_SHIFT) |
(0x1 << FORCE_SDA_OEN_SHIFT);
writel(val, i2c->reg_base + I2C_CTRL2);
udelay(5); /* delay: 5 us */
}
time_cnt++;
if (time_cnt > I2C_WAIT_TIMEOUT) {
goto disable_rescue;
}
val = readl(i2c->reg_base + I2C_CTRL2);
} while (!(val & (0x1 << CHECK_SDA_IN_SHIFT)));
val = (0x1 << GPIO_MODE_SHIFT) | (0x1 << FORCE_SCL_OEN_SHIFT) |
(0x1 << FORCE_SDA_OEN_SHIFT);
writel(val, i2c->reg_base + I2C_CTRL2);
val = (0x1 << GPIO_MODE_SHIFT) | (0x1 << FORCE_SCL_OEN_SHIFT);
writel(val, i2c->reg_base + I2C_CTRL2);
udelay(10); /* delay: 10 us */
val = (0x1 << GPIO_MODE_SHIFT) | (0x1 << FORCE_SCL_OEN_SHIFT) |
(0x1 << FORCE_SDA_OEN_SHIFT);
writel(val, i2c->reg_base + I2C_CTRL2);
disable_rescue:
val = (0x1 << FORCE_SCL_OEN_SHIFT) | 0x1;
writel(val, i2c->reg_base + I2C_CTRL2);
}
static void i2c_disable(const struct i2c_driver_data *i2c)
{
unsigned int val = readl(i2c->reg_base + I2C_GLB);
val &= ~GLB_EN_MASK;
writel(val, i2c->reg_base + I2C_GLB);
}
static void i2c_disable_irq(const struct i2c_driver_data *i2c, unsigned int flag)
{
unsigned int val = readl(i2c->reg_base + I2C_INTR_EN);
val &= ~flag;
writel(val, i2c->reg_base + I2C_INTR_EN);
}
static unsigned int i2c_clr_irq(const struct i2c_driver_data *i2c)
{
unsigned int val = readl(i2c->reg_base + I2C_INTR_STAT);
writel(INTR_ALL_MASK, i2c->reg_base + I2C_INTR_RAW);
return val;
}
static void i2c_set_freq(struct i2c_driver_data *i2c)
{
unsigned int val;
unsigned int freq = i2c->freq;
unsigned int clk_rate = i2c->clk;
unsigned int max_freq = clk_rate >> 1;
if (freq > max_freq) {
i2c->freq = max_freq;
freq = i2c->freq;
}
if (freq <= 100000) { /* 100000:100KHz */
val = clk_rate / (freq * 2); /* 1/2:0.5 */
writel(val, i2c->reg_base + I2C_SCL_H);
writel(val, i2c->reg_base + I2C_SCL_L);
} else {
val = (clk_rate * 36) / (freq * 100); /* 36/100:0.36 */
writel(val, i2c->reg_base + I2C_SCL_H);
val = (clk_rate * 64) / (freq * 100); /* 64/100:0.64 */
writel(val, i2c->reg_base + I2C_SCL_L);
}
val = readl(i2c->reg_base + I2C_GLB);
val &= ~GLB_SDA_HOLD_MASK;
val |= ((0xa << GLB_SDA_HOLD_SHIFT) & GLB_SDA_HOLD_MASK);
writel(val, i2c->reg_base + I2C_GLB);
}
/*
* set i2c controller TX and RX FIFO water
*/
static void i2c_set_water(const struct i2c_driver_data *i2c)
{
writel(I2C_TXF_WATER, i2c->reg_base + I2C_TX_WATER);
writel(I2C_RXF_WATER, i2c->reg_base + I2C_RX_WATER);
}
static void i2c_enable_clk(unsigned char i2c_num)
{
const unsigned int clk_start_bit = 16 + i2c_num; /* 16: i2c clk start bit */
const unsigned int rst_start_bit = 24 + i2c_num; /* 24: i2c rst start bit */
const unsigned int enable_clck = 1;
const unsigned int enable_rst = 0;
write_reg_bit(enable_clck, clk_start_bit, (uintptr_t)I2C_CRG_REG_BASE);
write_reg_bit(enable_rst, rst_start_bit, (uintptr_t)I2C_CRG_REG_BASE);
}
/*
* initialise the controller, set i2c bus interface freq
*/
static void i2c_init_cfg(const struct i2c_driver_data *i2c, unsigned char i2c_num)
{
i2c_enable_clk(i2c_num);
i2c_disable(i2c);
i2c_disable_irq(i2c, INTR_ALL_MASK);
i2c_set_freq((struct i2c_driver_data *)i2c);
i2c_set_water(i2c);
}
static void i2c_cmdreg_set(const struct i2c_driver_data *i2c, unsigned int cmd,
unsigned int *offset)
{
writel(cmd, i2c->reg_base + I2C_CMD_BASE + (*offset) * 4); /* 4: bytes */
(*offset)++;
}
static void i2c_cfg_cmd(const struct i2c_driver_data *i2c)
{
struct i2c_msg *msg = i2c->msgs;
unsigned int offset = 0;
if (i2c->msg_idx == 0)
i2c_cmdreg_set(i2c, CMD_TX_S, &offset);
else
i2c_cmdreg_set(i2c, CMD_TX_RS, &offset);
if (msg->flags & I2C_M_TEN) {
if (i2c->msg_idx == 0) {
i2c_cmdreg_set(i2c, CMD_TX_D1_2, &offset);
i2c_cmdreg_set(i2c, CMD_RX_ACK, &offset);
i2c_cmdreg_set(i2c, CMD_TX_D1_1, &offset);
} else {
i2c_cmdreg_set(i2c, CMD_TX_D1_2, &offset);
}
} else {
i2c_cmdreg_set(i2c, CMD_TX_D1_1, &offset);
}
if (msg->flags & I2C_M_IGNORE_NAK)
i2c_cmdreg_set(i2c, CMD_IGN_ACK, &offset);
else
i2c_cmdreg_set(i2c, CMD_RX_ACK, &offset);
if (msg->flags & I2C_M_RD) {
if (msg->len >= 2) { /* msg len:2 */
writel(offset, i2c->reg_base + I2C_DST1);
writel(msg->len - 2, i2c->reg_base + I2C_LOOP1); /* 2: max len */
i2c_cmdreg_set(i2c, CMD_RX_FIFO, &offset);
i2c_cmdreg_set(i2c, CMD_TX_ACK, &offset);
i2c_cmdreg_set(i2c, CMD_JMP1, &offset);
}
i2c_cmdreg_set(i2c, CMD_RX_FIFO, &offset);
i2c_cmdreg_set(i2c, CMD_TX_NACK, &offset);
} else {
writel(offset, i2c->reg_base + I2C_DST1);
writel(msg->len - 1, i2c->reg_base + I2C_LOOP1);
i2c_cmdreg_set(i2c, CMD_UP_TXF, &offset);
i2c_cmdreg_set(i2c, CMD_TX_FIFO, &offset);
if (msg->flags & I2C_M_IGNORE_NAK) {
i2c_cmdreg_set(i2c, CMD_IGN_ACK, &offset);
}
else {
i2c_cmdreg_set(i2c, CMD_RX_ACK, &offset);
}
i2c_cmdreg_set(i2c, CMD_JMP1, &offset);
}
if ((i2c->msg_idx == (i2c->msg_num - 1)) || (msg->flags & I2C_M_STOP)) {
i2c_cmdreg_set(i2c, CMD_TX_P, &offset);
}
i2c_cmdreg_set(i2c, CMD_EXIT, &offset);
}
static void i2c_enable(const struct i2c_driver_data *i2c)
{
unsigned int val = readl(i2c->reg_base + I2C_GLB);
val |= GLB_EN_MASK;
writel(val, i2c->reg_base + I2C_GLB);
}
/*
* config i2c slave addr
*/
static void i2c_set_addr(const struct i2c_driver_data *i2c)
{
struct i2c_msg *msg = i2c->msgs;
unsigned int addr;
if (msg->flags & I2C_M_TEN) {
/* first byte is 11110XX0 where XX is upper 2 bits */
addr = ((msg->addr & 0x300) << 1) | 0xf000;
if (msg->flags & I2C_M_RD) {
addr |= 1 << 8; /* shift:8 */
}
/* second byte is the remaining 8 bits */
addr |= msg->addr & 0xff;
} else {
addr = (msg->addr & 0x7f) << 1;
if (msg->flags & I2C_M_RD) {
addr |= 1;
}
}
writel(addr, i2c->reg_base + I2C_DATA1);
}
/*
* start command sequence
*/
static void i2c_start_cmd(const struct i2c_driver_data *i2c)
{
unsigned int val = readl(i2c->reg_base + I2C_CTRL1);
val |= CTRL1_CMD_START_MASK;
writel(val, i2c->reg_base + I2C_CTRL1);
}
static int i2c_wait_rx_noempty(const struct i2c_driver_data *i2c)
{
unsigned int time_cnt = 0;
unsigned int val;
do {
val = readl(i2c->reg_base + I2C_STAT);
if (val & STAT_RXF_NOE_MASK) {
return 0;
}
udelay(50); /* delay:50 us */
time_cnt++;
} while (time_cnt < I2C_TIMEOUT_COUNT);
i2c_rescue(i2c);
return -1;
}
static int i2c_wait_tx_nofull(const struct i2c_driver_data *i2c)
{
unsigned int time_cnt = 0;
unsigned int val;
do {
val = readl(i2c->reg_base + I2C_STAT);
if (val & STAT_TXF_NOF_MASK) {
return 0;
}
udelay(50); /* delay:50 us */
time_cnt++;
} while (time_cnt < I2C_TIMEOUT_COUNT);
i2c_rescue(i2c);
return -1;
}
static int i2c_wait_idle(const struct i2c_driver_data *i2c)
{
unsigned int time_cnt = 0;
unsigned int val;
do {
val = readl(i2c->reg_base + I2C_INTR_RAW);
if (val & (INTR_ABORT_MASK)) {
//printf("i2c wait idle 1,val==0x%x\n",val);
return -1;
}
if (val & INTR_CMD_DONE_MASK) {
return 0;
}
udelay(50); /* delay:50 us */
time_cnt++;
} while (time_cnt < I2C_WAIT_TIMEOUT);
i2c_rescue(i2c);
return -1;
}
static int i2c_polling_xfer_one_msg(const struct i2c_driver_data *i2c)
{
int status;
unsigned int val;
struct i2c_msg *msg = i2c->msgs;
unsigned int msg_buf_ptr = 0;
i2c_enable(i2c);
i2c_clr_irq(i2c);
i2c_set_addr(i2c);
i2c_cfg_cmd(i2c);
i2c_start_cmd(i2c);
if (msg->flags & I2C_M_RD) {
while (msg_buf_ptr < msg->len) {
status = i2c_wait_rx_noempty(i2c);
if (status) {
goto end;
}
val = readl(i2c->reg_base + I2C_RXF);
msg->buf[msg_buf_ptr] = val;
msg_buf_ptr++;
}
} else {
while (msg_buf_ptr < msg->len) {
status = i2c_wait_tx_nofull(i2c);
if (status) {
goto end;
}
val = msg->buf[msg_buf_ptr];
writel(val, i2c->reg_base + I2C_TXF);
msg_buf_ptr++;
}
}
status = i2c_wait_idle(i2c);
end:
i2c_disable(i2c);
return status;
}
static void i2c_cfg_irq(const struct i2c_driver_data *i2c, unsigned int flag)
{
writel(flag, i2c->reg_base + I2C_INTR_EN);
}
static int i2c_xfer(unsigned char i2c_num, const struct i2c_msg *msgs, int num)
{
int status = 0;
if (msgs == NULL) {
//printf("[error] msg pointer is null.\n");
return -1;
}
struct i2c_driver_data *i2c = &g_i2c_data[i2c_num];
struct platform_i2c *hpi = &g_i2c_platform_data[i2c_num];
i2c->clk = get_host_clock(0);
i2c->private = (void *)(hpi);
i2c->msgs = (struct i2c_msg *)msgs;
i2c->msg_num = (unsigned int)num;
i2c->msg_idx = 0;
while (i2c->msg_idx < i2c->msg_num) {
status = i2c_polling_xfer_one_msg(i2c);
if (status) {
break;
}
i2c->msgs++;
i2c->msg_idx++;
}
if (!status || i2c->msg_idx > 0) {
status = i2c->msg_idx;
}
return status;
}
static int i2c_check_enable(unsigned char i2c_num)
{
if (i2c_num >= I2C_NUM) {
return -1;
}
return g_i2c_host_cfg[i2c_num];
}
static int hal_i2c_recv_inner(const struct i2c_client *client, unsigned char *buf,
unsigned int count)
{
struct i2c_msg msg[I2C_BUF_SIZE] = {0};
unsigned char reg_addr[2] = {0};
if (client->reg_width == 2) { /* reg_width:2 */
reg_addr[0] = (client->reg_addr >> 8) & 0xff; /* shift:8 */
reg_addr[1] = client->reg_addr & 0xff;
} else {
reg_addr[0] = client->reg_addr & 0xff;
}
msg[0].addr = client->dev_addr;
msg[0].flags = 0;
msg[0].len = client->reg_width;
msg[0].buf = reg_addr;
msg[1].addr = client->dev_addr;
msg[1].flags = 0;
msg[1].flags |= I2C_M_RD;
msg[1].len = count;
msg[1].buf = buf;
return i2c_xfer(client->i2c_num, msg, 2); /* msg num:2 */
}
static int hal_i2c_send_inner(unsigned char i2c_num, unsigned short dev_addr, const char *buf,
unsigned int count)
{
struct i2c_msg msg = {0};
msg.addr = dev_addr;
msg.flags = 0;
msg.len = count;
msg.buf = (unsigned char *)buf;
int ret = i2c_xfer(i2c_num, &msg, 1);
return (ret == 1) ? count : ret;
}
static int hal_i2c_init_inner(unsigned char i2c_num)
{
struct i2c_driver_data *i2c = NULL;
struct platform_i2c *hpi = NULL;
int ret = i2c_check_enable(i2c_num);
if (ret < 0) {
return -1;
}
i2c = &g_i2c_data[i2c_num];
hpi = &g_i2c_platform_data[i2c_num];
i2c->clk = get_host_clock(i2c_num);
i2c->private = (void *)(hpi);
i2c->irq = 0;
i2c_init_cfg(i2c, i2c_num);
return 0;
}
int i2c_recv(const struct i2c_client *client, unsigned char *buf,
unsigned int count)
{
if ((client == NULL) || (buf == NULL)) {
return -1;
}
if (client->i2c_num >= I2C_NUM) {
return -1;
}
if (count > I2C_BUF_SIZE) {
return -1;
}
return hal_i2c_recv_inner(client, buf, count);
}
int i2c_send(unsigned char i2c_num, unsigned short dev_addr, const char *buf,
unsigned int count)
{
if (i2c_num >= I2C_NUM) {
return -1;
}
if (buf == NULL) {
return -1;
}
if (count > I2C_BUF_SIZE) {
return -1;
}
return hal_i2c_send_inner(i2c_num, dev_addr, buf, count);
}
int i2c_init(unsigned char i2c_num)
{
if (i2c_num >= I2C_NUM) {
return -1;
}
return hal_i2c_init_inner(i2c_num);
}
+1
View File
@@ -0,0 +1 @@
SRCS-y += pwm.c
+80
View File
@@ -0,0 +1,80 @@
#include <io.h>
#include "pwm.h"
static void pwm_set_bits(void* base, u32 offset, unsigned int mask, u32 data)
{
void *address = base + offset;
unsigned int value;
value = readl(address);
value &= ~mask;
value |= (data & mask);
writel(value, address);
}
static void get_pwm_clk(unsigned int *clk)
{
void *pwm_clock_addr = (void *)PWM_CLOCK_ADDR_BASE;
unsigned int val = readl(pwm_clock_addr);
val = (val >> 8) & 0x3;
switch (val) {
case 0:
*clk = PWM_CLOCK_3M;
break;
case 1:
*clk = PWM_CLOCK_50M;
break;
default:
*clk = PWM_CLOCK_24M;
break;
}
}
int pwm_enable(int pwm_id)
{
if (pwm_id > PWM_MAX_NUM)
return -1;
pwm_set_bits((void *)PWM_ADDR_BASE, PWM_CTRL_ADDR(pwm_id), PWM_ENABLE_MASK, (0x1 << PWM_ENABLE_SHIFT));
return 0;
}
int pwm_disable(int pwm_id)
{
if (pwm_id > PWM_MAX_NUM)
return -1;
pwm_set_bits((void *)PWM_ADDR_BASE, PWM_CTRL_ADDR(pwm_id), PWM_ENABLE_MASK, (0x0 << PWM_ENABLE_SHIFT));
return 0;
}
int pwm_config(int pwm_id, int duty_cycle_us, int period_us)
{
unsigned int duty;
unsigned int period, freq;
unsigned int clk;
if ((pwm_id > PWM_MAX_NUM) || (duty_cycle_us > period_us))
return -1;
get_pwm_clk(&clk);
freq = clk/1000000;
period = freq * period_us;
duty = period * duty_cycle_us/period_us;
if ((period < 2) || (duty < 1))
return -1;
pwm_set_bits((void *)PWM_ADDR_BASE, PWM_CFG_CYCLE_ADDR(pwm_id), PWM_PERIOD_MASK, period);
pwm_set_bits((void *)PWM_ADDR_BASE, PWM_CFG_HLINT_ADDR(pwm_id), PWM_DUTY_MASK, duty);
pwm_set_bits((void *)PWM_ADDR_BASE, PWM_CTRL_ADDR(pwm_id),
PWM_KEEP_MASK, (0x1 << PWM_KEEP_SHIFT));
return 0;
}
+1
View File
@@ -0,0 +1 @@
SRCS-y += serial.c
+199
View File
@@ -0,0 +1,199 @@
/* serial.c - print to uart */
#include <platform.h>
#include <serial.h>
#include <common.h>
static int serial_test_enable(void)
{
#ifdef CONFIG_SERIAL_DISABLE
return 0;
#else
return 1;
#endif
}
static void pl01x_putc(char c)
{
/* Wait until there is space in the FIFO */
while (readl(UART_PL01x_FR) & UART_PL01x_FR_TXFF);
/* Send the character */
writel(c, UART_PL01x_DR);
}
static u32 pl01x_getc(void)
{
u32 data;
while (readl(UART_PL01x_FR) & UART_PL01x_FR_RXFE) {
/* Wait until there is data in the FIFO */
}
data = readl(UART_PL01x_DR);
/* Check for an error flag */
if (data & 0xFFFFFF00) {
/* Clear the error */
writel(0xFFFFFFFF, UART_PL01x_ECR);
return 0;
}
return data;
}
void serial_putc(const char c)
{
if (!serial_test_enable())
return;
if (c == '\n')
pl01x_putc('\r');
pl01x_putc(c);
}
char serial_getc(void)
{
return (pl01x_getc() & 0xFF);
}
void serial_puts(const char *s)
{
if (!serial_test_enable())
return;
if (s == NULL)
return;
while (*s) {
serial_putc(*s);
s++;
}
}
void serial_puts_always(const char *s)
{
if (s == NULL)
return;
while (*s) {
if (*s == '\n')
pl01x_putc('\r');
pl01x_putc(*s);
s++;
}
}
void serial_put_dec(u32 dec)
{
u32 num = dec;
char c[20] = {0}; /* size 20 */
int i = 0;
if (!serial_test_enable())
return;
if (num == 0) {
pl01x_putc('0');
return;
}
while (num) {
c[i] = '0' + (num % 10); /* bit size 10 */
++i;
num /= 10; /* bit size 10 */
}
for (i -= 1; i >= 0; --i)
pl01x_putc(c[i]);
}
void serial_put_hex(u32 hex)
{
int i;
char c;
if (!serial_test_enable())
return;
for (i = 28; i >= 0; i -= 4) { /* bit size 28 4 */
c = ((unsigned int)hex >> (unsigned int)i) & 0x0F;
if (c < 10) /* bit size 10 */
c += '0';
else
c += 'A' - 10; /* bit size 10 */
pl01x_putc(c);
}
}
void serial_put_hex_always(u32 hex)
{
int i;
char c;
for (i = 28; i >= 0; i -= 4) { /* bit size 28 4 */
c = ((unsigned int)hex >> (unsigned int)i) & 0x0F;
if (c < 10) /* bit size 10 */
c += '0';
else
c += 'A' - 10; /* bit size 10 */
pl01x_putc(c);
}
}
static void _serial_crg_init(void)
{
u32 tmp;
/* configure pinmux of uart */
/* writel(0x1502, 0x112C00F0);
* writel(0x1402, 0x119800E0); */
/* enable uart clock */
tmp = readl(REG_PERI_CRG110);
tmp |= 1 << 3;
writel(tmp, REG_PERI_CRG110);
/* cancel uart reset */
tmp = readl(REG_PERI_CRG110);
tmp &= ~(1 << 11);
writel(tmp, REG_PERI_CRG110);
}
void serial_init(void)
{
u32 tmp;
u32 divider;
u32 remainder;
u32 fraction;
_serial_crg_init();
/* first, disable everything */
writel(0, UART_PL01x_CR);
/*
* Set baud rate
*
* IBRD = UART_CLK / (16 * BAUD_RATE)
* FBRD = RND((64 * MOD(UART_CLK,(16 * BAUD_RATE)))
* / (16 * BAUD_RATE))
*/
tmp = 16 * UART_BAUDRATE;
divider = UART_CLOCK / tmp;
remainder = UART_CLOCK % tmp;
tmp = (8 * remainder) / UART_BAUDRATE;
fraction = (tmp >> 1) + (tmp & 1);
writel(divider, UART_PL01x_IBRD);
writel(fraction, UART_PL01x_FBRD);
writel(UART_PL011_LCRH_WLEN_8 | UART_PL011_LCRH_FEN, UART_PL01x_LCRH);
/* Finally, enable the UART */
writel(UART_PL011_CR_UARTEN | UART_PL011_CR_TXE |
UART_PL011_CR_RXE, UART_PL01x_CR);
return;
}
+2
View File
@@ -0,0 +1,2 @@
SRCS-y += stopwatch.c
+27
View File
@@ -0,0 +1,27 @@
#include <sys/types.h>
#include <platform.h>
#include <io.h>
typedef union {
u32 value;
struct {
/* [0] timer trigger */
u32 timer_trigger : 1;
/* [2] timer clear */
u32 timer_clear : 1;
/* [3] running timer trigger */
u32 running_timer_trigger : 1;
/* [3:31] reserved */
u32 reserved : 29;
};
} stopwatch_cfg;
void stopwatch_trigger(void)
{
stopwatch_cfg cfg = {0};
cfg.timer_clear = 0; /* false */
cfg.timer_trigger = 1; /* true */
writel(cfg.value, (STOPWATCH_CTRL_REG2));
}
+1
View File
@@ -0,0 +1 @@
SRCS-y += timer.c
+78
View File
@@ -0,0 +1,78 @@
#include <common.h>
#include <timer.h>
#define TIMER_LOAD 0
#define TIMER_VALUE 0x4
#define TIMER_CONTROL 0x8
#define CFG_TIMER_CTRL 0xc0
#define TIMER_FEQ 24000000
#define TIMER_DIV 1
#define TIMER_NOR_DIVIDER_US (TIMER_FEQ / TIMER_DIV / 1000000)
#define UDELAY_US_MAX (61 * 1000 * 1000UL)
#define REG_TIMER_BASE TIMER3_REG_BASE
#define timer_reg_get(offset) readl(REG_TIMER_BASE + (offset))
#define timer_reg_set(offset, val) writel(val, REG_TIMER_BASE + (offset))
static u8 g_timer_init = 0;
ulong timer_get_val(void)
{
return ~1UL - timer_reg_get(TIMER_VALUE);
}
void udelay(ulong us)
{
ulong cur, start, end;
ulong count;
if (us == 0)
return;
assert(g_timer_init == 1);
start = timer_get_val();
if (us >= UDELAY_US_MAX) {
puts("WARNING: long udelay, use ");
putdec(UDELAY_US_MAX);
puts("us instead!\n");
count = UDELAY_US_MAX * TIMER_NOR_DIVIDER_US;
} else
count = us * TIMER_NOR_DIVIDER_US;
end = start + count;
while (1) {
cur = timer_get_val();
if ((end >= start && cur >= end ) ||
(end < start && cur >= end && cur < start))
break;
}
}
void mdelay(u32 msec)
{
assert(g_timer_init == 1);
udelay(msec * 1000);
}
void timer_init(void)
{
timer_reg_set(TIMER_CONTROL, 0);
timer_reg_set(TIMER_LOAD, 0xffffffff);
timer_reg_set(TIMER_CONTROL, CFG_TIMER_CTRL);
g_timer_init = 1;
}
+9
View File
@@ -0,0 +1,9 @@
#ifndef _ASSERT_H_
#define _ASSERT_H_
#include <debug.h>
#define assert(x) ASSERT(x)
#endif /* _ASSERT_H_ */
+63
View File
@@ -0,0 +1,63 @@
#ifndef __COMMON_H_
#define __COMMON_H_
#include <config.h>
#include <sys/types.h>
#include <io.h>
#include <serial.h>
#include <stdio.h>
#include <compile.h>
#include <core.h>
#include <debug.h>
#include <assert.h>
#include <timer.h>
#include <string.h>
#include <reserved_mem.h>
extern char g_base_irqstack[];
extern char g_top_irqstack[];
extern u32 g_heap_start;
extern u32 g_heap_end;
extern char _start[];
extern char _end[];
extern char __text_start[];
extern char __text_end[];
extern char __rodata_start[];
extern char __rodata_end[];
extern char __data_start[];
extern char __data_end[];
extern char __text2_start[];
extern char __text2_end[];
extern char __rodata2_start[];
extern char __rodata2_end[];
extern char __data2_start[];
extern char __data2_end[];
extern char __bss_start[];
extern char __bss_end[];
extern char __bin_end_pad[];
extern char __bin_end[];
extern char __param_start[];
extern char __param_end[];
u32 start_shell(void);
int run_stage2_func(int (*func)(void));
u64 get_ddr_size(void);
ulong get_reserved_ddr(u32 size);
void stopwatch_trigger(void);
#endif /*__COMMON_H_*/
+45
View File
@@ -0,0 +1,45 @@
#ifndef _COMPILE_H_
#define _COMPILE_H_
#include <stddef.h>
#define __FILENAME__ (__builtin_strrchr(__FILE__, '/')? __builtin_strrchr(__FILE__, '/') + 1 : __FILE__)
#define array_size(x) (sizeof(x) / sizeof(*(x)))
#define swap32(_x) ((uint32)( \
((((uint32)(_x)) & 0x000000FF) << 24) | \
((((uint32)(_x)) & 0x0000FF00) << 8) | \
((((uint32)(_x)) & 0xFF000000) >> 24) | \
((((uint32)(_x)) & 0x00FF0000) >> 8)))
#define swap16(_x) ((uint16)( \
((((uint16)(_x)) & 0xFF00) >> 8) | \
((((uint16)(_x)) & 0x00FF) << 8)))
#define around(size, align) (((size) + (align) - 1) & (~((align) - 1)))
#define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
#define STAGE1_FUNC __attribute__((section(".text.stage1")))
#define STAGE1_GLOBAL __attribute__((section(".data.stage1")))
#define STAGE1_CONST_GLOBAL __attribute__((section(".rodata.stage1"))) const
#define STAGE1_STR(str) \
({ \
static const char _str_##__COUNTER__[] \
__attribute__((section(".rodata.stage1"))) = str; \
_str_##__COUNTER__; \
})
#define STAGE2_FUNC __attribute__((section(".text.stage2")))
#define STAGE2_GLOBAL __attribute__((section(".data.stage2")))
#define STAGE2_CONST_GLOBAL __attribute__((section(".rodata.stage2"))) const
#define STAGE2_STR(str) \
({ \
static const char _str_##__COUNTER__[] \
__attribute__((section(".rodata.stage2"))) = str; \
_str_##__COUNTER__; \
})
#endif /* _COMPILE_H_ */
+5
View File
@@ -0,0 +1,5 @@
#ifndef CONFIGH
#define CONFIGH
#include <autoconf.h>
#include <platform.h>
#endif
+28
View File
@@ -0,0 +1,28 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#ifndef _SYS_CTYPE_H_
#define _SYS_CTYPE_H_
#define isspace(c) ((c) == ' ' || ((c) >= '\t' && (c) <= '\r'))
#define isascii(c) (((c) & ~0x7f) == 0)
#define isupper(c) ((c) >= 'A' && (c) <= 'Z')
#define islower(c) ((c) >= 'a' && (c) <= 'z')
#define isalpha(c) (isupper(c) || islower(c))
#define isdigit(c) ((c) >= '0' && (c) <= '9')
#define isxdigit(c) (isdigit(c) \
|| ((c) >= 'A' && (c) <= 'F') \
|| ((c) >= 'a' && (c) <= 'f'))
#define isprint(c) ((c) >= ' ' && (c) <= '~')
#define toupper(c) ((c) - 0x20 * (((c) >= 'a') && ((c) <= 'z')))
#define tolower(c) ((c) + 0x20 * (((c) >= 'A') && ((c) <= 'Z')))
#define min(x, y) ((x) < (y) ? (x) : (y))
#define min_t(t, x, y) ((t)((t)(x) < (t)(y) ? (x) : (y)))
#define tohex(c) (((c) >= '0' && (c) <= '9') ? ((c) - '0') : \
(((c) >= 'a' && (c) <= 'f') ? ((c) - 'a' + 10) : \
(((c) >= 'A' && (c) <= 'F') ? ((c) - 'A' + 10) : -1)))
#endif /* !_SYS_CTYPE_H_ */
+38
View File
@@ -0,0 +1,38 @@
/*
* Copyright (c) XMEDIA 2021. All rights reserved.
*/
#ifndef _DEBUG_H_
#define _DEBUG_H_
/******************************************************************************/
#include <config.h>
#include <stdio.h>
#include <lib.h>
/* #define ASSERT(_p) if (!(_p)) { \
* printf("%s(%s,%d):assert:(%s)\n", __FILE__, __FUNCTION__, __LINE__, #_p);
*
* #define ASSERT1(_p, _fmt, args...) if (!(_p)) { \
* printf("%s(%s,%d):assert:(%s)\n" _fmt, __FILE__, __FUNCTION__, __LINE__, #_p, ##args); */
#define ASSERT(_condition) do { \
if (!(_condition)) { \
puts("ASSERT "); \
putchar('['); \
puts(__FILE__); \
putchar(','); \
putdec(__LINE__); \
puts("]: "); \
puts(#_condition); \
puts("\n"); \
} \
} while(0)
#define __PRINT_MACRO(x) #x
#define PRINT_MARCO(x) #x"="__PRINT_MACRO(x)
/* #pragma message(PRINT_MARCO(MACRO_NAME_XXX)) */
int dump_hex(u32 addr, char *buf, u32 sz_buf, u32 width);
/******************************************************************************/
#endif /* _DEBUG_H_ */
+20
View File
@@ -0,0 +1,20 @@
#ifndef _DIV64_H_
#define _DIV64_H_
#include <sys/types.h>
extern uint32_t __div64_32(uint64_t *dividend, uint32_t divisor);
#define do_div(n, base) ({ \
uint32_t __base = (base); \
uint32_t __rem; \
if (((n) >> 32) == 0) { \
__rem = (uint32_t)(n) % __base; \
(n) = (uint32_t)(n) / __base; \
} else \
__rem = __div64_32(&(n), __base); \
__rem; \
})
#endif /* _DIV64_H_ */
+153
View File
@@ -0,0 +1,153 @@
#ifndef _ERRNO_H_
#define _ERRNO_H_
/****************************************************************************
* Error Number Definitions
****************************************************************************/
#define EPERM 1 /* Operation not permitted */
#define ENOENT 2 /* No such file or directory */
#define ESRCH 3 /* No such process */
#define EINTR 4 /* Interrupted system call */
#define EIO 5 /* I/O error */
#define ENXIO 6 /* No such device or address */
#define E2BIG 7 /* Argument list too long */
#define ENOEXEC 8 /* Exec format error */
#define EBADF 9 /* Bad file number */
#define ECHILD 10 /* No child processes */
#define EAGAIN 11 /* Try again */
#define ENOMEM 12 /* Out of memory */
#define EACCES 13 /* Permission denied */
#define EFAULT 14 /* Bad address */
#define ENOTBLK 15 /* Block device required */
#define EBUSY 16 /* Device or resource busy */
#define EEXIST 17 /* File exists */
#define EXDEV 18 /* Cross-device link */
#define ENODEV 19 /* No such device */
#define ENOTDIR 20 /* Not a directory */
#define EISDIR 21 /* Is a directory */
#define EINVAL 22 /* Invalid argument */
#define ENFILE 23 /* File table overflow */
#define EMFILE 24 /* Too many open files */
#define ENOTTY 25 /* Not a typewriter */
#define ETXTBSY 26 /* Text file busy */
#define EFBIG 27 /* File too large */
#define ENOSPC 28 /* No space left on device */
#define ESPIPE 29 /* Illegal seek */
#define EROFS 30 /* Read-only file system */
#define EMLINK 31 /* Too many links */
#define EPIPE 32 /* Broken pipe */
#define EDOM 33 /* Math argument out of domain of func */
#define ERANGE 34 /* Math result not representable */
#define EDEADLK 35 /* Resource deadlock would occur */
#define ENAMETOOLONG 36 /* File name too long */
#define ENOLCK 37 /* No record locks available */
#define ENOSYS 38 /* Invalid system call number */
#define ENOTEMPTY 39 /* Directory not empty */
#define ELOOP 40 /* Too many symbolic links encountered */
#define EWOULDBLOCK EAGAIN /* Operation would block */
#define ENOMSG 42 /* No message of desired type */
#define EIDRM 43 /* Identifier removed */
#define ECHRNG 44 /* Channel number out of range */
#define EL2NSYNC 45 /* Level 2 not synchronized */
#define EL3HLT 46 /* Level 3 halted */
#define EL3RST 47 /* Level 3 reset */
#define ELNRNG 48 /* Link number out of range */
#define EUNATCH 49 /* Protocol driver not attached */
#define ENOCSI 50 /* No CSI structure available */
#define EL2HLT 51 /* Level 2 halted */
#define EBADE 52 /* Invalid exchange */
#define EBADR 53 /* Invalid request descriptor */
#define EXFULL 54 /* Exchange full */
#define ENOANO 55 /* No anode */
#define EBADRQC 56 /* Invalid request code */
#define EBADSLT 57 /* Invalid slot */
#define EDEADLOCK EDEADLK
#define EBFONT 59 /* Bad font file format */
#define ENOSTR 60 /* Device not a stream */
#define ENODATA 61 /* No data available */
#define ETIME 62 /* Timer expired */
#define ENOSR 63 /* Out of streams resources */
#define ENONET 64 /* Machine is not on the network */
#define ENOPKG 65 /* Package not installed */
#define EREMOTE 66 /* Object is remote */
#define ENOLINK 67 /* Link has been severed */
#define EADV 68 /* Advertise error */
#define ESRMNT 69 /* Srmount error */
#define ECOMM 70 /* Communication error on send */
#define EPROTO 71 /* Protocol error */
#define EMULTIHOP 72 /* Multihop attempted */
#define EDOTDOT 73 /* RFS specific error */
#define EBADMSG 74 /* Not a data message */
#define EOVERFLOW 75 /* Value too large for defined data type */
#define ENOTUNIQ 76 /* Name not unique on network */
#define EBADFD 77 /* File descriptor in bad state */
#define EREMCHG 78 /* Remote address changed */
#define ELIBACC 79 /* Can not access a needed shared library */
#define ELIBBAD 80 /* Accessing a corrupted shared library */
#define ELIBSCN 81 /* .lib section in a.out corrupted */
#define ELIBMAX 82 /* Attempting to link in too many shared libraries */
#define ELIBEXEC 83 /* Cannot exec a shared library directly */
#define EILSEQ 84 /* Illegal byte sequence */
#define ERESTART 85 /* Interrupted system call should be restarted */
#define ESTRPIPE 86 /* Streams pipe error */
#define EUSERS 87 /* Too many users */
#define ENOTSOCK 88 /* Socket operation on non-socket */
#define EDESTADDRREQ 89 /* Destination address required */
#define EMSGSIZE 90 /* Message too long */
#define EPROTOTYPE 91 /* Protocol wrong type for socket */
#define ENOPROTOOPT 92 /* Protocol not available */
#define EPROTONOSUPPORT 93 /* Protocol not supported */
#define ESOCKTNOSUPPORT 94 /* Socket type not supported */
#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
#define EPFNOSUPPORT 96 /* Protocol family not supported */
#define EAFNOSUPPORT 97 /* Address family not supported by protocol */
#define EADDRINUSE 98 /* Address already in use */
#define EADDRNOTAVAIL 99 /* Cannot assign requested address */
#define ENETDOWN 100 /* Network is down */
#define ENETUNREACH 101 /* Network is unreachable */
#define ENETRESET 102 /* Network dropped connection because of reset */
#define ECONNABORTED 103 /* Software caused connection abort */
#define ECONNRESET 104 /* Connection reset by peer */
#define ENOBUFS 105 /* No buffer space available */
#define EISCONN 106 /* Transport endpoint is already connected */
#define ENOTCONN 107 /* Transport endpoint is not connected */
#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */
#define ETOOMANYREFS 109 /* Too many references: cannot splice */
#define ETIMEDOUT 110 /* Connection timed out */
#define ECONNREFUSED 111 /* Connection refused */
#define EHOSTDOWN 112 /* Host is down */
#define EHOSTUNREACH 113 /* No route to host */
#define EALREADY 114 /* Operation already in progress */
#define EINPROGRESS 115 /* Operation now in progress */
#define ESTALE 116 /* Stale file handle */
#define EUCLEAN 117 /* Structure needs cleaning */
#define ENOTNAM 118 /* Not a XENIX named type file */
#define ENAVAIL 119 /* No XENIX semaphores available */
#define EISNAM 120 /* Is a named type file */
#define EREMOTEIO 121 /* Remote I/O error */
#define EDQUOT 122 /* Quota exceeded */
#define ENOMEDIUM 123 /* No medium found */
#define EMEDIUMTYPE 124 /* Wrong medium type */
#define ECANCELED 125 /* Operation Canceled */
#define ENOKEY 126 /* Required key not available */
#define EKEYEXPIRED 127 /* Key has expired */
#define EKEYREVOKED 128 /* Key has been revoked */
#define EKEYREJECTED 129 /* Key was rejected by service */
/* for robust mutexes */
#define EOWNERDEAD 130 /* Owner died */
#define ENOTRECOVERABLE 131 /* State not recoverable */
#define ERFKILL 132 /* Operation not possible due to RF-kill */
#define EHWPOISON 133 /* Memory page has hardware error */
#define ENOTSUP 134 /* Not supported */
#endif /* _ERRNO_H_ */
+23
View File
@@ -0,0 +1,23 @@
#ifndef _FLOAT_H_
#define _FLOAT_H_
#undef FLT_MAX
#define FLT_MAX __FLT_MAX__
#undef DBL_MAX
#define DBL_MAX __DBL_MAX__
#undef FLT_MIN
#define FLT_MIN __FLT_MIN__
#undef DBL_MIN
#define DBL_MIN __DBL_MIN__
#undef FLT_EPSILON
#define FLT_EPSILON __FLT_EPSILON__
#undef DBL_EPSILON
#define DBL_EPSILON __DBL_EPSILON__
#endif /* ifndef _FLOAT_H_ */
+8
View File
@@ -0,0 +1,8 @@
#ifndef _GPIO_H_
#define _GPIO_H_
void gpio_set_dir(int group, int bit, int dir);
void gpio_set_data(int group, int bit, int data);
#endif /* _GPIO_H_ */
+147
View File
@@ -0,0 +1,147 @@
#ifndef _HLIST_H_
#define _HLIST_H_
#include <stddef.h>
/*
* 该结构体用于嵌入到业务数据结构体中(entry),用于实现链表
* 例:
* struct Entry { // 你的业务数据结构体
* ...
* struct node node; // 嵌入其中,位置任意
* ...
* };
*/
struct node {
struct node *next, *prev;
};
/*
* 由成员变量 node 地址获取结构体 entry 地址
* 例:
* struct Entry entry;
* struct node *n = &entry.node;
* struct Entry *p = node_entry(n, struct Entry, node);
* 此时 p 指向 entry
*/
#define node_entry(node, type, member) \
((type*)((char*)(node) - (size_t)&((type*)0)->member))
/* 带哨兵节点的双向链表 */
struct list {
struct node base;
};
static inline void list_init(struct list *list)
{
list->base.next = &list->base;
list->base.prev = &list->base;
}
static inline bool list_empty(const struct list *list)
{
return list->base.next == &list->base;
}
static inline bool list_is_head(const struct list *list, const struct node *node)
{
return list->base.next == node;
}
static inline bool list_is_tail(const struct list *list, const struct node *node)
{
return list->base.prev == node;
}
/* node 插入到 pos 后面 */
static inline void list_insert_backward(struct node *pos, struct node *node)
{
node->prev = pos;
node->next = pos->next;
node->prev->next = node;
node->next->prev = node;
}
/* node 插入到 pos 前面 */
static inline void list_insert(struct node *pos, struct node *node)
{
node->prev = pos->prev;
node->next = pos;
node->prev->next = node;
node->next->prev = node;
}
static inline void list_add_tail(struct list *list, struct node *node)
{
list_insert(&list->base, node);
}
static inline void list_add_head(struct list *list, struct node *node)
{
list_insert(list->base.next, node);
}
static inline void list_remove(struct node *node)
{
node->prev->next = node->next;
node->next->prev = node->prev;
}
static inline void list_remove_tail(struct list *list)
{
list_remove(list->base.prev);
}
static inline void list_remove_head(struct list *list)
{
list_remove(list->base.next);
}
static inline void list_replace(struct node *old, struct node *node)
{
node->next = old->next;
node->next->prev = node;
node->prev = old->prev;
node->prev->next = node;
}
#define list_for_each(node, list) \
for (node = (list)->base.next; node != &(list)->base; node = (node)->next)
#define list_for_each_safe(node, tmp, list) \
for (node = (list)->base.next, tmp = (node)->next; node != &(list)->base; node = tmp, tmp = (node)->next)
/* 获取头结点,或空 */
#define list_head_entry(list, type, member) \
(list_empty(list) ? NULL : node_entry((list)->base.next, type, member))
/* 获取尾结点,或空 */
#define list_tail_entry(list, type, member) \
(list_empty(list) ? NULL : node_entry((list)->base.prev, type, member))
/* 获取下一结点,或空 */
#define list_next_entry(entry, list, type, member) \
(list_is_tail(list, &(entry)->member) ? \
NULL : \
node_entry((entry)->member.next, type, member))
/* 获取上一结点,或空 */
#define list_prev_entry(entry, list, type, member) \
(list_is_head(list, &(entry)->member) ? \
NULL : \
node_entry((entry)->member.prev, type, member))
/* 遍历链表;过程中如需操作链表,请使用 _SAFE 版本 */
#define list_for_each_entry(entry, list, type, member) \
for (entry = node_entry((list)->base.next, type, member); \
&(entry)->member != &(list)->base; \
entry = node_entry((entry)->member.next, type, member))
#define list_for_each_entry_safe(entry, tmp, list, type, member) \
for (entry = node_entry((list)->base.next, type, member), \
tmp = node_entry((entry)->member.next, type, member); \
&(entry)->member != &(list)->base; \
entry = tmp, tmp = node_entry((entry)->member.next, type, member))
#endif /* _HLIST_H_ */
+21
View File
@@ -0,0 +1,21 @@
#ifndef _I2C_H_
#define _I2C_H_
#include <platform.h>
#include <sys/types.h>
#include <io.h>
#include <lib.h>
struct i2c_client {
unsigned char i2c_num;
unsigned short dev_addr;
unsigned long int reg_addr;
unsigned int reg_width;
};
int i2c_init(unsigned char i2c_num);
int i2c_recv(const struct i2c_client *client, unsigned char *buf, unsigned int count);
int i2c_send(unsigned char i2c_num, unsigned short dev_addr, const char *buf,unsigned int count);
#endif
+17
View File
@@ -0,0 +1,17 @@
#ifndef _IMAGE_H_
#define _IMAGE_H_
#include <sys/types.h>
struct mcu_fw_head {
u32 j_instruction; /* Jump to real excutable entry */
u32 fw_magic; /* MCU Firmware magic */
u32 fw_ver; /* MCU Firmware version */
u32 fw_total_size; /* MCU Firmware total size */
u32 fw_stage1_size; /* MCU Stage1 size */
u8 resv[CONFIG_MCU_HEAD_SIZE - 20]; /* Reserved */
};
#endif /* _IMAGE_H_ */
+15
View File
@@ -0,0 +1,15 @@
#ifndef _INTERRUPT_H_
#define _INTERRUPT_H_
#include <stdint.h>
#define ATTRIBUTE_ISR __attribute__ ((interrupt ("machine")))
void drv_irq_enable(uint32_t irq_num);
void drv_irq_disable(uint32_t irq_num);
int drv_irq_register(uint32_t irq_num, void *irq_handler);
void drv_irq_unregister(uint32_t irq_num);
int irq_init(void);
#endif /* ifndef _INTERRUPT_H_ */
+10
View File
@@ -0,0 +1,10 @@
#ifdef CONFIG_ARM_ARCH
#include <arm/include/io.h>
#endif
#ifdef CONFIG_RISCV_ARCH
#include <riscv/include/io.h>
#endif
+15
View File
@@ -0,0 +1,15 @@
#ifndef __LIB_H__
#define __LIB_H__
#include <sys/types.h>
#include <config.h>
#define SECUREC_MEM_MAX_LEN (0x100000) //1MB
void reset_cpu(void);
int memset_s(void* dest, size_t destMax, unsigned char c, size_t count);
int memcpy_s(void* dest, size_t destMax, const void* src, size_t count);
unsigned short crc16(unsigned char *data, unsigned int length);
#endif /*__LIB_H__*/
+22
View File
@@ -0,0 +1,22 @@
#ifndef _MALLOC_H_
#define _MALLOC_H_
#include <config.h>
#include <stddef.h>
void malloc_init(uint32 start, uint32 len);
#ifdef CONFIG_MALLOC
void *malloc(uint32 bytes); /* not thread safe */
void *memalign(uint32 alignment, uint32 bytes);
void free(void *ptr);
void show_memnode(unsigned int);
#else
void *__malloc(uint32 bytes, const char *file, int line);
void *__memalign(uint32 alignment, uint32 bytes, const char *file, int line);
void __free(const void *mem, const char *file, int line);
#define malloc(bytes) __malloc(bytes, __FILE__, __LINE__)
#define memalign(alignment, bytes) __memalign(alignment, bytes, __FILE__, __LINE__)
#define free(mem) __free(mem, __FILE__, __LINE__)
#endif
#endif /* _MALLOC_H_ */
+61
View File
@@ -0,0 +1,61 @@
#ifndef _MATH_H_
#define _MATH_H_
#define FP_NAN 0
#define FP_INFINITE 1
#define FP_ZERO 2
#define FP_SUBNORMAL 3
#define FP_NORMAL 4
# ifndef HUGE_VALF
# define HUGE_VALF (__builtin_huge_valf())
# endif
# ifndef INFINITY
# define INFINITY (__builtin_inff())
# endif
# ifndef NAN
# define NAN (__builtin_nanf(""))
# endif
#define fpclassify(__x) (__builtin_fpclassify (FP_NAN, FP_INFINITE, \
FP_NORMAL, FP_SUBNORMAL, \
FP_ZERO, __x))
#ifndef isfinite
#define isfinite(__x) (__builtin_isfinite (__x))
#endif
#ifndef isinf
#define isinf(__x) (__builtin_isinf_sign (__x))
#endif
#ifndef isnan
#define isnan(__x) (__builtin_isnan (__x))
#endif
#define isnormal(__x) (__builtin_isnormal (__x))
float logf(float x);
float sqrtf(float x);
float powf(float x, float y);
float fabsf(float x);
float sinf(float x);
float cosf(float x);
#undef log
#define log(x) logf(x)
#undef pow
#define pow(x, y) powf(x, y)
#undef abs
#define abs(x) fabsf(x)
#undef fabs
#define fabs(x) fabsf(x)
#undef sqrt
#define sqrt(x) sqrtf(x)
#undef sin
#define sin(x) sinf(x)
#undef cos
#define cos(x) cosf(x)
#endif /* _MATH_H_ */
+14
View File
@@ -0,0 +1,14 @@
#ifndef _PWM_H_
#define _PWM_H_
#include <platform.h>
#include <sys/types.h>
#include <io.h>
#include <lib.h>
int pwm_enable(int pwm_id);
int pwm_disable(int pwm_id);
int pwm_config(int pwm_id, int duty_cycle_us, int period_us);
#endif
+18
View File
@@ -0,0 +1,18 @@
#ifndef _RESERVED_MEM_H_
#define _RESERVED_MEM_H_
#include <sys/types.h>
#include <compile.h>
void rsv_mem_init(uint32 start, uint32 len);
void *__rsv_mem_alloc(uint32 bytes, const char *file, int line);
#define reserved_mem_alloc(bytes) \
__rsv_mem_alloc(bytes, __FILENAME__, __LINE__)
void *__rsv_mem_align(uint32 alignment, uint32 bytes, const char *file, int line);
#define reserved_mem_align(alignment, bytes) \
__rsv_mem_align(alignment, bytes, __FILENAME__, __LINE__)
void dump_rsv_mem_info(void);
#endif /* ifndef _RESERVED_MEM_H_ */
+22
View File
@@ -0,0 +1,22 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#ifndef __SERIAL_H__
#define __SERIAL_H__
#include <sys/types.h>
/*-----------------------------------------------------------------
* serial interface
------------------------------------------------------------------*/
void serial_init(void);
void serial_putc(const char c);
void serial_puts(const char *s);
void serial_puts_always(const char *s);
void serial_put_dec(u32 dec);
void serial_put_hex(u32 hex);
void serial_put_hex_always(u32 hex);
char serial_getc(void);
#endif
+13
View File
@@ -0,0 +1,13 @@
#ifndef _STDARG_H_
#define _STDARG_H_
/******************************************************************************/
typedef __builtin_va_list va_list;
#define va_start(v,l) __builtin_va_start(v,l)
#define va_end(v) __builtin_va_end(v)
#define va_arg(v,l) __builtin_va_arg(v,l)
/******************************************************************************/
#endif /* _STDARG_H_ */
+8
View File
@@ -0,0 +1,8 @@
#ifndef _STDBOOL_H_
#define _STDBOOL_H_
#define true 1
#define false 0
#endif /* ifndef _STDBOOL_H_ */
+40
View File
@@ -0,0 +1,40 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#ifndef __STDDEFH__
#define __STDDEFH__
#include <sys/types.h>
#include <ctype.h>
#define _1K (0x400)
#define _2K (0x800)
#define _4K (0x1000)
#define _8K (0x2000)
#define _16K (0x4000)
#define _32K (0x8000)
#define _64K (0x10000)
#define _128K (0x20000)
#define _256K (0x40000)
#define _512K (0x80000)
#define _1M (0x100000)
#define _2M (0x200000)
#define _4M (0x400000)
#define _8M (0x800000)
#define _16M (0x1000000)
#define _32M (0x2000000)
#define _64M (0x4000000)
#define _128M (0x8000000)
#define _256M (0x10000000)
#define _512M (0x20000000)
#define _1G (0x40000000)
#define _2G (0x80000000)
#define _3G (0xC0000000)
#define _4G (0x100000000ULL)
#define _8G (0x200000000ULL)
#define _16G (0x400000000ULL)
#define _32G (0x800000000ULL)
#define _64G (0x1000000000ULL)
#endif /* __STDDEFH__ */
+7
View File
@@ -0,0 +1,7 @@
#ifndef _STDINT_H_
#define _STDINT_H_
#include <sys/types.h>
#endif
+54
View File
@@ -0,0 +1,54 @@
#ifndef _STDIO_H_
#define _STDIO_H_
/******************************************************************************/
#include <config.h>
#include <stddef.h>
int sprintf(char *buf, const char *cfmt, ...);
int snprintf(char *str, size_t size, const char *format, ...);
int getchar(void);
void puts_always(const char *s);
void puthex_always(unsigned int hex);
#ifdef CONFIG_PRINT
#ifdef CONFIG_PRINTF
int printf(const char *cfmt, ...);
#else
# define printf(_cfmt, ...)
#endif
int putchar(int c);
int puts(const char *s);
void puthex(unsigned int hex);
void putdec(unsigned int dec);
#else
# define printf(_cfmt, ...)
# define putchar(c)
# define puts(_s)
# define puthex(hex)
# define putdec(dec)
#endif
#ifndef MOULE_NAME
#define MOULE_NAME ""
#endif
#define pr_error(_fmt, args...) printf(MOULE_NAME _fmt, ##args)
#define pr_warn(_fmt, args...) printf(MOULE_NAME _fmt, ##args)
#define pr_info(_fmt, args...) printf(MOULE_NAME _fmt, ##args)
#ifdef PR_DEBUG
# define pr_debug(_fmt, args...) printf(MOULE_NAME _fmt, ##args)
#else
# define pr_debug(_fmt, args...)
#endif /* pr_debug */
#define bug(_fmt, args...) { \
printf(MOULE_NAME "%s(%d): "_fmt, __FILE__, __LINE__, ##args); \
while (1); }
/******************************************************************************/
#endif /* _STDIO_H_ */
+7
View File
@@ -0,0 +1,7 @@
#ifndef _STDLIB_H_
#define _STDLIB_H_
#include <malloc.h>
#endif /* _STDLIB_H_ */
+41
View File
@@ -0,0 +1,41 @@
#ifndef _STRING_H_
#define _STRING_H_
/******************************************************************************/
#include <stddef.h>
extern char const hex2ascii_data[];
#define hex2ascii(hex) (hex2ascii_data[hex])
#define imax(_a, _b) ((_a) > (_b) ? (_a) : (_b))
#define bcpy(src, dst, len) memcpy((dst), (src), (len))
#define bzero(buf, size) memset((buf), 0, (size))
#define bcmp(b1, b2, len) (memcmp((b1), (b2), (len)) != 0)
void *memmove(void *dest, const void *src, size_t size);
void *memcpy(void *dst, const void *src, size_t len);
void *memset(void *b, int c, size_t len);
int memcmp(const void *b1, const void *b2, size_t len);
int strncmp(const char *s1, const char *s2, size_t len);
uint32_t strnlen(const char *s, uint32_t len);
unsigned long strtoul(const char *nptr, char **endptr, int base);
uint64_t strtoull(const char *nptr, char **endptr, int base);
char *strncpy(char * dst, const char * src, size_t n);
uint64_t memparse(const char *ptr, char **retptr);
char *strndup(const char *str, size_t n);
char *strtok(char *s, const char *delim);
int strcmp(const char *s1, const char *s2);
void strcpy(char *dst, const char *src);
void strcat(char *dst, const char *src);
char *strncat(char *dst, const char *src, size_t n);
char *strchr(const char *s, char ch);
char *strdup(const char *s);
size_t strlen(const char *s);
char *strstr(const char *s1, const char *s2);
/******************************************************************************/
#endif /* _STRING_H_ */
+65
View File
@@ -0,0 +1,65 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#ifndef __TYPES_H__
#define __TYPES_H__
typedef signed char s8;
typedef unsigned char u8;
typedef signed short s16;
typedef unsigned short u16;
typedef signed int s32;
typedef unsigned int u32;
typedef signed long long s64;
typedef unsigned long long u64;
typedef signed char int8_t;
typedef unsigned char uint8_t;
typedef signed short int16_t;
typedef unsigned short uint16_t;
typedef signed int int32_t;
typedef unsigned int uint32_t;
typedef long long int64_t;
typedef unsigned long long uint64_t;
typedef long long intmax_t;
typedef unsigned long long uintmax_t;
typedef unsigned char uchar;
typedef unsigned long ulong;
typedef unsigned int uint;
typedef unsigned char uint8;
typedef char int8;
typedef unsigned short uint16;
typedef short int16;
typedef unsigned int uint32;
typedef int int32;
typedef unsigned long uintptr_t;
typedef unsigned int size_t;
#define BITS_PER_LONG 32
#undef NULL
#define NULL ((void *)0)
typedef int bool;
#define true 1
#define false 0
#define ERROR -1
#define OK 0
#define SZ_4M 0x400000
#define SZ_8M 0x800000
#define SZ_16M 0x1000000
#define SZ_128M 0x8000000
#define SZ_256M 0x10000000
#define SZ_512M 0x20000000
#define SZ_750M 0x30000000
#define SZ_1G 0x40000000
#define SZ_2G 0x80000000
#define SZ_3G 0xc0000000
#define SZ_4G 0x100000000
#endif
+7
View File
@@ -0,0 +1,7 @@
#ifndef _TIME_H_
#define _TIME_H_
#include <timer.h>
#endif /* _TIME_H_ */
+16
View File
@@ -0,0 +1,16 @@
#ifndef _TIMER_H_
#define _TIMER_H_
#include <sys/types.h>
#include <io.h>
#include <lib.h>
void timer_init(void);
void timer_start(void);
ulong timer_get_val(void);
void udelay(ulong us);
void mdelay(u32 msec);
#endif /* _TIMER_H_ */
+15
View File
@@ -0,0 +1,15 @@
#ifndef _UT_CASE_H_
#define _UT_CASE_H_
void test_math(void);
void test_libc(void);
void test_time(void);
void test_multi_stage_in_stage1(void);
void test_multi_stage_in_stage2(void);
void test_submakefile1(void);
void test_reserved_mem(void);
int run_ut_in_stage1(void);
int run_ut_in_stage2(void);
#endif /* ifndef _UT_CASE_H_ */
+7
View File
@@ -0,0 +1,7 @@
#ifndef __VERSION_H__
#define __VERSION_H__
#define MCU_VERSION "v1.00"
#endif
+3
View File
@@ -0,0 +1,3 @@
SRCS-y += main.c
SRCS-$(CONFIG_SIMPILE_SHELL) += shell.c
+63
View File
@@ -0,0 +1,63 @@
#include <platform.h>
#include <sys/types.h>
#include <common.h>
#include <version.h>
#include <timer.h>
#include <image.h>
#include <i2c.h>
#include <ut_case.h>
#include "media_sample.h"
int *__errno(void)
{
return NULL;
}
void show_version(void)
{
#ifdef CONFIG_DEBUG_INFO
puts("\nRISC-V MCU code - ");
puts(MCU_VERSION"\n");
puts("Build: ");
puts(__DATE__" - "__TIME__"\n");
puts("\n");
#endif
}
unsigned int main(void)
{
__attribute__((unused)) int ret;
show_version();
#ifdef CONFIG_MEDIA_SAMPLE_QUICKSTART
quickstart_media_preinit();
ret = run_stage2_func(quickstart_media_start);
if (ret != 0) {
puts("UT is Failed\n");
goto sleep;
}
#endif
#ifdef CONFIG_UT_ENABLE
ret = run_ut_in_stage1();
if (ret != 0) {
puts("UT in stage1 Failed\n");
goto sleep;
}
ret = run_stage2_func(run_ut_in_stage2);
if (ret != 0) {
puts("UT in stage2 Failed\n");
goto sleep;
}
#endif
#ifdef CONFIG_SIMPILE_SHELL
start_shell();
#endif
sleep: __attribute__((unused))
while(1) {
__WFI();
}
return 0;
}
+289
View File
@@ -0,0 +1,289 @@
#include <stdio.h>
#include <string.h>
#include <config.h>
#include <lib.h>
#include <timer.h>
#include <serial.h>
#define CMD_BUFF_LEN 16
#define REV_BUFF_LEN 128
typedef enum {
CMD_0 = 0,
CMD_1,
CMD_2,
CMD_3,
CMD_4,
CMD_5,
CMD_6,
CMD_7,
CMD_8,
CMD_9,
CMD_10,
CMD_11,
CMD_12,
CMD_13,
CMD_14,
CMD_15,
CMD_16
} cmd_len;
static void show_help(void)
{
puts("usage: \n");
puts(" help -- show command infomation \n");
puts(" mw [addr] [value] -- write [value] to [addr] \n");
puts(" both need be hex and start with 0x or 0X \n");
puts(" md [addr] [length] -- read from [addr] and print to the console \n");
puts(" total read [length] bytes data \n");
puts(" both need be hex and start with 0x or 0X \n");
}
static u32 read_line(u8 *buff, u32 buff_len)
{
u32 recv_len = 0;
char c = 0;
while (1) {
c = getchar();
if (c == '\n' || c == '\r') {
serial_putc('\n');
break;
}
if (recv_len < buff_len) {
serial_putc(c);
buff[recv_len++] = c;
} else {
return FAILURE;
}
}
if (recv_len < (buff_len - 1)) {
buff[recv_len + 1] = '\0';
}
return recv_len;
}
/* return value : index is started from 0 */
static u32 str_get_pos(u8 *buff, u32 buff_len, char c)
{
u32 index = 0;
for (; index < buff_len; index++) {
if (c == buff[index]) {
return index;
}
}
if (index == buff_len) {
return index;
}
return FAILURE;
}
/* find the cmd dilived by the space */
static u32 get_cmd(u8 *cmd, u32 cmd_buff_len, u8 *buff, u32 buff_len)
{
u32 cmd_len = 0;
/* the cmd is divided by space */
cmd_len = str_get_pos(buff, buff_len, ' ');
if (cmd_len == 0 || cmd_len == FAILURE || cmd_len > cmd_buff_len) {
return FAILURE;
}
for (u32 i = 0; i < cmd_len; i++) {
cmd[i] = buff[i];
}
if (cmd_len < (cmd_buff_len - 1)) {
cmd[cmd_len + 1] = '\0';
}
return cmd_len;
}
static u8 char_to_hex(u8 value)
{
if((value <= '9') && (value >= '0')) {
return (value - '0');
} else if ((value <= 'f') && ((value >= 'a'))) {
return (value - 'a' + 0x0a);
} else if ((value <= 'F') && (value >= 'A')) {
return (value - 'A' + 0x0a);
} else {
puts("Data format error!\n");
return -1;
}
}
static u32 pow_t(u32 v, u32 n)
{
u32 value = v;
if (n == 0) {
return 1;
} else if (n == 1) {
return v;
}
for (u32 i = 1; i < n; i++) {
value = value * v;
}
return value;
}
static u32 str_to_hex(u8 *str, u32 str_len)
{
u32 hex = 0;
for (int i = 0; i < str_len; i++) {
hex += char_to_hex(str[i]) * pow_t(16, (str_len - i - 1));
}
return hex;
}
static u32 get_params(u8 * buff, u32 buff_Len, u32 *param_len)
{
u8 param_s[10];
*param_len = get_cmd(param_s, 10, buff, buff_Len);
if (*param_len < 2 || *param_len == FAILURE) {
puts("command error, too few params!\n");
return FAILURE;
}
if (param_s[0] != '0' && (param_s[1] != 'x' || param_s[1] != 'X')) {
puts("command error, params should start with 0x or 0X\n");
return FAILURE;
}
return str_to_hex(param_s + 2, *param_len - 2);
}
/*
* input: [addr] [value]
*/
void memory_write(u8 *buff, u32 buff_Len)
{
u32 addr_len = 0;
u32 value_len = 0;
u32 addr = 0;
u32 value = 0;
/* get address */
addr = get_params(buff, buff_Len, &addr_len);
if (addr == FAILURE) {
return;
}
/* get value */
value = get_params(buff + addr_len + 1, buff_Len - addr_len - 1, &value_len);
if (value == FAILURE) {
return;
}
puts("write address=0x");
serial_put_hex(addr);
puts(" value=0x");
serial_put_hex(value);
puts("\n");
writel(value, addr);
}
/*
* input: [addr] [length]
*/
void memory_read(u8 *buff, u32 buff_Len)
{
u32 addr_len = 0;
u32 length_len = 0;
u32 addr = 0;
u32 length = 0;
u32 value = 0;
/* get address */
addr = get_params(buff, buff_Len, &addr_len);
if (addr == FAILURE) {
return;
}
/* get length */
length = get_params(buff + addr_len + 1, buff_Len - addr_len - 1, &length_len);
if (length == FAILURE) {
return;
}
if (length % 4 != 0) {
puts("error: length should be align with 4\n");
return;
}
/* read and print */
for (u32 i = 0; i < length / 4; i++) {
value = readl(addr + i * 4);
if (i % 4 == 0) {
serial_put_hex(addr + i * 4);
puts(": ");
}
serial_put_hex(value);
puts(" ");
if (i % 4 == 3) {
puts("\n");
}
}
puts("\n");
}
u32 start_shell(void)
{
u8 buff[REV_BUFF_LEN];
u32 recv_len = 0;
u8 cmd[CMD_BUFF_LEN];
u32 cmd_len = 0;
puts("\n## Micro shell ##\n");
/* cmd [param1] [param2] ... */
while (1) {
puts("# ");
memset_s(buff, REV_BUFF_LEN, 0, REV_BUFF_LEN);
memset_s(cmd, CMD_BUFF_LEN, 0, CMD_BUFF_LEN);
recv_len = read_line(buff, REV_BUFF_LEN);
if (recv_len == 0 || recv_len == FAILURE) {
continue;
}
cmd_len = get_cmd(cmd, CMD_BUFF_LEN, buff, recv_len);
if (cmd_len == FAILURE) {
continue;
}
switch (cmd_len) {
case CMD_2:
if (memcmp(cmd, "mw", CMD_2) == SUCCESS) {
/* mw [addr] [value]; addr and value should start with 0x/0X */
memory_write(buff + cmd_len + 1, recv_len - cmd_len - 1);
} else if (memcmp(cmd, "md", CMD_2) == SUCCESS) {
/* md [addr] [length]; addr and length should start with 0x/0X */
memory_read(buff + cmd_len + 1, recv_len - cmd_len - 1);
}
break;
case CMD_4:
if (memcmp(cmd, "help", CMD_4) == SUCCESS) {
show_help();
}
default:
puts("Unknown command!\n");
break;
}
}
return SUCCESS;
}
+8
View File
@@ -0,0 +1,8 @@
SRCS-y += lib.c stdio.c div64.c
SRCS-$(CONFIG_PRINTF) += printf.c
ifdef CONFIG_MALLOC
SRCS-y += malloc.c memlib.c
else
SRCS-y += simple_malloc.c
endif
SRCS-y += reserved_mem.c
+34
View File
@@ -0,0 +1,34 @@
#include <sys/types.h>
uint32_t __div64_32(uint64_t *n, uint32_t base)
{
uint64_t rem = *n;
uint64_t b = base;
uint64_t res, d = 1;
uint32_t high = rem >> 32;
res = 0;
if (high >= base) {
high /= base;
res = (uint64_t) high << 32;
rem -= (uint64_t) (high * base) << 32;
}
while ((int64_t)b > 0 && b < rem) {
b = b + b;
d = d + d;
}
do {
if (rem >= b) {
rem -= b;
res += d;
}
b >>= 1;
d >>= 1;
} while (d);
*n = res;
return rem;
}
+216
View File
@@ -0,0 +1,216 @@
#include <stdio.h>
#include <lib.h>
#include <serial.h>
int memset_s(void* dest, size_t destMax, unsigned char c, size_t count)
{
unsigned char *__dest = (unsigned char *)dest;
if (destMax == 0 || destMax > SECUREC_MEM_MAX_LEN) {
return FAILURE;
}
if (__dest == NULL) {
return FAILURE;
}
if (count > destMax) {
while (destMax--)
*__dest++ = (unsigned char)c; /*set entire buffer to value c*/
return FAILURE;
}
while (count--)
*__dest++ = (unsigned char)c;
return SUCCESS;
}
int memset(void* dest, unsigned char c, size_t count)
{
return memset_s(dest, SECUREC_MEM_MAX_LEN, c, count);
}
int memcpy_s(void* dest, size_t destMax, const void* src, size_t count)
{
unsigned char *__dest = (unsigned char *)dest;
unsigned char *__src = (unsigned char *)src;
if (destMax == 0 || destMax > SECUREC_MEM_MAX_LEN ) {
return FAILURE;
}
if (__dest == NULL || __src == NULL) {
if (__dest != NULL ) {
while (destMax--)
*__dest++ = 0; /*set entire buffer to value 0 */
return FAILURE;
}
return FAILURE;
}
if (count > destMax) {
while (destMax--)
*__dest++ = 0; /*set entire buffer to value 0 */
return FAILURE;
}
if (__dest == __src) {
return SUCCESS;
}
if ((__dest > __src && __dest < ((u8*)__src + count)) ||
(__src > __dest && __src < ((u8*)__dest + count)) ) {
while (destMax--)
*__dest++ = 0; /*set entire buffer to value 0 */
return FAILURE;
}
while (count--)
*__dest++ = *__src++;
return SUCCESS;
}
void *memcpy(void *dst, const void *src, size_t len)
{
if(SUCCESS == memcpy_s(dst, len, src, len))
return dst;
return NULL;
}
int memcmp(const void *b1, const void *b2, size_t len)
{
int res = 0;
const char *d = b1;
const char *s = b2;
if (b1 == NULL || b2 == NULL) {
puts("memcmp : Invalid args\n");
return res;
}
while (len > 0) {
res = *d - *s;
if (res != 0)
break;
d++;
s++;
len--;
}
return res;
}
u32 strlen(const char * s)
{
const char *sc;
for (sc = s; *sc != '\0'; ++sc)
/* nothing */;
return sc - s;
}
char *strcat(char *dest, const char *src)
{
char *tmp = dest;
while (*dest)
dest++;
while ((*dest++ = *src++) != '\0')
;
return tmp;
}
char *strcpy(char *dest, const char*src)
{
char *tmp = dest;
while (*src != '\0') {
*dest = *src;
dest++;
src++;
}
*dest = '\0';
return tmp;
}
char *strncpy(char *dest, char *src, size_t n)
{
char *tmp = dest;
while (n > 0 && *src != '\0') {
*dest = *src;
dest++;
src++;
n--;
}
while (n > 0) {
*dest = '\0';
dest++;
n--;
}
return tmp;
}
int strcmp(const char *s1, const char *s2) {
while (*s1 && (*s1 == *s2)) {
s1++;
s2++;
}
return *(const unsigned char*)s1 - *(const unsigned char*)s2;
}
int strncmp(const char *s1, const char *s2, size_t n) {
if (n == 0)
return 0;
do {
if (*s1 != *s2++)
return *(const unsigned char*)s1 - *(const unsigned char*)--s2;
if (*s1++ == 0)
break;
} while (--n != 0);
return 0;
}
/*****************************************************************************/
/* for gcc -fstack-protector-all */
unsigned long __stack_chk_guard = 0x000a0dff;
void __stack_chk_fail(void)
{
serial_puts("Stack is corrupted\n");
while (1) {
reset_cpu();
}
}
unsigned short crc16(unsigned char *data, unsigned int length)
{
unsigned int i;
unsigned short crc_table;
unsigned short crc = 0xffff;
unsigned char inter1;
unsigned char inter2;
if (data == NULL)
return (crc);
for (i = 0; i < length; ++i) {
inter1 = data[i] ^ ((unsigned char) crc);
inter2 = (unsigned char) (inter1 ^ (inter1 << 4)); /* bit size 4 */
crc_table = (inter2 << 8) ^ (inter2 << 3) ^ (inter2 >> 4); /* bit size 8 3 4 */
crc = (crc >> 8) ^ crc_table; /* bit size 8 */
}
crc ^= 0xffff;
return (crc);
}
+46
View File
@@ -0,0 +1,46 @@
#include <stddef.h>
#include <hlist.h>
#include "memlib.h"
static struct list g_malloc_list = {0};
void malloc_init(unsigned int base, unsigned int size)
{
if ((g_malloc_list.base.next != NULL) && (g_malloc_list.base.prev != NULL)) {
return;
}
memlib_init(&g_malloc_list, base, size);
}
void *malloc(uint32 bytes)
{
if ((g_malloc_list.base.next == NULL) || (g_malloc_list.base.prev == NULL)) {
return NULL;
}
return memlib_malloc(&g_malloc_list, bytes);
}
void *memalign(uint32 alignment, uint32 bytes)
{
if ((g_malloc_list.base.next == NULL) || (g_malloc_list.base.prev == NULL)) {
return NULL;
}
return memlib_memalign(&g_malloc_list, alignment, bytes);
}
void free(void *ptr)
{
if ((g_malloc_list.base.next == NULL) || (g_malloc_list.base.prev == NULL)) {
return;
}
memlib_free(&g_malloc_list, ptr);
}
void show_memnode(unsigned int cnt)
{
if ((g_malloc_list.base.next == NULL) || (g_malloc_list.base.prev == NULL)) {
return;
}
memlib_show_memnode(&g_malloc_list, cnt);
}
+205
View File
@@ -0,0 +1,205 @@
#include <stddef.h>
#include <hlist.h>
#include <stdio.h>
#define MEM_ALLOC_MAGIC_NUM 0xACCA5995
typedef struct _mem_node {
uint32 magicnum;
struct node nodeinfo;
/* Size & flag of the current node (the high two bits represent a flag,and the rest bits specify the size) */
uint32 size_flag;
}mem_node;
uint32 g_heap_start = 0;
uint32 g_heap_end = 0;
#define around(size, align) (((size) + (align) - 1) & (~((align) - 1)))
#define MEM_NODE_HEAD_SIZE sizeof(struct _mem_node)
#define MEM_ALIGN_SIZE 4
#define MEM_NODE_USED_FLAG 0x80000000U
#define MEM_NODE_ALIGNED_FLAG 0x40000000U
#define MEM_NODE_ALIGNED_AND_USED_FLAG (MEM_NODE_USED_FLAG | MEM_NODE_ALIGNED_FLAG)
#define mem_node_get_used_flag(size_flag) ((size_flag) & MEM_NODE_USED_FLAG)
#define mem_node_set_used_flag(size_flag) ((size_flag) = ((size_flag) | MEM_NODE_USED_FLAG))
#define mem_node_get_aligned_gapsize(sizeAndFlag) ((sizeAndFlag) & ~MEM_NODE_ALIGNED_FLAG)
#define mem_node_get_aligned_flag(size_flag) ((size_flag) & MEM_NODE_ALIGNED_FLAG)
#define mem_node_set_aligned_flag(size_flag) ((size_flag) = ((size_flag) | MEM_NODE_ALIGNED_FLAG))
#define mem_node_get_size(size_flag) ((size_flag) & ~MEM_NODE_ALIGNED_AND_USED_FLAG)
#define mem_node_clear_used_aligned_flag(size_flag) ((size_flag) = (size_flag) & (~ (MEM_NODE_ALIGNED_AND_USED_FLAG)))
#define is_pow_two(value) ((((uintptr_t)(value)) & ((uintptr_t)(value) - 1)) == 0)
#define is_aligned(value, alignSize) ((((uintptr_t)(value)) & ((uintptr_t)((alignSize) - 1))) == 0)
void memlib_init(struct list *listhead, unsigned int base, unsigned int size)
{
mem_node *firstnode = (mem_node *)(uintptr_t)(base);
if (mem_node_get_used_flag(size) || mem_node_get_aligned_flag(size)) {
printf("malloc init failed, size:0x%x\n", size);
return;
}
list_init(listhead);
firstnode->magicnum = MEM_ALLOC_MAGIC_NUM;
firstnode->size_flag = size;
list_add_tail(listhead, &firstnode->nodeinfo);
g_heap_start = base;
g_heap_end = base + size;
#ifdef CONFIG_DEBUG_INFO
puts("malloc init,base: 0x");puthex(g_heap_start);puts(", size: ");putdec(size);puts("\n");
#endif
}
static void *mem_find_freeblock(struct list *listhead, uint32 allocsize)
{
mem_node *entry = NULL;
mem_node *tmp = NULL;
mem_node *newnode = NULL;
unsigned int nodesize;
list_for_each_entry_safe(entry, tmp, listhead, mem_node, nodeinfo) {
nodesize = mem_node_get_size(entry->size_flag);
if ((!mem_node_get_used_flag(entry->size_flag)) && nodesize >= allocsize) {
if ((nodesize - allocsize) < (MEM_NODE_HEAD_SIZE + MEM_ALIGN_SIZE)) {
mem_node_set_used_flag(entry->size_flag);
return entry + 1;
} else {
newnode = (mem_node *)((uintptr_t)entry + allocsize);
newnode->magicnum = MEM_ALLOC_MAGIC_NUM;
newnode->size_flag = entry->size_flag - allocsize;
entry->size_flag = allocsize;
mem_node_set_used_flag(entry->size_flag);
list_insert_backward(&entry->nodeinfo, &newnode->nodeinfo); /* newnode 插入到 entry 后面 */
return entry + 1;
}
}
}
printf("no suitable free mem block\n");
return NULL;
}
void *memlib_malloc(struct list *listhead, uint32 bytes)
{
void *ptr = NULL;
if (bytes == 0) {
return NULL;
}
uint32 allocsize = around(bytes + MEM_NODE_HEAD_SIZE, MEM_ALIGN_SIZE);
ptr = mem_find_freeblock(listhead, allocsize);
return ptr;
}
void *memlib_memalign(struct list *listhead, uint32 alignment, uint32 bytes)
{
uint32 gap_size;
uint32 use_size;
void *ptr = NULL;
void *align_ptr = NULL;
mem_node *node = NULL;
if (bytes == 0 || alignment == 0 || !is_pow_two(alignment) || !is_aligned(alignment, sizeof(void*))) {
return NULL;
}
/*
* sizeof(gap_size) bytes stores offset between align_ptr and ptr,
* the ptr has been OS_MEM_ALIGN_SIZE(4 or 8) aligned, so maximum
* offset between alignedPtr and ptr is alignment - OS_MEM_ALIGN_SIZE
*/
if ((alignment - sizeof(gap_size)) > ((uint32)(-1) - bytes)) {
return NULL;
}
use_size = around(bytes + MEM_NODE_HEAD_SIZE + alignment - sizeof(gap_size), MEM_ALIGN_SIZE);
if (mem_node_get_used_flag(use_size) || mem_node_get_aligned_flag(use_size)) {
printf("size is too large:0x%x\n", use_size);
return NULL;
}
ptr = mem_find_freeblock(listhead, use_size);
if (ptr == NULL) {
return NULL;
}
align_ptr = (void *)around((uintptr_t)ptr, alignment);
if (ptr == align_ptr) {
return ptr;
}
gap_size = (uintptr_t)align_ptr - (uintptr_t)ptr;
mem_node_set_aligned_flag(gap_size);
node = (mem_node *)ptr - 1;
mem_node_set_aligned_flag(node->size_flag);
*(uint32 *)((uintptr_t)align_ptr - sizeof(gap_size)) = gap_size;
ptr = align_ptr;
return ptr;
}
void *memptr_to_node(void *ptr)
{
uint32 gapsize;
if (((uintptr_t)ptr) & (MEM_ALIGN_SIZE - 1)) {
printf("ptr not align by 4byte\n");
return NULL;
}
gapsize = *(uint32 *)((uintptr_t)ptr - sizeof(uint32));
if (mem_node_get_aligned_flag(gapsize) && mem_node_get_used_flag(gapsize)) {
printf("gapsize:0x%x error\n", gapsize);
return NULL;
}
if (mem_node_get_aligned_flag(gapsize)) {
gapsize = mem_node_get_aligned_gapsize(gapsize);
if ((gapsize & (MEM_ALIGN_SIZE - 1)) || (gapsize > ((uintptr_t)ptr - MEM_NODE_HEAD_SIZE))) {
return NULL;
}
ptr = (void *)((uintptr_t)ptr - gapsize);
}
return (void *)((uintptr_t)ptr - MEM_NODE_HEAD_SIZE);
}
void memlib_free(struct list *listhead, void *ptr)
{
mem_node *entry = NULL;
mem_node *next_entry = NULL;
mem_node *pre_entry = NULL;
if (ptr == NULL) {
return;
}
entry = (mem_node *)memptr_to_node(ptr);
if (entry == NULL) {
return;
}
if (entry->magicnum != MEM_ALLOC_MAGIC_NUM) {
printf("MAGIC NUM is wrong! magicnum:0x%x\n", entry->magicnum);
return;
}
if (!mem_node_get_used_flag(entry->size_flag)) {
return;
}
mem_node_clear_used_aligned_flag(entry->size_flag);
next_entry = list_next_entry(entry, listhead, mem_node, nodeinfo);
if (next_entry != NULL) {
if (!mem_node_get_used_flag(next_entry->size_flag)) {
entry->size_flag += next_entry->size_flag;
next_entry->magicnum = 0;
list_remove(&next_entry->nodeinfo);
}
}
pre_entry = list_prev_entry(entry, listhead, mem_node, nodeinfo);
if (pre_entry != NULL) {
if (!mem_node_get_used_flag(pre_entry->size_flag)) {
pre_entry->size_flag += entry->size_flag;
entry->magicnum = 0;
list_remove(&entry->nodeinfo);
}
}
}
void memlib_show_memnode(struct list *listhead, unsigned int cnt)
{
mem_node *entry = NULL;
uint32 i = 0;
list_for_each_entry(entry, listhead, mem_node, nodeinfo) {
printf("%d:entry, magic:0x%x, size: %d, used:0x%x, aligned:0x%x\n", i++, entry->magicnum,
mem_node_get_size(entry->size_flag), mem_node_get_used_flag(entry->size_flag),
mem_node_get_aligned_flag(entry->size_flag));
if (cnt != 0 && i == cnt) {
break;
}
}
}
+12
View File
@@ -0,0 +1,12 @@
#ifndef _MEM_LIB_H_
#define _MEM_LIB_H_
#include <hlist.h>
void memlib_init(struct list *listhead, unsigned int base, unsigned int size);
void *memlib_malloc(struct list *listhead, unsigned int bytes);
void *memlib_memalign(struct list *listhead, unsigned int alignment, unsigned int bytes);
void memlib_free(struct list *listhead, void *ptr);
void memlib_show_memnode(struct list *listhead, unsigned int cnt);
#endif /* _MEM_LIB_H_ */
+995
View File
@@ -0,0 +1,995 @@
///////////////////////////////////////////////////////////////////////////////
// \author (c) Marco Paland (info@paland.com)
// 2014-2019, PALANDesign Hannover, Germany
//
// \license The MIT License (MIT)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
// \brief Tiny printf, sprintf and (v)snprintf implementation, optimized for speed on
// embedded systems with a very limited resources. These routines are thread
// safe and reentrant!
// Use this instead of the bloated standard/newlib printf cause these use
// malloc for printf (and may not be thread safe).
//
///////////////////////////////////////////////////////////////////////////////
#include <stdarg.h>
#include <stddef.h>
/* #include <sys/stat.h> */
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
// define this globally (e.g. gcc -DPRINTF_INCLUDE_CONFIG_H ...) to include the
// printf_config.h header file
// default: undefined
#ifdef PRINTF_INCLUDE_CONFIG_H
#include "printf_config.h"
#endif
// 'ntoa' conversion buffer size, this must be big enough to hold one converted
// numeric number including padded zeros (dynamically created on stack)
// default: 32 byte
#ifndef PRINTF_NTOA_BUFFER_SIZE
#define PRINTF_NTOA_BUFFER_SIZE 32U
#endif
// 'ftoa' conversion buffer size, this must be big enough to hold one converted
// float number including padded zeros (dynamically created on stack)
// default: 32 byte
#ifndef PRINTF_FTOA_BUFFER_SIZE
#define PRINTF_FTOA_BUFFER_SIZE 32U
#endif
// support for the floating point type (%f)
// default: activated
#ifndef PRINTF_DISABLE_SUPPORT_FLOAT
#define PRINTF_SUPPORT_FLOAT
#endif
// support for exponential floating point notation (%e/%g)
// default: activated
#ifndef PRINTF_DISABLE_SUPPORT_EXPONENTIAL
#define PRINTF_SUPPORT_EXPONENTIAL
#endif
// define the default floating point precision
// default: 6 digits
#ifndef PRINTF_DEFAULT_FLOAT_PRECISION
#define PRINTF_DEFAULT_FLOAT_PRECISION 6U
#endif
// define the largest float suitable to print with %f
// default: 1e9
#ifndef PRINTF_MAX_FLOAT
#define PRINTF_MAX_FLOAT 1e9
#endif
// support for the long long types (%llu or %p)
// default: activated
#ifndef PRINTF_DISABLE_SUPPORT_LONG_LONG
#define PRINTF_SUPPORT_LONG_LONG
#endif
// support for the ptrdiff_t type (%t)
// ptrdiff_t is normally defined in <stddef.h> as long or long long type
// default: activated
/* #ifndef PRINTF_DISABLE_SUPPORT_PTRDIFF_T
* #define PRINTF_SUPPORT_PTRDIFF_T
* #endif */
///////////////////////////////////////////////////////////////////////////////
// internal flag definitions
#define FLAGS_ZEROPAD (1U << 0U)
#define FLAGS_LEFT (1U << 1U)
#define FLAGS_PLUS (1U << 2U)
#define FLAGS_SPACE (1U << 3U)
#define FLAGS_HASH (1U << 4U)
#define FLAGS_UPPERCASE (1U << 5U)
#define FLAGS_CHAR (1U << 6U)
#define FLAGS_SHORT (1U << 7U)
#define FLAGS_LONG (1U << 8U)
#define FLAGS_LONG_LONG (1U << 9U)
#define FLAGS_PRECISION (1U << 10U)
#define FLAGS_ADAPT_EXP (1U << 11U)
// import float.h for DBL_MAX
#if defined(PRINTF_SUPPORT_FLOAT)
#include <float.h>
#endif
/* int _close(int fd)
* {
* return -1;
* }
*
* caddr_t _sbrk(int incr)
* {
* return NULL;
* }
*
* int _fstat(int fd, struct stat* st)
* {
* return -1;
* }
*
* int _isatty(int fd)
* {
* if (fd == (int)stdout || fd == (int)stderr)
* return 1;
*
* return 0;
* }
*
* long _lseek(int fd, off_t ptr, int dir)
* {
* return -1;
* }
*
* int _read(int fd, void* ptr, size_t len)
* {
* return -1;
* }
*
* int _write(int fd, const void* buffer, size_t count)
* {
* char *s = (char *)buffer;
* if (_isatty(fd))
* {
* for (int i = 0; i < count; i++)
* {
* fputc(*s, (void *)-1);
* return count;
* }
* }
*
* return -1;
* } */
/* int putc(int c, FILE *stream)
* {
* return fputc(c, stream);
* } */
/* int puts(const char *s)
* {
* while(*s !='\0')
* {
* putchar(*s);
* s++;
* }
* putchar('\n');
* return 0;
* } */
// output function type
typedef void (*out_fct_type)(char character, void* buffer, size_t idx, size_t maxlen);
// wrapper (used as buffer) for output function type
typedef struct {
void (*fct)(char character, void* arg);
void* arg;
} out_fct_wrap_type;
// internal buffer output
static inline void _out_buffer(char character, void* buffer, size_t idx, size_t maxlen)
{
if (idx < maxlen) {
((char*)buffer)[idx] = character;
}
}
// internal null output
static inline void _out_null(char character, void* buffer, size_t idx, size_t maxlen)
{
(void)character; (void)buffer; (void)idx; (void)maxlen;
}
static inline void _out_char(char character, void* buffer, size_t idx, size_t maxlen)
{
(void)buffer; (void)idx; (void)maxlen;
if (character) {
putchar(character);
}
}
// internal output function wrapper
static inline void _out_fct(char character, void* buffer, size_t idx, size_t maxlen)
{
(void)idx; (void)maxlen;
if (character) {
// buffer is the output fct pointer
((out_fct_wrap_type*)buffer)->fct(character, ((out_fct_wrap_type*)buffer)->arg);
}
}
// internal secure strlen
// \return The length of the string (excluding the terminating 0) limited by 'maxsize'
static inline unsigned int _strnlen_s(const char* str, size_t maxsize)
{
const char* s;
for (s = str; *s && maxsize--; ++s);
return (unsigned int)(s - str);
}
// internal test if char is a digit (0-9)
// \return true if char is a digit
static inline bool _is_digit(char ch)
{
return (ch >= '0') && (ch <= '9');
}
// internal ASCII string to unsigned int conversion
static unsigned int _atoi(const char** str)
{
unsigned int i = 0U;
while (_is_digit(**str)) {
i = i * 10U + (unsigned int)(*((*str)++) - '0');
}
return i;
}
// output the specified string in reverse, taking care of any zero-padding
static size_t _out_rev(out_fct_type out, char* buffer, size_t idx, size_t maxlen, const char* buf, size_t len, unsigned int width, unsigned int flags)
{
const size_t start_idx = idx;
// pad spaces up to given width
if (!(flags & FLAGS_LEFT) && !(flags & FLAGS_ZEROPAD)) {
for (size_t i = len; i < width; i++) {
out(' ', buffer, idx++, maxlen);
}
}
// reverse string
while (len) {
out(buf[--len], buffer, idx++, maxlen);
}
// append pad spaces up to given width
if (flags & FLAGS_LEFT) {
while (idx - start_idx < width) {
out(' ', buffer, idx++, maxlen);
}
}
return idx;
}
// internal itoa format
static size_t _ntoa_format(out_fct_type out, char* buffer, size_t idx, size_t maxlen, char* buf, size_t len, bool negative, unsigned int base, unsigned int prec, unsigned int width, unsigned int flags)
{
// pad leading zeros
if (!(flags & FLAGS_LEFT)) {
if (width && (flags & FLAGS_ZEROPAD) && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) {
width--;
}
while ((len < prec) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
buf[len++] = '0';
}
while ((flags & FLAGS_ZEROPAD) && (len < width) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
buf[len++] = '0';
}
}
// handle hash
if (flags & FLAGS_HASH) {
if (!(flags & FLAGS_PRECISION) && len && ((len == prec) || (len == width))) {
len--;
if (len && (base == 16U)) {
len--;
}
}
if ((base == 16U) && !(flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
buf[len++] = 'x';
}
else if ((base == 16U) && (flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
buf[len++] = 'X';
}
else if ((base == 2U) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
buf[len++] = 'b';
}
if (len < PRINTF_NTOA_BUFFER_SIZE) {
buf[len++] = '0';
}
}
if (len < PRINTF_NTOA_BUFFER_SIZE) {
if (negative) {
buf[len++] = '-';
}
else if (flags & FLAGS_PLUS) {
buf[len++] = '+'; // ignore the space if the '+' exists
}
else if (flags & FLAGS_SPACE) {
buf[len++] = ' ';
}
}
return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags);
}
// internal itoa for 'long' type
static size_t _ntoa_long(out_fct_type out, char* buffer, size_t idx, size_t maxlen, unsigned long value, bool negative, unsigned long base, unsigned int prec, unsigned int width, unsigned int flags)
{
char buf[PRINTF_NTOA_BUFFER_SIZE];
size_t len = 0U;
// no hash for 0 values
if (!value) {
flags &= ~FLAGS_HASH;
}
// write if precision != 0 and value is != 0
if (!(flags & FLAGS_PRECISION) || value) {
do {
const char digit = (char)(value % base);
buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10;
value /= base;
} while (value && (len < PRINTF_NTOA_BUFFER_SIZE));
}
return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags);
}
// internal itoa for 'long long' type
#if defined(PRINTF_SUPPORT_LONG_LONG)
static size_t _ntoa_long_long(out_fct_type out, char* buffer, size_t idx, size_t maxlen, unsigned long long value, bool negative, unsigned long long base, unsigned int prec, unsigned int width, unsigned int flags)
{
char buf[PRINTF_NTOA_BUFFER_SIZE];
size_t len = 0U;
// no hash for 0 values
if (!value) {
flags &= ~FLAGS_HASH;
}
// write if precision != 0 and value is != 0
if (!(flags & FLAGS_PRECISION) || value) {
do {
const char digit = (char)(value % base);
buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10;
value /= base;
} while (value && (len < PRINTF_NTOA_BUFFER_SIZE));
}
return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags);
}
#endif // PRINTF_SUPPORT_LONG_LONG
#if defined(PRINTF_SUPPORT_FLOAT)
#if defined(PRINTF_SUPPORT_EXPONENTIAL)
// forward declaration so that _ftoa can switch to exp notation for values > PRINTF_MAX_FLOAT
static size_t _etoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags);
#endif
// internal ftoa for fixed decimal floating point
static size_t _ftoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags)
{
char buf[PRINTF_FTOA_BUFFER_SIZE];
size_t len = 0U;
double diff = 0.0;
// powers of 10
static const double pow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
// test for special values
if (value != value)
return _out_rev(out, buffer, idx, maxlen, "nan", 3, width, flags);
if (value < -DBL_MAX)
return _out_rev(out, buffer, idx, maxlen, "fni-", 4, width, flags);
if (value > DBL_MAX)
return _out_rev(out, buffer, idx, maxlen, (flags & FLAGS_PLUS) ? "fni+" : "fni", (flags & FLAGS_PLUS) ? 4U : 3U, width, flags);
// test for very large values
// standard printf behavior is to print EVERY whole number digit -- which could be 100s of characters overflowing your buffers == bad
if ((value > PRINTF_MAX_FLOAT) || (value < -PRINTF_MAX_FLOAT)) {
#if defined(PRINTF_SUPPORT_EXPONENTIAL)
return _etoa(out, buffer, idx, maxlen, value, prec, width, flags);
#else
return 0U;
#endif
}
// test for negative
bool negative = false;
if (value < 0) {
negative = true;
value = 0 - value;
}
// set default precision, if not set explicitly
if (!(flags & FLAGS_PRECISION)) {
prec = PRINTF_DEFAULT_FLOAT_PRECISION;
}
// limit precision to 9, cause a prec >= 10 can lead to overflow errors
while ((len < PRINTF_FTOA_BUFFER_SIZE) && (prec > 9U)) {
buf[len++] = '0';
prec--;
}
int whole = (int)value;
double tmp = (value - whole) * pow10[prec];
unsigned long frac = (unsigned long)tmp;
diff = tmp - frac;
if (diff > 0.5) {
++frac;
// handle rollover, e.g. case 0.99 with prec 1 is 1.0
if (frac >= pow10[prec]) {
frac = 0;
++whole;
}
}
else if (diff < 0.5) {
}
else if ((frac == 0U) || (frac & 1U)) {
// if halfway, round up if odd OR if last digit is 0
++frac;
}
if (prec == 0U) {
diff = value - (double)whole;
if ((!(diff < 0.5) || (diff > 0.5)) && (whole & 1)) {
// exactly 0.5 and ODD, then round up
// 1.5 -> 2, but 2.5 -> 2
++whole;
}
}
else {
unsigned int count = prec;
// now do fractional part, as an unsigned number
while (len < PRINTF_FTOA_BUFFER_SIZE) {
--count;
buf[len++] = (char)(48U + (frac % 10U));
if (!(frac /= 10U)) {
break;
}
}
// add extra 0s
while ((len < PRINTF_FTOA_BUFFER_SIZE) && (count-- > 0U)) {
buf[len++] = '0';
}
if (len < PRINTF_FTOA_BUFFER_SIZE) {
// add decimal
buf[len++] = '.';
}
}
// do whole part, number is reversed
while (len < PRINTF_FTOA_BUFFER_SIZE) {
buf[len++] = (char)(48 + (whole % 10));
if (!(whole /= 10)) {
break;
}
}
// pad leading zeros
if (!(flags & FLAGS_LEFT) && (flags & FLAGS_ZEROPAD)) {
if (width && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) {
width--;
}
while ((len < width) && (len < PRINTF_FTOA_BUFFER_SIZE)) {
buf[len++] = '0';
}
}
if (len < PRINTF_FTOA_BUFFER_SIZE) {
if (negative) {
buf[len++] = '-';
}
else if (flags & FLAGS_PLUS) {
buf[len++] = '+'; // ignore the space if the '+' exists
}
else if (flags & FLAGS_SPACE) {
buf[len++] = ' ';
}
}
return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags);
}
#if defined(PRINTF_SUPPORT_EXPONENTIAL)
// internal ftoa variant for exponential floating-point type, contributed by Martijn Jasperse <m.jasperse@gmail.com>
static size_t _etoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags)
{
// check for NaN and special values
if ((value != value) || (value > DBL_MAX) || (value < -DBL_MAX)) {
return _ftoa(out, buffer, idx, maxlen, value, prec, width, flags);
}
// determine the sign
const bool negative = value < 0;
if (negative) {
value = -value;
}
// default precision
if (!(flags & FLAGS_PRECISION)) {
prec = PRINTF_DEFAULT_FLOAT_PRECISION;
}
// determine the decimal exponent
// based on the algorithm by David Gay (https://www.ampl.com/netlib/fp/dtoa.c)
union {
uint64_t U;
double F;
} conv;
conv.F = value;
int exp2 = (int)((conv.U >> 52U) & 0x07FFU) - 1023; // effectively log2
conv.U = (conv.U & ((1ULL << 52U) - 1U)) | (1023ULL << 52U); // drop the exponent so conv.F is now in [1,2)
// now approximate log10 from the log2 integer part and an expansion of ln around 1.5
int expval = (int)(0.1760912590558 + exp2 * 0.301029995663981 + (conv.F - 1.5) * 0.289529654602168);
// now we want to compute 10^expval but we want to be sure it won't overflow
exp2 = (int)(expval * 3.321928094887362 + 0.5);
const double z = expval * 2.302585092994046 - exp2 * 0.6931471805599453;
const double z2 = z * z;
conv.U = (uint64_t)(exp2 + 1023) << 52U;
// compute exp(z) using continued fractions, see https://en.wikipedia.org/wiki/Exponential_function#Continued_fractions_for_ex
conv.F *= 1 + 2 * z / (2 - z + (z2 / (6 + (z2 / (10 + z2 / 14)))));
// correct for rounding errors
if (value < conv.F) {
expval--;
conv.F /= 10;
}
// the exponent format is "%+03d" and largest value is "307", so set aside 4-5 characters
unsigned int minwidth = ((expval < 100) && (expval > -100)) ? 4U : 5U;
// in "%g" mode, "prec" is the number of *significant figures* not decimals
if (flags & FLAGS_ADAPT_EXP) {
// do we want to fall-back to "%f" mode?
if ((value >= 1e-4) && (value < 1e6)) {
if ((int)prec > expval) {
prec = (unsigned)((int)prec - expval - 1);
}
else {
prec = 0;
}
flags |= FLAGS_PRECISION; // make sure _ftoa respects precision
// no characters in exponent
minwidth = 0U;
expval = 0;
}
else {
// we use one sigfig for the whole part
if ((prec > 0) && (flags & FLAGS_PRECISION)) {
--prec;
}
}
}
// will everything fit?
unsigned int fwidth = width;
if (width > minwidth) {
// we didn't fall-back so subtract the characters required for the exponent
fwidth -= minwidth;
} else {
// not enough characters, so go back to default sizing
fwidth = 0U;
}
if ((flags & FLAGS_LEFT) && minwidth) {
// if we're padding on the right, DON'T pad the floating part
fwidth = 0U;
}
// rescale the float value
if (expval) {
value /= conv.F;
}
// output the floating part
const size_t start_idx = idx;
idx = _ftoa(out, buffer, idx, maxlen, negative ? -value : value, prec, fwidth, flags & ~FLAGS_ADAPT_EXP);
// output the exponent part
if (minwidth) {
// output the exponential symbol
out((flags & FLAGS_UPPERCASE) ? 'E' : 'e', buffer, idx++, maxlen);
// output the exponent value
idx = _ntoa_long(out, buffer, idx, maxlen, (expval < 0) ? -expval : expval, expval < 0, 10, 0, minwidth-1, FLAGS_ZEROPAD | FLAGS_PLUS);
// might need to right-pad spaces
if (flags & FLAGS_LEFT) {
while (idx - start_idx < width) out(' ', buffer, idx++, maxlen);
}
}
return idx;
}
#endif // PRINTF_SUPPORT_EXPONENTIAL
#endif // PRINTF_SUPPORT_FLOAT
// internal vsnprintf
static int _vsnprintf(out_fct_type out, char* buffer, const size_t maxlen, const char* format, va_list va)
{
unsigned int flags, width, precision, n;
size_t idx = 0U;
if (!buffer) {
// use null output function
out = _out_null;
}
while (*format)
{
// format specifier? %[flags][width][.precision][length]
if (*format != '%') {
// no
out(*format, buffer, idx++, maxlen);
format++;
continue;
}
else {
// yes, evaluate it
format++;
}
// evaluate flags
flags = 0U;
do {
switch (*format) {
case '0': flags |= FLAGS_ZEROPAD; format++; n = 1U; break;
case '-': flags |= FLAGS_LEFT; format++; n = 1U; break;
case '+': flags |= FLAGS_PLUS; format++; n = 1U; break;
case ' ': flags |= FLAGS_SPACE; format++; n = 1U; break;
case '#': flags |= FLAGS_HASH; format++; n = 1U; break;
default : n = 0U; break;
}
} while (n);
// evaluate width field
width = 0U;
if (_is_digit(*format)) {
width = _atoi(&format);
}
else if (*format == '*') {
const int w = va_arg(va, int);
if (w < 0) {
flags |= FLAGS_LEFT; // reverse padding
width = (unsigned int)-w;
}
else {
width = (unsigned int)w;
}
format++;
}
// evaluate precision field
precision = 0U;
if (*format == '.') {
flags |= FLAGS_PRECISION;
format++;
if (_is_digit(*format)) {
precision = _atoi(&format);
}
else if (*format == '*') {
const int prec = (int)va_arg(va, int);
precision = prec > 0 ? (unsigned int)prec : 0U;
format++;
}
}
// evaluate length field
switch (*format) {
case 'l' :
flags |= FLAGS_LONG;
format++;
if (*format == 'l') {
flags |= FLAGS_LONG_LONG;
format++;
}
break;
case 'h' :
flags |= FLAGS_SHORT;
format++;
if (*format == 'h') {
flags |= FLAGS_CHAR;
format++;
}
break;
#if defined(PRINTF_SUPPORT_PTRDIFF_T)
case 't' :
flags |= (sizeof(ptrdiff_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG);
format++;
break;
#endif
case 'j' :
flags |= (sizeof(intmax_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG);
format++;
break;
case 'z' :
flags |= (sizeof(size_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG);
format++;
break;
default :
break;
}
// evaluate specifier
switch (*format) {
case 'd' :
case 'i' :
case 'u' :
case 'x' :
case 'X' :
case 'o' :
case 'b' : {
// set the base
unsigned int base;
if (*format == 'x' || *format == 'X') {
base = 16U;
}
else if (*format == 'o') {
base = 8U;
}
else if (*format == 'b') {
base = 2U;
}
else {
base = 10U;
flags &= ~FLAGS_HASH; // no hash for dec format
}
// uppercase
if (*format == 'X') {
flags |= FLAGS_UPPERCASE;
}
// no plus or space flag for u, x, X, o, b
if ((*format != 'i') && (*format != 'd')) {
flags &= ~(FLAGS_PLUS | FLAGS_SPACE);
}
// ignore '0' flag when precision is given
if (flags & FLAGS_PRECISION) {
flags &= ~FLAGS_ZEROPAD;
}
// convert the integer
if ((*format == 'i') || (*format == 'd')) {
// signed
if (flags & FLAGS_LONG_LONG) {
#if defined(PRINTF_SUPPORT_LONG_LONG)
const long long value = va_arg(va, long long);
idx = _ntoa_long_long(out, buffer, idx, maxlen, (unsigned long long)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags);
#endif
}
else if (flags & FLAGS_LONG) {
const long value = va_arg(va, long);
idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned long)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags);
}
else {
const int value = (flags & FLAGS_CHAR) ? (char)va_arg(va, int) : (flags & FLAGS_SHORT) ? (short int)va_arg(va, int) : va_arg(va, int);
idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned int)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags);
}
}
else {
// unsigned
if (flags & FLAGS_LONG_LONG) {
#if defined(PRINTF_SUPPORT_LONG_LONG)
idx = _ntoa_long_long(out, buffer, idx, maxlen, va_arg(va, unsigned long long), false, base, precision, width, flags);
#endif
}
else if (flags & FLAGS_LONG) {
idx = _ntoa_long(out, buffer, idx, maxlen, va_arg(va, unsigned long), false, base, precision, width, flags);
}
else {
const unsigned int value = (flags & FLAGS_CHAR) ? (unsigned char)va_arg(va, unsigned int) : (flags & FLAGS_SHORT) ? (unsigned short int)va_arg(va, unsigned int) : va_arg(va, unsigned int);
idx = _ntoa_long(out, buffer, idx, maxlen, value, false, base, precision, width, flags);
}
}
format++;
break;
}
#if defined(PRINTF_SUPPORT_FLOAT)
case 'f' :
case 'F' :
if (*format == 'F') flags |= FLAGS_UPPERCASE;
idx = _ftoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags);
format++;
break;
#if defined(PRINTF_SUPPORT_EXPONENTIAL)
case 'e':
case 'E':
case 'g':
case 'G':
if ((*format == 'g')||(*format == 'G')) flags |= FLAGS_ADAPT_EXP;
if ((*format == 'E')||(*format == 'G')) flags |= FLAGS_UPPERCASE;
idx = _etoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags);
format++;
break;
#endif // PRINTF_SUPPORT_EXPONENTIAL
#endif // PRINTF_SUPPORT_FLOAT
case 'c' : {
unsigned int l = 1U;
// pre padding
if (!(flags & FLAGS_LEFT)) {
while (l++ < width) {
out(' ', buffer, idx++, maxlen);
}
}
// char output
out((char)va_arg(va, int), buffer, idx++, maxlen);
// post padding
if (flags & FLAGS_LEFT) {
while (l++ < width) {
out(' ', buffer, idx++, maxlen);
}
}
format++;
break;
}
case 's' : {
const char* p = va_arg(va, char*);
unsigned int l = _strnlen_s(p, precision ? precision : (size_t)-1);
// pre padding
if (flags & FLAGS_PRECISION) {
l = (l < precision ? l : precision);
}
if (!(flags & FLAGS_LEFT)) {
while (l++ < width) {
out(' ', buffer, idx++, maxlen);
}
}
// string output
while ((*p != 0) && (!(flags & FLAGS_PRECISION) || precision--)) {
out(*(p++), buffer, idx++, maxlen);
}
// post padding
if (flags & FLAGS_LEFT) {
while (l++ < width) {
out(' ', buffer, idx++, maxlen);
}
}
format++;
break;
}
case 'p' : {
width = sizeof(void*) * 2U;
flags |= FLAGS_ZEROPAD | FLAGS_UPPERCASE;
#if defined(PRINTF_SUPPORT_LONG_LONG)
const bool is_ll = sizeof(uintptr_t) == sizeof(long long);
if (is_ll) {
idx = _ntoa_long_long(out, buffer, idx, maxlen, (uintptr_t)va_arg(va, void*), false, 16U, precision, width, flags);
}
else {
#endif
idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned long)((uintptr_t)va_arg(va, void*)), false, 16U, precision, width, flags);
#if defined(PRINTF_SUPPORT_LONG_LONG)
}
#endif
format++;
break;
}
case '%' :
out('%', buffer, idx++, maxlen);
format++;
break;
default :
out(*format, buffer, idx++, maxlen);
format++;
break;
}
}
// termination
out((char)0, buffer, idx < maxlen ? idx : maxlen - 1U, maxlen);
// return written chars without terminating \0
return (int)idx;
}
///////////////////////////////////////////////////////////////////////////////
int printf(const char* format, ...)
{
va_list va;
va_start(va, format);
char buffer[1];
const int ret = _vsnprintf(_out_char, buffer, (size_t)-1, format, va);
va_end(va);
return ret;
}
/* int fprintf(FILE *stream, const char* format, ...)
* {
*
* va_list va;
* va_start(va, format);
* char buffer[1];
* const int ret = _vsnprintf(_out_char, buffer, (size_t)-1, format, va);
* va_end(va);
* return ret;
* } */
int sprintf(char* buffer, const char* format, ...)
{
va_list va;
va_start(va, format);
const int ret = _vsnprintf(_out_buffer, buffer, (size_t)-1, format, va);
va_end(va);
return ret;
}
int snprintf(char* buffer, size_t count, const char* format, ...)
{
va_list va;
va_start(va, format);
const int ret = _vsnprintf(_out_buffer, buffer, count, format, va);
va_end(va);
return ret;
}
int vprintf(const char* format, va_list va)
{
char buffer[1];
return _vsnprintf(_out_char, buffer, (size_t)-1, format, va);
}
int vsnprintf(char* buffer, size_t count, const char* format, va_list va)
{
return _vsnprintf(_out_buffer, buffer, count, format, va);
}
int fctprintf(void (*out)(char character, void* arg), void* arg, const char* format, ...)
{
va_list va;
va_start(va, format);
const out_fct_wrap_type out_fct_wrap = { out, arg };
const int ret = _vsnprintf(_out_fct, (char*)(uintptr_t)&out_fct_wrap, (size_t)-1, format, va);
va_end(va);
return ret;
}
+91
View File
@@ -0,0 +1,91 @@
#include <string.h>
#include <debug.h>
#include <common.h>
#undef __RSV_MEM_DEBUG
struct rsv_memctrl_t {
uint32 start;
uint32 end;
uint32 pos;
};
static struct rsv_memctrl_t g_rsv_memctrl = {0};
void rsv_mem_init(uint32 start, uint32 len)
{
if (g_rsv_memctrl.end == 0) {
g_rsv_memctrl.start = start;
g_rsv_memctrl.end = start + len;
g_rsv_memctrl.pos = 0;
}
#ifdef CONFIG_DEBUG_INFO
puts("Reserved mem: 0x");puthex(start);puts(" - 0x");puthex(start + len);puts("\n");
#endif
}
void rsv_mem_reinit(uint32 start, uint32 len)
{
g_rsv_memctrl.end = 0;
rsv_mem_init(start, len);
}
void *__rsv_mem_alloc(uint32 bytes, const char *file, int line)
{
uint32 new_ptr;
void *ptr = NULL;
if (g_rsv_memctrl.end == 0) {
pr_error("malloc module uninitializtion.\n");
return NULL;
}
new_ptr = g_rsv_memctrl.start + g_rsv_memctrl.pos + around(bytes, 4); /* 4 bytes align */
if (new_ptr > g_rsv_memctrl.end) {
return NULL;
}
ptr = (void *)(uintptr_t)(g_rsv_memctrl.start + g_rsv_memctrl.pos);
g_rsv_memctrl.pos += around(bytes, 4); /* 4 bytes align */
#ifdef __RSV_MEM_DEBUG
puts(file);puts("(");putdec(line);puts("): rsv mem alloc 0x");puthex((ulong)ptr);puts("(");putdec(bytes);puts(")\n");
#endif
return ptr;
}
void *__rsv_mem_align(uint32 alignment, uint32 bytes, const char *file, int line)
{
uint32 new_addr;
void *ptr = NULL;
if (g_rsv_memctrl.end == 0) {
puts("rsv mem NOT initialized.\n");
return NULL;
}
if (alignment & (alignment - 1)) {
puts("align must be powed of 2\n");
return NULL;
}
new_addr = around(g_rsv_memctrl.start + g_rsv_memctrl.pos, alignment);
if (new_addr + around(bytes, 4) > g_rsv_memctrl.end) { /* 4 bytes align */
return NULL;
}
g_rsv_memctrl.pos = new_addr - g_rsv_memctrl.start + around(bytes, 4); /* 4 bytes align */
ptr = (void *)(uintptr_t)new_addr;
#ifdef __RSV_MEM_DEBUG
puts(file);puts("(");putdec(line);puts("): rsv mem align 0x");puthex((ulong)ptr);puts("(");putdec(bytes);puts(")\n");
#endif
return ptr;
}
void dump_rsv_mem_info(void)
{
puts("Reserved Mem Info:\n");
puts("start: 0x");puthex(g_rsv_memctrl.start);puts("\n");
puts("end: 0x");puthex(g_rsv_memctrl.end);puts("\n");
puts("pos: 0x");puthex(g_rsv_memctrl.pos);puts("\n");
}
+84
View File
@@ -0,0 +1,84 @@
#include <malloc.h>
#include <string.h>
#include <debug.h>
#include <common.h>
struct memctrl_t {
uint32 start;
uint32 end;
uint32 pos;
};
uint32 g_heap_start = 0;
uint32 g_heap_end = 0;
static struct memctrl_t g_memctrl = {0};
void malloc_init(uint32 start, uint32 len)
{
if (g_memctrl.end == 0) {
g_heap_start = g_memctrl.start = start;
g_heap_end = g_memctrl.end = start + len;
g_memctrl.pos = 0;
}
}
void *__malloc(uint32 bytes, const char *file, int line)
{
uint32 new_ptr;
void *ptr = NULL;
if (g_memctrl.end == 0) {
pr_error("malloc module uninitializtion.\n");
return NULL;
}
pr_debug("%s(%d): malloc:0x%x\n" _NONE, file, line, bytes);
new_ptr = g_memctrl.start + g_memctrl.pos + around(bytes, 4); /* 4 bytes align */
if (new_ptr > g_memctrl.end) {
return NULL;
}
ptr = (void *)(uintptr_t)(g_memctrl.start + g_memctrl.pos);
g_memctrl.pos += around(bytes, 4); /* 4 bytes align */
return ptr;
}
void __free(const void *mem, const char *file, int line)
{
if (g_memctrl.end == 0) {
pr_error("malloc module uninitializtion.\n");
return;
}
pr_debug("%s(%d): free\n" _NONE, file, line);
return;
}
void *__memalign(uint32 alignment, uint32 bytes, const char *file, int line)
{
uint32 new_addr;
void *ptr = NULL;
if (g_memctrl.end == 0) {
pr_error("malloc module uninitializtion.\n");
return NULL;
}
if (alignment & (alignment - 1)) {
pr_error("align must be powed of 2\n");
return NULL;
}
new_addr = around(g_memctrl.start + g_memctrl.pos, alignment);
if (new_addr + around(bytes, 4) > g_memctrl.end) { /* 4 bytes align */
return NULL;
}
g_memctrl.pos = new_addr - g_memctrl.start + around(bytes, 4); /* 4 bytes align */
ptr = (void *)(uintptr_t)new_addr;
pr_debug("%s(%d): memalign:0x%x\n" _NONE, file, line, bytes);
return ptr;
}
void dump_malloc(void)
{
printf("start: 0x%08x\n", g_memctrl.start);
printf("end: 0x%08x\n", g_memctrl.end);
printf("pos: 0x%08x\n", g_memctrl.pos);
}
+53
View File
@@ -0,0 +1,53 @@
#include <stddef.h>
#include <stdarg.h>
#include <string.h>
#include <div64.h>
#include <serial.h>
extern void serial_put_hex(u32 hex);
extern void serial_put_dec(u32 dec);
/*****************************************************************************/
int putchar(int c)
{
if (c == '\n')
serial_putc('\r');
serial_putc(c);
return c;
}
int puts(const char *s)
{
const char *ptr = s;
while (*ptr)
putchar(*ptr++);
return (ptr - s);
}
void puts_always(const char *s)
{
serial_puts_always(s);
}
void puthex(unsigned int hex)
{
serial_put_hex(hex);
}
void puthex_always(unsigned int hex)
{
serial_put_hex_always(hex);
}
void putdec(unsigned int dec)
{
serial_put_dec(dec);
}
int getchar(void)
{
return serial_getc();
}
+1
View File
@@ -0,0 +1 @@
../media
+3
View File
@@ -0,0 +1,3 @@
编译命令:
make xmfalcon_defconfig
make
+12
View File
@@ -0,0 +1,12 @@
CFLAGS_start += -DTEXT_BASE=$(CONFIG_TEXT_BASE)
CFLAGS_start += -DSTACK_TOP=$(CONFIG_STACK_TOP)
CFLAGS += -DSTACK_TOP=$(CONFIG_STACK_TOP)
ASFLAGS += -DSTACK_TOP=$(CONFIG_STACK_TOP)
LINKLDS := firmware.lds
START = start.S
TAIL = tail.S
SRCS-y += vectors.S
SRCS-y += chip.c system.c
SRCS-y += isr.c trap_c.c drv_irq.c
+17
View File
@@ -0,0 +1,17 @@
#include <platform.h>
#include <io.h>
#include <lib.h>
#include <common.h>
void reset_cpu(void)
{
}
u64 get_ddr_size(void)
{
u64 size = readl(REG_SC_DDRT12);
assert(size != 0);
return size;
}
+50
View File
@@ -0,0 +1,50 @@
#include <stdio.h>
#include <stdint.h>
#include <config.h>
#include <platform.h>
#include <core.h>
#include <errno.h>
extern void default_handler(void);
void drv_irq_enable(uint32_t irq_num)
{
rv32_vic_enable_irq(irq_num);
}
void drv_irq_disable(uint32_t irq_num)
{
rv32_vic_disable_irq(irq_num);
}
int drv_irq_register(uint32_t irq_num, void *irq_handler)
{
uint32_t handler = rv32_vic_get_vector(irq_num);
if(handler != (uint32_t)&default_handler) {
puts("IRQ ");puthex(irq_num);puts(" has been registered by 0x");
puthex(handler);puts("!\n");
return -EBUSY;
}
__disable_irq();
rv32_vic_set_vector(irq_num, (uintptr_t)irq_handler);
__enable_irq();
drv_irq_enable(irq_num);
return 0;
}
void drv_irq_unregister(uint32_t irq_num)
{
__disable_irq();
rv32_vic_set_vector(irq_num, (uintptr_t)default_handler);
drv_irq_disable(irq_num);
__enable_irq();
}
+130
View File
@@ -0,0 +1,130 @@
OUTPUT_FORMAT("elf32-littleriscv", "elf32-littleriscv", "elf32-littleriscv")
#include <config.h>
MEMORY
{
STAGE1_MEM : ORIGIN = CONFIG_TEXT_BASE, LENGTH = (CONFIG_STAGE2_START - CONFIG_TEXT_BASE)
STAGE2_MEM : ORIGIN = CONFIG_STAGE2_START, LENGTH = (CONFIG_MCU_SRAM_SIZE - (CONFIG_STAGE2_START - CONFIG_TEXT_BASE) - CONFIG_PARAM_MEM_SIZE)
PARAM_MEM : ORIGIN = CONFIG_PARAM_MEM_START, LENGTH = CONFIG_PARAM_MEM_SIZE
}
ENTRY(_start)
SECTIONS
{
. = ALIGN(4);
.text : {
. = ALIGN(4);
__text_start = .;
start.o (.text)
libstage1.a(.text)
libstage1.a(.text.*)
libstage1.a(.text.stage1)
libstage2.a(.text.stage1)
__text_end = .;
} >STAGE1_MEM
. = ALIGN(4);
.rodata : {
__rodata_start = .;
start.o(.rodata*)
libstage1.a(.rodata)
libstage1.a(.rodata.*)
libstage1.a(.rodata.stage1)
libstage2.a(.rodata.stage1)
__global_pointer$ = .;
libstage1.a(.srodata)
libstage1.a(.srodata.*)
libstage1.a(.srodata2.*)
__rodata_end = .;
} >STAGE1_MEM
. = ALIGN(4);
.data : {
__data_start = .;
KEEP(*start.o(*.vectors*))
libstage1.a(.data)
libstage1.a(.data.*)
libstage1.a(.data.stage1)
libstage2.a(.data.stage1)
libstage1.a(.sdata)
libstage1.a(.sdata.*)
libstage1.a(.sdata2.*)
__data_end = .;
ASSERT((__data_end <= CONFIG_STAGE2_START), "No more Stage1 Space!!");
} >STAGE1_MEM
. = ALIGN(4);
.text2 : {
. = ALIGN(4);
__text2_start = .;
KEEP(libstage2.a(.text))
KEEP(libstage2.a(.text.*))
KEEP(libstage2.a(.text.stage2))
libstage1.a(.text.stage2)
__text2_end = .;
} >STAGE2_MEM
. = ALIGN(4);
.rodata2 : {
__rodata2_start = .;
KEEP(libstage2.a(.rodata))
KEEP(libstage2.a(.rodata.*))
KEEP(libstage2.a(.rodata.stage2))
KEEP(libstage2.a(.srodata))
KEEP(libstage2.a(.srodata.*))
KEEP(libstage2.a(.srodata2.*))
libstage1.a(.rodata.stage2)
__rodata2_end = .;
} >STAGE2_MEM
. = ALIGN(4);
.data2 : {
__data2_start = .;
KEEP(libstage2.a(.data))
KEEP(libstage2.a(.data.*))
KEEP(libstage2.a(.data.stage2))
KEEP(libstage2.a(.sdata))
KEEP(libstage2.a(.sdata.*))
KEEP(libstage2.a(.sdata2.*))
libstage1.a(.data.stage2)
__data2_end = .;
} >STAGE2_MEM
.tail : {
tail.o(.tail)
} >STAGE2_MEM
. = ALIGN(4);
.bin_end : {
__bin_end_pad = .;
LONG(CONFIG_BIN_END_PAD)
__bin_end = .;
} >STAGE2_MEM
. = ALIGN(4);
.bss : {
__bss_start = .;
*(.sbss)
*(.sbss.*)
*(.bss)
*(.bss.*)
__bss_end = .;
KEEP(*vectors.o(.stack.trap))
KEEP(*start.o(.stack))
__stack_top = .;
} >STAGE2_MEM
. = ALIGN(2);
_end = .;
.assert : {
ASSERT(((_end - CONFIG_TEXT_BASE) <= (CONFIG_MCU_SRAM_SIZE - CONFIG_PARAM_MEM_SIZE)), "No more Stage2 Space!!");
}
. = ALIGN(4);
.param : {
__param_start = .;
__param_end = .;
} >PARAM_MEM
}
+8
View File
@@ -0,0 +1,8 @@
#ifndef _CORE_H_
#define _CORE_H_
#include <core_rv32.h>
#include <rv32_gcc.h>
#endif /* _CORE_H_ */
File diff suppressed because it is too large Load Diff
+7
View File
@@ -0,0 +1,7 @@
#ifndef __INTERRUPT_H__
#define __INTERRUPT_H__
#include <sys/types.h>
#endif
+31
View File
@@ -0,0 +1,31 @@
#ifndef __RISCV_IO_H__
#define __RISCV_IO_H__
#include <sys/types.h>
#define __arch_getl(a) (*(volatile unsigned int *)(a))
#define __arch_putl(v,a) (*(volatile unsigned int *)(a) = (v))
#define __iormb() //dmb()
#define __iowmb() //dmb()
#define writel(v,c) ({ u32 __v = v; __iowmb(); __arch_putl(__v,c); __v; })
#define readl(c) ({ u32 __v = __arch_getl(c); __iormb(); __v; })
#define csr_read(csr) \
({ \
register unsigned long __v; \
__asm__ __volatile__ ("csrr %0, " #csr \
: "=r" (__v) : \
: "memory"); \
__v; \
})
#define csr_write(csr, val) \
({ \
unsigned long __v = (unsigned long)(val); \
__asm__ __volatile__ ("csrw " #csr ", %0" \
: : "rK" (__v) \
: "memory"); \
})
#endif /* __RISCV_IO_H__ */
+321
View File
@@ -0,0 +1,321 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#ifndef __CHIP_REGS_H__
#define __CHIP_REGS_H__
#define BIT(nr) (1 << (nr))
#define RAM_START_ADRS 0x04010500
#define STACK_TRAINING 0x04018000
#define DDR_DDRT_REG_BASE 0x11330000
#define TIMER0_REG_BASE 0x12000000
#define TIMER1_REG_BASE 0x12000100
#define TIMER2_REG_BASE 0x12000200
#define TIMER3_REG_BASE 0x12000300
#define REG_TIMER_RELOAD 0x0
#define REG_TIMER_VALUE 0x4
#define REG_TIMER_CONTROL 0x8
#define CRG_REG_BASE 0x12010000
#define REG_PERI_CRG110 (CRG_REG_BASE + 0x01B8)
#define SYS_CTRL_REG_BASE 0x12020000
#define REG_BASE_SCTL SYS_CTRL_REG_BASE
#define REG_SC_CTRL 0
#define REMAPCLEAR BIT(8)
#define REMAPCLEAR_SHIFT 8
#define TIME0_CLK_SEL BIT(16)
#define TIME0_CLK_SEL_SHIFT 16
#define TIME0_CLK_SEL_3M 0x0
#define TIME0_CLK_SEL_APB 0x1
#define REG_SC_SYSRES 0x8
#define REG_SYSSTAT 0x008C
#define STOPWATCH_CTRL_REG2 (SYS_CTRL_REG_BASE + 0x8110)
/* Generic register */
#define REG_SC_DDRT0 (SYS_CTRL_REG_BASE + 0x90)
#define REG_SC_DDRT1 (SYS_CTRL_REG_BASE + 0x94)
#define REG_SC_DDRT2 (SYS_CTRL_REG_BASE + 0x98)
#define REG_SC_DDRT3 (SYS_CTRL_REG_BASE + 0x9c)
#define REG_SC_DDRT4 (SYS_CTRL_REG_BASE + 0xa0)
#define REG_SC_DDRT5 (SYS_CTRL_REG_BASE + 0xa4)
#define REG_SC_DDRT6 (SYS_CTRL_REG_BASE + 0xa8)
#define REG_SC_DDRT7 (SYS_CTRL_REG_BASE + 0xac)
#define REG_SC_DDRT8 (SYS_CTRL_REG_BASE + 0xb0)
#define REG_SC_DDRT9 (SYS_CTRL_REG_BASE + 0xb4)
#define REG_SC_DDRT10 (SYS_CTRL_REG_BASE + 0xb8)
#define REG_SC_DDRT11 (SYS_CTRL_REG_BASE + 0xbc)
#define REG_SC_DDRT12 (SYS_CTRL_REG_BASE + 0xc0)
#define REG_SC_DDRT13 (SYS_CTRL_REG_BASE + 0xc4)
#define REG_SC_DDRT14 (SYS_CTRL_REG_BASE + 0xc8)
#define REG_SC_DDRT15 (SYS_CTRL_REG_BASE + 0xcc)
#define REG_SC_SYSBOOT0 (SYS_CTRL_REG_BASE + 0x130)
#define REG_SC_SYSBOOT1 (SYS_CTRL_REG_BASE + 0x134)
#define REG_SC_SYSBOOT2 (SYS_CTRL_REG_BASE + 0x138)
#define REG_SC_SYSBOOT3 (SYS_CTRL_REG_BASE + 0x13c)
#define REG_SC_SYSBOOT4 (SYS_CTRL_REG_BASE + 0x140)
#define REG_SC_SYSBOOT5 (SYS_CTRL_REG_BASE + 0x144)
#define REG_SC_SYSBOOT6 (SYS_CTRL_REG_BASE + 0x148)
#define REG_SC_SYSBOOT7 (SYS_CTRL_REG_BASE + 0x14c)
#define REG_SC_SYSBOOT8 (SYS_CTRL_REG_BASE + 0x150)
#define REG_SC_SYSBOOT9 (SYS_CTRL_REG_BASE + 0x154)
#define REG_SC_SYSBOOT10 (SYS_CTRL_REG_BASE + 0x158)
#define REG_SC_SYSBOOT11 (SYS_CTRL_REG_BASE + 0x15c)
#define REG_SC_SYSBOOT12 (SYS_CTRL_REG_BASE + 0x160)
#define REG_SC_SYSBOOT13 (SYS_CTRL_REG_BASE + 0x164)
#define REG_SC_SYSBOOT14 (SYS_CTRL_REG_BASE + 0x168)
#define REG_SC_SYSBOOT15 (SYS_CTRL_REG_BASE + 0x16c)
#define DDRCA_UPDATE (SYS_CTRL_REG_BASE + 0x8034)
#define DDRCA_RANDOM0 (SYS_CTRL_REG_BASE + 0x8600)
#define DDRCA_RANDOM1 (SYS_CTRL_REG_BASE + 0x8604)
#define DDRCA_RANDOM2 (SYS_CTRL_REG_BASE + 0x8608)
#define DDRCA_RANDOM3 (SYS_CTRL_REG_BASE + 0x860c)
#define MISC_REG_BASE 0x12028000
#define DDRC0_REG_BASE 0x11330000
#define UART0_REG_BASE 0x12040000
#define UART3_REG_BASE 0x12043000
#define FMC_MEM_BASE 0x14000000
#define DDR_MEM_BASE 0x40000000
#define TIMER0_BASE 0x12000000
#define TIMER1_BASE 0x12000100
#define TIMER2_BASE 0x12001000
#define SERIAL_BASE UART3_REG_BASE
#define UART_PL01x_DR (SERIAL_BASE + 0x00)
#define UART_PL01x_RSR (SERIAL_BASE + 0x04)
#define UART_PL01x_ECR (SERIAL_BASE + 0x04)
#define UART_PL01x_FR (SERIAL_BASE + 0x18)
#define UART_PL01x_IBRD (SERIAL_BASE + 0x0024)
#define UART_PL01x_FBRD (SERIAL_BASE + 0x0028)
#define UART_PL01x_LCRH (SERIAL_BASE + 0x002C)
#define UART_PL01x_CR (SERIAL_BASE + 0x0030)
#define UART_PL01x_FR_TXFE 0x80
#define UART_PL01x_FR_RXFF 0x40
#define UART_PL01x_FR_TXFF 0x20
#define UART_PL01x_FR_RXFE 0x10
#define UART_PL01x_FR_BUSY 0x08
#define UART_PL01x_FR_TMSK (UART_PL01x_FR_TXFF + UART_PL01x_FR_BUSY)
/*
* PL011 definitions
*
*/
#define UART_PL011_LCRH_SPS (1 << 7)
#define UART_PL011_LCRH_WLEN_8 (3 << 5)
#define UART_PL011_LCRH_WLEN_7 (2 << 5)
#define UART_PL011_LCRH_WLEN_6 (1 << 5)
#define UART_PL011_LCRH_WLEN_5 (0 << 5)
#define UART_PL011_LCRH_FEN (1 << 4)
#define UART_PL011_LCRH_STP2 (1 << 3)
#define UART_PL011_LCRH_EPS (1 << 2)
#define UART_PL011_LCRH_PEN (1 << 1)
#define UART_PL011_LCRH_BRK (1 << 0)
#define UART_PL011_CR_CTSEN (1 << 15)
#define UART_PL011_CR_RTSEN (1 << 14)
#define UART_PL011_CR_OUT2 (1 << 13)
#define UART_PL011_CR_OUT1 (1 << 12)
#define UART_PL011_CR_RTS (1 << 11)
#define UART_PL011_CR_DTR (1 << 10)
#define UART_PL011_CR_RXE (1 << 9)
#define UART_PL011_CR_TXE (1 << 8)
#define UART_PL011_CR_LPE (1 << 7)
#define UART_PL011_CR_IIRLP (1 << 2)
#define UART_PL011_CR_SIREN (1 << 1)
#define UART_PL011_CR_UARTEN (1 << 0)
#define UART_PL011_IMSC_OEIM (1 << 10)
#define UART_PL011_IMSC_BEIM (1 << 9)
#define UART_PL011_IMSC_PEIM (1 << 8)
#define UART_PL011_IMSC_FEIM (1 << 7)
#define UART_PL011_IMSC_RTIM (1 << 6)
#define UART_PL011_IMSC_TXIM (1 << 5)
#define UART_PL011_IMSC_RXIM (1 << 4)
#define UART_PL011_IMSC_DSRMIM (1 << 3)
#define UART_PL011_IMSC_DCDMIM (1 << 2)
#define UART_PL011_IMSC_CTSMIM (1 << 1)
#define UART_PL011_IMSC_RIMIM (1 << 0)
#define UART_BAUDRATE 115200
#define UART_CLOCK 24000000
#define START_MAGIC 0x444f574e
#define SUCCESS 0
#define FAILURE -1
#define REG_OTP_PO_BIT0 0x12020080
#define REG_OTP_PO_BIT2 0x12020088
#if defined(CONFIG_PLATFORM_XMFALCON) || defined(CONFIG_PLATFORM_XMORCA)
#define PERI_CRG110 0x01b8
#define I2C_CRG_REG_BASE (CRG_REG_BASE + PERI_CRG110)
#define I2C0_REG_BASE 0x12060000
#define I2C1_REG_BASE 0x12061000
#define I2C2_REG_BASE 0x12062000
#define I2C3_REG_BASE 0x12063000
#define I2C4_REG_BASE 0x12064000
#define I2C5_REG_BASE 0x12065000
#define I2C6_REG_BASE 0x12066000
#define I2C7_REG_BASE 0x12067000
#define I2C_NUM 8
#elif defined(CONFIG_TARGET_XM720XXX)
#define PERI_CRG110 0x01b8
#define I2C_CRG_REG_BASE (CRG_REG_BASE + PERI_CRG110)
#define I2C0_REG_BASE 0x12060000
#define I2C1_REG_BASE 0x12061000
#define I2C2_REG_BASE 0x12062000
#define I2C_NUM 3
#endif
/*
* I2C Registers offsets
*/
#define I2C_GLB 0x0
#define I2C_SCL_H 0x20
#define I2C_SCL_L 0x24
#define I2C_DATA1 0x28
#define I2C_TXF 0x10
#define I2C_RXF 0x14
#define I2C_CMD_BASE 0x40
#define I2C_LOOP1 0xc0
#define I2C_DST1 0xc4
#define I2C_TX_WATER 0x18
#define I2C_RX_WATER 0x1c
#define I2C_CTRL1 0x04
#define I2C_CTRL2 0x08
#define I2C_STAT 0x0c
#define I2C_INTR_RAW 0x30
#define I2C_INTR_EN 0x34
#define I2C_INTR_STAT 0x38
/*
* I2C Global Config Register -- I2C_GLB
* */
#define GLB_EN_MASK BIT(0)
#define GLB_SDA_HOLD_MASK 0xffff0
#define GLB_SDA_HOLD_SHIFT (4)
/*
* I2C Timing CMD Register -- I2C_CMD_BASE + n * 4 (n = 0, 1, 2, ... 31)
* */
#define CMD_EXIT 0x0
#define CMD_TX_S 0x1
#define CMD_TX_D1_2 0x4
#define CMD_TX_D1_1 0x5
#define CMD_TX_FIFO 0x9
#define CMD_RX_FIFO 0x12
#define CMD_RX_ACK 0x13
#define CMD_IGN_ACK 0x15
#define CMD_TX_ACK 0x16
#define CMD_TX_NACK 0x17
#define CMD_JMP1 0x18
#define CMD_UP_TXF 0x1d
#define CMD_TX_RS 0x1e
#define CMD_TX_P 0x1f
/*
* I2C Control Register 1 -- I2C_CTRL1
*/
#define CTRL1_CMD_START_MASK BIT(0)
/*
* I2C Status Register -- I2C_STAT
*/
#define STAT_RXF_NOE_MASK BIT(0) /* RX FIFO not empty flag */
#define STAT_TXF_NOF_MASK BIT(3) /* TX FIFO not full flag */
/*
* I2C Interrupt status and mask Register --
* I2C_INTR_RAW, I2C_STAT, I2C_INTR_STAT
*/
#define INTR_ABORT_MASK (BIT(0) | BIT(3))
#define INTR_RX_MASK BIT(5)
#define INTR_TX_MASK BIT(6)
#define INTR_CMD_DONE_MASK BIT(4)
#define INTR_USE_MASK (INTR_ABORT_MASK | INTR_RX_MASK | INTR_TX_MASK | INTR_CMD_DONE_MASK)
#define INTR_ALL_MASK 0xffffffff
#define I2C_TXF_DEPTH 64
#define I2C_RXF_DEPTH 64
#define I2C_TXF_WATER 32
#define I2C_RXF_WATER 32
/* for i2c rescue */
#define CHECK_SDA_IN_SHIFT (5)
#define GPIO_MODE_SHIFT (0)
#define FORCE_SCL_OEN_SHIFT (1)
#define FORCE_SDA_OEN_SHIFT (2)
#define GPIO_DATA 0x0
#define GPIO_DIR 0x400
#define GPIO0_BASE 0x120B0000
/*pwm reg*/
#define PWM_ADDR_BASE 0x12080000
#define PWM_CLOCK_ADDR_BASE 0x120101BC
#define PWM_CLOCK_3M 3000000
#define PWM_CLOCK_24M 24000000
#define PWM_CLOCK_50M 50000000
#define PWM_CTRL_ADDR(x) (((x)*0x100) + 0x0)
#define PWM_CFG_PLUSE_ADDR(x) (((x)*0x100) + 0x10)
#define PWM_CFG_HLINT_ADDR(x) (((x)*0x100) + 0x20)
#define PWM_CFG_CYCLE_ADDR(x) (((x)*0x100) + 0x30)
#define PWM_ENABLE_SHIFT 2
#define PWM_ENABLE_MASK BIT(2)
#define PWM_POLARITY_SHIFT 1
#define PWM_POLARITY_MASK BIT(1)
#define PWM_KEEP_SHIFT 0
#define PWM_KEEP_MASK BIT(0)
#define PWM_PERIOD_MASK 0xffffffff
#define PWM_DUTY_MASK 0xffffffff
#define PWM_MAX_NUM 17
#define CONFIG_PARAM_MEM_START (CONFIG_TEXT_BASE + CONFIG_MCU_SRAM_SIZE - CONFIG_PARAM_MEM_SIZE)
#define CONFIG_DDR_BASE 0x40000000
/* ------------------------- Interrupt Number Definition ------------------------ */
#define IRQ_NUM_M_SW 3 /* Machine software interrupt */
#define IRQ_NUM_CORE_TIMER 7 /* core Timer Interrupt */
#define IRQ_NUM_M_EXT 11 /* Machine external interrupt */
#define IRQ_NUM_RTC 16 /* rtc Interrupt */
#define IRQ_NUM_SOFTWARE 17 /* software Interrupt */
#define IRQ_NUM_WDG2 20 /* watchdog2 Interrupt */
#define IRQ_NUM_IR 21 /* ir Interrupt */
#define IRQ_NUM_TIMER3 26 /* timer3 Interrupt */
#define IRQ_NUM_I2C0 36 /* i2c0 Interrupt */
#define IRQ_NUM_I2C1 37 /* i2c1 Interrupt */
#define IRQ_NUM_I2C2 38 /* i2c2 Interrupt */
#define IRQ_NUM_I2C3 39 /* i2c3 Interrupt */
#define IRQ_NUM_I2C4 40 /* i2c4 Interrupt */
#define IRQ_NUM_I2C5 41 /* i2c5 Interrupt */
#define IRQ_NUM_I2C6 42 /* i2c6 Interrupt */
#define IRQ_NUM_I2C7 43 /* i2c7 Interrupt */
#define IRQ_NUM_TIMER4 44 /* timer4 Interrupt */
#define IRQ_NUM_TIMER5 45 /* timer5 Interrupt */
#define IRQ_NUM_SPI0 46 /* spi0 Interrupt */
#define IRQ_NUM_SPI1 47 /* spi1 Interrupt */
#define IRQ_NUM_SPI2 48 /* spi2 Interrupt */
#define IRQ_NUM_SPI3 49 /* spi3 Interrupt */
#define IRQ_NUM_MBOX 105 /* CPU2MCU Mailbox Interrupt */
#endif
File diff suppressed because it is too large Load Diff
+53
View File
@@ -0,0 +1,53 @@
#include <stdio.h>
#include <config.h>
#include <io.h>
#include <interrupt.h>
#include <core.h>
void systick_handler(void)
{
}
ATTRIBUTE_ISR void core_timer_irq_handler(void)
{
systick_handler();
}
ATTRIBUTE_ISR void nmi_handler(void)
{
puts("NMI Exception!\n");
puts("mepc : 0x");puthex(__get_MEPC());puts("\n");
puts("mnmipc : 0x");puthex(__get_MNMIPC());puts("\n");
puts("mcause : 0x");puthex(__get_MCAUSE());puts("\n");
puts("mnmicause : 0x");puthex(__get_MNMICAUSE());puts("\n");
puts("mstatus : 0x");puthex(__get_MSTATUS());puts("\n");
puts("mtval : 0x");puthex(__get_MTVAL());puts("\n");
puts("mxstatus : 0x");puthex(__get_MXSTATUS());puts("\n");
puts("mexstatus : 0x");puthex(__get_MEXSTATUS());puts("\n");
puts("mintstatus : 0x");puthex(__get_MINTSTATUS());puts("\n");
puts("mie : 0x");puthex(__get_MIE());puts("\n");
puts("mhcr : 0x");puthex(__get_MHCR());puts("\n");
}
ATTRIBUTE_ISR void mbox_handler(void)
{
puts("Mailbox interrupt!\n");
writel(0, 0x100AF030);
}
int irq_init(void)
{
int ret;
ret = drv_irq_register(IRQ_NUM_MBOX, &mbox_handler);
if (ret <0) {
puts("Fail to register Mailbox irq!\n");
}
return 0;
}
+191
View File
@@ -0,0 +1,191 @@
#include <config.h>
.text
.align 2
.globl _start
.type _start, %function
_start:
.option push
.option norvc
.option norelax
/* struct mcu_fw_head */
j _reset
.word CONFIG_MCU_FW_MAGIC
.word CONFIG_MCU_FW_VERSION
.word __bin_end - _start
.word (CONFIG_STAGE2_START - CONFIG_TEXT_BASE)
.option pop
.=CONFIG_MCU_HEAD_SIZE
.align 2
_reset:
.option push
.option norelax
la gp, __global_pointer$
.option pop
la a0, default_handler
ori a0, a0, 3
csrw mtvec, a0
la a0, __vectors
csrw mtvt, a0
la sp, g_top_irqstack
csrw mscratch, sp
/* Clear bss section */
la a0, __bss_start
la a1, __bss_end
bgeu a0, a1, 2f
1:
sw zero, (a0)
addi a0, a0, 4
bltu a0, a1, 1b
2:
jal system_init
jal main
.size _start, . - _start
__exit:
j __exit
.section .stack, "aw", @nobits
.align 2
.global g_base_irqstack
.global g_top_irqstack
g_base_irqstack:
.space CONFIG_STACK_SIZE
g_top_irqstack:
.section .vectors, "aw", @progbits
.align 6
.globl __vectors
.type __vectors, @object
__vectors:
.long default_handler
.long default_handler
.long default_handler
.long tspend_handler
.long default_handler
.long default_handler
.long default_handler
.long core_timer_irq_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
/* External interrupts */
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.long default_handler
.size __vectors, . - __vectors
+105
View File
@@ -0,0 +1,105 @@
#include <stdio.h>
#include <malloc.h>
#include <config.h>
#include <core.h>
#include <interrupt.h>
#include <common.h>
void show_memlayout(void)
{
puts("Mem Layout Info:\n");
puts(".text : 0x");puthex((ulong)&__text_start); puts(" - 0x");puthex((ulong)&__text_end);puts("\n");
puts(".rodata : 0x");puthex((ulong)&__rodata_start); puts(" - 0x");puthex((ulong)&__rodata_end);puts("\n");
puts(".data : 0x");puthex((ulong)&__data_start); puts(" - 0x");puthex((ulong)&__data_end);puts("\n");
puts(".text2 : 0x");puthex((ulong)&__text2_start); puts(" - 0x");puthex((ulong)&__text2_end);puts("\n");
puts(".rodata2 : 0x");puthex((ulong)&__rodata2_start); puts(" - 0x");puthex((ulong)&__rodata2_end);puts("\n");
puts(".data2 : 0x");puthex((ulong)&__data2_start); puts(" - 0x");puthex((ulong)&__data2_end);puts("\n");
puts(".bss : 0x");puthex((ulong)&__bss_start); puts(" - 0x");puthex((ulong)&__bss_end);puts("\n");
puts(".stack : 0x");puthex((ulong)&g_base_irqstack); puts(" - 0x");puthex((ulong)&g_top_irqstack);puts("(top)\n");
puts("Heap : 0x");puthex(g_heap_start); puts(" - 0x");puthex(g_heap_end);puts("\n");
puts("Param : 0x");puthex((ulong)&__param_start); puts(" - 0x");puthex((ulong)&__param_start + CONFIG_PARAM_MEM_SIZE);puts("\n");
puts("\n");
}
void clic_config(void)
{
int i, num_int;
/* get interrupt level from info */
CLIC->CLICCFG = (((CLIC->CLICINFO & CLIC_INFO_CLICINTCTLBITS_Msk) >> CLIC_INFO_CLICINTCTLBITS_Pos) << CLIC_CLICCFG_NLBIT_Pos);
/* get interrutp num */
num_int = CLIC->CLICINFO & 0x1fff ? CLIC->CLICINFO & 0x1fff : 256;
for (i = 0; i < num_int; i++) {
CLIC->CLICINT[i].IP = 0;
/* use vector interrupt */
CLIC->CLICINT[i].ATTR = 1;
/* set all interrupts with lowest prio */
rv32_vic_set_prio(i, 0);
}
}
void cpu_config(void)
{
#ifdef CONFIG_XTHEAD_ISA_EXT
uint32_t mxstatus = __get_MXSTATUS();
#endif
uint32_t mstatus = __get_MSTATUS();
uint32_t mhcr = __get_MHCR();
/* enable mstatus FS and XS */
mstatus |= (1 << 13);
mstatus |= (3 << 15);
__set_MSTATUS(mstatus);
#ifdef CONFIG_XTHEAD_ISA_EXT
Enable T-HEAD Ext instruction set
mxstatus |= (1 << 22);
__set_MXSTATUS(mxstatus);
#endif
mhcr &= ~(CACHE_MHCR_WA_Msk | CACHE_MHCR_WB_Msk);
mhcr |= CACHE_MHCR_RS_Msk | CACHE_MHCR_BPE_Msk | CACHE_MHCR_L0BTB_Msk;
__set_MHCR(mhcr);
}
void cache_config(void)
{
/* rv32_dcache_enable(); */ //FIXME
rv32_icache_enable();
}
void system_init(void)
{
timer_init();
serial_init();
puts_always("MCU Start\n\n");
cpu_config();
clic_config();
irq_init();
cache_config();
__enable_excp_irq();
/* core_timer_config(drv_get_sys_freq() / CONFIG_SYSTICK_HZ, CORET_IRQn); //10ms */
malloc_init((u32)_end, _start + CONFIG_MCU_SRAM_SIZE - _end - CONFIG_PARAM_MEM_SIZE);
rsv_mem_init(CONFIG_DDR_BASE + (ulong)get_ddr_size() - CONFIG_RESERVED_MEM_SIZE, CONFIG_RESERVED_MEM_SIZE);
#ifdef CONFIG_DEBUG_INFO
puts("\nRISC-V status:\n");
puts("MSTATUS: 0x");puthex(__get_MSTATUS());puts("\n");
puts("MXSTATUS: 0x");puthex(__get_MXSTATUS());puts("\n");
puts("MHCR: 0x");puthex(__get_MHCR());puts("\n\n");
show_memlayout();
#endif
}
+6
View File
@@ -0,0 +1,6 @@
#include <platform.h>
.section ".tail"
.fill 0x200,1,0
+39
View File
@@ -0,0 +1,39 @@
#include <config.h>
#include <stdint.h>
#ifndef CONFIG_PRINT
#define CONFIG_PRINT
#endif
#include <stdio.h>
#include <stdlib.h>
#include <core.h>
void (*trap_c_callback)(void);
void trap_c(uint32_t *regs)
{
int i;
uint32_t vec = 0;
vec = __get_MCAUSE() & 0x3FF;
puts("CPU Exception: NO.");puthex(vec);puts("\n");
for (i = 0; i < 31; i++) {
puts("x");putdec(i+1);puts(": 0x");puthex(regs[i]);puts("\t");
if ((i % 4) == 3) {
puts("\n");
}
}
puts("\n");
puts("mepc : 0x");puthex(regs[31]);puts("\n");
puts("mstatus: : 0x");puthex(regs[32]);puts("\n");
if (trap_c_callback) {
trap_c_callback();
}
while (1);
}
+116
View File
@@ -0,0 +1,116 @@
#include <config.h>
.section .stack.trap, "aw", @nobits
.align 2
.globl g_trapstackalloc
.global g_trapstackbase
.global g_top_trapstack
g_trapstackalloc:
g_trapstackbase:
.space 768
g_top_trapstack:
.align 2
.globl g_trap_sp
.type g_trap_sp, object
g_trap_sp:
.long 0
.size g_trap_sp, .-g_trap_sp
/******************************************************************************
* Functions:
* void trap(void);
* default exception handler
******************************************************************************/
.text
.align 2
.global trap
.type trap, %function
trap:
la t0, g_trap_sp
addi t0, t0, -132
sw x1, 0(t0)
sw x2, 4(t0)
sw x3, 8(t0)
sw x4, 12(t0)
sw x6, 20(t0)
sw x7, 24(t0)
sw x8, 28(t0)
sw x9, 32(t0)
sw x10, 36(t0)
sw x11, 40(t0)
sw x12, 44(t0)
sw x13, 48(t0)
sw x14, 52(t0)
sw x15, 56(t0)
sw x16, 60(t0)
sw x17, 64(t0)
sw x18, 68(t0)
sw x19, 72(t0)
sw x20, 76(t0)
sw x21, 80(t0)
sw x22, 84(t0)
sw x23, 88(t0)
sw x24, 92(t0)
sw x25, 96(t0)
sw x26, 100(t0)
sw x27, 104(t0)
sw x28, 108(t0)
sw x29, 112(t0)
sw x30, 116(t0)
sw x31, 120(t0)
csrr a0, mepc
sw a0, 124(t0)
csrr a0, mstatus
sw a0, 128(t0)
mv a0, t0
lw t0, -4(sp)
mv sp, a0
sw t0, 16(sp)
jal trap_c
.align 6
.weak default_handler
.global default_handler
.type default_handler, %function
default_handler:
/* Check for nmi */
addi sp, sp, -8
sw t0, 0x0(sp)
sw t1, 0x4(sp)
csrr t0, mcause
andi t0, t0, 0x3FF
li t1, 24
beq t0, t1, .nmi_handler
lw t0, 0x0(sp)
lw t1, 0x4(sp)
addi sp, sp, 8
j trap
.nmi_handler:
lw t0, 0x0(sp)
lw t1, 0x4(sp)
addi sp, sp, 8
j nmi_handler
.size default_handler, . - default_handler
/* Macro to define default handlers. Default handler
* will be weak symbol and just dead loops. They can be
* overwritten by other handlers */
.macro def_irq_handler handler_name
.weak \handler_name
.globl \handler_name
.set \handler_name, default_handler
.endm
def_irq_handler tspend_handler
def_irq_handler core_timer_irq_handler
+99
View File
@@ -0,0 +1,99 @@
SRCS-y :=
TEMPS :=
include $(CONFIG_FILE)
include $(TOPDIR)/$(SRCDIR)Makefile
include $(TOPDIR)/scripts/Makefile.define
# find all directory in SRCS-y
SRCS-subdir := $(filter-out %.c %.S,$(SRCS-y))
# find all file in SRCS-y
SRCS-y := $(addprefix $(SRCDIR),$(SRCS-y))
# start.S file
ifneq ("$(START)","")
START := $(O)$(SRCDIR)$(START:.S=.o)
else
START :=
endif
ifneq ("$(TAIL)","")
TAIL := $(O)$(SRCDIR)$(TAIL:.S=.o)
else
TAIL :=
endif
# relative path
LIB_SUBOBJS := $(foreach LIB,$(SRCS-subdir),$(SRCDIR)$(LIB)lib$(LIB:/=).a)
AOBJS := $(addprefix $(O),$(subst .S,.o,$(filter %.S,$(SRCS-y))))
ADEPS := $(AOBJS:.o=.d) $(START:.o=.d) $(TAIL:.o=.d)
COBJS := $(addprefix $(O),$(subst .c,.o,$(filter %.c,$(SRCS-y))))
CDEPS := $(COBJS:.o=.d)
ALG_LIBS := media/alg_libs/libae.a media/alg_libs/libawb.a
# all xxx.o, exclude start.o,libxxx.a
OBJS := $(strip $(AOBJS) $(COBJS))
# all depend file, exclude libxxx.a
DEPS := $(CDEPS) $(ADEPS)
_MKDEP := $(O)$(SRCDIR)$(MKDEP)
P_MKDEP := $(O)$(SRCDIR)../$(MKDEP)
$(shell test -d $(O)$(SRCDIR) || mkdir -p $(O)$(SRCDIR))
################################################################################
lib$(notdir $(SRCDIR:/=)).a: $(_MKDEP) $(LIB_SUBOBJS) $(OBJS) $(CONFIG_FILE)
$(call show_cmd,LD,$(SRCDIR)$@)
$(Q)${LD} $(LDFLAGS) -EL -r -o $(O)$(SRCDIR)$@ $(OBJS) $(addprefix $(O),$(LIB_SUBOBJS))
$(MCU).elf: $(START) $(TAIL) $(OBJS) $(_MKDEP) $(O)$(SRCDIR)$(LINKLDS) $(CONFIG_FILE) force
$(call show_cmd,LD,libstage1.a)
$(Q)${LD} $(LDFLAGS) -EL -r -o $(O)$(SRCDIR)/libstage1.a $(OBJS) $(addprefix $(O),$(LIBS))
$(call show_cmd,LD,libstage2.a)
$(Q)${LD} $(LDFLAGS) -EL -r -o $(O)$(SRCDIR)/libstage2.a $(addprefix $(O),$(LIBS-stage2)) $(ALG_LIBS)
$(call show_cmd,LD,$@)
$(Q)$(LD) -L$(O)$(SRCDIR) -X -Bstatic \
--gc-sections $(if $(filter 1,$(strip $(V))),--print-gc-sections) \
--print-memory-usage \
-T$(O)$(SRCDIR)$(LINKLDS) \
-Ttext $(CONFIG_TEXT_BASE) \
$(LDFLAGS) \
-Map $(O)$(@:.elf=.map) -o $(O)$@
$(O)$(SRCDIR)$(LINKLDS): $(TOPDIR)/$(SRCDIR)$(addsuffix .S,$(LINKLDS)) force
$(call show_cmd,CC,$@)
$(Q)$(CC) -E -P $(ASFLAGS) -DLINKER_SCRIPT -o $@ $<
$(LIB_SUBOBJS): $(CONFIG_FILE) $(_MKDEP)
$(Q)$(MAKE) $(MKFLAGS) -C $(TOPDIR)/$(@D)/ SRCDIR="$(@D)/" O="$(O)" $(@F)
$(COBJS): $(_MKDEP) $(CONFIG_FILE)
$(call show_cmd,CC,$(SRCDIR)$(@F:.o=.c))
$(call $(@F:.o=_cmd))
$(CDEPS): $(_MKDEP) $(CONFIG_FILE)
$(call show_cmd,DEP,$(SRCDIR)$(@F:.d=.c))
$(Q)$(CC) -M $(TOPDIR)/$(SRCDIR)$(@F:.d=.c) $(CFLAGS) \
| sed -e "s,^$(@F:.d=.o),$(@:.d=.o),g" > $(@)
(echo $(@F:.d=_cmd)=$$\(Q\)$(CC) -c $(TOPDIR)/$(SRCDIR)$(@F:.d=.c) $(CFLAGS) $$\(CFLAGS_$(basename $(@F))\) -o $(@:.d=.o);) >> $(@)
$(AOBJS) $(START) $(TAIL): $(_MKDEP) $(CONFIG_FILE)
$(call show_cmd,CC,$(SRCDIR)$(@F:.o=.S))
$(call $(@F:.o=_cmd))
$(ADEPS): $(_MKDEP) $(CONFIG_FILE)
$(call show_cmd,DEP,$(SRCDIR)$(@F:.d=.S))
$(Q)$(CC) -M $(TOPDIR)/$(SRCDIR)$(@F:.d=.S) $(ASFLAGS) \
| sed -e "s,^$(@F:.d=.o),$(@:.d=.o),g" > $(@)
(echo $(@F:.d=_cmd)=$(Q)$(CC) -c $(TOPDIR)/$(SRCDIR)$(@F:.d=.S) $(ASFLAGS) $$\(CFLAGS_$(basename $(@F))\) -o $(@:.d=.o);) >> $(@)
$(_MKDEP): $(TOPDIR)/$(SRCDIR)Makefile $(P_MKDEP)
$(Q)touch $@
force:;
sinclude $(DEPS)
+37
View File
@@ -0,0 +1,37 @@
SRCS-y :=
TEMPS :=
sinclude $(CONFIG_FILE)
sinclude $(TOPDIR)/$(SRCDIR)Makefile
include $(TOPDIR)/scripts/Makefile.define
# find all directory in SRCS-y
SRCS-subdir := $(filter-out %.c %.S,$(SRCS-y))
# find all file in SRCS-y
SRCS-y := $(addprefix $(SRCDIR),$(SRCS-y) $(START) $(TAIL))
# relative path
LIBOBJS := $(O)$(SRCDIR)lib$(notdir $(SRCDIR:/=)).a
LIB_SUBOBJS := $(wildcard $(foreach LIB,$(SRCS-subdir),$(SRCDIR)$(LIB)lib$(LIB:/=).a))
AOBJS := $(addprefix $(O),$(subst .S,.o,$(filter %.S,$(SRCS-y))))
ADEPS := $(AOBJS:.o=.d) $(START:.o=.d) $(TAIL:.o=.d)
COBJS := $(addprefix $(O),$(subst .c,.o,$(filter %.c,$(SRCS-y))))
CDEPS := $(COBJS:.o=.d)
# all xxx.o, exclude start.o,libxxx.a
OBJS := $(strip $(AOBJS) $(COBJS))
# all depend file, exclude libxxx.a
DEPS := $(CDEPS) $(ADEPS)
################################################################################
clean: $(addsuffix .clean,$(LIB_SUBOBJS))
$(call show_cmd,clean,$(SRCDIR))
$(Q)$(RM) $(OBJS) $(DEPS) $(LIBOBJS) $(O)$(SRCDIR)$(MKDEP)
$(addsuffix .clean,$(LIB_SUBOBJS)):
$(call show_cmd,ENTRY,$(TOPDIR)/$(@D))
$(Q)$(MAKE) $(CLFLAGS) SRCDIR="$(@D)/" O="$(O)" clean
+24
View File
@@ -0,0 +1,24 @@
SHELL := $(shell if [ -x "$${BASH}" ]; then echo $${BASH}; \
else if [ -x /bin/bash ]; then echo /bin/bash; \
else echo sh; fi; \
fi)
# $(call show_cmd,cmd,file)
define show_cmd
@(CMD=" "$1" "; echo "$${CMD:0:10}$2";)
endef
# $(call checkdir,dir)
define checkdir
@(test -d $1 || mkdir -p $1)
endef
# $(call upper,val)
define upper
$(strip $(shell echo $1 | tr a-z A-Z))
endef
# $(call is_enable,val,true-case,false-case)
define is_enabled
$(if $(filter y,$($(strip $(1)))),$(2),$(3))
endef
+10
View File
@@ -0,0 +1,10 @@
/^[A-Za-z][A-Za-z0-9_]*/ {
# add #define to the line head
s/^/#define /;
# remove '='
s/=/ /;
p
}