Add zynq7000 bsp
1034
bsp/zynq/zynq7000/.config
Normal file
37
bsp/zynq/zynq7000/Kconfig
Normal file
@ -0,0 +1,37 @@
|
||||
mainmenu "RT-Thread Project Configuration"
|
||||
|
||||
config BSP_DIR
|
||||
string
|
||||
option env="BSP_ROOT"
|
||||
default "."
|
||||
|
||||
config RTT_DIR
|
||||
string
|
||||
option env="RTT_ROOT"
|
||||
default "../../.."
|
||||
|
||||
config PKGS_DIR
|
||||
string
|
||||
option env="PKGS_ROOT"
|
||||
default "packages"
|
||||
|
||||
source "$RTT_DIR/Kconfig"
|
||||
source "drivers/Kconfig"
|
||||
|
||||
config SOC_ZYNQ_7000
|
||||
bool
|
||||
select ARCH_ARM_CORTEX_A9
|
||||
select RT_USING_COMPONENTS_INIT
|
||||
select RT_USING_USER_MAIN
|
||||
select RT_USING_GIC_V2
|
||||
default y
|
||||
|
||||
config RT_USING_CACHE
|
||||
bool
|
||||
default y
|
||||
|
||||
config RT_USING_FPU
|
||||
bool
|
||||
default y
|
||||
|
||||
source "$PKGS_DIR/Kconfig"
|
125
bsp/zynq/zynq7000/README.md
Normal file
@ -0,0 +1,125 @@
|
||||
# 正点原子启明星开发板 BSP 说明
|
||||
|
||||
## 简介
|
||||
|
||||
本文档是为 正点原子启明星开发板提供的 BSP (板级支持包) 说明。
|
||||
|
||||
主要内容如下:
|
||||
|
||||
- 开发板资源介绍
|
||||
- 开发流程说明
|
||||
|
||||
## 开发板介绍
|
||||
|
||||
正点原子开发的基于 zynq7000 生成的开发板, 注: 理论上也可以适用于其它 zynq7000的开发板.
|
||||
|
||||
![board](figures/board.jpg)
|
||||
|
||||
开发板更多详细信息请参考[官方文档](http://www.openedv.com/docs/boards/fpga/zdyz_qimxing(V2).html)。
|
||||
|
||||
## 外设支持
|
||||
|
||||
本 BSP 目前对外设的支持情况如下:
|
||||
|
||||
| **核心** | **支持情况** | **备注** |
|
||||
| :----------------- | :----------: | :------------------------------------- |
|
||||
| cortex-a9 | 支持 | 运行系统的为cortex-a9核的CPU0 |
|
||||
| **板载外设** | **支持情况** | **备注** |
|
||||
| 无 | | |
|
||||
| **片上外设** | **支持情况** | **备注** |
|
||||
| GPIO | 支持 | |
|
||||
| UART | 支持 | UART0, UART1 |
|
||||
| SPI FLASH | 支持 | |
|
||||
| EMMC / SDIO | 支持 | |
|
||||
| CAN | 即将支持 | |
|
||||
|
||||
## 使用说明
|
||||
|
||||
本 bsp 驱动基于之前的 zynq7000 bsp 的基础上,除了定时器仍然沿用之前的寄存器写法外,其余驱动均基于 vivado sdk 2017.4 生成的驱动库开发。具体开发使用流程如下:
|
||||
|
||||
### 1. 创建 vivado 工程 & pl 部分开发
|
||||
|
||||
使用 vivado 创建工程, 完成 pl 部分开发, 此部分与 rtt 软件开发无关,
|
||||
故省略具体说明. 注意 zynq ps 部分必须启用 `MIO`, `UART0` 和 `Quad SPI FLASH`.
|
||||
|
||||
### 2. 启动 sdk 生成 bsp 和 fsbl
|
||||
|
||||
完成第一步后, 导出硬件到 sdk, 然后启动 sdk, 创建 fsbl 工程
|
||||
|
||||
![step2](figures/step_2.png)
|
||||
![step3](figures/step_3.png)
|
||||
|
||||
由于后续即将添加的复杂驱动依赖于usleep.c 的接口函数, 故需要对 sdk
|
||||
中的 `bsp\ps7_cortexa9_0\libsrc\standalone_v6_5\src\usleep.c` 做如下修改:
|
||||
|
||||
```DIFF
|
||||
@@ -63,6 +63,15 @@
|
||||
/* Global Timer is always clocked at half of the CPU frequency */
|
||||
#define COUNTS_PER_USECOND (XPAR_CPU_CORTEXA9_CORE_CLOCK_FREQ_HZ / (2U*1000000U))
|
||||
|
||||
+typedef void (*usleep_hook_t) (unsigned long useconds);
|
||||
+
|
||||
+static usleep_hook_t usleep_hook;
|
||||
+
|
||||
+void zynq_set_usleep_hook(usleep_hook_t hook)
|
||||
+{
|
||||
+ usleep_hook = hook;
|
||||
+}
|
||||
+
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
@@ -78,6 +87,12 @@
|
||||
****************************************************************************/
|
||||
int usleep(unsigned long useconds)
|
||||
{
|
||||
+ if (usleep_hook)
|
||||
+ {
|
||||
+ usleep_hook(useconds);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
XTime tEnd, tCur;
|
||||
|
||||
XTime_GetTime(&tCur);
|
||||
|
||||
```
|
||||
|
||||
修改完成后保存文件,等待sdk 自动完成编译.
|
||||
|
||||
### 3. 拷贝 sdk 下的 bsp, 完成 app 编译
|
||||
|
||||
拷贝 sdk bsp 文件夹下的 `include` 和 `lib` 文件夹到 [bsp](bsp) 文件夹下
|
||||
|
||||
![step4](figures/step_4.png)
|
||||
|
||||
然后 scons 编译app, 得到 `rtthread-zynq7000.elf`
|
||||
|
||||
### 4. 调试运行
|
||||
|
||||
#### 方式1: sdk 调试运行
|
||||
|
||||
1. 点击 SDK `Run` -> `Debug Configurations...`
|
||||
![step5](figures/step_5.png)
|
||||
|
||||
2. 右键 new 创建新的 debug
|
||||
![stp6](figures/step_6.png)
|
||||
|
||||
3. 配置 debug, 选择 app 所在路径
|
||||
![step7](figures/step_7.png)
|
||||
![step8](figures/step_8.png)
|
||||
|
||||
4. 随后点击 debug 就可以运行了.效果如下图所示:
|
||||
![step9](figures/step_9.png)
|
||||
![step9_1](figures/step_9_1.png)
|
||||
|
||||
#### 方式2: 生成 BOOT.BIN 拷贝到 sd 卡运行
|
||||
|
||||
参见 vivado bootgen 使用方法,将 app 换成
|
||||
scons 编译生成的 `rtthread-zynq7000.elf` 即可
|
||||
|
||||
## 联系人信息
|
||||
|
||||
维护人:
|
||||
|
||||
- [a1012112796](https://github.com/a1012112796)
|
15
bsp/zynq/zynq7000/SConscript
Normal file
@ -0,0 +1,15 @@
|
||||
# for module compiling
|
||||
import os
|
||||
Import('RTT_ROOT')
|
||||
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')
|
40
bsp/zynq/zynq7000/SConstruct
Normal file
@ -0,0 +1,40 @@
|
||||
import os
|
||||
import sys
|
||||
import rtconfig
|
||||
|
||||
if os.getenv('RTT_ROOT'):
|
||||
RTT_ROOT = os.getenv('RTT_ROOT')
|
||||
else:
|
||||
RTT_ROOT = os.path.normpath(os.getcwd() + '/../../..')
|
||||
|
||||
sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')]
|
||||
|
||||
try:
|
||||
from building import *
|
||||
except:
|
||||
print('Cannot found RT-Thread root directory, please check RTT_TOOLS')
|
||||
print(RTT_ROOT)
|
||||
exit(-1)
|
||||
|
||||
TARGET = 'rtthread-zynq7000.' + rtconfig.TARGET_EXT
|
||||
|
||||
DefaultEnvironment(tools=[])
|
||||
env = Environment(tools = ['mingw'],
|
||||
AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS,
|
||||
CC = rtconfig.CC, CCFLAGS = rtconfig.CFLAGS,
|
||||
CXX = rtconfig.CXX, 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)
|
||||
|
||||
# if the linker script changed, relink the target
|
||||
Depends(TARGET, rtconfig.LINK_SCRIPT)
|
||||
|
||||
# make a building
|
||||
DoBuilding(TARGET, objs)
|
2
bsp/zynq/zynq7000/Xilinx.spec
Normal file
@ -0,0 +1,2 @@
|
||||
*startfile:
|
||||
crti%O%s crtbegin%O%s
|
14
bsp/zynq/zynq7000/applications/SConscript
Normal file
@ -0,0 +1,14 @@
|
||||
Import('RTT_ROOT')
|
||||
Import('rtconfig')
|
||||
from building import *
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
CPPPATH = [cwd + '/..']
|
||||
|
||||
src = Split('''
|
||||
app.c
|
||||
''')
|
||||
|
||||
group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH)
|
||||
|
||||
Return('group')
|
18
bsp/zynq/zynq7000/applications/app.c
Normal file
@ -0,0 +1,18 @@
|
||||
#include "rtthread.h"
|
||||
#include "rtdevice.h"
|
||||
|
||||
#define LED_PIN 0
|
||||
|
||||
int main(void)
|
||||
{
|
||||
rt_pin_mode(LED_PIN, PIN_MODE_OUTPUT);
|
||||
rt_uint8_t out = 0;
|
||||
|
||||
while(1)
|
||||
{
|
||||
rt_thread_mdelay(500);
|
||||
rt_pin_write(LED_PIN, out);
|
||||
out = (out + 1) % 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
1
bsp/zynq/zynq7000/bootgen/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
*.bit
|
1
bsp/zynq/zynq7000/bootgen/build.bat
Normal file
@ -0,0 +1 @@
|
||||
.\bootgen.exe -image output.bif -o BOOT.BIN -w on
|
6
bsp/zynq/zynq7000/bootgen/output.bif
Normal file
@ -0,0 +1,6 @@
|
||||
//arch = zynq; split = false; format = BIN
|
||||
the_ROM_image:
|
||||
{
|
||||
[bootloader]fsbl.elf
|
||||
..\rtthread-zynq7000.elf
|
||||
}
|
2
bsp/zynq/zynq7000/bsp/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/lib
|
||||
/include
|
15
bsp/zynq/zynq7000/bsp/SConscript
Normal file
@ -0,0 +1,15 @@
|
||||
|
||||
from building import *
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
CPPPATH = [cwd + '/include',]
|
||||
LIBS = ['libxil',]
|
||||
LIBPATH = [cwd + '/lib']
|
||||
|
||||
group = DefineGroup('zynq_hal', [],
|
||||
depend = [],
|
||||
CPPPATH = CPPPATH,
|
||||
LIBS = LIBS,
|
||||
LIBPATH = LIBPATH)
|
||||
|
||||
Return('group')
|
43
bsp/zynq/zynq7000/drivers/Kconfig
Normal file
@ -0,0 +1,43 @@
|
||||
menu "Hardware Drivers Config"
|
||||
|
||||
menu "On-chip Peripheral Drivers"
|
||||
config BSP_USING_GPIO
|
||||
bool "Enable zynq MIO"
|
||||
select RT_USING_PIN
|
||||
default y
|
||||
|
||||
menuconfig BSP_USING_UART
|
||||
bool "Enable UART"
|
||||
default y
|
||||
select RT_USING_SERIAL
|
||||
if BSP_USING_UART
|
||||
config BSP_USING_UART0
|
||||
bool "Enable UART0"
|
||||
default y
|
||||
|
||||
config BSP_USING_UART1
|
||||
bool "Enable UART1"
|
||||
default n
|
||||
endif
|
||||
|
||||
config BSP_USING_SPIFLASH
|
||||
bool "Enable spi flash"
|
||||
select RT_USING_FAL
|
||||
default n
|
||||
|
||||
menuconfig BSP_USING_SDIO
|
||||
bool "Enable sdio (emmc)"
|
||||
default n
|
||||
|
||||
if BSP_USING_SDIO
|
||||
config BSP_USING_SDIO0
|
||||
bool "Enable sdio0"
|
||||
default n
|
||||
|
||||
config BSP_USING_SDIO1
|
||||
bool "Enable sdio1"
|
||||
default n
|
||||
endif
|
||||
endmenu
|
||||
|
||||
endmenu
|
22
bsp/zynq/zynq7000/drivers/SConscript
Normal file
@ -0,0 +1,22 @@
|
||||
from building import *
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
src = Glob('*.c')
|
||||
|
||||
if GetDepend('BSP_USING_UART') == False:
|
||||
src_need_remove = ['drv_uart.c'] # need remove file list.
|
||||
SrcRemove(src, src_need_remove)
|
||||
|
||||
if GetDepend('BSP_USING_SPIFLASH') == False:
|
||||
src_need_remove = ['drv_spiflash.c'] # need remove file list.
|
||||
SrcRemove(src, src_need_remove)
|
||||
|
||||
if GetDepend('BSP_USING_SDIO') == False:
|
||||
src_need_remove = ['drv_emmc.c'] # need remove file list.
|
||||
SrcRemove(src, src_need_remove)
|
||||
|
||||
CPPPATH = [cwd]
|
||||
|
||||
group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH)
|
||||
|
||||
Return('group')
|
130
bsp/zynq/zynq7000/drivers/board.c
Normal file
@ -0,0 +1,130 @@
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
#include "xil_assert.h"
|
||||
#include "rtdevice.h"
|
||||
#include "drv_gpio.h"
|
||||
#include <mmu.h>
|
||||
|
||||
extern rt_uint32_t __text_start;
|
||||
|
||||
struct mem_desc platform_mem_desc[] = {
|
||||
/* no access to the memory below .text */
|
||||
/* 521Mb cached DDR memory */
|
||||
{(rt_uint32_t)&__text_start, 0x3F600000-1, (rt_uint32_t)&__text_start, NORMAL_MEM},
|
||||
/* PL region */
|
||||
{0x40000000, 0xBFFFFFFF, 0x40000000, DEVICE_MEM},
|
||||
/* IOP registers */
|
||||
{0xE0000000, 0xE02FFFFF, 0xE0000000, DEVICE_MEM},
|
||||
/* SLCR, PS and CPU private registers, note we map more memory space as the
|
||||
* entry is 1MB in size. */
|
||||
{0xF8000000, 0xFFFFFFFF, 0xF8000000, DEVICE_MEM},
|
||||
};
|
||||
|
||||
const rt_uint32_t platform_mem_desc_size = sizeof(platform_mem_desc)/sizeof(platform_mem_desc[0]);
|
||||
|
||||
void idle_wfi(void)
|
||||
{
|
||||
asm volatile ("wfi");
|
||||
}
|
||||
|
||||
static void rt_xil_assert_callback(const char8 *File, s32 Line)
|
||||
{
|
||||
rt_kprintf("Xil_AssertCallback: %s, %d\n", File, Line);
|
||||
RT_ASSERT(0);
|
||||
}
|
||||
|
||||
typedef void (*usleep_hook_t) (unsigned long useconds);
|
||||
|
||||
// note: should edit usleep.c in bsp to fix it
|
||||
//
|
||||
// static usleep_hook_t usleep_hook;
|
||||
//
|
||||
// void zynq_set_usleep_hook(usleep_hook_t hook)
|
||||
// {
|
||||
// usleep_hook = hook;
|
||||
// }
|
||||
//
|
||||
// int usleep(unsigned long useconds)
|
||||
// {
|
||||
// if (usleep_hook)
|
||||
// {
|
||||
// usleep_hook(useconds);
|
||||
// return 0;
|
||||
// }
|
||||
|
||||
// XTime tEnd, tCur;
|
||||
|
||||
// XTime_GetTime(&tCur);
|
||||
// tEnd = tCur + (((XTime) useconds) * COUNTS_PER_USECOND);
|
||||
// do
|
||||
// {
|
||||
// XTime_GetTime(&tCur);
|
||||
// } while (tCur < tEnd);
|
||||
|
||||
// return 0;
|
||||
// }
|
||||
//
|
||||
|
||||
extern void zynq_set_usleep_hook(usleep_hook_t hook);
|
||||
|
||||
static void hw_usleep_hook(unsigned long useconds)
|
||||
{
|
||||
useconds /= 1000;
|
||||
if (useconds == 0)
|
||||
useconds = 1;
|
||||
|
||||
rt_thread_mdelay(useconds);
|
||||
}
|
||||
|
||||
static int setup_zynq_usleep_hook(void)
|
||||
{
|
||||
zynq_set_usleep_hook(hw_usleep_hook);
|
||||
return 0;
|
||||
}
|
||||
INIT_BOARD_EXPORT(setup_zynq_usleep_hook);
|
||||
|
||||
static void _assert_hook (const char *ex, const char *func, rt_size_t line)
|
||||
{
|
||||
RT_ASSERT(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will initialize beaglebone board
|
||||
*/
|
||||
void rt_hw_board_init(void)
|
||||
{
|
||||
Xil_AssertSetCallback(rt_xil_assert_callback);
|
||||
|
||||
/* initialize hardware interrupt */
|
||||
rt_hw_interrupt_init();
|
||||
/* initialize system heap */
|
||||
rt_system_heap_init(HEAP_BEGIN, HEAP_END);
|
||||
|
||||
rt_hw_pin_init();
|
||||
|
||||
rt_components_board_init();
|
||||
|
||||
rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
|
||||
|
||||
rt_thread_idle_sethook(idle_wfi);
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
/* install IPI handle */
|
||||
rt_hw_ipi_handler_install(RT_SCHEDULE_IPI, rt_scheduler_ipi_handler);
|
||||
#endif
|
||||
|
||||
rt_assert_set_hook(_assert_hook);
|
||||
}
|
||||
|
||||
#include "xil_io.h"
|
||||
#define PSS_RST_CTRL_REG 0xF8000200
|
||||
#define SLCR_UNLOCK_ADDR 0xF8000008
|
||||
#define UNLOCK_KEY 0xDF0D
|
||||
#define PSS_RST_MASK 0x01
|
||||
|
||||
static void zynq_hw_software_reset(void)
|
||||
{
|
||||
Xil_Out32(SLCR_UNLOCK_ADDR, UNLOCK_KEY);
|
||||
Xil_Out32(PSS_RST_CTRL_REG, PSS_RST_MASK);
|
||||
}
|
||||
MSH_CMD_EXPORT_ALIAS(zynq_hw_software_reset, reboot, soft reboot);
|
42
bsp/zynq/zynq7000/drivers/board.h
Normal file
@ -0,0 +1,42 @@
|
||||
#ifndef __BOARD_H__
|
||||
#define __BOARD_H__
|
||||
|
||||
#if defined(__CC_ARM)
|
||||
extern int Image$$RW_IRAM1$$ZI$$Limit;
|
||||
#define HEAP_BEGIN ((void*)&Image$$RW_IRAM1$$ZI$$Limit)
|
||||
#elif defined(__GNUC__)
|
||||
extern int __bss_end;
|
||||
#define HEAP_BEGIN ((void*)&__bss_end)
|
||||
#endif
|
||||
|
||||
#define HEAP_END (void*)(0x20100000-1)
|
||||
#define GIC_IRQ_START 0
|
||||
#define MAX_HANDLERS 94
|
||||
#define GIC_ACK_INTID_MASK 0x000003ff
|
||||
#define ARM_GIC_MAX_NR 1
|
||||
#define ARM_GIC_NR_IRQS MAX_HANDLERS
|
||||
|
||||
#include "rtthread.h"
|
||||
#include "xparameters.h"
|
||||
|
||||
#define Zynq7000_GIC_CPU_BASE XPAR_PS7_SCUGIC_0_BASEADDR
|
||||
#define Zynq7000_GIC_DIST_BASE XPAR_PS7_SCUGIC_0_DIST_BASEADDR
|
||||
|
||||
rt_inline rt_uint32_t platform_get_gic_dist_base(void)
|
||||
{
|
||||
return Zynq7000_GIC_DIST_BASE;
|
||||
}
|
||||
|
||||
rt_inline rt_uint32_t platform_get_gic_cpu_base(void)
|
||||
{
|
||||
return Zynq7000_GIC_CPU_BASE;
|
||||
}
|
||||
|
||||
#define __REG32(x) (*((volatile unsigned int *)(x)))
|
||||
#define __REG16(x) (*((volatile unsigned short *)(x)))
|
||||
|
||||
void rt_hw_board_init();
|
||||
|
||||
int rt_hw_uart_init(void);
|
||||
|
||||
#endif
|
373
bsp/zynq/zynq7000/drivers/drv_emmc.c
Normal file
@ -0,0 +1,373 @@
|
||||
#include "xil_exception.h"
|
||||
#include "xsdps.h"
|
||||
#include <stdio.h>
|
||||
#include "xparameters.h"
|
||||
#include "rtthread.h"
|
||||
#include <rtdevice.h>
|
||||
|
||||
#define DBG_TAG "drv.mmc"
|
||||
#define DBG_LVL DBG_INFO
|
||||
#include <rtdbg.h>
|
||||
|
||||
#define EMMC_BLOCK_SIZE (512)
|
||||
|
||||
extern u16 TransferMode;
|
||||
extern s32 XSdPs_CmdTransfer(XSdPs *InstancePtr, u32 Cmd, u32 Arg, u32 BlkCnt);
|
||||
extern void XSdPs_SetupADMA2DescTbl(XSdPs *InstancePtr, u32 BlkCnt, const u8 *Buff);
|
||||
|
||||
// replace XSdPs_ReadPolled, using `rt_thread_mdelay`
|
||||
s32 XSdPs_ReadPolled_rtt(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, u8 *Buff)
|
||||
{
|
||||
s32 Status;
|
||||
u32 PresentStateReg;
|
||||
u32 StatusReg;
|
||||
|
||||
if ((InstancePtr->HC_Version != XSDPS_HC_SPEC_V3) ||
|
||||
((InstancePtr->Host_Caps & XSDPS_CAPS_SLOT_TYPE_MASK)
|
||||
!= XSDPS_CAPS_EMB_SLOT)) {
|
||||
if(InstancePtr->Config.CardDetect != 0U) {
|
||||
/* Check status to ensure card is initialized */
|
||||
PresentStateReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
|
||||
XSDPS_PRES_STATE_OFFSET);
|
||||
if ((PresentStateReg & XSDPS_PSR_CARD_INSRT_MASK) == 0x0U) {
|
||||
Status = XST_FAILURE;
|
||||
goto RETURN_PATH;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Set block size to 512 if not already set */
|
||||
if( XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
|
||||
XSDPS_BLK_SIZE_OFFSET) != XSDPS_BLK_SIZE_512_MASK ) {
|
||||
Status = XSdPs_SetBlkSize(InstancePtr,
|
||||
XSDPS_BLK_SIZE_512_MASK);
|
||||
if (Status != XST_SUCCESS) {
|
||||
Status = XST_FAILURE;
|
||||
goto RETURN_PATH;
|
||||
}
|
||||
}
|
||||
|
||||
XSdPs_SetupADMA2DescTbl(InstancePtr, BlkCnt, Buff);
|
||||
|
||||
TransferMode = XSDPS_TM_AUTO_CMD12_EN_MASK |
|
||||
XSDPS_TM_BLK_CNT_EN_MASK | XSDPS_TM_DAT_DIR_SEL_MASK |
|
||||
XSDPS_TM_DMA_EN_MASK | XSDPS_TM_MUL_SIN_BLK_SEL_MASK;
|
||||
|
||||
if (InstancePtr->Config.IsCacheCoherent == 0) {
|
||||
Xil_DCacheInvalidateRange((INTPTR)Buff,
|
||||
BlkCnt * XSDPS_BLK_SIZE_512_MASK);
|
||||
}
|
||||
|
||||
/* Send block read command */
|
||||
Status = XSdPs_CmdTransfer(InstancePtr, CMD18, Arg, BlkCnt);
|
||||
if (Status != XST_SUCCESS) {
|
||||
Status = XST_FAILURE;
|
||||
goto RETURN_PATH;
|
||||
}
|
||||
|
||||
/* Check for transfer complete */
|
||||
do {
|
||||
StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
|
||||
XSDPS_NORM_INTR_STS_OFFSET);
|
||||
if ((StatusReg & XSDPS_INTR_ERR_MASK) != 0U) {
|
||||
/* Write to clear error bits */
|
||||
XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
|
||||
XSDPS_ERR_INTR_STS_OFFSET,
|
||||
XSDPS_ERROR_INTR_ALL_MASK);
|
||||
Status = XST_FAILURE;
|
||||
goto RETURN_PATH;
|
||||
}
|
||||
|
||||
// delay 1ms
|
||||
if ((StatusReg & XSDPS_INTR_TC_MASK) == 0U)
|
||||
rt_thread_mdelay(1);
|
||||
|
||||
} while((StatusReg & XSDPS_INTR_TC_MASK) == 0U);
|
||||
|
||||
/* Write to clear bit */
|
||||
XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
|
||||
XSDPS_NORM_INTR_STS_OFFSET, XSDPS_INTR_TC_MASK);
|
||||
Status = (s32)XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
|
||||
XSDPS_RESP0_OFFSET);
|
||||
|
||||
Status = XST_SUCCESS;
|
||||
|
||||
RETURN_PATH:
|
||||
return Status;
|
||||
}
|
||||
|
||||
// replace XSdPs_WritePolled, using rt_thread_mdelay
|
||||
s32 XSdPs_WritePolled_rtt(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, const u8 *Buff)
|
||||
{
|
||||
s32 Status;
|
||||
u32 PresentStateReg;
|
||||
u32 StatusReg;
|
||||
|
||||
if ((InstancePtr->HC_Version != XSDPS_HC_SPEC_V3) ||
|
||||
((InstancePtr->Host_Caps & XSDPS_CAPS_SLOT_TYPE_MASK)
|
||||
!= XSDPS_CAPS_EMB_SLOT)) {
|
||||
if(InstancePtr->Config.CardDetect != 0U) {
|
||||
/* Check status to ensure card is initialized */
|
||||
PresentStateReg = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
|
||||
XSDPS_PRES_STATE_OFFSET);
|
||||
if ((PresentStateReg & XSDPS_PSR_CARD_INSRT_MASK) == 0x0U) {
|
||||
Status = XST_FAILURE;
|
||||
goto RETURN_PATH;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Set block size to 512 if not already set */
|
||||
if( XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
|
||||
XSDPS_BLK_SIZE_OFFSET) != XSDPS_BLK_SIZE_512_MASK ) {
|
||||
Status = XSdPs_SetBlkSize(InstancePtr,
|
||||
XSDPS_BLK_SIZE_512_MASK);
|
||||
if (Status != XST_SUCCESS) {
|
||||
Status = XST_FAILURE;
|
||||
goto RETURN_PATH;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
XSdPs_SetupADMA2DescTbl(InstancePtr, BlkCnt, Buff);
|
||||
if (InstancePtr->Config.IsCacheCoherent == 0) {
|
||||
Xil_DCacheFlushRange((INTPTR)Buff,
|
||||
BlkCnt * XSDPS_BLK_SIZE_512_MASK);
|
||||
}
|
||||
|
||||
TransferMode = XSDPS_TM_AUTO_CMD12_EN_MASK |
|
||||
XSDPS_TM_BLK_CNT_EN_MASK |
|
||||
XSDPS_TM_MUL_SIN_BLK_SEL_MASK | XSDPS_TM_DMA_EN_MASK;
|
||||
|
||||
/* Send block write command */
|
||||
Status = XSdPs_CmdTransfer(InstancePtr, CMD25, Arg, BlkCnt);
|
||||
if (Status != XST_SUCCESS) {
|
||||
Status = XST_FAILURE;
|
||||
goto RETURN_PATH;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for transfer complete
|
||||
* Polling for response for now
|
||||
*/
|
||||
do {
|
||||
StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
|
||||
XSDPS_NORM_INTR_STS_OFFSET);
|
||||
if ((StatusReg & XSDPS_INTR_ERR_MASK) != 0U) {
|
||||
/* Write to clear error bits */
|
||||
XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
|
||||
XSDPS_ERR_INTR_STS_OFFSET,
|
||||
XSDPS_ERROR_INTR_ALL_MASK);
|
||||
Status = XST_FAILURE;
|
||||
goto RETURN_PATH;
|
||||
}
|
||||
|
||||
if ((StatusReg & XSDPS_INTR_TC_MASK) == 0U)
|
||||
rt_thread_mdelay(1);
|
||||
|
||||
} while((StatusReg & XSDPS_INTR_TC_MASK) == 0U);
|
||||
|
||||
/* Write to clear bit */
|
||||
XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
|
||||
XSDPS_NORM_INTR_STS_OFFSET, XSDPS_INTR_TC_MASK);
|
||||
|
||||
Status = XST_SUCCESS;
|
||||
|
||||
RETURN_PATH:
|
||||
return Status;
|
||||
}
|
||||
|
||||
struct rt_hw_emmc_device {
|
||||
struct rt_device dev;
|
||||
XSdPs emmc;
|
||||
XSdPs_Config *cfg;
|
||||
struct rt_mutex lock;
|
||||
u16 dev_id;
|
||||
};
|
||||
|
||||
#ifdef BSP_USING_SDIO0
|
||||
static struct rt_hw_emmc_device emmc0 = {
|
||||
.dev_id = XPAR_PS7_SD_0_DEVICE_ID,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef BSP_USING_SDIO1
|
||||
static struct rt_hw_emmc_device emmc1 = {
|
||||
.dev_id = XPAR_PS7_SD_1_DEVICE_ID,
|
||||
};
|
||||
#endif
|
||||
|
||||
#define __INIT_CHECK_CFG(cfg) \
|
||||
if (Status != XST_SUCCESS) \
|
||||
{ \
|
||||
rt_kprintf("EMMC Config '%s' failed: err: %d\n", cfg, Status); \
|
||||
return -RT_EIO; \
|
||||
}
|
||||
|
||||
static rt_err_t rt_sdcard_init(rt_device_t dev)
|
||||
{
|
||||
RT_ASSERT(dev);
|
||||
struct rt_hw_emmc_device *pdev = rt_container_of(dev, struct rt_hw_emmc_device, dev);
|
||||
RT_ASSERT(pdev != RT_NULL);
|
||||
|
||||
rt_mutex_take(&pdev->lock, RT_WAITING_FOREVER);
|
||||
if (pdev->cfg != RT_NULL)
|
||||
{
|
||||
LOG_I("init '%s' success", pdev->dev.parent.name);
|
||||
rt_mutex_release(&pdev->lock);
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
pdev->cfg = XSdPs_LookupConfig(pdev->dev_id);
|
||||
RT_ASSERT(pdev->cfg != RT_NULL);
|
||||
s32 Status = XSdPs_CfgInitialize(&pdev->emmc, pdev->cfg, pdev->cfg->BaseAddress);
|
||||
__INIT_CHECK_CFG("cfg");
|
||||
|
||||
Status = XSdPs_CardInitialize(&pdev->emmc);
|
||||
__INIT_CHECK_CFG("init");
|
||||
|
||||
LOG_I("init '%s' success", pdev->dev.parent.name);
|
||||
rt_mutex_release(&pdev->lock);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
rt_inline rt_uint32_t _emmc_start_addr(struct rt_hw_emmc_device *pdev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
rt_inline rt_uint32_t _emmc_size(struct rt_hw_emmc_device *pdev)
|
||||
{
|
||||
return pdev->emmc.SectorCount;
|
||||
}
|
||||
|
||||
rt_inline rt_uint32_t _emmc_end_addr(struct rt_hw_emmc_device *pdev)
|
||||
{
|
||||
return pdev->emmc.SectorCount;
|
||||
}
|
||||
|
||||
static rt_err_t rt_sdcard_open(rt_device_t dev, rt_uint16_t oflag)
|
||||
{
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t rt_sdcard_close(rt_device_t dev)
|
||||
{
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_ssize_t rt_sdcard_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
|
||||
{
|
||||
s32 status;
|
||||
RT_ASSERT(dev);
|
||||
struct rt_hw_emmc_device *pdev = rt_container_of(dev, struct rt_hw_emmc_device, dev);
|
||||
RT_ASSERT(pdev != RT_NULL);
|
||||
|
||||
pos += _emmc_start_addr(pdev);
|
||||
if (size + pos >= _emmc_end_addr(pdev))
|
||||
{
|
||||
LOG_E("addr out of ranger: %d %d", pos, size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
rt_mutex_take(&pdev->lock, RT_WAITING_FOREVER);
|
||||
status = XSdPs_ReadPolled_rtt(&pdev->emmc, pos, size, buffer);
|
||||
rt_mutex_release(&pdev->lock);
|
||||
|
||||
if (status == XST_SUCCESS)
|
||||
return size;
|
||||
|
||||
rt_kprintf("sdcard read failed: %d\n", status);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static rt_uint8_t sdio_write_buf[2][EMMC_BLOCK_SIZE] __attribute__((aligned(32)));
|
||||
|
||||
static rt_ssize_t rt_sdcard_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
|
||||
{
|
||||
s32 status;
|
||||
rt_ssize_t rt = 0;
|
||||
|
||||
RT_ASSERT(dev);
|
||||
struct rt_hw_emmc_device *pdev = rt_container_of(dev, struct rt_hw_emmc_device, dev);
|
||||
RT_ASSERT(pdev != RT_NULL);
|
||||
|
||||
pos += _emmc_start_addr(pdev);
|
||||
if (size + pos >= _emmc_end_addr(pdev))
|
||||
{
|
||||
LOG_E("addr out of ranger: %d %d", pos, size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
rt_mutex_take(&pdev->lock, RT_WAITING_FOREVER);
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
rt_memcpy(sdio_write_buf[pdev->dev_id], ((rt_uint8_t *)buffer) + EMMC_BLOCK_SIZE * i, EMMC_BLOCK_SIZE);
|
||||
|
||||
status = XSdPs_WritePolled_rtt(&pdev->emmc, pos + i, 1, sdio_write_buf[pdev->dev_id]);
|
||||
|
||||
if (status != XST_SUCCESS)
|
||||
{
|
||||
rt_kprintf("sdcard write failed: %d\n", status);
|
||||
break;
|
||||
}
|
||||
|
||||
rt++;
|
||||
}
|
||||
rt_mutex_release(&pdev->lock);
|
||||
|
||||
return rt;
|
||||
}
|
||||
|
||||
static rt_err_t rt_sdcard_control(rt_device_t dev, int cmd, void *args)
|
||||
{
|
||||
RT_ASSERT(dev);
|
||||
struct rt_hw_emmc_device *pdev = rt_container_of(dev, struct rt_hw_emmc_device, dev);
|
||||
RT_ASSERT(pdev != RT_NULL);
|
||||
|
||||
if (cmd == RT_DEVICE_CTRL_BLK_GETGEOME)
|
||||
{
|
||||
struct rt_device_blk_geometry *geometry;
|
||||
|
||||
geometry = (struct rt_device_blk_geometry *)args;
|
||||
if (geometry == RT_NULL)
|
||||
return -RT_ERROR;
|
||||
|
||||
geometry->bytes_per_sector = EMMC_BLOCK_SIZE;
|
||||
geometry->block_size = EMMC_BLOCK_SIZE;
|
||||
geometry->sector_count = _emmc_size(pdev);
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static void _init_emmc_dev(struct rt_hw_emmc_device *pdev, const char *name)
|
||||
{
|
||||
rt_mutex_init(&pdev->lock, name, RT_IPC_FLAG_PRIO);
|
||||
|
||||
pdev->dev.type = RT_Device_Class_Block;
|
||||
pdev->dev.init = rt_sdcard_init;
|
||||
pdev->dev.open = rt_sdcard_open;
|
||||
pdev->dev.close = rt_sdcard_close;
|
||||
pdev->dev.read = rt_sdcard_read;
|
||||
pdev->dev.write = rt_sdcard_write;
|
||||
pdev->dev.control = rt_sdcard_control;
|
||||
pdev->dev.user_data = RT_NULL;
|
||||
|
||||
rt_device_register(&pdev->dev, name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE);
|
||||
}
|
||||
|
||||
int rt_hw_emmc_init(void)
|
||||
{
|
||||
#ifdef BSP_USING_SDIO0
|
||||
_init_emmc_dev(&emmc0, "sd0");
|
||||
#endif
|
||||
|
||||
#ifdef BSP_USING_SDIO1
|
||||
_init_emmc_dev(&emmc1, "sd1");
|
||||
#endif
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
INIT_BOARD_EXPORT(rt_hw_emmc_init);
|
202
bsp/zynq/zynq7000/drivers/drv_gpio.c
Normal file
@ -0,0 +1,202 @@
|
||||
#include <board.h>
|
||||
#include "drv_gpio.h"
|
||||
#include "rtdevice.h"
|
||||
#include "rthw.h"
|
||||
|
||||
#include "xparameters.h"
|
||||
#include "xgpiops.h"
|
||||
|
||||
#define GPIOPS_ID XPAR_XGPIOPS_0_DEVICE_ID
|
||||
#define GPIO_INTERRUPT_ID XPAR_XGPIOPS_0_INTR
|
||||
|
||||
struct hw_intr_node {
|
||||
rt_slist_t node;
|
||||
rt_uint32_t id;
|
||||
void (*hdr)(void *args);
|
||||
void *args;
|
||||
};
|
||||
|
||||
static XGpioPs gpio;
|
||||
static rt_slist_t intr_list;
|
||||
|
||||
rt_inline struct hw_intr_node *_find_intr_node(rt_uint32_t id)
|
||||
{
|
||||
struct hw_intr_node *p;
|
||||
rt_slist_for_each_entry(p, &intr_list, node)
|
||||
{
|
||||
if (p->id == id)
|
||||
{
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
return RT_NULL;
|
||||
}
|
||||
|
||||
static void intr_handler(int vector, void *param)
|
||||
{
|
||||
struct hw_intr_node *p;
|
||||
rt_slist_for_each_entry(p, &intr_list, node)
|
||||
{
|
||||
if (!XGpioPs_IntrGetStatusPin(&gpio, p->id))
|
||||
continue;
|
||||
|
||||
XGpioPs_IntrDisablePin(&gpio, p->id);
|
||||
if (p->hdr)
|
||||
p->hdr(p->args);
|
||||
|
||||
XGpioPs_IntrClearPin(&gpio, p->id);
|
||||
XGpioPs_IntrEnablePin(&gpio, p->id);
|
||||
}
|
||||
}
|
||||
|
||||
static rt_base_t zynq_pin_get(const char *name)
|
||||
{
|
||||
rt_set_errno(-RT_ENOSYS);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void zynq_pin_write(rt_device_t dev, rt_base_t pin, rt_uint8_t value)
|
||||
{
|
||||
if (pin >= XGPIOPS_DEVICE_MAX_PIN_NUM)
|
||||
{
|
||||
rt_set_errno(-RT_ENOSYS);
|
||||
return;
|
||||
}
|
||||
|
||||
XGpioPs_WritePin(&gpio, pin, value);
|
||||
}
|
||||
|
||||
static rt_int8_t zynq_pin_read(rt_device_t dev, rt_base_t pin)
|
||||
{
|
||||
if (pin >= XGPIOPS_DEVICE_MAX_PIN_NUM)
|
||||
{
|
||||
rt_set_errno(-RT_ENOSYS);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return XGpioPs_ReadPin(&gpio, pin);
|
||||
}
|
||||
|
||||
static void zynq_pin_mode(rt_device_t dev, rt_base_t pin, rt_uint8_t mode)
|
||||
{
|
||||
rt_uint8_t isOutput = (mode == PIN_MODE_OUTPUT) || (mode == PIN_MODE_OUTPUT_OD);
|
||||
XGpioPs_SetDirectionPin(&gpio, pin, isOutput);
|
||||
XGpioPs_SetOutputEnablePin(&gpio, pin, isOutput);
|
||||
}
|
||||
|
||||
static rt_err_t zynq_pin_attach_irq(struct rt_device *device, rt_int32_t pin,
|
||||
rt_uint8_t mode, void (*hdr)(void *args), void *args)
|
||||
{
|
||||
u8 irq_type;
|
||||
switch (mode)
|
||||
{
|
||||
case PIN_IRQ_MODE_RISING:
|
||||
irq_type = XGPIOPS_IRQ_TYPE_EDGE_RISING;
|
||||
break;
|
||||
|
||||
case PIN_IRQ_MODE_FALLING:
|
||||
irq_type = XGPIOPS_IRQ_TYPE_EDGE_FALLING;
|
||||
break;
|
||||
|
||||
case PIN_IRQ_MODE_RISING_FALLING:
|
||||
irq_type = XGPIOPS_IRQ_TYPE_EDGE_BOTH;
|
||||
break;
|
||||
|
||||
case PIN_IRQ_MODE_HIGH_LEVEL:
|
||||
irq_type = XGPIOPS_IRQ_TYPE_LEVEL_HIGH;
|
||||
break;
|
||||
|
||||
case PIN_IRQ_MODE_LOW_LEVEL:
|
||||
irq_type = XGPIOPS_IRQ_TYPE_LEVEL_LOW;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -RT_ENOSYS;
|
||||
}
|
||||
|
||||
struct hw_intr_node *node = _find_intr_node(pin);
|
||||
if (node != RT_NULL)
|
||||
{
|
||||
return -RT_EBUSY;
|
||||
}
|
||||
|
||||
node = rt_malloc(sizeof(struct hw_intr_node));
|
||||
if (node == RT_NULL)
|
||||
{
|
||||
return -RT_ENOMEM;
|
||||
}
|
||||
|
||||
XGpioPs_SetIntrTypePin(&gpio, pin, irq_type);
|
||||
|
||||
node->id = pin;
|
||||
node->hdr = hdr;
|
||||
node->args = args;
|
||||
|
||||
rt_slist_append(&intr_list, &node->node);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t zynq_pin_dettach_irq(struct rt_device *device, rt_base_t pin)
|
||||
{
|
||||
struct hw_intr_node *node;
|
||||
|
||||
rt_enter_critical();
|
||||
node = _find_intr_node(pin);
|
||||
if (node != RT_NULL)
|
||||
{
|
||||
rt_exit_critical();
|
||||
return -RT_ERROR;
|
||||
}
|
||||
rt_slist_remove(&intr_list, &node->node);
|
||||
rt_exit_critical();
|
||||
|
||||
rt_free(node);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t zynq_pin_irq_enable(struct rt_device *device, rt_base_t pin,
|
||||
rt_uint8_t enabled)
|
||||
{
|
||||
if (enabled)
|
||||
{
|
||||
XGpioPs_IntrEnablePin(&gpio, pin);
|
||||
}
|
||||
else
|
||||
{
|
||||
XGpioPs_IntrDisablePin(&gpio, pin);
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
const static struct rt_pin_ops _zynq_pin_ops =
|
||||
{
|
||||
zynq_pin_mode,
|
||||
zynq_pin_write,
|
||||
zynq_pin_read,
|
||||
zynq_pin_attach_irq,
|
||||
zynq_pin_dettach_irq,
|
||||
zynq_pin_irq_enable,
|
||||
zynq_pin_get,
|
||||
};
|
||||
|
||||
int rt_hw_pin_init(void)
|
||||
{
|
||||
XGpioPs_Config *gpiops_cfg_ptr;
|
||||
gpiops_cfg_ptr = XGpioPs_LookupConfig(GPIOPS_ID);
|
||||
RT_ASSERT(gpiops_cfg_ptr);
|
||||
|
||||
RT_ASSERT(
|
||||
XGpioPs_CfgInitialize(&gpio, gpiops_cfg_ptr, gpiops_cfg_ptr->BaseAddr)
|
||||
== 0
|
||||
)
|
||||
|
||||
rt_slist_init(&intr_list);
|
||||
rt_hw_interrupt_install(GPIO_INTERRUPT_ID, intr_handler, RT_NULL, "pin");
|
||||
rt_hw_interrupt_umask(GPIO_INTERRUPT_ID);
|
||||
|
||||
return rt_device_pin_register("pin", &_zynq_pin_ops, RT_NULL);
|
||||
}
|
16
bsp/zynq/zynq7000/drivers/drv_gpio.h
Normal file
@ -0,0 +1,16 @@
|
||||
#ifndef __DRV_GPIO_H__
|
||||
#define __DRV_GPIO_H__
|
||||
|
||||
#include <board.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int rt_hw_pin_init(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __DRV_GPIO_H__ */
|
446
bsp/zynq/zynq7000/drivers/drv_spiflash.c
Normal file
@ -0,0 +1,446 @@
|
||||
#include "xparameters.h"
|
||||
#include "xqspips.h"
|
||||
|
||||
#define QSPI_DEVICE_ID XPAR_XQSPIPS_0_DEVICE_ID
|
||||
|
||||
#include <rthw.h>
|
||||
#include <rtdevice.h>
|
||||
#include "board.h"
|
||||
|
||||
#define DBG_TAG "drv.spiflash"
|
||||
#define DBG_LVL DBG_INFO
|
||||
#include <rtdbg.h>
|
||||
|
||||
#define WRITE_STATUS_CMD 0x01
|
||||
#define WRITE_CMD 0x02
|
||||
#define READ_CMD 0x03
|
||||
#define WRITE_DISABLE_CMD 0x04
|
||||
#define READ_STATUS_CMD 0x05
|
||||
#define WRITE_ENABLE_CMD 0x06
|
||||
#define FAST_READ_CMD 0x0B
|
||||
#define DUAL_READ_CMD 0x3B
|
||||
#define QUAD_READ_CMD 0x6B
|
||||
#define BULK_ERASE_CMD 0xC7
|
||||
#define SEC_ERASE_CMD 0xD8
|
||||
#define READ_ID 0x9F
|
||||
|
||||
#define COMMAND_OFFSET 0 // FLASH instruction */
|
||||
#define ADDRESS_1_OFFSET 1 // MSB byte of address to read or write */
|
||||
#define ADDRESS_2_OFFSET 2 // Middle byte of address to read or write */
|
||||
#define ADDRESS_3_OFFSET 3 // LSB byte of address to read or write */
|
||||
#define DATA_OFFSET 4 // Start of Data for Read/Write */
|
||||
#define DUMMY_OFFSET 4 // Dummy byte offset for fast, dual and quad reads
|
||||
#define DUMMY_SIZE 1 // Number of dummy bytes for fast, dual and quad reads
|
||||
#define RD_ID_SIZE 4 // Read ID command + 3 bytes ID response */
|
||||
#define BULK_ERASE_SIZE 1 // Bulk Erase command size */
|
||||
#define SEC_ERASE_SIZE 4 // Sector Erase command + Sector address */
|
||||
#define OVERHEAD_SIZE 4 // control information: command and address
|
||||
|
||||
#define SECTOR_SIZE 0x10000
|
||||
#define NUM_SECTORS 0x200
|
||||
#define NUM_PAGES 0x10000
|
||||
#define PAGE_SIZE 256
|
||||
|
||||
static XQspiPs qspi_dev;
|
||||
|
||||
static u8 ReadBuffer[PAGE_SIZE + DATA_OFFSET + DUMMY_SIZE];
|
||||
static u8 WriteBuffer[PAGE_SIZE + DATA_OFFSET];
|
||||
|
||||
static int FlashReadID(void);
|
||||
static void FlashQuadEnable(XQspiPs *QspiPtr);
|
||||
|
||||
static int init(void)
|
||||
{
|
||||
int Status;
|
||||
|
||||
XQspiPs_Config *QspiConfig;
|
||||
|
||||
QspiConfig = XQspiPs_LookupConfig(QSPI_DEVICE_ID);
|
||||
if (QspiConfig == NULL) {
|
||||
LOG_E("lockup failed");
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
Status = XQspiPs_CfgInitialize(&qspi_dev, QspiConfig,
|
||||
QspiConfig->BaseAddress);
|
||||
if (Status != XST_SUCCESS) {
|
||||
LOG_E("cfg init failed : %d", Status);
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
XQspiPs_SetOptions(&qspi_dev, XQSPIPS_FORCE_SSELECT_OPTION | XQSPIPS_HOLD_B_DRIVE_OPTION);
|
||||
XQspiPs_SetClkPrescaler(&qspi_dev, XQSPIPS_CLK_PRESCALE_8);
|
||||
XQspiPs_SetSlaveSelect(&qspi_dev);
|
||||
FlashReadID();
|
||||
FlashQuadEnable(&qspi_dev);
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function writes to the serial FLASH connected to the QSPI interface.
|
||||
* All the data put into the buffer must be in the same page of the device with
|
||||
* page boundaries being on 256 byte boundaries.
|
||||
*
|
||||
* @param QspiPtr is a pointer to the QSPI driver component to use.
|
||||
* @param Address contains the address to write data to in the FLASH.
|
||||
* @param ByteCount contains the number of bytes to write.
|
||||
* @param Command is the command used to write data to the flash. QSPI
|
||||
* device supports only Page Program command to write data to the
|
||||
* flash.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
rt_inline void FlashWrite(XQspiPs *QspiPtr, u32 Address, u32 ByteCount, u8 Command)
|
||||
{
|
||||
u8 WriteEnableCmd = { WRITE_ENABLE_CMD };
|
||||
u8 ReadStatusCmd[] = { READ_STATUS_CMD, 0 }; /* must send 2 bytes */
|
||||
u8 FlashStatus[2];
|
||||
|
||||
/*
|
||||
* Send the write enable command to the FLASH so that it can be
|
||||
* written to, this needs to be sent as a seperate transfer before
|
||||
* the write
|
||||
*/
|
||||
XQspiPs_PolledTransfer(QspiPtr, &WriteEnableCmd, NULL,
|
||||
sizeof(WriteEnableCmd));
|
||||
|
||||
/*
|
||||
* Setup the write command with the specified address and data for the
|
||||
* FLASH
|
||||
*/
|
||||
WriteBuffer[COMMAND_OFFSET] = Command;
|
||||
WriteBuffer[ADDRESS_1_OFFSET] = (u8) ((Address & 0xFF0000) >> 16);
|
||||
WriteBuffer[ADDRESS_2_OFFSET] = (u8) ((Address & 0xFF00) >> 8);
|
||||
WriteBuffer[ADDRESS_3_OFFSET] = (u8) (Address & 0xFF);
|
||||
|
||||
/*
|
||||
* Send the write command, address, and data to the FLASH to be
|
||||
* written, no receive buffer is specified since there is nothing to
|
||||
* receive
|
||||
*/
|
||||
XQspiPs_PolledTransfer(QspiPtr, WriteBuffer, NULL,
|
||||
ByteCount + OVERHEAD_SIZE);
|
||||
|
||||
/*
|
||||
* Wait for the write command to the FLASH to be completed, it takes
|
||||
* some time for the data to be written
|
||||
*/
|
||||
while (1) {
|
||||
/*
|
||||
* Poll the status register of the FLASH to determine when it
|
||||
* completes, by sending a read status command and receiving the
|
||||
* status byte
|
||||
*/
|
||||
XQspiPs_PolledTransfer(QspiPtr, ReadStatusCmd, FlashStatus,
|
||||
sizeof(ReadStatusCmd));
|
||||
|
||||
/*
|
||||
* If the status indicates the write is done, then stop waiting,
|
||||
* if a value of 0xFF in the status byte is read from the
|
||||
* device and this loop never exits, the device slave select is
|
||||
* possibly incorrect such that the device status is not being
|
||||
* read
|
||||
*/
|
||||
if ((FlashStatus[1] & 0x01) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int write(long offset, const uint8_t *buf, size_t size)
|
||||
{
|
||||
RT_ASSERT(size > 0 && size % PAGE_SIZE == 0 && offset % PAGE_SIZE == 0);
|
||||
|
||||
for (int pos = 0; pos < size; pos += PAGE_SIZE)
|
||||
{
|
||||
rt_memcpy(&WriteBuffer[DATA_OFFSET], &buf[pos], PAGE_SIZE);
|
||||
FlashWrite(&qspi_dev, offset + pos, PAGE_SIZE, WRITE_CMD);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function reads from the serial FLASH connected to the
|
||||
* QSPI interface.
|
||||
*
|
||||
* @param QspiPtr is a pointer to the QSPI driver component to use.
|
||||
* @param Address contains the address to read data from in the FLASH.
|
||||
* @param ByteCount contains the number of bytes to read.
|
||||
* @param Command is the command used to read data from the flash. QSPI
|
||||
* device supports one of the Read, Fast Read, Dual Read and Fast
|
||||
* Read commands to read data from the flash.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
rt_inline void FlashRead(XQspiPs *QspiPtr, u32 Address, u32 ByteCount, u8 Command)
|
||||
{
|
||||
/*
|
||||
* Setup the write command with the specified address and data for the
|
||||
* FLASH
|
||||
*/
|
||||
WriteBuffer[COMMAND_OFFSET] = Command;
|
||||
WriteBuffer[ADDRESS_1_OFFSET] = (u8) ((Address & 0xFF0000) >> 16);
|
||||
WriteBuffer[ADDRESS_2_OFFSET] = (u8) ((Address & 0xFF00) >> 8);
|
||||
WriteBuffer[ADDRESS_3_OFFSET] = (u8) (Address & 0xFF);
|
||||
|
||||
if ((Command == FAST_READ_CMD) || (Command == DUAL_READ_CMD)
|
||||
|| (Command == QUAD_READ_CMD)) {
|
||||
ByteCount += DUMMY_SIZE;
|
||||
}
|
||||
/*
|
||||
* Send the read command to the FLASH to read the specified number
|
||||
* of bytes from the FLASH, send the read command and address and
|
||||
* receive the specified number of bytes of data in the data buffer
|
||||
*/
|
||||
XQspiPs_PolledTransfer(QspiPtr, WriteBuffer, ReadBuffer,
|
||||
ByteCount + OVERHEAD_SIZE);
|
||||
}
|
||||
|
||||
static int read(long offset, uint8_t *buf, size_t size)
|
||||
{
|
||||
RT_ASSERT(size > 0 && size % PAGE_SIZE == 0 && offset % PAGE_SIZE == 0);
|
||||
|
||||
for (int pos = 0; pos < size; pos += PAGE_SIZE)
|
||||
{
|
||||
FlashRead(&qspi_dev, offset + pos, PAGE_SIZE, QUAD_READ_CMD);
|
||||
rt_memcpy(&buf[pos], &ReadBuffer[DATA_OFFSET + DUMMY_SIZE], PAGE_SIZE);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function erases the sectors in the serial FLASH connected to the
|
||||
* QSPI interface.
|
||||
*
|
||||
* @param QspiPtr is a pointer to the QSPI driver component to use.
|
||||
* @param Address contains the address of the first sector which needs to
|
||||
* be erased.
|
||||
* @param ByteCount contains the total size to be erased.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
rt_inline void Erase (XQspiPs *QspiPtr, u32 Address, u32 ByteCount)
|
||||
{
|
||||
u8 WriteEnableCmd = { WRITE_ENABLE_CMD };
|
||||
u8 ReadStatusCmd[] = { READ_STATUS_CMD, 0 }; /* must send 2 bytes */
|
||||
u8 FlashStatus[2];
|
||||
int Sector;
|
||||
int total_sector;
|
||||
|
||||
/*
|
||||
* If erase size is same as the total size of the flash, use bulk erase
|
||||
* command
|
||||
*/
|
||||
if (ByteCount == (NUM_SECTORS * SECTOR_SIZE)) {
|
||||
/*
|
||||
* Send the write enable command to the FLASH so that it can be
|
||||
* written to, this needs to be sent as a seperate transfer
|
||||
* before the erase
|
||||
*/
|
||||
XQspiPs_PolledTransfer(QspiPtr, &WriteEnableCmd, NULL,
|
||||
sizeof(WriteEnableCmd));
|
||||
|
||||
/* Setup the bulk erase command*/
|
||||
WriteBuffer[COMMAND_OFFSET] = BULK_ERASE_CMD;
|
||||
|
||||
/*
|
||||
* Send the bulk erase command; no receive buffer is specified
|
||||
* since there is nothing to receive
|
||||
*/
|
||||
XQspiPs_PolledTransfer(QspiPtr, WriteBuffer, NULL,
|
||||
BULK_ERASE_SIZE);
|
||||
|
||||
/* Wait for the erase command to the FLASH to be completed*/
|
||||
while (1) {
|
||||
/*
|
||||
* Poll the status register of the device to determine
|
||||
* when it completes, by sending a read status command
|
||||
* and receiving the status byte
|
||||
*/
|
||||
XQspiPs_PolledTransfer(QspiPtr, ReadStatusCmd, FlashStatus,
|
||||
sizeof(ReadStatusCmd));
|
||||
|
||||
/*
|
||||
* If the status indicates the write is done, then stop
|
||||
* waiting; if a value of 0xFF in the status byte is
|
||||
* read from the device and this loop never exits, the
|
||||
* device slave select is possibly incorrect such that
|
||||
* the device status is not being read
|
||||
*/
|
||||
if ((FlashStatus[1] & 0x01) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the erase size is less than the total size of the flash, use
|
||||
* sector erase command
|
||||
*/
|
||||
total_sector = RT_ALIGN(ByteCount, SECTOR_SIZE) / SECTOR_SIZE;
|
||||
|
||||
for (Sector = 0; Sector < total_sector; Sector++) {
|
||||
/*
|
||||
* Send the write enable command to the SEEPOM so that it can be
|
||||
* written to, this needs to be sent as a seperate transfer
|
||||
* before the write
|
||||
*/
|
||||
XQspiPs_PolledTransfer(QspiPtr, &WriteEnableCmd, NULL,
|
||||
sizeof(WriteEnableCmd));
|
||||
|
||||
/*
|
||||
* Setup the write command with the specified address and data
|
||||
* for the FLASH
|
||||
*/
|
||||
WriteBuffer[COMMAND_OFFSET] = SEC_ERASE_CMD;
|
||||
WriteBuffer[ADDRESS_1_OFFSET] = (u8) (Address >> 16);
|
||||
WriteBuffer[ADDRESS_2_OFFSET] = (u8) (Address >> 8);
|
||||
WriteBuffer[ADDRESS_3_OFFSET] = (u8) (Address & 0xFF);
|
||||
|
||||
/*
|
||||
* Send the sector erase command and address; no receive buffer
|
||||
* is specified since there is nothing to receive
|
||||
*/
|
||||
XQspiPs_PolledTransfer(QspiPtr, WriteBuffer, NULL,
|
||||
SEC_ERASE_SIZE);
|
||||
|
||||
/*
|
||||
* Wait for the sector erse command to the
|
||||
* FLASH to be completed
|
||||
*/
|
||||
while (1) {
|
||||
/*
|
||||
* Poll the status register of the device to determine
|
||||
* when it completes, by sending a read status command
|
||||
* and receiving the status byte
|
||||
*/
|
||||
XQspiPs_PolledTransfer(QspiPtr, ReadStatusCmd, FlashStatus,
|
||||
sizeof(ReadStatusCmd));
|
||||
|
||||
/*
|
||||
* If the status indicates the write is done, then stop
|
||||
* waiting, if a value of 0xFF in the status byte is
|
||||
* read from the device and this loop never exits, the
|
||||
* device slave select is possibly incorrect such that
|
||||
* the device status is not being read
|
||||
*/
|
||||
if ((FlashStatus[1] & 0x01) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Address += SECTOR_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
static int erase(long offset, size_t size)
|
||||
{
|
||||
Erase(&qspi_dev, offset, size);
|
||||
return size % SECTOR_SIZE == 0? size : (size / SECTOR_SIZE + 1) * SECTOR_SIZE;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function reads serial FLASH ID connected to the SPI interface.
|
||||
*
|
||||
* @param None.
|
||||
*
|
||||
* @return XST_SUCCESS if read id, otherwise XST_FAILURE.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
static int FlashReadID(void)
|
||||
{
|
||||
int Status;
|
||||
|
||||
/* Read ID in Auto mode.*/
|
||||
WriteBuffer[COMMAND_OFFSET] = READ_ID;
|
||||
WriteBuffer[ADDRESS_1_OFFSET] = 0x23; /* 3 dummy bytes */
|
||||
WriteBuffer[ADDRESS_2_OFFSET] = 0x08;
|
||||
WriteBuffer[ADDRESS_3_OFFSET] = 0x09;
|
||||
|
||||
Status = XQspiPs_PolledTransfer(&qspi_dev, WriteBuffer, ReadBuffer, RD_ID_SIZE);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
LOG_I("FlashID=0x%x 0x%x 0x%x\n\r", ReadBuffer[1], ReadBuffer[2], ReadBuffer[3]);
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
*
|
||||
* This function enables quad mode in the serial flash connected to the
|
||||
* SPI interface.
|
||||
*
|
||||
* @param QspiPtr is a pointer to the QSPI driver component to use.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
static void FlashQuadEnable(XQspiPs *QspiPtr)
|
||||
{
|
||||
u8 WriteEnableCmd = { WRITE_ENABLE_CMD };
|
||||
u8 ReadStatusCmd[] = { READ_STATUS_CMD, 0 };
|
||||
u8 QuadEnableCmd[] = { WRITE_STATUS_CMD, 0 };
|
||||
u8 FlashStatus[2];
|
||||
|
||||
if (ReadBuffer[1] == 0x9D) {
|
||||
|
||||
XQspiPs_PolledTransfer(QspiPtr, ReadStatusCmd, FlashStatus,
|
||||
sizeof(ReadStatusCmd));
|
||||
|
||||
QuadEnableCmd[1] = FlashStatus[1] | 1 << 6;
|
||||
|
||||
XQspiPs_PolledTransfer(QspiPtr, &WriteEnableCmd, NULL,
|
||||
sizeof(WriteEnableCmd));
|
||||
|
||||
XQspiPs_PolledTransfer(QspiPtr, QuadEnableCmd, NULL,
|
||||
sizeof(QuadEnableCmd));
|
||||
}
|
||||
}
|
||||
|
||||
#include "fal.h"
|
||||
const struct fal_flash_dev spi_flash =
|
||||
{
|
||||
.name = "spi_flash",
|
||||
.addr = 0x00000000,
|
||||
.len = NUM_SECTORS * SECTOR_SIZE,
|
||||
.blk_size = PAGE_SIZE,
|
||||
.ops = {init, read, write, erase},
|
||||
.write_gran = PAGE_SIZE,
|
||||
};
|
||||
|
||||
static int rt_hw_on_chip_flash_init(void)
|
||||
{
|
||||
fal_init();
|
||||
return RT_EOK;
|
||||
}
|
||||
INIT_ENV_EXPORT(rt_hw_on_chip_flash_init);
|
44
bsp/zynq/zynq7000/drivers/drv_timer.c
Normal file
@ -0,0 +1,44 @@
|
||||
#include "rtthread.h"
|
||||
|
||||
#include "xparameters.h"
|
||||
#include "xscutimer.h"
|
||||
|
||||
#define APU_FREQ XPAR_PS7_CORTEXA9_0_CPU_CLK_FREQ_HZ
|
||||
#define TIMER_DEVICE_ID XPAR_XSCUTIMER_0_DEVICE_ID
|
||||
#define TIMER_IRPT_INTR XPAR_SCUTIMER_INTR
|
||||
|
||||
static XScuTimer timer;
|
||||
|
||||
static void rt_hw_timer_isr(int vector, void *param)
|
||||
{
|
||||
rt_tick_increase();
|
||||
|
||||
XScuTimer_ClearInterruptStatus(&timer);
|
||||
}
|
||||
|
||||
int rt_hw_timer_init(void)
|
||||
{
|
||||
XScuTimer_Config *cfg;
|
||||
s32 err;
|
||||
|
||||
cfg = XScuTimer_LookupConfig(TIMER_DEVICE_ID);
|
||||
RT_ASSERT(cfg);
|
||||
|
||||
err = XScuTimer_CfgInitialize(&timer, cfg, cfg->BaseAddr);
|
||||
RT_ASSERT(err == XST_SUCCESS);
|
||||
|
||||
err = XScuTimer_SelfTest(&timer);
|
||||
RT_ASSERT(err == XST_SUCCESS);
|
||||
|
||||
rt_hw_interrupt_install(TIMER_IRPT_INTR, rt_hw_timer_isr, RT_NULL, "tick");
|
||||
rt_hw_interrupt_umask(TIMER_IRPT_INTR);
|
||||
XScuTimer_EnableInterrupt(&timer);
|
||||
|
||||
XScuTimer_LoadTimer(&timer, APU_FREQ/2/RT_TICK_PER_SECOND);
|
||||
XScuTimer_EnableAutoReload(&timer);
|
||||
|
||||
XScuTimer_Start(&timer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
INIT_BOARD_EXPORT(rt_hw_timer_init);
|
277
bsp/zynq/zynq7000/drivers/drv_uart.c
Normal file
@ -0,0 +1,277 @@
|
||||
#include "stdio.h"
|
||||
#include "xparameters.h"
|
||||
#include "xscugic.h"
|
||||
#include "xuartps.h"
|
||||
|
||||
#include "board.h"
|
||||
#include <rtdevice.h>
|
||||
#include <rthw.h>
|
||||
|
||||
struct hw_uart_device
|
||||
{
|
||||
XUartPs uart;
|
||||
rt_uint32_t irqno;
|
||||
uint16_t dev_id;
|
||||
u32 base_addr;
|
||||
rt_bool_t inited;
|
||||
};
|
||||
|
||||
#ifdef BSP_USING_UART0
|
||||
static struct hw_uart_device _uart_device0 = {
|
||||
.dev_id = XPAR_PS7_UART_0_DEVICE_ID,
|
||||
.irqno = XPAR_XUARTPS_0_INTR,
|
||||
.base_addr = XPAR_PS7_UART_0_BASEADDR,
|
||||
.inited = RT_FALSE,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef BSP_USING_UART1
|
||||
static struct hw_uart_device _uart_device1 = {
|
||||
.dev_id = XPAR_PS7_UART_1_DEVICE_ID,
|
||||
.irqno = XPAR_XUARTPS_1_INTR,
|
||||
.base_addr = XPAR_PS7_UART_1_BASEADDR,
|
||||
.inited = RT_FALSE,
|
||||
};
|
||||
#endif
|
||||
|
||||
rt_inline rt_err_t _uart_init(struct hw_uart_device *device)
|
||||
{
|
||||
XUartPs_Config *uart_cfg = XUartPs_LookupConfig(device->dev_id);
|
||||
if (NULL == uart_cfg)
|
||||
return XST_FAILURE;
|
||||
int status = XUartPs_CfgInitialize(&device->uart, uart_cfg,
|
||||
uart_cfg->BaseAddress);
|
||||
if (status != XST_SUCCESS)
|
||||
return XST_FAILURE;
|
||||
|
||||
status = XUartPs_SelfTest(&device->uart);
|
||||
if (status != XST_SUCCESS)
|
||||
return XST_FAILURE;
|
||||
|
||||
XUartPs_SetOperMode(&device->uart, XUARTPS_OPER_MODE_NORMAL);
|
||||
|
||||
XUartPs_SetFifoThreshold(&device->uart, 1);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
rt_inline void _uart_set_fmt(struct hw_uart_device *device,
|
||||
struct serial_configure *cfg)
|
||||
{
|
||||
XUartPsFormat uart_format;
|
||||
uart_format.BaudRate = cfg->baud_rate;
|
||||
switch (cfg->data_bits)
|
||||
{
|
||||
case 7:
|
||||
uart_format.DataBits = XUARTPS_FORMAT_7_BITS;
|
||||
break;
|
||||
case 6:
|
||||
uart_format.DataBits = XUARTPS_FORMAT_6_BITS;
|
||||
break;
|
||||
default: /* 8 */
|
||||
uart_format.DataBits = XUARTPS_FORMAT_8_BITS;
|
||||
break;
|
||||
}
|
||||
// cfg->bit_order ?
|
||||
switch (cfg->parity)
|
||||
{
|
||||
case PARITY_ODD:
|
||||
uart_format.Parity = XUARTPS_FORMAT_ODD_PARITY;
|
||||
break;
|
||||
case PARITY_EVEN:
|
||||
uart_format.Parity = XUARTPS_FORMAT_EVEN_PARITY;
|
||||
break;
|
||||
default: /** None */
|
||||
uart_format.Parity = XUARTPS_FORMAT_NO_PARITY;
|
||||
break;
|
||||
}
|
||||
switch (cfg->stop_bits)
|
||||
{
|
||||
case STOP_BITS_2:
|
||||
uart_format.StopBits = XUARTPS_FORMAT_2_STOP_BIT;
|
||||
break;
|
||||
default:
|
||||
uart_format.StopBits = XUARTPS_FORMAT_1_STOP_BIT;
|
||||
break;
|
||||
}
|
||||
|
||||
XUartPs_SetDataFormat(&device->uart, &uart_format);
|
||||
}
|
||||
|
||||
static rt_err_t uart_configure(struct rt_serial_device *serial,
|
||||
struct serial_configure *cfg)
|
||||
{
|
||||
RT_ASSERT(serial != RT_NULL);
|
||||
RT_ASSERT(cfg != RT_NULL);
|
||||
struct hw_uart_device *device
|
||||
= (struct hw_uart_device *)serial->parent.user_data;
|
||||
RT_ASSERT(device != RT_NULL);
|
||||
|
||||
if (!device->inited)
|
||||
{
|
||||
int err = _uart_init(device);
|
||||
if (err != RT_EOK)
|
||||
return err;
|
||||
|
||||
device->inited = RT_TRUE;
|
||||
}
|
||||
|
||||
_uart_set_fmt(device, cfg);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static void rt_hw_uart_isr(int irqno, void *param)
|
||||
{
|
||||
struct rt_serial_device *serial = (struct rt_serial_device *)param;
|
||||
struct hw_uart_device *device
|
||||
= (struct hw_uart_device *)serial->parent.user_data;
|
||||
|
||||
u32 isr_status;
|
||||
|
||||
isr_status
|
||||
= XUartPs_ReadReg(device->uart.Config.BaseAddress, XUARTPS_IMR_OFFSET);
|
||||
isr_status &= XUartPs_ReadReg(device->uart.Config.BaseAddress,
|
||||
XUARTPS_ISR_OFFSET);
|
||||
|
||||
if (isr_status & (u32)XUARTPS_IXR_RXOVR)
|
||||
{
|
||||
XUartPs_WriteReg(device->uart.Config.BaseAddress, XUARTPS_ISR_OFFSET,
|
||||
XUARTPS_IXR_RXOVR);
|
||||
}
|
||||
|
||||
rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
|
||||
}
|
||||
|
||||
static rt_err_t
|
||||
uart_control(struct rt_serial_device *serial, int cmd, void *arg)
|
||||
{
|
||||
struct hw_uart_device *pdev;
|
||||
|
||||
RT_ASSERT(serial != RT_NULL);
|
||||
|
||||
pdev = serial->parent.user_data;
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case RT_DEVICE_CTRL_CLR_INT:
|
||||
break;
|
||||
|
||||
case RT_DEVICE_CTRL_SET_INT:
|
||||
rt_hw_interrupt_install(pdev->irqno, rt_hw_uart_isr, (void *)serial,
|
||||
serial->parent.parent.name);
|
||||
rt_hw_interrupt_umask(pdev->irqno);
|
||||
|
||||
XUartPs_SetInterruptMask(&pdev->uart, XUARTPS_IXR_RXOVR);
|
||||
break;
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static int uart_putc(struct rt_serial_device *serial, char c)
|
||||
{
|
||||
struct hw_uart_device *dev;
|
||||
|
||||
RT_ASSERT(serial != RT_NULL);
|
||||
dev = (struct hw_uart_device *)serial->parent.user_data;
|
||||
RT_ASSERT(dev != RT_NULL);
|
||||
|
||||
XUartPs_SendByte(dev->base_addr, c);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int uart_getc(struct rt_serial_device *serial)
|
||||
{
|
||||
struct hw_uart_device *dev;
|
||||
|
||||
RT_ASSERT(serial != RT_NULL);
|
||||
dev = (struct hw_uart_device *)serial->parent.user_data;
|
||||
|
||||
u32 RecievedByte;
|
||||
if (!XUartPs_IsReceiveData(dev->base_addr))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
RecievedByte = XUartPs_ReadReg(dev->base_addr, XUARTPS_FIFO_OFFSET);
|
||||
/* Return the byte received */
|
||||
return RecievedByte;
|
||||
}
|
||||
|
||||
#ifdef RT_SERIAL_USING_DMA
|
||||
static rt_ssize_t dma_transmit(struct rt_serial_device *serial,
|
||||
rt_uint8_t *buf,
|
||||
rt_size_t size,
|
||||
int direction)
|
||||
{
|
||||
RT_ASSERT(serial != RT_NULL);
|
||||
struct hw_uart_device *dev
|
||||
= (struct hw_uart_device *)serial->parent.user_data;
|
||||
RT_ASSERT(dev != RT_NULL);
|
||||
|
||||
for (int i = 0; i < size; i++)
|
||||
XUartPs_SendByte(dev->base_addr, buf[i]);
|
||||
rt_hw_serial_isr(serial, RT_SERIAL_EVENT_TX_DMADONE);
|
||||
|
||||
return size;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct rt_uart_ops _uart_ops = {
|
||||
uart_configure,
|
||||
uart_control,
|
||||
uart_putc,
|
||||
uart_getc,
|
||||
#ifdef RT_SERIAL_USING_DMA
|
||||
dma_transmit,
|
||||
#endif
|
||||
};
|
||||
|
||||
#include "rtthread.h"
|
||||
|
||||
#ifdef BSP_USING_UART0
|
||||
static struct rt_serial_device _serial0;
|
||||
#endif
|
||||
|
||||
#ifdef BSP_USING_UART1
|
||||
static struct rt_serial_device _serial1;
|
||||
#endif
|
||||
|
||||
int rt_hw_uart_init(void)
|
||||
{
|
||||
struct serial_configure config;
|
||||
|
||||
config.baud_rate = BAUD_RATE_115200;
|
||||
config.bit_order = BIT_ORDER_LSB;
|
||||
config.data_bits = DATA_BITS_8;
|
||||
config.parity = PARITY_NONE;
|
||||
config.stop_bits = STOP_BITS_1;
|
||||
config.invert = NRZ_NORMAL;
|
||||
config.bufsz = RT_SERIAL_RB_BUFSZ;
|
||||
|
||||
#ifdef BSP_USING_UART0
|
||||
_serial0.ops = &_uart_ops;
|
||||
_serial0.config = config;
|
||||
|
||||
/* register uart device */
|
||||
rt_hw_serial_register(&_serial0, "uart0",
|
||||
RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX
|
||||
| RT_DEVICE_FLAG_DMA_TX,
|
||||
&_uart_device0);
|
||||
#endif
|
||||
|
||||
#ifdef BSP_USING_UART1
|
||||
_serial1.ops = &_uart_ops;
|
||||
_serial1.config = config;
|
||||
|
||||
rt_hw_serial_register(&_serial1, "uart1",
|
||||
RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX
|
||||
| RT_DEVICE_FLAG_DMA_TX,
|
||||
&_uart_device1);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
INIT_BOARD_EXPORT(rt_hw_uart_init);
|
36
bsp/zynq/zynq7000/drivers/fal_cfg.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2018, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2018-05-17 armink the first version
|
||||
*/
|
||||
|
||||
#ifndef _FAL_CFG_H_
|
||||
#define _FAL_CFG_H_
|
||||
|
||||
#include <rtconfig.h>
|
||||
|
||||
/* ===================== Flash device Configuration ========================= */
|
||||
extern const struct fal_flash_dev spi_flash;
|
||||
|
||||
/* flash device table */
|
||||
#define FAL_FLASH_DEV_TABLE \
|
||||
{ \
|
||||
&spi_flash, \
|
||||
}
|
||||
|
||||
/* ====================== Partition Configuration ========================== */
|
||||
#ifdef FAL_PART_HAS_TABLE_CFG
|
||||
/* partition table */
|
||||
#define FAL_PART_TABLE \
|
||||
{ \
|
||||
{FAL_PART_MAGIC_WORD, "golden", "spi_flash", 0, 8*1024*1024, 0}, \
|
||||
{FAL_PART_MAGIC_WORD, "app", "spi_flash", 8*1024*1024, 8*1024*1024, 0}, \
|
||||
{FAL_PART_MAGIC_WORD, "data", "spi_flash", 16*1024*1024, 8*1024*1024, 0}, \
|
||||
}
|
||||
#endif /* FAL_PART_HAS_TABLE_CFG */
|
||||
|
||||
#endif /* _FAL_CFG_H_ */
|
BIN
bsp/zynq/zynq7000/figures/board.jpg
Normal file
After Width: | Height: | Size: 1.7 MiB |
BIN
bsp/zynq/zynq7000/figures/step_2.png
Normal file
After Width: | Height: | Size: 165 KiB |
BIN
bsp/zynq/zynq7000/figures/step_3.png
Normal file
After Width: | Height: | Size: 170 KiB |
BIN
bsp/zynq/zynq7000/figures/step_4.png
Normal file
After Width: | Height: | Size: 179 KiB |
BIN
bsp/zynq/zynq7000/figures/step_5.png
Normal file
After Width: | Height: | Size: 677 KiB |
BIN
bsp/zynq/zynq7000/figures/step_6.png
Normal file
After Width: | Height: | Size: 952 KiB |
BIN
bsp/zynq/zynq7000/figures/step_7.png
Normal file
After Width: | Height: | Size: 936 KiB |
BIN
bsp/zynq/zynq7000/figures/step_8.png
Normal file
After Width: | Height: | Size: 799 KiB |
BIN
bsp/zynq/zynq7000/figures/step_9.png
Normal file
After Width: | Height: | Size: 985 KiB |
BIN
bsp/zynq/zynq7000/figures/step_9_1.png
Normal file
After Width: | Height: | Size: 765 KiB |
312
bsp/zynq/zynq7000/lscript.ld
Normal file
@ -0,0 +1,312 @@
|
||||
/*******************************************************************/
|
||||
/* */
|
||||
/* This file is automatically generated by linker script generator.*/
|
||||
/* */
|
||||
/* Version: 2018.3 */
|
||||
/* */
|
||||
/* Copyright (c) 2010-2016 Xilinx, Inc. All rights reserved. */
|
||||
/* */
|
||||
/* Description : Cortex-A9 Linker Script */
|
||||
/* */
|
||||
/*******************************************************************/
|
||||
|
||||
_STACK_SIZE = DEFINED(_STACK_SIZE) ? _STACK_SIZE : 0x2000;
|
||||
_HEAP_SIZE = DEFINED(_HEAP_SIZE) ? _HEAP_SIZE : 0x2000;
|
||||
|
||||
_ABORT_STACK_SIZE = DEFINED(_ABORT_STACK_SIZE) ? _ABORT_STACK_SIZE : 1024;
|
||||
_SUPERVISOR_STACK_SIZE = DEFINED(_SUPERVISOR_STACK_SIZE) ? _SUPERVISOR_STACK_SIZE : 2048;
|
||||
_IRQ_STACK_SIZE = DEFINED(_IRQ_STACK_SIZE) ? _IRQ_STACK_SIZE : 1024;
|
||||
_FIQ_STACK_SIZE = DEFINED(_FIQ_STACK_SIZE) ? _FIQ_STACK_SIZE : 1024;
|
||||
_UNDEF_STACK_SIZE = DEFINED(_UNDEF_STACK_SIZE) ? _UNDEF_STACK_SIZE : 1024;
|
||||
|
||||
/* Define Memories in the system */
|
||||
|
||||
MEMORY
|
||||
{
|
||||
ps7_ddr_0 : ORIGIN = 0x100000, LENGTH = 0x20000000
|
||||
ps7_qspi_linear_0 : ORIGIN = 0xFC000000, LENGTH = 0x1000000
|
||||
ps7_ram_0 : ORIGIN = 0x0, LENGTH = 0x30000
|
||||
ps7_ram_1 : ORIGIN = 0xFFFF0000, LENGTH = 0xFE00
|
||||
}
|
||||
|
||||
/* Specify the default entry point to the program */
|
||||
|
||||
ENTRY(_reset)
|
||||
|
||||
/* Define the sections, and where they are mapped in memory */
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text : {
|
||||
__text_start = .;
|
||||
KEEP (*(.vectors))
|
||||
*(.boot)
|
||||
*(.text)
|
||||
*(.text.*)
|
||||
|
||||
/* 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 = .;
|
||||
|
||||
*(.gnu.linkonce.t.*)
|
||||
*(.plt)
|
||||
*(.gnu_warning)
|
||||
*(.gcc_execpt_table)
|
||||
*(.glue_7)
|
||||
*(.glue_7t)
|
||||
*(.vfp11_veneer)
|
||||
*(.ARM.extab)
|
||||
*(.gnu.linkonce.armextab.*)
|
||||
} > ps7_ddr_0
|
||||
|
||||
.init : {
|
||||
KEEP (*(.init))
|
||||
} > ps7_ddr_0
|
||||
|
||||
.fini : {
|
||||
KEEP (*(.fini))
|
||||
} > ps7_ddr_0
|
||||
|
||||
.rodata : {
|
||||
__rodata_start = .;
|
||||
*(.rodata)
|
||||
*(.rodata.*)
|
||||
*(.gnu.linkonce.r.*)
|
||||
__rodata_end = .;
|
||||
} > ps7_ddr_0
|
||||
|
||||
.rodata1 : {
|
||||
__rodata1_start = .;
|
||||
*(.rodata1)
|
||||
*(.rodata1.*)
|
||||
__rodata1_end = .;
|
||||
} > ps7_ddr_0
|
||||
|
||||
.sdata2 : {
|
||||
__sdata2_start = .;
|
||||
*(.sdata2)
|
||||
*(.sdata2.*)
|
||||
*(.gnu.linkonce.s2.*)
|
||||
__sdata2_end = .;
|
||||
} > ps7_ddr_0
|
||||
|
||||
.sbss2 : {
|
||||
__sbss2_start = .;
|
||||
*(.sbss2)
|
||||
*(.sbss2.*)
|
||||
*(.gnu.linkonce.sb2.*)
|
||||
__sbss2_end = .;
|
||||
} > ps7_ddr_0
|
||||
|
||||
.data : {
|
||||
__data_start = .;
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
*(.gnu.linkonce.d.*)
|
||||
*(.jcr)
|
||||
*(.got)
|
||||
*(.got.plt)
|
||||
__data_end = .;
|
||||
} > ps7_ddr_0
|
||||
|
||||
.data1 : {
|
||||
__data1_start = .;
|
||||
*(.data1)
|
||||
*(.data1.*)
|
||||
__data1_end = .;
|
||||
} > ps7_ddr_0
|
||||
|
||||
.got : {
|
||||
*(.got)
|
||||
} > ps7_ddr_0
|
||||
|
||||
.ctors : {
|
||||
PROVIDE(__ctors_start__ = .);
|
||||
KEEP(*(SORT(.ctors.*)))
|
||||
KEEP(*(.ctors))
|
||||
KEEP (*(SORT(.init_array.*)))
|
||||
KEEP (*(.init_array))
|
||||
PROVIDE(__ctors_end__ = .);
|
||||
} > ps7_ddr_0
|
||||
|
||||
.dtors : {
|
||||
__DTOR_LIST__ = .;
|
||||
___DTORS_LIST___ = .;
|
||||
KEEP (*crtbegin.o(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE(*crtend.o) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*(.dtors))
|
||||
__DTOR_END__ = .;
|
||||
___DTORS_END___ = .;
|
||||
} > ps7_ddr_0
|
||||
|
||||
.fixup : {
|
||||
__fixup_start = .;
|
||||
*(.fixup)
|
||||
__fixup_end = .;
|
||||
} > ps7_ddr_0
|
||||
|
||||
.eh_frame : {
|
||||
*(.eh_frame)
|
||||
} > ps7_ddr_0
|
||||
|
||||
.eh_framehdr : {
|
||||
__eh_framehdr_start = .;
|
||||
*(.eh_framehdr)
|
||||
__eh_framehdr_end = .;
|
||||
} > ps7_ddr_0
|
||||
|
||||
.gcc_except_table : {
|
||||
*(.gcc_except_table)
|
||||
} > ps7_ddr_0
|
||||
|
||||
.mmu_tbl (ALIGN(16384)) : {
|
||||
__mmu_tbl_start = .;
|
||||
*(.mmu_tbl)
|
||||
__mmu_tbl_end = .;
|
||||
} > ps7_ddr_0
|
||||
|
||||
.ARM.exidx : {
|
||||
__exidx_start = .;
|
||||
*(.ARM.exidx*)
|
||||
*(.gnu.linkonce.armexidix.*.*)
|
||||
__exidx_end = .;
|
||||
} > ps7_ddr_0
|
||||
|
||||
.preinit_array : {
|
||||
__preinit_array_start = .;
|
||||
KEEP (*(SORT(.preinit_array.*)))
|
||||
KEEP (*(.preinit_array))
|
||||
__preinit_array_end = .;
|
||||
} > ps7_ddr_0
|
||||
|
||||
.init_array : {
|
||||
__init_array_start = .;
|
||||
KEEP (*(SORT(.init_array.*)))
|
||||
KEEP (*(.init_array))
|
||||
__init_array_end = .;
|
||||
} > ps7_ddr_0
|
||||
|
||||
.fini_array : {
|
||||
__fini_array_start = .;
|
||||
KEEP (*(SORT(.fini_array.*)))
|
||||
KEEP (*(.fini_array))
|
||||
__fini_array_end = .;
|
||||
} > ps7_ddr_0
|
||||
|
||||
.ARM.attributes : {
|
||||
__ARM.attributes_start = .;
|
||||
*(.ARM.attributes)
|
||||
__ARM.attributes_end = .;
|
||||
} > ps7_ddr_0
|
||||
|
||||
.sdata : {
|
||||
__sdata_start = .;
|
||||
*(.sdata)
|
||||
*(.sdata.*)
|
||||
*(.gnu.linkonce.s.*)
|
||||
__sdata_end = .;
|
||||
} > ps7_ddr_0
|
||||
|
||||
.sbss (NOLOAD) : {
|
||||
__sbss_start = .;
|
||||
*(.sbss)
|
||||
*(.sbss.*)
|
||||
*(.gnu.linkonce.sb.*)
|
||||
__sbss_end = .;
|
||||
} > ps7_ddr_0
|
||||
|
||||
.tdata : {
|
||||
__tdata_start = .;
|
||||
*(.tdata)
|
||||
*(.tdata.*)
|
||||
*(.gnu.linkonce.td.*)
|
||||
__tdata_end = .;
|
||||
} > ps7_ddr_0
|
||||
|
||||
.tbss : {
|
||||
__tbss_start = .;
|
||||
*(.tbss)
|
||||
*(.tbss.*)
|
||||
*(.gnu.linkonce.tb.*)
|
||||
__tbss_end = .;
|
||||
} > ps7_ddr_0
|
||||
|
||||
.bss (NOLOAD) : {
|
||||
__bss_start = .;
|
||||
*(.bss)
|
||||
*(.bss.*)
|
||||
*(.gnu.linkonce.b.*)
|
||||
*(COMMON)
|
||||
__bss_end = .;
|
||||
_exit = .;
|
||||
} > ps7_ddr_0
|
||||
|
||||
_SDA_BASE_ = __sdata_start + ((__sbss_end - __sdata_start) / 2 );
|
||||
|
||||
_SDA2_BASE_ = __sdata2_start + ((__sbss2_end - __sdata2_start) / 2 );
|
||||
|
||||
/* Generate Stack and Heap definitions */
|
||||
|
||||
.heap (NOLOAD) : {
|
||||
. = ALIGN(16);
|
||||
_heap = .;
|
||||
HeapBase = .;
|
||||
_heap_start = .;
|
||||
. += _HEAP_SIZE;
|
||||
_heap_end = .;
|
||||
HeapLimit = .;
|
||||
} > ps7_ddr_0
|
||||
|
||||
.stack (NOLOAD) : {
|
||||
. = ALIGN(16);
|
||||
_stack_end = .;
|
||||
. += _STACK_SIZE;
|
||||
. = ALIGN(16);
|
||||
_stack = .;
|
||||
__stack = _stack;
|
||||
. = ALIGN(16);
|
||||
_irq_stack_end = .;
|
||||
. += _IRQ_STACK_SIZE;
|
||||
. = ALIGN(16);
|
||||
__irq_stack = .;
|
||||
_supervisor_stack_end = .;
|
||||
. += _SUPERVISOR_STACK_SIZE;
|
||||
. = ALIGN(16);
|
||||
__supervisor_stack = .;
|
||||
_abort_stack_end = .;
|
||||
. += _ABORT_STACK_SIZE;
|
||||
. = ALIGN(16);
|
||||
__abort_stack = .;
|
||||
_fiq_stack_end = .;
|
||||
. += _FIQ_STACK_SIZE;
|
||||
. = ALIGN(16);
|
||||
__fiq_stack = .;
|
||||
_undef_stack_end = .;
|
||||
. += _UNDEF_STACK_SIZE;
|
||||
. = ALIGN(16);
|
||||
__undef_stack = .;
|
||||
} > ps7_ddr_0
|
||||
|
||||
_end = .;
|
||||
}
|
||||
|
263
bsp/zynq/zynq7000/rtconfig.h
Normal file
@ -0,0 +1,263 @@
|
||||
#ifndef RT_CONFIG_H__
|
||||
#define RT_CONFIG_H__
|
||||
|
||||
/* Automatically generated file; DO NOT EDIT. */
|
||||
/* RT-Thread Project Configuration */
|
||||
|
||||
/* RT-Thread Kernel */
|
||||
|
||||
#define RT_NAME_MAX 8
|
||||
#define RT_ALIGN_SIZE 8
|
||||
#define RT_THREAD_PRIORITY_32
|
||||
#define RT_THREAD_PRIORITY_MAX 32
|
||||
#define RT_TICK_PER_SECOND 1000
|
||||
#define RT_USING_OVERFLOW_CHECK
|
||||
#define RT_USING_HOOK
|
||||
#define RT_HOOK_USING_FUNC_PTR
|
||||
#define RT_USING_IDLE_HOOK
|
||||
#define RT_IDLE_HOOK_LIST_SIZE 4
|
||||
#define IDLE_THREAD_STACK_SIZE 256
|
||||
#define RT_USING_TIMER_SOFT
|
||||
#define RT_TIMER_THREAD_PRIO 4
|
||||
#define RT_TIMER_THREAD_STACK_SIZE 512
|
||||
|
||||
/* kservice optimization */
|
||||
|
||||
#define RT_KSERVICE_USING_STDLIB
|
||||
#define RT_USING_DEBUG
|
||||
#define RT_DEBUGING_COLOR
|
||||
#define RT_DEBUGING_CONTEXT
|
||||
#define RT_DEBUGING_INIT
|
||||
|
||||
/* Inter-Thread communication */
|
||||
|
||||
#define RT_USING_SEMAPHORE
|
||||
#define RT_USING_MUTEX
|
||||
#define RT_USING_EVENT
|
||||
#define RT_USING_MAILBOX
|
||||
#define RT_USING_MESSAGEQUEUE
|
||||
|
||||
/* Memory Management */
|
||||
|
||||
#define RT_PAGE_MAX_ORDER 11
|
||||
#define RT_USING_MEMPOOL
|
||||
#define RT_USING_SMALL_MEM
|
||||
#define RT_USING_SMALL_MEM_AS_HEAP
|
||||
#define RT_USING_HEAP
|
||||
|
||||
/* Kernel Device Object */
|
||||
|
||||
#define RT_USING_DEVICE
|
||||
#define RT_USING_CONSOLE
|
||||
#define RT_CONSOLEBUF_SIZE 128
|
||||
#define RT_CONSOLE_DEVICE_NAME "uart0"
|
||||
#define RT_VER_NUM 0x50001
|
||||
#define RT_USING_CACHE
|
||||
#define RT_USING_HW_ATOMIC
|
||||
#define RT_USING_CPU_FFS
|
||||
#define ARCH_MM_MMU
|
||||
#define ARCH_ARM
|
||||
#define ARCH_ARM_MMU
|
||||
#define ARCH_ARM_CORTEX_A
|
||||
#define RT_USING_GIC_V2
|
||||
#define ARCH_ARM_CORTEX_A9
|
||||
|
||||
/* RT-Thread Components */
|
||||
|
||||
#define RT_USING_COMPONENTS_INIT
|
||||
#define RT_USING_USER_MAIN
|
||||
#define RT_MAIN_THREAD_STACK_SIZE 2048
|
||||
#define RT_MAIN_THREAD_PRIORITY 10
|
||||
#define RT_USING_MSH
|
||||
#define RT_USING_FINSH
|
||||
#define FINSH_USING_MSH
|
||||
#define FINSH_THREAD_NAME "tshell"
|
||||
#define FINSH_THREAD_PRIORITY 20
|
||||
#define FINSH_THREAD_STACK_SIZE 4096
|
||||
#define FINSH_USING_HISTORY
|
||||
#define FINSH_HISTORY_LINES 5
|
||||
#define FINSH_USING_SYMTAB
|
||||
#define FINSH_CMD_SIZE 80
|
||||
#define MSH_USING_BUILT_IN_COMMANDS
|
||||
#define FINSH_USING_DESCRIPTION
|
||||
#define FINSH_ARG_MAX 10
|
||||
|
||||
/* DFS: device virtual file system */
|
||||
|
||||
#define RT_USING_DFS
|
||||
#define DFS_USING_POSIX
|
||||
#define DFS_USING_WORKDIR
|
||||
#define DFS_FD_MAX 16
|
||||
#define RT_USING_DFS_V1
|
||||
#define DFS_FILESYSTEMS_MAX 4
|
||||
#define DFS_FILESYSTEM_TYPES_MAX 4
|
||||
#define RT_USING_DFS_DEVFS
|
||||
|
||||
/* Device Drivers */
|
||||
|
||||
#define RT_USING_DEVICE_IPC
|
||||
#define RT_UNAMED_PIPE_NUMBER 64
|
||||
#define RT_USING_SERIAL
|
||||
#define RT_USING_SERIAL_V1
|
||||
#define RT_SERIAL_USING_DMA
|
||||
#define RT_SERIAL_RB_BUFSZ 64
|
||||
#define RT_USING_PIN
|
||||
|
||||
/* Using USB */
|
||||
|
||||
|
||||
/* C/C++ and POSIX layer */
|
||||
|
||||
#define RT_LIBC_DEFAULT_TIMEZONE 8
|
||||
|
||||
/* POSIX (Portable Operating System Interface) layer */
|
||||
|
||||
|
||||
/* Interprocess Communication (IPC) */
|
||||
|
||||
|
||||
/* Socket is in the 'Network' category */
|
||||
|
||||
|
||||
/* Network */
|
||||
|
||||
|
||||
/* Utilities */
|
||||
|
||||
#define RT_USING_ADT
|
||||
#define RT_USING_ADT_AVL
|
||||
#define RT_USING_ADT_BITMAP
|
||||
#define RT_USING_ADT_HASHMAP
|
||||
#define RT_USING_ADT_REF
|
||||
|
||||
/* RT-Thread Utestcases */
|
||||
|
||||
|
||||
/* Hardware Drivers Config */
|
||||
|
||||
/* On-chip Peripheral Drivers */
|
||||
|
||||
#define BSP_USING_GPIO
|
||||
#define BSP_USING_UART
|
||||
#define BSP_USING_UART0
|
||||
#define SOC_ZYNQ_7000
|
||||
#define RT_USING_FPU
|
||||
|
||||
/* RT-Thread online packages */
|
||||
|
||||
/* IoT - internet of things */
|
||||
|
||||
|
||||
/* Wi-Fi */
|
||||
|
||||
/* Marvell WiFi */
|
||||
|
||||
|
||||
/* Wiced WiFi */
|
||||
|
||||
|
||||
/* CYW43012 WiFi */
|
||||
|
||||
|
||||
/* IoT Cloud */
|
||||
|
||||
|
||||
/* security packages */
|
||||
|
||||
|
||||
/* language packages */
|
||||
|
||||
/* JSON: JavaScript Object Notation, a lightweight data-interchange format */
|
||||
|
||||
|
||||
/* XML: Extensible Markup Language */
|
||||
|
||||
|
||||
/* multimedia packages */
|
||||
|
||||
/* LVGL: powerful and easy-to-use embedded GUI library */
|
||||
|
||||
|
||||
/* u8g2: a monochrome graphic library */
|
||||
|
||||
|
||||
/* tools packages */
|
||||
|
||||
|
||||
/* system packages */
|
||||
|
||||
/* enhanced kernel services */
|
||||
|
||||
|
||||
/* acceleration: Assembly language or algorithmic acceleration packages */
|
||||
|
||||
|
||||
/* CMSIS: ARM Cortex-M Microcontroller Software Interface Standard */
|
||||
|
||||
|
||||
/* Micrium: Micrium software products porting for RT-Thread */
|
||||
|
||||
|
||||
/* peripheral libraries and drivers */
|
||||
|
||||
/* sensors drivers */
|
||||
|
||||
|
||||
/* touch drivers */
|
||||
|
||||
|
||||
/* Kendryte SDK */
|
||||
|
||||
|
||||
/* AI packages */
|
||||
|
||||
|
||||
/* Signal Processing and Control Algorithm Packages */
|
||||
|
||||
|
||||
/* miscellaneous packages */
|
||||
|
||||
/* project laboratory */
|
||||
|
||||
/* samples: kernel and components samples */
|
||||
|
||||
|
||||
/* entertainment: terminal games and other interesting software packages */
|
||||
|
||||
|
||||
/* Arduino libraries */
|
||||
|
||||
|
||||
/* Projects and Demos */
|
||||
|
||||
|
||||
/* Sensors */
|
||||
|
||||
|
||||
/* Display */
|
||||
|
||||
|
||||
/* Timing */
|
||||
|
||||
|
||||
/* Data Processing */
|
||||
|
||||
|
||||
/* Data Storage */
|
||||
|
||||
/* Communication */
|
||||
|
||||
|
||||
/* Device Control */
|
||||
|
||||
|
||||
/* Other */
|
||||
|
||||
|
||||
/* Signal IO */
|
||||
|
||||
|
||||
/* Uncategorized */
|
||||
|
||||
|
||||
#endif
|
59
bsp/zynq/zynq7000/rtconfig.py
Normal file
@ -0,0 +1,59 @@
|
||||
import os
|
||||
|
||||
# toolchains options
|
||||
ARCH='arm'
|
||||
CPU='cortex-a'
|
||||
CROSS_TOOL='gcc'
|
||||
|
||||
if os.getenv('RTT_CC'):
|
||||
CROSS_TOOL = os.getenv('RTT_CC')
|
||||
|
||||
# only support GNU GCC compiler
|
||||
PLATFORM = 'gcc'
|
||||
EXEC_PATH = '/opt/arm-none-eabi-gcc'
|
||||
|
||||
if os.getenv('RTT_EXEC_PATH'):
|
||||
EXEC_PATH = os.getenv('RTT_EXEC_PATH')
|
||||
|
||||
# BUILD = 'relsase'
|
||||
BUILD = 'debug'
|
||||
if os.getenv('RTT_BUILD_TYPE'):
|
||||
BUILD = os.getenv('RTT_BUILD_TYPE')
|
||||
|
||||
if PLATFORM == 'gcc':
|
||||
# toolchains
|
||||
PREFIX = 'arm-none-eabi-'
|
||||
CC = PREFIX + 'gcc'
|
||||
CXX = PREFIX + 'g++'
|
||||
AS = PREFIX + 'gcc'
|
||||
AR = PREFIX + 'ar'
|
||||
LINK = PREFIX + 'gcc'
|
||||
TARGET_EXT = 'elf'
|
||||
SIZE = PREFIX + 'size'
|
||||
OBJDUMP = PREFIX + 'objdump'
|
||||
OBJCPY = PREFIX + 'objcopy'
|
||||
STRIP = PREFIX + 'strip'
|
||||
DEVICE = ' -Wall -Werror -mcpu=cortex-a9 -mfloat-abi=hard -mfpu=vfpv3 -ffunction-sections -fdata-sections -funwind-tables '
|
||||
CFLAGS = DEVICE
|
||||
AFLAGS = ' -c -fmessage-length=0' + DEVICE + ' -x assembler-with-cpp -D__ASSEMBLY__ -I. '
|
||||
LINK_SCRIPT = 'lscript.ld'
|
||||
LFLAGS = DEVICE + ' -Wl,-Map=zynq7000.map,--gc-sections,-build-id=none -specs=Xilinx.spec -Wl,-T -Wl,%s' % LINK_SCRIPT
|
||||
CXXFLAGS = DEVICE + ' -std=gnu++11 -Woverloaded-virtual -fno-exceptions -fno-rtti'
|
||||
|
||||
CPATH = ''
|
||||
LPATH = ''
|
||||
|
||||
M_CFLAGS = CFLAGS + ' -mlong-calls -fPIC '
|
||||
M_CXXFLAGS = CXXFLAGS + ' -mlong-calls -fPIC'
|
||||
M_LFLAGS = DEVICE + CXXFLAGS + ' -Wl,--gc-sections,-z,max-page-size=0x4' +\
|
||||
' -shared -fPIC -nostartfiles -nostdlib -static-libgcc'
|
||||
M_POST_ACTION = STRIP + ' -R .hash $TARGET\n' + SIZE + ' $TARGET \n'
|
||||
|
||||
if BUILD == 'debug':
|
||||
CFLAGS += ' -O0 -gdwarf-2'
|
||||
AFLAGS += ' -gdwarf-2'
|
||||
else:
|
||||
CFLAGS += ' -O3'
|
||||
|
||||
POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.bin\n' +\
|
||||
SIZE + ' $TARGET \n'
|