add allwinnner driver as submodule

This commit is contained in:
hathach 2021-12-29 18:59:47 +07:00
parent 30aba24ddc
commit 2d13ecde1b
29 changed files with 4 additions and 4842 deletions

3
.gitmodules vendored
View File

@ -134,3 +134,6 @@
[submodule "hw/mcu/infineon/mtb-xmclib-cat3"]
path = hw/mcu/infineon/mtb-xmclib-cat3
url = https://github.com/Infineon/mtb-xmclib-cat3.git
[submodule "hw/mcu/allwinner"]
path = hw/mcu/allwinner
url = https://github.com/hathach/allwinner_driver.git

1
hw/mcu/allwinner Submodule

@ -0,0 +1 @@
Subproject commit c56955e156b1050a4a8ccf8589555148f00a1bb6

View File

@ -1,136 +0,0 @@
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
STACK_UND_SIZE = 0x10000;
STACK_ABT_SIZE = 0x10000;
STACK_IRQ_SIZE = 0x10000;
STACK_FIQ_SIZE = 0x10000;
STACK_SRV_SIZE = 0x40000;
MEMORY
{
ram : org = 0x80000000, len = 8M
heap : org = 0x81000000, len = 16M
}
SECTIONS
{
.bootloader :
{
PROVIDE(__bootloader_start = .);
PROVIDE(__image_start = .);
PROVIDE(__text_start = .);
_build/*/obj/hw/mcu/allwinner/*/machine/start_asm.o (.text)
_build/*/obj/hw/mcu/allwinner/*/lib/memcpy_asm.o (.text)
_build/*/obj/hw/mcu/allwinner/*/lib/memset_asm.o (.text)
_build/*/obj/hw/mcu/allwinner/*/machine/sys-uart.o (.text*)
_build/*/obj/hw/mcu/allwinner/*/machine/sys-clock.o (.text*)
_build/*/obj/hw/mcu/allwinner/*/machine/sys-dram.o (.text*)
_build/*/obj/hw/mcu/allwinner/*/machine/sys-mmu.o (.text*)
_build/*/obj/hw/mcu/allwinner/*/machine/sys-spi-flash.o (.text*)
_build/*/obj/hw/mcu/allwinner/*/machine/sys-copyself.o (.text*)
PROVIDE(__bootloader_end = .);
} > ram
__bootloader_size = SIZEOF(.bootloader);
.text :
{
*(.text*)
*(.glue*)
*(.note.gnu.build-id)
PROVIDE(__text_end = .);
} > ram
.rodata ALIGN(8) :
{
PROVIDE(__rodata_start = .);
*(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
PROVIDE(__rodata_end = .);
} > ram
.data_shadow ALIGN(8) :
{
PROVIDE(__data_shadow_start = .);
PROVIDE(__data_shadow_end = (. + SIZEOF(.data)));
PROVIDE(__image_end = __data_shadow_end);
} > ram
.data : AT(ADDR(.data_shadow))
{
PROVIDE(__data_start = .);
*(.data*)
. = ALIGN(8);
PROVIDE(__data_end = .);
} > ram
.ARM.exidx ALIGN(8) :
{
PROVIDE (__exidx_start = .);
*(.ARM.exidx*)
PROVIDE (__exidx_end = .);
} > ram
.ARM.extab ALIGN(8) :
{
PROVIDE (__extab_start = .);
*(.ARM.extab*)
PROVIDE (__extab_end = .);
} > ram
.bss ALIGN(8) (NOLOAD) :
{
PROVIDE(__bss_start = .);
*(.bss*)
*(.sbss*)
*(COMMON)
. = ALIGN(8);
PROVIDE(__bss_end = .);
} > ram
.stack ALIGN(8) (NOLOAD) :
{
PROVIDE(__stack_start = .);
PROVIDE(__stack_und_start = .);
. += STACK_UND_SIZE;
PROVIDE(__stack_und_end = .);
. = ALIGN(8);
PROVIDE(__stack_abt_start = .);
. += STACK_ABT_SIZE;
PROVIDE(__stack_abt_end = .);
. = ALIGN(8);
PROVIDE(__stack_irq_start = .);
. += STACK_IRQ_SIZE;
PROVIDE(__stack_irq_end = .);
. = ALIGN(8);
PROVIDE(__stack_fiq_start = .);
. += STACK_FIQ_SIZE;
PROVIDE(__stack_fiq_end = .);
. = ALIGN(8);
PROVIDE(__stack_srv_start = .);
. += STACK_SRV_SIZE;
PROVIDE(__stack_srv_end = .);
. = ALIGN(8);
PROVIDE(__stack_end = .);
} > ram
.heap ALIGN(8) (NOLOAD) :
{
PROVIDE(__heap_start = ORIGIN(heap));
PROVIDE(__heap_end = ORIGIN(heap) + LENGTH(heap));
} > heap
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_info 0 : { *(.debug_info) }
.debug_line 0 : { *(.debug_line) }
.debug_pubnames 0 : { *(.debug_pubnames) }
.debug_aranges 0 : { *(.debug_aranges) }
}

View File

@ -1,150 +0,0 @@
#ifndef __ARM32_H__
#define __ARM32_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
struct arm_regs_t {
uint32_t r[13];
uint32_t sp;
uint32_t lr;
uint32_t pc;
uint32_t cpsr;
};
static inline uint32_t arm32_read_p15_c1(void)
{
uint32_t value;
__asm__ __volatile__(
"mrc p15, 0, %0, c1, c0, 0"
: "=r" (value)
:
: "memory");
return value;
}
static inline void arm32_write_p15_c1(uint32_t value)
{
__asm__ __volatile__(
"mcr p15, 0, %0, c1, c0, 0"
:
: "r" (value)
: "memory");
arm32_read_p15_c1();
}
static inline void arm32_interrupt_enable(void)
{
uint32_t tmp;
__asm__ __volatile__(
"mrs %0, cpsr\n"
"bic %0, %0, #(1<<7)\n"
"msr cpsr_cxsf, %0"
: "=r" (tmp)
:
: "memory");
}
static inline void arm32_interrupt_disable(void)
{
uint32_t tmp;
__asm__ __volatile__(
"mrs %0, cpsr\n"
"orr %0, %0, #(1<<7)\n"
"msr cpsr_cxsf, %0"
: "=r" (tmp)
:
: "memory");
}
static inline void arm32_mmu_enable(void)
{
uint32_t value = arm32_read_p15_c1();
arm32_write_p15_c1(value | (1 << 0));
}
static inline void arm32_mmu_disable(void)
{
uint32_t value = arm32_read_p15_c1();
arm32_write_p15_c1(value & ~(1 << 0));
}
static inline void arm32_dcache_enable(void)
{
uint32_t value = arm32_read_p15_c1();
arm32_write_p15_c1(value | (1 << 2));
}
static inline void arm32_dcache_disable(void)
{
uint32_t value = arm32_read_p15_c1();
arm32_write_p15_c1(value & ~(1 << 2));
}
static inline void arm32_icache_enable(void)
{
uint32_t value = arm32_read_p15_c1();
arm32_write_p15_c1(value | (1 << 12));
}
static inline void arm32_icache_disable(void)
{
uint32_t value = arm32_read_p15_c1();
arm32_write_p15_c1(value & ~(1 << 12));
}
static inline uint32_t arm32_smp_processor_id(void)
{
uint32_t tmp;
__asm__ __volatile__(
"mrc p15,0,%0,c0,c0,5\n"
"and %0,%0,#0x3\n"
: "=r" (tmp)
:
: "memory");
return tmp;
}
static inline void arm32_ttb_set(uint32_t base)
{
__asm__ __volatile__(
"mcr p15, 0, %0, c2, c0, 0"
:
: "r" (base)
: "memory");
}
static inline void arm32_domain_set(uint32_t domain)
{
__asm__ __volatile__(
"mcr p15, 0, %0, c3, c0, 0"
:
: "r" (domain)
: "memory");
}
static inline void arm32_tlb_invalidate(void)
{
__asm__ __volatile__(
"mov r0, #0\n"
"mcr p15, 0, r0, c7, c10, 4\n"
"mcr p15, 0, r0, c8, c6, 0\n"
"mcr p15, 0, r0, c8, c5, 0\n"
:
:
: "r0");
}
#ifdef __cplusplus
}
#endif
#endif /* __ARM32_H__ */

View File

@ -1,66 +0,0 @@
#ifndef __F1C100S_GPIO_H__
#define __F1C100S_GPIO_H__
#ifdef __cplusplus
extern "C" {
#endif
#define F1C100S_GPIOA0 (0)
#define F1C100S_GPIOA1 (1)
#define F1C100S_GPIOA2 (2)
#define F1C100S_GPIOA3 (3)
#define F1C100S_GPIOC0 (64)
#define F1C100S_GPIOC1 (65)
#define F1C100S_GPIOC2 (66)
#define F1C100S_GPIOC3 (67)
#define F1C100S_GPIOD0 (96)
#define F1C100S_GPIOD1 (97)
#define F1C100S_GPIOD2 (98)
#define F1C100S_GPIOD3 (99)
#define F1C100S_GPIOD4 (100)
#define F1C100S_GPIOD5 (101)
#define F1C100S_GPIOD6 (102)
#define F1C100S_GPIOD7 (103)
#define F1C100S_GPIOD8 (104)
#define F1C100S_GPIOD9 (105)
#define F1C100S_GPIOD10 (106)
#define F1C100S_GPIOD11 (107)
#define F1C100S_GPIOD12 (108)
#define F1C100S_GPIOD13 (109)
#define F1C100S_GPIOD14 (110)
#define F1C100S_GPIOD15 (111)
#define F1C100S_GPIOD16 (112)
#define F1C100S_GPIOD17 (113)
#define F1C100S_GPIOD18 (114)
#define F1C100S_GPIOD19 (115)
#define F1C100S_GPIOD20 (116)
#define F1C100S_GPIOD21 (117)
#define F1C100S_GPIOE0 (128)
#define F1C100S_GPIOE1 (129)
#define F1C100S_GPIOE2 (130)
#define F1C100S_GPIOE3 (131)
#define F1C100S_GPIOE4 (132)
#define F1C100S_GPIOE5 (133)
#define F1C100S_GPIOE6 (134)
#define F1C100S_GPIOE7 (135)
#define F1C100S_GPIOE8 (136)
#define F1C100S_GPIOE9 (137)
#define F1C100S_GPIOE10 (138)
#define F1C100S_GPIOE11 (139)
#define F1C100S_GPIOE12 (140)
#define F1C100S_GPIOF0 (160)
#define F1C100S_GPIOF1 (161)
#define F1C100S_GPIOF2 (162)
#define F1C100S_GPIOF3 (163)
#define F1C100S_GPIOF4 (164)
#define F1C100S_GPIOF5 (165)
#ifdef __cplusplus
}
#endif
#endif /* __F1C100S_GPIO_H__ */

View File

@ -1,104 +0,0 @@
#ifndef __F1C100S_IRQ_H__
#define __F1C100S_IRQ_H__
#ifdef __cplusplus
extern "C" {
#endif
#define F1C100S_IRQ_NMI (0)
#define F1C100S_IRQ_UART0 (1)
#define F1C100S_IRQ_UART1 (2)
#define F1C100S_IRQ_UART2 (3)
#define F1C100S_IRQ_SPDIF (5)
#define F1C100S_IRQ_CIR (6)
#define F1C100S_IRQ_I2C0 (7)
#define F1C100S_IRQ_I2C1 (8)
#define F1C100S_IRQ_I2C2 (9)
#define F1C100S_IRQ_SPI0 (10)
#define F1C100S_IRQ_SPI1 (11)
#define F1C100S_IRQ_TIMER0 (13)
#define F1C100S_IRQ_TIMER1 (14)
#define F1C100S_IRQ_TIMER2 (15)
#define F1C100S_IRQ_WDOG (16)
#define F1C100S_IRQ_RSB (17)
#define F1C100S_IRQ_DMA (18)
#define F1C100S_IRQ_TP (20)
#define F1C100S_IRQ_AUDIO (21)
#define F1C100S_IRQ_LRADC (22)
#define F1C100S_IRQ_MMC0 (23)
#define F1C100S_IRQ_MMC1 (24)
#define F1C100S_IRQ_USBOTG (26)
#define F1C100S_IRQ_TVD (27)
#define F1C100S_IRQ_TVE (28)
#define F1C100S_IRQ_LCD (29)
#define F1C100S_IRQ_DEFE (30)
#define F1C100S_IRQ_DEBE (31)
#define F1C100S_IRQ_CSI (32)
#define F1C100S_IRQ_DEITLA (33)
#define F1C100S_IRQ_VE (34)
#define F1C100S_IRQ_I2S (35)
#define F1C100S_IRQ_GPIOD (38)
#define F1C100S_IRQ_GPIOE (39)
#define F1C100S_IRQ_GPIOF (40)
#define F1C100S_IRQ_GPIOD0 (64)
#define F1C100S_IRQ_GPIOD1 (65)
#define F1C100S_IRQ_GPIOD2 (66)
#define F1C100S_IRQ_GPIOD3 (67)
#define F1C100S_IRQ_GPIOD4 (68)
#define F1C100S_IRQ_GPIOD5 (69)
#define F1C100S_IRQ_GPIOD6 (70)
#define F1C100S_IRQ_GPIOD7 (71)
#define F1C100S_IRQ_GPIOD8 (72)
#define F1C100S_IRQ_GPIOD9 (73)
#define F1C100S_IRQ_GPIOD10 (74)
#define F1C100S_IRQ_GPIOD11 (75)
#define F1C100S_IRQ_GPIOD12 (76)
#define F1C100S_IRQ_GPIOD13 (77)
#define F1C100S_IRQ_GPIOD14 (78)
#define F1C100S_IRQ_GPIOD15 (79)
#define F1C100S_IRQ_GPIOD17 (80)
#define F1C100S_IRQ_GPIOD18 (81)
#define F1C100S_IRQ_GPIOD19 (82)
#define F1C100S_IRQ_GPIOD20 (83)
#define F1C100S_IRQ_GPIOD21 (84)
#define F1C100S_IRQ_GPIOE0 (96)
#define F1C100S_IRQ_GPIOE1 (97)
#define F1C100S_IRQ_GPIOE2 (98)
#define F1C100S_IRQ_GPIOE3 (99)
#define F1C100S_IRQ_GPIOE4 (100)
#define F1C100S_IRQ_GPIOE5 (101)
#define F1C100S_IRQ_GPIOE6 (102)
#define F1C100S_IRQ_GPIOE7 (103)
#define F1C100S_IRQ_GPIOE8 (104)
#define F1C100S_IRQ_GPIOE9 (105)
#define F1C100S_IRQ_GPIOE10 (106)
#define F1C100S_IRQ_GPIOE11 (107)
#define F1C100S_IRQ_GPIOE12 (108)
#define F1C100S_IRQ_GPIOF0 (128)
#define F1C100S_IRQ_GPIOF1 (129)
#define F1C100S_IRQ_GPIOF2 (130)
#define F1C100S_IRQ_GPIOF3 (131)
#define F1C100S_IRQ_GPIOF4 (132)
#define F1C100S_IRQ_GPIOF5 (133)
typedef void (*IRQHandleTypeDef)(void);
uint8_t f1c100s_intc_get_nirq(void);
void f1c100s_intc_dispatch(uint8_t nIRQ);
void f1c100s_intc_set_isr(uint8_t nIRQ, IRQHandleTypeDef handle);
void f1c100s_intc_enable_irq(uint8_t nIRQ);
void f1c100s_intc_disable_irq(uint8_t nIRQ);
void f1c100s_intc_unmask_irq(uint8_t nIRQ);
void f1c100s_intc_mask_irq(uint8_t nIRQ);
void f1c100s_intc_force_irq(uint8_t nIRQ);
void f1c100s_intc_clear_pend(uint8_t nIRQ);
void f1c100s_intc_init(void);
#ifdef __cplusplus
}
#endif
#endif /* __F1C100S_IRQ_H__ */

View File

@ -1,39 +0,0 @@
#ifndef __F1C100S_RESET_H__
#define __F1C100S_RESET_H__
#ifdef __cplusplus
extern "C" {
#endif
#define F1C100S_RESET_DMA (6)
#define F1C100S_RESET_SD0 (8)
#define F1C100S_RESET_SD1 (9)
#define F1C100S_RESET_SDRAM (14)
#define F1C100S_RESET_SPI0 (20)
#define F1C100S_RESET_SPI1 (21)
#define F1C100S_RESET_USB_OTG (24)
#define F1C100S_RESET_VE (32)
#define F1C100S_RESET_LCD (36)
#define F1C100S_RESET_DEINTERLACE (37)
#define F1C100S_RESET_CSI (40)
#define F1C100S_RESET_TVD (41)
#define F1C100S_RESET_TVE (42)
#define F1C100S_RESET_DEBE (44)
#define F1C100S_RESET_DEFE (46)
#define F1C100S_RESET_ADDA (64)
#define F1C100S_RESET_SPDIF (65)
#define F1C100S_RESET_CIR (66)
#define F1C100S_RESET_RSB (67)
#define F1C100S_RESET_DAUDIO (76)
#define F1C100S_RESET_I2C0 (80)
#define F1C100S_RESET_I2C1 (81)
#define F1C100S_RESET_I2C2 (82)
#define F1C100S_RESET_UART0 (84)
#define F1C100S_RESET_UART1 (85)
#define F1C100S_RESET_UART2 (86)
#ifdef __cplusplus
}
#endif
#endif /* __F1C100S_RESET_H__ */

View File

@ -1,139 +0,0 @@
// Designed by Hong Xuyao
#ifndef __TARGET_H__
#define __TARGET_H__
////////////////////////////////////////////////////////////////////////////////
#include <stdint.h>
typedef unsigned long ubase_t;
#define MEM_PI_SRAM __attribute__((section("SRAM")))
#define MEM_PI_SUMMARY __attribute__((section("SUMMARY")))
#define MEM_PI_NOINIT __attribute__((section("NOINIT"),zero_init))
#define MEM_PI_CPUONLY __attribute__((section("CPUONLY"),zero_init))
#define MEM_PI_HARDWARE __attribute__((section("HARDWARE"),zero_init,aligned(32)))
#define MEM_PI_NCNB __attribute__((section("NCNB"),zero_init,aligned(32)))
#define MEM_PI_STACK __attribute__((section("STACK"),zero_init,aligned(8)))
#define CACHE_ALIGNED __attribute__((aligned(32)))
#ifndef INLINE
#define INLINE __attribute__((always_inline))
#endif
#ifndef NOINLINE
#define NOINLINE __attribute__((noinline))
#endif
#ifndef NOINLINE_FUNC
#define NOINLINE_FUNC __attribute__((noinline))
#endif
#ifndef ALIGN
#define ALIGN(n) __attribute__((aligned(n)))
#endif
#define CPU_SR_DECL ubase_t cpu_sr
#ifdef __thumb__
#define __SWITCH_TO_ARM__
#pragma arm
#endif
#if 0
#define CPU_ENTER_CRITICAL() do{cpu_sr = util_enter_critical();}while(0)
#else
#define CPU_ENTER_CRITICAL() do{cpu_sr = __fast_enter_critical();}while(0)
static inline ubase_t __fast_enter_critical(void)
{
ubase_t cpu_sr, tmp_sr;
__asm volatile {
MRS cpu_sr, CPSR
ORR tmp_sr, cpu_sr, #0xC0
MSR CPSR_c, tmp_sr
}
return cpu_sr;
}
#endif
#if 0
#define CPU_EXIT_CRITICAL() do{util_exit_critical(cpu_sr);}while(0)
#else
#define CPU_EXIT_CRITICAL() do{__fast_exit_critical(cpu_sr);}while(0)
static inline void __fast_exit_critical(ubase_t cpu_sr)
{
__asm volatile {
MSR CPSR_c, cpu_sr
}
}
#endif
static inline unsigned CPU_CLZ16(uint16_t val)
{
__asm volatile {
CLZ val, val
}
return (val - 16);
}
static inline uint8_t __swap_byte(uint8_t newval, uint8_t volatile* pmem)
{
uint8_t oldval;
__asm volatile {
SWPB oldval, newval, [pmem]
};
return oldval;
}
static inline uint32_t UTL_REV32(uint32_t val)
{
uint32_t tmpval;
__asm volatile {
EOR tmpval, val, val, ROR #16
MOV tmpval, tmpval, LSR #8
BIC tmpval, tmpval, #0xFF00
EOR val, tmpval, val, ROR #8
}
return val;
}
static inline uint16_t UTL_REV16(uint16_t val)
{
uint32_t tmpval;
__asm volatile {
LSR tmpval, val, #8
ORR val, tmpval, val, LSL #8
BIC val, val, #0xFF0000
}
return val;
}
#ifdef __SWITCH_TO_ARM__
#undef __SWITCH_TO_ARM__
#pragma thumb
#endif
#ifndef COUNTOF
#define COUNTOF(ar) (sizeof(ar)/sizeof(ar[0]))
#endif
/*
void util_halt(void);
void util_fastloop(ubase_t n);
ubase_t util_getCPSR(void);
ubase_t util_enter_critical(void);
void util_exit_critical(ubase_t sr);
void util_enable_interrupt(void);
void util_disable_interrupt(void);
void target_wdt_setup(void);
void target_wdt_feed(void);
void target_reset(void);
*/
////////////////////////////////////////////////////////////////////////////////
#endif /* __TARGET_H__ */

View File

@ -1,55 +0,0 @@
#ifndef __F1C100S_REG_CCU_H__
#define __F1C100S_REG_CCU_H__
#define F1C100S_CCU_BASE (0x01c20000)
#define CCU_PLL_CPU_CTRL (0x000)
#define CCU_PLL_AUDIO_CTRL (0x008)
#define CCU_PLL_VIDEO_CTRL (0x010)
#define CCU_PLL_VE_CTRL (0x018)
#define CCU_PLL_DDR_CTRL (0x020)
#define CCU_PLL_PERIPH_CTRL (0x028)
#define CCU_CPU_CFG (0x050)
#define CCU_AHB_APB_CFG (0x054)
#define CCU_BUS_CLK_GATE0 (0x060)
#define CCU_BUS_CLK_GATE1 (0x064)
#define CCU_BUS_CLK_GATE2 (0x068)
#define CCU_SDMMC0_CLK (0x088)
#define CCU_SDMMC1_CLK (0x08c)
#define CCU_DAUDIO_CLK (0x0b0)
#define CCU_SPDIF_CLK (0x0b4)
#define CCU_I2S_CLK (0x0b8)
#define CCU_USBPHY_CFG (0x0cc)
#define CCU_DRAM_CLK_GATE (0x100)
#define CCU_DEBE_CLK (0x104)
#define CCU_DEFE_CLK (0x10c)
#define CCU_LCD_CLK (0x118)
#define CCU_DEINTERLACE_CLK (0x11c)
#define CCU_TVE_CLK (0x120)
#define CCU_TVD_CLK (0x124)
#define CCU_CSI_CLK (0x134)
#define CCU_VE_CLK (0x13c)
#define CCU_ADDA_CLK (0x140)
#define CCU_AVS_CLK (0x144)
#define CCU_PLL_STABLE_TIME0 (0x200)
#define CCU_PLL_STABLE_TIME1 (0x204)
#define CCU_PLL_CPU_BIAS (0x220)
#define CCU_PLL_AUDIO_BIAS (0x224)
#define CCU_PLL_VIDEO_BIAS (0x228)
#define CCU_PLL_VE_BIAS (0x22c)
#define CCU_PLL_DDR0_BIAS (0x230)
#define CCU_PLL_PERIPH_BIAS (0x234)
#define CCU_PLL_CPU_TUN (0x250)
#define CCU_PLL_DDR_TUN (0x260)
#define CCU_PLL_AUDIO_PAT (0x284)
#define CCU_PLL_VIDEO_PAT (0x288)
#define CCU_PLL_DDR0_PAT (0x290)
#define CCU_BUS_SOFT_RST0 (0x2c0)
#define CCU_BUS_SOFT_RST1 (0x2c4)
#define CCU_BUS_SOFT_RST3 (0x2d0)
#endif /* __F1C100S_REG_CCU_H__ */

View File

@ -1,39 +0,0 @@
#ifndef __F1C100S_REG_DRAM_H__
#define __F1C100S_REG_DRAM_H__
#define F1C100S_DRAM_BASE (0x01c01000)
#define DRAM_SCONR (0x00)
#define DRAM_STMG0R (0x04)
#define DRAM_STMG1R (0x08)
#define DRAM_SCTLR (0x0c)
#define DRAM_SREFR (0x10)
#define DRAM_SEXTMR (0x14)
#define DRAM_DDLYR (0x24)
#define DRAM_DADRR (0x28)
#define DRAM_DVALR (0x2c)
#define DRAM_DRPTR0 (0x30)
#define DRAM_DRPTR1 (0x34)
#define DRAM_DRPTR2 (0x38)
#define DRAM_DRPTR3 (0x3c)
#define DRAM_SEFR (0x40)
#define DRAM_MAE (0x44)
#define DRAM_ASPR (0x48)
#define DRAM_SDLY0 (0x4C)
#define DRAM_SDLY1 (0x50)
#define DRAM_SDLY2 (0x54)
#define DRAM_MCR0 (0x100)
#define DRAM_MCR1 (0x104)
#define DRAM_MCR2 (0x108)
#define DRAM_MCR3 (0x10c)
#define DRAM_MCR4 (0x110)
#define DRAM_MCR5 (0x114)
#define DRAM_MCR6 (0x118)
#define DRAM_MCR7 (0x11c)
#define DRAM_MCR8 (0x120)
#define DRAM_MCR9 (0x124)
#define DRAM_MCR10 (0x128)
#define DRAM_MCR11 (0x12c)
#define DRAM_BWCR (0x140)
#endif /* __F1C100S_REG_DRAM_H__ */

View File

@ -1,57 +0,0 @@
#ifndef __IO_H__
#define __IO_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <types.h>
static inline u8_t read8(virtual_addr_t addr)
{
return( *((volatile u8_t *)(addr)) );
}
static inline u16_t read16(virtual_addr_t addr)
{
return( *((volatile u16_t *)(addr)) );
}
static inline u32_t read32(virtual_addr_t addr)
{
return( *((volatile u32_t *)(addr)) );
}
static inline u64_t read64(virtual_addr_t addr)
{
return( *((volatile u64_t *)(addr)) );
}
static inline void write8(virtual_addr_t addr, u8_t value)
{
*((volatile u8_t *)(addr)) = value;
}
static inline void write16(virtual_addr_t addr, u16_t value)
{
*((volatile u16_t *)(addr)) = value;
}
static inline void write32(virtual_addr_t addr, u32_t value)
{
*((volatile u32_t *)(addr)) = value;
}
static inline void write64(virtual_addr_t addr, u64_t value)
{
*((volatile u64_t *)(addr)) = value;
}
virtual_addr_t phys_to_virt(physical_addr_t phys);
physical_addr_t virt_to_phys(virtual_addr_t virt);
#ifdef __cplusplus
}
#endif
#endif /* __IO_H__ */

View File

@ -1,104 +0,0 @@
#ifndef __ARM32_IRQFLAGS_H__
#define __ARM32_IRQFLAGS_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <types.h>
#if __ARM32_ARCH__ == 5
static inline void arch_local_irq_enable(void)
{
irq_flags_t temp;
__asm__ __volatile__(
"mrs %0, cpsr\n"
"bic %0, %0, #(1<<7)\n"
"msr cpsr_c, %0"
: "=r" (temp)
:
: "memory", "cc");
}
static inline void arch_local_irq_disable(void)
{
irq_flags_t temp;
__asm__ __volatile__(
"mrs %0, cpsr\n"
"orr %0, %0, #(1<<7)\n"
"msr cpsr_c, %0"
: "=r" (temp)
:
: "memory", "cc");
}
static inline irq_flags_t arch_local_irq_save(void)
{
irq_flags_t flags, temp;
__asm__ __volatile__(
"mrs %0, cpsr\n"
"orr %1, %0, #(1<<7)\n"
"msr cpsr_c, %1"
: "=r" (flags), "=r" (temp)
:
: "memory", "cc");
return flags;
}
static inline void arch_local_irq_restore(irq_flags_t flags)
{
__asm__ __volatile__(
"msr cpsr_c, %0"
:
: "r" (flags)
: "memory", "cc");
}
#else
static inline void arch_local_irq_enable(void)
{
__asm__ __volatile__("cpsie i" ::: "memory", "cc");
}
static inline void arch_local_irq_disable(void)
{
__asm__ __volatile__("cpsid i" ::: "memory", "cc");
}
static inline irq_flags_t arch_local_irq_save(void)
{
irq_flags_t flags;
__asm__ __volatile__(
"mrs %0, cpsr\n"
"cpsid i"
: "=r" (flags)
:
: "memory", "cc");
return flags;
}
static inline void arch_local_irq_restore(irq_flags_t flags)
{
__asm__ __volatile__(
"msr cpsr_c, %0"
:
: "r" (flags)
: "memory", "cc");
}
#endif
#define local_irq_enable() do { arch_local_irq_enable(); } while(0)
#define local_irq_disable() do { arch_local_irq_disable(); } while(0)
#define local_irq_save(flags) do { flags = arch_local_irq_save(); } while(0)
#define local_irq_restore(flags) do { arch_local_irq_restore(flags); } while(0)
#ifdef __cplusplus
}
#endif
#endif /* __ARM32_IRQFLAGS_H__ */

View File

@ -1,35 +0,0 @@
#ifndef __MALLOC_H__
#define __MALLOC_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <types.h>
#include <stddef.h>
#include <string.h>
#include <assert.h>
void * mm_create(void * mem, size_t bytes);
void mm_destroy(void * mm);
void * mm_get_pool(void * mm);
void * mm_add_pool(void * mm, void * mem, size_t bytes);
void mm_remove_pool(void * mm, void * pool);
void * mm_malloc(void * mm, size_t size);
void * mm_memalign(void * mm, size_t align, size_t size);
void * mm_realloc(void * mm, void * ptr, size_t size);
void mm_free(void * mm, void * ptr);
void * malloc(size_t size);
void * memalign(size_t align, size_t size);
void * realloc(void * ptr, size_t size);
void * calloc(size_t nmemb, size_t size);
void free(void * ptr);
void do_init_mem_pool(void);
#ifdef __cplusplus
}
#endif
#endif /* __MALLOC_H__ */

View File

@ -1,99 +0,0 @@
///////////////////////////////////////////////////////////////////////////////
// \author (c) Marco Paland (info@paland.com)
// 2014-2018, 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 snprintf implementation, optimized for speed on
// embedded systems with a very limited resources.
// Use this instead of bloated standard/newlib printf.
// These routines are thread safe and reentrant!
//
///////////////////////////////////////////////////////////////////////////////
#ifndef _PRINTF_H_
#define _PRINTF_H_
#include <stdarg.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* Output a character to a custom device like UART, used by the printf() function
* This function is declared here only. You have to write your custom implementation somewhere
* \param character Character to output
*/
void _putchar(char character);
/**
* Tiny printf implementation
* You have to implement _putchar if you use printf()
* \param format A string that specifies the format of the output
* \return The number of characters that are written into the array, not counting the terminating null character
*/
int printf(const char* format, ...);
/**
* Tiny sprintf implementation
* Due to security reasons (buffer overflow) YOU SHOULD CONSIDER USING (V)SNPRINTF INSTEAD!
* \param buffer A pointer to the buffer where to store the formatted string. MUST be big enough to store the output!
* \param format A string that specifies the format of the output
* \return The number of characters that are WRITTEN into the buffer, not counting the terminating null character
*/
int sprintf(char* buffer, const char* format, ...);
/**
* Tiny snprintf/vsnprintf implementation
* \param buffer A pointer to the buffer where to store the formatted string
* \param count The maximum number of characters to store in the buffer, including a terminating null character
* \param format A string that specifies the format of the output
* \return The number of characters that are WRITTEN into the buffer, not counting the terminating null character
* If the formatted string is truncated the buffer size (count) is returned
*/
int snprintf(char* buffer, size_t count, const char* format, ...);
int vsnprintf(char* buffer, size_t count, const char* format, va_list va);
/**
* printf with output function
* You may use this as dynamic alternative to printf() with its fixed _putchar() output
* \param out An output function which takes one character and an argument pointer
* \param arg An argument pointer for user data passed to output function
* \param format A string that specifies the format of the output
* \return The number of characters that are sent to the output function, not counting the terminating null character
*/
int fctprintf(void (*out)(char character, void* arg), void* arg, const char* format, ...);
#ifdef __cplusplus
}
#endif
#endif // _PRINTF_H_

View File

@ -1,42 +0,0 @@
#ifndef __SIZES_H__
#define __SIZES_H__
#ifdef __cplusplus
extern "C" {
#endif
#define SZ_16 (0x00000010)
#define SZ_256 (0x00000100)
#define SZ_512 (0x00000200)
#define SZ_1K (0x00000400)
#define SZ_4K (0x00001000)
#define SZ_8K (0x00002000)
#define SZ_16K (0x00004000)
#define SZ_32K (0x00008000)
#define SZ_64K (0x00010000)
#define SZ_128K (0x00020000)
#define SZ_256K (0x00040000)
#define SZ_512K (0x00080000)
#define SZ_1M (0x00100000)
#define SZ_2M (0x00200000)
#define SZ_4M (0x00400000)
#define SZ_8M (0x00800000)
#define SZ_16M (0x01000000)
#define SZ_32M (0x02000000)
#define SZ_64M (0x04000000)
#define SZ_128M (0x08000000)
#define SZ_256M (0x10000000)
#define SZ_512M (0x20000000)
#define SZ_1G (0x40000000)
#define SZ_2G (0x80000000)
#define ARRAY_SIZE(array) ( sizeof(array) / sizeof((array)[0]) )
#ifdef __cplusplus
}
#endif
#endif /* __SIZES_H__ */

View File

@ -1,55 +0,0 @@
#ifndef __ARM32_TYPES_H__
#define __ARM32_TYPES_H__
#ifdef __cplusplus
extern "C" {
#endif
typedef signed char s8_t;
typedef unsigned char u8_t;
typedef signed short s16_t;
typedef unsigned short u16_t;
typedef signed int s32_t;
typedef unsigned int u32_t;
typedef signed long long s64_t;
typedef unsigned long long u64_t;
typedef signed long long intmax_t;
typedef unsigned long long uintmax_t;
typedef signed int ptrdiff_t;
typedef signed int intptr_t;
typedef unsigned int uintptr_t;
typedef unsigned int size_t;
typedef signed int ssize_t;
// typedef signed int off_t;
typedef signed long long loff_t;
typedef signed int bool_t;
typedef signed int register_t;
typedef unsigned int irq_flags_t;
typedef unsigned int virtual_addr_t;
typedef unsigned int virtual_size_t;
typedef unsigned int physical_addr_t;
typedef unsigned int physical_size_t;
typedef struct {
volatile long counter;
} atomic_t;
typedef struct {
volatile long lock;
} spinlock_t;
#ifdef __cplusplus
}
#endif
#endif /* __ARM32_TYPES_H__ */

View File

@ -1,834 +0,0 @@
/*
* lib/libc/malloc/malloc.c
*/
#include <malloc.h>
static void * __heap_pool = NULL;
/*
* Some macros.
*/
#define tlsf_cast(t, exp) ((t)(exp))
#define tlsf_min(a, b) ((a) < (b) ? (a) : (b))
#define tlsf_max(a, b) ((a) > (b) ? (a) : (b))
#define tlsf_assert assert
#define tlsf_insist(x) { tlsf_assert(x); if (!(x)) { status--; } }
#if defined(__ARM64__) || defined(__X64__)
# define TLSF_64BIT
#else
# undef TLSF_64BIT
#endif
/*
* Public constants
*/
enum tlsf_public
{
/*
* log2 of number of linear subdivisions of block sizes
*/
SL_INDEX_COUNT_LOG2 = 5,
};
/*
* Private constants
*/
enum tlsf_private
{
#if defined(TLSF_64BIT)
/*
* All allocation sizes and addresses are aligned to 8 bytes
*/
ALIGN_SIZE_LOG2 = 3,
#else
/*
* All allocation sizes and addresses are aligned to 4 bytes
*/
ALIGN_SIZE_LOG2 = 2,
#endif
ALIGN_SIZE = (1 << ALIGN_SIZE_LOG2),
#if defined(TLSF_64BIT)
FL_INDEX_MAX = 32,
#else
FL_INDEX_MAX = 30,
#endif
SL_INDEX_COUNT = (1 << SL_INDEX_COUNT_LOG2),
FL_INDEX_SHIFT = (SL_INDEX_COUNT_LOG2 + ALIGN_SIZE_LOG2),
FL_INDEX_COUNT = (FL_INDEX_MAX - FL_INDEX_SHIFT + 1),
SMALL_BLOCK_SIZE = (1 << FL_INDEX_SHIFT),
};
/*
* Block header structure
*/
typedef struct block_header_t
{
/*
* Points to the previous physical block
*/
struct block_header_t * prev_phys_block;
/*
* The size of this block, excluding the block header
*/
size_t size;
/*
* Next and previous free blocks
*/
struct block_header_t * next_free;
struct block_header_t * prev_free;
} block_header_t;
/*
* The TLSF control structure.
*/
typedef struct control_t
{
/*
* Empty lists point at this block to indicate they are free.
*/
block_header_t block_null;
/*
* Bitmaps for free lists.
*/
unsigned int fl_bitmap;
unsigned int sl_bitmap[FL_INDEX_COUNT];
/*
* Head of free lists.
*/
block_header_t * blocks[FL_INDEX_COUNT][SL_INDEX_COUNT];
} control_t;
/*
* A type used for casting when doing pointer arithmetic.
*/
typedef ptrdiff_t tlsfptr_t;
/*
* Associated constants
*/
static const size_t block_header_free_bit = 1 << 0;
static const size_t block_header_prev_free_bit = 1 << 1;
static const size_t block_header_overhead = sizeof(size_t);
static const size_t block_start_offset = offsetof(block_header_t, size) + sizeof(size_t);
static const size_t block_size_min = sizeof(block_header_t) - sizeof(block_header_t *);
static const size_t block_size_max = tlsf_cast(size_t, 1) << FL_INDEX_MAX;
#if defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) && defined(__GNUC_PATCHLEVEL__)
static int tlsf_ffs(unsigned int word)
{
return __builtin_ffs(word) - 1;
}
static int tlsf_fls(unsigned int word)
{
const int bit = word ? 32 - __builtin_clz(word) : 0;
return bit - 1;
}
#else
static int tlsf_fls_generic(unsigned int word)
{
int bit = 32;
if (!word) bit -= 1;
if (!(word & 0xffff0000)) { word <<= 16; bit -= 16; }
if (!(word & 0xff000000)) { word <<= 8; bit -= 8; }
if (!(word & 0xf0000000)) { word <<= 4; bit -= 4; }
if (!(word & 0xc0000000)) { word <<= 2; bit -= 2; }
if (!(word & 0x80000000)) { word <<= 1; bit -= 1; }
return bit;
}
static int tlsf_ffs(unsigned int word)
{
return tlsf_fls_generic(word & (~word + 1)) - 1;
}
static int tlsf_fls(unsigned int word)
{
return tlsf_fls_generic(word) - 1;
}
#endif
#if defined(TLSF_64BIT)
static int tlsf_fls_sizet(size_t size)
{
int high = (int)(size >> 32);
int bits = 0;
if(high)
{
bits = 32 + tlsf_fls(high);
}
else
{
bits = tlsf_fls((int)size & 0xffffffff);
}
return bits;
}
#else
#define tlsf_fls_sizet tlsf_fls
#endif
static size_t block_get_size(const block_header_t * block)
{
return block->size & ~(block_header_free_bit | block_header_prev_free_bit);
}
static void block_set_size(block_header_t * block, size_t size)
{
const size_t oldsize = block->size;
block->size = size | (oldsize & (block_header_free_bit | block_header_prev_free_bit));
}
static int block_is_last(const block_header_t * block)
{
return (0 == block_get_size(block));
}
static int block_is_free(const block_header_t * block)
{
return tlsf_cast(int, block->size & block_header_free_bit);
}
static void block_set_free(block_header_t * block)
{
block->size |= block_header_free_bit;
}
static void block_set_used(block_header_t * block)
{
block->size &= ~block_header_free_bit;
}
static int block_is_prev_free(const block_header_t * block)
{
return tlsf_cast(int, block->size & block_header_prev_free_bit);
}
static void block_set_prev_free(block_header_t * block)
{
block->size |= block_header_prev_free_bit;
}
static void block_set_prev_used(block_header_t * block)
{
block->size &= ~block_header_prev_free_bit;
}
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-align"
static block_header_t * block_from_ptr(void * ptr)
{
return tlsf_cast(block_header_t *, tlsf_cast(unsigned char*, ptr) - block_start_offset);
}
#pragma GCC diagnostic pop
static void * block_to_ptr(block_header_t * block)
{
return tlsf_cast(void *, tlsf_cast(unsigned char*, block) + block_start_offset);
}
static block_header_t * offset_to_block(void * ptr, size_t size)
{
return tlsf_cast(block_header_t *, tlsf_cast(tlsfptr_t, ptr) + size);
}
static block_header_t * block_prev(block_header_t * block)
{
return block->prev_phys_block;
}
static block_header_t * block_next(block_header_t * block)
{
block_header_t * next = offset_to_block(block_to_ptr(block), block_get_size(block) - block_header_overhead);
tlsf_assert(!block_is_last(block));
return next;
}
static block_header_t * block_link_next(block_header_t * block)
{
block_header_t * next = block_next(block);
next->prev_phys_block = block;
return next;
}
static void block_mark_as_free(block_header_t * block)
{
block_header_t * next = block_link_next(block);
block_set_prev_free(next);
block_set_free(block);
}
static void block_mark_as_used(block_header_t * block)
{
block_header_t * next = block_next(block);
block_set_prev_used(next);
block_set_used(block);
}
static size_t align_up(size_t x, size_t align)
{
tlsf_assert(0 == (align & (align - 1)) && "must align to a power of two");
return (x + (align - 1)) & ~(align - 1);
}
static size_t align_down(size_t x, size_t align)
{
tlsf_assert(0 == (align & (align - 1)) && "must align to a power of two");
return x - (x & (align - 1));
}
static void * align_ptr(const void * ptr, size_t align)
{
const tlsfptr_t aligned = (tlsf_cast(tlsfptr_t, ptr) + (align - 1)) & ~(align - 1);
tlsf_assert(0 == (align & (align - 1)) && "must align to a power of two");
return tlsf_cast(void*, aligned);
}
static size_t adjust_request_size(size_t size, size_t align)
{
size_t adjust = 0;
if (size && size < block_size_max)
{
const size_t aligned = align_up(size, align);
adjust = tlsf_max(aligned, block_size_min);
}
return adjust;
}
static void mapping_insert(size_t size, int * fli, int * sli)
{
int fl, sl;
if (size < SMALL_BLOCK_SIZE)
{
fl = 0;
sl = tlsf_cast(int, size) / (SMALL_BLOCK_SIZE / SL_INDEX_COUNT);
}
else
{
fl = tlsf_fls_sizet(size);
sl = tlsf_cast(int, size >> (fl - SL_INDEX_COUNT_LOG2)) ^ (1 << SL_INDEX_COUNT_LOG2);
fl -= (FL_INDEX_SHIFT - 1);
}
*fli = fl;
*sli = sl;
}
static void mapping_search(size_t size, int * fli, int * sli)
{
if (size >= (1 << SL_INDEX_COUNT_LOG2))
{
const size_t round = (1 << (tlsf_fls_sizet(size) - SL_INDEX_COUNT_LOG2)) - 1;
size += round;
}
mapping_insert(size, fli, sli);
}
static block_header_t * search_suitable_block(control_t * control, int * fli, int * sli)
{
int fl = *fli;
int sl = *sli;
unsigned int sl_map = control->sl_bitmap[fl] & (~0U << sl);
if (!sl_map)
{
const unsigned int fl_map = control->fl_bitmap & (~0U << (fl + 1));
if (!fl_map)
{
return 0;
}
fl = tlsf_ffs(fl_map);
*fli = fl;
sl_map = control->sl_bitmap[fl];
}
tlsf_assert(sl_map && "internal error - second level bitmap is null");
sl = tlsf_ffs(sl_map);
*sli = sl;
return control->blocks[fl][sl];
}
static void remove_free_block(control_t * control, block_header_t * block, int fl, int sl)
{
block_header_t * prev = block->prev_free;
block_header_t * next = block->next_free;
tlsf_assert(prev && "prev_free field can not be null");
tlsf_assert(next && "next_free field can not be null");
next->prev_free = prev;
prev->next_free = next;
if (control->blocks[fl][sl] == block)
{
control->blocks[fl][sl] = next;
if (next == &control->block_null)
{
control->sl_bitmap[fl] &= ~(1 << sl);
if (!control->sl_bitmap[fl])
{
control->fl_bitmap &= ~(1 << fl);
}
}
}
}
static void insert_free_block(control_t * control, block_header_t * block, int fl, int sl)
{
block_header_t * current = control->blocks[fl][sl];
tlsf_assert(current && "free list cannot have a null entry");
tlsf_assert(block && "cannot insert a null entry into the free list");
block->next_free = current;
block->prev_free = &control->block_null;
current->prev_free = block;
tlsf_assert(block_to_ptr(block) == align_ptr(block_to_ptr(block), ALIGN_SIZE) && "block not aligned properly");
control->blocks[fl][sl] = block;
control->fl_bitmap |= (1 << fl);
control->sl_bitmap[fl] |= (1 << sl);
}
static void block_remove(control_t * control, block_header_t * block)
{
int fl, sl;
mapping_insert(block_get_size(block), &fl, &sl);
remove_free_block(control, block, fl, sl);
}
static void block_insert(control_t * control, block_header_t * block)
{
int fl, sl;
mapping_insert(block_get_size(block), &fl, &sl);
insert_free_block(control, block, fl, sl);
}
static int block_can_split(block_header_t * block, size_t size)
{
return block_get_size(block) >= sizeof(block_header_t) + size;
}
static block_header_t * block_split(block_header_t * block, size_t size)
{
block_header_t* remaining = offset_to_block(block_to_ptr(block), size - block_header_overhead);
const size_t remain_size = block_get_size(block) - (size + block_header_overhead);
tlsf_assert(block_to_ptr(remaining) == align_ptr(block_to_ptr(remaining), ALIGN_SIZE) && "remaining block not aligned properly");
tlsf_assert(block_get_size(block) == remain_size + size + block_header_overhead);
block_set_size(remaining, remain_size);
tlsf_assert(block_get_size(remaining) >= block_size_min && "block split with invalid size");
block_set_size(block, size);
block_mark_as_free(remaining);
return remaining;
}
static block_header_t * block_absorb(block_header_t * prev, block_header_t * block)
{
tlsf_assert(!block_is_last(prev) && "previous block can't be last!");
prev->size += block_get_size(block) + block_header_overhead;
block_link_next(prev);
return prev;
}
static block_header_t * block_merge_prev(control_t * control, block_header_t * block)
{
if (block_is_prev_free(block))
{
block_header_t* prev = block_prev(block);
tlsf_assert(prev && "prev physical block can't be null");
tlsf_assert(block_is_free(prev) && "prev block is not free though marked as such");
block_remove(control, prev);
block = block_absorb(prev, block);
}
return block;
}
static block_header_t * block_merge_next(control_t * control, block_header_t * block)
{
block_header_t* next = block_next(block);
tlsf_assert(next && "next physical block can't be null");
if (block_is_free(next))
{
tlsf_assert(!block_is_last(block) && "previous block can't be last!");
block_remove(control, next);
block = block_absorb(block, next);
}
return block;
}
static void block_trim_free(control_t * control, block_header_t * block, size_t size)
{
tlsf_assert(block_is_free(block) && "block must be free");
if (block_can_split(block, size))
{
block_header_t* remaining_block = block_split(block, size);
block_link_next(block);
block_set_prev_free(remaining_block);
block_insert(control, remaining_block);
}
}
static void block_trim_used(control_t * control, block_header_t * block, size_t size)
{
tlsf_assert(!block_is_free(block) && "block must be used");
if (block_can_split(block, size))
{
block_header_t* remaining_block = block_split(block, size);
block_set_prev_used(remaining_block);
remaining_block = block_merge_next(control, remaining_block);
block_insert(control, remaining_block);
}
}
static block_header_t * block_trim_free_leading(control_t * control, block_header_t * block, size_t size)
{
block_header_t * remaining_block = block;
if (block_can_split(block, size))
{
remaining_block = block_split(block, size - block_header_overhead);
block_set_prev_free(remaining_block);
block_link_next(block);
block_insert(control, block);
}
return remaining_block;
}
static block_header_t * block_locate_free(control_t * control, size_t size)
{
int fl = 0, sl = 0;
block_header_t * block = 0;
if (size)
{
mapping_search(size, &fl, &sl);
block = search_suitable_block(control, &fl, &sl);
}
if (block)
{
tlsf_assert(block_get_size(block) >= size);
remove_free_block(control, block, fl, sl);
}
return block;
}
static void * block_prepare_used(control_t * control, block_header_t * block, size_t size)
{
void* p = 0;
if (block)
{
block_trim_free(control, block, size);
block_mark_as_used(block);
p = block_to_ptr(block);
}
return p;
}
static void control_construct(control_t * control)
{
int i, j;
control->block_null.next_free = &control->block_null;
control->block_null.prev_free = &control->block_null;
control->fl_bitmap = 0;
for (i = 0; i < FL_INDEX_COUNT; ++i)
{
control->sl_bitmap[i] = 0;
for (j = 0; j < SL_INDEX_COUNT; ++j)
{
control->blocks[i][j] = &control->block_null;
}
}
}
static inline void * tlsf_add_pool(void * tlsf, void * mem, size_t bytes)
{
block_header_t * block;
block_header_t * next;
const size_t pool_overhead = 2 * block_header_overhead;
const size_t pool_bytes = align_down(bytes - pool_overhead, ALIGN_SIZE);
if (((ptrdiff_t)mem % ALIGN_SIZE) != 0)
return 0;
if (pool_bytes < block_size_min || pool_bytes > block_size_max)
return 0;
block = offset_to_block(mem, -(tlsfptr_t)block_header_overhead);
block_set_size(block, pool_bytes);
block_set_free(block);
block_set_prev_used(block);
block_insert(tlsf_cast(control_t*, tlsf), block);
next = block_link_next(block);
block_set_size(next, 0);
block_set_used(next);
block_set_prev_free(next);
return mem;
}
static inline void tlsf_remove_pool(void * tlsf, void * pool)
{
control_t * control = tlsf_cast(control_t *, tlsf);
block_header_t * block = offset_to_block(pool, -(int)block_header_overhead);
int fl = 0, sl = 0;
tlsf_assert(block_is_free(block) && "block should be free");
tlsf_assert(!block_is_free(block_next(block)) && "next block should not be free");
tlsf_assert(block_get_size(block_next(block)) == 0 && "next block size should be zero");
mapping_insert(block_get_size(block), &fl, &sl);
remove_free_block(control, block, fl, sl);
}
static inline void * tlsf_create(void * mem)
{
if (((tlsfptr_t)mem % ALIGN_SIZE) != 0)
return 0;
control_construct(tlsf_cast(control_t *, mem));
return tlsf_cast(void *, mem);
}
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Warray-bounds"
static inline void * tlsf_create_with_pool(void * mem, size_t bytes)
{
void * tlsf = tlsf_create(mem);
tlsf_add_pool(tlsf, (char *)mem + sizeof(control_t), bytes - sizeof(control_t));
return tlsf;
}
#pragma GCC diagnostic pop
static inline void tlsf_destroy(void * tlsf)
{
(void)tlsf;
}
static inline void * tlsf_get_pool(void * tlsf)
{
return tlsf_cast(void *, (char *)tlsf + sizeof(control_t));
}
static inline void * tlsf_malloc(void * tlsf, size_t size)
{
control_t * control = tlsf_cast(control_t *, tlsf);
const size_t adjust = adjust_request_size(size, ALIGN_SIZE);
block_header_t * block = block_locate_free(control, adjust);
return block_prepare_used(control, block, adjust);
}
static inline void * tlsf_memalign(void * tlsf, size_t align, size_t size)
{
control_t * control = tlsf_cast(control_t *, tlsf);
const size_t adjust = adjust_request_size(size, ALIGN_SIZE);
const size_t gap_minimum = sizeof(block_header_t);
const size_t size_with_gap = adjust_request_size(adjust + align + gap_minimum, align);
const size_t aligned_size = (align <= ALIGN_SIZE) ? adjust : size_with_gap;
block_header_t* block = block_locate_free(control, aligned_size);
tlsf_assert(sizeof(block_header_t) == block_size_min + block_header_overhead);
if (block)
{
void * ptr = block_to_ptr(block);
void * aligned = align_ptr(ptr, align);
size_t gap = tlsf_cast(size_t, tlsf_cast(tlsfptr_t, aligned) - tlsf_cast(tlsfptr_t, ptr));
if (gap && gap < gap_minimum)
{
const size_t gap_remain = gap_minimum - gap;
const size_t offset = tlsf_max(gap_remain, align);
const void * next_aligned = tlsf_cast(void *, tlsf_cast(tlsfptr_t, aligned) + offset);
aligned = align_ptr(next_aligned, align);
gap = tlsf_cast(size_t, tlsf_cast(tlsfptr_t, aligned) - tlsf_cast(tlsfptr_t, ptr));
}
if (gap)
{
tlsf_assert(gap >= gap_minimum && "gap size too small");
block = block_trim_free_leading(control, block, gap);
}
}
return block_prepare_used(control, block, adjust);
}
static inline void tlsf_free(void * tlsf, void * ptr)
{
if (ptr)
{
control_t * control = tlsf_cast(control_t *, tlsf);
block_header_t * block = block_from_ptr(ptr);
tlsf_assert(!block_is_free(block) && "block already marked as free");
block_mark_as_free(block);
block = block_merge_prev(control, block);
block = block_merge_next(control, block);
block_insert(control, block);
}
}
static inline void * tlsf_realloc(void * tlsf, void * ptr, size_t size)
{
control_t * control = tlsf_cast(control_t *, tlsf);
void * p = 0;
if (ptr && size == 0)
{
tlsf_free(tlsf, ptr);
}
else if (!ptr)
{
p = tlsf_malloc(tlsf, size);
}
else
{
block_header_t * block = block_from_ptr(ptr);
block_header_t * next = block_next(block);
const size_t cursize = block_get_size(block);
const size_t combined = cursize + block_get_size(next) + block_header_overhead;
const size_t adjust = adjust_request_size(size, ALIGN_SIZE);
tlsf_assert(!block_is_free(block) && "block already marked as free");
if (adjust > cursize && (!block_is_free(next) || adjust > combined))
{
p = tlsf_malloc(tlsf, size);
if (p)
{
const size_t minsize = tlsf_min(cursize, size);
memcpy(p, ptr, minsize);
tlsf_free(tlsf, ptr);
}
}
else
{
if (adjust > cursize)
{
block_merge_next(control, block);
block_mark_as_used(block);
}
block_trim_used(control, block, adjust);
p = ptr;
}
}
return p;
}
void * mm_create(void * mem, size_t bytes)
{
return tlsf_create_with_pool(mem, bytes);
}
void mm_destroy(void * mm)
{
tlsf_destroy(mm);
}
void * mm_get_pool(void * mm)
{
return tlsf_get_pool(mm);
}
void * mm_add_pool(void * mm, void * mem, size_t bytes)
{
return tlsf_add_pool(mm, mem, bytes);
}
void mm_remove_pool(void * mm, void * pool)
{
tlsf_remove_pool(mm, pool);
}
void * mm_malloc(void * mm, size_t size)
{
return tlsf_malloc(mm, size);
}
void * mm_memalign(void * mm, size_t align, size_t size)
{
return tlsf_memalign(mm, align, size);
}
void * mm_realloc(void * mm, void * ptr, size_t size)
{
return tlsf_realloc(mm, ptr, size);
}
void mm_free(void * mm, void * ptr)
{
tlsf_free(mm, ptr);
}
void * malloc(size_t size)
{
return tlsf_malloc(__heap_pool, size);
}
void * memalign(size_t align, size_t size)
{
return tlsf_memalign(__heap_pool, align, size);
}
void * realloc(void * ptr, size_t size)
{
return tlsf_realloc(__heap_pool, ptr, size);
}
void * calloc(size_t nmemb, size_t size)
{
void * ptr;
if((ptr = malloc(nmemb * size)))
memset(ptr, 0, nmemb * size);
return ptr;
}
void free(void * ptr)
{
tlsf_free(__heap_pool, ptr);
}
void do_init_mem_pool(void)
{
#ifndef __SANDBOX__
extern unsigned char __heap_start;
extern unsigned char __heap_end;
__heap_pool = tlsf_create_with_pool((void *)&__heap_start, (size_t)(&__heap_end - &__heap_start));
#else
static char __heap_buf[SZ_16M];
__heap_pool = tlsf_create_with_pool((void *)__heap_buf, (size_t)(sizeof(__heap_buf)));
#endif
}

View File

@ -1,404 +0,0 @@
/*
* memcpy.S
*/
.text
.global memcpy
.type memcpy, %function
.align 4
memcpy:
/* determine copy direction */
cmp r1, r0
bcc .Lmemcpy_backwards
moveq r0, #0 /* quick abort for len=0 */
moveq pc, lr
stmdb sp!, {r0, lr} /* memcpy() returns dest addr */
subs r2, r2, #4
blt .Lmemcpy_fl4 /* less than 4 bytes */
ands r12, r0, #3
bne .Lmemcpy_fdestul /* oh unaligned destination addr */
ands r12, r1, #3
bne .Lmemcpy_fsrcul /* oh unaligned source addr */
.Lmemcpy_ft8:
/* we have aligned source and destination */
subs r2, r2, #8
blt .Lmemcpy_fl12 /* less than 12 bytes (4 from above) */
subs r2, r2, #0x14
blt .Lmemcpy_fl32 /* less than 32 bytes (12 from above) */
stmdb sp!, {r4} /* borrow r4 */
/* blat 32 bytes at a time */
.Lmemcpy_floop32:
ldmia r1!, {r3, r4, r12, lr}
stmia r0!, {r3, r4, r12, lr}
ldmia r1!, {r3, r4, r12, lr}
stmia r0!, {r3, r4, r12, lr}
subs r2, r2, #0x20
bge .Lmemcpy_floop32
cmn r2, #0x10
ldmgeia r1!, {r3, r4, r12, lr} /* blat a remaining 16 bytes */
stmgeia r0!, {r3, r4, r12, lr}
subge r2, r2, #0x10
ldmia sp!, {r4} /* return r4 */
.Lmemcpy_fl32:
adds r2, r2, #0x14
/* blat 12 bytes at a time */
.Lmemcpy_floop12:
ldmgeia r1!, {r3, r12, lr}
stmgeia r0!, {r3, r12, lr}
subges r2, r2, #0x0c
bge .Lmemcpy_floop12
.Lmemcpy_fl12:
adds r2, r2, #8
blt .Lmemcpy_fl4
subs r2, r2, #4
ldrlt r3, [r1], #4
strlt r3, [r0], #4
ldmgeia r1!, {r3, r12}
stmgeia r0!, {r3, r12}
subge r2, r2, #4
.Lmemcpy_fl4:
/* less than 4 bytes to go */
adds r2, r2, #4
ldmeqia sp!, {r0, pc} /* done */
/* copy the crud byte at a time */
cmp r2, #2
ldrb r3, [r1], #1
strb r3, [r0], #1
ldrgeb r3, [r1], #1
strgeb r3, [r0], #1
ldrgtb r3, [r1], #1
strgtb r3, [r0], #1
ldmia sp!, {r0, pc}
/* erg - unaligned destination */
.Lmemcpy_fdestul:
rsb r12, r12, #4
cmp r12, #2
/* align destination with byte copies */
ldrb r3, [r1], #1
strb r3, [r0], #1
ldrgeb r3, [r1], #1
strgeb r3, [r0], #1
ldrgtb r3, [r1], #1
strgtb r3, [r0], #1
subs r2, r2, r12
blt .Lmemcpy_fl4 /* less the 4 bytes */
ands r12, r1, #3
beq .Lmemcpy_ft8 /* we have an aligned source */
/* erg - unaligned source */
/* This is where it gets nasty ... */
.Lmemcpy_fsrcul:
bic r1, r1, #3
ldr lr, [r1], #4
cmp r12, #2
bgt .Lmemcpy_fsrcul3
beq .Lmemcpy_fsrcul2
cmp r2, #0x0c
blt .Lmemcpy_fsrcul1loop4
sub r2, r2, #0x0c
stmdb sp!, {r4, r5}
.Lmemcpy_fsrcul1loop16:
mov r3, lr, lsr #8
ldmia r1!, {r4, r5, r12, lr}
orr r3, r3, r4, lsl #24
mov r4, r4, lsr #8
orr r4, r4, r5, lsl #24
mov r5, r5, lsr #8
orr r5, r5, r12, lsl #24
mov r12, r12, lsr #8
orr r12, r12, lr, lsl #24
stmia r0!, {r3-r5, r12}
subs r2, r2, #0x10
bge .Lmemcpy_fsrcul1loop16
ldmia sp!, {r4, r5}
adds r2, r2, #0x0c
blt .Lmemcpy_fsrcul1l4
.Lmemcpy_fsrcul1loop4:
mov r12, lr, lsr #8
ldr lr, [r1], #4
orr r12, r12, lr, lsl #24
str r12, [r0], #4
subs r2, r2, #4
bge .Lmemcpy_fsrcul1loop4
.Lmemcpy_fsrcul1l4:
sub r1, r1, #3
b .Lmemcpy_fl4
.Lmemcpy_fsrcul2:
cmp r2, #0x0c
blt .Lmemcpy_fsrcul2loop4
sub r2, r2, #0x0c
stmdb sp!, {r4, r5}
.Lmemcpy_fsrcul2loop16:
mov r3, lr, lsr #16
ldmia r1!, {r4, r5, r12, lr}
orr r3, r3, r4, lsl #16
mov r4, r4, lsr #16
orr r4, r4, r5, lsl #16
mov r5, r5, lsr #16
orr r5, r5, r12, lsl #16
mov r12, r12, lsr #16
orr r12, r12, lr, lsl #16
stmia r0!, {r3-r5, r12}
subs r2, r2, #0x10
bge .Lmemcpy_fsrcul2loop16
ldmia sp!, {r4, r5}
adds r2, r2, #0x0c
blt .Lmemcpy_fsrcul2l4
.Lmemcpy_fsrcul2loop4:
mov r12, lr, lsr #16
ldr lr, [r1], #4
orr r12, r12, lr, lsl #16
str r12, [r0], #4
subs r2, r2, #4
bge .Lmemcpy_fsrcul2loop4
.Lmemcpy_fsrcul2l4:
sub r1, r1, #2
b .Lmemcpy_fl4
.Lmemcpy_fsrcul3:
cmp r2, #0x0c
blt .Lmemcpy_fsrcul3loop4
sub r2, r2, #0x0c
stmdb sp!, {r4, r5}
.Lmemcpy_fsrcul3loop16:
mov r3, lr, lsr #24
ldmia r1!, {r4, r5, r12, lr}
orr r3, r3, r4, lsl #8
mov r4, r4, lsr #24
orr r4, r4, r5, lsl #8
mov r5, r5, lsr #24
orr r5, r5, r12, lsl #8
mov r12, r12, lsr #24
orr r12, r12, lr, lsl #8
stmia r0!, {r3-r5, r12}
subs r2, r2, #0x10
bge .Lmemcpy_fsrcul3loop16
ldmia sp!, {r4, r5}
adds r2, r2, #0x0c
blt .Lmemcpy_fsrcul3l4
.Lmemcpy_fsrcul3loop4:
mov r12, lr, lsr #24
ldr lr, [r1], #4
orr r12, r12, lr, lsl #8
str r12, [r0], #4
subs r2, r2, #4
bge .Lmemcpy_fsrcul3loop4
.Lmemcpy_fsrcul3l4:
sub r1, r1, #1
b .Lmemcpy_fl4
.Lmemcpy_backwards:
add r1, r1, r2
add r0, r0, r2
subs r2, r2, #4
blt .Lmemcpy_bl4 /* less than 4 bytes */
ands r12, r0, #3
bne .Lmemcpy_bdestul /* oh unaligned destination addr */
ands r12, r1, #3
bne .Lmemcpy_bsrcul /* oh unaligned source addr */
.Lmemcpy_bt8:
/* we have aligned source and destination */
subs r2, r2, #8
blt .Lmemcpy_bl12 /* less than 12 bytes (4 from above) */
stmdb sp!, {r4, lr}
subs r2, r2, #0x14 /* less than 32 bytes (12 from above) */
blt .Lmemcpy_bl32
/* blat 32 bytes at a time */
.Lmemcpy_bloop32:
ldmdb r1!, {r3, r4, r12, lr}
stmdb r0!, {r3, r4, r12, lr}
ldmdb r1!, {r3, r4, r12, lr}
stmdb r0!, {r3, r4, r12, lr}
subs r2, r2, #0x20
bge .Lmemcpy_bloop32
.Lmemcpy_bl32:
cmn r2, #0x10
ldmgedb r1!, {r3, r4, r12, lr} /* blat a remaining 16 bytes */
stmgedb r0!, {r3, r4, r12, lr}
subge r2, r2, #0x10
adds r2, r2, #0x14
ldmgedb r1!, {r3, r12, lr} /* blat a remaining 12 bytes */
stmgedb r0!, {r3, r12, lr}
subge r2, r2, #0x0c
ldmia sp!, {r4, lr}
.Lmemcpy_bl12:
adds r2, r2, #8
blt .Lmemcpy_bl4
subs r2, r2, #4
ldrlt r3, [r1, #-4]!
strlt r3, [r0, #-4]!
ldmgedb r1!, {r3, r12}
stmgedb r0!, {r3, r12}
subge r2, r2, #4
.Lmemcpy_bl4:
/* less than 4 bytes to go */
adds r2, r2, #4
moveq pc, lr
/* copy the crud byte at a time */
cmp r2, #2
ldrb r3, [r1, #-1]!
strb r3, [r0, #-1]!
ldrgeb r3, [r1, #-1]!
strgeb r3, [r0, #-1]!
ldrgtb r3, [r1, #-1]!
strgtb r3, [r0, #-1]!
mov pc, lr
/* erg - unaligned destination */
.Lmemcpy_bdestul:
cmp r12, #2
/* align destination with byte copies */
ldrb r3, [r1, #-1]!
strb r3, [r0, #-1]!
ldrgeb r3, [r1, #-1]!
strgeb r3, [r0, #-1]!
ldrgtb r3, [r1, #-1]!
strgtb r3, [r0, #-1]!
subs r2, r2, r12
blt .Lmemcpy_bl4 /* less than 4 bytes to go */
ands r12, r1, #3
beq .Lmemcpy_bt8 /* we have an aligned source */
/* erg - unaligned source */
/* This is where it gets nasty ... */
.Lmemcpy_bsrcul:
bic r1, r1, #3
ldr r3, [r1, #0]
cmp r12, #2
blt .Lmemcpy_bsrcul1
beq .Lmemcpy_bsrcul2
cmp r2, #0x0c
blt .Lmemcpy_bsrcul3loop4
sub r2, r2, #0x0c
stmdb sp!, {r4, r5, lr}
.Lmemcpy_bsrcul3loop16:
mov lr, r3, lsl #8
ldmdb r1!, {r3-r5, r12}
orr lr, lr, r12, lsr #24
mov r12, r12, lsl #8
orr r12, r12, r5, lsr #24
mov r5, r5, lsl #8
orr r5, r5, r4, lsr #24
mov r4, r4, lsl #8
orr r4, r4, r3, lsr #24
stmdb r0!, {r4, r5, r12, lr}
subs r2, r2, #0x10
bge .Lmemcpy_bsrcul3loop16
ldmia sp!, {r4, r5, lr}
adds r2, r2, #0x0c
blt .Lmemcpy_bsrcul3l4
.Lmemcpy_bsrcul3loop4:
mov r12, r3, lsl #8
ldr r3, [r1, #-4]!
orr r12, r12, r3, lsr #24
str r12, [r0, #-4]!
subs r2, r2, #4
bge .Lmemcpy_bsrcul3loop4
.Lmemcpy_bsrcul3l4:
add r1, r1, #3
b .Lmemcpy_bl4
.Lmemcpy_bsrcul2:
cmp r2, #0x0c
blt .Lmemcpy_bsrcul2loop4
sub r2, r2, #0x0c
stmdb sp!, {r4, r5, lr}
.Lmemcpy_bsrcul2loop16:
mov lr, r3, lsl #16
ldmdb r1!, {r3-r5, r12}
orr lr, lr, r12, lsr #16
mov r12, r12, lsl #16
orr r12, r12, r5, lsr #16
mov r5, r5, lsl #16
orr r5, r5, r4, lsr #16
mov r4, r4, lsl #16
orr r4, r4, r3, lsr #16
stmdb r0!, {r4, r5, r12, lr}
subs r2, r2, #0x10
bge .Lmemcpy_bsrcul2loop16
ldmia sp!, {r4, r5, lr}
adds r2, r2, #0x0c
blt .Lmemcpy_bsrcul2l4
.Lmemcpy_bsrcul2loop4:
mov r12, r3, lsl #16
ldr r3, [r1, #-4]!
orr r12, r12, r3, lsr #16
str r12, [r0, #-4]!
subs r2, r2, #4
bge .Lmemcpy_bsrcul2loop4
.Lmemcpy_bsrcul2l4:
add r1, r1, #2
b .Lmemcpy_bl4
.Lmemcpy_bsrcul1:
cmp r2, #0x0c
blt .Lmemcpy_bsrcul1loop4
sub r2, r2, #0x0c
stmdb sp!, {r4, r5, lr}
.Lmemcpy_bsrcul1loop32:
mov lr, r3, lsl #24
ldmdb r1!, {r3-r5, r12}
orr lr, lr, r12, lsr #8
mov r12, r12, lsl #24
orr r12, r12, r5, lsr #8
mov r5, r5, lsl #24
orr r5, r5, r4, lsr #8
mov r4, r4, lsl #24
orr r4, r4, r3, lsr #8
stmdb r0!, {r4, r5, r12, lr}
subs r2, r2, #0x10
bge .Lmemcpy_bsrcul1loop32
ldmia sp!, {r4, r5, lr}
adds r2, r2, #0x0c
blt .Lmemcpy_bsrcul1l4
.Lmemcpy_bsrcul1loop4:
mov r12, r3, lsl #24
ldr r3, [r1, #-4]!
orr r12, r12, r3, lsr #8
str r12, [r0, #-4]!
subs r2, r2, #4
bge .Lmemcpy_bsrcul1loop4
.Lmemcpy_bsrcul1l4:
add r1, r1, #1
b .Lmemcpy_bl4

View File

@ -1,79 +0,0 @@
/*
* memcpy.S
*/
.text
.global memset
.type memset, %function
.align 4
memset:
stmfd sp!, {r0} /* remember address for return value */
and r1, r1, #0x000000ff /* we write bytes */
cmp r2, #0x00000004 /* do we have less than 4 bytes */
blt .Lmemset_lessthanfour
/* first we will word align the address */
ands r3, r0, #0x00000003 /* get the bottom two bits */
beq .Lmemset_addraligned /* the address is word aligned */
rsb r3, r3, #0x00000004
sub r2, r2, r3
cmp r3, #0x00000002
strb r1, [r0], #0x0001 /* set 1 byte */
strgeb r1, [r0], #0x0001 /* set another byte */
strgtb r1, [r0], #0x0001 /* and a third */
cmp r2, #0x00000004
blt .Lmemset_lessthanfour
/* now we must be word aligned */
.Lmemset_addraligned:
orr r3, r1, r1, lsl #8 /* repeat the byte into a word */
orr r3, r3, r3, lsl #16
/* we know we have at least 4 bytes ... */
cmp r2, #0x00000020 /* if less than 32 then use words */
blt .Lmemset_lessthan32
/* we have at least 32 so lets use quad words */
stmfd sp!, {r4-r6} /* store registers */
mov r4, r3 /* duplicate data */
mov r5, r3
mov r6, r3
.Lmemset_loop16:
stmia r0!, {r3-r6} /* store 16 bytes */
sub r2, r2, #0x00000010 /* adjust count */
cmp r2, #0x00000010 /* still got at least 16 bytes ? */
bgt .Lmemset_loop16
ldmfd sp!, {r4-r6} /* restore registers */
/* do we need to set some words as well ? */
cmp r2, #0x00000004
blt .Lmemset_lessthanfour
/* have either less than 16 or less than 32 depending on route taken */
.Lmemset_lessthan32:
/* we have at least 4 bytes so copy as words */
.Lmemset_loop4:
str r3, [r0], #0x0004
sub r2, r2, #0x0004
cmp r2, #0x00000004
bge .Lmemset_loop4
.Lmemset_lessthanfour:
cmp r2, #0x00000000
ldmeqfd sp!, {r0}
moveq pc, lr /* zero length so exit */
cmp r2, #0x00000002
strb r1, [r0], #0x0001 /* set 1 byte */
strgeb r1, [r0], #0x0001 /* set another byte */
strgtb r1, [r0], #0x0001 /* and a third */
ldmfd sp!, {r0}
mov pc, lr /* exit */

View File

@ -1,757 +0,0 @@
///////////////////////////////////////////////////////////////////////////////
// \author (c) Marco Paland (info@paland.com)
// 2014-2018, 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 <stdint.h>
#include "printf.h"
// ntoa conversion buffer size, this must be big enough to hold
// one converted numeric number including padded zeros (dynamically created on stack)
// 32 byte is a good default
#define PRINTF_NTOA_BUFFER_SIZE 32U
// ftoa conversion buffer size, this must be big enough to hold
// one converted float number including padded zeros (dynamically created on stack)
// 32 byte is a good default
#define PRINTF_FTOA_BUFFER_SIZE 32U
// define this to support floating point (%f)
#define PRINTF_SUPPORT_FLOAT
// define this to support long long types (%llu or %p)
#define PRINTF_SUPPORT_LONG_LONG
// define this to support the ptrdiff_t type (%t)
// ptrdiff_t is normally defined in <stddef.h> as long or long long type
#define PRINTF_SUPPORT_PTRDIFF_T
///////////////////////////////////////////////////////////////////////////////
// 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)
typedef unsigned char bool;
#ifndef false
#define false 0
#endif
#ifndef true
#define true (!false)
#endif
extern void sys_uart_putc(char c);
static char last_ch;
void _putchar(char character)
{
if(character == 0x0a && last_ch != 0x0d)
{
sys_uart_putc(0x0d);
}
sys_uart_putc(character);
}
// 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;
}
// internal _putchar wrapper
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;
// buffer is the output fct pointer
((out_fct_wrap_type*)buffer)->fct(character, ((out_fct_wrap_type*)buffer)->arg);
}
// internal strlen
// \return The length of the string (excluding the terminating 0)
static inline unsigned int _strlen(const char* str)
{
const char* s;
for (s = str; *s; ++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;
}
// 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)
{
const size_t start_idx = idx;
// pad leading zeros
while (!(flags & FLAGS_LEFT) && (len < prec) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
buf[len++] = '0';
}
while (!(flags & FLAGS_LEFT) && (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';
}
}
// handle sign
if (len && (len == width) && (negative || (flags & FLAGS_PLUS) || (flags & FLAGS_SPACE))) {
len--;
}
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++] = ' ';
}
}
// 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
for (size_t i = 0U; i < len; i++) {
out(buf[len - i - 1U], 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 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)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wfloat-equal"
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)
{
const size_t start_idx = idx;
char buf[PRINTF_FTOA_BUFFER_SIZE];
size_t len = 0U;
double diff = 0.0;
// if input is larger than thres_max, revert to exponential
const double thres_max = (double)0x7FFFFFFF;
// powers of 10
static const double pow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
// test for negative
bool negative = false;
if (value < 0) {
negative = true;
value = 0 - value;
}
// set default precision to 6, if not set explicitly
if (!(flags & FLAGS_PRECISION)) {
prec = 6U;
}
// 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.5l) {
++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.5l) && ((frac == 0U) || (frac & 1U))) {
// if halfway, round up if odd, OR if last digit is 0
++frac;
}
// TBD: for very large numbers switch back to native sprintf for exponentials. Anyone want to write code to replace this?
// Normal printf behavior is to print EVERY whole number digit which can be 100s of characters overflowing your buffers == bad
if (value > thres_max) {
return 0U;
}
if (prec == 0U) {
diff = value - (double)whole;
if (diff > 0.5l) {
// greater than 0.5, round up, e.g. 1.6 -> 2
++whole;
}
else if ((diff == 0.5l) && (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
while (!(flags & FLAGS_LEFT) && (flags & FLAGS_ZEROPAD) && (len < width) && (len < PRINTF_FTOA_BUFFER_SIZE)) {
buf[len++] = '0';
}
// handle sign
if ((len == width) && (negative || (flags & FLAGS_PLUS) || (flags & FLAGS_SPACE))) {
len--;
}
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++] = ' ';
}
}
// 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
for (size_t i = 0U; i < len; i++) {
out(buf[len - i - 1U], 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;
}
#pragma GCC diagnostic pop
#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' :
idx = _ftoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags);
format++;
break;
#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' : {
char* p = va_arg(va, char*);
unsigned int l = _strlen(p);
// 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 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 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);
out_fct_wrap_type out_fct_wrap = { out, arg };
const int ret = _vsnprintf(_out_fct, (char*)&out_fct_wrap, (size_t)-1, format, va);
va_end(va);
return ret;
}

View File

@ -1,76 +0,0 @@
/*
* exception.c
*
* Copyright(c) 2007-2018 Jianjun Jiang <8192542@qq.com>
* Official site: http://xboot.org
* Mobile phone: +86-18665388956
* QQ: 8192542
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <stdio.h>
#include <arm32.h>
#include <string.h>
static void show_regs(struct arm_regs_t * regs)
{
int i;
printf("pc : [<%08lx>] lr : [<%08lx>] cpsr: %08lx\r\n", regs->pc, regs->lr, regs->cpsr);
printf("sp : %08lx\r\n", regs->sp);
for(i = 12; i >= 0; i--)
{
printf("r%-2d: %08lx ", i, regs->r[i]);
if(i % 2 == 0)
printf("\r\n");
}
printf("\r\n");
}
void arm32_do_undefined_instruction(struct arm_regs_t * regs)
{
//gdbserver_handle_exception(regs);
}
void arm32_do_software_interrupt(struct arm_regs_t * regs)
{
show_regs(regs);
regs->pc += 4;
}
void arm32_do_prefetch_abort(struct arm_regs_t * regs)
{
show_regs(regs);
regs->pc += 4;
}
void arm32_do_data_abort(struct arm_regs_t * regs)
{
show_regs(regs);
regs->pc += 4;
}
_Noreturn void __fatal_error(const char *msg) {
printf("%s\n", msg);
while (1);
}
#ifndef NDEBUG
_Noreturn void __assert_func(const char *file, int line, const char *func, const char *expr) {
//printf("Assertion '%s' failed, at file %s:%d\n", expr, file, line);
__fatal_error("Assertion failed");
}
#endif

View File

@ -1,173 +0,0 @@
// Originally designed by Hong Xuyao
#include <stdint.h>
#include <stdio.h>
#include <f1c100s-irq.h>
#include <arm32.h>
#define __irq __attribute__ ((interrupt ("IRQ")))
#ifndef __IO
#define __IO volatile
#endif
typedef struct {
__IO uint32_t INTC_VECTOR_REG; // 0x00
__IO uint32_t INTC_BASE_ADDR_REG; // 0x04
uint32_t resv1[1]; // 0x08
__IO uint32_t NMI_INT_CTRL_REG; // 0x0c
__IO uint32_t INTC_PEND_REG[2]; // 0x10
uint32_t resv2[2]; // 0x18
__IO uint32_t INTC_EN_REG[2]; // 0x20
uint32_t resv3[2]; // 0x28
__IO uint32_t INTC_MASK_REG[2]; // 0x30
uint32_t resv4[2]; // 0x38
__IO uint32_t INTC_RESP_REG[2]; // 0x40
uint32_t resv5[2]; // 0x48
__IO uint32_t INTC_FF_REG[2]; // 0x50
uint32_t resv6[2]; // 0x58
__IO uint32_t INTC_PRIO_REG[4]; // 0x60
} INTC_TypeDef;
#ifndef COUNTOF
#define COUNTOF(ar) (sizeof(ar)/sizeof(ar[0]))
#endif
#define INTC ((INTC_TypeDef*)0x01C20400)
static IRQHandleTypeDef irq_table[64] __attribute__((used, aligned(32)));
void arm32_do_irq(struct arm_regs_t * regs)
{
uint8_t nIRQ = f1c100s_intc_get_nirq();
// ForceIRQ flag must be cleared by ISR
// Otherwise ISR will be entered repeatedly
INTC->INTC_FF_REG[nIRQ / 32] &= ~(1 << nIRQ);
// Call the drivers ISR
f1c100s_intc_dispatch(nIRQ);
// Clear pending at the end of ISR
f1c100s_intc_clear_pend(nIRQ);
}
void arm32_do_fiq(struct arm_regs_t * regs)
{
// Call the drivers ISR
f1c100s_intc_dispatch(0);
// Clear pending at the end of ISR.
f1c100s_intc_clear_pend(0);
}
/*
* Read active IRQ number
* @return: none
*/
uint8_t f1c100s_intc_get_nirq(void)
{
return ((INTC->INTC_VECTOR_REG >> 2) & 0x3F);
}
/*
* Execute ISR corresponding to IRQ number
* @nIRQ: IRQ number
* @return: none
*/
void f1c100s_intc_dispatch(uint8_t nIRQ)
{
IRQHandleTypeDef handle = irq_table[nIRQ];
if (handle)
handle();
}
/*
* Set handler function for specified IRQ
* @nIRQ: IRQ number
* @handle: Handle function
* @return: none
*/
void f1c100s_intc_set_isr(uint8_t nIRQ, IRQHandleTypeDef handle)
{
if (nIRQ < COUNTOF(irq_table)) {
irq_table[nIRQ] = handle;
}
}
/*
* Enable IRQ
* @nIRQ: IRQ number
* @return: none
*/
void f1c100s_intc_enable_irq(uint8_t nIRQ)
{
INTC->INTC_EN_REG[nIRQ / 32] |= (1 << (nIRQ % 32));
}
/*
* Disable IRQ
* @nIRQ: IRQ number
* @return: none
*/
void f1c100s_intc_disable_irq(uint8_t nIRQ)
{
INTC->INTC_EN_REG[nIRQ / 32] &= ~(1 << (nIRQ % 32));
}
/*
* Mask IRQ
* @nIRQ: IRQ number
* @return: none
*/
void f1c100s_intc_mask_irq(uint8_t nIRQ)
{
INTC->INTC_MASK_REG[nIRQ / 32] |= (1 << (nIRQ % 32));
}
/*
* Unmask IRQ
* @nIRQ: IRQ number
* @return: none
*/
void f1c100s_intc_unmask_irq(uint8_t nIRQ)
{
INTC->INTC_MASK_REG[nIRQ / 32] &= ~(1 << (nIRQ % 32));
}
/*
* Immediately trigger IRQ
* @nIRQ: IRQ number
* @return: none
*/
void f1c100s_intc_force_irq(uint8_t nIRQ)
{
// This bit is to be cleared in IRQ handler
INTC->INTC_FF_REG[nIRQ / 32] = (1 << (nIRQ % 32));
}
/*
* Clear pending flag
* @nIRQ: IRQ number
* @return: none
*/
void f1c100s_intc_clear_pend(uint8_t nIRQ)
{
INTC->INTC_PEND_REG[nIRQ / 32] = (1 << (nIRQ % 32));
}
/*
* Initialize IRQ module
* @return: none
*/
void f1c100s_intc_init(void)
{
INTC->INTC_EN_REG[0] = INTC->INTC_EN_REG[1] = 0;
INTC->INTC_MASK_REG[0] = INTC->INTC_MASK_REG[1] = 0;
INTC->INTC_FF_REG[0] = INTC->INTC_FF_REG[1] = 0;
INTC->INTC_RESP_REG[0] = INTC->INTC_RESP_REG[1] = 0;
INTC->INTC_PEND_REG[0] = INTC->INTC_PEND_REG[1] = ~0UL;
INTC->INTC_BASE_ADDR_REG = 0;
INTC->NMI_INT_CTRL_REG = 0;
for (unsigned int i = 0; i < COUNTOF(irq_table); i++) {
irq_table[i] = 0;
}
}

View File

@ -1,314 +0,0 @@
/*
* start.S
*
* Copyright(c) 2007-2018 Jianjun Jiang <8192542@qq.com>
* Official site: http://xboot.org
* Mobile phone: +86-18665388956
* QQ: 8192542
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
/*
* Exception vector table
*/
.text
.arm
.global _start
_start:
/* Boot head information for BROM */
.long 0xea000016
.byte 'e', 'G', 'O', 'N', '.', 'B', 'T', '0'
.long 0, __bootloader_size
.byte 'S', 'P', 'L', 2
.long 0, 0
.long 0, 0, 0, 0, 0, 0, 0, 0
.long 0, 0, 0, 0, 0, 0, 0, 0 /* 0x40 - boot params, 0x58 - fel boot type, 0x5c - dram size */
_vector:
b reset
ldr pc, _undefined_instruction
ldr pc, _software_interrupt
ldr pc, _prefetch_abort
ldr pc, _data_abort
ldr pc, _not_used
ldr pc, _irq
ldr pc, _fiq
_undefined_instruction:
.word undefined_instruction
_software_interrupt:
.word software_interrupt
_prefetch_abort:
.word prefetch_abort
_data_abort:
.word data_abort
_not_used:
.word not_used
_irq:
.word irq
_fiq:
.word fiq
/*
* The actual reset code
*/
reset:
/* Save boot params to 0x00000040 */
ldr r0, =0x00000040
str sp, [r0, #0]
str lr, [r0, #4]
mrs lr, cpsr
str lr, [r0, #8]
mrc p15, 0, lr, c1, c0, 0
str lr, [r0, #12]
mrc p15, 0, lr, c1, c0, 0
str lr, [r0, #16]
/* Check boot type just for fel */
mov r0, #0x0
ldr r1, [r0, #8]
ldr r2, =0x4c45462e
cmp r1, r2
bne 1f
ldr r1, =0x1
str r1, [r0, #0x58]
1: nop
/* Enter svc mode and mask interrupts */
mrs r0, cpsr
bic r0, r0, #0x1f
orr r0, r0, #0xd3
msr cpsr, r0
/* Set vector to the low address */
mrc p15, 0, r0, c1, c0, 0
bic r0, #(1<<13)
mcr p15, 0, r0, c1, c0, 0
/* Copy vector to the correct address */
adr r0, _vector
mrc p15, 0, r2, c1, c0, 0
ands r2, r2, #(1 << 13)
ldreq r1, =0x00000000
ldrne r1, =0xffff0000
ldmia r0!, {r2-r8, r10}
stmia r1!, {r2-r8, r10}
ldmia r0!, {r2-r8, r10}
stmia r1!, {r2-r8, r10}
/* Initial system clock, ddr and uart */
bl sys_clock_init
bl sys_uart_init
/* Check if we are already running from dram */
adr r0, _start
ldr r1, =_start
cmp r0, r1
beq _init_mmu
/* Init dram if not running from dram */
bl sys_dram_init
/* Copy bootloader to faster dram (sram is slower) */
ldr r0, =0x81f80000
adr r1, _start
mov r2, #0x4000
bl memcpy
ldr r0, =_copy_self
ldr r1, =_start
sub r0, r0, r1
ldr r1, =0x81f80000
add r0, r0, r1
mov pc, r0
_init_mmu:
bl sys_mmu_init
b 1f
_copy_self:
/* Copyself to link address */
bl sys_copyself
1: nop
/* Initialize stacks */
mrs r0, cpsr
bic r0, r0, #0x1f
orr r1, r0, #0x1b
msr cpsr_cxsf, r1
ldr sp, _stack_und_end
bic r0, r0, #0x1f
orr r1, r0, #0x17
msr cpsr_cxsf, r1
ldr sp, _stack_abt_end
bic r0, r0, #0x1f
orr r1, r0, #0x12
msr cpsr_cxsf, r1
ldr sp, _stack_irq_end
bic r0, r0, #0x1f
orr r1, r0, #0x11
msr cpsr_cxsf, r1
ldr sp, _stack_fiq_end
bic r0, r0, #0x1f
orr r1, r0, #0x13
msr cpsr_cxsf, r1
ldr sp, _stack_srv_end
/* Copy data section */
ldr r0, _data_start
ldr r1, _data_shadow_start
ldr r2, _data_shadow_end
sub r2, r2, r1
bl memcpy
/* Clear bss section */
ldr r0, _bss_start
ldr r2, _bss_end
sub r2, r2, r0
mov r1, #0
bl memset
/* Call _main */
ldr r1, =_main
mov pc, r1
_main:
bl main
b _main
.global return_to_fel
return_to_fel:
mov r0, #0x4
mov r1, #'e'
strb r1, [r0, #0]
mov r1, #'G'
strb r1, [r0, #1]
mov r1, #'O'
strb r1, [r0, #2]
mov r1, #'N'
strb r1, [r0, #3]
mov r1, #'.'
strb r1, [r0, #4]
mov r1, #'F'
strb r1, [r0, #5]
mov r1, #'E'
strb r1, [r0, #6]
mov r1, #'L'
strb r1, [r0, #7]
ldr r0, =0x00000040
ldr sp, [r0, #0]
ldr lr, [r0, #4]
ldr r1, [r0, #16]
mcr p15, 0, r1, c1, c0, 0
ldr r1, [r0, #12]
mcr p15, 0, r1, c1, c0, 0
ldr r1, [r0, #8]
msr cpsr, r1
bx lr
/*
* Exception handlers
*/
.align 5
undefined_instruction:
b .
.align 5
software_interrupt:
b .
.align 5
prefetch_abort:
b .
.align 5
data_abort:
b .
.align 5
not_used:
b .
.align 5
irq:
ldr sp, _stack_irq_end
sub sp, sp, #72
stmia sp, {r0 - r12}
add r8, sp, #60
stmdb r8, {sp, lr}^
str lr, [r8, #0]
mrs r6, spsr
str r6, [r8, #4]
str r0, [r8, #8]
mov r0, sp
bl arm32_do_irq
ldmia sp, {r0 - lr}^
mov r0, r0
ldr lr, [sp, #60]
add sp, sp, #72
subs pc, lr, #4
.align 5
fiq:
ldr sp, _stack_irq_end
sub sp, sp, #72
stmia sp, {r0 - r12}
add r8, sp, #60
stmdb r8, {sp, lr}^
str lr, [r8, #0]
mrs r6, spsr
str r6, [r8, #4]
str r0, [r8, #8]
mov r0, sp
bl arm32_do_fiq
ldmia sp, {r0 - lr}^
mov r0, r0
ldr lr, [sp, #60]
add sp, sp, #72
subs pc, lr, #4
/*
* The location of section
*/
.align 4
_image_start:
.long __image_start
_image_end:
.long __image_end
_data_shadow_start:
.long __data_shadow_start
_data_shadow_end:
.long __data_shadow_end
_data_start:
.long __data_start
_data_end:
.long __data_end
_bss_start:
.long __bss_start
_bss_end:
.long __bss_end
_stack_und_end:
.long __stack_und_end
_stack_abt_end:
.long __stack_abt_end
_stack_irq_end:
.long __stack_irq_end
_stack_fiq_end:
.long __stack_fiq_end
_stack_srv_end:
.long __stack_srv_end

View File

@ -1,124 +0,0 @@
/*
* sys-clock.c
*
* Copyright(c) 2007-2018 Jianjun Jiang <8192542@qq.com>
* Official site: http://xboot.org
* Mobile phone: +86-18665388956
* QQ: 8192542
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
//#include <xboot.h>
#include <stdint.h>
#include <f1c100s/reg-ccu.h>
#include <io.h>
static inline void sdelay(int loops)
{
__asm__ __volatile__ ("1:\n" "subs %0, %1, #1\n"
"bne 1b":"=r" (loops):"0"(loops));
}
static void wait_pll_stable(uint32_t base)
{
uint32_t rval = 0;
uint32_t time = 0xfff;
do {
rval = read32(base);
time--;
} while(time && !(rval & (1 << 28)));
}
static void clock_set_pll_cpu(uint32_t clk)
{
uint32_t n, k, m, p;
uint32_t rval = 0;
uint32_t div = 0;
if(clk > 720000000)
clk = 720000000;
if((clk % 24000000) == 0)
{
div = clk / 24000000;
n = div - 1;
k = 0;
m = 0;
p = 0;
}
else if((clk % 12000000) == 0)
{
m = 1;
div = clk / 12000000;
if((div % 3) == 0)
k = 2;
else if((div % 4) == 0)
k = 3;
else
k = 1;
n = (div / (k + 1)) - 1;
p = 0;
}
else
{
div = clk / 24000000;
n = div - 1;
k = 0;
m = 0;
p = 0;
}
rval = read32(F1C100S_CCU_BASE + CCU_PLL_CPU_CTRL);
rval &= ~((0x3 << 16) | (0x1f << 8) | (0x3 << 4) | (0x3 << 0));
rval |= (1U << 31) | (p << 16) | (n << 8) | (k << 4) | m;
write32(F1C100S_CCU_BASE + CCU_PLL_CPU_CTRL, rval);
wait_pll_stable(F1C100S_CCU_BASE + CCU_PLL_CPU_CTRL);
}
void sys_clock_init(void)
{
uint32_t val;
write32(F1C100S_CCU_BASE + CCU_PLL_STABLE_TIME0, 0x1ff);
write32(F1C100S_CCU_BASE + CCU_PLL_STABLE_TIME1, 0x1ff);
val = read32(F1C100S_CCU_BASE + CCU_CPU_CFG);
val &= ~(0x3 << 16);
val |= (0x1 << 16);
write32(F1C100S_CCU_BASE + CCU_CPU_CFG, val);
sdelay(100);
write32(F1C100S_CCU_BASE + CCU_PLL_VIDEO_CTRL, 0x81004107);
sdelay(100);
write32(F1C100S_CCU_BASE + CCU_PLL_PERIPH_CTRL, 0x80041800);
sdelay(100);
write32(F1C100S_CCU_BASE + CCU_AHB_APB_CFG, 0x00003180);
sdelay(100);
val = read32(F1C100S_CCU_BASE + CCU_DRAM_CLK_GATE);
val |= (0x1 << 26) | (0x1 << 24);
write32(F1C100S_CCU_BASE + CCU_DRAM_CLK_GATE, val);
sdelay(100);
clock_set_pll_cpu(408000000);
val = read32(F1C100S_CCU_BASE + CCU_CPU_CFG);
val &= ~(0x3 << 16);
val |= (0x2 << 16);
write32(F1C100S_CCU_BASE + CCU_CPU_CFG, val);
sdelay(100);
}

View File

@ -1,111 +0,0 @@
/*
* sys-copyself.c
*
* Copyright(c) 2007-2018 Jianjun Jiang <8192542@qq.com>
* Official site: http://xboot.org
* Mobile phone: +86-18665388956
* QQ: 8192542
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <stdint.h>
extern unsigned char __image_start;
extern unsigned char __image_end;
extern void return_to_fel(void);
extern void sys_mmu_init(void);
extern void sys_uart_putc(char c);
extern void sys_spi_flash_init(void);
extern void sys_spi_flash_exit(void);
extern void sys_spi_flash_read(int addr, void * buf, int count);
enum {
BOOT_DEVICE_FEL = 0,
BOOT_DEVICE_SPI = 1,
BOOT_DEVICE_MMC = 2,
};
static int get_boot_device(void)
{
uint32_t * t = (void *)0x00000058;
if(t[0] == 0x1)
return BOOT_DEVICE_FEL;
return BOOT_DEVICE_SPI;
}
void sys_copyself(void)
{
int d = get_boot_device();
void * mem;
uint32_t size;
if(d == BOOT_DEVICE_FEL)
{
sys_uart_putc('B');
sys_uart_putc('o');
sys_uart_putc('o');
sys_uart_putc('t');
sys_uart_putc(' ');
sys_uart_putc('t');
sys_uart_putc('o');
sys_uart_putc(' ');
sys_uart_putc('F');
sys_uart_putc('E');
sys_uart_putc('L');
sys_uart_putc(' ');
sys_uart_putc('m');
sys_uart_putc('o');
sys_uart_putc('d');
sys_uart_putc('e');
sys_uart_putc('\r');
sys_uart_putc('\n');
return_to_fel();
}
else if(d == BOOT_DEVICE_SPI)
{
sys_uart_putc('B');
sys_uart_putc('o');
sys_uart_putc('o');
sys_uart_putc('t');
sys_uart_putc(' ');
sys_uart_putc('t');
sys_uart_putc('o');
sys_uart_putc(' ');
sys_uart_putc('S');
sys_uart_putc('P');
sys_uart_putc('I');
sys_uart_putc(' ');
sys_uart_putc('m');
sys_uart_putc('o');
sys_uart_putc('d');
sys_uart_putc('e');
sys_uart_putc('\r');
sys_uart_putc('\n');
mem = (void *)&__image_start;
size = &__image_end - &__image_start;
sys_mmu_init();
sys_spi_flash_init();
sys_spi_flash_read(0, mem, size);
sys_spi_flash_exit();
}
else if(d == BOOT_DEVICE_MMC)
{
mem = (void *)&__image_start;
size = (&__image_end - &__image_start + 512) >> 9;
}
}

View File

@ -1,506 +0,0 @@
/*
* sys-dram.c
*
* Copyright(c) 2007-2018 Jianjun Jiang <8192542@qq.com>
* Official site: http://xboot.org
* Mobile phone: +86-18665388956
* QQ: 8192542
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <stdint.h>
#include <f1c100s/reg-ccu.h>
#include <f1c100s/reg-dram.h>
#include <io.h>
#define PLL_DDR_CLK (156000000)
#define SDR_T_CAS (0x2)
#define SDR_T_RAS (0x8)
#define SDR_T_RCD (0x3)
#define SDR_T_RP (0x3)
#define SDR_T_WR (0x3)
#define SDR_T_RFC (0xd)
#define SDR_T_XSR (0xf9)
#define SDR_T_RC (0xb)
#define SDR_T_INIT (0x8)
#define SDR_T_INIT_REF (0x7)
#define SDR_T_WTR (0x2)
#define SDR_T_RRD (0x2)
#define SDR_T_XP (0x0)
enum dram_type_t
{
DRAM_TYPE_SDR = 0,
DRAM_TYPE_DDR = 1,
DRAM_TYPE_MDDR = 2,
};
struct dram_para_t
{
uint32_t base; /* dram base address */
uint32_t size; /* dram size (unit: MByte) */
uint32_t clk; /* dram work clock (unit: MHz) */
uint32_t access_mode; /* 0: interleave mode 1: sequence mode */
uint32_t cs_num; /* dram chip count 1: one chip 2: two chip */
uint32_t ddr8_remap; /* for 8bits data width DDR 0: normal 1: 8bits */
enum dram_type_t sdr_ddr;
uint32_t bwidth; /* dram bus width */
uint32_t col_width; /* column address width */
uint32_t row_width; /* row address width */
uint32_t bank_size; /* dram bank count */
uint32_t cas; /* dram cas */
};
static inline void sdelay(int loops)
{
__asm__ __volatile__ ("1:\n" "subs %0, %1, #1\n"
"bne 1b":"=r" (loops):"0"(loops));
}
static void dram_delay(int ms)
{
sdelay(ms * 2 * 1000);
}
static int dram_initial(void)
{
unsigned int time = 0xffffff;
write32(F1C100S_DRAM_BASE + DRAM_SCTLR, read32(F1C100S_DRAM_BASE + DRAM_SCTLR) | 0x1);
while((read32(F1C100S_DRAM_BASE + DRAM_SCTLR) & 0x1) && time--)
{
if(time == 0)
return 0;
}
return 1;
}
static int dram_delay_scan(void)
{
unsigned int time = 0xffffff;
write32(F1C100S_DRAM_BASE + DRAM_DDLYR, read32(F1C100S_DRAM_BASE + DRAM_DDLYR) | 0x1);
while((read32(F1C100S_DRAM_BASE + DRAM_DDLYR) & 0x1) && time--)
{
if(time == 0)
return 0;
}
return 1;
}
static void dram_set_autofresh_cycle(uint32_t clk)
{
uint32_t val = 0;
uint32_t row = 0;
uint32_t temp = 0;
row = read32(F1C100S_DRAM_BASE + DRAM_SCONR);
row &= 0x1e0;
row >>= 0x5;
if(row == 0xc)
{
if(clk >= 1000000)
{
temp = clk + (clk >> 3) + (clk >> 4) + (clk >> 5);
while(temp >= (10000000 >> 6))
{
temp -= (10000000 >> 6);
val++;
}
}
else
{
val = (clk * 499) >> 6;
}
}
else if(row == 0xb)
{
if(clk >= 1000000)
{
temp = clk + (clk >> 3) + (clk >> 4) + (clk >> 5);
while(temp >= (10000000 >> 7))
{
temp -= (10000000 >> 7);
val++;
}
}
else
{
val = (clk * 499) >> 5;
}
}
write32(F1C100S_DRAM_BASE + DRAM_SREFR, val);
}
static int dram_para_setup(struct dram_para_t * para)
{
uint32_t val = 0;
val = (para->ddr8_remap) |
(0x1 << 1) |
((para->bank_size >> 2) << 3) |
((para->cs_num >> 1) << 4) |
((para->row_width - 1) << 5) |
((para->col_width - 1) << 9) |
((para->sdr_ddr ? (para->bwidth >> 4) : (para->bwidth >> 5)) << 13) |
(para->access_mode << 15) |
(para->sdr_ddr << 16);
write32(F1C100S_DRAM_BASE + DRAM_SCONR, val);
write32(F1C100S_DRAM_BASE + DRAM_SCTLR, read32(F1C100S_DRAM_BASE + DRAM_SCTLR) | (0x1 << 19));
return dram_initial();
}
static uint32_t dram_check_delay(uint32_t bwidth)
{
uint32_t dsize;
uint32_t i,j;
uint32_t num = 0;
uint32_t dflag = 0;
dsize = ((bwidth == 16) ? 4 : 2);
for(i = 0; i < dsize; i++)
{
if(i == 0)
dflag = read32(F1C100S_DRAM_BASE + DRAM_DRPTR0);
else if(i == 1)
dflag = read32(F1C100S_DRAM_BASE + DRAM_DRPTR1);
else if(i == 2)
dflag = read32(F1C100S_DRAM_BASE + DRAM_DRPTR2);
else if(i == 3)
dflag = read32(F1C100S_DRAM_BASE + DRAM_DRPTR3);
for(j = 0; j < 32; j++)
{
if(dflag & 0x1)
num++;
dflag >>= 1;
}
}
return num;
}
static int sdr_readpipe_scan(void)
{
uint32_t k = 0;
for(k = 0; k < 32; k++)
{
write32(0x80000000 + 4 * k, k);
}
for(k = 0; k < 32; k++)
{
if(read32(0x80000000 + 4 * k) != k)
return 0;
}
return 1;
}
static uint32_t sdr_readpipe_select(void)
{
uint32_t value = 0;
uint32_t i = 0;
for(i = 0; i < 8; i++)
{
write32(F1C100S_DRAM_BASE + DRAM_SCTLR, (read32(F1C100S_DRAM_BASE + DRAM_SCTLR) & (~(0x7 << 6))) | (i << 6));
if(sdr_readpipe_scan())
{
value = i;
return value;
}
}
return value;
}
static uint32_t dram_check_type(struct dram_para_t * para)
{
uint32_t val = 0;
uint32_t times = 0;
uint32_t i;
for(i = 0; i < 8; i++)
{
val = read32(F1C100S_DRAM_BASE + DRAM_SCTLR);
val &= ~(0x7 << 6);
val |= (i << 6);
write32(F1C100S_DRAM_BASE + DRAM_SCTLR, val);
dram_delay_scan();
if(read32(F1C100S_DRAM_BASE + DRAM_DDLYR) & 0x30)
times++;
}
if(times == 8)
{
para->sdr_ddr = DRAM_TYPE_SDR;
return 0;
}
else
{
para->sdr_ddr = DRAM_TYPE_DDR;
return 1;
}
}
static uint32_t dram_scan_readpipe(struct dram_para_t * para)
{
uint32_t i, rp_best = 0, rp_val = 0;
uint32_t val = 0;
uint32_t readpipe[8];
if(para->sdr_ddr == DRAM_TYPE_DDR)
{
for(i = 0; i < 8; i++)
{
val = read32(F1C100S_DRAM_BASE + DRAM_SCTLR);
val &= ~(0x7 << 6);
val |= (i << 6);
write32(F1C100S_DRAM_BASE + DRAM_SCTLR, val);
dram_delay_scan();
readpipe[i] = 0;
if((((read32(F1C100S_DRAM_BASE + DRAM_DDLYR) >> 4) & 0x3) == 0x0) &&
(((read32(F1C100S_DRAM_BASE + DRAM_DDLYR) >> 4) & 0x1) == 0x0))
{
readpipe[i] = dram_check_delay(para->bwidth);
}
if(rp_val < readpipe[i])
{
rp_val = readpipe[i];
rp_best = i;
}
}
val = read32(F1C100S_DRAM_BASE + DRAM_SCTLR);
val &= ~(0x7 << 6);
val |= (rp_best << 6);
write32(F1C100S_DRAM_BASE + DRAM_SCTLR, val);
dram_delay_scan();
}
else
{
val = read32(F1C100S_DRAM_BASE + DRAM_SCONR);
val &= (~(0x1 << 16));
val &= (~(0x3 << 13));
write32(F1C100S_DRAM_BASE + DRAM_SCONR, val);
rp_best = sdr_readpipe_select();
val = read32(F1C100S_DRAM_BASE + DRAM_SCTLR);
val &= ~(0x7 << 6);
val |= (rp_best << 6);
write32(F1C100S_DRAM_BASE + DRAM_SCTLR, val);
}
return 0;
}
static uint32_t dram_get_dram_size(struct dram_para_t * para)
{
uint32_t colflag = 10, rowflag = 13;
uint32_t i = 0;
uint32_t val1 = 0;
uint32_t count = 0;
uint32_t addr1, addr2;
para->col_width = colflag;
para->row_width = rowflag;
dram_para_setup(para);
dram_scan_readpipe(para);
for(i = 0; i < 32; i++)
{
*((uint32_t *)(0x80000200 + i)) = 0x11111111;
*((uint32_t *)(0x80000600 + i)) = 0x22222222;
}
for(i = 0; i < 32; i++)
{
val1 = *((uint32_t *)(0x80000200 + i));
if(val1 == 0x22222222)
count++;
}
if(count == 32)
{
colflag = 9;
}
else
{
colflag = 10;
}
count = 0;
para->col_width = colflag;
para->row_width = rowflag;
dram_para_setup(para);
if(colflag == 10)
{
addr1 = 0x80400000;
addr2 = 0x80c00000;
}
else
{
addr1 = 0x80200000;
addr2 = 0x80600000;
}
for(i = 0; i < 32; i++)
{
*((uint32_t *)(addr1 + i)) = 0x33333333;
*((uint32_t *)(addr2 + i)) = 0x44444444;
}
for(i = 0; i < 32; i++)
{
val1 = *((uint32_t *)(addr1 + i));
if(val1 == 0x44444444)
{
count++;
}
}
if(count == 32)
{
rowflag = 12;
}
else
{
rowflag = 13;
}
para->col_width = colflag;
para->row_width = rowflag;
if(para->row_width != 13)
{
para->size = 16;
}
else if(para->col_width == 10)
{
para->size = 64;
}
else
{
para->size = 32;
}
dram_set_autofresh_cycle(para->clk);
para->access_mode = 0;
dram_para_setup(para);
return 0;
}
static int dram_init(struct dram_para_t * para)
{
uint32_t val = 0;
uint32_t i;
write32(0x01c20800 + 0x24, read32(0x01c20800 + 0x24) | (0x7 << 12));
dram_delay(5);
if(((para->cas) >> 3) & 0x1)
{
write32(0x01c20800 + 0x2c4, read32(0x01c20800 + 0x2c4) | (0x1 << 23) | (0x20 << 17));
}
if((para->clk >= 144) && (para->clk <= 180))
{
write32(0x01c20800 + 0x2c0, 0xaaa);
}
if(para->clk >= 180)
{
write32(0x01c20800 + 0x2c0, 0xfff);
}
if((para->clk) <= 96)
{
val = (0x1 << 0) | (0x0 << 4) | (((para->clk * 2) / 12 - 1) << 8) | (0x1u << 31);
}
else
{
val = (0x0 << 0) | (0x0 << 4) | (((para->clk * 2) / 24 - 1) << 8) | (0x1u << 31);
}
if(para->cas & (0x1 << 4))
{
write32(F1C100S_CCU_BASE + CCU_PLL_DDR0_PAT, 0xd1303333);
}
else if(para->cas & (0x1 << 5))
{
write32(F1C100S_CCU_BASE + CCU_PLL_DDR0_PAT, 0xcce06666);
}
else if(para->cas & (0x1 << 6))
{
write32(F1C100S_CCU_BASE + CCU_PLL_DDR0_PAT, 0xc8909999);
}
else if(para->cas & (0x1 << 7))
{
write32(F1C100S_CCU_BASE + CCU_PLL_DDR0_PAT, 0xc440cccc);
}
if(para->cas & (0xf << 4))
{
val |= 0x1 << 24;
}
write32(F1C100S_CCU_BASE + CCU_PLL_DDR_CTRL, val);
write32(F1C100S_CCU_BASE + CCU_PLL_DDR_CTRL, read32(F1C100S_CCU_BASE + CCU_PLL_DDR_CTRL) | (0x1 << 20));
while((read32(F1C100S_CCU_BASE + CCU_PLL_DDR_CTRL) & (1 << 28)) == 0);
dram_delay(5);
write32(F1C100S_CCU_BASE + CCU_BUS_CLK_GATE0, read32(F1C100S_CCU_BASE + CCU_BUS_CLK_GATE0) | (0x1 << 14));
write32(F1C100S_CCU_BASE + CCU_BUS_SOFT_RST0, read32(F1C100S_CCU_BASE + CCU_BUS_SOFT_RST0) & ~(0x1 << 14));
for(i = 0; i < 10; i++)
continue;
write32(F1C100S_CCU_BASE + CCU_BUS_SOFT_RST0, read32(F1C100S_CCU_BASE + CCU_BUS_SOFT_RST0) | (0x1 << 14));
val = read32(0x01c20800 + 0x2c4);
(para->sdr_ddr == DRAM_TYPE_DDR) ? (val |= (0x1 << 16)) : (val &= ~(0x1 << 16));
write32(0x01c20800 + 0x2c4, val);
val = (SDR_T_CAS << 0) | (SDR_T_RAS << 3) | (SDR_T_RCD << 7) | (SDR_T_RP << 10) | (SDR_T_WR << 13) | (SDR_T_RFC << 15) | (SDR_T_XSR << 19) | (SDR_T_RC << 28);
write32(F1C100S_DRAM_BASE + DRAM_STMG0R, val);
val = (SDR_T_INIT << 0) | (SDR_T_INIT_REF << 16) | (SDR_T_WTR << 20) | (SDR_T_RRD << 22) | (SDR_T_XP << 25);
write32(F1C100S_DRAM_BASE + DRAM_STMG1R, val);
dram_para_setup(para);
dram_check_type(para);
val = read32(0x01c20800 + 0x2c4);
(para->sdr_ddr == DRAM_TYPE_DDR) ? (val |= (0x1 << 16)) : (val &= ~(0x1 << 16));
write32(0x01c20800 + 0x2c4, val);
dram_set_autofresh_cycle(para->clk);
dram_scan_readpipe(para);
dram_get_dram_size(para);
for(i = 0; i < 128; i++)
{
*((volatile uint32_t *)(para->base + 4 * i)) = para->base + 4 * i;
}
for(i = 0; i < 128; i++)
{
if(*((volatile uint32_t *)(para->base + 4 * i)) != (para->base + 4 * i))
return 0;
}
return 1;
}
void sys_dram_init(void)
{
struct dram_para_t para;
uint32_t * dsz = (void *)0x0000005c;
para.base = 0x80000000;
para.size = 32;
para.clk = PLL_DDR_CLK / 1000000;
para.access_mode = 1;
para.cs_num = 1;
para.ddr8_remap = 0;
para.sdr_ddr = DRAM_TYPE_DDR;
para.bwidth = 16;
para.col_width = 10;
para.row_width = 13;
para.bank_size = 4;
para.cas = 0x3;
if((dsz[0] >> 24) == 'X')
return;
if(dram_init(&para))
dsz[0] = (((uint32_t)'X') << 24) | (para.size << 0);
}

View File

@ -1,57 +0,0 @@
/*
* sys-mmu.c
*
* Copyright(c) 2007-2018 Jianjun Jiang <8192542@qq.com>
* Official site: http://xboot.org
* Mobile phone: +86-18665388956
* QQ: 8192542
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <stdint.h>
#include <io.h>
#include <sizes.h>
#include <arm32.h>
static void map_l1_section(uint32_t * ttb, virtual_addr_t virt, physical_addr_t phys, physical_size_t size, int type)
{
physical_size_t i;
virt >>= 20;
phys >>= 20;
size >>= 20;
type &= 0x3;
for(i = size; i > 0; i--, virt++, phys++)
ttb[virt] = (phys << 20) | (0x3 << 10) | (0x0 << 5) | (type << 2) | (0x2 << 0);
}
void sys_mmu_init(void)
{
uint32_t * ttb = (uint32_t *)(0x80000000 + SZ_1M * 31);
map_l1_section(ttb, 0x00000000, 0x00000000, SZ_2G, 0);
map_l1_section(ttb, 0x80000000, 0x80000000, SZ_2G, 0);
map_l1_section(ttb, 0x80000000, 0x80000000, SZ_1M * 32, 3);
arm32_ttb_set((uint32_t)(ttb));
arm32_tlb_invalidate();
arm32_domain_set(0x3);
arm32_mmu_enable();
arm32_icache_enable();
arm32_dcache_enable();
}

View File

@ -1,204 +0,0 @@
/*
* sys-spi-flash.c
*
* Copyright(c) 2007-2018 Jianjun Jiang <8192542@qq.com>
* Official site: http://xboot.org
* Mobile phone: +86-18665388956
* QQ: 8192542
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <stdint.h>
#include <types.h>
#include <string.h>
#include <io.h>
enum {
SPI_GCR = 0x04,
SPI_TCR = 0x08,
SPI_IER = 0x10,
SPI_ISR = 0x14,
SPI_FCR = 0x18,
SPI_FSR = 0x1c,
SPI_WCR = 0x20,
SPI_CCR = 0x24,
SPI_MBC = 0x30,
SPI_MTC = 0x34,
SPI_BCC = 0x38,
SPI_TXD = 0x200,
SPI_RXD = 0x300,
};
void sys_spi_flash_init(void)
{
virtual_addr_t addr;
uint32_t val;
/* Config GPIOC0, GPIOC1, GPIOC2 and GPIOC3 */
addr = 0x01c20848 + 0x00;
val = read32(addr);
val &= ~(0xf << ((0 & 0x7) << 2));
val |= ((0x2 & 0x7) << ((0 & 0x7) << 2));
write32(addr, val);
val = read32(addr);
val &= ~(0xf << ((1 & 0x7) << 2));
val |= ((0x2 & 0x7) << ((1 & 0x7) << 2));
write32(addr, val);
val = read32(addr);
val &= ~(0xf << ((2 & 0x7) << 2));
val |= ((0x2 & 0x7) << ((2 & 0x7) << 2));
write32(addr, val);
val = read32(addr);
val &= ~(0xf << ((3 & 0x7) << 2));
val |= ((0x2 & 0x7) << ((3 & 0x7) << 2));
write32(addr, val);
/* Deassert spi0 reset */
addr = 0x01c202c0;
val = read32(addr);
val |= (1 << 20);
write32(addr, val);
/* Open the spi0 bus gate */
addr = 0x01c20000 + 0x60;
val = read32(addr);
val |= (1 << 20);
write32(addr, val);
/* Set spi clock rate control register, divided by 4 */
addr = 0x01c05000;
write32(addr + SPI_CCR, 0x00001001);
/* Enable spi0 and do a soft reset */
addr = 0x01c05000;
val = read32(addr + SPI_GCR);
val |= (1 << 31) | (1 << 7) | (1 << 1) | (1 << 0);
write32(addr + SPI_GCR, val);
while(read32(addr + SPI_GCR) & (1 << 31));
val = read32(addr + SPI_TCR);
val &= ~(0x3 << 0);
val |= (1 << 6) | (1 << 2);
write32(addr + SPI_TCR, val);
val = read32(addr + SPI_FCR);
val |= (1 << 31) | (1 << 15);
write32(addr + SPI_FCR, val);
}
void sys_spi_flash_exit(void)
{
virtual_addr_t addr = 0x01c05000;
uint32_t val;
/* Disable the spi0 controller */
val = read32(addr + SPI_GCR);
val &= ~((1 << 1) | (1 << 0));
write32(addr + SPI_GCR, val);
}
static void sys_spi_select(void)
{
virtual_addr_t addr = 0x01c05000;
uint32_t val;
val = read32(addr + SPI_TCR);
val &= ~((0x3 << 4) | (0x1 << 7));
val |= ((0 & 0x3) << 4) | (0x0 << 7);
write32(addr + SPI_TCR, val);
}
static void sys_spi_deselect(void)
{
virtual_addr_t addr = 0x01c05000;
uint32_t val;
val = read32(addr + SPI_TCR);
val &= ~((0x3 << 4) | (0x1 << 7));
val |= ((0 & 0x3) << 4) | (0x1 << 7);
write32(addr + SPI_TCR, val);
}
static void sys_spi_write_txbuf(uint8_t * buf, int len)
{
virtual_addr_t addr = 0x01c05000;
int i;
if(!buf)
len = 0;
write32(addr + SPI_MTC, len & 0xffffff);
write32(addr + SPI_BCC, len & 0xffffff);
for(i = 0; i < len; ++i)
write8(addr + SPI_TXD, *buf++);
}
static int sys_spi_transfer(void * txbuf, void * rxbuf, int len)
{
virtual_addr_t addr = 0x01c05000;
int count = len;
uint8_t * tx = txbuf;
uint8_t * rx = rxbuf;
uint8_t val;
unsigned int n, i;
while(count > 0)
{
n = (count <= 64) ? count : 64;
write32(addr + SPI_MBC, n);
sys_spi_write_txbuf(tx, n);
write32(addr + SPI_TCR, read32(addr + SPI_TCR) | (1 << 31));
while((read32(addr + SPI_FSR) & 0xff) < n);
for(i = 0; i < n; i++)
{
val = read8(addr + SPI_RXD);
if(rx)
*rx++ = val;
}
if(tx)
tx += n;
count -= n;
}
return len;
}
static int sys_spi_write_then_read(void * txbuf, int txlen, void * rxbuf, int rxlen)
{
if(sys_spi_transfer(txbuf, NULL, txlen) != txlen)
return -1;
if(sys_spi_transfer(NULL, rxbuf, rxlen) != rxlen)
return -1;
return 0;
}
void sys_spi_flash_read(int addr, void * buf, int count)
{
uint8_t tx[4];
tx[0] = 0x03;
tx[1] = (uint8_t)(addr >> 16);
tx[2] = (uint8_t)(addr >> 8);
tx[3] = (uint8_t)(addr >> 0);
sys_spi_select();
sys_spi_write_then_read(tx, 4, buf, count);
sys_spi_deselect();
}

View File

@ -1,83 +0,0 @@
/*
* sys-uart.c
*
* Copyright(c) 2007-2018 Jianjun Jiang <8192542@qq.com>
* Official site: http://xboot.org
* Mobile phone: +86-18665388956
* QQ: 8192542
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <types.h>
#include <stdint.h>
#include <io.h>
void sys_uart_init(void)
{
virtual_addr_t addr;
uint32_t val;
/* Config GPIOE1 and GPIOE0 to txd0 and rxd0 */
addr = 0x01c20890 + 0x00;
val = read32(addr);
val &= ~(0xf << ((1 & 0x7) << 2));
val |= ((0x5 & 0x7) << ((1 & 0x7) << 2));
write32(addr, val);
val = read32(addr);
val &= ~(0xf << ((0 & 0x7) << 2));
val |= ((0x5 & 0x7) << ((0 & 0x7) << 2));
write32(addr, val);
/* Open the clock gate for uart0 */
addr = 0x01c20068;
val = read32(addr);
val |= 1 << 20;
write32(addr, val);
/* Deassert uart0 reset */
addr = 0x01c202d0;
val = read32(addr);
val |= 1 << 20;
write32(addr, val);
/* Config uart0 to 115200-8-1-0 */
addr = 0x01c25000;
write32(addr + 0x04, 0x0);
write32(addr + 0x08, 0xf7);
write32(addr + 0x10, 0x0);
val = read32(addr + 0x0c);
val |= (1 << 7);
write32(addr + 0x0c, val);
write32(addr + 0x00, 0x36 & 0xff);
write32(addr + 0x04, (0x36 >> 8) & 0xff);
val = read32(addr + 0x0c);
val &= ~(1 << 7);
write32(addr + 0x0c, val);
val = read32(addr + 0x0c);
val &= ~0x1f;
val |= (0x3 << 0) | (0 << 2) | (0x0 << 3);
write32(addr + 0x0c, val);
}
void sys_uart_putc(char c)
{
virtual_addr_t addr = 0x01c25000;
while((read32(addr + 0x7c) & (0x1 << 1)) == 0);
write32(addr + 0x00, c);
}