Browse Source

[Bsp][New BSP]New bsp for allwinner tina

uestczyh222 7 years ago
parent
commit
9bf2a755e0

+ 1 - 0
.travis.yml

@@ -27,6 +27,7 @@ env:
 #  - RTT_BSP='apollo2' RTT_TOOL_CHAIN='sourcery-arm'
   - RTT_BSP='asm9260t' RTT_TOOL_CHAIN='sourcery-arm'
   - RTT_BSP='at91sam9260' RTT_TOOL_CHAIN='sourcery-arm'
+  - RTT_BSP='allwinner_tina' RTT_TOOL_CHAIN='sourcery-arm'
 #  - RTT_BSP='avr32uc3b0' RTT_TOOL_CHAIN='atmel-avr32'
 #  - RTT_BSP='bf533' # no scons
   - RTT_BSP='efm32' RTT_TOOL_CHAIN='sourcery-arm' 

+ 265 - 0
bsp/allwinner_tina/.config

@@ -0,0 +1,265 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# RT-Thread Configuration
+#
+
+#
+# RT-Thread Kernel
+#
+CONFIG_RT_NAME_MAX=8
+CONFIG_RT_ALIGN_SIZE=4
+# CONFIG_RT_THREAD_PRIORITY_8 is not set
+CONFIG_RT_THREAD_PRIORITY_32=y
+# CONFIG_RT_THREAD_PRIORITY_256 is not set
+CONFIG_RT_THREAD_PRIORITY_MAX=32
+CONFIG_RT_TICK_PER_SECOND=100
+CONFIG_RT_DEBUG=y
+CONFIG_RT_USING_OVERFLOW_CHECK=y
+CONFIG_RT_DEBUG_INIT=0
+CONFIG_RT_DEBUG_THREAD=0
+CONFIG_RT_USING_HOOK=y
+CONFIG_IDLE_THREAD_STACK_SIZE=256
+# CONFIG_RT_USING_TIMER_SOFT is not set
+
+#
+# Inter-Thread communication
+#
+CONFIG_RT_USING_SEMAPHORE=y
+CONFIG_RT_USING_MUTEX=y
+CONFIG_RT_USING_EVENT=y
+CONFIG_RT_USING_MAILBOX=y
+CONFIG_RT_USING_MESSAGEQUEUE=y
+# CONFIG_RT_USING_SIGNALS is not set
+
+#
+# Memory Management
+#
+CONFIG_RT_USING_MEMPOOL=y
+# CONFIG_RT_USING_MEMHEAP is not set
+# CONFIG_RT_USING_NOHEAP is not set
+CONFIG_RT_USING_SMALL_MEM=y
+# CONFIG_RT_USING_SLAB is not set
+# CONFIG_RT_USING_MEMTRACE is not set
+CONFIG_RT_USING_HEAP=y
+
+#
+# Kernel Device Object
+#
+CONFIG_RT_USING_DEVICE=y
+# CONFIG_RT_USING_INTERRUPT_INFO is not set
+CONFIG_RT_USING_CONSOLE=y
+CONFIG_RT_CONSOLEBUF_SIZE=128
+CONFIG_RT_CONSOLE_DEVICE_NAME="uart0"
+# CONFIG_RT_USING_MODULE is not set
+CONFIG_ARCH_ARM=y
+CONFIG_ARCH_ARM_ARM9=y
+
+#
+# RT-Thread Components
+#
+CONFIG_RT_USING_COMPONENTS_INIT=y
+CONFIG_RT_USING_USER_MAIN=y
+
+#
+# C++ features
+#
+# CONFIG_RT_USING_CPLUSPLUS is not set
+
+#
+# Command shell
+#
+CONFIG_RT_USING_FINSH=y
+CONFIG_FINSH_THREAD_NAME="tshell"
+CONFIG_FINSH_USING_HISTORY=y
+CONFIG_FINSH_HISTORY_LINES=5
+CONFIG_FINSH_USING_SYMTAB=y
+CONFIG_FINSH_USING_DESCRIPTION=y
+CONFIG_FINSH_THREAD_PRIORITY=20
+CONFIG_FINSH_THREAD_STACK_SIZE=4096
+CONFIG_FINSH_CMD_SIZE=80
+# CONFIG_FINSH_USING_AUTH is not set
+CONFIG_FINSH_USING_MSH=y
+CONFIG_FINSH_USING_MSH_DEFAULT=y
+# CONFIG_FINSH_USING_MSH_ONLY is not set
+
+#
+# Device virtual file system
+#
+CONFIG_RT_USING_DFS=y
+CONFIG_DFS_USING_WORKDIR=y
+CONFIG_DFS_FILESYSTEMS_MAX=2
+CONFIG_DFS_FILESYSTEM_TYPES_MAX=2
+CONFIG_DFS_FD_MAX=4
+CONFIG_RT_USING_DFS_ELMFAT=y
+
+#
+# elm-chan's FatFs, Generic FAT Filesystem Module
+#
+CONFIG_RT_DFS_ELM_CODE_PAGE=437
+CONFIG_RT_DFS_ELM_WORD_ACCESS=y
+CONFIG_RT_DFS_ELM_USE_LFN_0=y
+# CONFIG_RT_DFS_ELM_USE_LFN_1 is not set
+# CONFIG_RT_DFS_ELM_USE_LFN_2 is not set
+# CONFIG_RT_DFS_ELM_USE_LFN_3 is not set
+CONFIG_RT_DFS_ELM_USE_LFN=0
+CONFIG_RT_DFS_ELM_MAX_LFN=255
+CONFIG_RT_DFS_ELM_DRIVES=2
+CONFIG_RT_DFS_ELM_MAX_SECTOR_SIZE=512
+# CONFIG_RT_DFS_ELM_USE_ERASE is not set
+CONFIG_RT_DFS_ELM_REENTRANT=y
+CONFIG_RT_USING_DFS_DEVFS=y
+# CONFIG_RT_USING_DFS_NET is not set
+# CONFIG_RT_USING_DFS_ROMFS is not set
+# CONFIG_RT_USING_DFS_RAMFS is not set
+# CONFIG_RT_USING_DFS_UFFS is not set
+# CONFIG_RT_USING_DFS_JFFS2 is not set
+# CONFIG_RT_USING_DFS_NFS is not set
+
+#
+# Device Drivers
+#
+CONFIG_RT_USING_DEVICE_IPC=y
+CONFIG_RT_USING_SERIAL=y
+# CONFIG_RT_USING_CAN is not set
+# CONFIG_RT_USING_HWTIMER is not set
+# CONFIG_RT_USING_CPUTIME is not set
+# CONFIG_RT_USING_I2C is not set
+CONFIG_RT_USING_PIN=y
+# CONFIG_RT_USING_MTD_NOR is not set
+# CONFIG_RT_USING_MTD_NAND is not set
+# CONFIG_RT_USING_RTC is not set
+# CONFIG_RT_USING_SDIO is not set
+# CONFIG_RT_USING_SPI is not set
+# CONFIG_RT_USING_WDT is not set
+# CONFIG_RT_USING_WIFI is not set
+
+#
+# Using USB
+#
+# CONFIG_RT_USING_USB_HOST is not set
+# CONFIG_RT_USING_USB_DEVICE is not set
+
+#
+# POSIX layer and C standard library
+#
+CONFIG_RT_USING_LIBC=y
+# CONFIG_RT_USING_PTHREADS is not set
+CONFIG_RT_USING_POSIX=y
+# CONFIG_RT_USING_POSIX_MMAP is not set
+# CONFIG_RT_USING_POSIX_TERMIOS is not set
+# CONFIG_RT_USING_POSIX_AIO is not set
+
+#
+# Network stack
+#
+
+#
+# light weight TCP/IP stack
+#
+# CONFIG_RT_USING_LWIP is not set
+
+#
+# Modbus master and slave stack
+#
+# CONFIG_RT_USING_MODBUS is not set
+
+#
+# RT-Thread UI Engine
+#
+# CONFIG_RT_USING_GUIENGINE is not set
+
+#
+# VBUS(Virtual Software BUS)
+#
+# CONFIG_RT_USING_VBUS is not set
+
+#
+# Utilities
+#
+# CONFIG_RT_USING_LOGTRACE is not set
+# CONFIG_RT_USING_RYM is not set
+
+#
+# RT-Thread online packages
+#
+
+#
+# system packages
+#
+# CONFIG_PKG_USING_LWEXT4 is not set
+# CONFIG_PKG_USING_PARTITION is not set
+# CONFIG_PKG_USING_PERSIMMON is not set
+# CONFIG_PKG_USING_SQLITE is not set
+# CONFIG_PKG_USING_RTI is not set
+
+#
+# IoT - internet of things
+#
+# CONFIG_PKG_USING_PAHOMQTT is not set
+# CONFIG_PKG_USING_WEBCLIENT is not set
+# CONFIG_PKG_USING_MONGOOSE is not set
+# CONFIG_PKG_USING_WEBTERMINAL is not set
+# CONFIG_PKG_USING_CJSON is not set
+# CONFIG_PKG_USING_LJSON is not set
+# CONFIG_PKG_USING_EZXML is not set
+# CONFIG_PKG_USING_NANOPB is not set
+# CONFIG_PKG_USING_GAGENT_CLOUD is not set
+
+#
+# Wi-Fi
+#
+
+#
+# Marvell WiFi
+#
+# CONFIG_PKG_USING_WLANMARVELL is not set
+
+#
+# Wiced WiFi
+#
+# CONFIG_PKG_USING_WLAN_WICED is not set
+# CONFIG_PKG_USING_COAP is not set
+# CONFIG_PKG_USING_NOPOLL is not set
+
+#
+# security packages
+#
+# CONFIG_PKG_USING_MBEDTLS is not set
+# CONFIG_PKG_USING_libsodium is not set
+# CONFIG_PKG_USING_TINYCRYPT is not set
+
+#
+# language packages
+#
+# CONFIG_PKG_USING_JERRYSCRIPT is not set
+# CONFIG_PKG_USING_MICROPYTHON is not set
+
+#
+# multimedia packages
+#
+# CONFIG_PKG_USING_OPENMV is not set
+
+#
+# tools packages
+#
+# CONFIG_PKG_USING_CMBACKTRACE is not set
+# CONFIG_PKG_USING_EASYLOGGER is not set
+# CONFIG_PKG_USING_SYSTEMVIEW is not set
+# CONFIG_PKG_USING_IPERF is not set
+
+#
+# miscellaneous packages
+#
+# CONFIG_PKG_USING_FASTLZ is not set
+# CONFIG_PKG_USING_MINILZO is not set
+
+#
+# example package: hello
+#
+# CONFIG_PKG_USING_HELLO is not set
+# CONFIG_PKG_USING_MULTIBUTTON is not set
+CONFIG_TINA_USING_UART0=y
+# CONFIG_TINA_USING_UART1 is not set
+CONFIG_TINA_USING_UART2=y
+CONFIG_RT_USING_CPU_FFS=y
+CONFIG_RT_MAIN_THREAD_STACK_SIZE=2048

+ 29 - 0
bsp/allwinner_tina/Kconfig

@@ -0,0 +1,29 @@
+mainmenu "RT-Thread Configuration"
+
+config $BSP_DIR
+    string
+    option env="BSP_ROOT"
+    default "."
+
+config $RTT_DIR
+    string
+    option env="RTT_ROOT"
+    default "../.."
+
+# you can change the RTT_ROOT default "../.." to your rtthread_root,
+# example : default "F:/git_repositories/rt-thread"
+
+config $PKGS_DIR
+    string
+    option env="PKGS_ROOT"
+    default "packages"
+
+source "$RTT_DIR/KConfig"
+source "$PKGS_DIR/KConfig"
+
+config SOC_TINA
+    bool 
+    select ARCH_ARM_ARM9
+    default y
+
+source "$BSP_DIR/drivers/Kconfig"

+ 132 - 0
bsp/allwinner_tina/README.md

@@ -0,0 +1,132 @@
+# Allwinner tina板级支持包
+
+## 1. 简介
+
+Allwinner tina 是由全志公司推出的ARM9内核的SOC
+包括如下硬件特性:
+
+| 硬件 | 描述 |
+| -- | -- |
+|芯片型号| tina系列 |
+|CPU| ARM9 |
+|主频| 408MHz |
+|片内DDR | 32MB |
+|板载SPI Nor Flash | 8/16MB|
+
+## 2. 编译说明
+
+| 环境 | 说明 |
+| --- | --- |
+|PC操作系统|Linux/MacOS|
+|编译器|arm-none-eabi-gcc version 6.3.1 20170620 (release)|
+|构建工具|scons|
+1) 下载源码
+
+```
+    git clone https://github.com/RT-Thread/rt-thread.git
+```
+2) 配置工程并准备env
+```
+    cd rt-thread/bsp/allwinner_tina
+    scons --menuconfig
+    source ~/.env/env.sh
+    pkgs --upgrade
+    
+```
+3) 编译安装下载工具
+```
+    pushd /tmp
+    git clone https://github.com/Icenowy/sunxi-tools.git
+    pushd sunxi-tools
+    git checkout -b f1c100s
+    git checkout -b f1c100s origin/f1c100s
+    make
+    sudo make install
+    popd
+    popd
+```
+4) 编译
+```
+    scons
+```
+如果编译正确无误,会产生rtthread.elf、rtthread.bin文件。其中rtthread.bin需要烧写到设备中进行运行。
+
+## 3. 烧写及执行
+**烧写工具目前仅支持Linux/MacOS环境,请在Linux/MaxOS环境下进行烧写操作**
+当正确编译产生出rtthread.bin映像文件后可以使用下面的方式来烧写到设备中。
+
+1)编译初始化引导文件
+编译依赖 arm-eabi-gcc
+```
+    pushd ../../..
+    git clone https://github.com/uestczyh222/tina-spl.git
+    pushd tina-spl
+    make
+    cp output/f1c100s.bin ../rt-thread/bsp/tina/tina-spl.bin
+    popd
+    popd
+```
+2)下载并运行
+
+```
+1.短接flash 1、4脚(当flash中无可引导代码时无需此步骤)
+2.连接USB
+3.松开短接的引脚
+4.输入下列指令
+```
+
+```
+    sudo sunxi-fel -p write  0x00000000 tina-spl.bin
+    sudo sunxi-fel exec 0x00000000
+    sudo sunxi-fel -p write  0x80000000 rtthread.bin
+    sudo sunxi-fel exec 0x80000000
+```
+
+### 3.1 运行结果
+
+如果编译 & 烧写无误,会在串口0上看到RT-Thread的启动logo信息:
+
+```
+ \ | /
+- RT -     Thread Operating System
+ / | \     3.0.2 build Feb  8 2018
+ 2006 - 2017 Copyright by rt-thread team
+periph_get_pll_clk:600000000
+cpu_get_clk:408000000
+ahb_get_clk:200000000
+apb_get_clk:100000000
+msh />
+```
+
+
+## 4. 驱动支持情况及计划
+
+| 驱动 | 支持情况  |  备注  |
+| ------ | :----:  | :------:  |
+| UART | 支持 | UART0/1/2 |
+| GPIO | 支持 | / |
+| clock | 支持 | / |
+| mmu | 支持 | / |
+
+
+### 4.1 IO在板级支持包中的映射情况
+
+| IO号 | 板级包中的定义 |
+| -- | -- |
+| PE8 | USART2 RX |
+| PE7 | USART2 TX |
+| PA3 | USART1 RX |
+| PA2 | USART1 TX |
+| PE1 | USART0 TX |
+| PE0 | USART0 RX |
+
+
+## 5. 联系人信息
+
+维护人:
+[uestczyh222][4] < [lymz@foxmail.com][5] >
+
+
+  [1]: https://www.rt-thread.org/page/download.html
+  [4]: https://github.com/uestczyh222
+  [5]: mailto:lymz@foxmail.com

+ 14 - 0
bsp/allwinner_tina/SConscript

@@ -0,0 +1,14 @@
+# for module compiling
+import os
+from building import *
+
+cwd = GetCurrentDir()
+objs = []
+list = os.listdir(cwd)
+
+for d in list:
+    path = os.path.join(cwd, d)
+    if os.path.isfile(os.path.join(path, 'SConscript')):
+        objs = objs + SConscript(os.path.join(d, 'SConscript'))
+
+Return('objs')

+ 27 - 0
bsp/allwinner_tina/SConstruct

@@ -0,0 +1,27 @@
+import os
+import sys
+import rtconfig
+
+from rtconfig import RTT_ROOT
+
+sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')]
+from building import *
+
+TARGET = 'rtthread.' + rtconfig.TARGET_EXT
+
+env = Environment(tools = ['mingw'],
+    AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS,
+    CC = rtconfig.CC, CCFLAGS = rtconfig.CFLAGS,
+    CXX = rtconfig.CC, CXXFLAGS = rtconfig.CXXFLAGS,
+    AR = rtconfig.AR, ARFLAGS = '-rc',
+    LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS)
+env.PrependENVPath('PATH', rtconfig.EXEC_PATH)
+
+Export('RTT_ROOT')
+Export('rtconfig')
+
+# prepare building environment
+objs = PrepareBuilding(env, RTT_ROOT, has_libcpu=True)
+
+# make a building
+DoBuilding(TARGET, objs)

+ 9 - 0
bsp/allwinner_tina/applications/SConscript

@@ -0,0 +1,9 @@
+from building import *
+
+cwd     = GetCurrentDir()
+src     = Glob('*.c')
+CPPPATH = [cwd, str(Dir('#'))]
+
+group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')

+ 36 - 0
bsp/allwinner_tina/applications/main.c

@@ -0,0 +1,36 @@
+/*
+ * File      : main.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2017, RT-Thread Development Team
+ *
+ *  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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2017-5-30      Bernard      the first version
+ */
+
+#include "rtthread.h"
+#include "drv_clock.h"
+
+int main(int argc, char **argv)
+{
+    rt_kprintf("periph_get_pll_clk:%d\n", periph_get_pll_clk());
+    rt_kprintf("cpu_get_clk:%d\n", cpu_get_clk());
+    rt_kprintf("ahb_get_clk:%d\n", ahb_get_clk());
+    rt_kprintf("apb_get_clk:%d\n", apb_get_clk());
+
+    return 0;
+}

+ 16 - 0
bsp/allwinner_tina/drivers/Kconfig

@@ -0,0 +1,16 @@
+
+
+config TINA_USING_UART0
+    bool "Using UART0"
+    select RT_USING_SERIAL
+    default n
+
+config TINA_USING_UART1
+    bool "Using UART1"
+    select RT_USING_SERIAL
+    default y
+
+config TINA_USING_UART2
+    bool "Using UART2"
+    select RT_USING_SERIAL
+    default y

+ 16 - 0
bsp/allwinner_tina/drivers/SConscript

@@ -0,0 +1,16 @@
+from building import *
+
+cwd  = GetCurrentDir()
+src  = Glob('*.c')
+list = os.listdir(cwd)
+CPPPATH = [cwd]
+objs = []
+
+group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH)
+
+for d in list:
+    path = os.path.join(cwd, d)
+    if os.path.isfile(os.path.join(path, 'SConscript')):
+        objs = objs + SConscript(os.path.join(d, 'SConscript'))
+objs = objs + group
+Return('objs')

+ 117 - 0
bsp/allwinner_tina/drivers/board.c

@@ -0,0 +1,117 @@
+/*
+ * File      : board.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2017, RT-Thread Development Team
+ *
+ *  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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2017-5-30      Bernard      the first version
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+
+#include "board.h"
+#include "drv_uart.h"
+#include "interrupt.h"
+#include "mmu.h"
+
+static void os_clock_irq_handle(int irqno, void *param)
+{
+    volatile rt_uint32_t *temp_addr = (rt_uint32_t *)(0x01C20C00 + 0x04);
+
+    /* clear timer */
+    *temp_addr |= 0x01;
+
+    rt_tick_increase();
+}
+
+static void mmu_init(void)
+{
+    struct mem_desc r6_mem_desc[] =
+    {
+        { 0x00000000, 0xFFFFFFFF, 0x00000000, RW_NCNB },     /* None cached for 4G memory */
+        { 0x80000000, 0x82000000 - 1, 0x80000000, RW_CB },   /* 32M cached SDRAM memory */
+        //{ 0x00000000, 0x00001000-1, 0x80000000, RW_CB },         /* isr vector table */
+        //here not set mmu
+        //start_gcc.S Copy vector to the correct address
+    };
+
+    rt_hw_mmu_init(r6_mem_desc, sizeof(r6_mem_desc) / sizeof(r6_mem_desc[0]));
+}
+
+static void os_clock_init(void)
+{
+    rt_uint32_t temp;
+    volatile rt_uint32_t *temp_addr;
+
+    /* reload value */
+    temp = 0xB71B00 / RT_TICK_PER_SECOND;
+    temp_addr = (rt_uint32_t *)(0x01C20C00 + 0x14);
+    *temp_addr = temp;
+
+    /* continuous | /2 | 24Mhz |  reload*/
+    temp = (0x00 << 7) | (0x01 << 4) | (0x01 << 2) | (0x00 << 1);
+    temp_addr = (rt_uint32_t *)(0x01C20C00 + 0x10);
+    *temp_addr &= 0xffffff00;
+    *temp_addr |= temp;
+
+    /* open timer irq */
+    temp = 0x01 << 0;
+    temp_addr = (rt_uint32_t *)(0x01C20C00);
+    *temp_addr |= temp;
+
+    /* set init value */
+    temp_addr = (rt_uint32_t *)(0x01C20C00 + 0x18);
+    *temp_addr = 0;
+
+    /* begin run timer */
+    temp = 0x01 << 0;
+    temp_addr = (rt_uint32_t *)(0x01C20C00 + 0x10);
+    *temp_addr |= temp;
+
+    temp_addr = (rt_uint32_t *)(0x01C20C00);
+    /* set irq handle */
+    rt_hw_interrupt_install(TIMER0_INTERRUPT, os_clock_irq_handle, (void *)temp_addr, "timer");
+    rt_hw_interrupt_umask(TIMER0_INTERRUPT);
+
+}
+
+void rt_hw_board_init(void)
+{
+    mmu_init();
+
+    rt_hw_interrupt_init();
+
+#ifdef RT_USING_HEAP
+    /* init memory system */
+    rt_system_heap_init(RT_HW_HEAP_BEGIN, RT_HW_HEAP_END);
+#endif
+    /* init hardware interrupt */
+    rt_hw_uart_init();
+
+#ifdef RT_USING_CONSOLE
+    /* set console device */
+    rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
+#endif /* RT_USING_CONSOLE */
+
+    os_clock_init();
+
+#ifdef RT_USING_COMPONENTS_INIT
+    rt_components_board_init();
+#endif
+}

+ 38 - 0
bsp/allwinner_tina/drivers/board.h

@@ -0,0 +1,38 @@
+/*
+ * File      : board.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2017, RT-Thread Development Team
+ *
+ *  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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2017-5-30      Bernard      the first version
+ */
+
+#ifndef _BOARD_H_
+#define _BOARD_H_
+
+#include <stdint.h>
+
+extern unsigned char __bss_start;
+extern unsigned char __bss_end;
+
+#define RT_HW_HEAP_BEGIN    (void*)&__bss_end
+#define RT_HW_HEAP_END      (void*)(0x80000000 + 32 * 1024 * 1024)
+
+void rt_hw_board_init(void);
+
+#endif

+ 527 - 0
bsp/allwinner_tina/drivers/drv_clock.c

@@ -0,0 +1,527 @@
+/*
+ * File      : drv_clock.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2017, RT-Thread Development Team
+ *
+ *  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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-02-08     RT-Thread    the first version
+ */
+#include <rtthread.h>
+#include <rthw.h>
+
+#include "drv_clock.h"
+
+int cpu_get_pll_clk(void)
+{
+    rt_uint32_t reg;
+    int n, k, m, p;
+
+    reg = CCU->pll_cpu_ctrl;
+    if (!(reg & (0x01 << 31)))
+        return 0;
+
+    p = PLL_CPU_DIV_P(reg) + 1;
+    n = PLL_CPU_FACTOR_N(reg) + 1;
+    k = PLL_CPU_FACTOR_K(reg) + 1;
+    m = PLL_CPU_FACTOR_M(reg) + 1;
+    //(24MHz*n*k)/(m*p)
+    return (_24MHZ_ * n * k) / (m * p);
+}
+
+int audio_get_pll_clk(void)
+{
+    rt_uint32_t reg;
+    unsigned char n, m;
+
+    reg = CCU->pll_audio_ctrl;
+    if (!(reg & (0x01 << 31)))
+        return 0;
+
+    n = PLL_AUDIO_FACTOR_N(reg) + 1;
+    m = PLL_AUDIO_PREDIV_M(reg) + 1;
+
+    //24MHz*n*2/m
+    return _24MHZ_ * 2 * n / m;
+}
+
+int video_get_pll_clk(void)
+{
+    rt_uint32_t reg;
+    int n, m;
+
+    reg = CCU->pll_video_ctrl;
+    if (!(reg & (0x01 << 31)))
+        return 0;
+
+    if (reg & PLL_VIDEO_MODE_SEL)
+    {
+        //(24MHz*n)/m
+        n = PLL_VIDEO_FACTOR_N(reg) + 1;
+        m = PLL_VIDEO_PREDIV_M(reg) + 1;
+        return (_24MHZ_ * n) / m;
+    }
+
+    if (reg & PLL_VIDEO_FRAC_CLK_OUT)
+        return 270000000;
+    else
+        return 297000000;
+
+    return 0;
+}
+
+int ve_get_pll_clk(void)
+{
+    rt_uint32_t reg;
+    int n, m;
+
+    reg = CCU->pll_ve_ctrl;
+    if (!(reg & (0x01 << 31)))
+        return 0;
+
+    if (reg & PLL_VE_MODE_SEL)
+    {
+        //(24MHz*n)/m
+        n = PLL_VE_FACTOR_N(reg) + 1;
+        m = PLL_VE_PREDIV_M(reg) + 1;
+
+        return (_24MHZ_ * n) / m;
+    }
+
+    if (reg & PLL_VE_FRAC_CLK_OUT)
+        return 297000000;
+    else
+        return 270000000;
+
+    return 0;
+}
+
+int ddr_get_pll_clk(void)
+{
+    rt_uint32_t reg;
+    int n, k, m;
+
+    reg = CCU->pll_ddr_ctrl;
+    if (!(reg & (0x01 << 31)))
+        return 0;
+
+    n = PLL_DDR_FACTOR_N(reg) + 1;
+    k = PLL_DDR_FACTOR_K(reg) + 1;
+    m = PLL_DDR_FACTOR_M(reg) + 1;
+
+    //(24MHz*n*k)/m
+    return (_24MHZ_ * n * k) / m;
+}
+
+int periph_get_pll_clk(void)
+{
+    rt_uint32_t reg;
+    int n, k;
+
+    reg = CCU->pll_periph_ctrl;
+    if (!(reg & (0x01 << 31)))
+        return 0;
+
+    n = PLL_PERIPH_FACTOR_N(reg) + 1;
+    k = PLL_PERIPH_FACTOR_K(reg) + 1;
+
+    return _24MHZ_ * n * k;
+}
+
+static int cpu_get_clk_src(void)
+{
+    return (CCU->cpu_clk_src >> 16) & 0x3;
+}
+
+int cpu_get_clk(void)
+{
+    rt_uint32_t reg;
+    int cpusrc;
+
+    reg = CCU->ahb_apb_hclkc_cfg;
+    cpusrc = cpu_get_clk_src();
+
+    if (cpusrc == CLK_PLL_SRC)
+        return (cpu_get_pll_clk() / (HCLKC_DIV(reg) + 1));
+    else if (cpusrc == CLK_OSC24M_SRC)
+        return _24MHZ_ / (HCLKC_DIV(reg) + 1);
+    else
+        return _32KHZ_ / (HCLKC_DIV(reg) + 1);  //猜测 内部32KHz时钟
+
+    return 0;
+}
+
+int ahb_get_clk(void)
+{
+    rt_uint32_t reg;
+    int sel, spd;
+
+    reg = CCU->ahb_apb_hclkc_cfg;
+    sel = AHB_SRC_SEL(reg);
+
+    if (sel == CLK_PLL_SRC)
+    {
+        spd = cpu_get_clk();
+        return spd / (1 << AHB_CLK_DIV(reg));
+    }
+    else if (sel == PRE_DIV_SRC)
+    {
+        spd = periph_get_pll_clk();
+        return spd / (AHB_PRE_DIV(reg) + 1) / (1 << AHB_CLK_DIV(reg));
+    }
+    else if (sel == CLK_OSC24M_SRC)
+        return _24MHZ_ / (1 << AHB_CLK_DIV(reg));
+    else
+        return _32KHZ_ / (1 << AHB_CLK_DIV(reg));
+}
+
+int apb_get_clk(void)
+{
+    rt_uint32_t reg;
+    int spd;
+
+    reg = CCU->ahb_apb_hclkc_cfg;
+    spd = ahb_get_clk();
+    // 0x:/2 10:/4 11:/8
+    if (!(APH_CLK_PATIO(reg) & 0x1))
+        return spd / 2;
+    else
+        return spd / (1 << APH_CLK_PATIO(reg));
+}
+
+
+static rt_err_t wait_pll_stable(rt_uint32_t base)
+{
+    rt_uint32_t rval = 0;
+    volatile int time = 0xfff;
+
+    do
+    {
+        rval = *((volatile rt_uint32_t *)base);
+        time--;
+    }
+    while (time && !(rval & (1 << 28)));
+
+    return !time;
+}
+
+rt_err_t cpu_set_pll_clk(int clk)
+{
+    rt_uint32_t cpu_src;
+    int p = 0, k = 1, m = 1, n = 0;
+
+    if (clk == 0)
+        return RT_EINVAL;
+
+    if (clk > 1152000000)
+    {
+        k = 2;
+    }
+    else if (clk > 768000000)
+    {
+        k = 3;
+        m = 2;
+    }
+
+    n = clk / (_24MHZ_ * k / m) - 1;
+    cpu_src = (CCU->cpu_clk_src >> 16) & 0x3;
+    CCU->cpu_clk_src = CLK_OSC24M_SRC << 16;
+    CCU->pll_cpu_ctrl &= ~(0x1 << 31);
+    //PLL1 rate = ((24000000 * n * k) >> 0) / m   (p is ignored)
+    CCU->pll_cpu_ctrl = (0x1 << 31) | (m << 0) | (k << 4) | (n << 8) | (p << 16);
+    if (wait_pll_stable((rt_uint32_t)(&CCU->pll_cpu_ctrl)))
+        return RT_ERROR;
+
+    CCU->cpu_clk_src = cpu_src << 16;
+
+    return RT_EOK;
+}
+
+rt_err_t audio_set_pll_clk(int clk)
+{
+    int n = 0, m = 0;
+    int n_temp = clk;
+    int m_temp = _24MHZ_ * 2;
+
+    if ((clk > 200000000) || (clk < 20000000))
+        return RT_EINVAL;
+
+    if (clk == 0)
+    {
+        CCU->pll_audio_ctrl &= ~(0x1 << 31);
+        return RT_EOK;
+    }
+
+    while (n_temp != m_temp)
+    {
+        if (n_temp > m_temp)
+        {
+            n_temp = n_temp - m_temp;
+        }
+        else if (m_temp > n_temp)
+        {
+            m_temp = m_temp - n_temp;
+        }
+    }
+
+    n = clk / n_temp;
+    m = _24MHZ_ * 2 / m_temp;
+    if ((n > 128) || (m > 32) || (clk != (_24MHZ_ * n * 2) / m))
+        return RT_ERROR;
+
+    CCU->pll_audio_ctrl &= ~(0x1 << 31);
+    n = (n - 1) & 0x7f;
+    m = (m - 1) & 0x1f;
+    //clk = (24 * n * 2) / m
+    CCU->pll_audio_ctrl = (0x1 << 31) | (0x0 << 24) | (n << 8) | m;
+
+    if (wait_pll_stable((rt_uint32_t)(&CCU->pll_audio_ctrl)))
+        return RT_ERROR;
+    else
+        return RT_EOK;
+}
+
+rt_err_t video_set_pll_clk(int clk)
+{
+    int n = 0, m = 0;
+    int n_temp = clk;
+    int m_temp = _24MHZ_;
+
+    if ((clk > 600000000) || (clk < 30000000))
+        return RT_EINVAL;
+
+    if (clk == 0)
+    {
+        CCU->pll_video_ctrl &= ~(0x1 << 31);
+        return RT_EOK;
+    }
+
+    while (n_temp != m_temp)
+    {
+        if (n_temp > m_temp)
+        {
+            n_temp = n_temp - m_temp;
+        }
+        else if (m_temp > n_temp)
+        {
+            m_temp = m_temp - n_temp;
+        }
+    }
+
+    n = clk / n_temp;
+    m = _24MHZ_ / m_temp;
+
+    if ((n > 128) || (m > 16) || (clk != (_24MHZ_ * n) / m))
+        return RT_ERROR;
+
+    CCU->pll_video_ctrl &= ~(0x1 << 31);
+    n = (n - 1) & 0x7f;
+    m = (m - 1) & 0xf;
+    //speed = (24*n)/m
+    CCU->pll_video_ctrl = (0x1 << 31) | (0x0 << 30) | (0x1 << 24) | (n << 8) | m;
+
+    if (wait_pll_stable((rt_uint32_t)(&CCU->pll_video_ctrl)))
+        return RT_ERROR;
+    else
+        return RT_EOK;
+}
+
+rt_err_t ve_set_pll_clk(int clk)
+{
+    int n = 0, m = 0;
+    int n_temp = clk;
+    int m_temp = _24MHZ_;
+
+    if ((clk > 600000000) || (clk < 30000000))
+        return RT_EINVAL;
+
+    if (clk == 0)
+    {
+        CCU->pll_ve_ctrl &= ~(0x1 << 31);
+        return RT_EOK;
+    }
+
+    while (n_temp != m_temp)
+    {
+        if (n_temp > m_temp)
+        {
+            n_temp = n_temp - m_temp;
+        }
+        else if (m_temp > n_temp)
+        {
+            m_temp = m_temp - n_temp;
+        }
+    }
+
+    n = clk / n_temp;
+    m = _24MHZ_ / m_temp;
+
+    if ((n > 128) || (m > 16) || (clk != (_24MHZ_ * n) / m))
+        return RT_ERROR;
+
+    CCU->pll_ve_ctrl &= ~(0x1 << 31);
+    n = (n - 1) & 0x7f;
+    m = (m - 1) & 0xf;
+    //clk = (24 * n) / m
+    CCU->pll_ve_ctrl = (0x1 << 31) | (0x1 << 24) | (n << 8) | m;
+    if (wait_pll_stable((rt_uint32_t)(&CCU->pll_ve_ctrl)))
+        return RT_ERROR;
+    else
+        return RT_EOK;
+}
+
+rt_err_t periph_set_pll_clk(int clk)
+{
+    rt_uint32_t clk_src;
+    rt_uint32_t temp_data;
+    int n = 0, k = 0;
+
+    if ((clk > 1800000000) || (clk < 200000000) || (clk == 0) || (clk % _24MHZ_ != 0))
+        return RT_EINVAL;
+
+    n = clk / _24MHZ_;
+
+    for (k = 2; ((n > 32) || (k < 5)); k++)
+    {
+        if ((n % k) != 0)
+            n /= k;
+    }
+
+    if ((n > 32) || (k > 4) || (clk != (_24MHZ_ * n * k)))
+        return RT_ERROR;
+    temp_data = CCU->ahb_apb_hclkc_cfg;
+    clk_src = (temp_data >> 12) & 0x3;
+    temp_data &= ~(0x3 << 12);
+    temp_data |= (CLK_PLL_SRC << 12);
+    CCU->ahb_apb_hclkc_cfg = temp_data;
+    CCU->pll_periph_ctrl &= ~(0x1 << 31);
+    n = (n - 1) & 0x1f;
+    k = (k - 1) & 0x3;
+    //clk = 24 * n *k
+    CCU->pll_periph_ctrl = (0x1 << 31) | (0x1 << 18) | (n << 8) | (k << 4) || (0x1);
+    if (wait_pll_stable((rt_uint32_t)(&CCU->pll_periph_ctrl)))
+        return RT_ERROR;
+
+    temp_data = CCU->ahb_apb_hclkc_cfg;
+    temp_data &= ~(0x3 << 12);
+    temp_data |= (clk_src << 12);
+    CCU->ahb_apb_hclkc_cfg = temp_data;
+
+    return RT_EOK;
+}
+
+rt_err_t cpu_set_clk(int clk)
+{
+    if (clk < _24MHZ_)
+        return RT_EINVAL;
+
+    if (clk == cpu_get_clk())
+        return RT_EOK;
+
+    CCU->cpu_clk_src = CLK_OSC24M_SRC << 16;
+    if (clk == _24MHZ_)
+        return RT_EOK;
+
+    if (cpu_set_pll_clk(clk))
+        return RT_ERROR;
+
+    CCU->ahb_apb_hclkc_cfg &= ~(0x3 << 16);
+    CCU->cpu_clk_src = CLK_PLL_SRC << 16;
+
+    return RT_EOK;
+}
+
+rt_err_t bus_gate_clk_enalbe(enum bus_gate bus)
+{
+    rt_uint32_t offset;
+    rt_uint32_t gate_reg;
+
+    offset = bus & 0xfff;
+    gate_reg = bus >> BUS_GATE_OFFSET_BIT;
+
+    if (gate_reg == 0x00)
+        CCU->bus_clk_gating0 |= (0x1 << offset);
+    else if (gate_reg == 0x01)
+        CCU->bus_clk_gating1 |= (0x1 << offset);
+    else if (gate_reg == 0x02)
+        CCU->bus_clk_gating2 |= (0x1 << offset);
+    else
+        return RT_EINVAL;
+
+    return RT_EOK;
+}
+
+rt_err_t bus_gate_clk_disalbe(enum bus_gate bus)
+{
+    rt_uint32_t offset;
+    rt_uint32_t gate_reg;
+
+    offset = bus & 0xfff;
+    gate_reg = bus >> BUS_GATE_OFFSET_BIT;
+
+    if (gate_reg == 0x00)
+        CCU->bus_clk_gating0 &= ~(0x1 << offset);
+    else if (gate_reg == 0x01)
+        CCU->bus_clk_gating1 &= ~(0x1 << offset);
+    else if (gate_reg == 0x02)
+        CCU->bus_clk_gating2 &= ~(0x1 << offset);
+    else
+        return RT_EINVAL;
+
+    return RT_EOK;
+}
+
+rt_err_t bus_software_reset_enalbe(enum bus_gate bus)
+{
+    rt_uint32_t offset;
+    rt_uint32_t gate_reg;
+
+    offset = bus & 0xfff;
+    gate_reg = bus >> BUS_GATE_OFFSET_BIT;
+
+    if (gate_reg == 0x00)
+        CCU->bus_soft_rst0 |= (0x1 << offset);
+    else if (gate_reg == 0x01)
+        CCU->bus_soft_rst1 |= (0x1 << offset);
+    else if (gate_reg == 0x02)
+        CCU->bus_soft_rst2 |= (0x1 << offset);
+    else
+        return RT_EINVAL;
+
+    return RT_EOK;
+}
+
+rt_err_t bus_software_reset_disalbe(enum bus_gate bus)
+{
+    rt_uint32_t offset;
+    rt_uint32_t gate_reg;
+
+    offset = bus & 0xfff;
+    gate_reg = bus >> BUS_GATE_OFFSET_BIT;
+
+    if (gate_reg == 0x00)
+        CCU->bus_soft_rst0 &= ~(0x1 << offset);
+    else if (gate_reg == 0x01)
+        CCU->bus_soft_rst1 &= ~(0x1 << offset);
+    else if (gate_reg == 0x02)
+        CCU->bus_soft_rst2 &= ~(0x1 << offset);
+    else
+        return RT_EINVAL;
+
+    return RT_EOK;
+}
+

+ 252 - 0
bsp/allwinner_tina/drivers/drv_clock.h

@@ -0,0 +1,252 @@
+/*
+ * File      : drv_clock.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2017, RT-Thread Development Team
+ *
+ *  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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-02-08     RT-Thread    the first version
+ */
+#ifndef __DRV_CLOCK_H__
+#define __DRV_CLOCK_H__
+
+/* PLL state */
+#define PLL_ENBALE              (0x1)
+#define PLL_STABLE              (0x2)
+
+/* Clock source selection */
+#define CLK_LOSC_SRC            (0x00)
+#define CLK_OSC24M_SRC          (0x01)
+#define CLK_PLL_SRC             (0x02)
+#define PRE_DIV_SRC             (0x03)
+
+/*  */
+#define BE_GATING_DRAM          (0x1<<26)
+#define FE_GATING_DRAM          (0x1<<24)
+#define TVD_GATING_DRAM         (0x1<<3)
+#define DEINTERLACE_GATING_DRAM (0x1<<2)
+#define CSI_GATING_DRAM         (0x1<<1)
+#define VE_GATING_DRAM          (0x1<<0)
+
+
+/*  */
+#define TCON_PLL_VIDEO_X1       (0x000)
+#define TCON_PLL_VIDEO_X2       (0x002)
+
+
+#define PLL_CPU_ENABLE_STATE            (0x1<<31)
+#define PLL_CPU_HAS_BEEN_STABLE         (0x1<<28)
+#define PLL_CPU_DIV_P(reg)              ((reg>>16)&0x3)
+#define PLL_CPU_FACTOR_N(reg)           ((reg>>8)&0x1f)
+#define PLL_CPU_FACTOR_K(reg)           ((reg>>4)&0x3)
+#define PLL_CPU_FACTOR_M(reg)           ((reg)&0x3)
+
+#define PLL_AUDIO_ENABLE_STATE          (0x1<<31)
+#define PLL_AUDIO_HAS_BEEN_STABLE       (0x1<<28)
+#define PLL_AUDIO_FACTOR_N(reg)         ((reg>>8)&0x7f)
+#define PLL_AUDIO_PREDIV_M(reg)         ((reg)&0x1f)
+
+#define PLL_VIDEO_ENABLE_STATE          (0x1<<31)
+#define PLL_VIDEO_MODE                  (0x1<<30)
+#define PLL_VIDEO_HAS_BEEN_STABLE       (0x1<<28)
+#define PLL_VIDEO_FRAC_CLK_OUT          (0x1<<25)
+#define PLL_VIDEO_MODE_SEL              (0x1<<24)
+#define PLL_VIDEO_SDM_EN                (0x1<<20)
+#define PLL_VIDEO_FACTOR_N(reg)         ((reg>>8)&0x7f)
+#define PLL_VIDEO_PREDIV_M(reg)         (reg&0xf)
+
+#define PLL_VE_ENABLE_STATE             (0x1<<31)
+#define PLL_VE_HAS_BEEN_STABLE          (0x1<<28)
+#define PLL_VE_FRAC_CLK_OUT             (0x1<<25)
+#define PLL_VE_MODE_SEL                 (0x1<<24)
+#define PLL_VE_FACTOR_N(reg)            ((reg>>8)&0x7f)
+#define PLL_VE_PREDIV_M(reg)            (reg&0xf)
+
+#define PLL_DDR_ENABLE_STATE            (0x1<<31)
+#define PLL_DDR_HAS_BEEN_STABLE         (0x1<<28)
+#define SDRAM_SIGMA_DELTA_EN            (0x1<<24)
+#define PLL_DDR_CFG_UPDATE              (0x1<<20)
+#define PLL_DDR_FACTOR_N(reg)           ((reg>>8)&0x1f)
+#define PLL_DDR_FACTOR_K(reg)           ((reg>>4)&0x3)
+#define PLL_DDR_FACTOR_M(reg)           ((reg)&0x3)
+
+#define PLL_PERIPH_ENABLE_STATE         (0x1<<31)
+#define PLL_PERIPH_HAS_BEEN_STABLE      (0x1<<28)
+#define PLL_PERIPH_24M_OUT_EN           (0x1<<18)
+#define PLL_PERIPH_24M_POST_DIV(reg)    ((reg>>16)&0x3)
+#define PLL_PERIPH_FACTOR_N(reg)        ((reg>>8)&0x1f)
+#define PLL_PERIPH_FACTOR_K(reg)        ((reg>>4)&0x3)
+#define PLL_PERIPH_FACTOR_M(reg)        (reg&0x3)
+
+#define HCLKC_DIV(reg)                  ((reg>>16)&0x3)
+#define AHB_SRC_SEL(reg)                ((reg>>12)&0x3)
+#define AHB_CLK_DIV(reg)                ((reg>>4)&0x3)
+#define AHB_PRE_DIV(reg)                ((reg>>6)&0x3)
+#define APH_CLK_PATIO(reg)              ((reg>>8)&0x3)
+
+
+#define CCM_MMC_CTRL_OSCM24             (0x00)
+#define CCM_MMC_CTRL_PLL_PERIPH         (0x01)
+
+#define CCU_BASE_ADDR      (0x01C20000)
+
+#define _24MHZ_     (24000000U)
+#define _32KHZ_     (32000U)
+
+/* GATE */
+
+#define BUS_GATE_OFFSET_BIT    (12)
+
+enum bus_gate
+{
+    USB_OTG_GATING     = (0x18 | (0x0 << BUS_GATE_OFFSET_BIT)),
+    SPI1_GATING        = (0x15 | (0x0 << BUS_GATE_OFFSET_BIT)),
+    SPI0_GATING        = (0x14 | (0x0 << BUS_GATE_OFFSET_BIT)),
+    SDRAM_GATING       = (0x0E | (0x0 << BUS_GATE_OFFSET_BIT)),
+    SD1_GATING         = (0x09 | (0x0 << BUS_GATE_OFFSET_BIT)),
+    SD0_GATING         = (0x08 | (0x0 << BUS_GATE_OFFSET_BIT)),
+    DMA_GATING         = (0x06 | (0x0 << BUS_GATE_OFFSET_BIT)),
+
+    DEFE_GATING        = (0x0E | (0x1 << BUS_GATE_OFFSET_BIT)),
+    DEBE_GATING        = (0x0C | (0x1 << BUS_GATE_OFFSET_BIT)),
+    TVE_GATING         = (0x0A | (0x1 << BUS_GATE_OFFSET_BIT)),
+    TVD_GATING         = (0x09 | (0x1 << BUS_GATE_OFFSET_BIT)),
+    CSI_GATING         = (0x08 | (0x1 << BUS_GATE_OFFSET_BIT)),
+    DEINTERLACE_GATING = (0x05 | (0x1 << BUS_GATE_OFFSET_BIT)),
+    LCD_GATING         = (0x04 | (0x1 << BUS_GATE_OFFSET_BIT)),
+    VE_GATING          = (0x00 | (0x1 << BUS_GATE_OFFSET_BIT)),
+
+    UART2_GATING       = (0x16 | (0x2 << BUS_GATE_OFFSET_BIT)),
+    UART1_GATING       = (0x15 | (0x2 << BUS_GATE_OFFSET_BIT)),
+    UART0_GATING       = (0x14 | (0x2 << BUS_GATE_OFFSET_BIT)),
+    TWI2_GATING        = (0x12 | (0x2 << BUS_GATE_OFFSET_BIT)),
+    TWI1_GATING        = (0x11 | (0x2 << BUS_GATE_OFFSET_BIT)),
+    TWI0_GATING        = (0x10 | (0x2 << BUS_GATE_OFFSET_BIT)),
+    DAUDIO_GATING      = (0x0C | (0x2 << BUS_GATE_OFFSET_BIT)),
+    RSB_GATING         = (0x03 | (0x2 << BUS_GATE_OFFSET_BIT)),
+    CIR_GATING         = (0x02 | (0x2 << BUS_GATE_OFFSET_BIT)),
+    OWA_GATING         = (0x01 | (0x2 << BUS_GATE_OFFSET_BIT)),
+    AUDIO_CODEC_GATING = (0x00 | (0x2 << BUS_GATE_OFFSET_BIT)),
+};
+
+struct tina_ccu
+{
+    volatile rt_uint32_t pll_cpu_ctrl;         /* 0x000 */
+    volatile rt_uint32_t reserved0;
+    volatile rt_uint32_t pll_audio_ctrl;       /* 0x008 */
+    volatile rt_uint32_t reserved1;
+    volatile rt_uint32_t pll_video_ctrl;       /* 0x010 */
+    volatile rt_uint32_t reserved2;
+    volatile rt_uint32_t pll_ve_ctrl;          /* 0x018 */
+    volatile rt_uint32_t reserved3;
+    volatile rt_uint32_t pll_ddr_ctrl;         /* 0x020 */
+    volatile rt_uint32_t reserved4;
+    volatile rt_uint32_t pll_periph_ctrl;      /* 0x028 */
+    volatile rt_uint32_t reserved5[9];
+    volatile rt_uint32_t cpu_clk_src;          /* 0x050 */
+    volatile rt_uint32_t ahb_apb_hclkc_cfg;    /* 0x054 */
+    volatile rt_uint32_t reserved6[2];
+    volatile rt_uint32_t bus_clk_gating0;      /* 0x060 */
+    volatile rt_uint32_t bus_clk_gating1;      /* 0x064 */
+    volatile rt_uint32_t bus_clk_gating2;      /* 0x068 */
+    volatile rt_uint32_t reserved7[7];
+    volatile rt_uint32_t sdmmc0_clk;           /* 0x088 */
+    volatile rt_uint32_t sdmmc1_clk;           /* 0x08C */
+    volatile rt_uint32_t reserved8[8];
+    volatile rt_uint32_t daudio_clk;           /* 0x0B0 */
+    volatile rt_uint32_t owa_clk;              /* 0x0B4 */
+    volatile rt_uint32_t cir_clk;              /* 0x0B8 */
+    volatile rt_uint32_t reserved9[4];
+    volatile rt_uint32_t usbphy_clk;           /* 0x0CC */
+    volatile rt_uint32_t reserved10[12];
+    volatile rt_uint32_t dram_gating;          /* 0x100 */
+    volatile rt_uint32_t be_clk;               /* 0x104 */
+    volatile rt_uint32_t reserved11;
+    volatile rt_uint32_t fe_clk;               /* 0x10C */
+    volatile rt_uint32_t reserved12[2];
+    volatile rt_uint32_t tcon_clk;             /* 0x118*/
+    volatile rt_uint32_t di_clk;               /* 0x11C */
+    volatile rt_uint32_t tve_clk;              /* 0x120 */
+    volatile rt_uint32_t tvd_clk;              /* 0x124 */
+    volatile rt_uint32_t reserved13[3];
+    volatile rt_uint32_t csi_clk;              /* 0x134 */
+    volatile rt_uint32_t reserved14;
+    volatile rt_uint32_t ve_clk;               /* 0x13C */
+    volatile rt_uint32_t audio_codec_clk;      /* 0x140 */
+    volatile rt_uint32_t avs_clk;              /* 0x144 */
+    volatile rt_uint32_t reserved15[46];
+    volatile rt_uint32_t pll_stable_time0;     /* 0x200 */
+    volatile rt_uint32_t pll_stable_time1;     /* 0x204 */
+    volatile rt_uint32_t reserved16[6];
+    volatile rt_uint32_t pll_cpu_bias;         /* 0x220 */
+    volatile rt_uint32_t pll_audio_bias;       /* 0x224 */
+    volatile rt_uint32_t pll_video_bias;       /* 0x228 */
+    volatile rt_uint32_t pll_ve_bias;          /* 0x22C */
+    volatile rt_uint32_t pll_ddr_bias;         /* 0x230 */
+    volatile rt_uint32_t pll_periph_bias;      /* 0x234 */
+    volatile rt_uint32_t reserved17[6];
+    volatile rt_uint32_t pll_cpu_tun;          /* 0x250 */
+    volatile rt_uint32_t reserved18[3];
+    volatile rt_uint32_t pll_ddr_tun;          /* 0x260 */
+    volatile rt_uint32_t reserved19[8];
+    volatile rt_uint32_t pll_audio_pat_ctrl;   /* 0x284 */
+    volatile rt_uint32_t pll_video_pat_ctrl;   /* 0x288 */
+    volatile rt_uint32_t reserved20;
+    volatile rt_uint32_t pll_ddr_pat_ctrl;     /* 0x290 */
+    volatile rt_uint32_t reserved21[11];
+    volatile rt_uint32_t bus_soft_rst0;        /* 0x2C0 */
+    volatile rt_uint32_t bus_soft_rst1;        /* 0x2C4 */
+    volatile rt_uint32_t reserved22[2];
+    volatile rt_uint32_t bus_soft_rst2;        /* 0x2D0 */
+};
+
+typedef struct tina_ccu *tina_ccu_t;
+
+#define CCU ((tina_ccu_t) CCU_BASE_ADDR)
+
+
+
+
+
+
+
+
+int cpu_get_pll_clk(void);
+int audio_get_pll_clk(void);
+int video_get_pll_clk(void);
+int ve_get_pll_clk(void);
+int ddr_get_pll_clk(void);
+int periph_get_pll_clk(void);
+int cpu_get_clk(void);
+int ahb_get_clk(void);
+int apb_get_clk(void);
+
+rt_err_t cpu_set_pll_clk(int clk);
+rt_err_t audio_set_pll_clk(int clk);
+rt_err_t video_set_pll_clk(int clk);
+rt_err_t ve_set_pll_clk(int clk);
+rt_err_t periph_set_pll_clk(int clk);
+
+rt_err_t cpu_set_clk(int clk);
+
+
+rt_err_t bus_gate_clk_enalbe(enum bus_gate bus);
+rt_err_t bus_gate_clk_disalbe(enum bus_gate bus);
+rt_err_t bus_software_reset_enalbe(enum bus_gate bus);
+rt_err_t bus_software_reset_disalbe(enum bus_gate bus);
+
+#endif

+ 564 - 0
bsp/allwinner_tina/drivers/drv_gpio.c

@@ -0,0 +1,564 @@
+/*
+ * File      : drv_gpio.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2017, RT-Thread Development Team
+ *
+ *  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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-02-08     RT-Thread    the first version
+ */
+#include <rtthread.h>
+#include <rthw.h>
+
+#include "drv_gpio.h"
+#include "interrupt.h"
+
+#define DBG_ENABLE
+#define DBG_SECTION_NAME  "[GPIO]"
+#define DBG_LEVEL         DBG_WARNING
+#define DBG_COLOR
+#include <rtdbg.h>
+
+
+#define readl(addr)           (*(volatile unsigned int *)(addr))
+#define writel(value,addr)    (*(volatile unsigned int *)(addr) = (value))
+
+// Todo: add RT_ASSERT.
+
+/*********************************************************
+**   IO
+*********************************************************/
+int gpio_set_func(enum gpio_port port, enum gpio_pin pin, rt_uint8_t func)
+{
+    rt_uint32_t addr;
+    rt_uint32_t offset;
+    rt_uint32_t data;
+
+    RT_ASSERT((GPIO_PORT_A <= port) && (port < GPIO_PORT_NUM));
+    RT_ASSERT((GPIO_PIN_0 <= pin) && (pin < GPIO_PIN_NUM));
+
+    if (func & 0x8)
+    {
+        dbg_log(DBG_WARNING, "[line]:%d There is a warning with parameter input\n", __LINE__);
+        return RT_EINVAL;
+    }
+
+    addr = GPIOn_CFG_ADDR(port) + (pin / 8) * 4;
+    offset = (pin % 8) * 4;
+
+    data = readl(addr);
+    data &= ~(0x7 << offset);
+    data |= func << offset;
+    writel(data, addr);
+
+    dbg_log(DBG_LOG, "[line]:%d offset:%d addr:%08x data:%08x\n", __LINE__, offset, addr, *((rt_uint32_t *)addr));
+    return RT_EOK;
+}
+
+int gpio_set_value(enum gpio_port port, enum gpio_pin pin, rt_uint8_t value)
+{
+    rt_uint32_t addr;
+    rt_uint32_t offset;
+    rt_uint32_t data;
+
+    RT_ASSERT((GPIO_PORT_A <= port) && (port < GPIO_PORT_NUM));
+    RT_ASSERT((GPIO_PIN_0 <= pin) && (pin < GPIO_PIN_NUM));
+
+    if (value & 0xE)
+    {
+        dbg_log(DBG_WARNING, "[line]:%d There is a warning with parameter input\n", __LINE__);
+        return RT_EINVAL;
+    }
+
+    addr = GPIOn_DATA_ADDR(port);
+    offset = pin;
+
+    data = readl(addr);
+    data &= ~(0x1 << offset);
+    data |= value << offset;
+    writel(data, addr);
+
+    dbg_log(DBG_LOG, "[line]:%d offset:%d addr:%08x data:%08x\n", __LINE__, offset, addr, *((rt_uint32_t *)addr));
+    return RT_EOK;
+}
+
+int gpio_get_value(enum gpio_port port, enum gpio_pin pin)
+{
+    rt_uint32_t addr;
+    rt_uint32_t offset;
+    rt_uint32_t data;
+
+    RT_ASSERT((GPIO_PORT_A <= port) && (port < GPIO_PORT_NUM));
+    RT_ASSERT((GPIO_PIN_0 <= pin) && (pin < GPIO_PIN_NUM));
+
+    addr = GPIOn_DATA_ADDR(port);
+    offset = pin;
+
+    data = readl(addr);
+
+    dbg_log(DBG_LOG, "[line]:%d offset:%d addr:%08x data:%08x\n", __LINE__, offset, addr, *((rt_uint32_t *)addr));
+    return (data >> offset) & 0x01;
+}
+
+int gpio_set_pull_mode(enum gpio_port port,  enum gpio_pin pin, enum gpio_pull pull)
+{
+    rt_uint32_t addr;
+    rt_uint32_t offset;
+    rt_uint32_t data;
+
+    RT_ASSERT((GPIO_PORT_A <= port) && (port < GPIO_PORT_NUM));
+    RT_ASSERT((GPIO_PIN_0 <= pin) && (pin < GPIO_PIN_NUM));
+
+    if (pull & 0xC)
+    {
+        dbg_log(DBG_WARNING, "[line]:%d There is a warning with parameter input\n", __LINE__);
+        return RT_EINVAL;
+    }
+
+    addr = GPIOn_PUL_ADDR(port);
+    addr += pin > GPIO_PIN_15 ? 0x4 : 0x0;
+    offset = (pin & 0xf) << 1;
+
+    data = readl(addr);
+    data &= ~(0x3 << offset);
+    data |= pull << offset;
+    writel(data, addr);
+
+    dbg_log(DBG_LOG, "[line]:%d offset:%d addr:%08x data:%08x\n", __LINE__, offset, addr, *((rt_uint32_t *)addr));
+    return RT_EOK;
+}
+
+int gpio_set_drive_level(enum gpio_port port, enum gpio_pin pin, enum gpio_drv_level level)
+{
+    volatile rt_uint32_t addr;
+    rt_uint32_t offset;
+    rt_uint32_t data;
+
+    RT_ASSERT((GPIO_PORT_A <= port) && (port < GPIO_PORT_NUM));
+    RT_ASSERT((GPIO_PIN_0 <= pin) && (pin < GPIO_PIN_NUM));
+
+    if (level & 0xC)
+    {
+        dbg_log(DBG_WARNING, "[line]:%d There is a warning with parameter input\n", __LINE__);
+        return RT_EINVAL;
+    }
+
+    addr = GPIOn_DRV_ADDR(port);
+    addr += pin > GPIO_PIN_15 ? 0x4 : 0x0;
+    offset = (pin & 0xf) << 1;
+
+    data = readl(addr);
+    data &= ~(0x3 << offset);
+    data |= level << offset;
+    writel(data, addr);
+
+    dbg_log(DBG_LOG, "[line]:%d offset:%d addr:%08x data:%08x\n", __LINE__, offset, addr, *((rt_uint32_t *)addr));
+    return RT_EOK;
+}
+
+void gpio_direction_input(enum gpio_port port,  enum gpio_pin pin)
+{
+    volatile rt_uint32_t addr;
+    rt_uint32_t offset;
+    rt_uint32_t data;
+
+    RT_ASSERT((GPIO_PORT_A <= port) && (port < GPIO_PORT_NUM));
+    RT_ASSERT((GPIO_PIN_0 <= pin) && (pin < GPIO_PIN_NUM));
+
+    addr = GPIOn_CFG_ADDR(port) + (pin / 8) * 4;
+    offset = (pin % 8) * 4;
+
+    data = readl(addr);
+    data &= ~(0x7 << offset);
+    data |= IO_INPUT << offset;
+    writel(data, addr);
+
+    dbg_log(DBG_LOG, "[line]:%d offset:%d addr:%08x data:%08x\n", __LINE__, offset, addr, *((rt_uint32_t *)addr));
+}
+
+void gpio_direction_output(enum gpio_port port, enum gpio_pin pin, int value)
+{
+    volatile rt_uint32_t addr;
+    rt_uint32_t offset;
+    rt_uint32_t data;
+
+    RT_ASSERT((GPIO_PORT_A <= port) && (port < GPIO_PORT_NUM));
+    RT_ASSERT((GPIO_PIN_0 <= pin) && (pin < GPIO_PIN_NUM));
+
+    gpio_set_value(port, pin, value);
+    addr = GPIOn_CFG_ADDR(port) + (pin / 8) * 4;
+    offset = (pin % 8) * 4;
+
+    data = readl(addr);
+    data &= ~(0x7 << offset);
+    data |= IO_OUTPUT << offset;
+    writel(data, addr);
+
+    dbg_log(DBG_LOG, "[line]:%d offset:%d addr:%08x data:%08x\n", __LINE__, offset, addr, *((rt_uint32_t *)addr));
+}
+/*********************************************************
+**   IRQ
+*********************************************************/
+static void gpio_ack_irq(enum gpio_port port,  enum gpio_pin pin)
+{
+    rt_uint32_t addr;
+    rt_uint32_t data;
+
+    addr = GPIOn_INT_STA_ADDR(port);
+    data = readl(addr);
+    data |= 0x1 << pin;
+    writel(data, addr);
+}
+
+void gpio_select_irq_clock(enum gpio_port port, enum gpio_irq_clock clock)
+{
+    rt_uint32_t addr;
+    rt_uint32_t data;
+
+    RT_ASSERT((GPIO_PORT_C < port) && (port < GPIO_PORT_NUM));
+
+    addr = GPIOn_INT_DEB_ADDR(port - GPIO_PORT_D);
+
+    data = readl(addr);
+    data &= ~0x01;
+    data |= clock;
+    writel(data, addr);
+    dbg_log(DBG_LOG, "[line]:%d addr:%08x data:%08x\n", __LINE__, addr, *((rt_uint32_t *)addr));
+}
+
+void gpio_set_debounce(enum gpio_port port, enum gpio_direction_type prescaler)
+{
+    rt_uint32_t addr;
+    rt_uint32_t data;
+
+    RT_ASSERT((GPIO_PORT_C < port) && (port < GPIO_PORT_NUM));
+
+    addr = GPIOn_INT_DEB_ADDR(port - GPIO_PORT_D);
+
+    data = readl(addr);
+    data &= ~(0x07 << 4);
+    data |= prescaler << 4;
+    writel(data, addr);
+    dbg_log(DBG_LOG, "[line]:%d addr:%08x data:%08x\n", __LINE__, addr, *((rt_uint32_t *)addr));
+}
+
+void gpio_irq_enable(enum gpio_port port,  enum gpio_pin pin)
+{
+    rt_uint32_t addr;
+    rt_uint32_t offset;
+    rt_uint32_t data;
+
+    RT_ASSERT((GPIO_PORT_C < port) && (port < GPIO_PORT_NUM));
+    RT_ASSERT((GPIO_PIN_0 <= pin) && (pin < GPIO_PIN_NUM));
+
+    addr = GPIOn_INT_CTRL_ADDR(port - GPIO_PORT_D);
+    offset = pin;
+
+    data = readl(addr);
+    data |= 0x1 << offset;
+    writel(data, addr);
+    gpio_select_irq_clock(port, GPIO_IRQ_HOSC_24MHZ);
+    dbg_log(DBG_LOG, "[line]:%d offset:%d addr:%08x data:%08x\n", __LINE__, offset, addr, *((rt_uint32_t *)addr));
+}
+
+void gpio_irq_disable(enum gpio_port port,  enum gpio_pin pin)
+{
+    rt_uint32_t addr;
+    rt_uint32_t offset;
+    rt_uint32_t data;
+
+    RT_ASSERT((GPIO_PORT_C < port) && (port < GPIO_PORT_NUM));
+    RT_ASSERT((GPIO_PIN_0 <= pin) && (pin < GPIO_PIN_NUM));
+
+    gpio_ack_irq(port - GPIO_PORT_D, pin);
+    addr = GPIOn_INT_CTRL_ADDR(port - GPIO_PORT_D);
+    offset = pin;
+
+    data = readl(addr);
+    data &= ~(0x1 << offset);
+
+    writel(data, addr);
+    dbg_log(DBG_LOG, "[line]:%d offset:%d addr:%08x data:%08x\n", __LINE__, offset, addr, *((rt_uint32_t *)addr));
+}
+
+void gpio_set_irq_type(enum gpio_port port,  enum gpio_pin pin, enum gpio_irq_type irq_type)
+{
+    rt_uint32_t addr;
+    rt_uint32_t offset;
+    rt_uint32_t data;
+
+    RT_ASSERT((GPIO_PORT_C < port) && (port < GPIO_PORT_NUM));
+    RT_ASSERT((GPIO_PIN_0 <= pin) && (pin < GPIO_PIN_NUM));
+
+    addr = GPIOn_INT_CFG_ADDR(port - GPIO_PORT_D) + (pin / 8) * 4;
+    offset = (pin % 8) * 4;
+
+    data = readl(addr);
+    data &= ~(0x7 << offset);
+    data |= irq_type << offset;
+    writel(data, addr);
+
+    dbg_log(DBG_LOG, "[line]:%d offset:%d addr:%08x data:%08x\n", __LINE__, offset, addr, *((rt_uint32_t *)addr));
+}
+
+static struct gpio_irq_def _g_gpio_irq_tbl[GPIO_PORT_NUM];
+
+void gpio_set_irq_callback(enum gpio_port port, enum gpio_pin pin, void (*irq_cb)(void *), void *irq_arg)
+{
+    RT_ASSERT((GPIO_PORT_C < port) && (port < GPIO_PORT_NUM));
+    RT_ASSERT((GPIO_PIN_0 <= pin) && (pin < GPIO_PIN_NUM));
+
+    _g_gpio_irq_tbl[port].irq_cb[pin]    = irq_cb;
+    _g_gpio_irq_tbl[port].irq_arg[pin]   = irq_arg;
+}
+
+void gpio_clear_irq_callback(enum gpio_port port, enum gpio_pin pin)
+{
+    gpio_irq_disable(port, pin);
+
+    _g_gpio_irq_tbl[port].irq_cb[pin]    = RT_NULL;
+    _g_gpio_irq_tbl[port].irq_arg[pin]   = RT_NULL;
+}
+
+static void gpio_irq_handler(int irq, void *param)
+{
+    struct gpio_irq_def *irq_def = (struct gpio_irq_def *)param;
+    rt_uint32_t pend, enable;
+    int port, pin;
+    rt_uint32_t addr;
+
+    pin = 0;
+    port = irq - PIOD_INTERRUPT;
+    addr = GPIOn_INT_STA_ADDR(port);
+    pend = readl(addr);
+    addr = GPIOn_INT_CTRL_ADDR(port);
+    enable = readl(addr);
+    pend &= enable;
+
+    while (pend)
+    {
+        if ((pend & 0x1) && (irq_def->irq_cb[pin] != RT_NULL))
+        {
+            dbg_log(DBG_LOG, "do irq callback...\n", port, pin);
+            irq_def->irq_cb[pin](irq_def->irq_arg[pin]);
+        }
+        pin++;
+        pend = pend >> 1;
+        gpio_ack_irq(port, pin);
+    }
+}
+
+
+#ifdef RT_USING_PIN
+#include <rtdevice.h>
+
+#define PIN_MAGIC    (0x5A)
+#define PIN_NUM(_N)      (sizeof(_N) / sizeof(_N[0]))
+
+struct _pin_index
+{
+    rt_uint8_t id;
+    rt_uint8_t pin_port;
+    rt_uint8_t pin;
+    rt_uint8_t magic;
+};
+
+static struct _pin_index pin_index[] =
+{
+    {0, 0, 0, 0},
+    {1, 0, 0, 0},
+    {2, 0, 0, 0},
+    {3, 0, 0, 0},
+    {4, 0, 0, 0},
+    {5, 0, 0, 0},
+    {6, GPIO_PORT_D, GPIO_PIN_0,  PIN_MAGIC},
+    {7, GPIO_PORT_D, GPIO_PIN_1,  PIN_MAGIC},
+    {8, GPIO_PORT_D, GPIO_PIN_2,  PIN_MAGIC},
+    {9, GPIO_PORT_D, GPIO_PIN_3,  PIN_MAGIC},
+    {10, GPIO_PORT_D, GPIO_PIN_4,  PIN_MAGIC},
+    {11, GPIO_PORT_D, GPIO_PIN_5,  PIN_MAGIC},
+    {12, GPIO_PORT_D, GPIO_PIN_6,  PIN_MAGIC},
+    {13, GPIO_PORT_D, GPIO_PIN_7,  PIN_MAGIC},
+    {14, GPIO_PORT_D, GPIO_PIN_8,  PIN_MAGIC},
+    {15, GPIO_PORT_D, GPIO_PIN_9,  PIN_MAGIC},
+    {16, GPIO_PORT_D, GPIO_PIN_10, PIN_MAGIC},
+    {17, GPIO_PORT_D, GPIO_PIN_11, PIN_MAGIC},
+    {18, GPIO_PORT_D, GPIO_PIN_12, PIN_MAGIC},
+    {19, GPIO_PORT_D, GPIO_PIN_13, PIN_MAGIC},
+    {20, 0, 0, 0},
+    {21, GPIO_PORT_D, GPIO_PIN_14, PIN_MAGIC},
+    {22, 0, 0, 0},
+    {23, GPIO_PORT_D, GPIO_PIN_15, PIN_MAGIC},
+    {24, GPIO_PORT_D, GPIO_PIN_16, PIN_MAGIC},
+    {25, GPIO_PORT_D, GPIO_PIN_17, PIN_MAGIC},
+    {26, GPIO_PORT_D, GPIO_PIN_18, PIN_MAGIC},
+    {27, GPIO_PORT_D, GPIO_PIN_19, PIN_MAGIC},
+    {28, GPIO_PORT_D, GPIO_PIN_20, PIN_MAGIC},
+    {29, GPIO_PORT_D, GPIO_PIN_21, PIN_MAGIC},
+    {30, 0, 0, 0},
+    {31, 0, 0, 0},
+    {32, 0, 0, 0},
+    {33, 0, 0, 0},
+    {34, 0, 0, 0},
+    {35, 0, 0, 0},
+    {36, 0, 0, 0},
+    {37, GPIO_PORT_E, GPIO_PIN_12, PIN_MAGIC},
+    {38, GPIO_PORT_E, GPIO_PIN_11, PIN_MAGIC},
+    {39, GPIO_PORT_E, GPIO_PIN_10, PIN_MAGIC},
+    {40, GPIO_PORT_E, GPIO_PIN_9,  PIN_MAGIC},
+    {41, GPIO_PORT_E, GPIO_PIN_8,  PIN_MAGIC},
+    {42, GPIO_PORT_E, GPIO_PIN_7,  PIN_MAGIC},
+    {43, GPIO_PORT_E, GPIO_PIN_6,  PIN_MAGIC},
+    {44, GPIO_PORT_E, GPIO_PIN_5,  PIN_MAGIC},
+    {45, GPIO_PORT_E, GPIO_PIN_4,  PIN_MAGIC},
+    {46, GPIO_PORT_E, GPIO_PIN_3,  PIN_MAGIC},
+    {47, GPIO_PORT_E, GPIO_PIN_2,  PIN_MAGIC},
+    {48, GPIO_PORT_E, GPIO_PIN_1,  PIN_MAGIC},
+    {49, GPIO_PORT_E, GPIO_PIN_0,  PIN_MAGIC},
+    {50, 0, 0, 0},
+    {51, 0, 0, 0},
+    {52, 0, 0, 0},
+    {53, GPIO_PORT_F, GPIO_PIN_5, PIN_MAGIC},
+    {54, GPIO_PORT_F, GPIO_PIN_4, PIN_MAGIC},
+    {55, GPIO_PORT_F, GPIO_PIN_3, PIN_MAGIC},
+    {56, GPIO_PORT_F, GPIO_PIN_2, PIN_MAGIC},
+    {57, GPIO_PORT_F, GPIO_PIN_1, PIN_MAGIC},
+    {58, GPIO_PORT_F, GPIO_PIN_0, PIN_MAGIC},
+    {59, GPIO_PORT_C, GPIO_PIN_0, PIN_MAGIC},
+    {60, GPIO_PORT_C, GPIO_PIN_1, PIN_MAGIC},
+    {61, GPIO_PORT_C, GPIO_PIN_2, PIN_MAGIC},
+    {62, GPIO_PORT_C, GPIO_PIN_3, PIN_MAGIC},
+    {63, GPIO_PORT_A, GPIO_PIN_3, PIN_MAGIC},
+    {64, GPIO_PORT_A, GPIO_PIN_2, PIN_MAGIC},
+    {65, GPIO_PORT_A, GPIO_PIN_1, PIN_MAGIC},
+    {66, GPIO_PORT_A, GPIO_PIN_0, PIN_MAGIC},
+};
+
+static void pin_mode(struct rt_device *dev, rt_base_t pin, rt_base_t mode)
+{
+    if ((pin > PIN_NUM(pin_index)) || (pin_index[pin].magic != PIN_MAGIC))
+    {
+        dbg_log(DBG_ERROR, "pin:%d value wrongful\n", pin);
+        return;
+    }
+
+    gpio_set_func(pin_index[pin].pin_port, pin_index[pin].pin, mode);
+}
+
+static void pin_write(struct rt_device *dev, rt_base_t pin, rt_base_t value)
+{
+    if ((pin > PIN_NUM(pin_index)) || (pin_index[pin].magic != PIN_MAGIC))
+    {
+        dbg_log(DBG_ERROR, "pin:%d value wrongful\n", pin);
+        return;
+    }
+
+    gpio_set_value(pin_index[pin].pin_port, pin_index[pin].pin, value);
+}
+
+static int pin_read(struct rt_device *device, rt_base_t pin)
+{
+    if ((pin > PIN_NUM(pin_index)) || (pin_index[pin].magic != PIN_MAGIC))
+    {
+        dbg_log(DBG_ERROR, "pin:%d value wrongful\n", pin);
+        return 0;
+    }
+
+    return gpio_get_value(pin_index[pin].pin_port, pin_index[pin].pin);
+}
+
+static rt_err_t pin_attach_irq(struct rt_device *device, rt_int32_t pin, rt_uint32_t mode, void (*hdr)(void *args), void *args)
+{
+    if ((pin > PIN_NUM(pin_index)) || (pin_index[pin].magic != PIN_MAGIC))
+    {
+        dbg_log(DBG_ERROR, "pin:%d value wrongful\n", pin);
+        return RT_ERROR;
+    }
+
+    gpio_set_irq_callback(pin_index[pin].pin_port, pin_index[pin].pin, hdr, args);
+    gpio_set_irq_type(pin_index[pin].pin_port, pin_index[pin].pin, mode);
+    return RT_EOK;
+}
+static rt_err_t pin_dettach_irq(struct rt_device *device, rt_int32_t pin)
+{
+    if ((pin > PIN_NUM(pin_index)) || (pin_index[pin].magic != PIN_MAGIC))
+    {
+        dbg_log(DBG_ERROR, "pin:%d value wrongful\n", pin);
+        return RT_ERROR;
+    }
+
+    gpio_clear_irq_callback(pin_index[pin].pin_port, pin_index[pin].pin);
+
+    return RT_EOK;
+}
+
+rt_err_t pin_irq_enable(struct rt_device *device, rt_base_t pin, rt_uint32_t enabled)
+{
+    if ((pin > PIN_NUM(pin_index)) || (pin_index[pin].magic != PIN_MAGIC))
+    {
+        dbg_log(DBG_ERROR, "pin:%d value wrongful\n", pin);
+        return RT_ERROR;
+    }
+
+    if (enabled)
+        gpio_irq_enable(pin_index[pin].pin_port, pin_index[pin].pin);
+    else
+        gpio_irq_disable(pin_index[pin].pin_port, pin_index[pin].pin);
+
+    return RT_EOK;
+}
+
+/*
+ID GPIO   ID GPIO    ID GPIO    ID GPIO    ID GPIO   ID GPIO   ID GPIO
+6  PD0    13 PD7     21 PD14    29 PD21    43 PE6    53 PF5    60 PC1
+7  PD1    14 PD8     23 PD15    37 PE12    44 PE5    54 PF4    61 PC2
+8  PD2    15 PD9     24 PD16    38 PE11    45 PE4    55 PF3    62 PC3
+9  PD3    16 PD10    25 PD17    39 PE10    46 PE3    56 PF2    63 PA3
+10 PD4    17 PD11    26 PD18    40 PE9     47 PE2    57 PF1    64 PA2
+11 PD5    18 PD12    27 PD19    41 PE8     48 PE1    58 PF0    65 PA1
+12 PD6    19 PD13    28 PD20    42 PE7     49 PE0    59 PC0    66 PA0
+*/
+
+static const struct rt_pin_ops ops =
+{
+    pin_mode,
+    pin_write,
+    pin_read,
+    pin_attach_irq,
+    pin_dettach_irq,
+    pin_irq_enable,
+};
+#endif
+
+int rt_hw_gpio_init(void)
+{
+#ifdef RT_USING_PIN
+    rt_device_pin_register("gpio", &ops, RT_NULL);
+#endif
+    /* install ISR */
+    rt_hw_interrupt_install(PIOD_INTERRUPT, gpio_irq_handler, &_g_gpio_irq_tbl[GPIO_PORT_D], "gpiod_irq");
+    rt_hw_interrupt_umask(PIOD_INTERRUPT);
+
+    rt_hw_interrupt_install(PIOE_INTERRUPT, gpio_irq_handler, &_g_gpio_irq_tbl[GPIO_PORT_E], "gpioe_irq");
+    rt_hw_interrupt_umask(PIOE_INTERRUPT);
+
+    rt_hw_interrupt_install(PIOF_INTERRUPT, gpio_irq_handler, &_g_gpio_irq_tbl[GPIO_PORT_F], "gpiof_irq");
+    rt_hw_interrupt_umask(PIOF_INTERRUPT);
+
+    return 0;
+}
+INIT_DEVICE_EXPORT(rt_hw_gpio_init);

+ 244 - 0
bsp/allwinner_tina/drivers/drv_gpio.h

@@ -0,0 +1,244 @@
+/*
+ * File      : drv_gpio.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2017, RT-Thread Development Team
+ *
+ *  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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-02-08     RT-Thread    the first version
+ */
+#ifndef __DRV_GPIO_H__
+#define __DRV_GPIO_H__
+
+/* IO default function */
+#define IO_INPUT         (0x00)
+#define IO_OUTPUT        (0x01)
+#define IO_DISABLE       (0x07)
+
+#define IO_FUN_1         (0x02)
+#define IO_FUN_2         (0x03)
+#define IO_FUN_3         (0x04)
+#define IO_FUN_4         (0x05)
+#define IO_FUN_5         (0x06)
+
+/* IO port */
+enum gpio_port
+{
+    GPIO_PORT_A = 0,
+    GPIO_PORT_B,
+    GPIO_PORT_C,
+    GPIO_PORT_D,
+    GPIO_PORT_E,
+    GPIO_PORT_F,
+    GPIO_PORT_NUM,
+};
+
+/* IO pin */
+enum gpio_pin
+{
+    GPIO_PIN_0 = 0,
+    GPIO_PIN_1,
+    GPIO_PIN_2,
+    GPIO_PIN_3,
+    GPIO_PIN_4,
+    GPIO_PIN_5,
+    GPIO_PIN_6,
+    GPIO_PIN_7,
+    GPIO_PIN_8,
+    GPIO_PIN_9,
+    GPIO_PIN_10,
+    GPIO_PIN_11,
+    GPIO_PIN_12,
+    GPIO_PIN_13,
+    GPIO_PIN_14,
+    GPIO_PIN_15,
+    GPIO_PIN_16,
+    GPIO_PIN_17,
+    GPIO_PIN_18,
+    GPIO_PIN_19,
+    GPIO_PIN_20,
+    GPIO_PIN_21,
+    GPIO_PIN_22,
+    GPIO_PIN_23,
+    GPIO_PIN_NUM,
+};
+
+/* Drive level */
+enum gpio_drv_level
+{
+    DRV_LEVEL_0 = 0,
+    DRV_LEVEL_1,
+    DRV_LEVEL_2,
+    DRV_LEVEL_3,
+};
+
+/* Pull mode */
+enum gpio_pull
+{
+    PULL_DISABLE = 0,
+    PULL_UP,
+    PULL_DOWN,
+};
+
+/* interrupt type */
+enum gpio_irq_type
+{
+    POSITIVE = 0,
+    NEGATIVE,
+    HIGH,
+    LOW,
+    DOUBLE,
+};
+
+enum gpio_irq_clock
+{
+    GPIO_IRQ_LOSC_32KHZ = 0,
+    GPIO_IRQ_HOSC_24MHZ
+};
+
+enum gpio_direction_type
+{
+    DEBOUNCE_PRE_SCALE_1 = 0,
+    DEBOUNCE_PRE_SCALE_2,
+    DEBOUNCE_PRE_SCALE_4,
+    DEBOUNCE_PRE_SCALE_8,
+    DEBOUNCE_PRE_SCALE_16,
+    DEBOUNCE_PRE_SCALE_32,
+    DEBOUNCE_PRE_SCALE_64,
+    DEBOUNCE_PRE_SCALE_128,
+};
+
+struct gpio_irq_def
+{
+    void    *irq_arg[32];
+    void (*irq_cb[32])(void *param);
+};
+
+#define GPIO_BASE_ADDR           (0x01C20800)
+#define GPIOn_CFG_ADDR(n)        (GPIO_BASE_ADDR + (n) * 0x24 + 0x00)
+#define GPIOn_DATA_ADDR(n)       (GPIO_BASE_ADDR + (n) * 0x24 + 0x10)
+#define GPIOn_DRV_ADDR(n)        (GPIO_BASE_ADDR + (n) * 0x24 + 0x14)
+#define GPIOn_PUL_ADDR(n)        (GPIO_BASE_ADDR + (n) * 0x24 + 0x1C)
+#define GPIOn_INT_CFG_ADDR(n)    (GPIO_BASE_ADDR + 0x200 + (n) * 0x20 + 0x00)
+#define GPIOn_INT_CTRL_ADDR(n)   (GPIO_BASE_ADDR + 0x200 + (n) * 0x20 + 0x10)
+#define GPIOn_INT_STA_ADDR(n)    (GPIO_BASE_ADDR + 0x200 + (n) * 0x20 + 0x14)
+#define GPIOn_INT_DEB_ADDR(n)    (GPIO_BASE_ADDR + 0x200 + (n) * 0x20 + 0x18)
+
+struct tina_gpio
+{
+    volatile rt_uint32_t pa_cfg0;        /* 0x00 */
+    volatile rt_uint32_t pa_cfg1;        /* 0x04 */
+    volatile rt_uint32_t pa_cfg2;        /* 0x08 */
+    volatile rt_uint32_t pa_cfg3;        /* 0x0C */
+    volatile rt_uint32_t pa_data;        /* 0x10 */
+    volatile rt_uint32_t pa_drv0;        /* 0x14 */
+    volatile rt_uint32_t pa_drv1;        /* 0x18 */
+    volatile rt_uint32_t pa_pul0;        /* 0x1C */
+    volatile rt_uint32_t pa_pul1;        /* 0x20 */
+    volatile rt_uint32_t pb_cfg0;        /* 0x24 */
+    volatile rt_uint32_t pb_cfg1;        /* 0x28 */
+    volatile rt_uint32_t pb_cfg2;        /* 0x2C */
+    volatile rt_uint32_t pb_cfg3;        /* 0x30 */
+    volatile rt_uint32_t pb_data;        /* 0x34 */
+    volatile rt_uint32_t pb_drv0;        /* 0x38 */
+    volatile rt_uint32_t pb_drv1;        /* 0x3C */
+    volatile rt_uint32_t pb_pul0;        /* 0x40 */
+    volatile rt_uint32_t pb_pul1;        /* 0x44 */
+    volatile rt_uint32_t pc_cfg0;        /* 0x48 */
+    volatile rt_uint32_t pc_cfg1;        /* 0x4C */
+    volatile rt_uint32_t pc_cfg2;        /* 0x50 */
+    volatile rt_uint32_t pc_cfg3;        /* 0x54 */
+    volatile rt_uint32_t pc_data;        /* 0x58 */
+    volatile rt_uint32_t pc_drv0;        /* 0x5C */
+    volatile rt_uint32_t pc_drv1;        /* 0x60 */
+    volatile rt_uint32_t pc_pul0;        /* 0x64 */
+    volatile rt_uint32_t pc_pul1;        /* 0x68 */
+    volatile rt_uint32_t pd_cfg0;        /* 0x6C */
+    volatile rt_uint32_t pd_cfg1;        /* 0x70 */
+    volatile rt_uint32_t pd_cfg2;        /* 0x74 */
+    volatile rt_uint32_t pd_cfg3;        /* 0x78 */
+    volatile rt_uint32_t pd_data;        /* 0x7C */
+    volatile rt_uint32_t pd_drv0;        /* 0x80 */
+    volatile rt_uint32_t pd_drv1;        /* 0x84 */
+    volatile rt_uint32_t pd_pul0;        /* 0x88 */
+    volatile rt_uint32_t pd_pul1;        /* 0x8C */
+    volatile rt_uint32_t pe_cfg0;        /* 0x90 */
+    volatile rt_uint32_t pe_cfg1;        /* 0x94 */
+    volatile rt_uint32_t pe_cfg2;        /* 0x98 */
+    volatile rt_uint32_t pe_cfg3;        /* 0x9C */
+    volatile rt_uint32_t pe_data;        /* 0xA0 */
+    volatile rt_uint32_t pe_drv0;        /* 0xA4 */
+    volatile rt_uint32_t pe_drv1;        /* 0xA8 */
+    volatile rt_uint32_t pe_pul0;        /* 0xAC */
+    volatile rt_uint32_t pe_pul1;        /* 0xB0 */
+    volatile rt_uint32_t pf_cfg0;        /* 0xB4 */
+    volatile rt_uint32_t pf_cfg1;        /* 0xB8 */
+    volatile rt_uint32_t pf_cfg2;        /* 0xBC */
+    volatile rt_uint32_t pf_cfg3;        /* 0xC0 */
+    volatile rt_uint32_t pf_data;        /* 0xC4 */
+    volatile rt_uint32_t pf_drv0;        /* 0xC8 */
+    volatile rt_uint32_t pf_drv1;        /* 0xCC */
+    volatile rt_uint32_t pf_pul0;        /* 0xD0 */
+    volatile rt_uint32_t reserved0[76];
+    volatile rt_uint32_t pd_int_cfg0;    /* 0x200 */
+    volatile rt_uint32_t pd_int_cfg1;    /* 0x204 */
+    volatile rt_uint32_t pd_int_cfg2;    /* 0x208 */
+    volatile rt_uint32_t pd_int_cfg3;    /* 0x20C */
+    volatile rt_uint32_t pd_int_ctrl;    /* 0x210 */
+    volatile rt_uint32_t pd_int_sta;     /* 0x214 */
+    volatile rt_uint32_t pd_int_deb;     /* 0x218 */
+    volatile rt_uint32_t reserved1;
+    volatile rt_uint32_t pe_int_cfg0;    /* 0x220 */
+    volatile rt_uint32_t pe_int_cfg1;    /* 0x224 */
+    volatile rt_uint32_t pe_int_cfg2;    /* 0x228 */
+    volatile rt_uint32_t pe_int_cfg3;    /* 0x22C */
+    volatile rt_uint32_t pe_int_ctrl;    /* 0x230 */
+    volatile rt_uint32_t pe_int_sta;     /* 0x234 */
+    volatile rt_uint32_t pe_int_deb;     /* 0x238 */
+    volatile rt_uint32_t reserved2;
+    volatile rt_uint32_t pf_int_cfg0;    /* 0x240 */
+    volatile rt_uint32_t pf_int_cfg1;    /* 0x244 */
+    volatile rt_uint32_t pf_int_cfg2;    /* 0x248 */
+    volatile rt_uint32_t pf_int_cfg3;    /* 0x24C */
+    volatile rt_uint32_t pf_int_ctrl;    /* 0x250 */
+    volatile rt_uint32_t pf_int_sta;     /* 0x254 */
+    volatile rt_uint32_t pf_int_deb;     /* 0x258 */
+    volatile rt_uint32_t reserved3[26];
+    volatile rt_uint32_t sdr_pad_drv;    /* 0x2C0*/
+    volatile rt_uint32_t sdr_pad_pul;    /* 0x2C4 */
+};
+
+typedef struct tina_gpio *tina_gpio_t;
+
+#define GPIO ((tina_gpio_t)GPIO_BASE_ADDR)
+
+int gpio_set_func(enum gpio_port port, enum gpio_pin pin, rt_uint8_t func);
+int gpio_set_value(enum gpio_port port, enum gpio_pin pin, rt_uint8_t value);
+int gpio_get_value(enum gpio_port port, enum gpio_pin pin);
+int gpio_set_pull_mode(enum gpio_port port,  enum gpio_pin pin, enum gpio_pull pull);
+int gpio_set_drive_level(enum gpio_port port, enum gpio_pin pin, enum gpio_drv_level level);
+void gpio_direction_input(enum gpio_port port,  enum gpio_pin pin);
+void gpio_direction_output(enum gpio_port port, enum gpio_pin pin, int value);
+void gpio_irq_enable(enum gpio_port port,  enum gpio_pin pin);
+void gpio_irq_disable(enum gpio_port port,  enum gpio_pin pin);
+void gpio_set_irq_type(enum gpio_port port,  enum gpio_pin pin, enum gpio_irq_type irq_type);
+void gpio_select_irq_clock(enum gpio_port port, enum gpio_irq_clock clock);
+void gpio_set_debounce(enum gpio_port port, rt_uint8_t prescaler);
+void gpio_set_irq_callback(enum gpio_port port, enum gpio_pin pin, void (*irq_cb)(void *), void *irq_arg);
+int rt_hw_gpio_init(void);
+
+#endif /* __DRV_GPIO_H__ */

+ 324 - 0
bsp/allwinner_tina/drivers/drv_uart.c

@@ -0,0 +1,324 @@
+/*
+ * File      : drv_uart.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2017, RT-Thread Development Team
+ *
+ *  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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-02-08     RT-Thread    the first version
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#include "drv_uart.h"
+#include "interrupt.h"
+
+#include "drv_gpio.h"
+#include "drv_clock.h"
+
+#define readl(addr)           (*(volatile unsigned int *)(addr))
+#define writel(value,addr)    (*(volatile unsigned int *)(addr) = (value))
+
+#ifdef RT_USING_SERIAL
+
+struct device_uart
+{
+    rt_uint32_t hw_base;
+    rt_uint32_t irqno;
+    char name[RT_NAME_MAX];
+    rt_uint32_t gpio_rx_port;
+    rt_uint32_t gpio_tx_port;
+    rt_uint32_t gpio_rx_pin;
+    rt_uint32_t gpio_tx_pin;
+    rt_uint32_t gpio_rx_fun;
+    rt_uint32_t gpio_tx_fun;
+};
+
+static rt_err_t uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg);
+static rt_err_t uart_control(struct rt_serial_device *serial, int cmd, void *arg);
+static int      uart_putc(struct rt_serial_device *serial, char c);
+static int      uart_getc(struct rt_serial_device *serial);
+static rt_size_t uart_dma_transmit(struct rt_serial_device *serial, rt_uint8_t *buf, rt_size_t size, int direction);
+
+void     uart_irq_handler(int irqno, void *param);
+
+const struct rt_uart_ops _uart_ops =
+{
+    uart_configure,
+    uart_control,
+    uart_putc,
+    uart_getc,
+    uart_dma_transmit
+};
+
+/*
+ * UART Initiation
+ */
+int rt_hw_uart_init(void)
+{
+    struct rt_serial_device *serial;
+    struct device_uart      *uart;
+    struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
+
+#ifdef TINA_USING_UART0
+    {
+        static struct rt_serial_device  serial0;
+        static struct device_uart       uart0;
+
+        serial  = &serial0;
+        uart    = &uart0;
+
+        serial->ops              = &_uart_ops;
+        serial->config           = config;
+        serial->config.baud_rate = 115200;
+
+        uart->hw_base      = UART0_BASE_ADDR; // UART0_BASE;
+        uart->irqno        = UART0_INTERRUPT; // IRQ_UART0;
+        uart->gpio_rx_port = GPIO_PORT_E;
+        uart->gpio_tx_port = GPIO_PORT_E;
+        uart->gpio_rx_pin  = GPIO_PIN_0;
+        uart->gpio_tx_pin  = GPIO_PIN_1;
+        uart->gpio_rx_fun  = IO_FUN_4;
+        uart->gpio_tx_fun  = IO_FUN_4;
+
+        rt_hw_serial_register(serial,
+                              "uart0",
+                              RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
+                              uart);
+    }
+#endif
+
+#ifdef TINA_USING_UART1
+    {
+        static struct rt_serial_device  serial1;
+        static struct device_uart       uart1;
+
+        serial  = &serial1;
+        uart    = &uart1;
+
+        serial->ops              = &_uart_ops;
+        serial->config           = config;
+        serial->config.baud_rate = 115200;
+
+        uart->hw_base      = UART1_BASE_ADDR; // UART1_BASE;
+        uart->irqno        = UART1_INTERRUPT; // IRQ_UART1;
+        uart->gpio_rx_port = GPIO_PORT_A;
+        uart->gpio_tx_port = GPIO_PORT_A;
+        uart->gpio_rx_pin  = GPIO_PIN_3;
+        uart->gpio_tx_pin  = GPIO_PIN_2;
+        uart->gpio_rx_fun  = IO_FUN_4;
+        uart->gpio_tx_fun  = IO_FUN_4;
+
+        rt_hw_serial_register(serial,
+                              "uart1",
+                              RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
+                              uart);
+    }
+#endif
+
+#ifdef TINA_USING_UART2
+    {
+        static struct rt_serial_device  serial2;
+        static struct device_uart       uart2;
+
+        serial  = &serial2;
+        uart    = &uart2;
+
+        serial->ops              = &_uart_ops;
+        serial->config           = config;
+        serial->config.baud_rate = 115200;
+
+        uart->hw_base      = UART2_BASE_ADDR; // UART1_BASE;
+        uart->irqno        = UART2_INTERRUPT; // IRQ_UART1;
+        uart->gpio_rx_port = GPIO_PORT_E;
+        uart->gpio_tx_port = GPIO_PORT_E;
+        uart->gpio_rx_pin  = GPIO_PIN_8;
+        uart->gpio_tx_pin  = GPIO_PIN_7;
+        uart->gpio_rx_fun  = IO_FUN_2;
+        uart->gpio_tx_fun  = IO_FUN_2;
+
+        rt_hw_serial_register(serial,
+                              "uart2",
+                              RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
+                              uart);
+    }
+#endif
+
+    return 0;
+}
+
+/*
+ * UART interface
+ */
+static rt_err_t uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
+{
+    rt_uint32_t addr, val;
+    struct device_uart *uart;
+
+    RT_ASSERT(serial != RT_NULL);
+    serial->config = *cfg;
+
+    uart = serial->parent.user_data;
+    RT_ASSERT(uart != RT_NULL);
+    /* config gpio port */
+    gpio_set_func(uart->gpio_rx_port, uart->gpio_rx_pin, uart->gpio_rx_fun);
+    gpio_set_func(uart->gpio_tx_port, uart->gpio_tx_pin, uart->gpio_tx_fun);
+    /* Enable UART clock */
+    /* Open the clock gate for uart */
+    if ((rt_uint32_t)(uart->hw_base) == UART0_BASE_ADDR)
+    {
+        bus_gate_clk_enalbe(UART0_GATING);
+        bus_software_reset_enalbe(UART0_GATING);
+    }
+    else if ((rt_uint32_t)(uart->hw_base) == UART1_BASE_ADDR)
+    {
+        bus_gate_clk_enalbe(UART1_GATING);
+        bus_software_reset_enalbe(UART1_GATING);
+    }
+    else if ((rt_uint32_t)(uart->hw_base) == UART2_BASE_ADDR)
+    {
+        bus_gate_clk_enalbe(UART2_GATING);
+        bus_software_reset_enalbe(UART2_GATING);
+    }
+    else
+        RT_ASSERT(0);
+    /* Config uart0 to 115200-8-1-0 */
+    addr = uart->hw_base;
+    /* close uart irq */
+    writel(0x0, addr + UART_IER);
+    /* config fifo */
+    writel(0x37, addr + UART_FCR);
+    /* config modem */
+    writel(0x0, addr + UART_MCR);
+    /* config baud */
+    val = readl(addr + UART_LCR);
+    val |= (1 << 7);
+    writel(val, addr + UART_LCR);
+    val = apb_get_clk() / 16 / serial->config.baud_rate;
+    writel(val & 0xff, addr + UART_DLL);
+    writel((val >> 8) & 0xff, addr + UART_DLH);
+    val = readl(addr + UART_LCR);
+    val &= ~(1 << 7);
+    writel(val, addr + UART_LCR);
+
+    val = readl(addr + UART_LCR);
+    val &= ~0x1f;
+    val |= ((serial->config.data_bits - DATA_BITS_5) << 0) | (0 << 2) | (0x0 << 3);
+    writel(val, addr + UART_LCR);
+
+    writel(0xf, addr + UART_TFL);
+    writel(0x3F, addr + UART_RFL);
+
+    writel(0x1, addr + UART_IER);
+    return RT_EOK;
+}
+
+static rt_err_t uart_control(struct rt_serial_device *serial, int cmd, void *arg)
+{
+    struct device_uart *uart;
+
+    uart = serial->parent.user_data;
+
+    RT_ASSERT(uart != RT_NULL);
+
+    switch (cmd)
+    {
+    case RT_DEVICE_CTRL_CLR_INT:
+        /* Disable the UART Interrupt */
+        rt_hw_interrupt_mask(uart->irqno);
+        writel(0x00, uart->hw_base + UART_IER);
+        break;
+
+    case RT_DEVICE_CTRL_SET_INT:
+        /* install interrupt */
+        rt_hw_interrupt_install(uart->irqno, uart_irq_handler,
+                                serial, uart->name);
+        rt_hw_interrupt_umask(uart->irqno);
+        writel(0x01, uart->hw_base + UART_IER);
+        /* Enable the UART Interrupt */
+        break;
+    }
+
+    return (RT_EOK);
+}
+
+
+static int uart_putc(struct rt_serial_device *serial, char c)
+{
+    struct device_uart *uart;
+    volatile rt_uint32_t *sed_buf;
+    volatile rt_uint32_t *sta;
+
+    uart = serial->parent.user_data;
+    sed_buf = (rt_uint32_t *)(uart->hw_base + UART_THR);
+    sta = (rt_uint32_t *)(uart->hw_base + UART_USR);
+    /* FIFO status, contain valid data */
+    while (!(*sta & 0x02));
+    *sed_buf = c;
+
+    return (1);
+}
+
+static int uart_getc(struct rt_serial_device *serial)
+{
+    int ch = -1;
+    volatile rt_uint32_t *rec_buf;
+    volatile rt_uint32_t *sta;
+    struct device_uart *uart = serial->parent.user_data;
+
+    RT_ASSERT(serial != RT_NULL);
+
+    rec_buf = (rt_uint32_t *)(uart->hw_base + UART_RHB);
+    sta = (rt_uint32_t *)(uart->hw_base + UART_USR);
+    /* Receive Data Available */
+    if (*sta & 0x08)
+    {
+        ch = *rec_buf & 0xff;
+    }
+
+    return ch;
+}
+
+static rt_size_t uart_dma_transmit(struct rt_serial_device *serial, rt_uint8_t *buf, rt_size_t size, int direction)
+{
+    return (0);
+}
+
+/* UART ISR */
+void uart_irq_handler(int irqno, void *param)
+{
+    rt_uint32_t val;
+    struct rt_serial_device *serial = (struct rt_serial_device *)param;
+    struct device_uart *uart = serial->parent.user_data;
+
+    val = readl(uart->hw_base + 0x08) & 0x0F;
+    /* read interrupt status and clear it */
+    if (val & 0x4) /* rx ind */
+    {
+        rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
+    }
+
+    if (0) /* tx done */
+    {
+        rt_hw_serial_isr(serial, RT_SERIAL_EVENT_TX_DONE);
+    }
+
+}
+
+#endif

+ 83 - 0
bsp/allwinner_tina/drivers/drv_uart.h

@@ -0,0 +1,83 @@
+/*
+ * File      : drv_uart.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2017, RT-Thread Development Team
+ *
+ *  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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-02-08     RT-Thread    the first version
+ */
+
+
+#ifndef __DRV_UART_H__
+#define __DRV_UART_H__
+
+#define UART0_BASE_ADDR (0x01C25000)
+#define UART1_BASE_ADDR (0x01C25400)
+#define UART2_BASE_ADDR (0x01C25800)
+
+#define UART_THR        (0X00)
+#define UART_RHB        (0X00)
+#define UART_DLL        (0X00)
+#define UART_DLH        (0X04)
+#define UART_IER        (0X04)
+#define UART_IIR        (0X08)
+#define UART_FCR        (0X08)
+#define UART_LCR        (0X0C)
+#define UART_MCR        (0X10)
+#define UART_LSR        (0X14)
+#define UART_MSR        (0X18)
+#define UART_SCH        (0X1C)
+#define UART_USR        (0X7C)
+#define UART_TFL        (0X80)
+#define UART_RFL        (0X84)
+#define UART_HSK        (0X88)
+#define UART_HALT       (0XA4)
+#define UART_DBG_DLL    (0XB0)
+#define UART_DBG_DLH    (0XB4)
+
+struct tina_uart
+{
+    volatile rt_uint32_t rx_tx_dll;          /* 0x00 */
+    volatile rt_uint32_t dlh_ier;           /* 0x04 */
+    volatile rt_uint32_t iir_fcr;           /* 0x08 */
+    volatile rt_uint32_t lcr;               /* 0x0C */
+    volatile rt_uint32_t mcr;               /* 0x10 */
+    volatile rt_uint32_t lsr;               /* 0x14 */
+    volatile rt_uint32_t msr;               /* 0x18 */
+    volatile rt_uint32_t sch;               /* 0x1C */
+    volatile rt_uint32_t reserved0[23];
+    volatile rt_uint32_t usr;               /* 0x7c */
+    volatile rt_uint32_t tfl;               /* 0x80 */
+    volatile rt_uint32_t rfl;               /* 0x84 */
+    volatile rt_uint32_t hsk;               /* 0x88 */
+    volatile rt_uint32_t reserved1[6];
+    volatile rt_uint32_t halt;              /* 0xa4 */
+    volatile rt_uint32_t reserved2[2];
+    volatile rt_uint32_t dbg_dll;           /* 0xb0 */
+    volatile rt_uint32_t dbg_dlh;           /* 0xb4 */
+};
+
+typedef struct tina_uart *tina_uart_t;
+
+#define UART0 ((tina_gpio_t)UART0_BASE_ADDR)
+#define UART1 ((tina_gpio_t)UART1_BASE_ADDR)
+#define UART2 ((tina_gpio_t)UART2_BASE_ADDR)
+
+int rt_hw_uart_init(void);
+
+#endif /* __DRV_UART_H__ */

+ 13 - 0
bsp/allwinner_tina/libcpu/SConscript

@@ -0,0 +1,13 @@
+Import('rtconfig')
+from building import *
+
+cwd     = GetCurrentDir()
+src     = Glob('*.c')
+CPPPATH = [cwd]
+
+if rtconfig.PLATFORM == 'gcc':
+    src += Glob('*_gcc.S')
+
+group = DefineGroup('CPU', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')

+ 92 - 0
bsp/allwinner_tina/libcpu/context_gcc.S

@@ -0,0 +1,92 @@
+;/*
+; * File      : context_iar.S
+; * This file is part of RT-Thread RTOS
+; * COPYRIGHT (C) 2006, RT-Thread Development Team
+; *
+; *  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.,
+; *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+; *
+; * Change Logs:
+; * Date           Author       Notes
+; * 2011-08-14     weety    copy from mini2440
+; */
+
+#define NOINT   0xC0
+
+;/*
+; * rt_base_t rt_hw_interrupt_disable();
+; */
+    .globl rt_hw_interrupt_disable
+rt_hw_interrupt_disable:
+    MRS     R0, CPSR
+    ORR     R1, R0, #NOINT
+    MSR     CPSR_c, R1
+    BX      LR
+
+/*
+ * void rt_hw_interrupt_enable(rt_base_t level);
+ */
+    .globl rt_hw_interrupt_enable
+rt_hw_interrupt_enable:
+    MSR     CPSR, R0
+    BX      LR
+
+/*
+ * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);
+ * r0 --> from
+ * r1 --> to
+ */
+    .globl rt_hw_context_switch
+rt_hw_context_switch:
+    STMFD   SP!, {LR}           @; push pc (lr should be pushed in place of pc)
+    STMFD   SP!, {R0-R12, LR}       @; push lr & register file
+    MRS     R4, CPSR
+    STMFD   SP!, {R4}               @; push cpsr
+    STR     SP, [R0]                @; store sp in preempted tasks tcb
+    LDR     SP, [R1]                @; get new task stack pointer
+    LDMFD   SP!, {R4}               @; pop new task spsr
+    MSR     SPSR_cxsf, R4
+    LDMFD   SP!, {R0-R12, LR, PC}^  @; pop new task r0-r12, lr & pc
+
+/*
+ * void rt_hw_context_switch_to(rt_uint32 to);
+ * r0 --> to
+ */
+    .globl rt_hw_context_switch_to
+rt_hw_context_switch_to:
+    LDR     SP, [R0]                @; get new task stack pointer
+    LDMFD   SP!, {R4}               @; pop new task cpsr
+    MSR     SPSR_cxsf, R4
+    LDMFD   SP!, {R0-R12, LR, PC}^  @; pop new task r0-r12, lr & pc
+
+/*
+ * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to);
+ */
+    .globl rt_thread_switch_interrupt_flag
+    .globl rt_interrupt_from_thread
+    .globl rt_interrupt_to_thread
+    .globl rt_hw_context_switch_interrupt
+rt_hw_context_switch_interrupt:
+    LDR     R2, =rt_thread_switch_interrupt_flag
+    LDR     R3, [R2]
+    CMP     R3, #1
+    BEQ     _reswitch
+    MOV     R3, #1                          @; set flag to 1
+    STR     R3, [R2]
+    LDR     R2, =rt_interrupt_from_thread   @; set rt_interrupt_from_thread
+    STR     R0, [R2]
+_reswitch:
+    LDR     R2, =rt_interrupt_to_thread     @; set rt_interrupt_to_thread
+    STR     R1, [R2]
+    BX      LR

+ 41 - 0
bsp/allwinner_tina/libcpu/cpu.c

@@ -0,0 +1,41 @@
+/*
+ * File      : cpu.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2017, RT-Thread Development Team
+ *
+ *  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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-02-08     RT-Thread    the first version
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+
+RT_WEAK void machine_reset(void)
+{
+    rt_kprintf("reboot system...\n");
+    rt_hw_interrupt_disable();
+    while (1);
+}
+
+RT_WEAK void machine_shutdown(void)
+{
+    rt_kprintf("shutdown...\n");
+    rt_hw_interrupt_disable();
+    while (1);
+}
+

+ 229 - 0
bsp/allwinner_tina/libcpu/cpuport.c

@@ -0,0 +1,229 @@
+/*
+ * File      : cpuport.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2017, RT-Thread Development Team
+ *
+ *  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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-02-08     RT-Thread    the first version
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+
+#define ICACHE_MASK    (rt_uint32_t)(1 << 12)
+#define DCACHE_MASK    (rt_uint32_t)(1 << 2)
+
+extern void machine_reset(void);
+extern void machine_shutdown(void);
+
+#if defined(__GNUC__) || defined(__ICCARM__)
+rt_inline rt_uint32_t cp15_rd(void)
+{
+    rt_uint32_t i;
+
+    __asm volatile("mrc p15, 0, %0, c1, c0, 0":"=r"(i));
+    return i;
+}
+
+rt_inline void cache_enable(rt_uint32_t bit)
+{
+    __asm volatile(\
+                   "mrc  p15,0,r0,c1,c0,0\n\t"    \
+                   "orr  r0,r0,%0\n\t"            \
+                   "mcr  p15,0,r0,c1,c0,0"        \
+                   :                              \
+                   : "r"(bit)                     \
+                   : "memory");
+}
+
+rt_inline void cache_disable(rt_uint32_t bit)
+{
+    __asm volatile(\
+                   "mrc  p15,0,r0,c1,c0,0\n\t"    \
+                   "bic  r0,r0,%0\n\t"            \
+                   "mcr  p15,0,r0,c1,c0,0"        \
+                   :                              \
+                   : "r"(bit)                     \
+                   : "memory");
+}
+#endif
+
+#if defined(__CC_ARM)
+rt_inline rt_uint32_t cp15_rd(void)
+{
+    rt_uint32_t i;
+
+    __asm volatile
+    {
+        mrc p15, 0, i, c1, c0, 0
+    }
+
+    return i;
+}
+
+rt_inline void cache_enable(rt_uint32_t bit)
+{
+    rt_uint32_t value;
+
+    __asm volatile
+    {
+        mrc p15, 0, value, c1, c0, 0
+        orr value, value, bit
+        mcr p15, 0, value, c1, c0, 0
+    }
+}
+
+rt_inline void cache_disable(rt_uint32_t bit)
+{
+    rt_uint32_t value;
+
+    __asm volatile
+    {
+        mrc p15, 0, value, c1, c0, 0
+        bic value, value, bit
+        mcr p15, 0, value, c1, c0, 0
+    }
+}
+#endif
+
+/**
+ * enable I-Cache
+ *
+ */
+void rt_hw_cpu_icache_enable()
+{
+    cache_enable(ICACHE_MASK);
+}
+
+/**
+ * disable I-Cache
+ *
+ */
+void rt_hw_cpu_icache_disable()
+{
+    cache_disable(ICACHE_MASK);
+}
+
+/**
+ * return the status of I-Cache
+ *
+ */
+rt_base_t rt_hw_cpu_icache_status()
+{
+    return (cp15_rd() & ICACHE_MASK);
+}
+
+/**
+ * enable D-Cache
+ *
+ */
+void rt_hw_cpu_dcache_enable()
+{
+    cache_enable(DCACHE_MASK);
+}
+
+/**
+ * disable D-Cache
+ *
+ */
+void rt_hw_cpu_dcache_disable()
+{
+    cache_disable(DCACHE_MASK);
+}
+
+/**
+ * return the status of D-Cache
+ *
+ */
+rt_base_t rt_hw_cpu_dcache_status()
+{
+    return (cp15_rd() & DCACHE_MASK);
+}
+
+/**
+ * reset cpu by dog's time-out
+ *
+ */
+void rt_hw_cpu_reset()
+{
+
+    rt_kprintf("Restarting system...\n");
+    machine_reset();
+
+    while (1);   /* loop forever and wait for reset to happen */
+
+    /* NEVER REACHED */
+}
+
+/**
+ *  shutdown CPU
+ *
+ */
+void rt_hw_cpu_shutdown()
+{
+    rt_uint32_t level;
+    rt_kprintf("shutdown...\n");
+
+    level = rt_hw_interrupt_disable();
+    machine_shutdown();
+    while (level)
+    {
+        RT_ASSERT(0);
+    }
+}
+
+#ifdef RT_USING_CPU_FFS
+/**
+ * This function finds the first bit set (beginning with the least significant bit)
+ * in value and return the index of that bit.
+ *
+ * Bits are numbered starting at 1 (the least significant bit).  A return value of
+ * zero from any of these functions means that the argument was zero.
+ *
+ * @return return the index of the first bit set. If value is 0, then this function
+ * shall return 0.
+ */
+#if defined(__CC_ARM)
+int __rt_ffs(int value)
+{
+    register rt_uint32_t x;
+
+    if (value == 0)
+        return value;
+
+    __asm
+    {
+        rsb x, value, #0
+        and x, x, value
+        clz x, x
+        rsb x, x, #32
+    }
+
+    return x;
+}
+#elif defined(__GNUC__) || defined(__ICCARM__)
+int __rt_ffs(int value)
+{
+    return __builtin_ffs(value);
+}
+#endif
+
+#endif
+
+
+/*@}*/

+ 206 - 0
bsp/allwinner_tina/libcpu/interrupt.c

@@ -0,0 +1,206 @@
+/*
+ * File      : interrupt.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2017, RT-Thread Development Team
+ *
+ *  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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-02-08     RT-Thread    the first version
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+
+#include "interrupt.h"
+
+extern rt_uint32_t rt_interrupt_nest;
+rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread;
+rt_uint32_t rt_thread_switch_interrupt_flag;
+
+static struct rt_irq_desc isr_table[INTERRUPTS_MAX];
+
+static void rt_hw_interrupt_handler(int vector, void *param)
+{
+    rt_kprintf("Unhandled interrupt %d occured!!!\n", vector);
+}
+
+#define readl(addr)           (*(volatile unsigned int *)(addr))
+#define writel(value,addr)    (*(volatile unsigned int *)(addr) = (value))
+
+/**
+ * This function will initialize hardware interrupt
+ */
+void rt_hw_interrupt_init(void)
+{
+    rt_int32_t idx;
+
+    rt_memset(isr_table, 0x00, sizeof(isr_table));
+    for (idx = 0; idx < INTERRUPTS_MAX; idx ++)
+    {
+        isr_table[idx].handler = rt_hw_interrupt_handler;
+    }
+
+    /* init interrupt nest, and context in thread sp */
+    rt_interrupt_nest               = 0;
+    rt_interrupt_from_thread        = 0;
+    rt_interrupt_to_thread          = 0;
+    rt_thread_switch_interrupt_flag = 0;
+
+    /* set base_addr reg */
+    INTC->base_addr_reg = 0x00000000;
+    /* clear enable */
+    INTC->en_reg0 = 0x00000000;
+    INTC->en_reg1 = 0x00000000;
+    /* mask interrupt */
+    INTC->mask_reg0 = 0xFFFFFFFF;
+    INTC->mask_reg1 = 0xFFFFFFFF;
+    /* clear pending */
+    INTC->pend_reg0 = 0x00000000;
+    INTC->pend_reg1 = 0x00000000;
+    /* set priority */
+    INTC->resp_reg0 = 0x00000000;
+    INTC->resp_reg1 = 0x00000000;
+    /* close fiq interrupt */
+    INTC->ff_reg0 = 0x00000000;
+    INTC->ff_reg1 = 0x00000000;
+}
+
+/**
+ * This function will mask a interrupt.
+ * @param vector the interrupt number
+ */
+void rt_hw_interrupt_mask(int vector)
+{
+    rt_uint32_t mask_addr, data;
+
+    if ((vector < 0) || (vector > INTERRUPTS_MAX))
+    {
+        return;
+    }
+
+    mask_addr = (rt_uint32_t)(&INTC->mask_reg0);
+    mask_addr += vector & 0xE0 ? sizeof(rt_uint32_t *) : 0;
+
+    vector &= 0x1F;
+    data = readl(mask_addr);
+    data |= 0x1 << vector;
+    writel(data, mask_addr);
+}
+
+/**
+ * This function will un-mask a interrupt.
+ * @param vector the interrupt number
+ */
+void rt_hw_interrupt_umask(int vector)
+{
+    rt_uint32_t mask_addr, data;
+
+    if ((vector < 0) || (vector > INTERRUPTS_MAX))
+    {
+        return;
+    }
+
+    mask_addr = (rt_uint32_t)(&INTC->mask_reg0);
+    mask_addr += vector & 0xE0 ? sizeof(rt_uint32_t *) : 0;
+
+    vector &= 0x1F;
+    data = readl(mask_addr);
+    data &= ~(0x1 << vector);
+    writel(data, mask_addr);
+}
+
+/**
+ * This function will install a interrupt service routine to a interrupt.
+ * @param vector the interrupt number
+ * @param handler the interrupt service routine to be installed
+ * @param param the interrupt service function parameter
+ * @param name the interrupt name
+ * @return old handler
+ */
+rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
+        void *param, char *name)
+{
+    rt_isr_handler_t old_handler = RT_NULL;
+    rt_uint32_t pend_addr, en_addr, data;
+
+    if ((vector < 0) || (vector > INTERRUPTS_MAX))
+    {
+        return old_handler;
+    }
+
+    old_handler = isr_table[vector].handler;
+
+#ifdef RT_USING_INTERRUPT_INFO
+    rt_strncpy(isr_table[vector].name, name, RT_NAME_MAX);
+#endif /* RT_USING_INTERRUPT_INFO */
+    isr_table[vector].handler = handler;
+    isr_table[vector].param = param;
+
+    pend_addr = (rt_uint32_t)(&INTC->pend_reg0);
+    en_addr = (rt_uint32_t)(&INTC->en_reg0);
+    pend_addr += vector & 0xE0 ? sizeof(rt_uint32_t *) : 0;
+    en_addr += vector & 0xE0 ? sizeof(rt_uint32_t *) : 0;
+
+    vector &= 0x1F;
+    data = readl(pend_addr);
+    data &= ~(0x1 << vector);
+    writel(data, pend_addr);
+
+    data = readl(en_addr);
+    data |= 0x1 << vector;
+    writel(data, en_addr);
+
+    return old_handler;
+}
+
+void rt_interrupt_dispatch(void)
+{
+    void *param;
+    int vector;
+    rt_isr_handler_t isr_func;
+    rt_uint32_t pend_addr, data;
+
+    vector = INTC->vector_reg - INTC->base_addr_reg;
+    vector = vector >> 2;
+
+    isr_func = isr_table[vector].handler;
+    param = isr_table[vector].param;
+
+    /* jump to fun */
+    isr_func(vector, param);
+    /* clear pend bit */
+    pend_addr = (rt_uint32_t)(&INTC->pend_reg0);
+    pend_addr += vector & 0xE0 ? sizeof(rt_uint32_t *) : 0;
+
+    vector &= 0x1F;
+    data = readl(pend_addr);
+    data &= ~(0x1 << vector);
+    writel(data, pend_addr);
+
+#ifdef RT_USING_INTERRUPT_INFO
+    isr_table[vector].counter ++;
+#endif
+}
+
+
+
+
+
+
+
+
+

+ 107 - 0
bsp/allwinner_tina/libcpu/interrupt.h

@@ -0,0 +1,107 @@
+/*
+ * File      : interrupt.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2017, RT-Thread Development Team
+ *
+ *  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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-02-08     RT-Thread    the first version
+ */
+#ifndef __INTERRUPT_H__
+#define __INTERRUPT_H__
+
+/* Max number of interruptions */
+#define INTERRUPTS_MAX       (64)
+/* a group num */
+#define GROUP_NUM            (32)
+/* Interrupt Source */
+#define NMI_INTERRUPT              (0)
+#define UART0_INTERRUPT            (1)
+#define UART1_INTERRUPT            (2)
+#define UART2_INTERRUPT            (3)
+#define OWA_INTERRUPT              (5)
+#define CIR_INTERRUPT              (6)
+#define TWI0_INTERRUPT             (7)
+#define TWI1_INTERRUPT             (8)
+#define TWI2_INTERRUPT             (9)
+#define SPI0_INTERRUPT             (10)
+#define SPI1_INTERRUPT             (11)
+#define TIMER0_INTERRUPT           (13)
+#define TIMER1_INTERRUPT           (14)
+#define TIMER2_INTERRUPT           (15)
+#define WATCHDOG_INTERRUPT         (16)
+#define RSB_INTERRUPT              (17)
+#define DMA_INTERRUPT              (18)
+#define TOUCHPANEL_INTERRUPT       (20)
+#define AUDIOCODEC_INTERRUPT       (21)
+#define KEYADC_INTERRUPT           (22)
+#define SDC0_INTERRUPT             (23)
+#define SDC1_INTERRUPT             (24)
+#define USB_OTG_INTERRUPT          (26)
+#define TVD_INTERRUPT              (27)
+#define TVE_INTERRUPT              (28)
+#define TCON_INTERRUPT             (29)
+#define DE_FE_INTERRUPT            (30)
+#define DE_BE_INTERRUPT            (31)
+#define CSI_INTERRUPT              (32)
+#define DE_INTERLACER_INTERRUPT    (33)
+#define VE_INTERRUPT               (34)
+#define DAUDIO_INTERRUPT           (35)
+#define PIOD_INTERRUPT             (38)
+#define PIOE_INTERRUPT             (39)
+#define PIOF_INTERRUPT             (40)
+
+/* intc  register address */
+#define INTC_BASE_ADDR     (0x01C20400)
+
+struct tina_intc
+{
+    volatile rt_uint32_t vector_reg;       /* 0x00 */
+    volatile rt_uint32_t base_addr_reg;    /* 0x04 */
+    volatile rt_uint32_t reserved0;
+    volatile rt_uint32_t nmi_ctrl_reg;     /* 0x0C */
+    volatile rt_uint32_t pend_reg0;        /* 0x10 */
+    volatile rt_uint32_t pend_reg1;        /* 0x14 */
+    volatile rt_uint32_t reserved1[2];
+    volatile rt_uint32_t en_reg0;          /* 0x20 */
+    volatile rt_uint32_t en_reg1;          /* 0x24 */
+    volatile rt_uint32_t reserved2[2];
+    volatile rt_uint32_t mask_reg0;        /* 0x30 */
+    volatile rt_uint32_t mask_reg1;        /* 0x34 */
+    volatile rt_uint32_t reserved3[2];
+    volatile rt_uint32_t resp_reg0;        /* 0x40 */
+    volatile rt_uint32_t resp_reg1;        /* 0x44 */
+    volatile rt_uint32_t reserved4[2];
+    volatile rt_uint32_t ff_reg0;          /* 0x50 */
+    volatile rt_uint32_t ff_reg1;          /* 0x54 */
+    volatile rt_uint32_t reserved5[2];
+    volatile rt_uint32_t prio_reg0;        /* 0x60 */
+    volatile rt_uint32_t prio_reg1;        /* 0x64 */
+    volatile rt_uint32_t prio_reg2;        /* 0x68 */
+    volatile rt_uint32_t prio_reg3;        /* 0x6C */
+} ;
+
+typedef struct tina_intc *tina_intc_t;
+
+#define INTC ((tina_intc_t)INTC_BASE_ADDR)
+
+void rt_hw_interrupt_init(void);
+void rt_hw_interrupt_mask(int vector);
+void rt_hw_interrupt_umask(int vector);
+rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, void *param, char *name);
+
+#endif /* __INTERRUPT_H__ */

+ 457 - 0
bsp/allwinner_tina/libcpu/mmu.c

@@ -0,0 +1,457 @@
+/*
+ * File      : mmu.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2017, RT-Thread Development Team
+ *
+ *  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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-02-08     RT-Thread    the first version
+ */
+
+#include "mmu.h"
+
+/*----- Keil -----------------------------------------------------------------*/
+#ifdef __CC_ARM
+void mmu_setttbase(rt_uint32_t i)
+{
+    register rt_uint32_t value;
+
+    /* Invalidates all TLBs.Domain access is selected as
+     * client by configuring domain access register,
+     * in that case access controlled by permission value
+     * set by page table entry
+     */
+    value = 0;
+    __asm volatile{ mcr p15, 0, value, c8, c7, 0 }
+    value = 0x55555555;
+    __asm volatile { mcr p15, 0, value, c3, c0, 0 }
+    __asm volatile { mcr p15, 0, i, c2, c0, 0 }
+}
+
+void mmu_set_domain(rt_uint32_t i)
+{
+    __asm volatile { mcr p15, 0, i, c3, c0,  0 }
+}
+
+void mmu_enable()
+{
+    register rt_uint32_t value;
+
+    __asm volatile
+    {
+        mrc p15, 0, value, c1, c0, 0
+        orr value, value, #0x01
+        mcr p15, 0, value, c1, c0, 0
+    }
+}
+
+void mmu_disable()
+{
+    register rt_uint32_t value;
+
+    __asm volatile
+    {
+        mrc p15, 0, value, c1, c0, 0
+        bic value, value, #0x01
+        mcr p15, 0, value, c1, c0, 0
+    }
+}
+
+void mmu_enable_icache()
+{
+    register rt_uint32_t value;
+
+    __asm volatile
+    {
+        mrc p15, 0, value, c1, c0, 0
+        orr value, value, #0x1000
+        mcr p15, 0, value, c1, c0, 0
+    }
+}
+
+void mmu_enable_dcache()
+{
+    register rt_uint32_t value;
+
+    __asm volatile
+    {
+        mrc p15, 0, value, c1, c0, 0
+        orr value, value, #0x04
+        mcr p15, 0, value, c1, c0, 0
+    }
+}
+
+void mmu_disable_icache()
+{
+    register rt_uint32_t value;
+
+    __asm volatile
+    {
+        mrc p15, 0, value, c1, c0, 0
+        bic value, value, #0x1000
+        mcr p15, 0, value, c1, c0, 0
+    }
+}
+
+void mmu_disable_dcache()
+{
+    register rt_uint32_t value;
+
+    __asm volatile
+    {
+        mrc p15, 0, value, c1, c0, 0
+        bic value, value, #0x04
+        mcr p15, 0, value, c1, c0, 0
+    }
+}
+
+void mmu_enable_alignfault()
+{
+    register rt_uint32_t value;
+
+    __asm volatile
+    {
+        mrc p15, 0, value, c1, c0, 0
+        orr value, value, #0x02
+        mcr p15, 0, value, c1, c0, 0
+    }
+}
+
+void mmu_disable_alignfault()
+{
+    register rt_uint32_t value;
+
+    __asm volatile
+    {
+        mrc p15, 0, value, c1, c0, 0
+        bic value, value, #0x02
+        mcr p15, 0, value, c1, c0, 0
+    }
+}
+
+void mmu_clean_invalidated_cache_index(int index)
+{
+    __asm volatile { mcr p15, 0, index, c7, c14, 2 }
+}
+
+void mmu_clean_invalidated_dcache(rt_uint32_t buffer, rt_uint32_t size)
+{
+    unsigned int ptr;
+
+    ptr = buffer & ~(CACHE_LINE_SIZE - 1);
+
+    while (ptr < buffer + size)
+    {
+        __asm volatile { MCR p15, 0, ptr, c7, c14, 1 }
+        ptr += CACHE_LINE_SIZE;
+    }
+}
+
+void mmu_clean_dcache(rt_uint32_t buffer, rt_uint32_t size)
+{
+    unsigned int ptr;
+
+    ptr = buffer & ~(CACHE_LINE_SIZE - 1);
+
+    while (ptr < buffer + size)
+    {
+        __asm volatile { MCR p15, 0, ptr, c7, c10, 1 }
+        ptr += CACHE_LINE_SIZE;
+    }
+}
+
+void mmu_invalidate_dcache(rt_uint32_t buffer, rt_uint32_t size)
+{
+    unsigned int ptr;
+
+    ptr = buffer & ~(CACHE_LINE_SIZE - 1);
+
+    while (ptr < buffer + size)
+    {
+        __asm volatile { MCR p15, 0, ptr, c7, c6, 1 }
+        ptr += CACHE_LINE_SIZE;
+    }
+}
+
+void mmu_invalidate_tlb()
+{
+    register rt_uint32_t value;
+
+    value = 0;
+    __asm volatile { mcr p15, 0, value, c8, c7, 0 }
+}
+
+void mmu_invalidate_icache()
+{
+    register rt_uint32_t value;
+
+    value = 0;
+
+    __asm volatile { mcr p15, 0, value, c7, c5, 0 }
+}
+
+
+void mmu_invalidate_dcache_all()
+{
+    register rt_uint32_t value;
+
+    value = 0;
+
+    __asm volatile { mcr p15, 0, value, c7, c6, 0 }
+}
+/*----- GNU ------------------------------------------------------------------*/
+#elif defined(__GNUC__) || defined(__ICCARM__)
+void mmu_setttbase(register rt_uint32_t i)
+{
+    register rt_uint32_t value;
+
+    /* Invalidates all TLBs.Domain access is selected as
+     * client by configuring domain access register,
+     * in that case access controlled by permission value
+     * set by page table entry
+     */
+    value = 0;
+    asm volatile("mcr p15, 0, %0, c8, c7, 0"::"r"(value));
+
+    value = 0x55555555;
+    asm volatile("mcr p15, 0, %0, c3, c0, 0"::"r"(value));
+
+    asm volatile("mcr p15, 0, %0, c2, c0, 0"::"r"(i));
+
+}
+
+void mmu_set_domain(register rt_uint32_t i)
+{
+    asm volatile("mcr p15,0, %0, c3, c0,  0": :"r"(i));
+}
+
+void mmu_enable()
+{
+    asm volatile
+    (
+        "mrc p15, 0, r0, c1, c0, 0 \n"
+        "orr r0, r0, #0x1 \n"
+        "mcr p15, 0, r0, c1, c0, 0 \n"
+        :::"r0"
+    );
+}
+
+void mmu_disable()
+{
+    asm volatile
+    (
+        "mrc p15, 0, r0, c1, c0, 0 \n"
+        "bic r0, r0, #0x1 \n"
+        "mcr p15, 0, r0, c1, c0, 0 \n"
+        :::"r0"
+    );
+
+}
+
+void mmu_enable_icache()
+{
+    asm volatile
+    (
+        "mrc p15, 0, r0, c1, c0, 0 \n"
+        "orr r0, r0, #(1<<12) \n"
+        "mcr p15, 0, r0, c1, c0, 0 \n"
+        :::"r0"
+    );
+}
+
+void mmu_enable_dcache()
+{
+    asm volatile
+    (
+        "mrc p15, 0, r0, c1, c0, 0 \n"
+        "orr r0, r0, #(1<<2) \n"
+        "mcr p15, 0, r0, c1, c0, 0 \n"
+        :::"r0"
+    );
+
+}
+
+void mmu_disable_icache()
+{
+    asm volatile
+    (
+        "mrc p15, 0, r0, c1, c0, 0 \n"
+        "bic r0, r0, #(1<<12) \n"
+        "mcr p15, 0, r0, c1, c0, 0 \n"
+        :::"r0"
+    );
+
+}
+
+void mmu_disable_dcache()
+{
+    asm volatile
+    (
+        "mrc p15, 0, r0, c1, c0, 0 \n"
+        "bic r0, r0, #(1<<2) \n"
+        "mcr p15, 0, r0, c1, c0, 0 \n"
+        :::"r0"
+    );
+
+}
+
+void mmu_enable_alignfault()
+{
+    asm volatile
+    (
+        "mrc p15, 0, r0, c1, c0, 0 \n"
+        "orr r0, r0, #1 \n"
+        "mcr p15, 0, r0, c1, c0, 0 \n"
+        :::"r0"
+    );
+
+}
+
+void mmu_disable_alignfault()
+{
+    asm volatile
+    (
+        "mrc p15, 0, r0, c1, c0, 0 \n"
+        "bic r0, r0, #1 \n"
+        "mcr p15, 0, r0, c1, c0, 0 \n"
+        :::"r0"
+    );
+
+}
+
+void mmu_clean_invalidated_cache_index(int index)
+{
+    asm volatile("mcr p15, 0, %0, c7, c14, 2": :"r"(index));
+}
+
+void mmu_clean_invalidated_dcache(rt_uint32_t buffer, rt_uint32_t size)
+{
+    unsigned int ptr;
+
+    ptr = buffer & ~(CACHE_LINE_SIZE - 1);
+
+    while (ptr < buffer + size)
+    {
+        asm volatile("mcr p15, 0, %0, c7, c14, 1": :"r"(ptr));
+
+        ptr += CACHE_LINE_SIZE;
+    }
+}
+
+
+void mmu_clean_dcache(rt_uint32_t buffer, rt_uint32_t size)
+{
+    unsigned int ptr;
+
+    ptr = buffer & ~(CACHE_LINE_SIZE - 1);
+
+    while (ptr < buffer + size)
+    {
+        asm volatile("mcr p15, 0, %0, c7, c10, 1": :"r"(ptr));
+
+        ptr += CACHE_LINE_SIZE;
+    }
+}
+
+void mmu_invalidate_dcache(rt_uint32_t buffer, rt_uint32_t size)
+{
+    unsigned int ptr;
+
+    ptr = buffer & ~(CACHE_LINE_SIZE - 1);
+
+    while (ptr < buffer + size)
+    {
+        asm volatile("mcr p15, 0, %0, c7, c6, 1": :"r"(ptr));
+
+        ptr += CACHE_LINE_SIZE;
+    }
+}
+
+void mmu_invalidate_tlb()
+{
+    asm volatile("mcr p15, 0, %0, c8, c7, 0": :"r"(0));
+
+}
+
+void mmu_invalidate_icache()
+{
+    asm volatile("mcr p15, 0, %0, c7, c5, 0": :"r"(0));
+
+}
+
+void mmu_invalidate_dcache_all()
+{
+    asm volatile("mcr p15, 0, %0, c7, c6, 0": :"r"(0));
+
+}
+#endif
+
+/* level1 page table */
+#if defined(__ICCARM__)
+#pragma data_alignment=(16*1024)
+static volatile rt_uint32_t _page_table[4 * 1024];
+#else
+static volatile rt_uint32_t _page_table[4 * 1024] \
+__attribute__((aligned(16 * 1024)));
+#endif
+
+void mmu_setmtt(rt_uint32_t vaddrStart, rt_uint32_t vaddrEnd,
+                rt_uint32_t paddrStart, rt_uint32_t attr)
+{
+    volatile rt_uint32_t *pTT;
+    volatile int nSec;
+    int i = 0;
+    pTT = (rt_uint32_t *)_page_table + (vaddrStart >> 20);
+    nSec = (vaddrEnd >> 20) - (vaddrStart >> 20);
+    for (i = 0; i <= nSec; i++)
+    {
+        *pTT = attr | (((paddrStart >> 20) + i) << 20);
+        pTT++;
+    }
+}
+
+void rt_hw_mmu_init(struct mem_desc *mdesc, rt_uint32_t size)
+{
+    /* disable I/D cache */
+    mmu_disable_dcache();
+    mmu_disable_icache();
+    mmu_disable();
+    mmu_invalidate_tlb();
+
+    /* set page table */
+    for (; size > 0; size--)
+    {
+        mmu_setmtt(mdesc->vaddr_start, mdesc->vaddr_end,
+                   mdesc->paddr_start, mdesc->attr);
+        mdesc++;
+    }
+
+    /* set MMU table address */
+    mmu_setttbase((rt_uint32_t)_page_table);
+
+    /* enables MMU */
+    mmu_enable();
+
+    /* enable Instruction Cache */
+    mmu_enable_icache();
+
+    /* enable Data Cache */
+    mmu_enable_dcache();
+
+    mmu_invalidate_icache();
+    mmu_invalidate_dcache_all();
+}

+ 65 - 0
bsp/allwinner_tina/libcpu/mmu.h

@@ -0,0 +1,65 @@
+/*
+ * File      : mmu.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2017, RT-Thread Development Team
+ *
+ *  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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-02-08     RT-Thread    the first version
+ */
+#ifndef __MMU_H__
+#define __MMU_H__
+
+#include <rtthread.h>
+
+#define CACHE_LINE_SIZE     32
+
+#define DESC_SEC            (0x2|(1<<4))
+#define CB                  (3<<2)  //cache_on, write_back
+#define CNB                 (2<<2)  //cache_on, write_through
+#define NCB                 (1<<2)  //cache_off,WR_BUF on
+#define NCNB                (0<<2)  //cache_off,WR_BUF off
+#define AP_RW               (3<<10) //supervisor=RW, user=RW
+#define AP_RO               (2<<10) //supervisor=RW, user=RO
+
+#define DOMAIN_FAULT        (0x0)
+#define DOMAIN_CHK          (0x1)
+#define DOMAIN_NOTCHK       (0x3)
+#define DOMAIN0             (0x0<<5)
+#define DOMAIN1             (0x1<<5)
+
+#define DOMAIN0_ATTR        (DOMAIN_CHK<<0)
+#define DOMAIN1_ATTR        (DOMAIN_FAULT<<2)
+
+#define RW_CB       (AP_RW|DOMAIN0|CB|DESC_SEC)     /* Read/Write, cache, write back */
+#define RW_CNB      (AP_RW|DOMAIN0|CNB|DESC_SEC)    /* Read/Write, cache, write through */
+#define RW_NCNB     (AP_RW|DOMAIN0|NCNB|DESC_SEC)   /* Read/Write without cache and write buffer */
+#define RW_FAULT    (AP_RW|DOMAIN1|NCNB|DESC_SEC)   /* Read/Write without cache and write buffer */
+
+struct mem_desc
+{
+    rt_uint32_t vaddr_start;
+    rt_uint32_t vaddr_end;
+    rt_uint32_t paddr_start;
+    rt_uint32_t attr;
+};
+
+void rt_hw_mmu_init(struct mem_desc *mdesc, rt_uint32_t size);
+void mmu_clean_invalidated_dcache(rt_uint32_t buffer, rt_uint32_t size);
+void mmu_clean_dcache(rt_uint32_t buffer, rt_uint32_t size);
+void mmu_invalidate_dcache(rt_uint32_t buffer, rt_uint32_t size);
+#endif

+ 81 - 0
bsp/allwinner_tina/libcpu/rt_low_level_init.c

@@ -0,0 +1,81 @@
+/*
+ * File      : rt_low_level_init.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2017, RT-Thread Development Team
+ *
+ *  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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-02-08     RT-Thread    the first version
+ */
+
+void rt_low_level_init(void)
+{
+    volatile unsigned int *addr;
+    volatile unsigned int time;
+    int i;
+
+    //change cpu clk source to 24M
+    addr = (unsigned int *)(0x01c20000 + 0x050);
+    *addr = 0x10000;
+    //init cpu pll clk 408M
+    addr = (unsigned int *)(0x01c20000 + 0x000);
+    *addr = 0x80001000;
+    time = 0xffff;
+    while ((!(*addr & (0x1 << 28))) && (time--));
+    //change cpu clk source to pll
+    if (time > 0)
+    {
+        addr = (unsigned int *)(0x01c20000 + 0x050);
+        *addr = 0x20000;
+    }
+
+    //init periph pll clk:600M
+    //init ahb    pll clk:200M
+    //init apb    pll clk:100M
+    addr = (unsigned int *)(0x01c20000 + 0x028);
+    if (*addr & (0x1 << 31))
+        return;
+
+    addr = (unsigned int *)(0x01c20000 + 0x200);
+    *addr = 0x1ff;
+    addr = (unsigned int *)(0x01c20000 + 0x204);
+    *addr = 0x1ff;
+
+    addr = (unsigned int *)(0x01c20000 + 0x028);
+    *addr |= (0x1 << 31);
+    while (!(*addr & (0x1 << 28)));
+
+    addr = (unsigned int *)(0x01c20000 + 0x054);
+    *addr = (0x0 << 16) | (0x3 << 12) | (0x0 << 8) | (0x2 << 6) | (0x0 << 4);
+
+    //init gpio config
+    for (i = 0; i < 6; i++)
+    {
+        if (i == 1)
+            continue;// not config gpio B
+
+        addr = (unsigned int *)(0x01c20800 + i * 0x24 + 0x00);
+        *addr = 0x77777777;
+        addr = (unsigned int *)(0x01c20800 + i * 0x24 + 0x04);
+        *addr = 0x77777777;
+        addr = (unsigned int *)(0x01c20800 + i * 0x24 + 0x08);
+        *addr = 0x77777777;
+        addr = (unsigned int *)(0x01c20800 + i * 0x24 + 0x0C);
+        *addr = 0x77777777;
+    }
+}
+

+ 81 - 0
bsp/allwinner_tina/libcpu/stack.c

@@ -0,0 +1,81 @@
+/*
+ * File      : stack.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2017, RT-Thread Development Team
+ *
+ *  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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-02-08     RT-Thread    the first version
+ */
+#include <rtthread.h>
+
+/*****************************/
+/* CPU Mode                  */
+/*****************************/
+#define USERMODE        0x10
+#define FIQMODE         0x11
+#define IRQMODE         0x12
+#define SVCMODE         0x13
+#define ABORTMODE       0x17
+#define UNDEFMODE       0x1b
+#define MODEMASK        0x1f
+#define NOINT           0xc0
+
+/**
+ * This function will initialize thread stack
+ *
+ * @param tentry the entry of thread
+ * @param parameter the parameter of entry
+ * @param stack_addr the beginning stack address
+ * @param texit the function will be called when thread exit
+ *
+ * @return stack address
+ */
+rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter,
+                             rt_uint8_t *stack_addr, void *texit)
+{
+    rt_uint32_t *stk;
+
+    //stk      = (rt_uint32_t*)stack_addr;
+    stack_addr += sizeof(rt_uint32_t);
+    stack_addr  = (rt_uint8_t *)RT_ALIGN_DOWN((rt_uint32_t)stack_addr, 8);
+    stk  = (rt_uint32_t *)stack_addr;
+
+    *(--stk) = (rt_uint32_t)tentry;         /* entry point */
+    *(--stk) = (rt_uint32_t)texit;          /* lr */
+    *(--stk) = 0xdeadbeef;                  /* r12 */
+    *(--stk) = 0xdeadbeef;                  /* r11 */
+    *(--stk) = 0xdeadbeef;                  /* r10 */
+    *(--stk) = 0xdeadbeef;                  /* r9 */
+    *(--stk) = 0xdeadbeef;                  /* r8 */
+    *(--stk) = 0xdeadbeef;                  /* r7 */
+    *(--stk) = 0xdeadbeef;                  /* r6 */
+    *(--stk) = 0xdeadbeef;                  /* r5 */
+    *(--stk) = 0xdeadbeef;                  /* r4 */
+    *(--stk) = 0xdeadbeef;                  /* r3 */
+    *(--stk) = 0xdeadbeef;                  /* r2 */
+    *(--stk) = 0xdeadbeef;                  /* r1 */
+    *(--stk) = (rt_uint32_t)parameter;      /* r0 : argument */
+    /* cpsr */
+    if ((rt_uint32_t)tentry & 0x01)
+        *(--stk) = SVCMODE | 0x20;          /* thumb mode */
+    else
+        *(--stk) = SVCMODE;                 /* arm mode   */
+
+    /* return task's current stack address */
+    return (rt_uint8_t *)stk;
+}

+ 346 - 0
bsp/allwinner_tina/libcpu/start_gcc.S

@@ -0,0 +1,346 @@
+/*
+ * File      : start_gcc.S
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2013-2018, RT-Thread Development Team
+ */
+
+.equ MODE_USR,        0x10
+.equ MODE_FIQ,        0x11
+.equ MODE_IRQ,        0x12
+.equ MODE_SVC,        0x13
+.equ MODE_ABT,        0x17
+.equ MODE_UND,        0x1B
+.equ MODE_SYS,        0x1F
+.equ MODEMASK,        0x1F
+.equ NOINT,           0xC0
+
+.equ I_BIT,           0x80
+.equ F_BIT,           0x40
+
+.equ UND_STACK_SIZE,  0x00000100
+.equ SVC_STACK_SIZE,  0x00000100
+.equ ABT_STACK_SIZE,  0x00000100
+.equ FIQ_STACK_SIZE,  0x00000100
+.equ IRQ_STACK_SIZE,  0x00000100
+.equ SYS_STACK_SIZE,  0x00000100
+
+ /*
+ ***************************************
+ * Interrupt vector table
+ ***************************************
+ */
+.section .vectors
+.code 32
+
+.global system_vectors
+system_vectors:
+    ldr pc, _vector_reset
+    ldr pc, _vector_undef
+    ldr pc, _vector_swi
+    ldr pc, _vector_pabt
+    ldr pc, _vector_dabt
+    ldr pc, _vector_resv
+    ldr pc, _vector_irq
+    ldr pc, _vector_fiq
+
+_vector_reset:
+    .word reset
+_vector_undef:
+    .word vector_undef
+_vector_swi:
+    .word vector_swi
+_vector_pabt:
+    .word vector_pabt
+_vector_dabt:
+    .word vector_dabt
+_vector_resv:
+    .word vector_resv
+_vector_irq:
+    .word vector_irq
+_vector_fiq:
+    .word vector_fiq
+
+.balignl    16,0xdeadbeef
+
+
+ /*
+ ***************************************
+ *  Stack and Heap Definitions 
+ ***************************************
+ */
+    .section .data
+    .space UND_STACK_SIZE
+    .align 3
+    .global und_stack_start
+und_stack_start:
+
+    .space ABT_STACK_SIZE
+    .align 3
+    .global abt_stack_start
+abt_stack_start:
+
+    .space FIQ_STACK_SIZE
+    .align 3
+    .global fiq_stack_start
+fiq_stack_start:
+
+    .space IRQ_STACK_SIZE
+    .align 3
+    .global irq_stack_start
+irq_stack_start:
+
+    .skip SYS_STACK_SIZE
+    .align 3
+    .global sys_stack_start
+sys_stack_start:
+
+    .space SVC_STACK_SIZE
+    .align 3
+    .global svc_stack_start
+svc_stack_start:
+
+/*
+ ***************************************
+ * Startup Code 
+ ***************************************
+ */
+    .section .text
+    .global reset
+reset:
+    /* Enter svc mode and mask interrupts */
+    mrs r0, cpsr
+    bic r0, r0, #MODEMASK
+    orr r0, r0, #MODE_SVC|NOINT
+    msr cpsr_cxsf, r0
+
+    /* init cpu  */
+    bl  cpu_init_crit
+    
+    /* todo:copyself to link address */
+    
+    /* Copy vector to the correct address */
+    ldr r0, =system_vectors
+    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}
+
+    /* turn off the watchdog */
+    ldr r0, =0x01C20CB8
+    mov     r1, #0x0
+    str     r1, [r0]
+
+    /* mask all IRQs source */
+    ldr r1, =0xffffffff
+    ldr r0, =0x01C20430
+    str r1, [r0], #0x04
+    str r1, [r0]
+    
+    /* Call low level init function */
+    ldr     sp, =svc_stack_start
+    ldr     r0, =rt_low_level_init
+    blx     r0
+    
+    /* init stack */
+    bl stack_setup
+    
+    /* clear bss */
+    mov     r0, #0
+    ldr     r1, =__bss_start
+    ldr     r2, =__bss_end
+
+bss_clear_loop:
+    cmp     r1, r2
+    strlo   r0, [r1], #4
+    blo     bss_clear_loop
+       
+    /* call c++ constructors of global objects */
+    /*
+    ldr     r0, =__ctors_start__
+    ldr     r1, =__ctors_end__
+
+ctor_loop:
+    cmp     r0, r1
+    beq     ctor_end
+    ldr     r2, [r0], #4
+    stmfd   sp!, {r0-r1}
+    mov     lr, pc
+    bx      r2
+    ldmfd   sp!, {r0-r1}
+    b       ctor_loop
+ctor_end:
+    */
+    /* start RT-Thread Kernel */
+    ldr     pc, _rtthread_startup
+_rtthread_startup:
+    .word  rtthread_startup
+
+
+
+cpu_init_crit:
+    /* invalidate I/D caches */
+    mov r0, #0
+    mcr p15, 0, r0, c7, c7, 0
+    mcr p15, 0, r0, c8, c7, 0
+
+    /* disable MMU stuff and caches */
+    mrc p15, 0, r0, c1, c0, 0
+    bic r0, r0, #0x00002300
+    bic r0, r0, #0x00000087
+    orr r0, r0, #0x00000002
+    orr r0, r0, #0x00001000
+    mcr p15, 0, r0, c1, c0, 0
+
+    bx lr
+ 
+stack_setup:
+    /* Setup Stack for each mode */
+    mrs     r0, cpsr
+    bic     r0, r0, #MODEMASK
+
+    orr     r1, r0, #MODE_UND|NOINT
+    msr     cpsr_cxsf, r1
+    ldr     sp, =und_stack_start
+
+    orr     r1, r0, #MODE_ABT|NOINT
+    msr     cpsr_cxsf, r1
+    ldr     sp, =abt_stack_start
+
+    orr     r1, r0, #MODE_IRQ|NOINT
+    msr     cpsr_cxsf, r1
+    ldr     sp, =irq_stack_start
+
+    orr     r1, r0, #MODE_FIQ|NOINT
+    msr     cpsr_cxsf, r1
+    ldr     sp, =fiq_stack_start
+
+    orr     r1, r0, #MODE_SYS|NOINT
+    msr     cpsr_cxsf,r1
+    ldr     sp, =sys_stack_start
+
+    orr     r1, r0, #MODE_SVC|NOINT
+    msr     cpsr_cxsf, r1
+    ldr     sp, =svc_stack_start
+
+    bx      lr
+ 
+/*
+ ***************************************
+ * exception handlers 
+ ***************************************
+ */
+    .global rt_hw_trap_udef
+    .global rt_hw_trap_swi
+    .global rt_hw_trap_pabt
+    .global rt_hw_trap_dabt
+    .global rt_hw_trap_resv
+    .global rt_hw_trap_irq
+    .global rt_hw_trap_fiq
+    
+    .global rt_interrupt_enter
+    .global rt_interrupt_leave
+    .global rt_thread_switch_interrupt_flag
+    .global rt_interrupt_from_thread
+    .global rt_interrupt_to_thread
+
+    /* Interrupt */
+    .align  5
+vector_fiq:
+    stmfd   sp!,{r0-r7,lr}
+    bl      rt_hw_trap_fiq
+    ldmfd   sp!,{r0-r7,lr}
+    subs    pc, lr, #4
+
+    .align  5
+vector_irq:
+    stmfd   sp!, {r0-r12,lr}
+
+    bl      rt_interrupt_enter
+    bl      rt_hw_trap_irq
+    bl      rt_interrupt_leave
+
+    ldr     r0, =rt_thread_switch_interrupt_flag
+    ldr     r1, [r0]
+    cmp     r1, #1
+    beq     rt_hw_context_switch_interrupt_do
+
+    ldmfd   sp!, {r0-r12,lr}
+    subs    pc,  lr, #4
+
+rt_hw_context_switch_interrupt_do:
+    mov     r1,  #0         
+    str     r1,  [r0]
+
+    mov     r1, sp          
+    add     sp, sp, #4*4
+    ldmfd   sp!, {r4-r12,lr}
+    mrs     r0,  spsr       
+    sub     r2,  lr, #4     
+
+    msr     cpsr_c, #I_BIT|F_BIT|MODE_SVC
+
+    stmfd   sp!, {r2}       
+    stmfd   sp!, {r4-r12,lr}
+    ldmfd   r1,  {r1-r4}    
+    stmfd   sp!, {r1-r4}    
+    stmfd   sp!, {r0}       
+
+    ldr     r4,  =rt_interrupt_from_thread
+    ldr     r5,  [r4]
+    str     sp,  [r5]       
+
+    ldr     r6,  =rt_interrupt_to_thread
+    ldr     r6,  [r6]
+    ldr     sp,  [r6]       
+
+    ldmfd   sp!, {r4}       
+    msr     spsr_cxsf, r4
+
+    ldmfd   sp!, {r0-r12,lr,pc}^ 
+
+    /* Exception */
+.macro push_svc_reg
+    sub     sp, sp, #17 * 4
+    stmia   sp, {r0 - r12} 
+    mov     r0, sp
+    mrs     r6, spsr       
+    str     lr, [r0, #15*4]
+    str     r6, [r0, #16*4]
+    str     sp, [r0, #13*4]
+    str     lr, [r0, #14*4]
+.endm
+
+    .align  5
+vector_swi:
+    push_svc_reg
+    bl      rt_hw_trap_swi
+    b       .
+
+    .align  5
+vector_undef:
+    push_svc_reg
+    bl      rt_hw_trap_udef
+    b       .
+
+    .align  5
+vector_pabt:
+    push_svc_reg
+    bl      rt_hw_trap_pabt
+    b       .
+
+    .align  5
+vector_dabt:
+    push_svc_reg
+    bl      rt_hw_trap_dabt
+    b       .
+
+    .align  5
+vector_resv:
+    push_svc_reg
+    bl      rt_hw_trap_resv
+    b       .
+

+ 223 - 0
bsp/allwinner_tina/libcpu/trap.c

@@ -0,0 +1,223 @@
+/*
+ * File      : trap.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2017, RT-Thread Development Team
+ *
+ *  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.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-02-08     RT-Thread    the first version
+ */
+
+#include <rtthread.h>
+#include <rthw.h>
+
+#define INT_IRQ     0x00
+#define INT_FIQ     0x01
+
+extern struct rt_thread *rt_current_thread;
+#ifdef RT_USING_FINSH
+extern long list_thread(void);
+#endif
+
+struct rt_hw_register
+{
+    rt_uint32_t r0;
+    rt_uint32_t r1;
+    rt_uint32_t r2;
+    rt_uint32_t r3;
+    rt_uint32_t r4;
+    rt_uint32_t r5;
+    rt_uint32_t r6;
+    rt_uint32_t r7;
+    rt_uint32_t r8;
+    rt_uint32_t r9;
+    rt_uint32_t r10;
+    rt_uint32_t fp;
+    rt_uint32_t ip;
+    rt_uint32_t sp;
+    rt_uint32_t lr;
+    rt_uint32_t pc;
+    rt_uint32_t cpsr;
+    rt_uint32_t ORIG_r0;
+};
+static rt_err_t (*rt_exception_hook)(void *context) = RT_NULL;
+void rt_hw_exception_install(rt_err_t (*exception_handle)(void *context))
+{
+    rt_exception_hook = exception_handle;
+}
+/**
+ * this function will show registers of CPU
+ *
+ * @param regs the registers point
+ */
+
+void rt_hw_show_register(struct rt_hw_register *regs)
+{
+    rt_kprintf("Execption:\n");
+    rt_kprintf("r00:0x%08x r01:0x%08x r02:0x%08x r03:0x%08x\n",
+               regs->r0, regs->r1, regs->r2, regs->r3);
+    rt_kprintf("r04:0x%08x r05:0x%08x r06:0x%08x r07:0x%08x\n",
+               regs->r4, regs->r5, regs->r6, regs->r7);
+    rt_kprintf("r08:0x%08x r09:0x%08x r10:0x%08x\n",
+               regs->r8, regs->r9, regs->r10);
+    rt_kprintf("fp :0x%08x ip :0x%08x\n",
+               regs->fp, regs->ip);
+    rt_kprintf("sp :0x%08x lr :0x%08x pc :0x%08x\n",
+               regs->sp, regs->lr, regs->pc);
+    rt_kprintf("cpsr:0x%08x\n", regs->cpsr);
+}
+
+/**
+ * When ARM7TDMI comes across an instruction which it cannot handle,
+ * it takes the undefined instruction trap.
+ *
+ * @param regs system registers
+ *
+ * @note never invoke this function in application
+ */
+void rt_hw_trap_udef(struct rt_hw_register *regs)
+{
+    if (rt_exception_hook != RT_NULL)
+    {
+        rt_err_t result;
+
+        result = rt_exception_hook(regs);
+        if (result == RT_EOK) return;
+    }
+    rt_hw_show_register(regs);
+
+    rt_kprintf("undefined instruction\n");
+    rt_kprintf("thread - %s stack:\n", rt_current_thread->name);
+
+#ifdef RT_USING_FINSH
+    list_thread();
+#endif
+    rt_hw_cpu_shutdown();
+}
+
+/**
+ * The software interrupt instruction (SWI) is used for entering
+ * Supervisor mode, usually to request a particular supervisor
+ * function.
+ *
+ * @param regs system registers
+ *
+ * @note never invoke this function in application
+ */
+void rt_hw_trap_swi(struct rt_hw_register *regs)
+{
+    if (rt_exception_hook != RT_NULL)
+    {
+        rt_err_t result;
+
+        result = rt_exception_hook(regs);
+        if (result == RT_EOK) return;
+    }
+    rt_hw_show_register(regs);
+
+    rt_kprintf("software interrupt\n");
+    rt_hw_cpu_shutdown();
+}
+
+/**
+ * An abort indicates that the current memory access cannot be completed,
+ * which occurs during an instruction prefetch.
+ *
+ * @param regs system registers
+ *
+ * @note never invoke this function in application
+ */
+void rt_hw_trap_pabt(struct rt_hw_register *regs)
+{
+    if (rt_exception_hook != RT_NULL)
+    {
+        rt_err_t result;
+
+        result = rt_exception_hook(regs);
+        if (result == RT_EOK) return;
+    }
+    rt_hw_show_register(regs);
+
+    rt_kprintf("prefetch abort\n");
+    rt_kprintf("thread - %s stack:\n", RT_NAME_MAX, rt_current_thread->name);
+
+#ifdef RT_USING_FINSH
+    list_thread();
+#endif
+    rt_hw_cpu_shutdown();
+}
+
+/**
+ * An abort indicates that the current memory access cannot be completed,
+ * which occurs during a data access.
+ *
+ * @param regs system registers
+ *
+ * @note never invoke this function in application
+ */
+void rt_hw_trap_dabt(struct rt_hw_register *regs)
+{
+    if (rt_exception_hook != RT_NULL)
+    {
+        rt_err_t result;
+
+        result = rt_exception_hook(regs);
+        if (result == RT_EOK) return;
+    }
+    rt_hw_show_register(regs);
+
+    rt_kprintf("data abort\n");
+    rt_kprintf("thread - %s stack:\n", RT_NAME_MAX, rt_current_thread->name);
+
+#ifdef RT_USING_FINSH
+    list_thread();
+#endif
+    rt_hw_cpu_shutdown();
+}
+
+/**
+ * Normally, system will never reach here
+ *
+ * @param regs system registers
+ *
+ * @note never invoke this function in application
+ */
+void rt_hw_trap_resv(struct rt_hw_register *regs)
+{
+    if (rt_exception_hook != RT_NULL)
+    {
+        rt_err_t result;
+
+        result = rt_exception_hook(regs);
+        if (result == RT_EOK) return;
+    }
+    rt_kprintf("not used\n");
+    rt_hw_show_register(regs);
+    rt_hw_cpu_shutdown();
+}
+
+extern void rt_interrupt_dispatch(void);
+
+void rt_hw_trap_irq(void)
+{
+    rt_interrupt_dispatch();
+}
+
+void rt_hw_trap_fiq(void)
+{
+    rt_interrupt_dispatch();
+}

+ 148 - 0
bsp/allwinner_tina/link.lds

@@ -0,0 +1,148 @@
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
+OUTPUT_ARCH(arm)
+
+SECTIONS
+{
+    . = 0x80000000;
+    
+    . = ALIGN(4);
+    __text_start = .;
+    .text :
+    {
+        *(.vectors)
+        *(.text)
+        *(.text.*)
+	KEEP(*(.fini))
+
+        /* section information for finsh shell */
+        . = ALIGN(4);
+        __fsymtab_start = .;
+        KEEP(*(FSymTab))
+        __fsymtab_end = .;
+        . = ALIGN(4);
+        __vsymtab_start = .;
+        KEEP(*(VSymTab))
+        __vsymtab_end = .;
+        . = ALIGN(4);
+
+        /* section information for modules */
+        . = ALIGN(4);
+        __rtmsymtab_start = .;
+        KEEP(*(RTMSymTab))
+        __rtmsymtab_end = .;
+
+        /* section information for initialization */
+        . = ALIGN(4);
+        __rt_init_start = .;
+        KEEP(*(SORT(.rti_fn*)))
+        __rt_init_end = .;
+    } =0
+    __text_end = .;
+
+    __rodata_start = .;
+    .rodata   : { *(.rodata) *(.rodata.*) *(.eh_frame) }
+    __rodata_end = .;
+
+    . = ALIGN(4);
+    .ctors :
+    {
+        PROVIDE(__ctors_start__ = .);
+	*crtbegin.o(.ctors)
+	*crtbegin?.o(.ctors)
+	*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+	*(SORT(.ctors.*))
+	*(.ctors)
+        PROVIDE(__ctors_end__ = .);       
+    }
+
+    .ARM.extab : 
+    {
+	*(.ARM.extab* .gnu.linkonce.armextab.*)
+    } 
+    /* The .ARM.exidx section is used for C++ exception handling. */
+    /* .ARM.exidx is sorted, so has to go in its own output section.  */
+    __exidx_start = .;
+    ARM.exidx :
+    {
+        *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+
+        /* This is used by the startup in order to initialize the .data secion */
+        _sidata = .;
+    }
+    __exidx_end = .;
+    
+    .dtors :
+    {
+        PROVIDE(__dtors_start__ = .);
+        *crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+        PROVIDE(__dtors_end__ = .);
+    }
+
+    __data_start = .;
+    . = ALIGN(4);
+    .data :
+    {
+        *(.data)
+        *(.data.*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(4);
+		/* All data end */
+
+        *(.gnu.linkonce.d*)
+    }
+    __data_end = .;
+
+    . = ALIGN(4);
+    __bss_start = .;
+    .bss       :
+    {
+    *(.bss)
+    *(.bss.*)
+    *(COMMON)
+    . = ALIGN(4);
+    }
+    . = ALIGN(4);
+    __bss_end = .;
+
+    /* Stabs debugging sections.  */
+    .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) }
+    _end = .;
+}

+ 235 - 0
bsp/allwinner_tina/rtconfig.h

@@ -0,0 +1,235 @@
+#ifndef RT_CONFIG_H__
+#define RT_CONFIG_H__
+
+/* Automatically generated file; DO NOT EDIT. */
+/* RT-Thread Configuration */
+
+/* RT-Thread Kernel */
+
+#define RT_NAME_MAX 8
+#define RT_ALIGN_SIZE 4
+/* RT_THREAD_PRIORITY_8 is not set */
+#define RT_THREAD_PRIORITY_32
+/* RT_THREAD_PRIORITY_256 is not set */
+#define RT_THREAD_PRIORITY_MAX 32
+#define RT_TICK_PER_SECOND 100
+#define RT_DEBUG
+#define RT_USING_OVERFLOW_CHECK
+#define RT_DEBUG_INIT 0
+#define RT_DEBUG_THREAD 0
+#define RT_USING_HOOK
+#define IDLE_THREAD_STACK_SIZE 256
+/* RT_USING_TIMER_SOFT is not set */
+
+/* Inter-Thread communication */
+
+#define RT_USING_SEMAPHORE
+#define RT_USING_MUTEX
+#define RT_USING_EVENT
+#define RT_USING_MAILBOX
+#define RT_USING_MESSAGEQUEUE
+/* RT_USING_SIGNALS is not set */
+
+/* Memory Management */
+
+#define RT_USING_MEMPOOL
+/* RT_USING_MEMHEAP is not set */
+/* RT_USING_NOHEAP is not set */
+#define RT_USING_SMALL_MEM
+/* RT_USING_SLAB is not set */
+/* RT_USING_MEMTRACE is not set */
+#define RT_USING_HEAP
+
+/* Kernel Device Object */
+
+#define RT_USING_DEVICE
+/* RT_USING_INTERRUPT_INFO is not set */
+#define RT_USING_CONSOLE
+#define RT_CONSOLEBUF_SIZE 128
+#define RT_CONSOLE_DEVICE_NAME "uart0"
+/* RT_USING_MODULE is not set */
+#define ARCH_ARM
+#define ARCH_ARM_ARM9
+
+/* RT-Thread Components */
+
+#define RT_USING_COMPONENTS_INIT
+#define RT_USING_USER_MAIN
+
+/* C++ features */
+
+/* RT_USING_CPLUSPLUS is not set */
+
+/* Command shell */
+
+#define RT_USING_FINSH
+#define FINSH_THREAD_NAME "tshell"
+#define FINSH_USING_HISTORY
+#define FINSH_HISTORY_LINES 5
+#define FINSH_USING_SYMTAB
+#define FINSH_USING_DESCRIPTION
+#define FINSH_THREAD_PRIORITY 20
+#define FINSH_THREAD_STACK_SIZE 4096
+#define FINSH_CMD_SIZE 80
+/* FINSH_USING_AUTH is not set */
+#define FINSH_USING_MSH
+#define FINSH_USING_MSH_DEFAULT
+/* FINSH_USING_MSH_ONLY is not set */
+
+/* Device virtual file system */
+
+#define RT_USING_DFS
+#define DFS_USING_WORKDIR
+#define DFS_FILESYSTEMS_MAX 2
+#define DFS_FILESYSTEM_TYPES_MAX 2
+#define DFS_FD_MAX 4
+#define RT_USING_DFS_ELMFAT
+
+/* elm-chan's FatFs, Generic FAT Filesystem Module */
+
+#define RT_DFS_ELM_CODE_PAGE 437
+#define RT_DFS_ELM_WORD_ACCESS
+#define RT_DFS_ELM_USE_LFN_0
+/* RT_DFS_ELM_USE_LFN_1 is not set */
+/* RT_DFS_ELM_USE_LFN_2 is not set */
+/* RT_DFS_ELM_USE_LFN_3 is not set */
+#define RT_DFS_ELM_USE_LFN 0
+#define RT_DFS_ELM_MAX_LFN 255
+#define RT_DFS_ELM_DRIVES 2
+#define RT_DFS_ELM_MAX_SECTOR_SIZE 512
+/* RT_DFS_ELM_USE_ERASE is not set */
+#define RT_DFS_ELM_REENTRANT
+#define RT_USING_DFS_DEVFS
+/* RT_USING_DFS_NET is not set */
+/* RT_USING_DFS_ROMFS is not set */
+/* RT_USING_DFS_RAMFS is not set */
+/* RT_USING_DFS_UFFS is not set */
+/* RT_USING_DFS_JFFS2 is not set */
+/* RT_USING_DFS_NFS is not set */
+
+/* Device Drivers */
+
+#define RT_USING_DEVICE_IPC
+#define RT_USING_SERIAL
+/* RT_USING_CAN is not set */
+/* RT_USING_HWTIMER is not set */
+/* RT_USING_CPUTIME is not set */
+/* RT_USING_I2C is not set */
+#define RT_USING_PIN
+/* RT_USING_MTD_NOR is not set */
+/* RT_USING_MTD_NAND is not set */
+/* RT_USING_RTC is not set */
+/* RT_USING_SDIO is not set */
+/* RT_USING_SPI is not set */
+/* RT_USING_WDT is not set */
+/* RT_USING_WIFI is not set */
+
+/* Using USB */
+
+/* RT_USING_USB_HOST is not set */
+/* RT_USING_USB_DEVICE is not set */
+
+/* POSIX layer and C standard library */
+
+#define RT_USING_LIBC
+/* RT_USING_PTHREADS is not set */
+#define RT_USING_POSIX
+/* RT_USING_POSIX_MMAP is not set */
+/* RT_USING_POSIX_TERMIOS is not set */
+/* RT_USING_POSIX_AIO is not set */
+
+/* Network stack */
+
+/* light weight TCP/IP stack */
+
+/* RT_USING_LWIP is not set */
+
+/* Modbus master and slave stack */
+
+/* RT_USING_MODBUS is not set */
+
+/* RT-Thread UI Engine */
+
+/* RT_USING_GUIENGINE is not set */
+
+/* VBUS(Virtual Software BUS) */
+
+/* RT_USING_VBUS is not set */
+
+/* Utilities */
+
+/* RT_USING_LOGTRACE is not set */
+/* RT_USING_RYM is not set */
+
+/* RT-Thread online packages */
+
+/* system packages */
+
+/* PKG_USING_LWEXT4 is not set */
+/* PKG_USING_PARTITION is not set */
+/* PKG_USING_PERSIMMON is not set */
+/* PKG_USING_SQLITE is not set */
+/* PKG_USING_RTI is not set */
+
+/* IoT - internet of things */
+
+/* PKG_USING_PAHOMQTT is not set */
+/* PKG_USING_WEBCLIENT is not set */
+/* PKG_USING_MONGOOSE is not set */
+/* PKG_USING_WEBTERMINAL is not set */
+/* PKG_USING_CJSON is not set */
+/* PKG_USING_LJSON is not set */
+/* PKG_USING_EZXML is not set */
+/* PKG_USING_NANOPB is not set */
+/* PKG_USING_GAGENT_CLOUD is not set */
+
+/* Wi-Fi */
+
+/* Marvell WiFi */
+
+/* PKG_USING_WLANMARVELL is not set */
+
+/* Wiced WiFi */
+
+/* PKG_USING_WLAN_WICED is not set */
+/* PKG_USING_COAP is not set */
+/* PKG_USING_NOPOLL is not set */
+
+/* security packages */
+
+/* PKG_USING_MBEDTLS is not set */
+/* PKG_USING_libsodium is not set */
+/* PKG_USING_TINYCRYPT is not set */
+
+/* language packages */
+
+/* PKG_USING_JERRYSCRIPT is not set */
+/* PKG_USING_MICROPYTHON is not set */
+
+/* multimedia packages */
+
+/* PKG_USING_OPENMV is not set */
+
+/* tools packages */
+
+/* PKG_USING_CMBACKTRACE is not set */
+/* PKG_USING_EASYLOGGER is not set */
+/* PKG_USING_SYSTEMVIEW is not set */
+/* PKG_USING_IPERF is not set */
+
+/* miscellaneous packages */
+
+/* PKG_USING_FASTLZ is not set */
+/* PKG_USING_MINILZO is not set */
+
+/* example package: hello */
+
+/* PKG_USING_HELLO is not set */
+/* PKG_USING_MULTIBUTTON is not set */
+#define TINA_USING_UART0
+/* TINA_USING_UART1 is not set */
+#define TINA_USING_UART2
+#define RT_USING_CPU_FFS
+#define RT_MAIN_THREAD_STACK_SIZE 2048
+
+#endif

+ 58 - 0
bsp/allwinner_tina/rtconfig.py

@@ -0,0 +1,58 @@
+import os
+
+# toolchains options
+ARCH        ='arm'
+CPU         ='R6'
+CROSS_TOOL  ='gcc'
+
+if os.getenv('RTT_ROOT'):
+    RTT_ROOT = os.getenv('RTT_ROOT')
+else:
+    RTT_ROOT = '../..'
+
+if os.getenv('RTT_CC'):
+    CROSS_TOOL = os.getenv('RTT_CC')
+
+if  CROSS_TOOL == 'gcc':
+    PLATFORM    = 'gcc'
+    EXEC_PATH   = r'E:\work\env\tools\gnu_gcc\arm_gcc\mingw\bin'
+else:
+    print 'Please make sure your toolchains is GNU GCC!'
+    exit(0)
+
+if os.getenv('RTT_EXEC_PATH'):
+    EXEC_PATH = os.getenv('RTT_EXEC_PATH')
+
+BUILD = 'release'
+# BUILD = 'debug'
+
+if PLATFORM == 'gcc':
+    # toolchains
+    PREFIX  = 'arm-none-eabi-'
+    CC      = PREFIX + 'gcc'
+    CXX     = PREFIX + 'g++'
+    AS      = PREFIX + 'gcc'
+    AR      = PREFIX + 'ar'
+    LINK    = PREFIX + 'g++'
+    TARGET_EXT = 'elf'
+    SIZE    = PREFIX + 'size'
+    OBJDUMP = PREFIX + 'objdump'
+    OBJCPY  = PREFIX + 'objcopy'
+
+    DEVICE  = ' -mcpu=arm926ej-s -ffunction-sections -fdata-sections'
+    CFLAGS  = DEVICE + ' -Wall'
+    AFLAGS  = ' -c' + DEVICE + ' -x assembler-with-cpp'
+    LFLAGS  = DEVICE + ' -nostartfiles -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,system_vectors -T link.lds'
+    CPATH   = ''
+    LPATH   = ''
+
+    if BUILD == 'debug':
+        CFLAGS += ' -O0 -gdwarf-2'
+        AFLAGS += ' -gdwarf-2'
+    else:
+        CFLAGS += ' -O2'
+
+    CXXFLAGS = CFLAGS
+
+DUMP_ACTION = OBJDUMP + ' -D -S $TARGET > rtt.asm\n'
+POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.bin\n' + SIZE + ' $TARGET \n'