From dba59217da489dc497cbe2b573e7e144d085c869 Mon Sep 17 00:00:00 2001 From: Yunhao Tian Date: Tue, 30 Nov 2021 17:10:53 +0800 Subject: [PATCH 01/22] usbd: supress "statement is unreachable" warning on ARMCC --- src/device/usbd.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/device/usbd.c b/src/device/usbd.c index 6a5210b3..0e31f47c 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -44,6 +44,11 @@ #define CFG_TUD_TASK_QUEUE_SZ 16 #endif +#ifdef __ARMCC_VERSION +// Supress "statement is unreachable" warning +#pragma diag_suppress 111 +#endif + //--------------------------------------------------------------------+ // Device Data //--------------------------------------------------------------------+ From ac20605e3f098687ce40349bbecc9266333d951b Mon Sep 17 00:00:00 2001 From: Yunhao Tian Date: Tue, 30 Nov 2021 17:11:09 +0800 Subject: [PATCH 02/22] Ignore certain compiler options on ARMCC ARMCC also sets __GNU__ macro, but doesn't support GCC diagnostic pragmas. --- src/common/tusb_compiler.h | 4 +++- src/device/dcd.h | 4 ++-- src/osal/osal.h | 4 ++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/common/tusb_compiler.h b/src/common/tusb_compiler.h index d3284c62..38e6a16d 100644 --- a/src/common/tusb_compiler.h +++ b/src/common/tusb_compiler.h @@ -137,9 +137,11 @@ #define TU_BSWAP16(u16) (__builtin_bswap16(u16)) #define TU_BSWAP32(u32) (__builtin_bswap32(u32)) + #ifndef __ARMCC_VERSION // List of obsolete callback function that is renamed and should not be defined. // Put it here since only gcc support this pragma - #pragma GCC poison tud_vendor_control_request_cb + #pragma GCC poison tud_vendor_control_request_cb + #endif #elif defined(__TI_COMPILER_VERSION__) #define TU_ATTR_ALIGNED(Bytes) __attribute__ ((aligned(Bytes))) diff --git a/src/device/dcd.h b/src/device/dcd.h index c042cc70..fbcef40d 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -106,12 +106,12 @@ typedef struct TU_ATTR_ALIGNED(4) void dcd_init (uint8_t rhport); // Interrupt Handler -#if __GNUC__ +#if __GNUC__ && !defined(__ARMCC_VERSION) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wredundant-decls" #endif void dcd_int_handler(uint8_t rhport); -#if __GNUC__ +#if __GNUC__ && !defined(__ARMCC_VERSION) #pragma GCC diagnostic pop #endif diff --git a/src/osal/osal.h b/src/osal/osal.h index c8131d19..9194f80d 100644 --- a/src/osal/osal.h +++ b/src/osal/osal.h @@ -67,7 +67,7 @@ typedef void (*osal_task_func_t)( void * ); // OSAL Porting API //--------------------------------------------------------------------+ -#if __GNUC__ +#if __GNUC__ && !defined(__ARMCC_VERSION) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wredundant-decls" #endif @@ -88,7 +88,7 @@ static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef); static inline bool osal_queue_receive(osal_queue_t qhdl, void* data); static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr); static inline bool osal_queue_empty(osal_queue_t qhdl); -#if __GNUC__ +#if __GNUC__ && !defined(__ARMCC_VERSION) #pragma GCC diagnostic pop #endif From a6929cf03eabe9f4fc0404d7c15b04ee2761945c Mon Sep 17 00:00:00 2001 From: Yunhao Tian Date: Tue, 30 Nov 2021 17:11:14 +0800 Subject: [PATCH 03/22] Add support for Keil RTX4 OS abstraction layer --- src/osal/osal.h | 2 + src/osal/osal_rtx4.h | 169 +++++++++++++++++++++++++++++++++++++++++++ src/tusb_option.h | 1 + 3 files changed, 172 insertions(+) create mode 100644 src/osal/osal_rtx4.h diff --git a/src/osal/osal.h b/src/osal/osal.h index 9194f80d..b2943cc7 100644 --- a/src/osal/osal.h +++ b/src/osal/osal.h @@ -57,6 +57,8 @@ typedef void (*osal_task_func_t)( void * ); #include "osal_pico.h" #elif CFG_TUSB_OS == OPT_OS_RTTHREAD #include "osal_rtthread.h" +#elif CFG_TUSB_OS == OPT_OS_RTX4 + #include "osal_rtx4.h" #elif CFG_TUSB_OS == OPT_OS_CUSTOM #include "tusb_os_custom.h" // implemented by application #else diff --git a/src/osal/osal_rtx4.h b/src/osal/osal_rtx4.h new file mode 100644 index 00000000..93d1a7a2 --- /dev/null +++ b/src/osal/osal_rtx4.h @@ -0,0 +1,169 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_OSAL_RTX4_H_ +#define _TUSB_OSAL_RTX4_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +//--------------------------------------------------------------------+ +// TASK API +//--------------------------------------------------------------------+ +static inline void osal_task_delay(uint32_t msec) +{ + uint16_t hi = msec >> 16; + uint16_t lo = msec; + while (hi--) { + os_dly_wait(0xFFFE); + } + os_dly_wait(lo); +} + +static inline uint16_t msec2wait(uint32_t msec) { + if (msec == OSAL_TIMEOUT_WAIT_FOREVER) + return 0xFFFF; + else if (msec >= 0xFFFE) + return 0xFFFE; + else + return msec; +} + +//--------------------------------------------------------------------+ +// Semaphore API +//--------------------------------------------------------------------+ +typedef OS_SEM osal_semaphore_def_t; +typedef OS_ID osal_semaphore_t; + +static inline OS_ID osal_semaphore_create(osal_semaphore_def_t* semdef) { + os_sem_init(semdef, 0); + return semdef; +} + +static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) { + if ( !in_isr ) { + os_sem_send(sem_hdl); + } else { + isr_sem_send(sem_hdl); + } + return true; +} + +static inline bool osal_semaphore_wait (osal_semaphore_t sem_hdl, uint32_t msec) { + return os_sem_wait(sem_hdl, msec2wait(msec)) != OS_R_TMO; +} + +static inline void osal_semaphore_reset(osal_semaphore_t const sem_hdl) { + // TODO: implement +} + +//--------------------------------------------------------------------+ +// MUTEX API (priority inheritance) +//--------------------------------------------------------------------+ +typedef OS_MUT osal_mutex_def_t; +typedef OS_ID osal_mutex_t; + +static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) +{ + os_mut_init(mdef); + return mdef; +} + +static inline bool osal_mutex_lock (osal_mutex_t mutex_hdl, uint32_t msec) +{ + return os_mut_wait(mutex_hdl, msec2wait(msec)) != OS_R_TMO; +} + +static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) +{ + return os_mut_release(mutex_hdl) == OS_R_OK; +} + +//--------------------------------------------------------------------+ +// QUEUE API +//--------------------------------------------------------------------+ + +// role device/host is used by OS NONE for mutex (disable usb isr) only +#define OSAL_QUEUE_DEF(_role, _name, _depth, _type) \ + os_mbx_declare(_name##__mbox, _depth); \ + _declare_box(_name##__pool, sizeof(_type), _depth); \ + osal_queue_def_t _name = { .depth = _depth, .item_sz = sizeof(_type), .pool = _name##__pool, .mbox = _name##__mbox }; + + +typedef struct +{ + uint16_t depth; + uint16_t item_sz; + U32* pool; + U32* mbox; +}osal_queue_def_t; + +typedef osal_queue_def_t* osal_queue_t; + +static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) +{ + os_mbx_init(qdef->mbox, (qdef->depth + 4) * 4); + _init_box(qdef->pool, ((qdef->item_sz+3)/4)*(qdef->depth) + 3, qdef->item_sz); + return qdef; +} + +static inline bool osal_queue_receive(osal_queue_t qhdl, void* data) +{ + void* buf; + os_mbx_wait(qhdl->mbox, &buf, 0xFFFF); + memcpy(data, buf, qhdl->item_sz); + _free_box(qhdl->pool, buf); + return true; +} + +static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) +{ + void* buf = _alloc_box(qhdl->pool); + memcpy(buf, data, qhdl->item_sz); + if ( !in_isr ) + { + os_mbx_send(qhdl->mbox, buf, 0xFFFF); + } + else + { + isr_mbx_send(qhdl->mbox, buf); + } + return true; +} + +static inline bool osal_queue_empty(osal_queue_t qhdl) +{ + return os_mbx_check(qhdl->mbox) == qhdl->depth; +} + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_OSAL_FREERTOS_H_ */ diff --git a/src/tusb_option.h b/src/tusb_option.h index 2edd310f..dcf1c461 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -151,6 +151,7 @@ #define OPT_OS_CUSTOM 4 ///< Custom OS is implemented by application #define OPT_OS_PICO 5 ///< Raspberry Pi Pico SDK #define OPT_OS_RTTHREAD 6 ///< RT-Thread +#define OPT_OS_RTX4 7 ///< Keil RTX 4 // Allow to use command line to change the config name/location #ifdef CFG_TUSB_CONFIG_FILE From bb7d1fa3bacb08717e8eebc55f81fde7bf810e3a Mon Sep 17 00:00:00 2001 From: Yunhao Tian Date: Tue, 30 Nov 2021 17:12:56 +0800 Subject: [PATCH 04/22] Add support for Allwinner F1Cx00s family Allwinner F1Cx00s family is a series of SoCs with Mentor MUSB controller and HS phy. It comes with a slightly different register space layout, and some quirks, so it's not multiplexed with the existing musb support library. This library currently requires to be compiled with https://github.com/hongxuyao/F1C100s_with_Keil_RTX4_emWin5 --- src/device/dcd_attr.h | 4 + src/portable/sunxi/dcd_sunxi_musb.c | 1152 +++++++++++++++++++++++++++ src/portable/sunxi/musb_def.h | 615 ++++++++++++++ src/tusb_option.h | 3 + 4 files changed, 1774 insertions(+) create mode 100644 src/portable/sunxi/dcd_sunxi_musb.c create mode 100644 src/portable/sunxi/musb_def.h diff --git a/src/device/dcd_attr.h b/src/device/dcd_attr.h index 73d592e5..0ea46ebe 100644 --- a/src/device/dcd_attr.h +++ b/src/device/dcd_attr.h @@ -195,6 +195,10 @@ #elif TU_CHECK_MCU(OPT_MCU_XMC4000) #define DCD_ATTR_ENDPOINT_MAX 8 +//------------ Allwinner -------------// +#elif TU_CHECK_MCU(OPT_MCU_F1C100S) + #define DCD_ATTR_ENDPOINT_MAX 4 + #else #warning "DCD_ATTR_ENDPOINT_MAX is not defined for this MCU, default to 8" #define DCD_ATTR_ENDPOINT_MAX 8 diff --git a/src/portable/sunxi/dcd_sunxi_musb.c b/src/portable/sunxi/dcd_sunxi_musb.c new file mode 100644 index 00000000..bb39d389 --- /dev/null +++ b/src/portable/sunxi/dcd_sunxi_musb.c @@ -0,0 +1,1152 @@ +#include +#include +#include + +#include +#include +#include "musb_def.h" + +typedef uint32_t u32; +typedef uint16_t u16; +typedef uint8_t u8; + +#if !TU_CHECK_MCU(OPT_MCU_F1C100S) + #error "Only f1c100s is supported" +#endif + +#define REQUEST_TYPE_INVALID (0xFFu) + +typedef struct { + uint_fast16_t beg; /* offset of including first element */ + uint_fast16_t end; /* offset of excluding the last element */ +} free_block_t; + +typedef struct TU_ATTR_PACKED +{ + void *buf; /* the start address of a transfer data buffer */ + uint16_t length; /* the number of bytes in the buffer */ + uint16_t remaining; /* the number of bytes remaining in the buffer */ +} pipe_state_t; + +typedef struct +{ + tusb_control_request_t setup_packet; + uint16_t remaining_ctrl; /* The number of bytes remaining in data stage of control transfer. */ + int8_t status_out; + pipe_state_t pipe0; + pipe_state_t pipe[2][7]; /* pipe[direction][endpoint number - 1] */ + uint16_t pipe_buf_is_fifo[2]; /* Bitmap. Each bit means whether 1:TU_FIFO or 0:POD. */ +} dcd_data_t; + +/*------------------------------------------------------------------ + * SUNXI FUNCTION + *------------------------------------------------------------------*/ + +static void usb_phy_write(int addr, int data, int len) +{ + int j = 0, usbc_bit = 0; + void *dest = (void *)USBC_REG_CSR(USBC0_BASE); + + usbc_bit = 1 << (0 * 2); + for (j = 0; j < len; j++) + { + /* set the bit address to be written */ + USBC_ClrBit_Mask_l(dest, 0xff << 8); + USBC_SetBit_Mask_l(dest, (addr + j) << 8); + + USBC_ClrBit_Mask_l(dest, usbc_bit); + /* set data bit */ + if (data & 0x1) + USBC_SetBit_Mask_l(dest, 1 << 7); + else + USBC_ClrBit_Mask_l(dest, 1 << 7); + + USBC_SetBit_Mask_l(dest, usbc_bit); + + USBC_ClrBit_Mask_l(dest, usbc_bit); + + data >>= 1; + } +} + +static void USBC_HardwareReset(void) +{ + // Reset phy and controller + USBC_REG_set_bit_l(USBPHY_CLK_RST_BIT, USBPHY_CLK_REG); + USBC_REG_set_bit_l(BUS_RST_USB_BIT, BUS_CLK_RST_REG); + osal_task_delay(2); + + USBC_REG_set_bit_l(USBPHY_CLK_GAT_BIT, USBPHY_CLK_REG); + USBC_REG_set_bit_l(USBPHY_CLK_RST_BIT, USBPHY_CLK_REG); + + USBC_REG_set_bit_l(BUS_CLK_USB_BIT, BUS_CLK_GATE0_REG); + USBC_REG_set_bit_l(BUS_RST_USB_BIT, BUS_CLK_RST_REG); +} + +static void USBC_PhyConfig() +{ + /* Regulation 45 ohms */ + usb_phy_write(0x0c, 0x01, 1); + + /* adjust PHY's magnitude and rate */ + usb_phy_write(0x20, 0x14, 5); + + /* threshold adjustment disconnect */ + usb_phy_write(0x2a, 3, 2); + + return; +} + +static void USBC_ConfigFIFO_Base() +{ + u32 reg_value; + + /* config usb fifo, 8kb mode */ + reg_value = USBC_Readl(SUNXI_SRAMC_BASE + 0x04); + reg_value &= ~(0x03 << 0); + reg_value |= (1 << 0); + USBC_Writel(reg_value, SUNXI_SRAMC_BASE + 0x04); +} + +static unsigned int USBC_WakeUp_ClearChangeDetect(unsigned int reg_val) +{ + unsigned int temp = reg_val; + /* vbus, id, dpdm, these bit is set 1 to clear, so we clear these bit when operate other bits */ + temp &= ~(1 << USBC_BP_ISCR_VBUS_CHANGE_DETECT); + temp &= ~(1 << USBC_BP_ISCR_ID_CHANGE_DETECT); + temp &= ~(1 << USBC_BP_ISCR_DPDM_CHANGE_DETECT); + + return temp; +} + +static void USBC_EnableDpDmPullUp(void) +{ + u32 reg_val = USBC_Readl(USBC_REG_ISCR(USBC0_BASE)); + reg_val |= (1 << USBC_BP_ISCR_DPDM_PULLUP_EN); + reg_val |= 3<beg) || (cur->end <= addr)); ++cur) ; + return cur; +} + +static inline int update_free_block_list(free_block_t *blks, unsigned num, uint_fast16_t addr, uint_fast16_t size) +{ + free_block_t *p = find_containing_block(blks, blks + num, addr); + TU_ASSERT(p != blks + num, -2); + if (p->beg == addr) { + /* Shrink block */ + p->beg = addr + size; + if (p->beg != p->end) return 0; + /* remove block */ + free_block_t *end = blks + num; + while (p + 1 < end) { + *p = *(p + 1); + ++p; + } + return -1; + } else { + /* Split into 2 blocks */ + free_block_t tmp = { + .beg = addr + size, + .end = p->end + }; + p->end = addr; + if (p->beg == p->end) { + if (tmp.beg != tmp.end) { + *p = tmp; + return 0; + } + /* remove block */ + free_block_t *end = blks + num; + while (p + 1 < end) { + *p = *(p + 1); + ++p; + } + return -1; + } + if (tmp.beg == tmp.end) return 0; + blks[num] = tmp; + return 1; + } +} + +static inline unsigned free_block_size(free_block_t const *blk) +{ + return blk->end - blk->beg; +} + +#if 0 +static inline void print_block_list(free_block_t const *blk, unsigned num) +{ + TU_LOG1("*************\n"); + for (unsigned i = 0; i < num; ++i) { + TU_LOG1(" Blk%u %u %u\n", i, blk->beg, blk->end); + ++blk; + } +} +#else +#define print_block_list(a,b) +#endif + +static unsigned find_free_memory(uint_fast16_t size_in_log2_minus3) +{ + free_block_t free_blocks[2 * (DCD_ATTR_ENDPOINT_MAX - 1)]; + unsigned num_blocks = 1; + + /* Initialize free memory block list */ + free_blocks[0].beg = 64 / 8; + free_blocks[0].end = (4 << 10) / 8; /* 4KiB / 8 bytes */ + for (int i = 1; i < DCD_ATTR_ENDPOINT_MAX; ++i) { + uint_fast16_t addr; + int num; + USBC_SelectActiveEp(i); + addr = USBC_Readw(USBC_REG_TXFIFOAD(USBC0_BASE)); + if (addr) { + unsigned sz = USBC_Readb(USBC_REG_TXFIFOSZ(USBC0_BASE)); + unsigned sft = (sz & USB_TXFIFOSZ_SIZE_M) + ((sz & USB_TXFIFOSZ_DPB) ? 1: 0); + num = update_free_block_list(free_blocks, num_blocks, addr, 1 << sft); + TU_ASSERT(-2 < num, 0); + num_blocks += num; + print_block_list(free_blocks, num_blocks); + } + addr = USBC_Readw(USBC_REG_RXFIFOAD(USBC0_BASE)); + if (addr) { + unsigned sz = USBC_Readb(USBC_REG_RXFIFOSZ(USBC0_BASE)); + unsigned sft = (sz & USB_RXFIFOSZ_SIZE_M) + ((sz & USB_RXFIFOSZ_DPB) ? 1: 0); + num = update_free_block_list(free_blocks, num_blocks, addr, 1 << sft); + TU_ASSERT(-2 < num, 0); + num_blocks += num; + print_block_list(free_blocks, num_blocks); + } + } + print_block_list(free_blocks, num_blocks); + + /* Find the best fit memory block */ + uint_fast16_t size_in_8byte_unit = 1 << size_in_log2_minus3; + free_block_t const *min = NULL; + uint_fast16_t min_sz = 0xFFFFu; + free_block_t const *end = &free_blocks[num_blocks]; + for (free_block_t const *cur = &free_blocks[0]; cur < end; ++cur) { + uint_fast16_t sz = free_block_size(cur); + if (sz < size_in_8byte_unit) continue; + if (size_in_8byte_unit == sz) return cur->beg; + if (sz < min_sz) min = cur; + } + TU_ASSERT(min, 0); + return min->beg; +} + +static void pipe_write_packet(void *buff, volatile void *fifo, unsigned cnt) +{ + u32 len = 0; + u32 i32 = 0; + u32 i8 = 0; + u8 *buf8 = 0; + u32 *buf32 = 0; + + //--<1>-- adjust data + buf32 = buff; + len = cnt; + + i32 = len >> 2; + i8 = len & 0x03; + + //--<2>-- deal with 4byte part + while (i32--) { + USBC_Writel(*buf32++, fifo); + } + + //--<3>-- deal with no 4byte part + buf8 = (u8 *)buf32; + while (i8--) { + USBC_Writeb(*buf8++, fifo); + } +} + +static void pipe_read_packet(void *buff, volatile void *fifo, unsigned cnt) +{ + u32 len = 0; + u32 i32 = 0; + u32 i8 = 0; + u8 *buf8 = 0; + u32 *buf32 = 0; + + //--<1>-- adjust data + buf32 = buff; + len = cnt; + + i32 = len >> 2; + i8 = len & 0x03; + + //--<2>-- deal with 4byte part + while (i32--) { + *buf32++ = USBC_Readl(fifo); + } + + //--<3>-- deal with no 4byte part + buf8 = (u8 *)buf32; + while (i8--) { + *buf8++ = USBC_Readb(fifo); + } +} + +static void pipe_read_write_packet_ff(tu_fifo_t *f, volatile void *fifo, unsigned len, unsigned dir) +{ + static const struct { + void (*tu_fifo_get_info)(tu_fifo_t *f, tu_fifo_buffer_info_t *info); + void (*tu_fifo_advance)(tu_fifo_t *f, uint16_t n); + void (*pipe_read_write)(void *buf, volatile void *fifo, unsigned len); + } ops[] = { + /* OUT */ {tu_fifo_get_write_info,tu_fifo_advance_write_pointer,pipe_read_packet}, + /* IN */ {tu_fifo_get_read_info, tu_fifo_advance_read_pointer, pipe_write_packet}, + }; + tu_fifo_buffer_info_t info; + ops[dir].tu_fifo_get_info(f, &info); + unsigned total_len = len; + len = TU_MIN(total_len, info.len_lin); + ops[dir].pipe_read_write(info.ptr_lin, fifo, len); + unsigned rem = total_len - len; + if (rem) { + len = TU_MIN(rem, info.len_wrap); + ops[dir].pipe_read_write(info.ptr_wrap, fifo, len); + rem -= len; + } + ops[dir].tu_fifo_advance(f, total_len - rem); +} + +/*------------------------------------------------------------------ + * TRANSFER FUNCTION DECLARATION + *------------------------------------------------------------------*/ + +static void process_setup_packet(uint8_t rhport) +{ + uint32_t *p = (void*)&_dcd.setup_packet; + p[0] = USBC_Readl(USBC_REG_EPFIFO0(USBC0_BASE)); + p[1] = USBC_Readl(USBC_REG_EPFIFO0(USBC0_BASE)); + + _dcd.pipe0.buf = NULL; + _dcd.pipe0.length = 0; + _dcd.pipe0.remaining = 0; + dcd_event_setup_received(rhport, (const uint8_t*)(uintptr_t)&_dcd.setup_packet, true); + + const unsigned len = _dcd.setup_packet.wLength; + _dcd.remaining_ctrl = len; + const unsigned dir_in = tu_edpt_dir(_dcd.setup_packet.bmRequestType); + /* Clear RX FIFO and reverse the transaction direction */ + if (len && dir_in) __USBC_Dev_ep0_ReadDataHalf(); +} + +static bool handle_xfer_in(uint_fast8_t ep_addr) +{ + unsigned epnum_minus1 = tu_edpt_number(ep_addr) - 1; + pipe_state_t *pipe = &_dcd.pipe[tu_edpt_dir(ep_addr)][epnum_minus1]; + const unsigned rem = pipe->remaining; + + if (!rem) { + pipe->buf = NULL; + return true; + } + + const unsigned mps = USBC_Readw(USBC_REG_TXMAXP(USBC0_BASE)); + const unsigned len = TU_MIN(mps, rem); + uint8_t *buf = pipe->buf; + // TU_LOG1(" %p mps %d len %d rem %d\n", buf, mps, len, rem); + if (len) { + volatile void* addr = (volatile void*)(USBC_REG_EPFIFO1(USBC0_BASE) + (epnum_minus1 << 2)); + if (_dcd.pipe_buf_is_fifo[TUSB_DIR_IN] & TU_BIT(epnum_minus1)) { + pipe_read_write_packet_ff((tu_fifo_t *)buf, addr, len, TUSB_DIR_IN); + } else { + pipe_write_packet(buf, addr, len); + pipe->buf = buf + len; + } + pipe->remaining = rem - len; + } + __USBC_Dev_Tx_WriteDataComplete(); + // TU_LOG1(" TXCSRL%d = %x %d\n", epnum_minus1 + 1, regs->TXCSRL, rem - len); + return false; +} + +static bool handle_xfer_out(uint_fast8_t ep_addr) +{ + unsigned epnum_minus1 = tu_edpt_number(ep_addr) - 1; + pipe_state_t *pipe = &_dcd.pipe[tu_edpt_dir(ep_addr)][epnum_minus1]; + // TU_LOG1(" RXCSRL%d = %x\n", epnum_minus1 + 1, regs->RXCSRL); + + TU_ASSERT(__USBC_Dev_Rx_IsReadDataReady()); + + const unsigned mps = USBC_Readw(USBC_REG_RXMAXP(USBC0_BASE)); + const unsigned rem = pipe->remaining; + const unsigned vld = USBC_Readw(USBC_REG_RXCOUNT(USBC0_BASE)); + const unsigned len = TU_MIN(TU_MIN(rem, mps), vld); + uint8_t *buf = pipe->buf; + if (len) { + volatile void* addr = (volatile void*)(USBC_REG_EPFIFO1(USBC0_BASE) + (epnum_minus1 << 2)); + if (_dcd.pipe_buf_is_fifo[TUSB_DIR_OUT] & TU_BIT(epnum_minus1)) { + pipe_read_write_packet_ff((tu_fifo_t *)buf, addr, len, TUSB_DIR_OUT); + } else { + pipe_read_packet(buf, addr, len); + pipe->buf = buf + len; + } + pipe->remaining = rem - len; + __USBC_Dev_ep0_ReadDataComplete(); + } + if ((len < mps) || (rem == len)) { + pipe->buf = NULL; + return NULL != buf; + } + return false; +} + +static bool edpt_n_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) +{ + (void)rhport; + + unsigned epnum_minus1 = tu_edpt_number(ep_addr) - 1; + unsigned dir_in = tu_edpt_dir(ep_addr); + + pipe_state_t *pipe = &_dcd.pipe[dir_in][epnum_minus1]; + pipe->buf = buffer; + pipe->length = total_bytes; + pipe->remaining = total_bytes; + + USBC_SelectActiveEp(tu_edpt_number(ep_addr)); + + if (dir_in) { + handle_xfer_in(ep_addr); + } else { + if (__USBC_Dev_Rx_IsReadDataReady()) + __USBC_Dev_Rx_ReadDataComplete(); + } + return true; +} + +static bool edpt0_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) +{ + (void)rhport; + TU_ASSERT(total_bytes <= 64); /* Current implementation supports for only up to 64 bytes. */ + + const unsigned req = _dcd.setup_packet.bmRequestType; + TU_ASSERT(req != REQUEST_TYPE_INVALID || total_bytes == 0); + + USBC_SelectActiveEp(0); + + if (req == REQUEST_TYPE_INVALID || _dcd.status_out) { + /* STATUS OUT stage. + * MUSB controller automatically handles STATUS OUT packets without + * software helps. We do not have to do anything. And STATUS stage + * may have already finished and received the next setup packet + * without calling this function, so we have no choice but to + * invoke the callback function of status packet here. */ + // TU_LOG1(" STATUS OUT CSRL0 = %x\n", CSRL0); + _dcd.status_out = 0; + if (req == REQUEST_TYPE_INVALID) { + dcd_event_xfer_complete(rhport, ep_addr, total_bytes, XFER_RESULT_SUCCESS, false); + } else { + /* The next setup packet has already been received, it aborts + * invoking callback function to avoid confusing TUSB stack. */ + TU_LOG1("Drop CONTROL_STAGE_ACK\n"); + } + return true; + } + const unsigned dir_in = tu_edpt_dir(ep_addr); + if (tu_edpt_dir(req) == dir_in) { /* DATA stage */ + TU_ASSERT(total_bytes <= _dcd.remaining_ctrl); + const unsigned rem = _dcd.remaining_ctrl; + const unsigned len = TU_MIN(TU_MIN(rem, 64), total_bytes); + if (dir_in) { + pipe_write_packet(buffer, (volatile void*) USBC_REG_EPFIFO0(USBC0_BASE), len); + + _dcd.pipe0.buf = buffer + len; + _dcd.pipe0.length = len; + _dcd.pipe0.remaining = 0; + + _dcd.remaining_ctrl = rem - len; + if ((len < 64) || (rem == len)) { + _dcd.setup_packet.bmRequestType = REQUEST_TYPE_INVALID; /* Change to STATUS/SETUP stage */ + _dcd.status_out = 1; + /* Flush TX FIFO and reverse the transaction direction. */ + __USBC_Dev_ep0_WriteDataComplete(); + } else { + __USBC_Dev_ep0_WriteDataHalf(); + } + // TU_LOG1(" IN CSRL0 = %x\n", CSRL0); + } else { + // TU_LOG1(" OUT CSRL0 = %x\n", CSRL0); + _dcd.pipe0.buf = buffer; + _dcd.pipe0.length = len; + _dcd.pipe0.remaining = len; + __USBC_Dev_ep0_ReadDataHalf(); + } + } else if (dir_in) { + // TU_LOG1(" STATUS IN CSRL0 = %x\n", CSRL0); + _dcd.pipe0.buf = NULL; + _dcd.pipe0.length = 0; + _dcd.pipe0.remaining = 0; + /* Clear RX FIFO and reverse the transaction direction */ + __USBC_Dev_ep0_ReadDataComplete(); + } + return true; +} + +static void process_ep0(uint8_t rhport) +{ + USBC_SelectActiveEp(0); + uint_fast8_t csrl = USBC_Readw(USBC_REG_CSR0(USBC0_BASE)); + + // TU_LOG1(" EP0 CSRL0 = %x\n", csrl); + + if (csrl & USB_CSRL0_STALLED) { + /* Returned STALL packet to HOST. */ + __USBC_Dev_ep0_ClearStall(); + return; + } + + unsigned req = _dcd.setup_packet.bmRequestType; + if (csrl & USB_CSRL0_SETEND) { + // TU_LOG1(" ABORT by the next packets\n"); + USBC_Dev_Ctrl_ClearSetupEnd(); + if (req != REQUEST_TYPE_INVALID && _dcd.pipe0.buf) { + /* DATA stage was aborted by receiving STATUS or SETUP packet. */ + _dcd.pipe0.buf = NULL; + _dcd.setup_packet.bmRequestType = REQUEST_TYPE_INVALID; + dcd_event_xfer_complete(rhport, + req & TUSB_DIR_IN_MASK, + _dcd.pipe0.length - _dcd.pipe0.remaining, + XFER_RESULT_SUCCESS, true); + } + req = REQUEST_TYPE_INVALID; + if (!(csrl & USB_CSRL0_RXRDY)) return; /* Received SETUP packet */ + } + + if (csrl & USB_CSRL0_RXRDY) { + /* Received SETUP or DATA OUT packet */ + if (req == REQUEST_TYPE_INVALID) { + /* SETUP */ + TU_ASSERT(sizeof(tusb_control_request_t) == USBC_Readw(USBC_REG_COUNT0(USBC0_BASE)),); + process_setup_packet(rhport); + return; + } + if (_dcd.pipe0.buf) { + /* DATA OUT */ + const unsigned vld = USBC_Readw(USBC_REG_COUNT0(USBC0_BASE)); + const unsigned rem = _dcd.pipe0.remaining; + const unsigned len = TU_MIN(TU_MIN(rem, 64), vld); + pipe_read_packet(_dcd.pipe0.buf, (volatile void*)USBC_REG_EPFIFO0(USBC0_BASE), len); + + _dcd.pipe0.remaining = rem - len; + _dcd.remaining_ctrl -= len; + + _dcd.pipe0.buf = NULL; + dcd_event_xfer_complete(rhport, + tu_edpt_addr(0, TUSB_DIR_OUT), + _dcd.pipe0.length - _dcd.pipe0.remaining, + XFER_RESULT_SUCCESS, true); + } + return; + } + + /* When CSRL0 is zero, it means that completion of sending a any length packet + * or receiving a zero length packet. */ + if (req != REQUEST_TYPE_INVALID && !tu_edpt_dir(req)) { + /* STATUS IN */ + if (*(const uint16_t*)(uintptr_t)&_dcd.setup_packet == 0x0500) { + /* The address must be changed on completion of the control transfer. */ + USBC_Dev_SetAddress((uint8_t)_dcd.setup_packet.wValue); + } + _dcd.setup_packet.bmRequestType = REQUEST_TYPE_INVALID; + dcd_event_xfer_complete(rhport, + tu_edpt_addr(0, TUSB_DIR_IN), + _dcd.pipe0.length - _dcd.pipe0.remaining, + XFER_RESULT_SUCCESS, true); + return; + } + if (_dcd.pipe0.buf) { + /* DATA IN */ + _dcd.pipe0.buf = NULL; + dcd_event_xfer_complete(rhport, + tu_edpt_addr(0, TUSB_DIR_IN), + _dcd.pipe0.length - _dcd.pipe0.remaining, + XFER_RESULT_SUCCESS, true); + } +} + +static void process_edpt_n(uint8_t rhport, uint_fast8_t ep_addr) +{ + bool completed; + const unsigned dir_in = tu_edpt_dir(ep_addr); + const unsigned epn = tu_edpt_number(ep_addr); + + USBC_SelectActiveEp(epn); + + if (dir_in) { + // TU_LOG1(" TXCSRL%d = %x\n", epn_minus1 + 1, regs->TXCSRL); + if (__USBC_Dev_Tx_IsEpStall()) { + __USBC_Dev_Tx_ClearStall(); + return; + } + completed = handle_xfer_in(ep_addr); + } else { + // TU_LOG1(" RXCSRL%d = %x\n", epn_minus1 + 1, regs->RXCSRL); + if (__USBC_Dev_Rx_IsEpStall()) { + __USBC_Dev_Rx_ClearStall(); + return; + } + completed = handle_xfer_out(ep_addr); + } + + if (completed) { + pipe_state_t *pipe = &_dcd.pipe[dir_in][tu_edpt_number(ep_addr) - 1]; + dcd_event_xfer_complete(rhport, ep_addr, + pipe->length - pipe->remaining, + XFER_RESULT_SUCCESS, true); + } +} + +static void process_bus_reset(uint8_t rhport) +{ + /* When bmRequestType is REQUEST_TYPE_INVALID(0xFF), + * a control transfer state is SETUP or STATUS stage. */ + _dcd.setup_packet.bmRequestType = REQUEST_TYPE_INVALID; + _dcd.status_out = 0; + /* When pipe0.buf has not NULL, DATA stage works in progress. */ + _dcd.pipe0.buf = NULL; + + USBC_Writew(1, USBC_REG_INTTxE(USBC0_BASE)); /* Enable only EP0 */ + USBC_Writew(0, USBC_REG_INTRxE(USBC0_BASE)); + + dcd_event_bus_reset(rhport, USBC_Dev_QueryTransferMode(), true); +} + +/*------------------------------------------------------------------ + * Device API + *------------------------------------------------------------------*/ + +static void usb_isr_handler() { + dcd_int_handler(0); +} + +void dcd_init(uint8_t rhport) +{ + dcd_disconnect(rhport); + USBC_HardwareReset(); + USBC_PhyConfig(); + USBC_ConfigFIFO_Base(); + USBC_EnableDpDmPullUp(); + USBC_ForceIdToHigh(); // Force device mode + USBC_ForceVbusValidToHigh(); + USBC_SelectBus(USBC_IO_TYPE_PIO, 0, 0); + + #if TUD_OPT_HIGH_SPEED + USBC_REG_set_bit_b(USBC_BP_POWER_D_HIGH_SPEED_EN, USBC_REG_PCTL(USBC0_BASE)); + #else + USBC_REG_clear_bit_b(USBC_BP_POWER_D_HIGH_SPEED_EN, USBC_REG_PCTL(USBC0_BASE)); + #endif + + USBC_Writeb((1 << USBC_BP_INTUSBE_EN_SUSPEND) + | (1 << USBC_BP_INTUSBE_EN_RESUME) + | (1 << USBC_BP_INTUSBE_EN_RESET) + | (1 << USBC_BP_INTUSBE_EN_SOF) + | (1 << USBC_BP_INTUSBE_EN_DISCONNECT) + , USBC_REG_INTUSBE(USBC0_BASE)); + f1c100s_intc_clear_pend(F1C100S_IRQ_USBOTG); + f1c100s_intc_set_isr(F1C100S_IRQ_USBOTG, usb_isr_handler); + + dcd_connect(rhport); +} + +// Connect by enabling internal pull-up resistor on D+/D- +void dcd_connect(uint8_t rhport) +{ + (void)rhport; + USBC_REG_set_bit_b(USBC_BP_POWER_D_SOFT_CONNECT, USBC_REG_PCTL(USBC0_BASE)); +} + +// Disconnect by disabling internal pull-up resistor on D+/D- +void dcd_disconnect(uint8_t rhport) +{ + (void)rhport; + USBC_REG_clear_bit_b(USBC_BP_POWER_D_SOFT_CONNECT, USBC_REG_PCTL(USBC0_BASE)); +} + +void dcd_int_enable(uint8_t rhport) +{ + (void)rhport; + f1c100s_intc_enable_irq(F1C100S_IRQ_USBOTG); +} + +static void musb_int_mask() +{ + f1c100s_intc_mask_irq(F1C100S_IRQ_USBOTG); +} + +void dcd_int_disable(uint8_t rhport) +{ + (void)rhport; + f1c100s_intc_disable_irq(F1C100S_IRQ_USBOTG); +} + +static void musb_int_unmask() +{ + f1c100s_intc_unmask_irq(F1C100S_IRQ_USBOTG); +} + +// Receive Set Address request, mcu port must also include status IN response +void dcd_set_address(uint8_t rhport, uint8_t dev_addr) +{ + (void)rhport; + (void)dev_addr; + _dcd.pipe0.buf = NULL; + _dcd.pipe0.length = 0; + _dcd.pipe0.remaining = 0; + /* Clear RX FIFO to return ACK. */ + USBC_SelectActiveEp(0); + __USBC_Dev_ep0_ReadDataComplete(); +} + +// Wake up host +void dcd_remote_wakeup(uint8_t rhport) +{ + (void)rhport; + USBC_REG_set_bit_b(USBC_BP_POWER_D_RESUME, USBC_REG_PCTL(USBC0_BASE)); + osal_task_delay(10); + USBC_REG_clear_bit_b(USBC_BP_POWER_D_RESUME, USBC_REG_PCTL(USBC0_BASE)); +} + +//--------------------------------------------------------------------+ +// Endpoint API +//--------------------------------------------------------------------+ + +// Configure endpoint's registers according to descriptor +bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) +{ + (void) rhport; + + uint16_t reg_val; + + const unsigned ep_addr = ep_desc->bEndpointAddress; + const unsigned epn = tu_edpt_number(ep_addr); + const unsigned dir_in = tu_edpt_dir(ep_addr); + const unsigned xfer = ep_desc->bmAttributes.xfer; + const unsigned mps = tu_edpt_packet_size(ep_desc); + + TU_ASSERT(epn < DCD_ATTR_ENDPOINT_MAX); + + pipe_state_t *pipe = &_dcd.pipe[dir_in][epn - 1]; + pipe->buf = NULL; + pipe->length = 0; + pipe->remaining = 0; + + musb_int_mask(); + + // volatile hw_endpoint_t *regs = edpt_regs(epn - 1); + USBC_SelectActiveEp(epn); + if (dir_in) { + USBC_Writew(mps, USBC_REG_TXMAXP(USBC0_BASE)); + + reg_val = (1 << USBC_BP_TXCSR_D_MODE) + | (1 << USBC_BP_TXCSR_D_FLUSH_FIFO) + | (1 << USBC_BP_TXCSR_D_CLEAR_DATA_TOGGLE); + if (xfer == TUSB_XFER_ISOCHRONOUS) + reg_val |= (1 << USBC_BP_TXCSR_D_ISO); + USBC_Writew(reg_val, USBC_REG_TXCSR(USBC0_BASE)); + + USBC_INT_EnableTxEp(epn); + } else { + USBC_Writew(mps, USBC_REG_RXMAXP(USBC0_BASE)); + + reg_val = (1 << USBC_BP_RXCSR_D_FLUSH_FIFO) + | (1 << USBC_BP_RXCSR_D_CLEAR_DATA_TOGGLE); + if (xfer == TUSB_XFER_ISOCHRONOUS) + reg_val |= (1 << USBC_BP_RXCSR_D_ISO); + USBC_Writew(reg_val, USBC_REG_RXCSR(USBC0_BASE)); + + USBC_INT_EnableRxEp(epn); + } + + /* Setup FIFO */ + int size_in_log2_minus3 = 28 - TU_MIN(28, __clz((uint32_t)mps)); + if ((8u << size_in_log2_minus3) < mps) ++size_in_log2_minus3; + unsigned addr = find_free_memory(size_in_log2_minus3); + TU_ASSERT(addr); + + if (dir_in) { + USBC_Writew(addr, USBC_REG_TXFIFOAD(USBC0_BASE)); + USBC_Writeb(size_in_log2_minus3, USBC_REG_TXFIFOSZ(USBC0_BASE)); + } else { + USBC_Writew(addr, USBC_REG_RXFIFOAD(USBC0_BASE)); + USBC_Writeb(size_in_log2_minus3, USBC_REG_RXFIFOSZ(USBC0_BASE)); + } + + musb_int_unmask(); + + return true; +} + +void dcd_edpt_close_all(uint8_t rhport) +{ + (void) rhport; + musb_int_mask(); + USBC_Writew(1, USBC_REG_INTTxE(USBC0_BASE)); /* Enable only EP0 */ + USBC_Writew(0, USBC_REG_INTRxE(USBC0_BASE)); + for (unsigned i = 1; i < DCD_ATTR_ENDPOINT_MAX; ++i) { + USBC_SelectActiveEp(i); + USBC_Writew(0, USBC_REG_TXMAXP(USBC0_BASE)); + USBC_Writew((1 << USBC_BP_TXCSR_D_MODE) | (1 << USBC_BP_TXCSR_D_CLEAR_DATA_TOGGLE) | (1 << USBC_BP_TXCSR_D_FLUSH_FIFO), + USBC_REG_TXCSR(USBC0_BASE)); + + USBC_Writew(0, USBC_REG_RXMAXP(USBC0_BASE)); + USBC_Writew((1 << USBC_BP_RXCSR_D_CLEAR_DATA_TOGGLE) | (1 << USBC_BP_RXCSR_D_FLUSH_FIFO), + USBC_REG_RXCSR(USBC0_BASE)); + + USBC_Writew(0, USBC_REG_TXFIFOAD(USBC0_BASE)); + USBC_Writeb(0, USBC_REG_TXFIFOSZ(USBC0_BASE)); + USBC_Writew(0, USBC_REG_RXFIFOAD(USBC0_BASE)); + USBC_Writeb(0, USBC_REG_RXFIFOSZ(USBC0_BASE)); + } + musb_int_unmask(); +} + +void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) +{ + (void)rhport; + unsigned const epn = tu_edpt_number(ep_addr); + unsigned const dir_in = tu_edpt_dir(ep_addr); + + musb_int_mask(); + USBC_SelectActiveEp(epn); + if (dir_in) { + USBC_INT_DisableTxEp(epn); + USBC_Writew(0, USBC_REG_TXMAXP(USBC0_BASE)); + USBC_Writew((1 << USBC_BP_TXCSR_D_MODE) | (1 << USBC_BP_TXCSR_D_CLEAR_DATA_TOGGLE) | (1 << USBC_BP_TXCSR_D_FLUSH_FIFO), + USBC_REG_TXCSR(USBC0_BASE)); + + USBC_Writew(0, USBC_REG_TXFIFOAD(USBC0_BASE)); + USBC_Writeb(0, USBC_REG_TXFIFOSZ(USBC0_BASE)); + } else { + USBC_INT_DisableRxEp(epn); + USBC_Writew(0, USBC_REG_RXMAXP(USBC0_BASE)); + USBC_Writew((1 << USBC_BP_RXCSR_D_CLEAR_DATA_TOGGLE) | (1 << USBC_BP_RXCSR_D_FLUSH_FIFO), + USBC_REG_RXCSR(USBC0_BASE)); + + USBC_Writew(0, USBC_REG_RXFIFOAD(USBC0_BASE)); + USBC_Writeb(0, USBC_REG_RXFIFOSZ(USBC0_BASE)); + } + musb_int_unmask(); +} + +// Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) +{ + (void)rhport; + bool ret; + // TU_LOG1("X %x %d\n", ep_addr, total_bytes); + unsigned const epnum = tu_edpt_number(ep_addr); + musb_int_mask(); + + if (epnum) { + _dcd.pipe_buf_is_fifo[tu_edpt_dir(ep_addr)] &= ~TU_BIT(epnum - 1); + ret = edpt_n_xfer(rhport, ep_addr, buffer, total_bytes); + } else { + ret = edpt0_xfer(rhport, ep_addr, buffer, total_bytes); + } + musb_int_unmask(); + return ret; +} + +// Submit a transfer where is managed by FIFO, When complete dcd_event_xfer_complete() is invoked to notify the stack - optional, however, must be listed in usbd.c +bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) +{ + (void)rhport; + bool ret; + // TU_LOG1("X %x %d\n", ep_addr, total_bytes); + unsigned const epnum = tu_edpt_number(ep_addr); + TU_ASSERT(epnum); + + musb_int_mask(); + _dcd.pipe_buf_is_fifo[tu_edpt_dir(ep_addr)] |= TU_BIT(epnum - 1); + ret = edpt_n_xfer(rhport, ep_addr, (uint8_t*)ff, total_bytes); + musb_int_unmask(); + + return ret; +} + +// Stall endpoint +void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) +{ + (void)rhport; + unsigned const epn = tu_edpt_number(ep_addr); + musb_int_mask(); + USBC_SelectActiveEp(epn); + if (0 == epn) { + if (!ep_addr) { /* Ignore EP80 */ + _dcd.setup_packet.bmRequestType = REQUEST_TYPE_INVALID; + _dcd.pipe0.buf = NULL; + __USBC_Dev_ep0_SendStall(); + } + } else { + if (tu_edpt_dir(ep_addr)) { /* IN */ + __USBC_Dev_Tx_SendStall(); + } else { /* OUT */ + TU_ASSERT(!__USBC_Dev_Rx_IsReadDataReady(),); + __USBC_Dev_Rx_SendStall(); + } + } + musb_int_unmask(); +} + +// clear stall, data toggle is also reset to DATA0 +void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) +{ + (void)rhport; + unsigned const epn = tu_edpt_number(ep_addr); + musb_int_mask(); + USBC_SelectActiveEp(epn); + if (0 != epn) { + if (tu_edpt_dir(ep_addr)) { /* IN */ + __USBC_Dev_Tx_ClearStall(); + } else { /* OUT */ + __USBC_Dev_Rx_ClearStall(); + } + } + musb_int_unmask(); +} + + +void dcd_int_handler(uint8_t rhport) +{ + uint8_t is; + uint16_t txis, rxis; + + is = USBC_Readb(USBC_REG_INTUSB(USBC0_BASE)); /* read interrupt status */ + txis = USBC_Readw(USBC_REG_INTTx(USBC0_BASE)); /* read interrupt status */ + rxis = USBC_Readw(USBC_REG_INTRx(USBC0_BASE)); /* read interrupt status */ + + is &= USBC_Readb(USBC_REG_INTUSBE(USBC0_BASE)); /* ignore disabled interrupts */ + USBC_Writeb(is, USBC_REG_INTUSB(USBC0_BASE)); /* sunxi musb requires a write to interrupt register to clear */ + if (is & USBC_INTUSB_DISCONNECT) { + dcd_event_bus_signal(rhport, DCD_EVENT_UNPLUGGED, true); + } + if (is & USBC_INTUSB_SOF) { + dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true); + } + if (is & USBC_INTUSB_RESET) { + /* ep0 FADDR must be 0 when (re)entering peripheral mode */ + USBC_SelectActiveEp(0); + USBC_Dev_SetAddress(0); + process_bus_reset(rhport); + } + if (is & USBC_INTUSB_RESUME) { + dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true); + } + if (is & USBC_INTUSB_SUSPEND) { + dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true); + } + + txis &= USBC_Readw(USBC_REG_INTTxE(USBC0_BASE)); + USBC_Writew(txis, USBC_REG_INTTx(USBC0_BASE)); + if (txis & USBC_INTTx_FLAG_EP0) { + process_ep0(rhport); + txis &= ~TU_BIT(0); + } + while (txis) { + unsigned const num = __builtin_ctz(txis); + process_edpt_n(rhport, tu_edpt_addr(num, TUSB_DIR_IN)); + txis &= ~TU_BIT(num); + } + + rxis &= USBC_Readw(USBC_REG_INTRxE(USBC0_BASE)); + USBC_Writew(rxis, USBC_REG_INTRx(USBC0_BASE)); + while (rxis) { + unsigned const num = __builtin_ctz(rxis); + process_edpt_n(rhport, tu_edpt_addr(num, TUSB_DIR_OUT)); + rxis &= ~TU_BIT(num); + } +} + diff --git a/src/portable/sunxi/musb_def.h b/src/portable/sunxi/musb_def.h new file mode 100644 index 00000000..f55ddab3 --- /dev/null +++ b/src/portable/sunxi/musb_def.h @@ -0,0 +1,615 @@ +#ifndef _TUSB_MUSB_DEF +#define _TUSB_MUSB_DEF + + +#define USBC_Readb(reg) (*(volatile unsigned char *)(reg)) +#define USBC_Readw(reg) (*(volatile unsigned short *)(reg)) +#define USBC_Readl(reg) (*(volatile unsigned long *)(reg)) + +#define USBC_Writeb(value, reg) (*(volatile unsigned char *)(reg) = (value)) +#define USBC_Writew(value, reg) (*(volatile unsigned short *)(reg) = (value)) +#define USBC_Writel(value, reg) (*(volatile unsigned long *)(reg) = (value)) + + +#define USBC_SetBit_Mask_b(reg,mask) do { \ + unsigned char _r = USBC_Readb(reg); \ + _r |= (unsigned char)(mask); \ + USBC_Writeb(_r,reg); \ + }while(0) +#define USBC_SetBit_Mask_w(reg,mask) do { \ + unsigned short _r = USBC_Readw(reg); \ + _r |= (unsigned short)(mask); \ + USBC_Writew(_r,reg); \ + }while(0) +#define USBC_SetBit_Mask_l(reg,mask) do { \ + unsigned int _r = USBC_Readl(reg); \ + _r |= (unsigned int)(mask); \ + USBC_Writel(_r,reg); \ + }while(0) + + +#define USBC_ClrBit_Mask_b(reg,mask) do { \ + unsigned char _r = USBC_Readb(reg); \ + _r &= (~(unsigned char)(mask)); \ + USBC_Writeb(_r,reg); \ + }while(0); +#define USBC_ClrBit_Mask_w(reg,mask) do { \ + unsigned short _r = USBC_Readw(reg); \ + _r &= (~(unsigned short)(mask)); \ + USBC_Writew(_r,reg); \ + }while(0) +#define USBC_ClrBit_Mask_l(reg,mask) do { \ + unsigned int _r = USBC_Readl(reg); \ + _r &= (~(unsigned int)(mask)); \ + USBC_Writel(_r,reg); \ + }while(0) +#define USBC_REG_test_bit_b(bp, reg) (USBC_Readb(reg) & (1 << (bp))) +#define USBC_REG_test_bit_w(bp, reg) (USBC_Readw(reg) & (1 << (bp))) +#define USBC_REG_test_bit_l(bp, reg) (USBC_Readl(reg) & (1 << (bp))) + +#define USBC_REG_set_bit_b(bp, reg) (USBC_Writeb((USBC_Readb(reg) | (1 << (bp))) , (reg))) +#define USBC_REG_set_bit_w(bp, reg) (USBC_Writew((USBC_Readw(reg) | (1 << (bp))) , (reg))) +#define USBC_REG_set_bit_l(bp, reg) (USBC_Writel((USBC_Readl(reg) | (1 << (bp))) , (reg))) + +#define USBC_REG_clear_bit_b(bp, reg) (USBC_Writeb((USBC_Readb(reg) & (~ (1 << (bp)))) , (reg))) +#define USBC_REG_clear_bit_w(bp, reg) (USBC_Writew((USBC_Readw(reg) & (~ (1 << (bp)))) , (reg))) +#define USBC_REG_clear_bit_l(bp, reg) (USBC_Writel((USBC_Readl(reg) & (~ (1 << (bp)))) , (reg))) + +#define SW_UDC_EPNUMS 3 + +#define SUNXI_SRAMC_BASE 0x01c00000 +//--------------------------------------------------------------- +// reg base +//--------------------------------------------------------------- +#define USBC0_BASE 0x01c13000 +#define USBC1_BASE 0x01c14000 +#define USBC2_BASE 0x01c1E000 + +//Some reg whithin musb +#define USBPHY_CLK_REG 0x01c200CC +#define USBPHY_CLK_RST_BIT 0 +#define USBPHY_CLK_GAT_BIT 1 + +#define BUS_CLK_RST_REG 0x01c202c0 //Bus Clock Reset Register Bit24 : USB CLK RST +#define BUS_RST_USB_BIT 24 + +#define BUS_CLK_GATE0_REG 0x01c20060 //Bus Clock Gating Register Bit24 : USB CLK GATE 0: Mask 1 : Pass +#define BUS_CLK_USB_BIT 24 + +//#define USB_INTR + +#define NDMA_CFG_REG +//----------------------------------------------------------------------- +// musb reg offset +//----------------------------------------------------------------------- + +#define USBC_REG_o_FADDR 0x0098 +#define USBC_REG_o_PCTL 0x0040 +#define USBC_REG_o_INTTx 0x0044 +#define USBC_REG_o_INTRx 0x0046 +#define USBC_REG_o_INTTxE 0x0048 +#define USBC_REG_o_INTRxE 0x004A +#define USBC_REG_o_INTUSB 0x004C +#define USBC_REG_o_INTUSBE 0x0050 +#define USBC_REG_o_FRNUM 0x0054 +#define USBC_REG_o_EPIND 0x0042 +#define USBC_REG_o_TMCTL 0x007C + +#define USBC_REG_o_TXMAXP 0x0080 +#define USBC_REG_o_CSR0 0x0082 +#define USBC_REG_o_TXCSR 0x0082 +#define USBC_REG_o_RXMAXP 0x0084 +#define USBC_REG_o_RXCSR 0x0086 +#define USBC_REG_o_COUNT0 0x0088 +#define USBC_REG_o_RXCOUNT 0x0088 +#define USBC_REG_o_EP0TYPE 0x008C +#define USBC_REG_o_TXTYPE 0x008C +#define USBC_REG_o_NAKLIMIT0 0x008D +#define USBC_REG_o_TXINTERVAL 0x008D +#define USBC_REG_o_RXTYPE 0x008E +#define USBC_REG_o_RXINTERVAL 0x008F + +//#define USBC_REG_o_CONFIGDATA 0x001F // + +#define USBC_REG_o_EPFIFO0 0x0000 +#define USBC_REG_o_EPFIFO1 0x0004 +#define USBC_REG_o_EPFIFO2 0x0008 +#define USBC_REG_o_EPFIFO3 0x000C +#define USBC_REG_o_EPFIFO4 0x0010 +#define USBC_REG_o_EPFIFO5 0x0014 +#define USBC_REG_o_EPFIFOx(n) (0x0000 + (n<<2)) + +#define USBC_REG_o_DEVCTL 0x0041 + +#define USBC_REG_o_TXFIFOSZ 0x0090 +#define USBC_REG_o_RXFIFOSZ 0x0094 +#define USBC_REG_o_TXFIFOAD 0x0092 +#define USBC_REG_o_RXFIFOAD 0x0096 + +#define USBC_REG_o_VEND0 0x0043 +#define USBC_REG_o_VEND1 0x007D +#define USBC_REG_o_VEND3 0x007E + +//#define USBC_REG_o_PHYCTL 0x006C +#define USBC_REG_o_EPINFO 0x0078 +#define USBC_REG_o_RAMINFO 0x0079 +#define USBC_REG_o_LINKINFO 0x007A +#define USBC_REG_o_VPLEN 0x007B +#define USBC_REG_o_HSEOF 0x007C +#define USBC_REG_o_FSEOF 0x007D +#define USBC_REG_o_LSEOF 0x007E + +//new +#define USBC_REG_o_FADDR0 0x0098 +#define USBC_REG_o_HADDR0 0x009A +#define USBC_REG_o_HPORT0 0x009B +#define USBC_REG_o_TXFADDRx 0x0098 +#define USBC_REG_o_TXHADDRx 0x009A +#define USBC_REG_o_TXHPORTx 0x009B +#define USBC_REG_o_RXFADDRx 0x009C +#define USBC_REG_o_RXHADDRx 0x009E +#define USBC_REG_o_RXHPORTx 0x009F + + +#define USBC_REG_o_RPCOUNT 0x008A + +//new +#define USBC_REG_o_ISCR 0x0400 +#define USBC_REG_o_PHYCTL 0x0404 +#define USBC_REG_o_PHYBIST 0x0408 +#define USBC_REG_o_PHYTUNE 0x040c + +#define USBC_REG_o_CSR 0x0410 + +#define USBC_REG_o_PMU_IRQ 0x0800 + +//----------------------------------------------------------------------- +// registers +//----------------------------------------------------------------------- + +#define USBC_REG_FADDR(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_FADDR ) +#define USBC_REG_PCTL(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_PCTL ) +#define USBC_REG_INTTx(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_INTTx ) +#define USBC_REG_INTRx(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_INTRx ) +#define USBC_REG_INTTxE(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_INTTxE ) +#define USBC_REG_INTRxE(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_INTRxE ) +#define USBC_REG_INTUSB(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_INTUSB ) +#define USBC_REG_INTUSBE(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_INTUSBE ) +#define USBC_REG_FRNUM(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_FRNUM ) +#define USBC_REG_EPIND(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_EPIND ) +#define USBC_REG_TMCTL(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_TMCTL ) +#define USBC_REG_TXMAXP(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_TXMAXP ) + +#define USBC_REG_CSR0(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_CSR0 ) +#define USBC_REG_TXCSR(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_TXCSR ) + +#define USBC_REG_RXMAXP(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_RXMAXP ) +#define USBC_REG_RXCSR(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_RXCSR ) + +#define USBC_REG_COUNT0(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_COUNT0 ) +#define USBC_REG_RXCOUNT(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_RXCOUNT ) + +#define USBC_REG_EP0TYPE(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_EP0TYPE ) +#define USBC_REG_TXTYPE(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_TXTYPE ) + +#define USBC_REG_NAKLIMIT0(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_NAKLIMIT0 ) +#define USBC_REG_TXINTERVAL(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_TXINTERVAL ) + +#define USBC_REG_RXTYPE(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_RXTYPE ) +#define USBC_REG_RXINTERVAL(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_RXINTERVAL ) +//#define USBC_REG_CONFIGDATA(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_CONFIGDATA ) +#define USBC_REG_EPFIFO0(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_EPFIFO0 ) +#define USBC_REG_EPFIFO1(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_EPFIFO1 ) +#define USBC_REG_EPFIFO2(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_EPFIFO2 ) +#define USBC_REG_EPFIFO3(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_EPFIFO3 ) +#define USBC_REG_EPFIFO4(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_EPFIFO4 ) +#define USBC_REG_EPFIFO5(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_EPFIFO5 ) +#define USBC_REG_EPFIFOx(usbc_base_addr, n) ((usbc_base_addr) + USBC_REG_o_EPFIFOx(n) ) +#define USBC_REG_DEVCTL(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_DEVCTL ) +#define USBC_REG_TXFIFOSZ(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_TXFIFOSZ ) +#define USBC_REG_RXFIFOSZ(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_RXFIFOSZ ) +#define USBC_REG_TXFIFOAD(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_TXFIFOAD ) +#define USBC_REG_RXFIFOAD(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_RXFIFOAD ) +#define USBC_REG_VEND0(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_VEND0 ) +#define USBC_REG_VEND1(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_VEND1 ) +#define USBC_REG_EPINFO(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_EPINFO ) +#define USBC_REG_RAMINFO(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_RAMINFO ) +#define USBC_REG_LINKINFO(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_LINKINFO ) +#define USBC_REG_VPLEN(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_VPLEN ) +#define USBC_REG_HSEOF(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_HSEOF ) +#define USBC_REG_FSEOF(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_FSEOF ) +#define USBC_REG_LSEOF(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_LSEOF ) + +#define USBC_REG_FADDR0(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_FADDR0 ) +#define USBC_REG_HADDR0(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_HADDR0 ) +#define USBC_REG_HPORT0(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_HPORT0 ) + +#define USBC_REG_TXFADDRx(usbc_base_addr, n) ((usbc_base_addr) + USBC_REG_o_TXFADDRx ) +#define USBC_REG_TXHADDRx(usbc_base_addr, n) ((usbc_base_addr) + USBC_REG_o_TXHADDRx ) +#define USBC_REG_TXHPORTx(usbc_base_addr, n) ((usbc_base_addr) + USBC_REG_o_TXHPORTx ) +#define USBC_REG_RXFADDRx(usbc_base_addr, n) ((usbc_base_addr) + USBC_REG_o_RXFADDRx ) +#define USBC_REG_RXHADDRx(usbc_base_addr, n) ((usbc_base_addr) + USBC_REG_o_RXHADDRx ) +#define USBC_REG_RXHPORTx(usbc_base_addr, n) ((usbc_base_addr) + USBC_REG_o_RXHPORTx ) + +#define USBC_REG_RPCOUNTx(usbc_base_addr, n) ((usbc_base_addr) + USBC_REG_o_RPCOUNT ) + +#define USBC_REG_ISCR(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_ISCR ) +#define USBC_REG_PHYCTL(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_PHYCTL ) +#define USBC_REG_PHYBIST(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_PHYBIST ) +#define USBC_REG_PHYTUNE(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_PHYTUNE ) +#define USBC_REG_PMU_IRQ(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_PMU_IRQ ) +#define USBC_REG_CSR(usbc_base_addr) ((usbc_base_addr) + USBC_REG_o_CSR) +//----------------------------------------------------------------------- +// bit position +//----------------------------------------------------------------------- + +/* USB Power Control for Host only */ +#define USBC_BP_POWER_H_HIGH_SPEED_EN 5 +#define USBC_BP_POWER_H_HIGH_SPEED_FLAG 4 +#define USBC_BP_POWER_H_RESET 3 +#define USBC_BP_POWER_H_RESUME 2 +#define USBC_BP_POWER_H_SUSPEND 1 +#define USBC_BP_POWER_H_SUEPEND_EN 0 + +/* USB Power Control for device only */ +#define USBC_BP_POWER_D_ISO_UPDATE_EN 7 +#define USBC_BP_POWER_D_SOFT_CONNECT 6 +#define USBC_BP_POWER_D_HIGH_SPEED_EN 5 +#define USBC_BP_POWER_D_HIGH_SPEED_FLAG 4 +#define USBC_BP_POWER_D_RESET_FLAG 3 +#define USBC_BP_POWER_D_RESUME 2 +#define USBC_BP_POWER_D_SUSPEND 1 +#define USBC_BP_POWER_D_ENABLE_SUSPENDM 0 + +/* interrupt flags for ep0 and the Tx ep1~4 */ +#define USBC_BP_INTTx_FLAG_EP5 5 +#define USBC_BP_INTTx_FLAG_EP4 4 +#define USBC_BP_INTTx_FLAG_EP3 3 +#define USBC_BP_INTTx_FLAG_EP2 2 +#define USBC_BP_INTTx_FLAG_EP1 1 +#define USBC_BP_INTTx_FLAG_EP0 0 + +/* interrupt flags for Rx ep1~4 */ +#define USBC_BP_INTRx_FLAG_EP5 5 +#define USBC_BP_INTRx_FLAG_EP4 4 +#define USBC_BP_INTRx_FLAG_EP3 3 +#define USBC_BP_INTRx_FLAG_EP2 2 +#define USBC_BP_INTRx_FLAG_EP1 1 + +/* interrupt enable for Tx ep0~4 */ +#define USBC_BP_INTTxE_EN_EP5 5 +#define USBC_BP_INTTxE_EN_EP4 4 +#define USBC_BP_INTTxE_EN_EP3 3 +#define USBC_BP_INTTxE_EN_EP2 2 +#define USBC_BP_INTTxE_EN_EP1 1 +#define USBC_BP_INTTxE_EN_EP0 0 + +/* interrupt enable for Rx ep1~4 */ +#define USBC_BP_INTRxE_EN_EP5 5 +#define USBC_BP_INTRxE_EN_EP4 4 +#define USBC_BP_INTRxE_EN_EP3 3 +#define USBC_BP_INTRxE_EN_EP2 2 +#define USBC_BP_INTRxE_EN_EP1 1 + +/* USB interrupt */ +#define USBC_BP_INTUSB_VBUS_ERROR 7 +#define USBC_BP_INTUSB_SESSION_REQ 6 +#define USBC_BP_INTUSB_DISCONNECT 5 +#define USBC_BP_INTUSB_CONNECT 4 +#define USBC_BP_INTUSB_SOF 3 +#define USBC_BP_INTUSB_RESET 2 +#define USBC_BP_INTUSB_RESUME 1 +#define USBC_BP_INTUSB_SUSPEND 0 + +/* USB interrupt enable */ +#define USBC_BP_INTUSBE_EN_VBUS_ERROR 7 +#define USBC_BP_INTUSBE_EN_SESSION_REQ 6 +#define USBC_BP_INTUSBE_EN_DISCONNECT 5 +#define USBC_BP_INTUSBE_EN_CONNECT 4 +#define USBC_BP_INTUSBE_EN_SOF 3 +#define USBC_BP_INTUSBE_EN_RESET 2 +#define USBC_BP_INTUSBE_EN_RESUME 1 +#define USBC_BP_INTUSBE_EN_SUSPEND 0 + +/* Test Mode Control */ +#define USBC_BP_TMCTL_FORCE_HOST 7 +#define USBC_BP_TMCTL_FIFO_ACCESS 6 +#define USBC_BP_TMCTL_FORCE_FS 5 +#define USBC_BP_TMCTL_FORCE_HS 4 +#define USBC_BP_TMCTL_TEST_PACKET 3 +#define USBC_BP_TMCTL_TEST_K 2 +#define USBC_BP_TMCTL_TEST_J 1 +#define USBC_BP_TMCTL_TEST_SE0_NAK 0 + +/* Tx Max packet */ +#define USBC_BP_TXMAXP_PACKET_COUNT 11 +#define USBC_BP_TXMAXP_MAXIMUM_PAYLOAD 0 + +/* Control and Status Register for ep0 for Host only */ +#define USBC_BP_CSR0_H_DisPing 11 +#define USBC_BP_CSR0_H_FlushFIFO 8 +#define USBC_BP_CSR0_H_NAK_Timeout 7 +#define USBC_BP_CSR0_H_StatusPkt 6 +#define USBC_BP_CSR0_H_ReqPkt 5 +#define USBC_BP_CSR0_H_Error 4 +#define USBC_BP_CSR0_H_SetupPkt 3 +#define USBC_BP_CSR0_H_RxStall 2 +#define USBC_BP_CSR0_H_TxPkRdy 1 +#define USBC_BP_CSR0_H_RxPkRdy 0 + +/* Control and Status Register for ep0 for device only */ +#define USBC_BP_CSR0_D_FLUSH_FIFO 8 +#define USBC_BP_CSR0_D_SERVICED_SETUP_END 7 +#define USBC_BP_CSR0_D_SERVICED_RX_PKT_READY 6 +#define USBC_BP_CSR0_D_SEND_STALL 5 +#define USBC_BP_CSR0_D_SETUP_END 4 +#define USBC_BP_CSR0_D_DATA_END 3 +#define USBC_BP_CSR0_D_SENT_STALL 2 +#define USBC_BP_CSR0_D_TX_PKT_READY 1 +#define USBC_BP_CSR0_D_RX_PKT_READY 0 + +/* Tx ep Control and Status Register for Host only */ +#define USBC_BP_TXCSR_H_AUTOSET 15 +#define USBC_BP_TXCSR_H_RESERVED 14 +#define USBC_BP_TXCSR_H_MODE 13 +#define USBC_BP_TXCSR_H_DMA_REQ_EN 12 +#define USBC_BP_TXCSR_H_FORCE_DATA_TOGGLE 11 +#define USBC_BP_TXCSR_H_DMA_REQ_MODE 10 +#define USBC_BP_TXCSR_H_NAK_TIMEOUT 7 +#define USBC_BP_TXCSR_H_CLEAR_DATA_TOGGLE 6 +#define USBC_BP_TXCSR_H_TX_STALL 5 +#define USBC_BP_TXCSR_H_FLUSH_FIFO 3 +#define USBC_BP_TXCSR_H_ERROR 2 +#define USBC_BP_TXCSR_H_FIFO_NOT_EMPTY 1 +#define USBC_BP_TXCSR_H_TX_READY 0 + +/* Tx ep Control and Status Register for Device only */ +#define USBC_BP_TXCSR_D_AUTOSET 15 +#define USBC_BP_TXCSR_D_ISO 14 +#define USBC_BP_TXCSR_D_MODE 13 +#define USBC_BP_TXCSR_D_DMA_REQ_EN 12 +#define USBC_BP_TXCSR_D_FORCE_DATA_TOGGLE 11 +#define USBC_BP_TXCSR_D_DMA_REQ_MODE 10 +#define USBC_BP_TXCSR_D_INCOMPLETE 7 +#define USBC_BP_TXCSR_D_CLEAR_DATA_TOGGLE 6 +#define USBC_BP_TXCSR_D_SENT_STALL 5 +#define USBC_BP_TXCSR_D_SEND_STALL 4 +#define USBC_BP_TXCSR_D_FLUSH_FIFO 3 +#define USBC_BP_TXCSR_D_UNDER_RUN 2 +#define USBC_BP_TXCSR_D_FIFO_NOT_EMPTY 1 +#define USBC_BP_TXCSR_D_TX_READY 0 + +/* Rx Max Packet */ +#define USBC_BP_RXMAXP_PACKET_COUNT 11 +#define USBC_BP_RXMAXP_MAXIMUM_PAYLOAD 0 + +/* Rx ep Control and Status Register for Host only */ +#define USBC_BP_RXCSR_H_AUTO_CLEAR 15 +#define USBC_BP_RXCSR_H_AUTO_REQ 14 +#define USBC_BP_RXCSR_H_DMA_REQ_EN 13 +#define USBC_BP_RXCSR_H_PID_ERROR 12 +#define USBC_BP_RXCSR_H_DMA_REQ_MODE 11 + +#define USBC_BP_RXCSR_H_INCOMPLETE 8 +#define USBC_BP_RXCSR_H_CLEAR_DATA_TOGGLE 7 +#define USBC_BP_RXCSR_H_RX_STALL 6 +#define USBC_BP_RXCSR_H_REQ_PACKET 5 +#define USBC_BP_RXCSR_H_FLUSH_FIFO 4 +#define USBC_BP_RXCSR_H_NAK_TIMEOUT 3 +#define USBC_BP_RXCSR_H_ERROR 2 +#define USBC_BP_RXCSR_H_FIFO_FULL 1 +#define USBC_BP_RXCSR_H_RX_PKT_READY 0 + +/* Rx ep Control and Status Register for Device only */ +#define USBC_BP_RXCSR_D_AUTO_CLEAR 15 +#define USBC_BP_RXCSR_D_ISO 14 +#define USBC_BP_RXCSR_D_DMA_REQ_EN 13 +#define USBC_BP_RXCSR_D_DISABLE_NYET 12 +#define USBC_BP_RXCSR_D_DMA_REQ_MODE 11 + +#define USBC_BP_RXCSR_D_INCOMPLETE 8 +#define USBC_BP_RXCSR_D_CLEAR_DATA_TOGGLE 7 +#define USBC_BP_RXCSR_D_SENT_STALL 6 +#define USBC_BP_RXCSR_D_SEND_STALL 5 +#define USBC_BP_RXCSR_D_FLUSH_FIFO 4 +#define USBC_BP_RXCSR_D_DATA_ERROR 3 +#define USBC_BP_RXCSR_D_OVERRUN 2 +#define USBC_BP_RXCSR_D_FIFO_FULL 1 +#define USBC_BP_RXCSR_D_RX_PKT_READY 0 + +/* Tx Type Register for host only */ +#define USBC_BP_TXTYPE_SPEED 6 //new +#define USBC_BP_TXTYPE_PROROCOL 4 +#define USBC_BP_TXTYPE_TARGET_EP_NUM 0 + +/* Rx Type Register for host only */ +#define USBC_BP_RXTYPE_SPEED 6 //new +#define USBC_BP_RXTYPE_PROROCOL 4 +#define USBC_BP_RXTYPE_TARGET_EP_NUM 0 + +/* Core Configueation */ +#define USBC_BP_CONFIGDATA_MPRXE 7 +#define USBC_BP_CONFIGDATA_MPTXE 6 +#define USBC_BP_CONFIGDATA_BIGENDIAN 5 +#define USBC_BP_CONFIGDATA_HBRXE 4 +#define USBC_BP_CONFIGDATA_HBTXE 3 +#define USBC_BP_CONFIGDATA_DYNFIFO_SIZING 2 +#define USBC_BP_CONFIGDATA_SOFTCONE 1 +#define USBC_BP_CONFIGDATA_UTMI_DATAWIDTH 0 + +/* OTG Device Control */ +#define USBC_BP_DEVCTL_B_DEVICE 7 +#define USBC_BP_DEVCTL_FS_DEV 6 +#define USBC_BP_DEVCTL_LS_DEV 5 + +#define USBC_BP_DEVCTL_VBUS 3 +#define USBC_BP_DEVCTL_HOST_MODE 2 +#define USBC_BP_DEVCTL_HOST_REQ 1 +#define USBC_BP_DEVCTL_SESSION 0 + +/* Tx EP FIFO size control */ +#define USBC_BP_TXFIFOSZ_DPB 4 +#define USBC_BP_TXFIFOSZ_SZ 0 + +/* Rx EP FIFO size control */ +#define USBC_BP_RXFIFOSZ_DPB 4 +#define USBC_BP_RXFIFOSZ_SZ 0 + +/* vendor0 */ +#define USBC_BP_VEND0_DRQ_SEL 1 +#define USBC_BP_VEND0_BUS_SEL 0 + +/* hub address */ +#define USBC_BP_HADDR_MULTI_TT 7 + +/* Interface Status and Control */ +#define USBC_BP_ISCR_VBUS_VALID_FROM_DATA 30 +#define USBC_BP_ISCR_VBUS_VALID_FROM_VBUS 29 +#define USBC_BP_ISCR_EXT_ID_STATUS 28 +#define USBC_BP_ISCR_EXT_DM_STATUS 27 +#define USBC_BP_ISCR_EXT_DP_STATUS 26 +#define USBC_BP_ISCR_MERGED_VBUS_STATUS 25 +#define USBC_BP_ISCR_MERGED_ID_STATUS 24 + +#define USBC_BP_ISCR_ID_PULLUP_EN 17 +#define USBC_BP_ISCR_DPDM_PULLUP_EN 16 +#define USBC_BP_ISCR_FORCE_ID 14 +#define USBC_BP_ISCR_FORCE_VBUS_VALID 12 +#define USBC_BP_ISCR_VBUS_VALID_SRC 10 + +#define USBC_BP_ISCR_HOSC_EN 7 +#define USBC_BP_ISCR_VBUS_CHANGE_DETECT 6 +#define USBC_BP_ISCR_ID_CHANGE_DETECT 5 +#define USBC_BP_ISCR_DPDM_CHANGE_DETECT 4 +#define USBC_BP_ISCR_IRQ_ENABLE 3 +#define USBC_BP_ISCR_VBUS_CHANGE_DETECT_EN 2 +#define USBC_BP_ISCR_ID_CHANGE_DETECT_EN 1 +#define USBC_BP_ISCR_DPDM_CHANGE_DETECT_EN 0 + + +#define SUNXI_EHCI_AHB_ICHR8_EN (1 << 10) +#define SUNXI_EHCI_AHB_INCR4_BURST_EN (1 << 9) +#define SUNXI_EHCI_AHB_INCRX_ALIGN_EN (1 << 8) +#define SUNXI_EHCI_ULPI_BYPASS_EN (1 << 0) +//----------------------------------------------------------------------- +// �Զ��� +//----------------------------------------------------------------------- + +/* usb��Դ���� */ +#define USBC_MAX_CTL_NUM 1 +#define USBC_MAX_EP_NUM 3 //ep0~2, ep�ĸ��� +#define USBC_MAX_FIFO_SIZE (2 * 1024) + +/* usb OTG mode */ +#define USBC_OTG_HOST 0 +#define USBC_OTG_DEVICE 1 + +/* usb device type */ +#define USBC_DEVICE_HSDEV 0 +#define USBC_DEVICE_FSDEV 1 +#define USBC_DEVICE_LSDEV 2 + +/* usb transfer type */ +#define USBC_TS_TYPE_IDLE 0 +#define USBC_TS_TYPE_CTRL 1 +#define USBC_TS_TYPE_ISO 2 +#define USBC_TS_TYPE_INT 3 +#define USBC_TS_TYPE_BULK 4 + +/* usb transfer mode */ +#define USBC_TS_MODE_UNKOWN 0 +#define USBC_TS_MODE_LS 1 +#define USBC_TS_MODE_FS 2 +#define USBC_TS_MODE_HS 3 + +/* usb Vbus status */ +#define USBC_VBUS_STATUS_BELOW_SESSIONEND 0 +#define USBC_VBUS_STATUS_ABOVE_SESSIONEND_BELOW_AVALID 1 +#define USBC_VBUS_STATUS_ABOVE_AVALID_BELOW_VBUSVALID 2 +#define USBC_VBUS_STATUS_ABOVE_VBUSVALID 3 + +/* usb io type */ +#define USBC_IO_TYPE_PIO 0 +#define USBC_IO_TYPE_DMA 1 + +/* usb ep type */ +#define USBC_EP_TYPE_IDLE 0 +#define USBC_EP_TYPE_EP0 1 +#define USBC_EP_TYPE_TX 2 +#define USBC_EP_TYPE_RX 3 + +/* usb id type */ +#define USBC_ID_TYPE_DISABLE 0 +#define USBC_ID_TYPE_HOST 1 +#define USBC_ID_TYPE_DEVICE 2 + +/* usb vbus valid type */ +#define USBC_VBUS_TYPE_DISABLE 0 +#define USBC_VBUS_TYPE_LOW 1 +#define USBC_VBUS_TYPE_HIGH 2 + +/* usb a valid source */ +#define USBC_A_VALID_SOURCE_UTMI_AVALID 0 +#define USBC_A_VALID_SOURCE_UTMI_VBUS 1 + +/* usb device switch */ +#define USBC_DEVICE_SWITCH_OFF 0 +#define USBC_DEVICE_SWITCH_ON 1 + +/* usb fifo config mode */ +#define USBC_FIFO_MODE_4K 0 +#define USBC_FIFO_MODE_8K 1 + +/* + ************************************************** + * usb interrupt mask + * + ************************************************** + */ + +/* interrupt flags for ep0 and the Tx ep1~4 */ +#define USBC_INTTx_FLAG_EP5 (1 << USBC_BP_INTTx_FLAG_EP5) +#define USBC_INTTx_FLAG_EP4 (1 << USBC_BP_INTTx_FLAG_EP4) +#define USBC_INTTx_FLAG_EP3 (1 << USBC_BP_INTTx_FLAG_EP3) +#define USBC_INTTx_FLAG_EP2 (1 << USBC_BP_INTTx_FLAG_EP2) +#define USBC_INTTx_FLAG_EP1 (1 << USBC_BP_INTTx_FLAG_EP1) +#define USBC_INTTx_FLAG_EP0 (1 << USBC_BP_INTTx_FLAG_EP0) + +/* interrupt flags for Rx ep1~4 */ +#define USBC_INTRx_FLAG_EP5 (1 << USBC_BP_INTRx_FLAG_EP5) +#define USBC_INTRx_FLAG_EP4 (1 << USBC_BP_INTRx_FLAG_EP4) +#define USBC_INTRx_FLAG_EP3 (1 << USBC_BP_INTRx_FLAG_EP3) +#define USBC_INTRx_FLAG_EP2 (1 << USBC_BP_INTRx_FLAG_EP2) +#define USBC_INTRx_FLAG_EP1 (1 << USBC_BP_INTRx_FLAG_EP1) + +/* USB interrupt */ +#define USBC_INTUSB_VBUS_ERROR (1 << USBC_BP_INTUSB_VBUS_ERROR) +#define USBC_INTUSB_SESSION_REQ (1 << USBC_BP_INTUSB_SESSION_REQ) +#define USBC_INTUSB_DISCONNECT (1 << USBC_BP_INTUSB_DISCONNECT) +#define USBC_INTUSB_CONNECT (1 << USBC_BP_INTUSB_CONNECT) +#define USBC_INTUSB_SOF (1 << USBC_BP_INTUSB_SOF) +#define USBC_INTUSB_RESET (1 << USBC_BP_INTUSB_RESET) +#define USBC_INTUSB_RESUME (1 << USBC_BP_INTUSB_RESUME) +#define USBC_INTUSB_SUSPEND (1 << USBC_BP_INTUSB_SUSPEND) + +#define USB_CSRL0_NAKTO 0x00000080 // NAK Timeout +#define USB_CSRL0_SETENDC 0x00000080 // Setup End Clear +#define USB_CSRL0_STATUS 0x00000040 // STATUS Packet +#define USB_CSRL0_RXRDYC 0x00000040 // RXRDY Clear +#define USB_CSRL0_REQPKT 0x00000020 // Request Packet +#define USB_CSRL0_STALL 0x00000020 // Send Stall +#define USB_CSRL0_SETEND 0x00000010 // Setup End +#define USB_CSRL0_ERROR 0x00000010 // Error +#define USB_CSRL0_DATAEND 0x00000008 // Data End +#define USB_CSRL0_SETUP 0x00000008 // Setup Packet +#define USB_CSRL0_STALLED 0x00000004 // Endpoint Stalled +#define USB_CSRL0_TXRDY 0x00000002 // Transmit Packet Ready +#define USB_CSRL0_RXRDY 0x00000001 // Receive Packet Ready + +#define USB_RXFIFOSZ_DPB 0x00000010 // Double Packet Buffer Support +#define USB_RXFIFOSZ_SIZE_M 0x0000000F // Max Packet Size + +#define USB_TXFIFOSZ_DPB 0x00000010 // Double Packet Buffer Support +#define USB_TXFIFOSZ_SIZE_M 0x0000000F // Max Packet Size + +#endif diff --git a/src/tusb_option.h b/src/tusb_option.h index dcf1c461..dbdc83c6 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -136,6 +136,9 @@ // Infineon #define OPT_MCU_XMC4000 1800 ///< Infineon XMC4000 +// Allwinner +#define OPT_MCU_F1C100S 1900 ///< Allwinner F1C100s family + // Helper to check if configured MCU is one of listed // Apply _TU_CHECK_MCU with || as separator to list of input #define _TU_CHECK_MCU(_m) (CFG_TUSB_MCU == _m) From dff54d854ddae3ff5c8dc81bac77fd8b50564598 Mon Sep 17 00:00:00 2001 From: Yunhao Tian Date: Sat, 4 Dec 2021 17:18:39 +0800 Subject: [PATCH 05/22] Modify sunxi_musb code --- src/portable/sunxi/dcd_sunxi_musb.c | 40 +++++++++++++++++++---------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/src/portable/sunxi/dcd_sunxi_musb.c b/src/portable/sunxi/dcd_sunxi_musb.c index bb39d389..b13842de 100644 --- a/src/portable/sunxi/dcd_sunxi_musb.c +++ b/src/portable/sunxi/dcd_sunxi_musb.c @@ -1,8 +1,7 @@ #include -#include +#include "tusb_option.h" +#include "osal/osal.h" #include - -#include #include #include "musb_def.h" @@ -10,9 +9,7 @@ typedef uint32_t u32; typedef uint16_t u16; typedef uint8_t u8; -#if !TU_CHECK_MCU(OPT_MCU_F1C100S) - #error "Only f1c100s is supported" -#endif +#if TUSB_OPT_DEVICE_ENABLED && CFG_TUSB_MCU == OPT_MCU_F1C100S #define REQUEST_TYPE_INVALID (0xFFu) @@ -69,12 +66,22 @@ static void usb_phy_write(int addr, int data, int len) } } +static void delay_ms(uint32_t ms) +{ +#if CFG_TUSB_OS == OPT_OS_NONE + int cnt = ms * 1000 * 1000 / 2; + while (cnt--) asm("nop"); +#else + osal_task_delay(ms); +#endif +} + static void USBC_HardwareReset(void) { // Reset phy and controller USBC_REG_set_bit_l(USBPHY_CLK_RST_BIT, USBPHY_CLK_REG); USBC_REG_set_bit_l(BUS_RST_USB_BIT, BUS_CLK_RST_REG); - osal_task_delay(2); + delay_ms(2); USBC_REG_set_bit_l(USBPHY_CLK_GAT_BIT, USBPHY_CLK_REG); USBC_REG_set_bit_l(USBPHY_CLK_RST_BIT, USBPHY_CLK_REG); @@ -83,7 +90,7 @@ static void USBC_HardwareReset(void) USBC_REG_set_bit_l(BUS_RST_USB_BIT, BUS_CLK_RST_REG); } -static void USBC_PhyConfig() +static void USBC_PhyConfig(void) { /* Regulation 45 ohms */ usb_phy_write(0x0c, 0x01, 1); @@ -97,7 +104,7 @@ static void USBC_PhyConfig() return; } -static void USBC_ConfigFIFO_Base() +static void USBC_ConfigFIFO_Base(void) { u32 reg_value; @@ -507,7 +514,7 @@ static void pipe_read_write_packet_ff(tu_fifo_t *f, volatile void *fifo, unsigne static void process_setup_packet(uint8_t rhport) { - uint32_t *p = (void*)&_dcd.setup_packet; + uint32_t *p = (uint32_t*)&_dcd.setup_packet; p[0] = USBC_Readl(USBC_REG_EPFIFO0(USBC0_BASE)); p[1] = USBC_Readl(USBC_REG_EPFIFO0(USBC0_BASE)); @@ -808,7 +815,7 @@ static void process_bus_reset(uint8_t rhport) * Device API *------------------------------------------------------------------*/ -static void usb_isr_handler() { +static void usb_isr_handler(void) { dcd_int_handler(0); } @@ -861,7 +868,7 @@ void dcd_int_enable(uint8_t rhport) f1c100s_intc_enable_irq(F1C100S_IRQ_USBOTG); } -static void musb_int_mask() +static void musb_int_mask(void) { f1c100s_intc_mask_irq(F1C100S_IRQ_USBOTG); } @@ -872,7 +879,7 @@ void dcd_int_disable(uint8_t rhport) f1c100s_intc_disable_irq(F1C100S_IRQ_USBOTG); } -static void musb_int_unmask() +static void musb_int_unmask(void) { f1c100s_intc_unmask_irq(F1C100S_IRQ_USBOTG); } @@ -895,7 +902,7 @@ void dcd_remote_wakeup(uint8_t rhport) { (void)rhport; USBC_REG_set_bit_b(USBC_BP_POWER_D_RESUME, USBC_REG_PCTL(USBC0_BASE)); - osal_task_delay(10); + delay_ms(10); USBC_REG_clear_bit_b(USBC_BP_POWER_D_RESUME, USBC_REG_PCTL(USBC0_BASE)); } @@ -903,6 +910,10 @@ void dcd_remote_wakeup(uint8_t rhport) // Endpoint API //--------------------------------------------------------------------+ +#ifndef __ARMCC_VERSION +#define __clz __builtin_clz +#endif + // Configure endpoint's registers according to descriptor bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) { @@ -1150,3 +1161,4 @@ void dcd_int_handler(uint8_t rhport) } } +#endif From 68ca62dfd7e7fe757ba436fee7721520119da92b Mon Sep 17 00:00:00 2001 From: Yunhao Tian Date: Sat, 4 Dec 2021 18:02:07 +0800 Subject: [PATCH 06/22] Add BSP support for F1C100s --- examples/rules.mk | 5 + hw/bsp/f1c100s/README.md | 17 + hw/bsp/f1c100s/board.h | 1 + hw/bsp/f1c100s/board.mk | 45 + hw/bsp/f1c100s/f1c100s.c | 130 +++ hw/mcu/allwinner/f1c100s/f1c100s.ld | 137 +++ hw/mcu/allwinner/f1c100s/include/arm32.h | 150 ++++ .../allwinner/f1c100s/include/f1c100s-gpio.h | 66 ++ .../allwinner/f1c100s/include/f1c100s-irq.h | 104 +++ .../allwinner/f1c100s/include/f1c100s-reset.h | 39 + .../allwinner/f1c100s/include/f1c100s-util.h | 139 +++ .../f1c100s/include/f1c100s/reg-ccu.h | 55 ++ .../f1c100s/include/f1c100s/reg-dram.h | 39 + hw/mcu/allwinner/f1c100s/include/io.h | 57 ++ hw/mcu/allwinner/f1c100s/include/irqflags.h | 104 +++ hw/mcu/allwinner/f1c100s/include/malloc.h | 35 + hw/mcu/allwinner/f1c100s/include/printf.h | 99 +++ hw/mcu/allwinner/f1c100s/include/sizes.h | 42 + hw/mcu/allwinner/f1c100s/include/types.h | 55 ++ hw/mcu/allwinner/f1c100s/lib/malloc.c | 834 ++++++++++++++++++ hw/mcu/allwinner/f1c100s/lib/memcpy.S | 404 +++++++++ hw/mcu/allwinner/f1c100s/lib/memset.S | 79 ++ hw/mcu/allwinner/f1c100s/lib/printf.c | 757 ++++++++++++++++ hw/mcu/allwinner/f1c100s/machine/exception.c | 76 ++ .../allwinner/f1c100s/machine/f1c100s-intc.c | 173 ++++ hw/mcu/allwinner/f1c100s/machine/start.S | 313 +++++++ hw/mcu/allwinner/f1c100s/machine/sys-clock.c | 124 +++ .../allwinner/f1c100s/machine/sys-copyself.c | 111 +++ hw/mcu/allwinner/f1c100s/machine/sys-dram.c | 506 +++++++++++ hw/mcu/allwinner/f1c100s/machine/sys-mmu.c | 57 ++ .../allwinner/f1c100s/machine/sys-spi-flash.c | 204 +++++ hw/mcu/allwinner/f1c100s/machine/sys-uart.c | 83 ++ src/portable/sunxi/dcd_sunxi_musb.c | 5 +- 33 files changed, 5043 insertions(+), 2 deletions(-) create mode 100644 hw/bsp/f1c100s/README.md create mode 100644 hw/bsp/f1c100s/board.h create mode 100644 hw/bsp/f1c100s/board.mk create mode 100644 hw/bsp/f1c100s/f1c100s.c create mode 100644 hw/mcu/allwinner/f1c100s/f1c100s.ld create mode 100644 hw/mcu/allwinner/f1c100s/include/arm32.h create mode 100644 hw/mcu/allwinner/f1c100s/include/f1c100s-gpio.h create mode 100644 hw/mcu/allwinner/f1c100s/include/f1c100s-irq.h create mode 100644 hw/mcu/allwinner/f1c100s/include/f1c100s-reset.h create mode 100644 hw/mcu/allwinner/f1c100s/include/f1c100s-util.h create mode 100644 hw/mcu/allwinner/f1c100s/include/f1c100s/reg-ccu.h create mode 100644 hw/mcu/allwinner/f1c100s/include/f1c100s/reg-dram.h create mode 100644 hw/mcu/allwinner/f1c100s/include/io.h create mode 100644 hw/mcu/allwinner/f1c100s/include/irqflags.h create mode 100644 hw/mcu/allwinner/f1c100s/include/malloc.h create mode 100644 hw/mcu/allwinner/f1c100s/include/printf.h create mode 100644 hw/mcu/allwinner/f1c100s/include/sizes.h create mode 100644 hw/mcu/allwinner/f1c100s/include/types.h create mode 100644 hw/mcu/allwinner/f1c100s/lib/malloc.c create mode 100644 hw/mcu/allwinner/f1c100s/lib/memcpy.S create mode 100644 hw/mcu/allwinner/f1c100s/lib/memset.S create mode 100644 hw/mcu/allwinner/f1c100s/lib/printf.c create mode 100644 hw/mcu/allwinner/f1c100s/machine/exception.c create mode 100644 hw/mcu/allwinner/f1c100s/machine/f1c100s-intc.c create mode 100644 hw/mcu/allwinner/f1c100s/machine/start.S create mode 100644 hw/mcu/allwinner/f1c100s/machine/sys-clock.c create mode 100644 hw/mcu/allwinner/f1c100s/machine/sys-copyself.c create mode 100644 hw/mcu/allwinner/f1c100s/machine/sys-dram.c create mode 100644 hw/mcu/allwinner/f1c100s/machine/sys-mmu.c create mode 100644 hw/mcu/allwinner/f1c100s/machine/sys-spi-flash.c create mode 100644 hw/mcu/allwinner/f1c100s/machine/sys-uart.c diff --git a/examples/rules.mk b/examples/rules.mk index 4cc35cb2..6314380e 100644 --- a/examples/rules.mk +++ b/examples/rules.mk @@ -182,6 +182,11 @@ flash-jlink: $(BUILD)/$(PROJECT).hex flash-stlink: $(BUILD)/$(PROJECT).elf STM32_Programmer_CLI --connect port=swd --write $< --go +flash-xfel: $(BUILD)/$(PROJECT).bin + xfel ddr + xfel write 0x80000000 $< + xfel exec 0x80000000 + # Flash using pyocd PYOCD_OPTION ?= flash-pyocd: $(BUILD)/$(PROJECT).hex diff --git a/hw/bsp/f1c100s/README.md b/hw/bsp/f1c100s/README.md new file mode 100644 index 00000000..a4865b92 --- /dev/null +++ b/hw/bsp/f1c100s/README.md @@ -0,0 +1,17 @@ +# BSP support for F1Cx00s boards + +This folder contains necessary file and scripts to run TinyUSB examples on F1Cx00s boards. + +Currently tested on: + +* Lichee Pi Nano (F1C100s) + +## make flash +`make flash` will use [xfel](https://github.com/xboot/xfel) to write the code to onchip DDR memory and execute it. It will not write the program to SPI Flash. + +To enter FEL mode, you have to press BOOT button, then press RESET once, and release BOOT button. You will find VID/PID=1f3a:efe8 on your PC. + +## TODO +* Test on Tiny200 v2 (F1C200s) +* Make it able to load .bin directly to SPI Flash and boot +* Add F1C100s to `#if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX` high speed MCU check in examples (maybe we should extract the logic?) \ No newline at end of file diff --git a/hw/bsp/f1c100s/board.h b/hw/bsp/f1c100s/board.h new file mode 100644 index 00000000..238ac796 --- /dev/null +++ b/hw/bsp/f1c100s/board.h @@ -0,0 +1 @@ +// Nothing valuable here \ No newline at end of file diff --git a/hw/bsp/f1c100s/board.mk b/hw/bsp/f1c100s/board.mk new file mode 100644 index 00000000..993aa0d2 --- /dev/null +++ b/hw/bsp/f1c100s/board.mk @@ -0,0 +1,45 @@ +DEFINES += -D__ARM32_ARCH__=5 -D__ARM926EJS__ + +CFLAGS += \ + -ffreestanding \ + -std=gnu99 \ + -march=armv5te \ + -mtune=arm926ej-s \ + -mfloat-abi=soft \ + -marm \ + -mno-thumb-interwork \ + -Wno-unused-parameter \ + -Wno-float-equal \ + -DCFG_TUSB_MCU=OPT_MCU_F1C100S \ + -Wno-error=cast-align \ + -Wno-error=address-of-packed-member \ + $(DEFINES) + +LD_FILE = hw/mcu/allwinner/f1c100s/f1c100s.ld +LDFLAGS += -nostdlib -lgcc +MCU_DIR = hw/mcu/allwinner/f1c100s + +SRC_C += \ + src/portable/sunxi/dcd_sunxi_musb.c \ + $(MCU_DIR)/machine/sys-uart.c \ + $(MCU_DIR)/machine/exception.c \ + $(MCU_DIR)/machine/sys-clock.c \ + $(MCU_DIR)/machine/sys-copyself.c \ + $(MCU_DIR)/machine/sys-dram.c \ + $(MCU_DIR)/machine/sys-mmu.c \ + $(MCU_DIR)/machine/sys-spi-flash.c \ + $(MCU_DIR)/machine/f1c100s-intc.c \ + $(MCU_DIR)/lib/malloc.c \ + $(MCU_DIR)/lib/printf.c + +SRC_S += \ + $(MCU_DIR)/machine/start.S \ + $(MCU_DIR)/lib/memcpy.S \ + $(MCU_DIR)/lib/memset.S + +INC += \ + $(TOP)/$(MCU_DIR)/include \ + $(TOP)/$(BOARD_PATH) + +# flash target using on-board stlink +flash: flash-xfel diff --git a/hw/bsp/f1c100s/f1c100s.c b/hw/bsp/f1c100s/f1c100s.c new file mode 100644 index 00000000..6cf18597 --- /dev/null +++ b/hw/bsp/f1c100s/f1c100s.c @@ -0,0 +1,130 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#include +#include +#include +#include +#include "bsp/board.h" +#include "board.h" + +extern void sys_uart_putc(char c); + +//--------------------------------------------------------------------+ +// Board porting API +//--------------------------------------------------------------------+ + +static void timer_init(void); + +void board_init(void) +{ + arch_local_irq_disable(); + do_init_mem_pool(); + f1c100s_intc_init(); + timer_init(); + printf("Timer INIT done\n"); + arch_local_irq_enable(); +} + +// No LED, no button, sorry +void board_led_write(bool state) +{ + +} + +uint32_t board_button_read(void) +{ + return 0; +} + +int board_uart_read(uint8_t* buf, int len) +{ + return 0; +} + +int board_uart_write(void const * buf, int len) +{ + int txsize = len; + while (txsize--) { + sys_uart_putc(*(uint8_t const*)buf); + buf++; + } + return len; +} + +#if CFG_TUSB_OS == OPT_OS_NONE +volatile uint32_t system_ticks = 0; + +uint32_t board_millis(void) +{ + return system_ticks; +} + +static void timer_handler(void) +{ + volatile uint32_t *temp_addr = (uint32_t *)(0x01C20C00 + 0x04); + + /* clear timer */ + *temp_addr |= 0x01; + + system_ticks++; +} + +static void timer_init(void) { + uint32_t temp; + volatile uint32_t *temp_addr; + + /* reload value */ + temp = 12000000 / 1000; + temp_addr = (uint32_t *)(0x01C20C00 + 0x14); + *temp_addr = temp; + + /* continuous | /2 | 24Mhz | reload*/ + temp = (0x00 << 7) | (0x01 << 4) | (0x01 << 2) | (0x00 << 1); + temp_addr = (uint32_t *)(0x01C20C00 + 0x10); + *temp_addr &= 0xffffff00; + *temp_addr |= temp; + + /* open timer irq */ + temp = 0x01 << 0; + temp_addr = (uint32_t *)(0x01C20C00); + *temp_addr |= temp; + + /* set init value */ + temp_addr = (uint32_t *)(0x01C20C00 + 0x18); + *temp_addr = 0; + + /* begin run timer */ + temp = 0x01 << 0; + temp_addr = (uint32_t *)(0x01C20C00 + 0x10); + *temp_addr |= temp; + + f1c100s_intc_set_isr(F1C100S_IRQ_TIMER0, timer_handler); + f1c100s_intc_enable_irq(F1C100S_IRQ_TIMER0); +} +#else +static void timer_init(void) { } +#endif diff --git a/hw/mcu/allwinner/f1c100s/f1c100s.ld b/hw/mcu/allwinner/f1c100s/f1c100s.ld new file mode 100644 index 00000000..a261618e --- /dev/null +++ b/hw/mcu/allwinner/f1c100s/f1c100s.ld @@ -0,0 +1,137 @@ +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 = .); + */machine/start.o (.text) + */lib/memcpy.o (.text) + */lib/memset.o (.text) + */machine/sys-uart.o (.text) + */machine/sys-clock.o (.text) + */machine/sys-dram.o (.text) + */machine/sys-mmu.o (.text) + */machine/sys-spi-flash.o (.text) + */machine/sys-copyself.o (.text) + PROVIDE(__bootloader_end = .); + } > ram + + __bootloader_size = SIZEOF(.bootloader); + + .text : + { + */main.o (.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) } +} diff --git a/hw/mcu/allwinner/f1c100s/include/arm32.h b/hw/mcu/allwinner/f1c100s/include/arm32.h new file mode 100644 index 00000000..a3a25455 --- /dev/null +++ b/hw/mcu/allwinner/f1c100s/include/arm32.h @@ -0,0 +1,150 @@ +#ifndef __ARM32_H__ +#define __ARM32_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +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__ */ diff --git a/hw/mcu/allwinner/f1c100s/include/f1c100s-gpio.h b/hw/mcu/allwinner/f1c100s/include/f1c100s-gpio.h new file mode 100644 index 00000000..3dbe8bf1 --- /dev/null +++ b/hw/mcu/allwinner/f1c100s/include/f1c100s-gpio.h @@ -0,0 +1,66 @@ +#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__ */ diff --git a/hw/mcu/allwinner/f1c100s/include/f1c100s-irq.h b/hw/mcu/allwinner/f1c100s/include/f1c100s-irq.h new file mode 100644 index 00000000..410d1be9 --- /dev/null +++ b/hw/mcu/allwinner/f1c100s/include/f1c100s-irq.h @@ -0,0 +1,104 @@ +#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__ */ diff --git a/hw/mcu/allwinner/f1c100s/include/f1c100s-reset.h b/hw/mcu/allwinner/f1c100s/include/f1c100s-reset.h new file mode 100644 index 00000000..e787a1ac --- /dev/null +++ b/hw/mcu/allwinner/f1c100s/include/f1c100s-reset.h @@ -0,0 +1,39 @@ +#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__ */ diff --git a/hw/mcu/allwinner/f1c100s/include/f1c100s-util.h b/hw/mcu/allwinner/f1c100s/include/f1c100s-util.h new file mode 100644 index 00000000..cb3829f8 --- /dev/null +++ b/hw/mcu/allwinner/f1c100s/include/f1c100s-util.h @@ -0,0 +1,139 @@ +// Designed by Hong Xuyao + +#ifndef __TARGET_H__ +#define __TARGET_H__ +//////////////////////////////////////////////////////////////////////////////// +#include +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__ */ + diff --git a/hw/mcu/allwinner/f1c100s/include/f1c100s/reg-ccu.h b/hw/mcu/allwinner/f1c100s/include/f1c100s/reg-ccu.h new file mode 100644 index 00000000..1770ad7f --- /dev/null +++ b/hw/mcu/allwinner/f1c100s/include/f1c100s/reg-ccu.h @@ -0,0 +1,55 @@ +#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__ */ diff --git a/hw/mcu/allwinner/f1c100s/include/f1c100s/reg-dram.h b/hw/mcu/allwinner/f1c100s/include/f1c100s/reg-dram.h new file mode 100644 index 00000000..8a0ac3e0 --- /dev/null +++ b/hw/mcu/allwinner/f1c100s/include/f1c100s/reg-dram.h @@ -0,0 +1,39 @@ +#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__ */ diff --git a/hw/mcu/allwinner/f1c100s/include/io.h b/hw/mcu/allwinner/f1c100s/include/io.h new file mode 100644 index 00000000..f0dad178 --- /dev/null +++ b/hw/mcu/allwinner/f1c100s/include/io.h @@ -0,0 +1,57 @@ +#ifndef __IO_H__ +#define __IO_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +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__ */ diff --git a/hw/mcu/allwinner/f1c100s/include/irqflags.h b/hw/mcu/allwinner/f1c100s/include/irqflags.h new file mode 100644 index 00000000..e4ef97cd --- /dev/null +++ b/hw/mcu/allwinner/f1c100s/include/irqflags.h @@ -0,0 +1,104 @@ +#ifndef __ARM32_IRQFLAGS_H__ +#define __ARM32_IRQFLAGS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#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__ */ diff --git a/hw/mcu/allwinner/f1c100s/include/malloc.h b/hw/mcu/allwinner/f1c100s/include/malloc.h new file mode 100644 index 00000000..6669fe48 --- /dev/null +++ b/hw/mcu/allwinner/f1c100s/include/malloc.h @@ -0,0 +1,35 @@ +#ifndef __MALLOC_H__ +#define __MALLOC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include + +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__ */ diff --git a/hw/mcu/allwinner/f1c100s/include/printf.h b/hw/mcu/allwinner/f1c100s/include/printf.h new file mode 100644 index 00000000..632bfc20 --- /dev/null +++ b/hw/mcu/allwinner/f1c100s/include/printf.h @@ -0,0 +1,99 @@ +/////////////////////////////////////////////////////////////////////////////// +// \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 +#include + + +#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_ diff --git a/hw/mcu/allwinner/f1c100s/include/sizes.h b/hw/mcu/allwinner/f1c100s/include/sizes.h new file mode 100644 index 00000000..3edeed50 --- /dev/null +++ b/hw/mcu/allwinner/f1c100s/include/sizes.h @@ -0,0 +1,42 @@ +#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__ */ diff --git a/hw/mcu/allwinner/f1c100s/include/types.h b/hw/mcu/allwinner/f1c100s/include/types.h new file mode 100644 index 00000000..61b87b6d --- /dev/null +++ b/hw/mcu/allwinner/f1c100s/include/types.h @@ -0,0 +1,55 @@ +#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__ */ diff --git a/hw/mcu/allwinner/f1c100s/lib/malloc.c b/hw/mcu/allwinner/f1c100s/lib/malloc.c new file mode 100644 index 00000000..763746a4 --- /dev/null +++ b/hw/mcu/allwinner/f1c100s/lib/malloc.c @@ -0,0 +1,834 @@ +/* + * lib/libc/malloc/malloc.c + */ + +#include + +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 +} diff --git a/hw/mcu/allwinner/f1c100s/lib/memcpy.S b/hw/mcu/allwinner/f1c100s/lib/memcpy.S new file mode 100644 index 00000000..f7ed3130 --- /dev/null +++ b/hw/mcu/allwinner/f1c100s/lib/memcpy.S @@ -0,0 +1,404 @@ +/* + * 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 diff --git a/hw/mcu/allwinner/f1c100s/lib/memset.S b/hw/mcu/allwinner/f1c100s/lib/memset.S new file mode 100644 index 00000000..3eea2db1 --- /dev/null +++ b/hw/mcu/allwinner/f1c100s/lib/memset.S @@ -0,0 +1,79 @@ +/* + * 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 */ diff --git a/hw/mcu/allwinner/f1c100s/lib/printf.c b/hw/mcu/allwinner/f1c100s/lib/printf.c new file mode 100644 index 00000000..366bb9c0 --- /dev/null +++ b/hw/mcu/allwinner/f1c100s/lib/printf.c @@ -0,0 +1,757 @@ + +/////////////////////////////////////////////////////////////////////////////// +// \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 +#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 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; +} diff --git a/hw/mcu/allwinner/f1c100s/machine/exception.c b/hw/mcu/allwinner/f1c100s/machine/exception.c new file mode 100644 index 00000000..ffc61bf4 --- /dev/null +++ b/hw/mcu/allwinner/f1c100s/machine/exception.c @@ -0,0 +1,76 @@ +/* + * 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 +#include +#include + +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 \ No newline at end of file diff --git a/hw/mcu/allwinner/f1c100s/machine/f1c100s-intc.c b/hw/mcu/allwinner/f1c100s/machine/f1c100s-intc.c new file mode 100644 index 00000000..2993f0b6 --- /dev/null +++ b/hw/mcu/allwinner/f1c100s/machine/f1c100s-intc.c @@ -0,0 +1,173 @@ +// Originally designed by Hong Xuyao + +#include +#include +#include +#include + +#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; + } +} diff --git a/hw/mcu/allwinner/f1c100s/machine/start.S b/hw/mcu/allwinner/f1c100s/machine/start.S new file mode 100644 index 00000000..1fd7cb1f --- /dev/null +++ b/hw/mcu/allwinner/f1c100s/machine/start.S @@ -0,0 +1,313 @@ +/* + * 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 add uart */ + bl sys_clock_init + bl sys_dram_init + bl sys_uart_init + + /* Boot speed up, leave slower sram */ + adr r0, _start + ldr r1, =_start + cmp r0, r1 + beq _speedup + ldr r0, =0x81f80000 + adr r1, _start + mov r2, #0x4000 + bl memcpy + ldr r0, =_speedup + ldr r1, =_start + sub r0, r0, r1 + ldr r1, =0x81f80000 + add r0, r0, r1 + mov pc, r0 +_speedup: + nop + + /* Copyself to link address */ + adr r0, _start + ldr r1, =_start + cmp r0, r1 + beq 1f + 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 diff --git a/hw/mcu/allwinner/f1c100s/machine/sys-clock.c b/hw/mcu/allwinner/f1c100s/machine/sys-clock.c new file mode 100644 index 00000000..d151dd0c --- /dev/null +++ b/hw/mcu/allwinner/f1c100s/machine/sys-clock.c @@ -0,0 +1,124 @@ +/* + * 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 +#include +#include +#include + +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); +} diff --git a/hw/mcu/allwinner/f1c100s/machine/sys-copyself.c b/hw/mcu/allwinner/f1c100s/machine/sys-copyself.c new file mode 100644 index 00000000..4116e126 --- /dev/null +++ b/hw/mcu/allwinner/f1c100s/machine/sys-copyself.c @@ -0,0 +1,111 @@ +/* + * 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 + +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; + } +} diff --git a/hw/mcu/allwinner/f1c100s/machine/sys-dram.c b/hw/mcu/allwinner/f1c100s/machine/sys-dram.c new file mode 100644 index 00000000..a819520a --- /dev/null +++ b/hw/mcu/allwinner/f1c100s/machine/sys-dram.c @@ -0,0 +1,506 @@ +/* + * 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 +#include +#include +#include + +#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(¶)) + dsz[0] = (((uint32_t)'X') << 24) | (para.size << 0); +} diff --git a/hw/mcu/allwinner/f1c100s/machine/sys-mmu.c b/hw/mcu/allwinner/f1c100s/machine/sys-mmu.c new file mode 100644 index 00000000..3c89c725 --- /dev/null +++ b/hw/mcu/allwinner/f1c100s/machine/sys-mmu.c @@ -0,0 +1,57 @@ +/* + * 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 +#include +#include +#include + +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(); +} \ No newline at end of file diff --git a/hw/mcu/allwinner/f1c100s/machine/sys-spi-flash.c b/hw/mcu/allwinner/f1c100s/machine/sys-spi-flash.c new file mode 100644 index 00000000..5c3b0f0a --- /dev/null +++ b/hw/mcu/allwinner/f1c100s/machine/sys-spi-flash.c @@ -0,0 +1,204 @@ +/* + * 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 +#include +#include +#include + +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(); +} diff --git a/hw/mcu/allwinner/f1c100s/machine/sys-uart.c b/hw/mcu/allwinner/f1c100s/machine/sys-uart.c new file mode 100644 index 00000000..0e61627b --- /dev/null +++ b/hw/mcu/allwinner/f1c100s/machine/sys-uart.c @@ -0,0 +1,83 @@ +/* + * 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 +#include +#include + +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); +} diff --git a/src/portable/sunxi/dcd_sunxi_musb.c b/src/portable/sunxi/dcd_sunxi_musb.c index b13842de..71d0b92b 100644 --- a/src/portable/sunxi/dcd_sunxi_musb.c +++ b/src/portable/sunxi/dcd_sunxi_musb.c @@ -4,6 +4,7 @@ #include #include #include "musb_def.h" +#include "bsp/board.h" typedef uint32_t u32; typedef uint16_t u16; @@ -69,8 +70,8 @@ static void usb_phy_write(int addr, int data, int len) static void delay_ms(uint32_t ms) { #if CFG_TUSB_OS == OPT_OS_NONE - int cnt = ms * 1000 * 1000 / 2; - while (cnt--) asm("nop"); + int now = board_millis(); + while (board_millis() - now <= ms) asm("nop"); #else osal_task_delay(ms); #endif From 28fb51c180e644cfb0be4b980b71850b19fe2ab9 Mon Sep 17 00:00:00 2001 From: Yunhao Tian Date: Sat, 4 Dec 2021 18:08:23 +0800 Subject: [PATCH 07/22] Add TODO to README --- hw/bsp/f1c100s/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/bsp/f1c100s/README.md b/hw/bsp/f1c100s/README.md index a4865b92..893b32ea 100644 --- a/hw/bsp/f1c100s/README.md +++ b/hw/bsp/f1c100s/README.md @@ -14,4 +14,5 @@ To enter FEL mode, you have to press BOOT button, then press RESET once, and rel ## TODO * Test on Tiny200 v2 (F1C200s) * Make it able to load .bin directly to SPI Flash and boot -* Add F1C100s to `#if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX` high speed MCU check in examples (maybe we should extract the logic?) \ No newline at end of file +* Add F1C100s to `#if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX` high speed MCU check in examples (maybe we should extract the logic?) +* `cdc_msc` example is not working. Device is only echoing the first character. \ No newline at end of file From fa0e4d91f9e22b8c7b8f561fe225116b5f6a14a5 Mon Sep 17 00:00:00 2001 From: Yunhao Tian Date: Sun, 5 Dec 2021 18:07:35 +0800 Subject: [PATCH 08/22] Save current EP before querying other EPs --- src/portable/sunxi/dcd_sunxi_musb.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/portable/sunxi/dcd_sunxi_musb.c b/src/portable/sunxi/dcd_sunxi_musb.c index 71d0b92b..0bb031a8 100644 --- a/src/portable/sunxi/dcd_sunxi_musb.c +++ b/src/portable/sunxi/dcd_sunxi_musb.c @@ -185,6 +185,11 @@ static void USBC_SelectActiveEp(u8 ep_index) USBC_Writeb(ep_index, USBC_REG_EPIND(USBC0_BASE)); } +static u8 USBC_GetActiveEp(void) +{ + return USBC_Readb(USBC_REG_EPIND(USBC0_BASE)); +} + static void __USBC_Dev_ep0_SendStall(void) { USBC_REG_set_bit_w(USBC_BP_CSR0_D_SEND_STALL, USBC_REG_CSR0(USBC0_BASE)); @@ -387,6 +392,8 @@ static unsigned find_free_memory(uint_fast16_t size_in_log2_minus3) { free_block_t free_blocks[2 * (DCD_ATTR_ENDPOINT_MAX - 1)]; unsigned num_blocks = 1; + /* Backup current EP to restore later */ + u8 backup_ep = USBC_GetActiveEp(); /* Initialize free memory block list */ free_blocks[0].beg = 64 / 8; @@ -416,6 +423,8 @@ static unsigned find_free_memory(uint_fast16_t size_in_log2_minus3) } print_block_list(free_blocks, num_blocks); + USBC_SelectActiveEp(backup_ep); + /* Find the best fit memory block */ uint_fast16_t size_in_8byte_unit = 1 << size_in_log2_minus3; free_block_t const *min = NULL; From 64b81fd4d316ff8e0390c843bdff236ed4151147 Mon Sep 17 00:00:00 2001 From: Yunhao Tian Date: Sun, 5 Dec 2021 18:08:01 +0800 Subject: [PATCH 09/22] Close all EPs upon reset --- src/portable/sunxi/dcd_sunxi_musb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/portable/sunxi/dcd_sunxi_musb.c b/src/portable/sunxi/dcd_sunxi_musb.c index 0bb031a8..2150403a 100644 --- a/src/portable/sunxi/dcd_sunxi_musb.c +++ b/src/portable/sunxi/dcd_sunxi_musb.c @@ -839,6 +839,7 @@ void dcd_init(uint8_t rhport) USBC_ForceIdToHigh(); // Force device mode USBC_ForceVbusValidToHigh(); USBC_SelectBus(USBC_IO_TYPE_PIO, 0, 0); + dcd_edpt_close_all(rhport); #if TUD_OPT_HIGH_SPEED USBC_REG_set_bit_b(USBC_BP_POWER_D_HIGH_SPEED_EN, USBC_REG_PCTL(USBC0_BASE)); From 702698ee293727d31efb0c7134a15a261d878cb9 Mon Sep 17 00:00:00 2001 From: Yunhao Tian Date: Sun, 5 Dec 2021 18:18:41 +0800 Subject: [PATCH 10/22] Add FIFO size check --- src/portable/sunxi/dcd_sunxi_musb.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/portable/sunxi/dcd_sunxi_musb.c b/src/portable/sunxi/dcd_sunxi_musb.c index 2150403a..ecc07665 100644 --- a/src/portable/sunxi/dcd_sunxi_musb.c +++ b/src/portable/sunxi/dcd_sunxi_musb.c @@ -388,6 +388,12 @@ static inline void print_block_list(free_block_t const *blk, unsigned num) #define print_block_list(a,b) #endif +#if CFG_TUSB_MCU == OPT_MCU_F1C100S +#define USB_FIFO_SIZE_KB 2 +#else +#error "Unsupported MCU" +#endif + static unsigned find_free_memory(uint_fast16_t size_in_log2_minus3) { free_block_t free_blocks[2 * (DCD_ATTR_ENDPOINT_MAX - 1)]; @@ -397,7 +403,7 @@ static unsigned find_free_memory(uint_fast16_t size_in_log2_minus3) /* Initialize free memory block list */ free_blocks[0].beg = 64 / 8; - free_blocks[0].end = (4 << 10) / 8; /* 4KiB / 8 bytes */ + free_blocks[0].end = (USB_FIFO_SIZE_KB << 10) / 8; /* 2KiB / 8 bytes */ for (int i = 1; i < DCD_ATTR_ENDPOINT_MAX; ++i) { uint_fast16_t addr; int num; From f308603a3aeffcf77e83d2cfb1c76a28e543272d Mon Sep 17 00:00:00 2001 From: Yunhao Tian Date: Sun, 5 Dec 2021 22:31:09 +0800 Subject: [PATCH 11/22] Fix a typo that leads to incorrect RX handling --- src/portable/sunxi/dcd_sunxi_musb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/portable/sunxi/dcd_sunxi_musb.c b/src/portable/sunxi/dcd_sunxi_musb.c index ecc07665..420ce1de 100644 --- a/src/portable/sunxi/dcd_sunxi_musb.c +++ b/src/portable/sunxi/dcd_sunxi_musb.c @@ -598,7 +598,7 @@ static bool handle_xfer_out(uint_fast8_t ep_addr) pipe->buf = buf + len; } pipe->remaining = rem - len; - __USBC_Dev_ep0_ReadDataComplete(); + __USBC_Dev_Rx_ReadDataComplete(); } if ((len < mps) || (rem == len)) { pipe->buf = NULL; From 1ffc366aa9bb9c2dda8210956c2ac9a6fbafc88b Mon Sep 17 00:00:00 2001 From: Yunhao Tian Date: Sun, 5 Dec 2021 22:40:05 +0800 Subject: [PATCH 12/22] Change FIFO size to 4KB (not sure) The datasheet says 2KB FIFO, but accroding to many code examples, the F1C100s has at least 4KB of FIFO memory. This is working with cdc_msc example, but I'm not sure, this should be checked. --- src/portable/sunxi/dcd_sunxi_musb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/portable/sunxi/dcd_sunxi_musb.c b/src/portable/sunxi/dcd_sunxi_musb.c index 420ce1de..e164f2c1 100644 --- a/src/portable/sunxi/dcd_sunxi_musb.c +++ b/src/portable/sunxi/dcd_sunxi_musb.c @@ -389,7 +389,7 @@ static inline void print_block_list(free_block_t const *blk, unsigned num) #endif #if CFG_TUSB_MCU == OPT_MCU_F1C100S -#define USB_FIFO_SIZE_KB 2 +#define USB_FIFO_SIZE_KB 4 #else #error "Unsupported MCU" #endif From 96979a2c4a43902a3051c678858e788e7ffc8c60 Mon Sep 17 00:00:00 2001 From: Yunhao Tian Date: Mon, 6 Dec 2021 19:56:27 +0800 Subject: [PATCH 13/22] Fix handling of RXRDY bit --- src/portable/sunxi/dcd_sunxi_musb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/portable/sunxi/dcd_sunxi_musb.c b/src/portable/sunxi/dcd_sunxi_musb.c index e164f2c1..be1847b2 100644 --- a/src/portable/sunxi/dcd_sunxi_musb.c +++ b/src/portable/sunxi/dcd_sunxi_musb.c @@ -598,12 +598,12 @@ static bool handle_xfer_out(uint_fast8_t ep_addr) pipe->buf = buf + len; } pipe->remaining = rem - len; - __USBC_Dev_Rx_ReadDataComplete(); } if ((len < mps) || (rem == len)) { pipe->buf = NULL; return NULL != buf; } + __USBC_Dev_Rx_ReadDataComplete(); return false; } From 75f7fb3d9d267f168bc45fc218e1c443701ff11d Mon Sep 17 00:00:00 2001 From: Yunhao Tian Date: Tue, 7 Dec 2021 22:53:52 +0800 Subject: [PATCH 14/22] Add mksunxi tool to make flashable image --- examples/rules.mk | 10 +++--- hw/bsp/f1c100s/board.mk | 7 ++++- hw/mcu/allwinner/f1c100s/f1c100s.ld | 19 ++++++------ tools/mksunxi.py | 48 +++++++++++++++++++++++++++++ 4 files changed, 69 insertions(+), 15 deletions(-) create mode 100644 tools/mksunxi.py diff --git a/examples/rules.mk b/examples/rules.mk index 6314380e..55e39f4e 100644 --- a/examples/rules.mk +++ b/examples/rules.mk @@ -182,10 +182,12 @@ flash-jlink: $(BUILD)/$(PROJECT).hex flash-stlink: $(BUILD)/$(PROJECT).elf STM32_Programmer_CLI --connect port=swd --write $< --go -flash-xfel: $(BUILD)/$(PROJECT).bin - xfel ddr - xfel write 0x80000000 $< - xfel exec 0x80000000 +$(BUILD)/$(PROJECT)-sunxi.bin: $(BUILD)/$(PROJECT).bin + $(PYTHON) $(TOP)/tools/mksunxi.py $< $@ + +flash-xfel: $(BUILD)/$(PROJECT)-sunxi.bin + xfel spinor write 0 $< + xfel reset # Flash using pyocd PYOCD_OPTION ?= diff --git a/hw/bsp/f1c100s/board.mk b/hw/bsp/f1c100s/board.mk index 993aa0d2..9bd9380a 100644 --- a/hw/bsp/f1c100s/board.mk +++ b/hw/bsp/f1c100s/board.mk @@ -41,5 +41,10 @@ INC += \ $(TOP)/$(MCU_DIR)/include \ $(TOP)/$(BOARD_PATH) -# flash target using on-board stlink +# flash target using xfel flash: flash-xfel + +exec: $(BUILD)/$(PROJECT).bin + xfel ddr + xfel write 0x80000000 $< + xfel exec 0x80000000 \ No newline at end of file diff --git a/hw/mcu/allwinner/f1c100s/f1c100s.ld b/hw/mcu/allwinner/f1c100s/f1c100s.ld index a261618e..43c353bb 100644 --- a/hw/mcu/allwinner/f1c100s/f1c100s.ld +++ b/hw/mcu/allwinner/f1c100s/f1c100s.ld @@ -21,15 +21,15 @@ SECTIONS PROVIDE(__bootloader_start = .); PROVIDE(__image_start = .); PROVIDE(__text_start = .); - */machine/start.o (.text) - */lib/memcpy.o (.text) - */lib/memset.o (.text) - */machine/sys-uart.o (.text) - */machine/sys-clock.o (.text) - */machine/sys-dram.o (.text) - */machine/sys-mmu.o (.text) - */machine/sys-spi-flash.o (.text) - */machine/sys-copyself.o (.text) + _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 @@ -37,7 +37,6 @@ SECTIONS .text : { - */main.o (.text) *(.text*) *(.glue*) *(.note.gnu.build-id) diff --git a/tools/mksunxi.py b/tools/mksunxi.py new file mode 100644 index 00000000..04786f42 --- /dev/null +++ b/tools/mksunxi.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 +import sys +import struct + +def align(num, alignment): + if num % alignment != 0: + num += (alignment - num % alignment) + return num + + +def process_file(input, output): + with open(input, 'rb') as fin: + content = bytearray(fin.read()) + + align_value = 512 + padded_length = align(len(content), align_value) + # pad file to actual length + content += b'\x00' * (padded_length - len(content)) + + struct_format = ' Date: Tue, 7 Dec 2021 22:58:19 +0800 Subject: [PATCH 15/22] Update README --- hw/bsp/f1c100s/README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/hw/bsp/f1c100s/README.md b/hw/bsp/f1c100s/README.md index 893b32ea..cc33ca1f 100644 --- a/hw/bsp/f1c100s/README.md +++ b/hw/bsp/f1c100s/README.md @@ -6,13 +6,13 @@ Currently tested on: * Lichee Pi Nano (F1C100s) -## make flash -`make flash` will use [xfel](https://github.com/xboot/xfel) to write the code to onchip DDR memory and execute it. It will not write the program to SPI Flash. +## Flashing +There are two options to put your code into the MCU: `flash` and `exec`. Both modes require you to install [xfel](https://github.com/xboot/xfel) tool to your PATH. You must enter FEL mode before any operation can be done. To enter FEL mode, press BOOT button, then press RESET once, and release BOOT button. You will find VID/PID=1f3a:efe8 on your PC. -To enter FEL mode, you have to press BOOT button, then press RESET once, and release BOOT button. You will find VID/PID=1f3a:efe8 on your PC. +Exec: `make BOARD=f1c100s exec` will just upload the image to the DDR ram and execute it. It will not touch anything in the SPI flash. + +Flash: `make BOARD=f1c100s flash` will write the image to SPI flash, and then reset the chip to execute it. ## TODO * Test on Tiny200 v2 (F1C200s) -* Make it able to load .bin directly to SPI Flash and boot -* Add F1C100s to `#if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX` high speed MCU check in examples (maybe we should extract the logic?) -* `cdc_msc` example is not working. Device is only echoing the first character. \ No newline at end of file +* Add F1C100s to `#if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX` high speed MCU check in examples (maybe we should extract the logic?) \ No newline at end of file From 527036b1f5a3f0aa3994f62e3ab18fa990a40cf8 Mon Sep 17 00:00:00 2001 From: Yunhao Tian Date: Wed, 8 Dec 2021 13:39:27 +0800 Subject: [PATCH 16/22] Initialize MMU if we are executing from DDR --- hw/mcu/allwinner/f1c100s/machine/start.S | 27 ++++++++++++------------ 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/hw/mcu/allwinner/f1c100s/machine/start.S b/hw/mcu/allwinner/f1c100s/machine/start.S index 1fd7cb1f..befb2214 100644 --- a/hw/mcu/allwinner/f1c100s/machine/start.S +++ b/hw/mcu/allwinner/f1c100s/machine/start.S @@ -111,37 +111,38 @@ reset: ldmia r0!, {r2-r8, r10} stmia r1!, {r2-r8, r10} - /* Initial system clock, ddr add uart */ + /* Initial system clock, ddr and uart */ bl sys_clock_init - bl sys_dram_init bl sys_uart_init - /* Boot speed up, leave slower sram */ + /* Check if we are already running from dram */ adr r0, _start ldr r1, =_start cmp r0, r1 - beq _speedup + 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, =_speedup + ldr r0, =_copy_self ldr r1, =_start sub r0, r0, r1 ldr r1, =0x81f80000 add r0, r0, r1 mov pc, r0 -_speedup: - nop - +_init_mmu: + bl sys_mmu_init + b 1f +_copy_self: /* Copyself to link address */ - adr r0, _start - ldr r1, =_start - cmp r0, r1 - beq 1f bl sys_copyself -1: nop +1: nop /* Initialize stacks */ mrs r0, cpsr bic r0, r0, #0x1f From 2d13ecde1bdb94575398b2e0e64e6e50a192fd18 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 29 Dec 2021 18:59:47 +0700 Subject: [PATCH 17/22] add allwinnner driver as submodule --- .gitmodules | 3 + hw/mcu/allwinner | 1 + hw/mcu/allwinner/f1c100s/f1c100s.ld | 136 --- hw/mcu/allwinner/f1c100s/include/arm32.h | 150 ---- .../allwinner/f1c100s/include/f1c100s-gpio.h | 66 -- .../allwinner/f1c100s/include/f1c100s-irq.h | 104 --- .../allwinner/f1c100s/include/f1c100s-reset.h | 39 - .../allwinner/f1c100s/include/f1c100s-util.h | 139 --- .../f1c100s/include/f1c100s/reg-ccu.h | 55 -- .../f1c100s/include/f1c100s/reg-dram.h | 39 - hw/mcu/allwinner/f1c100s/include/io.h | 57 -- hw/mcu/allwinner/f1c100s/include/irqflags.h | 104 --- hw/mcu/allwinner/f1c100s/include/malloc.h | 35 - hw/mcu/allwinner/f1c100s/include/printf.h | 99 --- hw/mcu/allwinner/f1c100s/include/sizes.h | 42 - hw/mcu/allwinner/f1c100s/include/types.h | 55 -- hw/mcu/allwinner/f1c100s/lib/malloc.c | 834 ------------------ hw/mcu/allwinner/f1c100s/lib/memcpy.S | 404 --------- hw/mcu/allwinner/f1c100s/lib/memset.S | 79 -- hw/mcu/allwinner/f1c100s/lib/printf.c | 757 ---------------- hw/mcu/allwinner/f1c100s/machine/exception.c | 76 -- .../allwinner/f1c100s/machine/f1c100s-intc.c | 173 ---- hw/mcu/allwinner/f1c100s/machine/start.S | 314 ------- hw/mcu/allwinner/f1c100s/machine/sys-clock.c | 124 --- .../allwinner/f1c100s/machine/sys-copyself.c | 111 --- hw/mcu/allwinner/f1c100s/machine/sys-dram.c | 506 ----------- hw/mcu/allwinner/f1c100s/machine/sys-mmu.c | 57 -- .../allwinner/f1c100s/machine/sys-spi-flash.c | 204 ----- hw/mcu/allwinner/f1c100s/machine/sys-uart.c | 83 -- 29 files changed, 4 insertions(+), 4842 deletions(-) create mode 160000 hw/mcu/allwinner delete mode 100644 hw/mcu/allwinner/f1c100s/f1c100s.ld delete mode 100644 hw/mcu/allwinner/f1c100s/include/arm32.h delete mode 100644 hw/mcu/allwinner/f1c100s/include/f1c100s-gpio.h delete mode 100644 hw/mcu/allwinner/f1c100s/include/f1c100s-irq.h delete mode 100644 hw/mcu/allwinner/f1c100s/include/f1c100s-reset.h delete mode 100644 hw/mcu/allwinner/f1c100s/include/f1c100s-util.h delete mode 100644 hw/mcu/allwinner/f1c100s/include/f1c100s/reg-ccu.h delete mode 100644 hw/mcu/allwinner/f1c100s/include/f1c100s/reg-dram.h delete mode 100644 hw/mcu/allwinner/f1c100s/include/io.h delete mode 100644 hw/mcu/allwinner/f1c100s/include/irqflags.h delete mode 100644 hw/mcu/allwinner/f1c100s/include/malloc.h delete mode 100644 hw/mcu/allwinner/f1c100s/include/printf.h delete mode 100644 hw/mcu/allwinner/f1c100s/include/sizes.h delete mode 100644 hw/mcu/allwinner/f1c100s/include/types.h delete mode 100644 hw/mcu/allwinner/f1c100s/lib/malloc.c delete mode 100644 hw/mcu/allwinner/f1c100s/lib/memcpy.S delete mode 100644 hw/mcu/allwinner/f1c100s/lib/memset.S delete mode 100644 hw/mcu/allwinner/f1c100s/lib/printf.c delete mode 100644 hw/mcu/allwinner/f1c100s/machine/exception.c delete mode 100644 hw/mcu/allwinner/f1c100s/machine/f1c100s-intc.c delete mode 100644 hw/mcu/allwinner/f1c100s/machine/start.S delete mode 100644 hw/mcu/allwinner/f1c100s/machine/sys-clock.c delete mode 100644 hw/mcu/allwinner/f1c100s/machine/sys-copyself.c delete mode 100644 hw/mcu/allwinner/f1c100s/machine/sys-dram.c delete mode 100644 hw/mcu/allwinner/f1c100s/machine/sys-mmu.c delete mode 100644 hw/mcu/allwinner/f1c100s/machine/sys-spi-flash.c delete mode 100644 hw/mcu/allwinner/f1c100s/machine/sys-uart.c diff --git a/.gitmodules b/.gitmodules index 5c79ea91..4ce5d0f0 100644 --- a/.gitmodules +++ b/.gitmodules @@ -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 diff --git a/hw/mcu/allwinner b/hw/mcu/allwinner new file mode 160000 index 00000000..c56955e1 --- /dev/null +++ b/hw/mcu/allwinner @@ -0,0 +1 @@ +Subproject commit c56955e156b1050a4a8ccf8589555148f00a1bb6 diff --git a/hw/mcu/allwinner/f1c100s/f1c100s.ld b/hw/mcu/allwinner/f1c100s/f1c100s.ld deleted file mode 100644 index 43c353bb..00000000 --- a/hw/mcu/allwinner/f1c100s/f1c100s.ld +++ /dev/null @@ -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) } -} diff --git a/hw/mcu/allwinner/f1c100s/include/arm32.h b/hw/mcu/allwinner/f1c100s/include/arm32.h deleted file mode 100644 index a3a25455..00000000 --- a/hw/mcu/allwinner/f1c100s/include/arm32.h +++ /dev/null @@ -1,150 +0,0 @@ -#ifndef __ARM32_H__ -#define __ARM32_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -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__ */ diff --git a/hw/mcu/allwinner/f1c100s/include/f1c100s-gpio.h b/hw/mcu/allwinner/f1c100s/include/f1c100s-gpio.h deleted file mode 100644 index 3dbe8bf1..00000000 --- a/hw/mcu/allwinner/f1c100s/include/f1c100s-gpio.h +++ /dev/null @@ -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__ */ diff --git a/hw/mcu/allwinner/f1c100s/include/f1c100s-irq.h b/hw/mcu/allwinner/f1c100s/include/f1c100s-irq.h deleted file mode 100644 index 410d1be9..00000000 --- a/hw/mcu/allwinner/f1c100s/include/f1c100s-irq.h +++ /dev/null @@ -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__ */ diff --git a/hw/mcu/allwinner/f1c100s/include/f1c100s-reset.h b/hw/mcu/allwinner/f1c100s/include/f1c100s-reset.h deleted file mode 100644 index e787a1ac..00000000 --- a/hw/mcu/allwinner/f1c100s/include/f1c100s-reset.h +++ /dev/null @@ -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__ */ diff --git a/hw/mcu/allwinner/f1c100s/include/f1c100s-util.h b/hw/mcu/allwinner/f1c100s/include/f1c100s-util.h deleted file mode 100644 index cb3829f8..00000000 --- a/hw/mcu/allwinner/f1c100s/include/f1c100s-util.h +++ /dev/null @@ -1,139 +0,0 @@ -// Designed by Hong Xuyao - -#ifndef __TARGET_H__ -#define __TARGET_H__ -//////////////////////////////////////////////////////////////////////////////// -#include -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__ */ - diff --git a/hw/mcu/allwinner/f1c100s/include/f1c100s/reg-ccu.h b/hw/mcu/allwinner/f1c100s/include/f1c100s/reg-ccu.h deleted file mode 100644 index 1770ad7f..00000000 --- a/hw/mcu/allwinner/f1c100s/include/f1c100s/reg-ccu.h +++ /dev/null @@ -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__ */ diff --git a/hw/mcu/allwinner/f1c100s/include/f1c100s/reg-dram.h b/hw/mcu/allwinner/f1c100s/include/f1c100s/reg-dram.h deleted file mode 100644 index 8a0ac3e0..00000000 --- a/hw/mcu/allwinner/f1c100s/include/f1c100s/reg-dram.h +++ /dev/null @@ -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__ */ diff --git a/hw/mcu/allwinner/f1c100s/include/io.h b/hw/mcu/allwinner/f1c100s/include/io.h deleted file mode 100644 index f0dad178..00000000 --- a/hw/mcu/allwinner/f1c100s/include/io.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef __IO_H__ -#define __IO_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -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__ */ diff --git a/hw/mcu/allwinner/f1c100s/include/irqflags.h b/hw/mcu/allwinner/f1c100s/include/irqflags.h deleted file mode 100644 index e4ef97cd..00000000 --- a/hw/mcu/allwinner/f1c100s/include/irqflags.h +++ /dev/null @@ -1,104 +0,0 @@ -#ifndef __ARM32_IRQFLAGS_H__ -#define __ARM32_IRQFLAGS_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#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__ */ diff --git a/hw/mcu/allwinner/f1c100s/include/malloc.h b/hw/mcu/allwinner/f1c100s/include/malloc.h deleted file mode 100644 index 6669fe48..00000000 --- a/hw/mcu/allwinner/f1c100s/include/malloc.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef __MALLOC_H__ -#define __MALLOC_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include -#include - -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__ */ diff --git a/hw/mcu/allwinner/f1c100s/include/printf.h b/hw/mcu/allwinner/f1c100s/include/printf.h deleted file mode 100644 index 632bfc20..00000000 --- a/hw/mcu/allwinner/f1c100s/include/printf.h +++ /dev/null @@ -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 -#include - - -#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_ diff --git a/hw/mcu/allwinner/f1c100s/include/sizes.h b/hw/mcu/allwinner/f1c100s/include/sizes.h deleted file mode 100644 index 3edeed50..00000000 --- a/hw/mcu/allwinner/f1c100s/include/sizes.h +++ /dev/null @@ -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__ */ diff --git a/hw/mcu/allwinner/f1c100s/include/types.h b/hw/mcu/allwinner/f1c100s/include/types.h deleted file mode 100644 index 61b87b6d..00000000 --- a/hw/mcu/allwinner/f1c100s/include/types.h +++ /dev/null @@ -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__ */ diff --git a/hw/mcu/allwinner/f1c100s/lib/malloc.c b/hw/mcu/allwinner/f1c100s/lib/malloc.c deleted file mode 100644 index 763746a4..00000000 --- a/hw/mcu/allwinner/f1c100s/lib/malloc.c +++ /dev/null @@ -1,834 +0,0 @@ -/* - * lib/libc/malloc/malloc.c - */ - -#include - -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 -} diff --git a/hw/mcu/allwinner/f1c100s/lib/memcpy.S b/hw/mcu/allwinner/f1c100s/lib/memcpy.S deleted file mode 100644 index f7ed3130..00000000 --- a/hw/mcu/allwinner/f1c100s/lib/memcpy.S +++ /dev/null @@ -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 diff --git a/hw/mcu/allwinner/f1c100s/lib/memset.S b/hw/mcu/allwinner/f1c100s/lib/memset.S deleted file mode 100644 index 3eea2db1..00000000 --- a/hw/mcu/allwinner/f1c100s/lib/memset.S +++ /dev/null @@ -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 */ diff --git a/hw/mcu/allwinner/f1c100s/lib/printf.c b/hw/mcu/allwinner/f1c100s/lib/printf.c deleted file mode 100644 index 366bb9c0..00000000 --- a/hw/mcu/allwinner/f1c100s/lib/printf.c +++ /dev/null @@ -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 -#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 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; -} diff --git a/hw/mcu/allwinner/f1c100s/machine/exception.c b/hw/mcu/allwinner/f1c100s/machine/exception.c deleted file mode 100644 index ffc61bf4..00000000 --- a/hw/mcu/allwinner/f1c100s/machine/exception.c +++ /dev/null @@ -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 -#include -#include - -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 \ No newline at end of file diff --git a/hw/mcu/allwinner/f1c100s/machine/f1c100s-intc.c b/hw/mcu/allwinner/f1c100s/machine/f1c100s-intc.c deleted file mode 100644 index 2993f0b6..00000000 --- a/hw/mcu/allwinner/f1c100s/machine/f1c100s-intc.c +++ /dev/null @@ -1,173 +0,0 @@ -// Originally designed by Hong Xuyao - -#include -#include -#include -#include - -#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; - } -} diff --git a/hw/mcu/allwinner/f1c100s/machine/start.S b/hw/mcu/allwinner/f1c100s/machine/start.S deleted file mode 100644 index befb2214..00000000 --- a/hw/mcu/allwinner/f1c100s/machine/start.S +++ /dev/null @@ -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 diff --git a/hw/mcu/allwinner/f1c100s/machine/sys-clock.c b/hw/mcu/allwinner/f1c100s/machine/sys-clock.c deleted file mode 100644 index d151dd0c..00000000 --- a/hw/mcu/allwinner/f1c100s/machine/sys-clock.c +++ /dev/null @@ -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 -#include -#include -#include - -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); -} diff --git a/hw/mcu/allwinner/f1c100s/machine/sys-copyself.c b/hw/mcu/allwinner/f1c100s/machine/sys-copyself.c deleted file mode 100644 index 4116e126..00000000 --- a/hw/mcu/allwinner/f1c100s/machine/sys-copyself.c +++ /dev/null @@ -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 - -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; - } -} diff --git a/hw/mcu/allwinner/f1c100s/machine/sys-dram.c b/hw/mcu/allwinner/f1c100s/machine/sys-dram.c deleted file mode 100644 index a819520a..00000000 --- a/hw/mcu/allwinner/f1c100s/machine/sys-dram.c +++ /dev/null @@ -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 -#include -#include -#include - -#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(¶)) - dsz[0] = (((uint32_t)'X') << 24) | (para.size << 0); -} diff --git a/hw/mcu/allwinner/f1c100s/machine/sys-mmu.c b/hw/mcu/allwinner/f1c100s/machine/sys-mmu.c deleted file mode 100644 index 3c89c725..00000000 --- a/hw/mcu/allwinner/f1c100s/machine/sys-mmu.c +++ /dev/null @@ -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 -#include -#include -#include - -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(); -} \ No newline at end of file diff --git a/hw/mcu/allwinner/f1c100s/machine/sys-spi-flash.c b/hw/mcu/allwinner/f1c100s/machine/sys-spi-flash.c deleted file mode 100644 index 5c3b0f0a..00000000 --- a/hw/mcu/allwinner/f1c100s/machine/sys-spi-flash.c +++ /dev/null @@ -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 -#include -#include -#include - -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(); -} diff --git a/hw/mcu/allwinner/f1c100s/machine/sys-uart.c b/hw/mcu/allwinner/f1c100s/machine/sys-uart.c deleted file mode 100644 index 0e61627b..00000000 --- a/hw/mcu/allwinner/f1c100s/machine/sys-uart.c +++ /dev/null @@ -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 -#include -#include - -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); -} From b943a53b1066e8a736eb7a32e42af6324a208718 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 29 Dec 2021 19:04:08 +0700 Subject: [PATCH 18/22] update allwinner submodule --- hw/mcu/allwinner | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/mcu/allwinner b/hw/mcu/allwinner index c56955e1..8e5e89e8 160000 --- a/hw/mcu/allwinner +++ b/hw/mcu/allwinner @@ -1 +1 @@ -Subproject commit c56955e156b1050a4a8ccf8589555148f00a1bb6 +Subproject commit 8e5e89e8e132c0fd90e72d5422e5d3d68232b756 From 84e2f6e0e144614b306f68416958f8f662c8cb46 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 29 Dec 2021 19:12:41 +0700 Subject: [PATCH 19/22] skip freertos example for f1c100s --- examples/device/cdc_msc_freertos/.skip.MCU_F1C100S | 0 examples/device/hid_composite_freertos/.skip.MCU_F1C100S | 0 hw/bsp/f1c100s/f1c100s.c | 2 +- 3 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 examples/device/cdc_msc_freertos/.skip.MCU_F1C100S create mode 100644 examples/device/hid_composite_freertos/.skip.MCU_F1C100S diff --git a/examples/device/cdc_msc_freertos/.skip.MCU_F1C100S b/examples/device/cdc_msc_freertos/.skip.MCU_F1C100S new file mode 100644 index 00000000..e69de29b diff --git a/examples/device/hid_composite_freertos/.skip.MCU_F1C100S b/examples/device/hid_composite_freertos/.skip.MCU_F1C100S new file mode 100644 index 00000000..e69de29b diff --git a/hw/bsp/f1c100s/f1c100s.c b/hw/bsp/f1c100s/f1c100s.c index 6cf18597..d45072ec 100644 --- a/hw/bsp/f1c100s/f1c100s.c +++ b/hw/bsp/f1c100s/f1c100s.c @@ -49,7 +49,7 @@ void board_init(void) arch_local_irq_enable(); } -// No LED, no button, sorry +// No LED, no button void board_led_write(bool state) { From 5f280b30290e540f24d55fdd3e0dd46efa251547 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 29 Dec 2021 19:22:39 +0700 Subject: [PATCH 20/22] add license to dcd file, slightly update readme --- hw/bsp/f1c100s/README.md | 6 ++++-- hw/bsp/f1c100s/board.mk | 4 +++- src/osal/osal_rtx4.h | 1 + src/portable/sunxi/dcd_sunxi_musb.c | 27 +++++++++++++++++++++++++++ src/portable/sunxi/musb_def.h | 27 +++++++++++++++++++++++++++ 5 files changed, 62 insertions(+), 3 deletions(-) diff --git a/hw/bsp/f1c100s/README.md b/hw/bsp/f1c100s/README.md index cc33ca1f..32504471 100644 --- a/hw/bsp/f1c100s/README.md +++ b/hw/bsp/f1c100s/README.md @@ -4,9 +4,11 @@ This folder contains necessary file and scripts to run TinyUSB examples on F1Cx0 Currently tested on: -* Lichee Pi Nano (F1C100s) +- Lichee Pi Nano (F1C100s) +- [Widora Tiny200 v2 (also called MangoPi-R3c)](https://mangopi.org/tiny200) ## Flashing + There are two options to put your code into the MCU: `flash` and `exec`. Both modes require you to install [xfel](https://github.com/xboot/xfel) tool to your PATH. You must enter FEL mode before any operation can be done. To enter FEL mode, press BOOT button, then press RESET once, and release BOOT button. You will find VID/PID=1f3a:efe8 on your PC. Exec: `make BOARD=f1c100s exec` will just upload the image to the DDR ram and execute it. It will not touch anything in the SPI flash. @@ -14,5 +16,5 @@ Exec: `make BOARD=f1c100s exec` will just upload the image to the DDR ram and ex Flash: `make BOARD=f1c100s flash` will write the image to SPI flash, and then reset the chip to execute it. ## TODO -* Test on Tiny200 v2 (F1C200s) + * Add F1C100s to `#if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX` high speed MCU check in examples (maybe we should extract the logic?) \ No newline at end of file diff --git a/hw/bsp/f1c100s/board.mk b/hw/bsp/f1c100s/board.mk index 9bd9380a..5fe26a9e 100644 --- a/hw/bsp/f1c100s/board.mk +++ b/hw/bsp/f1c100s/board.mk @@ -1,3 +1,5 @@ +DEPS_SUBMODULES += hw/mcu/allwinner + DEFINES += -D__ARM32_ARCH__=5 -D__ARM926EJS__ CFLAGS += \ @@ -33,7 +35,7 @@ SRC_C += \ $(MCU_DIR)/lib/printf.c SRC_S += \ - $(MCU_DIR)/machine/start.S \ + $(MCU_DIR)/machine/start.S \ $(MCU_DIR)/lib/memcpy.S \ $(MCU_DIR)/lib/memset.S diff --git a/src/osal/osal_rtx4.h b/src/osal/osal_rtx4.h index 93d1a7a2..32d7782d 100644 --- a/src/osal/osal_rtx4.h +++ b/src/osal/osal_rtx4.h @@ -1,6 +1,7 @@ /* * The MIT License (MIT) * + * Copyright (c) 2021 Tian Yunhao (t123yh) * Copyright (c) 2019 Ha Thach (tinyusb.org) * * Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/src/portable/sunxi/dcd_sunxi_musb.c b/src/portable/sunxi/dcd_sunxi_musb.c index be1847b2..3d39248c 100644 --- a/src/portable/sunxi/dcd_sunxi_musb.c +++ b/src/portable/sunxi/dcd_sunxi_musb.c @@ -1,3 +1,30 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021 Tian Yunhao (t123yh) + * Copyright (c) 2021 Ha Thach (tinyusb.org) + * + * 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. + * + * This file is part of the TinyUSB stack. + */ + #include #include "tusb_option.h" #include "osal/osal.h" diff --git a/src/portable/sunxi/musb_def.h b/src/portable/sunxi/musb_def.h index f55ddab3..e0c8a5e2 100644 --- a/src/portable/sunxi/musb_def.h +++ b/src/portable/sunxi/musb_def.h @@ -1,3 +1,30 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021 Tian Yunhao (t123yh) + * Copyright (c) 2021 Ha Thach (tinyusb.org) + * + * 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. + * + * This file is part of the TinyUSB stack. + */ + #ifndef _TUSB_MUSB_DEF #define _TUSB_MUSB_DEF From adb848f75489ea6a9fa27be8c7c53cfa0679af91 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 29 Dec 2021 19:40:55 +0700 Subject: [PATCH 21/22] update docs --- CONTRIBUTORS.rst | 6 ++++++ README.rst | 1 + src/portable/sunxi/dcd_sunxi_musb.c | 1 + src/portable/sunxi/musb_def.h | 1 + 4 files changed, 9 insertions(+) diff --git a/CONTRIBUTORS.rst b/CONTRIBUTORS.rst index e3186f08..05d088ee 100644 --- a/CONTRIBUTORS.rst +++ b/CONTRIBUTORS.rst @@ -153,6 +153,12 @@ Notable contributors - Add new class driver for DFU Runtime +`Tian Yunhao `__ +------------------------------------------- + +- Add new DCD port for Allwinner F1C100S/F1C200S +- Add support for osal_rtx4 + `Timon Skerutsch `__ ---------------------------------------------- diff --git a/README.rst b/README.rst index 03219db3..7f1eff8b 100644 --- a/README.rst +++ b/README.rst @@ -32,6 +32,7 @@ Supported MCUs The stack supports the following MCUs: +- **Allwinner:** F1C100s/F1C200s - **Broadcom:** BCM2837, BCM2711 - **Dialog:** DA1469x - **Espressif:** ESP32-S2, ESP32-S3 diff --git a/src/portable/sunxi/dcd_sunxi_musb.c b/src/portable/sunxi/dcd_sunxi_musb.c index 3d39248c..89464c5b 100644 --- a/src/portable/sunxi/dcd_sunxi_musb.c +++ b/src/portable/sunxi/dcd_sunxi_musb.c @@ -1,6 +1,7 @@ /* * The MIT License (MIT) * + * Copyright (c) 2021 Koji KITAYAMA * Copyright (c) 2021 Tian Yunhao (t123yh) * Copyright (c) 2021 Ha Thach (tinyusb.org) * diff --git a/src/portable/sunxi/musb_def.h b/src/portable/sunxi/musb_def.h index e0c8a5e2..602b4f11 100644 --- a/src/portable/sunxi/musb_def.h +++ b/src/portable/sunxi/musb_def.h @@ -1,6 +1,7 @@ /* * The MIT License (MIT) * + * Copyright (c) 2021 Koji KITAYAMA * Copyright (c) 2021 Tian Yunhao (t123yh) * Copyright (c) 2021 Ha Thach (tinyusb.org) * From c5d2c82cbbabf02cef16c2da565867f63900f69b Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 30 Dec 2021 20:59:53 +0700 Subject: [PATCH 22/22] fix unreachable warnings with keil --- src/device/usbd.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/device/usbd.c b/src/device/usbd.c index 0e31f47c..44811430 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -44,11 +44,6 @@ #define CFG_TUD_TASK_QUEUE_SZ 16 #endif -#ifdef __ARMCC_VERSION -// Supress "statement is unreachable" warning -#pragma diag_suppress 111 -#endif - //--------------------------------------------------------------------+ // Device Data //--------------------------------------------------------------------+ @@ -1013,7 +1008,7 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const return tud_control_xfer(rhport, p_request, desc_device, sizeof(tusb_desc_device_t)); } } - break; + // break; // unreachable case TUSB_DESC_BOS: { @@ -1030,7 +1025,7 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const return tud_control_xfer(rhport, p_request, (void*) desc_bos, total_len); } - break; + // break; // unreachable case TUSB_DESC_CONFIGURATION: case TUSB_DESC_OTHER_SPEED_CONFIG: @@ -1056,7 +1051,7 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const return tud_control_xfer(rhport, p_request, (void*) desc_config, total_len); } - break; + // break; // unreachable case TUSB_DESC_STRING: { @@ -1069,7 +1064,7 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const // first byte of descriptor is its size return tud_control_xfer(rhport, p_request, (void*) (uintptr_t) desc_str, tu_desc_len(desc_str)); } - break; + // break; // unreachable case TUSB_DESC_DEVICE_QUALIFIER: { @@ -1083,7 +1078,7 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const // first byte of descriptor is its size return tud_control_xfer(rhport, p_request, (void*) (uintptr_t) desc_qualifier, tu_desc_len(desc_qualifier)); } - break; + // break; // unreachable default: return false; }