From 6edd0586f23a2088dacfc34c5d514d0c0c7f2915 Mon Sep 17 00:00:00 2001 From: flyingcys Date: Thu, 4 May 2023 11:49:38 +0800 Subject: [PATCH] [bsp/bouffalo_lab]add spi driver (#7435) --- bsp/bouffalo_lab/README.md | 66 +- bsp/bouffalo_lab/bl808/README.md | 156 +++++ bsp/bouffalo_lab/bl808/figures/bl808.png | Bin 0 -> 38677 bytes bsp/bouffalo_lab/bl808/figures/d0.png | Bin 0 -> 33979 bytes .../bl808/figures/kernel_start.png | Bin 0 -> 19196 bytes .../applications/{dfs_mnt_sample.c => mnt.c} | 39 +- bsp/bouffalo_lab/bl808/m0/flash_prog_cfg.ini | 4 +- bsp/bouffalo_lab/libraries/rt_drivers/Kconfig | 336 ++++++++++- .../libraries/rt_drivers/SConscript | 13 +- .../libraries/rt_drivers/drv_flash.c | 20 +- .../libraries/rt_drivers/drv_gpio.c | 5 +- .../libraries/rt_drivers/drv_hwtimer.c | 8 +- .../libraries/rt_drivers/drv_pwm.c | 4 +- .../libraries/rt_drivers/drv_rtc.c | 6 +- .../libraries/rt_drivers/drv_soft_i2c.c | 5 +- .../libraries/rt_drivers/drv_spi.c | 568 ++++++++++++++++++ .../libraries/rt_drivers/drv_spi.h | 175 ++++++ .../libraries/rt_drivers/drv_wdt.c | 2 - .../rt_drivers/sample}/hwtimer_sample.c | 3 +- .../rt_drivers/sample}/pwm_led_sample.c | 2 +- .../libraries/rt_drivers/sample/spi_sample.c | 86 +++ .../rt_drivers/sample}/wdt_sample.c | 2 +- 22 files changed, 1412 insertions(+), 88 deletions(-) create mode 100644 bsp/bouffalo_lab/bl808/README.md create mode 100755 bsp/bouffalo_lab/bl808/figures/bl808.png create mode 100755 bsp/bouffalo_lab/bl808/figures/d0.png create mode 100755 bsp/bouffalo_lab/bl808/figures/kernel_start.png rename bsp/bouffalo_lab/bl808/m0/applications/{dfs_mnt_sample.c => mnt.c} (52%) mode change 100644 => 100755 create mode 100644 bsp/bouffalo_lab/libraries/rt_drivers/drv_spi.c create mode 100755 bsp/bouffalo_lab/libraries/rt_drivers/drv_spi.h rename bsp/bouffalo_lab/{bl808/m0/applications => libraries/rt_drivers/sample}/hwtimer_sample.c (99%) mode change 100644 => 100755 rename bsp/bouffalo_lab/{bl808/m0/applications => libraries/rt_drivers/sample}/pwm_led_sample.c (99%) mode change 100644 => 100755 create mode 100755 bsp/bouffalo_lab/libraries/rt_drivers/sample/spi_sample.c rename bsp/bouffalo_lab/{bl808/m0/applications => libraries/rt_drivers/sample}/wdt_sample.c (99%) mode change 100644 => 100755 diff --git a/bsp/bouffalo_lab/README.md b/bsp/bouffalo_lab/README.md index a731cb3172..85425812c3 100755 --- a/bsp/bouffalo_lab/README.md +++ b/bsp/bouffalo_lab/README.md @@ -2,7 +2,7 @@ ## 1. 简介 -bouffalo_lab bsp针对bouffalo_lab的系列AIoT芯片,采用bouffalo_lab最新**LHAL** 驱动库,驱动库与[bl_mcu_sdk](https://github.com/bouffalolab/bl_mcu_sdk) 代码同步,当前commitid:`47c662afae69309fd49d2721b5c9b93219a91af7` +bouffalo_lab bsp针对bouffalo_lab的系列AIoT芯片,采用bouffalo_lab最新**LHAL** 驱动库,驱动库与[bouffalo_sdk](https://github.com/bouffalolab/bouffalo_sdk)(原bl_mcu_sdk)代码同步,当前commitid:`e6e8da79a50aeb4fcb67ac380c3bd8885cd56faf` 目前支持以下芯片: @@ -50,9 +50,9 @@ bouffalo_lab bsp针对bouffalo_lab的系列AIoT芯片,采用bouffalo_lab最新 ## 2. 环境搭建及编译 -bl60x/bl70x/bl61x可在对应芯片直接编译;bl808是多核异构架构,分为m0、lp、d0(适配中,敬请期待),每个核需要单独编译并烧录到对应的位置。 +bl60x/bl70x/bl61x可在对应芯片直接编译;bl808是多核异构架构,分为m0、lp、d0,每个核需要单独编译并烧录到对应的位置,bl808三核使用详细参考[bl808三核使用指南](./bl808/README.md)。 -以下操作以bl61x为例,其他芯片操作类同。 +以下操作以单核bl61x为例,其他芯片操作类同。 ### 2.1. 下载 @@ -106,17 +106,40 @@ Windows下推荐使用[env工具][1],在console下进入bsp/bouffalo_lab/bl61x 脚本会自动采用curl命令行方式下载`bflb_fw_post_proc`,如自动下载失败,可采用手工方式下载对应操作系统文件后保存至`libraries/bl_mcu_sdk/tools/bflb_tools/bflb_fw_post_proc` -[windows](https://raw.githubusercontent.com/bouffalolab/bl_mcu_sdk/master/tools/bflb_tools/bflb_fw_post_proc/bflb_fw_post_proc.exe) +| 下载地址1 | [windows](https://raw.githubusercontent.com/bouffalolab/bl_mcu_sdk/master/tools/bflb_tools/bflb_fw_post_proc/bflb_fw_post_proc.exe)/[Linux](https://raw.githubusercontent.com/bouffalolab/bl_mcu_sdk/master/tools/bflb_tools/bflb_fw_post_proc/bflb_fw_post_proc-ubuntu)/[macos](https://raw.githubusercontent.com/bouffalolab/bl_mcu_sdk/master/tools/bflb_tools/bflb_fw_post_proc/bflb_fw_post_proc-macos) | +| --------- | ------------------------------------------------------------ | +| 下载地址2 | [bflb_fw_post_proc-win.tar.gz](https://gitee.com/flyingcys/bflb_tools/releases/download/v1.0.4/bflb_fw_post_proc-win.tar.gz)/[bflb_fw_post_proc-linux.tar.gz](https://gitee.com/flyingcys/bflb_tools/releases/download/v1.0.4/bflb_fw_post_proc-linux.tar.gz)/[bflb_fw_post_proc-macos.tar.gz](https://gitee.com/flyingcys/bflb_tools/releases/download/v1.0.4/bflb_fw_post_proc-macos.tar.gz) | +| 下载地址3 | [bflb_fw_post_proc-win.tar.gz](https://github.com/flyingcys/bflb_tools/releases/download/v1.0.4/bflb_fw_post_proc-win.tar.gz)/[bflb_fw_post_proc-linux.tar.gz](https://github.com/flyingcys/bflb_tools/releases/download/v1.0.4/bflb_fw_post_proc-linux.tar.gz)/[bflb_fw_post_proc-macos.tar.gz](https://github.com/flyingcys/bflb_tools/releases/download/v1.0.4/bflb_fw_post_proc-macos.tar.gz) | -[Linux](https://raw.githubusercontent.com/bouffalolab/bl_mcu_sdk/master/tools/bflb_tools/bflb_fw_post_proc/bflb_fw_post_proc-ubuntu) -[macos](https://raw.githubusercontent.com/bouffalolab/bl_mcu_sdk/master/tools/bflb_tools/bflb_fw_post_proc/bflb_fw_post_proc-macos) ## 3. 下载烧录 -### 3.1. GUI方式下载 +### 3.1. 烧录工具下载 -当前bsp必须使用[bouffalo_flash_cube-1.0.4](https://pan.baidu.com/s/1eG9pkxf3riAqQAu9aXiOjw?pwd=miv1)工具进行烧录,否则无法正常运行。 +当前bsp必须使用`bouffalo_flash_cube-1.0.4`工具进行烧录,使用其他工作无法正常运行。 + +- 烧录工具下载地址1:[百度网盘](https://pan.baidu.com/s/1eG9pkxf3riAqQAu9aXiOjw?pwd=miv1) + +- 烧录工具下载地址2: + +[bouffalo_flash_cube-win.zip](https://gitee.com/flyingcys/bflb_tools/releases/download/v1.0.4/bouffalo_flash_cube-win.zip)/[bouffalo_flash_cube-win.tar.gz](https://gitee.com/flyingcys/bflb_tools/releases/download/v1.0.4/bouffalo_flash_cube-win.tar.gz) + +[bouffalo_flash_cube-linux.zip](https://gitee.com/flyingcys/bflb_tools/releases/download/v1.0.4/bouffalo_flash_cube-linux.zip)/[bouffalo_flash_cube-linux.tar.gz](https://gitee.com/flyingcys/bflb_tools/releases/download/v1.0.4/bouffalo_flash_cube-linux.tar.gz) + +[bouffalo_flash_cube-macos.zip](https://gitee.com/flyingcys/bflb_tools/releases/download/v1.0.4/bouffalo_flash_cube-macos.zip)/[bouffalo_flash_cube-macos.tar.gz](https://gitee.com/flyingcys/bflb_tools/releases/download/v1.0.4/bouffalo_flash_cube-macos.tar.gz) + +- 烧录工具下载地址3: + +[bouffalo_flash_cube-win.zip](https://github.com/flyingcys/bflb_tools/releases/download/v1.0.4/bouffalo_flash_cube-win.zip)/[bouffalo_flash_cube-win.tar.gz](https://github.com/flyingcys/bflb_tools/releases/download/v1.0.4/bouffalo_flash_cube-win.tar.gz) + +[bouffalo_flash_cube-linux.zip](https://github.com/flyingcys/bflb_tools/releases/download/v1.0.4/bouffalo_flash_cube-linux.zip)/[bouffalo_flash_cube-linux.tar.gz](https://github.com/flyingcys/bflb_tools/releases/download/v1.0.4/bouffalo_flash_cube-linux.tar.gz) + +[bouffalo_flash_cube-macos.zip](https://github.com/flyingcys/bflb_tools/releases/download/v1.0.4/bouffalo_flash_cube-macos.zip)/[bouffalo_flash_cube-macos.tar.gz](https://github.com/flyingcys/bflb_tools/releases/download/v1.0.4/bouffalo_flash_cube-macos.tar.gz) + + + +### 3.2. GUI方式下载 1. 连接好串口并在工具上选择对应的串口号 @@ -128,9 +151,13 @@ Windows下推荐使用[env工具][1],在console下进入bsp/bouffalo_lab/bl61x ![Flash Download](figures/bouffalo_flash_cube.jpg) + + ### 3.2. 命令行下载 -或者可使用`bsp/bouffalo_lab`目录下的`bouffalo_flash_cube.sh`脚本通过命令行下载,输入`./`bouffalo_flash_cube.sh bl616 /dev/ttyUSB1`,使用前先确定脚本中bouffalo_flash_cube工具路径,需手工修改为工具所在目录。 +命令行下载可使用`bsp/bouffalo_lab`目录下的`bouffalo_flash_cube.sh`脚本,输入`./bouffalo_flash_cube.sh bl616 /dev/ttyUSB1`,脚本会自动采用curl命令行方式下载`bouffalo_flash_cube`。 + +如自动下载失败,可采用手工方式下载对应操作系统文件后保存至`libraries/bl_mcu_sdk/tools/bflb_tools/bouffalo_flash_cube`目录。 其中: @@ -153,7 +180,7 @@ Windows下推荐使用[env工具][1],在console下进入bsp/bouffalo_lab/bl61x | ----- | ---------------------- | | bl602 | BL602-IoT-3S/BL-HWC-G1 | | bl702 | Maix Zero Sense | -| bl616 | M0S Dock | +| bl616/bl618 | M0S Dock/M0P Dock | | bl808 | M1s Dock | @@ -164,8 +191,14 @@ Windows下推荐使用[env工具][1],在console下进入bsp/bouffalo_lab/bl61x | :--- | :------- | :---------------- | | UART | 支持 | 默认波特率2000000 | | GPIO | 支持 | | -| I2C | 开发中 | | -| SPI | 开发中 | | +| I2C | 支持 | | +| SPI | 支持 | 支持DMA | +| PWM | 支持 | | +| ADC | 支持 | | +| RTC | 支持 | | +| WDT | 支持 | | +| HWTIMER | 支持 | | +| FLASH | 支持 | | @@ -182,12 +215,3 @@ Windows下推荐使用[env工具][1],在console下进入bsp/bouffalo_lab/bl61x [1]: https://www.rt-thread.org/download.html#download-rt-thread-env-tool [2]: https://github.com/bouffalolab/bl_docs - - -## 9. FAQ - -| | M1s Dock | -| ---- | :----------------------------------------------------------- | -| 1 | 在 windows 环境下,通过 UART 接口将开发板连接至电脑时,仅能识别到两个 USB converter 设备,但是识别不到对应的串口设备。
进入到设备管理器中,右击对应的 USB converter 设备,进入到属性中的高级设置,钩选 vcp 选项,刷新后即可看到对应的串口设备。
也可通过安装以下驱动解决问题: https://dl.sipeed.com/shareURL/MAIX/tools/ftdi_vcp_driver | -| 2 | 使用 TypeC 数据线将电脑与板子的 UART 口连接起来,此时电脑上会出现两个串口 (如果出现鼠标不能动的现象请拔掉 USB 并且查看 [更新板载 bl702 固件](https://wiki.sipeed.com/hardware/zh/maix/m1s/other/start.html#给板载-bl702-进行烧录) 相关内容来修复问题)。 | - diff --git a/bsp/bouffalo_lab/bl808/README.md b/bsp/bouffalo_lab/bl808/README.md new file mode 100644 index 0000000000..6dfd212792 --- /dev/null +++ b/bsp/bouffalo_lab/bl808/README.md @@ -0,0 +1,156 @@ +# 博流智能 BL808板级支持包说明 + +## 1. 简介 + +BL808 是高度集成的 AIoT 芯片组,具有 Wi-Fi/BT/BLE/Zigbee 等无线互联单元,包含多个 CPU 以及音频编码译码器、视频编码译码器和 AI 硬件加速器,适用于各种高性能和低功耗应用领域。 + +BL808 系列芯片主要包含无线和多媒体两个子系统。 + +无线子系统包含一颗 RISC-V 32-bit 高性能 CPU(m0),集成 Wi-Fi/BT/Zigbee 无线子系统,可以实现多种无线连接和数据传输,提供多样化的连接与传输体验。 +多媒体子系统包含一颗 RISC-V 64-bit 超高性能 CPU(d0),集成 DVP/CSI/ H264/NPU 等视频处理模块,可以广泛应用于视频监控/智能音箱等多种 AI 领域 + +多媒体子系统组成部分如下: + +- NPU HW NN 协处理器 (BLAI-100),适用于人工智能应用领域 +- 摄像头接口 +- 音频编码译码器 +- 视频编码解码器 +- 传感器 +- 显示接口 + +电源管理单元控制低功耗模式。此外,还支持各种安全功能。 + +外围接口包括 USB2.0、 Ethernet、 SD/MMC、 SPI、 UART、 I2C、 I2S、 PWM、 GPDAC/GPADC、 ACOMP、 PIR、 Touch、 +IR remote、 Display 和 GPIO。 + +支持灵活的 GPIO 配置, BL808 最多可达 40 个 GPIO。 + +芯片规格包括如下: + +| 硬件 | 描述 | +| -- | -- | +|芯片型号| bl808 | +|CPU| 三核异构RISC-V CPUs:
RV64GCV 480MHz
RV32GCP 320MHz
RV32EMC 160MHz | +|RAM| 768KB SRAM + 64MB UHS PSRAM | +| 外设 | 内嵌AES与SHA256算法加速器 | +| AI NN 通用硬件加速器 | BLAI-100 用于视频/音频检测/识别,100GOPS 算力 | +| 摄像头接口 | DVP 和 MIPI-CSI | +| 显示接口 | SPI、DBI、DPI(RGB) | +| 无线 | 支持 Wi-Fi 802.11 b/g/n
支持 Bluetooth 5.x Dual-mode(BT+BLE)
支持 Wi-Fi / 蓝牙 共存 | + + + +## 2. RT-Thread 版本 + +BL808是三核异构架构,分别为m0、lp、d0,当前bsp已实现三核同时启动,三核分别采用了不同的RT-Thread版本 + +| 名称 | CPU核 | RT-Thread版本 | +| ---- | ----- | ---------------- | +| M0 | E907 | RT-Thread 标准版 | +| LP | E902 | RT-Thread Nano | +| D0 | C906 | RT-SMART | + + + + +## 3. 编译说明 + +BL808是三核异构架构,分别为m0、lp、d0,三核需要单独编译,并烧录到对应的位置。 + +烧录地址: + +| 名称 | CPU核 | 烧录地址 | 说明 | +| ---- | ----- | -------- | ------------------------------------------------------------ | +| M0 | E907 | 0x00000 | | +| LP | E902 | 0xC0000 | 调整lp烧录地址需修改
`bsp/bouffalo_lab/bl808/lp/board/linker_scripts/bl808_flash_lp.ld`中的xip_memory地址
`bsp/bouffalo_lab/bl808/m0/board/board.h`中`CONFIG_LP_FLASH_ADDR`地址 | +| D0 | C906 | 0x100000 | 在spl文件中设定,调整d0烧录地址需重新编译spl文件及打包文件`bsp/bouffalo_lab/bl808/d0/merge_rtsmart.py` | + + + +### 3.1. m0/lp + +- #### 工具链下载 + + +下载risc-v的工具链,[下载地址1](https://occ.t-head.cn/community/download?id=4073475960903634944)或[下载地址2](https://dl.sipeed.com/shareURL/others/toolchain) + +Windows下请使用使用[env工具][1],使用命令 `tar -xvf Xuantie-900-gcc-elf-newlib-mingw-V2.6.1-20220906.tar.gz` 解压交叉编译器,使用Windows下解压工具直接解压可能出现Windows下编译错误。 + +在`rtconfig.py`中将risc-v工具链的本地路径加入 `EXEC_PATH` 或通过 `RTT_EXEC_PATH` 环境变量指定路径 + +Windows: +``` +set RTT_EXEC_PATH=C:\Users\xxxx\Downloads\Xuantie-900-gcc-elf-newlib-x86_64-V2.6.1\bin +``` + +Linux: +``` +export RTT_EXEC_PATH=/opt/Xuantie-900-gcc-elf-newlib-x86_64-V2.6.1/bin +``` + +- ### 编译 + +Windows下推荐使用[env工具][1],在console下进入bsp/bl808目录中,选择需要编译的核心,m0或lp,运行: + + cd bsp/bl808/m0 + menuconfig + pkgs --update + +如果在Linux平台下,可以先执行: + + scons --menuconfig + +它会自动下载env相关脚本到~/.env目录,然后执行 + + source ~/.env/env.sh + + cd bsp/bl808/m0 + pkgs --update + +更新完软件包后,执行 `scons -j10` 或 `scons -j10 --verbose` 来编译这个板级支持包。或者通过 `scons --exec-path="GCC工具链路径"` 命令,在指定工具链位置的同时直接编译。 + +如果编译正确无误,会产生rtthread.elf、rtthread_m0.bin文件。其中rtthread_m0.bin需要烧写到设备中进行运行。 + + + +- #### 注意 + + 由于BL808为三核异构,lp核、d0核都是通过m0核启动的,必须正确烧录m0核才可以实现三核正常运行 + + m0烧录配置文件:`bsp/bouffalo_lab/bl808/m0/flash_prog_cfg.ini` + + + +### 3.2. d0 + +bl808-d0运行在S态下,支持RT-Smart,采用的交叉编译器为`riscv64-unknown-linux-musl-gcc`,编译请参考[构建内核镜像](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-smart/quick-start/qemu-linux/quickstart?id=%e6%9e%84%e5%bb%ba%e5%86%85%e6%a0%b8%e9%95%9c%e5%83%8f) + +其中内核虚拟地址开始地址为`0x50000000` + +![kernel_start](./figures/kernel_start.png) + +bl808-d0编译完成后通过`merge_rtsmart.py`脚本,将`hw.dtb.5M`,`spl_bl808_d0.bin`,`opensbi_v0.6.bin`与`rtthread_d0.bin`,合成最终烧录文件`whole_img_d0.bin`,烧录地址为`0x100000`,否则无法启动。 + +预编译bin文件位于`bsp/bouffalo_lab/bl808/d0/pre_build_bin`文件夹下,如有修改需求可下载[Low-Starup-BL808](https://github.com/flyingcys/Low-Starup-BL808)后自行修改。 + +d0单独烧录文件为`bsp/bouffalo_lab/bl808/d0/flash_prog_cfg.ini` + +![d0](./figures/d0.png) + + + +### 3.3. 三核同时编译与烧录 + +- 可运行`bsp/bouffalo_lab/bl808/build_bl808_all.sh`依次编译m0、lp、d0核 +- 可通过`bsp/bouffalo_lab/bl808/flash_prog_cfg.ini`烧录配置文件,同时烧录m0、lp、d0核。 + +![bl808](./figures/bl808.png) + + + +## 4. FAQ + +- 在 windows 环境下,通过 UART 接口将开发板连接至电脑时,仅能识别到两个 USB converter 设备,但是识别不到对应的串口设备。 + - 进入到设备管理器中,右击对应的 USB converter 设备,进入到属性中的高级设置,钩选 vcp 选项,刷新后即可看到对应的串口设备。 + - 也可通过安装以下驱动解决问题: https://dl.sipeed.com/shareURL/MAIX/tools/ftdi_vcp_driver +- 使用 TypeC 数据线将电脑与板子的 UART 口连接起来,此时电脑上会出现两个串口 (如果出现鼠标不能动的现象请拔掉 USB 并且查看 [更新板载 bl702 固件](https://wiki.sipeed.com/hardware/zh/maix/m1s/other/start.html#给板载-bl702-进行烧录) 相关内容来修复问题)。 diff --git a/bsp/bouffalo_lab/bl808/figures/bl808.png b/bsp/bouffalo_lab/bl808/figures/bl808.png new file mode 100755 index 0000000000000000000000000000000000000000..6f2d3559f8e8a2b7956011890ef04a212b0a9f98 GIT binary patch literal 38677 zcmb?@1z40_*Di{Lg5W5El)#_@k|I(=O9~PqB{3i+(m5b8(nw2(fV9#j4I?033QC8x z2*c1hah^e6-}gKJ_kZVH|2bZl!1K(0_OtfdYp=cTd#ydM)KwKOUZA@`KtOO&Nm2F@ z0l_&C0m0cZQexoF?Y`&Sz^^mTj}&AGN(LBKfs1pN(hsEx2+E_#&?ZE{^?3(HJ!b*} ziZ=ZJGoAMD%m@e)3Y27}AG;eNF}7tlM$=XfriCaZn_}<3SWt)DXt>%~11l;s>)fd4 zkPNstXTi=8=9!ATq!_dm&kcEcQ_3`u&}PO{&Q(2SdX6jQZiwJ$wxQBS^Ea5%Q>h~P z#%IwjEmwT)1db&Lt_jvEpFKzF5X=yjC?zSGbs~&o8|)TM-Wx2^bgjHy$d5pTP=1ad zjMqzc9Y9q4Pw0);8%lzxHOEQX& z*};DvxpA8c^jE7(m#>DB{?&@~)q}7w(!~B(_sJ|wOj;N`pLiN1nqD36X#oy@ue9`>-(MQmn(rcz8;K{1W%7yC}h@WZ^+Px2VQ%wdUMS z9tHc!a#E{gy<~oM8;oB109l?Due8MOFnJqeCUM^%X^VaKS_no>tTv;kdzTR&CpvZ< z{v2-W3n=Pq*F#COE#km_DiAvs<2T*{V)2~^+vlCxYwUw;{8ivT0z^QVl;88-=eb-L z!hAlAIQBNPqWrOF+bm4(oa4{-j8yyP-JK$bP5AWKT{vp#pdWVIocdgLifCO7M_Z3$IG1?pJ{dG z$Y@5uITMwB8I_e*4(blqonZl5s94hDGt&I~_F%=i@0%!u%?vhQr$3`He#W+J&l15; zUkZPQV~q8(lzhFGl*ia@z{b;fv8f_kbnHx@q^f9Wr=RPRojoOF;eNFVvpFNWU@v!P zF@d%`(gBe>Nn;0VKMp}z%-=~*>o=KoR9+l z-VxD&rHn2GyEdr;NaOKwl}Cr3g08HhCKkQuST6O}b%sqxmfgE~|K9hSI(uEq=887n zUaoaM*W=cm0)xNISL?M;Ct$wAkG;-FW0|lG8|w`rn>&a`yJp-1bVbZ%n7r4Rjr&Je zg4_4$LktyYy{f&_gl!VzIVMOhyT;7+-e5Lbbx*3NgJ{yQP9noa1oO0&R4%~Rij1Sg zK5nIOV`uLD`X(h;r5Al`tK6;R#9sp)+EAQ?>pso10zdg;{3tNM`zi=KfoifDKpdp@ z&BB)mcMfZ2_!DufT0&Z`#G*b!t zVB0pSssXE*p1ryOYd+1bx<$>3NQZ{Pk;L_yE8~rG6`_G=XmyO(6%+NYWfYBW6!w_j zT|de@5%cm(w@@p(p#!09wym;kxHJ(v3E;e3Fm}E2&hpoZ@AxDKgs_GQG0pW!pIuHJrX?Oe~6S zpO>;rZaMzrA7ge;*uGhCS3J~`J4>sx;ud8n>uzz7K~Z~%wV%@c_1 z17~|d?%bd5WCOuxe=qh+GFdYJaPa@Zr`v$$dg3|pdmaJ7TcEeoKP~}1o&FIb13Gj1 zhiqoZ>2HFpaBbOI_bD$6lNK&2ujNBIp$(9;XzBpQ^KwrDQ^SmsJ=1AJZUK3a39;xZ z6|kuS|B~vDLrLdqeOFae6)GS!&wn%~+A6HSa31a!h)P=Mlw8O=2^aDCGDvyay74^~ zNL6yac{>_?lI1eOB$Ac^du%=lYM7aFDfzsays(@lCV^2D52QG4{=@=@c=gt`k3@8J zF8^ee4R`W0$9nShE8WsZvhIsj85>z5SlSKw)3$G)U4Vge(ssQR;2CMV703`n)JK;i z$e;PC&q%_gI!a+0x+jeZH%$;IlCBuSb)Q?ZIQS44Vi^z7qVC_I9GMPCwie zdB#Z+d}Vnw_DQgH#GzGu1fqqL_zzO={z z%iu^ZkXQ|?g;rz1wi1lLXW*#=+kZO)W8hZFBR1Tp(=G@em&*m9nqafPul~%Fy6mqz z8tlKMf64xPDx|1FNl!mw{twgrzA0oAg&xr9Z*4uh9L^wwbUzj6`!{XbLkMn@Xr~mj zhx?#+5{0{Rf0@^5YVok!@oOZi7ORGvgBMYA^SxPz*k<6LkGCr ztGS5=iE(|Vi-(wa+$!R^4~hx<{>2*wmi7?bIP?UXj9W=WJS{P(^Sjg49P6zMGdb05 zhn6yE4vN)D=!2jd7wWUj(pft-BJ5ur-h*P)4jBUk>k3x zXVahQ9ivIO+Wz}>ecKE|pw-8!^}>*kIA7 zKaLN=9U-<5cX27216#wLeyWy^>88tLg7yvM}Ej_ zY}sD9bCNH%ai)ObmHtIEE!lU-QvTXVS43=l*Hwb5$fg@y3{;{cCZWCT`WCD8i#&vg zb+2-8jZyNf>u!cb0y*Th%Xj1s>2m2r!c=YO9{G(o)xxt_!~pXv%!4*d+yT7pjku>a z@=%_0t&uW3Ruyg8w-si-aNJw#j=pO#_j=NbQDoXuy6lf zv^ck!SoVd**nOWCmTQ*zdu{#{Fh^SRHO}csnM`J(2yJ5r++f~C(S5DSNBj1v4&qi{ zF?@Vb(P^JB(sHO(wCxwsCf0Js&CR--PDC$#g2i~(i)b#8XU_BYB+%X!Tb|XLte~ub zR+-}GiXc`{88%8n1PV_qAx$CB?DXI{s-&M0@JQ8Xv;9eyB^ zY+R2dTH0c7GsUKfYgd~ynL&FcMk7yszsgXTT);$g4>QMFqw)jDxYD}mX!(HaZtPcW zS$3DPSaS5Tlw(u(u8-GN4d`}FE?cVyv$H!i#w#xe3d;II2y#QZ|?dW=Y>yL1Dlh!lK~4?BAJ~{R>#~64(%j5S~^E`j+6T~`NoJ$@3lbxT!AK*^~7M`d&?dF=8rcb9?QPlDUf-b4{@oARVcoC2c}|+$#ePe88@#C%v>|`;pbaI7VcjXk@nQ=my4x4Kn-fhh zUB7~Fm6Y=Xd=_|Td#L~e<^apO^Pv=z|D1#-mhHqSQrbNozdL=rAx8r`yiLdfxMR5c zcPPJo(_X?v%kO^D^YQ)gDSeSU*W4r3S}O2nV&ZOw-ZAI%73yKuPN_(_Eib&`yi^L| z0W*lXe|Ej8l*n4@FL~%M$p_!D$3EO?K%6u@@1!2ysln~fR(H-v;SQrtwl8-uPc9~lwJb@*h&N#jw4;4H(@@`7^R%Ko_Ku?u1A z%501`ps$x4oL2S{#@5u>?L&6RrN~$~6T0zeUHZLlPgzYr4aF^*=1$2Btvkr} zmB(}CX*};7sCkq4n-J0Cjt{h4jHmg*;U~4sdt9m$m%%{jE<2liViH?t4)|Ma^*ie4E zZ{VOeXHxZ{aGK8T^yd0i`;6`0)u>o9wJn(^)f*?vz1@NAH7bZ1b=|jJ=gH_d{8sWS zX(}9=dJtFUj-A&WCkrB-Y0MGfLr5T^l=7sScs*WbKwqB2XzK{P$+#&Nl-^&=f* z*u3zbW4j;_#=JEoo`?k7MCE;TD`U5o4C;-CCsN;J05qnO9im=KFdjCz(9Pcpxl{qU zjNWYtta6&>x9t{OiBn0`H`7*;i1Td;3xCt(#v$t#QRkwz|Hvo)!oNh~2u)}*Pq z%(xEGVayxwQ?Q=w&D9belhLL8i##RT^=TQHH&ED?NOzgpG~wi>63J^uZ%Q_GdCD-h z=M#a@@TGPIvZd@|(uK*KT;z8%1FMtr3hyUhB=P`b&pF}%yBNL5EaH*@1R+S1n!NVx zf?PmdOW|O{lMia0Kl}^!R)_<{Le3}>UA#NNOqR= z>fV3<66|6727*gCp5VCu4=J8eaxky2uO|glGM&v`yth4NZC_Bza`7LsWQs3pE|XAR zC%E5jE$4aB>Yp!1vS8SY+eoSY%_nmw8Xx(nKwt+AJQyI>kbOqEsxXa!GhGV>%beqR z4&40697>9m2AwHq2g`oX!cQT2R>kZ!!>wK2b&X5fTUd~c_X7$EQoihph%~Fs@@w49}H}-lYH8wqc4{_9Q zPe3qMla`jY*tGO;Ph3GXpC3Ed7W^!l!GFbQ;aY!1foYCaNl2Mxx^RUVH8u4klEl7j zHDvBW^+><3*_dzV)WT;?1>|mU#%=OoBiS*1A!Q#Xl1RItg{YK%hjev2?7U0r@;j!Q zD!ctw$M~I0B|v2wvPtAeUqb+n>;2vBnXIOjF18}d>tY|tqfJ}xq}ZBwDh{iFOa{eX z@U0qLHxN>@$&JczSGjOOd0E55KucDNV^u+kZEGJn>D@4t484;|2<$V*cHM`4d3syJ zH=|&qv8Gj3c5cX8!^-9=V{JiyN6u8xPNvm1U1rE7UvR5gS2-9Uy??6cwRO}`ein=T zvd#&SPmvELZQHoDDHq_cfW+n2I*id!wR%h=C>gefT^lx;I}Jr&)!0q{oHV=}M#i~p zBfLIRqNi^lVBKK8z(`wDYvERDV%h&d(Du+?s2FY_!t`^y7m6Jc!yYayD?^Wm2xxg0 zJ{&FH8~Svwb!U{_)&L|IKpkT$2QaQ*lPiKE?3vzrFl3MGxP=Qm1n8GQ7$f_FH%NNp zvG5Y=iLUVT^k~NiAeOWN-kJueYxKf(Em=~?(Zpf63)Zll#iOyI`WbcW5%C2gpNY^T zbpCwJ!I+!}e^>IVo2 zJx#)hqYGew0anxKQE9IbdaeR@Ax0IWD(KU`+v?%;!Xj5V>PPV+)8s03|AgwHZZhSE zlONepHgn&@py(_NLTn^&=hqmsLq0n?6#=7*7S$Xndp$QKasfATFR!$~zvoWM#T~%d zo35}_hkQot7!NZfsII;4$5x2SMm8A9vQwXT>zkPO(_4*?fUVcQXN2%+LOq(On@MQrNoxP5>^7DAO|G)65p;(s!J*x{s0-cKXUtE!lhx zeKnXOW}$=zG$ld7W&b#8@WR<@g73j3foGIML3UH~1$A*3)gBK7-_no`5g?O02Q~cg z?aM+-yIOL!$|`?r*n9rjoUZbo?cF;ywjRN%25wgZ>TFaQM9qlh4FR5mo8hinL-2xS z_)_q~^T|jJ@MNQLq&X*2GB`gfux+j9Mq-9U;_e}Cv<2~D)K8i5#4Eu3vE)jKx28d& z_d4{T-PV1AVP}CNO)=qmj*|p}u?36Phg%n%SV>%Np1EygYV!0zdTsxkS5A=$Yg_(= z^mHsDZDUZ)zMH{tb~qmuQpXEkpH_=3yhEmZ(4Q_iGcJ~*Qn~rjCQ{grx=#(1N!%Rr zd9GDjF|xtsQmJ7Baa>l&rT0f*zmwNAu)=tWe!i={Nr7OQJJnmoE{iw$OU9C8zJ4=i zvOJort*2>=kNDK#;(G+N_x ze2TistX4;osC|U0as=L7XCAjfqPKs?Sw=L^%^>sbl?HUh z%JTk~?+Xsc@H_4sb{O-M?ApdDr`EZv8Z}CKIx(3iE@RE-M{nXNAUL;4j9UOs^|Cnh zaswkS%2@Ko$tHqgIq|WW0t7B-=Rp5;6lOkz)P!p8*M&P61uU$41&&%;wVL;cwRZ+u z^&}KC1YeoJlIF8&D(kh$2Pu;%`Dneky*{f7?1x8j1{0dVe^D+531MyTfd6);76+DIVm|!&Y_O zNlG>qsDO0)2w9jc4KI#$<50^Ts1k9-eQSQNJG7_^L|FS3oru(XTAhk_N9E2fb~z?a zek(OQ3kZxe;a%Be< z1uRT?{j3k`Rk>_u`Hii=eUDNMVO%%v?0_36o#oAbE?FBHmodmAiP)IyRqKpL1!G<6 zI?ZvaSp9m*3%#6%_F7Lz4ANXP2EO*FHA15{a)qTXeyVfaax`21h>tgOP?#q zLzkQ2c~7mSSTSmg6%7h_@T9o3+rkps2Fc; z1NkNXww%d{S*Dwl&#u^o-Iz+BuSHAnJ{)&j4mwp`?NouI+3nNqc$GO2zV;$(eO3gv zVrlG{yMpDZM?c&()7>5$tXv2q#@c5$m~)jN7jd>Yi+cUMzETyo-tx8W-k}6kf+=pK zA=P4N@mgQs9l9@(O{w3d>v1nKZs7#Sn|mXaud_7>dZ6E98uqmo&=r)ZQByX7rQ<|ku33i|eAR?2s`w@IqY zvxcup@SN22e#YG48$3)?aW!;vk2vYTLXvp6a;_#MhOaXvjvWz?e1l()saQ!;T?-~z zz2S$Gbw^0Wn9a-PS;xI=q_RCdbpBU&>28OvDVdlmUjp^BJ0gAL{xRjr3 z##!zyWR;PK6SjW%G?Ur8hz8W^h*=t>2qm4q*=cB}gIkPMd->>BP~gbcDmL|sPui)d zb!;FUsqt7=^np)GL5Jt|?6w*|*?CE1gwfw7Ho(U};97B`&LeC`$+Ghyy+rU0J%#>T zNhL`Rl4DE3C!9Z2wV;|*ui@cwRggiC4s~0$H~bEqlF?u_qK0Ev6`{+2Un> z!mhNs9ZPOwYIlTLd5Ul@MP^sPmDf#c!hh^(-*7Wj>PdIrZKgeheb$Ia_K&1dUq?IB zqHWK5H&3}eE*ULlQ>ty8mmp&*+#!lm*2Ja^C1|*klXL{0WC}=wIwf4zxQZap$LGY_ zZA<@FB|acy>%ky*fdFp2OnC#9p5Hb#t8f5U7Ee+L>Yi0bEJ83?R5l4bN*qIv#30Jk zi`i-@^yH7nRH0*ezDsJp4F1U?@~pLHWM}elHCthAJh^f~?cY+nYbU!MmB@(b`E9?| z(mr+#7XXl<=^6>|m}=Hk1$L{GiI8yd1Is_5+`E`acURQT^ZuRLFY#wZm7K#u;IwU2Uyor=l3TD3iNfp zNpMl$|9W&`^3DKO<pQ{`6(PnyK$_@~7P*Ld{Ygbl|L zH?A9@I0X~#z2?wHdi+fhVyd|dc ziYm8uQ&P+n(!d`L@``p?+j5<6NRkFFf1(0a9r1}%f$EW-k`o^?_i!Gbt|$ZzOWOi)Vq5{BThdNhjfFqR zVjzkUntr5s;i0Ga>jP?}crXG!BQ}2EMBamK z7VdoK(e^Kri=Xu9TUc6l-aEl#MvS?q=VWuuGn5D#v$NdYTzY&m&yc-*5h4%F)Nc}M ze`P#zwkm_J`!^l(NLy<2@MNVw##^$;x#!Mv?Y=v=|1(;#*L%=tlEqD{sH{LIwt ze1l=GYW#!Znz(;~blcOMl1bv+gKq1^y3v`((EET4f7mM-&#wGFfW9CIiWv>vrvn1` zzxlC=`^OqjfUa?EjY`>G9r(G? zE$!`26?*QYqLe);hS^TAQ%7GyB>)$7--vKXsnL0bLj8de>-Li`M!ys!Exs5V%BfRA zKwuGIkoaM3@5YwVXQMl%Y=0=ZENLh5bWiT)kTFHj-23d)ibbCXv^owy-@7^=mOpeg z2xq&lU$OQ?SC>D^ZgsdS@X0C1M5fShAzbwQkZ)liIQcgX5WA3fPn3Y5|5~oEI?W8( z1n2VJjSN3Y_f3MkQjviGt5RtwJ0=jEOWx2nI>vBE;CE4DchV}-aI3e=K59awF>NKdA42S=9*J4 zX`6)mVc5=O8Gb&VHJ8irjwOsW9=hS5J=sXw_^Spc;L4m>LK1Ouw6Kd zmmOCG_)@ShFGCI^))xZuYH7Jjn=YKCk}6ISL_`!q*fL7@^(fZ0yDGm*Cb%9ioOdI* zRj;z5?AeH0ykkjiH0Nz~sU+GbESUu_nE_MI3gPo`nyQi~A$UuhEpX{)tEaSQdt}Rr)1#Mm$(%LYfyf)?2H&e{j)nRlBTrO4~qk)Dz*zo zA&|vdWwx#5{#0*>RX&1-qL9vRuP>BI=S_)|guq;Olte|KKd;YL*gkGsH+3NP6nRB~ z&+`9U306M_!J`<4N3meP@ImF32zGF->v$=v*b<6eF^te>dHq~SCL znAk!`gw!vZ3F)Bw)bkq`51x5SA*!4r>)_@}HQJh;FzsXfHGS-0X4cM!)-D7DDR&+a zX7V)BRO$4sDdoLZwK>fHl=s|zT1-V$M#;X^e)U~lO}>hLmB&|AoUtabaA3~UV!E@B zJNwUy5NE%^?Etk@s;Q`{PHGVP#k8STfI?&gSh7Bt7Xuwm+l>iAekO^1 zKLN_kpeatGIgXlG5bb{A{-wz1Ha(44$JFazxHe7h9880Z(Wl^$mG?aCPB)LNn>$t} zobCcs1!@YyhVQL_WEZFaFCh8mqmib~9N{WeuyLY~{_g7Z% zdCO>|A=`y(4>p@&mDZ5%V4EDmt&w*N2KL@IM6E|Jlw1V`aNjVSWTLwCM!7HyvlZ5B z;o;cAWq)IVIF#7x%u`>P)+vBQvRV&&!q=$lxDNe%Ow%+k_gP!Gl1w8wjC9C~vF=O) z>LsFPFGs}Z_$l0LoWJ)1NrcNAHVxTp70|P}KuRNx?*ZZ5c`L;R6zM@Q>L$w7DqEzw z{0*Ep1Ywk0ke89`I8C+lBE~A`3MT?R9byQT9Ya!18kD#DstKJ8dp##3b4qLttwTV1 zTpCK)=T@LXu!4kffJ_4BI07JxK!A<;yCWy=ou(CBsX*Ip-dCNw8KQw&JPSKIoufFb zbsWS1C>@-**PNrVpEEx3;Ch1^EPd()FC&vg^-edNlyp8q_uOW0ReQkjvdhpI#0MQG zvXl^ugYjpi;#`Kx_t&-~+R*%HQ9re}t$W9-m5wb=p*wZv%bnKGr+Clk%L-3Jkdl0pMrd4mP&vU^!|A!TpG>^+!H&I01;Mvsf7A&{>RH~i*OGmxSd z>u9mG{(YMy&o+p`e{2W(i#QWv2OE?AT1E8$LyqF#gqjOiBsVPG#=vl%T2a@P=uGsz z(lT+c+>g6e_pKsrOoF$x(5mHBgxf?xPjqdHg8n=}4_w^k;TjA?y6ris{W!=CEQq7ZlwSZ{RlU(^CioRmd};GRQnc*`iwf)=2yS|~8KiS)k97R3NdKcR=whw0gw>BD;&-G>i9kVet#3z`7)57rt7H4>(7coZ zh{a&G_T*+Mw2?zBa+;T5`N?BKmWJN9n@uK1MrC4dvm^=NBcLpYWt3C@Z86tVd83m& z@xMl6u^dX;QdZT*3%js5zDg2GdUN=_TtJ1Dzildze!^pC39FF-laIf=bE!TId;@Jr z65Ix%Kr>!Yn2IW1^y!mxX$)ab8!BQEl(7^Mg0|Nds5*=zf+H%|MAN5dGJ1rrBlFSY zwG~U`Zi}w>kcl?BKj&9lZ1X}0TohCYTV}kOQTiKAMYx$n>Z?PoEjKn~9Tvi(OiNB4 zM)d}{D*y7EMN_vYLy+I9jLYi9`PO|VKmK$ut$xG?p z2I97N7q5L{;Ee(Uv7KXn$Z4EbP#6;3@a=BH!bh6(kNkIB0iiRN&7efrGAnIxhC_81 z6KN@U0fytC%(2~dr3=VfM5opWXNVzE!br7Fa+#qYNvm^z*6DCje)M`}#XL4&O9euE zW^mHwAcDWo4BPm!Y^WtK&5{+A>g?0qL`=q<)a#A|hVy4#v_a2g6eu@`e22SYW9pi? zV8mRhlRby2%>>Nw4!bs>u&DG)qAJWA|5rwD;hSn&C-SF}iKo$CZ7=d?hS&Cae0=uM zfVFYpDhMqM@&U)rWHMLDYuAL4`ZJD?4LD7#e)CCWuIYQ)#^YtMk1|=fTtTr%t?w#= zSpjOwbRF2W27NeUY&F8TwFa9GuYH^f{WX$yj6G&?7g3OSa@X?eHj3!#C}-Ws*xGaV zro#H>{-IjC)3{^EH(srdZmUDbCRoB_YoD7ZRp0*H@EbjfJUxMf!QJ5AvdwZ)!}$)K z9ChZlSaZtc>hl0}QjUbkog=>wVtHgMcMg~K5+2Nw=zlhRkfekR7O0#gl;IP6e}YK6+vnqmfT6U)!E|ZJ9K@%&_i`_f6KAY zM~Nyun7i5xo|b8rp@pO&aON)Xy)_FTt^zvd>acm}jFtJzS+{-YOc=XH#7|htGz;y$%FULi|9ixL99g zSnBFoVtfhxvJCUQEk*?Wm|r!`@)7_buHrW-cCY{tXuSkZ(Ev#2Crjr;PgX(#0n<2D zSwnZ;XQfG_u_~-J!`3yQpT1bU7VZSR^LH(PIwd|zASC!4t|1C?{Vg8)o&Jv5Z10_C z^9sZGdIMQJGJZ#LQGpXT1OizGvh8@EE_N`H`qLV~;C~lTJfl2{J8JPK`KbOkq<5016B|6(t|6@tu|X zH=i8(P~me&|A3GH2t7c}k^})!jBgme!kRAx=s{gpiYt^9^f!bI<^@kRz$n?}fV3*j zhgJ8#iVc3NVz8NiV)kXpm4Ahixxc*Qe3qcc&@(U0-e^AwlNV5iH5N!l6SL-o2A&`T zo)G9+Q^Kk?p;!5=22GC5W-}m?Prd}>{j0T<=qng%h6n)HvPPT}zg6%q*z1wwQqNU_ zkKxg46>d%GH+~~JqJXqC#+}W%`vQuQEzYIwG$0OOcihd+iFIEYV0;_bD1VBn1^*oo zS=4kuqF$RGFX}$~RbnvAU<4Gui6}2`ntJwBIjV|(Nbf_?lE=C-+*3R3RAanH(&{R{ z6l7nV-$q%Is%bZ&8O1$rb$!}txbM7(nsOLvs=~B0EMcVI$Rwr7)nf)@6=_Gja4^yz zLoQjLoNBrAPQ~-9O?_v(dB6f6{eO>;yyz+V0eoa%72@y-c6`uxMIon6#ICccw(*mu zQoe}in@CCHFe=aGFaB05Bh=TtKrC})WIG13(W>*v$r@)j+fJW$8{#%WotTwIpzxv1 z%CED=-aaMXEQ6~Ul@|re4Jk8A(7rItb+gUSyw^!b5aZql{=Y(s{)VSW(S{0ix#Vt! z+wO2@u&t$}V-N>^X=K^|f&)7zv2acLF?mWSZSFB%i z*0R5+HA`>uV(=@&%IYMS!@*-K?Y{A;!%rJ2db@4Y2pw%d^P6qj+Si7EppMPFdb!{NsUKM8 zMkr}4+rLF*6nI3&=M4~yUGOxMw^yK#jNd(($tKy6d+CyF)v2A3hQZ2IulMg-Q;>}I zUvWO2wEk3~lNW#xxrt2LkMBHGYfk^HjBSdgCVR0Bhae;M^j)INYgO!VO#skFqxl~m zUW?uQqQErX+CqaklskcY6g^z&w$6EF9RP59w10dm9qC^_^>-Zonc){epawZDc2W#S zV!o#ln7n4r3SkaBvs6g7-${ef0kqwAHV_@@hn}2?{~QDMb6KYu?Nb#ldRG;~EcX(q z=n5+C+J0dnw|qW~G_;5`GyJ}Hj>G1MQg7R5XQY8D4q1@N_P?bWhF)ES6L}TvkMy_Y z5GL(nj}szOJb`s4mkJaNQMN*}c^yyD>L5-A!}Z#fujgp?8Hh!P^vC2u8fhJq7FSHe z^`VB#>!XZLz59~&*QjW}n)ls0#jTDD@^38@XsG*tx(Tb;q<(7$VD!!~fTHcZ@X-2r zt_9)Q+r6!w*gyZ%&4*6Te!P^hQs!6e<3m$RapM;s`5(V zljR#7(*H*=t9f`AR+)2AE}$qaEu0tgFd!5-X_`SzG_-{+B>$O4Q3saU7G5LkvjjTN)6($aKCJsIIWki&}QE7Ol&CAi| zZw^$c0EH;aqhZUxjA`^ISO&oteOp@=)7~XmftF)yB(=?@sU&P^x4F(MUw%5v%A!p} z?DV-iYb#%ZtONZu5)4y=fSvJ@NgS~s=CP^|MoedYMtP=T=&Adbc)1F;i5VW@WxuB6 zjNWZGMl(Ym&b{CmZT0DFex4kAjf58<>4p{Aw0)`yK@C7`i@lLHc8Yp28E=&Hj=oY; zFY*Llb%w*@R^1FWS}FgDd++MWUQ%kP-!8pNwT!Ikk4iy+ufYANl^J(tg#QmNYY!7M_1KRqNWe+-p)PBRvRzRE-hK zOl+#6s(R_hfoZzghCI=6U^5CtdrH4(>Mbd4`Jh~4uV&X|8GHai@;A9XB!?U=^}gv7 zcK;0~x4kFj*GtA5&Rs7;{%mtvfb~ybT|F#KYT%#N(~)&R$N(oniYu3g&EDvVKx)yx zR;etV%=>7XethZwx$gfNheCsleI z_5{b)_Ot}5)%)gCt=k=Ni=ibaK4 zKe&!64VPMnmf9q_2(jY|93LY6fo^p9A<_0y-NLZ7I57&ci~F;WgdJdPX2S=88S7M? z9|BJoypJE1z}E_jN`awP3U@xkRk1*zZsNM2-CJMwsJ5+42Ls1?G{ z+(Y4g{QSKmmT^mz-n`D%wj}t}W8ID>LFN!Z%f4As*a>U0+IH}dvQp4vZs*Gj6(%8g z^7XEcENM_KqfebC^PsAvI&jocl^Y!QkltpJ3Me<@5!rBRIQ~|sgD2+kC1|c|ssRCr zweJq@oxX_sb0H_7_SS>S<5|RW6pDou@A})^o_jCYyuF)dpR**|{qwin10@ac6Zmrn z{o{q6gu7#3be5J2-DiA`ZQR?j9Fw=q>Cd=m{`ctFd6=^xLFAR=I3M0i(E$W!zCpy8 z(L*xg?XaytlLJqozT$7YCB6-Wh({SexF-j2pI7a6`!Hsrl~a{bh52|&CTU>_Ulc2{ z0T6<26hJynKBZRPJ&hB*2=KTYw>J?{(HBRr5Bp1<0n z@(PF8DVTPfo?D0xCllSnr_duj*<`wRC{~mf!^m3d3(_Y)Ium`?x^wZIK0_kd4~}w{ z^WQzVH07DX&G+eQ>kf)2(Ar||*sRoXyMfmn%GMh&I#FP*`jnyZ6r-e#ZIU$R{fyxS z*Fs|fUpQry03l51w>3vUgc3wE`Aj;7{%c8A>5!DNr4pRq+)zR;n;bB>0$6*5IosJ_W ze2-fF?k7+2_h!HxCG--XsBoOr>|c|zY!|p>Q?4I6-{Pqa#TCB5@?N|c3+GjY;IJvl zCm7l~?Qv^pb99PNI}7|`M& zpn?P6fAUz@3C700a~p6B+789sRA(!!Ez6UBUZ_g;l_{+5Q;PIIT}Z%pQyBkRF~5uD z48Gn{!((H1wu{wXD^2wE$Bk!H^bH7Gyl<9ntNJHdJ<3MV7#p2hbX}Se-MeRz4F0t{ zl5#*ktlDSO4|$_Uhi#Yj zqNijiqBk0!FvX+e33^(5^27yLB>q*#>W82|6BBX* zV2th&0M+THacBMhumk(@#01ZR{vcd@!Yx_eE`L-4)4JPr=h_lF|F3HNQ_TM>UE>1& zD_wIa;r1JkpA7tsp#6hb3HlO}RH4(qApVuvPP_E=le}h>3UI)H4WAE{76&q^Srb11 zp5uN=@5J7V7<|*QQG8SF*jZR!)5WSQzo>@6=Iw+!hdIBAP2lKmqCwOWo^m+NF+Tsf z7qI&FkAM<`&FDN#j!YyApcW@ayNb3>Pw55$%!}5=|M>}n05^Ogy-y->ZpTp?{lBDg z70;N!V58_|A;g&n$o2IxCh3vi$;>~<8_4zseEJ7e1@JWfxC6fYA9VT3-$nMoeFEU9 zL#8-8IC>0-GX9al{SS9+MGs^72|hPEV!bre{y{w;Sys4M?)=A8tx1mL>|=c9(<*Ls z_^*Qz)hm476{x{9`(^u&!!vg2jl`s{UNvf0jYbFkvbm$2dEg5O2wu{%jG7}~h%5az zGa%`G(8(m>6++w%ly!bs#a(otnC#CEk$MU+armVT5%JZikQuF)oNN#*S?>v6-;a%m0t{eX>vrqVU!VXUX zhc)gR$L$~(x#Zr=m{g8t4|jODz8G92AD-QFp8b%XpuS3#p<`;nV^Df6nkM8 z64e;^$@BtE5;|Th<^CrGHj>%C3k+@WIcV;yse(U*v=u^P(24yXLyyDffF;w&p+fmn z{M_b-@a?Y}5ae9`Q0H;|eqT08{L-yn$a*l7nCO1mm00FZ@!sK1V$lUPrkylb4n78D z?AlW@a_kmY1Z(UApxpF7Bt2&UKIh_dIZ#U^iiRp(7@W4By?h>0%n3G&@;CVc19zcW zi+Xv5YKod#tNLRXjIOU1H9$Z)+36<}AHySAuPFb=?mq!#2s9UC@W@RvR_+{xYc)sm zR>pDf=G);?YVsf&PzB_IY(<|!#?MlSn<3$(Zf$m^mDAK-4wP1S(R0};QAV%R8_?sc z|ENcor>LpA;qWHc9lq7iH=F94bF-Ic()n$_ENeh8{twL!TBiG5cZ|I?8HLDB>Bd1b zPzwybw02g>QWCcEF$tgAwX5IU@CA*;+hvCjl4U5wF4j`Yi!Mn6-)y4{qkkOnYow(> zep5$-oKcmBeHE4!M;6J5T7l8f9i+Y2?5;oyRPLv}ukUsorel16&^HpRmQs9BHP_j{ z8iw8aN3N4TNn1Z?zKMHhacg)v3&?}k?gRp*;mzR{Y9~DD6f5TiuwDe=)&N>6LrA52 zUq}>7Y4sfa?kPQW@7c>2$oEf1sybcO@R^I`KyYi@p16?B;1o3GX{&~Fsjw|@ zYSm;|Ofm1S0tc8X;_Hl??Q#o{SRdi>nTH--^&c`(EjONS9-tH1s8b{n zAIG-La>PX*3nMi6kd9`L@WJJW`VjR-?)UCr6q$PEZq>2}(!4L;%*v)>c_NSBNXv5W zyc7J`N@3r;b22j$yL`ABhOtsk%)C~!Fd0g*LwX{h{zR65uLdYC7=zx1Wwh@7N^RZ| z+t;235DfYr`^x-k)k1p1bscW&iG_NOUubV1IJ(n6wkH=bjV|4`7id-}|K;Om~o z>xY*js!CcbEQ;R&Yb6XBZcTJf3A=W20;-%8@q47M1tHN)Gl)Y5QXco*9crHNBS$1N zp3u=9V(z1Z&apxA`&Wxz-)i$GHZ8wzpSaa#kj;~Js}>@i_gcn3^}uE5jw*dtioEgdL+&HKg^+EVhr@XDk zxboJF`kLpGFT3@~z}LW0!pfrsi*PLm;u8N%a`QaKUb{-IT<5NKd-{c+!5^EU(l5b7 zLT=ITeG0Ta)U1iAVHE8{BDtlm7eM9PU8`YRgH?iF5NL} z6M6*6KETpmn3p{w9W4PHoFDA@>qMSls1gDSA6YZd*&|s}x1uOj9yH(Hl(?hw?q#1c z1iW}mAw59@53M|J)u2Gi3x!li*AmUDsLU-VS(7ea5r&(>-TapJHy`aKlSX%3rOF7} zq(4&>ycm&bDOIFRXjoh8^f;_4%Zx<%8?k)%WL`xQJP(}J1QFILx98>9CHO}YO`wO6GDy1PRc|l{_^G32IJA*{gj}M^j0B zHE41;6yD?D=cBVZ64`a2Il}Hsm+xZx>4s(4{6MM^(dq01ZVh?l>M7Bh=sRx zV$yq8TaGdnz34D&xsL6bV}Fc~Y~(%eKHHD6WviQD%HU0DWy({*rv{7$36wO9;a?AC z!%VK;{r0D9%CN|4<(RC*XVjY)onUbC+IX}&$j&}>Dz zZ9@w0_qePyZd0<7yXkgEU3Jx!l9w0P+$d%*G&3@Pt$Y^k#s8|3tZzD$$f#)R(N3kM z`zA^V_Y=h7wz0NkqO~CBt7zSO(!ouAmP$>yDDsDh2g&HIb5N{S*k5ToQY+l)bVnKT zSqL;VgM>L?X#Dj=0ZJip*flCskz4`EPbbosP+uLFrl|;R=4)yjo0ZeWYj$Hchv=in zu+7)wc{y)d&M+LMwe;D_KkZz4ro@<@lBBMo^D0jI=%9#zobQii^QSzQd260;Xu479 zrGEhCrJYvb*UchN`!(G!5;vTqwJ!ol##h!8J+yAud3Bf)A5JTNS+e{ov&onH3oKe6 zV7Ln}qskwwGe);&i99lI<00?jiCZ^at2I_zRZHZv!*Ji?3Lk6AeXKOFe>?uaJ5Ruv zOKqw+<@iPx&gFOmuZ5*ih_tyc1N^ahZHwmxj+N;BzK(A;L`U>h zqx7TMsq)ycfo(V$LqRo_MMpcfHR8Fz0Uh@Qe#Ce;(p9k!X)HgK@ubE9K+6COdjB+a z2KOxL;l=^IC|RLHkIJaVS3GCjqRMp%UYr;jX9adi(C5X3k?6nb~V*nO-)^$0usHLqfbo$iaFHIqY?QfRAZ`S9YEoj7AlDHY6 zB6Sh;Z99-_7Hz8Q+4awZ$Nx4ETb{ISRe$)n$nHfHVC4X;9}kaE;+R4FcsEo0AELY& zS*j~71U%NtRG4UVr0X~+QoZ6yzoiON!uQHN9%N0~0eVhciP&jqWm4rziuU^H;{0uE z=gMggil4#S@5e^6em6C*Y_u7&0mCXIT}LGbBzWw`bidcqmcV52TRYU*GwmAYr86MH=cR zNJl^N_HBUeWF#tfZf4WZWwJpP#~Gcg1;Z=08H%B*D)7_eL_h^L90qdH!Q*EeQbV+^ z(2d0co+o&ArG@mn=MzA}+e@JcpURer-EHf3I~)g-YQO^q3jm4kpj3<@h@~q5Gar1{ z3k5d%S%BCF-@V1;=}6uSg8u-YNoMeSm+Zfyz?ZwSqAUHHlY_LnxmGSP90zu>gwp0M zmRJl{4EQ)?h9Vx(A98kfZmE4tOOhX)Fo13AQN0RW4B*r9P9u;4&<98Yl(39qlNdU2 z9kcg~cpycmXOH+%SpTuYE_Oq7AjOCWw$ybD>e)6u0zF;o22FCJxVo&U+olJ8sJZ7e zB`5f?<8G&X6vXNf3WyHOij*1Y+R7Ks;}eIf&bAX*-((ejw9*8R$*3yCtM%893=^C> z?`^*B_YXaZTUlS3BQ<*siX;(!Fy#ICURL<=OpygNu-cqf7>GimFtR|{kw;gy7&&*; zJ8H^udl26nfvM;Z+MYLW4TW`WaX1uH?>J{~4Zs)Ra|5_JWZZT}{|2{tm7*!8El~od zA>U@Ty*6O?FVpGE+CD`SQj>FLeFK+nSju9>e(ElZX{(FO|KyLEg3Zpk+Scr9ybap^Avx+;y4aDWjR>t zM44xVY~?wXxKvjFEPy=j<=ID(c^l^U7>BeE263BMsrt{w2}!qT2$qZ%Nozk*G| z)6`0UB}#JGu4`pb```ta!R9~;31^qtAJ_O3oqLIWrA(~`=RllTzSu6vV#;|@>){J* zgW;d;d8K7K#6a?>%~fN6xV}rt)MG}v1^hC$%G}lOM-aC)7|+RF7QljM%Vmzj)`P_l z)pIN2oV!(vx*94b@-J5bhkB7}m&9N9iYW2w7xH+zAmH%)yLi<*?Q>S~xZyYI&QQ>^Fj3cS^mJPGi4~pRUjMH^{E+1?58?#d+TDRzB->Was{2j72Xrs&JymnQ zg(=MnY?xt$=sjKb|&Et_^1mR_@jtvG5A-%Zihf?ahKV@%%@W9b}^F6x~23H)SpofpKPK@DgZpg5FSY$y}m8S#PJv%v%VYO1s2Y)on^jiun4 z?~`r8W8N%)XvK^_kfL9-=VAM-(rQXgew~Yohg7joa&e2T`rYZ<^%LC@%6PvS>jPd5 zvibzl_P0hG=Y~K{+eATwgd2nes3QAL&**_9C}}s@cziHDAo;Hbri|7LZA`Ekwgag3 zdxZ)7oQaNJA{Xtn_(?cQg!}As zD+@b`=7Y5T`O7;@KCqKe1LWu~!Z~Yx)QS(j2+Th4oI94UD9M0M{}~cNKb{29a^1Mz zKW9IH=R~>h+wD2ax8N0t`6-lvBPNh-rUuhFa)PUox9gdczgOZhkA$IjhxoV$y8#{U z=5=2^k1@=#o%SMdNWzB&OqetoBxaDs0i!lO?eNt=83b-T14Aph`DKuk*m-lVo!zm8 zw}(*V@6IbDKHZl;Hpd>2AO54Soq*#Sj^wC)=EM|4TCzl5`! zRy_EZOj)BCFSalN(_bPT3TSv*67vIYsQZFvU?%UoEo|cO*!BVCD-Ym;-h@-w{DcAf zPz&s)C>KJBYWoOk3CmIiDMI(IX&#l4XcW^ng&+%1X&CGui8-GG8XZYIhI_IlY*@&& zy~?K2>BnX8WHLV0svMHV5TOo9vi0vAJz5;uao`*tl3b5~gGXgdcZ7Q1Mo?-N@q7U_ zHOwhK9`WdodX*a?ju3$whL+0cRk(WpM-4bD?7Ogt-2M`6#Wz{~e$edvq~#%%8Jc_( zz)@sn&ZG=A;caS&5;#EfcaPkE_W=E$IuC)4usqQhz0z_XtCQbw1RSNpE`TX6vgq@Q zP7>&Sn_r~YOI$5Ke!eRkzAWMG{LDd1Vx>Xg;{s5RuNIg*DGOc>&Fel3<}L5~ zaBabg^HlLQ!^5o>07a7+0`c>hv4|BJN^A%KxfIMe=(+S zgC(0v*aoJ;K7B;gpemi4%I9k+k3V(EH-3?D#57AE=vyZ7<&Q1qaP)L0mv77M2j?VU z?U8A2+$;5n{y@G+%b9awg*?wAFqt?-pr8$mU(j;1i4J}1Xi%$?a~5!ffB_v&>XR(p zrs`2tH1TlYXDf2~Oe0aMoprWgF6|q<&TfNNyr|!l*^B}HI$5d z)grYw{>4<>h*xZzcH4Rm^|S3s7e@mel5}<4tFTHN<)hNp%AQ*(mc6s}0Fbh(fZqr^ z*yS8>gfx&M;2mJlks#^|aB%V<0HOl%{v|KXOk5r}nuDXO4`hRn*AoE20W%&5=U!zm zsz3@pLx7?#-cI|nH{gw}t#-^fD#1EfcPJPy=W8S-Ev4!CE+9PfxVH1x(N7ygBsb5C zwQ1A>`3ANMv~bff;$K3?AGc@7`2znN?Lc1+@`U9~BZe*S7?LwV(mX@L)4g`aJ*KV5 zu5+lw*1lGfzxJ66Qg~3%S)Dx&ixcFe#B_leP1RUbERA9h_BoH2#yB%jvBRB4%3TgS zq+-R_FBm6$0Un~^>vlN#%ns+Q+JJk?9!rccEyygRmWj9yceB8Z~IX>KA~fb`E* zgaX_um4`-wR~Dn!TOUd|>p~pEPbE?orr1y(njNw3yG3y|dM@xFCrX5UZRu1qvzn=O zyc7>0g8*>U%!f5HpJeDRt{rv>vXGdZRCbMiv=MmOrh$PIq(Jy347^L+1gW@M{=ogn z89z;AqNMUkB&K4vVg?mPy?DPcFc1?dD$mmKfyYzp{6<%p0+FW$mHzGSRW3MA2=crl z?PzZ}K&(;D!yP0W=##9Pm-EpbkG5MN=#FnyBo2SlYa)Jh%so=ZSH)vRuoi<4Y?zgu%c&WUc3z zIBqHj;C8L!bho(;hMkdzByBQQw&vQ4tk|0cUq`^(2WsR>iJSA5?l~b5z})&#*!qTe z43puBCsvwfJ%V2g?s?p!m_eXZu*R->-_?pqahh&31_aaEltNrfYdX4jr}={ z5p7%bX^w;b+z88J^N5BqUA;#C=5s_{tMD;vm#I~1RoPzKE`#A;<9QAwq!m?1m31ZC za$edLp?h9Nf3O)<@bb~0LbcN_@&1(s4_(*;Y54MH+Iir_qA42>q(EP$Z#iB&96jZc zv9(dN`XN^FTnq2tuw9522c2>C2)9fZsZ0(gtFCSGM zJ~jzb@x#`qRiZGD+hKoh_jn-T$fX=R87Mx3^wai{3%11Z*h}OiOw?;^TZ*Qg=3Or@ zT?=H`a6$>1KDy*j&ti{xL`Z+Q3$*7;kSk!MyK(K$#jGpa!TKU52{iB4`(oFnGu}~8 z9VCFYni47J%fvs^`|>@P(NQaPF3vyJRGFjJ)Ky`XP!gabIe`QPEzwU@f3_7UTK=F? zdnVsySCX?Md*Z?SU6Wn6PAahM3!B`EmxuY-RK=gQMi|QcaaJxPz~TJ!to+D124$WA zK29)3yP84DWk^=gR%)K&c4h06Pr)@vnA{2&(Qlgeq*oIKi|}S{VU_Dc#r_1cx9^7HFTp zTo;}9y8Am|H;RD1o8U5GIw?`+r4JkqcQvgd2MR%HZ}cK7nyX<45q* z^9Q@0RO9*uDuhZf$9VM?8ly5V)wW@gg`@+ej%j5RsNysMG#}~G4 zquTvxt@%L{OM?-Y^5jn=dTYGdM&?p8@GI*iNr~BL#3Q&()tOHNcFiEVM9YOR!}zkX zyLa*@PR=NML%hdiiT9=3S`X9EVpXhqbR~l|;+4dbXIM1? zvFnkau78E%SBH^n8DLaou-o1}5$i#j!-c9{G{o=D)~n0+`=96zDIZ;litr-u+K&g* zKFP1l8Rpj9NzfIp`06O)YEqIzJ!Riz9yHwu92-delD&bMwWYhL^Xfo}vSY`K>~8^B zkjAJYK49&lyQ#I==DnG*c8h{y)~F+jn{D-(aw$DY4Wg!FVzT=wKUr#+Vxh5~)D}qh zfq8?lT&tqQgaT(pwDZ>@H*>7?v~L;ECBMGui~6CTQF(*w6{{*B2o-+2yz=)myTTiz zN3q>SdQomo#a5~uje!S&;iKLVM4?Y!n*8Q4?^c^sBrO$B7jis88995K=uR%lz5lt@ zZF9O84>&JR>tCdiA8P>{S39lJljO)&-b-&BDAGC1g`r)p#HkLVYur z`%LfB34GK1M960D-_crQFC0B$4nktV?2Y&*WBi%gD#GeB!VLCNwh)!$^6^>O96Xh# zE?6X!e?`N2Qi^%g2BI20zCim$8yf_v54D-%m_Q0$m&@$5&jDC3Dkwn%kDaHKBPYqh;JJDtFG$hXhx)dov~=AdV4nuy+CH;#677n zz146mf8FEFLf>X+G4+7OWbIbDt2va#%lVo=Z9~qkP<6I>R{7{gEAT>e&dh)=H@O1% zRBo&>_!=}MZAculf?k-MYLP!{yhfv#YG7R!2!;>$YPx ze&g=0w=cAxJ<@|nKANHv1l)u%r$9J>vN3~E6|F^bgH#NakEg1&G zk4m{yKyF1TWM$>0ePG!fFe@fqVo4hdl|;+Qc*vJ9ez_&PI;J=Y@)}_p*Y-54fASbG zW0%a?XrYKsvGZ&gq|r)y;GVgR`7y~O@Mg{XCLbm^XpruI|83m8v+X=pLjlFBcCMb6 zrBK+0yhC}%5h$+?@m{BLC2I%2ZItZK^>*RFCM=hdofZG1&jCQo*56S=f^#7v>|oYF ziWpP-HgoDju#^bAg2c}7Nu_87{q!*Hg^NZn(Y+XaozdMo)*$@FE{6J_m*Uw@u9Rs8 z^guwDr>Fa#Z%)I{6XSPWh>32SOu2;o=s;J)oM!3JW7NUNxY#SSr`nCj0K=zf78_qw zi@sHSlKB0Gu+oYGdcB#_pn(KVY(h7TWTz)By5tKzk^04qB+M#P1y>>G6~wUZm-lKG zQS-VXw4WxsKSxo#Ry}2I^d|n>y*l^1)a|(wt8L3qQ>@+V)*LWe*salL1O8AtUn9oJ z;S944{AK0MxXfA`n|_%kYHiN=BC^ALhy+*5(|wc4@5&g2+iK-=+(OY;7e3I5NQs7a zt5GA7RLk1le}zVhC;3a<;DmSBx; z%qOLGDoWJ9EPdj)ndXtKD!?O0`>P8m-b+2#38Du!MQWZMNPdL`>W-%z#C!R^AQ4x6 zaIahzPmlB-45C;N<+qAC8IoPIN~(Yn*zo1bwihd@*Qvb7Bz!ce`Lo0pdMu7AulWbY zKBV<)c?2)Qs9i|SbFKVM&>2$d$&UB^zRIHMcJ`6Ma_iVl(eY5lDdC9~?H2sA zANN1KUKC3kPv~OhfXQ=WBb<{a+Gaid;Hf!FU?P=3cj^m^A4)bWP8Gx^5iz zr1w0?o?Q=B(>OOB@AlC#rB7?6St)8|X>r5Awf!#;P2pl{dkNgMb@knPoI2*?6EkVj zX2$Sf^w1J&chfo~PFr`C|$#Q8ZMvD~f%>=F~`aFCAw~N{oYC##eze;SS0c-Y_6jRr+0`s%RG5 zZP0QaT0!1xzs7fc*-EJ{U0ng4p*UUERE2C^d#2@}+LA7Al{i=mGJq$o*FVtIsB8qQMz2PQHA%c=MvCJNnSy_Ra9Yo@=#3R#$|r z`pW&RcqB{+R-LS~6Ybn-^od3frW~#{iDd}Mz=D^Y-8Z za{(mSuCLX9NGOl1XA&^8z6~DH)>LTF3^Fmc5@D&d=w_^SX-j8YiOidFZ#t)HRIWW6 zs6Noj-z8pV(2$*Qx8B9L*>0e`IQMHkQ=wvd5m5STT%CIuyX=}47;*Vcf@9(WH|?#P zcSGvn9!=SABFi71iOp1IvkJemH0=$eWxdxa))vyt>KK?iLC+ch+^gbJ>vlY`eA6@0 zPMbrvs%LX*-Ba?%`DIe6m06BvBCFmcsVbyANd87gL&-2Xcbj$AQ!N)|VLb{|WvHPI1UewWI>em}7`C0kL^Cwr)V?j8_;4d+J$q#Ak%&&&_l z1*u~ol9%I){T2ZOXo(*ls&9VW%^_1_}y+)ojv9kIJoE;Z$($jL_-uGbgz6* z2eNAiCeu>_&VmaOo>Q9MtdR39yctO8Cy%*95AUgKXcBHRbko1inyGIm&+9wR)&2?0 z){}V^G=pcFBnGg4^1oa+U$nXg$5xATC#l~3^g93YSmSR~i0^s0>7wbJ#Uh*prf}?9 zwp<`|%Jmhy;7_F+HF$~JG-a$wRIjpiX+}uwBMK^9@#JI~c1Xl0p}guAbB#;PjW+d4 zH_zF`C2{jLN{-pu=!r>G!on>zSLckhJk={Q19Faskr(DwwdfCcuQiqINaug!M6!A& zgovm&N0WSmrhFz)llLHC7}g05kRR-cTYQvF zvl?1BojH*G_oA~_#sIQL+ted1nnq>QCOU%q>LP*0tFY4GX|kTJyO#$LX`K!9bm_oD zXg?;4e9m}@ER}kS$VL@GS9RSmS1#$har1BE1E+;v#WJCBM-`;P!hvn{{JMJYS?14`ij4ZEiN0kp$W=NWDC z3q5rFj`QS!B(YX`XOL1S5;v0AimY5qmeQKl)n@w)WUR#uAyfbX3m_PA+YzVa>EA`E zzUZFn1mb6H^-I$|0u0eD{$=YN1!hqqe8w2dDT8ij##e!9GObuR?-u`*GJ`S5WyjYHOnAFAj5=a*#gs`BIxS zq{ThnSF;I}+-1{*ZEd6kr_OyJ7Gv{EN&)2`_VbbxJ_siuqY475;R8w1gz>}B`MT?# z0YIz$zXiW{FgAK$Zp!xlv%obtjv=$+$lJ7l`TqDxA^~66MK?@FtykIfGq??&k*Ng= zewgmLE2lRNU~%himqkdLT*i-Y9pKrL0 z@mIaB^!HZy%Ie3gl@h0_3Y=QtMiCh63Djug%5$LJ7QC$R|M1qP%9O8yVCeRi)jz^x z={sseYbd%A!|JD|mGb?3n-Fvxi#ZrU!K-ZySpsA`H=ihAh^Er(u`ctYB=YmKWplT# z2D}$K_^w#~i^XRP$n^$cxy%kxJAOE0kzDm|#q>TYeQi@^*YfGLV)_b4M zdSH3Os9!z|RWqh`ELpmXE@DoE?x}nkWAGqhf(8&lCO zGtzl5=J#}4eOG`A-=$szI4MIadOH8zh65Ue_nG&N=`IHD>xXMG#9q;4JgXqsL1&>x zx&e|@n5$n=FQUQ7K%E3u47d%-icbGC2ss@#OFn+@E~z$a0>DevQ5c~BWn1V@V|rfg zGzJKv<`w{J5x)=aKWQ1ucy1>ow)DAFjM$qlP7@(V%J%Nmu*}v3ZOhMyru1r>)J6ih z?&|SQO-x{f@`8b`i=2ZPD47^rYMzSmB8m~sAlvC$L*Kp@(YhGGBAIO2C-h>we~#w1 z;MNvXFR8Ukt7I?CI=gYLv)f2c$l{#WotVM{MksI(=&KjK688k6E$B@sdS1DPxb6*b z@f|<_?B74;qi{vSJd^i`6UC8J%aOKl8fL#<%jB})MN2;&!z2T>r0$gAJtZ$1b6Tj z&jh{MIB)KU`%)h=l(Vv)|Fsy$1Qx)X`^kzvc#z<+9wFGFa*BE}LV@%Gys%7P8aL1z z*-&P3S&AUx(y5FjuKM?Fa3$JcQrGXykIQ$)s9=YNYyks^hf$?XhL}1tN^0}lI@~&T zD#y`7xoKfVaar9;&esE;7t<_s@Vu|ZotM=XcL3mV&ok{NNs{lA(1qnI&q~5$UIvWb z(vWQw>Ret_cIup$h?HDro6qmk5JGcs!&0dm2gPd$_5)v|bh!|{mt^i8p=jVWPF&B$ z>J_DRoL0?fJ<54zrJaK48nzh3re0foKOQlex6Vf_3RWz1GkeInGDvh?Ul%9}&V2B7 zx#9xNg6NQGpD;sX$xESna1&7$xM|1S=$a261hm)jV|a7Y4FYYRz6APdg(3S~D)r)w z-C0Y+2KN}r&3QsZ;lmB$#?7+tuUrD61b!jnMtT9xgdHx&1#$R<{8P?TOjh z;W8jtpBWJDxxg;?@r`);i#K+1=wn>dPcPNH&UweolTpkIxDNVbs3h&CF&S;ZDsv_*@;cNE?GM~!9S}CgBWc8E-cp~GCw!!((7W6*;g&q%3E|6ttP3E z(P}gDK9`O4Tfp5fGSOsMKzFi&W!jK;{5D=+NbpNE84#*3%5(7?gO67=@?*yFRgGJ2 z5*zs)&j^uIMqs`T$%YDFs>(d0(+ z_X#tm0~wHR7jjK$nl9xSprLJ3NN&Hm`^4)IVdKhNfAvp?{g#f1 zew8|TkoCdTx%H3^t;=V7^ghFLmm^+fxEtoS0hWyjEH><(n$0ZXj@9iC?#s*oH$QnA zvl5S)qo=Dge5#oqpY7E`+=R=5-JkwNrYOWjWQGZSF@Yw?EE$_lkXuvGS(vk0nHt19 zyKZf5x(`6?^Wr5x%5n6m&2zNv_2dJh=oqM9H_<-EJ<-*8X>^RHi$_ybWS#SC3rI!jL4h?L|mzpHv<`cBeZh=!mIt(euEH#fE}GT!!-mLr-KJHu9VqV zY5*R-byIrMb#67)FJO)`<{E61{`Mnt^^#tUzWLlbrA%A2kE|@Kdh^UP2RVyiKu`s7 z_I5TtC&Pls_A=JT0W8=-^6Ggj2YJ>y(?ZHEF+>wD<pmVP+>M@t zhxkoAX2WS^xHPwCi0E+l+)QxRTl>1na#5dsJW7+9NvbG@K(=hSY7?6gtQp0-NDq`Z zm$e@YnCQO3)8ks7SPf;KZl}Hqo=dBC0Vx_AE+Zo7k#_$Iuc=@wo{U<)60)_lhb~6F z>*p$LZdBQZgnI~Q1|;jK=1=R5#eJpRZ@;;& zUuPjdD}GPSWYOvQj!ZtSlR^(%p;X7WeI16+C!F#EIG)wVTD?-Q)>S^Fa2&lw>Y-qm z*-;JRs2tSqL4+g)-647%?%5w|s!`7Ji19#}W)yl4EINy-&%Yw2aw72}5)_fd=>?!%4QaQ3UEw?~_W2mq=# zK(5s&(g7~TDU_D>;-m80lt*%E*(Acl-*!1;_JFO)Cx5>o%b_;;vMFN)q~v zP3(Tcd;%NT%}g4&tu&b>hjG3M=!lzs>Tf~+y-w&2!Q*=^*1_fQSS7N&lf9*FFO?%K|Kv>i`4$wg}(;4YDNkw>M;BGJ4 zgmR4$Iu12^5yZgbki#ww!jfs9 zo{T{ixlLrPeD(;G+G&CmMhi3{|HE*p`m^kKKS1f!dcn9~p;xJ@4e5BBMI^m7WkK>8 zHaWOq8=)+3c6=`-nazG+L^B9=Xw z{0f}zb(V}7iM~6yvpe-6<_^Yz17Wv*Q`!Z;#X9i6*<0ciF(-Cfs=nhGo9^ZnG~R}r zukOIj(S}}y(ybp~mMQ8($g=d>_R_XBb%_zQdR`X~V?AdW%6VE%-L6?(klWMa>Ga=a z7TnHa&RWG(64nCorYDQE%>tothj-KiD3=D%+O%IqHzgOo%kmT zad(R8idi^E*qH+;_(4mO_ZtJP$Jq#uQmS{Fw$vr_prYwrEW$*5BNQ z+ja^_MEjeRZHbukFx2CQUbu2a#aj+S(OhwM-_*v|kUNHvuEwdvxHnsL(RuLPBDgjt z263rt+i(TNli%*Rm+C{{W*D-qlLQ9L$5blf?~TnX+rGu2>U1kI4C^1G2^6Ot@{k`O|a74TOw|U7w}aN0q#U zjXGcBJl4>%%1?70Wn=KdtKp8TB7=g~Y=ABc+@v6G1R;_3cYU8OHM+MkZ=~JajD9sb z34lXX=i2Ry-35OpPhdWHqD?Wm%}(0O4q82);j`7akJR9x>LB5FG&VKCVp%mfVf^54g2)9(N|U>v(C z6R<;m+o4DpEZ{%5e-#K!=;O_`6PAR@{J&KL(Ae_}S5R>oTc1{1Mm!c29KL>lrVJqJ z=O2#{+grVUEQ;Y<;=NukXRR1o2U75Fj`vJX>u!}28n#y1y!Rc=BbyJaK)cwWn%xeKHX_Y*)7PJXGlJQ-hi&>D9{x zs0-*4E(B3^gkUqnM)C83Ct-t6=XKpp6>%0}hJ1k(RV(W%3k+m??=d@aHPPO++iYNb9uL*xWzR=as@&W?pu$^m2 zs+_4W){@c>W&0i`eUsU$rE4-KSi-S}Dj2%$v+>SuLnGR|8no;<=6buV%fZ!#S4pZF zD3YX3VZvf99iM^A{TL>pzBT4w-s#ujQ0_xKJTaGNm-p!&0;rH;_nP6faCY{=kkNYn z8yBJBVg>PWXmFH-D`CkD2Z%#tm!bRK{_0mf0(J9T>&`$l8r|k$?kye>X*@{EpldqH z2Ng0h*=yGIWj6{9x?`&$KF$5K+-upF#=Y3LN4C{>XSh$r_aYuKiezua)pj)u+MI68 zF_Nzwg2r1(WM@Fn^~ri9UQ`_8+pl^fNA7Wr4Hq=#M&diO65ezQh_eHv1v%j=KUBmg zw`NkfFWnighiV8f-RrLM2h@Wj0o;G@$DH1tvDU}CZ%54_=@vfTht-uGvRoA>1s&^r zursMfXG(~R0xJw;c8y2eN>gE@Ro|2EFt6&%ftRQD{dcc|?Pc{ZUTmEuh#Gcc)n+5{ zyK0ra3hL+56(HcHw;b@FN7mQx>$)9rxGB4uVk2$3Ig{u$<4p2%QyAD27L4(_Qh1Mo z>p^XkXxak0<87Vy>vpjYGnx|Yfh%92&v=s! zN24n9_j1ze__AFYX|{tqg#C|7&3}>b{aMXn?poHNicw0Eb%F>0u#o*%-rsT4YaZ#< zP9*o5-qN{N|F~<%!3<0GNtKyz*viQW#T&V+?dGt;WXPKm$;J#%Gy5Wst?s)l3Vc7? zBO?AvO_s|IWDP-od57Zb9_k}GR<|g3Tjm&k??i|HUd@;{ffPD+l6yt3a{o>Bvnb6% z-NW1waFGbW)o<6_adEqS2^ThW-(Vz9b2U0{3hb4JF=5h+TEbd=r_dUT|hFv>^~0s;!sn{-GN zgs2FJln??$2%Ut`5=tQXPjqG;-{*b)Z~g!J%KEYvD;&-~XYYOQd*9{S*G-&>k-^bJ zLWejwIF4Sss(XurV?T(4V=tcTAn=!oKN@3!uRZ>^4754Qdqn1ei~X)wZeHQws7gM( zV}Ag+{>A6&9e)lE?soRi9<29kCk~EClWV$HZU@;>c0K<%yMYp?(}ZJk#y_5J_2uIJ z82!6uLrvRLQMju~1lMBQJqZ!)65cm-({4gUT~ zxUtTMRq=}R92pxcJK24%Q`)aN?XGUnl;P~dQD5kIhmB!&D;4RH-)BaFEcKQJbn<+? zk`2$kFZZ&Qm};sU8!SYSTev2o56T@ysvlHFH_}LCzT7%Xj$pTQYac}%=tnF+$ZDv zc&l&4p|KGs~ch#1n@+WZZ_A1xqH;(&lLyE6EX&q#nj8xpR; z!`C#3QxKvS&~=70-CL)|NA5|l$EiXNvOP+4KGCRTR4{fS?HD2gO+U z_r&nYC~`^;;#??Q40HFUVpawc8bCjX>YjUjt`moPm*=QP`H-5^WUOBPSTEA3uv*hQ zUmi_V`h0d!wOhUcUA#7uUc|5&nZIM;-yAcPMy+R@TT@CKls@vlfvJ6^@pI2+SZfDb zNJELCN%YH6&LN(0-KKXa$XC1?QVO8o@n;3p)n>eFi~MfdN^cuI0NKB`@)3-Rw7vj- zxf80cTzsBx9Pl;XI7GY&)lsd3S4NY=Qb|i6)Sq`7V>lDI0u7W@fic-R1qqMbm#sGm zu!tG54D?yE@86?J>Rmz}G$A|Md0eRy>#SSZ27J z;~B!-=9gAua}wmarb0&f_J;kOHFKDDl1|?PyyKACWzd9Rz*j!NnR0ylAYC5&MMPPC zOb2fu4wsR7u{K^W>WCvemnqnCgHc<>iVGMfFsd1C2WWknay6cdC;ZL!CmklWFt3K$ z7c;WfQ{t`OSzfPbYwia0iZ@%?%uSXl_yTmrAvrUIIDUFiE@%FwveuZa))wZKQOE=J zbNZ#qrn;MRI|=Z%ODV_ZPnFM<2v;6G98Fas99`g}M+4%RB)Ut2G}bT6Hs54iu( zM^`U0JD9te-5cDc$p!Qd#eVJ&zbQUB*7n!5?EUZ*t6K-t7d}@c<1hzC7Ut zofDS;Por#}%iX%fW5yoQGUr6=+En(crIU zZkXu;e}5=98V7uFB<8Whj(@&x@q(CrTH6NSSLcts*yT{I2-$r=1Hu2=?*IE$^)k2( zvvworlai8>iv486E2KE^x&eL*-A!Qxs|1gsr!jH(M%Jd*$Em5`kk%p?6=V@9)Pz;Y zTGle+mmY?an+G63_+ynC#S4P0ZB@7+mU@8)aTq48_{IfsIo}=TC~FhXHzuN{JKc5 zN_i2fH3zdn6LV%wvgV-IVbQ7$!-ZAeW(*Oalh=T8eP?;XLbiVOSv0GwHRmJqakEwi znakgY6@fN(Bo@$BfoYgFz5@SVajDdcd;3|m7OR5QLGFSw{i@G=e%Ap>3eOyw1;lJH zof^-D{#4nd`oU5Nmc5O|v%cl91fHVqdD)T)!`Py5K%;zk0ki7U1$7RhqshqkL@b7c zb}jLBtu`pW#`9-Y*Bl-xU;k!RwK{fIEycBlv81x;uL8V}xoeD&VZfOSm`pN<|Dpr2 z6JkUOWl!1%ur%7}PZtM*A**0*c#}c3yn*>um1w=l4=vF9n>j3DRx?>_=P}|BGDq_2 zKr22*Eh=j{H#DcXGh885LXl|YnAWFk>%Wt!Qe*F^7|L6{$fzCj=!_o!GiAPgs$Kz~T{~~4t&qdvPQrn`jSD^k(B#+w(e2ef zg;qkJ9rcXs*RJ@$q4ortvf4(9uMXks9Rx9Cm2)5Cv>en?o%?Ap`s=b-IGvS(+R|bY zJ|d}ZI-<)<4U;Qx(pURpg!&=teIJ*TGJ+w`!`JgQ*8&R`Wshn68UChmXJ&mYm{B+V z&_N7~HWCFk>ce)}3vgQ-^McM`RW_{JuWaw-Vn?z2{M>4yi!M!FbJi}@rb(H{A$W>| zo_nhtVz3V}We6doTlPUUk~?>Ru?Z;>fU?Ap`u zlkhGB!rL{E9`6awe&4Y9GW@QOTcTt^S&XvU=$P|*Sp{5OE$a6ng`&MWG}gyANyyzV zb?dv$SN%1epEB%S(0)zU(qLdvIvzKQ`_%X$w^Ic%n6fA@Vr-2TvjVQN=e zf6G35KLhO}Lc^&;4Y{-ZI9%%N$zJ)e&lvIK;{?CM4p1z_SoAP^RTSVLdwZyJEbzpcRuoyIgH-G|wlFt) z#|o6&Z{I7wmbq_?Hq(zIHDi)4Hb|pF5y6Yc@!rfC?{n%c z{`0W6q1X=bog|{X;PZ;DXHia^T8hwK(fxAa5AKAsmKGS>@3S1Btjw){?>|7jqdTB; z5Vfj3E6bxh8+^&DAVqVz!AP#9G4ZPhXN#27=Th-oQjR0Jvg#{m>YZJhw{h}s#8#_1 z#yIDFIeR0Z_hT`F%UHw?_9HjdCR**Ajwo%?cW|Bx8{oOE`+CXGZ8zeb8NOBQ!A`a| zk*>hfd?Q_diXKQ_8>j+ykBXtc0EnM%eo$5J#P;=e#P$~w9p~bPR>5CZV;zy)Rj5xd5(#nsXe{QC=(aSoFPmWm6cQQz8KhDsghi?P{ z%|r?szne_-weVLH-jLO9GL!|~iE0Pbsdt}mTXJ=N66A)cxlmN)#QPsBr6`;3oPPf>h0f)Zn|9xMos(O)Ft!HC(RZlzv zM(H1^=A?+zjOl?e@ei|*;9}Y+WanN;(~0g`44AQ(Po6+GAhEGJ5RQ%bb`KLA_dpH`*i&LbC&xPQlcBPVEZ^KFS(37 z$$fAG=Q-){T$Pagn9_gykv2gPSu-dFeq*#dLXLEKR3N7yGO&z=7{6? zg2PIe*vFWTvBMo|O=}8@G8g0*y`-AeJrdW75?yw0p>QY^8aIQzMdSfhIla(9ZCz=+fQQ6JGQJR`j=jc{vaN{G) zXU<(qDNUHQBz^t%o1_UVGu=6xhw%x$;%m+d)XV9kPfU!74S#T#s~1r4GpX70ce@tt zBtm6EgYB1W5v#$slbZ>um1Dp_ zV|A@zEF?_P>-FyNbJ>weh5#5C<>oD2H#+^ux4 z2!D>^$vI03`K~~Z=vBaS-ViU0t)zcCJbe!YSev2W>*S;oz-@68+P`pc{O0Ls#s44E zuH$C9LFyd8;G@_mzp2&EdY)vYE!^_&ZK^KO4|XI(K5<`BEyUTqoYI#In6YR%6Mb9N4_f2F!x0^>>h;wg85a! z3#az$MFLO(pz%YO;<+|P2PF=@3_$mMc@7B_*ACx!_Z)E)ylvWdEsT_;TmZ|zdW=zV zhB`ns>hyM1?+(5TtEMbz*t<6GHl%yWtJf34veJ{ILRUHj658I0LssG@St}}vw$gTI z;!93?3i;a| zk5m)5C`4VshIac7J*^9BamwD~SxpwOC0T`-u@)29LIo|Uf|pc0Ke-ZB7RDOtx9jTh z@^Z>_t>7b-qsBff)yX8LCp#zLV!>@(Y(sO=9SBW)&M<~;ohM#M?Vm!iIKRSq$)VzH zwuLq731U!>9ljXF0jTb4x^MeX)Wk~4@0U$EUdJdO+7~6Ef19M#>w-Ji?*DkL$`Ftw zV4DC*P6LtZ3r1kHqNM=HE|j7;_v&x4+|soYjps_t{rg%C2qEtR+p@j{v%OIAMe_S{ zG`!x!@m7j$Uv^(_zTA3dY4->)FMwLV(>n^N^?7h9x8D9v6J5cNe_tc#3_2(avY4Gq z>+#=bCi4K88DI+nCBPS>!EIOnxwc`hS|%7dj8-$h-jIEl807ih{j8m25zZtYtnE+; z48Dmy#57Fc88#ZycgG`Q^++wd)zk)BmD!tj;V1LA8cH0Mgg7H1d;uNqj@f&)O?0o4 zc>!Nz8P5e^ga6n%jw7c3+iz6fMQ@e~LFcyY%n~qogWS_6nj9?(35XhjTy5cJ+ z_&8fr;&9g&6#vX)&s@ZY_ZXc{uhwGJXzhDwUDw>4iK*8>h4seu+)reEd(2~%r*aUw zQ|B0vbyPGT@K0==1B~J>o$!w`iXt}$t^y}dPvSOG2SSa)+MaJ)<3xa*1=+VU1W&w` zdP_IxTR>e^)swNU%MLc!$2?iROD&9BexrgLqv6F?xX#WZvSV6*e`&lEXrgnAJkZH@ z5W`=VcSQmq$fMuQ9JhgpByc>US5RSZR?lMv!Om?is_UP}Hplv$ZK>mdgtj3*aOo z!4TSB;3ZZW28uL6$>L2?6vCt?Vh=sgCKa9SRM5@0)BindyyI zt%b`FKCABvWVYXGPr%ari681@m7=}9TnU+SJF-p)`%5<+GDM1UcFC@IajmV7WC6sA zfb08Z!JOx^c4xX8^amE)Z$Gd}1GgQDcl-?uuKuvD=;08wlc&%%D=3Nx$4X2$0FDHF z#a2Z^eMcS+9ykzF{K2Q!HtxQ7vT(c5fmnhN)ctBtPK9Ja_(k)%tK}P;v80Gfa9f8* zC}3dg(*!N~1n%k`I1uT0<|jY%(*hiC&-WkLkvA7<&E+n34A96L0Bhr~P^rV%2F?Vc zvfEDGl|^?D>USM~<`C|Lm(#|mD4Z`KLNd3uv~GfSQp|TWKV`F1*xQhjiejQ>Dsv~I zP#(=EaVRezNa{p~095J_XU^t(@pu-NG!Rf5lq5wGGBwk+^7kzTPBi#4(9t)K;I7z0 z^dd>#v;;0WbXgW$7nFO~awRa5b3y&kr^(B$WF}aLVNFZcOhr}dZ@bD?|ny_`=XvOd@GPruc8t|axncj6glqAeE)oJO+#eXarFKEc-AN>Wy z_xOkSR1N|PrxcKQ%jgy;SKYJOU#l+Gq@rFZEgch#)2=Fi_m{AO)@Hg>4_j}ojWm4` zgh{J6H$L&qZnc1*E%*=043HAAnRvW=I7uj3)%S;f-vrrnmtjoVL7~B5bK-B|vXaQb zv&mUSb!8MJBfIRJ8!%e5`qBp%ea%oP4BMGOezGv}&i~=GGFI9{ede0Snm){>`s=(u zaANMindg_@C7W|2c!#yvi7~5)x{xqD>o4WFshT{jJQm28yod{j3!nVhGeBBukcEbv zdAxSBJ|E@BGOBmKx0T|ofcyw$xEnN880!l$T;~EuJ`aai`Y{%k`*D?V69yw!q?!C7 zfnGPWJ{jd;o@7Vd%-RGZ%Z*jib7$eg@h-2Iot84Foi#;Os6PkiMeh%Y$p?b z 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

p|NPUvf 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 NUbX$D!rbe@{{<&eNx=XB literal 0 HcmV?d00001 diff --git a/bsp/bouffalo_lab/bl808/m0/applications/dfs_mnt_sample.c b/bsp/bouffalo_lab/bl808/m0/applications/mnt.c old mode 100644 new mode 100755 similarity index 52% rename from bsp/bouffalo_lab/bl808/m0/applications/dfs_mnt_sample.c rename to bsp/bouffalo_lab/bl808/m0/applications/mnt.c index 6a4dbcf7b3..d7c9798587 --- a/bsp/bouffalo_lab/bl808/m0/applications/dfs_mnt_sample.c +++ b/bsp/bouffalo_lab/bl808/m0/applications/mnt.c @@ -7,26 +7,20 @@ * Date Author Notes * 2023-04-08 wcx1024979076 first version */ - /* - * 程序清单:这是一个 dfs 虚拟文件系统挂载文件系统使用例程 - * 例程导出了 mnt_init 命令到应用初始化中 - * 程序功能:挂载 elm 文件系统到片上flash filesystem 分区中 - * 使用前参考文章 https://blog.csdn.net/h451884098/article/details/118544347 和 https://blog.csdn.net/u013213069/article/details/117384971 开启以下配置: - * 1、修改 menuconfig 打开RT_USING_DFS 和 elm-chan 文件系统并修改扇区 sector 大小为 4096 - * 2、修改 components/dfs/dfs_v1/include/dfs.h 和 components/dfs/dfs_v2/include/dfs.h 中 SECTOR_SIZE 改为 4096 - * 3、修改芯片外设配置打开 BSP_USING_ON_CHIP_FLASH - * 4、修改 menuconfig 打开 RT_USING_FAL 配置 -*/ #include #include -#ifdef RT_USING_DFS -#ifdef RT_USING_FAL -#ifdef BSP_USING_ON_CHIP_FLASH +#define DBG_TAG "mnt" +#define DBG_LVL DBG_INFO +#include -#include "dfs_file.h" +#ifdef RT_USING_DFS +#include + +#ifdef RT_USING_FAL #include "fal.h" +#ifdef BSP_USING_ON_CHIP_FLASH int mnt_init(void) { struct rt_device *rootfs = RT_NULL; @@ -34,33 +28,38 @@ int mnt_init(void) /* 使用 filesystem 分区创建块设备,块设备名称为 filesystem */ rootfs = fal_blk_device_create("filesystem"); if(rootfs == RT_NULL) + { + LOG_E("Failed to create device.\n"); return -RT_ERROR; + } /* 将 elm fat 文件系统挂载 filesystem 分区 */ if (dfs_mount("filesystem", "/", "elm", 0, 0) == 0) { - rt_kprintf("file system initialization done!\n"); + LOG_D("file system initialization done!\n"); } else { + LOG_I("file system initialization failed!\n"); if(dfs_mkfs("elm", "filesystem") == 0) { if (dfs_mount("filesystem", "/", "elm", 0, 0) == 0) { - rt_kprintf("file system initialization done!\n"); + LOG_D("file system initialization done!\n"); } else { - rt_kprintf("file system initialization failed!\n"); + LOG_D("file system initialization failed!\n"); } } } return RT_EOK; } +INIT_ENV_EXPORT(mnt_init); -INIT_APP_EXPORT(mnt_init); +#endif /* BSP_USING_ON_CHIP_FLASH */ + +#endif /* RT_USING_FAL */ #endif /* RT_USING_DFS */ -#endif /* RT_USING_FAL */ -#endif /* BSP_USING_ON_CHIP_FLASH */ diff --git a/bsp/bouffalo_lab/bl808/m0/flash_prog_cfg.ini b/bsp/bouffalo_lab/bl808/m0/flash_prog_cfg.ini index 090dc7a363..a3906661fd 100755 --- a/bsp/bouffalo_lab/bl808/m0/flash_prog_cfg.ini +++ b/bsp/bouffalo_lab/bl808/m0/flash_prog_cfg.ini @@ -8,5 +8,5 @@ boot2_isp_mode = 0 [FW] filedir = ./rtthread_m0.bin -# since D0 is boot by M0,this address should consistent with m0's board_init in board.c -address = 0x000000 \ No newline at end of file +address = 0x000000 + diff --git a/bsp/bouffalo_lab/libraries/rt_drivers/Kconfig b/bsp/bouffalo_lab/libraries/rt_drivers/Kconfig index c4ef0fd855..3f58f34fe0 100755 --- a/bsp/bouffalo_lab/libraries/rt_drivers/Kconfig +++ b/bsp/bouffalo_lab/libraries/rt_drivers/Kconfig @@ -1,17 +1,6 @@ menu "General Drivers Configuration" - config BSP_USING_GPIO - bool "Enable GPIO" - select RT_USING_PIN - default y - - config BSP_USING_ADC - bool "Enable ADC" - select RT_USING_ADC - default n - menu "General Purpose UARTs" - menuconfig BSP_USING_UART0 bool "Enable UART0" default y @@ -126,7 +115,17 @@ menu "General Drivers Configuration" endmenu - menuconfig BSP_USING_RTC + config BSP_USING_GPIO + bool "Enable GPIO" + select RT_USING_PIN + default n + + config BSP_USING_ADC + bool "Enable ADC" + select RT_USING_ADC + default n + + config BSP_USING_RTC bool "Enable RTC" select RT_USING_RTC default n @@ -171,11 +170,7 @@ menu "General Drivers Configuration" default n endif - config BSP_USING_ON_CHIP_FLASH - bool "Enable on-chip FLASH" - default n menu "General Purpose I2C" - menuconfig BSP_USING_I2C1 bool "Enable I2C1" default n @@ -225,5 +220,314 @@ menu "General Drivers Configuration" endif endmenu + menuconfig BSP_USING_SPI + bool "Enable SPI" + select RT_USING_SPI + default n + + if BSP_USING_SPI + choice + prompt "SPI SCK PIN" + default SPI_SCK_USING_GPIO3 if BSP_USING_BL60X + default SPI_SCK_USING_GPIO13 if BSP_USING_BL61X + default SPI_SCK_USING_GPIO15 if BSP_USING_BL70X + default SPI_SCK_USING_GPIO19 if BSP_USING_BL808 + + config SPI_SCK_USING_GPIO1 + depends on BSP_USING_BL61X + bool "GPIO_1" + config SPI_SCK_USING_GPIO3 + depends on BSP_USING_BL60X || BSP_USING_BL70X || BSP_USING_BL808 + bool "GPIO_3" + config SPI_SCK_USING_GPIO5 + depends on BSP_USING_BL61X + bool "GPIO_5" + config SPI_SCK_USING_GPIO7 + depends on BSP_USING_BL60X || BSP_USING_BL70X || BSP_USING_BL808 + bool "GPIO_7" + config SPI_SCK_USING_GPIO9 + depends on BSP_USING_BL61X + bool "GPIO_9" + config SPI_SCK_USING_GPIO11 + depends on BSP_USING_BL60X || BSP_USING_BL70X || BSP_USING_BL808 + bool "GPIO_11" + config SPI_SCK_USING_GPIO13 + depends on BSP_USING_BL61X + bool "GPIO_13" + config SPI_SCK_USING_GPIO15 + depends on BSP_USING_BL60X || BSP_USING_BL70X || BSP_USING_BL808 + bool "GPIO_15" + config SPI_SCK_USING_GPIO17 + depends on BSP_USING_BL61X + bool "GPIO_17" + config SPI_SCK_USING_GPIO19 + depends on BSP_USING_BL60X || BSP_USING_BL70X || BSP_USING_BL808 + bool "GPIO_19" + config SPI_SCK_USING_GPIO21 + depends on BSP_USING_BL61X + bool "GPIO_21" + config SPI_SCK_USING_GPIO23 + depends on BSP_USING_BL70X || BSP_USING_BL808 + bool "GPIO_23" + config SPI_SCK_USING_GPIO25 + depends on BSP_USING_BL61X + bool "GPIO_25" + config SPI_SCK_USING_GPIO27 + depends on BSP_USING_BL70X || BSP_USING_BL808 + bool "GPIO_27" + config SPI_SCK_USING_GPIO29 + depends on BSP_USING_BL61X + bool "GPIO_29" + config SPI_SCK_USING_GPIO31 + depends on BSP_USING_BL808 + bool "GPIO_31" + config SPI_SCK_USING_GPIO33 + depends on BSP_USING_BL61X + bool "GPIO_33" + config SPI_SCK_USING_GPIO35 + depends on BSP_USING_BL808 + bool "GPIO_35" + config SPI_SCK_USING_GPIO39 + depends on BSP_USING_BL808 + bool "GPIO_39" + config SPI_SCK_USING_GPIO43 + depends on BSP_USING_BL808 + bool "GPIO_43" + endchoice + + choice + prompt "SPI MISO PIN" + default SPI_MISO_USING_GPIO0 if BSP_USING_BL60X + default SPI_MISO_USING_GPIO10 if BSP_USING_BL61X + default SPI_MISO_USING_GPIO17 if BSP_USING_BL70X + default SPI_MISO_USING_GPIO22 if BSP_USING_BL808 + + config SPI_MISO_USING_GPIO0 + depends on BSP_USING_BL60X + bool "GPIO_0" + config SPI_MISO_USING_GPIO1 + depends on BSP_USING_BL60X || BSP_USING_BL70X + bool "GPIO_1" + config SPI_MISO_USING_GPIO2 + depends on BSP_USING_BL61X || BSP_USING_BL808 + bool "GPIO_2" + config SPI_MISO_USING_GPIO4 + depends on BSP_USING_BL60X + bool "GPIO_4" + config SPI_MISO_USING_GPIO5 + depends on BSP_USING_BL60X || BSP_USING_BL70X + bool "GPIO_5" + config SPI_MISO_USING_GPIO6 + depends on BSP_USING_BL61X || BSP_USING_BL808 + bool "GPIO_6" + config SPI_MISO_USING_GPIO8 + depends on BSP_USING_BL60X + bool "GPIO_8" + config SPI_MISO_USING_GPIO9 + depends on BSP_USING_BL60X || BSP_USING_BL70X + bool "GPIO_9" + config SPI_MISO_USING_GPIO10 + depends on BSP_USING_BL61X || BSP_USING_BL808 + bool "GPIO_10" + config SPI_MISO_USING_GPIO12 + depends on BSP_USING_BL60X + bool "GPIO_12" + config SPI_MISO_USING_GPIO13 + depends on BSP_USING_BL60X || BSP_USING_BL60X + bool "GPIO_13" + config SPI_MISO_USING_GPIO14 + depends on BSP_USING_BL61X || BSP_USING_BL808 + bool "GPIO_14" + config SPI_MISO_USING_GPIO16 + depends on BSP_USING_BL60X + bool "GPIO_16" + config SPI_MISO_USING_GPIO17 + depends on BSP_USING_BL60X || BSP_USING_BL70X + bool "GPIO_17" + config SPI_MISO_USING_GPIO18 + depends on BSP_USING_BL61X || BSP_USING_BL808 + bool "GPIO_18" + config SPI_MISO_USING_GPIO20 + depends on BSP_USING_BL60X + bool "GPIO_20" + config SPI_MISO_USING_GPIO21 + depends on BSP_USING_BL60X || BSP_USING_BL70X + bool "GPIO_21" + config SPI_MISO_USING_GPIO22 + depends on BSP_USING_BL61X || BSP_USING_BL808 + bool "GPIO_22" + config SPI_MISO_USING_GPIO25 + depends on BSP_USING_BL70X + bool "GPIO_25" + config SPI_MISO_USING_GPIO26 + depends on BSP_USING_BL61X || BSP_USING_BL808 + bool "GPIO_26" + config SPI_MISO_USING_GPIO29 + depends on BSP_USING_BL70X + bool "GPIO_29" + config SPI_MISO_USING_GPIO30 + depends on BSP_USING_BL61X || BSP_USING_BL808 + bool "GPIO_30" + config SPI_MISO_USING_GPIO34 + depends on BSP_USING_BL808 + bool "GPIO_34" + config SPI_MISO_USING_GPIO38 + depends on BSP_USING_BL808 + bool "GPIO_38" + config SPI_MISO_USING_GPIO42 + depends on BSP_USING_BL808 + bool "GPIO_42" + endchoice + + choice + prompt "SPI MOSI PIN" + default SPI_MOSI_USING_GPIO1 if BSP_USING_BL60X + default SPI_MOSI_USING_GPIO11 if BSP_USING_BL61X + default SPI_MOSI_USING_GPIO16 if BSP_USING_BL70X + default SPI_MOSI_USING_GPIO21 if BSP_USING_BL808 + + config SPI_MOSI_USING_GPIO0 + depends on BSP_USING_BL60X || BSP_USING_BL70X + bool "GPIO_0" + config SPI_MOSI_USING_GPIO1 + depends on BSP_USING_BL60X || BSP_USING_BL808 + bool "GPIO_1" + config SPI_MOSI_USING_GPIO3 + depends on BSP_USING_BL61X + bool "GPIO_3" + config SPI_MOSI_USING_GPIO4 + depends on BSP_USING_BL60X || BSP_USING_BL70X + bool "GPIO_4" + config SPI_MOSI_USING_GPIO5 + depends on BSP_USING_BL60X || BSP_USING_BL808 + bool "GPIO_5" + config SPI_MOSI_USING_GPIO7 + depends on BSP_USING_BL61X + bool "GPIO_7" + config SPI_MOSI_USING_GPIO8 + depends on BSP_USING_BL60X || BSP_USING_BL70X + bool "GPIO_8" + config SPI_MOSI_USING_GPIO9 + depends on BSP_USING_BL60X || BSP_USING_BL808 + bool "GPIO_9" + config SPI_MOSI_USING_GPIO11 + depends on BSP_USING_BL61X + bool "GPIO_11" + config SPI_MOSI_USING_GPIO12 + depends on BSP_USING_BL60X || BSP_USING_BL70X + bool "GPIO_12" + config SPI_MOSI_USING_GPIO13 + depends on BSP_USING_BL60X || BSP_USING_BL808 + bool "GPIO_13" + config SPI_MOSI_USING_GPIO15 + depends on BSP_USING_BL61X + bool "GPIO_15" + config SPI_MOSI_USING_GPIO16 + depends on BSP_USING_BL60X || BSP_USING_BL70X + bool "GPIO_16" + config SPI_MOSI_USING_GPIO17 + depends on BSP_USING_BL60X || BSP_USING_BL808 + bool "GPIO_17" + config SPI_MOSI_USING_GPIO19 + depends on BSP_USING_BL61X + bool "GPIO_19" + config SPI_MOSI_USING_GPIO20 + depends on BSP_USING_BL60X || BSP_USING_BL70X + bool "GPIO_20" + config SPI_MOSI_USING_GPIO21 + depends on BSP_USING_BL60X || BSP_USING_BL808 + bool "GPIO_21" + config SPI_MOSI_USING_GPIO23 + depends on BSP_USING_BL61X + bool "GPIO_23" + config SPI_MOSI_USING_GPIO24 + depends on BSP_USING_BL70X + bool "GPIO_24" + config SPI_MOSI_USING_GPIO25 + depends on BSP_USING_BL808 + bool "GPIO_25" + config SPI_MOSI_USING_GPIO27 + depends on BSP_USING_BL61X + bool "GPIO_27" + config SPI_MOSI_USING_GPIO28 + depends on BSP_USING_BL70X + bool "GPIO_28" + config SPI_MOSI_USING_GPIO29 + depends on BSP_USING_BL808 + bool "GPIO_29" + config SPI_MOSI_USING_GPIO31 + depends on BSP_USING_BL61X + bool "GPIO_31" + config SPI_MOSI_USING_GPIO33 + depends on BSP_USING_BL808 + bool "GPIO_33" + config SPI_MOSI_USING_GPIO37 + depends on BSP_USING_BL808 + bool "GPIO_37" + config SPI_MOSI_USING_GPIO41 + depends on BSP_USING_BL808 + bool "GPIO_41" + config SPI_MOSI_USING_GPIO45 + depends on BSP_USING_BL808 + bool "GPIO_45" + endchoice + + config BSP_SPI_TX_USING_DMA + bool "Enable SPI TX DMA" + default n + if BSP_SPI_TX_USING_DMA + config BSP_SPI_TX_DMA_CHANNEL + string "SPI TX DMA Channel Name" + default "dma0_ch0" + + config BSP_SPI_TX_DMA_TIMEOUT + int "SPI TX DMA Timeout(ms)" + default 10 + range 5 100 + + config BSP_SPI_TX_DMA_NOCACHE_BUFSIZE + depends on BSP_USING_BL61X || BSP_USING_BL808 + int "SPI TX DMA Nocache Buffer Size" + default 512 + range 0 4095 + endif + + config BSP_SPI_RX_USING_DMA + bool "Enable SPI RX DMA" + default n + if BSP_SPI_RX_USING_DMA + config BSP_SPI_RX_DMA_CHANNEL + string "SPI RX DMA Channel Name" + default "dma0_ch1" + + config BSP_SPI_RX_DMA_TIMEOUT + int "SPI RX DMA Timeout(ms)" + default 10 + range 5 100 + + config BSP_SPI_RX_DMA_NOCACHE_BUFSIZE + depends on BSP_USING_BL61X || BSP_USING_BL808 + int "SPI RX DMA Nocache Buffer Size" + default 512 + range 0 4095 + endif + endif + config BSP_USING_ON_CHIP_FLASH + bool "Enable On-Chip FLASH" + default n + menuconfig BSP_USING_FS + bool "Enable File System" + select RT_USING_DFS + select RT_USING_DFS_ELMFAT + select RT_USING_FAL + select FAL_DEBUG_CONFIG + select FAL_PART_HAS_TABLE_CFG + default n + if BSP_USING_FS + config BSP_USING_ON_CHIP_FLASH_FATFS + bool "Enable On-Chip Flash File System" + select BSP_USING_ON_CHIP_FLASH + default n + endif endmenu diff --git a/bsp/bouffalo_lab/libraries/rt_drivers/SConscript b/bsp/bouffalo_lab/libraries/rt_drivers/SConscript index 8eb236373b..c6fc95188a 100755 --- a/bsp/bouffalo_lab/libraries/rt_drivers/SConscript +++ b/bsp/bouffalo_lab/libraries/rt_drivers/SConscript @@ -9,7 +9,7 @@ CPPPATH = [cwd] if GetDepend('BSP_USING_GPIO'): src += ['drv_gpio.c'] -if GetDepend('RT_USING_I2C'): +if GetDepend('BSP_USING_I2C'): src += ['drv_soft_i2c.c'] if GetDepend('BSP_USING_ADC'): @@ -18,14 +18,21 @@ if GetDepend('BSP_USING_ADC'): if GetDepend('BSP_USING_RTC'): src += ['drv_rtc.c'] -if GetDepend('RT_USING_PWM'): +if GetDepend('BSP_USING_PWM'): src += ['drv_pwm.c'] + src += ['src/pwm_led_sample.c'] -if GetDepend('RT_USING_WDT'): +if GetDepend('BSP_USING_WDT'): src += ['drv_wdt.c'] + src += ['sample/wdt_sample.c'] if GetDepend('BSP_USING_HWTIMER'): src += ['drv_hwtimer.c'] + src += ['sample/hwtimer_sample.c'] + +if GetDepend('BSP_USING_SPI'): + src += ['drv_spi.c'] + src += ['sample/spi_sample.c'] if GetDepend('BSP_USING_ON_CHIP_FLASH'): src += ['drv_flash.c'] diff --git a/bsp/bouffalo_lab/libraries/rt_drivers/drv_flash.c b/bsp/bouffalo_lab/libraries/rt_drivers/drv_flash.c index a2f1e9f567..88cd39051d 100644 --- a/bsp/bouffalo_lab/libraries/rt_drivers/drv_flash.c +++ b/bsp/bouffalo_lab/libraries/rt_drivers/drv_flash.c @@ -8,24 +8,20 @@ * 2023-04-08 wcx1024979076 first version */ +#include "drv_flash.h" #include #include #ifdef BSP_USING_ON_CHIP_FLASH -#include "drv_flash.h" - -#ifdef RT_USING_FAL - #include "fal.h" -#endif /* RT_USING_FAL */ #define DBG_LEVEL DBG_LOG #define LOG_TAG "DRV.FLASH" #include -#define BFLB_FLASH_START_ADRESS 0x58000000 +#define BFLB_FLASH_START_ADRESS 0x0000000 +#define BFLB_FLASH_END_ADDRESS 0x1000000 #define BFLB_FLASH_SIZE 16 * 1024 * 1024 #define BFLB_FLASH_PAGE_SIZE 4 * 1024 -#define BFLB_FLASH_END_ADDRESS 0x59000000 int _flash_read(rt_uint32_t addr, rt_uint8_t *buf, size_t size) { @@ -107,6 +103,8 @@ int _flash_erase(rt_uint32_t addr, size_t size) #ifdef RT_USING_FAL +#include "fal.h" + static int fal_flash_read(long offset, rt_uint8_t *buf, size_t size); static int fal_flash_write(long offset, const rt_uint8_t *buf, size_t size); static int fal_flash_erase(long offset, size_t size); @@ -140,6 +138,12 @@ static int fal_flash_erase(long offset, size_t size) return _flash_erase(_onchip_flash.addr + offset, size); } -INIT_DEVICE_EXPORT(fal_init); +static int rt_hw_on_chip_flash_init(void) +{ + fal_init(); + return RT_EOK; +} +INIT_COMPONENT_EXPORT(rt_hw_on_chip_flash_init); + #endif /* RT_USING_FAL */ #endif /* BSP_USING_ON_CHIP_FLASH */ diff --git a/bsp/bouffalo_lab/libraries/rt_drivers/drv_gpio.c b/bsp/bouffalo_lab/libraries/rt_drivers/drv_gpio.c index 226f3a2a66..923c120031 100755 --- a/bsp/bouffalo_lab/libraries/rt_drivers/drv_gpio.c +++ b/bsp/bouffalo_lab/libraries/rt_drivers/drv_gpio.c @@ -12,11 +12,12 @@ #include "drv_gpio.h" #include +#ifdef BSP_USING_PIN + #define DBG_TAG "drv.gpio" #define DBG_LVL DBG_INFO #include -#ifdef RT_USING_PIN static struct bflb_device_s *gpio; static struct rt_pin_irq_hdr pin_irq_hdr_tab[GPIO_MAX]; @@ -226,4 +227,4 @@ int rt_hw_pin_init(void) } INIT_BOARD_EXPORT(rt_hw_pin_init); -#endif /*RT_USING_PIN */ +#endif /*BSP_USING_PIN */ diff --git a/bsp/bouffalo_lab/libraries/rt_drivers/drv_hwtimer.c b/bsp/bouffalo_lab/libraries/rt_drivers/drv_hwtimer.c index 2bb532cca9..8256e226bd 100644 --- a/bsp/bouffalo_lab/libraries/rt_drivers/drv_hwtimer.c +++ b/bsp/bouffalo_lab/libraries/rt_drivers/drv_hwtimer.c @@ -8,16 +8,16 @@ * 2023-04-01 wcx1024979076 first version */ +#include "drv_hwtimer.h" #include #include +#ifdef BSP_USING_HWTIMER + #define DBG_LEVEL DBG_LOG #include #define LOG_TAG "DRV.HWTIMER" -#ifdef RT_USING_HWTIMER - -#include "drv_hwtimer.h" typedef struct _gptimer { @@ -196,4 +196,4 @@ int rt_hw_hwtimer_init(void) } INIT_DEVICE_EXPORT(rt_hw_hwtimer_init); -#endif /* RT_USING_HWTIMER */ +#endif /* BSP_USING_HWTIMER */ diff --git a/bsp/bouffalo_lab/libraries/rt_drivers/drv_pwm.c b/bsp/bouffalo_lab/libraries/rt_drivers/drv_pwm.c index 6c801e25b8..9f03136df3 100644 --- a/bsp/bouffalo_lab/libraries/rt_drivers/drv_pwm.c +++ b/bsp/bouffalo_lab/libraries/rt_drivers/drv_pwm.c @@ -12,12 +12,12 @@ #include #include "drv_pwm.h" +#ifdef BSP_USING_PWM + #define DBG_LEVEL DBG_LOG #include #define LOG_TAG "DRV.PWM" -#ifdef BSP_USING_PWM - static rt_err_t _pwm_set(rt_uint8_t channel, struct rt_pwm_configuration *configuration) { struct bflb_device_s* pwm = bflb_device_get_by_name("pwm_v2_0"); diff --git a/bsp/bouffalo_lab/libraries/rt_drivers/drv_rtc.c b/bsp/bouffalo_lab/libraries/rt_drivers/drv_rtc.c index 7684cefb14..b4da15d734 100644 --- a/bsp/bouffalo_lab/libraries/rt_drivers/drv_rtc.c +++ b/bsp/bouffalo_lab/libraries/rt_drivers/drv_rtc.c @@ -12,12 +12,12 @@ #include "board.h" #include "drv_rtc.h" +#ifdef BSP_USING_RTC + #define DBG_TAG "DRV.RTC" #define DBG_LVL DBG_WARNING #include -#ifdef RT_USING_RTC - static struct rt_device rtc; static rt_uint32_t rtc_time; @@ -87,4 +87,4 @@ int rt_hw_rtc_init(void) } INIT_DEVICE_EXPORT(rt_hw_rtc_init); -#endif /* RT_USING_RTC */ +#endif /* BSP_USING_RTC */ diff --git a/bsp/bouffalo_lab/libraries/rt_drivers/drv_soft_i2c.c b/bsp/bouffalo_lab/libraries/rt_drivers/drv_soft_i2c.c index 0d20c1d119..8ffb6dab9b 100644 --- a/bsp/bouffalo_lab/libraries/rt_drivers/drv_soft_i2c.c +++ b/bsp/bouffalo_lab/libraries/rt_drivers/drv_soft_i2c.c @@ -12,7 +12,8 @@ #include "bflb_gpio.h" #include "bflb_common.h" -#ifdef RT_USING_I2C +#ifdef BSP_USING_I2C + #define DBG_LEVEL DBG_LOG #include #define LOG_TAG "DRV.I2C" @@ -208,4 +209,4 @@ int rt_hw_i2c_init(void) } INIT_BOARD_EXPORT(rt_hw_i2c_init); -#endif /* RT_USING_I2C */ +#endif /* BSP_USING_I2C */ diff --git a/bsp/bouffalo_lab/libraries/rt_drivers/drv_spi.c b/bsp/bouffalo_lab/libraries/rt_drivers/drv_spi.c new file mode 100644 index 0000000000..f2429a1de1 --- /dev/null +++ b/bsp/bouffalo_lab/libraries/rt_drivers/drv_spi.c @@ -0,0 +1,568 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-05-01 flyingcys first version + */ + +#include +#include +#include + +#include "board.h" +#include "drv_spi.h" + +#ifdef BSP_USING_SPI + +#define DBG_LEVEL DBG_LOG +#include +#define LOG_TAG "drv.spi" + +#define DMA_MAX_BUFSIZE 4095 + +#if defined(BSP_USING_BL808) +#define NOCACHE_BUFSTART 0x22026000 +#define NOCACHE_BUFSIZE (40 * 1024) +#elif defined (BSP_USING_BL61X) +#define NOCACHE_BUFSTART 0x22FC6000 +#define NOCACHE_BUFSIZE (104 * 1024) +#endif + +struct bl_device_spi +{ + struct rt_spi_bus spi_bus; + struct bflb_device_s *spi; + +#if defined(BSP_SPI_TX_USING_DMA) + struct bflb_device_s *dma_tx; + rt_uint32_t dma_dst_req; + rt_sem_t sem_tx; +#endif + +#if defined(BSP_SPI_RX_USING_DMA) + struct bflb_device_s *dma_rx; + rt_uint32_t dma_src_req; + rt_sem_t sem_rx; +#endif +}; + +#if defined(BSP_SPI_TX_USING_DMA) && defined(BSP_SPI_TX_DMA_NOCACHE_BUFSIZE) +static ATTR_NOCACHE_NOINIT_RAM_SECTION rt_uint8_t dma_tx_buf[BSP_SPI_TX_DMA_NOCACHE_BUFSIZE]; +#endif + +#if defined(BSP_SPI_RX_USING_DMA) && defined(BSP_SPI_RX_DMA_NOCACHE_BUFSIZE) +static ATTR_NOCACHE_NOINIT_RAM_SECTION rt_uint8_t dma_rx_buf[BSP_SPI_RX_DMA_NOCACHE_BUFSIZE]; +#endif + +#if defined(BSP_SPI_TX_USING_DMA) +static void spi_bl_spi_dma_tx_isr(void *arg) +{ + struct bl_device_spi *bl_spi = (struct bl_device_spi *)arg; + LOG_D("spi dma tx done "); + + rt_sem_release(bl_spi->sem_tx); +} +#endif + +#if defined(BSP_SPI_RX_USING_DMA) +void spi_dma_rx_isr(void *arg) +{ + struct bl_device_spi *bl_spi = (struct bl_device_spi *)arg; + LOG_D("spi dma rx done"); + + rt_sem_release(bl_spi->sem_rx); +} +#endif + +static rt_err_t spi_configure(struct rt_spi_device *device, + struct rt_spi_configuration *cfg) +{ + RT_ASSERT(device != RT_NULL); + RT_ASSERT(device->bus != RT_NULL); + RT_ASSERT(device->bus->parent.user_data != RT_NULL); + RT_ASSERT(cfg != RT_NULL); + + struct bflb_spi_config_s spi_cfg = { + .freq = 1 * 1000 * 1000, + .role = SPI_ROLE_MASTER, + .mode = SPI_MODE3, + .data_width = SPI_DATA_WIDTH_8BIT, + .bit_order = SPI_BIT_MSB, + .byte_order = SPI_BYTE_LSB, + .tx_fifo_threshold = 0, + .rx_fifo_threshold = 0, + }; + + switch (cfg->mode & RT_SPI_MODE_3) + { + case RT_SPI_MODE_0: /* RT_SPI_CPOL:0 , RT_SPI_CPHA:0 */ + spi_cfg.mode = SPI_MODE0; + break; + case RT_SPI_MODE_1: /* RT_SPI_CPOL:0 , RT_SPI_CPHA:1 */ + spi_cfg.mode = SPI_MODE1; + break; + case RT_SPI_MODE_2: /* RT_SPI_CPOL:1 , RT_SPI_CPHA:0 */ + spi_cfg.mode = SPI_MODE2; + break; + case RT_SPI_MODE_3: /* RT_SPI_CPOL:1 , RT_SPI_CPHA:1 */ + spi_cfg.mode = SPI_MODE3; + break; + default: + LOG_E("spi_configure mode error %x\n", cfg->mode); + return -RT_EINVAL; + } + + switch (cfg->data_width) + { + case 8: + spi_cfg.data_width = SPI_DATA_WIDTH_8BIT; + break; + case 16: + spi_cfg.data_width = SPI_DATA_WIDTH_16BIT; + break; + case 24: + spi_cfg.data_width = SPI_DATA_WIDTH_24BIT; + break; + case 32: + spi_cfg.data_width = SPI_DATA_WIDTH_32BIT; + break; + default: + LOG_E("spi_configure data_width error %x\n", cfg->data_width); + return RT_ERROR; + } + + spi_cfg.freq = cfg->max_hz; + + if (cfg->mode & RT_SPI_MSB) + spi_cfg.bit_order = SPI_BIT_MSB; + else + spi_cfg.bit_order = SPI_BIT_LSB; + + if (cfg->mode & RT_SPI_SLAVE) + spi_cfg.role = SPI_ROLE_SLAVE; + else + spi_cfg.role = SPI_ROLE_MASTER; + + struct bl_device_spi *bl_spi; + bl_spi = (struct bl_device_spi *)device->bus->parent.user_data; + + bflb_spi_init(bl_spi->spi, &spi_cfg); + +#if defined(BSP_SPI_TX_USING_DMA) + bl_spi->sem_tx = rt_sem_create("dam_tx", 0, RT_IPC_FLAG_PRIO); + if (bl_spi->sem_tx == RT_NULL) + { + LOG_E("rt_sem_create dma_tx error"); + return -RT_ENOMEM; + } + + rt_uint8_t tx_data_width = DMA_DATA_WIDTH_8BIT; + if (spi_cfg.data_width == SPI_DATA_WIDTH_8BIT) + tx_data_width = DMA_DATA_WIDTH_8BIT; + else if (spi_cfg.data_width == SPI_DATA_WIDTH_16BIT) + tx_data_width = DMA_DATA_WIDTH_16BIT; + else if (spi_cfg.data_width == SPI_DATA_WIDTH_32BIT) + tx_data_width = DMA_DATA_WIDTH_32BIT; + else + { + LOG_E("spi dma not support 24bit..."); + return -RT_EINVAL; + } + + struct bflb_dma_channel_config_s tx_config = { + .direction = DMA_MEMORY_TO_PERIPH, + .src_req = DMA_REQUEST_NONE, + .dst_req = bl_spi->dma_dst_req, + .src_addr_inc = DMA_ADDR_INCREMENT_ENABLE, + .dst_addr_inc = DMA_ADDR_INCREMENT_DISABLE, + .src_burst_count = DMA_BURST_INCR1, + .dst_burst_count = DMA_BURST_INCR1, + .src_width = tx_data_width, + .dst_width = tx_data_width, + }; + + bflb_spi_link_txdma(bl_spi->spi, true); + bflb_dma_channel_init(bl_spi->dma_tx, &tx_config); + bflb_dma_channel_irq_attach(bl_spi->dma_tx, spi_bl_spi_dma_tx_isr, (void *)bl_spi); +#endif + +#if defined(BSP_SPI_RX_USING_DMA) + bl_spi->sem_rx = rt_sem_create("dam_rx", 0, RT_IPC_FLAG_PRIO); + if (bl_spi->sem_rx == RT_NULL) + { + LOG_E("rt_sem_create dma_rx error"); + return -RT_ENOMEM; + } + + rt_uint8_t rx_data_width = DMA_DATA_WIDTH_8BIT; + if (spi_cfg.data_width == SPI_DATA_WIDTH_8BIT) + rx_data_width = DMA_DATA_WIDTH_8BIT; + else if (spi_cfg.data_width == SPI_DATA_WIDTH_16BIT) + rx_data_width = DMA_DATA_WIDTH_16BIT; + else if (spi_cfg.data_width == SPI_DATA_WIDTH_32BIT) + rx_data_width = DMA_DATA_WIDTH_32BIT; + else + { + LOG_E("spi dma not support 24bit..."); + return -RT_EINVAL; + } + + struct bflb_dma_channel_config_s rx_config = { + .direction = DMA_PERIPH_TO_MEMORY, + .src_req = bl_spi->dma_src_req, + .dst_req = DMA_REQUEST_NONE, + .src_addr_inc = DMA_ADDR_INCREMENT_DISABLE, + .dst_addr_inc = DMA_ADDR_INCREMENT_ENABLE, + .src_burst_count = DMA_BURST_INCR1, + .dst_burst_count = DMA_BURST_INCR1, + .src_width = rx_data_width, + .dst_width = rx_data_width, + }; + + bflb_spi_link_rxdma(bl_spi->spi, true); + bflb_dma_channel_init(bl_spi->dma_rx, &rx_config); + bflb_dma_channel_irq_attach(bl_spi->dma_rx, spi_dma_rx_isr, (void *)bl_spi); +#endif + + return RT_EOK; +} + +#if defined(BSP_SPI_TX_USING_DMA) +static rt_err_t _bl_spi_dma_tx(struct bl_device_spi *bl_spi, rt_uint8_t *src, rt_size_t length) +{ + rt_err_t result; + struct bflb_dma_channel_lli_pool_s tx_llipool[1]; + struct bflb_dma_channel_lli_transfer_s tx_transfers[1]; + + tx_transfers[0].src_addr = (rt_uint32_t)src; + tx_transfers[0].dst_addr = (rt_uint32_t)DMA_ADDR_SPI0_TDR; + tx_transfers[0].nbytes = length; + + LOG_D("dma tx start..."); + rt_kprintf("tx length:%d\n", length); + bflb_dma_channel_lli_reload(bl_spi->dma_tx, tx_llipool, 1, tx_transfers, 1); + bflb_dma_channel_start(bl_spi->dma_tx); + + result = rt_sem_take(bl_spi->sem_tx, BSP_SPI_TX_DMA_TIMEOUT); + if (result != RT_EOK) + LOG_E("sem take dma tx error:%d", result); + + return result; +} + +static rt_err_t _spi_dma_xfer_tx(struct rt_spi_device *device, struct rt_spi_message *message) +{ + rt_err_t result = RT_EOK; + rt_uint8_t *src = (rt_uint8_t *)message->send_buf; + rt_size_t length = message->length; + struct bl_device_spi *bl_spi = (struct bl_device_spi *)device->bus->parent.user_data; + +#if defined(NOCACHE_BUFSTART) && defined(NOCACHE_BUFSIZE) + if ((message->send_buf < NOCACHE_BUFSTART) || (message->send_buf > (NOCACHE_BUFSTART + NOCACHE_BUFSIZE))) + { + if (length <= BSP_SPI_TX_DMA_NOCACHE_BUFSIZE) + { + memcpy(dma_tx_buf, src, length); + result = _bl_spi_dma_tx(bl_spi, dma_tx_buf, length); + } + else + { + while(length > 0) + { + if (length >= BSP_SPI_TX_DMA_NOCACHE_BUFSIZE) + { + memcpy(dma_tx_buf, src, BSP_SPI_TX_DMA_NOCACHE_BUFSIZE); + result = _bl_spi_dma_tx(bl_spi, dma_tx_buf, BSP_SPI_TX_DMA_NOCACHE_BUFSIZE); + if (result != RT_EOK) + break; + + length -= BSP_SPI_TX_DMA_NOCACHE_BUFSIZE; + src += BSP_SPI_TX_DMA_NOCACHE_BUFSIZE; + } + else + { + memcpy(dma_tx_buf, src, length); + result = _bl_spi_dma_tx(bl_spi, dma_tx_buf, length); + length = 0; + } + } + } + } + else +#endif + { + if (length <= DMA_MAX_BUFSIZE) + { + result = _bl_spi_dma_tx(bl_spi, src, length); + } + else + { + while(length > 0) + { + if (length >= DMA_MAX_BUFSIZE) + { + result = _bl_spi_dma_tx(bl_spi, src, DMA_MAX_BUFSIZE); + if (result != RT_EOK) + break; + + length -= DMA_MAX_BUFSIZE; + src += DMA_MAX_BUFSIZE; + } + else + { + result = _bl_spi_dma_tx(bl_spi, src, length); + length = 0; + } + } + } + } + + LOG_D("dma tx finish..."); + + return result; +} +#endif + +#if defined(BSP_SPI_RX_USING_DMA) +static rt_err_t _bl_spi_dma_rx(struct bl_device_spi *bl_spi, rt_uint8_t *dst, rt_size_t length) +{ + rt_err_t result; + struct bflb_dma_channel_lli_pool_s rx_llipool[1]; + struct bflb_dma_channel_lli_transfer_s rx_transfers[1]; + + rx_transfers[0].src_addr = (rt_uint32_t)DMA_ADDR_SPI0_RDR; + rx_transfers[0].dst_addr = (rt_uint32_t)dst; + rx_transfers[0].nbytes = length; + + bflb_dma_channel_lli_reload(bl_spi->dma_rx, rx_llipool, 1, rx_transfers, 1); + bflb_dma_channel_start(bl_spi->dma_rx); + + result = rt_sem_take(bl_spi->sem_rx, BSP_SPI_RX_DMA_TIMEOUT); + if (result != RT_EOK) + LOG_E("sem take dma rx error:%d", result); + + return result; +} + +static rt_err_t _spi_dma_xfer_rx(struct rt_spi_device *device, struct rt_spi_message *message) +{ + rt_err_t result = RT_EOK; + rt_uint8_t *dst = (rt_uint8_t *)message->recv_buf; + rt_size_t length = message->length; + struct bl_device_spi *bl_spi = (struct bl_device_spi *)device->bus->parent.user_data; + +#if defined(NOCACHE_BUFSTART) && defined(NOCACHE_BUFSIZE) + if ((message->recv_buf < NOCACHE_BUFSTART) || (message->recv_buf > (NOCACHE_BUFSTART + NOCACHE_BUFSIZE))) + { + if (length <= BSP_SPI_RX_DMA_NOCACHE_BUFSIZE) + { + result = _bl_spi_dma_rx(bl_spi, dst, length); + if (result == RT_EOK) + memcpy(dst, dma_rx_buf, length); + } + else + { + while(length > 0) + { + if (length >= BSP_SPI_RX_DMA_NOCACHE_BUFSIZE) + { + result = _bl_spi_dma_rx(bl_spi, dma_tx_buf, BSP_SPI_RX_DMA_NOCACHE_BUFSIZE); + if (result != RT_EOK) + break; + memcpy(dst, dma_rx_buf, BSP_SPI_RX_DMA_NOCACHE_BUFSIZE); + length -= BSP_SPI_RX_DMA_NOCACHE_BUFSIZE; + dst += BSP_SPI_RX_DMA_NOCACHE_BUFSIZE; + } + else + { + result = _bl_spi_dma_rx(bl_spi, dma_rx_buf, length); + if (result != RT_EOK) + break; + memcpy(dst, dma_rx_buf, length); + length = 0; + } + } + } + } + else +#endif + { + if (length <= DMA_MAX_BUFSIZE) + { + result = _bl_spi_dma_rx(bl_spi, dst, length); + if (result == RT_EOK) + memcpy(dst, dma_rx_buf, length); + } + else + { + while(length > 0) + { + if (length >= DMA_MAX_BUFSIZE) + { + result = _bl_spi_dma_rx(bl_spi, dst, DMA_MAX_BUFSIZE); + if (result != RT_EOK) + break; + + memcpy(dst, dma_rx_buf, DMA_MAX_BUFSIZE); + length -= DMA_MAX_BUFSIZE; + dst += DMA_MAX_BUFSIZE; + } + else + { + result = _bl_spi_dma_rx(bl_spi, dst, length); + if (result != RT_EOK) + break; + memcpy(dst, dma_rx_buf, length); + length = 0; + } + } + } + } + + LOG_D("dma rx finish..."); + + return result; +} +#endif + +static rt_ssize_t spixfer(struct rt_spi_device *device, struct rt_spi_message *message) +{ + RT_ASSERT(device != RT_NULL); + RT_ASSERT(device->bus != RT_NULL); + RT_ASSERT(device->bus->parent.user_data != RT_NULL); + + rt_err_t result; + rt_uint32_t cs_pin = (rt_uint32_t)device->parent.user_data; + struct bflb_device_s* gpio = bflb_device_get_by_name("gpio"); + + struct bl_device_spi *bl_spi; + bl_spi = (struct bl_device_spi *)device->bus->parent.user_data; + + if (message->cs_take && !(device->config.mode & RT_SPI_NO_CS)) + { + if (device->config.mode & RT_SPI_CS_HIGH) + bflb_gpio_set(gpio, cs_pin); + else + bflb_gpio_reset(gpio, cs_pin); + } + + if (message->send_buf && message->recv_buf) + { + rt_memset(message->recv_buf, 0x0, message->length); + + bflb_spi_poll_exchange(bl_spi->spi, (void *)message->send_buf, (void *)message->recv_buf, message->length); + message->length += strlen(message->recv_buf); + } + else if (message->send_buf) + { +#if defined(BSP_SPI_TX_USING_DMA) + result = _spi_dma_xfer_tx(device, message); + if(result != RT_EOK) + message->length = -1; +#else + bflb_spi_poll_exchange(bl_spi->spi, (void *)message->send_buf, NULL, message->length); +#endif + } + else if (message->recv_buf) + { + rt_memset(message->recv_buf, 0x0, message->length); + +#if defined(BSP_SPI_RX_USING_DMA) + result = _spi_dma_xfer_rx(device, message); + if(result != RT_EOK) + message->length = -1; +#else + bflb_spi_poll_exchange(bl_spi->spi, NULL, (void *)message->recv_buf, message->length); +#endif + } + else + { + LOG_E("both send_buf and recv_buf is null!"); + message->length = -1; + } + + if (message->cs_release && !(device->config.mode & RT_SPI_NO_CS)) + { + if (device->config.mode & RT_SPI_CS_HIGH) + bflb_gpio_reset(gpio, cs_pin); + else + bflb_gpio_set(gpio, cs_pin); + } + + return message->length; +} + +/* spi bus callback function */ +static const struct rt_spi_ops bl_spi_ops = +{ + .configure = spi_configure, + .xfer = spixfer, +}; + +/** + * 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, rt_uint32_t cs_pin) +{ + RT_ASSERT(bus_name != RT_NULL); + RT_ASSERT(device_name != RT_NULL); + + rt_err_t ret; + struct rt_spi_device *spi_device; + + /* attach the device to spi bus*/ + spi_device = (struct rt_spi_device *)rt_malloc(sizeof(struct rt_spi_device)); + + RT_ASSERT(spi_device != RT_NULL); + /* initialize the cs pin */ + ret = rt_spi_bus_attach_device(spi_device, device_name, bus_name, (void *)cs_pin); + if (ret != RT_EOK) + { + LOG_E("%s attach to %s faild, %d", device_name, bus_name, ret); + ret = RT_ERROR; + } + + RT_ASSERT(ret == RT_EOK); + return ret; +} + +int rt_hw_spi_init(void) +{ + rt_err_t ret = RT_ERROR; + + static struct bl_device_spi dev_spi; + + struct bflb_device_s *gpio; + gpio = bflb_device_get_by_name("gpio"); +#ifndef BL808_CORE_D0 + bflb_gpio_init(gpio, SPI_SCK_PIN, GPIO_FUNC_SPI0 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1); + bflb_gpio_init(gpio, SPI_MISO_PIN, GPIO_FUNC_SPI0 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1); + bflb_gpio_init(gpio, SPI_MOSI_PIN, GPIO_FUNC_SPI0 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1); + + dev_spi.spi = bflb_device_get_by_name("spi0"); + +#ifdef BSP_SPI_TX_USING_DMA + dev_spi.dma_dst_req = DMA_REQUEST_SPI0_TX; + dev_spi.dma_tx = bflb_device_get_by_name(BSP_SPI_TX_DMA_CHANNEL); +#endif + +#ifdef BSP_SPI_RX_USING_DMA + dev_spi.dma_src_req = DMA_REQUEST_SPI0_RX; + dev_spi.dma_rx = bflb_device_get_by_name(BSP_SPI_RX_DMA_CHANNEL); +#endif + +#endif /* BL808_CORE_D0 */ + + dev_spi.spi_bus.parent.user_data = (void *)&dev_spi; + + ret = rt_spi_bus_register(&dev_spi.spi_bus, "spi0", &bl_spi_ops); + RT_ASSERT(ret == RT_EOK); + + return ret; +} +INIT_BOARD_EXPORT(rt_hw_spi_init); + +#endif /* BSP_USING_SPI */ diff --git a/bsp/bouffalo_lab/libraries/rt_drivers/drv_spi.h b/bsp/bouffalo_lab/libraries/rt_drivers/drv_spi.h new file mode 100755 index 0000000000..01ea21e3e9 --- /dev/null +++ b/bsp/bouffalo_lab/libraries/rt_drivers/drv_spi.h @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-05-01 flyingcys first version + */ + +#include +#include +#include +#include "bflb_spi.h" +#include "bflb_dma.h" + +#ifndef __DRV_SPI_H_ +#define __DRV_SPI_H_ + +#ifdef SPI_SCK_USING_GPIO1 +#define SPI_SCK_PIN GPIO_PIN_1 +#elif defined(SPI_SCK_USING_GPIO3) +#define SPI_SCK_PIN GPIO_PIN_3 +#elif defined(SPI_SCK_USING_GPIO5) +#define SPI_SCK_PIN GPIO_PIN_5 +#elif defined(SPI_SCK_USING_GPIO7) +#define SPI_SCK_PIN GPIO_PIN_7 +#elif defined(SPI_SCK_USING_GPIO9) +#define SPI_SCK_PIN GPIO_PIN_9 +#elif defined(SPI_SCK_USING_GPIO11) +#define SPI_SCK_PIN GPIO_PIN_11 +#elif defined(SPI_SCK_USING_GPIO13) +#define SPI_SCK_PIN GPIO_PIN_13 +#elif defined(SPI_SCK_USING_GPIO15) +#define SPI_SCK_PIN GPIO_PIN_15 +#elif defined(SPI_SCK_USING_GPIO17) +#define SPI_SCK_PIN GPIO_PIN_17 +#elif defined(SPI_SCK_USING_GPIO19) +#define SPI_SCK_PIN GPIO_PIN_19 +#elif defined(SPI_SCK_USING_GPIO21) +#define SPI_SCK_PIN GPIO_PIN_21 +#elif defined(SPI_SCK_USING_GPIO23) +#define SPI_SCK_PIN GPIO_PIN_23 +#elif defined(SPI_SCK_USING_GPIO25) +#define SPI_SCK_PIN GPIO_PIN_25 +#elif defined(SPI_SCK_USING_GPIO27) +#define SPI_SCK_PIN GPIO_PIN_27 +#elif defined(SPI_SCK_USING_GPIO29) +#define SPI_SCK_PIN GPIO_PIN_29 +#elif defined(SPI_SCK_USING_GPIO31) +#define SPI_SCK_PIN GPIO_PIN_31 +#elif defined(SPI_SCK_USING_GPIO33) +#define SPI_SCK_PIN GPIO_PIN_33 +#elif defined(SPI_SCK_USING_GPIO35) +#define SPI_SCK_PIN GPIO_PIN_35 +#elif defined(SPI_SCK_USING_GPIO39) +#define SPI_SCK_PIN GPIO_PIN_39 +#elif defined(SPI_SCK_USING_GPIO43) +#define SPI_SCK_PIN GPIO_PIN_43 +#endif + +#ifdef SPI_MISO_USING_GPIO0 +#define SPI_MISO_PIN GPIO_PIN_0 +#elif defined(SPI_MISO_USING_GPIO1) +#define SPI_MISO_PIN GPIO_PIN_1 +#elif defined(SPI_MISO_USING_GPIO2) +#define SPI_MISO_PIN GPIO_PIN_2 +#elif defined(SPI_MISO_USING_GPIO4) +#define SPI_MISO_PIN GPIO_PIN_4 +#elif defined(SPI_MISO_USING_GPIO5) +#define SPI_MISO_PIN GPIO_PIN_5 +#elif defined(SPI_MISO_USING_GPIO6) +#define SPI_MISO_PIN GPIO_PIN_6 +#elif defined(SPI_MISO_USING_GPIO8) +#define SPI_MISO_PIN GPIO_PIN_8 +#elif defined(SPI_MISO_USING_GPIO9) +#define SPI_MISO_PIN GPIO_PIN_9 +#elif defined(SPI_MISO_USING_GPIO10) +#define SPI_MISO_PIN GPIO_PIN_10 +#elif defined(SPI_MISO_USING_GPIO12) +#define SPI_MISO_PIN GPIO_PIN_12 +#elif defined(SPI_MISO_USING_GPIO13) +#define SPI_MISO_PIN GPIO_PIN_13 +#elif defined(SPI_MISO_USING_GPIO14) +#define SPI_MISO_PIN GPIO_PIN_14 +#elif defined(SPI_MISO_USING_GPIO16) +#define SPI_MISO_PIN GPIO_PIN_16 +#elif defined(SPI_MISO_USING_GPIO17) +#define SPI_MISO_PIN GPIO_PIN_17 +#elif defined(SPI_MISO_USING_GPIO18) +#define SPI_MISO_PIN GPIO_PIN_18 +#elif defined(SPI_MISO_USING_GPIO20) +#define SPI_MISO_PIN GPIO_PIN_20 +#elif defined(SPI_MISO_USING_GPIO21) +#define SPI_MISO_PIN GPIO_PIN_21 +#elif defined(SPI_MISO_USING_GPIO22) +#define SPI_MISO_PIN GPIO_PIN_22 +#elif defined(SPI_MISO_USING_GPIO25) +#define SPI_MISO_PIN GPIO_PIN_25 +#elif defined(SPI_MISO_USING_GPIO26) +#define SPI_MISO_PIN GPIO_PIN_26 +#elif defined(SPI_MISO_USING_GPIO29) +#define SPI_MISO_PIN GPIO_PIN_29 +#elif defined(SPI_MISO_USING_GPIO30) +#define SPI_MISO_PIN GPIO_PIN_30 +#elif defined(SPI_MISO_USING_GPIO34) +#define SPI_MISO_PIN GPIO_PIN_34 +#elif defined(SPI_MISO_USING_GPIO38) +#define SPI_MISO_PIN GPIO_PIN_38 +#elif defined(SPI_MISO_USING_GPIO42) +#define SPI_MISO_PIN GPIO_PIN_42 +#endif + +#ifdef SPI_MOSI_USING_GPIO0 +#define SPI_MOSI_PIN GPIO_PIN_0 +#elif defined(SPI_MOSI_USING_GPIO1) +#define SPI_MOSI_PIN GPIO_PIN_1 +#elif defined(SPI_MOSI_USING_GPIO3) +#define SPI_MOSI_PIN GPIO_PIN_3 +#elif defined(SPI_MOSI_USING_GPIO4) +#define SPI_MOSI_PIN GPIO_PIN_4 +#elif defined(SPI_MOSI_USING_GPIO5) +#define SPI_MOSI_PIN GPIO_PIN_5 +#elif defined(SPI_MOSI_USING_GPIO7) +#define SPI_MOSI_PIN GPIO_PIN_7 +#elif defined(SPI_MOSI_USING_GPIO8) +#define SPI_MOSI_PIN GPIO_PIN_8 +#elif defined(SPI_MOSI_USING_GPIO9) +#define SPI_MOSI_PIN GPIO_PIN_9 +#elif defined(SPI_MOSI_USING_GPIO11) +#define SPI_MOSI_PIN GPIO_PIN_11 +#elif defined(SPI_MOSI_USING_GPIO12) +#define SPI_MOSI_PIN GPIO_PIN_12 +#elif defined(SPI_MOSI_USING_GPIO13) +#define SPI_MOSI_PIN GPIO_PIN_13 +#elif defined(SPI_MOSI_USING_GPIO15) +#define SPI_MOSI_PIN GPIO_PIN_15 +#elif defined(SPI_MOSI_USING_GPIO16) +#define SPI_MOSI_PIN GPIO_PIN_16 +#elif defined(SPI_MOSI_USING_GPIO17) +#define SPI_MOSI_PIN GPIO_PIN_17 +#elif defined(SPI_MOSI_USING_GPIO19) +#define SPI_MOSI_PIN GPIO_PIN_19 +#elif defined(SPI_MOSI_USING_GPIO20) +#define SPI_MOSI_PIN GPIO_PIN_20 +#elif defined(SPI_MOSI_USING_GPIO21) +#define SPI_MOSI_PIN GPIO_PIN_21 +#elif defined(SPI_MOSI_USING_GPIO23) +#define SPI_MOSI_PIN GPIO_PIN_23 +#elif defined(SPI_MOSI_USING_GPIO24) +#define SPI_MOSI_PIN GPIO_PIN_24 +#elif defined(SPI_MOSI_USING_GPIO25) +#define SPI_MOSI_PIN GPIO_PIN_25 +#elif defined(SPI_MOSI_USING_GPIO27) +#define SPI_MOSI_PIN GPIO_PIN_27 +#elif defined(SPI_MOSI_USING_GPIO28) +#define SPI_MOSI_PIN GPIO_PIN_28 +#elif defined(SPI_MOSI_USING_GPIO29) +#define SPI_MOSI_PIN GPIO_PIN_29 +#elif defined(SPI_MOSI_USING_GPIO31) +#define SPI_MOSI_PIN GPIO_PIN_31 +#elif defined(SPI_MOSI_USING_GPIO33) +#define SPI_MOSI_PIN GPIO_PIN_33 +#elif defined(SPI_MOSI_USING_GPIO37) +#define SPI_MOSI_PIN GPIO_PIN_37 +#elif defined(SPI_MOSI_USING_GPIO41) +#define SPI_MOSI_PIN GPIO_PIN_41 +#elif defined(SPI_MOSI_USING_GPIO45) +#define SPI_MOSI_PIN GPIO_PIN_45 +#endif + +rt_err_t rt_hw_spi_device_attach(const char *bus_name, const char *device_name, rt_uint32_t cs_pin); +int rt_hw_spi_init(void); + +#endif /*__DRV_SPI_H_*/ diff --git a/bsp/bouffalo_lab/libraries/rt_drivers/drv_wdt.c b/bsp/bouffalo_lab/libraries/rt_drivers/drv_wdt.c index 5a20a82d15..5c10b8ea18 100644 --- a/bsp/bouffalo_lab/libraries/rt_drivers/drv_wdt.c +++ b/bsp/bouffalo_lab/libraries/rt_drivers/drv_wdt.c @@ -10,7 +10,6 @@ #include "drv_wdt.h" -#ifdef RT_USING_WDT #ifdef BSP_USING_WDT #define DBG_LEVEL DBG_LOG #include @@ -94,4 +93,3 @@ int rt_hw_wdt_init(void) INIT_BOARD_EXPORT(rt_hw_wdt_init); #endif /* BSP_USING_WDT */ -#endif /* RT_USING_WDT */ diff --git a/bsp/bouffalo_lab/bl808/m0/applications/hwtimer_sample.c b/bsp/bouffalo_lab/libraries/rt_drivers/sample/hwtimer_sample.c old mode 100644 new mode 100755 similarity index 99% rename from bsp/bouffalo_lab/bl808/m0/applications/hwtimer_sample.c rename to bsp/bouffalo_lab/libraries/rt_drivers/sample/hwtimer_sample.c index ad5ce23475..e2f6e3abb2 --- a/bsp/bouffalo_lab/bl808/m0/applications/hwtimer_sample.c +++ b/bsp/bouffalo_lab/libraries/rt_drivers/sample/hwtimer_sample.c @@ -16,7 +16,8 @@ #include #include -#ifdef RT_USING_HWTIMER + +#ifdef BSP_USING_HWTIMER #define HWTIMER_DEV_NAME "timer0" /* 定时器名称 */ diff --git a/bsp/bouffalo_lab/bl808/m0/applications/pwm_led_sample.c b/bsp/bouffalo_lab/libraries/rt_drivers/sample/pwm_led_sample.c old mode 100644 new mode 100755 similarity index 99% rename from bsp/bouffalo_lab/bl808/m0/applications/pwm_led_sample.c rename to bsp/bouffalo_lab/libraries/rt_drivers/sample/pwm_led_sample.c index 4185847808..ca72ab2dc2 --- a/bsp/bouffalo_lab/bl808/m0/applications/pwm_led_sample.c +++ b/bsp/bouffalo_lab/libraries/rt_drivers/sample/pwm_led_sample.c @@ -16,7 +16,7 @@ #include #include -#ifdef RT_USING_PWM +#ifdef BSP_USING_PWM #define LED_PIN_NUM 8 /* LED PIN脚编号,查看驱动文件drv_gpio.c确定 */ #define PWM_DEV_NAME "pwm" /* PWM设备名称 */ diff --git a/bsp/bouffalo_lab/libraries/rt_drivers/sample/spi_sample.c b/bsp/bouffalo_lab/libraries/rt_drivers/sample/spi_sample.c new file mode 100755 index 0000000000..c395438801 --- /dev/null +++ b/bsp/bouffalo_lab/libraries/rt_drivers/sample/spi_sample.c @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2023-05-01 flyingcys first version + */ + +#include +#include + +#ifdef BSP_USING_SPI + +#define BUS_NAME "spi0" +#define SPI_NAME "spi00" + +static struct rt_spi_device *spi_dev = RT_NULL; + +/* attach spi5 device */ +static int rt_spi_device_init(void) +{ + struct rt_spi_configuration cfg; + + rt_hw_spi_device_attach(BUS_NAME, SPI_NAME, RT_NULL); + + cfg.data_width = 8; + cfg.mode = RT_SPI_MASTER | RT_SPI_MODE_0 | RT_SPI_MSB | RT_SPI_NO_CS; + cfg.max_hz = 10 *1000 *1000; + + spi_dev = (struct rt_spi_device *)rt_device_find(SPI_NAME); + + if (RT_NULL == spi_dev) + { + rt_kprintf("spi sample run failed! can't find %s device!\n", SPI_NAME); + return -RT_ERROR; + } + + rt_spi_configure(spi_dev, &cfg); + + return RT_EOK; +} +INIT_APP_EXPORT(rt_spi_device_init); + +/* spi loopback mode test case */ +static int spi_sample(int argc, char **argv) +{ + rt_uint8_t t_buf[8], r_buf[8]; + int i = 0; + static struct rt_spi_message msg1; + + if (argc != 9) + { + rt_kprintf("Please Usage:\n"); + rt_kprintf("spi_sample 1 2 3 4 5 6 7 8\n"); + return -RT_ERROR; + } + + for (i = 0; i < 8; i++) + { + t_buf[i] = atoi(argv[i+1]); + } + + msg1.send_buf = &t_buf; + msg1.recv_buf = &r_buf; + msg1.length = sizeof(t_buf); + msg1.cs_take = 1; + msg1.cs_release = 0; + msg1.next = RT_NULL; + + rt_spi_transfer_message(spi_dev, &msg1); + + rt_kprintf("spi rbuf : "); + for (i = 0; i < sizeof(t_buf); i++) + { + rt_kprintf("%x ", r_buf[i]); + } + + rt_kprintf("\nspi loopback mode test over!\n"); + + return RT_EOK; +} +MSH_CMD_EXPORT(spi_sample, spi loopback test); + +#endif /* BSP_USING_SPI */ diff --git a/bsp/bouffalo_lab/bl808/m0/applications/wdt_sample.c b/bsp/bouffalo_lab/libraries/rt_drivers/sample/wdt_sample.c old mode 100644 new mode 100755 similarity index 99% rename from bsp/bouffalo_lab/bl808/m0/applications/wdt_sample.c rename to bsp/bouffalo_lab/libraries/rt_drivers/sample/wdt_sample.c index 74418aab33..12093b1c3a --- a/bsp/bouffalo_lab/bl808/m0/applications/wdt_sample.c +++ b/bsp/bouffalo_lab/libraries/rt_drivers/sample/wdt_sample.c @@ -19,7 +19,7 @@ #include #include -#ifdef RT_USING_WDT +#ifdef BSP_USING_WDT #define WDT_DEVICE_NAME "wdt" /* 看门狗设备名称 */