GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)
This commit is contained in:
Executable
+166
@@ -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)
|
||||
################################################################################
|
||||
Executable
+10
@@ -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
|
||||
@@ -0,0 +1,4 @@
|
||||
|
||||
void reset_cpu(void)
|
||||
{
|
||||
}
|
||||
Executable
+45
@@ -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 = .;
|
||||
}
|
||||
@@ -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__ */
|
||||
@@ -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 */
|
||||
Executable
+113
@@ -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
|
||||
Executable
+19
@@ -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 */
|
||||
|
||||
Executable
+6
@@ -0,0 +1,6 @@
|
||||
#include <platform.h>
|
||||
|
||||
.section .tail,#alloc
|
||||
|
||||
.fill 0x200,1,0
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
SRCS-y += common.c
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
Executable
+30
@@ -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
|
||||
@@ -0,0 +1,7 @@
|
||||
SRCS-y += timer/
|
||||
SRCS-y += serial/
|
||||
SRCS-y += gpio/
|
||||
SRCS-y += stopwatch/
|
||||
SRCS-$(CONFIG_I2C) += i2c/
|
||||
SRCS-$(CONFIG_PWM) += pwm/
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
SRCS-y += gpio.c
|
||||
@@ -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);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
SRCS-y += i2c.c
|
||||
@@ -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);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
SRCS-y += pwm.c
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
SRCS-y += serial.c
|
||||
Executable
+199
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
SRCS-y += stopwatch.c
|
||||
@@ -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));
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
SRCS-y += timer.c
|
||||
Executable
+78
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
|
||||
#ifndef _ASSERT_H_
|
||||
#define _ASSERT_H_
|
||||
|
||||
#include <debug.h>
|
||||
|
||||
#define assert(x) ASSERT(x)
|
||||
|
||||
#endif /* _ASSERT_H_ */
|
||||
@@ -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_*/
|
||||
@@ -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_ */
|
||||
Executable
+5
@@ -0,0 +1,5 @@
|
||||
#ifndef CONFIGH
|
||||
#define CONFIGH
|
||||
#include <autoconf.h>
|
||||
#include <platform.h>
|
||||
#endif
|
||||
@@ -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_ */
|
||||
@@ -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_ */
|
||||
@@ -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_ */
|
||||
@@ -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_ */
|
||||
@@ -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_ */
|
||||
@@ -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_ */
|
||||
@@ -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_ */
|
||||
@@ -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
|
||||
Executable
+17
@@ -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_ */
|
||||
|
||||
@@ -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_ */
|
||||
@@ -0,0 +1,10 @@
|
||||
|
||||
#ifdef CONFIG_ARM_ARCH
|
||||
#include <arm/include/io.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_RISCV_ARCH
|
||||
#include <riscv/include/io.h>
|
||||
#endif
|
||||
|
||||
|
||||
@@ -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__*/
|
||||
|
||||
@@ -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_ */
|
||||
Executable
+61
@@ -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_ */
|
||||
|
||||
@@ -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
|
||||
@@ -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_ */
|
||||
@@ -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
|
||||
@@ -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_ */
|
||||
@@ -0,0 +1,8 @@
|
||||
|
||||
#ifndef _STDBOOL_H_
|
||||
#define _STDBOOL_H_
|
||||
|
||||
#define true 1
|
||||
#define false 0
|
||||
|
||||
#endif /* ifndef _STDBOOL_H_ */
|
||||
@@ -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__ */
|
||||
@@ -0,0 +1,7 @@
|
||||
|
||||
#ifndef _STDINT_H_
|
||||
#define _STDINT_H_
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#endif
|
||||
@@ -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_ */
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
|
||||
#ifndef _STDLIB_H_
|
||||
#define _STDLIB_H_
|
||||
|
||||
#include <malloc.h>
|
||||
|
||||
#endif /* _STDLIB_H_ */
|
||||
@@ -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_ */
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
|
||||
#ifndef _TIME_H_
|
||||
#define _TIME_H_
|
||||
|
||||
#include <timer.h>
|
||||
|
||||
#endif /* _TIME_H_ */
|
||||
@@ -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_ */
|
||||
@@ -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_ */
|
||||
@@ -0,0 +1,7 @@
|
||||
|
||||
#ifndef __VERSION_H__
|
||||
#define __VERSION_H__
|
||||
|
||||
#define MCU_VERSION "v1.00"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,3 @@
|
||||
|
||||
SRCS-y += main.c
|
||||
SRCS-$(CONFIG_SIMPILE_SHELL) += shell.c
|
||||
Executable
+63
@@ -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;
|
||||
}
|
||||
Executable
+289
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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_ */
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
Executable
+53
@@ -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();
|
||||
}
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../media
|
||||
@@ -0,0 +1,3 @@
|
||||
编译命令:
|
||||
make xmfalcon_defconfig
|
||||
make
|
||||
Executable
+12
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
Executable
+130
@@ -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
|
||||
}
|
||||
@@ -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
@@ -0,0 +1,7 @@
|
||||
|
||||
#ifndef __INTERRUPT_H__
|
||||
#define __INTERRUPT_H__
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#endif
|
||||
@@ -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__ */
|
||||
|
||||
Executable
+321
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Executable
+191
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
Executable
+6
@@ -0,0 +1,6 @@
|
||||
#include <platform.h>
|
||||
|
||||
.section ".tail"
|
||||
|
||||
.fill 0x200,1,0
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Executable
+99
@@ -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)
|
||||
Executable
+37
@@ -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
|
||||
Executable
+24
@@ -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
|
||||
Executable
+10
@@ -0,0 +1,10 @@
|
||||
|
||||
|
||||
/^[A-Za-z][A-Za-z0-9_]*/ {
|
||||
# add #define to the line head
|
||||
s/^/#define /;
|
||||
# remove '='
|
||||
s/=/ /;
|
||||
p
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user