[Bsp][New BSP]New bsp for allwinner tina
This commit is contained in:
parent
174787ce69
commit
9bf2a755e0
|
@ -27,6 +27,7 @@ env:
|
||||||
# - RTT_BSP='apollo2' RTT_TOOL_CHAIN='sourcery-arm'
|
# - RTT_BSP='apollo2' RTT_TOOL_CHAIN='sourcery-arm'
|
||||||
- RTT_BSP='asm9260t' RTT_TOOL_CHAIN='sourcery-arm'
|
- RTT_BSP='asm9260t' RTT_TOOL_CHAIN='sourcery-arm'
|
||||||
- RTT_BSP='at91sam9260' 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='avr32uc3b0' RTT_TOOL_CHAIN='atmel-avr32'
|
||||||
# - RTT_BSP='bf533' # no scons
|
# - RTT_BSP='bf533' # no scons
|
||||||
- RTT_BSP='efm32' RTT_TOOL_CHAIN='sourcery-arm'
|
- RTT_BSP='efm32' RTT_TOOL_CHAIN='sourcery-arm'
|
||||||
|
|
|
@ -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
|
|
@ -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"
|
|
@ -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
|
|
@ -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')
|
|
@ -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)
|
|
@ -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')
|
|
@ -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;
|
||||||
|
}
|
|
@ -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
|
|
@ -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')
|
|
@ -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
|
||||||
|
}
|
|
@ -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
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
|
@ -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);
|
|
@ -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__ */
|
|
@ -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
|
|
@ -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__ */
|
|
@ -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')
|
|
@ -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
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
/*@}*/
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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__ */
|
|
@ -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();
|
||||||
|
}
|
|
@ -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
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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 .
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
|
@ -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 = .;
|
||||||
|
}
|
|
@ -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
|
|
@ -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'
|
Loading…
Reference in New Issue