Merge branch 'master' into mutexrevert

This commit is contained in:
Meco Jianting Man
2021-06-05 13:03:45 +08:00
committed by GitHub
486 changed files with 129625 additions and 6158 deletions

View File

@@ -149,10 +149,10 @@ jobs:
if: ${{ matrix.legs.RTT_TOOL_CHAIN == 'sourcery-arm' && success() }}
shell: bash
run: |
wget -q https://github.com/RT-Thread/toolchains-ci/releases/download/arm-2017q2-v6/gcc-arm-none-eabi-6-2017-q2-update-linux.tar.bz2
sudo tar xjf gcc-arm-none-eabi-6-2017-q2-update-linux.tar.bz2 -C /opt
/opt/gcc-arm-none-eabi-6-2017-q2-update/bin/arm-none-eabi-gcc --version
echo "RTT_EXEC_PATH=/opt/gcc-arm-none-eabi-6-2017-q2-update/bin" >> $GITHUB_ENV
wget -q https://developer.arm.com/-/media/Files/downloads/gnu-rm/10-2020q4/gcc-arm-none-eabi-10-2020-q4-major-x86_64-linux.tar.bz2
sudo tar xjf gcc-arm-none-eabi-10-2020-q4-major-x86_64-linux.tar.bz2 -C /opt
/opt/gcc-arm-none-eabi-10-2020-q4-major/bin/arm-none-eabi-gcc --version
echo "RTT_EXEC_PATH=/opt/gcc-arm-none-eabi-10-2020-q4-major/bin" >> $GITHUB_ENV
- name: Install Mips ToolChains
if: ${{ matrix.legs.RTT_TOOL_CHAIN == 'sourcery-mips' && success() }}

View File

@@ -11,7 +11,7 @@ jobs:
fail-fast: false
matrix:
legs:
- {UTEST: "kernel/ipc", RTT_BSP: "bsp/qemu-vexpress-a9", QEMU_ARCH: "vexpress-a9", CONFIG_FILE: "examples/utest/configs/utest_self/config.h"}
- {UTEST: "kernel/mem", RTT_BSP: "bsp/qemu-vexpress-a9", QEMU_ARCH: "vexpress-a9", CONFIG_FILE: "examples/utest/configs/kernel/config.h"}
- {UTEST: "components/utest", RTT_BSP: "bsp/qemu-vexpress-a9", QEMU_ARCH: "vexpress-a9", CONFIG_FILE: "examples/utest/configs/utest_self/config.h"}
env:
@@ -23,12 +23,12 @@ jobs:
run: |
sudo apt-get update > /dev/null
sudo apt-get -yqq install scons qemu-system-arm git
wget -q https://github.com/RT-Thread/toolchains-ci/releases/download/arm-2017q2-v6/gcc-arm-none-eabi-6-2017-q2-update-linux.tar.bz2
sudo tar xjf gcc-arm-none-eabi-6-2017-q2-update-linux.tar.bz2 -C /opt
wget -q https://developer.arm.com/-/media/Files/downloads/gnu-rm/10-2020q4/gcc-arm-none-eabi-10-2020-q4-major-x86_64-linux.tar.bz2
sudo tar xjf gcc-arm-none-eabi-10-2020-q4-major-x86_64-linux.tar.bz2 -C /opt
- name: Build bsp
run: |
export RTT_EXEC_PATH=/opt/gcc-arm-none-eabi-6-2017-q2-update/bin
/opt/gcc-arm-none-eabi-6-2017-q2-update/bin/arm-none-eabi-gcc --version
export RTT_EXEC_PATH=/opt/gcc-arm-none-eabi-10-2020-q4-major/bin
/opt/gcc-arm-none-eabi-10-2020-q4-major/bin/arm-none-eabi-gcc --version
cp $TEST_CONFIG_FILE $TEST_BSP_ROOT/rtconfig.h
scons -j$(nproc) -C $TEST_BSP_ROOT
- name: Start test

725
bsp/ft2004/.config Normal file

File diff suppressed because it is too large Load Diff

31
bsp/ft2004/Kconfig Normal file
View File

@@ -0,0 +1,31 @@
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 "$PKGS_DIR/Kconfig"
config FT2004
bool
select ARCH_ARM_CORTEX_A
select RT_USING_COMPONENTS_INIT
select RT_USING_USER_MAIN
select RT_USING_GIC_V3
default y
source "./libraries/Kconfig"

236
bsp/ft2004/README.md Normal file
View File

@@ -0,0 +1,236 @@
# ft2004 四核开发板 BSP 说明
## 简介
本文档为 飞腾技术公司 ft2000/4 开发板的 BSP (板级支持包) 说明。
主要内容如下:
- 开发板资源介绍
- BSP 外设支持
- 使用方法
- 相关实验
### 1. 开发板资源介绍
FT-2000/4 是一款面向桌面应用的高性能通用 4 核处理器。每 2 个核构成 1
个处理器核簇Cluster并共享 L2 Cache。主要技术特征如下
- 兼容 ARM v8 64 位指令系统,兼容 32 位指令
- 支持单精度、双精度浮点运算指令
- 支持 ASIMD 处理指令
- 集成 2 个 DDR4 通道,可对 DDR 存储数据进行实时加密
- 集成 34 Lane PCIE3.0 接口2 个 X16每个可拆分成 2 个 X82 个 X1
- 集成 2 个 GMACRGMII 接口,支持 10/100/1000 自适应
- 集成 1 个 SD 卡控制器,兼容 SD 2.0 规范
- 集成 1 个 HDAudio支持音频输出可同时支持最多 4 个 Codec
- 集成 SM2、SM3、SM4 模块
- 集成 4 个 UART1 个 LPC32 个 GPIO4 个 I2C1 个 QSPI2 个通
用 SPI2 个 WDT16 个外部中断(和 GPIO 共用 IO
- 集成温度传感器
### 2. BSP 外设支持
| 外设名 | 支持情况 | 备注 |
| -------- | -------- | ---------------------- |
| ft_gicv3 | 支持 | gicv3 中断控制器 |
| ft_gmac | 支持 | ft gmac 千兆网卡控制器 |
| ft_i2c | 支持 | FT I2C |
| ft_qspi | 支持 | FT qspi 控制器 |
| ft_sd | 支持 | FT mmcsd 控制器 |
| ft_uart | 支持 | PrimeCell PL011 |
| ft_spi | 支持 | FT spi 控制器 |
| ft_gpio | 支持 | FT gpio 控制器 |
| ft_can | 支持 | FT can 控制器 |
### 3. 使用方法
#### ubuntu 上环境搭建
1. 在 ubuntu 环境下通过指令,下载并安装交叉编译链
```
sudo apt-get install gcc-arm-none-eabi
```
2. 安装之后,通过指令,确定交叉编译链安装完毕
```
arm-none-eabi-gcc -v
```
3. 搭建 tftp 环境
- 在主机安装 tftp 服务
> 使用 ubuntu 完成下列操作
```
sudo apt-get install tftp-hpa tftpd-hpa
sudo apt-get install xinetd
```
- 新建 tftboot 目录,如:
`/mnt/d/tftboot`
> 需要给 tftboot 目录执行权限`chmod 777 /**/tftboot`
- 配置主机 tftpboot 服务
新建并配置文件/etc/xinetd.d/tftp
```
# /etc/xinetd.d/tftp
server tftp
{
socket_type = dgram
protocol = udp
wait = yes
user = root
server = /usr/sbin/in.tftpd
server_args = -s /mnt/d/tftboot
disable = no
per_source = 11
cps = 100 2
flags = IPv4
}
```
- 启动主机 tftp 服务
```
sudo service tftpd-hpa start
```
- 修改主机 tftp 配置
修改/etc/default/tftpd-hpa
```
sudo nano /etc/default/tftpd-hpa
# /etc/default/tftpd-hpa
TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/mnt/d/tftboot"
TFTP_ADDRESS=":69"
TFTP_OPTIONS="-l -c -s"
```
- 重启主机 tftp 服务
> 每次开机要重启一次
```
sudo service tftpd-hpa restart
```
- 测试主机 tftp 服务的可用性
> 登录 tftp 服务,获取一个文件
```
$ tftp 192.168.4.50
tftp> get test1234
tftp> q
```
#### 执行
1. 将本 bsp 包拷贝至 RT-THREAD bsp/目录下
1. 在 Ubuntu 终端下,切换至 bsp 目录
```
cd rt-thread/bsp/ft2004
```
3. 使用 scons -c 清空工程缓存
4. 使用 scons --menuconfig 配置需要的外设
![](./figures/onchipPeripheral.png)
5. 使用 scons 编译代码,得到 rtthread.bin并将 rtthread.bin 放入之前配置的 tftp 路径下。
6. 连接开发板对应串口到 PC, 在终端工具里打开相应的串口115200-8-1-N
7. 将开发板网线接入局域网中
8. 本开发板自带 uboot使用 uboot 自带 指令进行将 bin 文件下载至 ram 中
```
setenv ipaddr 192.168.x.x # 设置开发板ip
setenv serverip 192.168.x.x # 设置tftp服务器ip
setenv gatewayip 192.168.x.x # 设置网关ip
tftpboot 80100000 rtthread.bin # 在主机 /tftpboot目录中的rtthread.bin文件下载到开发板内存的80100000地址中。
```
7. 执行跳转指令,便可以正常执行
```
bootvx32 80100000
boot32 80100000
```
![](./figures/启动演示图.png)
### 5. 相关实验
#### 网卡
- 主机 ping 本机 指令 sudo ping 192.168.3.20 (默认)
- rtt ping 主机 指令 ping 192.168.x.x (根据实际情况)
- 通过界面
![](./figures/rttPing通过界面.png)
#### sd 卡调试
- 通过基本命令进行mv echo ls cd rm ....
![](./figures/rttsd调试.png)
#### spi flash 卡调试
- 找一块有 spi flash 插槽的 ft-2004 开发板,插入 sf25s 或 gd25q 系列 spi flash
- 配置 rt-thread 的编译选项,打开 BSP_USE_SPI 和 BSP_USE_GPIO 配置,关闭 BSP_USE_QSPI 配置,打开 rt-thread 的 SFUD 调试开关
- 编译 rt-thread加载版本启动启动后显示 spi flash probe 成功
- 执行 sf 基本操作read, write, erase
#### 推荐指令
1. sf probe S25FS256
2. sf read 0x1FFF000 16
3. sf write 0x1FFF000 16 25 68 78 95 15 75 20
4. sf read 0x1FFF000 16
5. sf erase 0x1FFF000 16
#### can 测试
1. 使用 scons menuconfig 选中 Enable Can
2. 然后选中 Enable can0 Enable can0 work in loop back
3. 烧录程序并且烧录
4. 打开 can 盒,将波特率设为 1000000
5. 然后通过 can 盒发送对应的数据(标准帧,扩展帧),就可以看见回复同样的内容
## 6. 参考资源
- ARM Architecture Reference Manual
- FT-20004 软件编程手册-V1.4
## 7. 联系人信息
请联系飞腾嵌入式软件部
huanghe@phytium.com.cn
zhugengyu@phytium.com.cn

14
bsp/ft2004/SConscript Normal file
View File

@@ -0,0 +1,14 @@
# for module compiling
import os
Import('RTT_ROOT')
cwd = str(Dir('#'))
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')

32
bsp/ft2004/SConstruct Normal file
View File

@@ -0,0 +1,32 @@
import os
import sys
import rtconfig
if os.getenv('RTT_ROOT'):
RTT_ROOT = os.getenv('RTT_ROOT')
else:
RTT_ROOT = os.path.join(os.getcwd(), '..', '..')
sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')]
from building import *
TARGET = 'ft2004.' + 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.CFLAGS,
AR = rtconfig.AR, ARFLAGS = '-rc',
LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS)
env.PrependENVPath('PATH', rtconfig.EXEC_PATH)
env['ASCOM'] = env['ASPPCOM']
Export('RTT_ROOT')
Export('rtconfig')
# prepare building environment
objs = PrepareBuilding(env, RTT_ROOT)
# make a building
DoBuilding(TARGET, objs)

View File

@@ -0,0 +1,11 @@
Import('RTT_ROOT')
Import('rtconfig')
from building import *
cwd = GetCurrentDir()
src = Glob('*.c')
CPPPATH = [cwd]
group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH)
Return('group')

View File

@@ -0,0 +1,77 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2012-12-05 Bernard the first version
*/
#include <rthw.h>
#include <rtthread.h>
#include "ft_cpu.h"
#include "ft_generic_timer.h"
#include <board.h>
#ifdef RT_USING_SMP
struct rt_thread test_core[RT_CPUS_NR];
static char *core_thread_name[RT_CPUS_NR] = {
"core0_test",
"core1_test",
"core2_test",
"core3_test"};
static rt_uint8_t core_stack[RT_CPUS_NR][1024];
static void demo_core_thread(void *parameter)
{
rt_base_t level;
while (1)
{
/* code */
level = rt_cpus_lock();
rt_kprintf("Hi, core%d \r\n", FCpu_IdGet());
rt_cpus_unlock(level);
rt_thread_mdelay(20000);
}
}
void demo_core(void)
{
rt_ubase_t i;
rt_uint8_t cpu_id = 0;
for (i = 0; i < RT_CPUS_NR; i++)
{
cpu_id = i;
rt_thread_init(&test_core[i],
core_thread_name[i],
demo_core_thread,
RT_NULL,
&core_stack[i],
1024,
20,
32);
rt_thread_control(&test_core[i], RT_THREAD_CTRL_BIND_CPU, (void *)cpu_id);
rt_thread_startup(&test_core[i]);
}
}
#endif
int main(void)
{
int count = 1;
#ifdef RT_USING_SMP
demo_core();
#endif
while (count++)
{
rt_thread_mdelay(2000);
}
return RT_EOK;
}

View File

@@ -0,0 +1,14 @@
from building import *
cwd = GetCurrentDir()
src = Glob('*.S')
src += Glob('*.c')
CPPPATH = [cwd]
group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH)
Return('group')

155
bsp/ft2004/drivers/board.c Normal file
View File

@@ -0,0 +1,155 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-03-04 Carl the first version
*
*/
#include <rtthread.h>
#include "ft_printf.h"
#include "ft_assert.h"
#include "ft_cpu.h"
#include "ft_psci.h"
#include "ft_parameters.h"
#include "board.h"
#include "gtimer.h"
#include "ft_generic_timer.h"
#include <gicv3.h>
#include "interrupt.h"
#include <mmu.h>
#include "cp15.h"
#include "ft2004.h"
#define DDR_MEM (SHARED | AP_RW | DOMAIN0 | MEMWT | DESC_SEC)
struct mem_desc platform_mem_desc[] = {
{0x80000000,
0x80000000 + 0x7f000000,
0x80000000,
DDR_MEM},
{0, //< QSPI
0x1FFFFFFF,
0,
DEVICE_MEM},
{0x20000000, //<! LPC
0x27FFFFFF,
0x20000000,
DEVICE_MEM},
{FT_DEV_BASE_ADDR, //<! Device register
FT_DEV_END_ADDR,
FT_DEV_BASE_ADDR,
DEVICE_MEM},
{0x30000000, //<! debug
0x39FFFFFF,
0x30000000,
DEVICE_MEM},
{0x3A000000, //<! Internal register space in the on-chip network
0x3AFFFFFF,
0x3A000000,
DEVICE_MEM},
{FT_PCI_CONFIG_BASEADDR,
FT_PCI_CONFIG_BASEADDR + FT_PCI_CONFIG_REG_LENGTH,
FT_PCI_CONFIG_BASEADDR,
DEVICE_MEM},
{FT_PCI_IO_CONFIG_BASEADDR,
FT_PCI_IO_CONFIG_BASEADDR + FT_PCI_IO_CONFIG_REG_LENGTH,
FT_PCI_IO_CONFIG_BASEADDR,
DEVICE_MEM},
{FT_PCI_MEM32_BASEADDR,
FT_PCI_MEM32_BASEADDR + FT_PCI_MEM32_REG_LENGTH,
FT_PCI_MEM32_BASEADDR,
DEVICE_MEM},
};
const rt_uint32_t platform_mem_desc_size = sizeof(platform_mem_desc) / sizeof(platform_mem_desc[0]);
rt_uint32_t platform_get_gic_dist_base(void)
{
return FT_GICV3_DISTRIBUTOR_BASEADDRESS;
}
static rt_uint32_t timerStep;
void rt_hw_timer_isr(int vector, void *parameter)
{
gtimer_set_load_value(timerStep);
rt_tick_increase();
}
int rt_hw_timer_init(void)
{
rt_hw_interrupt_install(30, rt_hw_timer_isr, RT_NULL, "tick");
rt_hw_interrupt_umask(30);
timerStep = gtimer_get_counter_frequency();
timerStep /= RT_TICK_PER_SECOND;
gtimer_set_load_value(timerStep);
gtimer_set_control(1);
return 0;
}
INIT_BOARD_EXPORT(rt_hw_timer_init);
static void AssertCallback(const char *File, s32 Line)
{
Ft_printf("Assert Error is %s : %d \r\n", File, Line);
}
#ifdef RT_USING_SMP
void rt_hw_ipi_handler_install(int ipi_vector, rt_isr_handler_t ipi_isr_handler);
#endif
/**
* This function will initialize hardware board
*/
void rt_hw_board_init(void)
{
/* bsp debug */
FCpu_SpinLockInit();
Ft_GenericTimer_Init(0, RT_NULL);
Ft_vsprintfRegister((vsprintf_p)rt_vsprintf);
Ft_assertSetCallBack((Ft_assertCallback)AssertCallback);
/* interrupt init */
arm_gic_redist_address_set(0, FT_GICV3_RD_BASEADDRESS + 0, 0);
#if RT_CPUS_NR == 2
Ft_printf("arm_gic_redist_address_set is 2 \r\n");
arm_gic_redist_address_set(0, FT_GICV3_RD_BASEADDRESS + (2U << 16), 1);
#elif RT_CPUS_NR == 3
arm_gic_redist_address_set(0, FT_GICV3_RD_BASEADDRESS + (2U << 16), 1);
arm_gic_redist_address_set(0, FT_GICV3_RD_BASEADDRESS + 2 * (2U << 16), 2);
#elif RT_CPUS_NR == 4
arm_gic_redist_address_set(0, FT_GICV3_RD_BASEADDRESS + (2U << 16), 1);
arm_gic_redist_address_set(0, FT_GICV3_RD_BASEADDRESS + 2 * (2U << 16), 2);
arm_gic_redist_address_set(0, FT_GICV3_RD_BASEADDRESS + 3 * (2U << 16), 3);
#endif
rt_hw_interrupt_init();
rt_components_board_init();
rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
/* 初始化内存池 */
#ifdef RT_USING_HEAP
rt_system_heap_init(HEAP_BEGIN, HEAP_END);
#endif
#ifdef RT_USING_SMP
/* install IPI handle */
rt_hw_interrupt_set_priority(RT_SCHEDULE_IPI, 16);
rt_hw_ipi_handler_install(RT_SCHEDULE_IPI, rt_scheduler_ipi_handler);
rt_hw_interrupt_umask(RT_SCHEDULE_IPI);
#endif
}
static void ft_reset(void)
{
FPsci_Reset();
}
MSH_CMD_EXPORT_ALIAS(ft_reset, ft_reset, ft_reset);
/*@}*/

View File

@@ -0,0 +1,29 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2013-07-06 Bernard the first version
*/
#ifndef __BOARD_H__
#define __BOARD_H__
#include "ft_parameters.h"
#include "ft2004.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 *)(0x80000000 + 1024 * 1024 * 1024)
void rt_hw_board_init(void);
#endif

View File

@@ -0,0 +1,270 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-05-11 Carl the first version
*/
#include "drv_can.h"
#include "interrupt.h"
#include <string.h>
#ifdef BSP_USE_CAN
#define LOG_TAG "drv_can"
#include <drv_log.h>
#define _CAN0_NAME "can0"
#define _CAN1_NAME "can1"
#define RTHW_CAN_WAIT(_can) rt_sem_take(&_can->recv_semaphore, RT_WAITING_FOREVER);
#define RTHW_CAN_SEND(_can) rt_sem_release(&_can->recv_semaphore);
#ifdef BSP_USING_CAN0
struct ft2004_can drv_can0 =
{
.name = _CAN0_NAME,
.can_handle.Config.InstanceId = 0};
#endif
#ifdef BSP_USING_CAN1
struct ft2004_can drv_can1 =
{
.name = _CAN1_NAME,
.can_handle.Config.InstanceId = 1};
#endif
static void _can_recv_irq(void *args)
{
struct ft2004_can *drv_can = (struct ft2004_can *)args;
RTHW_CAN_SEND(drv_can);
}
static void rt_hw_inner_can_isr(int irqno, void *param)
{
FCan_IntrHandler(param);
}
static rt_err_t _can_config(struct rt_can_device *can, struct can_configure *cfg)
{
struct FCan_Bittiming bit_timing = {0};
struct ft2004_can *drv_can;
RT_ASSERT(can);
RT_ASSERT(cfg);
drv_can = (struct ft2004_can *)can->parent.user_data;
RT_ASSERT(drv_can);
FCan_CfgInitialize(&drv_can->can_handle, FCan_LookupConfig(drv_can->can_handle.Config.InstanceId));
FCan_SetHandler(&drv_can->can_handle, FCAN_HANDLER_RECV, _can_recv_irq, drv_can);
bit_timing.bitrate = cfg->baud_rate;
if (FCan_CalcBittiming(&bit_timing) != FCAN_SUCCESS)
{
LOG_E("Setting baud rate %x is not valid \r\n", bit_timing.bitrate);
return -RT_ERROR;
}
FCan_SetTiming(&drv_can->can_handle, &bit_timing);
rt_hw_interrupt_set_priority(drv_can->can_handle.Config.IrqNum, 16);
rt_hw_interrupt_install(drv_can->can_handle.Config.IrqNum, rt_hw_inner_can_isr, &drv_can->can_handle, drv_can->name);
rt_hw_interrupt_umask(drv_can->can_handle.Config.IrqNum);
FCan_Enable(&drv_can->can_handle);
return RT_EOK;
}
static rt_err_t _can_control(struct rt_can_device *can, int cmd, void *arg)
{
return RT_EOK;
}
static int _can_sendmsg(struct rt_can_device *can, const void *buf, rt_uint32_t box_num)
{
struct ft2004_can *drv_can;
struct rt_can_msg *pmsg = (struct rt_can_msg *)buf;
struct FCan_Frame can_frame = {0};
RT_ASSERT(can);
drv_can = (struct ft2004_can *)can->parent.user_data;
RT_ASSERT(drv_can);
/* Check the parameters */
RT_ASSERT(pmsg->len <= 8U);
if (RT_CAN_STDID == pmsg->ide)
{
can_frame.CanId = pmsg->id;
}
else
{
can_frame.CanId = pmsg->id;
can_frame.CanId |= CAN_EFF_FLAG;
}
if (RT_CAN_DTR == pmsg->rtr)
{
}
else
{
can_frame.CanId |= CAN_RTR_FLAG;
}
can_frame.CanDlc = pmsg->len & 0x0FU;
memcpy(can_frame.data, pmsg->data, 8);
return (FCan_SendByIrq(&drv_can->can_handle, &can_frame, 1, RT_NULL) == 1) ? RT_EOK : -RT_ERROR;
}
static int _can_recvmsg(struct rt_can_device *can, void *buf, rt_uint32_t fifo)
{
struct ft2004_can *drv_can;
struct rt_can_msg *pmsg = (struct rt_can_msg *)buf;
RT_ASSERT(can);
struct FCan_Frame recv_frame = {0};
drv_can = (struct ft2004_can *)can->parent.user_data;
RT_ASSERT(drv_can);
RTHW_CAN_WAIT(drv_can);
if (FCan_RecvByIrq(&drv_can->can_handle, &recv_frame, 1) == 0)
{
LOG_E("rx msg is error");
return -RT_ERROR;
}
if (CAN_EFF_FLAG & recv_frame.CanId)
{
pmsg->ide = RT_CAN_EXTID;
pmsg->id = (recv_frame.CanId & ~(RT_CAN_EXTID));
}
else
{
pmsg->ide = RT_CAN_STDID;
pmsg->id = recv_frame.CanId;
}
if (CAN_RTR_FLAG & recv_frame.CanId)
{
pmsg->id &= ~CAN_RTR_FLAG;
pmsg->rtr = RT_CAN_RTR;
}
else
{
pmsg->rtr = RT_CAN_DTR;
}
/* get len */
pmsg->len = recv_frame.CanDlc;
return RT_EOK;
}
static const struct rt_can_ops _can_ops =
{
_can_config,
_can_control,
_can_sendmsg,
_can_recvmsg,
};
int rt_hw_can_init(void)
{
#ifdef BSP_USING_CAN0
drv_can0.can_handle.Config.InstanceId = 0;
rt_sem_init(&drv_can0.recv_semaphore, "can0_recv", 0, RT_IPC_FLAG_FIFO);
drv_can0.device.config.ticks = 20000;
drv_can0.device.config.baud_rate = 1000000;
rt_hw_can_register(&drv_can0.device,
drv_can0.name,
&_can_ops,
&drv_can0);
#endif
#ifdef BSP_USING_CAN1
drv_can1.can_handle.Config.InstanceId = 1;
drv_can0.device.config.baud_rate = 1000000;
rt_sem_init(&drv_can1.recv_semaphore, "can1_recv", 0, RT_IPC_FLAG_FIFO);
rt_hw_can_register(&drv_can1.device,
drv_can1.name,
&_can_ops,
&drv_can1);
#endif
return 0;
}
INIT_BOARD_EXPORT(rt_hw_can_init);
#ifdef BSP_USING_CAN0_DEBUG
struct can_test_struct
{
const char *name;
struct rt_can_filter_config *filter;
rt_device_t candev;
struct rt_semaphore _sem;
};
static struct can_test_struct can0_test_obj = {
.name = _CAN0_NAME};
void can_recv_irq(void *param)
{
struct can_test_struct *_can_obj = (struct can_test_struct *)param;
rt_kprintf("can_recv_iqr \r\n");
rt_sem_release(&_can_obj->_sem);
}
static void rt_can_test_loopback_thread_entry(void *param)
{
struct can_test_struct *_can_obj = (struct can_test_struct *)param;
struct FCan_Frame recv_frame;
struct ft2004_can *drv_can;
rt_uint32_t i;
_can_obj->candev = rt_device_find(_can_obj->name);
RT_ASSERT(_can_obj->candev);
drv_can = (struct ft2004_can *)_can_obj->candev->user_data;
rt_sem_init(&_can_obj->_sem, "canrx_wait", 0, RT_IPC_FLAG_FIFO);
rt_device_open(_can_obj->candev, RT_DEVICE_OFLAG_RDWR);
while (1)
{
rt_kprintf(" start to wait loopback \r\n");
RTHW_CAN_WAIT(drv_can);
while (0 != FCan_RecvByIrq(&drv_can->can_handle, &recv_frame, 1))
{
rt_kprintf("CanId %x \r\n", recv_frame.CanId);
rt_kprintf("CanDlc %x \r\n", recv_frame.CanDlc);
for (i = 0; i < recv_frame.CanDlc; i++)
{
rt_kprintf("data [%d] %x \r\n", i, recv_frame.data[i]);
}
FCan_SendByIrq(&drv_can->can_handle, &recv_frame, 1, RT_NULL);
}
}
}
int rt_can0_test(void)
{
rt_thread_t tid;
tid = rt_thread_create("can0_loopback",
rt_can_test_loopback_thread_entry, &can0_test_obj,
1024, 16, 20);
if (tid != RT_NULL)
rt_thread_startup(tid);
return 0;
}
INIT_APP_EXPORT(rt_can0_test);
#endif
#endif

View File

@@ -0,0 +1,38 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-05-11 Carl the first version
*/
#ifndef __DRV_CAN_H__
#define __DRV_CAN_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include <board.h>
#include <rtdevice.h>
#include <rtthread.h>
#include "ft_can.h"
struct ft2004_can
{
const char *name;
FCan_t can_handle;
struct rt_semaphore recv_semaphore;
struct rt_can_device device; /* inherit from can device */
};
int rt_hw_can_init(void);
#ifdef __cplusplus
}
#endif
#endif // !

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,25 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-03-09 Carl the first version
*/
#ifndef __DRV_ETH_H__
#define __DRV_ETH_H__
#ifdef __cplusplus
extern "C"
{
#endif
#define FT_NETIF_LINKUP 0x1U
#define FT_NETIF_DOWN 0x2U
#ifdef __cplusplus
}
#endif
#endif // !

View File

@@ -0,0 +1,27 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-11-15 SummerGift first version
*/
/*
* NOTE: DO NOT include this file on the header file.
*/
#ifndef LOG_TAG
#define DBG_TAG "drv"
#else
#define DBG_TAG LOG_TAG
#endif /* LOG_TAG */
#ifdef DRV_DEBUG
#define DBG_LVL DBG_LOG
#else
#define DBG_LVL DBG_INFO
#endif /* DRV_DEBUG */
#include <rtdbg.h>

View File

@@ -0,0 +1,424 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-04-11 Carl the first version
*/
#include "drv_qspi.h"
#include <rtthread.h>
#include "rtdevice.h"
#include "ft_qspi.h"
#include "ft_parameters.h"
#ifdef BSP_USE_QSPI
#define DRV_DEBUG
#define LOG_TAG "drv.qspi"
#include <drv_log.h>
struct ft2004_qspi_bus
{
FQSpi_t fqspi;
char *name;
rt_uint32_t init; /* 1 is init already */
};
static struct rt_spi_bus _qspi_bus;
static struct ft2004_qspi_bus _ft2004_qspi_bus;
static int ft2004_qspi_init(struct rt_qspi_device *device, struct rt_qspi_configuration *qspi_cfg)
{
RT_ASSERT(device != RT_NULL);
RT_ASSERT(qspi_cfg != RT_NULL);
// struct rt_spi_configuration *cfg = &qspi_cfg->parent;
struct ft2004_qspi_bus *qspi_bus_p = device->parent.bus->parent.user_data;
if (qspi_bus_p->init == 0)
{
qspi_bus_p->init = 1;
FQSpi_CfgInitialize(&qspi_bus_p->fqspi, FQSpi_LookupConfig(0));
}
return RT_EOK;
}
static rt_err_t ft2004_cmdOperation(struct ft2004_qspi_bus *qspi_bus_p, struct rt_spi_message *message)
{
struct rt_qspi_message *qspi_message = (struct rt_qspi_message *)message;
const rt_uint8_t *sndb = message->send_buf;
rt_uint8_t *rcvb = message->recv_buf;
ft_error_t ret;
RT_ASSERT(qspi_bus_p != RT_NULL);
RT_ASSERT(message != RT_NULL);
struct FQSpi_CmdPack cmd_pack = {0};
if (qspi_message->instruction.qspi_lines == 0)
{
LOG_E("instruction is not valid");
return RT_ERROR;
}
cmd_pack.cmd = qspi_message->instruction.content;
if (qspi_message->address.qspi_lines != 0)
{
cmd_pack.flags |= FQSPI_CMD_NEED_ADDR_MASK;
cmd_pack.addr = qspi_message->address.content;
}
if (qspi_message->address.size == 24)
{
cmd_pack.flags |= FQSPI_CMD_ADDRESS_3BYTE_MASK;
}
else if (qspi_message->address.size == 32)
{
cmd_pack.flags |= FQSPI_CMD_ADDRESS_4BYTE_MASK;
}
if (qspi_message->qspi_data_lines != 0)
{
if (sndb && (message->length > 0))
{
cmd_pack.flags |= FQSPI_CMD_NEED_SET_MASK;
cmd_pack.txBuf = sndb;
cmd_pack.length = message->length;
}
else if (rcvb && (message->length > 0))
{
cmd_pack.flags |= FQSPI_CMD_NEED_GET_MASK;
cmd_pack.rxBuf = rcvb;
cmd_pack.length = message->length;
}
else
{
cmd_pack.flags &= ~(FQSPI_CMD_NEED_GET_MASK | FQSPI_CMD_NEED_SET_MASK);
}
}
if (qspi_message->dummy_cycles)
{
cmd_pack.flags |= FQSPI_CMD_NEED_DUMMY_MASK;
cmd_pack.dummyCycle = qspi_message->dummy_cycles;
}
if (cmd_pack.cmd == 0x20)
{
if (qspi_message->address.size == 32)
{
cmd_pack.cmd = 0xdc;
}
}
#ifdef BSP_QSPI_DEBUG
LOG_I("flags %x", cmd_pack.flags);
#endif
ret = FQSpi_CmdOperation(&qspi_bus_p->fqspi, &cmd_pack);
#ifdef BSP_QSPI_DEBUG
if (ret == FQSPI_SUCCESS)
if (cmd_pack.cmd == 5)
{
LOG_I("cmd05 0x%x", cmd_pack.rxBuf[0]);
}
#endif
return (ret == FQSPI_SUCCESS) ? RT_EOK : RT_ERROR;
}
static rt_uint32_t ft2004_qspi_xfer(struct ft2004_qspi_bus *qspi_bus_p, struct rt_spi_message *message)
{
struct rt_qspi_message *qspi_message = (struct rt_qspi_message *)message;
rt_uint32_t ret_length = 0;
const rt_uint8_t *sndb = message->send_buf;
rt_uint8_t *rcvb = message->recv_buf;
rt_int32_t length = message->length;
rt_uint32_t cmd;
rt_uint32_t addr;
FQSpi_t *qspi_p;
FQSpi_Config_t *qspi_config_p;
struct FQSpi_DataPack data_pack = {0};
qspi_p = &qspi_bus_p->fqspi;
qspi_config_p = &qspi_bus_p->fqspi.config;
cmd = qspi_message->instruction.content;
addr = qspi_message->address.content;
#ifdef BSP_QSPI_DEBUG
LOG_I("cmd is %x ", cmd);
LOG_I("length %d , rcvb %x sndb %x addr %x dummy_cycles %x ", length, rcvb, sndb, addr, qspi_message->dummy_cycles);
#endif
if (qspi_config_p->channel >= FT_QSPI_MAX_CS_NUM)
{
LOG_E("invalid channel[%x] ", qspi_config_p->channel);
return RT_ERROR;
}
switch (cmd)
{
case FQSPI_FLASH_CMD_PP:
{
if (RT_NULL != sndb)
{
data_pack.cmd = cmd;
data_pack.addr = addr;
if (qspi_message->address.size == 24)
{
data_pack.flags |= FQSPI_DATA_ADDRESS_3BYTE_MASK;
}
else
{
data_pack.flags |= FQSPI_DATA_ADDRESS_4BYTE_MASK;
}
LOG_E("write flags %x ", data_pack.flags);
data_pack.txBuf = sndb;
data_pack.length = length;
ret_length = ((FQSpi_Write(qspi_p, &data_pack) == FQSPI_SUCCESS) ? length : 0);
}
else
{
LOG_E("pp cmd %x sndb is null", cmd);
ret_length = 0;
}
}
break;
case FQSPI_FLASH_CMD_WRDI: /* for sufd qspi fast read */
FQSpi_FlashRegSet(qspi_p, cmd, RT_NULL, 0);
case FQSPI_FLASH_CMD_READ:
{
if (RT_NULL != rcvb)
{
data_pack.cmd = FQSPI_FLASH_CMD_READ;
data_pack.addr = addr;
if (qspi_message->address.size == 24)
{
data_pack.flags |= FQSPI_DATA_ADDRESS_3BYTE_MASK;
}
else
{
data_pack.flags |= FQSPI_DATA_ADDRESS_4BYTE_MASK;
}
if (qspi_message->dummy_cycles)
{
data_pack.flags |= FQSPI_DATA_NEED_DUMMY_MASK;
data_pack.dummyCycle = qspi_message->dummy_cycles;
}
data_pack.rxBuf = rcvb;
data_pack.length = length;
ret_length = ((FQSpi_Read(qspi_p, &data_pack) == FQSPI_SUCCESS) ? length : 0);
}
else
{
// LOG_E("read cmd %x rcvb is null", cmd);
ret_length = 0;
}
}
break;
default:
{
if (ft2004_cmdOperation(qspi_bus_p, message) == RT_EOK)
{
ret_length = 1;
}
else
{
LOG_E("ft2004_cmdOperation error");
ret_length = 0;
}
}
}
return ret_length;
}
static rt_uint32_t qspixfer(struct rt_spi_device *device, struct rt_spi_message *message)
{
RT_ASSERT(device != RT_NULL);
RT_ASSERT(device->bus != RT_NULL);
struct ft2004_qspi_bus *qspi_bus_p = device->bus->parent.user_data;
return ft2004_qspi_xfer(qspi_bus_p, message);
}
static rt_err_t qspi_configure(struct rt_spi_device *device, struct rt_spi_configuration *configuration)
{
RT_ASSERT(device != RT_NULL);
RT_ASSERT(configuration != RT_NULL);
struct rt_qspi_device *qspi_device = (struct rt_qspi_device *)device;
return ft2004_qspi_init(qspi_device, &qspi_device->config);
}
static const struct rt_spi_ops ft2004_qspi_ops =
{
.configure = qspi_configure,
.xfer = qspixfer,
};
static int ft2004_qspi_register_bus(struct ft2004_qspi_bus *qspi_bus, const char *name)
{
RT_ASSERT(qspi_bus != RT_NULL);
RT_ASSERT(name != RT_NULL);
_qspi_bus.parent.user_data = qspi_bus;
return rt_qspi_bus_register(&_qspi_bus, name, &ft2004_qspi_ops);
}
rt_err_t ft2004_qspi_bus_attach_device(const char *bus_name, const char *device_name, rt_uint8_t data_line_width, void (*enter_qspi_mode)(), void (*exit_qspi_mode)())
{
struct rt_qspi_device *qspi_device = RT_NULL;
rt_err_t result = RT_EOK;
RT_ASSERT(bus_name != RT_NULL);
RT_ASSERT(device_name != RT_NULL);
RT_ASSERT(data_line_width == 1 || data_line_width == 2 || data_line_width == 4);
qspi_device = (struct rt_qspi_device *)rt_malloc(sizeof(struct rt_qspi_device));
if (qspi_device == RT_NULL)
{
LOG_E("no memory, qspi bus attach device failed!");
result = RT_ENOMEM;
goto __exit;
}
qspi_device->enter_qspi_mode = enter_qspi_mode;
qspi_device->exit_qspi_mode = exit_qspi_mode;
qspi_device->config.qspi_dl_width = data_line_width;
result = rt_spi_bus_attach_device(&qspi_device->parent, device_name, bus_name, RT_NULL);
__exit:
if (result != RT_EOK)
{
if (qspi_device)
{
rt_free(qspi_device);
}
}
return result;
}
static int rt_hw_qspi_bus_init(void)
{
return ft2004_qspi_register_bus(&_ft2004_qspi_bus, FT2004_QSPI_NAME);
}
INIT_BOARD_EXPORT(rt_hw_qspi_bus_init);
#ifdef BSP_QSPI_DEBUG
static void cmd05_check(void)
{
struct FQSpi_CmdPack cmd_pack = {0};
u8 rx_buffer[1];
cmd_pack.cmd = 0x6;
FQSpi_CmdOperation(&_ft2004_qspi_bus.fqspi, &cmd_pack);
rt_memset(&cmd_pack, 0, sizeof(&cmd_pack));
cmd_pack.cmd = 0x5;
cmd_pack.flags = FQSPI_CMD_NEED_GET_MASK;
cmd_pack.rxBuf = rx_buffer;
cmd_pack.length = sizeof(rx_buffer);
FQSpi_CmdOperation(&_ft2004_qspi_bus.fqspi, &cmd_pack);
for (u32 i = 0; i < cmd_pack.length; i++)
{
LOG_I("cnt %d, 0x%x ", i, rx_buffer[i]);
}
rt_memset(&cmd_pack, 0, sizeof(&cmd_pack));
cmd_pack.cmd = 0x4;
FQSpi_CmdOperation(&_ft2004_qspi_bus.fqspi, &cmd_pack);
rt_memset(&cmd_pack, 0, sizeof(&cmd_pack));
cmd_pack.cmd = 0x5;
cmd_pack.flags = FQSPI_CMD_NEED_GET_MASK;
cmd_pack.rxBuf = rx_buffer;
cmd_pack.length = sizeof(rx_buffer);
FQSpi_CmdOperation(&_ft2004_qspi_bus.fqspi, &cmd_pack);
for (u32 i = 0; i < cmd_pack.length; i++)
{
LOG_I("cnt %d, 0x%x ", i, rx_buffer[i]);
}
}
MSH_CMD_EXPORT_ALIAS(cmd05_check, cmd05_check, cmd05_check);
#endif
#ifdef BSP_QSPI_DEBUG
static void cmd35_check(void)
{
struct FQSpi_CmdPack cmd_pack = {0};
u8 rx_buffer[1];
cmd_pack.cmd = 0x6;
FQSpi_CmdOperation(&_ft2004_qspi_bus.fqspi, &cmd_pack);
rt_memset(&cmd_pack, 0, sizeof(&cmd_pack));
cmd_pack.cmd = 0x5;
cmd_pack.flags = FQSPI_CMD_NEED_GET_MASK;
cmd_pack.rxBuf = rx_buffer;
cmd_pack.length = sizeof(rx_buffer);
FQSpi_CmdOperation(&_ft2004_qspi_bus.fqspi, &cmd_pack);
for (u32 i = 0; i < cmd_pack.length; i++)
{
LOG_I("cnt %d, 0x%x ", i, rx_buffer[i]);
}
cmd_pack.cmd = 0xB7;
FQSpi_CmdOperation(&_ft2004_qspi_bus.fqspi, &cmd_pack);
rt_memset(&cmd_pack, 0, sizeof(&cmd_pack));
cmd_pack.cmd = 0x35;
cmd_pack.flags = FQSPI_CMD_NEED_GET_MASK;
cmd_pack.rxBuf = rx_buffer;
cmd_pack.length = sizeof(rx_buffer);
FQSpi_CmdOperation(&_ft2004_qspi_bus.fqspi, &cmd_pack);
for (u32 i = 0; i < cmd_pack.length; i++)
{
LOG_I("cnt %d, 0x%x ", i, rx_buffer[i]);
}
}
MSH_CMD_EXPORT_ALIAS(cmd35_check, cmd35_check, cmd35_check);
#endif
#ifdef BSP_QSPI_DEBUG
static void cmd15_check(void)
{
struct FQSpi_CmdPack cmd_pack = {0};
u8 rx_buffer[1];
// cmd_pack.cmd = 0xB7;
// FQSpi_CmdOperation(&_ft2004_qspi_bus.fqspi, &cmd_pack);
rt_memset(&cmd_pack, 0, sizeof(&cmd_pack));
cmd_pack.cmd = 0x15;
cmd_pack.flags = FQSPI_CMD_NEED_GET_MASK;
cmd_pack.rxBuf = rx_buffer;
cmd_pack.length = sizeof(rx_buffer);
FQSpi_CmdOperation(&_ft2004_qspi_bus.fqspi, &cmd_pack);
for (u32 i = 0; i < cmd_pack.length; i++)
{
LOG_I("cnt %d, 0x%x ", i, rx_buffer[i]);
}
}
MSH_CMD_EXPORT_ALIAS(cmd15_check, cmd15_check, cmd15_check);
#endif
#endif

View File

@@ -0,0 +1,29 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-04-11 Carl the first version
*/
#ifndef __DRT_QSPI_H__
#define __DRT_QSPI_H__
#include <rtthread.h>
#ifdef __cplusplus
extern "C"
{
#endif
#define FT2004_QSPI_NAME "qspi"
rt_err_t ft2004_qspi_bus_attach_device(const char *bus_name, const char *device_name, rt_uint8_t data_line_width, void (*enter_qspi_mode)(), void (*exit_qspi_mode)());
#ifdef __cplusplus
}
#endif
#endif // !DRT_QSPI_H

View File

@@ -0,0 +1,39 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-04-08 Carl the first version
*/
#include <board.h>
#include <drv_qspi.h>
#include <rtdevice.h>
#include <rthw.h>
#include <finsh.h>
#ifdef BSP_USE_QSPI
#include "spi_flash.h"
#include "spi_flash_sfud.h"
#define _QSPI_DEVICE_NAME "qspiflash"
static int
rt_hw_qspi_flash_with_sfud_init(void)
{
ft2004_qspi_bus_attach_device(FT2004_QSPI_NAME, _QSPI_DEVICE_NAME, 1, RT_NULL, RT_NULL);
/* init gd */
rt_kprintf("start rt_sfud_flash_probe \r\n");
if (RT_NULL == rt_sfud_flash_probe("GD25LQ256D", _QSPI_DEVICE_NAME))
{
return -RT_ERROR;
}
return RT_EOK;
}
INIT_COMPONENT_EXPORT(rt_hw_qspi_flash_with_sfud_init);
#endif /* BSP_USING_QSPI_FLASH */

View File

@@ -0,0 +1,154 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-03-18 Carl the first version
*/
#include <rtthread.h>
#ifdef BSP_USING_SDC
#include <dfs_elm.h>
#include <dfs_fs.h>
#include <dfs_posix.h>
#include "drv_sdctrl.h"
#define DBG_TAG "app.card"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>
static rt_err_t _sdcard_mount(void)
{
rt_device_t device;
device = rt_device_find("sd0");
rt_kprintf("rt_device_find %x \r\n", device);
if (device == NULL)
{
mmcsd_wait_cd_changed(0);
ft2004_mmcsd_change();
if (mmcsd_wait_cd_changed(rt_tick_from_millisecond(5000)) == -RT_ETIMEOUT)
{
rt_kprintf("timeout \r\n");
return RT_ERROR;
}
device = rt_device_find("sd0");
}
rt_thread_mdelay(1000);
LOG_I("dfs_mount \r\n");
if (device != RT_NULL)
{
if (dfs_mount("sd0", "/", "elm", 0, 0) == RT_EOK)
{
LOG_I("sd card mount to '/'");
}
else
{
LOG_W("sd card mount to '/' failed!");
return RT_ERROR;
}
}
return RT_EOK;
}
static void _sdcard_unmount(void)
{
rt_thread_mdelay(200);
dfs_unmount("/");
LOG_I("Unmount \"/\"");
mmcsd_wait_cd_changed(0);
ft2004_mmcsd_change();
mmcsd_wait_cd_changed(rt_tick_from_millisecond(5000));
LOG_I("Unmount is over \r\n");
}
static void sd_mount(void *parameter)
{
rt_uint8_t state = 0; /* 1. is valid card ,0 is removal */
#ifdef BSP_SDC_IRQ_CARD_REMOVE
rt_uint32_t status;
#endif
while (1)
{
switch (state)
{
case 0:
if (ft2004_card_status() == 1)
{
#ifdef BSP_SDC_IRQ_CARD_REMOVE
ft2004_card_remove_check(0, RT_NULL); /* Clear removal flag bit */
#endif
if (_sdcard_mount() == RT_EOK)
{
state = 1;
}
else
{
/* For the critical case of frequent plug */
rt_kprintf("dfs_unmount \r\n");
_sdcard_unmount();
ft2004_sdctrl_reset();
}
}
else
{
rt_thread_mdelay(100);
}
break;
case 1:
#ifdef BSP_SDC_IRQ_CARD_REMOVE
if (ft2004_card_remove_check(RT_WAITING_FOREVER, &status) == RT_EOK)
{
if (status & SDCTR_CARD_REMOVE_FLG)
{
state = 0;
_sdcard_unmount();
}
}
#else
if (ft2004_card_status() == 0)
{
state = 0;
_sdcard_unmount();
}
#endif
else
{
rt_thread_mdelay(100);
}
break;
default:
state = 0;
break;
}
}
}
int ft2004_sdcard_mount(void)
{
rt_thread_t tid;
tid = rt_thread_create("sd_mount", sd_mount, RT_NULL,
8192, 2, 20);
if (tid != RT_NULL)
{
rt_thread_startup(tid);
}
else
{
LOG_E("create sd_mount thread err!");
}
return RT_EOK;
}
INIT_APP_EXPORT(ft2004_sdcard_mount);
#endif /* BSP_USING_SDCARD */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,47 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-03-18 Carl the first version
*/
#ifndef __DRV_SDCTRL_H__
#define __DRV_SDCTRL_H__
#include <rtthread.h>
#ifdef __cplusplus
extern "C"
{
#endif
#define SDCTR_CMD_IS_COMPLETE_FLG 0x1UL /* Command is complete */
#define SDCTR_WRITE_IS_COMPLETE_FLG 0x2UL
#define SDCTR_READ_IS_COMPLETE_FLG 0x4UL
#define SDCTR_CMD_IS_ERROR_FLG 0x8UL
#define SDCTR_CMD_CRC_IS_ERROR_FLG 0x10UL /* Command CRC error */
#define SDCTR_DMA_IS_ERROR_FLG 0x20UL /* */
#define SDCTR_CARD_REMOVE_FLG 0x40UL /* Card remove */
#define SDCTR_CMD_TIMEOUT_FLG 0x70UL /* command timeout */
#define SDCTR_CMD_RECEIVE_IS_ERROR_FLG 0x80UL /* CMD receive is error */
#ifndef SDCTR_BUFF_SIZE
#define SDCTR_BUFF_SIZE (512 * 128)
#endif
#ifndef SDCTR_ALIGN_LEN
#define SDCTR_ALIGN_LEN (32)
#endif
void ft2004_mmcsd_change(void);
rt_bool_t ft2004_card_status(void);
rt_err_t ft2004_card_remove_check(rt_int32_t timeout, rt_uint32_t *status);
void ft2004_sdctrl_reset(void);
#ifdef __cplusplus
}
#endif
#endif // !

View File

@@ -0,0 +1,449 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
 *
* @Date: 2021-04-25 14:01:29
* @LastEditTime: 2021-05-26 15:42:52
* @Description:  This files is for
*
* @Modify History:
* Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
*/
#include "drv_spi.h"
#include <rtthread.h>
#include <rtdevice.h>
#include <string.h>
#include "ft_spi.h"
#include "ft_mux.h"
#include "ft_trace.h"
#include "ft_generic_timer.h"
#ifdef BSP_USE_SPI
#define DRV_DEBUG
#define LOG_TAG "drv.spi"
#include <drv_log.h>
typedef void (*spi_cs_handler_t)(const rt_bool_t select);
typedef struct
{
FSpi_Ctrl_t spi_ctrl;
struct rt_spi_bus spi_bus;
uint16_t spi_cs_pin;
spi_cs_handler_t spi_cs_handler;
} ft2004_spi_class;
void ft2004_spi_cs(const rt_bool_t select);
static ft2004_spi_class spi_obj = {
.spi_cs_handler = ft2004_spi_cs,
.spi_ctrl = {
.CtrlId = SPI_CTRL_ID_0,
.DevId = SPI_DEV_ID_0,
.IsReady = FALSE,
.CsPin = 5, /* use pin 5 in gpio group a as cs signal pin */
},
};
static const FSpi_Conf_t spi_conf[NUM_OF_SPI_CTRL] =
{
{
.DevAddr = {0x00, 0x00, 0x00, 0x00},
.DevAddrLen = SPI_4_BYTE_ADDR,
.WorkMode = SPI_CTRL_MASTER_MODE,
/* mode 2 CPOL = 1, CPHA = 0 */
.Cpol = SPI_CTRL_CPOL_HIGH,
.Cpha = SPI_CTRL_CPHA_1EDGE,
.BaudRDiv = SPI_SCKDV_4,
},
{
.DevAddr = {0x00, 0x00, 0x00, 0x00},
.DevAddrLen = SPI_4_BYTE_ADDR,
.WorkMode = SPI_CTRL_MASTER_MODE,
.Cpol = SPI_CTRL_CPOL_HIGH,
.Cpha = SPI_CTRL_CPHA_1EDGE,
.BaudRDiv = SPI_SCKDV_MAX,
}};
inline static ft2004_spi_class *ft2004_spi_get_class()
{
return &spi_obj;
}
inline static FSpi_Ctrl_t *ft2004_spi_get_ctrl()
{
return &(ft2004_spi_get_class()->spi_ctrl);
}
static const FSpi_Conf_t *ft2004_lookup_conf(FT_IN FSpi_CtrlId_t CtrlId)
{
return &spi_conf[CtrlId];
}
void ft2004_spi_cs(const rt_bool_t select)
{
FSpi_Ctrl_t *ctrl_p = ft2004_spi_get_ctrl();
FSpi_SelectSlave(ctrl_p, ctrl_p->DevId, (bool_t)select);
}
/**spi flash operations***/
u32 ft2004_spi_transcation(const u8 tx_data, u8 *rx_data_p)
{
FSpi_Ctrl_t *ctrl_p = ft2004_spi_get_ctrl();
u32 ret = ERR_SPI_OK;
ret = FSpi_ReadWriteByte(ctrl_p, tx_data, rx_data_p);
return ret;
}
/**spi flash operations***/
static rt_err_t ft2004_spi_init(struct rt_spi_configuration *cfg)
{
FSpi_Ctrl_t *ctrl_p = ft2004_spi_get_ctrl();
FSpi_DevId_t dev_id;
u32 ret = ERR_SPI_OK;
//RT_ASSERT(cfg != RT_NULL);
RT_ASSERT(ctrl_p != RT_NULL);
dev_id = ctrl_p->DevId;
/* get spi flash default config */
ctrl_p->Config = *(ft2004_lookup_conf(dev_id));
/* change config according to inputs, cfg could be RT_NULL */
/* reset ctrl block */
ctrl_p->IsReady = FALSE;
/* set spi pin mux */
Ft_setSpiMux(ctrl_p->CtrlId);
/* init spi ctrl */
ret = FSpi_Init(ctrl_p);
if (ERR_SPI_OK == ret)
{
return RT_EOK;
}
else
{
return -RT_ERROR;
}
}
static rt_uint32_t spi_xfer(struct rt_spi_device *device, struct rt_spi_message *message)
{
rt_size_t message_length, loop;
rt_uint8_t *recv_buf;
const rt_uint8_t *send_buf;
u32 tx_rx_result = ERR_SPI_OK;
spi_cs_handler_t cs_handler = ft2004_spi_get_class()->spi_cs_handler;
RT_ASSERT(device != RT_NULL);
RT_ASSERT(device->bus != RT_NULL);
RT_ASSERT(device->bus->parent.user_data != RT_NULL);
RT_ASSERT(message != RT_NULL);
if (message->cs_take && cs_handler)
{
cs_handler(TRUE);
}
message_length = message->length;
recv_buf = message->recv_buf;
send_buf = message->send_buf;
/* handle msg */
for (loop = 0; loop < message_length; loop++)
{
/* start data exchange */
if ((message->recv_buf) && (message->send_buf))
{
/* need tx and rx */
tx_rx_result |= ft2004_spi_transcation(*send_buf, recv_buf);
send_buf++;
recv_buf++;
}
else if (message->send_buf)
{
/* tx only */
tx_rx_result |= ft2004_spi_transcation(*send_buf, RT_NULL);
send_buf++;
}
else
{
/* rx only */
tx_rx_result |= ft2004_spi_transcation(SPI_DUMMY_TX_DATA, recv_buf);
recv_buf++;
}
}
if (ERR_SPI_OK != tx_rx_result)
{
LOG_E("spi transfer error : 0x%x", tx_rx_result);
message->length = 0;
}
else
{
}
if (message->cs_release && cs_handler)
{
cs_handler(FALSE);
}
return message->length;
}
static rt_err_t spi_configure(struct rt_spi_device *device,
struct rt_spi_configuration *configuration)
{
RT_ASSERT(device != RT_NULL);
RT_ASSERT(configuration != RT_NULL);
return ft2004_spi_init(configuration);
}
static const struct rt_spi_ops ft2004_spi_ops =
{
.configure = spi_configure,
.xfer = spi_xfer,
};
/**
* Attach the spi device to SPI bus, this function must be used after initialization.
*/
rt_err_t rt_hw_spi_device_attach(const char *bus_name, const char *device_name, uint16_t cs_gpio_pin)
{
rt_err_t result;
struct rt_spi_device *spi_device;
ft2004_spi_class *spi_class = ft2004_spi_get_class();
RT_ASSERT(spi_class != RT_NULL);
spi_device = (struct rt_spi_device *)rt_malloc(sizeof(struct rt_spi_device));
RT_ASSERT(spi_device != RT_NULL);
result = rt_spi_bus_attach_device(spi_device, device_name, bus_name, RT_NULL);
LOG_I("attach result 0x%x", result);
if (result != RT_EOK)
{
if (spi_device)
{
rt_free(spi_device);
}
}
return result;
}
static int rt_hw_spi_bus_init(void)
{
rt_err_t result;
ft2004_spi_class *spi_class = ft2004_spi_get_class();
LOG_I("init spi ctrl");
spi_class->spi_bus.parent.user_data = &spi_class->spi_bus;
result = rt_spi_bus_register(&spi_class->spi_bus, SPI_BUS_NAME, &ft2004_spi_ops);
return result;
}
int rt_hw_spi_init(void)
{
return rt_hw_spi_bus_init();
}
INIT_BOARD_EXPORT(rt_hw_spi_init);
static void rthw_spi_delay(u32 delayCnt)
{
Ft_GenericTimer_UsDelay(delayCnt);
}
/************spi flash operatiosn implemented for sample test****************/
/* definition of s25fs maunfactor id */
typedef struct
{
u8 Mid;
u8 MemoryType;
u8 Density;
u8 RemainBytes;
u8 PhySectArch;
u8 FamilyID;
} ft2004_manuid_t;
/* definition of cmd for s25fs */
#define S25FS_ENABLE_WR 0x06
#define S25FS_DISABLE_WR 0x04
#define S25FS_READ_ID 0x9F
#define S25FS_READ_4BYTE_ADD 0x13
#define S25FS_ERASE_4BYTE_ADD 0x21
#define S25FS_READ_STATUS_1 0x05
#define S25FS_READ_FLASH_PARAM 0x5A
static void ft2004_dump_manuid(const ft2004_manuid_t *pId)
{
rt_kprintf("0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\r\n",
pId->Mid, pId->MemoryType, pId->Density, pId->RemainBytes,
pId->PhySectArch, pId->FamilyID);
}
static u32 ft2004_read_in_4byte_addr(const u32 ReadAddr, const u32 BytesToRead, u8 *pBuf)
{
u32 ret = ERR_SPI_OK;
u32 loop;
RT_ASSERT(RT_NULL != pBuf);
ft2004_spi_cs(TRUE);
ret |= ft2004_spi_transcation(S25FS_READ_4BYTE_ADD, RT_NULL);
/* only 4-bytes address, MSB first */
ret |= ft2004_spi_transcation((u8)(ReadAddr >> 24), RT_NULL);
ret |= ft2004_spi_transcation((u8)(ReadAddr >> 16), RT_NULL);
ret |= ft2004_spi_transcation((u8)(ReadAddr >> 8), RT_NULL);
ret |= ft2004_spi_transcation((u8)ReadAddr, RT_NULL);
/* read out data */
for (loop = 0; loop < BytesToRead; loop++)
{
ret |= ft2004_spi_transcation(SPI_DUMMY_TX_DATA, pBuf + loop);
if (ERR_SPI_OK != ret)
{
break;
}
}
ft2004_spi_cs(FALSE);
return ret;
}
u32 ft2004_spi_enable_wr(const bool_t enable)
{
u32 ret = ERR_SPI_OK;
ft2004_spi_cs(TRUE);
if (enable)
{
ret |= ft2004_spi_transcation(S25FS_ENABLE_WR, RT_NULL);
}
else
{
ret |= ft2004_spi_transcation(S25FS_DISABLE_WR, RT_NULL);
}
ft2004_spi_cs(FALSE);
return ret;
}
u32 ft2004_erase_sector_in_4byte_addr(const u32 sector_addr)
{
u32 Ret = ERR_SPI_OK;
ft2004_spi_enable_wr(TRUE);
LOG_I("erase sector 0x%x", Ret);
if (ERR_SPI_OK != Ret)
{
return Ret;
}
ft2004_spi_cs(TRUE);
Ret |= ft2004_spi_transcation(S25FS_ERASE_4BYTE_ADD, RT_NULL);
Ret |= ft2004_spi_transcation((u8)(sector_addr >> 24), RT_NULL);
Ret |= ft2004_spi_transcation((u8)(sector_addr >> 16), RT_NULL);
Ret |= ft2004_spi_transcation((u8)(sector_addr >> 8), RT_NULL);
Ret |= ft2004_spi_transcation((u8)(sector_addr), RT_NULL);
ft2004_spi_cs(FALSE);
return Ret;
}
u32 ft2004_spi_read_params(const u32 Addr)
{
u32 Ret = ERR_SPI_OK;
u8 dat[8] = {0};
u32 loop;
ft2004_spi_cs(TRUE);
Ret |= ft2004_spi_transcation(S25FS_READ_FLASH_PARAM, RT_NULL);
Ret |= ft2004_spi_transcation((u8)(Addr >> 16), RT_NULL);
Ret |= ft2004_spi_transcation((u8)(Addr >> 8), RT_NULL);
Ret |= ft2004_spi_transcation((u8)(Addr), RT_NULL);
for (loop = 0; loop < 8; loop++)
{
Ret |= ft2004_spi_transcation(SPI_DUMMY_TX_DATA, dat + loop);
rt_kprintf("%d: 0x%x", loop, *(dat + loop));
}
ft2004_spi_cs(FALSE);
return Ret;
}
static u32 ft2004_spi_readid_for_test(ft2004_manuid_t *pId)
{
FSpi_Ctrl_t *ctrl_p = ft2004_spi_get_ctrl();
u32 ret = ERR_SPI_OK;
if (!ctrl_p->IsReady)
{
return ERR_SPI_NOT_READY;
}
RT_ASSERT(RT_NULL != pId);
ft2004_spi_cs(TRUE);
/* shifting the command code “90H” followed by a 24-bit address */
ret |= ft2004_spi_transcation(S25FS_READ_ID, RT_NULL);
/* Manufacturer ID and the Device ID are shifted out */
ret |= ft2004_spi_transcation(SPI_DUMMY_TX_DATA, &pId->Mid);
ret |= ft2004_spi_transcation(SPI_DUMMY_TX_DATA, &pId->MemoryType);
ret |= ft2004_spi_transcation(SPI_DUMMY_TX_DATA, &pId->Density);
ret |= ft2004_spi_transcation(SPI_DUMMY_TX_DATA, &pId->RemainBytes);
ret |= ft2004_spi_transcation(SPI_DUMMY_TX_DATA, &pId->PhySectArch);
ret |= ft2004_spi_transcation(SPI_DUMMY_TX_DATA, &pId->FamilyID);
ft2004_spi_cs(FALSE);
if (ERR_SPI_OK == ret)
{
ft2004_dump_manuid(pId);
}
return ret;
}
static void spi_9f_s25fs_sample(int argc, char *argv[])
{
ft2004_manuid_t dev_id;
u32 ret = ERR_SPI_OK;
u32 delay = SPI_TIMEOUT * 10;
rt_kprintf("test s25fs spi flash\r\n");
ret |= ft2004_spi_init(RT_NULL);
ret |= ft2004_spi_readid_for_test(&dev_id);
rt_kprintf("result is: 0x%x \r\n", ret);
while (--delay)
{
rthw_spi_delay(10);
}
}
MSH_CMD_EXPORT(spi_9f_s25fs_sample, "spi s25fs cmd 9fH sample");
static u8 read_buf[256];
static void spi_5a_s25fs_sample(int argc, char *argv[])
{
u32 ret = ERR_SPI_OK;
u32 delay = SPI_TIMEOUT * 10;
u32 read_addr = 0x0000;
rt_kprintf("test s25fs spi flash\r\n");
ret |= ft2004_spi_init(RT_NULL);
ret |= ft2004_spi_read_params(read_addr);
ret |= ft2004_read_in_4byte_addr(read_addr, 256, read_buf);
rt_kprintf("result is: 0x%x \r\n", ret);
while (--delay)
{
rthw_spi_delay(10);
}
}
MSH_CMD_EXPORT(spi_5a_s25fs_sample, "spi s25fs cmd 5aH sample");
#endif

View File

@@ -0,0 +1,29 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
 *
* @Date: 2021-04-25 14:01:39
* @LastEditTime: 2021-04-29 09:40:13
* @Description:  This files is for
*
* @Modify History:
* Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
*/
#ifndef FT_DRIVERS_RTT_SPI_H
#define FT_DRIVERS_RTT_SPI_H
#include <rtthread.h>
#define SPI_BUS_NAME "spi0"
#define SPI_DEV_NAME "S25FS256"
rt_err_t rt_hw_spi_device_attach(const char *bus_name, const char *device_name, uint16_t cs_gpio_pin);
#ifdef __cplusplus
extern "C"
{
#endif
#endif

View File

@@ -0,0 +1,43 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
 *
* @Date: 2021-04-25 14:01:16
* @LastEditTime: 2021-04-30 14:43:12
* @Description:  This files is for
*
* @Modify History:
* Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
*/
#include <board.h>
#include <drv_spi.h>
#include <rtdevice.h>
#include <rthw.h>
#include <finsh.h>
#include "ft_spi.h"
#ifdef BSP_USE_SPI
#include "spi_flash.h"
#include "spi_flash_sfud.h"
static int rt_hw_spi_flash_init(void)
{
uint16_t cs_pin = 5;
rt_hw_spi_device_attach(SPI_BUS_NAME, SPI_DEV_NAME, cs_pin);
rt_kprintf("attach spi flash\r\n");
/* lookup flah */
if (RT_NULL == rt_sfud_flash_probe("S25FS256S", SPI_DEV_NAME))
{
rt_kprintf("attach spi flash failed\r\n");
return -RT_ERROR;
}
return RT_EOK;
}
INIT_COMPONENT_EXPORT(rt_hw_spi_flash_init);
#endif

View File

@@ -0,0 +1,192 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-03-04 Carl the first version
*/
#include "board.h"
#include "drv_usart.h"
#include "interrupt.h"
#include "serial.h"
#include "rtconfig.h"
#ifdef RT_USING_SERIAL
extern u32 FUart_GetInterruptMask(Ft_Uart *uart_ptr);
static void Ft_Os_Uart_Callback(void *Args, u32 Event, u32 EventData);
static void rt_hw_uart_isr(int irqno, void *param)
{
Ft_Uart *uart_ptr = (Ft_Uart *)param;
FUart_InterruptHandler(uart_ptr);
}
static rt_err_t uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
{
struct drv_usart *uart = RT_NULL;
Ft_Uart *uart_ptr = RT_NULL;
u32 RegTemp;
u32 ret;
RT_ASSERT(serial != RT_NULL);
RT_ASSERT(cfg != RT_NULL);
uart = rt_container_of(serial, struct drv_usart, serial);
uart_ptr = uart->handle;
RT_ASSERT(FUart_CfgInitialize(uart_ptr, FUart_LookupConfig(uart_ptr->Config.InstanceId)) == FST_SUCCESS);
FUart_SetHandler(uart_ptr, Ft_Os_Uart_Callback, serial);
rt_hw_interrupt_install(uart_ptr->Config.IsrNum, rt_hw_uart_isr, uart_ptr, "uart");
rt_hw_interrupt_umask(uart_ptr->Config.IsrNum);
//<! 设置波特率
ret = FUart_SetBaudRate(uart_ptr, cfg->baud_rate);
RT_ASSERT(ret == FST_SUCCESS);
//<! 打开接收中断
RegTemp = FUart_GetInterruptMask(uart_ptr);
RegTemp |= UARTMIS_RTMIS;
FUart_SetInterruptMask(uart_ptr, RegTemp);
FUart_SetOptions(uart_ptr, FUART_OPTION_UARTEN | FUART_OPTION_RXEN | FUART_OPTION_TXEN | FUART_OPTION_FIFOEN);
return RT_EOK;
}
static rt_err_t uart_control(struct rt_serial_device *serial, int cmd, void *arg)
{
struct drv_usart *uart = RT_NULL;
Ft_Uart *uart_ptr = RT_NULL;
RT_ASSERT(serial != RT_NULL);
uart = rt_container_of(serial, struct drv_usart, serial);
uart_ptr = uart->handle;
switch (cmd)
{
case RT_DEVICE_CTRL_CLR_INT:
/* disable rx irq */
rt_hw_interrupt_mask(uart_ptr->Config.IsrNum);
break;
case RT_DEVICE_CTRL_SET_INT:
/* enable rx irq */
rt_hw_interrupt_umask(uart_ptr->Config.IsrNum);
break;
}
return RT_EOK;
}
static void Ft_Os_Uart_Callback(void *Args, u32 Event, u32 EventData)
{
struct rt_serial_device *serial = (struct rt_serial_device *)Args;
if (FUART_EVENT_RECV_DATA == Event || FUART_EVENT_RECV_TOUT == Event)
{
rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
}
else if (FUART_EVENT_RECV_ERROR == Event)
{
}
else if (FUART_EVENT_SENT_DATA == Event)
{
}
else if (FUART_EVENT_PARE_FRAME_BRKE == Event)
{
}
else if (FUART_EVENT_RECV_ORERR == Event)
{
}
if (FUART_EVENT_SENT_DATA == Event)
{
}
else
{
}
}
static int uart_putc(struct rt_serial_device *serial, char c)
{
struct drv_usart *uart = RT_NULL;
Ft_Uart *uart_ptr = RT_NULL;
RT_ASSERT(serial != RT_NULL);
uart = rt_container_of(serial, struct drv_usart, serial);
uart_ptr = uart->handle;
FUart_SendByte(uart_ptr->Config.BaseAddress, c);
return 1;
}
static int uart_getc(struct rt_serial_device *serial)
{
int ch;
struct drv_usart *uart = RT_NULL;
Ft_Uart *uart_ptr = RT_NULL;
RT_ASSERT(serial != RT_NULL);
uart = rt_container_of(serial, struct drv_usart, serial);
uart_ptr = uart->handle;
ch = FUart_GetChar(uart_ptr->Config.BaseAddress);
if (ch == 0xff)
ch = -1;
return ch;
}
static const struct rt_uart_ops _uart_ops =
{
uart_configure,
uart_control,
uart_putc,
uart_getc,
};
#ifdef RT_USING_UART0
static Ft_Uart Ft_Uart0;
static struct drv_usart _RtUart0;
#endif
#ifdef RT_USING_UART1
static Ft_Uart Ft_Uart1;
static struct drv_usart _RtUart1;
#endif
int rt_hw_uart_init(void)
{
struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
#ifdef RT_USING_UART0
config.bufsz = RT_SERIAL_RB_BUFSZ;
_RtUart0.serial.ops = &_uart_ops;
_RtUart0.serial.config = config;
Ft_Uart0.Config.InstanceId = FT_UART0_ID;
_RtUart0.Handle = &Ft_Uart0;
rt_hw_serial_register(&_RtUart0.serial, "uart0",
RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
&_RtUart0);
#endif
#ifdef RT_USING_UART1
config.bufsz = RT_SERIAL_RB_BUFSZ;
_RtUart1.serial.ops = &_uart_ops;
_RtUart1.serial.config = config;
Ft_Uart1.Config.InstanceId = FT_UART1_ID;
_RtUart1.handle = &Ft_Uart1;
rt_hw_serial_register(&_RtUart1.serial, "uart1",
RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
&_RtUart1);
#endif
return 0;
}
INIT_BOARD_EXPORT(rt_hw_uart_init);
#endif /* RT_USING_SERIAL */

View File

@@ -0,0 +1,25 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-03-04 Carl the first version
*/
#ifndef __DRV_USART_H__
#define __DRV_USART_H__
#include <rtthread.h>
#include "rtdevice.h"
#include "ft_uart.h"
struct drv_usart
{
Ft_Uart *handle;
struct rt_serial_device serial;
};
#endif // !

View File

@@ -0,0 +1,88 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-04-29 Carl the first version
*
*/
#include <rtthread.h>
#include "ft2004.h"
#include "gicv3.h"
rt_uint64_t get_main_cpu_affval(void)
{
return 0;
}
rt_uint32_t arm_gic_cpumask_to_affval(rt_uint32_t *cpu_mask, rt_uint32_t *cluster_id, rt_uint32_t *target_list)
{
if (*cpu_mask == 0)
{
return 0;
}
*target_list = 0;
*cluster_id = 0;
if (*cpu_mask & 0x3)
{
if ((*cpu_mask & 0x3) == 0x3)
{
*target_list = 3;
}
else if ((*cpu_mask & 0x1))
{
*target_list = 1;
}
else
{
*target_list = 2;
}
*cpu_mask &= ~0x3;
}
else if (*cpu_mask & 0xc)
{
*cluster_id = 0x100;
if ((*cpu_mask & 0xc) == 0xc)
{
*target_list = 3;
}
else if ((*cpu_mask & 0x4))
{
*target_list = 1;
}
else
{
*target_list = 2;
}
*cpu_mask &= ~0xc;
}
else
{
*cpu_mask = 0;
return 0;
}
return 1;
}
#ifdef RT_USING_SMP
void send_core_isg(void)
{
for (size_t i = 0; i <= 0xf; i++)
{
/* code */
rt_kprintf("i %x \r\n", i);
arm_gic_send_affinity_sgi(0, 0, i, 0);
rt_thread_mdelay(100);
}
}
MSH_CMD_EXPORT(send_core_isg, send_core_isg);
#endif

View File

@@ -0,0 +1,25 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-04-29 Carl the first version
*
*/
#ifndef __FT2004_H__
#define __FT2004_H__
#include <rthw.h>
#include <rtthread.h>
#define ARM_GIC_NR_IRQS 160
#define ARM_GIC_MAX_NR 1
#define MAX_HANDLERS 160
#define GIC_IRQ_START 0
rt_uint64_t get_main_cpu_affval(void);
#endif // !

View File

@@ -0,0 +1,44 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-04-29 Carl the first version
*
*/
#include "rtconfig.h"
.globl rt_hw_cpu_id
rt_hw_cpu_id:
mrc p15, 0, r0, c0, c0, 5
ubfx r0, r0, #0, #12
cmp r0, #0
beq core0
cmp r0, #1
beq core1
cmp r0, #256
beq core2
mov r1 ,#257
cmp r0, r1
beq core3
b default
core0:
mov r0, #0
b return
core1:
mov r0, #1
b return
core2:
mov r0, #2
b return
core3:
mov r0, #3
b return
default:
and r0, r0, #15
return:
bx lr

View File

@@ -0,0 +1,86 @@
/*
* @ : Copyright (c) 2020 Phytium Information Technology, Inc.
*
* SPDX-License-Identifier: Apache-2.0.
*
* @Date: 2021-05-26 10:09:45
* @LastEditTime: 2021-05-26 10:31:44
* @Description:  This files is for
*
* @Modify History:
*  Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
*/
#include <rtthread.h>
#include "board.h"
#include <gicv3.h>
#ifdef RT_USING_SMP
#include <interrupt.h>
#include "ft_psci.h"
#include "ft_generic_timer.h"
extern int rt_hw_timer_init(void);
extern void secondary_cpu_start(void);
void rt_hw_secondary_cpu_up(void)
{
rt_uint32_t i;
rt_uint32_t cpu_mask = 0;
rt_kprintf("rt_hw_secondary_cpu_up is processing \r\n");
for (i = 1; i < RT_CPUS_NR; i++)
{
if (i == 1)
{
/* code */
FPsci_CpuOn(1 << i, (rt_uint32_t)secondary_cpu_start);
cpu_mask = 2;
}
else if (i == 2)
{
FPsci_CpuOn(1 << i, (rt_uint32_t)secondary_cpu_start);
cpu_mask = 4;
}
else if (i == 3)
{
FPsci_CpuOn(1 << i, (rt_uint32_t)secondary_cpu_start);
cpu_mask = 8;
}
else
{
continue;
}
__asm__ volatile("dsb" ::
: "memory");
rt_hw_ipi_send(RT_SCHEDULE_IPI, cpu_mask);
Ft_GenericTimer_UsDelay(1000000);
}
}
void secondary_cpu_c_start(void)
{
rt_hw_vector_init();
rt_hw_spin_lock(&_cpus_lock);
arm_gic_cpu_init(0);
arm_gic_redist_init(0);
rt_hw_timer_init();
rt_hw_interrupt_set_priority(RT_SCHEDULE_IPI, 16);
rt_hw_interrupt_umask(RT_SCHEDULE_IPI);
rt_system_scheduler_start();
}
void rt_hw_secondary_cpu_idle_exec(void)
{
asm volatile("wfe" ::
: "memory", "cc");
}
#endif

View File

@@ -0,0 +1,20 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-04-29 Carl the first version
*
*/
#ifndef __UART_H__
#define __UART_H__
#include <board.h>
int rt_hw_uart_init(void);
#endif

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

110
bsp/ft2004/ft_aarch32.lds Normal file
View File

@@ -0,0 +1,110 @@
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
SECTIONS
{
. = 0x80100000;
__text_start = .;
.text :
{
*(.vectors)
*(.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 = .;
} =0
__text_end = .;
__rodata_start = .;
.rodata : { *(.rodata) *(.rodata.*) }
__rodata_end = .;
. = ALIGN(4);
.ctors :
{
PROVIDE(__ctors_start__ = .);
KEEP(*(SORT(.ctors.*)))
KEEP(*(.ctors))
PROVIDE(__ctors_end__ = .);
}
.dtors :
{
PROVIDE(__dtors_start__ = .);
KEEP(*(SORT(.dtors.*)))
KEEP(*(.dtors))
PROVIDE(__dtors_end__ = .);
}
. = ALIGN(16 * 1024);
.l1_page_table :
{
__l1_page_table_start = .;
. += 16K;
}
. = ALIGN(8);
__data_start = .;
.data :
{
*(.data)
*(.data.*)
}
__data_end = .;
. = ALIGN(8);
__bss_start = .;
.bss :
{
*(.bss)
*(.bss.*)
*(COMMON)
. = ALIGN(4);
}
. = ALIGN(4);
__bss_end = .;
.heap :
{
. = ALIGN(8);
__end__ = .;
PROVIDE(end = .);
__HeapBase = .;
. += 0x400;
__HeapLimit = .;
__heap_limit = .; /* Add for _sbrk */
}
/* 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) }
_end = .;
}

4
bsp/ft2004/libraries/.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
*.o
*.elf
*.bin
*.map

View File

@@ -0,0 +1,146 @@
menu "Hardware Drivers Config"
menu "On-chip Peripheral Drivers"
menuconfig BSP_USING_UART
bool "Enable UART"
default y
select RT_USING_SERIAL
if BSP_USING_UART
config RT_USING_UART1
bool "Enable UART1"
default y
config RT_USING_UART0
bool "Enable UART0"
default n
endif
menuconfig BSP_USING_SDC
bool "Enable sd controller"
select RT_USING_SDIO
select RT_USING_DFS
select RT_USING_DFS_ELMFAT
default n
if BSP_USING_SDC
config BSP_SDC_DEBUG_PRINT
bool "Enable sd controller debug print"
default n
config BSP_SDC_USE_IRQ
bool "Use interrupt to handle when cmd complete, dma complete"
default n
if BSP_SDC_USE_IRQ
config BSP_SDC_IRQ_CARD_REMOVE
bool "Use interrupt to determine if the card is pulled out"
default n
endif
endif
menuconfig BSP_USING_GMAC
bool "Enable gmac"
default n
select RT_USING_NETDEV
if BSP_USING_GMAC
config BSP_USING_GMAC0
bool "Enable GMAC0"
default y
config BSP_USING_GMAC1
bool "Enable GMAC1"
default n
config RT_LWIP_ETH_PAD_SIZE
int "set lwip ETH_PAD_SIZE"
range 2 256
default 2
config RAW_DATA_PRINT
bool "Enable mac raw data print"
default n
if RAW_DATA_PRINT
config ETH_RX_DUMP
bool "Enable gmac receive raw data print "
default n
config ETH_TX_DUMP
bool "Enable gmac send raw data print "
default n
endif
endif
# menuconfig BSP_USE_QSPI
# bool "Enable Qspi"
# select RT_USING_SFUD
# select RT_SFUD_USING_QSPI
# default n
# if BSP_USE_QSPI
# config BSP_QSPI_DEBUG
# bool "Enable qspi debug print"
# default n
# endif
menuconfig BSP_USE_SPI
bool "Enable Spi"
select RT_USING_SFUD
select RT_SFUD_USING_SPI
select RT_SFUD_USING_SFDP
select RT_SFUD_USING_FLASH_INFO_TABLE
select BSP_USE_GPIO
default n
if BSP_USE_SPI
config BSP_SPI_DEBUG
bool "Enable spi debug print"
default n
endif
menuconfig BSP_USE_GPIO
bool "Enable Gpio"
default n
if BSP_USE_GPIO
config BSP_GPIO_DEBUG
bool "Enable gpio debug print"
default n
endif
menuconfig BSP_USE_CAN
bool "Enable Can"
select RT_USING_CAN
default n
if BSP_USE_CAN
config BSP_USING_CAN0
bool "Enable can0"
default n
config BSP_USING_CAN1
bool "Enable can1"
default n
if BSP_USING_CAN0
config BSP_USING_CAN0_DEBUG
bool "Enable can0 work in loop back"
default n
endif
endif
endmenu
menu "Board extended module Drivers"
endmenu
endmenu

View File

@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -0,0 +1,129 @@
'''
 : Copyright (c) 2020 Phytium Information Technology, Inc. 
 
SPDX-License-Identifier: Apache-2.0.
Date: 2021-05-24 14:30:13
LastEditTime: 2021-05-26 14:58:34
Description:  This files is for 
Modify History:
 Ver   Who        Date         Changes
----- ------     --------    --------------------------------------
'''
from building import *
import rtconfig
Import('RTT_ROOT')
# get current directory
cwd = GetCurrentDir()
# The set of source files associated with this SConscript file.
src = Split("""
bsp/standlone/ft_assert.c
bsp/standlone/ft_generic_timer.c
bsp/standlone/ft_printf.c
bsp/standlone/ft_trace.c
bsp/standlone/ft_mux.c
bsp/standlone/inbyte.c
bsp/standlone/outbyte.c
bsp/standlone/ft_cache.c
bsp/standlone/ft_cpu.c
bsp/standlone/ft_smc.S
bsp/standlone/ft_psci.c
bsp/standlone/ft_debug.c
""")
if GetDepend(['RT_USING_SERIAL']):
src += ['bsp/ft_uart/ft_uart_g.c']
src += ['bsp/ft_uart/ft_uart_hw.c']
src += ['bsp/ft_uart/ft_uart_intr.c']
src += ['bsp/ft_uart/ft_uart_options.c']
src += ['bsp/ft_uart/ft_uart_selftest.c']
src += ['bsp/ft_uart/ft_uart_sinit.c']
src += ['bsp/ft_uart/ft_uart.c']
if GetDepend(['RT_USING_I2C']):
None
if GetDepend(['RT_USING_USB_HOST']) or GetDepend(['RT_USING_USB_DEVICE']):
None
if GetDepend(['BSP_USE_CAN']):
src += ['bsp/ft_can/ft_can_g.c']
src += ['bsp/ft_can/ft_can_hw.c']
src += ['bsp/ft_can/ft_can_intr.c']
src += ['bsp/ft_can/ft_can_sinit.c']
src += ['bsp/ft_can/ft_can.c']
src += ['bsp/ft_can/ft_can_calc.c']
None
if GetDepend(['RT_USING_HWTIMER']) or GetDepend(['RT_USING_PWM']):
None
if GetDepend(['RT_USING_ADC']):
None
if GetDepend(['RT_USING_RTC']):
None
if GetDepend(['RT_USING_WDT']):
None
if GetDepend(['RT_USING_AUDIO']):
None
if GetDepend(['BSP_USING_ON_CHIP_FLASH']):
None
if GetDepend(['BSP_USING_GMAC']):
src += ['bsp/ft_gmac/ft_gmac_desc.c']
src += ['bsp/ft_gmac/ft_gmac_g.c']
src += ['bsp/ft_gmac/ft_gmac_hw.c']
src += ['bsp/ft_gmac/ft_gmac_intr.c']
src += ['bsp/ft_gmac/ft_gmac_sinit.c']
src += ['bsp/ft_gmac/ft_gmac.c']
if GetDepend(['BSP_USING_SDC']):
src += ['bsp/ft_sd/ft_sdctrl_option.c']
src += ['bsp/ft_sd/ft_sdctrl_sinit.c']
src += ['bsp/ft_sd/ft_sdctrl_intr.c']
src += ['bsp/ft_sd/ft_sdctrl_g.c']
src += ['bsp/ft_sd/ft_sdctrl_hw.c']
src += ['bsp/ft_sd/ft_sdctrl.c']
if GetDepend(['BSP_USE_QSPI']):
src += ['bsp/ft_qspi/qspi_g.c']
src += ['bsp/ft_qspi/qspi_hw.c']
src += ['bsp/ft_qspi/ft_qspi.c']
src += ['bsp/ft_qspi/qspi_sinit.c']
if GetDepend(['BSP_USE_SPI']):
src += ['bsp/ft_spi/ft_spi.c']
src += ['bsp/ft_spi/ft_spi_irq.c']
if GetDepend(['BSP_USE_GPIO']):
src += ['bsp/ft_gpio/ft_gpio.c']
path = [cwd + '/bsp/standlone/',
cwd + '/bsp/ft_gicv3',
cwd + '/bsp/ft_gmac',
cwd + '/bsp/ft_uart',
cwd + '/bsp/ft_sd',
cwd + '/bsp/ft_qspi',
cwd + '/bsp/ft_can',
cwd + '/bsp/ft_spi',
cwd + '/bsp/ft_gpio',
cwd + '/bsp/include',
cwd + '/include',
cwd + '/cpu', ]
CPPDEFINES = ['USE_FT_DRIVER']
group = DefineGroup('FT_DRIVER', src, depend=[
''], CPPPATH=path, CPPDEFINES=CPPDEFINES)
Return('group')

View File

@@ -0,0 +1,299 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
*
* @Date: 2021-04-29 10:21:53
* @LastEditTime: 2021-05-25 16:41:38
* @Description:  Description of file
* @Modify History:
* * * Ver   Who        Date         Changes
* * ----- ------     --------    --------------------------------------
*/
#include "ft_can.h"
#include "ft_can_hw.h"
#include "ft_assert.h"
#include "ft_debug.h"
#include "string.h"
#define FT_CAN_DEBUG_TAG "FT_CAN"
#define FT_CAN_DEBUG_I(format, ...) FT_DEBUG_PRINT_I(FT_CAN_DEBUG_TAG, format, ##__VA_ARGS__)
#define FT_CAN_DEBUG_E(format, ...) FT_DEBUG_PRINT_E(FT_CAN_DEBUG_TAG, format, ##__VA_ARGS__)
#define FT_CAN_DEBUG_W(format, ...) FT_DEBUG_PRINT_W(FT_CAN_DEBUG_TAG, format, ##__VA_ARGS__)
ft_error_t
FCan_CfgInitialize(FCan_t *Can_p, FCan_Config_t *Config_p)
{
Ft_assertNonvoid(Can_p != NULL);
Ft_assertNonvoid(Config_p != NULL);
Can_p->Config = *Config_p;
Can_p->IsReady = FT_COMPONENT_IS_READLY;
FCan_Reset(Can_p);
return FCAN_SUCCESS;
}
void FCan_GetErrorCnt(FCan_t *Can_p, u32 *TxErr, u32 *RxErr)
{
FCan_Config_t *Config_p;
Ft_assertVoid(Can_p != NULL);
Ft_assertVoid(Can_p->IsReady == FT_COMPONENT_IS_READLY);
Config_p = &Can_p->Config;
*RxErr = FCan_ReadReg(Config_p->CanBaseAddress, FCAN_ERR_CNT_OFFSET) & FCAN_ERR_CNT_RFN_MASK;
*TxErr = (FCan_ReadReg(Config_p->CanBaseAddress, FCAN_ERR_CNT_OFFSET) & FCAN_ERR_CNT_TFN_MASK) >> FCAN_ERR_CNT_TFN_SHIFT;
}
u32 FCan_RecvByIrq(FCan_t *Can_p, struct FCan_Frame *Frame_p, u32 FrameNumber)
{
u32 FifoCnt = 0;
FCan_Config_t *Config_p;
u32 CanId;
u32 Dlc;
u32 CanFrameIndex = 0;
u32 RxValue;
Ft_assertZeroNum(Can_p != NULL);
Ft_assertZeroNum(Can_p->IsReady == FT_COMPONENT_IS_READLY);
Config_p = &Can_p->Config;
FifoCnt = FCan_ReadReg(Config_p->CanBaseAddress, FCAN_FIFO_CNT_OFFSET) & 0x3f;
if (0 == FifoCnt)
{
return 0;
}
FrameNumber = (FrameNumber > FifoCnt) ? FifoCnt : FrameNumber;
while (FrameNumber)
{
/* Read a frame from Phytium CAN */
CanId = FCan_ReadReg(Config_p->CanBaseAddress, FCAN_RX_FIFO_OFFSET);
/* if CanId is big-endian ,use swap change to little-endian */
CanId = FT_SWAP32(CanId);
/* Identifier extension */
if (CanId & FCAN_IDR_IDE_MASK)
{
Dlc = FCan_ReadReg(Config_p->CanBaseAddress, FCAN_RX_FIFO_OFFSET);
Dlc = FT_SWAP32(Dlc);
Dlc = ((Dlc & FCAN_IDR_EDLC_MASK) >> FCAN_IDR_EDLC_SHIFT);
Frame_p[CanFrameIndex].CanId = (CanId & FCAN_IDR_ID1_MASK) >> 3;
Frame_p[CanFrameIndex].CanId |= (CanId & FCAN_IDR_ID2_MASK) >> FCAN_IDR_ID2_SHIFT;
Frame_p[CanFrameIndex].CanId |= CAN_EFF_FLAG;
if (CanId & FCAN_IDR_RTR_MASK)
{
Frame_p[CanFrameIndex].CanId |= CAN_RTR_FLAG;
}
}
else
{
Dlc = ((CanId & FCAN_IDR_DLC_MASK) >> FCAN_IDR_SDLC_SHIFT);
/* The received frame is a standard format frame */
Frame_p[CanFrameIndex].CanId = (CanId & FCAN_IDR_ID1_MASK) >> FCAN_IDR_ID1_SHIFT;
if (CanId & FCAN_IDR_SRR_MASK)
{
Frame_p[CanFrameIndex].CanId |= CAN_RTR_FLAG;
}
}
Frame_p[CanFrameIndex].CanDlc = (Dlc > sizeof(Frame_p[CanFrameIndex].data)) ? sizeof(Frame_p[CanFrameIndex].data) : Dlc;
if (!(Frame_p[CanFrameIndex].CanId & CAN_RTR_FLAG))
{
if (Frame_p[CanFrameIndex].CanDlc > 0)
{
RxValue = FCan_ReadReg(Config_p->CanBaseAddress, FCAN_RX_FIFO_OFFSET);
memcpy(Frame_p[CanFrameIndex].data, &RxValue, sizeof(RxValue));
}
if (Frame_p[CanFrameIndex].CanDlc > 4)
{
RxValue = FCan_ReadReg(Config_p->CanBaseAddress, FCAN_RX_FIFO_OFFSET);
memcpy(&Frame_p[CanFrameIndex].data[4], &RxValue, sizeof(RxValue));
}
}
FrameNumber--;
CanFrameIndex++;
}
return (CanFrameIndex + 1);
}
static void FCan_SendFifo(FCan_t *Can_p, struct FCan_Frame *Frame_p)
{
u32 Id, Dlc;
FCan_Config_t *Config_p;
u32 SendBuffer = 0;
Ft_assertVoid(Can_p != NULL);
Ft_assertVoid(Can_p->IsReady == FT_COMPONENT_IS_READLY);
Config_p = &Can_p->Config;
if (Frame_p->CanId & CAN_EFF_FLAG)
{
/* Extended CAN ID format */
Id = ((Frame_p->CanId & CAN_EFF_MASK) << FCAN_IDR_ID2_SHIFT) &
FCAN_IDR_ID2_MASK;
Id |= (((Frame_p->CanId & CAN_EFF_MASK) >>
(CAN_EFF_ID_BITS - CAN_SFF_ID_BITS))
<< FCAN_IDR_ID1_SHIFT) &
FCAN_IDR_ID1_MASK;
Id |= FCAN_IDR_IDE_MASK | FCAN_IDR_SRR_MASK;
if (Frame_p->CanId & CAN_RTR_FLAG)
{
Id |= FCAN_IDR_RTR_MASK;
}
Dlc = Frame_p->CanDlc << FCAN_IDR_EDLC_SHIFT;
FCan_WriteReg(Config_p->CanBaseAddress, FCAN_TX_FIFO_OFFSET, FT_SWAP32(Id));
FCan_WriteReg(Config_p->CanBaseAddress, FCAN_TX_FIFO_OFFSET, FT_SWAP32(Dlc));
}
else
{
/* Standard CAN ID format */
Id = ((Frame_p->CanId & CAN_SFF_MASK) << FCAN_IDR_ID1_SHIFT) &
FCAN_IDR_ID1_MASK;
if (Frame_p->CanId & CAN_RTR_FLAG)
Id |= FCAN_IDR_SRR_MASK;
Dlc = ((Frame_p->CanDlc << FCAN_IDR_SDLC_SHIFT) | FCAN_IDR_PAD_MASK);
Id |= Dlc;
FCan_WriteReg(Config_p->CanBaseAddress, FCAN_TX_FIFO_OFFSET, FT_SWAP32(Id));
}
if (!(Frame_p->CanId & CAN_RTR_FLAG))
{
if (Frame_p->CanDlc > 0)
{
memcpy(&SendBuffer, Frame_p->data, 4);
FCan_WriteReg(Config_p->CanBaseAddress, FCAN_TX_FIFO_OFFSET, SendBuffer);
}
if (Frame_p->CanDlc > 4)
{
memcpy(&SendBuffer, &Frame_p->data[4], 4);
FCan_WriteReg(Config_p->CanBaseAddress, FCAN_TX_FIFO_OFFSET, SendBuffer);
}
}
}
u32 FCan_SendByIrq(FCan_t *Can_p,
struct FCan_Frame *Frame_p,
u32 FrameNumber, void (*UserIrqWait)(void))
{
FCan_Config_t *Config_p;
u32 FrameIndex = 0;
u32 NeedSendOnce;
u32 cnt = 0;
Ft_assertZeroNum(Can_p != NULL);
Ft_assertZeroNum(Can_p->IsReady == FT_COMPONENT_IS_READLY);
Config_p = &Can_p->Config;
if (NULL == Frame_p)
{
FT_CAN_DEBUG_E("Frame_p is NULL , %s: %d", __FILE__, __LINE__);
return 0;
}
if (0 == FrameNumber)
{
FT_CAN_DEBUG_E("FrameNumber is 0 , %s: %d", __FILE__, __LINE__);
return 0;
}
for (; 0 < FrameNumber;)
{
if (FrameNumber > Config_p->TxFifoDeepth)
{
NeedSendOnce = Config_p->TxFifoDeepth;
FrameNumber -= Config_p->TxFifoDeepth;
}
else
{
NeedSendOnce = FrameNumber;
FrameNumber = 0;
}
Ft_printf("shut down tranmission \r\n");
/*shut down tranmission*/
FCan_ClearBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_XFER_MASK);
FCan_ClearBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_TXREQ_MASK);
FCan_SetBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_XFER_MASK);
Ft_printf("NeedSendOnce %d \r\n", NeedSendOnce);
for (cnt = 0; cnt < NeedSendOnce; cnt++)
{
FCan_SendFifo(Can_p, &Frame_p[FrameIndex]);
FrameIndex++;
}
Can_p->TxFifoCnt = NeedSendOnce;
/* triggers tranmission */
FCan_ClearBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_XFER_MASK);
FCan_SetBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_TXREQ_MASK);
FCan_SetBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_TXREQ_MASK | FCAN_CTRL_XFER_MASK);
if (UserIrqWait)
{
UserIrqWait();
}
else
{
while (0 != Can_p->TxFifoCnt)
{
};
}
}
return FrameIndex + 1;
}
ft_error_t FCan_SetTiming(FCan_t *Can_p,
struct FCan_Bittiming *Bittiming_p)
{
u32 Btr = 0;
FCan_Config_t *Config_p;
u32 IsConfigMode;
Ft_assertNonvoid(Can_p != NULL);
Ft_assertNonvoid(Can_p->IsReady == FT_COMPONENT_IS_READLY);
Config_p = &Can_p->Config;
Ft_assertNonvoid(Bittiming_p->brp != 0);
Ft_assertNonvoid(Bittiming_p->prop_seg != 0);
Ft_assertNonvoid(Bittiming_p->phase_seg1 != 0);
Ft_assertNonvoid(Bittiming_p->phase_seg2 != 0);
/* Setting Baud Rate prescalar value in BRPR Register */
Btr = (Bittiming_p->brp - 1) << 16;
Btr |= (Bittiming_p->prop_seg - 1) << 2;
Btr |= (Bittiming_p->phase_seg1 - 1) << 5;
Btr |= (Bittiming_p->phase_seg2 - 1) << 8;
Btr |= (Bittiming_p->sjw - 1);
IsConfigMode = (FCan_ReadReg(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET) & FCAN_CTRL_XFER_MASK);
if (IsConfigMode)
{
FCan_WriteReg(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_XFER_MASK);
}
FCan_WriteReg(Config_p->CanBaseAddress, FCAN_DAT_RATE_CTRL_OFFSET, Btr);
FCan_WriteReg(Config_p->CanBaseAddress, FCAN_ARB_RATE_CTRL_OFFSET, Btr);
/*Enable Transfer*/
FCan_SetBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_XFER_MASK);
return FCAN_SUCCESS;
}
void FCan_Enable(FCan_t *Can_p)
{
FCan_Config_t *Config_p;
Ft_assertVoid(Can_p != NULL);
Ft_assertVoid(Can_p->IsReady == FT_COMPONENT_IS_READLY);
Config_p = &Can_p->Config;
FCan_WriteReg(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_XFER_MASK);
}

View File

@@ -0,0 +1,142 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
*
* @Date: 2021-04-27 15:08:44
* @LastEditTime: 2021-04-27 15:08:44
* @Description:  Description of file
* @Modify History:
* * * Ver   Who        Date         Changes
* * ----- ------     --------    --------------------------------------
*/
#ifndef FT_CAN_H
#define FT_CAN_H
#include "ft_types.h"
#include "ft_error_code.h"
#define FCAN_SUCCESS FST_SUCCESS /* SUCCESS */
#define FCAN_FAILURE FT_MAKE_ERRCODE(errCan, errBspGeneral, FST_FAILURE) /* Normal */
#define FCAN_TIMEOUT FT_MAKE_ERRCODE(errCan, errBspGeneral, FST_TIMEOUT) /* Timeout */
#define FCAN_EILSEQ FT_MAKE_ERRCODE(errCan, errBspGeneral, FST_EILSEQ) /* Illegal byte sequence. */
#define FCAN_INVALID_PARAM FT_MAKE_ERRCODE(errCan, errBspGeneral, FST_INVALID_PARAM) /* Invalid param. */
#define FCAN_HANDLER_SEND 1U /**< Handler type for frame sending interrupt */
#define FCAN_HANDLER_RECV 2U /**< Handler type for frame reception interrupt*/
#define FCAN_HANDLER_ERROR 3U /**< Handler type for error interrupt */
#define FCAN_DATA_LENGTH 8U
/* CAN payload length and DLC definitions according to ISO 11898-1 */
#define CAN_MAX_DLC 8
#define CAN_MAX_DLEN 8
#define CAN_MAX_CTL 3
#define CAN_SFF_ID_BITS 11
#define CAN_EFF_ID_BITS 29
/* special address description flags for the CAN_ID */
#define CAN_EFF_FLAG 0x80000000U /* EFF/SFF is set in the MSB */
#define CAN_RTR_FLAG 0x40000000U /* remote transmission request */
#define CAN_ERR_FLAG 0x20000000U /* error message frame */
/* valid bits in CAN ID for frame formats */
#define CAN_SFF_MASK 0x000007FFU /* standard frame format (SFF) */
#define CAN_EFF_MASK 0x1FFFFFFFU /* extended frame format (EFF) */
#define CAN_ERR_MASK 0x1FFFFFFFU /* omit EFF, RTR, ERR flags */
/* Frame type */
#define STANDARD_FRAME 0 /* standard frame */
#define EXTEND_FRAME 1 /* extended frame */
typedef void (*FCan_irqHandler_t)(void *Args);
struct FCan_Frame
{
u32 CanId;
u8 CanDlc;
u8 data[FCAN_DATA_LENGTH];
};
struct FCan_Bittiming
{
u32 bitrate; /* Bit-rate in bits/second */
u32 sample_point; /* Sample point in one-tenth of a percent */
u32 tq; /* Time quanta (TQ) in nanoseconds */
u32 prop_seg; /* Propagation segment in TQs */
u32 phase_seg1; /* Phase buffer segment 1 in TQs */
u32 phase_seg2; /* Phase buffer segment 2 in TQs */
u32 sjw; /* Synchronisation jump width in TQs */
u32 brp; /* Bit-rate prescaler */
};
typedef struct
{
u32 InstanceId; /* Id of device */
u32 CanBaseAddress; /* Can base Address */
u32 IrqNum;
u32 BaudRate;
u32 TxFifoDeepth; /* The depth of the full frame , */
} FCan_Config_t;
typedef struct
{
FCan_Config_t Config;
u32 IsReady; /* Device is initialized and ready */
volatile u32 TxFifoCnt;
FCan_irqHandler_t SendHandler;
void *SendRef;
FCan_irqHandler_t RecvHandler;
void *RecvRef;
FCan_irqHandler_t ErrorHandler;
void *ErrorRef;
} FCan_t;
FCan_Config_t *FCan_LookupConfig(u32 InstanceId);
/**
* @name: FCan_CfgInitialize
* @msg: This function initializes a Can instance/driver.
* @in param Can_p: Can_p is a pointer to the FCan_t instance.
* @in param Config_p: Config_p points to the FCan_t device configuration structure.
* @return {*}
*/
ft_error_t FCan_CfgInitialize(FCan_t *Can_p, FCan_Config_t *Config_p);
/**
* @name: FCan_SetHandler
* @msg: This routine installs an asynchronous callback function for the given
* @inout param Can_p: Can_p is a pointer to the FCan_t instance.
* @in param HandlerType: specifies which handler is to be attached.
* @in param IrqCallBackFunc: IrqCallBackFunc is the address of the callback function.
* @in param IrqCallBackRef: IrqCallBackRef is a user data item that will be passed to the
* callback function when it is invoked.
* @return {*}
* @param {FCan_t} *Can_p
* @param {u32} HandlerType
* @param {FCan_irqHandler_t} *IrqCallBackFunc
* @param {void} *IrqCallBackRef
*/
ft_error_t FCan_SetHandler(FCan_t *Can_p, u32 HandlerType, FCan_irqHandler_t IrqCallBackFunc, void *IrqCallBackRef);
ft_error_t FCan_SetTiming(FCan_t *Can_p,
struct FCan_Bittiming *Bittiming_p);
void FCan_IntrHandler(void *InstancePtr);
ft_error_t FCan_CalcBittiming(struct FCan_Bittiming *Bt_p);
u32 FCan_SendByIrq(FCan_t *Can_p,
struct FCan_Frame *Frame_p,
u32 FrameNumber, void (*UserIrqWait)(void));
u32 FCan_RecvByIrq(FCan_t *Can_p, struct FCan_Frame *Frame_p, u32 FrameNumber);
void FCan_Enable(FCan_t *Can_p);
#endif // !FT_CAN_H

View File

@@ -0,0 +1,269 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
*
* @Date: 2021-05-06 09:30:51
* @LastEditTime: 2021-05-25 16:41:10
* @Description:  Description of file
* @Modify History:
* * * Ver   Who        Date         Changes
* * ----- ------     --------    --------------------------------------
*/
#include "ft_can.h"
#include "ft_debug.h"
#include "string.h"
#ifndef max
#define max(x, y) (((x) < (y)) ? (y) : (x))
#endif
#ifndef min
#define min(x, y) (((x) < (y)) ? (x) : (y))
#endif
#define FT_CAN_DEBUG_TAG "FT_CAN"
#define FT_CAN_DEBUG_I(format, ...) FT_DEBUG_PRINT_I(FT_CAN_DEBUG_TAG, format, ##__VA_ARGS__)
#define FT_CAN_DEBUG_E(format, ...) FT_DEBUG_PRINT_E(FT_CAN_DEBUG_TAG, format, ##__VA_ARGS__)
#define FT_CAN_DEBUG_W(format, ...) FT_DEBUG_PRINT_W(FT_CAN_DEBUG_TAG, format, ##__VA_ARGS__)
#define CAN_CLK_FREQ 600000000
#define CAN_CALC_SYNC_SEG 1
#define FCAN_TSEG1_MIN 1
#define FCAN_TSEG1_MAX 8
#define FCAN_TSEG2_MIN 1
#define FCAN_TSEG2_MAX 8
#define FCAN_SJW_MAX 4
#define FCAN_BRP_MIN 1
#define FCAN_BRP_MAX 512
#define FCAN_BRP_INC 1
#define FCAN_CALC_SYNC_SEG 1
#define CAN_CALC_MAX_ERROR 50 /* in one-tenth of a percent */
#define BEST_BITRATE_ERROR (2147483647 * 2U + 1)
#define clamp(x, low, high) (min(max(low, x), high))
typedef struct can_bittiming_const
{
char name[16]; /* Name of the CAN controller hardware */
u32 tseg1_min; /* Time segement 1 = prop_seg + phase_seg1 */
u32 tseg1_max;
u32 tseg2_min; /* Time segement 2 = phase_seg2 */
u32 tseg2_max;
u32 sjw_max; /* Synchronisation jump width */
u32 brp_min; /* Bit-rate prescaler */
u32 brp_max;
u32 brp_inc;
} FTCAN_BITTIMING_CONST;
static const struct can_bittiming_const ftcan_bittiming_const = {
.name = "vxbftCan",
.tseg1_min = 1,
.tseg1_max = 8,
.tseg2_min = 1,
.tseg2_max = 8,
.sjw_max = 4,
.brp_min = 1,
.brp_max = 512,
.brp_inc = 1,
};
static int abs(
int i /* integer for which to return absolute value */
)
{
return (i >= 0 ? i : -i);
}
static u32 div64_32(u64 *n, u32 base)
{
u64 rem = *n;
u64 b = base;
u64 res, d = 1;
u32 high = rem >> 32;
/* Reduce the thing a bit first */
res = 0;
if (high >= base)
{
high /= base;
res = (u64)high << 32;
rem -= (u64)(high * base) << 32;
}
while ((u64)b > 0 && b < rem)
{
b = b + b;
d = d + d;
}
do
{
if (rem >= b)
{
rem -= b;
res += d;
}
b >>= 1;
d >>= 1;
} while (d);
*n = res;
return rem;
}
s32 can_update_sample_point(const struct can_bittiming_const *btc,
u32 sample_point_nominal, u32 tseg,
u32 *tseg1_ptr, u32 *tseg2_ptr,
u32 *sample_point_error_ptr)
{
u32 sample_point_error, best_sample_point_error = BEST_BITRATE_ERROR;
u32 sample_point, best_sample_point = 0;
u32 tseg1, tseg2;
s32 i;
for (i = 0; i <= 1; i++)
{
tseg2 = tseg + CAN_CALC_SYNC_SEG - (sample_point_nominal * (tseg + CAN_CALC_SYNC_SEG)) / 1000 - i;
tseg2 = clamp(tseg2, btc->tseg2_min, btc->tseg2_max);
tseg1 = tseg - tseg2;
if (tseg1 > btc->tseg1_max)
{
tseg1 = btc->tseg1_max;
tseg2 = tseg - tseg1;
}
sample_point = 1000 * (tseg + CAN_CALC_SYNC_SEG - tseg2) / (tseg + CAN_CALC_SYNC_SEG);
sample_point_error = abs(sample_point_nominal - sample_point);
if ((sample_point <= sample_point_nominal) && (sample_point_error < best_sample_point_error))
{
best_sample_point = sample_point;
best_sample_point_error = sample_point_error;
*tseg1_ptr = tseg1;
*tseg2_ptr = tseg2;
}
}
if (sample_point_error_ptr)
*sample_point_error_ptr = best_sample_point_error;
return best_sample_point;
}
ft_error_t FCan_CalcBittiming(struct FCan_Bittiming *Bt_p)
{
u32 bitrate; /* current bitrate */
u32 bitrate_error; /* difference between current and nominal value */
u32 best_bitrate_error = BEST_BITRATE_ERROR;
u32 sample_point_error; /* difference between current and nominal value */
u32 best_sample_point_error = BEST_BITRATE_ERROR;
u32 sample_point_nominal; /* nominal sample point */
u32 best_tseg = 0; /* current best value for tseg */
u32 best_brp = 0; /* current best value for brp */
u32 brp, tsegall, tseg, tseg1 = 0, tseg2 = 0;
u64 v64;
const struct can_bittiming_const *btc = &ftcan_bittiming_const;
struct FCan_Bittiming *bt = Bt_p;
if (bt->sample_point)
{
sample_point_nominal = bt->sample_point;
}
else
{
if (bt->bitrate > 800000)
sample_point_nominal = 750;
else if (bt->bitrate > 500000)
sample_point_nominal = 800;
else
sample_point_nominal = 875;
}
for (tseg = (btc->tseg1_max + btc->tseg2_max) * 2 + 1;
tseg >= (btc->tseg1_min + btc->tseg2_min) * 2; tseg--)
{
tsegall = CAN_CALC_SYNC_SEG + tseg / 2;
/* Compute all possible tseg choices (tseg=tseg1+tseg2) */
brp = CAN_CLK_FREQ / (tsegall * bt->bitrate) + tseg % 2;
/* choose brp step which is possible in system */
brp = (brp / btc->brp_inc) * btc->brp_inc;
if ((brp < btc->brp_min) || (brp > btc->brp_max))
continue;
bitrate = CAN_CLK_FREQ / (brp * tsegall);
bitrate_error = abs(bt->bitrate - bitrate);
/* tseg brp biterror */
if (bitrate_error > best_bitrate_error)
continue;
/* reset sample point error if we have a better bitrate */
if (bitrate_error < best_bitrate_error)
best_sample_point_error = BEST_BITRATE_ERROR;
can_update_sample_point(btc, sample_point_nominal, tseg / 2, &tseg1, &tseg2, &sample_point_error);
if (sample_point_error > best_sample_point_error)
continue;
best_sample_point_error = sample_point_error;
best_bitrate_error = bitrate_error;
best_tseg = tseg / 2;
best_brp = brp;
if (bitrate_error == 0 && sample_point_error == 0)
break;
}
if (best_bitrate_error)
{
/* Error in one-tenth of a percent */
v64 = (u64)best_bitrate_error * 1000;
div64_32(&v64, bt->bitrate);
bitrate_error = (u32)v64;
if (bitrate_error > CAN_CALC_MAX_ERROR)
{
FT_CAN_DEBUG_E("bitrate error");
}
return FCAN_FAILURE;
FT_CAN_DEBUG_E("bitrate error 2");
}
/* real sample point */
bt->sample_point = can_update_sample_point(btc, sample_point_nominal, best_tseg,
&tseg1, &tseg2, NULL);
v64 = (u64)best_brp * 1000 * 1000 * 1000;
div64_32(&v64, CAN_CLK_FREQ);
bt->tq = (u64)v64;
bt->prop_seg = tseg1 / 2;
bt->phase_seg1 = tseg1 - bt->prop_seg;
bt->phase_seg2 = tseg2;
/* check for sjw user settings */
if (!bt->sjw || !btc->sjw_max)
{
bt->sjw = 1;
}
else
{
/* bt->sjw is at least 1 -> sanitize upper bound to sjw_max */
if (bt->sjw > btc->sjw_max)
bt->sjw = btc->sjw_max;
/* bt->sjw must not be higher than tseg2 */
if (tseg2 < bt->sjw)
bt->sjw = tseg2;
}
bt->brp = best_brp;
/* real bitrate */
bt->bitrate = CAN_CLK_FREQ / (bt->brp * (CAN_CALC_SYNC_SEG + tseg1 + tseg2));
return FCAN_SUCCESS;
}

View File

@@ -0,0 +1,39 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
*
* @Date: 2021-04-27 15:31:44
* @LastEditTime: 2021-04-27 15:31:44
* @Description:  Description of file
* @Modify History:
* * * Ver   Who        Date         Changes
* * ----- ------     --------    --------------------------------------
*/
#include "ft_can.h"
#include "ft_parameters.h"
FCan_Config_t FCan_Config[FT_CAN_NUM] =
{
{
.InstanceId = 0, /* Id of device */
.CanBaseAddress = FT_CAN0_BASEADDR, /* Can base Address */
.IrqNum = FT_CAN0_IRQNUM,
.BaudRate = 250000,
.TxFifoDeepth = 16,
},
{
.InstanceId = 1, /* Id of device */
.CanBaseAddress = FT_CAN1_BASEADDR, /* Can base Address */
.IrqNum = FT_CAN1_IRQNUM,
.BaudRate = 250000,
.TxFifoDeepth = 16,
},
{
.InstanceId = 2, /* Id of device */
.CanBaseAddress = FT_CAN2_BASEADDR, /* Can base Address */
.IrqNum = FT_CAN2_IRQNUM,
.BaudRate = 250000,
.TxFifoDeepth = 16,
}};

View File

@@ -0,0 +1,55 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
*
* @Date: 2021-04-27 13:52:41
* @LastEditTime: 2021-04-27 13:52:41
* @Description:  Description of file
* @Modify History:
* * * Ver   Who        Date         Changes
* * ----- ------     --------    --------------------------------------
*/
#include "ft_can_hw.h"
#include "ft_can.h"
#include "ft_mux.h"
#include "ft_parameters.h"
#include "ft_math.h"
#include "ft_assert.h"
#include "ft_debug.h"
#define CAN_HW_DEBUG_TAG "CAN_HW"
#define CAN_HW_DEBUG_I(format, ...) FT_DEBUG_PRINT_I(CAN_HW_DEBUG_TAG, format, ##__VA_ARGS__)
#define CAN_HW_DEBUG_E(format, ...) FT_DEBUG_PRINT_E(CAN_HW_DEBUG_TAG, format, ##__VA_ARGS__)
#define CAN_HW_DEBUG_W(format, ...) FT_DEBUG_PRINT_W(CAN_HW_DEBUG_TAG, format, ##__VA_ARGS__)
void FCan_Reset(FCan_t *Can_p)
{
u32 RegValue;
FCan_Config_t *Config_p;
Ft_assertVoid(Can_p != NULL);
Ft_assertVoid(Can_p->IsReady == FT_COMPONENT_IS_READLY);
Config_p = &Can_p->Config;
RegValue = FCan_ReadReg(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET);
if (RegValue & FCAN_CTRL_XFER_MASK)
{
CAN_HW_DEBUG_E("FT can is not in configration mode\n");
Ft_assertVoid(0);
return;
}
FCan_WriteReg(FT_PIN_DEMUX_BASE, FT_PIN_DEMUX_REG204_OFFSET, 0x89999990); // Reuse can IO
FCan_WriteReg(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_RESET_MASK);
FCan_SetBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_AIME_MASK);
FCan_WriteReg(Config_p->CanBaseAddress, FCAN_ACC_ID0_MASK_OFFSET, FCAN_ACC_IDN_MASK);
FCan_WriteReg(Config_p->CanBaseAddress, FCAN_ACC_ID1_MASK_OFFSET, FCAN_ACC_IDN_MASK);
FCan_WriteReg(Config_p->CanBaseAddress, FCAN_ACC_ID2_MASK_OFFSET, FCAN_ACC_IDN_MASK);
FCan_WriteReg(Config_p->CanBaseAddress, FCAN_ACC_ID3_MASK_OFFSET, FCAN_ACC_IDN_MASK);
FCan_ClearBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_RESET_MASK);
FCan_WriteReg(Config_p->CanBaseAddress, FCAN_INTR_OFFSET, FCAN_INTR_TEIE_MASK | FCAN_INTR_REIE_MASK);
}

View File

@@ -0,0 +1,161 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
*
* @Date: 2021-04-27 13:52:47
* @LastEditTime: 2021-04-27 13:52:47
* @Description:  Description of file
* @Modify History:
* * * Ver   Who        Date         Changes
* * ----- ------     --------    --------------------------------------
*/
#ifndef FT_CAN_HW_H
#define FT_CAN_HW_H
#include "ft_types.h"
#include "ft_io.h"
#include "ft_can.h"
/***ft CAN REGISTER offset*/
#define FCAN_CTRL_OFFSET 0x00 /* Global control register */
#define FCAN_INTR_OFFSET 0x04 /* Interrupt register */
#define FCAN_ARB_RATE_CTRL_OFFSET 0x08 /* Arbitration rate control register */
#define FCAN_DAT_RATE_CTRL_OFFSET 0x0C /* Data rate control register */
#define FCAN_ACC_ID0_OFFSET 0x10 /* Acceptance identifier0 register */
#define FCAN_ACC_ID1_OFFSET 0x14 /* Acceptance identifier1 register */
#define FCAN_ACC_ID2_OFFSET 0x18 /* Acceptance identifier2 register */
#define FCAN_ACC_ID3_OFFSET 0x1C /* Acceptance identifier3 register */
#define FCAN_ACC_ID0_MASK_OFFSET 0x20 /* Acceptance identifier0 mask register */
#define FCAN_ACC_ID1_MASK_OFFSET 0x24 /* Acceptance identifier1 mask register */
#define FCAN_ACC_ID2_MASK_OFFSET 0x28 /* Acceptance identifier2 mask register */
#define FCAN_ACC_ID3_MASK_OFFSET 0x2C /* Acceptance identifier3 mask register */
#define FCAN_XFER_STS_OFFSET 0x30 /* Transfer status register */
#define FCAN_ERR_CNT_OFFSET 0x34 /* Error counter register */
#define FCAN_FIFO_CNT_OFFSET 0x38 /* FIFO counter register */
#define FCAN_DMA_CTRL_OFFSET 0x3C /* DMA request control register */
#define FCAN_TX_FIFO_OFFSET 0x100 /* TX FIFO shadow register */
#define FCAN_RX_FIFO_OFFSET 0x200 /* RX FIFO shadow register */
/*----------------------------------------------------------------------------*/
/* CAN register bit masks - FCAN_<REG>_<BIT>_MASK */
/*----------------------------------------------------------------------------*/
/* FCAN_CTRL mask */
#define FCAN_CTRL_XFER_MASK (0x1 << 0) /* RW */ /*Transfer enable*/
#define FCAN_CTRL_TXREQ_MASK (0x1 << 1) /* RW */ /*Transmit request*/
#define FCAN_CTRL_AIME_MASK (0x1 << 2) /* RW */ /*Acceptance identifier mask enable*/
#define FCAN_CTRL_RESET_MASK (0x1 << 6)
/* FCAN_INTR mask */
#define FCAN_INTR_STATUS_MASK (0xFF << 0) /* RO */ /*the interrupt status*/
#define FCAN_INTR_BOIS_MASK (0x1 << 0) /* RO */ /*Bus off interrupt status*/
#define FCAN_INTR_PWIS_MASK (0x1 << 1) /* RO */ /*Passive warning interrupt status*/
#define FCAN_INTR_PEIS_MASK (0x1 << 2) /* RO */ /*Passive error interrupt status*/
#define FCAN_INTR_RFIS_MASK (0x1 << 3) /* RO */ /*RX FIFO full interrupt status*/
#define FCAN_INTR_TFIS_MASK (0x1 << 4) /* RO */ /*TX FIFO empty interrupt status*/
#define FCAN_INTR_REIS_MASK (0x1 << 5) /* RO */ /*RX frame end interrupt status*/
#define FCAN_INTR_TEIS_MASK (0x1 << 6) /* RO */ /*TX frame end interrupt status*/
#define FCAN_INTR_EIS_MASK (0x1 << 7) /* RO */ /*Error interrupt status*/
#define FCAN_INTR_EN_MASK (0xFF << 8) /* RO */ /*the interrupt enable*/
#define FCAN_INTR_BOIE_MASK (0x1 << 8) /* RW */ /*Bus off interrupt enable*/
#define FCAN_INTR_PWIE_MASK (0x1 << 9) /* RW */ /*Passive warning interrupt enable*/
#define FCAN_INTR_PEIE_MASK (0x1 << 10) /* RW */ /*Passive error interrupt enable*/
#define FCAN_INTR_RFIE_MASK (0x1 << 11) /* RW */ /*RX FIFO full interrupt enable*/
#define FCAN_INTR_TFIE_MASK (0x1 << 12) /* RW */ /*TX FIFO empty interrupt enable*/
#define FCAN_INTR_REIE_MASK (0x1 << 13) /* RW */ /*RX frame end interrupt enable*/
#define FCAN_INTR_TEIE_MASK (0x1 << 14) /* RW */ /*TX frame end interrupt enable*/
#define FCAN_INTR_EIE_MASK (0x1 << 15) /* RW */ /*Error interrupt enable*/
#define FCAN_INTR_BOIC_MASK (0x1 << 16) /* WO */ /*Bus off interrupt clear*/
#define FCAN_INTR_PWIC_MASK (0x1 << 17) /* WO */ /*Passive warning interrupt clear*/
#define FCAN_INTR_PEIC_MASK (0x1 << 18) /* WO */ /*Passive error interrupt clear*/
#define FCAN_INTR_RFIC_MASK (0x1 << 19) /* WO */ /*RX FIFO full interrupt clear*/
#define FCAN_INTR_TFIC_MASK (0x1 << 20) /* WO */ /*TX FIFO empty interrupt clear*/
#define FCAN_INTR_REIC_MASK (0x1 << 21) /* WO */ /*RX frame end interrupt clear*/
#define FCAN_INTR_TEIC_MASK (0x1 << 22) /* WO */ /*TX frame end interrupt clear*/
#define FCAN_INTR_EIC_MASK (0x1 << 23) /* WO */ /*Error interrupt clear*/
/* FCAN_ACC_ID(0-3)_MASK mask */
#define FCAN_ACC_IDN_MASK 0x1FFFFFFF /* WO */ /*dont care the matching */
/* FCAN_DAT_RATE_CTRL mask */
/* FCAN_ERR_CNT_OFFSET mask */
#define FCAN_ERR_CNT_RFN_MASK (0xFF << 0) /* RO */ /*Receive error counter*/
#define FCAN_ERR_CNT_TFN_MASK (0xFF << 16) /* RO */ /*Transmit error counter*/
/* FCAN_FIFO_CNT_OFFSET mask */
#define FCAN_FIFO_CNT_RFN_MASK (0xFF << 0) /* RO */ /*Receive FIFO valid data number*/
#define FCAN_FIFO_CNT_TFN_MASK (0xFF << 16) /* RO */ /*Transmit FIFO valid data number*/
#define FCAN_ERR_CNT_TFN_SHIFT 16 /* Tx Error Count shift */
#define FCAN_FIFO_CNT_TFN_SHIFT 16 /* Tx FIFO Count shift*/
#define FCAN_IDR_ID1_SHIFT 21 /* Standard Messg Identifier */
#define FCAN_IDR_ID2_SHIFT 1 /* Extended Message Identifier */
#define FCAN_IDR_SDLC_SHIFT 14
#define FCAN_IDR_EDLC_SHIFT 26
#define FCAN_ACC_IDN_SHIFT 18 /*Standard ACC ID shift*/
#define FCAN_IDR_ID2_MASK 0x0007FFFE /* Extended message ident */
#define FCAN_IDR_ID1_MASK 0xFFE00000 /* Standard msg identifier */
#define FCAN_IDR_IDE_MASK 0x00080000 /* Identifier extension */
#define FCAN_IDR_SRR_MASK 0x00100000 /* Substitute remote TXreq */
#define FCAN_IDR_RTR_MASK 0x00000001 /* Extended frames remote TX request */
#define FCAN_IDR_DLC_MASK 0x0003C000 /* Standard msg dlc */
#define FCAN_IDR_PAD_MASK 0x00003FFF /* Standard msg padding 1 */
#define FCAN_IDR_EDLC_MASK 0x3C000000 /* Extended msg dlc */
/* Can timming */
#define FCAN_TSEG1_MIN 1
#define FCAN_TSEG1_MAX 8
#define FCAN_TSEG2_MIN 1
#define FCAN_TSEG2_MAX 8
#define FCAN_SJW_MAX 4
#define FCAN_BRP_MIN 1
#define FCAN_BRP_MAX 512
#define FCAN_BRP_INC 1
#define FCAN_CALC_SYNC_SEG 1
/**
*
* This macro reads the given register.
*
* @param BaseAddr is the base address of the device.
* @param RegOffset is the register offset to be read.
*
* @return The 32-bit value of the register
*
* @note None.
*
*****************************************************************************/
#define FCan_ReadReg(BaseAddr, RegOffset) \
Ft_in32((BaseAddr) + (u32)(RegOffset))
/****************************************************************************/
/**
*
* This macro writes the given register.
*
* @param BaseAddr is the base address of the device.
* @param RegOffset is the register offset to be written.
* @param Data is the 32-bit value to write to the register.
*
* @return None.
*
* @note None.
*
*****************************************************************************/
#define FCan_WriteReg(BaseAddr, RegOffset, Data) \
Ft_out32((BaseAddr) + (u32)(RegOffset), (u32)(Data))
#define FCan_SetBit(BaseAddr, RegOffset, Data) \
Ft_setBit32((BaseAddr) + (u32)(RegOffset), (u32)(Data))
#define FCan_ClearBit(BaseAddr, RegOffset, Data) \
Ft_clearBit32((BaseAddr) + (u32)(RegOffset), (u32)(Data))
void FCan_Reset(FCan_t *Can_p);
#endif // !

View File

@@ -0,0 +1,118 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
*
* @Date: 2021-04-29 10:40:47
* @LastEditTime: 2021-04-29 10:40:47
* @Description:  Description of file
* @Modify History:
* * * Ver   Who        Date         Changes
* * ----- ------     --------    --------------------------------------
*/
#include "ft_can.h"
#include "ft_can_hw.h"
#include "ft_assert.h"
#include "ft_types.h"
ft_error_t FCan_SetHandler(FCan_t *Can_p, u32 HandlerType, FCan_irqHandler_t IrqCallBackFunc, void *IrqCallBackRef)
{
ft_error_t status = FCAN_SUCCESS;
Ft_assertNonvoid(Can_p != NULL);
Ft_assertNonvoid(Can_p->IsReady == FT_COMPONENT_IS_READLY);
switch (HandlerType)
{
case FCAN_HANDLER_SEND:
Can_p->SendHandler = IrqCallBackFunc;
Can_p->SendRef = IrqCallBackRef;
break;
case FCAN_HANDLER_RECV:
Can_p->RecvHandler = IrqCallBackFunc;
Can_p->RecvRef = IrqCallBackRef;
break;
case FCAN_HANDLER_ERROR:
Can_p->ErrorHandler = IrqCallBackFunc;
Can_p->ErrorRef = IrqCallBackRef;
break;
default:
status = FCAN_FAILURE;
}
return status;
}
static void FCan_TxInterrupt(FCan_t *Can_p)
{
FCan_Config_t *Config_p = &Can_p->Config;
FCan_SetBit(Config_p->CanBaseAddress, FCAN_INTR_OFFSET, FCAN_INTR_TEIC_MASK | FCAN_INTR_REIC_MASK);
if (0 != Can_p->TxFifoCnt)
{
Can_p->TxFifoCnt--;
FCan_ClearBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_XFER_MASK);
FCan_SetBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_TXREQ_MASK);
FCan_SetBit(Config_p->CanBaseAddress, FCAN_CTRL_OFFSET, FCAN_CTRL_XFER_MASK);
}
else
{
if (Can_p->SendHandler)
{
Can_p->SendHandler(Can_p->SendRef);
}
}
}
static void FCan_ErrorInterrupt(FCan_t *Can_p)
{
if (Can_p->ErrorHandler)
{
Can_p->ErrorHandler(Can_p->ErrorRef);
}
}
static void FCan_RxInterrupt(FCan_t *Can_p)
{
if (Can_p->RecvHandler)
{
Can_p->RecvHandler(Can_p->RecvRef);
}
}
void FCan_IntrHandler(void *InstancePtr)
{
u32 Irq;
FCan_t *Can_p = (FCan_t *)InstancePtr;
FCan_Config_t *Config_p;
Ft_assertVoid(Can_p != NULL);
Ft_assertVoid(Can_p->IsReady == FT_COMPONENT_IS_READLY);
Config_p = &Can_p->Config;
Irq = FCan_ReadReg(Config_p->CanBaseAddress, FCAN_INTR_OFFSET);
if (0 == Irq)
{
return;
}
/* Check for the type of error interrupt and Processing it */
if (Irq & FCAN_INTR_TEIS_MASK)
{
Irq &= ~FCAN_INTR_REIS_MASK;
FCan_TxInterrupt(Can_p);
}
if (Irq & (FCAN_INTR_EIS_MASK | FCAN_INTR_RFIS_MASK |
FCAN_INTR_BOIS_MASK | FCAN_INTR_PEIS_MASK | FCAN_INTR_PWIS_MASK))
{
FCan_SetBit(Config_p->CanBaseAddress, FCAN_INTR_OFFSET, (FCAN_INTR_EIC_MASK | FCAN_INTR_RFIC_MASK | FCAN_INTR_BOIC_MASK | FCAN_INTR_PEIC_MASK | FCAN_INTR_PWIC_MASK));
FCan_ErrorInterrupt(Can_p);
}
if (Irq & FCAN_INTR_REIS_MASK)
{
FCan_SetBit(Config_p->CanBaseAddress, FCAN_INTR_OFFSET, FCAN_INTR_REIE_MASK);
FCan_RxInterrupt(Can_p);
FCan_SetBit(Config_p->CanBaseAddress, FCAN_INTR_OFFSET, FCAN_INTR_REIC_MASK);
FCan_SetBit(Config_p->CanBaseAddress, FCAN_INTR_OFFSET, FCAN_INTR_REIE_MASK);
}
}

View File

@@ -0,0 +1,40 @@
/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0.
*
* @Date: 2021-04-27 15:31:57
* @LastEditTime: 2021-04-27 15:31:57
* @Description:  Description of file
* @Modify History:
* * * Ver   Who        Date         Changes
* * ----- ------     --------    --------------------------------------
*/
#include "ft_can.h"
#include "ft_parameters.h"
extern FCan_Config_t FCan_Config[FT_CAN_NUM];
/**
* @name:
* @msg:
* @in param:
* @return {*}
* @param {u32} InstanceId
*/
FCan_Config_t *FCan_LookupConfig(u32 InstanceId)
{
FCan_Config_t *CfgPtr = NULL;
u32 Index;
for (Index = 0; Index < (u32)FT_CAN_NUM; Index++)
{
if (FCan_Config[Index].InstanceId == InstanceId)
{
CfgPtr = &FCan_Config[Index];
break;
}
}
return (FCan_Config_t *)CfgPtr;
}

Some files were not shown because too many files have changed in this diff Show More