Browse Source

[bsp]add new bsp-bl808 (#6824)

* add new bsp-bl808

* support ARCH_RISCV_FPU_S && update rtconfig.py
flyingcys 2 years ago
parent
commit
98a997c57e
100 changed files with 21841 additions and 0 deletions
  1. 111 0
      bsp/bl808/README.md
  2. BIN
      bsp/bl808/figures/bl808.jpg
  3. BIN
      bsp/bl808/figures/program.jpg
  4. 971 0
      bsp/bl808/m0/.config
  5. 20 0
      bsp/bl808/m0/Kconfig
  6. 14 0
      bsp/bl808/m0/SConscript
  7. 36 0
      bsp/bl808/m0/SConstruct
  8. 9 0
      bsp/bl808/m0/applications/SConscript
  9. 19 0
      bsp/bl808/m0/applications/main.c
  10. 46 0
      bsp/bl808/m0/drivers/Kconfig
  11. 53 0
      bsp/bl808/m0/drivers/SConscript
  12. 104 0
      bsp/bl808/m0/drivers/board.c
  13. 35 0
      bsp/bl808/m0/drivers/board.h
  14. 318 0
      bsp/bl808/m0/drivers/drv_uart.c
  15. 25 0
      bsp/bl808/m0/drivers/drv_uart.h
  16. 101 0
      bsp/bl808/m0/libraries/SConscript
  17. 38 0
      bsp/bl808/m0/libraries/platform/hosal/adapter/hosal_adapter.h
  18. 45 0
      bsp/bl808/m0/libraries/platform/hosal/adapter/hosal_adpt_iotsdk.c
  19. 545 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_audio.c
  20. 120 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_audio.h
  21. 145 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_boot2.c
  22. 197 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_boot2.h
  23. 79 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_cam.c
  24. 35 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_cam.h
  25. 188 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_chip.c
  26. 35 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_chip.h
  27. 127 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_efuse.c
  28. 40 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_efuse.h
  29. 746 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_ethernetif.c
  30. 76 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_ethernetif.h
  31. 184 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_flash.c
  32. 42 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_flash.h
  33. 73 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_ipc.c
  34. 37 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_ipc.h
  35. 418 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_irq.c
  36. 74 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_irq.h
  37. 272 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_mm_clock.c
  38. 86 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_mm_clock.h
  39. 489 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_pm.c
  40. 111 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_pm.h
  41. 51 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_psram.c
  42. 34 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_psram.h
  43. 1715 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_sdh.c
  44. 516 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_sdh.h
  45. 797 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_sec.c
  46. 85 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_sec.h
  47. 180 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_sec_sha.c
  48. 325 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_sys.c
  49. 61 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_sys.h
  50. 132 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_timer.c
  51. 35 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_timer.h
  52. 552 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_uart.c
  53. 62 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_uart.h
  54. 322 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_usb_cam.c
  55. 35 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_usb_cam.h
  56. 255 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_wifi.c
  57. 52 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_wifi.h
  58. 30 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/emac_phy.c
  59. 49 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/ethernet_phy.h
  60. 574 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/ethernetif.c
  61. 49 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/ethernetif.h
  62. 1273 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/hal_board.c
  63. 34 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/hal_board.h
  64. 314 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/hal_boot2.c
  65. 87 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/hal_boot2.h
  66. 50 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/hal_common.h
  67. 666 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/hal_emac.c
  68. 127 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/hal_emac.h
  69. 91 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/hal_sdh.c
  70. 33 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/hal_sdh.h
  71. 139 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/hal_sys.c
  72. 67 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/hal_sys.h
  73. 284 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/hal_uart.c
  74. 35 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/hal_uart.h
  75. 1285 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/hal_usb.c
  76. 158 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/hal_usb.h
  77. 51 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/hal_wifi.c
  78. 33 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/hal_wifi.h
  79. 527 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/hosal_adc.c
  80. 314 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/hosal_dma.c
  81. 267 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/hosal_pwm.c
  82. 275 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/hosal_spi.c
  83. 557 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/hosal_uart.c
  84. 419 0
      bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/phy_8720.c
  85. 238 0
      bsp/bl808/m0/libraries/platform/hosal/include/hosal_adc.h
  86. 187 0
      bsp/bl808/m0/libraries/platform/hosal/include/hosal_dac.h
  87. 152 0
      bsp/bl808/m0/libraries/platform/hosal/include/hosal_dma.h
  88. 70 0
      bsp/bl808/m0/libraries/platform/hosal/include/hosal_efuse.h
  89. 229 0
      bsp/bl808/m0/libraries/platform/hosal/include/hosal_flash.h
  90. 186 0
      bsp/bl808/m0/libraries/platform/hosal/include/hosal_gpio.h
  91. 212 0
      bsp/bl808/m0/libraries/platform/hosal/include/hosal_i2c.h
  92. 175 0
      bsp/bl808/m0/libraries/platform/hosal/include/hosal_pwm.h
  93. 74 0
      bsp/bl808/m0/libraries/platform/hosal/include/hosal_rng.h
  94. 146 0
      bsp/bl808/m0/libraries/platform/hosal/include/hosal_rtc.h
  95. 178 0
      bsp/bl808/m0/libraries/platform/hosal/include/hosal_spi.h
  96. 118 0
      bsp/bl808/m0/libraries/platform/hosal/include/hosal_timer.h
  97. 356 0
      bsp/bl808/m0/libraries/platform/hosal/include/hosal_uart.h
  98. 99 0
      bsp/bl808/m0/libraries/platform/hosal/include/hosal_wdg.h
  99. 251 0
      bsp/bl808/m0/libraries/platform/hosal/platform_hal/platform_hal_device.cpp
  100. 109 0
      bsp/bl808/m0/libraries/platform/hosal/platform_hal/platform_hal_device.h

+ 111 - 0
bsp/bl808/README.md

@@ -0,0 +1,111 @@
+# 博流智能 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: <br />RV64GCV 480MHz<br/>RV32GCP 320MHz<br/>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<br/>支持 Bluetooth 5.x Dual-mode(BT+BLE)<br/>支持 Wi-Fi / 蓝牙 共存 |
+
+## 2. 编译说明
+
+BL808是多核异构架构,每个核需要单独编译,并烧录到对应的位置。
+
+Windows下推荐使用[env工具][1],然后在console下进入bsp/bl808目录中,选择需要编译的核心,m0或d0,运行:
+
+    cd bsp/bl808/m0
+    menuconfig
+    pkgs --update
+
+如果在Linux平台下,可以先执行
+
+    scons --menuconfig
+
+它会自动下载env相关脚本到~/.env目录,然后执行
+
+    source ~/.env/env.sh
+    
+    cd bsp/bl808/m0
+    pkgs --update
+下载risc-v的工具链,[下载地址](https://occ.t-head.cn/community/download?id=4073475960903634944)或[下载地址](https://dl.sipeed.com/shareURL/others/toolchain)
+
+更新完软件包后,在`rtconfig.py`中将risc-v工具链的本地路径加入文档。
+
+然后执行scons编译:  
+
+```
+    set RTT_EXEC_PATH=C:\Users\xxxx\Downloads\Xuantie-900-gcc-elf-newlib-x86_64-V2.6.1/bin
+    scons
+```
+来编译这个板级支持包。
+
+或者通过 `scons --exec-path="GCC工具链路径"` 命令,在指定工具链位置的同时直接编译。
+
+如果编译正确无误,会产生rtthread.elf、rtthread_m0.bin文件。其中rtthread_m0.bin需要烧写到设备中进行运行。  
+
+## 3. 烧写及执行
+
+连接好串口,然后使用[Bouffalo Lab Dev Cube](https://dev.bouffalolab.com/download)工具进行烧写bin文件。
+
+![Bouffalo Lab Dev Cube](figures/program.jpg)
+
+### 3.1 运行结果
+
+如果编译 & 烧写无误,当复位设备后,会在串口上看到RT-Thread的启动logo信息:
+
+![terminal](figures/bl808.jpg)
+
+## 4. 驱动支持情况及计划
+
+| 驱动 | 支持情况  |  备注  |
+| ------ | ----  | :------:  |
+| UART | 支持 | UART0,用于shell,默认波特率2000000 |
+
+## 5. 联系人信息
+
+维护人:[flyingcys](https://github.com/flyingcys)
+
+## 6. 支持开发板列表
+
+|        | 开发板型号 |
+| ------ | ---------- |
+| Sipeed | M1s Dock   |
+|        |            |
+
+
+## 7. 参考
+* 芯片[datasheet][2]
+
+  [1]: https://www.rt-thread.org/page/download.html
+  [2]: https://github.com/bouffalolab/bl_docs

BIN
bsp/bl808/figures/bl808.jpg


BIN
bsp/bl808/figures/program.jpg


+ 971 - 0
bsp/bl808/m0/.config

@@ -0,0 +1,971 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# RT-Thread Project Configuration
+#
+
+#
+# RT-Thread Kernel
+#
+CONFIG_RT_NAME_MAX=8
+# CONFIG_RT_USING_ARCH_DATA_TYPE is not set
+# CONFIG_RT_USING_SMP is not set
+CONFIG_RT_ALIGN_SIZE=4
+# CONFIG_RT_THREAD_PRIORITY_8 is not set
+CONFIG_RT_THREAD_PRIORITY_32=y
+# CONFIG_RT_THREAD_PRIORITY_256 is not set
+CONFIG_RT_THREAD_PRIORITY_MAX=32
+CONFIG_RT_TICK_PER_SECOND=1000
+CONFIG_RT_USING_OVERFLOW_CHECK=y
+CONFIG_RT_USING_HOOK=y
+CONFIG_RT_HOOK_USING_FUNC_PTR=y
+CONFIG_RT_USING_IDLE_HOOK=y
+CONFIG_RT_IDLE_HOOK_LIST_SIZE=4
+CONFIG_IDLE_THREAD_STACK_SIZE=1024
+CONFIG_RT_USING_TIMER_SOFT=y
+CONFIG_RT_TIMER_THREAD_PRIO=4
+CONFIG_RT_TIMER_THREAD_STACK_SIZE=1024
+
+#
+# kservice optimization
+#
+CONFIG_RT_KSERVICE_USING_STDLIB=y
+# CONFIG_RT_KSERVICE_USING_STDLIB_MEMORY is not set
+# CONFIG_RT_KSERVICE_USING_TINY_SIZE is not set
+# CONFIG_RT_USING_TINY_FFS is not set
+# CONFIG_RT_KPRINTF_USING_LONGLONG is not set
+CONFIG_RT_DEBUG=y
+# CONFIG_RT_DEBUG_COLOR is not set
+# CONFIG_RT_DEBUG_INIT_CONFIG is not set
+# CONFIG_RT_DEBUG_THREAD_CONFIG is not set
+# CONFIG_RT_DEBUG_SCHEDULER_CONFIG is not set
+# CONFIG_RT_DEBUG_IPC_CONFIG is not set
+# CONFIG_RT_DEBUG_TIMER_CONFIG is not set
+# CONFIG_RT_DEBUG_IRQ_CONFIG is not set
+# CONFIG_RT_DEBUG_MEM_CONFIG is not set
+# CONFIG_RT_DEBUG_SLAB_CONFIG is not set
+# CONFIG_RT_DEBUG_MEMHEAP_CONFIG is not set
+# CONFIG_RT_DEBUG_MODULE_CONFIG is not set
+
+#
+# Inter-Thread communication
+#
+CONFIG_RT_USING_SEMAPHORE=y
+CONFIG_RT_USING_MUTEX=y
+CONFIG_RT_USING_EVENT=y
+CONFIG_RT_USING_MAILBOX=y
+CONFIG_RT_USING_MESSAGEQUEUE=y
+# CONFIG_RT_USING_SIGNALS is not set
+
+#
+# Memory Management
+#
+# CONFIG_RT_USING_MEMPOOL is not set
+CONFIG_RT_USING_SMALL_MEM=y
+# CONFIG_RT_USING_SLAB is not set
+# CONFIG_RT_USING_MEMHEAP is not set
+CONFIG_RT_USING_SMALL_MEM_AS_HEAP=y
+# CONFIG_RT_USING_MEMHEAP_AS_HEAP is not set
+# CONFIG_RT_USING_SLAB_AS_HEAP is not set
+# CONFIG_RT_USING_USERHEAP is not set
+# CONFIG_RT_USING_NOHEAP is not set
+CONFIG_RT_USING_MEMTRACE=y
+# CONFIG_RT_USING_HEAP_ISR is not set
+CONFIG_RT_USING_HEAP=y
+
+#
+# Kernel Device Object
+#
+CONFIG_RT_USING_DEVICE=y
+# CONFIG_RT_USING_DEVICE_OPS is not set
+# CONFIG_RT_USING_DM is not set
+# CONFIG_RT_USING_INTERRUPT_INFO is not set
+CONFIG_RT_USING_CONSOLE=y
+CONFIG_RT_CONSOLEBUF_SIZE=128
+CONFIG_RT_CONSOLE_DEVICE_NAME="uart0"
+CONFIG_RT_VER_NUM=0x50000
+# CONFIG_RT_USING_CACHE is not set
+# CONFIG_ARCH_ARM_BOOTWITH_FLUSH_CACHE is not set
+# CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set
+# CONFIG_RT_USING_CPU_FFS is not set
+CONFIG_ARCH_RISCV_FPU=y
+CONFIG_ARCH_RISCV_FPU_S=y
+
+#
+# RT-Thread Components
+#
+CONFIG_RT_USING_COMPONENTS_INIT=y
+CONFIG_RT_USING_USER_MAIN=y
+CONFIG_RT_MAIN_THREAD_STACK_SIZE=2048
+CONFIG_RT_MAIN_THREAD_PRIORITY=10
+# CONFIG_RT_USING_LEGACY is not set
+CONFIG_RT_USING_MSH=y
+CONFIG_RT_USING_FINSH=y
+CONFIG_FINSH_USING_MSH=y
+CONFIG_FINSH_THREAD_NAME="tshell"
+CONFIG_FINSH_THREAD_PRIORITY=20
+CONFIG_FINSH_THREAD_STACK_SIZE=4096
+CONFIG_FINSH_USING_HISTORY=y
+CONFIG_FINSH_HISTORY_LINES=5
+CONFIG_FINSH_USING_SYMTAB=y
+CONFIG_FINSH_CMD_SIZE=80
+CONFIG_MSH_USING_BUILT_IN_COMMANDS=y
+CONFIG_FINSH_USING_DESCRIPTION=y
+# CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set
+# CONFIG_FINSH_USING_AUTH is not set
+CONFIG_FINSH_ARG_MAX=10
+# CONFIG_RT_USING_DFS is not set
+# CONFIG_RT_USING_FAL is not set
+
+#
+# Device Drivers
+#
+CONFIG_RT_USING_DEVICE_IPC=y
+CONFIG_RT_UNAMED_PIPE_NUMBER=64
+# CONFIG_RT_USING_SYSTEM_WORKQUEUE is not set
+CONFIG_RT_USING_SERIAL=y
+CONFIG_RT_USING_SERIAL_V1=y
+# CONFIG_RT_USING_SERIAL_V2 is not set
+CONFIG_RT_SERIAL_USING_DMA=y
+CONFIG_RT_SERIAL_RB_BUFSZ=64
+# CONFIG_RT_USING_CAN is not set
+# CONFIG_RT_USING_HWTIMER is not set
+# CONFIG_RT_USING_CPUTIME is not set
+# CONFIG_RT_USING_I2C is not set
+# CONFIG_RT_USING_PHY is not set
+CONFIG_RT_USING_PIN=y
+# CONFIG_RT_USING_ADC is not set
+# CONFIG_RT_USING_DAC is not set
+# CONFIG_RT_USING_NULL is not set
+# CONFIG_RT_USING_ZERO is not set
+# CONFIG_RT_USING_RANDOM is not set
+# CONFIG_RT_USING_PWM is not set
+# CONFIG_RT_USING_MTD_NOR is not set
+# CONFIG_RT_USING_MTD_NAND is not set
+# CONFIG_RT_USING_PM is not set
+# CONFIG_RT_USING_FDT is not set
+# CONFIG_RT_USING_RTC is not set
+# CONFIG_RT_USING_SDIO is not set
+# CONFIG_RT_USING_SPI is not set
+# CONFIG_RT_USING_WDT is not set
+# CONFIG_RT_USING_AUDIO is not set
+# CONFIG_RT_USING_SENSOR is not set
+# CONFIG_RT_USING_TOUCH is not set
+# CONFIG_RT_USING_LCD is not set
+# CONFIG_RT_USING_HWCRYPTO is not set
+# CONFIG_RT_USING_PULSE_ENCODER is not set
+# CONFIG_RT_USING_INPUT_CAPTURE is not set
+# CONFIG_RT_USING_DEV_BUS is not set
+# CONFIG_RT_USING_WIFI is not set
+# CONFIG_RT_USING_VIRTIO is not set
+
+#
+# Using USB
+#
+# CONFIG_RT_USING_USB is not set
+# CONFIG_RT_USING_USB_HOST is not set
+# CONFIG_RT_USING_USB_DEVICE is not set
+
+#
+# C/C++ and POSIX layer
+#
+CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8
+
+#
+# POSIX (Portable Operating System Interface) layer
+#
+# CONFIG_RT_USING_POSIX_FS is not set
+# CONFIG_RT_USING_POSIX_DELAY is not set
+# CONFIG_RT_USING_POSIX_CLOCK is not set
+# CONFIG_RT_USING_POSIX_TIMER is not set
+# CONFIG_RT_USING_PTHREADS is not set
+# CONFIG_RT_USING_MODULE is not set
+
+#
+# Interprocess Communication (IPC)
+#
+# CONFIG_RT_USING_POSIX_PIPE is not set
+# CONFIG_RT_USING_POSIX_MESSAGE_QUEUE is not set
+# CONFIG_RT_USING_POSIX_MESSAGE_SEMAPHORE is not set
+
+#
+# Socket is in the 'Network' category
+#
+# CONFIG_RT_USING_CPLUSPLUS is not set
+
+#
+# Network
+#
+# CONFIG_RT_USING_SAL is not set
+# CONFIG_RT_USING_NETDEV is not set
+# CONFIG_RT_USING_LWIP is not set
+# CONFIG_RT_USING_AT is not set
+
+#
+# Utilities
+#
+# CONFIG_RT_USING_RYM is not set
+# CONFIG_RT_USING_ULOG is not set
+# CONFIG_RT_USING_UTEST is not set
+# CONFIG_RT_USING_VAR_EXPORT is not set
+# CONFIG_RT_USING_RT_LINK is not set
+# CONFIG_RT_USING_VBUS is not set
+
+#
+# RT-Thread Utestcases
+#
+# CONFIG_RT_USING_UTESTCASES is not set
+
+#
+# RT-Thread online packages
+#
+
+#
+# IoT - internet of things
+#
+# CONFIG_PKG_USING_LWIP is not set
+# CONFIG_PKG_USING_LORAWAN_DRIVER is not set
+# CONFIG_PKG_USING_PAHOMQTT is not set
+# CONFIG_PKG_USING_UMQTT is not set
+# CONFIG_PKG_USING_WEBCLIENT is not set
+# CONFIG_PKG_USING_WEBNET is not set
+# CONFIG_PKG_USING_MONGOOSE is not set
+# CONFIG_PKG_USING_MYMQTT is not set
+# CONFIG_PKG_USING_KAWAII_MQTT is not set
+# CONFIG_PKG_USING_BC28_MQTT is not set
+# CONFIG_PKG_USING_WEBTERMINAL is not set
+# CONFIG_PKG_USING_LIBMODBUS is not set
+# CONFIG_PKG_USING_FREEMODBUS is not set
+# CONFIG_PKG_USING_NANOPB is not set
+
+#
+# Wi-Fi
+#
+
+#
+# Marvell WiFi
+#
+# CONFIG_PKG_USING_WLANMARVELL is not set
+
+#
+# Wiced WiFi
+#
+# CONFIG_PKG_USING_WLAN_WICED is not set
+# CONFIG_PKG_USING_RW007 is not set
+# CONFIG_PKG_USING_COAP is not set
+# CONFIG_PKG_USING_NOPOLL is not set
+# CONFIG_PKG_USING_NETUTILS is not set
+# CONFIG_PKG_USING_CMUX is not set
+# CONFIG_PKG_USING_PPP_DEVICE is not set
+# CONFIG_PKG_USING_AT_DEVICE is not set
+# CONFIG_PKG_USING_ATSRV_SOCKET is not set
+# CONFIG_PKG_USING_WIZNET is not set
+# CONFIG_PKG_USING_ZB_COORDINATOR is not set
+
+#
+# IoT Cloud
+#
+# CONFIG_PKG_USING_ONENET is not set
+# CONFIG_PKG_USING_GAGENT_CLOUD is not set
+# CONFIG_PKG_USING_ALI_IOTKIT is not set
+# CONFIG_PKG_USING_AZURE is not set
+# CONFIG_PKG_USING_TENCENT_IOT_EXPLORER is not set
+# CONFIG_PKG_USING_JIOT-C-SDK is not set
+# CONFIG_PKG_USING_UCLOUD_IOT_SDK is not set
+# CONFIG_PKG_USING_JOYLINK is not set
+# CONFIG_PKG_USING_EZ_IOT_OS is not set
+# CONFIG_PKG_USING_IOTSHARP_SDK is not set
+# CONFIG_PKG_USING_NIMBLE is not set
+# CONFIG_PKG_USING_LLSYNC_SDK_ADAPTER is not set
+# CONFIG_PKG_USING_OTA_DOWNLOADER is not set
+# CONFIG_PKG_USING_IPMSG is not set
+# CONFIG_PKG_USING_LSSDP is not set
+# CONFIG_PKG_USING_AIRKISS_OPEN is not set
+# CONFIG_PKG_USING_LIBRWS is not set
+# CONFIG_PKG_USING_TCPSERVER is not set
+# CONFIG_PKG_USING_PROTOBUF_C is not set
+# CONFIG_PKG_USING_DLT645 is not set
+# CONFIG_PKG_USING_QXWZ is not set
+# CONFIG_PKG_USING_SMTP_CLIENT is not set
+# CONFIG_PKG_USING_ABUP_FOTA is not set
+# CONFIG_PKG_USING_LIBCURL2RTT is not set
+# CONFIG_PKG_USING_CAPNP is not set
+# CONFIG_PKG_USING_AGILE_TELNET is not set
+# CONFIG_PKG_USING_NMEALIB is not set
+# CONFIG_PKG_USING_PDULIB is not set
+# CONFIG_PKG_USING_BTSTACK is not set
+# CONFIG_PKG_USING_LORAWAN_ED_STACK is not set
+# CONFIG_PKG_USING_WAYZ_IOTKIT is not set
+# CONFIG_PKG_USING_MAVLINK is not set
+# CONFIG_PKG_USING_BSAL is not set
+# CONFIG_PKG_USING_AGILE_MODBUS is not set
+# CONFIG_PKG_USING_AGILE_FTP is not set
+# CONFIG_PKG_USING_EMBEDDEDPROTO is not set
+# CONFIG_PKG_USING_RT_LINK_HW is not set
+# CONFIG_PKG_USING_RYANMQTT is not set
+# CONFIG_PKG_USING_RYANW5500 is not set
+# CONFIG_PKG_USING_LORA_PKT_FWD is not set
+# CONFIG_PKG_USING_LORA_GW_DRIVER_LIB is not set
+# CONFIG_PKG_USING_LORA_PKT_SNIFFER is not set
+# CONFIG_PKG_USING_HM is not set
+# CONFIG_PKG_USING_SMALL_MODBUS is not set
+# CONFIG_PKG_USING_NET_SERVER is not set
+# CONFIG_PKG_USING_ZFTP is not set
+# CONFIG_PKG_USING_WOL is not set
+
+#
+# security packages
+#
+# CONFIG_PKG_USING_MBEDTLS is not set
+# CONFIG_PKG_USING_LIBSODIUM is not set
+# CONFIG_PKG_USING_LIBHYDROGEN is not set
+# CONFIG_PKG_USING_TINYCRYPT is not set
+# CONFIG_PKG_USING_TFM is not set
+# CONFIG_PKG_USING_YD_CRYPTO is not set
+
+#
+# language packages
+#
+
+#
+# JSON: JavaScript Object Notation, a lightweight data-interchange format
+#
+# CONFIG_PKG_USING_CJSON is not set
+# CONFIG_PKG_USING_LJSON is not set
+# CONFIG_PKG_USING_RT_CJSON_TOOLS is not set
+# CONFIG_PKG_USING_RAPIDJSON is not set
+# CONFIG_PKG_USING_JSMN is not set
+# CONFIG_PKG_USING_AGILE_JSMN is not set
+# CONFIG_PKG_USING_PARSON is not set
+
+#
+# XML: Extensible Markup Language
+#
+# CONFIG_PKG_USING_SIMPLE_XML is not set
+# CONFIG_PKG_USING_EZXML is not set
+# CONFIG_PKG_USING_LUATOS_SOC is not set
+# CONFIG_PKG_USING_LUA is not set
+# CONFIG_PKG_USING_JERRYSCRIPT is not set
+# CONFIG_PKG_USING_MICROPYTHON is not set
+# CONFIG_PKG_USING_PIKASCRIPT is not set
+# CONFIG_PKG_USING_RTT_RUST is not set
+
+#
+# multimedia packages
+#
+
+#
+# LVGL: powerful and easy-to-use embedded GUI library
+#
+# CONFIG_PKG_USING_LVGL is not set
+# CONFIG_PKG_USING_LITTLEVGL2RTT is not set
+# CONFIG_PKG_USING_LV_MUSIC_DEMO is not set
+# CONFIG_PKG_USING_GUI_GUIDER_DEMO is not set
+
+#
+# u8g2: a monochrome graphic library
+#
+# CONFIG_PKG_USING_U8G2_OFFICIAL is not set
+# CONFIG_PKG_USING_U8G2 is not set
+# CONFIG_PKG_USING_OPENMV is not set
+# CONFIG_PKG_USING_MUPDF is not set
+# CONFIG_PKG_USING_STEMWIN is not set
+# CONFIG_PKG_USING_WAVPLAYER is not set
+# CONFIG_PKG_USING_TJPGD is not set
+# CONFIG_PKG_USING_PDFGEN is not set
+# CONFIG_PKG_USING_HELIX is not set
+# CONFIG_PKG_USING_AZUREGUIX is not set
+# CONFIG_PKG_USING_TOUCHGFX2RTT is not set
+# CONFIG_PKG_USING_NUEMWIN is not set
+# CONFIG_PKG_USING_MP3PLAYER is not set
+# CONFIG_PKG_USING_TINYJPEG is not set
+# CONFIG_PKG_USING_UGUI is not set
+
+#
+# PainterEngine: A cross-platform graphics application framework written in C language
+#
+# CONFIG_PKG_USING_PAINTERENGINE is not set
+# CONFIG_PKG_USING_PAINTERENGINE_AUX is not set
+# CONFIG_PKG_USING_MCURSES is not set
+# CONFIG_PKG_USING_TERMBOX is not set
+# CONFIG_PKG_USING_VT100 is not set
+# CONFIG_PKG_USING_QRCODE is not set
+# CONFIG_PKG_USING_GUIENGINE is not set
+
+#
+# tools packages
+#
+# CONFIG_PKG_USING_CMBACKTRACE is not set
+# CONFIG_PKG_USING_EASYFLASH is not set
+# CONFIG_PKG_USING_EASYLOGGER is not set
+# CONFIG_PKG_USING_SYSTEMVIEW is not set
+# CONFIG_PKG_USING_SEGGER_RTT is not set
+# CONFIG_PKG_USING_RDB is not set
+# CONFIG_PKG_USING_ULOG_EASYFLASH is not set
+# CONFIG_PKG_USING_LOGMGR is not set
+# CONFIG_PKG_USING_ADBD is not set
+# CONFIG_PKG_USING_COREMARK is not set
+# CONFIG_PKG_USING_DHRYSTONE is not set
+# CONFIG_PKG_USING_MEMORYPERF is not set
+# CONFIG_PKG_USING_NR_MICRO_SHELL is not set
+# CONFIG_PKG_USING_CHINESE_FONT_LIBRARY is not set
+# CONFIG_PKG_USING_LUNAR_CALENDAR is not set
+# CONFIG_PKG_USING_BS8116A is not set
+# CONFIG_PKG_USING_GPS_RMC is not set
+# CONFIG_PKG_USING_URLENCODE is not set
+# CONFIG_PKG_USING_UMCN is not set
+# CONFIG_PKG_USING_LWRB2RTT is not set
+# CONFIG_PKG_USING_CPU_USAGE is not set
+# CONFIG_PKG_USING_GBK2UTF8 is not set
+# CONFIG_PKG_USING_VCONSOLE is not set
+# CONFIG_PKG_USING_KDB is not set
+# CONFIG_PKG_USING_WAMR is not set
+# CONFIG_PKG_USING_MICRO_XRCE_DDS_CLIENT is not set
+# CONFIG_PKG_USING_LWLOG is not set
+# CONFIG_PKG_USING_ANV_TRACE is not set
+# CONFIG_PKG_USING_ANV_MEMLEAK is not set
+# CONFIG_PKG_USING_ANV_TESTSUIT is not set
+# CONFIG_PKG_USING_ANV_BENCH is not set
+# CONFIG_PKG_USING_DEVMEM is not set
+# CONFIG_PKG_USING_REGEX is not set
+# CONFIG_PKG_USING_MEM_SANDBOX is not set
+# CONFIG_PKG_USING_SOLAR_TERMS is not set
+# CONFIG_PKG_USING_GAN_ZHI is not set
+# CONFIG_PKG_USING_FDT is not set
+# CONFIG_PKG_USING_CBOX is not set
+# CONFIG_PKG_USING_SNOWFLAKE is not set
+# CONFIG_PKG_USING_HASH_MATCH is not set
+# CONFIG_PKG_USING_ARMV7M_DWT_TOOL is not set
+# CONFIG_PKG_USING_VOFA_PLUS is not set
+
+#
+# system packages
+#
+
+#
+# enhanced kernel services
+#
+# CONFIG_PKG_USING_RT_MEMCPY_CM is not set
+# CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set
+# CONFIG_PKG_USING_RT_VSNPRINTF_FULL is not set
+
+#
+# acceleration: Assembly language or algorithmic acceleration packages
+#
+# CONFIG_PKG_USING_QFPLIB_M0_FULL is not set
+# CONFIG_PKG_USING_QFPLIB_M0_TINY is not set
+# CONFIG_PKG_USING_QFPLIB_M3 is not set
+
+#
+# CMSIS: ARM Cortex-M Microcontroller Software Interface Standard
+#
+# CONFIG_PKG_USING_CMSIS_5 is not set
+# CONFIG_PKG_USING_CMSIS_RTOS1 is not set
+# CONFIG_PKG_USING_CMSIS_RTOS2 is not set
+
+#
+# Micrium: Micrium software products porting for RT-Thread
+#
+# CONFIG_PKG_USING_UCOSIII_WRAPPER is not set
+# CONFIG_PKG_USING_UCOSII_WRAPPER is not set
+# CONFIG_PKG_USING_UC_CRC is not set
+# CONFIG_PKG_USING_UC_CLK is not set
+# CONFIG_PKG_USING_UC_COMMON is not set
+# CONFIG_PKG_USING_UC_MODBUS is not set
+# CONFIG_PKG_USING_FREERTOS_WRAPPER is not set
+# CONFIG_PKG_USING_CAIRO is not set
+# CONFIG_PKG_USING_PIXMAN is not set
+# CONFIG_PKG_USING_PARTITION is not set
+# CONFIG_PKG_USING_PERF_COUNTER is not set
+# CONFIG_PKG_USING_FLASHDB is not set
+# CONFIG_PKG_USING_SQLITE is not set
+# CONFIG_PKG_USING_RTI is not set
+# CONFIG_PKG_USING_DFS_YAFFS is not set
+# CONFIG_PKG_USING_LITTLEFS is not set
+# CONFIG_PKG_USING_DFS_JFFS2 is not set
+# CONFIG_PKG_USING_DFS_UFFS is not set
+# CONFIG_PKG_USING_LWEXT4 is not set
+# CONFIG_PKG_USING_THREAD_POOL is not set
+# CONFIG_PKG_USING_ROBOTS is not set
+# CONFIG_PKG_USING_EV is not set
+# CONFIG_PKG_USING_SYSWATCH is not set
+# CONFIG_PKG_USING_SYS_LOAD_MONITOR is not set
+# CONFIG_PKG_USING_PLCCORE is not set
+# CONFIG_PKG_USING_RAMDISK is not set
+# CONFIG_PKG_USING_MININI is not set
+# CONFIG_PKG_USING_QBOOT is not set
+# CONFIG_PKG_USING_PPOOL is not set
+# CONFIG_PKG_USING_OPENAMP is not set
+# CONFIG_PKG_USING_LPM is not set
+# CONFIG_PKG_USING_TLSF is not set
+# CONFIG_PKG_USING_EVENT_RECORDER is not set
+# CONFIG_PKG_USING_ARM_2D is not set
+# CONFIG_PKG_USING_MCUBOOT is not set
+# CONFIG_PKG_USING_TINYUSB is not set
+# CONFIG_PKG_USING_CHERRYUSB is not set
+# CONFIG_PKG_USING_KMULTI_RTIMER is not set
+# CONFIG_PKG_USING_TFDB is not set
+# CONFIG_PKG_USING_QPC is not set
+# CONFIG_PKG_USING_AGILE_UPGRADE is not set
+
+#
+# peripheral libraries and drivers
+#
+
+#
+# sensors drivers
+#
+# CONFIG_PKG_USING_LSM6DSM is not set
+# CONFIG_PKG_USING_LSM6DSL is not set
+# CONFIG_PKG_USING_LPS22HB is not set
+# CONFIG_PKG_USING_HTS221 is not set
+# CONFIG_PKG_USING_LSM303AGR is not set
+# CONFIG_PKG_USING_BME280 is not set
+# CONFIG_PKG_USING_BME680 is not set
+# CONFIG_PKG_USING_BMA400 is not set
+# CONFIG_PKG_USING_BMI160_BMX160 is not set
+# CONFIG_PKG_USING_SPL0601 is not set
+# CONFIG_PKG_USING_MS5805 is not set
+# CONFIG_PKG_USING_DA270 is not set
+# CONFIG_PKG_USING_DF220 is not set
+# CONFIG_PKG_USING_HSHCAL001 is not set
+# CONFIG_PKG_USING_BH1750 is not set
+# CONFIG_PKG_USING_MPU6XXX is not set
+# CONFIG_PKG_USING_AHT10 is not set
+# CONFIG_PKG_USING_AP3216C is not set
+# CONFIG_PKG_USING_TSL4531 is not set
+# CONFIG_PKG_USING_DS18B20 is not set
+# CONFIG_PKG_USING_DHT11 is not set
+# CONFIG_PKG_USING_DHTXX is not set
+# CONFIG_PKG_USING_GY271 is not set
+# CONFIG_PKG_USING_GP2Y10 is not set
+# CONFIG_PKG_USING_SGP30 is not set
+# CONFIG_PKG_USING_HDC1000 is not set
+# CONFIG_PKG_USING_BMP180 is not set
+# CONFIG_PKG_USING_BMP280 is not set
+# CONFIG_PKG_USING_SHTC1 is not set
+# CONFIG_PKG_USING_BMI088 is not set
+# CONFIG_PKG_USING_HMC5883 is not set
+# CONFIG_PKG_USING_MAX6675 is not set
+# CONFIG_PKG_USING_TMP1075 is not set
+# CONFIG_PKG_USING_SR04 is not set
+# CONFIG_PKG_USING_CCS811 is not set
+# CONFIG_PKG_USING_PMSXX is not set
+# CONFIG_PKG_USING_RT3020 is not set
+# CONFIG_PKG_USING_MLX90632 is not set
+# CONFIG_PKG_USING_MLX90393 is not set
+# CONFIG_PKG_USING_MLX90392 is not set
+# CONFIG_PKG_USING_MLX90397 is not set
+# CONFIG_PKG_USING_MS5611 is not set
+# CONFIG_PKG_USING_MAX31865 is not set
+# CONFIG_PKG_USING_VL53L0X is not set
+# CONFIG_PKG_USING_INA260 is not set
+# CONFIG_PKG_USING_MAX30102 is not set
+# CONFIG_PKG_USING_INA226 is not set
+# CONFIG_PKG_USING_LIS2DH12 is not set
+# CONFIG_PKG_USING_HS300X is not set
+# CONFIG_PKG_USING_ZMOD4410 is not set
+# CONFIG_PKG_USING_ISL29035 is not set
+# CONFIG_PKG_USING_MMC3680KJ is not set
+# CONFIG_PKG_USING_QMP6989 is not set
+# CONFIG_PKG_USING_BALANCE is not set
+# CONFIG_PKG_USING_SHT2X is not set
+# CONFIG_PKG_USING_SHT3X is not set
+# CONFIG_PKG_USING_AD7746 is not set
+# CONFIG_PKG_USING_ADT74XX is not set
+# CONFIG_PKG_USING_MAX17048 is not set
+# CONFIG_PKG_USING_AS7341 is not set
+# CONFIG_PKG_USING_CW2015 is not set
+# CONFIG_PKG_USING_ICM20608 is not set
+# CONFIG_PKG_USING_PAJ7620 is not set
+
+#
+# touch drivers
+#
+# CONFIG_PKG_USING_GT9147 is not set
+# CONFIG_PKG_USING_GT1151 is not set
+# CONFIG_PKG_USING_GT917S is not set
+# CONFIG_PKG_USING_GT911 is not set
+# CONFIG_PKG_USING_FT6206 is not set
+# CONFIG_PKG_USING_FT5426 is not set
+# CONFIG_PKG_USING_FT6236 is not set
+# CONFIG_PKG_USING_XPT2046_TOUCH is not set
+# CONFIG_PKG_USING_REALTEK_AMEBA is not set
+# CONFIG_PKG_USING_STM32_SDIO is not set
+# CONFIG_PKG_USING_ESP_IDF is not set
+# CONFIG_PKG_USING_BUTTON is not set
+# CONFIG_PKG_USING_PCF8574 is not set
+# CONFIG_PKG_USING_SX12XX is not set
+# CONFIG_PKG_USING_SIGNAL_LED is not set
+# CONFIG_PKG_USING_LEDBLINK is not set
+# CONFIG_PKG_USING_LITTLED is not set
+# CONFIG_PKG_USING_LKDGUI is not set
+# CONFIG_PKG_USING_NRF5X_SDK is not set
+# CONFIG_PKG_USING_NRFX is not set
+# CONFIG_PKG_USING_WM_LIBRARIES is not set
+
+#
+# Kendryte SDK
+#
+# CONFIG_PKG_USING_K210_SDK is not set
+# CONFIG_PKG_USING_KENDRYTE_SDK is not set
+# CONFIG_PKG_USING_INFRARED is not set
+# CONFIG_PKG_USING_MULTI_INFRARED is not set
+# CONFIG_PKG_USING_AGILE_BUTTON is not set
+# CONFIG_PKG_USING_AGILE_LED is not set
+# CONFIG_PKG_USING_AT24CXX is not set
+# CONFIG_PKG_USING_MOTIONDRIVER2RTT is not set
+# CONFIG_PKG_USING_PCA9685 is not set
+# CONFIG_PKG_USING_I2C_TOOLS is not set
+# CONFIG_PKG_USING_NRF24L01 is not set
+# CONFIG_PKG_USING_RPLIDAR is not set
+# CONFIG_PKG_USING_AS608 is not set
+# CONFIG_PKG_USING_RC522 is not set
+# CONFIG_PKG_USING_WS2812B is not set
+# CONFIG_PKG_USING_EMBARC_BSP is not set
+# CONFIG_PKG_USING_EXTERN_RTC_DRIVERS is not set
+# CONFIG_PKG_USING_MULTI_RTIMER is not set
+# CONFIG_PKG_USING_MAX7219 is not set
+# CONFIG_PKG_USING_BEEP is not set
+# CONFIG_PKG_USING_EASYBLINK is not set
+# CONFIG_PKG_USING_PMS_SERIES is not set
+# CONFIG_PKG_USING_CAN_YMODEM is not set
+# CONFIG_PKG_USING_LORA_RADIO_DRIVER is not set
+# CONFIG_PKG_USING_QLED is not set
+# CONFIG_PKG_USING_AGILE_CONSOLE is not set
+# CONFIG_PKG_USING_LD3320 is not set
+# CONFIG_PKG_USING_WK2124 is not set
+# CONFIG_PKG_USING_LY68L6400 is not set
+# CONFIG_PKG_USING_DM9051 is not set
+# CONFIG_PKG_USING_SSD1306 is not set
+# CONFIG_PKG_USING_QKEY is not set
+# CONFIG_PKG_USING_RS485 is not set
+# CONFIG_PKG_USING_RS232 is not set
+# CONFIG_PKG_USING_NES is not set
+# CONFIG_PKG_USING_VIRTUAL_SENSOR is not set
+# CONFIG_PKG_USING_VDEVICE is not set
+# CONFIG_PKG_USING_SGM706 is not set
+# CONFIG_PKG_USING_STM32WB55_SDK is not set
+# CONFIG_PKG_USING_RDA58XX is not set
+# CONFIG_PKG_USING_LIBNFC is not set
+# CONFIG_PKG_USING_MFOC is not set
+# CONFIG_PKG_USING_TMC51XX is not set
+# CONFIG_PKG_USING_TCA9534 is not set
+# CONFIG_PKG_USING_KOBUKI is not set
+# CONFIG_PKG_USING_ROSSERIAL is not set
+# CONFIG_PKG_USING_MICRO_ROS is not set
+# CONFIG_PKG_USING_MCP23008 is not set
+# CONFIG_PKG_USING_BLUETRUM_SDK is not set
+# CONFIG_PKG_USING_MISAKA_AT24CXX is not set
+# CONFIG_PKG_USING_MISAKA_RGB_BLING is not set
+# CONFIG_PKG_USING_LORA_MODEM_DRIVER is not set
+# CONFIG_PKG_USING_BL_MCU_SDK is not set
+# CONFIG_PKG_USING_SOFT_SERIAL is not set
+# CONFIG_PKG_USING_MB85RS16 is not set
+# CONFIG_PKG_USING_RFM300 is not set
+# CONFIG_PKG_USING_IO_INPUT_FILTER is not set
+# CONFIG_PKG_USING_RASPBERRYPI_PICO_SDK is not set
+# CONFIG_PKG_USING_LRF_NV7LIDAR is not set
+# CONFIG_PKG_USING_FINGERPRINT is not set
+
+#
+# AI packages
+#
+# CONFIG_PKG_USING_LIBANN is not set
+# CONFIG_PKG_USING_NNOM is not set
+# CONFIG_PKG_USING_ONNX_BACKEND is not set
+# CONFIG_PKG_USING_ONNX_PARSER is not set
+# CONFIG_PKG_USING_TENSORFLOWLITEMICRO is not set
+# CONFIG_PKG_USING_ELAPACK is not set
+# CONFIG_PKG_USING_ULAPACK is not set
+# CONFIG_PKG_USING_QUEST is not set
+# CONFIG_PKG_USING_NAXOS is not set
+
+#
+# Signal Processing and Control Algorithm Packages
+#
+# CONFIG_PKG_USING_FIRE_PID_CURVE is not set
+# CONFIG_PKG_USING_UKAL is not set
+
+#
+# miscellaneous packages
+#
+
+#
+# project laboratory
+#
+
+#
+# samples: kernel and components samples
+#
+# CONFIG_PKG_USING_KERNEL_SAMPLES is not set
+# CONFIG_PKG_USING_FILESYSTEM_SAMPLES is not set
+# CONFIG_PKG_USING_NETWORK_SAMPLES is not set
+# CONFIG_PKG_USING_PERIPHERAL_SAMPLES is not set
+
+#
+# entertainment: terminal games and other interesting software packages
+#
+# CONFIG_PKG_USING_CMATRIX is not set
+# CONFIG_PKG_USING_SL is not set
+# CONFIG_PKG_USING_CAL is not set
+# CONFIG_PKG_USING_ACLOCK is not set
+# CONFIG_PKG_USING_THREES is not set
+# CONFIG_PKG_USING_2048 is not set
+# CONFIG_PKG_USING_SNAKE is not set
+# CONFIG_PKG_USING_TETRIS is not set
+# CONFIG_PKG_USING_DONUT is not set
+# CONFIG_PKG_USING_COWSAY is not set
+# CONFIG_PKG_USING_LIBCSV is not set
+# CONFIG_PKG_USING_OPTPARSE is not set
+# CONFIG_PKG_USING_FASTLZ is not set
+# CONFIG_PKG_USING_MINILZO is not set
+# CONFIG_PKG_USING_QUICKLZ is not set
+# CONFIG_PKG_USING_LZMA is not set
+# CONFIG_PKG_USING_MULTIBUTTON is not set
+# CONFIG_PKG_USING_FLEXIBLE_BUTTON is not set
+# CONFIG_PKG_USING_CANFESTIVAL is not set
+# CONFIG_PKG_USING_ZLIB is not set
+# CONFIG_PKG_USING_MINIZIP is not set
+# CONFIG_PKG_USING_HEATSHRINK is not set
+# CONFIG_PKG_USING_DSTR is not set
+# CONFIG_PKG_USING_TINYFRAME is not set
+# CONFIG_PKG_USING_KENDRYTE_DEMO is not set
+# CONFIG_PKG_USING_DIGITALCTRL is not set
+# CONFIG_PKG_USING_UPACKER is not set
+# CONFIG_PKG_USING_UPARAM is not set
+# CONFIG_PKG_USING_HELLO is not set
+# CONFIG_PKG_USING_VI is not set
+# CONFIG_PKG_USING_KI is not set
+# CONFIG_PKG_USING_ARMv7M_DWT is not set
+# CONFIG_PKG_USING_CRCLIB is not set
+# CONFIG_PKG_USING_LWGPS is not set
+# CONFIG_PKG_USING_STATE_MACHINE is not set
+# CONFIG_PKG_USING_DESIGN_PATTERN is not set
+# CONFIG_PKG_USING_CONTROLLER is not set
+# CONFIG_PKG_USING_PHASE_LOCKED_LOOP is not set
+# CONFIG_PKG_USING_MFBD is not set
+# CONFIG_PKG_USING_SLCAN2RTT is not set
+# CONFIG_PKG_USING_SOEM is not set
+# CONFIG_PKG_USING_QPARAM is not set
+# CONFIG_PKG_USING_CorevMCU_CLI is not set
+# CONFIG_PKG_USING_GET_IRQ_PRIORITY is not set
+
+#
+# Arduino libraries
+#
+# CONFIG_PKG_USING_RTDUINO is not set
+
+#
+# Projects
+#
+# CONFIG_PKG_USING_ARDUINO_ULTRASOUND_RADAR is not set
+# CONFIG_PKG_USING_ARDUINO_SENSOR_KIT is not set
+# CONFIG_PKG_USING_ARDUINO_MATLAB_SUPPORT is not set
+
+#
+# Sensors
+#
+# CONFIG_PKG_USING_ARDUINO_SENSOR_DEVICE_DRIVERS is not set
+# CONFIG_PKG_USING_ARDUINO_CAPACITIVESENSOR is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADXL375 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VL53L0X is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VL53L1X is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SENSOR is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VL6180X is not set
+# CONFIG_PKG_USING_ADAFRUIT_MAX31855 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MAX31865 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MAX31856 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MAX6675 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MLX90614 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM9DS1 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AHTX0 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM9DS0 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP280 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADT7410 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP085 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BME680 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP9808 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP4728 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_INA219 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LTR390 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADXL345 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_DHT is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP9600 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM6DS is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BNO055 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MAX1704X is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MMC56X3 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MLX90393 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MLX90395 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ICM20X is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_DPS310 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HTS221 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SHT4X is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SHT31 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADXL343 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BME280 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AS726X is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AMG88XX is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AM2320 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AM2315 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LTR329_LTR303 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP085_UNIFIED is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP183 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP183_UNIFIED is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP3XX is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MS8607 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LIS3MDL is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MLX90640 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MMA8451 is not set
+# CONFIG_PKG_USING_ADAFRUIT_MSA301 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPL115A2 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BNO08X is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BNO08X_RVC is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LIS2MDL is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM303DLH_MAG is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LC709203F is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_CAP1188 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_CCS811 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_NAU7802 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LIS331 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LPS2X is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LPS35HW is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LSM303_ACCEL is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_LIS3DH is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PCF8591 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPL3115A2 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPR121 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPRLS is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MPU6050 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PCT2075 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PM25AQI is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_EMC2101 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_FXAS21002C is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SCD30 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_FXOS8700 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HMC5883_UNIFIED is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SGP30 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TMP006 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TLA202X is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TCS34725 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SI7021 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SI1145 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SGP40 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SHTC3 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HDC1000 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HTU21DF is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AS7341 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_HTU31D is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SENSORLAB is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_INA260 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TMP007_LIBRARY is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_L3GD20 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TMP117 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TSC2007 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TSL2561 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TSL2591_LIBRARY is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VCNL4040 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VEML6070 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VEML6075 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_VEML7700 is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_LIS3DHTR is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_DHT is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_ADXL335 is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_ADXL345 is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_BME280 is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_BMP280 is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_H3LIS331DL is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_MMA7660 is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_TSL2561 is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_PAJ7620 is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_VL53L0X is not set
+# CONFIG_PKG_USING_SEEED_ITG3200 is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_SHT31 is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_HP20X is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_DRV2605L is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_BBM150 is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_HMC5883L is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_LSM303DLH is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_TCS3414CS is not set
+# CONFIG_PKG_USING_SEEED_MP503 is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_BMP085 is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_HIGHTEMP is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_VEML6070 is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_SI1145 is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_SHT35 is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_AT42QT1070 is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_LSM6DS3 is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_HDC1000 is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_HM3301 is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_MCP9600 is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_LTC2941 is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_LDC1612 is not set
+
+#
+# Display
+#
+# CONFIG_PKG_USING_ARDUINO_U8G2 is not set
+# CONFIG_PKG_USING_SEEED_TM1637 is not set
+
+#
+# Timing
+#
+# CONFIG_PKG_USING_ARDUINO_MSTIMER2 is not set
+
+#
+# Data Processing
+#
+# CONFIG_PKG_USING_ARDUINO_KALMANFILTER is not set
+# CONFIG_PKG_USING_ARDUINO_ARDUINOJSON is not set
+
+#
+# Data Storage
+#
+
+#
+# Communication
+#
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PN532 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SI4713 is not set
+
+#
+# Device Control
+#
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PCF8574 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_PCA9685 is not set
+# CONFIG_PKG_USING_ARDUINO_SEEED_PCF85063TP is not set
+
+#
+# Other
+#
+
+#
+# Signal IO
+#
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BUSIO is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TCA8418 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP23017 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADS1X15 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AW9523 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP3008 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MCP4725 is not set
+# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BD3491FS is not set
+
+#
+# Uncategorized
+#
+
+#
+# BL808_M0 Hardware Drivers Config
+#
+CONFIG_SOC_BL808=y
+# CONFIG_BSP_USING_JTAG_M0 is not set
+
+#
+# On-chip Peripheral Drivers
+#
+CONFIG_BSP_USING_GPIO=y
+CONFIG_BSP_USING_UART=y
+CONFIG_BSP_USING_UART0=y
+CONFIG_BSP_UART0_TXD_PIN=14
+CONFIG_BSP_UART0_RXD_PIN=15

+ 20 - 0
bsp/bl808/m0/Kconfig

@@ -0,0 +1,20 @@
+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"
+source "drivers/Kconfig"

+ 14 - 0
bsp/bl808/m0/SConscript

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

+ 36 - 0
bsp/bl808/m0/SConstruct

@@ -0,0 +1,36 @@
+import os
+import sys
+import rtconfig
+
+from rtconfig import RTT_ROOT
+
+sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')]
+from building import *
+
+TARGET = 'rtthread.' + rtconfig.TARGET_EXT
+
+DefaultEnvironment(tools=[])
+env = Environment(tools = ['mingw'],
+    AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS,
+    CC = rtconfig.CC, CFLAGS = rtconfig.CFLAGS,
+    CXX = rtconfig.CXX, CXXFLAGS = rtconfig.CXXFLAGS,
+    AR = rtconfig.AR, ARFLAGS = '-rc',
+    LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS)
+env.PrependENVPath('PATH', rtconfig.EXEC_PATH)
+env['ASCOM'] = env['ASPPCOM']
+
+Export('RTT_ROOT')
+Export('rtconfig')
+
+# prepare building environment
+objs = PrepareBuilding(env, RTT_ROOT, has_libcpu = False)
+
+stack_size = 4096
+
+stack_lds = open('link_stacksize.lds', 'w')
+if GetDepend('__STACKSIZE__'): stack_size = GetDepend('__STACKSIZE__')
+stack_lds.write('__STACKSIZE__ = %d;' % stack_size)
+stack_lds.close()
+
+# make a building
+DoBuilding(TARGET, objs)

+ 9 - 0
bsp/bl808/m0/applications/SConscript

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

+ 19 - 0
bsp/bl808/m0/applications/main.c

@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2022/12/25     flyingcys    first version
+ */
+
+#include <rtthread.h>
+#include <stdio.h>
+
+int main(void)
+{
+    rt_kprintf("Hello, world\n");
+
+    return 0;
+}

+ 46 - 0
bsp/bl808/m0/drivers/Kconfig

@@ -0,0 +1,46 @@
+menu "BL808_M0 Hardware Drivers Config"
+config SOC_BL808
+    bool 
+    select RT_USING_COMPONENTS_INIT
+    select RT_USING_USER_MAIN
+    select ARCH_RISCV_FPU_S
+    default y
+
+
+config BSP_USING_JTAG_M0
+    bool "Enable M0 JTAG "
+    default n
+
+menu "On-chip Peripheral Drivers"
+
+    config BSP_USING_GPIO
+        bool "Enable GPIO"
+        select RT_USING_PIN
+        default y
+
+    menuconfig BSP_USING_UART
+        bool "Enable UART"
+        default y
+        select RT_USING_SERIAL
+        if BSP_USING_UART
+            config BSP_USING_UART0
+                bool "Enable UART0"
+                default y
+
+            if BSP_USING_UART0
+                config BSP_UART0_TXD_PIN
+                    int "uart0 TXD pin number"
+                    default 14
+
+                config BSP_UART0_RXD_PIN
+                    int "uart0 RXD pin number"
+                    default 15
+
+            endif
+
+        endif
+
+endmenu
+
+endmenu
+

+ 53 - 0
bsp/bl808/m0/drivers/SConscript

@@ -0,0 +1,53 @@
+# RT-Thread building script for component
+
+from building import *
+
+cwd     = GetCurrentDir()
+src     = Split('''
+    board.c
+''')
+
+CPPPATH = [cwd]
+
+if GetDepend(['RT_USING_SERIAL']):
+    if GetDepend(['RT_USING_SERIAL_V2']):
+        src += ['drv_uart_v2.c']
+    else:
+        src += ['drv_uart.c']
+    
+# if GetDepend('RT_USING_PIN'):
+#     src += ['drv_gpio.c']
+
+# if GetDepend('BSP_USING_LCD'):
+#     src += ['drv_lcd.c']
+#     src += ['drv_mpylcd.c']
+
+# if GetDepend('RT_USING_HWTIMER'):
+#     src += ['drv_hw_timer.c']
+
+# if GetDepend('RT_USING_CPUTIME'):
+#     src += ['drv_cputime.c']
+
+# if GetDepend('RT_USING_I2C'):
+#     src += ['drv_i2c.c']
+
+# if GetDepend('RT_USING_SPI'):
+#     src += ['drv_spi.c']
+
+# if GetDepend('RT_USING_PWM'):
+#     src += ['drv_pwm.c']
+
+# if GetDepend('RT_USING_WDT'):
+#     src += ['drv_wdt.c']
+
+group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH)
+
+objs = [group]
+
+list = os.listdir(cwd)
+
+for item in list:
+    if os.path.isfile(os.path.join(cwd, item, 'SConscript')):
+        objs = objs + SConscript(os.path.join(item, 'SConscript'))
+
+Return('objs')

+ 104 - 0
bsp/bl808/m0/drivers/board.c

@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2022/12/25     flyingcys    first version
+ */
+#include <rthw.h>
+#include <rtthread.h>
+
+#include "board.h"
+#include "drv_uart.h"
+
+static void sipeed_bl_sys_enabe_jtag(int cpuid)
+{
+    GLB_GPIO_Cfg_Type gpio_cfg;
+
+    gpio_cfg.drive = 0;
+    gpio_cfg.smtCtrl = 1;
+    gpio_cfg.pullType = GPIO_PULL_NONE;
+
+    gpio_cfg.gpioMode = GPIO_MODE_AF;
+    switch (cpuid) {
+        case 0: {
+            gpio_cfg.gpioFun = GPIO_FUN_JTAG_M0;
+        } break;
+        case 1: {
+            gpio_cfg.gpioFun = GPIO_FUN_JTAG_D0;
+        } break;
+        default: {
+        } break;
+    }
+    gpio_cfg.gpioPin = GLB_GPIO_PIN_0;
+    GLB_GPIO_Init(&gpio_cfg);
+
+    gpio_cfg.gpioPin = GLB_GPIO_PIN_1;
+    GLB_GPIO_Init(&gpio_cfg);
+
+    gpio_cfg.gpioPin = GLB_GPIO_PIN_2;
+    GLB_GPIO_Init(&gpio_cfg);
+
+    gpio_cfg.gpioPin = GLB_GPIO_PIN_3;
+    GLB_GPIO_Init(&gpio_cfg);
+}
+
+static void cmd_jtag_m0(void)
+{
+    sipeed_bl_sys_enabe_jtag(0);
+}
+
+static void cmd_jtag_cpu0(void)
+{
+    sipeed_bl_sys_enabe_jtag(1);
+}
+
+/* This is the timer interrupt service routine. */
+static void mtime_handler(void)
+{   
+    rt_tick_increase();
+    
+    csi_coret_config(CPU_Get_MTimer_Clock() / RT_TICK_PER_SECOND, MTIME_IRQn);
+}
+
+void rt_hw_board_init(void)
+{
+    bl_sys_lowlevel_init();
+
+    csi_coret_config(CPU_Get_MTimer_Clock() / RT_TICK_PER_SECOND, MTIME_IRQn);
+    bl_irq_register(MTIME_IRQn, mtime_handler);
+    bl_irq_enable(MTIME_IRQn);
+
+#ifdef RT_USING_HEAP
+    /* initialize memory system */
+    rt_system_heap_init(RT_HW_HEAP_BEGIN, RT_HW_HEAP_END);
+#endif   
+
+    /* UART driver initialization is open by default */
+#ifdef RT_USING_SERIAL
+    rt_hw_uart_init();
+#endif
+
+    /* Set the shell console output device */
+#if defined(RT_USING_CONSOLE) && defined(RT_USING_DEVICE)
+    rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
+#endif
+
+#ifdef RT_USING_COMPONENTS_INIT
+    rt_components_board_init();
+#endif
+
+#ifdef BSP_USING_JTAG_M0
+    cmd_jtag_m0();
+#endif
+}
+
+void rt_hw_cpu_reset(void)
+{
+    bl_sys_reset_por();
+    while(1);
+}
+
+MSH_CMD_EXPORT_ALIAS(rt_hw_cpu_reset, reboot, reset machine);

+ 35 - 0
bsp/bl808/m0/drivers/board.h

@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2022/12/25     flyingcys    first version
+ */
+
+#ifndef BOARD_H__
+#define BOARD_H__
+
+#include <rtconfig.h>
+
+#include "core_rv32.h"
+#include "bl_sys.h"
+#include "bl_irq.h"
+#include "bl808_clock.h"
+
+#ifdef BL808
+#include "bl808.h"
+#elif defined(BL606P)
+#include "bl606p.h"
+#endif
+
+extern uint8_t _heap_start;
+extern uint8_t _heap_size;
+
+#define RT_HW_HEAP_BEGIN    (void*)&_heap_start
+#define RT_HW_HEAP_END      (void*)(&_heap_start + (rt_ubase_t)&_heap_size)
+
+void rt_hw_board_init(void);
+
+#endif

+ 318 - 0
bsp/bl808/m0/drivers/drv_uart.c

@@ -0,0 +1,318 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+* 2022/12/25     flyingcys    first version
+*/
+
+#include <rthw.h>
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#include "board.h"
+#include "drv_uart.h"
+
+
+struct device_uart
+{
+    struct rt_serial_device serial;
+    uint8_t port;
+    uint8_t tx_pin;
+    uint8_t rx_pin;
+};
+
+static void _uart_rx_irq(void *param)
+{
+    struct device_uart *uart = (struct device_uart *)param;;
+
+    struct rt_serial_device *serial = &uart->serial;
+
+    rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
+}
+
+static int uart_signal_get(uint8_t pin)
+{
+    //TODO no magic number is allowed here
+    if (pin >= 12 && pin <=23) {
+        return (pin + 6) % 12;
+    } else if (pin >= 36 && pin <=45) {
+        return (pin + 6) % 12;
+    }
+    return (pin % 12);
+}
+
+static int uart_func_get(uint8_t id, GLB_UART_SIG_FUN_Type uartfunc)
+{
+    switch (id) {
+        case 0:
+            return uartfunc;
+        case 1:
+            return (GLB_UART_SIG_FUN_UART1_RTS - GLB_UART_SIG_FUN_UART0_RTS) * 1 + uartfunc;
+        case 2:
+            return (GLB_UART_SIG_FUN_UART1_RTS - GLB_UART_SIG_FUN_UART0_RTS) * 1 + uartfunc;
+        default:
+            /*empty here*/
+            //TODO should assert here?
+            return uartfunc;
+    }
+}
+static void uart_gpio_demo(uint8_t id, uint8_t tx_pin, uint8_t rx_pin, uint8_t cts_pin, uint8_t rts_pin)
+{
+    GLB_GPIO_Cfg_Type gpio_cfg;
+    uint8_t uart_func, uart_sig;
+
+    //FIXME SWAP set is NOT put here
+    GLB_UART_Sig_Swap_Set(GLB_UART_SIG_SWAP_GRP_GPIO12_GPIO23, 1);
+    GLB_UART_Sig_Swap_Set(GLB_UART_SIG_SWAP_GRP_GPIO36_GPIO45, 1);
+
+    //common GPIO cfg
+    gpio_cfg.drive = 0;
+    gpio_cfg.smtCtrl = 1;
+    gpio_cfg.gpioMode = GPIO_MODE_AF;
+    gpio_cfg.pullType = GPIO_PULL_UP;
+    gpio_cfg.gpioFun = GPIO_FUN_UART;
+
+    //cfg for UART Tx
+    gpio_cfg.gpioPin = GLB_GPIO_PIN_0 + tx_pin;
+    uart_func = uart_func_get(id, GLB_UART_SIG_FUN_UART0_TXD);
+    uart_sig = uart_signal_get(gpio_cfg.gpioPin);
+    GLB_UART_Fun_Sel((GLB_UART_SIG_Type)uart_sig, (GLB_UART_SIG_FUN_Type)uart_func);
+    GLB_UART_Fun_Sel((GLB_UART_SIG_Type)uart_func, (GLB_UART_SIG_FUN_Type)uart_sig);
+    GLB_GPIO_Init(&gpio_cfg);
+
+    //cfg for UART Rx
+    gpio_cfg.gpioPin = GLB_GPIO_PIN_0 + rx_pin;
+    uart_func = uart_func_get(id, GLB_UART_SIG_FUN_UART0_RXD);
+    uart_sig = uart_signal_get(gpio_cfg.gpioPin);
+    GLB_UART_Fun_Sel((GLB_UART_SIG_Type)uart_sig, (GLB_UART_SIG_FUN_Type)uart_func);
+    GLB_UART_Fun_Sel((GLB_UART_SIG_Type)uart_func, (GLB_UART_SIG_FUN_Type)uart_sig);
+    GLB_GPIO_Init(&gpio_cfg);
+
+    //Enable UART clock
+    GLB_Set_UART_CLK(1, 0, 0);
+}
+
+static rt_err_t _uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
+{
+    struct device_uart *uart;
+    uint8_t id;
+
+    RT_ASSERT(serial != RT_NULL);
+    RT_ASSERT(cfg != RT_NULL);
+
+    uart = serial->parent.user_data;
+    RT_ASSERT(uart != RT_NULL);
+
+    id = uart->port;
+
+    UART_CFG_Type uart_cfg = {
+      80*1000*1000,     /*UART clock from XTAL*/
+      2000000,          /* baudrate  */
+      UART_DATABITS_8,  /* data bits  */
+      UART_STOPBITS_1,  /* stop bits */
+      UART_PARITY_NONE, /* parity  */
+      DISABLE,          /* Disable auto flow control */
+      DISABLE,          /* Disable rx input de-glitch function */
+      DISABLE,          /* Disable RTS output SW control mode */
+      DISABLE,          /* Disable tx output SW control mode */
+      DISABLE,          /* Disable tx lin mode */
+      DISABLE,          /* Disable rx lin mode */
+      0,                /* Tx break bit count for lin mode */
+      UART_LSB_FIRST,   /* UART each data byte is send out LSB-first */
+    };
+
+    UART_FifoCfg_Type fifoCfg = {
+      16,      /* TX FIFO threshold */
+      16,      /* RX FIFO threshold */
+      DISABLE, /* Disable tx dma req/ack interface */
+      DISABLE  /* Disable rx dma req/ack interface */
+    };
+
+    /* init debug uart gpio first */
+    uart_gpio_demo(id, uart->tx_pin, uart->rx_pin, 0xff, 0xff);
+
+    /* disable all interrupt */
+    UART_IntMask(id, UART_INT_ALL, MASK);
+
+    /* disable uart before config */
+    UART_Disable(id, UART_TXRX);
+
+    uart_cfg.baudRate = cfg->baud_rate;
+
+    switch (cfg->data_bits)
+    {
+        case DATA_BITS_5:
+            uart_cfg.dataBits = UART_DATABITS_5;
+            break;
+
+        case DATA_BITS_6:
+            uart_cfg.dataBits = UART_DATABITS_6;
+            break;
+
+        case DATA_BITS_7:
+            uart_cfg.dataBits = UART_DATABITS_7;
+            break;
+
+        case DATA_BITS_8:
+            uart_cfg.dataBits = UART_DATABITS_8;
+            break;
+
+        default:
+            uart_cfg.dataBits = UART_DATABITS_8;
+            break;
+    }
+
+    switch (cfg->stop_bits)
+    {
+        case STOP_BITS_1:
+            uart_cfg.stopBits = UART_STOPBITS_1;
+            break;
+        
+        case STOP_BITS_2:
+            uart_cfg.stopBits = UART_STOPBITS_2;
+            break;
+
+        default:
+            uart_cfg.stopBits = UART_STOPBITS_1;
+            break;
+    }
+
+    switch (cfg->parity)
+    {
+        case PARITY_NONE:
+            uart_cfg.parity = UART_PARITY_NONE;
+            break;
+
+        case PARITY_ODD:
+            uart_cfg.parity = UART_PARITY_ODD;
+            break;
+
+        case PARITY_EVEN:
+            uart_cfg.parity = UART_PARITY_EVEN;
+            break;
+
+        default:
+            uart_cfg.parity = UART_PARITY_NONE;
+            break;
+    }
+
+    /* uart init with configuration */
+    UART_Init(id, &uart_cfg);
+
+    /* UART fifo configuration */
+    UART_FifoConfig(id, &fifoCfg);
+
+    /* Enable tx free run mode */
+    UART_TxFreeRun(id, ENABLE);
+
+    /* Set rx time-out value */
+    UART_SetRxTimeoutValue(id, UART_DEFAULT_RTO_TIMEOUT);
+
+    /* enable uart */
+    UART_AutoBaudDetection(id, 0);
+    UART_Enable(id, UART_TXRX);    
+
+    return RT_EOK;
+}
+
+static rt_err_t _uart_control(struct rt_serial_device *serial, int cmd, void *arg)
+{
+    struct device_uart *uart;
+
+    RT_ASSERT(serial != RT_NULL);
+
+    uart = serial->parent.user_data;
+    RT_ASSERT(uart != RT_NULL);
+
+    switch (cmd)
+    {
+    /* disable interrupt */
+    case RT_DEVICE_CTRL_CLR_INT:
+    	bl_uart_int_disable(uart->port);
+        bl_uart_int_rx_notify_unregister(uart->port, _uart_rx_irq, uart);
+        break;
+
+    /* enable interrupt */
+    case RT_DEVICE_CTRL_SET_INT:
+        bl_uart_int_rx_notify_register(uart->port, _uart_rx_irq, uart);
+        bl_uart_int_enable(uart->port);
+        break;
+    }
+    return RT_EOK;
+}
+
+static int _uart_putc(struct rt_serial_device *serial, char c)
+{
+    struct device_uart *uart;
+
+    RT_ASSERT(serial != RT_NULL);
+
+    uart = serial->parent.user_data;
+    RT_ASSERT(uart != RT_NULL);
+
+    bl_uart_data_send(uart->port, c);
+
+    return 1;
+}
+
+static int _uart_getc(struct rt_serial_device *serial)
+{
+    int ch = -1;
+    struct device_uart *uart;
+
+    RT_ASSERT(serial != RT_NULL);
+    uart = serial->parent.user_data;
+    RT_ASSERT(uart != RT_NULL);
+
+    ch = bl_uart_data_recv(uart->port);
+
+    return ch;
+}
+
+static const struct rt_uart_ops _uart_ops =
+{
+    .configure = _uart_configure,
+    .control = _uart_control,
+    .putc = _uart_putc,
+    .getc = _uart_getc,
+    .dma_transmit = RT_NULL
+};
+
+/*
+ * UART Initiation
+ */
+int rt_hw_uart_init(void)
+{
+    rt_err_t result = 0;
+
+    struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
+    struct rt_serial_device *serial;
+    struct device_uart      *uart;
+
+#ifdef BSP_USING_UART0
+    static struct device_uart uart0;
+
+    serial  = &uart0.serial;
+    uart    = &uart0;
+
+    serial->ops              = &_uart_ops;
+    serial->config           = config;
+    serial->config.baud_rate = 2000000;
+
+    uart->port = 0;
+    uart->tx_pin = BSP_UART0_TXD_PIN;
+    uart->rx_pin = BSP_UART0_RXD_PIN;
+
+    /* register USART device */
+    result = rt_hw_serial_register(serial,
+                                    "uart0",
+                                    RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, 
+                                    uart);
+    RT_ASSERT(result == RT_EOK);
+#endif
+
+    return 0;
+}

+ 25 - 0
bsp/bl808/m0/drivers/drv_uart.h

@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2022/12/25     flyingcys    first version
+ */
+
+#ifndef __DRV_USART_H__
+#define __DRV_USART_H__
+
+#include <rtthread.h>
+#include "rtdevice.h"
+#include <rthw.h>
+
+#include "bl_uart.h"
+#include "bl808_uart.h"
+
+#include "uart_config.h"
+
+int rt_hw_uart_init(void);
+
+#endif  /* __DRV_USART_H__ */

+ 101 - 0
bsp/bl808/m0/libraries/SConscript

@@ -0,0 +1,101 @@
+import os
+from building import *
+
+cwd = GetCurrentDir()
+
+# add general drivers
+src = Split('''
+	platform/soc/bl808/startup_bl808/evb/src/startup_interrupt.c
+	platform/soc/bl808/startup_bl808/evb/src/startup_bl606p.c
+	platform/soc/bl808/startup_bl808/evb/src/debug.c
+	platform/soc/bl808/startup_bl808/evb/src/boot/gcc/start_load.c
+	platform/soc/bl808/startup_bl808/evb/src/boot/gcc/startup.S
+''')
+
+path = [cwd, 
+	cwd + r'/platform/soc/bl808/bl808_e907_std/bl808_bsp_driver/regs',
+    cwd + r'/platform/soc/bl808/bl808_e907_std/bl808_bsp_driver/startup/m0/source',
+	cwd + r'/platform/soc/bl808/bl808_e907_std/bl808_bsp_driver/std_drv/inc',
+	cwd + r'/platform/soc/bl808/bl808_e907_std/bl808_bsp_driver/risc-v/Core/Include',
+	cwd + r'/platform/soc/bl808/bl808_e907_std/bl808_bsp_driver/hal_drv/default_config',
+	cwd + r'/platform/soc/bl808/bl808_e907_std/common/misc',
+	cwd + r'/platform/soc/bl808/bl808_e907_std/common/soft_crc']
+
+src += Split("""
+	stage/blog/blog.c
+	utils/src/utils_log.c
+	stage/blfdt/src/fdt.c
+	stage/blfdt/src/fdt_ro.c
+	stage/blfdt/src/fdt_wip.c
+	stage/blfdt/src/fdt_sw.c
+	stage/blfdt/src/fdt_rw.c
+	stage/blfdt/src/fdt_strerror.c
+	stage/blfdt/src/fdt_empty_tree.c
+	stage/blfdt/src/fdt_addresses.c
+	stage/blfdt/src/fdt_overlay.c
+""")
+
+path += [cwd + r'/stage/blog',
+	cwd + r'/stage/blfdt/inc',
+	cwd + r'/utils/include'
+]
+	
+	# platform/hosal/bl808_e907_hal/bl_pm.c
+	# platform/hosal/bl808_e907_hal/bl_sec.c
+	# platform/hosal/bl808_e907_hal/bl_timer.c
+	# platform/hosal/bl808_e907_hal/hal_board.c
+	# platform/hosal/bl808_e907_hal/hal_sdh.c
+	# platform/hosal/bl808_e907_hal/hosal_adc.c
+	# platform/hosal/bl808_e907_hal/hosal_dma.c
+	# platform/hosal/bl808_e907_hal/hosal_pwm.c
+	# platform/hosal/bl808_e907_hal/hosal_spi.c
+	# platform/hosal/bl808_e907_hal/hosal_uart.c
+	# platform/hosal/bl808_e907_hal/hal_sdh.c
+
+
+src += Split("""
+    platform/hosal/bl808_e907_hal/bl_uart.c
+	platform/hosal/bl808_e907_hal/bl_irq.c
+	platform/hosal/bl808_e907_hal/bl_chip.c
+	platform/hosal/bl808_e907_hal/bl_flash.c
+	platform/hosal/bl808_e907_hal/bl_wifi.c
+	platform/hosal/bl808_e907_hal/bl_efuse.c
+	platform/hosal/bl808_e907_hal/bl_sys.c
+	platform/hosal/bl808_e907_hal/bl_boot2.c
+	platform/hosal/bl808_e907_hal/bl_ipc.c
+	platform/hosal/bl808_e907_hal/bl_cam.c
+	platform/hosal/bl808_e907_hal/bl_audio.c
+	platform/hosal/bl808_e907_hal/bl_sdh.c
+    platform/hosal/bl808_e907_hal/hal_boot2.c
+	platform/hosal/bl808_e907_hal/hal_sys.c
+	platform/hosal/bl808_e907_hal/bl_psram.c
+	platform/hosal/bl808_e907_hal/bl_mm_clock.c
+	platform/hosal/bl808_e907_hal/hal_board.c
+	platform/soc/bl808/bl808_e907_std/common/misc/misc.c
+	platform/soc/bl808/bl808_e907_std/common/soft_crc/softcrc.c
+""")
+
+src += Split("""
+	platform/soc/bl808/bl808_e907_std/bl808_bsp_driver/std_drv/src/bl808_common.c
+	platform/soc/bl808/bl808_e907_std/bl808_bsp_driver/std_drv/src/bl808_clock.c
+	platform/soc/bl808/bl808_e907_std/bl808_bsp_driver/std_drv/src/bl808_uart.c
+	platform/soc/bl808/bl808_e907_std/bl808_bsp_driver/std_drv/src/bl808_glb.c
+	platform/soc/bl808/bl808_e907_std/bl808_bsp_driver/std_drv/src/bl808_glb_gpio.c
+	platform/soc/bl808/bl808_e907_std/bl808_bsp_driver/std_drv/src/bl808_pds.c
+	platform/soc/bl808/bl808_e907_std/bl808_bsp_driver/std_drv/src/bl808_hbn.c
+	platform/soc/bl808/bl808_e907_std/bl808_bsp_driver/std_drv/src/bl808_sflash.c
+	platform/soc/bl808/bl808_e907_std/bl808_bsp_driver/std_drv/src/bl808_xip_sflash.c
+	platform/soc/bl808/bl808_e907_std/bl808_bsp_driver/std_drv/src/bl808_sf_cfg.c
+	platform/soc/bl808/bl808_e907_std/bl808_bsp_driver/std_drv/src/bl808_ef_ctrl.c
+	platform/soc/bl808/bl808_e907_std/bl808_bsp_driver/std_drv/src/bl808_sf_ctrl.c
+""")
+
+path += [cwd + r'/platform/hosal/bl808_e907_hal']
+
+libpath = []
+libs = []
+
+group = DefineGroup('Libraries', src, depend = [''], CPPPATH = path, LIBS = libs, LIBPATH = libpath)
+
+
+Return('group')

+ 38 - 0
bsp/bl808/m0/libraries/platform/hosal/adapter/hosal_adapter.h

@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _HOSAL_ADAPTER_H_
+#define _HOSAL_ADAPTER_H_
+
+#include <stdint.h>
+
+uintptr_t hosal_adpt_critical_enter(void);
+void hosal_adpt_critical_exit(uintptr_t);
+
+#endif

+ 45 - 0
bsp/bl808/m0/libraries/platform/hosal/adapter/hosal_adpt_iotsdk.c

@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "hosal_adapter.h"
+#include "FreeRTOS.h"
+#include "task.h"
+
+uintptr_t hosal_adpt_critical_enter(void)
+{
+  taskENTER_CRITICAL();
+  return 0;
+}
+
+void hosal_adpt_critical_exit(uintptr_t irq_state)
+{
+  (void)irq_state;
+  taskEXIT_CRITICAL();
+}
+

+ 545 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_audio.c

@@ -0,0 +1,545 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "bl_audio.h"
+
+#include "bl808.h"
+#include "bl808_audio.h"
+#include "bl808_glb.h"
+#include "bl808_hbn.h"
+#include "bl808_dma.h"
+#include "bl_irq.h"
+// #include <FreeRTOS.h>
+// #include <portable.h>
+
+static bl_audio_dev_t *gp_audio_dac_dev = NULL;
+
+#define AUDIO_DMA_ID       DMA0_ID
+#define AUDIO_TX_DMA_CHANNLE  DMA_CH0
+#define AUDIO_RX_DMA_CHANNLE  DMA_CH1
+
+static struct DMA_Control_Reg dmaCtrlRegVal={
+    .TransferSize = 1000,
+    .SBSize = DMA_BURST_SIZE_8,
+    .DBSize = DMA_BURST_SIZE_8,
+    .SWidth = DMA_TRNS_WIDTH_16BITS,
+    .DWidth = DMA_TRNS_WIDTH_16BITS,
+    .SI = DMA_MINC_ENABLE,
+    .DI = DMA_MINC_DISABLE,
+    .dst_min_mode = DISABLE,
+    .dst_add_mode = DISABLE,
+    .fix_cnt = 0,
+    .I = 1,
+};
+
+static DMA_LLI_Cfg_Type lliCfg={
+    DMA_TRNS_M2P,
+    DMA_REQ_NONE,
+    DMA_REQ_AUDIO_TX,
+};
+
+static int __hw_init(bl_audio_dev_t *p_dev)
+{
+    Audio_FifoCfg_Type audioFifoCfg;
+
+    Audio_Clock_CFG_Type audioClockCfg = {
+        AUDIO_ADC_16_KHZ,
+        AUDIO_DAC_16_KHZ,
+        DISABLE,
+        DISABLE,
+        DISABLE,
+    };
+
+    Audio_Volume_Cfg_Type audioVolumeCfg = {
+        AUIDO_MUTE_DIRECTLY,
+        AUIDO_RAMP_RATE_2_FS,
+        AUIDO_RAMP_RATE_2_FS,
+        AUIDO_VOLUME_UPDATE_FORCE,
+        AUIDO_ZERO_CROSS_RATE_2_FS,
+        AUIDO_RAMP_RATE_2_FS,
+        AUIDO_ZERO_CROSS_RATE_2_FS,
+    };
+ 
+    GLB_Config_AUDIO_PLL(GLB_XTAL_40M, audioPllCfg_451P584M);
+    /* ungate audio */
+    GLB_PER_Clock_UnGate(GLB_AHB_CLOCK_AUDIO);
+
+    /* enable dac clock*/
+    GLB_Set_Audio_DAC_CLK(ENABLE, 19);
+    /* enable adc clock*/
+    GLB_Set_Audio_ADC_CLK(ENABLE, 19);
+
+    Audio_Poweron();
+
+    switch (p_dev->samplerate) {
+        case AUDIO_8_KHZ:
+            audioClockCfg.dac_clock = AUDIO_DAC_8_KHZ;
+            printf("samplerate 8K\r\n");
+            break;
+        case AUDIO_16_KHZ:
+            audioClockCfg.dac_clock = AUDIO_DAC_16_KHZ;
+            printf("samplerate 16K\r\n");
+            break;
+        case AUDIO_24_KHZ:
+            audioClockCfg.dac_clock = AUDIO_DAC_24_KHZ;
+            printf("samplerate 24K\r\n");
+            break;
+        case AUDIO_32_KHZ:
+            audioClockCfg.dac_clock = AUDIO_DAC_32_KHZ;
+            printf("samplerate 32K\r\n");
+            break;
+        case AUDIO_48_KHZ:
+            audioClockCfg.dac_clock = AUDIO_DAC_48_KHZ;
+            printf("samplerate 48K\r\n");
+            break;
+        case AUDIO_96_KHZ:
+            audioClockCfg.dac_clock = AUDIO_DAC_96_KHZ;
+            printf("samplerate 96K\r\n");
+            break;
+        case AUDIO_192_KHZ:
+            audioClockCfg.dac_clock = AUDIO_DAC_192_KHZ;
+            printf("samplerate 192K\r\n");
+            break;
+        default:
+            printf("samplerate NULL\r\n");
+            break;
+    }
+
+    Audio_Clock_Init(&audioClockCfg);
+    //set mute ramp
+    Audio_DAC_Software_Volume_Config(AUDIO_DAC_0, &audioVolumeCfg);
+    if (p_dev->rx_channel == STEREO_CHANNEL) {
+        Audio_DAC_Software_Volume_Config(AUDIO_DAC_1, &audioVolumeCfg);
+    }
+
+    Audio_DAC_Set_Volume_Reg(ENABLE, 0, AUDIO_PLAY_DEFAULT_INITIAL_VOLUME);
+
+    Audio_DAC_Enable(AUDIO_DAC_0);
+    if (p_dev->rx_channel == STEREO_CHANNEL) {
+        Audio_DAC_Enable(AUDIO_DAC_1);
+    }
+
+    Audio_DAC_Set_Mute(ENABLE, 0, AUDIO_UNMUTE);
+
+    switch (p_dev->playBitWidth) {
+        case AUDIO_BIT_WIDTH_16:
+            audioFifoCfg.resolution = AUDIO_RES_16_BITS;
+            audioFifoCfg.ailgnMode = AUDIO_FIFO_AILGN_MSB_AT_BIT15;
+            printf("BitWidth 16\r\n");
+            break;
+        case AUDIO_BIT_WIDTH_24:
+            audioFifoCfg.resolution = AUDIO_RES_20_BITS;
+            audioFifoCfg.ailgnMode = AUDIO_FIFO_AILGN_MSB_AT_BIT23;
+            printf("BitWidth 24\r\n");
+            break;
+        case AUDIO_BIT_WIDTH_32:
+            audioFifoCfg.resolution = AUDIO_RES_20_BITS;
+            audioFifoCfg.ailgnMode = AUDIO_FIFO_AILGN_MSB_AT_BIT31;
+            printf("BitWidth 32\r\n");
+            break;
+        default:
+            printf("BitWidth NULL\r\n");
+            break;
+    }
+    audioFifoCfg.FifoIntThreshold = AUDIO_DEFAULT_TX_DRQ_THR;
+    audioFifoCfg.dmaThresholdMode = AUDIO_DRQ_EQUEL_TO_IRQ;
+    audioFifoCfg.dmaEn = ENABLE;
+
+    Audio_TxFifoConfig(&audioFifoCfg);
+
+    Audio_TxFifoDisable(p_dev->tx_channel);
+
+    if (p_dev->rx_enable) {
+        Audio_ADC_Software_Volume_Config(AUDIO_ADC_0, &audioVolumeCfg);
+        if (p_dev->rx_channel == STEREO_CHANNEL) {
+            Audio_ADC_Software_Volume_Config(AUDIO_ADC_1, &audioVolumeCfg);
+        }
+
+        Audio_ADC_Set_Volume_Reg(ENABLE, 0, AUDIO_PLAY_DEFAULT_INITIAL_VOLUME);
+
+        Audio_ADC_Enable(AUDIO_ADC_0);
+        if (p_dev->rx_channel == STEREO_CHANNEL) {
+            Audio_ADC_Enable(AUDIO_ADC_1);
+        }
+
+        Audio_ADC_Set_Mute(ENABLE, 0, AUDIO_UNMUTE);
+
+        audioFifoCfg.FifoIntThreshold = AUDIO_DEFAULT_RX_DRQ_THR;
+        Audio_RxFifoConfig(&audioFifoCfg);
+        Audio_RxFifoDisable(p_dev->rx_channel);
+    }
+    Auido_IntMask(AUDIO_INT_NUM_ALL, MASK);
+
+    return 0;
+}
+
+static void __audio_lli_init(bl_audio_dev_t *p_dev)
+{
+    p_dev->lli_tx_buffer_size = p_dev->lli_tx_buffer_size / 2;
+    
+    switch (p_dev->playBitWidth) {
+        case AUDIO_BIT_WIDTH_16:
+            dmaCtrlRegVal.SWidth = DMA_TRNS_WIDTH_16BITS;
+            dmaCtrlRegVal.DWidth = DMA_TRNS_WIDTH_16BITS;
+            dmaCtrlRegVal.SBSize = DMA_BURST_SIZE_8;
+            dmaCtrlRegVal.DBSize = DMA_BURST_SIZE_8;
+            dmaCtrlRegVal.TransferSize = p_dev->lli_tx_buffer_size / 2;
+            break;
+        case AUDIO_BIT_WIDTH_24:
+            dmaCtrlRegVal.SWidth = DMA_TRNS_WIDTH_32BITS;
+            dmaCtrlRegVal.DWidth = DMA_TRNS_WIDTH_32BITS;
+            dmaCtrlRegVal.SBSize = DMA_BURST_SIZE_4;
+            dmaCtrlRegVal.DBSize = DMA_BURST_SIZE_4;
+            dmaCtrlRegVal.TransferSize = p_dev->lli_tx_buffer_size / 4;
+            break;
+        case AUDIO_BIT_WIDTH_32:
+            dmaCtrlRegVal.SWidth = DMA_TRNS_WIDTH_32BITS;
+            dmaCtrlRegVal.DWidth = DMA_TRNS_WIDTH_32BITS;
+            dmaCtrlRegVal.SBSize = DMA_BURST_SIZE_4;
+            dmaCtrlRegVal.DBSize = DMA_BURST_SIZE_4;
+            dmaCtrlRegVal.TransferSize = p_dev->lli_tx_buffer_size / 4;
+            break;
+
+        default:
+            //private_bflb_platform_printf("BIT WIDTH Is Invaild\r\n");
+            break;
+    }
+ 
+    p_dev->lli_tx_list[0].srcDmaAddr = (uint32_t)p_dev->lli_tx_buffer;
+    p_dev->lli_tx_list[0].destDmaAddr = AUDIO_TX_FIFO_ADDR;
+    p_dev->lli_tx_list[0].nextLLI = (uint32_t)&p_dev->lli_tx_list[1];
+    p_dev->lli_tx_list[0].dmaCtrl= dmaCtrlRegVal;
+
+    p_dev->lli_tx_list[1].srcDmaAddr = (uint32_t)p_dev->lli_tx_buffer + p_dev->lli_tx_buffer_size;
+    p_dev->lli_tx_list[1].destDmaAddr = AUDIO_TX_FIFO_ADDR;
+    p_dev->lli_tx_list[1].nextLLI=(uint32_t)&p_dev->lli_tx_list[0];
+    p_dev->lli_tx_list[1].dmaCtrl= dmaCtrlRegVal;
+
+    DMA_LLI_Init(AUDIO_DMA_ID, AUDIO_TX_DMA_CHANNLE, &lliCfg);
+    DMA_LLI_Update(AUDIO_DMA_ID, AUDIO_TX_DMA_CHANNLE, (uint32_t)&gp_audio_dac_dev->lli_tx_list);
+
+    if (p_dev->rx_enable) {
+        p_dev->lli_rx_buffer_size = p_dev->lli_rx_buffer_size / 2;
+ 
+        switch (p_dev->playBitWidth) {
+            case AUDIO_BIT_WIDTH_16:
+                dmaCtrlRegVal.SWidth = DMA_TRNS_WIDTH_16BITS;
+                dmaCtrlRegVal.DWidth = DMA_TRNS_WIDTH_16BITS;
+                dmaCtrlRegVal.SBSize = DMA_BURST_SIZE_8;
+                dmaCtrlRegVal.DBSize = DMA_BURST_SIZE_8;
+                dmaCtrlRegVal.TransferSize = p_dev->lli_rx_buffer_size / 2;
+                break;
+            case AUDIO_BIT_WIDTH_24:
+                dmaCtrlRegVal.SWidth = DMA_TRNS_WIDTH_32BITS;
+                dmaCtrlRegVal.DWidth = DMA_TRNS_WIDTH_32BITS;
+                dmaCtrlRegVal.SBSize = DMA_BURST_SIZE_4;
+                dmaCtrlRegVal.DBSize = DMA_BURST_SIZE_4;
+                dmaCtrlRegVal.TransferSize = p_dev->lli_rx_buffer_size / 4;
+                break;
+            case AUDIO_BIT_WIDTH_32:
+                dmaCtrlRegVal.SWidth = DMA_TRNS_WIDTH_32BITS;
+                dmaCtrlRegVal.DWidth = DMA_TRNS_WIDTH_32BITS;
+                dmaCtrlRegVal.SBSize = DMA_BURST_SIZE_4;
+                dmaCtrlRegVal.DBSize = DMA_BURST_SIZE_4;
+                dmaCtrlRegVal.TransferSize = p_dev->lli_rx_buffer_size / 4;
+                break;
+
+            default:
+                //private_bflb_platform_printf("BIT WIDTH Is Invaild\r\n");
+                break;
+        }
+
+        dmaCtrlRegVal.SI = DMA_MINC_DISABLE;
+        dmaCtrlRegVal.DI = DMA_MINC_ENABLE;
+
+        p_dev->lli_rx_list[0].srcDmaAddr = AUDIO_RX_FIFO_ADDR;
+        p_dev->lli_rx_list[0].destDmaAddr = (uint32_t)p_dev->lli_rx_buffer;
+        p_dev->lli_rx_list[0].nextLLI = (uint32_t)&p_dev->lli_rx_list[1];
+        p_dev->lli_rx_list[0].dmaCtrl= dmaCtrlRegVal;
+
+        p_dev->lli_rx_list[1].srcDmaAddr = AUDIO_RX_FIFO_ADDR;
+        p_dev->lli_rx_list[1].destDmaAddr = (uint32_t)p_dev->lli_rx_buffer + p_dev->lli_rx_buffer_size;
+        p_dev->lli_rx_list[1].nextLLI=(uint32_t)&p_dev->lli_rx_list[0];
+        p_dev->lli_rx_list[1].dmaCtrl= dmaCtrlRegVal;
+
+        lliCfg.dir = DMA_TRNS_P2M;
+        lliCfg.srcPeriph = DMA_REQ_AUDIO_RX;
+        lliCfg.dstPeriph = DMA_REQ_NONE;
+
+        DMA_LLI_Init(AUDIO_DMA_ID, AUDIO_RX_DMA_CHANNLE, &lliCfg);
+        DMA_LLI_Update(AUDIO_DMA_ID, AUDIO_RX_DMA_CHANNLE, (uint32_t)&gp_audio_dac_dev->lli_rx_list);
+    }
+}
+
+static int __dma_int_clear(DMA_ID_Type dma_id, int ch)
+{
+    uint32_t tmpVal;
+    uint32_t intClr;
+    /* Get DMA register */
+
+    const uint32_t dmaAddr[] = { DMA0_BASE, DMA1_BASE, DMA2_BASE };
+    uint32_t DMAChs = dmaAddr[dma_id];
+
+    tmpVal = BL_RD_REG(DMAChs, DMA_INTTCSTATUS);
+    if((BL_GET_REG_BITS_VAL(tmpVal, DMA_INTTCSTATUS) & (1 << ch)) != 0) {
+        /* Clear interrupt */
+        tmpVal = BL_RD_REG(DMAChs, DMA_INTTCCLEAR);
+        intClr = BL_GET_REG_BITS_VAL(tmpVal, DMA_INTTCCLEAR);
+        intClr |= (1 << ch);
+        tmpVal = BL_SET_REG_BITS_VAL(tmpVal, DMA_INTTCCLEAR, intClr);
+        BL_WR_REG(DMAChs, DMA_INTTCCLEAR, tmpVal);
+    }
+
+    tmpVal = BL_RD_REG(DMAChs, DMA_INTERRORSTATUS);
+    if((BL_GET_REG_BITS_VAL(tmpVal, DMA_INTERRORSTATUS) & (1 << ch)) != 0) {
+        /*Clear interrupt */
+        tmpVal = BL_RD_REG(DMAChs, DMA_INTERRCLR);
+        intClr = BL_GET_REG_BITS_VAL(tmpVal, DMA_INTERRCLR);
+        intClr |= (1 << ch);
+        tmpVal = BL_SET_REG_BITS_VAL(tmpVal, DMA_INTERRCLR, intClr);
+        BL_WR_REG(DMAChs, DMA_INTERRCLR, tmpVal);
+    }
+
+    return 0;
+}
+
+static void __dma_irq_handler(void)
+{
+    uint32_t tmpVal, count;
+    int ret, size;
+    tmpVal = BL_RD_REG(DMA0_BASE, DMA_INTTCSTATUS);
+    if ((BL_GET_REG_BITS_VAL(tmpVal, DMA_INTTCSTATUS) & (1 << AUDIO_TX_DMA_CHANNLE)) != 0) {
+        __dma_int_clear(AUDIO_DMA_ID, AUDIO_TX_DMA_CHANNLE); //clear int first
+
+        if ( NULL == gp_audio_dac_dev) {
+            return;
+        }
+        size = gp_audio_dac_dev->lli_tx_buffer_size;
+        /*FIXME: set dma chain resonable option first 2 chain*/
+        if (gp_audio_dac_dev->usr_cb) {
+            /* software count may reliable*/
+            //if (++gp_audio_dac_dev->pingpang >= 2) {
+            //    gp_audio_dac_dev->pingpang = 0;
+            //}
+
+            count = ((*(volatile uint32_t *)0x2000c110) & (0x3FF << 20)) >> 20;
+            if (0x01 == (count & 0x01)) {
+                ret = gp_audio_dac_dev->usr_cb(gp_audio_dac_dev->p_usr_arg,
+                                               gp_audio_dac_dev->lli_tx_buffer,
+                                               size,
+                                               gp_audio_dac_dev->is_underrun);
+            } else {
+                ret = gp_audio_dac_dev->usr_cb(gp_audio_dac_dev->p_usr_arg,
+                                               gp_audio_dac_dev->lli_tx_buffer + size,
+                                               size,
+                                               gp_audio_dac_dev->is_underrun);
+            }
+            if (ret != 0) {
+                gp_audio_dac_dev->is_underrun = 1;
+            } else {
+                gp_audio_dac_dev->is_underrun = 0;
+            }
+        }
+    }
+
+    if((BL_GET_REG_BITS_VAL(tmpVal, DMA_INTTCSTATUS) & (1 << AUDIO_RX_DMA_CHANNLE)) != 0) {
+        __dma_int_clear(AUDIO_DMA_ID, AUDIO_RX_DMA_CHANNLE); //clear int first
+        if ( NULL == gp_audio_dac_dev) {
+            return;
+        }
+        size = gp_audio_dac_dev->lli_rx_buffer_size;
+        if (gp_audio_dac_dev->usr_rx_cb) {
+            count = ((*(volatile uint32_t *)0x2000c210) & (0x3FF << 20)) >> 20;
+            /*FIXME: set dma multi chains*/
+            if (0x01 == (count & 0x01)) {
+                ret = gp_audio_dac_dev->usr_rx_cb(gp_audio_dac_dev->p_usr_rx_arg,
+                                               gp_audio_dac_dev->lli_rx_buffer,
+                                               size,
+                                               gp_audio_dac_dev->is_overflow);
+            } else {
+                ret = gp_audio_dac_dev->usr_rx_cb(gp_audio_dac_dev->p_usr_rx_arg,
+                                               gp_audio_dac_dev->lli_rx_buffer + size,
+                                               size,
+                                               gp_audio_dac_dev->is_overflow);
+            }
+            if (ret != 0) {
+                gp_audio_dac_dev->is_overflow = 1;
+            } else {
+                gp_audio_dac_dev->is_overflow = 0;
+            }
+        }
+    }
+}
+
+int bl_audio_samplerate_set (bl_audio_dev_t *p_dev, Audio_Samplerate_Type samplerate)
+{
+    p_dev->samplerate = samplerate;
+
+    return 0;
+}
+
+int bl_audio_tx_ready_config(bl_audio_dev_t *p_dev,
+                              audio_callback_tx_ready_t cb,
+                              void *p_arg)
+{
+    if (NULL == p_dev) {
+        printf("tx ready config fail dev is null\r\n");
+        return -1;
+    }
+    p_dev->usr_cb = cb;
+    p_dev->p_usr_arg = p_arg;
+    return 0;
+}
+
+int bl_audio_rx_ready_config(bl_audio_dev_t *p_dev,
+                              audio_callback_rx_ready_t cb,
+                              void *p_arg)
+{
+    if (NULL == p_dev) {
+        printf("rx ready config fail dev is null\r\n");
+        return -1;
+    }
+    p_dev->usr_rx_cb = cb;
+    p_dev->p_usr_rx_arg = p_arg;
+    return 0;
+}
+
+int bl_audio_tx_buffer_config (bl_audio_dev_t *p_dev, void **ptr_mem, uint32_t bufsize)
+{
+    if (NULL == p_dev->lli_tx_buffer) {
+        p_dev->lli_tx_buffer = pvPortMalloc(bufsize);
+    }
+
+    if (NULL == p_dev->lli_tx_buffer) {
+        printf("malloc tx buffer fail\r\n");
+        return -1;
+    }
+
+    memset(p_dev->lli_tx_buffer, 0, bufsize);
+    csi_dcache_clean_range((void *)(p_dev->lli_tx_buffer), bufsize);
+    *ptr_mem = p_dev->lli_tx_buffer;
+    p_dev->lli_tx_buffer_size = bufsize;
+
+    return 0;
+}
+
+int bl_audio_rx_buffer_config (bl_audio_dev_t *p_dev,
+                                  void **ptr_mem,
+                                  uint32_t bufsize)
+{
+    if (NULL == p_dev->lli_rx_buffer) {
+        p_dev->lli_rx_buffer = pvPortMalloc(bufsize);
+    }
+
+    if (NULL == p_dev->lli_rx_buffer) {
+        printf("malloc rx buffer fail\r\n");
+        return -1;
+    }
+
+    memset(p_dev->lli_rx_buffer, 0, bufsize);
+    csi_dcache_clean_range((void *)(p_dev->lli_rx_buffer), bufsize);
+    *ptr_mem = p_dev->lli_rx_buffer;
+    p_dev->lli_rx_buffer_size = bufsize;
+
+    return 0;
+}
+
+int bl_audio_start (bl_audio_dev_t *p_dev)
+{
+    if (NULL == p_dev) {
+        printf("audio start fail dev is NULL\r\n");
+        return -1;
+    }
+
+    __hw_init(p_dev);
+
+    GLB_Set_DMA_CLK(ENABLE, GLB_DMA0_CLK_CH0);
+    GLB_PER_Clock_UnGate(GLB_AHB_CLOCK_DMA_0);
+
+    DMA_Disable(AUDIO_DMA_ID);
+    DMA_Channel_Disable(AUDIO_DMA_ID, AUDIO_TX_DMA_CHANNLE);
+    DMA_Channel_Disable(AUDIO_DMA_ID, AUDIO_RX_DMA_CHANNLE);
+
+    DMA_IntMask(AUDIO_DMA_ID, AUDIO_TX_DMA_CHANNLE, DMA_INT_ALL, MASK);
+    DMA_IntMask(AUDIO_DMA_ID, AUDIO_TX_DMA_CHANNLE, DMA_INT_TCOMPLETED, UNMASK);
+    DMA_IntMask(AUDIO_DMA_ID, AUDIO_RX_DMA_CHANNLE, DMA_INT_ALL, MASK);
+    DMA_IntMask(AUDIO_DMA_ID, AUDIO_RX_DMA_CHANNLE, DMA_INT_TCOMPLETED, UNMASK);
+    bl_irq_register(DMA0_ALL_IRQn, __dma_irq_handler);
+    bl_irq_enable(DMA0_ALL_IRQn);
+
+    __audio_lli_init(p_dev);
+
+    csi_dcache_clean();
+    DMA_Enable(AUDIO_DMA_ID);
+    DMA_Channel_Enable(AUDIO_DMA_ID, AUDIO_TX_DMA_CHANNLE);
+
+    Audio_TxFifoEnable(p_dev->tx_channel);
+
+    if (p_dev->rx_enable) {
+        DMA_Channel_Enable(AUDIO_DMA_ID, AUDIO_RX_DMA_CHANNLE);
+        Audio_RxFifoEnable(p_dev->rx_channel);
+    }
+    return 0;
+}
+
+int bl_audio_stop (bl_audio_dev_t *p_dev)
+{
+    gp_audio_dac_dev->pingpang = 0;
+
+    DMA_Disable(AUDIO_DMA_ID);
+    DMA_Channel_Disable(AUDIO_DMA_ID, AUDIO_TX_DMA_CHANNLE);
+    if (p_dev->rx_enable) {
+        DMA_Channel_Disable(AUDIO_DMA_ID, AUDIO_RX_DMA_CHANNLE);
+    }
+    bl_irq_disable(DMA0_ALL_IRQn);
+
+    return 0;
+}
+
+int bl_audio_init (bl_audio_dev_t *p_dev)
+{
+    if (NULL == p_dev) {
+        printf("init audio fail dev is null\r\n");
+        return -1;
+    }
+    memset(p_dev, 0, sizeof(bl_audio_dev_t));
+    gp_audio_dac_dev = p_dev;
+
+    return 0;
+}
+
+int bl_audio_deinit (bl_audio_dev_t *p_dev)
+{
+    vPortFree(p_dev->lli_tx_buffer);
+    p_dev->lli_tx_buffer =  NULL;
+
+    vPortFree(p_dev->lli_rx_buffer);
+    p_dev->lli_tx_buffer =  NULL;
+    return 0;
+}

+ 120 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_audio.h

@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __BL_AUDIO_H__
+#define __BL_AUDIO_H__
+
+#include <stdint.h>
+#include <bl808_dma.h>
+#include "bl808_audio.h"
+
+typedef int (*audio_callback_rx_ready_t)(void *usrdata, uint8_t *audiodata, int len, int is_overflow);
+typedef int (*audio_callback_tx_ready_t)(void *uerdata, uint8_t *audiodata, int len, int is_underrun);
+
+#define AUDIO_PLAY_DEFAULT_INITIAL_VOLUME    0x0
+#define AUDIO_TX_FIFO_ADDR                   AUDIO_BASE + 0x94
+#define AUDIO_RX_FIFO_ADDR                   AUDIO_BASE + 0x88
+#define AUDIO_DEFAULT_TX_DRQ_THR             8
+#define AUDIO_DEFAULT_RX_DRQ_THR             8
+
+typedef enum {
+    LEFT_CHANNEL = 1,   /*!< select mono mode left only */
+    RIGHT_CHANNEL = 2,  /*!< select mono mode right only */
+    STEREO_CHANNEL = 3, /*!< select stereo */
+    THREE_CHANNEL = 7,  /*!< select Three */
+} Audio_Channel_Type;
+
+typedef enum {
+    AUDIO_BIT_WIDTH_16, /*!< 16 bit */
+    AUDIO_BIT_WIDTH_24, /*!< 24 bit */
+    AUDIO_BIT_WIDTH_32, /*!< 32 bit */
+} Audio_BitWidth_Type;
+
+typedef enum {
+    AUDIO_8_KHZ,   /*!< Audio DAC Clock set as 8KHZ */
+    AUDIO_16_KHZ,  /*!< Audio DAC Clock set as 16KHZ */
+    AUDIO_24_KHZ,  /*!< Audio DAC Clock set as 24KHZ */
+    AUDIO_32_KHZ,  /*!< Audio DAC Clock set as 32KHZ */
+    AUDIO_48_KHZ,  /*!< Audio DAC Clock set as 48KHZ */
+    AUDIO_96_KHZ,  /*!< Audio DAC Clock set as 96KHZ */
+    AUDIO_192_KHZ, /*!< Audio DAC Clock set as 192KHZ */
+} Audio_Samplerate_Type;
+
+typedef struct {
+    uint8_t pingpang;
+    DMA_LLI_Ctrl_Type lli_tx_list[2];
+    DMA_LLI_Ctrl_Type lli_rx_list[2];
+    uint8_t *lli_tx_buffer;
+    uint32_t lli_tx_buffer_size;
+    uint8_t *lli_rx_buffer;
+    uint32_t lli_rx_buffer_size;
+
+    int is_underrun;
+    int is_overflow;
+    audio_callback_tx_ready_t usr_cb;
+    audio_callback_rx_ready_t usr_rx_cb;
+    void *p_usr_arg;
+    void *p_usr_rx_arg;
+
+    Audio_Samplerate_Type samplerate;
+    Audio_BitWidth_Type playBitWidth;
+    Audio_Channel_Type tx_channel;
+    Audio_Channel_Type rx_channel;
+    uint8_t rx_enable;
+
+} bl_audio_dev_t;
+
+int bl_audio_init (bl_audio_dev_t *p_dev);
+
+int bl_audio_deinit (bl_audio_dev_t *p_dev);
+
+int bl_audio_start (bl_audio_dev_t *p_dev);
+
+int bl_audio_stop (bl_audio_dev_t *p_dev);
+
+int bl_audio_tx_buffer_config (bl_audio_dev_t *p_dev,
+                                   void **ptr_mem,
+                                   uint32_t bufsize);
+
+int bl_audio_rx_buffer_config (bl_audio_dev_t *p_dev,
+                                   void **ptr_mem,
+                                   uint32_t bufsize);
+
+int bl_audio_tx_ready_config(bl_audio_dev_t *p_dev,
+                                 audio_callback_tx_ready_t cb,
+                                 void *p_arg);
+
+int bl_audio_rx_ready_config(bl_audio_dev_t *p_dev,
+                                 audio_callback_rx_ready_t cb,
+                                 void *p_arg);
+
+int bl_audio_samplerate_set (bl_audio_dev_t *p_dev,
+                                 Audio_Samplerate_Type samplerate);
+
+#endif

+ 145 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_boot2.c

@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <string.h>
+#include <softcrc.h>
+#include <bl_flash.h>
+#include <bl_boot2.h>
+PtTable_Error_Type PtTable_Update_Entry(const SPI_Flash_Cfg_Type *pFlashCfg,
+                                                PtTable_ID_Type targetTableID,
+                                                PtTable_Stuff_Config *ptStuff,
+                                                PtTable_Entry_Config *ptEntry)
+{
+    uint32_t i=0;
+    BL_Err_Type ret;
+    uint32_t writeAddr;
+    uint32_t entriesLen;
+    PtTable_Config *ptTable;
+    PtTable_Entry_Config *ptEntries;
+    uint32_t *pCrc32;
+
+    if(ptEntry==NULL||ptStuff==NULL){
+        return PT_ERROR_PARAMETER;
+    }
+    
+    ptTable=&ptStuff->ptTable;
+    ptEntries=ptStuff->ptEntries;
+    
+    if(targetTableID==PT_TABLE_ID_INVALID){
+        return PT_ERROR_TABLE_NOT_VALID;
+    }
+    
+    if(targetTableID==PT_TABLE_ID_0){
+        writeAddr=BFLB_PT_TABLE0_ADDRESS;
+    }else{
+        writeAddr=BFLB_PT_TABLE1_ADDRESS;
+    }
+    for (i=0; i < ptTable->entryCnt; i++) {
+        if (ptEntries[i].type == ptEntry->type){
+            memcpy(&ptEntries[i],ptEntry,sizeof(PtTable_Entry_Config));
+            break;
+        }
+    }
+    if(i==ptTable->entryCnt){
+        /* Not found this entry ,add new one */
+        if(ptTable->entryCnt<PT_ENTRY_MAX){
+            memcpy(&ptEntries[ptTable->entryCnt],ptEntry,sizeof(PtTable_Entry_Config));
+            ptTable->entryCnt++;
+        }else{
+            return PT_ERROR_ENTRY_UPDATE_FAIL;
+        }
+    }
+    
+    /* Prepare write back to flash */
+    /* Update age */
+    ptTable->age++;
+    ptTable->crc32=BFLB_Soft_CRC32((uint8_t*)ptTable,sizeof(PtTable_Config)-4);
+    
+    /* Update entries CRC */
+    entriesLen=ptTable->entryCnt*sizeof(PtTable_Entry_Config);
+    pCrc32=(uint32_t *)((uint32_t)ptEntries+entriesLen);
+    *pCrc32=BFLB_Soft_CRC32((uint8_t *)&ptEntries[0],entriesLen);
+    
+    /* Write back to flash */
+    /* Erase flash first */
+    ret=bl_flash_erase(writeAddr,sizeof(PtTable_Config)+entriesLen+4);
+    if(ret!=SUCCESS){
+        //MSG_ERR("Flash Erase error\r\n");
+        return PT_ERROR_FALSH_WRITE;
+    }
+    /* Write flash */
+    ret=bl_flash_write(writeAddr,(uint8_t *)ptStuff,sizeof(PtTable_Stuff_Config));
+    if(ret!=SUCCESS){
+        //MSG_ERR("Flash Write error\r\n");
+        return PT_ERROR_FALSH_WRITE;
+    }
+
+    return PT_ERROR_SUCCESS;
+}
+
+PtTable_Error_Type PtTable_Get_Active_Entries(PtTable_Stuff_Config *ptStuff,
+                                            PtTable_Entry_Type type,
+                                            PtTable_Entry_Config *ptEntry)
+{
+    uint32_t i=0;
+    
+    if(ptStuff==NULL||ptEntry==NULL){
+        return PT_ERROR_PARAMETER;
+    }
+    for (i=0; i < ptStuff->ptTable.entryCnt; i++) {
+        if (ptStuff->ptEntries[i].type == type){
+            memcpy(ptEntry,&ptStuff->ptEntries[i],sizeof(PtTable_Entry_Config));
+            return PT_ERROR_SUCCESS;
+        }
+    }
+    return PT_ERROR_ENTRY_NOT_FOUND;
+}
+
+PtTable_Error_Type PtTable_Get_Active_Entries_By_Name(PtTable_Stuff_Config *ptStuff,
+                                                    uint8_t *name,
+                                                    PtTable_Entry_Config *ptEntry)
+{
+    uint32_t i=0;
+    uint32_t len=strlen((char *)name);
+
+    if(ptStuff==NULL||ptEntry==NULL){
+        return PT_ERROR_PARAMETER;
+    }   
+    for (i=0; i < ptStuff->ptTable.entryCnt; i++) {
+        if (strlen((char *)ptStuff->ptEntries[i].name) == len &&
+        memcmp((char *)ptStuff->ptEntries[i].name,(char *)name,len) == 0){ 
+        //BL602_MemCpy_Fast(ptEntry,&ptStuff->ptEntries[i],sizeof(PtTable_Entry_Config));
+        /*FIXME :need fast memory copy*/
+        memcpy(ptEntry,&ptStuff->ptEntries[i],sizeof(PtTable_Entry_Config));
+        return PT_ERROR_SUCCESS;
+        }   
+    }   
+    return PT_ERROR_ENTRY_NOT_FOUND;
+}
+

+ 197 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_boot2.h

@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __BL606_PARTITION_H__
+#define __BL606_PARTITION_H__
+
+#include <stdint.h>
+
+//FIXME no BL808/BL606p header file including is Allowed here
+#ifdef BL808
+#include <bl808_common.h>
+#include <bl808_sflash.h>
+#elif defined(BL606P)
+#include <bl606p_common.h>
+#include <bl606p_sflash.h>
+#else
+#error "Use CHIP BL808/BL606P for this module"
+#endif
+
+/** @addtogroup  BL606_Common_Driver
+ *  @{
+ */
+
+/** @addtogroup  PARTITION
+ *  @{
+ */
+
+/** @defgroup  PARTITION_Public_Types
+ *  @{
+ */
+
+/**
+ *  @brief Partition table error type definition
+ */
+typedef enum {
+    PT_ERROR_SUCCESS,                       /*!< Partition table error type:success */
+    PT_ERROR_TABLE_NOT_VALID,               /*!< Partition table error type:entry not found */
+    PT_ERROR_ENTRY_NOT_FOUND,               /*!< Partition table error type:entry not found */
+    PT_ERROR_ENTRY_UPDATE_FAIL,             /*!< Partition table error type:entry update fail */
+    PT_ERROR_CRC32,                         /*!< Partition table error type:crc32 error */
+    PT_ERROR_PARAMETER,                     /*!< Partition table error type:input parameter error */
+    PT_ERROR_FALSH_READ,                    /*!< Partition table error type:flash read error */
+    PT_ERROR_FALSH_WRITE,                   /*!< Partition table error type:flash write error */
+    PT_ERROR_FALSH_ERASE,                   /*!< Partition table error type:flash erase error */
+}PtTable_Error_Type;
+
+/**
+ *  @brief Partition id type definition
+ */
+typedef enum {
+    PT_TABLE_ID_0,                          /*!< Partition table ID 0 */
+    PT_TABLE_ID_1,                          /*!< Partition table ID 1 */
+    PT_TABLE_ID_INVALID,                    /*!< Partition table ID invalid */
+}PtTable_ID_Type;
+
+/**
+ *  @brief Partition id type definition
+ */
+typedef enum {
+    PT_ENTRY_FW_CPU0,                       /*!< Partition entry type:CPU0 firmware */
+    PT_ENTRY_FW_CPU1,                       /*!< Partition entry type:CPU1 firmware */
+    PT_ENTRY_MAX=16,                        /*!< Partition entry type:Max */
+}PtTable_Entry_Type;
+
+/**
+ *  @brief Partition table config definition
+ */
+typedef struct {
+    uint32_t magicCode;                     /*!< Partition table magic code */
+    uint16_t version;                       /*!< Partition table verdion */
+    uint16_t entryCnt;                      /*!< Partition table entry count */
+    uint32_t age;                           /*!< Partition table age */
+    uint32_t crc32;                         /*!< Partition table CRC32 value */
+}PtTable_Config;
+
+/**
+ *  @brief Partition table entry config definition
+ */
+typedef struct {
+    uint8_t type;                           /*!< Partition entry type */
+    uint8_t device;                         /*!< Partition entry device */
+    uint8_t activeIndex;                    /*!< Partition entry active index */
+    uint8_t name[9];                        /*!< Partition entry name */
+    uint32_t Address[2];                    /*!< Partition entry start address */
+    uint32_t maxLen[2];                     /*!< Partition entry max length */
+    uint32_t len;                           /*!< Partition entry length */
+    uint32_t age;                           /*!< Partition entry age */
+}PtTable_Entry_Config;
+
+/**
+ *  @brief Partition table stuff config definition
+ */
+typedef struct {
+    PtTable_Config ptTable;                 /*!< Partition table */
+    PtTable_Entry_Config ptEntries[PT_ENTRY_MAX];    /*!< Partition entries */
+    uint32_t crc32;                         /*!< Partition entries crc32 */
+}PtTable_Stuff_Config;
+
+/*@} end of group PARTITION_Public_Types */
+
+/** @defgroup  PARTITION_Public_Constants
+ *  @{
+ */
+
+/** @defgroup  PTTABLE_ERROR_TYPE
+ *  @{
+ */
+#define IS_PTTABLE_ERROR_TYPE(type)                      (((type) == PT_ERROR_SUCCESS) || \
+                                                          ((type) == PT_ERROR_TABLE_NOT_VALID) || \
+                                                          ((type) == PT_ERROR_ENTRY_NOT_FOUND) || \
+                                                          ((type) == PT_ERROR_ENTRY_UPDATE_FAIL) || \
+                                                          ((type) == PT_ERROR_CRC32) || \
+                                                          ((type) == PT_ERROR_PARAMETER) || \
+                                                          ((type) == PT_ERROR_FALSH_READ) || \
+                                                          ((type) == PT_ERROR_FALSH_WRITE) || \
+                                                          ((type) == PT_ERROR_FALSH_ERASE))
+
+/** @defgroup  PTTABLE_ID_TYPE
+ *  @{
+ */
+#define IS_PTTABLE_ID_TYPE(type)                         (((type) == PT_TABLE_ID_0) || \
+                                                          ((type) == PT_TABLE_ID_1) || \
+                                                          ((type) == PT_TABLE_ID_INVALID))
+
+/** @defgroup  PTTABLE_ENTRY_TYPE
+ *  @{
+ */
+#define IS_PTTABLE_ENTRY_TYPE(type)                      (((type) == PT_ENTRY_FW_CPU0) || \
+                                                          ((type) == PT_ENTRY_FW_CPU1) || \
+                                                          ((type) == PT_ENTRY_MAX))
+
+/*@} end of group PARTITION_Public_Constants */
+
+/** @defgroup  PARTITION_Public_Macros
+ *  @{
+ */
+#define BFLB_PT_TABLE0_ADDRESS                               0xE000
+#define BFLB_PT_TABLE1_ADDRESS                               0xF000
+#define BFLB_PT_MAGIC_CODE                                   0x54504642
+typedef BL_Err_Type (*pPtTable_Flash_Erase)(uint32_t startaddr,uint32_t endaddr);
+typedef BL_Err_Type (*pPtTable_Flash_Write)(uint32_t addr,uint8_t *data, uint32_t len);
+typedef BL_Err_Type (*pPtTable_Flash_Read)(uint32_t addr,uint8_t *data, uint32_t len);
+
+/*@} end of group PARTITION_Public_Macros */
+
+/** @defgroup  PARTITION_Public_Functions
+ *  @{
+ */
+void PtTable_Set_Flash_Operation(pPtTable_Flash_Erase erase,pPtTable_Flash_Write write);
+PtTable_ID_Type PtTable_Get_Active_Partition(const SPI_Flash_Cfg_Type *pFlashCfg,
+                                             PtTable_Stuff_Config ptStuff[2]);
+PtTable_Error_Type PtTable_Get_Active_Entries(PtTable_Stuff_Config *ptStuff,
+PtTable_Entry_Type type,
+                                              PtTable_Entry_Config *ptEntry);
+PtTable_Error_Type PtTable_Update_Entry(const SPI_Flash_Cfg_Type *pFlashCfg,
+PtTable_ID_Type targetTableID,
+                                        PtTable_Stuff_Config *ptStuff,
+PtTable_Entry_Config *ptEntry);
+PtTable_Error_Type PtTable_Create(const SPI_Flash_Cfg_Type *pFlashCfg,PtTable_ID_Type ptID);
+PtTable_Error_Type PtTable_Get_Active_Entries_By_Name(PtTable_Stuff_Config *ptStuff,                                                             
+                                                    uint8_t *name,                                                     
+                                                    PtTable_Entry_Config *ptEntry);
+
+/*@} end of group PARTITION_Public_Functions */
+
+/*@} end of group PARTITION */
+
+/*@} end of group BL606_Common_Driver */
+
+#endif /* __BL606_PARTITION_H__ */

+ 79 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_cam.c

@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <string.h>
+#include <stdio.h>
+#include <bl808_mjpeg.h>
+#include "bl_cam.h"
+
+#define MJPEG_DEFAULT_ADDR      0x80400000
+
+int bl_cam_mjpeg_buffer_info_get(uint32_t *mjpeg_addr, uint32_t *mjpeg_size)
+{
+    int ret = 0;
+    uint32_t tmpVal;
+
+    *mjpeg_addr = BL_RD_REG(MJPEG_BASE, MJPEG_JPEG_FRAME_ADDR);
+    if (*mjpeg_addr == MJPEG_DEFAULT_ADDR) {
+        *mjpeg_addr = 0;
+        ret = -1;
+        goto exit;
+    }
+
+    tmpVal = BL_RD_REG(MJPEG_BASE, MJPEG_CONTROL_1);
+    tmpVal = BL_GET_REG_BITS_VAL(tmpVal, MJPEG_REG_W_XLEN);
+    /*get memory brust size 0 sigle; 1 INCR4; 2 INCR8; 3 INCR16*/
+    *mjpeg_size = BL_RD_REG(MJPEG_BASE, MJPEG_JPEG_STORE_MEMORY);
+    *mjpeg_size = *mjpeg_size << (3 + tmpVal + (tmpVal > 0 ? 1 : 0));
+
+exit:
+    return ret;
+}
+
+int bl_cam_mjpeg_get(uint8_t **ptr, uint32_t *len)
+{
+    int ret = 0;
+    MJPEG_Frame_Info mjpeg_info;
+    MJPEG_Get_Frame_Info(&mjpeg_info);
+
+    if (mjpeg_info.validFrames > 0) {
+        *ptr = (uint8_t *)(uintptr_t)mjpeg_info.curFrameAddr;
+        *len = mjpeg_info.curFrameBytes;
+    } else {
+        ret = -1;
+    }
+    return ret;
+}
+
+int bl_cam_mjpeg_pop(void)
+{
+    MJPEG_Pop_Frame();
+    return 0;
+}
+

+ 35 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_cam.h

@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __BL_CAM_H__
+#define __BL_CAM_H__
+int bl_cam_mjpeg_get(uint8_t **ptr, uint32_t *len);
+int bl_cam_mjpeg_pop();
+int bl_cam_mjpeg_buffer_info_get(uint32_t *mjpeg_addr, uint32_t *mjpeg_size);
+#endif

+ 188 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_chip.c

@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdint.h>
+#include <string.h>
+
+#include "bl_chip.h"
+
+static unsigned long _risc_isa_info(void)
+{
+    volatile unsigned long misa = 0;
+
+    __asm volatile( "csrr %0, misa" : "=r"( misa ) );
+
+    return misa;
+}
+
+
+int bl_chip_info(char *info)
+{
+    unsigned long misa;
+    int i;
+    i = sizeof(misa) * 8 - 2; // MXL field pos
+
+    misa = _risc_isa_info();
+
+    /*Get base ISA*/
+    i = (misa >> i);
+    switch (i) {
+        case 1:
+        {
+            memcpy(info, "RV32", 4);
+            info += 4;
+        }
+        break;
+        case 2:
+        {
+            memcpy(info, "RV64", 4);
+            info += 4;
+        }
+        break;
+        case 3:
+        {
+            memcpy(info, "RV128", 5);
+            info += 5;
+        }
+        break;
+        default:
+        {
+            memcpy(info, "RVxx", 4);
+            info += 4;
+        }
+        break;
+    }
+
+    /*add switch*/
+    *(info++) = '-';
+
+    /*add feature set*/
+    for (i = 0; i < 26; i++) {
+        if (misa & (1 << i)) {
+            /*Feature bit is set*/
+            *(info++) = ('A' + i);
+        }
+    }
+    *info = '\0';
+
+    return 0;
+}
+
+static const char bannder_shadow_bl602[] = {
+  0xe2, 0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2, 0x96, 0x88,
+  0xe2, 0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2, 0x95, 0x97, 0x20, 0xe2, 0x96,
+  0x88, 0xe2, 0x96, 0x88, 0xe2, 0x95, 0x97, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0xe2, 0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2, 0x96,
+  0x88, 0xe2, 0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2, 0x95, 0x97, 0x20, 0x20,
+  0xe2, 0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2, 0x96, 0x88,
+  0xe2, 0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2, 0x95, 0x97, 0x20, 0xe2, 0x96,
+  0x88, 0xe2, 0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2, 0x96,
+  0x88, 0xe2, 0x96, 0x88, 0xe2, 0x95, 0x97, 0x0a, 0x0d, 0xe2, 0x96, 0x88, 0xe2,
+  0x96, 0x88, 0xe2, 0x95, 0x94, 0xe2, 0x95, 0x90, 0xe2, 0x95, 0x90, 0xe2,
+  0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2, 0x95, 0x97, 0xe2, 0x96, 0x88, 0xe2,
+  0x96, 0x88, 0xe2, 0x95, 0x91, 0x20, 0x20, 0x20, 0x20, 0x20, 0xe2, 0x96,
+  0x88, 0xe2, 0x96, 0x88, 0xe2, 0x95, 0x94, 0xe2, 0x95, 0x90, 0xe2, 0x95,
+  0x90, 0xe2, 0x95, 0x90, 0xe2, 0x95, 0x90, 0xe2, 0x95, 0x9d, 0x20, 0xe2,
+  0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2, 0x95, 0x94, 0xe2, 0x95, 0x90, 0xe2,
+  0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2,
+  0x95, 0x97, 0xe2, 0x95, 0x9a, 0xe2, 0x95, 0x90, 0xe2, 0x95, 0x90, 0xe2,
+  0x95, 0x90, 0xe2, 0x95, 0x90, 0xe2, 0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2,
+  0x95, 0x97, 0x0a, 0x0d, 0xe2, 0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2, 0x96, 0x88,
+  0xe2, 0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2, 0x95, 0x94,
+  0xe2, 0x95, 0x9d, 0xe2, 0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2, 0x95, 0x91,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0xe2, 0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2,
+  0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2,
+  0x96, 0x88, 0xe2, 0x95, 0x97, 0x20, 0xe2, 0x96, 0x88, 0xe2, 0x96, 0x88,
+  0xe2, 0x95, 0x91, 0xe2, 0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2, 0x95, 0x94,
+  0xe2, 0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2, 0x95, 0x91, 0x20, 0xe2, 0x96,
+  0x88, 0xe2, 0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2, 0x96,
+  0x88, 0xe2, 0x95, 0x94, 0xe2, 0x95, 0x9d, 0x0a, 0x0d, 0xe2, 0x96, 0x88, 0xe2,
+  0x96, 0x88, 0xe2, 0x95, 0x94, 0xe2, 0x95, 0x90, 0xe2, 0x95, 0x90, 0xe2,
+  0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2, 0x95, 0x97, 0xe2, 0x96, 0x88, 0xe2,
+  0x96, 0x88, 0xe2, 0x95, 0x91, 0x20, 0x20, 0x20, 0x20, 0x20, 0xe2, 0x96,
+  0x88, 0xe2, 0x96, 0x88, 0xe2, 0x95, 0x94, 0xe2, 0x95, 0x90, 0xe2, 0x95,
+  0x90, 0xe2, 0x95, 0x90, 0xe2, 0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2, 0x95,
+  0x97, 0xe2, 0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2, 0x96,
+  0x88, 0xe2, 0x95, 0x94, 0xe2, 0x95, 0x9d, 0xe2, 0x96, 0x88, 0xe2, 0x96,
+  0x88, 0xe2, 0x95, 0x91, 0xe2, 0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2, 0x95,
+  0x94, 0xe2, 0x95, 0x90, 0xe2, 0x95, 0x90, 0xe2, 0x95, 0x90, 0xe2, 0x95,
+  0x9d, 0x0a, 0x0d, 0xe2, 0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2,
+  0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2, 0x95, 0x94, 0xe2,
+  0x95, 0x9d, 0xe2, 0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2,
+  0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2,
+  0x95, 0x97, 0xe2, 0x95, 0x9a, 0xe2, 0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2,
+  0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2,
+  0x95, 0x94, 0xe2, 0x95, 0x9d, 0xe2, 0x95, 0x9a, 0xe2, 0x96, 0x88, 0xe2,
+  0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2,
+  0x96, 0x88, 0xe2, 0x95, 0x94, 0xe2, 0x95, 0x9d, 0xe2, 0x96, 0x88, 0xe2,
+  0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2,
+  0x96, 0x88, 0xe2, 0x96, 0x88, 0xe2, 0x95, 0x97, 0x0a, 0x0d, 0xe2, 0x95, 0x9a,
+  0xe2, 0x95, 0x90, 0xe2, 0x95, 0x90, 0xe2, 0x95, 0x90, 0xe2, 0x95, 0x90,
+  0xe2, 0x95, 0x90, 0xe2, 0x95, 0x9d, 0x20, 0xe2, 0x95, 0x9a, 0xe2, 0x95,
+  0x90, 0xe2, 0x95, 0x90, 0xe2, 0x95, 0x90, 0xe2, 0x95, 0x90, 0xe2, 0x95,
+  0x90, 0xe2, 0x95, 0x90, 0xe2, 0x95, 0x9d, 0x20, 0xe2, 0x95, 0x9a, 0xe2,
+  0x95, 0x90, 0xe2, 0x95, 0x90, 0xe2, 0x95, 0x90, 0xe2, 0x95, 0x90, 0xe2,
+  0x95, 0x90, 0xe2, 0x95, 0x9d, 0x20, 0x20, 0xe2, 0x95, 0x9a, 0xe2, 0x95,
+  0x90, 0xe2, 0x95, 0x90, 0xe2, 0x95, 0x90, 0xe2, 0x95, 0x90, 0xe2, 0x95,
+  0x90, 0xe2, 0x95, 0x9d, 0x20, 0xe2, 0x95, 0x9a, 0xe2, 0x95, 0x90, 0xe2,
+  0x95, 0x90, 0xe2, 0x95, 0x90, 0xe2, 0x95, 0x90, 0xe2, 0x95, 0x90, 0xe2,
+  0x95, 0x90, 0xe2, 0x95, 0x9d, 0x0a, 0x0d, 0x00
+};
+
+int bl_chip_banner(const char **banner)
+{
+    *banner = bannder_shadow_bl602;
+    return 0;
+}
+
+int bl_chip_memory_ram(int *num, unsigned int addr[], unsigned int size[], char desc[][6])
+{
+    return -1;
+#if 0
+    if (*num < 3) {
+        /*only one block memory*/
+        return -1;
+    }
+    *num = 3;
+
+extern uint8_t _ld_ram_size0, _ld_ram_addr0;
+extern uint8_t _ld_ram_size1, _ld_ram_addr1;
+extern uint8_t _ld_ram_size2, _ld_ram_addr2;
+    addr[0] = (unsigned int)&_ld_ram_addr0;
+    size[0] = (unsigned int)&_ld_ram_size0;
+    strcpy(desc[0], "flash");
+    addr[1] = (unsigned int)&_ld_ram_addr1;
+    size[1] = (unsigned int)&_ld_ram_size1;
+    strcpy(desc[1], "tcm");
+    addr[2] = (unsigned int)&_ld_ram_addr2;
+    size[2] = (unsigned int)&_ld_ram_size2;
+    strcpy(desc[2], "wifi");
+    return 0;
+#endif
+}

+ 35 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_chip.h

@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __BL_CHIP_H__
+#define __BL_CHIP_H__
+int bl_chip_info(char *info);
+int bl_chip_banner(const char **banner);
+int bl_chip_memory_ram(int *num, unsigned int addr[], unsigned int size[], char desc[][6]);
+#endif

+ 127 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_efuse.c

@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "bl_efuse.h"
+#ifdef BL808
+#include <bl808_ef_ctrl.h>
+#include "bl808_mfg_media.h"
+#include "bl808_glb.h"
+#endif
+
+int bl_efuse_read_mac(uint8_t mac[6])
+{
+    EF_Ctrl_Read_MAC_Address(mac);
+    return 0;
+}
+
+int bl_efuse_read_mac_factory(uint8_t mac[6])
+{
+ //   if (0 == mfg_media_read_macaddr(mac, 1)) {
+   //     return 0;
+   //zys }
+    return -1;
+}
+
+int bl_efuse_read_capcode(uint8_t *capcode)
+{
+//    if (0 == mfg_media_read_xtal_capcode(capcode, 1)) {
+  //      return 0;
+   //zys  }
+    return -1;
+}
+
+int bl_efuse_read_pwroft(int8_t poweroffset[14])
+{
+  //  if (0 == mfg_media_read_poweroffset(poweroffset, 1)) {
+    //    return 0;
+    //}
+    return -1;
+}
+
+int bl_efuse_ctrl_program_R0(uint32_t index, uint32_t *data, uint32_t len)
+{
+    uint8_t hdiv=0, bdiv=0;
+    HBN_MCU_ROOT_CLK_Type rtClk=(HBN_MCU_ROOT_CLK_Type)HBN_Get_MCU_Root_CLK_Sel();
+
+//    bdiv=GLB_Get_BCLK_Div();
+//    hdiv=GLB_Get_HCLK_Div();
+    hdiv = BL_GET_REG_BITS_VAL(BL_RD_REG(GLB_BASE, GLB_SYS_CFG0), GLB_REG_HCLK_DIV);
+    bdiv = BL_GET_REG_BITS_VAL(BL_RD_REG(GLB_BASE, GLB_SYS_CFG0), GLB_REG_BCLK_DIV);
+
+    HBN_Set_MCU_Root_CLK_Sel(HBN_MCU_ROOT_CLK_XCLK);
+    
+    EF_Ctrl_Program_Direct_R0(index, data, len);
+    
+    GLB_Set_System_CLK_Div(hdiv, bdiv);
+    HBN_Set_MCU_Root_CLK_Sel(rtClk);
+
+    return 0;
+}
+
+int bl_efuse_ctrl_read_R0(uint32_t index, uint32_t *data, uint32_t len)
+{
+    uint8_t hdiv=0, bdiv=0;
+    HBN_MCU_ROOT_CLK_Type rtClk=(HBN_MCU_ROOT_CLK_Type)HBN_Get_MCU_Root_CLK_Sel();
+
+//    bdiv=GLB_Get_BCLK_Div();
+//    hdiv=GLB_Get_HCLK_Div();
+    hdiv = BL_GET_REG_BITS_VAL(BL_RD_REG(GLB_BASE, GLB_SYS_CFG0), GLB_REG_HCLK_DIV);
+    bdiv = BL_GET_REG_BITS_VAL(BL_RD_REG(GLB_BASE, GLB_SYS_CFG0), GLB_REG_BCLK_DIV);
+
+
+    HBN_Set_MCU_Root_CLK_Sel(HBN_MCU_ROOT_CLK_XCLK);
+    
+    EF_Ctrl_Read_Direct_R0(index, data, len);
+    
+    GLB_Set_System_CLK_Div(hdiv, bdiv);
+    HBN_Set_MCU_Root_CLK_Sel(rtClk);
+
+    return 0;
+}
+
+int bl_efuse_read_mac_opt(uint8_t slot, uint8_t mac[6], uint8_t reload)
+{
+    uint8_t hdiv=0, bdiv=0;
+    HBN_MCU_ROOT_CLK_Type rtClk=(HBN_MCU_ROOT_CLK_Type)HBN_Get_MCU_Root_CLK_Sel();
+
+//    bdiv=GLB_Get_BCLK_Div();
+//    hdiv=GLB_Get_HCLK_Div();
+    hdiv = BL_GET_REG_BITS_VAL(BL_RD_REG(GLB_BASE, GLB_SYS_CFG0), GLB_REG_HCLK_DIV);
+    bdiv = BL_GET_REG_BITS_VAL(BL_RD_REG(GLB_BASE, GLB_SYS_CFG0), GLB_REG_BCLK_DIV);
+
+    HBN_Set_MCU_Root_CLK_Sel(HBN_MCU_ROOT_CLK_XCLK);
+    
+//    EF_Ctrl_Read_MAC_Address_Opt(slot, mac, reload); 
+    EF_Ctrl_Read_MAC_Address_Raw(mac);
+
+    GLB_Set_System_CLK_Div(hdiv, bdiv);
+    HBN_Set_MCU_Root_CLK_Sel(rtClk);
+
+    return 0;
+}

+ 40 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_efuse.h

@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __BL_EFUSE_H__
+#define __BL_EFUSE_H__
+#include <stdint.h>
+int bl_efuse_read_mac(uint8_t mac[6]);
+int bl_efuse_read_mac_factory(uint8_t mac[6]);
+int bl_efuse_read_capcode(uint8_t *capcode);
+int bl_efuse_read_pwroft(int8_t poweroffset[14]);
+int bl_efuse_ctrl_program_R0(uint32_t index, uint32_t *data, uint32_t len);
+int bl_efuse_ctrl_read_R0(uint32_t index, uint32_t *data, uint32_t len);
+int bl_efuse_read_mac_opt(uint8_t slot, uint8_t mac[6], uint8_t reload);
+#endif

+ 746 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_ethernetif.c

@@ -0,0 +1,746 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "lwip/opt.h"
+#include "lwip/timeouts.h"
+#include "lwip/netif.h"
+#include "lwip/err.h"
+#define LWIP_DHCP 1
+#if LWIP_DHCP
+#include "lwip/dhcp.h"
+#endif
+#include "netif/etharp.h"
+#include "bl_ethernetif.h"
+#include <string.h>
+#include "hal_emac.h"
+#include <FreeRTOS.h>
+#include "semphr.h"
+#if CTX_TYPE
+#include <utils_list.h>
+#endif
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Network interface name */
+#define IFNAME0 'b'
+#define IFNAME1 'l'
+
+#define ETH_DMA_TRANSMIT_TIMEOUT (20U)
+
+#define BL702_EMAC  0
+#define EMAC_OUTPUT BL702_EMAC
+
+#if LWIP_DHCP
+#define MAX_DHCP_TRIES 4
+uint32_t DHCPfineTimer = 0;
+uint8_t DHCP_state = DHCP_OFF;
+// #else
+/*Static IP ADDRESS: IP_ADDR0.IP_ADDR1.IP_ADDR2.IP_ADDR3 */
+#define IP_ADDR0      (uint8_t)192
+#define IP_ADDR1      (uint8_t)168
+#define IP_ADDR2      (uint8_t)10
+#define IP_ADDR3      (uint8_t)221
+
+/*NETMASK*/
+#define NETMASK_ADDR0 (uint8_t)255
+#define NETMASK_ADDR1 (uint8_t)255
+#define NETMASK_ADDR2 (uint8_t)255
+#define NETMASK_ADDR3 (uint8_t)0
+
+/*Gateway Address*/
+#define GW_ADDR0      (uint8_t)192
+#define GW_ADDR1      (uint8_t)168
+#define GW_ADDR2      (uint8_t)10
+#define GW_ADDR3      (uint8_t)1
+#endif
+
+#if CTX_TYPE
+extern EMAC_Handle_Type *thiz;
+eth_context *ctx = NULL;
+TaskHandle_t DequeueTaskHandle;
+TaskHandle_t OutputTaskHandle;
+#endif
+/* Private function prototypes -----------------------------------------------*/
+void pbuf_free_custom(struct pbuf *p);
+void ethernetif_input(struct netif *netif);
+SemaphoreHandle_t emac_rx_sem = NULL;
+static StackType_t emac_rx_stack[256];
+static StaticTask_t emac_rx_handle;
+#if LWIP_DHCP
+static StackType_t emac_dhcp_stack[256];
+static StaticTask_t emac_dhcp_handle;
+#endif
+static uint8_t emac_rx_buffer[ETH_RX_BUFFER_SIZE] __attribute__((aligned(16))) = { 0 };
+
+LWIP_MEMPOOL_DECLARE(RX_POOL, 10, sizeof(struct pbuf_custom), "Zero-copy RX PBUF pool");
+
+/* Private functions ---------------------------------------------------------*/
+/*******************************************************************************
+                       LL Driver Interface ( LwIP stack --> ETH)
+*******************************************************************************/
+/**
+  * @brief In this function, the hardware should be initialized.
+  * Called from ethernetif_init().
+  *
+  * @param netif the already initialized lwip network interface structure
+  *        for this ethernetif
+  */
+extern void emac_init_txrx_buffer(void);
+extern int emac_phy_init(emac_phy_cfg_t *cfg);
+
+/* For emac tx and rx,we put here to make controlling it's size easy */
+#define ETH_RXBUFNB 6
+#define ETH_TXBUFNB 4
+#define ATTR_NOCACHE_RAM_SECTION   __attribute__((section(".nocache_ram")))
+ATTR_NOCACHE_RAM_SECTION ATTR_EALIGN(4) uint8_t ethRxBuff[ETH_RXBUFNB][ETH_RX_BUFFER_SIZE] ATTR_EALIGN(4) = { 0 }; /* Ethernet Receive Buffers */
+ATTR_NOCACHE_RAM_SECTION ATTR_EALIGN(4) uint8_t ethTxBuff[ETH_TXBUFNB][ETH_TX_BUFFER_SIZE] ATTR_EALIGN(4);         /* Ethernet Transmit Buffers */
+void emac_init_txrx_buffer(void)
+{
+#if CTX_TYPE
+    ctx = pvPortMalloc(sizeof(eth_context));
+    memset(ctx, 0, sizeof(eth_context));
+    utils_list_init(&ctx->unsent);
+#endif
+
+    emac_bd_init((uint8_t *)ethTxBuff, ETH_TXBUFNB, (uint8_t *)ethRxBuff, ETH_RXBUFNB);
+}
+void dhcp_thread(void const *argument);
+void low_level_init(struct netif *netif)
+{
+    int ret = 0;
+
+    emac_device_t emac_cfg = {
+        .mac_addr[0] = 0x18,
+        .mac_addr[1] = 0xB9,
+        .mac_addr[2] = 0x05,
+        .mac_addr[3] = 0x12,
+        .mac_addr[4] = 0x34,
+        .mac_addr[5] = 0x56,
+    };
+
+    /* set phy cfg */
+    emac_phy_cfg_t phy_cfg = {
+        .auto_negotiation = 1, /*!< Speed and mode auto negotiation */
+        .full_duplex = 0,      /*!< Duplex mode */
+        .speed = 0,            /*!< Speed mode */
+        .phy_address = 1,      /*!< PHY address */
+        .phy_id = 0x7c0f0,     /*!< PHY OUI, masked */
+        .phy_state = PHY_STATE_DOWN,
+    };
+
+    /* set MAC hardware address length */
+    netif->hwaddr_len = ETH_HWADDR_LEN;
+
+    /* set MAC hardware address */
+    netif->hwaddr[0] = emac_cfg.mac_addr[0];
+    netif->hwaddr[1] = emac_cfg.mac_addr[1];
+    netif->hwaddr[2] = emac_cfg.mac_addr[2];
+    netif->hwaddr[3] = emac_cfg.mac_addr[3];
+    netif->hwaddr[4] = emac_cfg.mac_addr[4];
+    netif->hwaddr[5] = emac_cfg.mac_addr[5];
+
+    /* maximum transfer unit */
+    netif->mtu = 1500;
+
+    /* emac init,configure ethernet peripheral (GPIOs, clocks, MAC, DMA) */
+    MSG("emac_init\r\n");
+    emac_init(&emac_cfg);
+
+    ret = emac_phy_init(&phy_cfg);
+    if (PHY_STATE_UP == phy_cfg.phy_state) {
+        MSG("PHY[%x] @%d ready on %dMbps, %s duplex\n\r", (int)phy_cfg.phy_id, (int)phy_cfg.phy_address,
+            (int)phy_cfg.speed,
+            phy_cfg.full_duplex ? "full" : "half");
+    } else {
+        MSG("PHY Init fail\n\r");
+        BL_CASE_FAIL;
+        while (1)
+            ;
+    }
+    emac_init_txrx_buffer();
+    emac_start();
+    // emac_start_tx();
+
+    /* device capabilities */
+    /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
+    netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;
+
+    /* Initialize the RX POOL */
+    LWIP_MEMPOOL_INIT(RX_POOL);
+
+    /* create a binary semaphore used for informing ethernetif of frame reception */
+    //vSemaphoreCreateBinary(emac_rx_sem);
+    emac_rx_sem = xSemaphoreCreateBinary();
+
+#if !CTX_TYPE
+    /* create the task that handles the ETH_MAC */
+    MSG("[OS] Starting emac rx task...\r\n");
+    xTaskCreateStatic(ethernetif_input, (char *)"emac_rx_task", sizeof(emac_rx_stack) / 4, netif, 16, emac_rx_stack, &emac_rx_handle);
+#endif
+#if LWIP_DHCP
+    MSG("[OS] Starting emac dhcp task...\r\n");
+    xTaskCreateStatic(dhcp_thread, (char *)"emac_dhcp_task", sizeof(emac_dhcp_stack) / 4, netif, 16, emac_dhcp_stack, &emac_dhcp_handle);
+#endif
+
+    if (ret == 0) {
+        MSG("[OS] %s Netif is up\r\n", netif->name);
+        netif_set_up(netif);
+        netif_set_link_up(netif);
+    }
+}
+
+void emac_tx_error_callback_app()
+{
+    MSG("EMAC tx error callback\r\n");
+}
+
+void emac_rx_error_callback_app()
+{
+    MSG("EMAC rx error callback\r\n");
+    // MSG("EMAC tx bd num 0x%x\r\n", BL_RD_WORD(0x4000D020));
+    // MSG("EMAC rx bd description0 0x%x\r\n", BL_RD_WORD(0x4000D400 + ((5 + 5) * 8)));
+    // MSG("EMAC rx bd description1 0x%x\r\n", BL_RD_WORD(0x4000D400 + ((5 + 5) * 8) + 0x4));
+}
+/**
+  * @brief This function should do the actual transmission of the packet. The packet is
+  * contained in the pbuf that is passed to the function. This pbuf
+  * might be chained.
+  *
+  * @param netif the lwip network interface structure for this ethernetif
+  * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
+  * @return ERR_OK if the packet could be sent
+  *         an err_t value if the packet couldn't be sent
+  *
+  * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
+  *       strange results. You might consider waiting for space in the DMA queue
+  *       to become available since the stack doesn't retry to send a packet
+  *       dropped because of memory failure (except for the TCP timers).
+  */
+
+static unsigned char emac_send_buf[1514];
+static err_t low_level_output(struct netif *netif, struct pbuf *p)
+{
+#if CTX_TYPE
+    struct unsent_item *item;
+
+    if (pbuf_header(p, PBUF_LINK_ENCAPSULATION_HLEN)) {
+        printf("[TX] Reserve room failed for header\r\n");
+        return ERR_IF;
+    }
+    item = (struct unsent_item *)(((uintptr_t)(p->payload + 3))&(~3));
+    item->p = p;
+
+    pbuf_ref(p);
+    __disable_irq();
+    utils_list_push_back(&ctx->unsent, (struct utils_list_hdr *)&(item->hdr));
+    ctx->unsent_num++;
+    __enable_irq();
+    xTaskNotify(DequeueTaskHandle, 0x01, eSetBits);
+
+    return ERR_OK;
+#else
+    err_t errval = ERR_OK;
+    struct pbuf *q;
+
+    if (!emac_bd_fragment_support()){
+
+        uint32_t byteslefttocopy = 0;
+        // uint32_t payloadoffset = 0;
+        // uint32_t bufferoffset = 0;
+        uint32_t framelength = 0;
+        uint32_t flags = (EMAC_NORMAL_PACKET);
+
+        for (q = p; q != NULL; q = q->next) {
+            // MSG("p->tot_len:%d,q->len:%d, q->next:%d,f:%d\r\n", q->tot_len, q->len, q->next, framelength);
+
+            byteslefttocopy = q->len;
+            // payloadoffset = 0;
+
+            // check is copy data is larger than emac tx buf
+            while ((byteslefttocopy + framelength) > ETH_TX_BUFFER_SIZE) {
+                // copy data to tx buf
+                MSG("tx buf is too larger!\r\n");
+                flags = EMAC_FRAGMENT_PACKET;
+                // ARCH_MemCpy_Fast(&emac_send_buf[framelength + bufferoffset], q->payload + payloadoffset, (ETH_TX_BUFFER_SIZE - bufferoffset));
+            }
+            ARCH_MemCpy_Fast(&emac_send_buf[framelength], q->payload, byteslefttocopy);
+            // bufferoffset = bufferoffset + byteslefttocopy;
+            framelength = framelength + byteslefttocopy;
+        }
+
+        if (0 != emac_bd_tx_enqueue(flags, framelength, emac_send_buf)) {
+            MSG("emac_bd_tx_enqueue error!\r\n");
+            return ERR_IF;
+        }
+
+    }else{
+        for (q = p; q != NULL; q = q->next) {
+            //MSG("p->tot_len:%d,q->len:%d, q->next:%d\r\n", q->tot_len, q->len, q->next);
+            if (q->len == q->tot_len) {
+                if (0 != emac_bd_tx_enqueue(EMAC_NORMAL_PACKET, q->len, q->payload)) {
+                    MSG("emac_bd_tx_enqueue error!\r\n");
+                    return ERR_IF;
+                }
+            } else if (q->len < q->tot_len) {
+                if (0 != emac_bd_tx_enqueue(EMAC_FRAGMENT_PACKET, q->len, q->payload)) {
+                    MSG("emac_bd_tx_enqueue error!\r\n");
+                    return ERR_IF;
+                }
+            } else {
+                MSG("low_level_output error! Wrong packet!\r\n");
+            }
+        }
+    }
+
+    return errval;
+#endif
+}
+
+/**
+  * @brief Should allocate a pbuf and transfer the bytes of the incoming
+  * packet from the interface into the pbuf.
+  *
+  * @param netif the lwip network interface structure for this ethernetif
+  * @return a pbuf filled with the received packet (including MAC header)
+  *         NULL on memory error
+  */
+static struct pbuf *low_level_input(struct netif *netif)
+{
+#if CTX_TYPE
+    uint16_t pkt_len;
+    uint16_t max_len, min_len;
+    struct pbuf *h = NULL;
+    EMAC_BD_Desc_Type *bd;
+	  bd = &thiz->bd[thiz->rxIndexCPU];
+	  if(bd->C_S_L & EMAC_BD_FIELD_MSK(RX_E)){
+        // MSG("RX BD is empty\r\n");
+        h = NULL;
+	  } else {
+	      emac_get_fram_len(&max_len, &min_len);
+        pkt_len = (bd->C_S_L & EMAC_BD_FIELD_MSK(RX_LEN)) >> BD_RX_LEN_POS;
+        //check length
+        if (pkt_len > max_len) {
+            MSG("pkt is too huge %d\r\n", pkt_len);
+            return NULL;
+        }
+        if (bd->C_S_L & 0xFF) {
+            // MSG("RX bd %x\r\n", (int)bd->C_S_L & 0xFF);
+        }
+        if ((bd->C_S_L >>16) == ETH_MAX_BUFFER_SIZE) {
+            puts("Bug now...\r\n");
+        }
+
+        h = pbuf_alloc(PBUF_RAW, pkt_len, PBUF_POOL);
+        if (h) {
+            pbuf_take(h, bd->Buffer, pkt_len);
+        }
+        if ((++thiz->rxIndexCPU) > thiz->rxBuffLimit) {
+            /* wrap back */
+            thiz->rxIndexCPU = thiz->txBuffLimit + 1;
+            bd->C_S_L = (EMAC_BD_FIELD_MSK(RX_IRQ) | EMAC_BD_FIELD_MSK(RX_E) | (ETH_MAX_BUFFER_SIZE << 16) | EMAC_BD_FIELD_MSK(RX_WR));
+        } else {
+            bd->C_S_L = (EMAC_BD_FIELD_MSK(RX_IRQ) | EMAC_BD_FIELD_MSK(RX_E) | (ETH_MAX_BUFFER_SIZE << 16));
+        }
+    }
+    return h;
+#else
+    uint32_t rx_len = 0;
+    struct pbuf *p = NULL, *q;
+
+    emac_bd_rx_dequeue(-1, &rx_len, emac_rx_buffer);
+
+    if (rx_len <= 0) {
+        //MSG("Recv Null Data\r\n");
+        return NULL;
+    }
+
+    //MSG("Recv full Data\r\n");
+
+    p = pbuf_alloc(PBUF_RAW, rx_len, PBUF_POOL);
+
+    if (p != NULL) {
+        for (q = p; q != NULL; q = q->next) {
+            memcpy(q->payload, emac_rx_buffer + rx_len - q->tot_len, q->len);
+        }
+    }
+
+    return p;
+#endif
+}
+
+void emac_rx_done_callback_app(void)
+{
+    BaseType_t xHigherPriorityTaskWoken;
+
+    /* Is it time for vATask() to run? */
+    xHigherPriorityTaskWoken = pdFALSE;
+    //MSG("emac_rx_done_callback_app\r\n");
+    //low_level_input(NULL);
+    xSemaphoreGiveFromISR(emac_rx_sem, &xHigherPriorityTaskWoken);
+    /* If xHigherPriorityTaskWoken was set to true you
+    we should yield.  The actual macro used here is
+    port specific. */
+    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
+}
+
+#if CTX_TYPE
+void ethernetif_output(struct netif *netif)
+{
+    struct unsent_item *item;
+    struct pbuf *q, *p;
+    EMAC_BD_Desc_Type *bd;
+    int wrap_found, offset;
+
+    bd = &thiz->bd[thiz->txIndexCPU];
+    while (0 == (bd->C_S_L & EMAC_BD_FIELD_MSK(TX_RD)) && ctx->unsent_num) {
+
+        __disable_irq();
+        item = (struct unsent_item *)utils_list_pop_front(&ctx->unsent);
+        ctx->unsent_num--;
+        __enable_irq();
+
+        p = item->p;
+        p->len -= PBUF_LINK_ENCAPSULATION_HLEN;
+        p->tot_len -= PBUF_LINK_ENCAPSULATION_HLEN;
+        p->payload += PBUF_LINK_ENCAPSULATION_HLEN;
+        if ((++thiz->txIndexCPU) > thiz->txBuffLimit) {
+            /* wrap back */
+            thiz->txIndexCPU = 0;
+            wrap_found = 1;
+        } else {
+            wrap_found = 0;
+        }
+
+        offset = 0;
+        for (q = p; q != NULL; q = q->next) {
+            memcpy((uint8_t *)bd->Buffer + offset, (uint8_t*)q->payload, q->len);
+            offset += q->len;
+        }
+
+        bd->C_S_L = (wrap_found ? EMAC_BD_FIELD_MSK(TX_WR) : 0) | EMAC_TX_COMMON_FLAGS | p->tot_len << BD_TX_LEN_POS;
+        pbuf_free(p);
+        bd = &thiz->bd[thiz->txIndexCPU];
+    }
+}
+#endif
+
+/**
+  * @brief This function is the ethernetif_input task, it is processed when a packet
+  * is ready to be read from the interface. It uses the function low_level_input()
+  * that should handle the actual reception of bytes from the network
+  * interface. Then the type of the received packet is determined and
+  * the appropriate input function is called.
+  *
+  * @param netif the lwip network interface structure for this ethernetif
+  */
+void ethernetif_input(struct netif *netif)
+{
+    struct pbuf *p = NULL;
+
+#if CTX_TYPE
+    static unsigned int rx_counter;
+    err_t err = ERR_OK;
+    EMAC_BD_Desc_Type *bd;
+
+    /* move received packet into a new pbuf */
+    do {
+        p = low_level_input(netif);
+        bd = &thiz->bd[thiz->rxIndexCPU];
+
+        rx_counter++;
+        /* no packet could be read, silently ignore this */
+        if (p == NULL) return;
+
+        /* entry point to the LwIP stack */
+        err = netif->input(p, netif);
+
+        if (err != ERR_OK)
+        {
+            LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
+            pbuf_free(p);
+        }
+    } while (!(bd->C_S_L & EMAC_BD_FIELD_MSK(RX_E)));
+    return;
+#else
+    for (;;) {
+        if (xSemaphoreTake(emac_rx_sem, portMAX_DELAY) == pdTRUE) {
+            do {
+                p = low_level_input(netif);
+
+                if (p != NULL) {
+                    if (netif->input(p, netif) != ERR_OK) {
+                        pbuf_free(p);
+                    }
+                }
+            } while (p != NULL);
+        }
+    }
+#endif
+}
+
+#if CTX_TYPE
+void unsent_recv_task(void *pvParameters)
+{
+    struct netif *netif = (struct netif *)pvParameters;
+    uint32_t NotifyValue;
+    BaseType_t recv;
+    printf("unsent_recv_task.\r\n");
+    while(1) {
+        NotifyValue = 0;
+        recv = xTaskNotifyWait(0, ULONG_MAX, &NotifyValue, 200);
+        if (recv == pdTRUE) {
+            if (NotifyValue & (1 << 0)) {
+                ethernetif_output(netif);
+                emac_intmask(EMAC_INT_TX_DONE, UNMASK);
+            }
+            if (NotifyValue & (1 << 1)) {
+                ethernetif_input(netif);
+                emac_intmask(EMAC_INT_RX_DONE, UNMASK);
+            }
+        } else {
+            /*XXX only work when we has no EVENT. Maybe buggy here??*/
+            // _emac_phy_if_init();
+            // printf("no EVENT!\r\n");
+        }
+    }
+}
+#endif
+
+/**
+  * @brief Should be called at the beginning of the program to set up the
+  * network interface. It calls the function low_level_init() to do the
+  * actual setup of the hardware.
+  *
+  * This function should be passed as a parameter to netif_add().
+  *
+  * @param netif the lwip network interface structure for this ethernetif
+  * @return ERR_OK if the loopif is initialized
+  *         ERR_MEM if private data couldn't be allocated
+  *         any other err_t on error
+  */
+err_t ethernetif_init(struct netif *netif)
+{
+    LWIP_ASSERT("netif != NULL", (netif != NULL));
+
+#if LWIP_NETIF_HOSTNAME
+    /* Initialize interface hostname */
+    netif->hostname = "lwip";
+#endif /* LWIP_NETIF_HOSTNAME */
+
+    netif->name[0] = IFNAME0;
+    netif->name[1] = IFNAME1;
+    /* We directly use etharp_output() here to save a function call.
+     * You can instead declare your own function an call etharp_output()
+     * from it if you have to do some checks before sending (e.g. if link
+     * is available...) */
+    netif->output = etharp_output;
+    netif->linkoutput = low_level_output;
+
+    /* initialize the hardware */
+    low_level_init(netif);
+#if CTX_TYPE
+    xTaskCreate(unsent_recv_task, (const char *)"Ontput_Unsent_queue", 1024, netif, 29, &DequeueTaskHandle);
+#endif
+
+    return ERR_OK;
+}
+
+/**
+  * @brief  Custom Rx pbuf free callback
+  * @param  pbuf: pbuf to be freed
+  * @retval None
+  */
+void pbuf_free_custom(struct pbuf *p)
+{
+    struct pbuf_custom *custom_pbuf = (struct pbuf_custom *)p;
+    LWIP_MEMPOOL_FREE(RX_POOL, custom_pbuf);
+}
+
+static void ethernet_set_static_ip(struct netif *netif)
+{
+    ip_addr_t ipaddr;
+    ip_addr_t netmask;
+    ip_addr_t gw;
+
+    IP4_ADDR(&ipaddr, IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3);
+    IP4_ADDR(&netmask, NETMASK_ADDR0, NETMASK_ADDR1, NETMASK_ADDR2, NETMASK_ADDR3);
+    IP4_ADDR(&gw, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);
+    netif_set_addr(netif, ip_2_ip4(&ipaddr), ip_2_ip4(&netmask), ip_2_ip4(&gw));
+}
+
+/**
+  * @brief  Notify the User about the network interface config status
+  * @param  netif: the network interface
+  * @retval None
+  */
+void ethernet_link_status_updated(struct netif *netif)
+{
+    if (netif_is_link_up(netif)) {
+#if LWIP_DHCP
+        /* Update DHCP state machine */
+        DHCP_state = DHCP_START;
+        MSG("DHCP Start\r\n");
+#else
+        /* IP address default setting */
+        ethernet_set_static_ip(netif);
+        uint8_t iptxt[20];
+        sprintf((char *)iptxt, "%s", ip4addr_ntoa(netif_ip4_addr(netif)));
+        MSG("Static IP address: %s\r\n", iptxt);
+#endif
+    } else {
+#if LWIP_DHCP
+        /* Update DHCP state machine */
+        DHCP_state = DHCP_LINK_DOWN;
+#else
+        MSG("The network cable is not connected.\r\n");
+#endif /* LWIP_DHCP */
+    }
+}
+
+/**
+  * @brief
+  * @retval None
+  */
+void ethernet_link_check_state(struct netif *netif)
+{
+    emac_phy_status_t phy_state;
+
+    uint32_t linkchanged = 0;
+    // uint32_t speed = 0, duplex = 0;
+
+    phy_state = ethernet_phy_status_get();
+
+    if (netif_is_link_up(netif) && (phy_state <= EMAC_PHY_STAT_LINK_DOWN)) {
+        MSG("Link Down\n");
+        emac_stop();
+        netif_set_down(netif);
+        netif_set_link_down(netif);
+    } else if (!netif_is_link_up(netif) && (phy_state <= EMAC_PHY_STAT_LINK_DOWN)) {
+        MSG("Reinit\n");
+        emac_phy_init(NULL);
+    } else if (!netif_is_link_up(netif) && (phy_state > EMAC_PHY_STAT_LINK_UP)) {
+        // switch (phy_state) {
+        //     case EMAC_PHY_STAT_100MBITS_FULLDUPLEX:
+        //         duplex = 1;
+        //         speed = 100;
+        //         linkchanged = 1;
+        //         break;
+
+        //     case EMAC_PHY_STAT_100MBITS_HALFDUPLEX:
+        //         duplex = 0;
+        //         speed = 100;
+        //         linkchanged = 1;
+        //         break;
+
+        //     case EMAC_PHY_STAT_10MBITS_FULLDUPLEX:
+        //         duplex = 1;
+        //         speed = 10;
+        //         linkchanged = 1;
+        //         break;
+
+        //     case EMAC_PHY_STAT_10MBITS_HALFDUPLEX:
+        //         duplex = 0;
+        //         speed = 10;
+        //         linkchanged = 1;
+        //         break;
+
+        //     default:
+        //         break;
+        // }
+
+        if (linkchanged) {
+            /* Get MAC Config MAC */
+            //HAL_ETH_GetMACConfig(&EthHandle, &MACConf);
+            //MACConf.DuplexMode = duplex;
+            //MACConf.Speed = speed;
+            //HAL_ETH_SetMACConfig(&EthHandle, &MACConf);
+            //HAL_ETH_Start(&EthHandle);
+            netif_set_up(netif);
+            netif_set_link_up(netif);
+        }
+    }
+}
+
+#if LWIP_DHCP
+/**
+  * @brief  DHCP Process
+  * @param  argument: network interface
+  * @retval None
+  */
+void dhcp_thread(void const *argument)
+{
+    struct netif *netif = (struct netif *)argument;
+    ip_addr_t ipaddr;
+    ip_addr_t netmask;
+    ip_addr_t gw;
+    struct dhcp *dhcp;
+    uint8_t iptxt[20];
+
+    for (;;) {
+        switch (DHCP_state) {
+            case DHCP_START: {
+                ip_addr_set_zero_ip4(&netif->ip_addr);
+                ip_addr_set_zero_ip4(&netif->netmask);
+                ip_addr_set_zero_ip4(&netif->gw);
+                DHCP_state = DHCP_WAIT_ADDRESS;
+                MSG("State: Looking for DHCP server ...\r\n");
+                dhcp_start(netif);
+            } break;
+            case DHCP_WAIT_ADDRESS: {
+                if (dhcp_supplied_address(netif)) {
+                    DHCP_state = DHCP_ADDRESS_ASSIGNED;
+                    sprintf((char *)iptxt, "%s", ip4addr_ntoa(netif_ip4_addr(netif)));
+                    MSG("IP address assigned by a DHCP server: %s\r\n", iptxt);
+                } else {
+                    dhcp = (struct dhcp *)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP);
+
+                    /* DHCP timeout */
+                    if (dhcp->tries > MAX_DHCP_TRIES) {
+                        DHCP_state = DHCP_TIMEOUT;
+
+                        /* Static address used */
+                        ethernet_set_static_ip(netif);
+                        sprintf((char *)iptxt, "%s", ip4addr_ntoa(netif_ip4_addr(netif)));
+                        MSG("DHCP Timeout !!\r\n");
+                        MSG("Static IP address: %s\r\n", iptxt);
+                    }
+                }
+            } break;
+            case DHCP_LINK_DOWN: {
+                DHCP_state = DHCP_OFF;
+                MSG("The network cable is not connected \r\n");
+            } break;
+            default:
+                break;
+        }
+        vTaskDelay(100);
+    }
+}
+#endif /* LWIP_DHCP */

+ 76 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_ethernetif.h

@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __ETHERNETIF_H__
+#define __ETHERNETIF_H__
+#include "hal_emac.h"
+#if CTX_TYPE
+#include <utils_list.h>
+#endif
+#include "lwip/err.h"
+#include "lwip/netif.h"
+#include "ethernet_phy.h"
+
+#define DHCP_OFF              (uint8_t)0
+#define DHCP_START            (uint8_t)1
+#define DHCP_WAIT_ADDRESS     (uint8_t)2
+#define DHCP_ADDRESS_ASSIGNED (uint8_t)3
+#define DHCP_TIMEOUT          (uint8_t)4
+#define DHCP_LINK_DOWN        (uint8_t)5
+
+#if CTX_TYPE
+#define ETH_MAX_BUFFER_SIZE        (ETH_MAX_PACKET_SIZE)
+#define EMAC_TX_COMMON_FLAGS   (EMAC_BD_FIELD_MSK(TX_RD)  | \
+                                EMAC_BD_FIELD_MSK(TX_IRQ) | \
+                                EMAC_BD_FIELD_MSK(TX_PAD) | \
+                                EMAC_BD_FIELD_MSK(TX_CRC) | \
+                                EMAC_BD_FIELD_MSK(TX_EOF) )
+
+struct unsent_item{
+    struct utils_list_hdr hdr;
+    struct pbuf *p;
+};
+
+typedef struct {
+    struct utils_list unsent;
+    uint8_t Tx_free_bd_num;
+    uint8_t Rx_free_bd_num;
+    volatile uint16_t unsent_num;
+    uint32_t tx_pkt_cnt;
+    uint32_t rx_pkt_cnt;
+    uint32_t out_tmr;
+    uint32_t done_tmr;
+}eth_context;
+#endif
+/* Exported types ------------------------------------------------------------*/
+err_t ethernetif_init(struct netif *netif);
+void ethernet_link_check_state(struct netif *netif);
+void ethernet_link_status_updated(struct netif *netif);
+
+#endif

+ 184 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_flash.c

@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <blog.h>
+#ifdef BL808
+#include <bl808_glb.h>
+#include <bl808_xip_sflash.h>
+#include <bl808_sf_cfg.h>
+#include <bl808_romdriver_e907.h>
+#elif defined(BL606P)
+#include <bl606p_glb.h>
+#include <bl606p_xip_sflash.h>
+#include <bl606p_sf_cfg.h>
+#include <bl606p_sf_cfg_ext.h>
+#include <bl606p_romdriver_e907.h>
+#else
+#error "Use CHIP BL808/BL606P for this module"
+#endif
+
+#include "bl_irq.h"
+
+#define XIP_START_ADDR    (0x58000000)
+#define ADDR_LIMIT        (0x1000000)
+
+#define USER_UNUSED(a) ((void)(a))
+static SPI_Flash_Cfg_Type g_flash_cfg;
+
+/**
+ * @brief flash read data
+ *
+ * @param addr
+ * @param data
+ * @param len
+ * @return BL_Err_Type
+ */
+int ATTR_TCM_SECTION bl_flash_read(uint32_t startaddr, void *data, uint32_t len)
+{
+    BL_Err_Type stat;
+    uint8_t isAesEnable=0;
+
+    GLOBAL_IRQ_SAVE();
+    XIP_SFlash_Opt_Enter(&isAesEnable);
+    stat = XIP_SFlash_Read_Need_Lock(&g_flash_cfg, startaddr, data, len, 0, 0);
+    XIP_SFlash_Opt_Exit(isAesEnable);
+    GLOBAL_IRQ_RESTORE();
+
+    return stat;
+}
+
+/**
+ * @brief flash write data
+ *
+ * @param addr
+ * @param data
+ * @param len
+ * @return BL_Err_Type
+ */
+int ATTR_TCM_SECTION bl_flash_write(uint32_t startaddr, void *data, uint32_t len)
+{
+    BL_Err_Type stat;
+    uint8_t isAesEnable=0;
+
+    GLOBAL_IRQ_SAVE();
+    XIP_SFlash_Opt_Enter(&isAesEnable);
+    stat = XIP_SFlash_Write_Need_Lock(&g_flash_cfg, startaddr, data, len, 0, 0);
+    XIP_SFlash_Opt_Exit(isAesEnable);
+    GLOBAL_IRQ_RESTORE();
+
+    return stat;
+}
+
+/**
+ * @brief flash erase
+ *
+ * @param startaddr
+ * @param endaddr
+ * @return BL_Err_Type
+ */
+int ATTR_TCM_SECTION bl_flash_erase(uint32_t startaddr, uint32_t len)
+{
+    BL_Err_Type stat;
+    uint8_t isAesEnable=0;
+
+    GLOBAL_IRQ_SAVE();
+    XIP_SFlash_Opt_Enter(&isAesEnable);
+    stat = XIP_SFlash_Erase_Need_Lock(&g_flash_cfg, startaddr, len-1, 0, 0);
+    XIP_SFlash_Opt_Exit(isAesEnable);
+    GLOBAL_IRQ_RESTORE();
+
+    return stat;
+}
+
+/**
+ * @brief flash read from xip
+ *
+ * @param xip addr
+ * @param dst
+ * @param len
+ * @return BL_Err_Type
+ */
+int bl_flash_read_byxip(uint32_t addr, uint8_t *dst, int len)
+{
+    uint32_t offset;
+    uint32_t xipaddr;
+
+    offset = RomDriver_SF_Ctrl_Get_Flash_Image_Offset(0, 0);
+
+    if ((addr < offset) || (addr >= ADDR_LIMIT)) {
+        // not support or arg err ?
+        return -1;
+    }
+
+    xipaddr =  XIP_START_ADDR - offset + addr;
+    memcpy(dst, (void *)xipaddr, len);
+
+    return 0;
+}
+
+/**
+ * @brief multi flash adapter
+ *
+ * @return BL_Err_Type
+ */
+int ATTR_TCM_SECTION bl_flash_init(void)
+{
+    uint8_t isAesEnable=0;
+
+    /* Get flash config identify */
+    GLOBAL_IRQ_SAVE();
+    XIP_SFlash_Opt_Enter(&isAesEnable);
+    SF_Cfg_Flash_Identify_Ext(1, 0x80, 0, &g_flash_cfg, 0, 0);
+    XIP_SFlash_Opt_Exit(isAesEnable);
+    GLOBAL_IRQ_RESTORE();
+
+    return 0;
+}
+
+static void _dump_flash_config()
+{
+    extern uint8_t __boot2_flashCfg_src;
+
+    USER_UNUSED(__boot2_flashCfg_src);
+    
+    blog_info("======= FlashCfg magiccode @%p=======\r\n", &__boot2_flashCfg_src);
+    blog_info("mid \t\t0x%X\r\n", g_flash_cfg.mid);
+    blog_info("clkDelay \t0x%X\r\n", g_flash_cfg.clkDelay);
+    blog_info("clkInvert \t0x%X\r\n", g_flash_cfg.clkInvert);
+    blog_info("sector size\t%uKBytes\r\n", g_flash_cfg.sectorSize);
+    blog_info("page size\t%uBytes\r\n", g_flash_cfg.pageSize);
+    blog_info("---------------------------------------------------------------\r\n");
+}
+
+int bl_flash_config_update(void)
+{
+    _dump_flash_config();
+
+    return 0;
+}

+ 42 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_flash.h

@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __BL_FLASH_H__
+#define __BL_FLASH_H__
+#include <stdint.h>
+
+int bl_flash_erase(uint32_t addr, int len);
+int bl_flash_write(uint32_t addr, void *src, int len);
+int bl_flash_read(uint32_t addr, void *dst, int len);
+int bl_flash_config_update(void);
+void* bl_flash_get_flashCfg(void);
+
+int bl_flash_read_byxip(uint32_t addr, uint8_t *dst, int len);
+int bl_flash_init(void);
+#endif

+ 73 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_ipc.c

@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "bl_ipc.h"
+
+//FIXME no BL808/BL606p header file including is Allowed here
+#ifdef BL808
+#include <bl808_glb.h>
+#include <bl808_ipc.h>
+#elif defined(BL606P)
+#include <bl606p_glb.h>
+#include <bl606p_ipc.h>
+#else
+#error "Use CHIP BL808/BL606P for this module"
+#endif
+
+
+extern void IPC_Common_Interrupt_Handler(uint32_t irqStatus, ipcIntCallback *callBack[GLB_CORE_ID_MAX -1]);
+extern ipcIntCallback *m0IpcIntCbfArra[GLB_CORE_ID_MAX - 1];
+
+static void ipc_m0_handler(void)
+{
+    uint32_t irqStatus;
+    irqStatus = IPC_M0_Get_Int_Raw_Status();
+    IPC_Common_Interrupt_Handler(irqStatus, m0IpcIntCbfArra);
+    IPC_M0_Clear_Int_By_Word(irqStatus);
+}
+//FIXME no BL808/BL606p header file including is Allowed here
+#ifdef BL808
+#include <bl808_glb.h>
+#elif defined(BL606P)
+#include <bl606p_glb.h>
+#else
+#error "Use CHIP BL808/BL606P for this module"
+#endif
+
+void ipc_m0_init(ipcIntCallback *onLPTriggerCallBack,
+                 ipcIntCallback *onD0TriggerCallBack)
+{
+    IPC_M0_Init(onLPTriggerCallBack, onD0TriggerCallBack);
+
+#ifdef BFLB_USE_HAL_DRIVER
+    Interrupt_Handler_Register(IPC_M0_IRQn, ipc_m0_handler);
+#endif
+
+    System_NVIC_SetPriority(IPC_M0_IRQn, 5, 0);
+}

+ 37 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_ipc.h

@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __BL_IPC_H__
+#define __BL_IPC_H__
+
+#include <stdint.h>
+typedef void(ipcIntCallback)(uint32_t src);
+void ipc_m0_init(ipcIntCallback *onLPTriggerCallBack, ipcIntCallback *onD0TriggerCallBack);
+
+#endif

+ 418 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_irq.c

@@ -0,0 +1,418 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdint.h>
+
+//FIXME no BL808/BL606p header file including is Allowed here
+#ifdef BL808
+#include <bl808.h>
+#elif defined(BL606P)
+#include <bl606p.h>
+#else
+#error "Use CHIP BL808/BL606P for this module"
+#endif
+
+#include "clic.h"
+
+#include <blog.h>
+#include "bl_irq.h"
+
+#ifdef SYS_ENABLE_COREDUMP
+#include <bl_coredump.h>
+#endif
+
+void CPU_Interrupt_Enable(uint32_t irq_num);
+void CPU_Interrupt_Disable(uint32_t irq_num);
+void bl_irq_enable(unsigned int source)
+{
+  CPU_Interrupt_Enable(source);
+    //*(volatile uint8_t*)(CLIC_HART0_ADDR + CLIC_INTIE + source) = 1;
+}
+
+void bl_irq_disable(unsigned int source)
+{
+  CPU_Interrupt_Disable(source);
+    //*(volatile uint8_t*)(CLIC_HART0_ADDR + CLIC_INTIE + source) = 0;
+}
+
+void bl_irq_pending_set(unsigned int source)
+{
+    *(volatile uint8_t*)(CLIC_HART0_ADDR + CLIC_INTIP + source) = 1;
+}
+
+void bl_irq_pending_clear(unsigned int source)
+{
+    *(volatile uint8_t*)(CLIC_HART0_ADDR + CLIC_INTIP + source) = 0;
+}
+
+void bl_irq_exception_trigger(BL_IRQ_EXCEPTION_TYPE_T type, void *ptr)
+{
+    uint32_t val = 0x12345678;;
+
+    switch (type) {
+        case BL_IRQ_EXCEPTION_TYPE_LOAD_MISALIGN:
+        {
+            val = *(uint32_t*)ptr;
+        }
+        break;
+        case BL_IRQ_EXCEPTION_TYPE_STORE_MISALIGN:
+        {
+            *(uint32_t*)ptr = val;
+        }
+        break;
+        case BL_IRQ_EXCEPTION_TYPE_ACCESS_ILLEGAL:
+        {
+            *(uint32_t*)ptr = val;
+        }
+        break;
+        case BL_IRQ_EXCEPTION_TYPE_ILLEGAL_INSTRUCTION:
+        {
+            uint32_t fun_val = 0;
+            typedef void (*ins_ptr_t)(void);
+            ins_ptr_t func = (ins_ptr_t)&fun_val;
+
+            func();
+        }
+        break;
+        default:
+        {
+            /*nothing here*/
+        }
+    }
+    printf("Trigger exception val is %08lx\r\n", val);
+}
+
+void bl_irq_default(void)
+{
+    while (1) {
+        /*dead loop*/
+    }
+}
+
+static void (*handler_list[2][16 + 64])(void) = {
+    
+};
+
+
+static inline void _irq_num_check(int irqnum)
+{
+    if (irqnum < 0 || irqnum >= sizeof(handler_list[0])/sizeof(handler_list[0][0])) {
+        blog_error("illegal irqnum %d\r\n", irqnum);
+        while (1) {
+            /*Deap loop here, TODO ass blog_assert*/
+        }
+    }
+}
+
+void bl_irq_register_with_ctx(int irqnum, void *handler, void *ctx)
+{
+    _irq_num_check(irqnum);
+    if (handler_list[0][irqnum] && handler_list[0][irqnum] != handler) {
+        blog_warn("IRQ %d already registered with %p \r\n",
+             irqnum,
+             handler_list[0][irqnum]
+        );
+    }
+   
+    if (handler == NULL) {
+        blog_error("handler is NULL pointer! \r\n");
+        return;
+    }
+
+    if (NULL == ctx) {
+        handler_list[0][irqnum] = handler;
+        handler_list[1][irqnum] = NULL;
+    }
+    else {
+        handler_list[0][irqnum] = handler;
+        handler_list[1][irqnum] = ctx;
+    }
+
+    return;
+    
+}
+
+void bl_irq_ctx_get(int irqnum, void **ctx)
+{
+    _irq_num_check(irqnum);
+    *ctx = handler_list[1][irqnum];
+
+    return;
+}
+
+struct irq_ctx **bl_irq_ctx_list(int *num)
+{
+    *num = 16 + 64;
+    return (struct irq_ctx **)handler_list[1];
+}
+
+void bl_irq_ctx_count_cost(int irqnum, uint64_t cost)
+{
+    struct irq_ctx *ctx;
+    _irq_num_check(irqnum);
+    if(handler_list[0][irqnum] != NULL) {
+	ctx = (struct irq_ctx *)(handler_list[1][irqnum]);
+	ctx->irq_run_time += cost;
+    }
+}
+
+//void Interrupt_Handler_Register(IRQn_Type irq,void * interruptFun);
+void Interrupt_Handler_Register(IRQn_Type irq,pFunc interruptFun);
+void bl_irq_register(int irqnum, void *handler)
+{
+
+  Interrupt_Handler_Register(irqnum, handler);
+    //bl_irq_register_with_ctx(irqnum, handler, NULL);
+}
+
+void bl_irq_unregister(int irqnum, void *handler)
+{
+#if 0
+    _irq_num_check(irqnum);
+    if (handler_list[0][irqnum] != handler) {
+        blog_warn("IRQ %d:%p Not match with registered %p\r\n",
+            irqnum,
+            handler,
+            handler_list[0][irqnum]
+        );
+    }
+    handler_list[0][irqnum] = handler;
+#endif
+}
+
+void interrupt_entry(uint32_t mcause) 
+{
+    void *handler = NULL;
+    mcause &= 0x7FFFFFF;
+    if (mcause < sizeof(handler_list[0])/sizeof(handler_list[0][0])) {
+        handler = handler_list[0][mcause];
+    }
+    if (handler) {
+        if (handler_list[1][mcause]) {
+           ((void (*)(void *))handler)(handler_list[1][mcause]);//handler(ctx)
+        }
+        else {
+            ((void (*)(void))handler)();
+        }
+    } else {
+        printf("Cannot handle mcause 0x%lx:%lu, adjust to externel(0x%lx:%lu)\r\n",
+                mcause,
+                mcause,
+                mcause - 16,
+                mcause - 16
+        );
+        while (1) {
+            /*dead loop now*/
+        }
+    }
+}
+
+static void __dump_exception_code_str(uint32_t code)
+{
+    printf("Exception code: %lu\r\n", code);
+    switch (code) {
+        case 0x00:
+        /*Instruction address misaligned*/
+        {
+            puts("  msg: Instruction address misaligned\r\n");
+        }
+        break;
+        case 0x01:
+        /*Instruction access fault*/
+        {
+            puts("  msg: Instruction access fault\r\n");
+        }
+        break;
+        case 0x02:
+        /*Illegal instruction*/
+        {
+            puts("  msg: Illegal instruction\r\n");
+        }
+        break;
+        case 0x03:
+        /*Breakpoint*/
+        {
+            puts("  msg: Breakpoint\r\n");
+        }
+        break;
+        case 0x04:
+        /*Load address misaligned*/
+        {
+            puts("  msg: Load address misaligned\r\n");
+        }
+        break;
+        case 0x05:
+        /*Load access fault*/
+        {
+            puts("  msg: Load access fault\r\n");
+        }
+        break;
+        case 0x06:
+        /*Store/AMO access misaligned*/
+        {
+            puts("  msg: Store/AMO access misaligned\r\n");
+        }
+        break;
+        case 0x07:
+        /*Store/AMO access fault*/
+        {
+            puts("  msg: Store/AMO access fault\r\n");
+        }
+        break;
+        case 0x08:
+        /*Environment call from U-mode*/
+        {
+            puts("  msg: Environment call from U-mode\r\n");
+        }
+        break;
+        case 0x09:
+        /*Environment call from S-mode*/
+        {
+            puts("  msg: Environment call from S-mode\r\n");
+        }
+        break;
+        case 0x0a:
+        case 0x0e:
+        /*Reserved*/
+        {
+            puts("  msg: Reserved\r\n");
+        }
+        break;
+        case 0x0b:
+        /*Environment call from M-mode*/
+        {
+            puts("  msg: Environment call from M-mode\r\n");
+        }
+        break;
+        case 0x0c:
+        /*Instruction page fault*/
+        {
+            puts("  msg: Instruction page fault\r\n");
+        }
+        break;
+        case 0x0d:
+        /*Load page fault*/
+        {
+            puts("  msg: Load page fault\r\n");
+        }
+        break;
+        case 0x0f:
+        /*Store/AMO page fault*/
+        {
+            puts("  msg: Store/AMO page fault\r\n");
+        }
+        break;
+        default:{
+            puts("  msg: Reserved default exception\r\n");
+        }
+    }
+}
+
+extern void misaligned_load_trap(uintptr_t* regs, uintptr_t mcause, uintptr_t mepc);
+extern void misaligned_store_trap(uintptr_t* regs, uintptr_t mcause, uintptr_t mepc);
+
+#define EXCPT_LOAD_MISALIGNED        4
+#define EXCPT_STORE_MISALIGNED       6
+
+#ifdef DBG_RECORD_EXCEP_VAL
+struct{
+	uint32_t mcause;
+	uint32_t mepc;
+	uint32_t mtval;
+}rval[4];
+int rval_idx;
+#endif /* DBG_RECORD_EXCEP_VAL */
+
+void exception_entry(uint32_t mcause, uint32_t mepc, uint32_t mtval, uintptr_t *regs)
+{
+#ifdef DBG_RECORD_EXCEP_VAL
+    rval[rval_idx&0x3].mcause = mcause;
+    rval[rval_idx&0x3].mepc = mepc;
+    rval[rval_idx&0x3].mtval = mtval;
+    rval_idx++;
+#endif /* DBG_RECORD_EXCEP_VAL */
+    if ((mcause & 0x3ff) == EXCPT_LOAD_MISALIGNED) {
+	//misaligned_load_trap(regs, mcause, mepc);
+    } else if ((mcause & 0x3ff) == EXCPT_STORE_MISALIGNED){
+	//misaligned_store_trap(regs, mcause, mepc);
+    }
+    {
+	//registerdump(tasksp);
+	puts("Exception Entry--->>>\r\n");
+	blog_info("mcause %08lx, mepc %08lx, mtval %08lx\r\n",
+		  mcause,
+		  mepc,
+		  mtval
+		  );
+        __dump_exception_code_str(mcause & 0xFFFF);
+	//backtrace_now_task((int (*)(const char *s))puts, regs);
+        while (1) {
+	    /*Deap loop now*/
+#ifdef SYS_ENABLE_COREDUMP
+	    /* For stack check */
+            extern uintptr_t _sp_main, _sp_base;
+
+            /* XXX change sp to irq stack base */
+            __asm__ volatile("add sp, x0, %0" ::"r"(&_sp_main));
+            bl_coredump_run();
+#endif
+        }
+    }
+}
+
+int bl_irq_save(void)
+{
+    uint32_t oldstat;
+
+    /* Read mstatus & clear machine interrupt enable (MIE) in mstatus */
+    __asm volatile("csrrc %0, mstatus, %1" : "=r"(oldstat) : "r"(8));
+    return oldstat;
+}
+
+void bl_irq_restore(int flags)
+{
+    __asm volatile("csrw mstatus, %0"
+                    : /* no output */
+                    : "r"(flags));
+}
+void bl_irq_init(void)
+{
+    uint32_t ptr;
+
+    // puts("[IRQ] Clearing and Disable all the pending IRQ...\r\n");
+
+    /*clear mask*/
+    for (ptr = 0x02800400; ptr < 0x02800400 + 128; ptr++) {
+        *(uint8_t*)ptr = 0;
+    }
+    /*clear pending*/
+    for (ptr = 0x02800000; ptr < 0x02800000 + 128; ptr++) {
+        *(uint8_t*)ptr = 0;
+    }
+}

+ 74 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_irq.h

@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __BL_IRQ_H__
+#define __BL_IRQ_H__
+void bl_irq_enable(unsigned int source);
+void bl_irq_disable(unsigned int source);
+typedef enum {
+    BL_IRQ_EXCEPTION_TYPE_LOAD_MISALIGN,
+    BL_IRQ_EXCEPTION_TYPE_STORE_MISALIGN,
+    BL_IRQ_EXCEPTION_TYPE_ACCESS_ILLEGAL,
+    BL_IRQ_EXCEPTION_TYPE_ILLEGAL_INSTRUCTION,
+} BL_IRQ_EXCEPTION_TYPE_T;
+
+struct irq_ctx {
+    char *name;
+    int irqnum;
+    uint64_t irq_run_time;
+};
+
+struct irq_ctx **bl_irq_ctx_list(int *num);
+void bl_irq_exception_trigger(BL_IRQ_EXCEPTION_TYPE_T type, void *ptr);
+
+void bl_irq_init(void);
+/*The following section define the IRQ handler for other files*/
+void bl_sec_aes_IRQHandler(void);
+void bl_sec_sha_IRQHandler(void);
+void bl_sec_pka_IRQHandler(void);
+void bl_dma_IRQHandler(void);
+void intc_irq(void);//MAC IRQ
+void bl_irq_handler(void);//IPC host IRQ
+void bl_irq_register_with_ctx(int irqnum, void *handler, void *ctx);
+void bl_irq_register(int irqnum, void *handler);
+void bl_irq_unregister(int irqnum, void *handler);
+void bl_irq_ctx_get(int irqnum, void **ctx);
+
+
+int bl_irq_save(void);
+void bl_irq_restore(int flags);
+void __attribute__((noreturn)) bl_sys_abort(const char *details);
+
+#define GLOBAL_IRQ_SAVE()  if (1) { \
+  int ____global_prev_mie_irq____ = bl_irq_save();
+
+#define GLOBAL_IRQ_RESTORE() \
+  bl_irq_restore(____global_prev_mie_irq____ ); \
+}
+#endif

+ 272 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_mm_clock.c

@@ -0,0 +1,272 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdint.h>
+#include <stdio.h>
+#include "bl_mm_clock.h"
+//FIXME no BL808/BL606p header file including is Allowed here
+#ifdef BL808
+#include <bl808_glb.h>
+#include <mm_glb_reg.h>
+#elif defined(BL606P)
+//TODO BL606P H FILE
+#include <bl606p_glb.h>
+#include <mm_glb_reg.h>
+#else
+#error "Use CHIP BL808/BL606P for this module"
+#endif
+
+static void get_mm_xclk(uint32_t reg_val)
+{
+    uint32_t cpu_pll_clk = 0;
+    cpu_pll_clk = BL_GET_REG_BITS_VAL(reg_val, MM_GLB_REG_XCLK_CLK_SEL);
+
+    switch (cpu_pll_clk) {
+        case 0:
+            printf("XCLK select RC32M\r\n");
+            break;
+        case 1:
+            printf("XCLK select XTAL\r\n");
+            break;
+        default:
+              break;
+    }
+}
+
+static void get_mm_cpu_pll_clk(uint32_t reg_val)
+{
+    uint32_t cpu_pll_clk = 0;
+    cpu_pll_clk = BL_GET_REG_BITS_VAL(reg_val, MM_GLB_REG_CPU_CLK_SEL);
+
+    switch (cpu_pll_clk) {
+        case 0:
+            printf("MM CPU select 240Mhz\r\n");
+            break;
+        case 1:
+            printf("MM CPU select 320Mhz\r\n");
+            break;
+        case 2:
+            printf("MM CPU select 400Mhz\r\n");
+            break;
+        default:
+            break;
+    }
+
+}
+
+static void dump_mm_cpu_clk(void)
+{
+    uint32_t tmpVal = 0, cpu_root_clk = 0;
+ 
+    tmpVal = BL_RD_REG(CLKRST_CTRL_BASE, MM_GLB_MM_CLK_CTRL_CPU);
+    cpu_root_clk = BL_GET_REG_BITS_VAL(tmpVal, MM_GLB_REG_CPU_ROOT_CLK_SEL);
+    switch (cpu_root_clk) {
+        case 0:
+            printf("MM CPU select XCLK--->");
+            get_mm_xclk(tmpVal);
+            break;
+        case 1:
+            printf("MM CPU select PLL--->");
+            get_mm_cpu_pll_clk(tmpVal);
+            break;
+        default:
+            break;
+    }
+}
+
+static void dump_mm_bus_clk(void)
+{
+    uint32_t tmpVal = 0, mm_bus_clk = 0;
+
+    tmpVal = BL_RD_REG(CLKRST_CTRL_BASE, MM_GLB_MM_CLK_CTRL_CPU);
+    mm_bus_clk = BL_GET_REG_BITS_VAL(tmpVal, MM_GLB_REG_BCLK1X_SEL);
+
+    switch (mm_bus_clk) {
+        case 0:
+            printf("MM BUS CLK select XCLK--->");
+            get_mm_xclk(tmpVal);
+            break;
+        case 2:
+            printf("MM BUS CLK select 160Mhz\r\n");
+            break;
+        case 3:
+            printf("MM BUS CLK select 240Mhz\r\n");
+            break;
+        default:
+            break;
+    }
+
+}
+
+static void dump_mm_xclk(void)
+{
+    uint32_t tmpVal = 0;
+    tmpVal = BL_RD_REG(CLKRST_CTRL_BASE, MM_GLB_MM_CLK_CTRL_CPU);
+    get_mm_xclk(tmpVal);
+}
+
+static void dump_mm_uart_clk(void)
+{
+    uint32_t tmpVal = 0, mm_uart_clk = 0;
+
+    tmpVal = BL_RD_REG(CLKRST_CTRL_BASE, MM_GLB_MM_CLK_CTRL_CPU);
+    mm_uart_clk = BL_GET_REG_BITS_VAL(tmpVal, MM_GLB_REG_UART_CLK_SEL);
+
+    switch (mm_uart_clk) {
+        case 0:
+            printf("UART CLK select MM BUS CLK--->");
+            dump_mm_bus_clk();
+            break;
+        case 1:
+            printf("UART CLK select 160Mhz\r\n");
+            break;
+        case 2:
+        case 3:
+            printf("UART CLK select MM XCLK--->");
+            get_mm_xclk(tmpVal);
+            break;
+        default:
+            break;
+    }
+}
+
+static void dump_mm_i2c_clk(void)
+{
+    uint32_t tmpVal = 0, mm_i2c_clk = 0;
+
+    tmpVal = BL_RD_REG(CLKRST_CTRL_BASE, MM_GLB_MM_CLK_CTRL_CPU);
+    mm_i2c_clk = BL_GET_REG_BITS_VAL(tmpVal, MM_GLB_REG_I2C_CLK_SEL);
+
+    switch (mm_i2c_clk) {
+        case 0:
+            printf("I2C CLK select MM BUS CLK--->");
+            dump_mm_bus_clk();
+            break;
+        case 1:
+            printf("I2C CLK select MM XCLK--->");
+            get_mm_xclk(tmpVal);
+            break;
+        default:
+            break;
+    }
+}
+
+static void dump_mm_spi_clk(void)
+{
+    uint32_t tmpVal = 0, mm_spi_clk = 0;
+
+    tmpVal = BL_RD_REG(CLKRST_CTRL_BASE, MM_GLB_MM_CLK_CTRL_CPU);
+    mm_spi_clk = BL_GET_REG_BITS_VAL(tmpVal, MM_GLB_REG_SPI_CLK_SEL);
+
+    switch (mm_spi_clk) {
+        case 0:
+            printf("SPI CLK select 160Mhz\r\n");
+            break;
+        case 1:
+            printf("SPI CLK select MM XCLK--->");
+            get_mm_xclk(tmpVal);
+            break;
+        default:
+            break;
+    }
+}
+
+void bl_mm_clk_dump(void)
+{
+    dump_mm_cpu_clk();
+    dump_mm_uart_clk();
+    dump_mm_i2c_clk();
+    dump_mm_spi_clk();
+    dump_mm_bus_clk();
+    dump_mm_xclk();
+}
+
+void bl_mm_xclk_config(mm_xclk_type xclk_num)
+{
+    uint32_t tmpVal;
+    tmpVal = BL_RD_REG(CLKRST_CTRL_BASE, MM_GLB_MM_CLK_CTRL_CPU);
+    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, MM_GLB_REG_XCLK_CLK_SEL, xclk_num);
+
+    BL_WR_REG(CLKRST_CTRL_BASE, MM_GLB_MM_CLK_CTRL_CPU, tmpVal);
+}
+
+void bl_mm_bclk_config(mm_bclk_type bclk_num)
+{
+    uint32_t tmpVal;
+    tmpVal = BL_RD_REG(CLKRST_CTRL_BASE, MM_GLB_MM_CLK_CTRL_CPU);
+    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, MM_GLB_REG_BCLK1X_SEL, bclk_num);
+
+    BL_WR_REG(CLKRST_CTRL_BASE, MM_GLB_MM_CLK_CTRL_CPU, tmpVal);
+}
+
+void bl_mm_cpu_root_clk_config(mm_cpu_root_clk_type cpu_root_clk_num)
+{
+    uint32_t tmpVal;
+    tmpVal = BL_RD_REG(CLKRST_CTRL_BASE, MM_GLB_MM_CLK_CTRL_CPU);
+    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, MM_GLB_REG_CPU_ROOT_CLK_SEL, cpu_root_clk_num);
+
+    BL_WR_REG(CLKRST_CTRL_BASE, MM_GLB_MM_CLK_CTRL_CPU, tmpVal);
+}
+
+void bl_mm_cpu_clk_config(mm_cpu_clk_type cpu_clk_num)
+{
+    uint32_t tmpVal;
+    tmpVal = BL_RD_REG(CLKRST_CTRL_BASE, MM_GLB_MM_CLK_CTRL_CPU);
+    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, MM_GLB_REG_CPU_CLK_SEL, cpu_clk_num);
+
+    BL_WR_REG(CLKRST_CTRL_BASE, MM_GLB_MM_CLK_CTRL_CPU, tmpVal);
+}
+
+void bl_mm_spi_clk_config(mm_spi_clk_type spi_clk_num)
+{
+    uint32_t tmpVal;
+    tmpVal = BL_RD_REG(CLKRST_CTRL_BASE, MM_GLB_MM_CLK_CTRL_CPU);
+    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, MM_GLB_REG_SPI_CLK_SEL, spi_clk_num);
+
+    BL_WR_REG(CLKRST_CTRL_BASE, MM_GLB_MM_CLK_CTRL_CPU, tmpVal);
+}
+
+void bl_mm_i2c_clk_config(mm_i2c_clk_type i2c_clk_num)
+{
+    uint32_t tmpVal;
+    tmpVal = BL_RD_REG(CLKRST_CTRL_BASE, MM_GLB_MM_CLK_CTRL_CPU);
+    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, MM_GLB_REG_I2C_CLK_SEL, i2c_clk_num);
+
+    BL_WR_REG(CLKRST_CTRL_BASE, MM_GLB_MM_CLK_CTRL_CPU, tmpVal);
+}
+
+void bl_mm_uart_clk_config(mm_uart_clk_type uart_clk_num)
+{
+    uint32_t tmpVal;
+    tmpVal = BL_RD_REG(CLKRST_CTRL_BASE, MM_GLB_MM_CLK_CTRL_CPU);
+    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, MM_GLB_REG_UART_CLK_SEL, uart_clk_num);
+
+    BL_WR_REG(CLKRST_CTRL_BASE, MM_GLB_MM_CLK_CTRL_CPU, tmpVal);
+}
+

+ 86 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_mm_clock.h

@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __BL_MM_CLOCK__
+#define __BL_MM_CLOCK__
+/*MM XCLK select*/
+typedef enum {
+    XCLK_RC32M = 0,
+    XCLK_XTAL,
+}mm_xclk_type;
+
+/*MM BCLK1x select*/
+typedef enum {
+    BCLK_XCLK = 0,
+    BCLK_MUXPLL_160M = 2,
+    BCLK_MUXPLL_240M = 3,
+}mm_bclk_type;
+
+/*MM CPU PLL select*/
+typedef enum {
+    CPU_CLK_MUXPLL_240M = 0,
+    CPU_CLK_MUXPLL_320M,
+    CPU_CLK_MUXPLL_400M,
+}mm_cpu_clk_type;
+
+/*MM CPU ROOT CLK select*/
+typedef enum {
+    CPU_ROOT_CLK_XCLK = 0,
+    CPU_ROOT_CLK_PLL,
+}mm_cpu_root_clk_type;
+
+/*MM SPI CLK select*/
+typedef enum {
+    SPI_CLK_MUXPLL_160M = 0,
+    SPI_CLK_XCLK,
+}mm_spi_clk_type;
+
+/*MM I2C CLK select*/
+typedef enum {
+    I2C_CLK_BCLK = 0,
+    I2C_CLK_XCLK,
+}mm_i2c_clk_type;
+
+/*MM UART CLK select*/
+typedef enum {
+    UART_CLK_BCLK = 0,
+    UART_CLK_MUXPLL_160M,
+    UART_CLK_XCLK1, //2 or 3 all select MM XCLK
+    UART_CLK_XCLK2,
+}mm_uart_clk_type;
+
+void bl_mm_clk_dump(void);
+void bl_mm_xclk_config(mm_xclk_type xclk_num);
+void bl_mm_bclk_config(mm_bclk_type bclk_num);
+void bl_mm_cpu_clk_config(mm_cpu_clk_type cpu_clk_num);
+void bl_mm_cpu_root_clk_config(mm_cpu_root_clk_type cpu_root_clk_num);
+void bl_mm_spi_clk_config(mm_spi_clk_type spi_clk_num);
+void bl_mm_i2c_clk_config(mm_i2c_clk_type i2c_clk_num);
+void bl_mm_uart_clk_config(mm_uart_clk_type uart_clk_num);
+#endif

+ 489 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_pm.c

@@ -0,0 +1,489 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <FreeRTOS.h>
+#include <task.h>
+#include <semphr.h>
+
+#include <stdint.h>
+#include <utils_list.h>
+#include <blog.h>
+#include "bl_pm.h"
+#include <assert.h>
+
+enum PM_STATE {
+    PM_STATE_INITED = 0,
+    PM_STATE_STOP,
+    PM_STATE_START,
+    PM_STATE_STOPPED,
+    PM_STATE_RUNNING,
+};
+
+union ps_cap {
+    uint32_t cap;
+    struct {
+        unsigned int uapsd_mode     :   1;
+        unsigned int mac_idle       :   1;
+        unsigned int ma_doze        :   1;
+        unsigned int rf_onoff       :   1;
+        unsigned int pti_pta_config :   1;
+        unsigned int force_sleep    :   1;
+    } bits;
+};
+
+struct pm_env
+{
+    uint32_t level;
+    union ps_cap wlan_capacity;
+    union ps_cap bt_capacity;
+    enum PM_STATE state;
+    SemaphoreHandle_t pm_mux;
+    utils_dlist_t *pm_list;
+};
+
+struct pm_node
+{
+    utils_dlist_t dlist_item;
+    enum PM_EVEMT event;
+    uint32_t code;
+    uint16_t priority;
+    uint32_t cap_bit;
+    bl_pm_cb_t ops;
+    enum PM_EVENT_ABLE enable;
+    void *ctx;
+};
+
+static struct pm_env *gp_pm_env = NULL;
+
+static int pm_env_init(void)
+{
+    int i = 0;
+
+    assert(!gp_pm_env);
+
+    gp_pm_env = pvPortMalloc(sizeof(struct pm_env));
+    assert(gp_pm_env);
+
+    memset(gp_pm_env, 0, sizeof(struct pm_env));
+    gp_pm_env->pm_list = pvPortMalloc(sizeof(utils_dlist_t) * PM_EVENT_MAX);
+    assert(gp_pm_env->pm_list);
+
+    memset(gp_pm_env->pm_list, 0, sizeof(bl_pm_cb_t) * PM_EVENT_MAX);
+
+    gp_pm_env->pm_mux = xSemaphoreCreateMutex();
+    assert(gp_pm_env->pm_mux);
+
+    for (i = 0; i < PM_EVENT_MAX; i++) {
+        INIT_UTILS_DLIST_HEAD(&(gp_pm_env->pm_list)[i]);
+    }
+
+    gp_pm_env->state = PM_STATE_INITED; 
+
+    ///for debug
+    gp_pm_env->bt_capacity.cap = 0xffff;
+
+    return 0;
+}
+
+static void pm_node_delete(utils_dlist_t *queue)
+{
+    struct pm_node *node = NULL;
+    utils_dlist_t *tmp;
+
+    utils_dlist_for_each_entry_safe(queue, tmp, node, struct pm_node, dlist_item) {
+        xSemaphoreTake(gp_pm_env->pm_mux, portMAX_DELAY);
+        utils_dlist_del(&(node->dlist_item));
+        vPortFree(node);
+        xSemaphoreGive(gp_pm_env->pm_mux);
+    }
+}
+
+static int pm_deinit(void)
+{
+    int i = 0;
+
+    assert(gp_pm_env);
+
+    for (i = 0; i < PM_EVENT_MAX; i++) {
+        pm_node_delete(&(gp_pm_env->pm_list)[i]);
+    }
+
+    vPortFree(gp_pm_env->pm_list);
+    gp_pm_env->pm_list = NULL;
+    
+    vSemaphoreDelete(gp_pm_env->pm_mux);
+    gp_pm_env->pm_mux = NULL;
+    
+    vPortFree(gp_pm_env);
+    gp_pm_env = NULL;
+    
+    return 0;
+}
+
+static int pm_set_wlan_capacity(uint32_t capacity)
+{
+    assert(gp_pm_env);
+
+    gp_pm_env->wlan_capacity.cap = capacity;
+
+    return 0;
+}
+
+static int pm_set_state(enum PM_STATE state)
+{
+    gp_pm_env->state = state;
+
+    return 0;
+}
+
+static enum PM_STATE pm_get_state(void)
+{
+    return gp_pm_env->state;
+}
+
+static void pm_node_add(struct pm_node *pnode, utils_dlist_t *queue)
+{
+    struct pm_node *node = NULL;
+    utils_dlist_t *tmp;
+    utils_dlist_t *pre_save;
+
+    pre_save = queue;
+    utils_dlist_for_each_entry_safe(queue, tmp, node, struct pm_node, dlist_item) {
+        if (pnode->priority < node->priority) {
+            xSemaphoreTake(gp_pm_env->pm_mux, portMAX_DELAY);
+            utils_dlist_add(&(pnode->dlist_item), pre_save);
+            xSemaphoreGive(gp_pm_env->pm_mux);
+            break;
+        } 
+
+        pre_save = &(node->dlist_item);
+    }
+
+    if (&(node->dlist_item) == queue) {
+        xSemaphoreTake(gp_pm_env->pm_mux, portMAX_DELAY);
+        utils_dlist_add_tail(&(pnode->dlist_item), queue);
+        xSemaphoreGive(gp_pm_env->pm_mux);
+    }
+}
+
+static int pm_node_ops_exec(struct pm_node *node)
+{
+    if (node->ops == NULL) {
+        return 0;
+    }
+
+    return node->ops(node->ctx);
+}
+
+static int pm_state_exec_func_check(enum PM_EVEMT event, uint32_t code)
+{
+    int ret;
+
+    if ((WLAN_PM_EVENT_CONTROL == event) || (PM_STATE_RUNNING == gp_pm_env->state)) {
+        ret = 0;
+    } else {
+        ret = 1;
+    }
+
+    return ret;
+}
+
+static int pm_pmlist_traverse(enum PM_EVEMT event, utils_dlist_t *queue, uint32_t code, uint32_t *retval)
+{
+    struct pm_node *node = NULL;
+    int ret = 0;
+    utils_dlist_t *tmp;
+
+    if (retval) {
+        *retval = 0;
+    }
+
+    utils_dlist_for_each_entry_safe(queue, tmp, node, struct pm_node, dlist_item) {
+        if ((node->enable) && (code == node->code) && (gp_pm_env->wlan_capacity.cap & node->cap_bit) && 
+                (gp_pm_env->bt_capacity.cap & node->cap_bit)) {
+
+            if (pm_state_exec_func_check(event, code)) {
+                return -1;
+            }
+
+            ret = pm_node_ops_exec(node);
+            if (ret && retval) {
+                *retval |= 1;
+            }
+        }
+    }
+
+    return 0;
+}
+
+static int pm_internal_process_event(enum PM_EVEMT event, uint32_t code)
+{
+    int ret = 0;
+
+    switch (event) {
+        case WLAN_PM_EVENT_CONTROL:
+        {
+            switch (code) {
+                case WLAN_CODE_PM_NOTIFY_START:
+                {
+                    if ((PM_STATE_INITED != pm_get_state()) && (PM_STATE_STOPPED != pm_get_state())) {
+                        blog_error("pm not init or is running.\r\n");
+                        ret = -1;
+
+                        return ret;
+                    }
+                    pm_set_state(PM_STATE_START);
+                }
+                break;
+
+                case WLAN_CODE_PM_NOTIFY_STOP:
+                {
+                    if (PM_STATE_RUNNING != pm_get_state()) {
+                        blog_error("pm is not running.\r\n");
+                        ret = -1;
+
+                        return ret;
+                    }
+
+                    pm_set_state(PM_STATE_STOP);
+                }
+                break;
+
+                default:
+                {
+                }
+            }
+        }
+        break;
+
+        default:
+        {
+
+        }
+    } 
+    
+    return ret;
+}
+
+int pm_post_event(enum PM_EVEMT event, uint32_t code, uint32_t *retval)
+{
+    if (!gp_pm_env) {
+        return -1;
+    }
+    
+    pm_pmlist_traverse(event, &(gp_pm_env->pm_list)[event], code, retval);
+    pm_internal_process_event(event, code);
+
+    return 0;
+}
+
+int bl_pm_event_register(enum PM_EVEMT event, uint32_t code, uint32_t cap_bit, uint16_t priority, bl_pm_cb_t ops, void *arg, enum PM_EVENT_ABLE enable)
+{
+    struct pm_node *p_node;
+
+    if (!gp_pm_env) {
+        return -1;
+    }
+
+    p_node = pvPortMalloc(sizeof(struct pm_node));
+    assert(p_node);
+
+    memset(p_node, 0, sizeof(struct pm_node));
+    p_node->event = event;
+    p_node->code = code;
+    p_node->cap_bit = cap_bit;
+    p_node->priority = priority;
+    p_node->ops = ops;
+    p_node->ctx = arg;
+    p_node->enable = enable;
+    
+    pm_node_add(p_node, &(gp_pm_env->pm_list)[event]);
+    
+    return 0;
+}
+
+int bl_pm_event_switch(enum PM_EVEMT event, uint32_t code, enum PM_EVENT_ABLE enable)
+{
+    struct pm_node *node = NULL;
+    utils_dlist_t *tmp;
+    utils_dlist_t *queue;
+    int ret = -1;
+
+    if (!gp_pm_env) {
+        return -1;
+    }
+
+    queue = &(gp_pm_env->pm_list)[event];
+
+    utils_dlist_for_each_entry_safe(queue, tmp, node, struct pm_node, dlist_item) {
+        if (code == node->code) {
+            node->enable = enable;
+            
+            ret = 0;
+        }
+    }
+
+    return ret;
+}
+
+int bl_pm_state_run(void)
+{
+    int ret = -1;
+
+    if (!gp_pm_env) {
+        return -1;
+    }
+
+    switch (gp_pm_env->state) {
+        case PM_STATE_INITED:
+        {
+        }
+        break;
+
+        case PM_STATE_START:
+        {
+            pm_set_state(PM_STATE_RUNNING);
+            pm_post_event(WLAN_PM_EVENT_CONTROL, WLAN_CODE_PM_START, NULL);;
+            ret = 0;
+        }
+        break;
+
+        case PM_STATE_STOP:
+        {
+            pm_set_state(PM_STATE_STOPPED);
+            pm_post_event(WLAN_PM_EVENT_CONTROL, WLAN_CODE_PM_STOP, NULL);
+        }
+        break;
+
+        case PM_STATE_RUNNING:
+        {
+            ret = 0;
+        }
+        break;
+
+        case PM_STATE_STOPPED:
+        {
+        }
+        break;
+
+        default:
+        {
+
+        }
+    } 
+    
+    return ret;
+}
+
+int bl_pm_capacity_set(enum PM_LEVEL level)
+{
+    uint32_t capacity = 0;
+
+    switch (level) {
+        case PM_MODE_STA_NONE:
+        {
+            return -1;
+        }
+        break;
+
+        case PM_MODE_STA_IDLE:
+        {
+            capacity |= NODE_CAP_BIT_UAPSD_MODE;
+            capacity |= NODE_CAP_BIT_MAC_IDLE;
+        }
+        break;
+
+        case PM_MODE_STA_MESH:
+        {
+            capacity |= NODE_CAP_BIT_UAPSD_MODE;
+            capacity |= NODE_CAP_BIT_MAC_IDLE;
+            capacity |= NODE_CAP_BIT_WLAN_BLE_ABORT;
+            capacity |= NODE_CAP_BIT_FORCE_SLEEP;
+        }
+        break;
+
+        case PM_MODE_STA_DOZE:
+        {
+            capacity |= NODE_CAP_BIT_UAPSD_MODE;
+            capacity |= NODE_CAP_BIT_MAC_IDLE;
+            capacity |= NODE_CAP_BIT_MAC_DOZE;
+            capacity |= NODE_CAP_BIT_RF_ONOFF;
+            capacity |= NODE_CAP_BIT_FORCE_SLEEP;
+        }
+        break;
+
+        case PM_MODE_STA_COEX:
+        {
+            capacity |= NODE_CAP_BIT_UAPSD_MODE;
+            capacity |= NODE_CAP_BIT_MAC_IDLE;
+            capacity |= NODE_CAP_BIT_MAC_DOZE;
+            capacity |= NODE_CAP_BIT_RF_ONOFF;
+            capacity |= NODE_CAP_BIT_WLAN_BLE_ABORT;
+        }
+        break;
+
+        case PM_MODE_STA_DOWN:
+        {
+            capacity |= NODE_CAP_BIT_MAC_IDLE;
+            capacity |= NODE_CAP_BIT_MAC_DOZE;
+            capacity |= NODE_CAP_BIT_RF_ONOFF;
+        }
+        break;
+
+        case PM_MODE_AP_IDLE:
+        {
+            capacity |= NODE_CAP_BIT_MAC_IDLE;
+            capacity |= NODE_CAP_BIT_MAC_DOZE;
+        }
+        break;
+
+        default:
+        {
+            return -1;
+        }
+    } 
+
+    pm_set_wlan_capacity(capacity);
+
+    return 0;
+}
+
+int bl_pm_init(void)
+{
+    pm_env_init();
+
+    return 0;
+}
+
+int bl_pm_deinit(void)
+{
+    pm_deinit();
+
+    return 0;
+}

+ 111 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_pm.h

@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __BL_PM_H__
+#define __BL_PM_H__
+#include <stdint.h>
+#include <utils_list.h>
+
+#define    NODE_CAP_BIT_UAPSD_MODE        (1 << 0)
+#define    NODE_CAP_BIT_MAC_IDLE          (1 << 1)
+#define    NODE_CAP_BIT_MAC_DOZE          (1 << 2)
+#define    NODE_CAP_BIT_RF_ONOFF          (1 << 3)
+#define    NODE_CAP_BIT_WLAN_BLE_ABORT    (1 << 4)
+#define    NODE_CAP_BIT_FORCE_SLEEP       (1 << 5)
+#define    NODE_CAP_BIT_ALL_ALLOWED       (0xffff)
+
+enum PM_EVENT_ABLE {
+    PM_DISABLE = 0,
+    PM_ENABLE,
+};
+
+enum WLAN_CODE_SLEEP_CONTROL {
+    WLAN_CODE_PM_NOTIFY_START = 0,
+    WLAN_CODE_PM_NOTIFY_STOP,
+    WLAN_CODE_PM_START,
+    WLAN_CODE_PM_STOP,
+};
+
+enum WLAN_CODE_ENTER_SLEEP {
+    WLAN_CODE_PM_ENTER_SLEEP_PRE = 0,
+    WLAN_CODE_PM_ENTER_SLEEP,
+};
+
+enum WLAN_CODE_EXIT_SLEEP {
+    WLAN_CODE_PM_ENTER_SLEEP_PRE_FAILED = 0,
+    WLAN_CODE_PM_EXIT_SLEEP_PRE,
+    WLAN_CODE_PM_EXIT_SLEEP,
+};
+
+enum WLAN_CODE_BEACON_LOSS {
+    WLAN_CODE_BEACON_LOSS = 0,
+};
+
+enum WLAN_CODE_SEND_NULLDATA {
+   WLAN_CODE_PM_PAUSE = 0,
+   WLAN_CODE_PM_NULLDATA_NOACK,
+   WLAN_CODE_PM_NULLDATA_SEND_ERROR,
+};
+
+enum BLE_CODE_BLE_CONTROL {
+    BLE_CODE_PM_TURNON_RF = 0,
+    BLE_CODE_PM_TURNOFF_RF,
+};
+
+enum PM_LEVEL{
+    PM_MODE_STA_NONE = 0,
+    PM_MODE_STA_IDLE,
+    PM_MODE_STA_MESH,
+    PM_MODE_STA_DOZE,
+    PM_MODE_STA_COEX,
+    PM_MODE_STA_DOWN,
+    PM_MODE_AP_IDLE,
+    PM_MODE_MAX,
+};
+
+enum PM_EVEMT{
+    WLAN_PM_EVENT_CONTROL = 0,
+    WLAN_PM_EVENT_ENTER_SLEEP,
+    WLAN_PM_EVENT_EXIT_SLEEP,
+    WLAN_PM_EVENT_BEACON_LOSS,
+    WLAN_PM_EVENT_SEND_NULLDATA,
+    BLE_PM_EVENT_CONTROL,
+    PM_EVENT_MAX,
+};
+
+typedef int (*bl_pm_cb_t)(void *arg);
+
+int bl_pm_init(void);
+int bl_pm_event_register(enum PM_EVEMT event, uint32_t code, uint32_t cap_bit, uint16_t pirority, bl_pm_cb_t ops, void *arg, enum PM_EVENT_ABLE enable);
+int bl_pm_deinit(void);
+int bl_pm_state_run(void);
+int bl_pm_capacity_set(enum PM_LEVEL level);
+int pm_post_event(enum PM_EVEMT event, uint32_t code, uint32_t *retval);
+int bl_pm_event_switch(enum PM_EVEMT event, uint32_t code, enum PM_EVENT_ABLE enable);
+#endif

+ 51 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_psram.c

@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "bl_psram.h"
+#ifdef BL808
+#include <bl808_psram_uhs.h>
+#include <bl808_glb.h>
+
+int bl_psram_init(void)
+{
+    GLB_Config_UHS_PLL(GLB_XTAL_40M, uhsPllCfg_2000M);
+    Psram_UHS_x16_Init(2000);
+    printf("Done. \r\nData @0x5000_0000 is %08lx\r\n", *(uint32_t*)0x50000000);
+    return 0;
+}
+
+#elif defined(BL606P)
+#include <bl606p_glb.h>
+int bl_psram_init(void)
+{
+    puts("--> dummy PSRAM init implemented\r\n");
+    return 0;
+}
+#endif
+

+ 34 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_psram.h

@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __BL_PSRAM_H__
+#define __BL_PSRAM_H__
+
+int bl_psram_init(void);
+#endif

+ 1715 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_sdh.c

@@ -0,0 +1,1715 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <bl808_glb.h>
+#include "bl_sdh.h"
+
+#define SDH_CLK_PIN                     GLB_GPIO_PIN_0
+#define SDH_CMD_PIN                     GLB_GPIO_PIN_1
+#define SDH_DAT0_PIN                    GLB_GPIO_PIN_2
+#define SDH_DAT1_PIN                    GLB_GPIO_PIN_3
+#define SDH_DAT2_PIN                    GLB_GPIO_PIN_4
+#define SDH_DAT3_PIN                    GLB_GPIO_PIN_5
+
+#define SDH_CLK_PIN_FUN                 GPIO_FUN_SDH
+#define SDH_CMD_PIN_FUN                 GPIO_FUN_SDH
+#define SDH_DAT0_PIN_FUN                GPIO_FUN_SDH
+#define SDH_DAT1_PIN_FUN                GPIO_FUN_SDH
+#define SDH_DAT2_PIN_FUN                GPIO_FUN_SDH
+#define SDH_DAT3_PIN_FUN                GPIO_FUN_SDH
+
+
+#if SDIO_SDCARD_INT_MODE
+#define SDH_SDCARD_IRQn                 SDH_IRQn
+#endif
+
+/* Private variables ---------------------------------------------------------*/
+
+static uint32_t sdhClockInit = 400000ul;
+static uint32_t sdhClockSrc = 96000000ul;
+static uint32_t sdhClockTransfer = 48000000ul;
+
+static sd_card_t *pSDCardInfo = NULL;
+static SDH_Cfg_Type SDH_Cfg_Type_Instance;
+
+#if SDIO_SDCARD_INT_MODE
+static volatile SD_Error SDH_DataWaitStatus = SD_WAITING;
+static volatile SD_Error SDH_CMDWaitStatus = SD_WAITING;
+
+static SDH_Trans_Callback_Cfg_Type SDH_Trans_Callback_Cfg_TypeInstance;
+static SDH_Handle_Cfg_Type SDH_Handle_Cfg_TypeInstance;
+#endif
+
+static SDH_DMA_Cfg_Type SDH_DMA_Cfg_TypeInstance;
+/*causion: ADMA related variables must on OCRAM or shared ram*/
+static __EALIGN(64) SDH_ADMA2_Desc_Type adma2Entries[32];
+
+/* Private function prototypes -----------------------------------------------*/
+static void SD_DecodeCid(sd_card_t *card, uint32_t *rawCid);
+static void SD_DecodeCsd(sd_card_t *card, uint32_t *rawCsd);
+static void SD_DecodeScr(sd_card_t *card, uint32_t *rawScr);
+#if SDIO_SDCARD_INT_MODE
+static void SDH_INT_Init(void);
+#endif
+static status_t SDH_SendCardCommand(SDH_CMD_Cfg_Type *cmd);
+static void SDH_HostInit(void);
+static status_t SDH_GoIdle(void);
+static status_t SD_SendApplicationCmd(uint32_t relativeAddress);
+static status_t SD_SendInterfaceCondition(void);
+static status_t SD_ApplicationSendOperationCondition(sd_card_t *card, uint32_t argument);
+static status_t SD_AllSendCid(sd_card_t *card);
+static status_t SD_SendRca(sd_card_t *card);
+static status_t SD_SendCsd(sd_card_t *card);
+static status_t SD_SelectCard(sd_card_t *card, BL_Fun_Type NewState);
+static status_t SD_SendScr(sd_card_t *card);
+static status_t SD_SendSsr(sd_card_t *card);
+static status_t SD_SetDataBusWidth(sd_card_t *card, SDH_Data_Bus_Width_Type width);
+static status_t SD_SwitchFunction(uint32_t mode, uint32_t group, uint32_t number, uint32_t status[16]);
+static status_t SD_SelectFunction(uint32_t group, uint32_t function);
+static status_t SD_SetBlockSize(uint32_t blockSize);
+static status_t SDH_SDCardInit(uint32_t bus_wide, sd_card_t *card);
+static status_t WaitInProgramming(void);
+static status_t IsCardProgramming(uint8_t *pstatus);
+static status_t SDH_CardTransferNonBlocking(SDH_DMA_Cfg_Type *dmaCfg, SDH_Trans_Cfg_Type *transfer);
+
+static void SD_DecodeCid(sd_card_t *card, uint32_t *rawCid)
+{
+    sd_cid_t *cid;
+
+    cid = &(card->cid);
+    cid->manufacturerID = (uint8_t)((rawCid[3U] & 0xFF0000U) >> 16U);
+    cid->applicationID = (uint16_t)((rawCid[3U] & 0xFFFFU) >> 0U);
+
+    cid->productName[0U] = (uint8_t)((rawCid[1U] & 0xFF000000U) >> 24);
+    cid->productName[1U] = (uint8_t)((rawCid[2U] & 0xFF) >> 0U);
+    cid->productName[2U] = (uint8_t)((rawCid[2U] & 0xFF00U) >> 8U);
+    cid->productName[3U] = (uint8_t)((rawCid[2U] & 0xFF0000U) >> 16U);
+    cid->productName[4U] = (uint8_t)((rawCid[2U] & 0xFF000000U) >> 24U);
+
+    cid->productVersion = (uint8_t)((rawCid[1U] & 0xFF0000U) >> 16U);
+
+    cid->productSerialNumber = (uint32_t)((rawCid[1U] & 0xFFFFU) << 16U);
+    cid->productSerialNumber |= (uint32_t)((rawCid[0U] & 0xFFFF0000U) >> 16U);
+
+    cid->manufacturerData = (uint16_t)((rawCid[0U] & 0xFFFU) >> 0U);
+}
+static void SD_DecodeCsd(sd_card_t *card, uint32_t *rawCsd)
+{
+    sd_csd_t *csd;
+
+    csd = &(card->csd);
+    csd->csdStructure = (uint8_t)((rawCsd[3U] & 0xC00000U) >> 22U);
+    csd->dataReadAccessTime1 = (uint8_t)((rawCsd[3U] & 0xFF00U) >> 8U);
+    csd->dataReadAccessTime2 = (uint8_t)((rawCsd[3U] & 0xFFU) >> 0U);
+
+    csd->transferSpeed = (uint8_t)((rawCsd[2U] & 0xFF000000U) >> 24);
+    csd->cardCommandClass = (uint16_t)((rawCsd[2U] & 0xFFF000U) >> 12U);
+    csd->readBlockLength = (uint8_t)((rawCsd[2U] & 0xF00U) >> 8U);
+
+    switch (csd->csdStructure) {
+        /*csd version 1.1*/
+        case 0:
+            csd->deviceSize = (uint32_t)((rawCsd[2U] & 0x3U) << 10U);
+            csd->deviceSize |= (uint32_t)((rawCsd[1U] & 0xFFC00000U) >> 22U);
+
+            csd->deviceSizeMultiplier = (uint8_t)((rawCsd[1U] & 0x380U) >> 7U);
+
+            /* Get card total block count and block size. */
+            card->blockCount = ((csd->deviceSize + 1U) << (csd->deviceSizeMultiplier + 2U));
+            card->blockSize = (1U << (csd->readBlockLength));
+
+            if (card->blockSize != SDH_DEFAULT_BLOCK_SIZE) {
+                card->blockCount = (card->blockCount * card->blockSize);
+                card->blockSize = SDH_DEFAULT_BLOCK_SIZE;
+                card->blockCount = (card->blockCount / card->blockSize);
+            }
+
+            break;
+
+        /*csd version 2.0*/
+        case 1:
+            card->blockSize = SDH_DEFAULT_BLOCK_SIZE;
+            csd->deviceSize = (uint32_t)((rawCsd[1U] & 0x3FFFFF00U) >> 8U);
+
+            if (csd->deviceSize >= 0xFFFFU) {
+                card->flags |= SD_SupportSdxcFlag;
+            }
+
+            card->blockCount = ((csd->deviceSize + 1U) * 1024U);
+            break;
+
+        default:
+            break;
+    }
+}
+static void SD_DecodeScr(sd_card_t *card, uint32_t *rawScr)
+{
+    sd_scr_t *scr;
+
+    scr = &(card->scr);
+    scr->scrStructure = (uint8_t)((rawScr[1U] & 0xF0000000U) >> 28U);
+    scr->sdSpecification = (uint8_t)((rawScr[1U] & 0xF000000U) >> 24U);
+
+    if ((uint8_t)((rawScr[1U] & 0x800000U) >> 23U)) {
+        scr->flags |= SD_ScrDataStatusAfterErase;
+    }
+
+    scr->sdSecurity = (uint8_t)((rawScr[1U] & 0x700000U) >> 20U);
+    scr->sdBusWidths = (uint8_t)((rawScr[1U] & 0xF0000U) >> 16U);
+
+    if ((uint8_t)((rawScr[0U] & 0x8000U) >> 15U)) {
+        scr->flags |= SD_ScrSdSpecification3;
+    }
+
+    scr->extendedSecurity = (uint8_t)((rawScr[1U] & 0x7800U) >> 10U);
+    scr->commandSupport = (uint8_t)(rawScr[1U] & 0x3U);
+    scr->reservedForManufacturer = rawScr[0U];
+
+    /* Get specification version. */
+    switch (scr->sdSpecification) {
+        case 0U:
+            card->version = SD_SpecificationVersion1_0;
+            break;
+
+        case 1U:
+            card->version = SD_SpecificationVersion1_1;
+            break;
+
+        case 2U:
+            card->version = SD_SpecificationVersion2_0;
+
+            if (card->scr.flags & SD_ScrSdSpecification3) {
+                card->version = SD_SpecificationVersion3_0;
+            }
+
+            break;
+
+        default:
+            break;
+    }
+
+    if (card->scr.sdBusWidths & 0x4U) {
+        card->flags |= SD_Support4BitWidthFlag;
+    }
+
+    /* speed class control cmd */
+    if (card->scr.commandSupport & 0x01U) {
+        card->flags |= SD_SupportSpeedClassControlCmd;
+    }
+
+    /* set block count cmd */
+    if (card->scr.commandSupport & 0x02U) {
+        card->flags |= SD_SupportSetBlockCountCmd;
+    }
+}
+
+#if SDIO_SDCARD_INT_MODE
+/*!< SDH transfer complete callback */
+void SDH_DataTransferFinished_CallBack(SDH_Handle_Cfg_Type *handle, SDH_Stat_Type status, void *userData)
+{
+    //bflb_platform_printf("Interrupt occurs! intFlag=0x%02lX,\r\n",handle->intFlag);
+    if (status != SDH_STAT_SUCCESS) {
+        SDH_DataWaitStatus = SD_DataCfg_ERROR;
+    } else {
+        SDH_DataWaitStatus = SD_OK;
+    }
+}
+/*!< SDH transfer complete callback */
+void SDH_CMDTransferFinished_CallBack(SDH_Handle_Cfg_Type *handle, SDH_Stat_Type status, void *userData)
+{
+    //bflb_platform_printf("Interrupt occurs! intFlag=0x%02lX,\r\n",handle->intFlag);
+    if (status != SDH_STAT_SUCCESS) {
+        SDH_CMDWaitStatus = SD_CMD_ERROR;
+    } else {
+        SDH_CMDWaitStatus = SD_OK;
+    }
+}
+
+/****************************************************************************/ /**
+ * @brief  SDH INT init
+ *
+ * @param  None
+ *
+ * @return None
+ *
+*******************************************************************************/
+static void SDH_INT_Init(void)
+{
+	System_NVIC_SetPriority(SDH_SDCARD_IRQn, 7, 1);
+    CPU_Interrupt_Enable(SDH_SDCARD_IRQn);
+
+    SDH_EnableIntStatus(SDH_INT_ALL);
+    SDH_DisableIntSource(SDH_INT_ALL);
+    SDH_Trans_Callback_Cfg_TypeInstance.SDH_CallBack_TransferFinished = SDH_DataTransferFinished_CallBack;
+    SDH_Trans_Callback_Cfg_TypeInstance.SDH_CMDCallBack_TransferFinished = SDH_CMDTransferFinished_CallBack;
+    SDH_InstallHandleCallback(&SDH_Handle_Cfg_TypeInstance, &SDH_Trans_Callback_Cfg_TypeInstance, NULL);
+}
+#endif
+
+static status_t SDH_SendCardCommand(SDH_CMD_Cfg_Type *cmd)
+{
+    status_t errorstatus = Status_Success;
+    SD_Error sd_status;
+    uint32_t time_node;
+
+    SDH_ClearIntStatus(SDH_INT_CMD_COMPLETED | SDH_INT_CMD_ERRORS);
+
+    SDH_SendCommand(cmd);
+    time_node = (uint32_t)SDH_GET_TIME();
+
+#if SDIO_SDCARD_INT_MODE
+
+    SDH_CMDWaitStatus = SD_WAITING;
+    SDH_EnableIntSource(SDH_INT_CMD_COMPLETED | SDH_INT_CMD_ERRORS);
+
+    /*wait for Xfer status. might pending here in multi-task OS*/
+    while (SDH_CMDWaitStatus == SD_WAITING) {
+        if ((uint32_t)SDH_GET_TIME() - time_node > SDIO_CMDTIMEOUT_MS) {
+            SDH_MSG("SDH send CMD%ld timeout: %ld ms\r\n", cmd->index, (uint32_t)SDH_GET_TIME() - time_node);
+            SDH_DisableIntSource(SDH_INT_CMD_COMPLETED | SDH_INT_CMD_ERRORS);
+            return Status_Timeout;
+        }
+        BL_DRV_DUMMY;
+        BL_DRV_DUMMY;
+    }
+    sd_status = SDH_CMDWaitStatus;
+    SDH_DisableIntSource(SDH_INT_CMD_COMPLETED | SDH_INT_CMD_ERRORS);
+
+#else
+
+    uint32_t intFlag;
+    while (1) {
+        intFlag = SDH_GetIntStatus();
+        if (intFlag & SDH_INT_CMD_ERRORS) {
+            sd_status = SD_CMD_ERROR;
+            break;
+
+        } else if (intFlag & SDH_INT_CMD_COMPLETED) {
+            sd_status = SD_OK;
+            break;
+
+        } else if ((uint32_t)SDH_GET_TIME() - time_node > SDIO_CMDTIMEOUT_MS) {
+            SDH_MSG("SDH send CMD%ld timeout: %ld ms\r\n", cmd->index, (uint32_t)SDH_GET_TIME() - time_node);
+            return Status_Timeout;
+        }
+        BL_DRV_DUMMY;
+        BL_DRV_DUMMY;
+    }
+    SDH_ClearIntStatus(intFlag);
+
+#endif
+
+    // SDH_MSG("SDH send CMD%ld used time : %ld\r\n", cmd->index, (uint32_t)SDH_GET_TIME() - time_node);
+
+    if (sd_status != SD_OK) {
+        SDH_MSG("SDH send CMD%ld error\r\n", cmd->index);
+        errorstatus = Status_SDH_CmdResponseError;
+    } else {
+        SDH_GetCmdResp(cmd);
+        SDH_MSG("SDH send CMD%ld success\r\n", cmd->index);
+    }
+
+    return errorstatus;
+}
+
+static void SDH_GPIO_Init(uint32_t bus_wide)
+{
+    GLB_GPIO_Cfg_Type cfg;
+    uint8_t gpiopins[6];
+    uint8_t gpiofuns[6];
+    uint8_t i = 0;
+
+    cfg.gpioMode = GPIO_MODE_AF;
+    cfg.pullType = GPIO_PULL_UP;
+    cfg.drive = 2;
+    cfg.smtCtrl = 1;
+
+    gpiopins[0] = SDH_CLK_PIN;
+    gpiopins[1] = SDH_CMD_PIN;
+    gpiopins[2] = SDH_DAT0_PIN;
+    gpiopins[3] = SDH_DAT1_PIN;
+    gpiopins[4] = SDH_DAT2_PIN;
+    gpiopins[5] = SDH_DAT3_PIN;
+
+    gpiofuns[0] = SDH_CLK_PIN_FUN;
+    gpiofuns[1] = SDH_CMD_PIN_FUN;
+    gpiofuns[2] = SDH_DAT0_PIN_FUN;
+    gpiofuns[3] = SDH_DAT1_PIN_FUN;
+    gpiofuns[4] = SDH_DAT2_PIN_FUN;
+    gpiofuns[5] = SDH_DAT3_PIN_FUN;
+    switch (bus_wide) {
+        case SDH_DATA_BUS_WIDTH_1BIT:
+            for (i = 1; i < sizeof(gpiopins) - 3; i++) {
+                cfg.gpioPin = gpiopins[i];
+                cfg.gpioFun = gpiofuns[i];
+                GLB_GPIO_Init(&cfg);
+            }
+            break;
+
+        case SDH_DATA_BUS_WIDTH_4BITS:
+            for (i = 1; i < sizeof(gpiopins); i++) {
+                cfg.gpioPin = gpiopins[i];
+                cfg.gpioFun = gpiofuns[i];
+                GLB_GPIO_Init(&cfg);
+            }
+            break;
+
+        /*set 1bit as default*/
+        default:
+            for (i = 1; i < sizeof(gpiopins) - 3; i++) {
+                cfg.gpioPin = gpiopins[i];
+                cfg.gpioFun = gpiofuns[i];
+                GLB_GPIO_Init(&cfg);
+            }
+            break;
+    }
+
+    cfg.gpioPin = gpiopins[0];
+    cfg.gpioFun = gpiofuns[0];
+    cfg.pullType = GPIO_PULL_NONE;
+    GLB_GPIO_Init(&cfg);
+}
+
+static void SDH_HostInit(void)
+{
+    /* initialise SDH controller*/
+    SDH_Cfg_Type_Instance.vlot18Enable = DISABLE;
+    SDH_Cfg_Type_Instance.highSpeed = ENABLE;
+    SDH_Cfg_Type_Instance.dataWidth = SDH_DATA_BUS_WIDTH_1BIT;
+    SDH_Cfg_Type_Instance.volt = SDH_VOLTAGE_3P3V;
+    SDH_Cfg_Type_Instance.srcClock = sdhClockSrc;
+    SDH_Cfg_Type_Instance.busClock = sdhClockInit;
+    SDH_Ctrl_Init(&SDH_Cfg_Type_Instance);
+
+    /*setup timeout counter*/
+    SDH_Set_Timeout(0x0e);
+
+    /*power on host controller*/
+    SDH_Powon();
+}
+
+/*
+* GO_IDLE_STATE, send card to reset state
+*/
+static status_t SDH_GoIdle(void)
+{
+    status_t errorstatus = Status_Success;
+    SDH_CMD_Cfg_Type SDH_CMD_Cfg_TypeInstance;
+
+    /*CMD0: GO_IDLE_STATE, send card to reset state*/
+    SDH_CMD_Cfg_TypeInstance.index = SD_CMD_GO_IDLE_STATE;
+    SDH_CMD_Cfg_TypeInstance.argument = 0;
+    SDH_CMD_Cfg_TypeInstance.type = SDH_CMD_NORMAL;
+    SDH_CMD_Cfg_TypeInstance.respType = SDH_RESP_NONE;
+    SDH_CMD_Cfg_TypeInstance.flag = SDH_TRANS_FLAG_NONE;
+
+    errorstatus = SDH_SendCardCommand(&SDH_CMD_Cfg_TypeInstance);
+    return errorstatus;
+}
+
+static status_t SD_SendApplicationCmd(uint32_t relativeAddress)
+{
+    status_t errorstatus = Status_Success;
+    SDH_CMD_Cfg_Type SDH_CMD_Cfg_TypeInstance;
+
+    /* send CMD55 */
+    SDH_CMD_Cfg_TypeInstance.index = SD_CMD_APP_CMD;
+    SDH_CMD_Cfg_TypeInstance.argument = relativeAddress;
+    SDH_CMD_Cfg_TypeInstance.type = SDH_CMD_NORMAL;
+    SDH_CMD_Cfg_TypeInstance.respType = SDH_RESP_R1;
+    SDH_CMD_Cfg_TypeInstance.flag = SDH_TRANS_FLAG_NONE;
+
+    errorstatus = SDH_SendCardCommand(&SDH_CMD_Cfg_TypeInstance);
+
+    if (errorstatus != Status_Success) {
+        return Status_SDH_CmdResponseError;
+    } else if (SDH_CMD_Cfg_TypeInstance.response[0] & SD_CSR_ERRORBITS) {
+        return Status_SDH_CmdResponseError;
+    }
+
+    return errorstatus;
+}
+
+static status_t SD_SendInterfaceCondition(void)
+{
+    status_t errorstatus = Status_Success;
+    SDH_CMD_Cfg_Type SDH_CMD_Cfg_TypeInstance;
+
+    /* CMD8: SEND_IF_COND */
+    SDH_CMD_Cfg_TypeInstance.index = SD_CMD_HS_SEND_EXT_CSD;
+    SDH_CMD_Cfg_TypeInstance.argument = SD_CHECK_PATTERN;
+    SDH_CMD_Cfg_TypeInstance.type = SDH_CMD_NORMAL;
+    SDH_CMD_Cfg_TypeInstance.respType = SDH_RESP_R7;
+    SDH_CMD_Cfg_TypeInstance.flag = SDH_TRANS_FLAG_NONE;
+
+    errorstatus = SDH_SendCardCommand(&SDH_CMD_Cfg_TypeInstance);
+
+    if (errorstatus != Status_Success) {
+        return Status_SDH_CmdResponseError;
+    }
+
+    SDH_MSG("Response to CMD8 is: 0x%02lX.\r\n", SDH_CMD_Cfg_TypeInstance.response[0]);
+
+    if ((SDH_CMD_Cfg_TypeInstance.response[0U] & 0xFFU) != (SD_CHECK_PATTERN & 0xff)) {
+        return Status_SDH_CardNotSupport;
+    }
+
+    return errorstatus;
+}
+
+static status_t SD_ApplicationSendOperationCondition(sd_card_t *card, uint32_t argument)
+{
+    status_t errorstatus = Status_Success;
+    uint32_t response = 0, count = 0, validvoltage = 0;
+    SDH_CMD_Cfg_Type SDH_CMD_Cfg_TypeInstance;
+
+    do {
+        if (Status_Success != (errorstatus = SD_SendApplicationCmd(0))) {
+            return errorstatus;
+        }
+
+        /*ACMD41*/
+        SDH_CMD_Cfg_TypeInstance.index = SD_CMD_SD_APP_OP_COND;
+        SDH_CMD_Cfg_TypeInstance.argument = argument;
+        SDH_CMD_Cfg_TypeInstance.type = SDH_CMD_NORMAL;
+        SDH_CMD_Cfg_TypeInstance.respType = SDH_RESP_R3;
+        SDH_CMD_Cfg_TypeInstance.flag = SDH_TRANS_FLAG_NONE;
+
+        errorstatus = SDH_SendCardCommand(&SDH_CMD_Cfg_TypeInstance);
+
+        if (errorstatus != Status_Success) {
+            return Status_SDH_CmdResponseError;
+        }
+
+        response = SDH_CMD_Cfg_TypeInstance.response[0];
+        validvoltage = (((response >> 31) == 1) ? 1 : 0);
+        count++;
+    } while ((!validvoltage) && (count < SD_MAX_VOLT_TRIAL));
+
+    if (count == SD_MAX_VOLT_TRIAL) {
+        return Status_Timeout;
+    } else {
+        card->ocr = response;
+
+        if (response &= SD_OcrHostCapacitySupportFlag) {
+            /* change from sdsc to sdhc */
+            card->flags |= SD_SupportHighCapacityFlag;
+        }
+    }
+
+    return errorstatus;
+}
+static status_t SD_AllSendCid(sd_card_t *card)
+{
+    status_t errorstatus = Status_Success;
+    SDH_CMD_Cfg_Type SDH_CMD_Cfg_TypeInstance;
+
+    /* CMD2: SD_CMD_ALL_SEND_CID */
+    SDH_CMD_Cfg_TypeInstance.index = SD_CMD_ALL_SEND_CID;
+    SDH_CMD_Cfg_TypeInstance.argument = 0;
+    SDH_CMD_Cfg_TypeInstance.type = SDH_CMD_NORMAL;
+    SDH_CMD_Cfg_TypeInstance.respType = SDH_RESP_R2;
+    SDH_CMD_Cfg_TypeInstance.flag = SDH_TRANS_FLAG_NONE;
+
+    errorstatus = SDH_SendCardCommand(&SDH_CMD_Cfg_TypeInstance);
+
+    if (errorstatus != Status_Success) {
+        return Status_SDH_CmdResponseError;
+    }
+
+    card->rawCid[0] = SDH_CMD_Cfg_TypeInstance.response[0];
+    card->rawCid[1] = SDH_CMD_Cfg_TypeInstance.response[1];
+    card->rawCid[2] = SDH_CMD_Cfg_TypeInstance.response[2];
+    card->rawCid[3] = SDH_CMD_Cfg_TypeInstance.response[3];
+
+    SD_DecodeCid(card, card->rawCid);
+
+    return errorstatus;
+}
+
+static status_t SD_SendRca(sd_card_t *card)
+{
+    status_t errorstatus = Status_Success;
+    SDH_CMD_Cfg_Type SDH_CMD_Cfg_TypeInstance;
+
+    /*CMD3: send relative card address*/
+    SDH_CMD_Cfg_TypeInstance.index = SD_CMD_SET_REL_ADDR;
+    SDH_CMD_Cfg_TypeInstance.argument = 0;
+    SDH_CMD_Cfg_TypeInstance.type = SDH_CMD_NORMAL;
+    SDH_CMD_Cfg_TypeInstance.respType = SDH_RESP_R6;
+    SDH_CMD_Cfg_TypeInstance.flag = SDH_TRANS_FLAG_NONE;
+
+    errorstatus = SDH_SendCardCommand(&SDH_CMD_Cfg_TypeInstance);
+
+    if (errorstatus != Status_Success) {
+        return Status_SDH_CmdResponseError;
+    }
+
+    card->relativeAddress = SDH_CMD_Cfg_TypeInstance.response[0] >> 16;
+
+    return errorstatus;
+}
+
+static status_t SD_SendCsd(sd_card_t *card)
+{
+    status_t errorstatus = Status_Success;
+    SDH_CMD_Cfg_Type SDH_CMD_Cfg_TypeInstance;
+
+    /*CMD9: send card-specific data(CSD)*/
+    SDH_CMD_Cfg_TypeInstance.index = SD_CMD_SEND_CSD;
+    SDH_CMD_Cfg_TypeInstance.argument = (uint32_t)((card->relativeAddress) << 16);
+    SDH_CMD_Cfg_TypeInstance.type = SDH_CMD_NORMAL;
+    SDH_CMD_Cfg_TypeInstance.respType = SDH_RESP_R2;
+    SDH_CMD_Cfg_TypeInstance.flag = SDH_TRANS_FLAG_NONE;
+
+    errorstatus = SDH_SendCardCommand(&SDH_CMD_Cfg_TypeInstance);
+
+    if (errorstatus != Status_Success) {
+        return Status_SDH_CmdResponseError;
+    }
+
+    card->rawCsd[0] = SDH_CMD_Cfg_TypeInstance.response[0];
+    card->rawCsd[1] = SDH_CMD_Cfg_TypeInstance.response[1];
+    card->rawCsd[2] = SDH_CMD_Cfg_TypeInstance.response[2];
+    card->rawCsd[3] = SDH_CMD_Cfg_TypeInstance.response[3];
+
+    SD_DecodeCsd(card, card->rawCsd);
+
+    return errorstatus;
+}
+
+static status_t SD_SelectCard(sd_card_t *card, BL_Fun_Type NewState)
+{
+    status_t errorstatus = Status_Success;
+    SDH_CMD_Cfg_Type SDH_CMD_Cfg_TypeInstance;
+
+    /* CMD7: select/deselect specified card */
+    SDH_CMD_Cfg_TypeInstance.index = SD_CMD_SEL_DESEL_CARD;
+
+    if (NewState == ENABLE) {
+        SDH_CMD_Cfg_TypeInstance.argument = (uint32_t)((card->relativeAddress) << 16);
+        SDH_CMD_Cfg_TypeInstance.respType = SDH_RESP_R1B;
+    } else {
+        SDH_CMD_Cfg_TypeInstance.argument = 0;
+        SDH_CMD_Cfg_TypeInstance.respType = SDH_RESP_NONE;
+    }
+
+    SDH_CMD_Cfg_TypeInstance.type = SDH_CMD_NORMAL;
+    SDH_CMD_Cfg_TypeInstance.flag = SDH_TRANS_FLAG_NONE;
+
+    errorstatus = SDH_SendCardCommand(&SDH_CMD_Cfg_TypeInstance);
+
+    if (errorstatus != Status_Success) {
+        return Status_SDH_TransferFailed;
+    } else if ((NewState == ENABLE) && (SDH_CMD_Cfg_TypeInstance.response[0] & SD_CSR_ERRORBITS)) {
+        return Status_SDH_CmdResponseError;
+    }
+
+    return errorstatus;
+}
+
+/* get CSR */
+static status_t SD_SendScr(sd_card_t *card)
+{
+    status_t errorstatus = Status_Success;
+    SDH_Stat_Type stat = SDH_STAT_SUCCESS;
+    SD_Error sd_status;
+
+    SDH_CMD_Cfg_Type SDH_CMD_Cfg_TypeInstance;
+    SDH_Data_Cfg_Type SDH_Data_Cfg_TypeInstance;
+    uint32_t tempscr[2] = { 0, 0 };
+    uint32_t time_node;
+
+    /* send CMD55 */
+    errorstatus = SD_SendApplicationCmd((uint32_t)((card->relativeAddress) << 16));
+
+    if (errorstatus != Status_Success) {
+        goto out;
+    }
+
+    /*!< Set Block Size To 8 Bytes */
+    SDH_Data_Cfg_TypeInstance.enableAutoCommand12 = DISABLE;
+    SDH_Data_Cfg_TypeInstance.enableAutoCommand23 = DISABLE;
+    SDH_Data_Cfg_TypeInstance.enableIgnoreError = DISABLE;
+    SDH_Data_Cfg_TypeInstance.dataType = SDH_TRANS_DATA_NORMAL;
+    SDH_Data_Cfg_TypeInstance.blockSize = 8;
+    SDH_Data_Cfg_TypeInstance.blockCount = 1;
+    SDH_Data_Cfg_TypeInstance.rxDataLen = 0;
+    SDH_Data_Cfg_TypeInstance.rxData = tempscr;
+    SDH_Data_Cfg_TypeInstance.txDataLen = 0;
+    SDH_Data_Cfg_TypeInstance.txData = NULL;
+    /* Config the data transfer parameter */
+    stat = SDH_ConfigDataTranfer(&SDH_Data_Cfg_TypeInstance);
+
+    if (SDH_STAT_SUCCESS != stat) {
+        return Status_SDH_TransferFailed;
+    }
+
+    /*!< Send ACMD51 SD_APP_SEND_SCR with argument as 0 */
+    SDH_CMD_Cfg_TypeInstance.index = SD_CMD_SD_APP_SEND_SCR;
+    SDH_CMD_Cfg_TypeInstance.argument = 0;
+    SDH_CMD_Cfg_TypeInstance.type = SDH_CMD_NORMAL;
+    SDH_CMD_Cfg_TypeInstance.respType = SDH_RESP_R1;
+    SDH_CMD_Cfg_TypeInstance.flag = SDH_TRANS_FLAG_DATA_PRESENT;
+
+    errorstatus = SDH_SendCardCommand(&SDH_CMD_Cfg_TypeInstance);
+
+    if (errorstatus != Status_Success) {
+        goto out;
+    } else if (SDH_CMD_Cfg_TypeInstance.response[0] & SD_CSR_ERRORBITS) {
+        errorstatus = Status_SDH_CmdResponseError;
+        goto out;
+    }
+
+    /* Waiting for CSR data */
+    time_node = (uint32_t)SDH_GET_TIME();
+
+#if SDIO_SDCARD_INT_MODE
+
+    SDH_DataWaitStatus = SD_WAITING;
+    SDH_EnableIntSource(SDH_INT_BUFFER_READ_READY | SDH_INT_DATA_COMPLETED | SDH_INT_DATA_ERRORS | SDH_INT_DMA_ERROR | SDH_INT_AUTO_CMD12_ERROR);
+
+    /*wait for Xfer status. might pending here in multi-task OS*/
+    while (SDH_DataWaitStatus == SD_WAITING) {
+        if ((uint32_t)SDH_GET_TIME() - time_node > SDIO_CMDTIMEOUT_MS) {
+            SDH_MSG("sdh get csr data timeout: %ld ms\r\n", (uint32_t)SDH_GET_TIME() - time_node);
+            SDH_DisableIntSource(SDH_INT_BUFFER_READ_READY | SDH_INT_DATA_COMPLETED | SDH_INT_DATA_ERRORS | SDH_INT_DMA_ERROR | SDH_INT_AUTO_CMD12_ERROR);
+            errorstatus = Status_Timeout;
+            goto out;
+        }
+        BL_DRV_DUMMY;
+        BL_DRV_DUMMY;
+    }
+
+    SDH_DisableIntSource(SDH_INT_BUFFER_READ_READY | SDH_INT_DATA_COMPLETED | SDH_INT_DATA_ERRORS | SDH_INT_DMA_ERROR | SDH_INT_AUTO_CMD12_ERROR);
+    sd_status = SDH_DataWaitStatus;
+
+#else
+
+    uint32_t intFlag;
+    while (1) {
+        intFlag = SDH_GetIntStatus();
+        if (intFlag & SDH_INT_DATA_ERRORS || intFlag & SDH_INT_DMA_ERROR) {
+            sd_status = SD_DataCfg_ERROR;
+            break;
+
+        } else if (intFlag & SDH_INT_BUFFER_READ_READY || intFlag & SDH_INT_DATA_COMPLETED) {
+            sd_status = SD_OK;
+            break;
+
+        } else if ((uint32_t)SDH_GET_TIME() - time_node > SDIO_CMDTIMEOUT_MS) {
+            SDH_MSG("SDH get csr data timeout: %ld ms\r\n", (uint32_t)SDH_GET_TIME() - time_node);
+            return Status_Timeout;
+        }
+        BL_DRV_DUMMY;
+        BL_DRV_DUMMY;
+    }
+    SDH_ClearIntStatus(intFlag);
+
+#endif
+
+    if (sd_status == SD_OK) {
+        SDH_ReadDataPort(&SDH_Data_Cfg_TypeInstance);
+        card->rawScr[1] = ((tempscr[0] & SD_0TO7BITS) << 24) | ((tempscr[0] & SD_8TO15BITS) << 8) | ((tempscr[0] & SD_16TO23BITS) >> 8) | ((tempscr[0] & SD_24TO31BITS) >> 24);
+        card->rawScr[0] = ((tempscr[1] & SD_0TO7BITS) << 24) | ((tempscr[1] & SD_8TO15BITS) << 8) | ((tempscr[1] & SD_16TO23BITS) >> 8) | ((tempscr[1] & SD_24TO31BITS) >> 24);
+        SD_DecodeScr(card, card->rawScr);
+        SDH_MSG("SDH get csr success\r\n");
+    } else {
+        errorstatus = Status_SDH_TransferFailed;
+        SDH_MSG("SDH get csr failed\r\n");
+        goto out;
+    }
+
+out:
+    return errorstatus;
+}
+
+/* get SSR */
+static status_t SD_SendSsr(sd_card_t *card)
+{
+    status_t errorstatus = Status_Success;
+    SDH_Stat_Type stat = SDH_STAT_SUCCESS;
+    SD_Error sd_status;
+    uint32_t time_node;
+
+    SDH_CMD_Cfg_Type SDH_CMD_Cfg_TypeInstance;
+    SDH_Data_Cfg_Type SDH_Data_Cfg_TypeInstance;
+
+    errorstatus = SD_SendApplicationCmd((uint32_t)((card->relativeAddress) << 16));
+
+    if (errorstatus != Status_Success) {
+        goto out;
+    }
+
+    /*!< Set Block Size To 512 Bytes */
+    SDH_Data_Cfg_TypeInstance.enableAutoCommand12 = DISABLE;
+    SDH_Data_Cfg_TypeInstance.enableAutoCommand23 = DISABLE;
+    SDH_Data_Cfg_TypeInstance.enableIgnoreError = DISABLE;
+    SDH_Data_Cfg_TypeInstance.dataType = SDH_TRANS_DATA_NORMAL;
+    SDH_Data_Cfg_TypeInstance.blockSize = 64;
+    SDH_Data_Cfg_TypeInstance.blockCount = 1;
+    SDH_Data_Cfg_TypeInstance.rxDataLen = 0;
+    SDH_Data_Cfg_TypeInstance.rxData = card->rawSsr;
+    SDH_Data_Cfg_TypeInstance.txDataLen = 0;
+    SDH_Data_Cfg_TypeInstance.txData = NULL;
+    /* Config the data transfer parameter */
+    stat = SDH_ConfigDataTranfer(&SDH_Data_Cfg_TypeInstance);
+
+    if (SDH_STAT_SUCCESS != stat) {
+        return Status_SDH_TransferFailed;
+    }
+
+    /*!< Send ACMD13 SD_APP_SEND_SCR with argument as 0 */
+    SDH_CMD_Cfg_TypeInstance.index = SD_CMD_SD_APP_STAUS;
+    SDH_CMD_Cfg_TypeInstance.argument = 0;
+    SDH_CMD_Cfg_TypeInstance.type = SDH_CMD_NORMAL;
+    SDH_CMD_Cfg_TypeInstance.respType = SDH_RESP_R1;
+    SDH_CMD_Cfg_TypeInstance.flag = SDH_TRANS_FLAG_DATA_PRESENT;
+
+    errorstatus = SDH_SendCardCommand(&SDH_CMD_Cfg_TypeInstance);
+
+    if (errorstatus != Status_Success) {
+        goto out;
+    } else if (SDH_CMD_Cfg_TypeInstance.response[0] & SD_CSR_ERRORBITS) {
+        errorstatus = Status_SDH_CmdResponseError;
+        goto out;
+    }
+
+    /* Waiting for SSR data */
+    time_node = (uint32_t)SDH_GET_TIME();
+
+#if SDIO_SDCARD_INT_MODE
+
+    SDH_DataWaitStatus = SD_WAITING;
+    SDH_EnableIntSource(SDH_INT_BUFFER_READ_READY | SDH_INT_DATA_COMPLETED | SDH_INT_DATA_ERRORS | SDH_INT_DMA_ERROR | SDH_INT_AUTO_CMD12_ERROR);
+
+    /*wait for Xfer status. might pending here in multi-task OS*/
+    while (SDH_DataWaitStatus == SD_WAITING) {
+        if ((uint32_t)SDH_GET_TIME() - time_node > SDIO_CMDTIMEOUT_MS) {
+            SDH_MSG("SDH get ssr data timeout: %ld ms\r\n", (uint32_t)SDH_GET_TIME() - time_node);
+            SDH_DisableIntSource(SDH_INT_BUFFER_READ_READY | SDH_INT_DATA_COMPLETED | SDH_INT_DATA_ERRORS | SDH_INT_DMA_ERROR | SDH_INT_AUTO_CMD12_ERROR);
+            errorstatus = Status_Timeout;
+            goto out;
+        }
+        BL_DRV_DUMMY;
+        BL_DRV_DUMMY;
+    }
+
+    SDH_DisableIntSource(SDH_INT_BUFFER_READ_READY | SDH_INT_DATA_COMPLETED | SDH_INT_DATA_ERRORS | SDH_INT_DMA_ERROR | SDH_INT_AUTO_CMD12_ERROR);
+    sd_status = SDH_DataWaitStatus;
+
+#else
+
+    uint32_t intFlag;
+    while (1) {
+        intFlag = SDH_GetIntStatus();
+        if (intFlag & SDH_INT_DATA_ERRORS || intFlag & SDH_INT_DMA_ERROR) {
+            sd_status = SD_DataCfg_ERROR;
+            break;
+
+        } else if (intFlag & SDH_INT_BUFFER_READ_READY || intFlag & SDH_INT_DATA_COMPLETED) {
+            sd_status = SD_OK;
+            break;
+
+        } else if ((uint32_t)SDH_GET_TIME() - time_node > SDIO_CMDTIMEOUT_MS) {
+            SDH_MSG("SDH get ssr data timeout: %ld ms\r\n", (uint32_t)SDH_GET_TIME() - time_node);
+            errorstatus = Status_Timeout;
+            goto out;
+        }
+        BL_DRV_DUMMY;
+        BL_DRV_DUMMY;
+    }
+    SDH_ClearIntStatus(intFlag);
+
+#endif
+
+    if (sd_status == SD_OK) {
+        SDH_ReadDataPort(&SDH_Data_Cfg_TypeInstance);
+        SDH_MSG("SDH get ssr success\r\n");
+    } else {
+        errorstatus = Status_SDH_TransferFailed;
+        SDH_MSG("SDH get ssr failed\r\n");
+        goto out;
+    }
+
+out:
+    return errorstatus;
+}
+
+/* Set Data Bus Width */
+static status_t SD_SetDataBusWidth(sd_card_t *card, SDH_Data_Bus_Width_Type width)
+{
+    status_t errorstatus = Status_Success;
+    SDH_CMD_Cfg_Type SDH_CMD_Cfg_TypeInstance;
+
+    if (width == SDH_DATA_BUS_WIDTH_1BIT) {
+        SDH_CMD_Cfg_TypeInstance.argument = 0;
+    } else if (width == SDH_DATA_BUS_WIDTH_4BITS) {
+        SDH_CMD_Cfg_TypeInstance.argument = 2;
+    } else {
+        return Status_InvalidArgument;
+    }
+
+    errorstatus = SD_SendApplicationCmd((uint32_t)((card->relativeAddress) << 16));
+
+    if (errorstatus != Status_Success) {
+        goto out;
+    }
+
+    /*!< Send ACMD6 APP_CMD with argument as 2 for wide bus mode */
+    SDH_CMD_Cfg_TypeInstance.index = SD_CMD_APP_SD_SET_BUSWIDTH;
+
+    SDH_CMD_Cfg_TypeInstance.type = SDH_CMD_NORMAL;
+    SDH_CMD_Cfg_TypeInstance.respType = SDH_RESP_R1;
+    SDH_CMD_Cfg_TypeInstance.flag = SDH_TRANS_FLAG_NONE;
+
+    errorstatus = SDH_SendCardCommand(&SDH_CMD_Cfg_TypeInstance);
+
+    if (errorstatus != Status_Success) {
+        goto out;
+    } else if (SDH_CMD_Cfg_TypeInstance.response[0] & SD_CSR_ERRORBITS) {
+        errorstatus = Status_SDH_CmdResponseError;
+        goto out;
+    }
+
+    /* reinitialise SDH controller*/
+    SDH_Cfg_Type_Instance.vlot18Enable = DISABLE;
+    SDH_Cfg_Type_Instance.highSpeed = ENABLE;
+    SDH_Cfg_Type_Instance.dataWidth = width;
+    SDH_Cfg_Type_Instance.volt = SDH_VOLTAGE_3P3V;
+    SDH_Cfg_Type_Instance.srcClock = sdhClockSrc;
+    SDH_Cfg_Type_Instance.busClock = sdhClockTransfer;
+    SDH_Ctrl_Init(&SDH_Cfg_Type_Instance);
+
+out:
+    return errorstatus;
+}
+
+/* switch function
+   mode: 0 check function, 1 set function
+   group: group number,1~6
+   number:
+ */
+static status_t SD_SwitchFunction(uint32_t mode, uint32_t group, uint32_t number, uint32_t status[16])
+{
+    status_t errorstatus = Status_Success;
+    SDH_Stat_Type stat = SDH_STAT_SUCCESS;
+    SD_Error sd_status;
+    uint32_t time_node;
+
+    SDH_CMD_Cfg_Type SDH_CMD_Cfg_TypeInstance;
+    SDH_Data_Cfg_Type SDH_Data_Cfg_TypeInstance;
+
+    /*!< Set Block Size To 64 Bytes */
+    SDH_Data_Cfg_TypeInstance.enableAutoCommand12 = DISABLE;
+    SDH_Data_Cfg_TypeInstance.enableAutoCommand23 = DISABLE;
+    SDH_Data_Cfg_TypeInstance.enableIgnoreError = DISABLE;
+    SDH_Data_Cfg_TypeInstance.dataType = SDH_TRANS_DATA_NORMAL;
+    SDH_Data_Cfg_TypeInstance.blockSize = 64;
+    SDH_Data_Cfg_TypeInstance.blockCount = 1;
+    SDH_Data_Cfg_TypeInstance.rxDataLen = 0;
+    SDH_Data_Cfg_TypeInstance.rxData = status;
+    SDH_Data_Cfg_TypeInstance.txDataLen = 0;
+    SDH_Data_Cfg_TypeInstance.txData = NULL;
+    /* Config the data transfer parameter */
+    stat = SDH_ConfigDataTranfer(&SDH_Data_Cfg_TypeInstance);
+
+    if (SDH_STAT_SUCCESS != stat) {
+        return Status_SDH_TransferFailed;
+    }
+
+    /*!< Send CMD6 SD_CMD_HS_SWITCH with argument as 0 */
+    SDH_CMD_Cfg_TypeInstance.index = SD_CMD_HS_SWITCH;
+    SDH_CMD_Cfg_TypeInstance.argument = (mode << 31U | 0x00FFFFFFU);
+    SDH_CMD_Cfg_TypeInstance.argument &= ~((uint32_t)(0xFU) << (group * 4U));
+    SDH_CMD_Cfg_TypeInstance.argument |= (number << (group * 4U));
+    SDH_CMD_Cfg_TypeInstance.type = SDH_CMD_NORMAL;
+    SDH_CMD_Cfg_TypeInstance.respType = SDH_RESP_R1;
+    SDH_CMD_Cfg_TypeInstance.flag = SDH_TRANS_FLAG_DATA_PRESENT;
+
+    errorstatus = SDH_SendCardCommand(&SDH_CMD_Cfg_TypeInstance);
+
+    if (errorstatus != Status_Success) {
+        goto out;
+    } else if (SDH_CMD_Cfg_TypeInstance.response[0] & SD_CSR_ERRORBITS) {
+        errorstatus = Status_SDH_CmdResponseError;
+        goto out;
+    }
+
+    /* Waiting for CSR data */
+    time_node = (uint32_t)SDH_GET_TIME();
+
+#if SDIO_SDCARD_INT_MODE
+
+    SDH_DataWaitStatus = SD_WAITING;
+    SDH_EnableIntSource(SDH_INT_BUFFER_READ_READY | SDH_INT_DATA_COMPLETED | SDH_INT_DATA_ERRORS | SDH_INT_DMA_ERROR);
+
+    /*wait for Xfer status. might pending here in multi-task OS*/
+    while (SDH_DataWaitStatus == SD_WAITING) {
+        if ((uint32_t)SDH_GET_TIME() - time_node > SDIO_CMDTIMEOUT_MS) {
+            SDH_MSG("SDH get CMD6 status data timeout: %ld ms\r\n", (uint32_t)SDH_GET_TIME() - time_node);
+            SDH_DisableIntSource(SDH_INT_BUFFER_READ_READY | SDH_INT_DATA_COMPLETED | SDH_INT_DATA_ERRORS | SDH_INT_DMA_ERROR);
+            errorstatus = Status_Timeout;
+            goto out;
+        }
+        BL_DRV_DUMMY;
+        BL_DRV_DUMMY;
+    }
+
+    SDH_DisableIntSource(SDH_INT_BUFFER_READ_READY | SDH_INT_DATA_COMPLETED | SDH_INT_DATA_ERRORS | SDH_INT_DMA_ERROR);
+    sd_status = SDH_DataWaitStatus;
+
+#else
+
+    uint32_t intFlag;
+    while (1) {
+        intFlag = SDH_GetIntStatus();
+        if (intFlag & SDH_INT_DATA_ERRORS || intFlag & SDH_INT_DMA_ERROR) {
+            sd_status = SD_DataCfg_ERROR;
+            break;
+
+        } else if (intFlag & SDH_INT_BUFFER_READ_READY || intFlag & SDH_INT_DATA_COMPLETED) {
+            sd_status = SD_OK;
+            break;
+
+        } else if ((uint32_t)SDH_GET_TIME() - time_node > SDIO_CMDTIMEOUT_MS) {
+            SDH_MSG("SDH get CMD6 status data timeout: %ld ms\r\n", (uint32_t)SDH_GET_TIME() - time_node);
+            return Status_Timeout;
+        }
+        BL_DRV_DUMMY;
+        BL_DRV_DUMMY;
+    }
+    SDH_ClearIntStatus(intFlag);
+
+#endif
+
+    if (sd_status == SD_OK) {
+        SDH_ReadDataPort(&SDH_Data_Cfg_TypeInstance);
+        SDH_MSG("SDH get CMD6 status data success\r\n");
+    } else {
+        errorstatus = Status_SDH_TransferFailed;
+        SDH_MSG("SDH get CMD6 status data failed\r\n");
+        goto out;
+    }
+
+out:
+    return errorstatus;
+}
+
+/*  */
+static ATTR_USED status_t SD_SelectFunction(uint32_t group, uint32_t function)
+{
+    status_t errorstatus = Status_Success;
+    uint32_t cmd6Status[16] = { 0 };
+    uint16_t functionGroupInfo[6U] = { 0 };
+    uint32_t currentFunctionStatus = 0U;
+
+    uint32_t i;
+
+    /* Check if card support high speed mode. */
+    if (Status_Success != SD_SwitchFunction(SDH_SwitchCheck, group, function, cmd6Status)) {
+        return Status_SDH_SDIO_SwitchHighSpeedFail;
+    }
+
+    for (i = 0; i < 16; i++) {
+        SDH_MSG("cmd6Status[%ld]=0x%lX.\r\n", i, cmd6Status[i]);
+    }
+
+    /* In little endian mode, SD bus byte transferred first is the byte stored in lowest byte position in
+    a word which will cause 4 byte's sequence in a word is not consistent with their original sequence from
+    card. So the sequence of 4 bytes received in a word should be converted. */
+    cmd6Status[0U] = SWAP_WORD_BYTE_SEQUENCE(cmd6Status[0U]);
+    cmd6Status[1U] = SWAP_WORD_BYTE_SEQUENCE(cmd6Status[1U]);
+    cmd6Status[2U] = SWAP_WORD_BYTE_SEQUENCE(cmd6Status[2U]);
+    cmd6Status[3U] = SWAP_WORD_BYTE_SEQUENCE(cmd6Status[3U]);
+    cmd6Status[4U] = SWAP_WORD_BYTE_SEQUENCE(cmd6Status[4U]);
+
+    functionGroupInfo[5U] = (uint16_t)cmd6Status[0U];
+    functionGroupInfo[4U] = (uint16_t)(cmd6Status[1U] >> 16U);
+    functionGroupInfo[3U] = (uint16_t)(cmd6Status[1U]);
+    functionGroupInfo[2U] = (uint16_t)(cmd6Status[2U] >> 16U);
+    functionGroupInfo[1U] = (uint16_t)(cmd6Status[2U]);
+    functionGroupInfo[0U] = (uint16_t)(cmd6Status[3U] >> 16U);
+    currentFunctionStatus = ((cmd6Status[3U] & 0xFFFFU) << 8U) | (cmd6Status[4U] >> 24U);
+
+    for (i = 0; i < 6; i++) {
+        SDH_MSG("functionGroupInfo[%ld]=0x%X.\r\n", i, functionGroupInfo[i]);
+    }
+
+    SDH_MSG("currentFunctionStatus = 0x%lX.\r\n", currentFunctionStatus);
+
+    /* check if function is support */
+    if (((functionGroupInfo[group] & (1 << function)) == 0U) ||
+        ((currentFunctionStatus >> (group * 4U)) & 0xFU) != function) {
+        return Status_SDH_SDIO_SwitchHighSpeedFail;
+    }
+
+    /* Check if card support high speed mode. */
+    if (Status_Success != SD_SwitchFunction(SDH_SwitchSet, group, function, cmd6Status)) {
+        return Status_SDH_SDIO_SwitchHighSpeedFail;
+    }
+
+    /* In little endian mode is little endian, SD bus byte transferred first is the byte stored in lowest byte
+    position in a word which will cause 4 byte's sequence in a word is not consistent with their original
+    sequence from card. So the sequence of 4 bytes received in a word should be converted. */
+    cmd6Status[3U] = SWAP_WORD_BYTE_SEQUENCE(cmd6Status[3U]);
+    cmd6Status[4U] = SWAP_WORD_BYTE_SEQUENCE(cmd6Status[4U]);
+
+    /* According to the "switch function status[bits 511~0]" return by switch command in mode "set function":
+         -check if group 1 is successfully changed to function 1 by checking if bits 379~376 equal value 1;
+     */
+    currentFunctionStatus = ((cmd6Status[3U] & 0xFFFFU) << 8U) | (cmd6Status[4U] >> 24U);
+    SDH_MSG("currentFunctionStatus = 0x%lX.\r\n", currentFunctionStatus);
+
+    if (((currentFunctionStatus >> (group * 4U)) & 0xFU) != function) {
+        return Status_SDH_SDIO_SwitchHighSpeedFail;
+    }
+
+    return errorstatus;
+}
+
+static status_t SD_SetBlockSize(uint32_t blockSize)
+{
+    status_t errorstatus = Status_Success;
+    SDH_CMD_Cfg_Type SDH_CMD_Cfg_TypeInstance;
+
+    /*!< Set Block Size for SDSC Card,cmd16,no impact on SDHC card */
+    SDH_CMD_Cfg_TypeInstance.index = SD_CMD_SET_BLOCKLEN;
+    SDH_CMD_Cfg_TypeInstance.argument = (uint32_t)blockSize;
+    SDH_CMD_Cfg_TypeInstance.type = SDH_CMD_NORMAL;
+    SDH_CMD_Cfg_TypeInstance.respType = SDH_RESP_R1;
+    SDH_CMD_Cfg_TypeInstance.flag = SDH_TRANS_FLAG_NONE;
+
+    errorstatus = SDH_SendCardCommand(&SDH_CMD_Cfg_TypeInstance);
+
+    if (errorstatus != Status_Success) {
+        goto out;
+    } else if (SDH_CMD_Cfg_TypeInstance.response[0] & SD_CSR_ERRORBITS) {
+        errorstatus = Status_SDH_CmdResponseError;
+        goto out;
+    }
+
+out:
+    return errorstatus;
+}
+
+static status_t SDH_SDCardInit(uint32_t bus_wide, sd_card_t *card)
+{
+    status_t errorstatus = Status_Success;
+    uint32_t applicationCommand41Argument = SD_OcrVdd33_34Flag | SD_OcrVdd32_33Flag;
+
+    /* reset variables */
+    card->flags = 0U;
+
+    SDH_MSG("SD CARD GO IDEL...\r\n");
+    errorstatus = SDH_GoIdle();
+
+    if (errorstatus != SD_OK) {
+        return Status_SDH_GoIdleFailed;
+    }
+
+    SDH_MSG("SD CARD GO IDEL END\r\n");
+
+    for (uint16_t i = 0; i < 4; i++) {
+        /* send CMD8 */
+        errorstatus = SD_SendInterfaceCondition();
+        /* check response */
+        if (errorstatus == Status_Success) {
+            /* SDHC or SDXC card */
+            applicationCommand41Argument |= SD_OcrHostCapacitySupportFlag;
+            card->flags |= SD_SupportSdhcFlag;
+            break;
+        } else {
+            /* Try sending CMD8 again */
+            SDH_MSG("Try sending CMD8 again:%d\r\n", i + 1);
+            errorstatus = SDH_GoIdle();
+            if (errorstatus != Status_Success) {
+                return Status_SDH_GoIdleFailed;
+            }
+        }
+    }
+
+    /* Set card interface condition according to SDHC capability and card's supported interface condition. */
+    errorstatus = SD_ApplicationSendOperationCondition(card, applicationCommand41Argument);
+
+    if (errorstatus != Status_Success) {
+        return Status_SDH_SendApplicationCommandFailed;
+    }
+
+    SDH_MSG("\r\nOCR is: 0x%02lX.\r\n", card->ocr);
+    SDH_MSG("\t SDHC supported[%s].\r\n\r\n", ((card->flags & SD_SupportHighCapacityFlag) ? "YES" : "NO"));
+
+    errorstatus = SD_AllSendCid(card);
+
+    if (errorstatus != Status_Success) {
+        return Status_SDH_AllSendCidFailed;
+    }
+
+    SDH_MSG("\r\nCID is: 0x%02lX-0x%02lX-0x%02lX-0x%02lX.\r\n",
+            card->rawCid[0], card->rawCid[1], card->rawCid[2], card->rawCid[3]);
+    SDH_MSG("\t manufacturerID is: 0x%02X.\r\n", card->cid.manufacturerID);
+    SDH_MSG("\t applicationID is: %c%c.\r\n", (card->cid.applicationID) >> 8, card->cid.applicationID);
+    SDH_MSG("\t productName is: %c%c%c%c%c.\r\n",
+            card->cid.productName[0], card->cid.productName[1], card->cid.productName[2], card->cid.productName[3], card->cid.productName[4]);
+    SDH_MSG("\t manufacturerData is: 0x%02X.\r\n\r\n", card->cid.manufacturerData);
+
+    errorstatus = SD_SendRca(card);
+
+    if (errorstatus != Status_Success) {
+        return Status_SDH_SendRelativeAddressFailed;
+    }
+
+    SDH_MSG("\r\nRCA is: 0x%02lX.\r\n\r\n", card->relativeAddress);
+
+    errorstatus = SD_SendCsd(card);
+
+    if (errorstatus != Status_Success) {
+        return Status_SDH_SendCsdFailed;
+    }
+
+    SDH_MSG("\r\nCSD is: 0x%02lX-0x%02lX-0x%02lX-0x%02lX.\r\n",
+            card->rawCsd[0], card->rawCsd[1], card->rawCsd[2], card->rawCsd[3]);
+    SDH_MSG("\t CSD Version is: %s .\r\n", card->csd.csdStructure ? "csd version 2.0" : "csd version 1.0");
+    SDH_MSG("\t blockLen=%ld, blockCounter=%ld, CardSize is %ld[MBytes].\r\n\r\n", card->blockSize, card->blockCount, (card->blockCount) >> 11);
+
+    errorstatus = SD_SelectCard(card, ENABLE);
+
+    if (errorstatus != Status_Success) {
+        return Status_SDH_SelectCardFailed;
+    }
+
+    errorstatus = SD_SendScr(card);
+
+    if (errorstatus != Status_Success) {
+        return Status_SDH_SendScrFailed;
+    }
+
+    SDH_MSG("\r\nSCR is: 0x%lX-0x%lX.\r\n", card->rawScr[0], card->rawScr[1]);
+    SDH_MSG("\t SD Spec Version is: [0x%02lX]%s.\r\n", card->version,
+            (card->version & SD_SpecificationVersion3_0) ? "V3.0" : ((card->version & SD_SpecificationVersion2_0) ? "V2.0" : ((card->version & SD_SpecificationVersion1_1) ? "V1.1" : "V1.0")));
+    SDH_MSG("\t Erased bit is %d.\r\n", (card->scr.flags & SD_ScrDataStatusAfterErase));
+    SDH_MSG("\t 4-line supported[%s].\r\n", ((card->flags & SD_Support4BitWidthFlag) ? "YES" : "NO"));
+    SDH_MSG("\t SetBlockCountCmd supported[%s].\r\n", ((card->flags & SD_SupportSetBlockCountCmd) ? "YES" : "NO"));
+    SDH_MSG("\t SDXC supported[%s].\r\n\r\n", ((card->flags & SD_SupportSdxcFlag) ? "YES" : "NO"));
+
+    if (card->flags & SD_Support4BitWidthFlag) {
+        errorstatus = SD_SetDataBusWidth(card, (SDH_Data_Bus_Width_Type)bus_wide);
+    } else {
+        errorstatus = SD_SetDataBusWidth(card, SDH_DATA_BUS_WIDTH_1BIT);
+    }
+
+    if (errorstatus != Status_Success) {
+        return Status_SDH_SetDataBusWidthFailed;
+    }
+
+    errorstatus = SD_SendSsr(card);
+
+    if (errorstatus != Status_Success) {
+        return Status_SDH_SendSsrFailed;
+    }
+
+    SDH_MSG("\r\nSSR[0] is: 0x%lX.\r\n", card->rawSsr[0]);
+    SDH_MSG("\t Current is %d-line mode.\r\n\r\n", (card->rawSsr[0] & 0x80) ? 4 : 1);
+
+    errorstatus = SD_SetBlockSize(SDH_DEFAULT_BLOCK_SIZE);
+
+    if (errorstatus != Status_Success) {
+        return Status_SDH_SetCardBlockSizeFailed;
+    }
+
+    //SD_SelectFunction(SDH_GroupTimingMode,SDH_TimingSDR25HighSpeedMode);
+
+    return errorstatus;
+}
+
+/**
+  * @brief  Initializes SD Card clock.
+  * @retval SD status
+  */
+status_t SDH_ClockSet(uint32_t clockInit, uint32_t clockSrc, uint32_t clockTransfer)
+{
+    sdhClockInit = clockInit;
+    sdhClockSrc = clockSrc;
+    sdhClockTransfer = clockTransfer;
+
+    return Status_Success;
+}
+
+/**
+  * @brief  Initializes the SD card device.
+  * @retval SD status
+  */
+status_t SDH_Init(uint32_t bus_wide, sd_card_t *pOutCardInfo)
+{
+    pSDCardInfo = pOutCardInfo;
+
+    /* gpio init */
+    SDH_GPIO_Init(bus_wide);
+
+	/* config sdh clock */
+	GLB_PER_Clock_UnGate(GLB_AHB_CLOCK_SDH);
+    GLB_Set_SDH_CLK(1, GLB_SDH_CLK_WIFIPLL_96M, 0);
+	SDH_ClockSet(400000, 96000000, 96000000);
+
+#if SDIO_SDCARD_INT_MODE
+    SDH_INT_Init();
+#endif
+
+    /* reset SDH controller*/
+    SDH_Reset();
+
+    SDH_HostInit();
+
+    if (pOutCardInfo == NULL) {
+        return Status_InvalidArgument;
+    } else {
+        return SDH_SDCardInit(bus_wide, pOutCardInfo);
+    }
+}
+
+/**
+  * @brief  Allows to erase memory area specified for the given card.
+  * @param  startaddr: the start address.
+  * @param  endaddr: the end address.
+  * @retval SD_Error: SD Card Error code.
+  */
+status_t SD_Erase(uint32_t startaddr, uint32_t endaddr)
+{
+    status_t errorstatus = Status_Success;
+    uint8_t cardstate = 0;
+
+    SDH_CMD_Cfg_Type SDH_CMD_Cfg_TypeInstance;
+
+    /* SDSC card uses byte unit address*/
+    if (!(pSDCardInfo->flags & SD_SupportHighCapacityFlag)) {
+        startaddr *= 512;
+        endaddr *= 512;
+    }
+
+    /*!< Send CMD32 SD_ERASE_GRP_START with argument as addr  */
+    SDH_CMD_Cfg_TypeInstance.index = SD_CMD_SD_ERASE_GRP_START;
+    SDH_CMD_Cfg_TypeInstance.argument = startaddr;
+    SDH_CMD_Cfg_TypeInstance.type = SDH_CMD_NORMAL;
+    SDH_CMD_Cfg_TypeInstance.respType = SDH_RESP_R1;
+    SDH_CMD_Cfg_TypeInstance.flag = SDH_TRANS_FLAG_NONE;
+
+    errorstatus = SDH_SendCardCommand(&SDH_CMD_Cfg_TypeInstance);
+
+    if (errorstatus != Status_Success) {
+        goto out;
+    } else if (SDH_CMD_Cfg_TypeInstance.response[0] & SD_CSR_ERRORBITS) {
+        errorstatus = Status_SDH_CmdResponseError;
+        goto out;
+    }
+
+    /*!< Send CMD33 SD_ERASE_GRP_END with argument as addr  */
+    SDH_CMD_Cfg_TypeInstance.index = SD_CMD_SD_ERASE_GRP_END;
+    SDH_CMD_Cfg_TypeInstance.argument = endaddr;
+    SDH_CMD_Cfg_TypeInstance.type = SDH_CMD_NORMAL;
+    SDH_CMD_Cfg_TypeInstance.respType = SDH_RESP_R1;
+    SDH_CMD_Cfg_TypeInstance.flag = SDH_TRANS_FLAG_NONE;
+
+    errorstatus = SDH_SendCardCommand(&SDH_CMD_Cfg_TypeInstance);
+
+    if (errorstatus != Status_Success) {
+        goto out;
+    } else if (SDH_CMD_Cfg_TypeInstance.response[0] & SD_CSR_ERRORBITS) {
+        errorstatus = Status_SDH_CmdResponseError;
+        goto out;
+    }
+
+    /*!< Send CMD38 ERASE */
+    SDH_CMD_Cfg_TypeInstance.index = SD_CMD_ERASE;
+    SDH_CMD_Cfg_TypeInstance.argument = 0;
+    SDH_CMD_Cfg_TypeInstance.type = SDH_CMD_NORMAL;
+    SDH_CMD_Cfg_TypeInstance.respType = SDH_RESP_R1B;
+    SDH_CMD_Cfg_TypeInstance.flag = SDH_TRANS_FLAG_NONE;
+
+    errorstatus = SDH_SendCardCommand(&SDH_CMD_Cfg_TypeInstance);
+
+    if (errorstatus != Status_Success) {
+        goto out;
+    } else if (SDH_CMD_Cfg_TypeInstance.response[0] & SD_CSR_ERRORBITS) {
+        errorstatus = Status_SDH_CmdResponseError;
+        goto out;
+    }
+
+    /*!< Wait till the card is in programming state */
+    errorstatus = IsCardProgramming(&cardstate);
+
+    while ((errorstatus == SD_OK) && ((SD_CARD_PROGRAMMING == cardstate) || (SD_CARD_RECEIVING == cardstate))) {
+        errorstatus = IsCardProgramming(&cardstate);
+    }
+
+out:
+    return errorstatus;
+}
+
+static status_t WaitInProgramming(void)
+{
+    uint8_t cardstate = 0;
+    status_t errorstatus = Status_Success;
+    //uint32_t maxdelay = 0;
+    //maxdelay = 120000/(sdhClockSrc/sdhClockTransfer);
+
+    //while(maxdelay--){}
+    /*!< Wait till the card is in programming state */
+    errorstatus = IsCardProgramming(&cardstate);
+
+    while ((errorstatus == Status_Success) && ((SD_CARD_PROGRAMMING == cardstate) || (SD_CARD_RECEIVING == cardstate))) {
+        errorstatus = IsCardProgramming(&cardstate);
+    }
+
+    return errorstatus;
+}
+
+/*check sd card state*/
+static status_t IsCardProgramming(uint8_t *pstatus)
+{
+    status_t errorstatus = Status_Success;
+    SDH_CMD_Cfg_Type SDH_CMD_Cfg_TypeInstance;
+
+    /*cmd13 addressed card send its status*/
+    SDH_CMD_Cfg_TypeInstance.index = SD_CMD_SEND_STATUS;
+    SDH_CMD_Cfg_TypeInstance.argument = (uint32_t)(pSDCardInfo->relativeAddress) << 16;
+    SDH_CMD_Cfg_TypeInstance.type = SDH_CMD_NORMAL;
+    SDH_CMD_Cfg_TypeInstance.respType = SDH_RESP_R1;
+    SDH_CMD_Cfg_TypeInstance.flag = SDH_TRANS_FLAG_NONE;
+
+    errorstatus = SDH_SendCardCommand(&SDH_CMD_Cfg_TypeInstance);
+
+    if (errorstatus != Status_Success) {
+        goto out;
+    } else if (SDH_CMD_Cfg_TypeInstance.response[0] & SD_CSR_ERRORBITS) {
+        errorstatus = Status_SDH_CmdResponseError;
+        goto out;
+    }
+
+    /*!< Find out card status */
+    *pstatus = (uint8_t)((SDH_CMD_Cfg_TypeInstance.response[0] >> 9) & 0x0000000F); //status[12:9] :cardstate
+
+out:
+    return (errorstatus);
+}
+
+/* Transmit data in non-blocking mode, Only the sending status of commands is checked */
+static status_t SDH_CardTransferNonBlocking(SDH_DMA_Cfg_Type *dmaCfg, SDH_Trans_Cfg_Type *transfer)
+{
+    status_t errorstatus = Status_Success;
+    SDH_Stat_Type stat = SDH_STAT_SUCCESS;
+
+    stat = SDH_TransferNonBlocking(dmaCfg, transfer);
+
+    if (stat != SDH_STAT_SUCCESS) {
+        return Status_SDH_TransferFailed;
+    }
+
+    /* Flush ADMA2-descriptor-table to RAM, Otherwise ADMA2 will fail */
+    L1C_DCache_Clean_By_Addr((uintptr_t)(dmaCfg->admaEntries), dmaCfg->maxEntries * sizeof(SDH_ADMA2_Desc_Type));
+
+    errorstatus = SDH_SendCardCommand(transfer->cmdCfg);
+
+    if (errorstatus != Status_Success) {
+        return errorstatus;
+    } else if (transfer->cmdCfg->response[0] & SD_CSR_ERRORBITS) {
+        return Status_SDH_CmdResponseError;
+    }
+
+    return errorstatus;
+}
+
+status_t SDH_ReadMultiBlocks(uint8_t *readbuff, uint32_t ReadAddr, uint16_t BlockSize, uint32_t NumberOfBlocks)
+{
+    status_t errorstatus = Status_Success;
+    SD_Error sd_status;
+    uint32_t time_node;
+
+    static SDH_CMD_Cfg_Type SDH_CMD_Cfg_TypeInstance;
+    static SDH_Data_Cfg_Type SDH_Data_Cfg_TypeInstance;
+    static SDH_Trans_Cfg_Type SDH_Trans_Cfg_TypeInstance = { &SDH_Data_Cfg_TypeInstance, &SDH_CMD_Cfg_TypeInstance };
+
+#if defined(BL808) || defined(BL606P)
+    /* BL808/BL606 supports only 8-byte aligned addresses */
+    if ((uintptr_t)readbuff % 8 != 0) {
+        return Status_InvalidArgument;
+    }
+#endif
+
+    /* SDSC card uses byte unit address*/
+    if (!(pSDCardInfo->flags & SD_SupportHighCapacityFlag)) {
+        BlockSize = 512;
+        ReadAddr *= 512;
+    }
+
+    SDH_MSG("\r\nRead-->IN, block num: %ld, block addr: %ld, read buffer addr: 0x%p.\r\n", NumberOfBlocks, ReadAddr, readbuff);
+
+    /*set cmd parameter for READ_MULTIPLE_BLOCK*/
+    if (NumberOfBlocks <= 1) {
+        SDH_CMD_Cfg_TypeInstance.index = SD_CMD_READ_SINGLE_BLOCK;
+    } else {
+        SDH_CMD_Cfg_TypeInstance.index = SD_CMD_READ_MULT_BLOCK;
+    }
+
+    SDH_CMD_Cfg_TypeInstance.argument = (uint32_t)ReadAddr;
+    SDH_CMD_Cfg_TypeInstance.type = SDH_CMD_NORMAL;
+    SDH_CMD_Cfg_TypeInstance.respType = SDH_RESP_R1;
+    SDH_CMD_Cfg_TypeInstance.flag = SDH_TRANS_FLAG_DATA_PRESENT;
+
+    /*set data parameter for READ_MULTIPLE_BLOCK*/
+    if (NumberOfBlocks <= 1) {
+        SDH_Data_Cfg_TypeInstance.enableAutoCommand12 = DISABLE;
+    } else {
+        if (pSDCardInfo->flags & SD_SupportSetBlockCountCmd) {
+            SDH_Data_Cfg_TypeInstance.enableAutoCommand23 = ENABLE;
+            SDH_Data_Cfg_TypeInstance.enableAutoCommand12 = DISABLE;
+        } else {
+            SDH_Data_Cfg_TypeInstance.enableAutoCommand23 = DISABLE;
+            SDH_Data_Cfg_TypeInstance.enableAutoCommand12 = ENABLE;
+        }
+    }
+
+    SDH_Data_Cfg_TypeInstance.enableIgnoreError = DISABLE;
+    SDH_Data_Cfg_TypeInstance.dataType = SDH_TRANS_DATA_NORMAL;
+    SDH_Data_Cfg_TypeInstance.blockSize = BlockSize;
+    SDH_Data_Cfg_TypeInstance.blockCount = NumberOfBlocks;
+    SDH_Data_Cfg_TypeInstance.rxDataLen = 0;
+    SDH_Data_Cfg_TypeInstance.rxData = (uint32_t *)readbuff;
+    SDH_Data_Cfg_TypeInstance.txDataLen = 0;
+    SDH_Data_Cfg_TypeInstance.txData = NULL;
+    SDH_Data_Cfg_TypeInstance.txDataLen = 0;
+    SDH_Data_Cfg_TypeInstance.txData = NULL;
+
+    /*set parameters for SDH_DMA_Cfg_TypeInstance*/
+    SDH_DMA_Cfg_TypeInstance.dmaMode = SDH_DMA_MODE_ADMA2;
+    SDH_DMA_Cfg_TypeInstance.burstSize = SDH_BURST_SIZE_64_BYTES;
+    SDH_DMA_Cfg_TypeInstance.fifoThreshold = SDH_FIFO_THRESHOLD_256_BYTES;
+    SDH_DMA_Cfg_TypeInstance.admaEntries = (uint32_t *)adma2Entries;
+    SDH_DMA_Cfg_TypeInstance.maxEntries = sizeof(adma2Entries) / sizeof(adma2Entries[0]);
+
+    L1C_DCache_Clean_By_Addr((uintptr_t)(readbuff), 0);
+    L1C_DCache_Clean_By_Addr((uintptr_t)(readbuff) + BlockSize * NumberOfBlocks, 0);
+    L1C_DCache_Invalid_By_Addr((uintptr_t)(readbuff), BlockSize * NumberOfBlocks);
+
+    errorstatus = SDH_CardTransferNonBlocking(&SDH_DMA_Cfg_TypeInstance, &SDH_Trans_Cfg_TypeInstance);
+
+    if (errorstatus != Status_Success) {
+        SDH_MSG("SDH Transfer err:%ld\r\n", errorstatus);
+        goto out;
+    }
+
+    time_node = (uint32_t)SDH_GET_TIME();
+
+#if SDIO_SDCARD_INT_MODE
+
+    SDH_DataWaitStatus = SD_WAITING;
+    SDH_EnableIntSource(SDH_INT_DATA_COMPLETED | SDH_INT_DATA_ERRORS | SDH_INT_DMA_ERROR | SDH_INT_AUTO_CMD12_ERROR);
+
+    /*wait for Xfer status. might pending here in multi-task OS*/
+    while (SDH_DataWaitStatus == SD_WAITING) {
+        if ((uint32_t)SDH_GET_TIME() - time_node > SDIO_CMDTIMEOUT_MS) {
+            SDH_MSG("SDH read data timeout: %ld", (uint32_t)SDH_GET_TIME() - time_node);
+            SDH_DisableIntSource(SDH_INT_DATA_COMPLETED | SDH_INT_DATA_ERRORS | SDH_INT_DMA_ERROR | SDH_INT_AUTO_CMD12_ERROR);
+            return Status_Timeout;
+        }
+        BL_DRV_DUMMY;
+        BL_DRV_DUMMY;
+    }
+    sd_status = SDH_DataWaitStatus;
+    SDH_DisableIntSource(SDH_INT_DATA_COMPLETED | SDH_INT_DATA_ERRORS | SDH_INT_DMA_ERROR | SDH_INT_AUTO_CMD12_ERROR);
+
+#else
+
+    uint32_t intFlag;
+    while (1) {
+        intFlag = SDH_GetIntStatus();
+        if (intFlag & SDH_INT_DATA_ERRORS || intFlag & SDH_INT_DMA_ERROR || intFlag & SDH_INT_AUTO_CMD12_ERROR) {
+            sd_status = SD_CMD_ERROR;
+            break;
+
+        } else if (intFlag & SDH_INT_DATA_COMPLETED) {
+            sd_status = SD_OK;
+            break;
+
+        } else if ((uint32_t)SDH_GET_TIME() - time_node > SDIO_CMDTIMEOUT_MS) {
+            SDH_MSG("SDH read data timeout: %ld ms\r\n", (uint32_t)SDH_GET_TIME() - time_node);
+            return Status_Timeout;
+        }
+        BL_DRV_DUMMY;
+        BL_DRV_DUMMY;
+    }
+    SDH_ClearIntStatus(intFlag);
+
+#endif
+
+    if (sd_status != SD_OK) {
+        errorstatus = Status_SDH_TransferFailed;
+        goto out;
+    }
+
+    SDH_MSG("Read data used time: %ld ms\r\n", (uint32_t)SDH_GET_TIME() - time_node);
+    SDH_MSG("Read-->OUT, block num: %ld, block addr: %ld, read buffer addr: 0x%p.\r\n", NumberOfBlocks, ReadAddr, readbuff);
+
+out:
+    return (errorstatus);
+}
+
+status_t SDH_WriteMultiBlocks(uint8_t *writebuff, uint32_t WriteAddr, uint16_t BlockSize, uint32_t NumberOfBlocks)
+{
+    status_t errorstatus = Status_Success;
+    SD_Error sd_status;
+    uint32_t time_node;
+
+    static SDH_CMD_Cfg_Type SDH_CMD_Cfg_TypeInstance;
+    static SDH_Data_Cfg_Type SDH_Data_Cfg_TypeInstance;
+    static SDH_Trans_Cfg_Type SDH_Trans_Cfg_TypeInstance = { &SDH_Data_Cfg_TypeInstance, &SDH_CMD_Cfg_TypeInstance };
+
+#if defined(BL808) || defined(BL606P)
+    /* BL808/BL606 supports only 8-byte aligned addresses */
+    if ((uintptr_t)writebuff % 8 != 0) {
+        return Status_InvalidArgument;
+    }
+#endif
+
+    if ((pSDCardInfo != NULL) && (!(pSDCardInfo->flags & SD_SupportHighCapacityFlag))) {
+        /* It's SDCS card,SDSC card uses byte unit address*/
+        BlockSize = 512;
+        WriteAddr *= 512;
+    }
+
+    SDH_MSG("\r\nWrite-->IN, block num: %ld, block addr: %ld, read buffer addr: 0x%p.\r\n", NumberOfBlocks, WriteAddr, writebuff);
+
+    /*set cmd parameter for SD_CMD_WRITE_MULT_BLOCK*/
+    if (NumberOfBlocks <= 1) {
+        SDH_CMD_Cfg_TypeInstance.index = SD_CMD_WRITE_SINGLE_BLOCK;
+    } else {
+        SDH_CMD_Cfg_TypeInstance.index = SD_CMD_WRITE_MULT_BLOCK;
+    }
+
+    SDH_CMD_Cfg_TypeInstance.argument = (uint32_t)WriteAddr;
+    SDH_CMD_Cfg_TypeInstance.type = SDH_CMD_NORMAL;
+    SDH_CMD_Cfg_TypeInstance.respType = SDH_RESP_R1;
+    SDH_CMD_Cfg_TypeInstance.flag = SDH_TRANS_FLAG_DATA_PRESENT;
+
+    /*set data parameter for WRITE_MULTIPLE_BLOCK*/
+    if (NumberOfBlocks <= 1) {
+        SDH_Data_Cfg_TypeInstance.enableAutoCommand12 = DISABLE;
+    } else {
+        if (pSDCardInfo->flags & SD_SupportSetBlockCountCmd) {
+            SDH_Data_Cfg_TypeInstance.enableAutoCommand23 = ENABLE;
+            SDH_Data_Cfg_TypeInstance.enableAutoCommand12 = DISABLE;
+        } else {
+            SDH_Data_Cfg_TypeInstance.enableAutoCommand23 = DISABLE;
+            SDH_Data_Cfg_TypeInstance.enableAutoCommand12 = ENABLE;
+        }
+    }
+
+    SDH_Data_Cfg_TypeInstance.enableIgnoreError = DISABLE;
+    SDH_Data_Cfg_TypeInstance.dataType = SDH_TRANS_DATA_NORMAL;
+    SDH_Data_Cfg_TypeInstance.blockSize = BlockSize;
+    SDH_Data_Cfg_TypeInstance.blockCount = NumberOfBlocks;
+    SDH_Data_Cfg_TypeInstance.rxDataLen = 0;
+    SDH_Data_Cfg_TypeInstance.rxData = NULL;
+    SDH_Data_Cfg_TypeInstance.txDataLen = 0;
+    SDH_Data_Cfg_TypeInstance.txData = (uint32_t *)writebuff;
+    /*set parameters for SDH_DMA_Cfg_TypeInstance*/
+    SDH_DMA_Cfg_TypeInstance.dmaMode = SDH_DMA_MODE_ADMA2;
+    SDH_DMA_Cfg_TypeInstance.burstSize = SDH_BURST_SIZE_64_BYTES;
+    SDH_DMA_Cfg_TypeInstance.fifoThreshold = SDH_FIFO_THRESHOLD_256_BYTES;
+    SDH_DMA_Cfg_TypeInstance.admaEntries = (uint32_t *)adma2Entries;
+    SDH_DMA_Cfg_TypeInstance.maxEntries = sizeof(adma2Entries) / sizeof(adma2Entries[0]);
+
+    L1C_DCache_Clean_By_Addr((uintptr_t)(writebuff), BlockSize * NumberOfBlocks);
+
+    errorstatus = SDH_CardTransferNonBlocking(&SDH_DMA_Cfg_TypeInstance, &SDH_Trans_Cfg_TypeInstance);
+
+    if (errorstatus != Status_Success) {
+        SDH_MSG("SDH Transfer err:%ld\r\n", errorstatus);
+        return errorstatus;
+    }
+
+    time_node = (uint32_t)SDH_GET_TIME();
+
+#if SDIO_SDCARD_INT_MODE
+
+    SDH_DataWaitStatus = SD_WAITING;
+    SDH_EnableIntSource(SDH_INT_DATA_COMPLETED | SDH_INT_DATA_ERRORS | SDH_INT_DMA_ERROR | SDH_INT_AUTO_CMD12_ERROR);
+
+    /*wait for Xfer status. might pending here in multi-task OS*/
+    while (SDH_DataWaitStatus == SD_WAITING) {
+        if ((uint32_t)SDH_GET_TIME() - time_node > SDIO_CMDTIMEOUT_MS) {
+            SDH_MSG("SDH write data timeout: %ld ms\r\n", (uint32_t)SDH_GET_TIME() - time_node);
+            SDH_DisableIntSource(SDH_INT_DATA_COMPLETED | SDH_INT_DATA_ERRORS | SDH_INT_DMA_ERROR | SDH_INT_AUTO_CMD12_ERROR);
+            errorstatus = Status_Timeout;
+            goto out;
+        }
+        BL_DRV_DUMMY;
+        BL_DRV_DUMMY;
+    }
+
+    SDH_DisableIntSource(SDH_INT_DATA_COMPLETED | SDH_INT_DATA_ERRORS | SDH_INT_DMA_ERROR | SDH_INT_AUTO_CMD12_ERROR);
+    sd_status = SDH_DataWaitStatus;
+
+#else
+
+    uint32_t intFlag;
+    while (1) {
+        intFlag = SDH_GetIntStatus();
+        if (intFlag & SDH_INT_DATA_ERRORS || intFlag & SDH_INT_DMA_ERROR || intFlag & SDH_INT_AUTO_CMD12_ERROR) {
+            sd_status = SD_DataCfg_ERROR;
+            break;
+
+        } else if (intFlag & SDH_INT_DATA_COMPLETED) {
+            sd_status = SD_OK;
+            break;
+
+        } else if ((uint32_t)SDH_GET_TIME() - time_node > SDIO_CMDTIMEOUT_MS) {
+            SDH_MSG("SDH write data timeout: %ld ms\r\n", (uint32_t)SDH_GET_TIME() - time_node);
+            return Status_Timeout;
+        }
+        BL_DRV_DUMMY;
+        BL_DRV_DUMMY;
+    }
+    SDH_ClearIntStatus(intFlag);
+
+#endif
+
+    if (sd_status != SD_OK) {
+        errorstatus = Status_SDH_TransferFailed;
+        goto out;
+    } else {
+        errorstatus = WaitInProgramming();
+    }
+
+    SDH_MSG("Write data used time: %ld ms\r\n", (uint32_t)SDH_GET_TIME() - time_node);
+    SDH_MSG("Write-->OUT, block num: %ld, block addr: %ld, read buffer addr: 0x%p.\r\n", NumberOfBlocks, WriteAddr, writebuff);
+
+out:
+    return (errorstatus);
+}
+

+ 516 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_sdh.h

@@ -0,0 +1,516 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __SDIO_SDCARD_H
+#define __SDIO_SDCARD_H
+#include "bl808_common.h"
+#include "bl808_glb.h"
+#include "bl808_sdh.h"
+
+#define SDIO_CMDTIMEOUT_MS   (100)                  /* time out */
+#define SDH_GET_TIME()  (0)                           /* get time */
+#define SDIO_SDCARD_INT_MODE (0)                    /* Interrupt mode, which can be paired with the OS */
+#define SDH_DEBUG 0                                 /* debug printf */
+
+/*! @brief Reverse byte sequence in uint32_t */
+#define SWAP_WORD_BYTE_SEQUENCE(x) (__REV(x))
+#define __OCRAM      __attribute__ ((section (".system_ram")))
+#define __EALIGN(x)  __attribute((aligned (x)))
+
+/*! @brief Default block size */
+#define SDH_DEFAULT_BLOCK_SIZE (512U)
+
+typedef enum {
+    SD_OK = 0,
+    SD_CMD_ERROR,
+    SD_DataCfg_ERROR,
+    SD_WAITING,
+} SD_Error;
+
+/*! @brief Type used for all status and error return values. */
+typedef int32_t status_t;
+/*! @brief Construct a status code value from a group and code number. */
+#define MAKE_STATUS(group, code) ((((group)*100) + (code)))
+
+/*! @brief Status group numbers. */
+enum _status_groups {
+    StatusGroup_Generic = 0, /*!< Group number for generic status codes. */
+    StatusGroup_SDH = 1,     /*!< Group number for SDHC status code */
+};
+
+/*! @brief Generic status return codes. */
+enum _generic_status {
+    Status_Success = MAKE_STATUS(StatusGroup_Generic, 0),
+    Status_Fail = MAKE_STATUS(StatusGroup_Generic, 1),
+    Status_OutOfRange = MAKE_STATUS(StatusGroup_Generic, 2),
+    Status_InvalidArgument = MAKE_STATUS(StatusGroup_Generic, 3),
+    Status_Timeout = MAKE_STATUS(StatusGroup_Generic, 4),
+
+};
+/*! @brief SD/MMC card API's running status. */
+enum _sdmmc_status {
+    Status_SDH_NotSupportYet = MAKE_STATUS(StatusGroup_SDH, 0U),                      /*!< Haven't supported */
+    Status_SDH_TransferFailed = MAKE_STATUS(StatusGroup_SDH, 1U),                     /*!< Send command failed */
+    Status_SDH_SetCardBlockSizeFailed = MAKE_STATUS(StatusGroup_SDH, 2U),             /*!< Set block size failed */
+    Status_SDH_HostNotSupport = MAKE_STATUS(StatusGroup_SDH, 3U),                     /*!< Host doesn't support */
+    Status_SDH_CardNotSupport = MAKE_STATUS(StatusGroup_SDH, 4U),                     /*!< Card doesn't support */
+    Status_SDH_AllSendCidFailed = MAKE_STATUS(StatusGroup_SDH, 5U),                   /*!< Send CID failed */
+    Status_SDH_SendRelativeAddressFailed = MAKE_STATUS(StatusGroup_SDH, 6U),          /*!< Send relative address failed */
+    Status_SDH_SendCsdFailed = MAKE_STATUS(StatusGroup_SDH, 7U),                      /*!< Send CSD failed */
+    Status_SDH_SelectCardFailed = MAKE_STATUS(StatusGroup_SDH, 8U),                   /*!< Select card failed */
+    Status_SDH_SendScrFailed = MAKE_STATUS(StatusGroup_SDH, 9U),                      /*!< Send SCR failed */
+    Status_SDH_SetDataBusWidthFailed = MAKE_STATUS(StatusGroup_SDH, 10U),             /*!< Set bus width failed */
+    Status_SDH_GoIdleFailed = MAKE_STATUS(StatusGroup_SDH, 11U),                      /*!< Go idle failed */
+    Status_SDH_HandShakeOperationConditionFailed = MAKE_STATUS(StatusGroup_SDH, 12U), /*!< Send Operation Condition failed */
+    Status_SDH_SendApplicationCommandFailed = MAKE_STATUS(StatusGroup_SDH, 13U),      /*!< Send application command failed */
+    Status_SDH_SwitchFailed = MAKE_STATUS(StatusGroup_SDH, 14U),                      /*!< Switch command failed */
+    Status_SDH_StopTransmissionFailed = MAKE_STATUS(StatusGroup_SDH, 15U),            /*!< Stop transmission failed */
+    Status_SDH_WaitWriteCompleteFailed = MAKE_STATUS(StatusGroup_SDH, 16U),           /*!< Wait write complete failed */
+    Status_SDH_SetBlockCountFailed = MAKE_STATUS(StatusGroup_SDH, 17U),               /*!< Set block count failed */
+    Status_SDH_SetRelativeAddressFailed = MAKE_STATUS(StatusGroup_SDH, 18U),          /*!< Set relative address failed */
+    Status_SDH_SwitchBusTimingFailed = MAKE_STATUS(StatusGroup_SDH, 19U),             /*!< Switch high speed failed */
+    Status_SDH_SendExtendedCsdFailed = MAKE_STATUS(StatusGroup_SDH, 20U),             /*!< Send EXT_CSD failed */
+    Status_SDH_ConfigureBootFailed = MAKE_STATUS(StatusGroup_SDH, 21U),               /*!< Configure boot failed */
+    Status_SDH_ConfigureExtendedCsdFailed = MAKE_STATUS(StatusGroup_SDH, 22U),        /*!< Configure EXT_CSD failed */
+    Status_SDH_EnableHighCapacityEraseFailed = MAKE_STATUS(StatusGroup_SDH, 23U),     /*!< Enable high capacity erase failed */
+    Status_SDH_SendTestPatternFailed = MAKE_STATUS(StatusGroup_SDH, 24U),             /*!< Send test pattern failed */
+    Status_SDH_ReceiveTestPatternFailed = MAKE_STATUS(StatusGroup_SDH, 25U),          /*!< Receive test pattern failed */
+    Status_SDH_SDIO_ResponseError = MAKE_STATUS(StatusGroup_SDH, 26U),                /*!< sdio response error */
+    Status_SDH_SDIO_InvalidArgument = MAKE_STATUS(StatusGroup_SDH, 27U),              /*!< sdio invalid argument response error */
+    Status_SDH_SDIO_SendOperationConditionFail = MAKE_STATUS(StatusGroup_SDH, 28U),   /*!< sdio send operation condition fail */
+    Status_SDH_InvalidVoltage = MAKE_STATUS(StatusGroup_SDH, 29U),                    /*!<  invaild voltage */
+    Status_SDH_SDIO_SwitchHighSpeedFail = MAKE_STATUS(StatusGroup_SDH, 30U),          /*!<  switch to high speed fail */
+    Status_SDH_SDIO_ReadCISFail = MAKE_STATUS(StatusGroup_SDH, 31U),                  /*!<  read CIS fail */
+    Status_SDH_SDIO_InvalidCard = MAKE_STATUS(StatusGroup_SDH, 32U),                  /*!<  invaild SDIO card */
+    Status_SDH_TuningFail = MAKE_STATUS(StatusGroup_SDH, 33U),                        /*!<  tuning fail */
+    Status_SDH_SwitchVoltageFail = MAKE_STATUS(StatusGroup_SDH, 34U),                 /*!< switch voltage fail*/
+    Status_SDH_ReTuningRequest = MAKE_STATUS(StatusGroup_SDH, 35U),                   /*!<  retuning request */
+    Status_SDH_SetDriverStrengthFail = MAKE_STATUS(StatusGroup_SDH, 36U),             /*!<  set driver strength fail */
+    Status_SDH_SetPowerClassFail = MAKE_STATUS(StatusGroup_SDH, 37U),                 /*!<  set power class fail */
+    Status_SDH_HostNotReady = MAKE_STATUS(StatusGroup_SDH, 38U),                      /*!<  host controller not ready */
+    Status_SDH_CardDetectFailed = MAKE_STATUS(StatusGroup_SDH, 39U),                  /*!<  card detect failed */
+    Status_SDH_CmdResponseError = MAKE_STATUS(StatusGroup_SDH, 40U),                  /*!<  cmd response timeout */
+    Status_SDH_SendSsrFailed = MAKE_STATUS(StatusGroup_SDH, 41U),                     /*!< Send SSR failed */
+};
+/**
+  * @brief  SDIO Transfer state
+  */
+typedef enum {
+    SD_TRANSFER_OK = 0,
+    SD_TRANSFER_BUSY = 1,
+    SD_TRANSFER_ERROR
+} SDTransferState;
+
+/**
+  * @brief  SD Card States
+  */
+typedef enum {
+    SD_CARD_READY = ((uint32_t)0x00000001),
+    SD_CARD_IDENTIFICATION = ((uint32_t)0x00000002),
+    SD_CARD_STANDBY = ((uint32_t)0x00000003),
+    SD_CARD_TRANSFER = ((uint32_t)0x00000004),
+    SD_CARD_SENDING = ((uint32_t)0x00000005),
+    SD_CARD_RECEIVING = ((uint32_t)0x00000006),
+    SD_CARD_PROGRAMMING = ((uint32_t)0x00000007),
+    SD_CARD_DISCONNECTED = ((uint32_t)0x00000008),
+    SD_CARD_ERROR = ((uint32_t)0x000000FF)
+} SDCardState;
+
+/**
+  * @brief  Card Specific Data: CSD Register
+  */
+typedef struct
+{
+    uint8_t CSDStruct;           /*!< CSD structure */
+    uint8_t SysSpecVersion;      /*!< System specification version */
+    uint8_t Reserved1;           /*!< Reserved */
+    uint8_t TAAC;                /*!< Data read access-time 1 */
+    uint8_t NSAC;                /*!< Data read access-time 2 in CLK cycles */
+    uint8_t MaxBusClkFrec;       /*!< Max. bus clock frequency */
+    uint16_t CardComdClasses;    /*!< Card command classes */
+    uint8_t RdBlockLen;          /*!< Max. read data block length */
+    uint8_t PartBlockRead;       /*!< Partial blocks for read allowed */
+    uint8_t WrBlockMisalign;     /*!< Write block misalignment */
+    uint8_t RdBlockMisalign;     /*!< Read block misalignment */
+    uint8_t DSRImpl;             /*!< DSR implemented */
+    uint8_t Reserved2;           /*!< Reserved */
+    uint32_t DeviceSize;         /*!< Device Size */
+    uint8_t MaxRdCurrentVDDMin;  /*!< Max. read current @ VDD min */
+    uint8_t MaxRdCurrentVDDMax;  /*!< Max. read current @ VDD max */
+    uint8_t MaxWrCurrentVDDMin;  /*!< Max. write current @ VDD min */
+    uint8_t MaxWrCurrentVDDMax;  /*!< Max. write current @ VDD max */
+    uint8_t DeviceSizeMul;       /*!< Device size multiplier */
+    uint8_t EraseGrSize;         /*!< Erase group size */
+    uint8_t EraseGrMul;          /*!< Erase group size multiplier */
+    uint8_t WrProtectGrSize;     /*!< Write protect group size */
+    uint8_t WrProtectGrEnable;   /*!< Write protect group enable */
+    uint8_t ManDeflECC;          /*!< Manufacturer default ECC */
+    uint8_t WrSpeedFact;         /*!< Write speed factor */
+    uint8_t MaxWrBlockLen;       /*!< Max. write data block length */
+    uint8_t WriteBlockPaPartial; /*!< Partial blocks for write allowed */
+    uint8_t Reserved3;           /*!< Reserded */
+    uint8_t ContentProtectAppli; /*!< Content protection application */
+    uint8_t FileFormatGrouop;    /*!< File format group */
+    uint8_t CopyFlag;            /*!< Copy flag (OTP) */
+    uint8_t PermWrProtect;       /*!< Permanent write protection */
+    uint8_t TempWrProtect;       /*!< Temporary write protection */
+    uint8_t FileFormat;          /*!< File Format */
+    uint8_t ECC;                 /*!< ECC code */
+} SD_CSD;
+
+/**
+  * @brief  Card Identification Data: CID Register
+  */
+typedef struct
+{
+    uint8_t ManufacturerID; /*!< ManufacturerID */
+    uint8_t OEM_AppliID[3]; /*!< OEM/Application ID end with 0 for str display*/
+    uint8_t ProdName[6];    /*!< Product Name part1 end with 0 for str display*/
+    uint8_t ProdRev;        /*!< Product Revision */
+    uint32_t ProdSN;        /*!< Product Serial Number */
+    uint8_t month;          /*!< Reserved1 */
+    uint32_t year;          /*!< Manufacturing Date */
+} SD_CID;
+
+/**
+  * @brief SD Card Status
+  */
+typedef struct
+{
+    uint8_t DAT_BUS_WIDTH;
+    uint8_t SECURED_MODE;
+    uint16_t SD_CARD_TYPE;
+    uint32_t SIZE_OF_PROTECTED_AREA;
+    uint8_t SPEED_CLASS;
+    uint8_t PERFORMANCE_MOVE;
+    uint8_t AU_SIZE;
+    uint16_t ERASE_SIZE;
+    uint8_t ERASE_TIMEOUT;
+    uint8_t ERASE_OFFSET;
+} SD_CardStatus;
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+/*! @brief OCR register in SD card */
+enum _sd_ocr_flag {
+
+    SD_OcrHostCapacitySupportFlag = (1U << 30U),                   /*!< Card capacity status */
+    SD_OcrCardCapacitySupportFlag = SD_OcrHostCapacitySupportFlag, /*!< Card capacity status */
+    SD_OcrSwitch18RequestFlag = (1U << 24U),                       /*!< Switch to 1.8V request */
+    SD_OcrSwitch18AcceptFlag = SD_OcrSwitch18RequestFlag,          /*!< Switch to 1.8V accepted */
+    SD_OcrVdd27_28Flag = (1U << 15U),                              /*!< VDD 2.7-2.8 */
+    SD_OcrVdd28_29Flag = (1U << 16U),                              /*!< VDD 2.8-2.9 */
+    SD_OcrVdd29_30Flag = (1U << 17U),                              /*!< VDD 2.9-3.0 */
+    SD_OcrVdd30_31Flag = (1U << 18U),                              /*!< VDD 2.9-3.0 */
+    SD_OcrVdd31_32Flag = (1U << 19U),                              /*!< VDD 3.0-3.1 */
+    SD_OcrVdd32_33Flag = (1U << 20U),                              /*!< VDD 3.1-3.2 */
+    SD_OcrVdd33_34Flag = (1U << 21U),                              /*!< VDD 3.2-3.3 */
+    SD_OcrVdd34_35Flag = (1U << 22U),                              /*!< VDD 3.3-3.4 */
+    SD_OcrVdd35_36Flag = (1U << 23U),                              /*!< VDD 3.4-3.5 */
+};
+/*! @brief SD card flags */
+enum _sd_card_flag {
+    SD_SupportHighCapacityFlag = (1U << 1U),     /*!< Support high capacity */
+    SD_Support4BitWidthFlag = (1U << 2U),        /*!< Support 4-bit data width */
+    SD_SupportSdhcFlag = (1U << 3U),             /*!< Card is SDHC */
+    SD_SupportSdxcFlag = (1U << 4U),             /*!< Card is SDXC */
+    SD_SupportVoltage180v = (1U << 5U),          /*!< card support 1.8v voltage*/
+    SD_SupportSetBlockCountCmd = (1U << 6U),     /*!< card support cmd23 flag*/
+    SD_SupportSpeedClassControlCmd = (1U << 7U), /*!< card support speed class control flag */
+};
+/*! @brief SD card CID register */
+typedef struct _sd_cid {
+    uint8_t manufacturerID;       /*!< Manufacturer ID [127:120] */
+    uint16_t applicationID;       /*!< OEM/Application ID [119:104] */
+    uint8_t productName[5];       /*!< Product name [103:64] */
+    uint8_t productVersion;       /*!< Product revision [63:56] */
+    uint32_t productSerialNumber; /*!< Product serial number [55:24] */
+    uint16_t manufacturerData;    /*!< Manufacturing date [19:8] */
+} sd_cid_t;
+
+/*! @brief SD card SCR register flags */
+enum _sd_scr_flag {
+    SD_ScrDataStatusAfterErase = (1U << 0U), /*!< Data status after erases [55:55] */
+    SD_ScrSdSpecification3 = (1U << 1U),     /*!< Specification version 3.00 or higher [47:47]*/
+};
+/*! @brief SD card CSD register */
+typedef struct _sd_csd {
+    uint8_t csdStructure;        /*!< CSD structure [127:126] */
+    uint8_t dataReadAccessTime1; /*!< Data read access-time-1 [119:112] */
+    uint8_t dataReadAccessTime2; /*!< Data read access-time-2 in clock cycles (NSAC*100) [111:104] */
+    uint8_t transferSpeed;       /*!< Maximum data transfer rate [103:96] */
+    uint16_t cardCommandClass;   /*!< Card command classes [95:84] */
+    uint8_t readBlockLength;     /*!< Maximum read data block length [83:80] */
+    uint16_t flags;              /*!< Flags in _sd_csd_flag */
+    uint32_t deviceSize;         /*!< Device size [73:62] */
+    /* Following fields from 'readCurrentVddMin' to 'deviceSizeMultiplier' exist in CSD version 1 */
+    uint8_t readCurrentVddMin;    /*!< Maximum read current at VDD min [61:59] */
+    uint8_t readCurrentVddMax;    /*!< Maximum read current at VDD max [58:56] */
+    uint8_t writeCurrentVddMin;   /*!< Maximum write current at VDD min [55:53] */
+    uint8_t writeCurrentVddMax;   /*!< Maximum write current at VDD max [52:50] */
+    uint8_t deviceSizeMultiplier; /*!< Device size multiplier [49:47] */
+
+    uint8_t eraseSectorSize;       /*!< Erase sector size [45:39] */
+    uint8_t writeProtectGroupSize; /*!< Write protect group size [38:32] */
+    uint8_t writeSpeedFactor;      /*!< Write speed factor [28:26] */
+    uint8_t writeBlockLength;      /*!< Maximum write data block length [25:22] */
+    uint8_t fileFormat;            /*!< File format [11:10] */
+} sd_csd_t;
+/*! @brief SD card SCR register */
+typedef struct _sd_scr {
+    uint8_t scrStructure;             /*!< SCR Structure [63:60] */
+    uint8_t sdSpecification;          /*!< SD memory card specification version [59:56] */
+    uint16_t flags;                   /*!< SCR flags in _sd_scr_flag */
+    uint8_t sdSecurity;               /*!< Security specification supported [54:52] */
+    uint8_t sdBusWidths;              /*!< Data bus widths supported [51:48] */
+    uint8_t extendedSecurity;         /*!< Extended security support [46:43] */
+    uint8_t commandSupport;           /*!< Command support bits [33:32] 33-support CMD23, 32-support cmd20*/
+    uint32_t reservedForManufacturer; /*!< reserved for manufacturer usage [31:0] */
+} sd_scr_t;
+/*! @brief SD Status register */
+typedef struct _sd_ssr {
+    uint8_t dataBusWidth;         /*!< Data Bus Width [511:510] 0b00--1line, 0b10--4line*/
+    uint8_t secureMode;           /*!< Secure Mode [509] */
+    uint16_t SDCardType;          /*!< SD Card Type [495:480] */
+    uint32_t sizeOfProtectedArea; /*!< Size Of Protected area [479:448] */
+    uint8_t speedClass;           /*!< speed classes [447:440] */
+    uint8_t performanceMove;      /*!< performance move [439:432] */
+    uint8_t AUSize;               /*!< AU size [431:428] */
+
+    uint16_t eraseSize;    /*!< erase size [423:408] */
+    uint8_t eraseTimeOut;  /*!< erase timeout [407:402] */
+    uint8_t eraseOffset;   /*!< erase offset [401:400] */
+    uint8_t UHSSpeedGrade; /*!< UHS speed grade [399:396] */
+    uint8_t UHSAUSize;     /*!< UHS AU size [395:392] */
+} sd_ssr_t;
+/*!
+ * @brief SD card state
+ *
+ * Define the card structure including the necessary fields to identify and describe the card.
+ */
+typedef struct _sd_card {
+    uint32_t relativeAddress; /*!< Relative address of the card */
+    uint32_t version;         /*!< Card version */
+    uint32_t flags;           /*!< Flags in _sd_card_flag */
+    uint32_t rawCid[4U];      /*!< Raw CID content */
+    uint32_t rawCsd[4U];      /*!< Raw CSD content */
+    uint32_t rawScr[2U];      /*!< Raw CSD content */
+    uint32_t rawSsr[16U];     /*!< Raw CSD content */
+    uint32_t ocr;             /*!< Raw OCR content */
+    sd_cid_t cid;             /*!< CID */
+    sd_csd_t csd;             /*!< CSD */
+    sd_scr_t scr;             /*!< SCR */
+    sd_ssr_t ssr;             /*!< SCR */
+    uint32_t blockCount;      /*!< Card total block number */
+    uint32_t blockSize;       /*!< Card block size */
+} sd_card_t;
+/**
+  * @brief SDIO Commands  Index
+  */
+#define SD_CMD_GO_IDLE_STATE        ((uint8_t)0)
+#define SD_CMD_SEND_OP_COND         ((uint8_t)1)
+#define SD_CMD_ALL_SEND_CID         ((uint8_t)2)
+#define SD_CMD_SET_REL_ADDR         ((uint8_t)3) /*!< SDIO_SEND_REL_ADDR for SD Card */
+#define SD_CMD_SET_DSR              ((uint8_t)4)
+#define SD_CMD_SDIO_SEN_OP_COND     ((uint8_t)5)
+#define SD_CMD_HS_SWITCH            ((uint8_t)6)
+#define SD_CMD_SEL_DESEL_CARD       ((uint8_t)7)
+#define SD_CMD_HS_SEND_EXT_CSD      ((uint8_t)8)
+#define SDIO_SEND_IF_COND           ((uint8_t)8)
+#define SD_CMD_SEND_CSD             ((uint8_t)9)
+#define SD_CMD_SEND_CID             ((uint8_t)10)
+#define SD_CMD_READ_DAT_UNTIL_STOP  ((uint8_t)11) /*!< SD Card doesn't support it */
+#define SD_CMD_STOP_TRANSMISSION    ((uint8_t)12)
+#define SD_CMD_SEND_STATUS          ((uint8_t)13)
+#define SD_CMD_HS_BUSTEST_READ      ((uint8_t)14)
+#define SD_CMD_GO_INACTIVE_STATE    ((uint8_t)15)
+#define SD_CMD_SET_BLOCKLEN         ((uint8_t)16)
+#define SD_CMD_READ_SINGLE_BLOCK    ((uint8_t)17)
+#define SD_CMD_READ_MULT_BLOCK      ((uint8_t)18)
+#define SD_CMD_HS_BUSTEST_WRITE     ((uint8_t)19)
+#define SD_CMD_WRITE_DAT_UNTIL_STOP ((uint8_t)20) /*!< SD Card doesn't support it */
+#define SD_CMD_SET_BLOCK_COUNT      ((uint8_t)23) /*!< SD Card doesn't support it */
+#define SD_CMD_WRITE_SINGLE_BLOCK   ((uint8_t)24)
+#define SD_CMD_WRITE_MULT_BLOCK     ((uint8_t)25)
+#define SD_CMD_PROG_CID             ((uint8_t)26) /*!< reserved for manufacturers */
+#define SD_CMD_PROG_CSD             ((uint8_t)27)
+#define SD_CMD_SET_WRITE_PROT       ((uint8_t)28)
+#define SD_CMD_CLR_WRITE_PROT       ((uint8_t)29)
+#define SD_CMD_SEND_WRITE_PROT      ((uint8_t)30)
+#define SD_CMD_SD_ERASE_GRP_START   ((uint8_t)32) /*!< To set the address of the first write
+                                                                  block to be erased. (For SD card only) */
+#define SD_CMD_SD_ERASE_GRP_END     ((uint8_t)33) /*!< To set the address of the last write block of the
+                                                                  continuous range to be erased. (For SD card only) */
+#define SD_CMD_ERASE_GRP_START      ((uint8_t)35) /*!< To set the address of the first write block to be erased.
+                                                                  (For MMC card only spec 3.31) */
+
+#define SD_CMD_ERASE_GRP_END ((uint8_t)36) /*!< To set the address of the last write block of the
+                                                                  continuous range to be erased. (For MMC card only spec 3.31) */
+
+#define SD_CMD_ERASE        ((uint8_t)38)
+#define SD_CMD_FAST_IO      ((uint8_t)39) /*!< SD Card doesn't support it */
+#define SD_CMD_GO_IRQ_STATE ((uint8_t)40) /*!< SD Card doesn't support it */
+#define SD_CMD_LOCK_UNLOCK  ((uint8_t)42)
+#define SD_CMD_APP_CMD      ((uint8_t)55)
+#define SD_CMD_GEN_CMD      ((uint8_t)56)
+#define SD_CMD_NO_CMD       ((uint8_t)64)
+
+/**
+  * @brief Following commands are SD Card Specific commands.
+  *        SDIO_APP_CMD :CMD55 should be sent before sending these commands.
+  */
+#define SD_CMD_APP_SD_SET_BUSWIDTH          ((uint8_t)6)  /*!< For SD Card only */
+#define SD_CMD_SD_APP_STAUS                 ((uint8_t)13) /*!< For SD Card only */
+#define SD_CMD_SD_APP_SEND_NUM_WRITE_BLOCKS ((uint8_t)22) /*!< For SD Card only */
+#define SD_CMD_SD_APP_OP_COND               ((uint8_t)41) /*!< For SD Card only */
+#define SD_CMD_SD_APP_SET_CLR_CARD_DETECT   ((uint8_t)42) /*!< For SD Card only */
+#define SD_CMD_SD_APP_SEND_SCR              ((uint8_t)51) /*!< For SD Card only */
+#define SD_CMD_SDIO_RW_DIRECT               ((uint8_t)52) /*!< For SD I/O Card only */
+#define SD_CMD_SDIO_RW_EXTENDED             ((uint8_t)53) /*!< For SD I/O Card only */
+
+/**
+  * @brief Following commands are SD Card Specific security commands.
+  *        SDIO_APP_CMD should be sent before sending these commands.
+  */
+#define SD_CMD_SD_APP_GET_MKB                     ((uint8_t)43) /*!< For SD Card only */
+#define SD_CMD_SD_APP_GET_MID                     ((uint8_t)44) /*!< For SD Card only */
+#define SD_CMD_SD_APP_SET_CER_RN1                 ((uint8_t)45) /*!< For SD Card only */
+#define SD_CMD_SD_APP_GET_CER_RN2                 ((uint8_t)46) /*!< For SD Card only */
+#define SD_CMD_SD_APP_SET_CER_RES2                ((uint8_t)47) /*!< For SD Card only */
+#define SD_CMD_SD_APP_GET_CER_RES1                ((uint8_t)48) /*!< For SD Card only */
+#define SD_CMD_SD_APP_SECURE_READ_MULTIPLE_BLOCK  ((uint8_t)18) /*!< For SD Card only */
+#define SD_CMD_SD_APP_SECURE_WRITE_MULTIPLE_BLOCK ((uint8_t)25) /*!< For SD Card only */
+#define SD_CMD_SD_APP_SECURE_ERASE                ((uint8_t)38) /*!< For SD Card only */
+#define SD_CMD_SD_APP_CHANGE_SECURE_AREA          ((uint8_t)49) /*!< For SD Card only */
+#define SD_CMD_SD_APP_SECURE_WRITE_MKB            ((uint8_t)48) /*!< For SD Card only */
+
+/**
+  * @brief  Mask for errors Card Status R1 (CSR Register)
+  */
+#define SD_CSR_ADDR_OUT_OF_RANGE     ((uint32_t)0x80000000)
+#define SD_CSR_ADDR_MISALIGNED       ((uint32_t)0x40000000)
+#define SD_CSR_BLOCK_LEN_ERR         ((uint32_t)0x20000000)
+#define SD_CSR_ERASE_SEQ_ERR         ((uint32_t)0x10000000)
+#define SD_CSR_BAD_ERASE_PARAM       ((uint32_t)0x08000000)
+#define SD_CSR_WRITE_PROT_VIOLATION  ((uint32_t)0x04000000)
+#define SD_CSR_LOCK_UNLOCK_FAILED    ((uint32_t)0x01000000)
+#define SD_CSR_COM_CRC_FAILED        ((uint32_t)0x00800000)
+#define SD_CSR_ILLEGAL_CMD           ((uint32_t)0x00400000)
+#define SD_CSR_CARD_ECC_FAILED       ((uint32_t)0x00200000)
+#define SD_CSR_CC_ERROR              ((uint32_t)0x00100000)
+#define SD_CSR_GENERAL_UNKNOWN_ERROR ((uint32_t)0x00080000)
+#define SD_CSR_STREAM_READ_UNDERRUN  ((uint32_t)0x00040000)
+#define SD_CSR_STREAM_WRITE_OVERRUN  ((uint32_t)0x00020000)
+#define SD_CSR_CID_CSD_OVERWRIETE    ((uint32_t)0x00010000)
+#define SD_CSR_WP_ERASE_SKIP         ((uint32_t)0x00008000)
+#define SD_CSR_CARD_ECC_DISABLED     ((uint32_t)0x00004000)
+#define SD_CSR_ERASE_RESET           ((uint32_t)0x00002000)
+#define SD_CSR_AKE_SEQ_ERROR         ((uint32_t)0x00000008)
+#define SD_CSR_ERRORBITS             ((uint32_t)0xFDFFE008)
+
+#define SD_MAX_VOLT_TRIAL ((uint32_t)0x0000FFFF)
+#define SD_ALLZERO        ((uint32_t)0x00000000)
+
+#define SD_WIDE_BUS_SUPPORT   ((uint32_t)0x00040000)
+#define SD_SINGLE_BUS_SUPPORT ((uint32_t)0x00010000)
+#define SD_CARD_LOCKED        ((uint32_t)0x02000000)
+
+#define SD_0TO7BITS        ((uint32_t)0x000000FF)
+#define SD_8TO15BITS       ((uint32_t)0x0000FF00)
+#define SD_16TO23BITS      ((uint32_t)0x00FF0000)
+#define SD_24TO31BITS      ((uint32_t)0xFF000000)
+#define SD_MAX_DATA_LENGTH ((uint32_t)0x01FFFFFF)
+/**
+  * @brief  Masks for R7 Response
+  */
+#define SD_VOLTAGE_WINDOW_SD ((uint32_t)0x00100000)
+#define SD_HIGH_CAPACITY     ((uint32_t)0x40000000)
+#define SD_STD_CAPACITY      ((uint32_t)0x00000000)
+#define SD_CHECK_PATTERN     ((uint32_t)0x000001AA)
+
+/**
+  * @brief Supported SD Memory Cards
+  */
+#define SDIO_STD_CAPACITY_SD_CARD_V1_1    ((uint32_t)0x00000000)
+#define SDIO_STD_CAPACITY_SD_CARD_V2_0    ((uint32_t)0x00000001)
+#define SDIO_HIGH_CAPACITY_SD_CARD        ((uint32_t)0x00000002)
+#define SDIO_MULTIMEDIA_CARD              ((uint32_t)0x00000003)
+#define SDIO_SECURE_DIGITAL_IO_CARD       ((uint32_t)0x00000004)
+#define SDIO_HIGH_SPEED_MULTIMEDIA_CARD   ((uint32_t)0x00000005)
+#define SDIO_SECURE_DIGITAL_IO_COMBO_CARD ((uint32_t)0x00000006)
+#define SDIO_HIGH_CAPACITY_MMC_CARD       ((uint32_t)0x00000007)
+
+/*! @brief SD group number */
+typedef enum _sd_group_num {
+    SDH_GroupTimingMode = 0U,     /*!< acess mode group*/
+    SDH_GroupCommandSystem = 1U,  /*!< command system group*/
+    SDH_GroupDriverStrength = 2U, /*!< driver strength group*/
+    SDH_GroupCurrentLimit = 3U,   /*!< current limit group*/
+} sd_group_num;
+
+/*! @brief SD card timing mode flags */
+typedef enum _sd_timing_mode {
+    SDH_TimingSDR12DefaultMode = 0U,   /*!< Identification mode & SDR12 */
+    SDH_TimingSDR25HighSpeedMode = 1U, /*!< High speed mode & SDR25 */
+    SDH_TimingSDR50Mode = 2U,          /*!< SDR50 mode*/
+    SDH_TimingSDR104Mode = 3U,         /*!< SDR104 mode */
+    SDH_TimingDDR50Mode = 4U,          /*!< DDR50 mode */
+} sd_timing_mode_t;
+
+/*! @brief SD card specification version number */
+enum _sd_specification_version {
+    SD_SpecificationVersion1_0 = (1U << 0U), /*!< SD card version 1.0-1.01 */
+    SD_SpecificationVersion1_1 = (1U << 1U), /*!< SD card version 1.10 */
+    SD_SpecificationVersion2_0 = (1U << 2U), /*!< SD card version 2.00 */
+    SD_SpecificationVersion3_0 = (1U << 3U), /*!< SD card version 3.0 */
+};
+
+/*! @brief SD card switch mode */
+typedef enum _sd_switch_mode {
+    SDH_SwitchCheck = 0U, /*!< SD switch mode 0: check function */
+    SDH_SwitchSet = 1U,   /*!< SD switch mode 1: set function */
+} sd_switch_mode_t;
+
+
+#if SDH_DEBUG
+#define SDH_MSG(a, ...) printf(a, ##__VA_ARGS__)
+#else
+#define SDH_MSG(a, ...)
+#endif
+
+/*
+bus_wide shoud be SDH_DATA_BUS_WIDTH_1BIT/SDH_DATA_BUS_WIDTH_4BITS/SDH_DATA_BUS_WIDTH_8BITS
+*/
+status_t SDH_ClockSet(uint32_t clockInit, uint32_t clockSrc, uint32_t clockTransfer);
+status_t SDH_Init(uint32_t bus_wide, sd_card_t *pOutCardInfo);
+status_t SD_Erase(uint32_t startaddr, uint32_t endaddr);
+status_t SDH_ReadMultiBlocks(uint8_t *readbuff, uint32_t ReadAddr, uint16_t BlockSize, uint32_t NumberOfBlocks);
+status_t SDH_WriteMultiBlocks(uint8_t *writebuff, uint32_t WriteAddr, uint16_t BlockSize, uint32_t NumberOfBlocks);
+#endif /* __SDCARD_H */

+ 797 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_sec.c

@@ -0,0 +1,797 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+
+#include <sec_eng_reg.h>
+//FIXME no BL808/BL606p header file including is Allowed here
+#ifdef BL808
+#include <bl808_sec_eng.h>
+#elif defined(BL606P)
+#include <bl606p_sec_eng.h>
+#else
+#error "Use CHIP BL808/BL606P for this module"
+#endif
+
+#include <aos/kernel.h>
+
+#include "bl_sec.h"
+#include "bl_irq.h"
+
+#include <blog.h>
+
+#define xstr(a) str_macro(a)
+#define str_macro(a) #a
+#define TRNG_LOOP_COUNTER   (17)
+
+#define TRNG_SIZE_IN_WORD (8)
+#define TRNG_SIZE_IN_BYTES (32)
+static uint32_t trng_buffer[TRNG_SIZE_IN_WORD];
+static unsigned int trng_idx = 0;
+
+static StaticSemaphore_t sha_mutex_buf;
+SemaphoreHandle_t g_bl_sec_sha_mutex = NULL;
+
+static inline void _trng_trigger()
+{
+    uint32_t TRNGx = SEC_ENG_BASE;
+    uint32_t val;
+
+    val = BL_RD_REG(TRNGx, SEC_ENG_SE_TRNG_0_CTRL_0);
+    if (BL_IS_REG_BIT_SET(val, SEC_ENG_SE_TRNG_0_BUSY)) {
+        return;
+    }
+    BL_WR_REG(TRNGx, SEC_ENG_SE_TRNG_0_CTRL_1, trng_buffer[0]);
+    BL_WR_REG(TRNGx, SEC_ENG_SE_TRNG_0_CTRL_2, trng_buffer[1]);
+    val = BL_SET_REG_BIT(val, SEC_ENG_SE_TRNG_0_INT_SET_1T);
+    val = BL_SET_REG_BIT(val, SEC_ENG_SE_TRNG_0_INT_CLR_1T);
+    val = BL_SET_REG_BIT(val, SEC_ENG_SE_TRNG_0_EN);
+    val = BL_SET_REG_BIT(val, SEC_ENG_SE_TRNG_0_TRIG_1T);
+
+    BL_WR_REG(TRNGx, SEC_ENG_SE_TRNG_0_CTRL_0, val);
+}
+
+static inline void wait_trng4feed()
+{
+    uint32_t TRNGx = SEC_ENG_BASE;
+    uint32_t val;
+
+    val = BL_RD_REG(TRNGx, SEC_ENG_SE_TRNG_0_CTRL_0);
+
+    while (BL_IS_REG_BIT_SET(val, SEC_ENG_SE_TRNG_0_BUSY)) {
+        /*wait until trng is NOT busy*/
+        val = BL_RD_REG(TRNGx, SEC_ENG_SE_TRNG_0_CTRL_0);
+    }
+
+    val = BL_SET_REG_BIT(val, SEC_ENG_SE_TRNG_0_INT_CLR_1T);
+    val = BL_CLR_REG_BIT(val, SEC_ENG_SE_TRNG_0_TRIG_1T);
+    BL_WR_REG(TRNGx, SEC_ENG_SE_TRNG_0_CTRL_0, val);
+
+    blog_debug("Feed random number is %08lx\r\n", trng_buffer[0]);
+    trng_buffer[0] = BL_RD_REG(TRNGx, SEC_ENG_SE_TRNG_0_DOUT_0);
+    trng_buffer[1] = BL_RD_REG(TRNGx, SEC_ENG_SE_TRNG_0_DOUT_1);
+    trng_buffer[2] = BL_RD_REG(TRNGx, SEC_ENG_SE_TRNG_0_DOUT_2);
+    trng_buffer[3] = BL_RD_REG(TRNGx, SEC_ENG_SE_TRNG_0_DOUT_3);
+    trng_buffer[4] = BL_RD_REG(TRNGx, SEC_ENG_SE_TRNG_0_DOUT_4);
+    trng_buffer[5] = BL_RD_REG(TRNGx, SEC_ENG_SE_TRNG_0_DOUT_5);
+    trng_buffer[6] = BL_RD_REG(TRNGx, SEC_ENG_SE_TRNG_0_DOUT_6);
+    trng_buffer[7] = BL_RD_REG(TRNGx, SEC_ENG_SE_TRNG_0_DOUT_7);
+}
+
+uint32_t bl_sec_get_random_word(void)
+{
+    trng_idx = (trng_idx & 0x7);
+    if (0 == trng_idx) {
+        _trng_trigger();
+    }
+    return trng_buffer[trng_idx++];
+}
+
+void bl_rand_stream(uint8_t *buf, int len)
+{
+    // int pos, copysize;
+
+    // pos = 0;
+    // if (trng_idx) {
+    //     /*reset trng_buffer*/
+    //     _trng_trigger();
+    //     wait_trng4feed();
+    //     trng_idx = 0;
+    // }
+
+    // while (len > 0) {
+    //     if (trng_idx) {
+    //         /*reset trng_buffer*/
+    //         _trng_trigger();
+    //         wait_trng4feed();
+    //         trng_idx = 0;
+    //     }
+    //     copysize = len > TRNG_SIZE_IN_BYTES ? TRNG_SIZE_IN_BYTES : len;
+    //     memcpy(buf + pos, trng_buffer, copysize);
+    //     pos += copysize;
+    //     len -= copysize;
+    //     trng_idx = TRNG_SIZE_IN_BYTES - 1;
+    // }
+    // _trng_trigger();
+    // wait_trng4feed();
+    // trng_idx = 0;
+    int i;
+
+    for (i = 0; i < len; i++) {
+        buf[i] = (uint8_t)bl_rand();
+    }
+}
+
+int bl_rand()
+{
+    // unsigned int val;
+    // int counter = 0;
+
+    // do {
+    //     val = bl_sec_get_random_word();
+    //     if ((counter++) > TRNG_LOOP_COUNTER) {
+    //         puts("[BL] [SEC] Failed after loop " xstr(TRNG_LOOP_COUNTER) "\r\n");
+    //         break;
+    //     }
+    // } while (0 == val);
+    // val >>= 1;//leave signe bit alone
+    return rand();
+}
+
+void sec_trng_IRQHandler(void)
+{
+    uint32_t TRNGx = SEC_ENG_BASE;
+    uint32_t val;
+
+    if (aos_now_ms() < 1000 * 2) {
+        /*debug when boot*/
+        puts("[BL] [SEC] TRNG Handler\r\n");
+    }
+    val = BL_RD_REG(TRNGx, SEC_ENG_SE_TRNG_0_CTRL_0);
+    val = BL_SET_REG_BIT(val, SEC_ENG_SE_TRNG_0_INT_CLR_1T);
+    val = BL_CLR_REG_BIT(val, SEC_ENG_SE_TRNG_0_TRIG_1T);
+    BL_WR_REG(TRNGx, SEC_ENG_SE_TRNG_0_CTRL_0, val);
+
+    blog_debug("random number is %08lx\r\n", trng_buffer[0]);
+    trng_buffer[0] = BL_RD_REG(TRNGx, SEC_ENG_SE_TRNG_0_DOUT_0);
+    trng_buffer[1] = BL_RD_REG(TRNGx, SEC_ENG_SE_TRNG_0_DOUT_1);
+    trng_buffer[2] = BL_RD_REG(TRNGx, SEC_ENG_SE_TRNG_0_DOUT_2);
+    trng_buffer[3] = BL_RD_REG(TRNGx, SEC_ENG_SE_TRNG_0_DOUT_3);
+    trng_buffer[4] = BL_RD_REG(TRNGx, SEC_ENG_SE_TRNG_0_DOUT_4);
+    trng_buffer[5] = BL_RD_REG(TRNGx, SEC_ENG_SE_TRNG_0_DOUT_5);
+    trng_buffer[6] = BL_RD_REG(TRNGx, SEC_ENG_SE_TRNG_0_DOUT_6);
+    trng_buffer[7] = BL_RD_REG(TRNGx, SEC_ENG_SE_TRNG_0_DOUT_7);
+}
+
+int bl_sec_init(void)
+{
+    if (g_bl_sec_sha_mutex) {
+        return 0;
+    }
+    g_bl_sec_sha_mutex = xSemaphoreCreateMutexStatic(&sha_mutex_buf);
+#if 0
+    _trng_trigger();
+    wait_trng4feed();
+    /*Trigger again*/
+    _trng_trigger();
+    wait_trng4feed();
+    bl_irq_register(SEC_TRNG_IRQn, sec_trng_IRQHandler);
+    bl_irq_enable(SEC_TRNG_IRQn);
+#endif
+
+    return 0;
+}
+
+int bl_exp_mod(uint32_t *src, uint32_t *result, int len, uint32_t *exp, int exp_len, uint32_t *mod, int mod_len)
+{
+    return 0;
+}
+
+int bl_sec_test(void)
+{
+    blog_print("------------------TRNG TEST---------------------------------\r\n");
+    blog_print("**********TRNG TEST rand[%08x]**************\r\n", bl_rand());
+    blog_print("**********TRNG TEST rand[%08x]**************\r\n", bl_rand());
+    blog_print("------------------------------------------------------------\r\n");
+
+    return 0;
+}
+
+void _dump_rsa_data(const uint8_t *data, int size)
+{
+    int i;
+
+    for (i = 0; i < size; i++) {
+        switch (i & 0xF) {
+            case 0x0:
+            {
+                blog_print("[%04X]:", i);
+                blog_print(" %02X", data[i]);
+            }
+            break;
+            case 0xF:
+            {
+                blog_print(" %02X", data[i]);
+                puts("\r\n");
+            }
+            break;
+            default:
+            {
+                blog_print(" %02X", data[i]);
+            }
+        }
+    }
+}
+
+static void RSA_Compare_Data(const uint8_t *expected, const uint8_t *input, uint32_t len)
+{
+    int i = 0, is_failed = 0;
+
+    for (i = 0; i < len; i++) {
+        if (input[i] != expected[i]) {
+            is_failed = 1;
+            blog_info("%s[%02d], %02x %02x\r\n",
+                input[i] ==expected[i] ? "S" : "F",
+                i,
+                input[i],
+                expected[i]
+            );
+        }
+    }
+    if (is_failed) {
+        blog_error("====== Failed %lu Bytes======\r\n", len);
+    } else {
+        blog_info("====== Success %lu Bytes=====\r\n", len);
+    }
+}
+
+static void _pka_test_case2(void)
+{
+    static const uint8_t n[256] = {
+        0xd8, 0xa6, 0x4f, 0xea, 0x28, 0xf9, 0xdf, 0x07, 0x04, 0x55, 0xfa, 0xfb, 0x50, 0x5d, 0xbe, 0xb6,
+        0x9f, 0x7b, 0x53, 0x96, 0xef, 0x05, 0x5e, 0x0a, 0xf5, 0x2d, 0xe3, 0x67, 0x78, 0x07, 0x6b, 0xf6,
+        0xb2, 0x17, 0xac, 0x2e, 0x51, 0x42, 0x84, 0xbb, 0xfe, 0x3e, 0x5f, 0x0c, 0x85, 0xc4, 0x9d, 0xd4,
+        0x8b, 0xd5, 0xfa, 0x17, 0x2d, 0xb1, 0x26, 0x81, 0xe7, 0x79, 0x07, 0x45, 0x82, 0x42, 0x22, 0x3d,
+        0x0d, 0x97, 0xcf, 0xde, 0xea, 0xb8, 0xba, 0x16, 0x05, 0x8a, 0x5b, 0x0f, 0xec, 0x07, 0x30, 0xa4,
+        0xc6, 0xbf, 0xff, 0x20, 0x52, 0x1b, 0x94, 0xad, 0xfa, 0xb7, 0x6e, 0x83, 0x14, 0x48, 0x58, 0x14,
+        0x99, 0xe7, 0xa3, 0x9e, 0xc1, 0x08, 0xbd, 0xfe, 0x20, 0x11, 0x56, 0xdb, 0x96, 0x0a, 0xbb, 0x0b,
+        0xbc, 0xd4, 0x37, 0x55, 0xf9, 0x9c, 0x6d, 0x5b, 0x87, 0x4e, 0x50, 0x9f, 0x24, 0x0e, 0x3a, 0x1a,
+        0x0c, 0x54, 0x67, 0xbd, 0x0f, 0x34, 0x03, 0x5e, 0x45, 0x5b, 0x93, 0x42, 0xbe, 0x71, 0xe6, 0xa7,
+        0xf9, 0x49, 0x1a, 0xb3, 0xb2, 0xfb, 0x0e, 0xee, 0x3d, 0xcf, 0x0c, 0x5a, 0xf8, 0xb5, 0x80, 0x42,
+        0x7c, 0x0c, 0x75, 0xc5, 0xe1, 0x17, 0x29, 0x39, 0x55, 0x2b, 0xb1, 0xf5, 0x72, 0x06, 0x9e, 0x54,
+        0x0b, 0x0e, 0xf2, 0x95, 0xc8, 0x5b, 0x69, 0xaf, 0x5b, 0x81, 0x97, 0xae, 0xb1, 0x6e, 0xc4, 0x6d,
+        0x95, 0xd8, 0x22, 0x1e, 0x39, 0xf0, 0x76, 0x54, 0x19, 0x96, 0x03, 0x4c, 0x25, 0x85, 0x2f, 0xe1,
+        0x84, 0xd7, 0xc1, 0x62, 0xe1, 0x9e, 0x9f, 0x1f, 0xd4, 0xb8, 0xf0, 0xc2, 0x68, 0x76, 0x7c, 0xcf,
+        0x43, 0x3e, 0x60, 0x93, 0xd0, 0x89, 0x65, 0xae, 0x72, 0xcd, 0xd6, 0x00, 0x0d, 0x91, 0x42, 0x90,
+        0x98, 0x02, 0xa9, 0xf6, 0x82, 0x1b, 0xb5, 0x22, 0xfd, 0xb6, 0xc2, 0x5c, 0xad, 0x86, 0x81, 0x1d,
+    };
+    static const uint8_t m[256] = {
+        0x30, 0x31, 0x36, 0x64, 0x61, 0x34, 0x31, 0x66, 0x34, 0x62, 0x66, 0x35, 0x38, 0x61, 0x36, 0x32,
+        0x35, 0x61, 0x61, 0x35, 0x63, 0x33, 0x30, 0x37, 0x62, 0x63, 0x64, 0x31, 0x61, 0x37, 0x35, 0x30,
+        0x33, 0x64, 0x62, 0x30, 0x36, 0x63, 0x39, 0x37, 0x62, 0x30, 0x39, 0x31, 0x39, 0x33, 0x38, 0x61,
+        0x32, 0x31, 0x62, 0x35, 0x66, 0x36, 0x38, 0x65, 0x33, 0x37, 0x37, 0x61, 0x62, 0x38, 0x39, 0x39,
+        0x62, 0x65, 0x66, 0x37, 0x63, 0x61, 0x31, 0x36, 0x35, 0x30, 0x65, 0x38, 0x66, 0x30, 0x38, 0x64,
+        0x37, 0x32, 0x38, 0x37, 0x64, 0x64, 0x30, 0x66, 0x36, 0x64, 0x32, 0x61, 0x64, 0x36, 0x34, 0x31,
+        0x32, 0x38, 0x38, 0x33, 0x38, 0x63, 0x35, 0x39, 0x35, 0x61, 0x32, 0x64, 0x31, 0x30, 0x65, 0x34,
+        0x36, 0x37, 0x61, 0x62, 0x35, 0x34, 0x35, 0x33, 0x63, 0x34, 0x65, 0x63, 0x37, 0x37, 0x30, 0x35,
+        0x33, 0x38, 0x61, 0x63, 0x39, 0x66, 0x38, 0x30, 0x36, 0x66, 0x30, 0x38, 0x66, 0x66, 0x33, 0x30,
+        0x38, 0x65, 0x36, 0x65, 0x64, 0x62, 0x35, 0x35, 0x34, 0x31, 0x66, 0x39, 0x66, 0x30, 0x34, 0x36,
+        0x63, 0x36, 0x37, 0x32, 0x62, 0x31, 0x32, 0x30, 0x37, 0x37, 0x35, 0x35, 0x62, 0x30, 0x35, 0x66,
+        0x35, 0x36, 0x64, 0x33, 0x61, 0x36, 0x36, 0x31, 0x37, 0x64, 0x63, 0x37, 0x35, 0x34, 0x64, 0x35,
+        0x65, 0x32, 0x30, 0x34, 0x63, 0x31, 0x36, 0x31, 0x36, 0x61, 0x31, 0x33, 0x65, 0x33, 0x62, 0x31,
+        0x34, 0x65, 0x38, 0x65, 0x32, 0x39, 0x63, 0x39, 0x35, 0x33, 0x33, 0x38, 0x36, 0x65, 0x65, 0x64,
+        0x62, 0x63, 0x30, 0x39, 0x34, 0x30, 0x37, 0x62, 0x39, 0x34, 0x33, 0x34, 0x38, 0x37, 0x37, 0x36,
+        0x36, 0x37, 0x63, 0x62, 0x33, 0x30, 0x39, 0x63, 0x36, 0x33, 0x30, 0x34, 0x32, 0x32, 0x36, 0x32,
+    };
+    static const uint8_t e[4] = {
+        0x00, 0x01, 0x00, 0x01,
+    };
+    static const uint8_t nprime[256] = {
+        0x38, 0x62, 0xc1, 0xf5, 0x55, 0x2d, 0x3d, 0x60, 0x5e, 0x42, 0xe1, 0x65, 0xde, 0xed, 0x35, 0xd5,
+        0xc5, 0x85, 0xe4, 0x4e, 0xeb, 0x74, 0xa5, 0x22, 0xb3, 0xed, 0x5f, 0x5b, 0xb1, 0xb9, 0xe9, 0x0a,
+        0x7d, 0xa5, 0x74, 0x58, 0xf8, 0xa1, 0xab, 0x17, 0x74, 0xd0, 0x07, 0xa3, 0x7f, 0xd2, 0x9b, 0x50,
+        0x2a, 0xed, 0x5e, 0xdc, 0x5a, 0x69, 0xfe, 0x0e, 0xb1, 0xd8, 0x53, 0x35, 0x9b, 0xef, 0x1d, 0x76,
+        0x52, 0x9e, 0x87, 0x3c, 0xb0, 0x82, 0x4e, 0x03, 0xdf, 0x75, 0xed, 0x09, 0x9f, 0x3d, 0x37, 0xf6,
+        0xe8, 0x0d, 0xc9, 0x2e, 0x81, 0xf2, 0x9d, 0x2e, 0xaa, 0xe6, 0x53, 0x79, 0x6b, 0x99, 0xef, 0x46,
+        0x36, 0xd9, 0x2e, 0x9d, 0x15, 0xd1, 0x7f, 0x23, 0x14, 0xb9, 0xeb, 0x33, 0xa7, 0xd4, 0x8e, 0x86,
+        0x60, 0xc9, 0xd9, 0x7c, 0xca, 0x54, 0x59, 0x57, 0x94, 0x1e, 0x52, 0x4d, 0xc8, 0x3f, 0x9b, 0x24,
+        0x28, 0x25, 0xcb, 0x57, 0xca, 0x8f, 0x16, 0x5a, 0x37, 0xc2, 0xc6, 0xae, 0xc5, 0xe7, 0xc4, 0x2e,
+        0xf3, 0x24, 0x1c, 0xb7, 0xe9, 0xf5, 0x92, 0x4e, 0xd4, 0x51, 0x50, 0xff, 0xde, 0x44, 0x3c, 0xae,
+        0x72, 0xbd, 0x16, 0x39, 0x63, 0x8a, 0x22, 0x9c, 0x95, 0xda, 0x21, 0xf0, 0x4c, 0x12, 0x36, 0x2d,
+        0x00, 0xad, 0xb3, 0x89, 0xb5, 0x09, 0x9e, 0x3d, 0x24, 0x81, 0xfc, 0xef, 0x99, 0x95, 0x22, 0x9d,
+        0xb3, 0x94, 0x39, 0x32, 0xdd, 0xc4, 0x2b, 0x2f, 0xb0, 0x13, 0xfe, 0xb5, 0x5e, 0xc7, 0x64, 0x93,
+        0x7a, 0xb5, 0x81, 0x93, 0x1f, 0x9f, 0x96, 0x1e, 0x7a, 0x5c, 0x8d, 0xde, 0x8f, 0xae, 0xd9, 0xc8,
+        0xdd, 0x35, 0x1e, 0x17, 0x47, 0xb6, 0xab, 0xed, 0xb6, 0x82, 0x22, 0x4c, 0x62, 0xbd, 0x12, 0x4e,
+        0x44, 0x5c, 0x48, 0x2b, 0x75, 0x63, 0x1c, 0xde, 0xfa, 0x15, 0x0d, 0xb1, 0x50, 0x31, 0xb6, 0xcb,
+    };
+    static const uint8_t inv_r[256] = {
+        0x2f, 0xb7, 0xf5, 0x4a, 0xd2, 0x19, 0xde, 0x24, 0x7c, 0xdb, 0xcd, 0x52, 0x6e, 0xbc, 0x2c, 0x5c,
+        0x76, 0x9a, 0x36, 0xc3, 0x87, 0x33, 0xf7, 0xe9, 0x3d, 0x5b, 0x3d, 0xcd, 0x33, 0x7a, 0x3b, 0x4e,
+        0x55, 0xf5, 0xd9, 0x42, 0x76, 0x63, 0x28, 0x7a, 0xa8, 0x7c, 0xf7, 0xd1, 0xf6, 0x0d, 0x26, 0xba,
+        0xbe, 0x9f, 0x35, 0xf4, 0x86, 0xc5, 0x93, 0x4c, 0xe8, 0x76, 0xda, 0x88, 0xb8, 0xbe, 0xad, 0x25,
+        0x6b, 0xe7, 0x44, 0x3b, 0x1c, 0x2c, 0x99, 0x15, 0xee, 0x33, 0x46, 0xc6, 0xe0, 0xb0, 0x39, 0x6d,
+        0x20, 0xb2, 0x68, 0xc7, 0x75, 0x41, 0x2c, 0xff, 0xcb, 0x93, 0x1d, 0x40, 0xd2, 0x0e, 0x64, 0xea,
+        0x2e, 0x0a, 0x55, 0x9f, 0x04, 0x9d, 0xfd, 0x5e, 0x24, 0xa9, 0x28, 0x5c, 0x2d, 0x1b, 0x29, 0x87,
+        0x61, 0x6b, 0x50, 0x6a, 0x31, 0x31, 0x43, 0x12, 0x13, 0xe3, 0x1f, 0x47, 0x8a, 0x11, 0xd2, 0x5b,
+        0x26, 0x5e, 0x79, 0x04, 0x0b, 0xa8, 0xb0, 0x36, 0x22, 0xda, 0x3c, 0x5e, 0xb9, 0x09, 0x48, 0xb0,
+        0x32, 0x38, 0x25, 0xec, 0xfd, 0x5e, 0xef, 0xff, 0x80, 0x33, 0x9f, 0x94, 0x8c, 0x6e, 0x2a, 0xfb,
+        0xbf, 0x65, 0x18, 0x98, 0x7e, 0xff, 0x41, 0xde, 0x00, 0x2f, 0xd2, 0x7d, 0xbf, 0x4c, 0x54, 0x4e,
+        0x1c, 0x46, 0xd6, 0xab, 0xf6, 0x07, 0x34, 0x63, 0xe3, 0x0b, 0x81, 0xa0, 0x94, 0x7d, 0xaf, 0x7e,
+        0x37, 0xd6, 0xc5, 0xa6, 0x4a, 0x90, 0x6c, 0x44, 0x6a, 0xd9, 0x0f, 0x20, 0xb2, 0xef, 0x22, 0xa0,
+        0xdf, 0x38, 0x2d, 0x0b, 0xb3, 0x03, 0xb2, 0xc8, 0xe6, 0x8d, 0x74, 0xbf, 0x45, 0x91, 0xe0, 0x22,
+        0x16, 0xbf, 0xc4, 0xda, 0x54, 0x26, 0xaa, 0x65, 0x85, 0x88, 0xc3, 0xfb, 0x9f, 0xfc, 0x14, 0xc4,
+        0xff, 0x8b, 0x88, 0x47, 0x5f, 0xb1, 0x55, 0xdf, 0x47, 0x5c, 0xc0, 0x27, 0x39, 0x7b, 0xe8, 0xad,
+    };
+    uint32_t result[64];
+    static const uint8_t encrypted[256] = {
+        0x9e, 0xf6, 0x6f, 0x46, 0xf5, 0x51, 0x1a, 0xbc, 0xc2, 0x9c, 0x49, 0x02, 0x21, 0x6c, 0x20, 0xae,
+        0x49, 0x91, 0xcd, 0xba, 0xb9, 0x4f, 0xaf, 0xfd, 0x8d, 0x9a, 0x27, 0xbc, 0x0b, 0x69, 0x57, 0xc4,
+        0xba, 0x18, 0xe1, 0x56, 0x45, 0x55, 0xbb, 0x3f, 0x7b, 0xca, 0x45, 0xb3, 0x9a, 0x0e, 0xd7, 0x64,
+        0x6e, 0x71, 0xce, 0xd3, 0x08, 0xc9, 0x4b, 0x97, 0xab, 0x24, 0xe4, 0x6c, 0xe3, 0xc7, 0x52, 0x97,
+        0x3c, 0x45, 0x17, 0x3b, 0x17, 0x0a, 0x90, 0x50, 0xed, 0x73, 0x4b, 0x49, 0x07, 0xee, 0x13, 0xaf,
+        0x47, 0x1e, 0xd0, 0x24, 0xb1, 0xd2, 0xc8, 0x09, 0x75, 0xf3, 0x14, 0x9c, 0x71, 0x99, 0xe3, 0x94,
+        0x5b, 0xf6, 0xef, 0x2e, 0x79, 0xf5, 0x1d, 0xdc, 0xa7, 0xc5, 0xed, 0x0a, 0x3f, 0x1d, 0x43, 0xd0,
+        0x19, 0x14, 0x3a, 0xb7, 0x35, 0xc2, 0x3f, 0xa1, 0x9c, 0x00, 0xde, 0xf6, 0x96, 0x55, 0xf8, 0x0c,
+        0x79, 0x08, 0x68, 0xf3, 0x84, 0x7c, 0x2e, 0x0c, 0x51, 0xb6, 0x5e, 0x9e, 0xcd, 0x50, 0xcc, 0x5f,
+        0x71, 0x99, 0xc1, 0x0d, 0xf0, 0x3c, 0xd0, 0x80, 0x02, 0xf0, 0x8f, 0x12, 0x3e, 0x49, 0xa4, 0x9b,
+        0x1f, 0x14, 0x05, 0xf2, 0x7b, 0x41, 0xc1, 0x3e, 0x8a, 0xb2, 0xab, 0x70, 0x28, 0x2f, 0x20, 0x94,
+        0x17, 0x65, 0xf3, 0x89, 0x28, 0x6d, 0xcd, 0x0c, 0xea, 0x03, 0x4a, 0x10, 0x9d, 0xf9, 0x2e, 0xf4,
+        0x64, 0x79, 0x7a, 0xec, 0x46, 0xb4, 0xdf, 0xce, 0x6a, 0x8e, 0xd8, 0x35, 0x62, 0xb3, 0x04, 0xea,
+        0xf9, 0xc4, 0xde, 0xba, 0x2a, 0x5e, 0xbf, 0x59, 0xfa, 0xef, 0x2a, 0x42, 0x18, 0xc9, 0xf5, 0x7a,
+        0x73, 0xb8, 0x67, 0x78, 0x97, 0x6d, 0x75, 0x4b, 0xdd, 0xfb, 0x9b, 0xe6, 0x4c, 0x04, 0x9c, 0x61,
+        0x5f, 0x9a, 0x12, 0xbf, 0x2e, 0x75, 0x63, 0xdd, 0x50, 0xba, 0x2c, 0xef, 0xb0, 0x9a, 0x65, 0x24,
+    };
+
+    Sec_Eng_PKA_Reset();
+    Sec_Eng_PKA_BigEndian_Enable();
+
+    Sec_Eng_PKA_Write_Data(SEC_ENG_PKA_REG_SIZE_256,  0, (uint32_t*)n, 64, 0);
+    Sec_Eng_PKA_Write_Data(SEC_ENG_PKA_REG_SIZE_256,  1, (uint32_t*)nprime, 64, 0);
+    Sec_Eng_PKA_Write_Data(SEC_ENG_PKA_REG_SIZE_256,  2, (uint32_t*)m, 64, 0);
+    Sec_Eng_PKA_Write_Data(SEC_ENG_PKA_REG_SIZE_256,  3, (uint32_t*)e, 1, 0);
+
+    Sec_Eng_PKA_CREG(SEC_ENG_PKA_REG_SIZE_256, 4, 0, 0);
+    Sec_Eng_PKA_CREG(SEC_ENG_PKA_REG_SIZE_256, 5, 0, 1);
+    Sec_Eng_PKA_LMUL2N(
+            SEC_ENG_PKA_REG_SIZE_512, 2,
+            SEC_ENG_PKA_REG_SIZE_256, 2,
+            2048,
+            0
+    );
+    Sec_Eng_PKA_MREM(
+            SEC_ENG_PKA_REG_SIZE_256, 2,
+            SEC_ENG_PKA_REG_SIZE_512, 2,
+            SEC_ENG_PKA_REG_SIZE_256, 0,
+            0
+    );
+    Sec_Eng_PKA_CREG(SEC_ENG_PKA_REG_SIZE_512, 2, 0, 1);
+
+    Sec_Eng_PKA_MEXP(
+            SEC_ENG_PKA_REG_SIZE_256, 4,
+            SEC_ENG_PKA_REG_SIZE_256, 2,
+            SEC_ENG_PKA_REG_SIZE_256, 3,
+            SEC_ENG_PKA_REG_SIZE_256, 0,
+            1
+    );
+    Sec_Eng_PKA_Move_Data(
+            SEC_ENG_PKA_REG_SIZE_256, 2,
+            SEC_ENG_PKA_REG_SIZE_256, 4,
+            1
+    );
+    Sec_Eng_PKA_Write_Data(SEC_ENG_PKA_REG_SIZE_256,  1, (uint32_t*)inv_r, 64, 0);
+    Sec_Eng_PKA_CREG(SEC_ENG_PKA_REG_SIZE_256, 4, 0, 0);
+    Sec_Eng_PKA_CREG(SEC_ENG_PKA_REG_SIZE_256, 5, 0, 1);
+    Sec_Eng_PKA_LMUL(
+            SEC_ENG_PKA_REG_SIZE_512, 2,
+            SEC_ENG_PKA_REG_SIZE_256, 2,
+            SEC_ENG_PKA_REG_SIZE_256, 1,
+            0
+    );
+    Sec_Eng_PKA_MREM(
+            SEC_ENG_PKA_REG_SIZE_256, 2,
+            SEC_ENG_PKA_REG_SIZE_512, 2,
+            SEC_ENG_PKA_REG_SIZE_256, 0,
+            0
+    );
+    Sec_Eng_PKA_CREG(SEC_ENG_PKA_REG_SIZE_512, 2, 0, 1);
+    Sec_Eng_PKA_Read_Data(
+            SEC_ENG_PKA_REG_SIZE_256, 2,
+            result,
+            64
+    );
+    _dump_rsa_data((uint8_t*)result, sizeof(result));
+    RSA_Compare_Data(encrypted, (uint8_t*)result, sizeof(result));
+}
+
+static void __attribute__((unused)) dump_xgcd_step(uint32_t result[64])
+{
+    puts(" ---- PKA 8:0\r\n");
+    Sec_Eng_PKA_Read_Data(
+            SEC_ENG_PKA_REG_SIZE_256, 0,
+            result,
+            64
+    );
+    _dump_rsa_data((uint8_t*)result, 256);
+
+    puts(" ---- PKA 8:1\r\n");
+    Sec_Eng_PKA_Read_Data(
+            SEC_ENG_PKA_REG_SIZE_256, 1,
+            result,
+            64
+    );
+    _dump_rsa_data((uint8_t*)result, 256);
+
+    puts(" ---- PKA 8:2\r\n");
+    Sec_Eng_PKA_Read_Data(
+            SEC_ENG_PKA_REG_SIZE_256, 2,
+            result,
+            64
+    );
+    _dump_rsa_data((uint8_t*)result, 256);
+
+    puts(" ---- PKA 8:3\r\n");
+    Sec_Eng_PKA_Read_Data(
+            SEC_ENG_PKA_REG_SIZE_256, 3,
+            result,
+            64
+    );
+    _dump_rsa_data((uint8_t*)result, 256);
+
+    puts(" ---- PKA 8:4\r\n");
+    Sec_Eng_PKA_Read_Data(
+            SEC_ENG_PKA_REG_SIZE_256, 4,
+            result,
+            64
+    );
+    _dump_rsa_data((uint8_t*)result, 256);
+
+    puts(" ---- PKA 8:5\r\n");
+    Sec_Eng_PKA_Read_Data(
+            SEC_ENG_PKA_REG_SIZE_256, 5,
+            result,
+            64
+    );
+    _dump_rsa_data((uint8_t*)result, 256);
+
+    puts(" ---- PKA 8:6\r\n");
+    Sec_Eng_PKA_Read_Data(
+            SEC_ENG_PKA_REG_SIZE_256, 6,
+            result,
+            64
+    );
+    _dump_rsa_data((uint8_t*)result, 256);
+
+    puts(" ---- PKA 8:7\r\n");
+    Sec_Eng_PKA_Read_Data(
+            SEC_ENG_PKA_REG_SIZE_256, 7,
+            result,
+            64
+    );
+    _dump_rsa_data((uint8_t*)result, 256);
+}
+
+
+static void _pka_test_case_xgcd(void)
+{
+    int count = 0;
+    static const uint8_t n[256] = {
+        0xd8, 0xa6, 0x4f, 0xea, 0x28, 0xf9, 0xdf, 0x07, 0x04, 0x55, 0xfa, 0xfb, 0x50, 0x5d, 0xbe, 0xb6,
+        0x9f, 0x7b, 0x53, 0x96, 0xef, 0x05, 0x5e, 0x0a, 0xf5, 0x2d, 0xe3, 0x67, 0x78, 0x07, 0x6b, 0xf6,
+        0xb2, 0x17, 0xac, 0x2e, 0x51, 0x42, 0x84, 0xbb, 0xfe, 0x3e, 0x5f, 0x0c, 0x85, 0xc4, 0x9d, 0xd4,
+        0x8b, 0xd5, 0xfa, 0x17, 0x2d, 0xb1, 0x26, 0x81, 0xe7, 0x79, 0x07, 0x45, 0x82, 0x42, 0x22, 0x3d,
+        0x0d, 0x97, 0xcf, 0xde, 0xea, 0xb8, 0xba, 0x16, 0x05, 0x8a, 0x5b, 0x0f, 0xec, 0x07, 0x30, 0xa4,
+        0xc6, 0xbf, 0xff, 0x20, 0x52, 0x1b, 0x94, 0xad, 0xfa, 0xb7, 0x6e, 0x83, 0x14, 0x48, 0x58, 0x14,
+        0x99, 0xe7, 0xa3, 0x9e, 0xc1, 0x08, 0xbd, 0xfe, 0x20, 0x11, 0x56, 0xdb, 0x96, 0x0a, 0xbb, 0x0b,
+        0xbc, 0xd4, 0x37, 0x55, 0xf9, 0x9c, 0x6d, 0x5b, 0x87, 0x4e, 0x50, 0x9f, 0x24, 0x0e, 0x3a, 0x1a,
+        0x0c, 0x54, 0x67, 0xbd, 0x0f, 0x34, 0x03, 0x5e, 0x45, 0x5b, 0x93, 0x42, 0xbe, 0x71, 0xe6, 0xa7,
+        0xf9, 0x49, 0x1a, 0xb3, 0xb2, 0xfb, 0x0e, 0xee, 0x3d, 0xcf, 0x0c, 0x5a, 0xf8, 0xb5, 0x80, 0x42,
+        0x7c, 0x0c, 0x75, 0xc5, 0xe1, 0x17, 0x29, 0x39, 0x55, 0x2b, 0xb1, 0xf5, 0x72, 0x06, 0x9e, 0x54,
+        0x0b, 0x0e, 0xf2, 0x95, 0xc8, 0x5b, 0x69, 0xaf, 0x5b, 0x81, 0x97, 0xae, 0xb1, 0x6e, 0xc4, 0x6d,
+        0x95, 0xd8, 0x22, 0x1e, 0x39, 0xf0, 0x76, 0x54, 0x19, 0x96, 0x03, 0x4c, 0x25, 0x85, 0x2f, 0xe1,
+        0x84, 0xd7, 0xc1, 0x62, 0xe1, 0x9e, 0x9f, 0x1f, 0xd4, 0xb8, 0xf0, 0xc2, 0x68, 0x76, 0x7c, 0xcf,
+        0x43, 0x3e, 0x60, 0x93, 0xd0, 0x89, 0x65, 0xae, 0x72, 0xcd, 0xd6, 0x00, 0x0d, 0x91, 0x42, 0x90,
+        0x98, 0x02, 0xa9, 0xf6, 0x82, 0x1b, 0xb5, 0x22, 0xfd, 0xb6, 0xc2, 0x5c, 0xad, 0x86, 0x81, 0x1d,
+    };
+#if 0
+    static const uint8_t nprime[256] = {
+        0x38, 0x62, 0xc1, 0xf5, 0x55, 0x2d, 0x3d, 0x60, 0x5e, 0x42, 0xe1, 0x65, 0xde, 0xed, 0x35, 0xd5,
+        0xc5, 0x85, 0xe4, 0x4e, 0xeb, 0x74, 0xa5, 0x22, 0xb3, 0xed, 0x5f, 0x5b, 0xb1, 0xb9, 0xe9, 0x0a,
+        0x7d, 0xa5, 0x74, 0x58, 0xf8, 0xa1, 0xab, 0x17, 0x74, 0xd0, 0x07, 0xa3, 0x7f, 0xd2, 0x9b, 0x50,
+        0x2a, 0xed, 0x5e, 0xdc, 0x5a, 0x69, 0xfe, 0x0e, 0xb1, 0xd8, 0x53, 0x35, 0x9b, 0xef, 0x1d, 0x76,
+        0x52, 0x9e, 0x87, 0x3c, 0xb0, 0x82, 0x4e, 0x03, 0xdf, 0x75, 0xed, 0x09, 0x9f, 0x3d, 0x37, 0xf6,
+        0xe8, 0x0d, 0xc9, 0x2e, 0x81, 0xf2, 0x9d, 0x2e, 0xaa, 0xe6, 0x53, 0x79, 0x6b, 0x99, 0xef, 0x46,
+        0x36, 0xd9, 0x2e, 0x9d, 0x15, 0xd1, 0x7f, 0x23, 0x14, 0xb9, 0xeb, 0x33, 0xa7, 0xd4, 0x8e, 0x86,
+        0x60, 0xc9, 0xd9, 0x7c, 0xca, 0x54, 0x59, 0x57, 0x94, 0x1e, 0x52, 0x4d, 0xc8, 0x3f, 0x9b, 0x24,
+        0x28, 0x25, 0xcb, 0x57, 0xca, 0x8f, 0x16, 0x5a, 0x37, 0xc2, 0xc6, 0xae, 0xc5, 0xe7, 0xc4, 0x2e,
+        0xf3, 0x24, 0x1c, 0xb7, 0xe9, 0xf5, 0x92, 0x4e, 0xd4, 0x51, 0x50, 0xff, 0xde, 0x44, 0x3c, 0xae,
+        0x72, 0xbd, 0x16, 0x39, 0x63, 0x8a, 0x22, 0x9c, 0x95, 0xda, 0x21, 0xf0, 0x4c, 0x12, 0x36, 0x2d,
+        0x00, 0xad, 0xb3, 0x89, 0xb5, 0x09, 0x9e, 0x3d, 0x24, 0x81, 0xfc, 0xef, 0x99, 0x95, 0x22, 0x9d,
+        0xb3, 0x94, 0x39, 0x32, 0xdd, 0xc4, 0x2b, 0x2f, 0xb0, 0x13, 0xfe, 0xb5, 0x5e, 0xc7, 0x64, 0x93,
+        0x7a, 0xb5, 0x81, 0x93, 0x1f, 0x9f, 0x96, 0x1e, 0x7a, 0x5c, 0x8d, 0xde, 0x8f, 0xae, 0xd9, 0xc8,
+        0xdd, 0x35, 0x1e, 0x17, 0x47, 0xb6, 0xab, 0xed, 0xb6, 0x82, 0x22, 0x4c, 0x62, 0xbd, 0x12, 0x4e,
+        0x44, 0x5c, 0x48, 0x2b, 0x75, 0x63, 0x1c, 0xde, 0xfa, 0x15, 0x0d, 0xb1, 0x50, 0x31, 0xb6, 0xcb,
+    };
+    static const uint8_t inv_r[256] = {
+        0x2f, 0xb7, 0xf5, 0x4a, 0xd2, 0x19, 0xde, 0x24, 0x7c, 0xdb, 0xcd, 0x52, 0x6e, 0xbc, 0x2c, 0x5c,
+        0x76, 0x9a, 0x36, 0xc3, 0x87, 0x33, 0xf7, 0xe9, 0x3d, 0x5b, 0x3d, 0xcd, 0x33, 0x7a, 0x3b, 0x4e,
+        0x55, 0xf5, 0xd9, 0x42, 0x76, 0x63, 0x28, 0x7a, 0xa8, 0x7c, 0xf7, 0xd1, 0xf6, 0x0d, 0x26, 0xba,
+        0xbe, 0x9f, 0x35, 0xf4, 0x86, 0xc5, 0x93, 0x4c, 0xe8, 0x76, 0xda, 0x88, 0xb8, 0xbe, 0xad, 0x25,
+        0x6b, 0xe7, 0x44, 0x3b, 0x1c, 0x2c, 0x99, 0x15, 0xee, 0x33, 0x46, 0xc6, 0xe0, 0xb0, 0x39, 0x6d,
+        0x20, 0xb2, 0x68, 0xc7, 0x75, 0x41, 0x2c, 0xff, 0xcb, 0x93, 0x1d, 0x40, 0xd2, 0x0e, 0x64, 0xea,
+        0x2e, 0x0a, 0x55, 0x9f, 0x04, 0x9d, 0xfd, 0x5e, 0x24, 0xa9, 0x28, 0x5c, 0x2d, 0x1b, 0x29, 0x87,
+        0x61, 0x6b, 0x50, 0x6a, 0x31, 0x31, 0x43, 0x12, 0x13, 0xe3, 0x1f, 0x47, 0x8a, 0x11, 0xd2, 0x5b,
+        0x26, 0x5e, 0x79, 0x04, 0x0b, 0xa8, 0xb0, 0x36, 0x22, 0xda, 0x3c, 0x5e, 0xb9, 0x09, 0x48, 0xb0,
+        0x32, 0x38, 0x25, 0xec, 0xfd, 0x5e, 0xef, 0xff, 0x80, 0x33, 0x9f, 0x94, 0x8c, 0x6e, 0x2a, 0xfb,
+        0xbf, 0x65, 0x18, 0x98, 0x7e, 0xff, 0x41, 0xde, 0x00, 0x2f, 0xd2, 0x7d, 0xbf, 0x4c, 0x54, 0x4e,
+        0x1c, 0x46, 0xd6, 0xab, 0xf6, 0x07, 0x34, 0x63, 0xe3, 0x0b, 0x81, 0xa0, 0x94, 0x7d, 0xaf, 0x7e,
+        0x37, 0xd6, 0xc5, 0xa6, 0x4a, 0x90, 0x6c, 0x44, 0x6a, 0xd9, 0x0f, 0x20, 0xb2, 0xef, 0x22, 0xa0,
+        0xdf, 0x38, 0x2d, 0x0b, 0xb3, 0x03, 0xb2, 0xc8, 0xe6, 0x8d, 0x74, 0xbf, 0x45, 0x91, 0xe0, 0x22,
+        0x16, 0xbf, 0xc4, 0xda, 0x54, 0x26, 0xaa, 0x65, 0x85, 0x88, 0xc3, 0xfb, 0x9f, 0xfc, 0x14, 0xc4,
+        0xff, 0x8b, 0x88, 0x47, 0x5f, 0xb1, 0x55, 0xdf, 0x47, 0x5c, 0xc0, 0x27, 0x39, 0x7b, 0xe8, 0xad,
+    };
+#endif
+    static const uint8_t n_exp[256] = {
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+    };
+    static const uint8_t all_zero[256] = {
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    };
+    uint32_t result[64];
+    uint8_t pka_a_eq_0 = 0;
+
+
+    (void) count;
+    Sec_Eng_PKA_Reset();
+    Sec_Eng_PKA_BigEndian_Enable();
+
+    Sec_Eng_PKA_Write_Data(SEC_ENG_PKA_REG_SIZE_256,  1, (uint32_t*)n, 64, 0);
+    Sec_Eng_PKA_CREG(SEC_ENG_PKA_REG_SIZE_256, 2, 0, 0);
+    Sec_Eng_PKA_CREG(SEC_ENG_PKA_REG_SIZE_256, 3, 0, 1);
+    Sec_Eng_PKA_Write_Data(SEC_ENG_PKA_REG_SIZE_256,  0, (uint32_t*)n_exp, 64, 0);
+
+
+    Sec_Eng_PKA_LMUL2N(
+            SEC_ENG_PKA_REG_SIZE_512, 1,
+            SEC_ENG_PKA_REG_SIZE_256, 0,
+            2048,
+            0
+    );
+    Sec_Eng_PKA_LDIV(
+            SEC_ENG_PKA_REG_SIZE_256, 0,
+            SEC_ENG_PKA_REG_SIZE_512, 1,
+            SEC_ENG_PKA_REG_SIZE_256, 1,
+            0
+    );
+    Sec_Eng_PKA_MREM(
+            SEC_ENG_PKA_REG_SIZE_256, 4,
+            SEC_ENG_PKA_REG_SIZE_512, 1,
+            SEC_ENG_PKA_REG_SIZE_256, 1,
+            0
+    );
+    Sec_Eng_PKA_CREG(SEC_ENG_PKA_REG_SIZE_512, 1, 0, 1);
+    Sec_Eng_PKA_Move_Data(
+            SEC_ENG_PKA_REG_SIZE_256, 2,
+            SEC_ENG_PKA_REG_SIZE_256, 1,
+            0
+    );
+    Sec_Eng_PKA_Move_Data(
+            SEC_ENG_PKA_REG_SIZE_256, 1,
+            SEC_ENG_PKA_REG_SIZE_256, 4,
+            1
+    );
+    Sec_Eng_PKA_Write_Data(SEC_ENG_PKA_REG_SIZE_256,  4, (uint32_t*)all_zero, 64, 0);
+    Sec_Eng_PKA_Write_Data(SEC_ENG_PKA_REG_SIZE_256,  5, (uint32_t*)n_exp, 64, 0);
+    Sec_Eng_PKA_Write_Data(SEC_ENG_PKA_REG_SIZE_256,  6, (uint32_t*)n_exp, 64, 0);
+    Sec_Eng_PKA_Write_Data(SEC_ENG_PKA_REG_SIZE_256,  7, (uint32_t*)all_zero, 64, 0);
+
+    Sec_Eng_PKA_LMUL(
+            SEC_ENG_PKA_REG_SIZE_256, 8,
+            SEC_ENG_PKA_REG_SIZE_256, 0,
+            SEC_ENG_PKA_REG_SIZE_256, 5,
+            0
+    );
+    Sec_Eng_PKA_LSUB(
+            SEC_ENG_PKA_REG_SIZE_256, 8,
+            SEC_ENG_PKA_REG_SIZE_256, 4,
+            SEC_ENG_PKA_REG_SIZE_256, 8,
+            0
+    );
+    Sec_Eng_PKA_LMUL(
+            SEC_ENG_PKA_REG_SIZE_256, 9,
+            SEC_ENG_PKA_REG_SIZE_256, 0,
+            SEC_ENG_PKA_REG_SIZE_256, 7,
+            0
+    );
+    Sec_Eng_PKA_LSUB(
+            SEC_ENG_PKA_REG_SIZE_256, 9,
+            SEC_ENG_PKA_REG_SIZE_256, 6,
+            SEC_ENG_PKA_REG_SIZE_256, 9,
+            0
+    );
+    Sec_Eng_PKA_Move_Data(
+            SEC_ENG_PKA_REG_SIZE_256, 4,
+            SEC_ENG_PKA_REG_SIZE_256, 5,
+            0
+    );
+    Sec_Eng_PKA_Move_Data(
+            SEC_ENG_PKA_REG_SIZE_256, 5,
+            SEC_ENG_PKA_REG_SIZE_256, 8,
+            0
+    );
+    Sec_Eng_PKA_Move_Data(
+            SEC_ENG_PKA_REG_SIZE_256, 6,
+            SEC_ENG_PKA_REG_SIZE_256, 7,
+            0
+    );
+    Sec_Eng_PKA_Move_Data(
+            SEC_ENG_PKA_REG_SIZE_256, 7,
+            SEC_ENG_PKA_REG_SIZE_256, 9,
+            1
+    );
+
+#if 0
+    blog_info("Dumping Step count %d\r\n", count++);
+    dump_xgcd_step(result);
+#endif
+    while (!pka_a_eq_0) {
+        Sec_Eng_PKA_LDIV(
+                SEC_ENG_PKA_REG_SIZE_256, 0,
+                SEC_ENG_PKA_REG_SIZE_256, 2,
+                SEC_ENG_PKA_REG_SIZE_256, 1,
+                0
+        );
+        Sec_Eng_PKA_MREM(
+                SEC_ENG_PKA_REG_SIZE_256, 3,
+                SEC_ENG_PKA_REG_SIZE_256, 2,
+                SEC_ENG_PKA_REG_SIZE_256, 1,
+                0
+        );
+        Sec_Eng_PKA_LMUL(
+                SEC_ENG_PKA_REG_SIZE_256, 8,
+                SEC_ENG_PKA_REG_SIZE_256, 0,
+                SEC_ENG_PKA_REG_SIZE_256, 5,
+                0
+        );
+        Sec_Eng_PKA_LSUB(
+                SEC_ENG_PKA_REG_SIZE_256, 8,
+                SEC_ENG_PKA_REG_SIZE_256, 4,
+                SEC_ENG_PKA_REG_SIZE_256, 8,
+                0
+        );
+        Sec_Eng_PKA_LMUL(
+                SEC_ENG_PKA_REG_SIZE_256, 9,
+                SEC_ENG_PKA_REG_SIZE_256, 0,
+                SEC_ENG_PKA_REG_SIZE_256, 7,
+                0
+        );
+        Sec_Eng_PKA_LSUB(
+                SEC_ENG_PKA_REG_SIZE_256, 9,
+                SEC_ENG_PKA_REG_SIZE_256, 6,
+                SEC_ENG_PKA_REG_SIZE_256, 9,
+                0
+        );
+        Sec_Eng_PKA_Move_Data(
+                SEC_ENG_PKA_REG_SIZE_256, 2,
+                SEC_ENG_PKA_REG_SIZE_256, 1,
+                0
+        );
+        Sec_Eng_PKA_Move_Data(
+                SEC_ENG_PKA_REG_SIZE_256, 4,
+                SEC_ENG_PKA_REG_SIZE_256, 5,
+                0
+        );
+        Sec_Eng_PKA_Move_Data(
+                SEC_ENG_PKA_REG_SIZE_256, 5,
+                SEC_ENG_PKA_REG_SIZE_256, 8,
+                0
+        );
+        Sec_Eng_PKA_Move_Data(
+                SEC_ENG_PKA_REG_SIZE_256, 6,
+                SEC_ENG_PKA_REG_SIZE_256, 7,
+                0
+        );
+        Sec_Eng_PKA_Move_Data(
+                SEC_ENG_PKA_REG_SIZE_256, 7,
+                SEC_ENG_PKA_REG_SIZE_256, 9,
+                1
+        );
+        Sec_Eng_PKA_Move_Data(
+                SEC_ENG_PKA_REG_SIZE_256, 1,
+                SEC_ENG_PKA_REG_SIZE_256, 3,
+                1
+        );
+        Sec_Eng_PKA_Write_Data(SEC_ENG_PKA_REG_SIZE_256,  10, (uint32_t*)n_exp, 64, 0);
+        Sec_Eng_PKA_LCMP(
+                &pka_a_eq_0,
+                SEC_ENG_PKA_REG_SIZE_256, 1,
+                SEC_ENG_PKA_REG_SIZE_256, 10
+        );
+#if 0
+        blog_info("Dumping Step count %d\r\n", count++);
+        dump_xgcd_step(result);
+#endif
+    }
+    Sec_Eng_PKA_Read_Data(
+            SEC_ENG_PKA_REG_SIZE_256, 6,
+            result,
+            64
+    );
+    _dump_rsa_data((uint8_t*)result, sizeof(result));
+    //RSA_Compare_Data(encrypted, (uint8_t*)result, sizeof(result));
+}
+
+int bl_pka_test(void)
+{
+#if 0
+    bl_irq_register(SEC_PKA_IRQn, bl_sec_pka_IRQHandler);
+    bl_irq_enable(SEC_PKA_IRQn);
+#endif
+
+    _pka_test_case2();
+    _pka_test_case_xgcd();
+    _pka_test_case2();
+
+    return 0;
+}
+
+void bl_sec_pka_IRQHandler(void)
+{
+    puts("--->>> PKA IRQ\r\n");
+    SEC_Eng_IntMask(SEC_ENG_INT_PKA, MASK);
+}

+ 85 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_sec.h

@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __BL_SEC_H__
+#define __BL_SEC_H__
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <FreeRTOS.h>
+#include <semphr.h>
+
+/* copied SEC_Eng_SHA256_Ctx from stddrv */
+typedef struct {
+    uint32_t total[2];
+    uint32_t *shaBuf;
+    uint32_t *shaPadding;
+    uint8_t  shaFeed;
+} _bl_sha_SEC_Eng_SHA256_Ctx_t;
+
+/* copied SEC_ENG_SHA_Type from stddrv, SHA1_RSVD removed */
+typedef enum {
+    BL_SHA256,
+    BL_SHA224,
+    BL_SHA1,
+} bl_sha_type_t;
+
+typedef struct bl_sha_ctx {
+    _bl_sha_SEC_Eng_SHA256_Ctx_t sha_ctx;
+    uint32_t tmp[16];
+    uint32_t pad[16];
+} bl_sha_ctx_t;
+
+extern SemaphoreHandle_t g_bl_sec_sha_mutex;
+
+int bl_sec_init(void);
+int bl_sec_test(void);
+int bl_pka_test(void);
+int bl_sec_aes_init(void);
+int bl_sec_aes_enc(uint8_t *key, int keysize, uint8_t *input, uint8_t *output);
+int bl_sec_aes_test(void);
+uint32_t bl_sec_get_random_word(void);
+void bl_rand_stream(uint8_t *buf, int len);
+int bl_rand(void);
+/*SHA Engine API*/
+int bl_sec_sha_test(void);
+
+int bl_sha_mutex_take();
+int bl_sha_mutex_give();
+void bl_sha_init(bl_sha_ctx_t *ctx, const bl_sha_type_t type);
+int bl_sha_update(bl_sha_ctx_t *ctx, const uint8_t *input, uint32_t len);
+int bl_sha_finish(bl_sha_ctx_t *ctx, uint8_t *hash);
+int bl_sec_ccm_encrypt_and_tag(const uint8_t *key, unsigned int key_bytelen, size_t length, const unsigned char *iv, size_t iv_len, const unsigned char *add, size_t add_len,
+                         const unsigned char *input, unsigned char *output, unsigned char *tag, size_t tag_len);
+int bl_sec_ccm_auth_decrypt(const uint8_t *key, unsigned int key_bytelen, size_t length,const unsigned char *iv, size_t iv_len, const unsigned char *add,
+							 size_t add_len, const unsigned char *input, unsigned char *output, const unsigned char *tag, size_t tag_len);
+int bl_sec_aes_ecb_encrypt(const uint8_t *key, unsigned int key_bytelen, size_t length, const unsigned char *input, unsigned char *output);
+int bl_sec_aes_ecb_decrypt(const uint8_t *key, unsigned int key_bytelen, size_t length, const unsigned char *input, unsigned char *output);
+#endif

+ 180 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_sec_sha.c

@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+
+#include <bl606p_sec_eng.h>
+
+#include <FreeRTOS.h>
+#include <semphr.h>
+
+#include "bl_irq.h"
+#include "bl_sec.h"
+
+#include <blog.h>
+
+typedef struct sha256_link_item {
+    SEC_Eng_SHA256_Link_Ctx ctx;
+    SEC_Eng_SHA_Link_Config_Type linkCfg;
+    uint32_t tmp[16];
+    uint32_t pad[16];
+} sha256_link_item_t;
+
+#define BL_SHA_ID SEC_ENG_SHA_ID0 // this is the only valid value
+
+int bl_sha_mutex_take()
+{
+    if (pdPASS != xSemaphoreTake(g_bl_sec_sha_mutex, portMAX_DELAY)) {
+        blog_error("sha semphr take failed\r\n");
+        return -1;
+    }
+    return 0;
+}
+
+int bl_sha_mutex_give()
+{
+    if (pdPASS != xSemaphoreGive(g_bl_sec_sha_mutex)) {
+        blog_error("sha semphr give failed\\n");
+        return -1;
+    }
+    return 0;
+}
+
+void bl_sha_init(bl_sha_ctx_t *ctx, const bl_sha_type_t type)
+{
+    const SEC_ENG_SHA_Type sha_type = (SEC_ENG_SHA_Type)type; // bl_sha_type_t is the same as SEC_ENG_SHA_Type in driver
+
+    Sec_Eng_SHA256_Init((SEC_Eng_SHA256_Ctx *)&ctx->sha_ctx, BL_SHA_ID, sha_type, ctx->tmp, ctx->pad);
+    Sec_Eng_SHA_Start(BL_SHA_ID);
+}
+
+int bl_sha_update(bl_sha_ctx_t *ctx, const uint8_t *input, uint32_t len)
+{
+    return Sec_Eng_SHA256_Update((SEC_Eng_SHA256_Ctx *)&ctx->sha_ctx, BL_SHA_ID, input, len);
+}
+
+int bl_sha_finish(bl_sha_ctx_t *ctx, uint8_t *hash)
+{
+    return Sec_Eng_SHA256_Finish((SEC_Eng_SHA256_Ctx *)&ctx->sha_ctx, BL_SHA_ID, hash);
+}
+
+static const uint8_t shaSrcBuf1[64] =
+{
+    '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
+    '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
+    '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
+    '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
+};
+
+static void SHA_Compare_Data(const uint8_t *expected, const uint8_t *input, uint32_t len)
+{
+    int i = 0, is_failed = 0;
+
+    for (i = 0; i < len; i++) {
+        if (input[i] != expected[i]) {
+            is_failed = 1;
+            blog_print("%s[%02d], %02x %02x\r\n",
+                input[i] ==expected[i] ? "S" : "F",
+                i,
+                input[i],
+                expected[i]
+            );
+        }
+    }
+    if (is_failed) {
+        blog_print("====== Failed %lu Bytes======\r\n", len);
+    } else {
+        blog_print("====== Success %lu Bytes=====\r\n", len);
+    }
+}
+
+void sha256_test_case0(void)
+{
+    SEC_ENG_SHA_ID_Type shaId = SEC_ENG_SHA_ID0;
+    sha256_link_item_t sha256_link = {
+        .linkCfg.shaMode = SEC_ENG_SHA256,
+        .linkCfg.shaHashSel = 0,
+        .linkCfg.shaIntClr = 0,
+        .linkCfg.shaIntSet = 1,
+        .linkCfg.shaMsgLen = 1,
+        .linkCfg.shaSrcAddr = 0x50020000,
+    };
+    static const uint8_t sha256_test_result[] = 
+    {
+        0x31, 0x38, 0xbb, 0x9b, 0xc7, 0x8d, 0xf2, 0x7c, 0x47, 0x3e, 0xcf, 0xd1, 0x41, 0x0f, 0x7b, 0xd4,
+        0x5e, 0xba, 0xc1, 0xf5, 0x9c, 0xf3, 0xff, 0x9c, 0xfe, 0x4d, 0xb7, 0x7a, 0xab, 0x7a, 0xed, 0xd3, 
+    };
+
+
+#define SEC_SHA_IRQn (IRQ_NUM_BASE+14)
+
+    bl_irq_register(SEC_SHA_IRQn, bl_sec_sha_IRQHandler);
+    bl_irq_enable(SEC_SHA_IRQn);
+
+    Sec_Eng_SHA_Enable_Link(shaId);
+    Sec_Eng_SHA256_Link_Init(&sha256_link.ctx, shaId,
+            (uint32_t)&sha256_link.linkCfg,
+            sha256_link.tmp,
+            sha256_link.pad
+    );
+    Sec_Eng_SHA256_Link_Update(&sha256_link.ctx, shaId,
+            shaSrcBuf1,
+            64
+    );
+    //FIXME Request to change driver API
+    Sec_Eng_SHA256_Link_Finish(&sha256_link.ctx, shaId, (uint8_t*)sha256_link.linkCfg.result);
+    Sec_Eng_SHA_Disable_Link(shaId);
+
+    SHA_Compare_Data((const uint8_t*)sha256_link.linkCfg.result, sha256_test_result, sizeof(sha256_test_result));
+}
+
+int bl_sec_sha_test(void)
+{
+    puts("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\r\n");
+    puts("^^^^^^^^^^^^^^^^^^^^^^^SHA256 TEST CASE^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\r\n");
+    sha256_test_case0();
+    puts("------------------------------------------------------------------------------------\r\n");
+
+    return 0;
+}
+static void _clear_sha_int()
+{
+    uint32_t SHAx = SEC_ENG_BASE;
+    uint32_t val;
+
+    val = BL_RD_REG(SHAx, SEC_ENG_SE_SHA_0_CTRL);
+    val = BL_SET_REG_BIT(val, SEC_ENG_SE_SHA_0_INT_CLR_1T);
+    BL_WR_REG(SHAx, SEC_ENG_SE_SHA_0_CTRL, val);
+}
+
+void bl_sec_sha_IRQHandler(void)
+{
+    puts("--->>> SHA IRQ\r\n");
+    _clear_sha_int();
+}

+ 325 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_sys.c

@@ -0,0 +1,325 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <stdbool.h>
+
+// #include <blog.h>
+#include <bl_irq.h>
+#include <bl_flash.h>
+#include <hal_boot2.h>
+#include <hal_board.h>
+//FIXME no BL808/BL606p header file including is Allowed here
+#ifdef BL808
+#include <bl808_glb.h>
+#include <bl808_pds.h>
+#elif defined(BL606P)
+#include <bl606p_glb.h>
+#include <bl606p_pds.h>
+#else
+#error "Use CHIP BL808/BL606P for this module"
+#endif
+#include "bl_sys.h"
+
+#define MFG_CONFIG_REG    (0x4000F100)
+#define MFG_CONFIG_VAL    ("0mfg")
+
+#define REASON_WDT        (0x77646F67) // watchdog reboot wdog
+#define REASON_SOFTWARE   (0x736F6674) // software        soft
+#define REASON_POWEROFF   (0x0) // software        soft
+
+#define RST_REASON (*((volatile uint32_t *)0x40010000)) // use 4 Bytes
+
+static BL_RST_REASON_E s_rst_reason = BL_RST_POWER_OFF;
+
+static char *RST_REASON_ARRAY[] = {
+    "BL_RST_POWER_OFF",
+    "BL_RST_HARDWARE_WATCHDOG",
+    "BL_RST_FATAL_EXCEPTION",
+    "BL_RST_SOFTWARE_WATCHDOG",
+    "BL_RST_SOFTWARE"
+};
+extern volatile bool sys_log_all_enable;//XXX in debug.c
+
+BL_RST_REASON_E bl_sys_rstinfo_get(void)
+{
+    BL_RST_REASON_E ret = s_rst_reason;
+
+    s_rst_reason = REASON_POWEROFF;
+
+    return ret;
+}
+
+int bl_sys_rstinfo_set(BL_RST_REASON_E val)
+{
+    if (val == BL_RST_SOFTWARE_WATCHDOG) {
+        RST_REASON = REASON_WDT;
+    } else if (val == BL_RST_SOFTWARE) {
+        RST_REASON = REASON_SOFTWARE;
+    }
+
+    return 0;
+}
+
+void bl_sys_rstinfo_init(void)
+{
+    if (RST_REASON == REASON_WDT) {
+        s_rst_reason = BL_RST_SOFTWARE_WATCHDOG;
+    } else if (RST_REASON == REASON_SOFTWARE) {
+        s_rst_reason = BL_RST_SOFTWARE;
+    } else {
+        s_rst_reason = BL_RST_POWER_OFF;
+    }
+
+    bl_sys_rstinfo_set(BL_RST_SOFTWARE_WATCHDOG);
+}
+
+int bl_sys_rstinfo_getsting(char *info)
+{
+    memcpy(info, (char *)RST_REASON_ARRAY[s_rst_reason], strlen(RST_REASON_ARRAY[s_rst_reason]));
+    *(info + strlen(RST_REASON_ARRAY[s_rst_reason])) = '\0';
+    return 0;
+}
+
+int bl_sys_logall_enable(void)
+{
+    sys_log_all_enable = true;
+    return 0;
+}
+
+int bl_sys_logall_disable(void)
+{
+    sys_log_all_enable = false;
+    return 0;
+}
+
+void bl_sys_mfg_config(void)
+{
+#if 0
+    union _reg_t {
+        uint8_t byte[4];
+        uint32_t word;
+    } mfg = {
+        .byte = MFG_CONFIG_VAL,
+    };
+
+    *(volatile uint32_t*)(MFG_CONFIG_REG) = mfg.word;
+#else
+    puts("WARN: bl_sys_mfg_config is NOT implemented\r\n");
+#endif
+}
+
+int bl_sys_reset_por(void)
+{
+#if 0
+    bl_sys_rstinfo_set(BL_RST_SOFTWARE);
+    __disable_irq();
+    GLB_SW_POR_Reset();
+    while (1) {
+        /*empty dead loop*/
+    }
+
+    return 0;
+#else
+    puts("WARN: bl_sys_rstinfo_set is NOT implemented\r\n");
+    __disable_irq();
+    GLB_SW_POR_Reset();
+    while (1) {
+        /*empty dead loop*/
+    }
+
+    return 0;
+#endif
+}
+
+void bl_sys_reset_system(void)
+{
+    __disable_irq();
+    GLB_SW_System_Reset();
+    while (1) {
+        /*empty dead loop*/
+    }
+}
+
+
+int bl_sys_em_config(void)
+{
+#if 0
+    extern uint8_t __LD_CONFIG_EM_SEL;
+    volatile uint32_t em_size;
+
+    em_size = (uint32_t)&__LD_CONFIG_EM_SEL;
+
+    switch (em_size) {
+        case 0 * 1024:
+        {
+            GLB_Set_EM_Sel(GLB_EM_0KB);
+        }
+        break;
+        case 8 * 1024:
+        {
+            GLB_Set_EM_Sel(GLB_EM_8KB);
+        }
+        break;
+        case 16 * 1024:
+        {
+            GLB_Set_EM_Sel(GLB_EM_16KB);
+        }
+        break;
+        default:
+        {
+            /*nothing here*/
+        }
+    }
+
+    return 0;
+#else
+    puts("WARN: bl_sys_em_config is NOT implemented\r\n");
+    return 0;
+#endif
+}
+
+int bl_sys_early_init(void)
+{
+#if 0
+    extern BL_Err_Type HBN_Aon_Pad_IeSmt_Cfg(uint8_t padCfg);
+    HBN_Aon_Pad_IeSmt_Cfg(1);
+
+    extern void freertos_risc_v_trap_handler(void); //freertos_riscv_ram/portable/GCC/RISC-V/portASM.S
+    write_csr(mtvec, &freertos_risc_v_trap_handler);
+    
+    /* reset here for use wtd first then init hwtimer later*/
+    GLB_AHB_Slave1_Reset(BL_AHB_SLAVE1_TMR);
+    /*debuger may NOT ready don't print anything*/
+    return 0;
+#else
+    puts("WARN: bl_sys_early_init is NOT implemented\r\n");
+    return 0;
+#endif
+}
+
+int bl_sys_init(void)
+{
+    bl_sys_em_config();
+    bl_sys_rstinfo_get();
+    bl_sys_rstinfo_init();
+    return 0;
+}
+
+int bl_sys_isxipaddr(uint32_t addr)
+{
+    //XXX is 0xD000_0000 Address Range is really used
+    if ( ((addr & 0xFF000000) == 0x58000000) || ((addr & 0xFF000000) == 0x5C000000) ||
+         ((addr & 0xFF000000) == 0xD8000000) || ((addr & 0xFF000000) == 0xDC000000)) {
+        return 1;
+    }
+    return 0;
+}
+
+void bl_enable_cpu0(void)
+{
+    PDS_Power_On_MM_System();
+}
+
+void bl_boot_cpu0(uint32_t start_addr)
+{
+    GLB_Halt_CPU(GLB_CORE_ID_D0);
+    GLB_Set_CPU_Reset_Address(GLB_CORE_ID_D0, start_addr);
+    GLB_Release_CPU(GLB_CORE_ID_D0);
+}
+
+void bl_halt_cpu0(void)
+{
+    GLB_Halt_CPU(GLB_CORE_ID_D0);
+}
+
+void bl_release_cpu0(void)
+{
+    GLB_Release_CPU(GLB_CORE_ID_D0);
+}
+
+void bl_sys_enabe_jtag(int cpuid)
+{
+    GLB_GPIO_Cfg_Type gpio_cfg;
+
+    gpio_cfg.drive = 0;
+    gpio_cfg.smtCtrl = 1;
+    gpio_cfg.pullType = GPIO_PULL_NONE;
+
+    gpio_cfg.gpioMode = GPIO_MODE_AF;
+    gpio_cfg.gpioFun = GPIO_FUN_JTAG_D0;
+    switch (cpuid) {
+        case 0:
+        {
+        }
+        break;
+        case 1:
+        {
+            puts("Enable CPU1 (D0/C906) on PIN6/PIN7/PIN12/PIN13\r\n");
+            gpio_cfg.gpioPin = GLB_GPIO_PIN_6;
+            GLB_GPIO_Init(&gpio_cfg);
+
+            gpio_cfg.gpioPin = GLB_GPIO_PIN_7;
+            GLB_GPIO_Init(&gpio_cfg);
+
+            gpio_cfg.gpioPin = GLB_GPIO_PIN_12;
+            GLB_GPIO_Init(&gpio_cfg);
+
+            gpio_cfg.gpioPin = GLB_GPIO_PIN_13;
+            GLB_GPIO_Init(&gpio_cfg);
+        }
+        break;
+        default:
+        {
+        }
+        break;
+    }
+}
+
+static void bl_sys_reduce_mcu2ext(void)
+{
+    uint32_t tmpVal;
+    tmpVal = BL_RD_WORD(MCU_MISC_BASE + MCU_MISC_MCU_BUS_CFG1_OFFSET);
+    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, MCU_MISC_REG_X_WTHRE_MCU2EXT, 3);
+    BL_WR_WORD(MCU_MISC_BASE + MCU_MISC_MCU_BUS_CFG1_OFFSET, tmpVal);
+}
+
+void bl_sys_lowlevel_init(void)
+{
+    bl_sys_reduce_mcu2ext();
+    // blog_init();
+    bl_irq_init();
+    bl_flash_init();
+    hal_boot2_init();
+    hal_board_cfg(0);
+#ifndef NO_BLE_CONFIG
+    GLB_Set_EM_Sel(GLB_WRAM96KB_EM64KB);
+#endif
+}
+

+ 61 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_sys.h

@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __BL_SYS_H__
+#define __BL_SYS_H__
+
+#include <stdint.h>
+
+typedef enum {
+    BL_RST_POWER_OFF = 0,
+    BL_RST_HARDWARE_WATCHDOG,
+    BL_RST_FATAL_EXCEPTION,
+    BL_RST_SOFTWARE_WATCHDOG,
+    BL_RST_SOFTWARE,
+} BL_RST_REASON_E;
+
+BL_RST_REASON_E bl_sys_rstinfo_get(void);
+int bl_sys_rstinfo_set(BL_RST_REASON_E val);
+int bl_sys_rstinfo_getsting(char *info);
+void bl_sys_rstinfo_init(void);
+int bl_sys_logall_enable(void);
+int bl_sys_logall_disable(void);
+void bl_sys_mfg_config(void);
+int bl_sys_reset_por(void);
+void bl_sys_reset_system(void);
+int bl_sys_isxipaddr(uint32_t addr);
+int bl_sys_early_init(void);
+int bl_sys_init(void);
+void bl_enable_cpu0(void);
+void bl_boot_cpu0(uint32_t start_addr);
+void bl_halt_cpu0(void);
+void bl_release_cpu0(void);
+void bl_sys_enabe_jtag(int cpuid);
+void bl_sys_lowlevel_init(void);
+#endif

+ 132 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_timer.c

@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "bl_timer.h"
+#ifdef BL808
+#include <bl808_clock.h>
+#include <bl808_glb.h>
+#elif defined(BL606P)
+#include <bl606p_clock.h>
+#include <bl606p_glb.h>
+#else
+#error "Use CHIP BL808/BL606P for this module"
+#endif
+
+#include <FreeRTOS.h>
+#include <task.h>
+
+uint32_t bl_timer_now_us(void)
+{
+    return xTaskGetTickCount() * 1000000 / configTICK_RATE_HZ;
+}
+
+uint32_t bl_system_core_clock_get(GLB_CORE_ID_Type core)
+{
+    uint32_t clockVal = 0;
+
+    switch (core) {
+        case GLB_CORE_ID_M0:
+            clockVal = Clock_System_Clock_Get(BL_SYSTEM_CLOCK_MCU_CLK);
+            break;
+        case GLB_CORE_ID_D0:
+            clockVal = Clock_System_Clock_Get(BL_SYSTEM_CLOCK_DSP_CLK);
+            break;
+        case GLB_CORE_ID_LP:
+            clockVal = Clock_System_Clock_Get(BL_SYSTEM_CLOCK_LP_CLK);
+            break;
+        default:
+            clockVal = 0;
+            break;
+    }
+    clockVal = clockVal ? clockVal : (32 * 1000 * 1000);
+
+    return clockVal;
+}
+
+BL_Err_Type bl_cpu_set_core_mtimer_clk(GLB_CORE_ID_Type core, uint8_t enable, uint16_t div)
+{
+    uint32_t tmpVal = 0;
+    uint32_t address = 0;
+
+    CHECK_PARAM((div <= 0x3FF));
+
+    switch (core) {
+        case GLB_CORE_ID_M0:
+            address = MCU_MISC_BASE + MCU_MISC_MCU_E907_RTC_OFFSET;
+            break;
+        case GLB_CORE_ID_D0:
+            address = MM_MISC_BASE + MM_MISC_CPU_RTC_OFFSET;
+            break;
+        case GLB_CORE_ID_LP:
+            address = PDS_BASE + PDS_CPU_CORE_CFG8_OFFSET;
+            break;
+        default:
+            address = MCU_MISC_BASE + MCU_MISC_MCU_E907_RTC_OFFSET;
+            break;
+    }
+
+    /* disable rtc first */
+    /* MCU RTC_EN is [31] */
+    /* DSP RTC_EN is [31] */
+    /* LP  RTC_EN is [31] */
+    tmpVal = BL_RD_WORD(address);
+    tmpVal = BL_CLR_REG_BIT(tmpVal, MCU_MISC_REG_MCU_RTC_EN);
+    BL_WR_WORD(address, tmpVal);
+
+    /* set div */
+    /* MCU RTC_DIV is [9:0] */
+    /* DSP RTC_DIV is [9:0] */
+    /* LP  RTC_DIV is [9:0] */
+    tmpVal = BL_RD_WORD(address);
+    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, MCU_MISC_REG_MCU_RTC_DIV, div);
+    BL_WR_WORD(address, tmpVal);
+
+    /* enable or not */
+    /* MCU RTC_EN is [31] */
+    /* DSP RTC_EN is [31] */
+    /* LP  RTC_EN is [31] */
+    tmpVal = BL_RD_WORD(address);
+    if (enable) {
+        tmpVal = BL_SET_REG_BIT(tmpVal, MCU_MISC_REG_MCU_RTC_EN);
+    } else {
+        tmpVal = BL_CLR_REG_BIT(tmpVal, MCU_MISC_REG_MCU_RTC_EN);
+    }
+    BL_WR_WORD(address, tmpVal);
+
+    return SUCCESS;
+}
+
+void bl_mtimer_c906_clock_init(void)
+{
+    uint32_t clockVal = 0;
+    clockVal = bl_system_core_clock_get(GLB_CORE_ID_D0);
+
+    /* Set MTimer clock source 10M */
+    bl_cpu_set_core_mtimer_clk(GLB_CORE_ID_D0, 1, (clockVal / 1000 / 1000 / 10) - 1);
+}

+ 35 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_timer.h

@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __BL_TIMER_H__
+#define __BL_TIMER_H__
+#include <stdint.h>
+uint32_t bl_timer_now_us(void);
+void bl_mtimer_c906_clock_init(void);
+#endif

+ 552 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_uart.c

@@ -0,0 +1,552 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+//FIXME no BL808/BL606p header file including is Allowed here
+#ifdef BL808
+#include <bl808.h>
+#include <bl808_uart.h>
+#include <bl808_glb.h>
+#elif defined(BL606P)
+#include <bl606p.h>
+#include <bl606p_uart.h>
+#include <bl606p_glb.h>
+#else
+#error "Use CHIP BL808/BL606P for this module"
+#endif
+
+#include "bl_uart.h"
+#include "bl_irq.h"
+
+#ifdef BFLB_USE_HAL_DRIVER
+void UART0_IRQHandler(void);
+void UART1_IRQHandler(void);
+void UART2_IRQHandler(void);
+void UART3_IRQHandler(void);
+#endif
+
+//TODO Do in std driver
+#define UART_NUMBER_SUPPORTED   4
+#define UART_FIFO_TX_CNT        (32)
+#define FIFO_TX_SIZE_BURST      (32)
+static const uint32_t uartAddr[4] = {UART0_BASE, UART1_BASE, UART2_BASE, UART3_BASE};
+
+typedef struct bl_uart_notify {
+    cb_uart_notify_t rx_cb;
+    void            *rx_cb_arg;
+
+    cb_uart_notify_t tx_cb;
+    void            *tx_cb_arg;
+} bl_uart_notify_t;
+
+static bl_uart_notify_t g_uart_notify_arg[UART_NUMBER_SUPPORTED];
+
+
+static void uart_init_demo(uint8_t id)
+{
+    static UART_CFG_Type uartCfg = {
+        80*1000*1000,                                        /* UART clock */
+        2000000,                                             /* UART Baudrate */
+        UART_DATABITS_8,                                     /* UART data bits length */
+        UART_STOPBITS_1,                                     /* UART data stop bits length */
+        UART_PARITY_NONE,                                    /* UART no parity */
+        DISABLE,                                             /* Disable auto flow control */
+        DISABLE,                                             /* Disable rx input de-glitch function */
+        DISABLE,                                             /* Disable RTS output SW control mode */
+        DISABLE,                                             /* Disable tx output SW control mode */
+        DISABLE,                                             /* Disable tx lin mode */
+        DISABLE,                                             /* Disable rx lin mode */
+        0,                                                   /* Tx break bit count for lin mode */
+        UART_LSB_FIRST                                       /* UART each data byte is send out LSB-first */
+    };
+
+    /* Disable all interrupt */
+    UART_IntMask(id, UART_INT_ALL,MASK);
+
+    /* Disable uart before config */
+    UART_Disable(id, UART_TXRX);
+
+    /* UART init */
+    UART_Init(id, &uartCfg);
+
+    /* Enable tx free run mode */
+    UART_TxFreeRun(id, ENABLE);
+
+    /* Enable uart */
+    UART_Enable(id, UART_TXRX);
+}
+
+static int uart_signal_get(uint8_t pin)
+{
+    //TODO no magic number is allowed here
+    if (pin >= 12 && pin <=23) {
+        return (pin + 6) % 12;
+    } else if (pin >= 36 && pin <=45) {
+        return (pin + 6) % 12;
+    }
+    return (pin % 12);
+}
+
+static int uart_func_get(uint8_t id, GLB_UART_SIG_FUN_Type uartfunc)
+{
+    switch (id) {
+        case 0:
+            return uartfunc;
+        case 1:
+            return (GLB_UART_SIG_FUN_UART1_RTS - GLB_UART_SIG_FUN_UART0_RTS) * 1 + uartfunc;
+        case 2:
+            return (GLB_UART_SIG_FUN_UART1_RTS - GLB_UART_SIG_FUN_UART0_RTS) * 1 + uartfunc;
+        default:
+            /*empty here*/
+            //TODO should assert here?
+            return uartfunc;
+    }
+}
+
+static void uart_gpio_demo(uint8_t id, uint8_t tx_pin, uint8_t rx_pin, uint8_t cts_pin, uint8_t rts_pin)
+{
+    GLB_GPIO_Cfg_Type gpio_cfg;
+    uint8_t uart_func, uart_sig;
+
+    //FIXME SWAP set is NOT put here
+    GLB_UART_Sig_Swap_Set(GLB_UART_SIG_SWAP_GRP_GPIO12_GPIO23, 1);
+    GLB_UART_Sig_Swap_Set(GLB_UART_SIG_SWAP_GRP_GPIO36_GPIO45, 1);
+
+    //common GPIO cfg
+    gpio_cfg.drive = 0;
+    gpio_cfg.smtCtrl = 1;
+    gpio_cfg.gpioMode = GPIO_MODE_AF;
+    gpio_cfg.pullType = GPIO_PULL_UP;
+    gpio_cfg.gpioFun = GPIO_FUN_UART;
+    //cfg for UART Tx
+    gpio_cfg.gpioPin = GLB_GPIO_PIN_0 + tx_pin;
+    uart_func = uart_func_get(id, GLB_UART_SIG_FUN_UART0_TXD);
+    uart_sig = uart_signal_get(gpio_cfg.gpioPin);
+    GLB_UART_Fun_Sel((GLB_UART_SIG_Type)uart_sig, (GLB_UART_SIG_FUN_Type)uart_func);
+    GLB_UART_Fun_Sel((GLB_UART_SIG_Type)uart_func, (GLB_UART_SIG_FUN_Type)uart_sig);
+    GLB_GPIO_Init(&gpio_cfg);
+    //cfg for UART Rx
+    gpio_cfg.gpioPin = GLB_GPIO_PIN_0 + rx_pin;
+    uart_func = uart_func_get(id, GLB_UART_SIG_FUN_UART0_RXD);
+    uart_sig = uart_signal_get(gpio_cfg.gpioPin);
+    GLB_UART_Fun_Sel((GLB_UART_SIG_Type)uart_sig, (GLB_UART_SIG_FUN_Type)uart_func);
+    GLB_UART_Fun_Sel((GLB_UART_SIG_Type)uart_func, (GLB_UART_SIG_FUN_Type)uart_sig);
+    GLB_GPIO_Init(&gpio_cfg);
+
+    //Enable UART clock
+    GLB_Set_UART_CLK(1, 0, 0);
+}
+
+int bl_uart_init(uint8_t id, uint8_t tx_pin, uint8_t rx_pin, uint8_t cts_pin, uint8_t rts_pin, uint32_t baudrate)
+{
+    UART_CFG_Type uart_dbg_cfg = {
+    //   32 * 1000 * 1000, /*UART clock*/
+      80*1000*1000, /*UART clock from XTAL*/
+      2000000,          /* baudrate  */
+      UART_DATABITS_8,  /* data bits  */
+      UART_STOPBITS_1,  /* stop bits */
+      UART_PARITY_NONE, /* parity  */
+      DISABLE,          /* Disable auto flow control */
+      DISABLE,          /* Disable rx input de-glitch function */
+      DISABLE,          /* Disable RTS output SW control mode */
+      DISABLE,          /* Disable tx output SW control mode */
+      DISABLE,          /* Disable tx lin mode */
+      DISABLE,          /* Disable rx lin mode */
+      0,                /* Tx break bit count for lin mode */
+      UART_LSB_FIRST,   /* UART each data byte is send out LSB-first */
+    };
+
+    UART_FifoCfg_Type fifoCfg = {
+      16,      /* TX FIFO threshold */
+      16,      /* RX FIFO threshold */
+      DISABLE, /* Disable tx dma req/ack interface */
+      DISABLE  /* Disable rx dma req/ack interface */
+    };
+
+    /* init debug uart gpio first */
+    uart_gpio_demo(id, tx_pin, rx_pin, cts_pin, rts_pin);
+    uart_init_demo(id);
+
+    /* disable all interrupt */
+    UART_IntMask(id, UART_INT_ALL, MASK);
+
+    /* disable uart before config */
+    UART_Disable(id, UART_TXRX);
+
+    /* uart init with default configuration */
+    UART_Init(id, &uart_dbg_cfg);
+
+    /* UART fifo configuration */
+    UART_FifoConfig(id, &fifoCfg);
+
+    /* Enable tx free run mode */
+    UART_TxFreeRun(id, ENABLE);
+
+    /* Set rx time-out value */
+    UART_SetRxTimeoutValue(id, 80);
+
+    /* enable uart */
+    UART_AutoBaudDetection(id, 0);
+    UART_Enable(id, UART_TXRX);
+
+    return 0;
+}
+
+/*This function is NOT thread safe*/
+int bl_uart_data_send(uint8_t id, uint8_t data)
+{
+
+//    UART_SendData(id, &data,1);
+    uint32_t UARTx = uartAddr[id];
+
+    /* Wait for FIFO */
+    while (UART_GetTxFifoCount(id) == 0) {
+    }
+
+    BL_WR_BYTE(UARTx + UART_FIFO_WDATA_OFFSET, data);
+
+    return 0;
+}
+
+int bl_uart_data_recv(uint8_t id)
+{
+    int ret;
+    uint32_t UARTx = uartAddr[id];
+
+    /* Receive data */
+    if (UART_GetRxFifoCount(id) > 0) {
+        ret  = BL_RD_BYTE(UARTx + UART_FIFO_RDATA_OFFSET);
+    } else {
+        ret = -1;
+    }
+
+    return ret;
+}
+
+int bl_uart_int_rx_enable(uint8_t id)
+{
+    UART_SetRxTimeoutValue((UART_ID_Type)id, 24);
+    UART_IntMask((UART_ID_Type)id, UART_INT_RX_FIFO_REQ, UNMASK);
+    UART_IntMask((UART_ID_Type)id, UART_INT_RX_END, UNMASK);
+    UART_IntMask((UART_ID_Type)id, UART_INT_RTO, UNMASK);
+    return 0;
+}
+
+int bl_uart_int_rx_disable(uint8_t id)
+{
+    UART_IntMask((UART_ID_Type)id, UART_INT_RX_FIFO_REQ, MASK);
+    UART_IntMask((UART_ID_Type)id, UART_INT_RX_END, MASK);
+    UART_IntMask((UART_ID_Type)id, UART_INT_RTO, MASK);
+    return 0;
+}
+
+int bl_uart_int_tx_enable(uint8_t id)
+{
+    UART_IntMask((UART_ID_Type)id, UART_INT_TX_FIFO_REQ, UNMASK);
+    return 0;
+}
+
+int bl_uart_int_tx_disable(uint8_t id)
+{
+    UART_IntMask((UART_ID_Type)id, UART_INT_TX_FIFO_REQ, MASK);
+    return 0;
+}
+
+int bl_uart_flush(uint8_t id)
+{
+    /* Wait for FIFO */
+    while (UART_FIFO_TX_CNT != UART_GetTxFifoCount(id)) {
+    }
+
+    return 0;
+}
+
+void bl_uart_getdefconfig(uint8_t id, uint8_t *parity)
+{
+    if (NULL == parity) {
+        return;
+    }
+
+    //*baudrate = 115200;/* not support set no baud */
+    *parity = (uint8_t)UART_PARITY_NONE;
+}
+
+void bl_uart_setbaud(uint8_t id, uint32_t baud)
+{
+    //FIXME
+    puts("uart is NOT implemented\r\n");
+    while (1) {
+    }
+}
+
+int bl_uart_int_enable(uint8_t id)
+{
+    switch (id) {
+        case 0:
+        {
+            bl_uart_int_rx_enable(0);
+            // bl_uart_int_tx_enable(0);
+            bl_irq_register(UART0_IRQn, UART0_IRQHandler);
+            bl_irq_enable(UART0_IRQn);
+        }
+        break;
+        case 1:
+        {
+            bl_uart_int_rx_enable(1);
+            // bl_uart_int_tx_enable(1);
+            bl_irq_register(UART1_IRQn, UART1_IRQHandler);
+            bl_irq_enable(UART1_IRQn);
+        }
+        break;
+        case 2:
+        {
+            bl_uart_int_rx_enable(2);
+            // bl_uart_int_tx_enable(2);
+            bl_irq_register(UART2_IRQn, UART2_IRQHandler);
+            bl_irq_enable(UART2_IRQn);
+        }
+        break;
+        case 3:
+        {
+            bl_uart_int_rx_enable(3);
+            // bl_uart_int_tx_enable(3);
+            bl_irq_register(UART3_IRQn, UART3_IRQHandler);
+            bl_irq_enable(UART3_IRQn);
+        }
+        break;
+        default:
+        {
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+int bl_uart_int_disable(uint8_t id)
+{
+    switch (id) {
+        case 0:
+        {
+            bl_uart_int_rx_disable(0);
+            bl_uart_int_tx_disable(0);
+            bl_irq_unregister(UART0_IRQn, UART0_IRQHandler);
+            bl_irq_disable(UART0_IRQn);
+        }
+        break;
+        case 1:
+        {
+            bl_uart_int_rx_disable(1);
+            bl_uart_int_tx_disable(1);
+            bl_irq_unregister(UART1_IRQn, UART1_IRQHandler);
+            bl_irq_disable(UART1_IRQn);
+        }
+        break;
+        case 2:
+        {
+            bl_uart_int_rx_disable(2);
+            bl_uart_int_tx_disable(2);
+            bl_irq_unregister(UART2_IRQn, UART2_IRQHandler);
+            bl_irq_disable(UART2_IRQn);
+        }
+        break;
+        case 3:
+        {
+            bl_uart_int_rx_disable(3);
+            bl_uart_int_tx_disable(3);
+            bl_irq_unregister(UART3_IRQn, UART3_IRQHandler);
+            bl_irq_disable(UART3_IRQn);
+        }
+        break;
+        default:
+        {
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+int bl_uart_int_rx_notify_register(uint8_t id, cb_uart_notify_t cb, void *arg)
+{
+    if (!(id < UART_NUMBER_SUPPORTED)) {
+        /*UART ID overflow*/
+        return -1;
+    }
+
+    g_uart_notify_arg[id].rx_cb = cb;
+    g_uart_notify_arg[id].rx_cb_arg = arg;
+
+    return 0;
+}
+
+int bl_uart_int_tx_notify_register(uint8_t id, cb_uart_notify_t cb, void *arg)
+{
+    if (!(id < UART_NUMBER_SUPPORTED)) {
+        /*UART ID overflow*/
+        return -1;
+    }
+
+    g_uart_notify_arg[id].tx_cb = cb;
+    g_uart_notify_arg[id].tx_cb_arg = arg;
+
+    return 0;
+}
+
+int bl_uart_int_rx_notify_unregister(uint8_t id, cb_uart_notify_t cb, void *arg)
+{
+    if (!(id < UART_NUMBER_SUPPORTED)) {
+        /*UART ID overflow*/
+        return -1;
+    }
+    g_uart_notify_arg[id].rx_cb = NULL;
+    g_uart_notify_arg[id].rx_cb_arg = NULL;
+
+    return 0;
+}
+
+int bl_uart_int_tx_notify_unregister(uint8_t id, cb_uart_notify_t cb, void *arg)
+{
+    if (!(id < UART_NUMBER_SUPPORTED)) {
+        /*UART ID overflow*/
+        return -1;
+    }
+    g_uart_notify_arg[id].tx_cb = NULL;
+    g_uart_notify_arg[id].tx_cb_arg = NULL;
+
+    return 0;
+}
+
+static inline void uart_generic_notify_handler(uint8_t id)
+{
+    cb_uart_notify_t cb;
+    void *arg;
+    uint32_t tmpVal = 0;
+    uint32_t maskVal = 0;
+    uint32_t UARTx = uartAddr[id];
+
+    tmpVal = BL_RD_REG(UARTx,UART_INT_STS);
+    maskVal = BL_RD_REG(UARTx,UART_INT_MASK);
+
+    /* Length of uart tx data transfer arrived interrupt */
+    if(BL_IS_REG_BIT_SET(tmpVal,UART_UTX_END_INT) && !BL_IS_REG_BIT_SET(maskVal,UART_CR_UTX_END_MASK)){
+        BL_WR_REG(UARTx,UART_INT_CLEAR,0x1);
+    }
+
+    /* Length of uart rx data transfer arrived interrupt */
+    if(BL_IS_REG_BIT_SET(tmpVal,UART_URX_END_INT) && !BL_IS_REG_BIT_SET(maskVal,UART_CR_URX_END_MASK)){
+        BL_WR_REG(UARTx,UART_INT_CLEAR,0x2);
+
+        /*Receive Data ready*/
+        cb = g_uart_notify_arg[id].rx_cb;
+        arg = g_uart_notify_arg[id].rx_cb_arg;
+
+        if (cb) {
+            /*notify up layer*/
+            cb(arg);
+        }
+    }
+
+    /* Tx fifo ready interrupt,auto-cleared when data is pushed */
+    if(BL_IS_REG_BIT_SET(tmpVal,UART_UTX_FRDY_INT) && !BL_IS_REG_BIT_SET(maskVal,UART_CR_UTX_FRDY_MASK)){
+        /* Transmit data request interrupt */
+        cb = g_uart_notify_arg[id].tx_cb;
+        arg = g_uart_notify_arg[id].tx_cb_arg;
+
+        if (cb) {
+            /*notify up layer*/
+            cb(arg);
+        }
+    }
+
+    /* Rx fifo ready interrupt,auto-cleared when data is popped */
+    if(BL_IS_REG_BIT_SET(tmpVal,UART_URX_FRDY_INT) && !BL_IS_REG_BIT_SET(maskVal,UART_CR_URX_FRDY_MASK)){
+        /*Receive Data ready*/
+
+        cb = g_uart_notify_arg[id].rx_cb;
+        arg = g_uart_notify_arg[id].rx_cb_arg;
+
+        if (cb) {
+            /*notify up layer*/
+            cb(arg);
+        }
+    }
+
+    /* Rx time-out interrupt */
+    if (BL_IS_REG_BIT_SET(tmpVal,UART_URX_RTO_INT) && !BL_IS_REG_BIT_SET(maskVal,UART_CR_URX_RTO_MASK)){
+        BL_WR_REG(UARTx,UART_INT_CLEAR,0x10);
+
+        /*Receive Data ready*/
+        cb = g_uart_notify_arg[id].rx_cb;
+        arg = g_uart_notify_arg[id].rx_cb_arg;
+
+        if (cb) {
+            /*notify up layer*/
+            cb(arg);
+        }
+    }
+
+    /* Rx parity check error interrupt */
+    if(BL_IS_REG_BIT_SET(tmpVal,UART_URX_PCE_INT) && !BL_IS_REG_BIT_SET(maskVal,UART_CR_URX_PCE_MASK)){
+        BL_WR_REG(UARTx,UART_INT_CLEAR,0x20);
+    }
+
+    /* Tx fifo overflow/underflow error interrupt */
+    if(BL_IS_REG_BIT_SET(tmpVal,UART_UTX_FER_INT) && !BL_IS_REG_BIT_SET(maskVal,UART_CR_UTX_FER_MASK)){
+    }
+
+    /* Rx fifo overflow/underflow error interrupt */
+    if(BL_IS_REG_BIT_SET(tmpVal,UART_URX_FER_INT) && !BL_IS_REG_BIT_SET(maskVal,UART_CR_URX_FER_MASK)){
+    }
+
+    return;
+}
+
+#ifdef BFLB_USE_HAL_DRIVER
+void UART0_IRQHandler(void)
+{
+    uart_generic_notify_handler(0);
+}
+
+void UART1_IRQHandler(void)
+{
+    uart_generic_notify_handler(1);
+}
+
+void UART2_IRQHandler(void)
+{
+    uart_generic_notify_handler(2);
+}
+
+void UART3_IRQHandler(void)
+{
+    uart_generic_notify_handler(3);
+}
+#endif
+

+ 62 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_uart.h

@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __BL_UART_H__
+#define __BL_UART_H__
+#include <stdint.h>
+#define BL_UART_BUFFER_SIZE_MIN   (128)
+#define BL_UART_BUFFER_SIZE_MASK  (128 - 1)
+
+typedef void (*cb_uart_notify_t)(void *arg);
+int bl_uart_gpio_init(uint8_t id, uint8_t tx, uint8_t rx, uint8_t rts, uint8_t cts, int baudrate);
+int bl_uart_init(uint8_t id, uint8_t tx_pin, uint8_t rx_pin, uint8_t cts_pin, uint8_t rts_pin, uint32_t baudrate);
+int bl_uart_simple_init(uint8_t id, uint8_t tx_pin, uint8_t rx_pin, uint8_t cts_pin, uint8_t rts_pin, uint32_t baudrate);
+int bl_uart_debug_early_init(uint32_t baudrate);
+int bl_uart_early_init(uint8_t id, uint8_t tx_pin, uint32_t baudrate);
+
+int bl_uart_int_rx_enable(uint8_t id);
+int bl_uart_int_rx_disable(uint8_t id);
+int bl_uart_int_tx_enable(uint8_t id);
+int bl_uart_int_tx_disable(uint8_t id);
+int bl_uart_string_send(uint8_t id, char *data);
+int bl_uart_flush(uint8_t id);
+void bl_uart_getdefconfig(uint8_t id, uint8_t *parity);
+//FIXME fix bl_uart_setconfig
+//void bl_uart_setconfig(uint8_t id, uint32_t baudrate, UART_Parity_Type parity);
+void bl_uart_setbaud(uint8_t id, uint32_t baud);
+int bl_uart_data_send(uint8_t id, uint8_t data);
+int bl_uart_datas_send(uint8_t id, uint8_t *data, int len);
+int bl_uart_data_recv(uint8_t id);
+int bl_uart_int_enable(uint8_t id);
+int bl_uart_int_disable(uint8_t id);
+int bl_uart_int_rx_notify_register(uint8_t id, cb_uart_notify_t cb, void *arg);
+int bl_uart_int_tx_notify_register(uint8_t id, cb_uart_notify_t cb, void *arg);
+int bl_uart_int_rx_notify_unregister(uint8_t id, cb_uart_notify_t cb, void *arg);
+int bl_uart_int_tx_notify_unregister(uint8_t id, cb_uart_notify_t cb, void *arg);
+#endif

+ 322 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_usb_cam.c

@@ -0,0 +1,322 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <FreeRTOS.h>
+#include <semphr.h>
+#include <bl_cam.h>
+#include <bl808_glb.h>
+#include <usbd_core.h>
+#include <usbd_video.h>
+#include "bl_usb_cam.h"
+
+#define VIDEO_IN_EP 0x81
+
+#ifdef CONFIG_USB_HS
+#define MAX_PAYLOAD_SIZE  1024
+#else
+#define MAX_PAYLOAD_SIZE  1023
+#endif
+#define VIDEO_PACKET_SIZE (unsigned int)(((MAX_PAYLOAD_SIZE / 1)) | (0x00 << 11))
+
+#define WIDTH  (unsigned int)(800)
+#define HEIGHT (unsigned int)(600)
+
+#define CAM_FPS        (30)
+#define INTERVAL       (unsigned long)(10000000 / CAM_FPS)
+#define MIN_BIT_RATE   (unsigned long)(WIDTH * HEIGHT * 16 * CAM_FPS) //16 bit
+#define MAX_BIT_RATE   (unsigned long)(WIDTH * HEIGHT * 16 * CAM_FPS)
+#define MAX_FRAME_SIZE (unsigned long)(WIDTH * HEIGHT * 2)
+
+#define USB_VIDEO_DESC_SIZ (unsigned long)(9 +  \
+                                           8 +  \
+                                           9 +  \
+                                           13 + \
+                                           18 + \
+                                           9 +  \
+                                           12 + \
+                                           9 +  \
+                                           14 + \
+                                           11 + \
+                                           38 + \
+                                           9 +  \
+                                           7)
+
+#define VC_TERMINAL_SIZ (unsigned int)(13 + 18 + 12 + 9)
+#define VS_HEADER_SIZ   (unsigned int)(13 + 1 + 11 + 38)
+
+#define USBD_VID           0xffff
+#define USBD_PID           0xffff
+#define USBD_MAX_POWER     100
+#define USBD_LANGID_STRING 1033
+#define TASK_MAIN_PRIORITY 20
+#define PER_FRAME_MJPEG     100*1024
+#define USB_MAX_BUFFER      120*1024
+#define MJPEG_DEFAULT_ADDR  0x80400000 //if mjpeg no init mjpeg addr reg default value
+
+const uint8_t video_descriptor[] = {
+    USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0001, 0x01),
+    USB_CONFIG_DESCRIPTOR_INIT(USB_VIDEO_DESC_SIZ, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
+    VIDEO_VC_DESCRIPTOR_INIT(0x00, 0, 0x0100, VC_TERMINAL_SIZ, 48000000, 0x02),
+    VIDEO_VS_DESCRIPTOR_INIT(0x01, 0x00, 0x00),
+    VIDEO_VS_HEADER_DESCRIPTOR_INIT(0x01, VS_HEADER_SIZ, VIDEO_IN_EP, 1, 0x00),
+    VIDEO_VS_FORMAT_MJPEG_DESCRIPTOR_INIT(0x01, 0x01),
+    VIDEO_VS_FRAME_MJPEG_DESCRIPTOR_INIT(0x01, WIDTH, HEIGHT, MIN_BIT_RATE, MAX_BIT_RATE, MAX_FRAME_SIZE, INTERVAL, 0x00, DBVAL(INTERVAL), DBVAL(INTERVAL), DBVAL(0)),
+    VIDEO_VS_DESCRIPTOR_INIT(0x01, 0x01, 0x01),
+    /* 1.2.2.2 Standard VideoStream Isochronous Video Data Endpoint Descriptor */
+    0x07,                         /* bLength */
+    USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: ENDPOINT */
+    0x81,                         /* bEndpointAddress: IN endpoint 2 */
+    0x01,                         /* bmAttributes: Isochronous transfer type. Asynchronous synchronization type. */
+    WBVAL(VIDEO_PACKET_SIZE),     /* wMaxPacketSize */
+    0x01,                         /* bInterval: One frame interval */
+
+    ///////////////////////////////////////
+    /// string0 descriptor
+    ///////////////////////////////////////
+    USB_LANGID_INIT(USBD_LANGID_STRING),
+    ///////////////////////////////////////
+    /// string1 descriptor
+    ///////////////////////////////////////
+    0x12,                       /* bLength */
+    USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
+    'B', 0x00,                  /* wcChar0 */
+    'o', 0x00,                  /* wcChar1 */
+    'u', 0x00,                  /* wcChar2 */
+    'f', 0x00,                  /* wcChar3 */
+    'f', 0x00,                  /* wcChar4 */
+    'a', 0x00,                  /* wcChar5 */
+    'l', 0x00,                  /* wcChar6 */
+    'o', 0x00,                  /* wcChar7 */
+    ///////////////////////////////////////
+    /// string2 descriptor
+    ///////////////////////////////////////
+    0x28,                       /* bLength */
+    USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
+    'B', 0x00,                  /* wcChar0 */
+    'o', 0x00,                  /* wcChar1 */
+    'u', 0x00,                  /* wcChar2 */
+    'f', 0x00,                  /* wcChar3 */
+    'f', 0x00,                  /* wcChar4 */
+    'a', 0x00,                  /* wcChar5 */
+    'l', 0x00,                  /* wcChar6 */
+    'o', 0x00,                  /* wcChar7 */
+    ' ', 0x00,                  /* wcChar8 */
+    'V', 0x00,                  /* wcChar9 */
+    'E', 0x00,                  /* wcChar10 */
+    'D', 0x00,                  /* wcChar11 */
+    'I', 0x00,                  /* wcChar12 */
+    'O', 0x00,                  /* wcChar13 */
+    ' ', 0x00,                  /* wcChar14 */
+    'D', 0x00,                  /* wcChar15 */
+    'E', 0x00,                  /* wcChar16 */
+    'M', 0x00,                  /* wcChar17 */
+    'O', 0x00,                  /* wcChar18 */
+    ///////////////////////////////////////
+    /// string3 descriptor
+    ///////////////////////////////////////
+    0x16,                       /* bLength */
+    USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
+    '2', 0x00,                  /* wcChar0 */
+    '0', 0x00,                  /* wcChar1 */
+    '2', 0x00,                  /* wcChar2 */
+    '1', 0x00,                  /* wcChar3 */
+    '0', 0x00,                  /* wcChar4 */
+    '3', 0x00,                  /* wcChar5 */
+    '1', 0x00,                  /* wcChar6 */
+    '0', 0x00,                  /* wcChar7 */
+    '0', 0x00,                  /* wcChar8 */
+    '0', 0x00,                  /* wcChar9 */
+#ifdef CONFIG_USB_HS
+    ///////////////////////////////////////
+    /// device qualifier descriptor
+    ///////////////////////////////////////
+    0x0a,
+    USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
+    0x00,
+    0x02,
+    0x00,
+    0x00,
+    0x00,
+    0x40,
+    0x01,
+    0x00,
+#endif
+    0x00
+};
+
+static usbd_class_t video_class;
+static usbd_interface_t video_control_intf;
+static usbd_interface_t video_stream_intf;
+#if defined NO_PSRAM_HEAP
+#define CUSTOMER_SECTION    __attribute__((section(".custom_psram_bss")))
+static uint8_t usb_buffer[USB_MAX_BUFFER]  CUSTOMER_SECTION;
+static uint8_t mjpeg_swap_buffer[PER_FRAME_MJPEG] CUSTOMER_SECTION;
+#else
+static uint8_t *usb_buffer = NULL;
+static uint8_t *mjpeg_swap_buffer = NULL;
+#endif
+static uint32_t mjpeg_start_addr, mjpeg_buffer_size;
+SemaphoreHandle_t usb_cam_semap = NULL;
+
+void usbd_video_iso_callback(uint8_t ep)
+{
+    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
+    if (usb_cam_semap) {
+        xSemaphoreGiveFromISR(usb_cam_semap, &xHigherPriorityTaskWoken);
+        portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
+    }
+}
+
+static usbd_endpoint_t video_in_ep = {
+    .ep_cb = usbd_video_iso_callback,
+    .ep_addr = VIDEO_IN_EP
+};
+
+volatile bool tx_flag = 0;
+
+void usbd_video_open(uint8_t intf)
+{
+    tx_flag = 1;
+    printf("OPEN\r\n");
+}
+void usbd_video_close(uint8_t intf)
+{
+    printf("CLOSE\r\n");
+    tx_flag = 0;
+}
+
+static void bl_usb_clock_init(void)
+{
+    uint32_t tmpVal;
+
+    tmpVal = BL_RD_REG(GLB_BASE, GLB_CGEN_CFG1);
+    tmpVal |= (1 << 13);
+    BL_WR_REG(GLB_BASE, GLB_CGEN_CFG1, tmpVal);
+    GLB_Set_USB_CLK_From_WIFIPLL(1);
+}
+
+int bl_usb_cam_init(void)
+{
+    int ret = 0;
+
+    ret = bl_cam_mjpeg_buffer_info_get(&mjpeg_start_addr, &mjpeg_buffer_size);
+    if (ret != 0) {
+        printf("mjpeg not init\r\n");
+        goto exit;
+    }
+
+    usb_cam_semap = xSemaphoreCreateBinary();
+    if (NULL == usb_cam_semap) {
+        printf("create usb_cam_semap fail\r\n");
+        ret = -1;
+        goto exit;
+    }
+
+#ifndef NO_PSRAM_HEAP
+    usb_buffer = pvPortMalloc(USB_MAX_BUFFER);
+    if (NULL == usb_buffer) {
+        printf("malloc usb_buffer fail!\r\n");
+        vSemaphoreDelete(usb_cam_semap);
+        usb_cam_semap = NULL;
+        ret = -1;
+        goto exit;
+    }
+
+    mjpeg_swap_buffer = pvPortMalloc(PER_FRAME_MJPEG);
+    if (NULL == mjpeg_swap_buffer) {
+        printf("malloc mjpeg_swap_buffer fail!\r\n");
+        vPortFree(usb_buffer);
+        usb_buffer = NULL;
+        vSemaphoreDelete(usb_cam_semap);
+        usb_cam_semap = NULL;
+        ret = -1;
+        goto exit;
+    }
+#endif
+    bl_usb_clock_init();
+    usbd_desc_register(video_descriptor);
+    usbd_video_add_interface(&video_class, &video_control_intf);
+    usbd_video_add_interface(&video_class, &video_stream_intf);
+    usbd_interface_add_endpoint(&video_stream_intf, &video_in_ep);
+
+    usbd_video_probe_and_commit_controls_init(CAM_FPS, MAX_FRAME_SIZE, MAX_PAYLOAD_SIZE);
+    usbd_initialize();
+
+    xSemaphoreGive(usb_cam_semap);
+exit:
+    return ret;
+}
+
+int bl_usb_cam_transfer(void)
+{
+    int ret = 0;
+    uint8_t *pic, *usb_ptr;
+    uint32_t len, first_len, second_len, out_len;
+
+    if (tx_flag) {
+        ret = bl_cam_mjpeg_get(&pic, &len);
+        if (ret == 0) {
+            if (((uint32_t)(uintptr_t)pic + len) > (mjpeg_start_addr + mjpeg_buffer_size)) {
+                /* if mjpeg store edge loop to start*/
+                first_len = mjpeg_start_addr + mjpeg_buffer_size - (uint32_t)(uintptr_t)pic;
+                second_len = len - first_len;
+                csi_dcache_invalid_range((void *)pic, first_len);
+                memcpy(mjpeg_swap_buffer, pic, first_len);
+                csi_dcache_invalid_range((void *)mjpeg_start_addr, second_len);
+                memcpy(mjpeg_swap_buffer + first_len, (void *)mjpeg_start_addr, second_len);
+                usb_ptr = mjpeg_swap_buffer;
+            } else {
+                /*mjpeg data not cut*/
+                usb_ptr = pic;
+                csi_dcache_invalid_range((void *)usb_ptr, len);
+            }
+
+            if (NULL == usb_cam_semap) {
+                ret = -1;
+                goto exit;
+            }
+            if (len > USB_MAX_BUFFER) {
+                ret = -1;
+                printf("jpeg frame size is out of %dbytes\r\n", USB_MAX_BUFFER);
+                goto exit;
+            }
+            xSemaphoreTake(usb_cam_semap, portMAX_DELAY);
+            /*fill mjpeg in usb data struct*/
+            usbd_video_mjpeg_payload_fill(usb_ptr, len, usb_buffer, &out_len);
+            bl_cam_mjpeg_pop();
+
+            /* send usb data async*/
+            usbd_ep_write_async(VIDEO_IN_EP, usb_buffer, out_len);
+        }
+    }
+
+exit:
+    return ret;
+}
+

+ 35 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_usb_cam.h

@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __BL_USB_CAM_H__
+#define __BL_USB_CAM_H__
+#include <stdint.h>
+int bl_usb_cam_init(void);
+int bl_usb_cam_transfer(void);
+#endif

+ 255 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_wifi.c

@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdint.h>
+#include <string.h>
+#include <stdio.h>
+
+//FIXME no BL808/BL606p header file including is Allowed here
+#ifdef BL808
+#include <bl808.h>
+#include <bl808_glb.h>
+#elif defined(BL606P)
+#include <bl606p.h>
+#include <bl606p_glb.h>
+#else
+#error "Use CHIP BL808/BL606P for this module"
+#endif
+
+#include "bl_wifi.h"
+#include "bl_irq.h"
+
+typedef struct _bl_wifi_env {
+    uint8_t sta_mac_addr_board[6];
+    uint8_t sta_mac_addr_usr[6];
+    uint8_t ap_mac_addr_board[6];
+    uint8_t ap_mac_addr_usr[6];
+    uint8_t country_code;
+
+    bl_wifi_ap_info_t ap_info;
+    uint8_t ap_info_en;
+
+    bl_wifi_ap_info_t sta_info;
+    uint8_t sta_info_en;
+} bl_wifi_env_t;
+
+bl_wifi_env_t wifi_env = {
+    .sta_mac_addr_board = {0x18, 0xb9, 0x05, 0x88, 0x88, 0x88}
+};
+
+
+/****************************************************************************/ /**
+ * @brief  set wifi core clock divider
+ *
+ * @param  clkDiv: divider
+ *
+ * @return SUCCESS or ERROR
+ *
+*******************************************************************************/
+/* 0x3B0 : wifi_cfg0 */
+#define GLB_WIFI_CFG0_OFFSET                                    (0x3B0)
+#define GLB_WIFI_MAC_CORE_DIV                                   GLB_WIFI_MAC_CORE_DIV
+#define GLB_WIFI_MAC_CORE_DIV_POS                               (0U)
+#define GLB_WIFI_MAC_CORE_DIV_LEN                               (4U)
+#define GLB_WIFI_MAC_CORE_DIV_MSK                               (((1U<<GLB_WIFI_MAC_CORE_DIV_LEN)-1)<<GLB_WIFI_MAC_CORE_DIV_POS)
+#define GLB_WIFI_MAC_CORE_DIV_UMSK                              (~(((1U<<GLB_WIFI_MAC_CORE_DIV_LEN)-1)<<GLB_WIFI_MAC_CORE_DIV_POS))
+#define GLB_WIFI_MAC_WT_DIV                                     GLB_WIFI_MAC_WT_DIV
+#define GLB_WIFI_MAC_WT_DIV_POS                                 (4U)
+#define GLB_WIFI_MAC_WT_DIV_LEN                                 (4U)
+#define GLB_WIFI_MAC_WT_DIV_MSK                                 (((1U<<GLB_WIFI_MAC_WT_DIV_LEN)-1)<<GLB_WIFI_MAC_WT_DIV_POS)
+#define GLB_WIFI_MAC_WT_DIV_UMSK                                (~(((1U<<GLB_WIFI_MAC_WT_DIV_LEN)-1)<<GLB_WIFI_MAC_WT_DIV_POS))
+BL_Err_Type GLB_Set_WiFi_Core_CLK(uint8_t clkDiv)
+{
+    uint32_t tmpVal = 0;
+
+    CHECK_PARAM((clkDiv <= 0xF));
+
+    tmpVal = BL_RD_REG(GLB_BASE, GLB_WIFI_CFG0);
+    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, GLB_WIFI_MAC_CORE_DIV, clkDiv);
+    BL_WR_REG(GLB_BASE, GLB_WIFI_CFG0, tmpVal);
+
+    return SUCCESS;
+}
+
+int bl_wifi_clock_enable(void)
+{
+    static int called = 0;
+    if (0 == called) {
+        called = 1;
+        //GLB_Set_System_CLK(PLL_XTAL_38P4M, GLB_PLL_CLK_160M);
+        GLB_Set_WiFi_Core_CLK(1);//0: 80MHZ, 1: 40MHZ
+    }
+    return 0;
+}
+
+void mac_irq(void);
+void bl_irq_handler(void);
+
+int bl_wifi_enable_irq(void)
+{
+    bl_irq_register(WIFI_IRQn, mac_irq);
+    bl_irq_register(WIFI_IPC_PUBLIC_IRQn, bl_irq_handler);
+    bl_irq_enable(WIFI_IRQn);
+    bl_irq_enable(WIFI_IPC_PUBLIC_IRQn);
+
+    //NVIC_SetPriority((IRQn_Type)5, 0);
+    //NVIC_EnableIRQ((IRQn_Type)5);
+    puts("Enable BMX IRQ\r\n");
+    //NVIC_EnableIRQ((IRQn_Type)0);
+    //NVIC_EnableIRQ((IRQn_Type)1);
+    //NVIC_EnableIRQ((IRQn_Type)2);
+    //NVIC_EnableIRQ((IRQn_Type)3);
+    //NVIC_EnableIRQ((IRQn_Type)4);
+    //*(uint32_t*)0x40000050 = ((0xF << 28) | (1 << 24));
+
+    return 0;
+}
+
+
+int bl_wifi_sta_mac_addr_set(uint8_t mac[6])
+{
+    memcpy(wifi_env.sta_mac_addr_board, mac, 6);
+    return 0;
+}
+
+int bl_wifi_ap_mac_addr_set(uint8_t mac[6])
+{
+    memcpy(wifi_env.ap_mac_addr_board, mac, 6);
+    return 0;
+}
+
+int bl_wifi_mac_addr_set(uint8_t mac[6])
+{
+    memcpy(wifi_env.sta_mac_addr_usr, mac, 6);
+    return 0;
+}
+
+int bl_wifi_mac_addr_get(uint8_t mac[6])
+{
+    memcpy(mac, wifi_env.sta_mac_addr_board, 6);
+    return 0;
+}
+
+
+int bl_wifi_country_code_set(uint8_t country_code)
+{
+    wifi_env.country_code = country_code;
+    return 0;
+}
+
+#if 0
+int bl_wifi_power_table_set(bl_tx_pwr_tbl_t* tx_pwr_tbl)
+{
+    bl60x_fw_rf_tx_power_table_set(tx_pwr_tbl);
+    return 0;
+}
+#endif
+
+int bl_wifi_ap_info_set(uint8_t* ssid, uint8_t ssid_len, 
+                      uint8_t* psk, uint8_t psk_len,
+                      uint8_t chan)
+{
+    memset(&wifi_env.ap_info, 0, sizeof(bl_wifi_ap_info_t));
+    memcpy(wifi_env.ap_info.ssid, ssid, ssid_len);
+    memcpy(wifi_env.ap_info.psk, psk, psk_len);
+    wifi_env.ap_info.chan = chan;
+    wifi_env.ap_info_en = 1;
+    return 0;
+}
+
+int bl_wifi_ap_info_get(bl_wifi_ap_info_t* ap_info)
+{
+    if (wifi_env.ap_info_en != 1) {
+        return -1;
+    }
+    memcpy(ap_info, &wifi_env.ap_info, sizeof(bl_wifi_ap_info_t));
+    return 0;
+}
+
+int bl_wifi_sta_info_set(uint8_t* ssid, uint8_t ssid_len, uint8_t* psk, uint8_t psk_len, int autoconnect)
+{
+    memset(&wifi_env.sta_info, 0, sizeof(bl_wifi_ap_info_t));
+    memcpy(wifi_env.sta_info.ssid, ssid, ssid_len);
+    memcpy(wifi_env.sta_info.psk, psk, psk_len);
+    wifi_env.sta_info_en = autoconnect;
+    return 0;
+}
+
+int bl_wifi_sta_info_get(bl_wifi_ap_info_t* sta_info)
+{
+    if (wifi_env.sta_info_en != 1) {
+        return -1;
+    }
+    memcpy(sta_info, &wifi_env.sta_info, sizeof(bl_wifi_ap_info_t));
+    return 0;
+}
+
+#if 0
+int bl_wifi_netif_init(void)
+{
+    struct netif *netif = &wifi_netif;
+    ip4_addr_t ipaddr;
+    ip4_addr_t netmask;
+    ip4_addr_t gw;
+
+    ipaddr.addr = 0;
+    netmask.addr = 0;
+    gw.addr = 0;
+
+    netif->hwaddr[0] =  0x18;
+    netif->hwaddr[1] =  0xB9;
+    netif->hwaddr[2] =  0x05;
+    netif->hwaddr[3] =  0x88;
+    netif->hwaddr[4] =  0x88;
+    netif->hwaddr[5] =  0x88;
+
+    /* - netif_add(struct netif *netif, struct ip_addr *ipaddr,
+    *  struct ip_addr *netmask, struct ip_addr *gw,
+    *  void *state, err_t (* init)(struct netif *netif),
+    *  err_t (* input)(struct pbuf *p, struct netif *netif))
+    *
+    *  Adds your network interface to the netif_list. Allocate a struct
+    *  netif and pass a pointer to this structure as the first argument.
+    *  Give pointers to cleared ip_addr structures when using DHCP,
+    *  or fill them with sane numbers otherwise. The state pointer may be NULL.
+    *
+    * The init function pointer must point to a initialization function for
+    * your ethernet netif interface. The following code illustrates it's use.*/
+
+    netif_add(netif, &ipaddr, &netmask, &gw, NULL, &bl606a0_wifi_netif_init, &tcpip_input);
+    netif->name[0] = 's';
+    netif->name[1] = 't';
+    netif->flags |= NETIF_FLAG_LINK_UP;
+    netif_set_default(netif);
+    netif_set_up(netif);
+    netifapi_dhcp_start(netif);
+
+    return 0;
+}
+#endif

+ 52 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/bl_wifi.h

@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __BL_WIFI_H__
+#define __BL_WIFI_H__
+typedef struct bl_wifi_ap_info {
+    uint8_t ssid[33];
+    uint8_t psk[65];
+    uint8_t chan;
+} bl_wifi_ap_info_t;
+
+
+int bl_wifi_enable_irq(void);
+int bl_wifi_clock_enable(void);
+int bl_wifi_sta_mac_addr_set(uint8_t mac[6]);
+int bl_wifi_ap_mac_addr_set(uint8_t mac[6]);
+int bl_wifi_mac_addr_set(uint8_t mac[6]);
+int bl_wifi_country_code_set(uint8_t country_code);
+int bl_wifi_ap_info_set(uint8_t* ssid, uint8_t ssid_len, 
+                      uint8_t* psk, uint8_t psk_len,
+                      uint8_t chan);
+int bl_wifi_mac_addr_get(uint8_t mac[6]);
+int bl_wifi_ap_info_get(bl_wifi_ap_info_t* ap_info);
+int bl_wifi_sta_info_set(uint8_t* ssid, uint8_t ssid_len, uint8_t* psk, uint8_t psk_len, int autoconnect);
+int bl_wifi_sta_info_get(bl_wifi_ap_info_t* sta_info);
+#endif

+ 30 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/emac_phy.c

@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "phy_8720.c"

+ 49 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/ethernet_phy.h

@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __ETHERNET_PHY_H__
+#define __ETHERNET_PHY_H__
+
+#include "hal_emac.h"
+
+typedef enum emac_phy_status {
+    EMAC_PHY_STAT_EEROR,
+    EMAC_PHY_STAT_LINK_DOWN,
+    EMAC_PHY_STAT_LINK_INIT,
+    EMAC_PHY_STAT_LINK_UP,
+    EMAC_PHY_STAT_100MBITS_FULLDUPLEX,
+    EMAC_PHY_STAT_100MBITS_HALFDUPLEX,
+    EMAC_PHY_STAT_10MBITS_FULLDUPLEX,
+    EMAC_PHY_STAT_10MBITS_HALFDUPLEX,
+} emac_phy_status_t;
+
+emac_phy_status_t ethernet_phy_status_get();
+int emac_phy_init(emac_phy_cfg_t *cfg);
+
+#endif

+ 574 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/ethernetif.c

@@ -0,0 +1,574 @@
+/*
+ * Copyright (c) 2020 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "lwip/opt.h"
+#include "lwip/timeouts.h"
+#include "lwip/netif.h"
+#define LWIP_DHCP 0
+#if LWIP_DHCP
+#include "lwip/dhcp.h"
+#endif
+#include "netif/etharp.h"
+#include "ethernetif.h"
+#include <string.h>
+#include "hal_emac.h"
+#include <FreeRTOS.h>
+#include "semphr.h"
+#include "bflb_platform.h"
+/* Private typedef -----------------------------------------------------------*/
+/* Private define ------------------------------------------------------------*/
+/* Network interface name */
+#define IFNAME0 'b'
+#define IFNAME1 'l'
+
+#define ETH_DMA_TRANSMIT_TIMEOUT (20U)
+
+#define BL702_EMAC  0
+#define EMAC_OUTPUT BL702_EMAC
+
+#if LWIP_DHCP
+#define MAX_DHCP_TRIES 4
+uint32_t DHCPfineTimer = 0;
+uint8_t DHCP_state = DHCP_OFF;
+#else
+/*Static IP ADDRESS: IP_ADDR0.IP_ADDR1.IP_ADDR2.IP_ADDR3 */
+#define IP_ADDR0      (uint8_t)10
+#define IP_ADDR1      (uint8_t)28
+#define IP_ADDR2      (uint8_t)30
+#define IP_ADDR3      (uint8_t)221
+
+/*NETMASK*/
+#define NETMASK_ADDR0 (uint8_t)255
+#define NETMASK_ADDR1 (uint8_t)255
+#define NETMASK_ADDR2 (uint8_t)255
+#define NETMASK_ADDR3 (uint8_t)0
+
+/*Gateway Address*/
+#define GW_ADDR0      (uint8_t)10
+#define GW_ADDR1      (uint8_t)28
+#define GW_ADDR2      (uint8_t)30
+#define GW_ADDR3      (uint8_t)1
+#endif
+
+/* Private function prototypes -----------------------------------------------*/
+void pbuf_free_custom(struct pbuf *p);
+void ethernetif_input(void *argument);
+SemaphoreHandle_t emac_rx_sem = NULL;
+static StackType_t emac_rx_stack[256];
+static StaticTask_t emac_rx_handle;
+#if LWIP_DHCP
+static StackType_t emac_dhcp_stack[256];
+static StaticTask_t emac_dhcp_handle;
+#endif
+static uint8_t emac_rx_buffer[ETH_RX_BUFFER_SIZE] __attribute__((aligned(16))) = { 0 };
+
+LWIP_MEMPOOL_DECLARE(RX_POOL, 10, sizeof(struct pbuf_custom), "Zero-copy RX PBUF pool");
+
+/* Private functions ---------------------------------------------------------*/
+/*******************************************************************************
+                       LL Driver Interface ( LwIP stack --> ETH)
+*******************************************************************************/
+/**
+  * @brief In this function, the hardware should be initialized.
+  * Called from ethernetif_init().
+  *
+  * @param netif the already initialized lwip network interface structure
+  *        for this ethernetif
+  */
+extern void emac_init_txrx_buffer(void);
+extern int emac_phy_init(emac_phy_cfg_t *cfg);
+
+/* For emac tx and rx,we put here to make controlling it's size easy */
+#define ETH_RXBUFNB 5
+#define ETH_TXBUFNB 5
+#define ATTR_NOCACHE_RAM_SECTION   __attribute__((section(".nocache_ram")))
+ATTR_NOCACHE_RAM_SECTION ATTR_EALIGN(4) uint8_t ethRxBuff[ETH_RXBUFNB][ETH_RX_BUFFER_SIZE] ATTR_EALIGN(4) = { 0 }; /* Ethernet Receive Buffers */
+ATTR_NOCACHE_RAM_SECTION ATTR_EALIGN(4) uint8_t ethTxBuff[ETH_TXBUFNB][ETH_TX_BUFFER_SIZE] ATTR_EALIGN(4);         /* Ethernet Transmit Buffers */
+void emac_init_txrx_buffer(void)
+{
+    emac_bd_init((uint8_t *)ethTxBuff, ETH_TXBUFNB, (uint8_t *)ethRxBuff, ETH_RXBUFNB);
+
+}
+void dhcp_thread(void const *argument);
+void low_level_init(struct netif *netif)
+{
+    int ret = 0;
+
+    emac_device_t emac_cfg = {
+        .mac_addr[0] = 0x18,
+        .mac_addr[1] = 0xB9,
+        .mac_addr[2] = 0x05,
+        .mac_addr[3] = 0x12,
+        .mac_addr[4] = 0x34,
+        .mac_addr[5] = 0x56,
+    };
+
+    /* set phy cfg */
+    emac_phy_cfg_t phy_cfg = {
+        .auto_negotiation = 1, /*!< Speed and mode auto negotiation */
+        .full_duplex = 0,      /*!< Duplex mode */
+        .speed = 0,            /*!< Speed mode */
+        .phy_address = 1,      /*!< PHY address */
+        .phy_id = 0x7c0f0,     /*!< PHY OUI, masked */
+        .phy_state = PHY_STATE_DOWN,
+    };
+
+    /* set MAC hardware address length */
+    netif->hwaddr_len = ETH_HWADDR_LEN;
+
+    /* set MAC hardware address */
+    netif->hwaddr[0] = emac_cfg.mac_addr[0];
+    netif->hwaddr[1] = emac_cfg.mac_addr[1];
+    netif->hwaddr[2] = emac_cfg.mac_addr[2];
+    netif->hwaddr[3] = emac_cfg.mac_addr[3];
+    netif->hwaddr[4] = emac_cfg.mac_addr[4];
+    netif->hwaddr[5] = emac_cfg.mac_addr[5];
+
+    /* maximum transfer unit */
+    netif->mtu = 1500;
+
+    /* emac init,configure ethernet peripheral (GPIOs, clocks, MAC, DMA) */
+    MSG("emac_init\r\n");
+    emac_init(&emac_cfg);
+
+    ret = emac_phy_init(&phy_cfg);
+    if (PHY_STATE_UP == phy_cfg.phy_state) {
+        MSG("PHY[%x] @%d ready on %dMbps, %s duplex\n\r", (int)phy_cfg.phy_id, (int)phy_cfg.phy_address,
+            (int)phy_cfg.speed,
+            phy_cfg.full_duplex ? "full" : "half");
+    } else {
+        MSG("PHY Init fail\n\r");
+        BL_CASE_FAIL;
+        while (1)
+            ;
+    }
+    emac_init_txrx_buffer();
+    emac_start();
+    // emac_start_tx();
+
+    /* device capabilities */
+    /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
+    netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;
+
+    /* Initialize the RX POOL */
+    LWIP_MEMPOOL_INIT(RX_POOL);
+
+    /* create a binary semaphore used for informing ethernetif of frame reception */
+    //vSemaphoreCreateBinary(emac_rx_sem);
+    emac_rx_sem = xSemaphoreCreateBinary();
+
+    /* create the task that handles the ETH_MAC */
+    MSG("[OS] Starting emac rx task...\r\n");
+    xTaskCreateStatic(ethernetif_input, (char *)"emac_rx_task", sizeof(emac_rx_stack) / 4, netif, 16, emac_rx_stack, &emac_rx_handle);
+#if LWIP_DHCP
+    MSG("[OS] Starting emac dhcp task...\r\n");
+    xTaskCreateStatic(dhcp_thread, (char *)"emac_dhcp_task", sizeof(emac_dhcp_stack) / 4, netif, 16, emac_dhcp_stack, &emac_dhcp_handle);
+#endif
+
+    if (ret == 0) {
+        MSG("[OS] %s Netif is up\r\n", netif->name);
+        netif_set_up(netif);
+        netif_set_link_up(netif);
+    }
+}
+
+void emac_tx_error_callback_app()
+{
+    MSG("EMAC tx error callback\r\n");
+}
+
+void emac_rx_error_callback_app()
+{
+    MSG("EMAC rx error callback\r\n");
+    // MSG("EMAC tx bd num 0x%x\r\n", BL_RD_WORD(0x4000D020));
+    // MSG("EMAC rx bd description0 0x%x\r\n", BL_RD_WORD(0x4000D400 + ((5 + 5) * 8)));
+    // MSG("EMAC rx bd description1 0x%x\r\n", BL_RD_WORD(0x4000D400 + ((5 + 5) * 8) + 0x4));
+}
+/**
+  * @brief This function should do the actual transmission of the packet. The packet is
+  * contained in the pbuf that is passed to the function. This pbuf
+  * might be chained.
+  *
+  * @param netif the lwip network interface structure for this ethernetif
+  * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
+  * @return ERR_OK if the packet could be sent
+  *         an err_t value if the packet couldn't be sent
+  *
+  * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
+  *       strange results. You might consider waiting for space in the DMA queue
+  *       to become available since the stack doesn't retry to send a packet
+  *       dropped because of memory failure (except for the TCP timers).
+  */
+
+static unsigned char emac_send_buf[1514];
+static err_t low_level_output(struct netif *netif, struct pbuf *p)
+{
+    err_t errval = ERR_OK;
+    struct pbuf *q;
+
+    if (!emac_bd_fragment_support()){
+
+        uint32_t byteslefttocopy = 0;
+        // uint32_t payloadoffset = 0;
+        // uint32_t bufferoffset = 0;
+        uint32_t framelength = 0;
+        uint32_t flags = (EMAC_NORMAL_PACKET);
+
+        for (q = p; q != NULL; q = q->next) {
+            // MSG("p->tot_len:%d,q->len:%d, q->next:%d,f:%d\r\n", q->tot_len, q->len, q->next, framelength);
+
+            byteslefttocopy = q->len;
+            // payloadoffset = 0;
+
+            // check is copy data is larger than emac tx buf
+            while ((byteslefttocopy + framelength) > ETH_TX_BUFFER_SIZE) {
+                // copy data to tx buf
+                MSG("tx buf is too larger!\r\n");
+                flags = EMAC_FRAGMENT_PACKET;
+                // ARCH_MemCpy_Fast(&emac_send_buf[framelength + bufferoffset], q->payload + payloadoffset, (ETH_TX_BUFFER_SIZE - bufferoffset));
+            }
+            ARCH_MemCpy_Fast(&emac_send_buf[framelength], q->payload, byteslefttocopy);
+            // bufferoffset = bufferoffset + byteslefttocopy;
+            framelength = framelength + byteslefttocopy;
+        }
+
+        if (0 != emac_bd_tx_enqueue(flags, framelength, emac_send_buf)) {
+            MSG("emac_bd_tx_enqueue error!\r\n");
+            return ERR_IF;
+        }
+
+    }else{
+        for (q = p; q != NULL; q = q->next) {
+            //MSG("p->tot_len:%d,q->len:%d, q->next:%d\r\n", q->tot_len, q->len, q->next);
+            if (q->len == q->tot_len) {
+                if (0 != emac_bd_tx_enqueue(EMAC_NORMAL_PACKET, q->len, q->payload)) {
+                    MSG("emac_bd_tx_enqueue error!\r\n");
+                    return ERR_IF;
+                }
+            } else if (q->len < q->tot_len) {
+                if (0 != emac_bd_tx_enqueue(EMAC_FRAGMENT_PACKET, q->len, q->payload)) {
+                    MSG("emac_bd_tx_enqueue error!\r\n");
+                    return ERR_IF;
+                }
+            } else {
+                MSG("low_level_output error! Wrong packet!\r\n");
+            }
+        }
+    }
+
+    return errval;
+}
+
+/**
+  * @brief Should allocate a pbuf and transfer the bytes of the incoming
+  * packet from the interface into the pbuf.
+  *
+  * @param netif the lwip network interface structure for this ethernetif
+  * @return a pbuf filled with the received packet (including MAC header)
+  *         NULL on memory error
+  */
+static struct pbuf *low_level_input(struct netif *netif)
+{
+    uint32_t rx_len = 0;
+    struct pbuf *p = NULL, *q;
+
+    emac_bd_rx_dequeue(-1, &rx_len, emac_rx_buffer);
+
+    if (rx_len <= 0) {
+        //MSG("Recv Null Data\r\n");
+        return NULL;
+    }
+
+    //MSG("Recv full Data\r\n");
+
+    p = pbuf_alloc(PBUF_RAW, rx_len, PBUF_POOL);
+
+    if (p != NULL) {
+        for (q = p; q != NULL; q = q->next) {
+            memcpy(q->payload, emac_rx_buffer + rx_len - q->tot_len, q->len);
+        }
+    }
+
+    return p;
+}
+
+void emac_rx_done_callback_app(void)
+{
+    BaseType_t xHigherPriorityTaskWoken;
+
+    /* Is it time for vATask() to run? */
+    xHigherPriorityTaskWoken = pdFALSE;
+    //MSG("emac_rx_done_callback_app\r\n");
+    //low_level_input(NULL);
+    xSemaphoreGiveFromISR(emac_rx_sem, &xHigherPriorityTaskWoken);
+    /* If xHigherPriorityTaskWoken was set to true you
+    we should yield.  The actual macro used here is
+    port specific. */
+    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
+}
+/**
+  * @brief This function is the ethernetif_input task, it is processed when a packet
+  * is ready to be read from the interface. It uses the function low_level_input()
+  * that should handle the actual reception of bytes from the network
+  * interface. Then the type of the received packet is determined and
+  * the appropriate input function is called.
+  *
+  * @param netif the lwip network interface structure for this ethernetif
+  */
+void ethernetif_input(void *argument)
+{
+    struct pbuf *p = NULL;
+    struct netif *netif = (struct netif *)argument;
+
+    for (;;) {
+        if (xSemaphoreTake(emac_rx_sem, portMAX_DELAY) == pdTRUE) {
+            do {
+                //MSG("ethernetif_input\r\n");
+                p = low_level_input(netif);
+
+                if (p != NULL) {
+                    if (netif->input(p, netif) != ERR_OK) {
+                        pbuf_free(p);
+                    }
+                }
+            } while (p != NULL);
+        }
+    }
+}
+
+/**
+  * @brief Should be called at the beginning of the program to set up the
+  * network interface. It calls the function low_level_init() to do the
+  * actual setup of the hardware.
+  *
+  * This function should be passed as a parameter to netif_add().
+  *
+  * @param netif the lwip network interface structure for this ethernetif
+  * @return ERR_OK if the loopif is initialized
+  *         ERR_MEM if private data couldn't be allocated
+  *         any other err_t on error
+  */
+err_t ethernetif_init(struct netif *netif)
+{
+    LWIP_ASSERT("netif != NULL", (netif != NULL));
+
+#if LWIP_NETIF_HOSTNAME
+    /* Initialize interface hostname */
+    netif->hostname = "lwip";
+#endif /* LWIP_NETIF_HOSTNAME */
+
+    netif->name[0] = IFNAME0;
+    netif->name[1] = IFNAME1;
+    /* We directly use etharp_output() here to save a function call.
+     * You can instead declare your own function an call etharp_output()
+     * from it if you have to do some checks before sending (e.g. if link
+     * is available...) */
+    netif->output = etharp_output;
+    netif->linkoutput = low_level_output;
+
+    /* initialize the hardware */
+    low_level_init(netif);
+
+    return ERR_OK;
+}
+
+/**
+  * @brief  Custom Rx pbuf free callback
+  * @param  pbuf: pbuf to be freed
+  * @retval None
+  */
+void pbuf_free_custom(struct pbuf *p)
+{
+    struct pbuf_custom *custom_pbuf = (struct pbuf_custom *)p;
+    LWIP_MEMPOOL_FREE(RX_POOL, custom_pbuf);
+}
+
+static void ethernet_set_static_ip(struct netif *netif)
+{
+    ip_addr_t ipaddr;
+    ip_addr_t netmask;
+    ip_addr_t gw;
+
+    IP4_ADDR(&ipaddr, IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3);
+    IP4_ADDR(&netmask, NETMASK_ADDR0, NETMASK_ADDR1, NETMASK_ADDR2, NETMASK_ADDR3);
+    IP4_ADDR(&gw, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);
+    netif_set_addr(netif, ip_2_ip4(&ipaddr), ip_2_ip4(&netmask), ip_2_ip4(&gw));
+}
+
+/**
+  * @brief  Notify the User about the network interface config status
+  * @param  netif: the network interface
+  * @retval None
+  */
+void ethernet_link_status_updated(struct netif *netif)
+{
+    if (netif_is_link_up(netif)) {
+#if LWIP_DHCP
+        /* Update DHCP state machine */
+        DHCP_state = DHCP_START;
+        MSG("DHCP Start\n");
+#else
+        /* IP address default setting */
+        ethernet_set_static_ip(netif);
+        uint8_t iptxt[20];
+        sprintf((char *)iptxt, "%s", ip4addr_ntoa(netif_ip4_addr(netif)));
+        MSG("Static IP address: %s\n", iptxt);
+#endif
+    } else {
+#if LWIP_DHCP
+        /* Update DHCP state machine */
+        DHCP_state = DHCP_LINK_DOWN;
+#else
+        MSG("The network cable is not connected \n");
+#endif /* LWIP_DHCP */
+    }
+}
+
+/**
+  * @brief
+  * @retval None
+  */
+void ethernet_link_check_state(struct netif *netif)
+{
+    emac_phy_status_t phy_state;
+
+    uint32_t linkchanged = 0;
+    // uint32_t speed = 0, duplex = 0;
+
+    phy_state = ethernet_phy_status_get();
+
+    if (netif_is_link_up(netif) && (phy_state <= EMAC_PHY_STAT_LINK_DOWN)) {
+        MSG("Link Down\n");
+        emac_stop();
+        netif_set_down(netif);
+        netif_set_link_down(netif);
+    } else if (!netif_is_link_up(netif) && (phy_state <= EMAC_PHY_STAT_LINK_DOWN)) {
+        MSG("Reinit\n");
+        emac_phy_init(NULL);
+    } else if (!netif_is_link_up(netif) && (phy_state > EMAC_PHY_STAT_LINK_UP)) {
+        // switch (phy_state) {
+        //     case EMAC_PHY_STAT_100MBITS_FULLDUPLEX:
+        //         duplex = 1;
+        //         speed = 100;
+        //         linkchanged = 1;
+        //         break;
+
+        //     case EMAC_PHY_STAT_100MBITS_HALFDUPLEX:
+        //         duplex = 0;
+        //         speed = 100;
+        //         linkchanged = 1;
+        //         break;
+
+        //     case EMAC_PHY_STAT_10MBITS_FULLDUPLEX:
+        //         duplex = 1;
+        //         speed = 10;
+        //         linkchanged = 1;
+        //         break;
+
+        //     case EMAC_PHY_STAT_10MBITS_HALFDUPLEX:
+        //         duplex = 0;
+        //         speed = 10;
+        //         linkchanged = 1;
+        //         break;
+
+        //     default:
+        //         break;
+        // }
+
+        if (linkchanged) {
+            /* Get MAC Config MAC */
+            //HAL_ETH_GetMACConfig(&EthHandle, &MACConf);
+            //MACConf.DuplexMode = duplex;
+            //MACConf.Speed = speed;
+            //HAL_ETH_SetMACConfig(&EthHandle, &MACConf);
+            //HAL_ETH_Start(&EthHandle);
+            netif_set_up(netif);
+            netif_set_link_up(netif);
+        }
+    }
+}
+
+#if LWIP_DHCP
+/**
+  * @brief  DHCP Process
+  * @param  argument: network interface
+  * @retval None
+  */
+void dhcp_thread(void const *argument)
+{
+    struct netif *netif = (struct netif *)argument;
+    ip_addr_t ipaddr;
+    ip_addr_t netmask;
+    ip_addr_t gw;
+    struct dhcp *dhcp;
+    uint8_t iptxt[20];
+
+    for (;;) {
+        switch (DHCP_state) {
+            case DHCP_START: {
+                ip_addr_set_zero_ip4(&netif->ip_addr);
+                ip_addr_set_zero_ip4(&netif->netmask);
+                ip_addr_set_zero_ip4(&netif->gw);
+                DHCP_state = DHCP_WAIT_ADDRESS;
+                MSG("  State: Looking for DHCP server ...\n");
+                dhcp_start(netif);
+            } break;
+            case DHCP_WAIT_ADDRESS: {
+                if (dhcp_supplied_address(netif)) {
+                    DHCP_state = DHCP_ADDRESS_ASSIGNED;
+                    sprintf((char *)iptxt, "%s", ip4addr_ntoa(netif_ip4_addr(netif)));
+                    MSG("IP address assigned by a DHCP server: %s\n", iptxt);
+                } else {
+                    dhcp = (struct dhcp *)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP);
+
+                    /* DHCP timeout */
+                    if (dhcp->tries > MAX_DHCP_TRIES) {
+                        DHCP_state = DHCP_TIMEOUT;
+
+                        /* Static address used */
+                        ethernet_set_static_ip(netif);
+                        sprintf((char *)iptxt, "%s", ip4addr_ntoa(netif_ip4_addr(netif)));
+                        MSG("DHCP Timeout !! \n");
+                        MSG("Static IP address: %s\n", iptxt);
+                    }
+                }
+            } break;
+            case DHCP_LINK_DOWN: {
+                DHCP_state = DHCP_OFF;
+                MSG("The network cable is not connected \n");
+            } break;
+            default:
+                break;
+        }
+        vTaskDelay(100);
+    }
+}
+#endif /* LWIP_DHCP */

+ 49 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/ethernetif.h

@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2020 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __ETHERNETIF_H__
+#define __ETHERNETIF_H__
+
+#include "lwip/err.h"
+#include "lwip/netif.h"
+#include "ethernet_phy.h"
+
+#define DHCP_OFF              (uint8_t)0
+#define DHCP_START            (uint8_t)1
+#define DHCP_WAIT_ADDRESS     (uint8_t)2
+#define DHCP_ADDRESS_ASSIGNED (uint8_t)3
+#define DHCP_TIMEOUT          (uint8_t)4
+#define DHCP_LINK_DOWN        (uint8_t)5
+
+/* Exported types ------------------------------------------------------------*/
+err_t ethernetif_init(struct netif *netif);
+void ethernet_link_check_state(struct netif *netif);
+void ethernet_link_status_updated(struct netif *netif);
+
+#endif

+ 1273 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/hal_board.c

@@ -0,0 +1,1273 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdint.h>
+#include <stdio.h>
+#include <bl_efuse.h>
+#include <bl_wifi.h>
+#include <hal_boot2.h>
+#include <hal_sys.h>
+
+#include <libfdt.h>
+
+#include <blog.h>
+BLOG_DECLARE(dts);
+#include <utils_log.h>
+
+#define USER_UNUSED(a) ((void)(a))
+
+#define BL_FDT32_TO_U8(addr, byte_offset)   ((uint8_t)fdt32_to_cpu(*(uint32_t *)((uint8_t *)addr + byte_offset)))
+#define BL_FDT32_TO_U16(addr, byte_offset)  ((uint16_t)fdt32_to_cpu(*(uint32_t *)((uint8_t *)addr + byte_offset)))
+#define BL_FDT32_TO_U32(addr, byte_offset)  ((uint32_t)fdt32_to_cpu(*(uint32_t *)((uint8_t *)addr + byte_offset)))
+
+static uint32_t factory_addr = 0;
+
+//#ifndef FEATURE_WIFI_DISABLE
+//#include <bl60x_fw_api.h>
+//#include <bl_phy_api.h>
+
+#ifdef CFG_BLE_ENABLE
+#include "ble_lib_api.h"
+#endif
+static int update_mac_config_get_mac_from_dtb(const void *fdt, int offset1, uint8_t mac_addr[6])
+{
+    int lentmp;
+    const uint8_t *addr_prop = 0;
+
+    /* set sta_mac_addr ap_mac_addr */
+    addr_prop = fdt_getprop(fdt, offset1, "sta_mac_addr", &lentmp);
+    if (6 == lentmp) {
+
+        memcpy(mac_addr, addr_prop, 6);
+        blog_info("sta_mac_addr :\r\n");
+        blog_buf(mac_addr, 6);
+
+        bl_wifi_sta_mac_addr_set(mac_addr);
+    } else {
+        blog_error("sta_mac_addr NULL.\r\n");
+        return -1;
+    }
+
+    addr_prop = fdt_getprop(fdt, offset1, "ap_mac_addr", &lentmp);
+    if (6 == lentmp) {
+
+        memcpy(mac_addr, addr_prop, 6);
+        blog_info("ap_mac_addr :\r\n");
+        blog_buf(mac_addr, 6);
+
+        bl_wifi_ap_mac_addr_set(mac_addr);
+    } else {
+        blog_error("ap_mac_addr NULL.\r\n");
+        return -1;
+    }
+    blog_info("return 0000 \r\n");
+
+    return 0;
+}
+
+static int update_mac_config_get_mac_from_efuse(uint8_t mac_addr[6])
+{
+    uint8_t result_or, result_and;
+
+    bl_efuse_read_mac(mac_addr);
+    result_or = mac_addr[0] | mac_addr[1] | mac_addr[2] | mac_addr[3] | mac_addr[4] | mac_addr[5];
+    result_and = mac_addr[0] & mac_addr[1] & mac_addr[2] & mac_addr[3] & mac_addr[4] & mac_addr[5];
+
+    if (0 == result_or || 1 == result_and) {
+        /*all zero or one found in efuse*/
+        return -1;
+    }
+    return 0;
+}
+
+static int update_mac_config_get_mac_from_factory(uint8_t mac_addr[6])
+{
+    uint8_t result_or, result_and;
+
+    if (bl_efuse_read_mac_factory(mac_addr)) {
+        return -1;
+    }
+    result_or = mac_addr[0] | mac_addr[1] | mac_addr[2] | mac_addr[3] | mac_addr[4] | mac_addr[5];
+    result_and = mac_addr[0] & mac_addr[1] & mac_addr[2] & mac_addr[3] & mac_addr[4] & mac_addr[5];
+    if (0 == result_or || 1 == result_and) {
+        /*all zero or one found in efuse*/
+        return -1;
+    }
+    return 0;
+}
+
+/*
+ * Update MAC address according to order string
+ * BFM:
+ *  'B' for EFUSE built-in MAC address
+ *  'F' for Flash built-in MAC address
+ *  'M' for manufacutre configured EFUSE built-in MAC address
+ * */
+#define MAC_ORDER_ADDR_LEN_MAX      (3)
+static void update_mac_config_with_order(const void *fdt, int offset1, const char *order)
+{
+    int i, set, len;
+    uint8_t mac_addr[6];
+    static const uint8_t mac_default[] = {0x18, 0xB9, 0x05, 0x88, 0x88, 0x88};
+
+    set = 0;
+    len = strlen(order);
+    for (i = 0; i < MAC_ORDER_ADDR_LEN_MAX && i < len; i++) {
+        switch (order[i]) {
+            case 'B':
+            {
+                if (0 == update_mac_config_get_mac_from_efuse(mac_addr)) {
+                    set = 1;
+                    blog_info("get MAC from B ready\r\n");
+                    goto break_scan;
+                } else {
+                    blog_info("get MAC from B failed\r\n");
+                }
+            }
+            break;
+            case 'F':
+            {
+                if (0 == update_mac_config_get_mac_from_dtb(fdt, offset1, mac_addr)) {
+                    set = 1;
+                    printf("get MAC from F ready\r\n");
+                    goto break_scan;
+                } else {
+                    printf("get MAC from F failed\r\n");
+                }
+            }
+            break;
+            case 'M':
+            {
+                if (0 == update_mac_config_get_mac_from_factory(mac_addr)) {
+                    set = 1;
+                    blog_info("get MAC from M ready\r\n");
+                    goto break_scan;
+                } else {
+                    blog_info("get MAC from M failed\r\n");
+                }
+            }
+            break;
+            default:
+            {
+                BL_ASSERT(0);
+            }
+        }
+    }
+break_scan:
+    if (0 == set) {
+        blog_info("Using Default MAC address\r\n");
+        memcpy(mac_addr, mac_default, 6);
+    }
+    //FIXME maybe we should set a different MAC address
+    blog_info("Set MAC addrress %02X:%02X:%02X:%02X:%02X:%02X\r\n",
+            mac_addr[0],
+            mac_addr[1],
+            mac_addr[2],
+            mac_addr[3],
+            mac_addr[4],
+            mac_addr[5]
+    );
+    bl_wifi_ap_mac_addr_set(mac_addr);
+    bl_wifi_sta_mac_addr_set(mac_addr);
+}
+
+static void update_mac_config(const void *fdt, int offset1)
+{
+    int countindex = 0, lentmp = 0;
+    const char *result = 0;
+    char mac_mode[4];
+
+    countindex = fdt_stringlist_count(fdt, offset1, "mode");
+    if (1 == countindex) {
+        result = fdt_stringlist_get(fdt, offset1, "mode", 0, &lentmp);
+        blog_info_user(dts, "MAC address mode length %d\r\n", lentmp);
+        if (lentmp <= MAC_ORDER_ADDR_LEN_MAX) {
+            memcpy(mac_mode, result, lentmp);
+            mac_mode[3] = '\0';
+            blog_info_user(dts, "MAC address mode is %s\r\n", mac_mode);
+            update_mac_config_with_order(fdt, offset1, mac_mode);
+        }
+    }
+}
+
+
+static int update_xtal_config_get_mac_from_factory(uint32_t capcode[5])
+{
+    uint8_t capcode_efuse = 0;
+
+    if (bl_efuse_read_capcode(&capcode_efuse)) {
+        return -1;
+    }
+    /*efuse only have one capcode entry, so we fill the left with hardcode*/
+    capcode[0] = capcode_efuse;
+    capcode[1] = capcode_efuse;
+    capcode[2] = 1;
+    capcode[3] = 60;
+    capcode[4] = 60;
+
+    return 0;
+}
+
+static int update_xtal_config_get_mac_from_dtb(const void *fdt, int offset1, uint32_t capcode[5])
+{
+    const uint8_t *addr_prop = 0;
+    int lentmp = 0;
+
+    addr_prop = fdt_getprop(fdt, offset1, "xtal", &lentmp);
+
+    if (5*4 == lentmp) {
+        blog_info(
+            "xtal dtb in DEC :%u %u %u %u %u\r\n",
+            BL_FDT32_TO_U8(addr_prop, 4*0),
+            BL_FDT32_TO_U8(addr_prop, 4*1),
+            BL_FDT32_TO_U8(addr_prop, 4*2),
+            BL_FDT32_TO_U8(addr_prop, 4*3),
+            BL_FDT32_TO_U8(addr_prop, 4*4)
+        );
+        capcode[0] = BL_FDT32_TO_U8(addr_prop, 4*0);
+        capcode[1] = BL_FDT32_TO_U8(addr_prop, 4*1);
+        capcode[2] = BL_FDT32_TO_U8(addr_prop, 4*2);
+        capcode[3] = BL_FDT32_TO_U8(addr_prop, 4*3);
+        capcode[4] = BL_FDT32_TO_U8(addr_prop, 4*4);
+    } else {
+        blog_error("xtal dtb NULL.");
+        return -1;
+    }
+    return 0;
+}
+
+#define XTAL_ORDER_ADDR_LEN_MAX      (2)
+static void update_xtal_config_with_order(const void *fdt, int offset1, const char *order)
+{
+    int i, set, len;
+    uint32_t capcode[5];
+
+    set = 0;
+    len = strlen(order);
+    for (i = 0; i < XTAL_ORDER_ADDR_LEN_MAX && i < len; i++) {
+        switch (order[i]) {
+            case 'F':
+            {
+                if (0 == update_xtal_config_get_mac_from_dtb(fdt, offset1, capcode)) {
+                    set = 1;
+                    blog_info("get xtal from F ready\r\n");
+                    goto break_scan;
+                } else {
+                    blog_info("get xtal from F failed\r\n");
+                }
+            }
+            break;
+            case 'M':
+            {
+                if (0 == update_xtal_config_get_mac_from_factory(capcode)) {
+                    set = 1;
+                    blog_info("get xtal from M ready\r\n");
+                    goto break_scan;
+                } else {
+                    blog_info("get xtal from M failed\r\n");
+                }
+            }
+            break;
+            default:
+            {
+                BL_ASSERT(0);
+            }
+        }
+    }
+break_scan:
+    if (0 == set) {
+        blog_info("Using Default xtal\r\n");
+        capcode[0] = 50;
+        capcode[1] = 50;
+        capcode[2] = 1;
+        capcode[3] = 60;
+        capcode[4] = 60;
+    }
+    hal_sys_capcode_update(capcode[0], capcode[1]);
+}
+
+static void update_xtal_config(const void *fdt, int offset1)
+{
+    int lentmp = 0, countindex;
+    char xtal_mode[3];
+    const char *result = 0;
+
+    countindex = fdt_stringlist_count(fdt, offset1, "xtal_mode");
+    if (1 == countindex) {
+        result = fdt_stringlist_get(fdt, offset1, "xtal_mode", 0, &lentmp);
+        blog_info("xtal_mode length %d\r\n", lentmp);
+        if (lentmp <= XTAL_ORDER_ADDR_LEN_MAX) {
+            memcpy(xtal_mode, result, lentmp);
+            xtal_mode[sizeof(xtal_mode) - 1] = '\0';
+            blog_info("xtal_mode is %s\r\n", xtal_mode);
+            update_xtal_config_with_order(fdt, offset1, xtal_mode);
+        }
+    }
+}
+#if 0
+static void update_xtal_config_rftv(uint32_t tlv_addr)
+{
+    int i, set, len;
+    uint8_t buffer[20] = {0};
+    uint32_t capcode[5] = {0};
+    char xtal_mode[3] = {0};
+    
+    if (rftlv_get(tlv_addr, RFTLV_API_TYPE_XTAL_MODE, 3, xtal_mode) > 0) {
+        xtal_mode[sizeof(xtal_mode) - 1] = '\0';
+        blog_info("xtal_mode is %s\r\n", xtal_mode);
+    }
+
+    set = 0;
+    len = strlen(xtal_mode);
+    for (i = 0; i < XTAL_ORDER_ADDR_LEN_MAX && i < len; i++) {
+        switch (xtal_mode[i]) {
+            case 'F':
+            {
+                if (rftlv_get(tlv_addr, RFTLV_API_TYPE_XTAL, sizeof(buffer), buffer) > 0) {
+                    capcode[0] = *(uint32_t *)buffer;
+                    capcode[1] = *(uint32_t *)(buffer + 4);
+                    capcode[2] = *(uint32_t *)(buffer + 8);
+                    capcode[3] = *(uint32_t *)(buffer + 12);
+                    capcode[4] = *(uint32_t *)(buffer + 16);
+                    set = 1;
+                    blog_info("get xtal from F ready %d %d %d %d %d\r\n",
+                            capcode[0],
+                            capcode[1],
+                            capcode[2],
+                            capcode[3],
+                            capcode[4]);
+                    goto break_scan;
+                } else {
+                    blog_info("get xtal from F failed\r\n");
+                }
+            }
+            break;
+            case 'M':
+            {
+                if (0 == update_xtal_config_get_mac_from_factory(capcode)) {
+                    set = 1;
+                    blog_info("get xtal from M ready %d %d %d %d %d\r\n",
+                            capcode[0],
+                            capcode[1],
+                            capcode[2],
+                            capcode[3],
+                            capcode[4]);
+                    goto break_scan;
+                } else {
+                    blog_info("get xtal from M failed\r\n");
+                }
+            }
+            break;
+            default:
+            {
+                BL_ASSERT(0);
+            }
+        }
+    }
+break_scan:
+    if (0 == set) {
+        blog_info("Using Default xtal\r\n");
+        capcode[0] = 50;
+        capcode[1] = 50;
+        capcode[2] = 1;
+        capcode[3] = 60;
+        capcode[4] = 60;
+    }
+    hal_sys_capcode_update(capcode[0], capcode[1]);
+}
+#endif
+static int update_poweroffset_config_get_mac_from_dtb(const void *fdt, int offset1, int8_t poweroffset[14])
+{
+    int lentmp = 0, i;
+    const uint8_t *addr_prop = 0;
+
+#define PWR_OFFSET_BASE (10)
+    addr_prop = fdt_getprop(fdt, offset1, "pwr_offset", &lentmp);
+    if (14*4 == lentmp) {
+        for (i = 0; i < 14; i++) {
+            poweroffset[i] = BL_FDT32_TO_U32(addr_prop, 4*i);
+        }
+        blog_info("pwr_offset from dtb:\r\n");
+        blog_buf(poweroffset, 14);
+        for (i = 0; i < 14; i++) {
+            poweroffset[i] -= PWR_OFFSET_BASE;
+            poweroffset[i] = poweroffset[i] * 4;
+        }
+        blog_info("pwr_offset from dtb (rebase on %d):\r\n", PWR_OFFSET_BASE);
+        //TODO FIXME log buffer
+        //blog_buf_int8(poweroffset, 14);
+    }  else {
+        blog_error("pwr_offset NULL. lentmp = %d\r\n", lentmp);
+        return -1;
+    }
+    return 0;
+}
+
+static void update_poweroffset_config_with_order(const void *fdt, int offset1, const char *order)
+{
+    int i, set, len, j;
+    int8_t poweroffset[14], poweroffset_tmp[14];
+
+    memset(poweroffset, 0, sizeof(poweroffset));
+    memset(poweroffset_tmp, 0, sizeof(poweroffset_tmp));
+    set = 0;
+    len = strlen(order);
+    for (i = 0; i < XTAL_ORDER_ADDR_LEN_MAX && i < len; i++) {
+        switch (order[i]) {
+            case 'B':
+            case 'b':
+            {
+                if (0 == bl_efuse_read_pwroft(poweroffset_tmp)) {
+                    set = 1;
+                    blog_info("get pwr offset from B(b) ready\r\n");
+                    log_buf_int8(poweroffset_tmp, sizeof(poweroffset_tmp));
+                    if ('B' == order[i]) {
+                        /*non-incremental mode*/
+                        for (j = 0; j < sizeof(poweroffset); j++) {
+                            poweroffset[j] = poweroffset_tmp[j];
+                        }
+                        blog_info("Use pwr offset from B only\r\n");
+                        goto break_scan;
+                    } else {
+                        /*incremental mode*/
+                        blog_info("Use pwr offset from b in incremental mode\r\n");
+                        for (j = 0; j < sizeof(poweroffset); j++) {
+                            poweroffset[j] += poweroffset_tmp[j];
+                        }
+                    }
+                } else {
+                    blog_info("get pwr offset from B(b) failed\r\n");
+                }
+            }
+            break;
+            case 'F':
+            case 'f':
+            {
+                if (0 == update_poweroffset_config_get_mac_from_dtb(fdt, offset1, poweroffset_tmp)) {
+                    set = 1;
+                    blog_info("get pwr offset from F(f) ready\r\n");
+                    if ('B' == order[i]) {
+                        /*non-incremental mode*/
+                        for (j = 0; j < sizeof(poweroffset); j++) {
+                            poweroffset[j] = poweroffset_tmp[j];
+                        }
+                        blog_info("Use pwr offset from F only\r\n");
+                        goto break_scan;
+                    } else {
+                        /*incremental mode*/
+                        blog_info("Use pwr offset from f in incremental mode\r\n");
+                        for (j = 0; j < sizeof(poweroffset); j++) {
+                            poweroffset[j] += poweroffset_tmp[j];
+                        }
+                    }
+                    goto break_scan;
+                } else {
+                    blog_info("get pwr offset from F(f) failed\r\n");
+                }
+            }
+            break;
+            default:
+            {
+                BL_ASSERT(0);
+            }
+        }
+    }
+break_scan:
+    if (0 == set) {
+        blog_info("Using Default pwr offset\r\n");//all zeros actually
+    }
+    log_buf_int8(poweroffset, sizeof(poweroffset));
+#ifdef CFG_BLE_ENABLE
+    extern void ble_rf_set_pwr_offset_table(int8_t *poweroffset_table);
+	ble_rf_set_pwr_offset_table(poweroffset);
+#endif
+   //zys phy_powroffset_set(poweroffset);
+}
+
+
+#define PWR_OFFSET_ORDER_ADDR_LEN_MAX      (2)
+static void update_poweroffset_config(const void *fdt, int offset1)
+{
+    int lentmp = 0, countindex;
+    char pwr_mode[3];
+    const char *result = 0;
+
+    countindex = fdt_stringlist_count(fdt, offset1, "pwr_mode");
+    if (1 == countindex) {
+        result = fdt_stringlist_get(fdt, offset1, "pwr_mode", 0, &lentmp);
+        blog_info("pwr_mode length %d\r\n", lentmp);
+        if (lentmp <= PWR_OFFSET_ORDER_ADDR_LEN_MAX) {
+            memcpy(pwr_mode, result, lentmp);
+            pwr_mode[sizeof(pwr_mode) - 1] = '\0';
+            blog_info("pwr_mode is %s\r\n", pwr_mode);
+            update_poweroffset_config_with_order(fdt, offset1, pwr_mode);
+        }
+    }
+}
+#if 0
+zys
+static void update_poweroffset_config_rftv(uint32_t tlv_addr, const char *pw_mode)
+{
+    int i, set, len, j;
+    int8_t poweroffset[14], poweroffset_tmp[14];
+
+    memset(poweroffset, 0, sizeof(poweroffset));
+    memset(poweroffset_tmp, 0, sizeof(poweroffset_tmp));
+    set = 0;
+    len = strlen(pw_mode);
+    for (i = 0; i < XTAL_ORDER_ADDR_LEN_MAX && i < len; i++) {
+        switch (pw_mode[i]) {
+            case 'B':
+            case 'b':
+            {
+                if (0 == bl_efuse_read_pwroft(poweroffset_tmp)) {
+                    set = 1;
+                    blog_info("get pwr offset from B(b) ready\r\n");
+                    log_buf_int8(poweroffset_tmp, sizeof(poweroffset_tmp));
+                    if ('B' == pw_mode[i]) {
+                        /*non-incremental mode*/
+                        for (j = 0; j < sizeof(poweroffset); j++) {
+                            poweroffset[j] = poweroffset_tmp[j];
+                        }
+                        blog_info("Use pwr offset from B only\r\n");
+                        goto break_scan;
+                    } else {
+                        /*incremental mode*/
+                        blog_info("Use pwr offset from b in incremental mode\r\n");
+                        for (j = 0; j < sizeof(poweroffset); j++) {
+                            poweroffset[j] += poweroffset_tmp[j];
+                        }
+                    }
+                } else {
+                    blog_info("get pwr offset from B(b) failed\r\n");
+                }
+            }
+            break;
+            case 'F':
+            case 'f':
+            {
+                if (rftlv_get(tlv_addr, RFTLV_TYPE_PWR_OFFSET, sizeof(poweroffset_tmp), poweroffset_tmp) > 0) {
+                    set = 1;
+                    blog_info("get pwr offset from F(f) ready\r\n");
+                    if ('F' == pw_mode[i]) {
+                        /*non-incremental mode*/
+                        for (j = 0; j < sizeof(poweroffset); j++) {
+                            poweroffset[j] = (poweroffset_tmp[j] - 10)*4;
+                        }
+                        blog_info("Use pwr offset from F only\r\n");
+                        goto break_scan;
+                    } else {
+                        /*incremental mode*/
+                        blog_info("Use pwr offset from f in incremental mode\r\n");
+                        for (j = 0; j < sizeof(poweroffset); j++) {
+                            poweroffset[j] = (poweroffset_tmp[j] - 10)*4;
+                        }
+                    }
+                    goto break_scan;
+                } else {
+                    blog_info("get pwr offset from F(f) failed\r\n");
+                }
+            }
+            break;
+            default:
+            {
+                BL_ASSERT(0);
+            }
+        }
+    }
+break_scan:
+    if (0 == set) {
+        blog_info("Using Default pwr offset\r\n");//all zeros actually
+    }
+    log_buf_int8(poweroffset, sizeof(poweroffset));
+#ifdef CFG_BLE_ENABLE
+    extern void ble_rf_set_pwr_offset_table(int8_t *poweroffset_table);
+	ble_rf_set_pwr_offset_table(poweroffset);
+#endif
+  //zys phy_powroffset_set(poweroffset);
+}
+#endif
+static int update_sta_field(const void *fdt, int wifi_offset, const char *name)
+{
+    int offset1 = 0;        /* subnode offset1 */
+    int countindex = 0, lentmp = 0;
+    const char *result = 0;
+    const uint8_t *addr_prop = 0;
+    int auto_connect_enable;
+
+    /* set ssid pwd */
+    uint8_t ap_ssid[32];
+    uint8_t ap_ssid_len = 0;
+    uint8_t ap_psk[64];
+    uint8_t ap_psk_len = 0;
+
+    offset1 = fdt_subnode_offset(fdt, wifi_offset, name);
+    if (offset1 > 0) {
+
+        countindex = fdt_stringlist_count(fdt, offset1, "ssid");
+        if (1 == countindex) {
+            result = fdt_stringlist_get(fdt, offset1, "ssid", 0, &lentmp);
+            if ((lentmp > 0) &&(lentmp<32)) {/* !NULL */
+                blog_info("[STA] ap_ssid string[%d] = %s, ap_ssid_len = %d\r\n", 0, result, lentmp);
+                memcpy(ap_ssid, result, lentmp);
+                ap_ssid[lentmp] = '\0';
+                ap_ssid_len = lentmp;
+            }
+        }
+
+        countindex = fdt_stringlist_count(fdt, offset1, "pwd");
+        if (1 == countindex) {
+            result = fdt_stringlist_get(fdt, offset1, "pwd", 0, &lentmp);
+            if ((lentmp > 0) &&(lentmp<32)) {/* !NULL */
+                blog_info("[STA] ap_psk string[%d] = %s, ap_psk_len = %d\r\n", 0, result, lentmp);
+                memcpy(ap_psk, result, lentmp);
+                ap_psk[lentmp] = '\0';
+                ap_psk_len = lentmp;
+            }
+        }
+        addr_prop = fdt_getprop(fdt, offset1, "auto_connect_enable", &lentmp);
+        if (addr_prop) {
+            blog_info("auto_connect_enable = %ld\r\n", BL_FDT32_TO_U32(addr_prop, 0));
+
+            auto_connect_enable = BL_FDT32_TO_U32(addr_prop, 0);
+        } else {
+            auto_connect_enable = 0;
+        }
+
+        bl_wifi_sta_info_set(ap_ssid, ap_ssid_len, ap_psk, ap_psk_len, auto_connect_enable);
+    }
+    return offset1;
+}
+
+static int update_ap_field(const void *fdt, int wifi_offset, const char *name)
+{
+    int offset1 = 0;        /* subnode offset1 */
+    int countindex = 0, lentmp = 0;
+    const char *result = 0;
+    const uint8_t *addr_prop = 0;
+     
+    /* set ssid pwd */
+    uint8_t ap_ssid[32];
+    uint8_t ap_ssid_len = 0;
+    uint8_t ap_psk[64];
+    uint8_t ap_psk_len = 0;
+    uint8_t ap_channel = 0;
+
+    offset1 = fdt_subnode_offset(fdt, wifi_offset, "ap");
+    if (offset1 > 0)
+    {
+        countindex = fdt_stringlist_count(fdt, offset1, "ssid");
+        if (1 == countindex) {
+            result = fdt_stringlist_get(fdt, offset1, "ssid", 0, &lentmp);
+            if ((lentmp > 0) &&(lentmp<32)) {/* !NULL */
+                blog_info("ap_ssid string[%d] = %s, ap_ssid_len = %d\r\n", 0, result, lentmp);
+                memcpy(ap_ssid, result, lentmp);
+                ap_ssid[lentmp] = '\0';
+                ap_ssid_len = lentmp;
+            }
+        }
+
+        countindex = fdt_stringlist_count(fdt, offset1, "pwd");
+        if (1 == countindex) {
+            result = fdt_stringlist_get(fdt, offset1, "pwd", 0, &lentmp);
+            if ((lentmp > 0) &&(lentmp<32)) {/* !NULL */
+                blog_info("ap_psk string[%d] = %s, ap_psk_len = %d\r\n", 0, result, lentmp);
+                memcpy(ap_psk, result, lentmp);
+                ap_psk[lentmp] = '\0';
+                ap_psk_len = lentmp;
+            }
+        }
+
+        addr_prop = fdt_getprop(fdt, offset1, "ap_channel", &lentmp);
+        if (addr_prop) {
+            blog_info("ap_channel = %ld\r\n", BL_FDT32_TO_U32(addr_prop, 0));
+
+            ap_channel = BL_FDT32_TO_U32(addr_prop, 0);
+        } else {
+            blog_error("ap_channel NULL.\r\n");
+        }
+
+        bl_wifi_ap_info_set(ap_ssid, ap_ssid_len,
+                            ap_psk, ap_psk_len,
+                            ap_channel);
+    }
+    return offset1;
+}
+
+typedef struct{
+    uint16_t Tchannels[5];
+    int16_t Tchannel_os[5];
+    int16_t Tchannel_os_low[5];
+    int16_t Troom_os;
+    uint8_t en_tcal;
+    uint8_t linear_or_follow;
+} tcal_param_struct;
+extern tcal_param_struct* tcal_param;
+enum {
+    E_RF_TCAL_UPDATE_PARAM = 0,
+};
+void rf_pri_update_tcal_param(uint8_t operation);//FIXME
+#define TCAL_PARA_CHANNELS          5
+
+static int update_rf_temp_field(const void *fdt, int wifi_offset, const char *name)
+{
+    int lentmp, i;
+    int offset1 = 0;
+    const uint8_t *addr_prop = 0;
+    uint32_t tmp[TCAL_PARA_CHANNELS];
+    tcal_param_struct tcal_param_tmp;
+
+    offset1 = fdt_subnode_offset(fdt, wifi_offset, name);
+    if (offset1 > 0) {
+        addr_prop = fdt_getprop(fdt, offset1, "Troom_os", &lentmp);
+        if (addr_prop) {
+            tcal_param_tmp.Troom_os=BL_FDT32_TO_U32(addr_prop, 0)-256;
+            blog_info_user(dts, "Troom_os = %d, lentmp = %d\r\n", (int)tcal_param_tmp.Troom_os, lentmp);
+        } else {
+            blog_info_user(dts, "Troom_os NULL.\r\n");
+            return -1;
+        }
+
+        addr_prop = fdt_getprop(fdt, offset1, "linear_or_follow", &lentmp);
+        if (addr_prop) {
+            tcal_param_tmp.linear_or_follow=BL_FDT32_TO_U32(addr_prop, 0);
+            blog_info_user(dts, "linear_or_follow = %d, lentmp = %d\r\n", (int)tcal_param_tmp.linear_or_follow, lentmp);
+        } else {
+            blog_info_user(dts, "linear_or_follow NULL.\r\n");
+            return -1;
+        }
+
+        addr_prop = fdt_getprop(fdt, offset1, "Tchannels", &lentmp);
+        if (lentmp == TCAL_PARA_CHANNELS*4) {            
+            memcpy(tmp, addr_prop, TCAL_PARA_CHANNELS*4);         
+            blog_info_user(dts, "Tchannels:");
+            for (i = 0; i < TCAL_PARA_CHANNELS; i++){
+                tcal_param_tmp.Tchannels[i]=fdt32_to_cpu(tmp[i]);
+                blog_info_user_raw(dts, "%d,", (int)tcal_param_tmp.Tchannels[i]);
+            }
+            blog_info_user_raw(dts, "\r\n");
+        } else {
+            blog_info_user(dts, "Tchannels NULL.\r\n");
+            return -1;
+        }
+
+        addr_prop = fdt_getprop(fdt, offset1, "Tchannel_os", &lentmp);
+        if (lentmp == TCAL_PARA_CHANNELS*4) {            
+            memcpy(tmp, addr_prop, TCAL_PARA_CHANNELS*4);         
+            blog_info_user(dts, "Tchannel_os:");
+            for (i = 0; i < TCAL_PARA_CHANNELS; i++){
+                tcal_param_tmp.Tchannel_os[i]=fdt32_to_cpu(tmp[i]);
+                blog_info_user_raw(dts, "%d,", (int)tcal_param_tmp.Tchannel_os[i]);
+            }
+            blog_info_user_raw(dts, "\r\b");
+        } else {
+            blog_info_user(dts, "Tchannel_os NULL.\r\n");
+            return -1;
+        }
+
+        addr_prop = fdt_getprop(fdt, offset1, "Tchannel_os_low", &lentmp);
+        if (lentmp == TCAL_PARA_CHANNELS*4) {            
+            memcpy(tmp, addr_prop, TCAL_PARA_CHANNELS*4);         
+            blog_info_user(dts, "Tchannel_os_low:");
+            for (i = 0; i < TCAL_PARA_CHANNELS; i++){
+                tcal_param_tmp.Tchannel_os_low[i]=fdt32_to_cpu(tmp[i]);
+                blog_info_user_raw(dts, "%d,", (int)tcal_param_tmp.Tchannel_os_low[i]);
+            }
+            blog_info_user_raw(dts, "\r\n");
+        } else {
+            blog_info_user(dts, "Tchannel_os_low NULL.\r\n");
+            return -1;
+        }
+        addr_prop = fdt_getprop(fdt, offset1, "en_tcal", &lentmp);
+        if (addr_prop) {
+            tcal_param_tmp.en_tcal=BL_FDT32_TO_U32(addr_prop, 0);
+            blog_info_user(dts, "en_tcal = %u, lentmp = %d\r\n", tcal_param_tmp.en_tcal, lentmp);
+        } else {
+            blog_info_user(dts, "en_tcal NULL.\r\n");
+            return -1;
+        }
+    }
+    memcpy(tcal_param, &tcal_param_tmp, sizeof(tcal_param_tmp));
+    rf_pri_update_tcal_param(E_RF_TCAL_UPDATE_PARAM);
+
+    return 0;
+}
+#if 0
+static int hal_board_load_rftv_info(uint32_t rftlv_addr)
+{
+    int i;
+    uint8_t *p_buffer;
+
+    /* set tx_pwr_tbl */
+    int8_t pwr_table[24];
+
+    int pwr_table_ble = 0;
+ 
+    if (!rftlv_valid(rftlv_addr)) {
+        return -2;
+    }
+
+    p_buffer = pvPortMalloc(80);
+    if (p_buffer == NULL) {
+        return -1;
+    }
+
+    /* set xtal */
+    update_xtal_config_rftv(rftlv_addr);
+
+    if (rftlv_get(rftlv_addr, RFTLV_API_TYPE_PWR_TABLE_11B, 80, p_buffer) > 0) {
+        for (i = 0; i < 4; i++) {
+            pwr_table[i] = *(int8_t *)(p_buffer + i);
+        }
+        blog_info("pwr_table_11b :%u %u %u %u\r\n",
+            pwr_table[0],
+            pwr_table[1],
+            pwr_table[2],
+            pwr_table[3]
+        );
+        bl_tpc_update_power_rate_11b((int8_t*)pwr_table);
+    } else {
+        blog_error("RFTLV_TYPE_PWR_TABLE_11B NULL\r\n");
+    }
+    if (rftlv_get(rftlv_addr, RFTLV_API_TYPE_PWR_TABLE_11G, 80, p_buffer) > 0) {
+        for (i = 0; i < 8; i++) {
+            pwr_table[i] = *(int8_t *)(p_buffer + i);
+        }
+        blog_info("pwr_table_11g :%u %u %u %u %u %u %u %u\r\n",
+            pwr_table[0],
+            pwr_table[1],
+            pwr_table[2],
+            pwr_table[3],
+            pwr_table[4],
+            pwr_table[5],
+            pwr_table[6],
+            pwr_table[7]
+        );
+        bl_tpc_update_power_rate_11g((int8_t*)pwr_table);
+    } else {
+        blog_error("RFTLV_TYPE_PWR_TABLE_11G NULL\r\n");
+    }
+    if (rftlv_get(rftlv_addr, RFTLV_API_TYPE_PWR_TABLE_11N, 80, p_buffer) > 0) {
+        for (i = 0; i < 8; i++) {
+            pwr_table[i] = *(int8_t *)(p_buffer + i);
+        }
+        blog_info("pwr_table_11n :%u %u %u %u %u %u %u %u\r\n",
+            pwr_table[0],
+            pwr_table[1],
+            pwr_table[2],
+            pwr_table[3],
+            pwr_table[4],
+            pwr_table[5],
+            pwr_table[6],
+            pwr_table[7]
+        );
+        bl_tpc_update_power_rate_11n((int8_t*)pwr_table);
+    } else {
+        blog_error("RFTLV_TYPE_PWR_TABLE_11N NULL\r\n");
+    }
+
+    if (rftlv_get(rftlv_addr, RFTLV_API_TYPE_PWR_MODE, 80, p_buffer) > 0) {
+        p_buffer[2] = '\0';
+        update_poweroffset_config_rftv(rftlv_addr, (const char *)p_buffer);
+    } else {
+        blog_error("RFTLV_TYPE_PWR_MODE NULL\r\n");
+    }
+
+    if (rftlv_get(rftlv_addr, RFTLV_API_TYPE_PWR_TABLE_BLE, 80, p_buffer) > 0) {
+        pwr_table_ble = *(int8_t *)p_buffer;
+        blog_info("set pwr_table_ble = %ld in dts\r\n", pwr_table_ble);
+    } else {
+        blog_error("RFTLV_TYPE_PWR_TABLE_BLE NULL\r\n");
+    }
+#ifdef CFG_BLE_ENABLE
+        ble_controller_set_tx_pwr(pwr_table_ble);
+#endif
+
+    vPortFree(p_buffer);
+    
+    return 0;
+}
+#endif
+//static int __try_load_rftlv()
+//{
+//extern uint32_t _ld_symbol_rftlv_address;
+//    return hal_board_load_rftv_info((uint32_t)&_ld_symbol_rftlv_address);
+//zys}
+
+static int hal_board_load_fdt_info(const void *dtb)
+{
+    const void *fdt = (const void *)dtb;/* const */
+
+    /* set tx_pwr_tbl */
+    uint8_t pwr_table[24];
+
+    uint32_t channel_div_table[15];
+    uint16_t channel_cnt_table[14];
+    uint16_t lo_fcal_div = 0;
+    int pwr_table_ble = 0;
+
+    int wifi_offset = 0, bt_offset = 0;    /* subnode wifi & bluetooth */
+    int offset1 = 0, offset2 = 0;        /* subnode offset1 */
+    const uint8_t *addr_prop = 0;
+
+    int lentmp = 0;
+    int i;
+
+    wifi_offset = fdt_subnode_offset(fdt, 0, "wifi");
+    if (!(wifi_offset > 0)) {
+       blog_error("wifi NULL.\r\n");
+    }
+
+    offset1 = fdt_subnode_offset(fdt, wifi_offset, "mac");
+    if (offset1 > 0) {
+        update_mac_config(fdt, offset1);
+    }
+
+    offset1 = fdt_subnode_offset(fdt, wifi_offset, "region");
+    if (offset1 > 0) {
+        /* set country_code */
+        addr_prop = fdt_getprop(fdt, offset1, "country_code", &lentmp);
+        if (4 == lentmp) {
+            blog_info("country_code : %d\r\n", BL_FDT32_TO_U8(addr_prop, 4*0));
+
+            bl_wifi_country_code_set(BL_FDT32_TO_U8(addr_prop, 4*0));
+        }  else {
+            blog_error("country_code NULL.\r\n");
+        }
+    }
+
+//zys    if (0 == __try_load_rftlv()) {
+
+        /* load rf from tlv successful */
+//        goto __exit;
+//    }
+
+    offset1 = fdt_subnode_offset(fdt, wifi_offset, "brd_rf");
+    if (offset1 > 0)
+    {
+
+        USER_UNUSED(lo_fcal_div);
+        USER_UNUSED(channel_div_table);
+        USER_UNUSED(channel_cnt_table);
+
+        /* set xtal */
+        //update_xtal_config(fdt, offset1);
+
+        /* set channel_div_table, channel_cnt_table, lo_fcal_div */
+        addr_prop = fdt_getprop(fdt, offset1, "channel_div_table", &lentmp);
+        if (15*4 == lentmp) {
+            for (i = 0; i < 15; i++) {
+                channel_div_table[i] = BL_FDT32_TO_U32(addr_prop, 4*i);
+            }
+            blog_info("channel_div_table :\r\n");
+            blog_buf(channel_div_table, 15*4);
+        }  else {
+            blog_error("channel_div_table NULL.\r\n");
+        }
+
+        addr_prop = fdt_getprop(fdt, offset1, "channel_cnt_table", &lentmp);
+        if (14*4 == lentmp) {
+            for (i = 0; i < 14; i++) {
+                channel_cnt_table[i] = BL_FDT32_TO_U16(addr_prop, 4*i);
+            }
+            blog_info("channel_cnt_table :\r\n");
+            blog_buf(channel_cnt_table, 14*4);
+        }  else {
+            blog_error("channel_cnt_table NULL.\r\n");
+        }
+
+        addr_prop = fdt_getprop(fdt, offset1, "lo_fcal_div", &lentmp);
+        if (4 == lentmp) {
+            lo_fcal_div = BL_FDT32_TO_U16(addr_prop, 4*0);
+            blog_info("lo_fcal_div : %d\r\n", lo_fcal_div);
+        }  else {
+            blog_error("lo_fcal_div NULL.\r\n");
+        }
+
+        //TODO FIXME POWER
+        //bl60x_fw_rf_table_set(channel_div_table, channel_cnt_table, lo_fcal_div);
+
+        USER_UNUSED(pwr_table);
+        addr_prop = fdt_getprop(fdt, offset1, "pwr_table_11b", &lentmp);
+        if (4*4 == lentmp) {
+            for (i = 0; i < 4; i++) {
+                pwr_table[i] = BL_FDT32_TO_U32(addr_prop, 4*i);
+            }
+            blog_info("pwr_table_11b :%u %u %u %u\r\n",
+                pwr_table[0],
+                pwr_table[1],
+                pwr_table[2],
+                pwr_table[3]
+            );
+           //bl_tpc_update_power_rate_11b((int8_t*)pwr_table);
+        }  else {
+            blog_error("pwr_table_11b NULL. lentmp = %d\r\n", lentmp);
+        }
+
+        addr_prop = fdt_getprop(fdt, offset1, "pwr_table_11g", &lentmp);
+        if (8*4 == lentmp) {
+            for (i = 0; i < 8; i++) {
+                pwr_table[i] = BL_FDT32_TO_U32(addr_prop, 4*i);
+            }
+            blog_info("pwr_table_11g :%u %u %u %u %u %u %u %u\r\n",
+                pwr_table[0],
+                pwr_table[1],
+                pwr_table[2],
+                pwr_table[3],
+                pwr_table[4],
+                pwr_table[5],
+                pwr_table[6],
+                pwr_table[7]
+            );
+            //bl_tpc_update_power_rate_11g((int8_t*)pwr_table);
+        } else {
+            blog_error("pwr_table_11g NULL. lentmp = %d\r\n", lentmp);
+        }
+
+        addr_prop = fdt_getprop(fdt, offset1, "pwr_table_11n", &lentmp);
+        if (8*4 == lentmp) {
+            for (i = 0; i < 8; i++) {
+                pwr_table[i] = BL_FDT32_TO_U32(addr_prop, 4*i);
+            }
+            blog_info("pwr_table_11n :%u %u %u %u %u %u %u %u\r\n",
+                pwr_table[0],
+                pwr_table[1],
+                pwr_table[2],
+                pwr_table[3],
+                pwr_table[4],
+                pwr_table[5],
+                pwr_table[6],
+                pwr_table[7]
+            );
+            //bl_tpc_update_power_rate_11n((int8_t*)pwr_table);
+        }  else {
+            blog_error("pwr_table_11n NULL. lentmp = %d\r\n", lentmp);
+        }
+        //update_poweroffset_config(fdt, offset1);
+    }
+
+    bt_offset = fdt_subnode_offset(fdt, 0, "bluetooth");
+    if (!(bt_offset > 0)) {
+       blog_error("bt NULL.\r\n");
+    }
+
+    offset2 = fdt_subnode_offset(fdt, bt_offset, "brd_rf");
+    if (offset2 > 0) {
+        addr_prop = fdt_getprop(fdt, offset2, "pwr_table_ble", &lentmp);
+        if (addr_prop) {
+            pwr_table_ble = (int8_t)BL_FDT32_TO_U32(addr_prop, 0);
+        } else {
+            pwr_table_ble = 0;
+        }
+        blog_info("set pwr_table_ble = %ld in dts\r\n", pwr_table_ble);
+#ifdef CFG_BLE_ENABLE
+        //ble_controller_set_tx_pwr(pwr_table_ble);
+#endif
+    }
+
+//__exit:
+    //offset1 = update_ap_field(fdt, wifi_offset, "ap");
+    //offset1 = update_sta_field(fdt, wifi_offset, "sta");
+//    offset1 = update_rf_temp_field(fdt, wifi_offset, "rf_temp");
+
+    return 0;
+}
+//#endif
+
+#ifdef CONFIG_USER_DTS_INAPP
+/*
+ {
+    model = "bl bl602 iot board";
+    wifi {
+        #address-cells = <1>;
+        #size-cells = <1>;
+        region {
+            country_code = <86>;
+        };
+        mac {
+            mode = "MBF";
+            sta_mac_addr = [C8 43 57 82 73 40];
+            ap_mac_addr = [C8 43 57 82 73 02];
+        };
+        ap {
+            ssid = "bl_test_005";
+            pwd = "12345678";
+            ap_channel = <11>;
+            auto_chan_detect = "disable";
+        };
+        brd_rf {
+            xtal_mode = "MF";
+            xtal = <36 36 0 60 60>;
+            pwr_mode = "bf";
+            pwr_table = <0x4 0x3 0x3 0xBA 0x4 0x3 0x4 0xB0 0x4 0x3 0x5 0xA7 0x3 0x3 0x0 0x9F 0x3 0x3 0x1 0x95 0x3 0x3 0x2 0x8C 0x3 0x3 0x3 0x81 0x3 0x3 0x4 0x77 0x3 0x3 0x5 0x6E 0x2 0x3 0x0 0x65 0x2 0x3 0x1 0x5B 0x2 0x3 0x2 0x52 0x2 0x3 0x3 0x48 0x2 0x3 0x4 0x3E 0x2 0x3 0x5 0x34 0x1 0x3 0x3 0xA>;
+            pwr_offset = <10 10 10 10 10 10 10 10 10 10 10 10 10 10>;
+            channel_div_table = <0x1EEC4EC4 0x1EFCB7CB 0x1F0D20D2 0x1F1D89D8 0x1F2DF2DF 0x1F3E5BE5 0x1F4EC4EC 0x1F5F2DF2 0x1F6F96F9 0x1F800000 0x1F906906 0x1FA0D20D 0x1FB13B13 0x1FD89D89 0x201F81F8>;
+            channel_cnt_table = <0xA78A 0xA7E3 0xA83C 0xA895 0xA8ED 0xA946 0xA99F 0xA9F8 0xAA51 0xAAAA 0xAB03 0xAB5C 0xABB5 0xAC8A>;
+            lo_fcal_div = <0x56B>;
+        };
+    };
+};
+*/
+const uint8_t factory_dtb[] = {//1126
+  0xd0, 0x0d, 0xfe, 0xed, 0x00, 0x00, 0x04, 0x66, 0x00, 0x00, 0x00, 0x38,
+  0x00, 0x00, 0x03, 0x98, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x11,
+  0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xce,
+  0x00, 0x00, 0x03, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x13,
+  0x00, 0x00, 0x00, 0x00, 0x62, 0x6c, 0x20, 0x62, 0x6c, 0x36, 0x30, 0x32,
+  0x20, 0x69, 0x6f, 0x74, 0x20, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x01, 0x77, 0x69, 0x66, 0x69, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x06,
+  0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04,
+  0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+  0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+  0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x56,
+  0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x6d, 0x61, 0x63, 0x00,
+  0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x2e,
+  0x4d, 0x42, 0x46, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06,
+  0x00, 0x00, 0x00, 0x33, 0xc8, 0x43, 0x57, 0x82, 0x73, 0x40, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x40,
+  0xc8, 0x43, 0x57, 0x82, 0x73, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+  0x00, 0x00, 0x00, 0x01, 0x61, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+  0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x4c, 0x62, 0x6c, 0x5f, 0x74,
+  0x65, 0x73, 0x74, 0x5f, 0x30, 0x30, 0x35, 0x00, 0x00, 0x00, 0x00, 0x03,
+  0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x51, 0x31, 0x32, 0x33, 0x34,
+  0x35, 0x36, 0x37, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+  0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x0b,
+  0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x60,
+  0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x00, 0x00, 0x00, 0x02,
+  0x00, 0x00, 0x00, 0x01, 0x62, 0x72, 0x64, 0x5f, 0x72, 0x66, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x71,
+  0x4d, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x14,
+  0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x24,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x3c,
+  0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x80,
+  0x62, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x01, 0x00,
+  0x00, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03,
+  0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xba, 0x00, 0x00, 0x00, 0x04,
+  0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xb0,
+  0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05,
+  0x00, 0x00, 0x00, 0xa7, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x03,
+  0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x95,
+  0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02,
+  0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03,
+  0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, 0x03,
+  0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x77,
+  0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05,
+  0x00, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x02,
+  0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x5b,
+  0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02,
+  0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03,
+  0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x02,
+  0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x3e,
+  0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05,
+  0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03,
+  0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x03,
+  0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x93, 0x00, 0x00, 0x00, 0x0a,
+  0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a,
+  0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a,
+  0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a,
+  0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a,
+  0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x3c,
+  0x00, 0x00, 0x00, 0x9e, 0x1e, 0xec, 0x4e, 0xc4, 0x1e, 0xfc, 0xb7, 0xcb,
+  0x1f, 0x0d, 0x20, 0xd2, 0x1f, 0x1d, 0x89, 0xd8, 0x1f, 0x2d, 0xf2, 0xdf,
+  0x1f, 0x3e, 0x5b, 0xe5, 0x1f, 0x4e, 0xc4, 0xec, 0x1f, 0x5f, 0x2d, 0xf2,
+  0x1f, 0x6f, 0x96, 0xf9, 0x1f, 0x80, 0x00, 0x00, 0x1f, 0x90, 0x69, 0x06,
+  0x1f, 0xa0, 0xd2, 0x0d, 0x1f, 0xb1, 0x3b, 0x13, 0x1f, 0xd8, 0x9d, 0x89,
+  0x20, 0x1f, 0x81, 0xf8, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x38,
+  0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0xa7, 0x8a, 0x00, 0x00, 0xa7, 0xe3,
+  0x00, 0x00, 0xa8, 0x3c, 0x00, 0x00, 0xa8, 0x95, 0x00, 0x00, 0xa8, 0xed,
+  0x00, 0x00, 0xa9, 0x46, 0x00, 0x00, 0xa9, 0x9f, 0x00, 0x00, 0xa9, 0xf8,
+  0x00, 0x00, 0xaa, 0x51, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0xab, 0x03,
+  0x00, 0x00, 0xab, 0x5c, 0x00, 0x00, 0xab, 0xb5, 0x00, 0x00, 0xac, 0x8a,
+  0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xc2,
+  0x00, 0x00, 0x05, 0x6b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02,
+  0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09, 0x6d, 0x6f, 0x64, 0x65,
+  0x6c, 0x00, 0x23, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x2d, 0x63,
+  0x65, 0x6c, 0x6c, 0x73, 0x00, 0x23, 0x73, 0x69, 0x7a, 0x65, 0x2d, 0x63,
+  0x65, 0x6c, 0x6c, 0x73, 0x00, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79,
+  0x5f, 0x63, 0x6f, 0x64, 0x65, 0x00, 0x6d, 0x6f, 0x64, 0x65, 0x00, 0x73,
+  0x74, 0x61, 0x5f, 0x6d, 0x61, 0x63, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x00,
+  0x61, 0x70, 0x5f, 0x6d, 0x61, 0x63, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x00,
+  0x73, 0x73, 0x69, 0x64, 0x00, 0x70, 0x77, 0x64, 0x00, 0x61, 0x70, 0x5f,
+  0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x00, 0x61, 0x75, 0x74, 0x6f,
+  0x5f, 0x63, 0x68, 0x61, 0x6e, 0x5f, 0x64, 0x65, 0x74, 0x65, 0x63, 0x74,
+  0x00, 0x78, 0x74, 0x61, 0x6c, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x00, 0x78,
+  0x74, 0x61, 0x6c, 0x00, 0x70, 0x77, 0x72, 0x5f, 0x6d, 0x6f, 0x64, 0x65,
+  0x00, 0x70, 0x77, 0x72, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x70,
+  0x77, 0x72, 0x5f, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x00, 0x63, 0x68,
+  0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x5f, 0x64, 0x69, 0x76, 0x5f, 0x74, 0x61,
+  0x62, 0x6c, 0x65, 0x00, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x5f,
+  0x63, 0x6e, 0x74, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x6c, 0x6f,
+  0x5f, 0x66, 0x63, 0x61, 0x6c, 0x5f, 0x64, 0x69, 0x76, 0x00
+};
+
+#endif
+
+uint32_t hal_board_get_factory_addr(void)
+{
+    return factory_addr;
+}
+
+int hal_board_cfg(uint8_t board_code)
+{
+#ifdef CONFIG_USER_DTS_INAPP
+    factory_addr = (uint32_t)factory_dtb;
+#else
+    int ret;
+    uint32_t size;
+
+    USER_UNUSED(ret);
+    ret = hal_boot2_partition_addr_active("factory", &factory_addr, &size);
+    blog_info("[MAIN] [BOARD] [FLASH] addr from partition is %08x, ret is %d\r\n", (unsigned int)factory_addr, ret);
+    if (0 == factory_addr) {
+        blog_error("[MAIN] [BOARD] [FLASH] Dead loop. Reason: NO valid Param Parition found\r\n");
+        while (1) {
+        }
+    }
+
+    ret = hal_boot2_partition_bus_addr_active("factory", &factory_addr, &size);
+    blog_info("[MAIN] [BOARD] [XIP] addr from partition is %08x, ret is %d\r\n", (unsigned int)factory_addr, ret);
+    if (0 == factory_addr) {
+        blog_error("[MAIN] [BOARD] [XIP] Dead loop. Reason: NO valid Param Parition found\r\n");
+        while (1) {
+        }
+    }
+#endif
+
+//#ifndef FEATURE_WIFI_DISABLE
+    // printf("hal_board_load_fdt_info\n\r");
+    hal_board_load_fdt_info((const void *)factory_addr);
+//#endif
+
+    return 0;
+}

+ 34 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/hal_board.h

@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __HAL_BOARD_H__
+#define __HAL_BOARD_H__
+int hal_board_cfg(uint8_t board_code);
+uint32_t hal_board_get_factory_addr(void);
+#endif

+ 314 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/hal_boot2.c

@@ -0,0 +1,314 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include "bl_boot2.h"
+#include "bl_flash.h"
+#include "hal_boot2.h"
+#include <blog.h>
+
+#define USER_UNUSED(a) ((void)(a))
+
+#define PARTITION_BOOT2_RAM_ADDR_ACTIVE (0x62047e00)
+#define PARTITION_MAGIC                 (0x54504642)
+#define PARTITION_FW_PART_NAME          "FW"
+#define PARTITION_FW_PART_HEADER_SIZE   (0x0)
+//TODO use header file from project
+#define FW_XIP_ADDRESS                  (0x58000000)
+
+static struct {
+    uint8_t partition_active_idx;
+    uint8_t pad[3];
+    PtTable_Stuff_Config table;
+} boot2_partition_table;//XXX Dont change the name of varaible, since we refer this boot2_partition_table in linker script
+
+void hal_boot2_set_ptable_opt(HALpPtTable_Flash_Erase erase, HALpPtTable_Flash_Write write)
+{
+    PtTable_Set_Flash_Operation((pPtTable_Flash_Erase)erase, (pPtTable_Flash_Write)write);
+}
+
+int hal_boot2_update_ptable(HALPartition_Entry_Config *ptEntry_hal)
+{
+    int ret;
+    //FIXME force covert
+    PtTable_Entry_Config *ptEntry = (PtTable_Entry_Config*)ptEntry_hal;
+
+    ptEntry->activeIndex = !ptEntry->activeIndex;
+    (ptEntry->age)++;
+    ret = PtTable_Update_Entry(NULL,!boot2_partition_table.partition_active_idx, &boot2_partition_table.table, ptEntry);
+    return ret;
+}
+
+static void _dump_partition(void)
+{
+    int i;
+    PtTable_Stuff_Config *part = &boot2_partition_table.table;
+
+    USER_UNUSED(i);
+    USER_UNUSED(part);
+
+    blog_info("======= PtTable_Config @%p=======\r\n", part);
+    blog_info("magicCode 0x%08X;", (unsigned int)(part->ptTable.magicCode));
+    blog_info_raw(" version 0x%04X;", part->ptTable.version);
+    blog_info_raw(" entryCnt %u;", part->ptTable.entryCnt);
+    blog_info_raw(" age %lu;", part->ptTable.age);
+    blog_info_raw(" crc32 0x%08X\r\n", (unsigned int)part->ptTable.crc32);
+
+    blog_info("idx  type device activeIndex     name   Address[0]  Address[1]  Length[0]   Length[1]   age\r\n");
+    for (i = 0; i < part->ptTable.entryCnt; i++) {
+        blog_info("[%02d] ", i);
+        blog_info_raw(" %02u", part->ptEntries[i].type);
+        blog_info_raw("     %u", part->ptEntries[i].device);
+        blog_info_raw("         %u", part->ptEntries[i].activeIndex);
+        blog_info_raw("     %8s", part->ptEntries[i].name);
+        blog_info_raw("  0x%08x", (part->ptEntries[i].Address[0]));
+        blog_info_raw("  0x%08x", (part->ptEntries[i].Address[1]));
+        blog_info_raw("  0x%08x", (part->ptEntries[i].maxLen[0]));
+        blog_info_raw("  0x%08x", (part->ptEntries[i].maxLen[1]));
+        blog_info_raw("  %lu\r\n", (part->ptEntries[i].age));
+    }
+}
+
+uint32_t hal_boot2_get_flash_addr(void)
+{
+    extern uint8_t __boot2_flashCfg_src;
+
+    return  (uint32_t)(&__boot2_flashCfg_src + 
+            (sizeof(boot2_partition_table.table.ptEntries[0]) * boot2_partition_table.table.ptTable.entryCnt));
+}
+
+int hal_boot2_partition_bus_addr(const char *name, uint32_t *addr0, uint32_t *addr1, uint32_t *size0, uint32_t *size1, int *active)
+{
+    int i;
+    uint32_t addr0_t, addr1_t;
+
+    if (PARTITION_MAGIC != boot2_partition_table.table.ptTable.magicCode) {
+        return -EIO;
+    }
+
+    /*Get Target partition*/
+    for (i = 0; i < boot2_partition_table.table.ptTable.entryCnt; i++) {
+        if (0 == strcmp((char *)&(boot2_partition_table.table.ptEntries[i].name[0]), name)) {
+            break;
+        }
+    }
+    if (boot2_partition_table.table.ptTable.entryCnt == i) {
+        return -ENOENT;
+    }
+    addr0_t = boot2_partition_table.table.ptEntries[i].Address[0];
+    addr1_t = boot2_partition_table.table.ptEntries[i].Address[1];
+    *active = boot2_partition_table.table.ptEntries[i].activeIndex;
+    *size0 = boot2_partition_table.table.ptEntries[i].maxLen[0];
+    *size1 = boot2_partition_table.table.ptEntries[i].maxLen[1];
+
+    /*cal partition address*/
+    for (i = 0; i < boot2_partition_table.table.ptTable.entryCnt; i++) {
+        if (0 == strcmp((char *)&(boot2_partition_table.table.ptEntries[i].name[0]), PARTITION_FW_PART_NAME)) {
+            break;
+        }
+    }
+    if (boot2_partition_table.table.ptTable.entryCnt == i) {
+        return -ECANCELED;
+    }
+    /*Make sure target partition is after FW partition*/
+    if ( (addr0_t && (addr0_t < boot2_partition_table.table.ptEntries[i].Address[0])) ||
+         (addr0_t && (addr0_t < boot2_partition_table.table.ptEntries[i].Address[1])) ||
+         (addr1_t && (addr1_t < boot2_partition_table.table.ptEntries[i].Address[0])) ||
+         (addr1_t && (addr1_t < boot2_partition_table.table.ptEntries[i].Address[1]))) {
+        return -EINVAL;
+    }
+    if ((0 != boot2_partition_table.table.ptEntries[i].activeIndex) &&
+        (1 != boot2_partition_table.table.ptEntries[i].activeIndex)) {
+        return -EFAULT;
+    }
+    *addr0 = addr0_t - boot2_partition_table.table.ptEntries[i].Address[boot2_partition_table.table.ptEntries[i].activeIndex] - PARTITION_FW_PART_HEADER_SIZE + FW_XIP_ADDRESS;
+    *addr1 = addr1_t - boot2_partition_table.table.ptEntries[i].Address[boot2_partition_table.table.ptEntries[i].activeIndex] - PARTITION_FW_PART_HEADER_SIZE + FW_XIP_ADDRESS;
+
+    return 0;
+}
+
+int hal_boot2_partition_bus_addr_active(const char *name, uint32_t *addr, uint32_t *size)
+{
+    uint32_t addr0, addr1;
+    uint32_t size0, size1;
+    int active, ret;
+
+    if ((ret = hal_boot2_partition_bus_addr(name, &addr0, &addr1, &size0, &size1, &active))) {
+        return ret;
+    }
+    *addr = active ? addr1 : addr0;
+    *size = active ? size1 : size0;
+
+    return 0;
+}
+
+int hal_boot2_partition_bus_addr_inactive(const char *name, uint32_t *addr, uint32_t *size)
+{
+    uint32_t addr0, addr1;
+    uint32_t size0, size1;
+    int active, ret;
+
+    if ((ret = hal_boot2_partition_bus_addr(name, &addr0, &addr1, &size0, &size1, &active))) {
+        return ret;
+    }
+    *addr = active ? addr0 : addr1;
+    *size = active ? size0 : size1;
+
+    return 0;
+}
+
+int hal_boot2_partition_addr(const char *name, uint32_t *addr0, uint32_t *addr1, uint32_t *size0, uint32_t *size1, int *active)
+{
+    int i;
+
+    if (PARTITION_MAGIC != boot2_partition_table.table.ptTable.magicCode) {
+        return -EIO;
+    }
+
+    /*Get Target partition*/
+    for (i = 0; i < boot2_partition_table.table.ptTable.entryCnt; i++) {
+        if (0 == strcmp((char *)&(boot2_partition_table.table.ptEntries[i].name[0]), name)) {
+            break;
+        }
+    }
+    if (boot2_partition_table.table.ptTable.entryCnt == i) {
+        return -ENOENT;
+    }
+    *addr0 = boot2_partition_table.table.ptEntries[i].Address[0];
+    *addr1 = boot2_partition_table.table.ptEntries[i].Address[1];
+    *size0 = boot2_partition_table.table.ptEntries[i].maxLen[0];
+    *size1 = boot2_partition_table.table.ptEntries[i].maxLen[1];
+    *active = boot2_partition_table.table.ptEntries[i].activeIndex;
+
+    return 0;
+}
+
+int hal_boot2_partition_addr_active(const char *name, uint32_t *addr, uint32_t *size)
+{
+    uint32_t addr0, addr1;
+    uint32_t size0, size1;
+    int active, ret;
+
+    if ((ret = hal_boot2_partition_addr(name, &addr0, &addr1, &size0, &size1, &active))) {
+        return ret;
+    }
+    *addr = active ? addr1 : addr0;
+    *size = active ? size1 : size0;
+
+    return 0;
+}
+
+int hal_boot2_partition_addr_inactive(const char *name, uint32_t *addr, uint32_t *size)
+{
+    uint32_t addr0, addr1;
+    uint32_t size0, size1;
+    int active, ret;
+
+    if ((ret = hal_boot2_partition_addr(name, &addr0, &addr1, &size0, &size1, &active))) {
+        return ret;
+    }
+    *addr = active ? addr0 : addr1;
+    *size = active ? size0 : size1;
+
+    return 0;
+}
+
+uint8_t hal_boot2_get_active_partition(void)
+{
+    return boot2_partition_table.partition_active_idx;
+}
+
+int hal_boot2_get_active_entries_byname(uint8_t *name, HALPartition_Entry_Config *ptEntry_hal) 
+{
+    PtTable_Entry_Config *ptEntry = (PtTable_Entry_Config*)ptEntry_hal;
+    if (PtTable_Get_Active_Entries_By_Name(&boot2_partition_table.table, name, ptEntry)) {
+        return -1; 
+    }   
+    return 0;
+}
+
+int hal_boot2_get_active_entries(int type, HALPartition_Entry_Config *ptEntry_hal)
+{
+    PtTable_Entry_Config *ptEntry = (PtTable_Entry_Config*)ptEntry_hal;
+    if (PtTable_Get_Active_Entries(&boot2_partition_table.table, type, ptEntry)) {
+        return -1;
+    }
+    return 0;
+}
+
+int hal_boot2_dump(void)
+{
+    _dump_partition();
+    return 0;
+}
+
+int hal_boot2_init(void)
+{
+    boot2_partition_table.partition_active_idx = *(uint8_t*)PARTITION_BOOT2_RAM_ADDR_ACTIVE;
+
+    blog_info("[HAL] [BOOT2] Active Partition[%u] consumed %d Bytes\r\n",
+            boot2_partition_table.partition_active_idx,
+            sizeof(PtTable_Stuff_Config)
+    );
+    _dump_partition();
+    bl_flash_config_update();
+
+    return 0;
+}
+
+#if 0
+#define     PT_OTA_TYPE_NAME         "FW" 
+#define     PT_MEDIA_TYPE_NAME       "mfg"
+void hal_update_mfg_ptable(void)
+{
+    PtTable_Entry_Config ptEntry_fw;
+    PtTable_Entry_Config ptEntry_media;
+
+    printf("update mfg table.\r\n");
+    printf("====================\r\n");
+    if (0 == hal_boot2_get_active_entries_byname((uint8_t *)PT_OTA_TYPE_NAME, (HALPartition_Entry_Config *)(&ptEntry_fw))) {       // ota
+        if (0 == hal_boot2_get_active_entries_byname((uint8_t *)PT_MEDIA_TYPE_NAME, (HALPartition_Entry_Config *)(&ptEntry_media))) { // media
+            if (ptEntry_fw.Address[1] == ptEntry_media.Address[0]) {
+                
+                memset(ptEntry_media.name, 0, sizeof(ptEntry_media.name));
+                PtTable_Update_Entry(NULL, !boot2_partition_table.partition_active_idx, &boot2_partition_table.table, &ptEntry_media);
+                
+                printf("===== update mfg partition =====\r\n");
+            }   
+        }   
+    }   
+
+    printf("====================\r\n");
+    printf("update mfg table.\r\n");
+}
+#endif
+

+ 87 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/hal_boot2.h

@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __HAL_BOOT2_H__
+#define __HAL_BOOT2_H__
+#include <stdint.h>
+
+typedef int (*fptr_Flash_Erase_t)(uint32_t startaddr,uint32_t endaddr);
+typedef int (*fptr_Flash_Write_t)(uint32_t addr,uint8_t *data, uint32_t len);
+typedef int (*fptr_Flash_Read_t) (uint32_t addr,uint8_t *data, uint32_t len);
+
+typedef struct {
+    uint8_t type;                           /*!< Partition entry type */
+    uint8_t device;                         /*!< Partition entry device */
+    uint8_t activeIndex;                    /*!< Partition entry active index */
+    uint8_t name[9];                        /*!< Partition entry name */
+    uint32_t Address[2];                    /*!< Partition entry start address */
+    uint32_t maxLen[2];                     /*!< Partition entry max length */
+    uint32_t len;                           /*!< Partition entry length */
+    uint32_t age;                           /*!< Partition entry age */
+} HALPartition_Entry_Config;
+
+/**
+ *  @brief Partition id type definition
+ */
+typedef enum {
+    HAL_PT_ENTRY_FW_CPU0,                       /*!< Partition entry type:CPU0 firmware */
+    HAL_PT_ENTRY_FW_CPU1,                       /*!< Partition entry type:CPU1 firmware */
+    HAL_PT_ENTRY_MAX=16,                        /*!< Partition entry type:Max */
+} HALPtTable_Entry_Type;
+
+#define BOOT2_PARTITION_TYPE_FW     (0)
+
+/**
+ * @brief Error type definition
+ */
+typedef enum 
+{
+  HAL_SUCCESS  = 0, 
+  HAL_ERROR   = 1,
+} HAL_Err_Type;
+
+typedef HAL_Err_Type (*HALpPtTable_Flash_Erase)(uint32_t startaddr,uint32_t endaddr);
+typedef HAL_Err_Type (*HALpPtTable_Flash_Write)(uint32_t addr,uint8_t *data, uint32_t len);
+typedef HAL_Err_Type (*HALpPtTable_Flash_Read) (uint32_t addr,uint8_t *data, uint32_t len);
+
+void hal_boot2_set_ptable_opt(HALpPtTable_Flash_Erase erase, HALpPtTable_Flash_Write write);
+int hal_boot2_partition_bus_addr_active(const char *name, uint32_t *addr, uint32_t *size);
+int hal_boot2_partition_bus_addr_inactive(const char *name, uint32_t *addr, uint32_t *size);
+int hal_boot2_partition_bus_addr(const char *name, uint32_t *addr0, uint32_t *addr1, uint32_t *size0, uint32_t *size1, int *active);
+int hal_boot2_partition_addr_active(const char *name, uint32_t *addr, uint32_t *size);
+int hal_boot2_partition_addr_inactive(const char *name, uint32_t *addr, uint32_t *size);
+int hal_boot2_partition_addr(const char *name, uint32_t *addr0, uint32_t *addr1, uint32_t *size0, uint32_t *size1, int *active);
+uint8_t hal_boot2_get_active_partition(void);
+int hal_boot2_get_active_entries(int type, HALPartition_Entry_Config *ptEntry);
+int hal_boot2_update_ptable(HALPartition_Entry_Config *ptEntry);
+int hal_boot2_dump(void);
+int hal_boot2_init(void);
+void hal_update_mfg_ptable(void);
+
+#endif

+ 50 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/hal_common.h

@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __HAL_COMMON__H__
+#define __HAL_COMMON__H__
+
+#include "bl808_common.h"
+
+void cpu_global_irq_enable(void);
+void cpu_global_irq_disable(void);
+void hal_por_reset(void);
+void hal_system_reset(void);
+void hal_cpu_reset(void);
+void hal_get_chip_id(uint8_t chip_id[8]);
+void hal_dcache_clean_all(void);
+void hal_dcache_invalid_all(void);
+void hal_dcache_clean_invalid_all(void);
+void hal_dcache_clean_byaddr(uintptr_t addr, uint32_t len);
+void hal_dcache_invalid_byaddr(uintptr_t addr, uint32_t len);
+void hal_dcache_clean_invalid_byaddr(uintptr_t addr, uint32_t len);
+void *hal_ioalloc(size_t size);
+void hal_iofree(void *addr);
+
+#endif

+ 666 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/hal_emac.c

@@ -0,0 +1,666 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "bl808_emac.h"
+#include "bl_irq.h"
+#include "bl808_glb.h"
+#include "hal_emac.h"
+#include "bl808_l1c.h"
+#if CTX_TYPE
+#include <FreeRTOS.h>
+#include <task.h>
+#endif
+
+#define EMAC_USE_INSIDE_CLOCK   (0)
+#define TAG                     "EMAC_BD: "
+#define EMAC_USED_ID            EMAC0_ID
+
+static const uint32_t emacAddr[EMAC_ID_MAX] = { EMAC_BASE };
+
+#ifdef EMAC_DBG
+#define MSG                     printf
+#else
+#define MSG(...)                ((void)0)
+#endif
+#define EMAC_DO_FLUSH_DATA      1
+
+#if CTX_TYPE
+extern TaskHandle_t DequeueTaskHandle;
+#endif
+static EMAC_Handle_Type ethHandle;
+EMAC_Handle_Type *thiz = NULL;
+
+/**
+ * @brief
+ *
+ */
+static void emac_gpio_init(void)
+{
+    uint8_t emacPins[] = { GLB_GPIO_PIN_24, GLB_GPIO_PIN_25, GLB_GPIO_PIN_26,
+                           GLB_GPIO_PIN_27, GLB_GPIO_PIN_28, GLB_GPIO_PIN_29,
+                           GLB_GPIO_PIN_30, GLB_GPIO_PIN_31, GLB_GPIO_PIN_32,
+                           GLB_GPIO_PIN_33 };
+
+    GLB_GPIO_Func_Init(GPIO_FUN_ETHER_MAC, (GLB_GPIO_Type *)emacPins, sizeof(emacPins));
+}
+
+/**
+ * @brief
+ *
+ * @param bdt
+ * @return int
+ */
+static uint32_t emac_bd_get_cur_active(EMAC_BD_TYPE_e bdt)
+{
+    uint32_t bd = 0;
+
+    EMAC_GetBD(EMAC_USED_ID, &bd);
+
+    if (bdt == EMAC_BD_TYPE_TX) {
+        bd &= EMAC_TXBDPTR_MSK;
+        bd >>= EMAC_TXBDPTR_POS;
+    }
+
+    if (bdt == EMAC_BD_TYPE_RX) {
+        bd &= EMAC_RXBDPTR_MSK;
+        bd >>= EMAC_RXBDPTR_POS;
+    }
+
+    return bd;
+}
+
+/**
+ * @brief
+ *
+ * @param index
+ * @return int
+ */
+static int emac_bd_rx_enqueue(uint32_t index)
+{
+    BL_Err_Type err = SUCCESS;
+
+    thiz->rxIndexEMAC = index;
+
+    return err;
+}
+
+/**
+ * @brief
+ *
+ * @param index
+ * @return int
+ */
+static void emac_bd_rx_on_err(uint32_t index)
+{
+    /* handle error */
+    if (thiz->bd[index].C_S_L & EMAC_BD_FIELD_MSK(RX_OR)) {
+        MSG("EMAC RX OR Error at %s:%d\r\n", __func__, __LINE__);
+    }
+
+    if (thiz->bd[index].C_S_L & EMAC_BD_FIELD_MSK(RX_RE)) {
+        MSG("MAC RX RE Error at %s:%d\r\n", __func__, __LINE__);
+    }
+
+    if (thiz->bd[index].C_S_L & EMAC_BD_FIELD_MSK(RX_DN)) {
+        MSG("MAC RX DN Error at %s:%d\r\n", __func__, __LINE__);
+    }
+
+    if (thiz->bd[index].C_S_L & EMAC_BD_FIELD_MSK(RX_TL)) {
+        MSG("MAC RX TL Error at %s:%d\r\n", __func__, __LINE__);
+    }
+
+    if (thiz->bd[index].C_S_L & EMAC_BD_FIELD_MSK(RX_CRC)) {
+        MSG("MAC RX CRC Error at %s:%d\r\n", __func__, __LINE__);
+    }
+
+    if (thiz->bd[index].C_S_L & EMAC_BD_FIELD_MSK(RX_LC)) {
+        MSG("MAC RX LC Error at %s:%d\r\n", __func__, __LINE__);
+    }
+
+    thiz->bd[index].C_S_L &= ~0xff;
+    /* RX BD is ready for RX */
+    thiz->bd[index].C_S_L |= EMAC_BD_FIELD_MSK(RX_E);
+}
+
+/**
+ * @brief this func will be called in ISR
+ *
+ * @param index
+ * @return int
+ */
+static int emac_bd_tx_dequeue(uint32_t index)
+{
+    BL_Err_Type err = SUCCESS;
+    EMAC_BD_Desc_Type *DMADesc;
+
+    thiz->txIndexEMAC = index;
+    DMADesc = &thiz->bd[thiz->txIndexEMAC];
+    /* release this tx BD to SW (HW will do this) */
+    DMADesc->C_S_L &= EMAC_BD_FIELD_UMSK(TX_RD);
+
+    return err;
+}
+
+/**
+ * @brief
+ *
+ * @param index
+ * @return int
+ */
+static void emac_bd_tx_on_err(uint32_t index)
+{
+    /* handle error */
+    if (thiz->bd[index].C_S_L & EMAC_BD_FIELD_MSK(TX_UR)) {
+        MSG("%s:%d\r\n", __func__, __LINE__);
+    }
+
+    if (thiz->bd[index].C_S_L & EMAC_BD_FIELD_MSK(TX_RTRY)) {
+        MSG("%s:%d\r\n", __func__, __LINE__);
+    }
+
+    if (thiz->bd[index].C_S_L & EMAC_BD_FIELD_MSK(TX_RL)) {
+        MSG("%s:%d\r\n", __func__, __LINE__);
+    }
+
+    if (thiz->bd[index].C_S_L & EMAC_BD_FIELD_MSK(TX_LC)) {
+        MSG("%s:%d\r\n", __func__, __LINE__);
+    }
+
+    if (thiz->bd[index].C_S_L & EMAC_BD_FIELD_MSK(TX_DF)) {
+        MSG("%s:%d\r\n", __func__, __LINE__);
+    }
+
+    if (thiz->bd[index].C_S_L & EMAC_BD_FIELD_MSK(TX_CS)) {
+        MSG("%s:%d\r\n", __func__, __LINE__);
+    }
+
+    thiz->bd[index].C_S_L &= ~0xff;
+}
+
+/**
+ * @brief
+ *
+ */
+__WEAK void emac_tx_done_callback_app(void)
+{
+}
+
+/**
+ * @brief
+ *
+ */
+static void emac_tx_done_callback(void)
+{
+#if CTX_TYPE
+    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
+
+    xTaskNotifyFromISR(DequeueTaskHandle, 0x01, eSetBits, &xHigherPriorityTaskWoken);
+    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
+#else
+    uint32_t index = 0;
+    index = emac_bd_get_cur_active(EMAC_BD_TYPE_TX);
+
+    emac_bd_tx_dequeue(index);
+
+    emac_tx_done_callback_app();
+#endif
+}
+
+/**
+ * @brief
+ *
+ */
+__WEAK void emac_tx_error_callback_app(void)
+{
+    puts("Tx error\r\n");
+}
+
+/**
+ * @brief
+ *
+ */
+static void emac_tx_error_callback(void)
+{
+    uint32_t index = 0;
+
+    index = emac_bd_get_cur_active(EMAC_BD_TYPE_TX);
+    emac_bd_tx_on_err(index);
+    emac_tx_error_callback_app();
+}
+
+/**
+ * @brief
+ *
+ */
+__WEAK void emac_rx_done_callback_app(void)
+{
+}
+
+/**
+ * @brief
+ *
+ */
+static void emac_rx_done_callback(void)
+{
+#if CTX_TYPE
+    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
+
+    xTaskNotifyFromISR(DequeueTaskHandle, 0x02, eSetBits, &xHigherPriorityTaskWoken);
+    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
+#else
+    uint32_t index = 0;
+
+    index = emac_bd_get_cur_active(EMAC_BD_TYPE_RX);
+
+    emac_bd_rx_enqueue(index);
+
+    emac_rx_done_callback_app();
+#endif
+}
+
+/**
+ * @brief
+ *
+ */
+__WEAK void emac_rx_error_callback_app(void)
+{
+    puts("Rx error\r\n");
+}
+
+/**
+ * @brief
+ *
+ */
+static void emac_rx_error_callback(void)
+{
+    uint32_t index;
+
+    index = emac_bd_get_cur_active(EMAC_BD_TYPE_RX);
+
+    emac_bd_rx_on_err(index);
+
+    emac_rx_error_callback_app();
+}
+
+/**
+ * @brief
+ *
+ */
+__WEAK void emac_rx_busy_callback_app(void)
+{
+}
+
+/**
+ * @brief
+ *
+ */
+static void emac_rx_busy_callback(void)
+{
+    MSG("EMAC Rx busy at %s:%d\r\n", __func__, __LINE__);
+    emac_rx_busy_callback_app();
+}
+
+void emac_irq_process(void)
+{
+    EMAC_ID_Type emacId = EMAC_USED_ID;
+    uint32_t tmpVal;
+    uint32_t EMACx = emacAddr[emacId];
+    
+    tmpVal = BL_RD_REG(EMACx,EMAC_INT_MASK);
+    
+    if (SET == EMAC_GetIntStatus(emacId,EMAC_INT_TX_DONE) && !BL_IS_REG_BIT_SET(tmpVal,EMAC_TXB_M)) {
+        EMAC_ClrIntStatus(emacId,EMAC_INT_TX_DONE);
+        EMAC_IntMask(emacId, EMAC_INT_TX_DONE, MASK);
+        emac_tx_done_callback();
+    }
+
+    if (SET == EMAC_GetIntStatus(emacId,EMAC_INT_TX_ERROR) && !BL_IS_REG_BIT_SET(tmpVal,EMAC_TXE_M)) {
+        EMAC_ClrIntStatus(emacId,EMAC_INT_TX_ERROR);
+        emac_tx_error_callback();
+    }
+
+    if (SET == EMAC_GetIntStatus(emacId,EMAC_INT_RX_DONE) && !BL_IS_REG_BIT_SET(tmpVal,EMAC_RXB_M)) {
+        EMAC_ClrIntStatus(emacId,EMAC_INT_RX_DONE);
+        EMAC_IntMask(emacId, EMAC_INT_RX_DONE, MASK);
+        emac_rx_done_callback();
+    }
+
+    if (SET == EMAC_GetIntStatus(emacId,EMAC_INT_RX_ERROR) && !BL_IS_REG_BIT_SET(tmpVal,EMAC_RXE_M)) {
+        EMAC_ClrIntStatus(emacId,EMAC_INT_RX_ERROR);
+        emac_rx_error_callback();
+    }
+
+    if (SET == EMAC_GetIntStatus(emacId,EMAC_INT_RX_BUSY) && !BL_IS_REG_BIT_SET(tmpVal,EMAC_BUSY_M)) {
+        EMAC_ClrIntStatus(emacId,EMAC_INT_RX_BUSY);
+        emac_rx_busy_callback();
+    }
+
+    if (SET == EMAC_GetIntStatus(emacId,EMAC_INT_TX_CTRL) && !BL_IS_REG_BIT_SET(tmpVal,EMAC_TXC_M)) {
+        EMAC_ClrIntStatus(emacId,EMAC_INT_TX_CTRL);
+    }
+
+    if (SET == EMAC_GetIntStatus(emacId,EMAC_INT_RX_CTRL) && !BL_IS_REG_BIT_SET(tmpVal,EMAC_RXC_M)) {
+        EMAC_ClrIntStatus(emacId,EMAC_INT_RX_CTRL);
+    }
+}
+
+void EMAC_Interrupt_Init(void)
+{
+    MSG("EMAC_Interrupt_Init.\r\n");
+    bl_irq_register(EMAC_IRQn, emac_irq_process);
+    bl_irq_enable(EMAC_IRQn);
+
+    EMAC_ClrIntStatus(EMAC_USED_ID,EMAC_INT_ALL);
+    EMAC_IntMask(EMAC_USED_ID,EMAC_INT_ALL, UNMASK);
+    MSG("emac_intmask.\r\n");
+}
+/**
+ * @brief
+ *
+ * @param emac_cfg
+ * @return int
+ */
+int emac_init(emac_device_t *emac_cfg)
+{
+    EMAC_CFG_Type emacCfg = {
+        .recvSmallFrame = ENABLE,           /*!< Receive small frmae or not */
+        .recvHugeFrame = DISABLE,           /*!< Receive huge frmae(>64K bytes) or not */
+        .padEnable = ENABLE,                /*!< Enable padding for frame which is less than MINFL or not */
+        .crcEnable = ENABLE,                /*!< Enable hardware CRC or not */
+        .noPreamble = DISABLE,              /*!< Enable preamble or not */
+        .recvBroadCast = ENABLE,            /*!< Receive broadcast frame or not */
+        .interFrameGapCheck = ENABLE,       /*!< Check inter frame gap or not */
+        .miiNoPreamble = ENABLE,            /*!< Enable MII interface preamble or not */
+        .miiClkDiv = 49,                    /*!< MII interface clock divider from bus clock */
+        .maxTxRetry = 16,                   /*!< Maximum tx retry count */
+        .interFrameGapValue = 24,           /*!< Inter frame gap vaule in clock cycles(default 24)*/
+        .minFrameLen = 64,                  /*!< Minimum frame length */
+        .maxFrameLen = ETH_MAX_PACKET_SIZE, /*!< Maximum frame length */
+        .collisionValid = 16,               /*!< Collision valid value */
+        .macAddr[0] = 0x18,                 /*!< MAC Address */
+        .macAddr[1] = 0xB0,
+        .macAddr[2] = 0x09,
+        .macAddr[3] = 0x00,
+        .macAddr[4] = 0x12,
+        .macAddr[5] = 0x34,
+    };
+    BL_Err_Type err = SUCCESS;
+
+    /* init emac giio */
+    emac_gpio_init();
+
+    memcpy(emacCfg.macAddr, emac_cfg->mac_addr, 6);
+    GLB_PER_Clock_UnGate(1<<12);
+#if EMAC_USE_INSIDE_CLOCK
+    /* 50MHZ clock is from uhs pll */
+    GLB_Set_ETH_REF_O_CLK_Sel(GLB_ETH_REF_CLK_OUT_INSIDE_50M);
+#else
+    GLB_Set_ETH_REF_O_CLK_Sel(GLB_ETH_REF_CLK_OUT_OUTSIDE_50M);
+#endif
+    //GLB_AHB_Slave1_Clock_Gate(DISABLE, BL_AHB_SLAVE1_EMAC);
+    GLB_PER_Clock_UnGate(1<<12);
+    //GLB_Invert_ETH_RX_CLK(0);
+    //GLB_Invert_ETH_TX_CLK(0);
+    EMAC_Init(EMAC_USED_ID,&emacCfg);
+
+    EMAC_Interrupt_Init();
+    return err;
+}
+
+/**
+ * @brief
+ *
+ * @param eth_tx_buff
+ * @param tx_buf_count
+ * @param eth_rx_buff
+ * @param rx_buf_count
+ * @return int
+ */
+int emac_bd_init(uint8_t *eth_tx_buff, uint8_t tx_buf_count, uint8_t *eth_rx_buff, uint8_t rx_buf_count)
+{
+    BL_Err_Type err = SUCCESS;
+    thiz = &ethHandle;
+
+    /* init the BDs in emac with buffer address */
+    err = EMAC_DMADescListInit(EMAC_USED_ID,thiz, (uint8_t *)eth_tx_buff, tx_buf_count,
+                               (uint8_t *)eth_rx_buff, rx_buf_count);
+    return err;
+}
+
+/**
+ * @brief
+ *
+ * @param none
+ * @return int
+ */
+int emac_bd_fragment_support(void){
+    return 1;
+}
+
+/**
+ * @brief
+ *
+ * @param flags
+ * @param len
+ * @param data_in
+ * @return int
+ */
+//uint32_t tmpbuf[400];
+int emac_bd_tx_enqueue(uint32_t flags, uint32_t len, const uint8_t *data_in)
+{
+    BL_Err_Type err = SUCCESS;
+    EMAC_BD_Desc_Type *DMADesc;
+    uint32_t tx_flags=EMAC_TX_COMMON_FLAGS;
+    DMADesc = &thiz->bd[thiz->txIndexCPU];
+
+    if (flags&EMAC_FRAGMENT_PACKET) {
+        /* Fragment packet, clear EOF */
+        tx_flags &= EMAC_BD_FIELD_UMSK(TX_EOF);
+    }
+
+    if (DMADesc->C_S_L & EMAC_BD_FIELD_MSK(TX_RD)) {
+        /* no free BD, lost sync with DMA TX? */
+        err = NORESC;
+        //MSG(TAG"%s:%d\n", __func__, __LINE__);
+    } else {
+        __DSB();
+        // MSG("tx q flags:%d,len:%d,data:0x%x\r\n", flags, len, data_in);
+        if (flags&EMAC_NOCOPY_PACKET) {
+            DMADesc->Buffer = (uint32_t)data_in;
+        }else{
+            ARCH_MemCpy_Fast((void *)DMADesc->Buffer, data_in, len);
+        }
+
+        /* following two lines is for cache test since tmpbuf is in cache range */
+        //ARCH_MemCpy_Fast(tmpbuf, data_in, len);        
+        //DMADesc->Buffer = (uint32_t)tmpbuf;
+#ifdef EMAC_DO_FLUSH_DATA
+        if(L1C_Is_DCache_Range((uintptr_t)DMADesc->Buffer)){
+            L1C_DCache_Clean_By_Addr((uintptr_t)DMADesc->Buffer,len);
+        }
+#endif
+        DMADesc->C_S_L = tx_flags | (len << BD_TX_LEN_POS);
+
+        /* move to next TX BD */
+        if ((++thiz->txIndexCPU) > thiz->txBuffLimit) {
+            /* the last BD */
+            DMADesc->C_S_L |= EMAC_BD_FIELD_MSK(TX_WR);
+            /* wrap back */
+            thiz->txIndexCPU = 0;
+        }
+    }
+
+    return err;
+}
+
+/**
+ * @brief
+ *
+ * @param flags
+ * @param len
+ * @param data_out
+ * @return int
+ */
+int emac_bd_rx_dequeue(uint32_t flags, uint32_t *len, uint8_t *data_out)
+{
+    BL_Err_Type err = SUCCESS;
+    EMAC_BD_Desc_Type *DMADesc;
+
+    DMADesc = &thiz->bd[thiz->rxIndexCPU];
+
+    if (DMADesc->C_S_L & EMAC_BD_FIELD_MSK(RX_E)) {
+        /* current RX BD is empty */
+        err = NORESC;
+        *len = 0;
+    } else {
+        *len = (thiz->bd[thiz->rxIndexCPU].C_S_L & EMAC_BD_FIELD_MSK(RX_LEN)) >> BD_RX_LEN_POS;
+#ifdef EMAC_DO_FLUSH_DATA
+        if(L1C_Is_DCache_Range((uintptr_t)DMADesc->Buffer)){
+            L1C_DCache_Invalid_By_Addr((uintptr_t)DMADesc->Buffer, *len);
+        }
+#endif
+        if (data_out) {
+            ARCH_MemCpy_Fast(data_out, (const void *)(uintptr_t)DMADesc->Buffer, *len);
+        }
+
+        /* RX BD can be used for another receive */
+        DMADesc->C_S_L |= EMAC_BD_FIELD_MSK(RX_E);
+
+        /* move to next RX BD */
+        if ((++thiz->rxIndexCPU) > thiz->rxBuffLimit) {
+            /* the last BD */
+            DMADesc->C_S_L |= EMAC_BD_FIELD_MSK(RX_WR);
+            /* wrap back */
+            thiz->rxIndexCPU = thiz->txBuffLimit + 1;
+        }
+    }
+
+    return err;
+}
+
+/**
+ * @brief
+ *
+ * @param phyAddress
+ * @return int
+ */
+int emac_phy_set_address(uint16_t phyAddress)
+{
+    EMAC_Phy_SetAddress(EMAC_USED_ID,phyAddress);
+
+    return 0;
+}
+
+/**
+ * @brief
+ *
+ * @param fullDuplex
+ * @return int
+ */
+int emac_phy_config_full_duplex(uint8_t fullDuplex)
+{
+    EMAC_Phy_Set_Full_Duplex(EMAC_USED_ID,fullDuplex);
+
+    return 0;
+}
+
+/**
+ * @brief
+ *
+ * @param phyReg
+ * @param regValue
+ * @return int
+ */
+int emac_phy_reg_read(uint16_t phyReg, uint16_t *regValue)
+{
+    if (EMAC_Phy_Read(EMAC_USED_ID,phyReg, regValue) != SUCCESS) {
+        return -1;
+    }
+
+    return 0;
+}
+
+/**
+ * @brief
+ *
+ * @param phyReg
+ * @param regValue
+ * @return int
+ */
+int emac_phy_reg_write(uint16_t phyReg, uint16_t regValue)
+{
+    if (EMAC_Phy_Write(EMAC_USED_ID,phyReg, regValue) != SUCCESS) {
+        return -1;
+    }
+
+    return 0;
+}
+
+int emac_stop(void)
+{
+    return EMAC_Disable(EMAC_USED_ID);
+}
+
+int emac_start(void)
+{
+    EMAC_Enable(EMAC_USED_ID);
+    return 0;
+}
+
+int emac_start_tx(void)
+{
+    return EMAC_Enable_TX(EMAC_USED_ID);
+}
+
+int emac_stop_tx(void)
+{
+    return EMAC_Disable_TX(EMAC_USED_ID);
+}
+
+int emac_start_rx(void)
+{
+    return EMAC_Enable_RX(EMAC_USED_ID);
+}
+
+int emac_stop_rx(void)
+{
+    return EMAC_Disable_RX(EMAC_USED_ID);
+}
+
+int emac_intmask(EMAC_INT_Type intType, BL_Mask_Type intMask)
+{
+    return EMAC_IntMask(EMAC_USED_ID,intType, intMask);
+}
+
+int emac_get_fram_len(uint16_t *max, uint16_t *min)
+{
+  return EMAC_GetFramLen(EMAC_USED_ID, max, min);
+}
+

+ 127 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/hal_emac.h

@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __HAL_EMAC_H__
+#define __HAL_EMAC_H__
+
+#include "hal_common.h"
+#include "drv_device.h"
+// #include "bl808_config.h"
+#include "bl808_emac.h"
+
+#define CTX_TYPE 1
+
+#define MSG(a,...)              printf(a,##__VA_ARGS__)
+// #define MSG_DBG(a,...)          printf(a,##__VA_ARGS__)
+// #define MSG_WAR(a,...)          printf(a,##__VA_ARGS__)
+// #define MSG_ERR(a,...)          printf(a,##__VA_ARGS__)
+#define BL_CASE_FAIL            {MSG(" Case Fail\r\n");while(1){}}
+#define BL_CASE_SUCCESS         {MSG(" Case Success\r\n");while(1){}}
+
+typedef struct emac_device {
+    struct device parent;
+    uint8_t mac_addr[6]; /*!< mac address */
+} emac_device_t;
+
+/**
+ *  @brief EMAC PHY configuration type definition
+ */
+typedef struct
+{
+    uint8_t auto_negotiation; /*!< Speed and mode auto negotiation */
+    uint8_t full_duplex;      /*!< Duplex mode */
+#define PHY_STATE_DOWN    (0) /* PHY is not usable */
+#define PHY_STATE_READY   (1) /* PHY is OK, wait for controller */
+#define PHY_STATE_UP      (2) /* Network is ready for TX/RX */
+#define PHY_STATE_RUNNING (3) /* working */
+#define PHY_STATE_NOLINK  (4) /* no cable connected */
+#define PHY_STATE_STOPPED (5) /* PHY has been stopped */
+#define PHY_STATE_TESTING (6) /* in test mode */
+    uint8_t phy_state;        /*!< down,ready,up,running,nolink,halted */
+    uint8_t use_irq;          /*!< 0: no IRQ used */
+    uint16_t speed;           /*!< Speed mode */
+    uint16_t phy_address;     /*!< PHY address */
+    uint32_t phy_id;          /*!< PHY OUI */
+} emac_phy_cfg_t;
+
+#define EMAC_NORMAL_PACKET    (uint32_t)(0)
+#define EMAC_FRAGMENT_PACKET  (uint32_t)(0x01)
+#define EMAC_NOCOPY_PACKET    (uint32_t)(0x02)
+
+#ifndef ETH_TX_BUFFER_SIZE
+#define ETH_TX_BUFFER_SIZE (ETH_MAX_PACKET_SIZE)
+#endif
+
+#ifndef ETH_RX_BUFFER_SIZE
+#define ETH_RX_BUFFER_SIZE (ETH_MAX_PACKET_SIZE)
+#endif
+
+#define EMAC_TX_COMMON_FLAGS (EMAC_BD_FIELD_MSK(TX_RD) |  \
+                              EMAC_BD_FIELD_MSK(TX_IRQ) | \
+                              EMAC_BD_FIELD_MSK(TX_PAD) | \
+                              EMAC_BD_FIELD_MSK(TX_CRC) | \
+                              EMAC_BD_FIELD_MSK(TX_EOF))
+
+#define EMAC_RX_COMMON_FLAGS    (ETH_MAX_PACKET_SIZE << 16) | \
+    EMAC_BD_FIELD_MSK(RX_IRQ) )
+
+typedef enum _BD_TYPE_ {
+    EMAC_BD_TYPE_INVLAID,
+    EMAC_BD_TYPE_TX,
+    EMAC_BD_TYPE_RX,
+    EMAC_BD_TYPE_NONE,
+    EMAC_BD_TYPE_MAX = 0x7FFFFFFF
+} EMAC_BD_TYPE_e;
+
+int emac_init(emac_device_t *emac_cfg);
+int emac_bd_init(uint8_t *ethTxBuff, uint8_t txBufCount, uint8_t *ethRxBuff, uint8_t rxBufCount);
+int emac_bd_fragment_support(void);
+int emac_bd_tx_enqueue(uint32_t flags, uint32_t len, const uint8_t *data_in);
+int emac_bd_rx_dequeue(uint32_t flags, uint32_t *len, uint8_t *data_out);
+__WEAK void emac_rx_done_callback_app(void);
+__WEAK void emac_rx_error_callback_app(void);
+__WEAK void emac_rx_busy_callback_app(void);
+__WEAK void emac_tx_error_callback_app(void);
+__WEAK void emac_tx_done_callback_app(void);
+int emac_phy_set_address(uint16_t phyAddress);
+int emac_phy_config_full_duplex(uint8_t fullDuplex);
+int emac_phy_reg_read(uint16_t phyReg, uint16_t *regValue);
+int emac_phy_reg_write(uint16_t phyReg, uint16_t regValue);
+int emac_stop(void);
+int emac_start(void);
+int emac_start_tx(void);
+int emac_stop_tx(void);
+int emac_start_rx(void);
+int emac_stop_rx(void);
+int emac_intmask(EMAC_INT_Type intType, BL_Mask_Type intMask);
+int emac_get_fram_len(uint16_t *max, uint16_t *min);
+BL_Err_Type EMAC_GetFramLen(EMAC_ID_Type emacId, uint16_t * max, uint16_t *min);
+BL_Err_Type EMAC_GetBD(EMAC_ID_Type emacId, uint32_t *bd);
+#endif

+ 91 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/hal_sdh.c

@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <hal/soc/sd.h>
+#include "bl_sdh.h"
+#include "hal_sdh.h"
+
+static sd_card_t gSDCardInfo;
+static uint32_t sdio_bus_width = SDH_DATA_BUS_WIDTH_1BIT;
+
+int32_t hal_sd_init(sd_dev_t *sd)
+{
+    static uint8_t inited = 0;
+
+    if (inited == 0) {
+        if (SDH_Init(sdio_bus_width, &gSDCardInfo) == SD_OK) {
+            inited = 1;
+            return 0;
+        } else {
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+void hal_sd_bus_4bits_enable()
+{
+    sdio_bus_width = SDH_DATA_BUS_WIDTH_4BITS;
+}
+
+int32_t hal_sd_stat_get(sd_dev_t *sd, hal_sd_stat *stat)
+{
+    *stat = SD_STAT_TRANSFER;
+    return 0;
+}
+
+int32_t hal_sd_blks_read(sd_dev_t *sd, uint8_t *data, uint32_t blk_addr, uint32_t blks, uint32_t timeout)
+{
+    if (SD_OK == SDH_ReadMultiBlocks(data, blk_addr, gSDCardInfo.blockSize, blks)) {
+        return 0;
+    } else {
+        return -1;
+    }
+}
+
+int32_t hal_sd_blks_write(sd_dev_t *sd, uint8_t *data, uint32_t blk_addr, uint32_t blks, uint32_t timeout)
+{
+    if (SD_OK == SDH_WriteMultiBlocks(data, blk_addr, gSDCardInfo.blockSize, blks)) {
+        return 0;
+    } else {
+        return -1;
+    }
+}
+
+int32_t hal_sd_info_get(sd_dev_t *sd, hal_sd_info_t *info)
+{
+
+    info->blk_nums = gSDCardInfo.blockCount;
+    info->blk_size = gSDCardInfo.blockSize;
+
+    return 0;
+}
+

+ 33 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/hal_sdh.h

@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __HAL_SDH_H__
+#define __HAL_SDH_H__
+void hal_sd_bus_4bits_enable();
+#endif

+ 139 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/hal_sys.c

@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <string.h>
+
+#include "bl_sys.h"
+#include "hal_sys.h"
+
+void hal_reboot()
+{
+    bl_sys_reset_por();
+}
+
+void hal_sys_reset()
+{
+    //bl_sys_reset_system();
+}
+
+void hal_poweroff()
+{
+    /*TODO empty now*/
+}
+
+#if 0
+static uint32_t user_clz(uint32_t priorities)
+{
+    return __builtin_clz(priorities);
+}
+
+struct romapi_freertos_map* hal_sys_romapi_get(void)
+{
+    extern uint8_t __global_pointer_head$;
+    uint32_t *gp_data_start = (uint32_t*)(&__global_pointer_head$);
+    struct romapi_freertos_map* romapi_freertos;
+
+    puts("  Configuring Version 1.0 ROM API...\r\n");
+
+    /*clear bss/common section in GP aera*/
+    memset(&__global_pointer_head$, 0, 0x498);
+    romapi_freertos = (struct romapi_freertos_map*) (((uint8_t*)gp_data_start) + 0x45c);
+
+    /* pTrapNetCounter */
+    *(gp_data_start + 0) = (uint32_t)((uint8_t*)(gp_data_start) + 0x58);
+    /* pullNextTime */
+    *(gp_data_start + 1) = (uint32_t)((uint8_t*)(gp_data_start) + 0x60);
+    /* system tick */
+    *(gp_data_start + 2) = 32 * 1000 / 1000;//Use 32K
+
+    return romapi_freertos;
+}
+
+void hal_sys_romapi_update(struct romapi_freertos_map *romapi_freertos)
+{
+    extern void interrupt_entry(uint32_t mcause);
+    extern void exception_entry(uint32_t mcause, uint32_t mepc, uint32_t mtval);
+    extern uint8_t __freertos_irq_stack_top;
+
+    romapi_freertos->interrupt_entry_ptr = interrupt_entry;
+    romapi_freertos->rtos_sprintf = sprintf;
+    romapi_freertos->rtos_memcpy_ptr = memcpy;
+    romapi_freertos->rtos_strlen_ptr = strlen;
+    romapi_freertos->rtos_memset_ptr = memset;
+    romapi_freertos->exception_entry_ptr = exception_entry;
+    romapi_freertos->rtos_strcpy_ptr = strcpy;
+    romapi_freertos->xISRStackTop = &__freertos_irq_stack_top;
+    romapi_freertos->rtos_clz = user_clz;
+}
+#endif
+void hal_sys_capcode_update(uint8_t capin, uint8_t capout)
+{
+    //TODO FPGA no capcode
+#if 0
+    static uint8_t capin_static, capout_static;
+
+    if (255 != capin && 255 != capout) {
+        RomDriver_AON_Set_Xtal_CapCode(capin, capout);
+        capin_static = capin;
+        capout_static = capout;
+    } else {
+        RomDriver_AON_Set_Xtal_CapCode(capin_static, capout_static);
+    }
+#endif
+}
+
+uint8_t hal_sys_capcode_get(void)
+{
+    return 0;
+   // return AON_Get_Xtal_CapCode();
+}
+
+void hal_sys_mtimer_div(void)
+{
+    *(volatile uint32_t *)0x20009014 = 0x80000004;
+}
+void hal_enable_cpu0(void)
+{
+    bl_enable_cpu0();
+}
+
+void hal_boot_cpu0(uint32_t start_addr)
+{
+    bl_boot_cpu0(start_addr);
+}
+
+void hal_halt_cpu0(void)
+{
+    bl_halt_cpu0();
+}
+
+void hal_release_cpu0(void)
+{
+    bl_release_cpu0();
+}

+ 67 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/hal_sys.h

@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __HAL_SYS_H__
+#define __HAL_SYS_H__
+
+#include <stdint.h>
+
+void hal_reboot();
+void hal_sys_reset();
+void hal_poweroff();
+
+struct romapi_freertos_map
+{
+    void *vApplicationIdleHook;
+    void *interrupt_entry_ptr;
+    void *vApplicationGetIdleTaskMemory;
+    void *vApplicationStackOverflowHook;
+    void *vApplicationGetTimerTaskMemory;
+    void *rtos_sprintf;
+    void *vApplicationMallocFailedHook;
+    void *rtos_memcpy_ptr;
+    void *vAssertCalled;
+    void *rtos_strlen_ptr;
+    void *rtos_memset_ptr;
+    void *rtos_clz;
+    void *exception_entry_ptr;
+    void *rtos_strcpy_ptr;
+    void *xISRStackTop;
+};
+struct romapi_freertos_map* hal_sys_romapi_get(void);
+void hal_sys_romapi_update(struct romapi_freertos_map *romapi);
+
+void hal_sys_capcode_update(uint8_t capin, uint8_t capout);
+uint8_t hal_sys_capcode_get(void);
+void hal_sys_mtimer_div(void);
+void hal_enable_cpu0(void);
+void hal_boot_cpu0(uint32_t start_addr);
+void hal_halt_cpu0(void);
+void hal_release_cpu0(void);
+#endif

+ 284 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/hal_uart.c

@@ -0,0 +1,284 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <device/vfs_uart.h>
+#include <vfs_err.h>
+#include <vfs_register.h>
+#include <hal/soc/uart.h>
+#include <aos/kernel.h>
+
+#include "bl_uart.h"
+#include "hal_uart.h"
+
+#include <blog.h>
+
+typedef struct uart_priv_data {
+    aos_mutex_t    mutex;
+} uart_priv_data_t;
+
+static int8_t inited;
+static uart_dev_t *dev_uart0 = NULL;
+static uart_dev_t *dev_uart1 = NULL;
+static uart_dev_t *dev_uart2 = NULL;
+static uart_dev_t *dev_uart3 = NULL;
+
+static int uart_dev_malloc(uart_dev_t **pdev)
+{
+    if (*pdev) {
+        blog_error("arg err.\r\n");
+        return -1;
+    }
+
+    *pdev = pvPortMalloc(sizeof(uart_dev_t));
+    if (*pdev == 0) {
+        blog_error("mem err.\r\n");
+        return -1;
+    }
+    memset(*pdev, 0, sizeof(uart_dev_t));
+
+    (*pdev)->read_block_flag = UART_READ_CFG_NOBLOCK;
+    (*pdev)->priv = NULL;
+    (*pdev)->priv = pvPortMalloc(sizeof(uart_priv_data_t));
+    if ((*pdev)->priv == NULL) {
+        blog_error("mem err.\r\n");
+        return -1;
+    }
+    memset((*pdev)->priv, 0, sizeof(uart_priv_data_t));
+
+    return 0;
+}
+
+static void uart_dev_setdef(uart_dev_t **pdev, uint8_t id)
+{
+    if (*pdev == NULL) {
+        blog_error("mem err.\r\n");
+        return;
+    }
+
+    (*pdev)->port = id;
+    (*pdev)->read_block_flag = UART_READ_CFG_NOBLOCK;
+    
+    (*pdev)->config.baud_rate = 2000000;
+    (*pdev)->config.data_width = DATA_WIDTH_8BIT;
+    (*pdev)->config.parity = NO_PARITY;
+    (*pdev)->config.stop_bits = STOP_BITS_1;
+    (*pdev)->config.flow_control = FLOW_CONTROL_DISABLED;
+    (*pdev)->config.mode = MODE_TX_RX;
+}
+
+static int dev_uart_init(uint8_t id, const char *path, uint32_t rx_buf_size, uint32_t tx_buf_size)
+{
+    uart_dev_t **pdev = NULL;
+    int ret;
+
+    if ((id >= 4) || (path == 0)) {
+        blog_error("arg err.\r\n");
+        return -1;
+    }
+
+    switch (id) {
+        case 0:
+        {
+            pdev = &dev_uart0;
+        } break;
+        case 1:
+        {
+            pdev = &dev_uart1;
+        } break;
+        case 2:
+        {
+            pdev = &dev_uart2;
+        } break;
+        case 3:
+        {
+            pdev = &dev_uart3;
+        } break;
+        default:
+        {
+            blog_error("err.\r\n");
+            return -1;
+        } break;
+    }
+
+    if (uart_dev_malloc(pdev) != 0) {
+        return -1;
+    }
+    (*pdev)->rx_buf_size = rx_buf_size;
+    (*pdev)->tx_buf_size = tx_buf_size;
+   // (*pdev)->ring_rx_buffer = pvPortMalloc((*pdev)->rx_buf_size);
+   // (*pdev)->ring_tx_buffer = pvPortMalloc((*pdev)->tx_buf_size);
+
+   // if ((*pdev)->ring_rx_buffe == NULL || (*pdev)->ring_rx_buffe == NULL ) {
+   //     return -1;
+   // }
+
+    uart_dev_setdef(pdev, id);
+    ret = aos_register_driver(path, &uart_ops, *pdev);
+    if (ret != VFS_SUCCESS) {
+        return ret;
+    }
+
+    return 0;
+}
+
+int32_t hal_uart_send_trigger(uart_dev_t *uart)
+{
+    bl_uart_int_tx_enable(uart->port);
+    return 0;
+}
+
+int32_t hal_uart_send_trigger_off(uart_dev_t *uart)
+{
+    bl_uart_int_tx_disable(uart->port);
+    return 0;
+}
+
+int32_t hal_uart_init(uart_dev_t *uart)
+{
+    uart_priv_data_t *data;
+    uint8_t parity;
+
+    data = uart->priv;
+    if (aos_mutex_new(&(data->mutex))) {
+        /*we should assert here?*/
+        return -1;
+    }
+
+    bl_uart_getdefconfig(uart->port, &parity);
+
+    if (parity == UART_PARITY_NONE) {
+        uart->config.parity = NO_PARITY;
+    } else if (parity == UART_PARITY_ODD) {
+        uart->config.parity = ODD_PARITY;
+    } else {
+        uart->config.parity = EVEN_PARITY;
+    }
+
+    bl_uart_int_enable(uart->port);
+
+    return 0;
+}
+
+int vfs_uart_init_simple_mode(uint8_t id, uint8_t pin_tx, uint8_t pin_rx, int baudrate, const char *path)
+{
+    //bl_uart_flush(id);
+
+    bl_uart_init(id, pin_tx, pin_rx, 255, 255, baudrate);
+
+    if (dev_uart_init(id, path, 128, 128) != 0) {
+        blog_error("dev_uart_init err.\r\n");
+    }
+
+    return 0;
+}
+
+int vfs_uart_init(uint32_t fdt, uint32_t dtb_uart_offset)
+{
+    dev_uart_init(0, "/dev/ttyS0", 512, 512);
+    return 0;
+}
+
+int32_t hal_uart_recv_II(uart_dev_t *uart, void *data, uint32_t expect_size, uint32_t *recv_size, uint32_t timeout)
+{
+    int ch;
+    uint32_t counter = 0;
+
+    while (counter < expect_size && (ch = bl_uart_data_recv(uart->port)) >= 0) {
+        ((uint8_t*)data)[counter] = ch;
+        counter++;
+    }
+
+    *recv_size = counter;
+    return 0;
+}
+
+int32_t hal_uart_send(uart_dev_t *uart, const void *data, uint32_t size, uint32_t timeout)
+{
+    uint32_t i = 0;
+
+    while (i < size) {
+        bl_uart_data_send(uart->port, ((uint8_t*)data)[i]);
+        i++;
+    }
+    return 0;
+}
+
+int32_t hal_uart_send_flush(uart_dev_t *uart, uint32_t timeout)
+{
+    bl_uart_flush(uart->port);                                                                                                                                                                 
+    return 0;
+}
+
+void hal_uart_setbaud(uart_dev_t *uart, uint32_t baud)
+{
+    bl_uart_setbaud(uart->port, baud);
+}
+
+void hal_uart_setconfig(uart_dev_t *uart, uint32_t baud, hal_uart_parity_t parity)
+{
+    bl_uart_setconfig(uart->port, baud, parity);
+}
+
+int32_t hal_uart_finalize(uart_dev_t *uart)
+{
+    uart_priv_data_t *data;
+
+    data = uart->priv;
+    bl_uart_int_disable(uart->port);
+    aos_mutex_free(&(data->mutex));
+    return 0;
+}
+
+/*TODO better glue for ring buffer?*/
+int32_t hal_uart_notify_register(uart_dev_t *uart, hal_uart_int_t type, void (*cb)(void *arg))
+{
+    if (type == UART_TX_INT) {
+        bl_uart_int_tx_notify_register(uart->port, cb, uart);
+    } else if (type == UART_RX_INT) {
+        bl_uart_int_rx_notify_register(uart->port, cb, uart);
+    } else {
+        return -1;
+    }
+
+    return 0;
+}
+
+int32_t hal_uart_notify_unregister(uart_dev_t *uart, hal_uart_int_t type, void (*cb)(void *arg))
+{
+    if (type == UART_TX_INT) {
+        bl_uart_int_tx_notify_unregister(uart->port, cb, uart);
+    } else if (type == UART_RX_INT) {
+        bl_uart_int_rx_notify_unregister(uart->port, cb, uart);
+    } else {
+        return -1;
+    }
+
+    return 0;
+}
+

+ 35 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/hal_uart.h

@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __HAL_UART_H__
+#define __HAL_UART_H__
+int vfs_uart_init(uint32_t fdt, uint32_t dtb_uart_offset);
+int vfs_uart_init_simple_mode(uint8_t id, uint8_t pin_tx, uint8_t pin_rx, int baudrate, const char *path);
+int hal_uart_data_notify(int number, int dir);
+#endif

+ 1285 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/hal_usb.c

@@ -0,0 +1,1285 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "hal_usb.h"
+#include "bl808_usb.h"
+#include "bl808_glb.h"
+
+#ifndef CONFIG_USB_VDMA_ENABLE
+#define CONFIG_USB_VDMA_ENABLE
+#endif
+
+#ifndef CONFIG_USB_PINGPONG_ENABLE
+// #define CONFIG_USB_PINGPONG_ENABLE
+#endif
+
+#ifndef CONFIG_USB_VDMA_OUT_ENABLE
+// #define CONFIG_USB_VDMA_OUT_ENABLE
+#endif
+
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+
+#define USB_DC_LOG_WRN(a, ...) //bflb_platform_printf(a, ##__VA_ARGS__)
+#define USB_DC_LOG_DBG(a, ...)
+#define USB_DC_LOG_ERR(a, ...) //bflb_platform_printf(a, ##__VA_ARGS__)
+#define USB_DC_LOG(a, ...)     //bflb_platform_printf(a, ##__VA_ARGS__)
+
+static uint8_t fifo_ep_map[4] = { 0, 0, 0, 0 };
+
+static usb_dc_device_t usb_hs_device __attribute__((section(".RW_OCRAM_NOINIT")));
+static void USBD_IRQHandler(void);
+
+static uint8_t usb_ep_is_enabled(uint8_t ep)
+{
+    uint8_t ep_idx = USB_EP_GET_IDX(ep);
+
+    /* Check if ep enabled */
+    if ((USB_EP_DIR_IS_OUT(ep)) &&
+        usb_hs_device.out_ep[ep_idx].ep_ena) {
+        return 1;
+    } else if ((USB_EP_DIR_IS_IN(ep)) &&
+               usb_hs_device.in_ep[ep_idx].ep_ena) {
+        return 1;
+    }
+
+    return 0;
+}
+#ifndef CONFIG_USB_VDMA_ENABLE
+static int usb_dma_write(uint8_t fifo_num, const uint8_t *data, uint32_t len)
+{
+    uint32_t timeout = 0xffffff;
+
+    USB_DMA_Cfg_Type dma_cfg;
+
+    dma_cfg.dir = USB_DMA_TRANS_DIR_MEM_2_FIFO;
+    dma_cfg.memAddr = (uint32_t)(uintptr_t)data;
+    dma_cfg.length = len;
+
+    csi_dcache_clean_range((uint32_t *)data, len);
+    /* dma config */
+    USB_Set_DMA_Config(fifo_num, &dma_cfg);
+    /* dma start */
+    USB_Set_DMA_Start();
+    /* dma wait */
+    while (1) {
+        if (USB_Get_Sub_Group_2_IntStatus() & USB_SUB_GROUP_2_ERROR_BIT_MUSK) {
+            USB_DC_LOG_ERR("dma error\r\n");
+            USB_Get_Sub_Group_2_IntClear(USB_SUB_GROUP_2_ERROR_BIT_MUSK);
+            return -USB_DC_DMA_ERR;
+        }
+        if (USB_Get_Sub_Group_2_IntStatus() & USB_SUB_GROUP_2_CMPLT_BIT_MUSK) {
+            USB_Get_Sub_Group_2_IntClear(USB_SUB_GROUP_2_CMPLT_BIT_MUSK);
+            break;
+        }
+        timeout--;
+        if (!timeout) {
+            USB_DC_LOG_ERR("fifo%d wait free timeout\r\n", fifo_num);
+            return -USB_DC_EP_TIMEOUT_ERR;
+        }
+    }
+    USB_Reset_DMA_Accessing_Fifo();
+    return 0;
+}
+
+static int usb_dma_read(uint8_t fifo_num, const uint8_t *data, uint32_t len)
+{
+    uint32_t timeout = 0xffffff;
+
+    USB_DMA_Cfg_Type dma_cfg;
+
+    dma_cfg.dir = USB_DMA_TRANS_DIR_FIFO_2_MEM;
+    dma_cfg.memAddr = (uint32_t)(uintptr_t)data;
+    dma_cfg.length = len;
+
+    /* dma config */
+    USB_Set_DMA_Config(fifo_num, &dma_cfg);
+    /* dma start */
+    USB_Set_DMA_Start();
+    /* dma wait */
+    while (1) {
+        if (USB_Get_Sub_Group_2_IntStatus() & USB_SUB_GROUP_2_ERROR_BIT_MUSK) {
+            USB_DC_LOG_ERR("dma error\r\n");
+            USB_Get_Sub_Group_2_IntClear(USB_SUB_GROUP_2_ERROR_BIT_MUSK);
+            return -USB_DC_DMA_ERR;
+        }
+        if (USB_Get_Sub_Group_2_IntStatus() & USB_SUB_GROUP_2_CMPLT_BIT_MUSK) {
+            USB_Get_Sub_Group_2_IntClear(USB_SUB_GROUP_2_CMPLT_BIT_MUSK);
+            break;
+        }
+        timeout--;
+        if (!timeout) {
+            USB_DC_LOG_ERR("fifo%d wait free timeout\r\n", fifo_num);
+            return -USB_DC_EP_TIMEOUT_ERR;
+        }
+    }
+    USB_Reset_DMA_Accessing_Fifo();
+    csi_dcache_invalid_range((uint32_t *)data, len);
+    return 0;
+}
+#else
+static int usb_vdma_write(uint8_t fifo_num, const uint8_t *data, uint32_t len)
+{
+    uint32_t timeout = 0xffffff;
+
+    USB_VDMA_Cfg_Type vdma_fifo_cfg;
+
+    vdma_fifo_cfg.dir = USB_VDMA_TRANS_DIR_MEM_2_FIFO;
+    vdma_fifo_cfg.memAddr = (uint32_t)(uintptr_t)data;
+    vdma_fifo_cfg.length = len;
+
+    csi_dcache_clean_range((void *)data, len);
+
+    USB_Set_VDMA_Config(fifo_num, &vdma_fifo_cfg);
+    USB_Set_VDMA_Start(fifo_num);
+
+    while (USB_Get_VDMA_Start(fifo_num)) {
+        timeout--;
+        if (!timeout) {
+            USB_DC_LOG_ERR("fifo%d wait free timeout\r\n", fifo_num);
+            return -USB_DC_EP_TIMEOUT_ERR;
+        }
+    }
+
+    return 0;
+}
+
+static int usb_vdma_read(uint8_t fifo_num, const uint8_t *data, uint32_t len)
+{
+    uint32_t timeout = 0xffffff;
+
+    USB_VDMA_Cfg_Type vdma_fifo_cfg;
+
+    vdma_fifo_cfg.dir = USB_VDMA_TRANS_DIR_FIFO_2_MEM;
+    vdma_fifo_cfg.memAddr = (uint32_t)(uintptr_t)data;
+    vdma_fifo_cfg.length = len;
+    USB_Set_VDMA_Config(fifo_num, &vdma_fifo_cfg);
+    USB_Set_VDMA_Start(fifo_num);
+
+    while (USB_Get_VDMA_Start(fifo_num)) {
+        timeout--;
+        if (!timeout) {
+            USB_DC_LOG_ERR("fifo%d wait free timeout\r\n", fifo_num);
+            return -USB_DC_EP_TIMEOUT_ERR;
+        }
+    }
+
+    csi_dcache_invalid_range((void *)data, len);
+    return 0;
+}
+#endif
+
+static uint8_t usb_get_transfer_fifo(uint8_t ep_idx)
+{
+    uint8_t target_fifo_id;
+
+    if (usb_hs_device.out_ep[ep_idx].ep_cfg.ep_mps > 512 || usb_hs_device.in_ep[ep_idx].ep_cfg.ep_mps > 512) {
+#ifdef CONFIG_USB_PINGPONG_ENABLE
+        target_fifo_id = (4 * ep_idx - 3);
+#else
+        target_fifo_id = (2 * ep_idx - 1);
+#endif
+    } else {
+#ifdef CONFIG_USB_PINGPONG_ENABLE
+        target_fifo_id = (2 * ep_idx - 1);
+#else
+        target_fifo_id = ep_idx;
+#endif
+    }
+
+    return target_fifo_id;
+}
+
+/**
+ * @brief
+ *
+ * @param dev
+ * @param oflag
+ * @return int
+ */
+int usb_dc_init(void)
+{
+    CPU_Interrupt_Disable(USB_IRQn);
+
+    PDS_Turn_On_USB(1);
+
+    /* interrupt config */
+    USB_Global_IntEnable(DISABLE);
+
+    /* software reset usb */
+    USB_NORMAL_Cfg_Type usbNormalCfg = {
+#ifdef CONFIG_USB_HS
+        .forceFullSpeed = 0,
+#else
+        .forceFullSpeed = 1,
+#endif
+        .chipEn = 1,
+        .swRst = 1,
+        .remoteWakeupEn = 0,
+        .rstTimeOut = 0xFFFF
+    };
+    USB_Set_Normal_Config(&usbNormalCfg);
+#ifdef CONFIG_USB_HS
+    USB_SOF_Mask_Time_HighSpeed();
+#else
+    USB_SOF_Mask_Time_FullSpeed();
+#endif
+    USB_Set_Device_Address(0);
+    USB_Non_Ctrl_Transfer_Disable();
+
+    USB_Reset_FIFO(USB_FIFO_0);
+    USB_Reset_FIFO(USB_FIFO_1);
+    USB_Reset_FIFO(USB_FIFO_2);
+    USB_Reset_FIFO(USB_FIFO_3);
+    USB_Clear_CTRL_FIFO();
+
+    USB_Group_IntMask(USB_GRP_INT_G0, UNMASK);
+    USB_Group_IntMask(USB_GRP_INT_G1, UNMASK);
+    USB_Group_IntMask(USB_GRP_INT_G2, UNMASK);
+    USB_Group_IntMask(USB_GRP_INT_G3, UNMASK);
+    USB_Group_IntMask(USB_GRP_INT_G4, UNMASK);
+
+    USB_Global_IntMask(USB_GLOBAL_INT_DEV, UNMASK);
+    USB_Global_IntMask(USB_GLOBAL_INT_OTG, MASK);
+    USB_Global_IntMask(USB_GLOBAL_INT_HC, MASK);
+
+    USB_Sub_Group_IntMask(USB_INT_DMA_CMPLT | USB_INT_DMA_ERROR | USB_INT_IDLE | USB_INT_RX0BYTE | USB_INT_TX0BYTE);
+    USB_Sub_Group_IntMask(USB_INT_VDMA_CMPLT_CXF | USB_INT_VDMA_CMPLT_F0 | USB_INT_VDMA_CMPLT_F1 | USB_INT_VDMA_CMPLT_F2 | USB_INT_VDMA_CMPLT_F3 |
+                          USB_INT_VDMA_ERROR_CXF | USB_INT_VDMA_ERROR_F0 | USB_INT_VDMA_ERROR_F1 | USB_INT_VDMA_ERROR_F2 | USB_INT_VDMA_ERROR_F3);
+
+    USB_Sub_Group_IntUnmask(USB_INT_CX_SETUP | USB_INT_CX_IN | USB_INT_CX_OUT | USB_INT_CX_COMFAIL | USB_INT_CX_COMABORT);
+    USB_Sub_Group_IntUnmask(USB_INT_RESET | USB_INT_SUSPEND | USB_INT_RESUME | USB_INT_RX0BYTE);
+
+    USB_Get_Sub_Group_0_IntClear(USB_SUB_GROUP_0_CX_COMABORT_BIT_MUSK);
+    USB_Get_Sub_Group_2_IntClear(USB_SUB_GROUP_2_RESET_BIT_MUSK | USB_SUB_GROUP_2_SUSPEND_BIT_MUSK | USB_SUB_GROUP_2_RESUME_BIT_MUSK |
+                                 USB_SUB_GROUP_2_TX0BYTE_BIT_MUSK | USB_SUB_GROUP_2_RX0BYTE_BIT_MUSK |
+                                 USB_SUB_GROUP_2_CMPLT_BIT_MUSK | USB_SUB_GROUP_2_ERROR_BIT_MUSK);
+    USB_Get_Sub_Group_3_IntClear(0xffffffff); //VDMA INT
+    USB_Get_Sub_Group_4_IntClear(USB_SUB_GROUP_4_L1_BIT_MUSK);
+    /*TODO mask no use rsv int use some drv*/
+    BL_WR_WORD(USB_BASE + USB_DEV_MISG0_OFFSET, 1 << 3);
+
+#ifdef CONFIG_USB_VDMA_ENABLE
+    USB_Set_VDMA_Enable();
+#endif
+
+    memset(&usb_hs_device, 0, sizeof(usb_hs_device));
+
+    usb_hs_device.out_ep[0].ep_ena = 1U;
+    usb_hs_device.in_ep[0].ep_ena = 1U;
+    usb_hs_device.out_ep[0].ep_cfg.ep_mps = 64;
+    usb_hs_device.out_ep[0].ep_cfg.ep_type = USBD_EP_TYPE_CTRL;
+    usb_hs_device.in_ep[0].ep_cfg.ep_mps = 64;
+    usb_hs_device.in_ep[0].ep_cfg.ep_type = USBD_EP_TYPE_CTRL;
+
+    Interrupt_Handler_Register(USB_IRQn, USBD_IRQHandler);
+    CPU_Interrupt_Enable(USB_IRQn);
+    USB_SoftDetach_Disable();
+    USB_Global_IntEnable(ENABLE);
+
+    return 0;
+}
+
+/**
+ * @brief Set USB device address
+ *
+ * @param[in] addr Device address
+ *
+ * @return 0 on success, negative errno code on fail.
+ */
+int usbd_set_address(const uint8_t addr)
+{
+    USB_Set_Device_Address(addr);
+    return 0;
+}
+
+/**
+ * @brief configure and enable endpoint
+ * This function sets endpoint configuration according to one specified in USB
+ * endpoint descriptor and then enables it for data transfers.
+ *
+ * @param dev
+ * @param ep_cfg  ep_cfg Endpoint
+ * @return int
+ */
+int usbd_ep_open(const struct usb_dc_ep_cfg *ep_cfg)
+{
+    uint8_t ep;
+    USB_FIFO_Cfg_Type fifo_cfg;
+
+    if (!ep_cfg) {
+        return -1;
+    }
+
+    ep = ep_cfg->ep_addr;
+
+    uint8_t ep_idx = USB_EP_GET_IDX(ep);
+
+    if (ep_idx > 4) {
+        return -1;
+    }
+
+    USB_DC_LOG_DBG("%s ep %x, mps %d, type %d\r\n", __func__, ep, ep_cfg->ep_mps, ep_cfg->ep_type);
+
+    if (ep_idx == 0) {
+        return 0;
+    }
+
+    fifo_cfg.enable = 1;
+    fifo_cfg.fifoType = ep_cfg->ep_type;
+    fifo_cfg.epID = ep_idx;
+
+    if (USB_EP_DIR_IS_OUT(ep)) {
+        fifo_cfg.dir = USB_FIFO_DIR_OUT;
+        usb_hs_device.out_ep[ep_idx].ep_cfg.ep_mps = ep_cfg->ep_mps;
+        usb_hs_device.out_ep[ep_idx].ep_cfg.ep_type = ep_cfg->ep_type;
+        usb_hs_device.out_ep[ep_idx].ep_ena = 1U;
+
+        USB_Set_Endpoint_OUT_MaxPacketSize(ep_idx, ep_cfg->ep_mps);
+
+    } else {
+        fifo_cfg.dir = USB_FIFO_DIR_IN;
+        usb_hs_device.in_ep[ep_idx].ep_cfg.ep_mps = ep_cfg->ep_mps;
+        usb_hs_device.in_ep[ep_idx].ep_cfg.ep_type = ep_cfg->ep_type;
+        usb_hs_device.in_ep[ep_idx].ep_ena = 1U;
+
+        USB_Set_Endpoint_IN_MaxPacketSize(ep_idx, ep_cfg->ep_mps);
+    }
+
+#ifndef CONFIG_USB_PINGPONG_ENABLE
+    fifo_cfg.blockType = USB_FIFO_BLOCK_CNT_SINGLE_BLOCK;
+
+    if (ep_cfg->ep_mps <= 512) {
+        if (ep_idx > 4) {
+            return -1;
+        }
+        fifo_ep_map[0] = 0x01;
+        fifo_ep_map[1] = 0x02;
+        fifo_ep_map[2] = 0x03;
+        fifo_ep_map[3] = 0x04;
+
+        USB_Set_FIFO_Of_Endpoint_IN(USB_Endpoint_1, USB_FIFO_0);
+        USB_Set_FIFO_Of_Endpoint_OUT(USB_Endpoint_1, USB_FIFO_0);
+        USB_Set_FIFO_Of_Endpoint_IN(USB_Endpoint_2, USB_FIFO_1);
+        USB_Set_FIFO_Of_Endpoint_OUT(USB_Endpoint_2, USB_FIFO_1);
+        USB_Set_FIFO_Of_Endpoint_IN(USB_Endpoint_3, USB_FIFO_2);
+        USB_Set_FIFO_Of_Endpoint_OUT(USB_Endpoint_3, USB_FIFO_2);
+        USB_Set_FIFO_Of_Endpoint_IN(USB_Endpoint_4, USB_FIFO_3);
+        USB_Set_FIFO_Of_Endpoint_OUT(USB_Endpoint_4, USB_FIFO_3);
+
+        fifo_cfg.blockSize = USB_FIFO_BLOCK_MAX_SIZE_512;
+        USB_Set_FIFO_Config(ep_idx - 1, &fifo_cfg);
+
+        if (USB_EP_DIR_IS_OUT(ep)) {
+#ifdef CONFIG_USB_VDMA_OUT_ENABLE
+            USB_Sub_Group_IntUnmask(1ULL << (USB_SUB_GRP3_INT_VDMA_CMPLT_F0 + (ep_idx - 1)));
+#else
+            USB_Sub_Group_IntUnmask(1ULL << (USB_SUB_GRP1_INT_F0_OUT + 2 * (ep_idx - 1)));
+#endif
+        } else {
+            USB_Sub_Group_IntUnmask(1ULL << (USB_SUB_GRP3_INT_VDMA_CMPLT_F0 + (ep_idx - 1)));
+        }
+
+        if (ep_cfg->ep_type == 0x01) {
+            uint32_t tmpVal;
+            tmpVal = BL_RD_WORD(USB_BASE + USB_DEV_INMPS1_OFFSET + 0x04 * (ep_idx - 1));
+            tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_TX_NUM_HBW_IEP1, 0);
+            BL_WR_WORD(USB_BASE + USB_DEV_INMPS1_OFFSET + 0x04 * (ep_idx - 1), tmpVal);
+        }
+    } else {
+        if (ep_idx > 2) {
+            return -1;
+        }
+        fifo_ep_map[0] = 0x01;
+        fifo_ep_map[1] = 0x01;
+        fifo_ep_map[2] = 0x02;
+        fifo_ep_map[3] = 0x02;
+
+        USB_Set_FIFO_Of_Endpoint_IN(USB_Endpoint_1, USB_FIFO_0);
+        USB_Set_FIFO_Of_Endpoint_OUT(USB_Endpoint_1, USB_FIFO_0);
+        USB_Set_FIFO_Of_Endpoint_IN(USB_Endpoint_2, USB_FIFO_2);
+        USB_Set_FIFO_Of_Endpoint_OUT(USB_Endpoint_2, USB_FIFO_2);
+
+        fifo_cfg.blockSize = USB_FIFO_BLOCK_MAX_SIZE_1024;
+        USB_Set_FIFO_Config(2 * ep_idx - 2, &fifo_cfg);
+        fifo_cfg.enable = 0;
+        USB_Set_FIFO_Config(2 * ep_idx - 1, &fifo_cfg);
+
+        if (USB_EP_DIR_IS_OUT(ep)) {
+#ifdef CONFIG_USB_VDMA_OUT_ENABLE
+            USB_Sub_Group_IntUnmask(1ULL << (USB_SUB_GRP3_INT_VDMA_CMPLT_F0 + 2 * (ep_idx - 1)));
+#else
+            USB_Sub_Group_IntUnmask(1ULL << (USB_SUB_GRP1_INT_F0_OUT + 4 * (ep_idx - 1)));
+#endif
+        } else {
+            USB_Sub_Group_IntUnmask(1ULL << (USB_SUB_GRP3_INT_VDMA_CMPLT_F0 + 2 * (ep_idx - 1)));
+        }
+
+        if (ep_cfg->ep_type == 0x01) {
+            uint32_t tmpVal;
+            tmpVal = BL_RD_WORD(USB_BASE + USB_DEV_INMPS1_OFFSET + 0x04 * (ep_idx - 1));
+            tmpVal = BL_SET_REG_BITS_VAL(tmpVal, USB_TX_NUM_HBW_IEP1, 0);
+            BL_WR_WORD(USB_BASE + USB_DEV_INMPS1_OFFSET + 0x04 * (ep_idx - 1), tmpVal);
+        }
+    }
+#else
+    fifo_cfg.blockType = USB_FIFO_BLOCK_CNT_DOUBLE_BLOCKS;
+
+    if (ep_cfg->ep_mps <= 512) {
+        if (ep_idx > 2) {
+            return -1;
+        }
+        fifo_ep_map[0] = 0x01;
+        fifo_ep_map[1] = 0x01;
+        fifo_ep_map[2] = 0x02;
+        fifo_ep_map[3] = 0x02;
+
+        USB_Set_FIFO_Of_Endpoint_IN(USB_Endpoint_1, USB_FIFO_0);
+        USB_Set_FIFO_Of_Endpoint_OUT(USB_Endpoint_1, USB_FIFO_0);
+        USB_Set_FIFO_Of_Endpoint_IN(USB_Endpoint_2, USB_FIFO_2);
+        USB_Set_FIFO_Of_Endpoint_OUT(USB_Endpoint_2, USB_FIFO_2);
+
+        fifo_cfg.blockSize = USB_FIFO_BLOCK_MAX_SIZE_512;
+        USB_Set_FIFO_Config(2 * ep_idx - 2, &fifo_cfg);
+        fifo_cfg.enable = 0;
+        USB_Set_FIFO_Config(2 * ep_idx - 1, &fifo_cfg);
+
+        if (USB_EP_DIR_IS_OUT(ep)) {
+#ifdef CONFIG_USB_VDMA_OUT_ENABLE
+            USB_Sub_Group_IntUnmask(1ULL << (USB_SUB_GRP3_INT_VDMA_CMPLT_F0 + 2 * (ep_idx - 1)));
+#else
+            USB_Sub_Group_IntUnmask(1ULL << (USB_SUB_GRP1_INT_F0_OUT + 4 * (ep_idx - 1)));
+#endif
+        } else {
+            USB_Sub_Group_IntUnmask(1ULL << (USB_SUB_GRP3_INT_VDMA_CMPLT_F0 + 2 * (ep_idx - 1)));
+        }
+    } else {
+        if (ep_idx > 1) {
+            return -1;
+        }
+
+        fifo_ep_map[0] = 0x01;
+        fifo_ep_map[1] = 0x01;
+        fifo_ep_map[2] = 0x01;
+        fifo_ep_map[3] = 0x01;
+
+        USB_Set_FIFO_Of_Endpoint_IN(USB_Endpoint_1, USB_FIFO_0);
+        USB_Set_FIFO_Of_Endpoint_OUT(USB_Endpoint_1, USB_FIFO_0);
+
+        fifo_cfg.blockSize = USB_FIFO_BLOCK_MAX_SIZE_1024;
+        USB_Set_FIFO_Config(2 * ep_idx - 2, &fifo_cfg);
+        fifo_cfg.enable = 0;
+        USB_Set_FIFO_Config(2 * ep_idx - 1, &fifo_cfg);
+        USB_Set_FIFO_Config(2 * ep_idx, &fifo_cfg);
+        USB_Set_FIFO_Config(2 * ep_idx + 1, &fifo_cfg);
+
+        if (USB_EP_DIR_IS_OUT(ep)) {
+#ifdef CONFIG_USB_VDMA_OUT_ENABLE
+            USB_Sub_Group_IntUnmask(1ULL << (USB_SUB_GRP3_INT_VDMA_CMPLT_F0));
+#else
+            USB_Sub_Group_IntUnmask(1ULL << (USB_SUB_GRP1_INT_F0_OUT));
+#endif
+        } else {
+            USB_Sub_Group_IntUnmask(1ULL << (USB_SUB_GRP3_INT_VDMA_CMPLT_F0));
+        }
+    }
+#endif
+
+    USB_Non_Ctrl_Transfer_Enable();
+
+    return 0;
+}
+
+/**
+ * @brief Disable the selected endpoint
+ *
+ * Function to disable the selected endpoint. Upon success interrupts are
+ * disabled for the corresponding endpoint and the endpoint is no longer able
+ * for transmitting/receiving data.
+ *
+ * @param[in] ep Endpoint address corresponding to the one
+ *               listed in the device configuration table
+ *
+ * @return 0 on success, negative errno code on fail.
+ */
+int usbd_ep_close(const uint8_t ep)
+{
+    return 0;
+}
+/**
+ * @brief Set stall condition for the selected endpoint
+ *
+ * @param[in] ep Endpoint address corresponding to the one
+ *               listed in the device configuration table
+ *
+ * @return 0 on success, negative errno code on fail.
+ */
+int usbd_ep_set_stall(const uint8_t ep)
+{
+    uint8_t ep_idx = USB_EP_GET_IDX(ep);
+
+    if (USB_EP_DIR_IS_OUT(ep)) {
+        if (ep_idx == 0) {
+            USB_Set_CTRL_Endpoint_Stall_Once();
+        } else {
+            USB_Set_Endpoint_OUT_Stall(ep_idx, ENABLE);
+            usb_hs_device.out_ep[ep_idx].is_stalled = 1U;
+        }
+    } else {
+        if (ep_idx == 0) {
+            USB_Set_CTRL_Endpoint_Stall_Once();
+        } else {
+            USB_Set_Endpoint_IN_Stall(ep_idx, ENABLE);
+            usb_hs_device.in_ep[ep_idx].is_stalled = 1U;
+        }
+    }
+    return 0;
+}
+/**
+ * @brief Clear stall condition for the selected endpoint
+ *
+ * @param[in] ep Endpoint address corresponding to the one
+ *               listed in the device configuration table
+ *
+ * @return 0 on success, negative errno code on fail.
+ */
+int usbd_ep_clear_stall(const uint8_t ep)
+{
+    uint8_t ep_idx = USB_EP_GET_IDX(ep);
+
+    if (ep_idx) {
+        if (USB_EP_DIR_IS_OUT(ep)) {
+            USB_Reset_Endpoint_OUT_Data_Toggle_Sequence(ep_idx);
+            USB_Set_Endpoint_OUT_Stall(ep_idx, DISABLE);
+            usb_hs_device.out_ep[ep_idx].is_stalled = 0;
+        } else {
+            USB_Reset_Endpoint_IN_Data_Toggle_Sequence(ep_idx);
+            USB_Set_Endpoint_IN_Stall(ep_idx, DISABLE);
+            usb_hs_device.in_ep[ep_idx].is_stalled = 0;
+        }
+    }
+    return 0;
+}
+/**
+ * @brief Check if the selected endpoint is stalled
+ *
+ * @param dev usb device
+ * @param[in]  ep       Endpoint address corresponding to the one
+ *                      listed in the device configuration table
+ * @param[out] stalled  Endpoint stall status
+ *
+ * @return 0 on success, negative errno code on fail.
+ */
+int usbd_ep_is_stalled(const uint8_t ep, uint8_t *stalled)
+{
+    uint8_t ep_idx = USB_EP_GET_IDX(ep);
+
+    if (!stalled) {
+        return -1;
+    }
+    *stalled = 0U;
+    if (ep_idx == 0)
+        return 0;
+
+    if (USB_EP_DIR_IS_OUT(ep)) {
+        if (usb_hs_device.out_ep[ep_idx].is_stalled) {
+            *stalled = 1U;
+        }
+    } else {
+        if (usb_hs_device.in_ep[ep_idx].is_stalled) {
+            *stalled = 1U;
+        }
+    }
+
+    return 0;
+}
+
+/**
+ * @brief Write data to the specified endpoint
+ *
+ * This function is called to write data to the specified endpoint. The
+ * supplied usbd_endpoint_callback function will be called when data is transmitted
+ * out.
+ *
+ * @param dev
+ * @param[in]  ep        Endpoint address corresponding to the one
+ *                       listed in the device configuration table
+ * @param[in]  data      Pointer to data to write
+ * @param[in]  data_len  Length of the data requested to write. This may
+ *                       be zero for a zero length status packet.
+ * @param[out] ret_bytes Bytes scheduled for transmission. This value
+ *                       may be NULL if the application expects all
+ *                       bytes to be written
+ *
+ * @return 0 on success, negative errno code on fail.
+ */
+int usbd_ep_write(const uint8_t ep, const uint8_t *data, uint32_t data_len, uint32_t *ret_bytes)
+{
+    uint32_t timeout = 0xffffff;
+    uint32_t target_fifo_id = 0;
+    uint8_t mps_over_flag = 0;
+    uint8_t ep_idx = USB_EP_GET_IDX(ep);
+    int ret = 0;
+    /* Check if IN ep */
+    if (USB_EP_GET_DIR(ep) != USB_EP_DIR_IN) {
+        return -USB_DC_EP_DIR_ERR;
+    }
+
+    /* Check if ep enabled */
+    if (!usb_ep_is_enabled(ep)) {
+        return -USB_DC_EP_EN_ERR;
+    }
+
+    if (!data && data_len) {
+        USB_DC_LOG_ERR("data is null\r\n");
+        return -USB_DC_ADDR_ERR;
+    }
+
+    if (ep_idx == 0) {
+        if (!data_len) {
+            /* enable ep0 transfer */
+            USB_CTRL_Endpoint_Data_Transfer_Done();
+            return USB_DC_OK;
+        }
+        if (data_len > usb_hs_device.in_ep[ep_idx].ep_cfg.ep_mps) {
+            /* Check if transfer len is too big */
+            data_len = usb_hs_device.in_ep[ep_idx].ep_cfg.ep_mps;
+            mps_over_flag = 1;
+        }
+
+#ifdef CONFIG_USB_VDMA_ENABLE
+        ret = usb_vdma_write(0, data, data_len);
+#else
+        ret = usb_dma_write(0, data, data_len);
+#endif
+        if (ret < 0) {
+            return ret;
+        }
+        if (!mps_over_flag) {
+            USB_CTRL_Endpoint_Data_Transfer_Done();
+        }
+
+    } else {
+        if (!data_len) {
+            /* send zlp */
+            USB_Endpoint_Transmit_Zero_Length_Packet(ep_idx);
+            while (1) {
+                if (USB_Is_Endpoint_Transfer_Zero_Length_Packet(ep_idx)) {
+                    USB_Clear_Endpoint_Transfer_Zero_Length_Packet_Status(ep_idx);
+                    break;
+                }
+                timeout--;
+                if (!timeout) {
+                    USB_DC_LOG_ERR("ep%d wait free timeout\r\n", ep);
+                    return -USB_DC_EP_TIMEOUT_ERR;
+                }
+            }
+            return USB_DC_OK;
+        }
+
+        target_fifo_id = usb_get_transfer_fifo(ep_idx);
+#ifdef CONFIG_USB_VDMA_ENABLE
+        ret = usb_vdma_write(target_fifo_id, data, data_len);
+#else
+        ret = usb_dma_write(target_fifo_id, data, data_len);
+#endif
+        if (ret < 0) {
+            return ret;
+        }
+    }
+
+    USB_DC_LOG_DBG("EP%d write %u bytes\r\n", ep_idx, data_len);
+
+    if (ret_bytes) {
+        *ret_bytes = data_len;
+    }
+
+    return USB_DC_OK;
+}
+
+/**
+ * @brief Read data from the specified endpoint
+ *
+ * This function is called by the endpoint handler function, after an OUT
+ * interrupt has been received for that EP. The application must only call this
+ * function through the supplied usbd_ep_callback function. This function clears
+ * the ENDPOINT NAK when max_data_len is 0, if all data in the endpoint FIFO has been read,
+ * so as to accept more data from host.
+ *
+ * @param[in]  ep           Endpoint address corresponding to the one
+ *                          listed in the device configuration table
+ * @param[in]  data         Pointer to data buffer to write to
+ * @param[in]  max_data_len Max length of data to read
+ * @param[out] read_bytes   Number of bytes read. If data is NULL and
+ *                          max_data_len is 0 the number of bytes
+ *                          available for read should be returned.
+ *
+ * @return 0 on success, negative errno code on fail.
+ */
+int usbd_ep_read(const uint8_t ep, uint8_t *data, uint32_t data_len, uint32_t *read_bytes)
+{
+    uint32_t read_len = 0;
+    uint32_t target_fifo_id = 0;
+    uint8_t ep_idx = USB_EP_GET_IDX(ep);
+    int ret = 0;
+
+    /* Check if OUT ep */
+    if (USB_EP_GET_DIR(ep) != USB_EP_DIR_OUT) {
+        USB_DC_LOG_ERR("Wrong endpoint direction\r\n");
+        return -USB_DC_EP_DIR_ERR;
+    }
+
+    /* Check if ep enabled */
+    if (!usb_ep_is_enabled(ep)) {
+        USB_DC_LOG_ERR("Not enabled endpoint\r\n");
+        return -USB_DC_EP_EN_ERR;
+    }
+
+    if (!data && data_len) {
+        USB_DC_LOG_ERR("data is null\r\n");
+        return -USB_DC_ADDR_ERR;
+    }
+
+    /* Allow to read 0 bytes */
+    if (!data_len) {
+        return USB_DC_OK;
+    }
+
+    if (ep_idx == 0) {
+        /*setup handler*/
+        if ((data_len == 8) && !read_bytes) {
+            USB_Get_Setup_Command((uint32_t *)data);
+            return USB_DC_OK;
+        } else {
+            read_len = BL_GET_REG_BITS_VAL(BL_RD_REG(USB_BASE, USB_DEV_CXCFE), USB_CX_FNT);
+#if defined(CONFIG_USB_VDMA_ENABLE)
+            ret = usb_vdma_read(0, data, read_len);
+#else
+            ret = usb_dma_read(0, data, read_len);
+#endif
+            if (ret < 0) {
+                return ret;
+            }
+        }
+    } else {
+        target_fifo_id = usb_get_transfer_fifo(ep_idx);
+        read_len = USB_Get_OUT_FIFO_Count(target_fifo_id - 1);
+        if (read_len == 0) {
+            if (read_bytes) {
+                *read_bytes = 0;
+            }
+            return 0;
+        }
+#ifdef CONFIG_USB_VDMA_ENABLE
+        ret = usb_vdma_read(target_fifo_id, data, read_len);
+#else
+        ret = usb_dma_read(target_fifo_id, data, read_len);
+#endif
+        if (ret < 0) {
+            return ret;
+        }
+    }
+    if (read_bytes) {
+        *read_bytes = read_len;
+    }
+    USB_DC_LOG_DBG("Read EP%d, req %d, read %d bytes\r\n", ep, data_len, *read_bytes);
+
+    return USB_DC_OK;
+}
+
+int usbd_ep_write_async(const uint8_t ep, const uint8_t *data, uint32_t data_len)
+{
+    uint32_t target_fifo_id = 0;
+    uint8_t ep_idx = USB_EP_GET_IDX(ep);
+
+    /* Check if IN ep */
+    if (USB_EP_GET_DIR(ep) != USB_EP_DIR_IN) {
+        return -USB_DC_EP_DIR_ERR;
+    }
+
+    /* Check if ep enabled */
+    if (!usb_ep_is_enabled(ep)) {
+        return -USB_DC_EP_EN_ERR;
+    }
+
+    if (!data && data_len) {
+        USB_DC_LOG_ERR("data is null\r\n");
+        return -USB_DC_ADDR_ERR;
+    }
+
+    target_fifo_id = usb_get_transfer_fifo(ep_idx);
+
+    USB_VDMA_Cfg_Type vdma_fifo_cfg;
+
+    vdma_fifo_cfg.dir = USB_VDMA_TRANS_DIR_MEM_2_FIFO;
+    vdma_fifo_cfg.memAddr = (uint32_t)(uintptr_t)data;
+    vdma_fifo_cfg.length = data_len;
+
+    USB_Set_VDMA_Config(target_fifo_id, &vdma_fifo_cfg);
+    csi_dcache_clean_range((void *)data, data_len);
+    USB_Set_VDMA_Start(target_fifo_id);
+
+    return 0;
+}
+
+int usbd_ep_read_async(const uint8_t ep, uint8_t *data, uint32_t data_len)
+{
+    uint32_t target_fifo_id = 0;
+    uint8_t ep_idx = USB_EP_GET_IDX(ep);
+
+    /* Check if IN ep */
+    if (USB_EP_GET_DIR(ep) != USB_EP_DIR_OUT) {
+        return -USB_DC_EP_DIR_ERR;
+    }
+
+    /* Check if ep enabled */
+    if (!usb_ep_is_enabled(ep)) {
+        return -USB_DC_EP_EN_ERR;
+    }
+
+    if (!data && data_len) {
+        USB_DC_LOG_ERR("data is null\r\n");
+        return -USB_DC_ADDR_ERR;
+    }
+
+    target_fifo_id = usb_get_transfer_fifo(ep_idx);
+
+    USB_VDMA_Cfg_Type vdma_fifo_cfg;
+
+    vdma_fifo_cfg.dir = USB_VDMA_TRANS_DIR_FIFO_2_MEM;
+    vdma_fifo_cfg.memAddr = (uint32_t)(uintptr_t)data;
+    vdma_fifo_cfg.length = data_len;
+
+    USB_Set_VDMA_Config(target_fifo_id, &vdma_fifo_cfg);
+    USB_Set_VDMA_Start(target_fifo_id);
+
+    return 0;
+}
+
+extern void usbd_event_notify_handler(uint8_t event, void *arg);
+
+static void usb_group0_isr(void)
+{
+    uint32_t group0intstatus = USB_Get_Sub_Group_0_IntStatus() & ~USB_Get_Sub_Group_0_IntMask();
+
+    if (group0intstatus & USB_SUB_GROUP_0_CX_COMABORT_BIT_MUSK) {
+        /* CX_COMABT_INT  */
+        USB_DC_LOG_ERR("CX COMABT\r\n");
+        USB_Get_Sub_Group_0_IntClear(USB_SUB_GROUP_0_CX_COMABORT_BIT_MUSK);
+        return;
+    }
+    if (group0intstatus & USB_SUB_GROUP_0_CX_COMFAIL_BIT_MUSK) {
+        /* CX_COMFAIL_INT */
+        USB_DC_LOG_ERR("CX COMFAIL\r\n");
+        return;
+    }
+    if (group0intstatus & USB_SUB_GROUP_0_CX_OUT_BIT_MUSK) {
+        /* CX_OUT_INT     */
+        usbd_event_notify_handler(USB_DC_EVENT_EP0_OUT_NOTIFY, NULL);
+        return;
+    }
+    if (group0intstatus & USB_SUB_GROUP_0_CX_IN_BIT_MUSK) {
+        /* CX_IN_INT      */
+        usbd_event_notify_handler(USB_DC_EVENT_EP0_IN_NOTIFY, NULL);
+        return;
+    }
+    if (group0intstatus & USB_SUB_GROUP_0_CX_SETUP_BIT_MUSK) {
+        /* CX_SETUP_INT   */
+        usbd_event_notify_handler(USB_DC_EVENT_SETUP_NOTIFY, NULL);
+        return;
+    }
+}
+static void usb_group1_isr(void)
+{
+    uint32_t group1intstatus = USB_Get_Sub_Group_1_IntStatus() & ~USB_Get_Sub_Group_1_IntMask();
+
+    if (group1intstatus & USB_SUB_GROUP_1_F0_OUT_BIT_MUSK) {
+        /* F0_OUT_INT */
+        usbd_event_notify_handler(USB_DC_EVENT_EP_OUT_NOTIFY, (void *)(uintptr_t)(fifo_ep_map[0] & 0x7f));
+    }
+
+    if (group1intstatus & USB_SUB_GROUP_1_F1_OUT_BIT_MUSK) {
+        /* F1_OUT_INT */
+        usbd_event_notify_handler(USB_DC_EVENT_EP_OUT_NOTIFY, (void *)(uintptr_t)(fifo_ep_map[1] & 0x7f));
+    }
+
+    if (group1intstatus & USB_SUB_GROUP_1_F2_OUT_BIT_MUSK) {
+        /* F2_OUT_INT */
+        usbd_event_notify_handler(USB_DC_EVENT_EP_OUT_NOTIFY, (void *)(uintptr_t)(fifo_ep_map[2] & 0x7f));
+    }
+
+    if (group1intstatus & USB_SUB_GROUP_1_F3_OUT_BIT_MUSK) {
+        /* F3_OUT_INT */
+        usbd_event_notify_handler(USB_DC_EVENT_EP_OUT_NOTIFY, (void *)(uintptr_t)(fifo_ep_map[3] & 0x7f));
+    }
+
+    if (group1intstatus & USB_SUB_GROUP_1_F0_IN_BIT_MUSK) {
+        /* F0_IN_INT  */
+        usbd_event_notify_handler(USB_DC_EVENT_EP_IN_NOTIFY, (void *)(uintptr_t)(fifo_ep_map[0] | 0x80));
+    }
+
+    if (group1intstatus & USB_SUB_GROUP_1_F1_IN_BIT_MUSK) {
+        /* F1_IN_INT  */
+        usbd_event_notify_handler(USB_DC_EVENT_EP_IN_NOTIFY, (void *)(uintptr_t)(fifo_ep_map[1] | 0x80));
+    }
+
+    if (group1intstatus & USB_SUB_GROUP_1_F2_IN_BIT_MUSK) {
+        /* F2_IN_INT  */
+        usbd_event_notify_handler(USB_DC_EVENT_EP_IN_NOTIFY, (void *)(uintptr_t)(fifo_ep_map[2] | 0x80));
+    }
+
+    if (group1intstatus & USB_SUB_GROUP_1_F3_IN_BIT_MUSK) {
+        /* F3_IN_INT  */
+        usbd_event_notify_handler(USB_DC_EVENT_EP_IN_NOTIFY, (void *)(uintptr_t)(fifo_ep_map[3] | 0x80));
+    }
+}
+static void usb_group2_isr(void)
+{
+    uint32_t group2intstatus = USB_Get_Sub_Group_2_IntStatus() & ~USB_Get_Sub_Group_2_IntMask();
+
+    if (group2intstatus & USB_SUB_GROUP_2_WAKEUP_BY_VBUS_BIT_MUSK) {
+        /* Dev_Wakeup_byVBUS */
+        return;
+    }
+    if (group2intstatus & USB_SUB_GROUP_2_IDLE_BIT_MUSK) {
+        /* Dev_Idle(HOV) */
+        return;
+    }
+    if (group2intstatus & USB_SUB_GROUP_2_ERROR_BIT_MUSK) {
+        /* DMA_ERROR(HOV) */
+        USB_Get_Sub_Group_2_IntClear(USB_SUB_GROUP_2_ERROR_BIT_MUSK);
+        return;
+    }
+    if (group2intstatus & USB_SUB_GROUP_2_CMPLT_BIT_MUSK) {
+        /* DMA_CMPLT(HOV) */
+        USB_Get_Sub_Group_2_IntClear(USB_SUB_GROUP_2_CMPLT_BIT_MUSK);
+        return;
+    }
+    if (group2intstatus & USB_SUB_GROUP_2_RX0BYTE_BIT_MUSK) {
+        /* RX0BYTE_INT */
+        USB_Get_Sub_Group_2_IntClear(USB_SUB_GROUP_2_RX0BYTE_BIT_MUSK);
+        for (uint32_t i = USB_Endpoint_1; i <= USB_Endpoint_8; i++) {
+            if (USB_Is_Endpoint_Receive_Zero_Length_Packet(i))
+                USB_Clear_Endpoint_Receive_Zero_Length_Packet_Status(i);
+        }
+        return;
+    }
+    if (group2intstatus & USB_SUB_GROUP_2_TX0BYTE_BIT_MUSK) {
+        /* TX0BYTE_INT */
+        USB_Get_Sub_Group_2_IntClear(USB_SUB_GROUP_2_TX0BYTE_BIT_MUSK);
+        for (uint32_t i = USB_Endpoint_1; i <= USB_Endpoint_8; i++) {
+            if (USB_Is_Endpoint_Transfer_Zero_Length_Packet(i))
+                USB_Clear_Endpoint_Transfer_Zero_Length_Packet_Status(i);
+        }
+        return;
+    }
+    if (group2intstatus & USB_SUB_GROUP_2_RESUME_BIT_MUSK) {
+        /* RESM_INT */
+        USB_Get_Sub_Group_2_IntClear(USB_SUB_GROUP_2_RESUME_BIT_MUSK);
+        usbd_event_notify_handler(USB_DC_EVENT_RESUME, NULL);
+        return;
+    }
+    if (group2intstatus & USB_SUB_GROUP_2_SUSPEND_BIT_MUSK) {
+        /* SUSP_INT */
+        USB_Get_Sub_Group_2_IntClear(USB_SUB_GROUP_2_SUSPEND_BIT_MUSK);
+        usbd_event_notify_handler(USB_DC_EVENT_SUSPEND, NULL);
+        return;
+    }
+    if (group2intstatus & USB_SUB_GROUP_2_RESET_BIT_MUSK) {
+        /* USBRST_INT */
+        USB_Get_Sub_Group_2_IntClear(USB_SUB_GROUP_2_RESET_BIT_MUSK);
+        USB_Non_Ctrl_Transfer_Disable();
+        USB_Reset_FIFO(USB_FIFO_0);
+        USB_Reset_FIFO(USB_FIFO_1);
+        USB_Reset_FIFO(USB_FIFO_2);
+        USB_Reset_FIFO(USB_FIFO_3);
+        USB_Clear_CTRL_FIFO();
+
+#ifdef CONFIG_USB_HS
+        USB_SOF_Mask_Time_HighSpeed();
+#else
+        USB_SOF_Mask_Time_FullSpeed();
+#endif
+        usbd_event_notify_handler(USB_DC_EVENT_RESET, NULL);
+        return;
+    }
+}
+#ifdef CONFIG_USB_VDMA_ENABLE
+static void usb_group3_isr(void)
+{
+    uint32_t group3intstatus = USB_Get_Sub_Group_3_IntStatus() & ~USB_Get_Sub_Group_3_IntMask();
+
+    if (group3intstatus & USB_SUB_GROUP_3_VDMA_CMPLT_CXF_BIT_MUSK) {
+        /* VDMA_CMPLT_CXF */
+        USB_Get_Sub_Group_3_IntClear(USB_SUB_GROUP_3_VDMA_CMPLT_CXF_BIT_MUSK);
+    }
+
+    if (group3intstatus & USB_SUB_GROUP_3_VDMA_CMPLT_F0_BIT_MUSK) {
+        /* VDMA_CMPLT_F0  */
+        USB_Get_Sub_Group_3_IntClear(USB_SUB_GROUP_3_VDMA_CMPLT_F0_BIT_MUSK);
+        if (usb_hs_device.in_ep[fifo_ep_map[0]].ep_ena) {
+            usbd_event_notify_handler(USB_DC_EVENT_EP_IN_NOTIFY, (void *)(uintptr_t)(fifo_ep_map[0] | 0x80));
+        } else if (usb_hs_device.out_ep[fifo_ep_map[0]].ep_ena) {
+            usbd_event_notify_handler(USB_DC_EVENT_EP_OUT_NOTIFY, (void *)(uintptr_t)(fifo_ep_map[0] & 0x7f));
+        }
+    }
+
+    if (group3intstatus & USB_SUB_GROUP_3_VDMA_CMPLT_F1_BIT_MUSK) {
+        /* VDMA_CMPLT_F1  */
+        USB_Get_Sub_Group_3_IntClear(USB_SUB_GROUP_3_VDMA_CMPLT_F1_BIT_MUSK);
+        if (usb_hs_device.in_ep[fifo_ep_map[1]].ep_ena) {
+            usbd_event_notify_handler(USB_DC_EVENT_EP_IN_NOTIFY, (void *)(uintptr_t)(fifo_ep_map[1] | 0x80));
+        } else if (usb_hs_device.out_ep[fifo_ep_map[1]].ep_ena) {
+            usbd_event_notify_handler(USB_DC_EVENT_EP_OUT_NOTIFY, (void *)(uintptr_t)(fifo_ep_map[1] & 0x7f));
+        }
+    }
+
+    if (group3intstatus & USB_SUB_GROUP_3_VDMA_CMPLT_F2_BIT_MUSK) {
+        /* VDMA_CMPLT_F2  */
+        USB_Get_Sub_Group_3_IntClear(USB_SUB_GROUP_3_VDMA_CMPLT_F2_BIT_MUSK);
+        if (usb_hs_device.in_ep[fifo_ep_map[2]].ep_ena) {
+            usbd_event_notify_handler(USB_DC_EVENT_EP_IN_NOTIFY, (void *)(uintptr_t)(fifo_ep_map[2] | 0x80));
+        } else if (usb_hs_device.out_ep[fifo_ep_map[2]].ep_ena) {
+            usbd_event_notify_handler(USB_DC_EVENT_EP_OUT_NOTIFY, (void *)(uintptr_t)(fifo_ep_map[2] & 0x7f));
+        }
+    }
+
+    if (group3intstatus & USB_SUB_GROUP_3_VDMA_CMPLT_F3_BIT_MUSK) {
+        /* VDMA_CMPLT_F3  */
+        USB_Get_Sub_Group_3_IntClear(USB_SUB_GROUP_3_VDMA_CMPLT_F3_BIT_MUSK);
+        if (usb_hs_device.in_ep[fifo_ep_map[3]].ep_ena) {
+            usbd_event_notify_handler(USB_DC_EVENT_EP_IN_NOTIFY, (void *)(uintptr_t)(fifo_ep_map[3] | 0x80));
+        } else if (usb_hs_device.out_ep[fifo_ep_map[3]].ep_ena) {
+            usbd_event_notify_handler(USB_DC_EVENT_EP_OUT_NOTIFY, (void *)(uintptr_t)(fifo_ep_map[3] & 0x7f));
+        }
+    }
+
+    if (group3intstatus & USB_SUB_GROUP_3_VDMA_ERROR_CXF_BIT_MUSK) {
+        /* VDMA_ERROR_CXF */
+        USB_Get_Sub_Group_3_IntClear(USB_SUB_GROUP_3_VDMA_ERROR_CXF_BIT_MUSK);
+    }
+
+    if (group3intstatus & USB_SUB_GROUP_3_VDMA_ERROR_F0_BIT_MUSK) {
+        /* VDMA_ERROR_F0  */
+        USB_Get_Sub_Group_3_IntClear(USB_SUB_GROUP_3_VDMA_ERROR_F0_BIT_MUSK);
+    }
+
+    if (group3intstatus & USB_SUB_GROUP_3_VDMA_ERROR_F1_BIT_MUSK) {
+        /* VDMA_ERROR_F1  */
+        USB_Get_Sub_Group_3_IntClear(USB_SUB_GROUP_3_VDMA_ERROR_F1_BIT_MUSK);
+    }
+
+    if (group3intstatus & USB_SUB_GROUP_3_VDMA_ERROR_F2_BIT_MUSK) {
+        /* VDMA_ERROR_F2  */
+        USB_Get_Sub_Group_3_IntClear(USB_SUB_GROUP_3_VDMA_ERROR_F2_BIT_MUSK);
+    }
+
+    if (group3intstatus & USB_SUB_GROUP_3_VDMA_ERROR_F3_BIT_MUSK) {
+        /* VDMA_ERROR_F3  */
+        USB_Get_Sub_Group_3_IntClear(USB_SUB_GROUP_3_VDMA_ERROR_F3_BIT_MUSK);
+    }
+}
+#endif
+static void usb_group4_isr(void)
+{
+    uint32_t group4intstatus = USB_Get_Sub_Group_4_IntStatus() & ~USB_Get_Sub_Group_4_IntMask();
+
+    if (group4intstatus & USB_SUB_GROUP_4_L1_BIT_MUSK) {
+        /* L1_INT  */
+        USB_Get_Sub_Group_3_IntClear(USB_SUB_GROUP_4_L1_BIT_MUSK);
+        return;
+    }
+}
+
+/**
+ * @brief
+ *
+ */
+void USBD_IRQHandler(void)
+{
+    if (USB_Global_IntStatus(USB_GLOBAL_INT_DEV)) {
+        /* group 0 int */
+        if (USB_Group_IntStatus(USB_GRP_INT_G0)) {
+            usb_group0_isr();
+        }
+        /* group 1 int */
+        if (USB_Group_IntStatus(USB_GRP_INT_G1)) {
+            usb_group1_isr();
+        }
+        /* group 2 int */
+        if (USB_Group_IntStatus(USB_GRP_INT_G2)) {
+            usb_group2_isr();
+        }
+#ifdef CONFIG_USB_VDMA_ENABLE
+        /* group 3 int */
+        if (USB_Group_IntStatus(USB_GRP_INT_G3)) {
+            usb_group3_isr();
+        }
+#endif
+        /* group 4 int */
+        if (USB_Group_IntStatus(USB_GRP_INT_G4)) {
+            usb_group4_isr();
+        }
+    }
+}
+
+#ifdef USB_TEST_MODE
+void usbd_set_feature(uint16_t index, uint16_t value)
+{
+    switch (value) {
+        case 0: //USB_FEATURE_ENDPOINT_HALT
+            //implement in usb_dc_ep_set_stall
+            break;
+        case 1: //USB_FEATURE_REMOTE_WAKEUP
+        {
+            uint32_t tmpVal;
+            tmpVal = BL_RD_REG(USB_BASE, USB_DEV_CTL);
+            tmpVal = BL_SET_REG_BIT(tmpVal, USB_CAP_RMWAKUP);
+            BL_WR_REG(USB_BASE, USB_DEV_CTL, tmpVal);
+        } break;
+        case 2: //USB_FEATURE_TEST_MODE
+            switch (index >> 8) {
+                case 1: // Test_J
+                {
+                    uint32_t tmpVal;
+                    tmpVal = BL_RD_REG(USB_BASE, USB_PHY_TST);
+                    tmpVal = BL_SET_REG_BIT(tmpVal, USB_TST_JSTA);
+                    BL_WR_REG(USB_BASE, USB_PHY_TST, tmpVal);
+                } break;
+                case 2: // Test_K
+                {
+                    uint32_t tmpVal;
+                    tmpVal = BL_RD_REG(USB_BASE, USB_PHY_TST);
+                    tmpVal = BL_SET_REG_BIT(tmpVal, USB_TST_KSTA);
+                    BL_WR_REG(USB_BASE, USB_PHY_TST, tmpVal);
+                } break;
+                case 3: // TEST_SE0_NAK
+                {
+                    uint32_t tmpVal;
+                    tmpVal = BL_RD_REG(USB_BASE, USB_PHY_TST);
+                    tmpVal = BL_SET_REG_BIT(tmpVal, USB_TST_SE0NAK);
+                    BL_WR_REG(USB_BASE, USB_PHY_TST, tmpVal);
+                } break;
+                case 4: // Test_Packet
+                {
+                    uint32_t tmpVal;
+                    tmpVal = BL_RD_REG(USB_BASE, USB_PHY_TST);
+                    tmpVal = BL_SET_REG_BIT(tmpVal, USB_TST_PKT);
+                    BL_WR_REG(USB_BASE, USB_PHY_TST, tmpVal);
+                } break;
+                case 5: // Test_Force_Enable
+                {
+                    uint8_t temp[53];
+                    uint8_t *pp;
+                    uint8_t i;
+                    pp = temp;
+
+                    for (i = 0; i < 9; i++) /*JKJKJKJK x 9*/
+                        *pp++ = 0x00;
+
+                    for (i = 0; i < 8; i++) /* 8*AA */
+                        *pp++ = 0xAA;
+
+                    for (i = 0; i < 8; i++) /* 8*EE */
+                        *pp++ = 0xEE;
+
+                    *pp++ = 0xFE;
+
+                    for (i = 0; i < 11; i++) /* 11*FF */
+                        *pp++ = 0xFF;
+
+                    *pp++ = 0x7F;
+                    *pp++ = 0xBF;
+                    *pp++ = 0xDF;
+                    *pp++ = 0xEF;
+                    *pp++ = 0xF7;
+                    *pp++ = 0xFB;
+                    *pp++ = 0xFD;
+                    *pp++ = 0xFC;
+                    *pp++ = 0x7E;
+                    *pp++ = 0xBF;
+                    *pp++ = 0xDF;
+                    *pp++ = 0xEF;
+                    *pp++ = 0xF7;
+                    *pp++ = 0xFB;
+                    *pp++ = 0xFD;
+                    *pp++ = 0x7E;
+
+                    uint32_t tmpVal;
+                    tmpVal = BL_RD_REG(USB_BASE, USB_DEV_CXCFE);
+                    tmpVal = BL_SET_REG_BIT(tmpVal, USB_TST_PKDONE);
+                    BL_WR_REG(USB_BASE, USB_DEV_CXCFE, tmpVal);
+
+                } break;
+
+                default:
+                    break;
+            }
+            break;
+        case 3: //USB_FEATURE_BHNPENABLE
+        {
+            uint32_t tmpVal;
+            tmpVal = BL_RD_REG(USB_BASE, USB_OTG_CSR);
+            tmpVal = BL_SET_REG_BIT(tmpVal, USB_B_BUS_REQ);
+            BL_WR_REG(USB_BASE, USB_OTG_CSR, tmpVal);
+
+            tmpVal = BL_RD_REG(USB_BASE, USB_OTG_CSR);
+            tmpVal = BL_SET_REG_BIT(tmpVal, USB_B_HNP_EN);
+            BL_WR_REG(USB_BASE, USB_OTG_CSR, tmpVal);
+        } break;
+        case 4: //USB_FEATURE_AHNPSUPPORT
+
+            break;
+        case 5: //USB_FEATURE_AALTHNPSUPPORT
+
+            break;
+
+        default:
+            break;
+    }
+}
+
+void usbd_clear_feature(uint16_t index, uint16_t value)
+{
+    switch (value) {
+        case 0: //USB_FEATURE_ENDPOINT_HALT
+            //implement in usb_dc_ep_clear_stall
+            break;
+        case 1: //USB_FEATURE_REMOTE_WAKEUP
+        {
+            uint32_t tmpVal;
+            tmpVal = BL_RD_REG(USB_BASE, USB_DEV_CTL);
+            tmpVal = BL_CLR_REG_BIT(tmpVal, USB_CAP_RMWAKUP);
+            BL_WR_REG(USB_BASE, USB_DEV_CTL, tmpVal);
+        } break;
+
+        default:
+            break;
+    }
+}
+#endif

+ 158 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/hal_usb.h

@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __HAL_USB__H__
+#define __HAL_USB__H__
+
+#include "stdint.h"
+
+/**
+ * USB endpoint Transfer Type mask.
+ */
+#define USBD_EP_TYPE_CTRL 0
+#define USBD_EP_TYPE_ISOC 1
+#define USBD_EP_TYPE_BULK 2
+#define USBD_EP_TYPE_INTR 3
+#define USBD_EP_TYPE_MASK 3
+
+/**
+ * USB endpoint direction and number.
+ */
+#define USB_EP_DIR_MASK 0x80U
+#define USB_EP_DIR_IN   0x80U
+#define USB_EP_DIR_OUT  0x00U
+
+#define USB_EP_OUT_MSK 0x7FU
+#define USB_EP_IN_MSK  0x80U
+
+/** Get endpoint index (number) from endpoint address */
+#define USB_EP_GET_IDX(ep) ((ep) & ~USB_EP_DIR_MASK)
+/** Get direction from endpoint address */
+#define USB_EP_GET_DIR(ep) ((ep)&USB_EP_DIR_MASK)
+/** Get endpoint address from endpoint index and direction */
+#define USB_EP_GET_ADDR(idx, dir) ((idx) | ((dir)&USB_EP_DIR_MASK))
+/** True if the endpoint is an IN endpoint */
+#define USB_EP_DIR_IS_IN(ep) (USB_EP_GET_DIR(ep) == USB_EP_DIR_IN)
+/** True if the endpoint is an OUT endpoint */
+#define USB_EP_DIR_IS_OUT(ep) (USB_EP_GET_DIR(ep) == USB_EP_DIR_OUT)
+
+#define USB_SET_EP_OUT(ep) (ep & USB_EP_OUT_MSK)
+#define USB_SET_EP_IN(ep)  (ep | USB_EP_IN_MSK)
+
+#define USB_OUT_EP_NUM 8
+#define USB_IN_EP_NUM  8
+
+enum usb_dc_event_type {
+    /** USB error reported by the controller */
+    USB_DC_EVENT_ERROR,
+    /** USB reset */
+    USB_DC_EVENT_RESET,
+    /** Start of Frame received */
+    USB_DC_EVENT_SOF,
+    /** USB connection established, hardware enumeration is completed */
+    USB_DC_EVENT_CONNECTED,
+    /** USB configuration done */
+    USB_DC_EVENT_CONFIGURED,
+    /** USB connection suspended by the HOST */
+    USB_DC_EVENT_SUSPEND,
+    /** USB connection lost */
+    USB_DC_EVENT_DISCONNECTED,
+    /** USB connection resumed by the HOST */
+    USB_DC_EVENT_RESUME,
+
+    /** USB interface selected */
+    USB_DC_EVENT_SET_INTERFACE,
+    /** USB interface selected */
+    USB_DC_EVENT_SET_REMOTE_WAKEUP,
+    /** USB interface selected */
+    USB_DC_EVENT_CLEAR_REMOTE_WAKEUP,
+    /** Set Feature ENDPOINT_HALT received */
+    USB_DC_EVENT_SET_HALT,
+    /** Clear Feature ENDPOINT_HALT received */
+    USB_DC_EVENT_CLEAR_HALT,
+    /** setup packet received */
+    USB_DC_EVENT_SETUP_NOTIFY,
+    /** ep0 in packet received */
+    USB_DC_EVENT_EP0_IN_NOTIFY,
+    /** ep0 out packet received */
+    USB_DC_EVENT_EP0_OUT_NOTIFY,
+    /** ep in packet except ep0 received */
+    USB_DC_EVENT_EP_IN_NOTIFY,
+    /** ep out packet except ep0 received */
+    USB_DC_EVENT_EP_OUT_NOTIFY,
+    /** Initial USB connection status */
+    USB_DC_EVENT_UNKNOWN
+};
+
+enum usb_error_type {
+    USB_DC_OK = 0,
+    USB_DC_EP_DIR_ERR = 1,
+    USB_DC_EP_EN_ERR = 2,
+    USB_DC_EP_TIMEOUT_ERR = 3,
+    USB_DC_ADDR_ERR = 4,
+    USB_DC_DMA_ERR = 5,
+    USB_DC_VDMA_ERR = 6,
+    USB_DC_DATA_NONE = 7,
+};
+/**
+ * @brief USB Endpoint Configuration.
+ *
+ * Structure containing the USB endpoint configuration.
+ */
+struct usb_dc_ep_cfg {
+    /** The number associated with the EP in the device
+     *  configuration structure
+     *       IN  EP = 0x80 | \<endpoint number\>
+     *       OUT EP = 0x00 | \<endpoint number\>
+     */
+    uint8_t ep_addr;
+    /** Endpoint Transfer Type.
+     * May be Bulk, Interrupt, Control or Isochronous
+     */
+    uint8_t ep_type;
+    /** Endpoint max packet size */
+    uint16_t ep_mps;
+};
+
+/*
+ * USB endpoint  structure.
+ */
+typedef struct
+{
+    uint8_t ep_ena;
+    uint8_t is_stalled;
+    struct usb_dc_ep_cfg ep_cfg;
+} usb_dc_ep_state_t;
+
+typedef struct usb_dc_device {
+    usb_dc_ep_state_t in_ep[8];  /*!< IN endpoint parameters             */
+    usb_dc_ep_state_t out_ep[8]; /*!< OUT endpoint parameters            */
+} usb_dc_device_t;
+
+#endif

+ 51 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/hal_wifi.c

@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <FreeRTOS.h>
+#include <task.h>
+#include "hal_wifi.h"
+#include <bl_pm.h>
+
+
+#define WIFI_STACK_SIZE     (1536)
+#define TASK_PRIORITY_FW    (30)
+
+#ifndef FEATURE_WIFI_DISABLE
+#include <bl60x_fw_api.h>
+int hal_wifi_start_firmware_task(void)
+{
+    static StackType_t wifi_fw_stack[WIFI_STACK_SIZE];
+    static StaticTask_t wifi_fw_task;
+
+    bl_pm_init();
+    xTaskCreateStatic(wifi_main, (char*)"fw", WIFI_STACK_SIZE, NULL, TASK_PRIORITY_FW, wifi_fw_stack, &wifi_fw_task);
+
+    return 0;
+}
+#endif

+ 33 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/hal_wifi.h

@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __HAL_WIFI_H__
+#define __HAL_WIFI_H__
+int hal_wifi_start_firmware_task(void);
+#endif

+ 527 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/hosal_adc.c

@@ -0,0 +1,527 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+//FIXME no BL808/BL606p header file including is Allowed here
+#ifdef BL808
+#include <bl808.h>
+#include <bl808_dma.h>
+#include <bl808_adc.h>
+#include <bl808_glb.h>
+#elif defined(BL606P)
+#include <bl606p.h>
+#include <bl606p_dma.h>
+#include <bl606p_adc.h>
+#include <bl606p_glb.h>
+#else
+#error "Use CHIP BL808/BL606P for this module"
+#endif
+
+#include <bl_irq.h>
+#include <blog.h>
+#include <hosal_dma.h>
+#include <hosal_adc.h>
+
+#define ADC_CLOCK_FREQ    40000000
+#define ADC_GPIO_NUM        12
+#define ADC_CHANNEL_MAX     12
+
+typedef struct adc_ctx {
+    uint32_t *channel_data;
+    void *adc_lli;
+    void *llibuf;
+    int lli_flag;
+    uint32_t chan_init_table;
+    uint32_t data_size;
+}hosal_adc_ctx_t;
+
+static hosal_adc_dev_t *pgdevice;
+
+void adc_data_update (void *p_arg, uint32_t flag)
+{
+    hosal_adc_dev_t *adc = (hosal_adc_dev_t *)p_arg;
+    hosal_adc_ctx_t *pstctx = (hosal_adc_ctx_t *)adc->priv;
+
+    if (pstctx->lli_flag == 0) {
+        pstctx->channel_data = (uint32_t *)((DMA_LLI_Ctrl_Type *)(pstctx->adc_lli))[0].destDmaAddr;
+        pstctx->lli_flag = 1;
+    } else {
+        pstctx->channel_data = (uint32_t *)((DMA_LLI_Ctrl_Type *)(pstctx->adc_lli))[1].destDmaAddr;
+        pstctx->lli_flag = 0;
+    }
+}
+
+static int adc_check_gpio_valid(GLB_GPIO_Type pin)
+{
+    int i;
+
+    GLB_GPIO_Type gpio_arr[ADC_GPIO_NUM] =
+    {
+        GLB_GPIO_PIN_4, GLB_GPIO_PIN_5, GLB_GPIO_PIN_6,
+        GLB_GPIO_PIN_11, GLB_GPIO_PIN_12, GLB_GPIO_PIN_13,
+        GLB_GPIO_PIN_16, GLB_GPIO_PIN_17, GLB_GPIO_PIN_18,
+        GLB_GPIO_PIN_19, GLB_GPIO_PIN_34, GLB_GPIO_PIN_40
+    };
+
+    for (i = 0; i < ADC_GPIO_NUM; i++) {
+        if (pin == gpio_arr[i]) {
+            return 0;
+        }
+    }
+
+    blog_error("gpio %d can not used as adc\r\n", pin);
+
+    return -1;
+}
+
+static int adc_get_channel_by_gpio(GLB_GPIO_Type pin)
+{
+    int channel = -1;
+
+    switch (pin) {
+        case GLB_GPIO_PIN_4:
+            channel = 2;
+            break;
+        case GLB_GPIO_PIN_5:
+            channel = 1;
+            break;
+        case GLB_GPIO_PIN_6:
+            channel = 4;
+            break;
+        case GLB_GPIO_PIN_11:
+            channel = 3;
+            break;
+        case GLB_GPIO_PIN_12:
+            channel = 6;
+            break;
+        case GLB_GPIO_PIN_13:
+            channel = 7;
+            break;
+        case GLB_GPIO_PIN_16:
+            channel = 8;
+            break;
+        case GLB_GPIO_PIN_17:
+            channel = 0;
+            break;
+        case GLB_GPIO_PIN_18:
+            channel = 9;
+            break;
+        case GLB_GPIO_PIN_19:
+            channel = 10;
+            break;
+        case GLB_GPIO_PIN_34:
+            channel = 11;
+            break;
+        case GLB_GPIO_PIN_40:
+            channel = 5;
+            break;
+        
+        default :
+            channel = -1;
+            break;
+    }
+
+    return channel;
+}
+
+static void adc_freq_init(hosal_adc_sample_mode_t mode, uint32_t freq)
+{
+    uint32_t div;
+    uint32_t source_freq;
+    uint32_t mode_freq;
+
+    if (mode == HOSAL_ADC_ONE_SHOT) {
+        mode_freq = ADC_CHANNEL_MAX;
+    } else {
+        mode_freq = 1;
+    }
+
+    source_freq = ADC_CLOCK_FREQ / (128 * 24 * mode_freq);
+
+    div = source_freq / freq;
+    if (((div + 1) * freq - source_freq) < (source_freq - freq * div)) {
+        div = div + 1;
+    }
+
+    if (div > 64) {
+        div = 64; 
+    }
+
+    /*adc clk can not more than 2M*/
+    /*when adc work at scan mode, adc clk can not more than 1M*/
+    blog_info("ADC freq: %ldHz. ,div:%lu\r\n", (int)(source_freq / div), div);
+
+    /* set clk */
+    GLB_PER_Clock_UnGate(GLB_AHB_CLOCK_GPIP | GLB_AHB_CLOCK_DMA_0);
+    GLB_Set_ADC_CLK(ENABLE, GLB_ADC_CLK_XCLK, div-1);
+}
+
+static void adc_dma_lli_init(DMA_LLI_Ctrl_Type *pstlli, uint32_t *buf, uint32_t data_num)
+{
+    struct DMA_Control_Reg dma_ctrl_reg={
+        .TransferSize=0,
+        .SBSize=DMA_BURST_SIZE_1,
+        .dst_min_mode=DISABLE,
+        .DBSize=DMA_BURST_SIZE_1,
+        .dst_add_mode=DISABLE,
+        .SWidth=DMA_TRNS_WIDTH_32BITS,
+        .DWidth=DMA_TRNS_WIDTH_32BITS,
+        .fix_cnt=0,
+        .SI=DMA_MINC_DISABLE,
+        .DI=DMA_MINC_ENABLE,
+        .I=1,
+    };
+    dma_ctrl_reg.TransferSize = data_num;
+
+    pstlli[0].srcDmaAddr = GPIP_BASE+GPIP_GPADC_DMA_RDATA_OFFSET;
+    pstlli[0].destDmaAddr = (uint32_t)&buf[0];
+    pstlli[0].nextLLI = (uint32_t)&pstlli[1]; 
+    pstlli[0].dmaCtrl= dma_ctrl_reg;
+
+    pstlli[1].srcDmaAddr = GPIP_BASE+GPIP_GPADC_DMA_RDATA_OFFSET;
+    pstlli[1].destDmaAddr = (uint32_t)&buf[ADC_CHANNEL_MAX];
+    pstlli[1].nextLLI = (uint32_t)&pstlli[0];
+    pstlli[1].dmaCtrl= dma_ctrl_reg;
+}
+
+static int adc_dma_init(hosal_adc_dev_t *adc, uint32_t data_num)
+{
+    DMA_LLI_Ctrl_Type *pstlli;
+    uint32_t *llibuf;
+    DMA_LLI_Cfg_Type llicfg = {
+        .dir = DMA_TRNS_P2M,
+        .srcPeriph = DMA_REQ_GPADC_RX,
+        .dstPeriph = DMA_REQ_NONE,
+    };
+    
+    hosal_adc_ctx_t *pstctx = (hosal_adc_ctx_t *)adc->priv;
+
+    if (data_num < 1) {
+        blog_error("illegal para. \r\n");
+        return -1;
+    }
+
+    adc->dma_chan = hosal_dma_chan_request(0);
+
+    pstlli = pvPortMalloc(sizeof(DMA_LLI_Ctrl_Type) * 2);
+    if (NULL == pstlli) {
+        blog_error("malloc lli failed. \r\n");
+        return -1;
+    }
+
+    llibuf = pvPortMalloc(sizeof(uint32_t) * data_num * 2);
+    if (NULL == llibuf) {
+        blog_error("malloc lli buf failed. \r\n");
+        return -1;
+    }
+
+    adc_dma_lli_init(pstlli, llibuf, data_num);
+    DMA_LLI_Init(DMA0_ID, adc->dma_chan, &llicfg);
+    DMA_LLI_Update(DMA0_ID, adc->dma_chan, (uint32_t)&(pstlli[0]));
+
+    pstctx->llibuf = llibuf;
+    pstctx->adc_lli = pstlli;
+    pstctx->lli_flag = 0;
+    pstctx->chan_init_table = 0;
+    pstctx->channel_data = NULL;
+    pstctx->data_size = data_num;
+
+    hosal_dma_irq_callback_set(adc->dma_chan, adc_data_update, adc);
+
+    return 0;
+}
+
+//mode = 0, for normal adc. freq 20HZ~1302HZ
+static void adc_init(hosal_adc_dev_t *adc)
+{
+    int i, chan;
+    uint8_t channel_table[ADC_CHANNEL_MAX] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
+    
+    hosal_adc_sample_mode_t mode = adc->config.mode;
+    GLB_GPIO_Type pin = adc->config.pin;
+
+    ADC_CFG_Type adccfg;
+    ADC_Chan_Type pos_chlist_single[ADC_CHANNEL_MAX];
+    ADC_Chan_Type neg_chlist_single[ADC_CHANNEL_MAX];
+    ADC_FIFO_Cfg_Type adc_fifo_cfg = {
+        /*dma request will happend when fifo count up to fifoThreshold.*/
+        .fifoThreshold = ADC_FIFO_THRESHOLD_1,
+        .dmaEn = ENABLE,
+    };
+
+    adccfg.v18Sel=ADC_V18_SEL_1P82V;
+    adccfg.v11Sel=ADC_V11_SEL_1P1V;
+    adccfg.clkDiv=ADC_CLK_DIV_24;
+    /* one shot mode */
+    if (mode == HOSAL_ADC_ONE_SHOT) {
+        adccfg.gain1=ADC_PGA_GAIN_NONE;
+        adccfg.gain2=ADC_PGA_GAIN_NONE;
+        adccfg.chopMode=ADC_CHOP_MOD_AZ_PGA_ON;
+    } else {
+        adccfg.gain1=ADC_PGA_GAIN_1;
+        adccfg.gain2=ADC_PGA_GAIN_1;
+        adccfg.chopMode=ADC_CHOP_MOD_AZ_PGA_ON;
+    }
+    adccfg.biasSel=ADC_BIAS_SEL_MAIN_BANDGAP;
+    adccfg.vcm=ADC_PGA_VCM_1V;
+    adccfg.vref=ADC_VREF_3P2V;
+    adccfg.inputMode=ADC_INPUT_SINGLE_END;
+    adccfg.resWidth = ADC_DATA_WIDTH_16_WITH_128_AVERAGE;
+    adccfg.offsetCalibEn=0;
+    adccfg.offsetCalibVal=0;
+
+    ADC_Disable();
+    ADC_Enable();
+    ADC_Reset();
+
+    ADC_Init(&adccfg);
+ 
+    if (mode == HOSAL_ADC_ONE_SHOT) {
+        for (i = 0; i < ADC_CHANNEL_MAX; i++) {
+            pos_chlist_single[i] = channel_table[i];;
+            neg_chlist_single[i] = ADC_CHAN_GND;
+        }
+
+        ADC_Scan_Channel_Config(pos_chlist_single, neg_chlist_single, ADC_CHANNEL_MAX, ENABLE);
+    } 
+    else {
+        chan = adc_get_channel_by_gpio(pin);
+        ADC_Channel_Config(chan, ADC_CHAN_GND, ENABLE);
+        ADC_Mic_Init(NULL);
+    }
+
+    ADC_FIFO_Cfg(&adc_fifo_cfg);
+}
+
+static void adc_dma_start(hosal_dma_chan_t chan)
+{
+    ADC_Start();
+
+    /* refresh cache */
+    L1C_DCache_Clean_Invalid_All();
+    hosal_dma_chan_start(chan);
+}
+
+static int adc_parse_data(uint32_t *parr, int data_size, int channel)
+{
+    int i;
+    int32_t data;
+
+    for (i = 0; i < data_size; i++) {
+        if (parr[i] >> 21 == channel) {
+            data = parr[i] & 0xFFFF;
+            data = (data * 3200) >> 16;
+
+            return data;
+        }
+    }   
+    blog_error("error!\r\n");
+    return -1;
+}
+
+int hosal_adc_init(hosal_adc_dev_t *adc)
+{
+    int res = -1;
+    int freq;
+    GLB_GPIO_Type pin;
+    hosal_adc_ctx_t *pstctx;
+
+    if (NULL == adc) {
+        blog_error("parameter is error!\r\n");
+        return -1;
+    }
+
+    freq = adc->config.sampling_freq;
+    pin = (GLB_GPIO_Type)adc->config.pin;
+
+    /* check adc pin*/
+    res = adc_check_gpio_valid(pin);
+    if (res) {
+        blog_error("pin is error!\r\n");
+        return -1;
+    }
+    
+    pstctx = (hosal_adc_ctx_t *)pvPortMalloc(sizeof(hosal_adc_ctx_t));
+    if (NULL == pstctx) {
+        blog_error("not have enough memory!\r\n");
+        return -1;
+    }
+
+    memset(pstctx, 0, sizeof(hosal_adc_ctx_t));
+    adc->priv = pstctx;
+
+    if (adc->config.mode == HOSAL_ADC_ONE_SHOT) {
+        if (freq < 20 || freq > 1250) {
+            blog_error("illegal freq. for mode0, freq 20HZ ~ 1250HZ \r\n");
+            return -1;
+        }
+        /* init gpio */ 
+        GLB_GPIO_Func_Init(GPIO_FUN_ANALOG, &pin, 1);
+
+        /* init freq */
+        adc_freq_init(adc->config.mode, freq);
+        adc_init(adc);
+        adc_dma_init(adc, ADC_CHANNEL_MAX);
+        adc_dma_start(adc->dma_chan);
+    } else {
+        blog_error("not support continue mode!\r\n");
+        return -1;
+    }
+    
+    pgdevice = adc;
+
+    return 0;
+}
+
+int hosal_adc_add_channel(hosal_adc_dev_t *adc, uint32_t channel)
+{
+    hosal_adc_ctx_t *pstctx = (hosal_adc_ctx_t *)adc->priv;
+
+    if (NULL == adc) {
+        blog_error("parameter is error!\r\n");
+        return -1;
+    }
+
+    if (channel > 11) {
+        blog_error("channel is error!");
+        return -1;
+    }
+    pstctx->chan_init_table |= 1 << channel;
+
+    return 0;
+}
+
+int hosal_adc_remove_channel(hosal_adc_dev_t *adc, uint32_t channel)
+{
+    hosal_adc_ctx_t *pstctx = (hosal_adc_ctx_t *)adc->priv;
+
+    if (NULL == adc) {
+        blog_error("parameter is error!\r\n");
+        return -1;
+    }
+
+    if (channel > 11) {
+        blog_error("channel is error!\r\n");
+        return -1;
+    }
+
+    pstctx->chan_init_table &= ~(1 << channel);
+
+    return 0;
+}
+
+hosal_adc_dev_t *hosal_adc_device_get(void)
+{
+    if (NULL == pgdevice) {
+        blog_error("please init adc first!\r\n");
+        return NULL;
+    }
+
+    return pgdevice;
+}
+
+int hosal_adc_value_get(hosal_adc_dev_t *adc, uint32_t channel, uint32_t timeout)
+{
+    int val = -1;
+    hosal_adc_ctx_t *pstctx = (hosal_adc_ctx_t *)adc->priv;
+ 
+    if (NULL == adc) {
+        blog_error("parameter is error!\r\n");
+        return -1;
+    }
+    
+    if (channel > 11) {
+        blog_error("channel is error!\r\n");
+        return -1;
+    }
+    
+    if (((1 << channel) & pstctx->chan_init_table) == 0) {
+        blog_error("channel = %d  not init as adc \r\n", channel);
+        return -1;
+    }
+    
+    if (pstctx->channel_data == NULL) {
+        blog_error("adc sampling not finish. \r\n");
+        return -1;
+    }
+
+    /* refresh cache */
+    L1C_DCache_Invalid_By_Addr(pstctx->channel_data, sizeof(uint32_t)*ADC_CHANNEL_MAX);
+    while ((val = adc_parse_data(pstctx->channel_data, ADC_CHANNEL_MAX, channel)) == -1) {
+        if (timeout-- == 0) {
+            return -1;
+        }
+        vTaskDelay(1);
+    }
+    
+    return val;
+}
+
+int hosal_adc_tsen_value_get(hosal_adc_dev_t *adc)
+{
+    blog_error("not support now!\r\n"); 
+    return -1;
+}
+
+int hosal_adc_sample_cb_reg(hosal_adc_dev_t *adc, hosal_adc_cb_t cb)
+{
+    blog_error("not support now!\r\n");
+    return -1;
+}
+
+int hosal_adc_start(hosal_adc_dev_t *adc, void *data, uint32_t size)
+{
+    blog_error("not support now!\r\n");
+    return -1;
+}
+
+int hosal_adc_stop(hosal_adc_dev_t *adc)
+{
+    return 0; 
+}
+
+int hosal_adc_finalize(hosal_adc_dev_t *adc)
+{
+    hosal_adc_ctx_t *pstctx = (hosal_adc_ctx_t *)adc->priv;
+
+    if (NULL == adc) {
+        blog_error("parm error!\r\n");
+        return -1;
+    }
+
+    vPortFree(pstctx->llibuf);
+    vPortFree(pstctx->adc_lli);
+    vPortFree(pstctx);
+    ADC_Stop();
+    hosal_dma_chan_stop(adc->dma_chan);
+    hosal_dma_chan_release(adc->dma_chan);
+
+    return 0;
+}
+

+ 314 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/hosal_dma.c

@@ -0,0 +1,314 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+//FIXME no BL808/BL606p header file including is Allowed here
+#ifdef BL808
+#include <bl808.h>
+#include <bl808_dma.h>
+#elif defined(BL606P)
+#include <bl606p_dma.h>
+#else
+#error "Use CHIP BL808/BL606P for this module"
+#endif
+
+#include <bl_irq.h>
+#include <blog.h>
+#include <hosal_dma.h>
+
+static hosal_dma_dev_t *gp_hosal_dma_dev = NULL;
+
+static void __dma_irq_process(void *p_arg)
+{
+    int ch;
+    uint32_t intclr;
+    uint32_t tmpval;
+    uint32_t interr_val;
+    int tc_flag, interr_flag;
+    /* Get DMA register */
+    uint32_t DMAChs = DMA0_BASE;
+    hosal_dma_dev_t *dma_dev = (hosal_dma_dev_t *)gp_hosal_dma_dev;
+    hosal_dma_irq_t pfn;
+    void *parg;
+
+    if (!dma_dev)
+        return;
+
+    tmpval = BL_RD_REG(DMAChs, DMA_INTTCSTATUS);
+    interr_val = BL_RD_REG(DMAChs, DMA_INTERRORSTATUS);
+
+    for (ch = 0; ch < dma_dev->max_chans; ch++) {
+        tc_flag = BL_GET_REG_BITS_VAL(tmpval, DMA_INTTCSTATUS) & (1 << ch);
+        interr_flag = BL_GET_REG_BITS_VAL(interr_val, DMA_INTERRORSTATUS) & (1 << ch);
+
+        if((tc_flag != 0) || (interr_flag != 0)) {
+            if (tc_flag != 0) {
+                /* tc int, clear interrupt */
+                tmpval = BL_RD_REG(DMAChs, DMA_INTTCCLEAR);
+                intclr = BL_GET_REG_BITS_VAL(tmpval, DMA_INTTCCLEAR);
+                intclr |= (1 << ch);
+                tmpval = BL_SET_REG_BITS_VAL(tmpval, DMA_INTTCCLEAR, intclr);
+                BL_WR_REG(DMAChs, DMA_INTTCCLEAR, tmpval);
+
+                pfn = gp_hosal_dma_dev->used_chan[ch].callback;
+                parg = gp_hosal_dma_dev->used_chan[ch].p_arg;
+                if (pfn) {
+                	pfn(parg, HOSAL_DMA_INT_TRANS_COMPLETE);
+                }
+            }
+
+            if (interr_flag != 0) {
+                /* int error, clear interrupt */
+                tmpval = BL_RD_REG(DMAChs, DMA_INTERRCLR);
+                intclr = BL_GET_REG_BITS_VAL(tmpval, DMA_INTERRCLR);
+                intclr |= (1 << ch);
+                tmpval = BL_SET_REG_BITS_VAL(tmpval, DMA_INTERRCLR, intclr);
+                BL_WR_REG(DMAChs, DMA_INTERRCLR, tmpval);
+
+                pfn = gp_hosal_dma_dev->used_chan[ch].callback;
+                parg = gp_hosal_dma_dev->used_chan[ch].p_arg;
+                if (pfn) {
+                	pfn(parg, HOSAL_DMA_INT_TRANS_ERROR);
+                }
+            }
+        }
+    }
+}
+
+static int __dma_int_clear(int ch)
+{
+    uint32_t tmpVal;
+    uint32_t intClr;
+    /* Get DMA register */
+    uint32_t DMAChs = DMA0_BASE;
+
+    tmpVal = BL_RD_REG(DMAChs, DMA_INTTCSTATUS);
+    if((BL_GET_REG_BITS_VAL(tmpVal, DMA_INTTCSTATUS) & (1 << ch)) != 0) {
+        /* Clear interrupt */
+        tmpVal = BL_RD_REG(DMAChs, DMA_INTTCCLEAR);
+        intClr = BL_GET_REG_BITS_VAL(tmpVal, DMA_INTTCCLEAR);
+        intClr |= (1 << ch);
+        tmpVal = BL_SET_REG_BITS_VAL(tmpVal, DMA_INTTCCLEAR, intClr);
+        BL_WR_REG(DMAChs, DMA_INTTCCLEAR, tmpVal);
+    }
+
+    tmpVal = BL_RD_REG(DMAChs, DMA_INTERRORSTATUS);
+    if((BL_GET_REG_BITS_VAL(tmpVal, DMA_INTERRORSTATUS) & (1 << ch)) != 0) {
+        /*Clear interrupt */
+        tmpVal = BL_RD_REG(DMAChs, DMA_INTERRCLR);
+        intClr = BL_GET_REG_BITS_VAL(tmpVal, DMA_INTERRCLR);
+        intClr |= (1 << ch);
+        tmpVal = BL_SET_REG_BITS_VAL(tmpVal, DMA_INTERRCLR, intClr);
+        BL_WR_REG(DMAChs, DMA_INTERRCLR, tmpVal);
+    }
+
+    return 0;
+}
+
+/**
+ * @brief Initialises a DMA interface
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int hosal_dma_init(void)
+{
+    int i;
+    if (gp_hosal_dma_dev) {
+        return 0;
+    }
+
+    gp_hosal_dma_dev = calloc(sizeof(hosal_dma_dev_t), 1);
+    if (gp_hosal_dma_dev == NULL) {
+        blog_error("no memory !!!\r\n");
+        return -1;
+    }
+
+    gp_hosal_dma_dev->max_chans = DMA_CH_MAX;
+    gp_hosal_dma_dev->used_chan = calloc(sizeof(struct hosal_dma_chan) * DMA_CH_MAX, 1);
+    if (gp_hosal_dma_dev->used_chan == NULL) {
+        blog_error("no memory !!!\r\n");
+        free(gp_hosal_dma_dev);
+        gp_hosal_dma_dev = NULL;
+        return -1;
+    }
+    DMA_Enable(DMA0_ID);
+    for (i = 0; i < gp_hosal_dma_dev->max_chans; i++) {
+        DMA_Channel_Disable(DMA0_ID, i);
+        DMA_IntMask(DMA0_ID, i, DMA_INT_ALL, MASK);
+    }
+    bl_irq_register(DMA0_ALL_IRQn, __dma_irq_process);
+    bl_irq_enable(DMA0_ALL_IRQn);
+    return 0;
+}
+
+/**
+ * @brief Request a DMA channel
+ *
+ * @return  < 0 : an error occurred with any step, otherwise is DMA channel number
+ */
+hosal_dma_chan_t hosal_dma_chan_request(int flag)
+{
+    int i;
+
+    (void)flag;
+
+    if (!gp_hosal_dma_dev) {
+        blog_error("please hosal_dma_init !\r\n");
+        return -1;
+    }
+
+    for (i = 0; i < gp_hosal_dma_dev->max_chans; i++) {
+        if (!gp_hosal_dma_dev->used_chan[i].used) {
+            gp_hosal_dma_dev->used_chan[i].used = 1;
+            return i;
+        }
+    }
+    return -1;
+}
+
+/**
+ * @brief Release a DMA channel
+ *
+ * @param[in]  chan  DMA channel number
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int hosal_dma_chan_release(hosal_dma_chan_t chan)
+{
+    if (!gp_hosal_dma_dev) {
+        blog_error("please hosal_dma_init !\r\n");
+        return -1;
+    }
+
+    if (chan > gp_hosal_dma_dev->max_chans) {
+        return -1;
+    }
+
+    hosal_dma_chan_stop(chan);
+    gp_hosal_dma_dev->used_chan[chan].used = 0;
+    gp_hosal_dma_dev->used_chan[chan].callback = NULL;
+    DMA_IntMask(DMA0_ID, chan, DMA_INT_TCOMPLETED, MASK);
+    DMA_IntMask(DMA0_ID, chan, DMA_INT_ERR, MASK);
+    return 0;
+}
+
+/**
+ * @brief DMA channel start
+ *
+ * @param[in]  chan  DMA channel number
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int hosal_dma_chan_start(hosal_dma_chan_t chan)
+{
+    if (!gp_hosal_dma_dev) {
+        blog_error("please hosal_dma_init !\r\n");
+        return -1;
+    }
+
+    if (chan > gp_hosal_dma_dev->max_chans) {
+        return -1;
+    }
+
+    DMA_Channel_Enable(DMA0_ID, chan);
+    return 0;
+}
+
+/**
+ * @brief DMA channel stop
+ *
+ * @param[in]  chan  DMA channel number
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int hosal_dma_chan_stop(hosal_dma_chan_t chan)
+{
+    if (!gp_hosal_dma_dev) {
+        blog_error("please hosal_dma_init !\r\n");
+        return -1;
+    }
+
+    if (chan > gp_hosal_dma_dev->max_chans) {
+        return -1;
+    }
+
+    __dma_int_clear(chan);
+    DMA_Channel_Disable(DMA0_ID, chan);
+    return 0;
+}
+
+/**
+ * @brief DMA irq callback set
+ *
+ * @param[in] chan : DMA channel number
+ * @param[in] pfn : callback function
+ * @param[in] arg : callback function parameter
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int hosal_dma_irq_callback_set(hosal_dma_chan_t chan, hosal_dma_irq_t pfn, void *p_arg)
+{
+    if (!gp_hosal_dma_dev) {
+        blog_error("please hosal_dma_init !\r\n");
+        return -1;
+    }
+
+    if (chan > gp_hosal_dma_dev->max_chans) {
+        return -1;
+    }
+
+    gp_hosal_dma_dev->used_chan[chan].callback = pfn;
+    gp_hosal_dma_dev->used_chan[chan].p_arg = p_arg;
+    DMA_IntMask(DMA0_ID, chan, DMA_INT_TCOMPLETED, UNMASK);
+    DMA_IntMask(DMA0_ID, chan, DMA_INT_ERR, UNMASK);
+    return 0;
+}
+
+/**
+ * @brief Deinitialises a DMA interface
+ *
+ * @param[in]  DMA the interface which should be deinitialised
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int hosal_dma_finalize(void)
+{
+    if (!gp_hosal_dma_dev) {
+        blog_error("please hosal_dma_init !\r\n");
+        return -1;
+    }
+
+    DMA_Disable(DMA0_ID);
+    bl_irq_disable(DMA0_ALL_IRQn);
+
+    free(gp_hosal_dma_dev);
+    gp_hosal_dma_dev = NULL;
+    return 0;
+}
+

+ 267 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/hosal_pwm.c

@@ -0,0 +1,267 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+//FIXME no BL808/BL606p header file including is Allowed here
+#ifdef BL808
+#include <bl808_pwm.h>
+#include <bl808_glb.h>
+#elif defined(BL606P)
+#include <bl606p_pwm.h>
+#include <bl606p_glb.h>
+#else
+#error "Use CHIP BL808/BL606P for this module"
+#endif
+
+#include "hosal_pwm.h"
+#include "blog.h"
+
+
+#define PWM_CHANNAL_MAX 4
+#define PWM_XCLK_CLK 40000000
+#define PWM_DUTY_MAX 10000
+
+
+/**
+ * Initialises a PWM pin
+ *
+ *
+ * @param[in]  pwm  the PWM device
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int hosal_pwm_init(hosal_pwm_dev_t *pwm)
+{
+    GLB_GPIO_Cfg_Type gpioCfg = {
+        .gpioPin = 0,
+        .gpioFun = GPIO_FUN_PWM0, //GPIO_FUN_PWM1
+        .gpioMode = GPIO_MODE_OUTPUT,
+        .pullType = GPIO_PULL_DOWN,
+        .drive = 0,
+        .smtCtrl = 1,
+    };
+
+    PWMx_CFG_Type pwmxCfg = {
+        .clk = PWM_CLK_XCLK,
+        .stopMode = PWM_STOP_GRACEFUL,
+        .clkDiv = 1,
+        .period = 0,
+        .intPulseCnt = 0,
+        .extPol = PWM_BREAK_Polarity_HIGH,
+        .stpRept = DISABLE,
+        .adcSrc = PWM_TRIGADC_SOURCE_NONE,
+    };
+
+    PWM_CHx_CFG_Type chxCfg = {
+        .modP = PWM_MODE_ENABLE,
+        .modN = PWM_MODE_ENABLE,
+        .polP = PWM_POL_ACTIVE_HIGH,
+        .polN = PWM_POL_ACTIVE_HIGH,
+        .idlP = PWM_IDLE_STATE_INACTIVE,
+        .idlN = PWM_IDLE_STATE_INACTIVE,
+        .brkP = PWM_BREAK_STATE_INACTIVE,
+        .brkN = PWM_BREAK_STATE_INACTIVE,
+        .thresholdL = 0,
+        .thresholdH = 0,
+        .dtg = 0,
+    };
+
+    if (NULL == pwm || (pwm->port != PWM0_ID && pwm->port != PWM1_ID)) {
+        blog_error("arg error.\r\n");
+        return -1;
+    }
+
+    gpioCfg.gpioPin = pwm->config.pin;
+    if (pwm->port == PWM0_ID)
+       gpioCfg.gpioFun = GPIO_FUN_PWM0;
+    else if (pwm->port == PWM1_ID)
+       gpioCfg.gpioFun = GPIO_FUN_PWM1;
+    GLB_GPIO_Init(&gpioCfg);
+
+    PWMx_Disable(pwm->port);
+    pwmxCfg.period = PWM_XCLK_CLK/pwm->config.freq;
+    PWMx_Init(pwm->port, &pwmxCfg);
+    chxCfg.thresholdL = 0;
+    chxCfg.thresholdH = (PWM_XCLK_CLK/pwm->config.freq)*pwm->config.duty_cycle/PWM_DUTY_MAX;
+    PWM_Channelx_Init(pwm->port, pwm->config.pin%PWM_CHANNAL_MAX, &chxCfg);
+    PWM_Channelx_Pwm_Mode_Set(pwm->port, pwm->config.pin%PWM_CHANNAL_MAX, PWM_MODE_DISABLE, PWM_MODE_DISABLE);
+    PWMx_Enable(pwm->port);
+    return 0;
+}
+
+/**
+ * Starts Pulse-Width Modulation signal output on a PWM pin
+ *
+ * @param[in]  pwm  the PWM device
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int hosal_pwm_start(hosal_pwm_dev_t *pwm)
+{
+    if (NULL == pwm || (pwm->port != PWM0_ID && pwm->port != PWM1_ID)) {
+        blog_error("arg error.\r\n");
+        return -1;
+    }
+
+    PWM_Channelx_Pwm_Mode_Set(pwm->port, pwm->config.pin%PWM_CHANNAL_MAX, PWM_MODE_ENABLE, PWM_MODE_ENABLE);
+    return 0;
+}
+
+/**
+ * Stops output on a PWM pin
+ *
+ * @param[in]  pwm  the PWM device, para  set duty and  freq
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int hosal_pwm_para_chg(hosal_pwm_dev_t *pwm, hosal_pwm_config_t para)
+{
+    PWM_CHx_CFG_Type chxCfg = {
+        .modP = PWM_MODE_ENABLE,
+        .modN = PWM_MODE_ENABLE,
+        .polP = PWM_POL_ACTIVE_HIGH,
+        .polN = PWM_POL_ACTIVE_HIGH,
+        .idlP = PWM_IDLE_STATE_INACTIVE,
+        .idlN = PWM_IDLE_STATE_INACTIVE,
+        .brkP = PWM_BREAK_STATE_INACTIVE,
+        .brkN = PWM_BREAK_STATE_INACTIVE,
+        .thresholdL = 0,
+        .thresholdH = 0,
+        .dtg = 0,
+    };
+
+    if (NULL == pwm || (pwm->port != PWM0_ID && pwm->port != PWM1_ID)) {
+        blog_error("arg error.\r\n");
+        return -1;
+    }
+
+    chxCfg.thresholdL = 0;
+    chxCfg.thresholdH = (PWM_XCLK_CLK/para.freq)*para.duty_cycle/PWM_DUTY_MAX;
+    PWM_Channelx_Init(pwm->port, pwm->config.pin%PWM_CHANNAL_MAX, &chxCfg);
+    return 0;
+}
+
+/**
+ * set pwm freq
+ *
+ *@param[in] id pwm channel
+ *@param[in] freq pwm freq
+ *
+ *@return 0 : on success -1 : fail
+ */
+int hosal_pwm_freq_set(hosal_pwm_dev_t *pwm, uint32_t freq)
+{
+    return -1;
+}
+
+int hosal_pwm_freq_get(hosal_pwm_dev_t *pwm,  uint32_t *p_freq)
+{
+    if (NULL == pwm || (pwm->port != PWM0_ID && pwm->port != PWM1_ID)) {
+        blog_error("arg error.\r\n");
+        return -1;
+    }
+
+    *p_freq = pwm->config.freq;
+    return 0;
+}
+
+int hosal_pwm_duty_set(hosal_pwm_dev_t *pwm, uint32_t duty)
+{
+    PWM_CHx_CFG_Type chxCfg = {
+        .modP = PWM_MODE_ENABLE,
+        .modN = PWM_MODE_ENABLE,
+        .polP = PWM_POL_ACTIVE_HIGH,
+        .polN = PWM_POL_ACTIVE_HIGH,
+        .idlP = PWM_IDLE_STATE_INACTIVE,
+        .idlN = PWM_IDLE_STATE_INACTIVE,
+        .brkP = PWM_BREAK_STATE_INACTIVE,
+        .brkN = PWM_BREAK_STATE_INACTIVE,
+        .thresholdL = 0,
+        .thresholdH = 0,
+        .dtg = 0,
+    };
+
+    if (NULL == pwm || (pwm->port != PWM0_ID && pwm->port != PWM1_ID)) {
+        blog_error("arg error.\r\n");
+        return -1;
+    }
+
+    chxCfg.thresholdL = 0;
+    chxCfg.thresholdH = (PWM_XCLK_CLK/pwm->config.freq)*duty/PWM_DUTY_MAX;
+    PWM_Channelx_Init(pwm->port, pwm->config.pin%PWM_CHANNAL_MAX, &chxCfg);
+    return 0;
+}
+
+int hosal_pwm_duty_get(hosal_pwm_dev_t *pwm, uint32_t *p_duty)
+{
+    if (NULL == pwm || (pwm->port != PWM0_ID && pwm->port != PWM1_ID)) {
+        blog_error("arg error.\r\n");
+        return -1;
+    }
+
+    *p_duty = pwm->config.duty_cycle;
+    return 0;
+}
+/**
+ * Stops output on a PWM pin
+ *
+ * @param[in]  pwm  the PWM device
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int hosal_pwm_stop(hosal_pwm_dev_t *pwm)
+{
+    if (NULL == pwm || (pwm->port != PWM0_ID && pwm->port != PWM1_ID)) {
+        blog_error("arg error.\r\n");
+        return -1;
+    }
+
+    PWM_Channelx_Pwm_Mode_Set(pwm->port, pwm->config.pin%PWM_CHANNAL_MAX, PWM_MODE_DISABLE, PWM_MODE_DISABLE);
+    return 0;
+}
+
+/**
+ * De-initialises an PWM interface, Turns off an PWM hardware interface
+ *
+ * @param[in]  pwm  the interface which should be de-initialised
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int hosal_pwm_finalize(hosal_pwm_dev_t *pwm)
+{
+    if (NULL == pwm || (pwm->port != PWM0_ID && pwm->port != PWM1_ID)) {
+        blog_error("arg error.\r\n");
+        return -1;
+    }
+
+    PWMx_Disable(pwm->port);
+    return 0;
+}
+
+

+ 275 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/hosal_spi.c

@@ -0,0 +1,275 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+//FIXME no BL808/BL606p header file including is Allowed here
+#ifdef BL808
+#include <bl808_spi.h>
+#include <bl808_glb.h>
+#elif defined(BL606P)
+#include <bl606p_spi.h>
+#include <bl606p_glb.h>
+#else
+#error "Use CHIP BL808/BL606P for this module"
+#endif
+
+#include "bl808_glb_gpio.h"
+#include "hosal_spi.h"
+#include "blog.h"
+
+static void spi_basic_init(hosal_spi_dev_t *arg)
+{
+    hosal_spi_dev_t *hw_arg = arg;
+    SPI_CFG_Type spicfg;
+    SPI_FifoCfg_Type fifocfg;
+    SPI_ID_Type spi_id;
+
+    spi_id = hw_arg->port;
+
+    /* clock config */
+    SPI_SetClock(spi_id, hw_arg->config.freq);
+
+    /* spi config */
+    spicfg.deglitchEnable = DISABLE;
+    spicfg.slavePin = SPI_SLAVE_PIN_4;
+    spicfg.continuousEnable = ENABLE;
+    spicfg.byteSequence = SPI_BYTE_INVERSE_BYTE0_FIRST;
+    spicfg.bitSequence = SPI_BIT_INVERSE_MSB_FIRST;
+    if (hw_arg->config.polar_phase == 0) {
+        spicfg.clkPhaseInv = SPI_CLK_PHASE_INVERSE_0;
+        spicfg.clkPolarity = SPI_CLK_POLARITY_LOW;
+    } else if (hw_arg->config.polar_phase == 1) {
+        spicfg.clkPhaseInv = SPI_CLK_PHASE_INVERSE_1;
+        spicfg.clkPolarity = SPI_CLK_POLARITY_LOW;
+    } else if (hw_arg->config.polar_phase == 2) {
+        spicfg.clkPhaseInv = SPI_CLK_PHASE_INVERSE_0;
+        spicfg.clkPolarity = SPI_CLK_POLARITY_HIGH;
+    } else if (hw_arg->config.polar_phase == 3) {
+        spicfg.clkPhaseInv = SPI_CLK_PHASE_INVERSE_1;
+        spicfg.clkPolarity = SPI_CLK_POLARITY_HIGH;
+    } else {
+        blog_error("node support polar_phase \r\n");
+    }
+    spicfg.frameSize = SPI_FRAME_SIZE_8;
+    SPI_Init(spi_id, &spicfg);
+
+    if (hw_arg->config.mode == 0) {
+        SPI_Disable(spi_id, SPI_WORK_MODE_MASTER);
+    } else {
+        SPI_Disable(spi_id, SPI_WORK_MODE_SLAVE);
+    }
+    SPI_IntMask(spi_id, SPI_INT_ALL, MASK);
+
+    /* fifo */
+    fifocfg.txFifoThreshold = 1;
+    fifocfg.rxFifoThreshold = 1;
+    if (hw_arg->config.dma_enable) {
+        fifocfg.txFifoDmaEnable = ENABLE;
+        fifocfg.rxFifoDmaEnable = ENABLE;
+        SPI_FifoConfig(spi_id,&fifocfg);
+    } else {
+        fifocfg.txFifoDmaEnable = DISABLE;
+        fifocfg.rxFifoDmaEnable = DISABLE;
+        SPI_FifoConfig(spi_id,&fifocfg);
+        blog_info("spi no dma mode\r\n");
+    }
+}
+
+static int hosal_spi_trans(hosal_spi_dev_t *spi, uint8_t *tx_data, uint8_t *rx_data, uint32_t length, uint32_t timeout)
+{
+    int ret = -1;
+
+    /* Clear tx and rx fifo */
+    SPI_ClrTxFifo(spi->port);
+    SPI_ClrRxFifo(spi->port);
+
+    if (spi->config.mode == 0) {
+        SPI_Enable(spi->port, SPI_WORK_MODE_MASTER);
+    } else {
+        SPI_Enable(spi->port, SPI_WORK_MODE_SLAVE);
+    }
+
+    if (tx_data && rx_data)
+        ret = SPI_SendRecvData(spi->port, tx_data, rx_data, length, SPI_TIMEOUT_DISABLE);
+    else if (tx_data)
+        ret = SPI_SendData(spi->port, tx_data, length, SPI_TIMEOUT_DISABLE);
+    else if (rx_data)
+        ret = SPI_ReceiveData(spi->port, rx_data, length, SPI_TIMEOUT_DISABLE);
+
+    if (spi->config.mode == 0) {
+        SPI_Disable(spi->port, SPI_WORK_MODE_MASTER);
+    } else {
+        SPI_Disable(spi->port, SPI_WORK_MODE_SLAVE);
+    }
+    return ret;
+}
+
+static void hosal_spi_gpio_init(hosal_spi_dev_t *arg)
+{
+    if (!arg) {
+        blog_error("arg err.\r\n");
+        return;
+    }
+
+    GLB_GPIO_Type gpiopins[3];
+    gpiopins[0] = arg->config.pin_clk;
+    gpiopins[1] = arg->config.pin_mosi;
+    gpiopins[2] = arg->config.pin_miso;
+    GLB_GPIO_Func_Init(GPIO_FUN_SPI0, gpiopins, sizeof(gpiopins)/sizeof(gpiopins[0]));
+
+    if (arg->config.mode == 0) {
+        if(arg->port == SPI0_ID) {       
+            GLB_Set_MCU_SPI_0_ACT_MOD_Sel(GLB_SPI_PAD_ACT_AS_MASTER);  
+        } else {      
+            GLB_Set_DSP_SPI_0_ACT_MOD_Sel(GLB_SPI_PAD_ACT_AS_MASTER);  
+        }
+    } else {
+        if(arg->port == SPI0_ID) {       
+            GLB_Set_MCU_SPI_0_ACT_MOD_Sel(GLB_SPI_PAD_ACT_AS_SLAVE);  
+        } else {      
+            GLB_Set_DSP_SPI_0_ACT_MOD_Sel(GLB_SPI_PAD_ACT_AS_SLAVE);  
+        }
+    }
+
+    return;
+}
+
+int hosal_spi_init(hosal_spi_dev_t *spi)
+{
+    hosal_spi_dev_t *dev = spi;
+    if (NULL == spi ) {
+        blog_error("arg err.\r\n");
+    }
+
+    hosal_spi_gpio_init(dev);
+    spi_basic_init(dev);
+    if (dev->config.dma_enable) {
+        blog_error("unsupport.\r\n");
+        return -1;
+    }
+    return 0;
+}
+
+int hosal_spi_set_cs(uint8_t pin, uint8_t value)
+{
+    GLB_GPIO_Cfg_Type cfg;
+    cfg.gpioPin = pin;
+    cfg.gpioFun = GPIO_FUN_GPIO;
+    cfg.gpioMode = GPIO_MODE_OUTPUT;
+    cfg.pullType = GPIO_PULL_UP;
+    cfg.drive = 0;
+    cfg.smtCtrl = 1;
+
+    if (GLB_GPIO_Get_Fun(pin) != GPIO_FUN_GPIO)
+        GLB_GPIO_Init(&cfg);
+    GLB_GPIO_Write(pin, value);
+    return 0;
+}
+
+int hosal_spi_irq_callback_set(hosal_spi_dev_t *spi, hosal_spi_irq_t pfn, void *p_arg)
+{
+    if (NULL == spi ) {
+        blog_error("not init.\r\n");
+        return -1;
+    }
+
+    spi->cb = pfn;
+    spi->p_arg = p_arg;
+    return 0;
+}
+
+int hosal_spi_finalize(hosal_spi_dev_t *spi)
+{
+    if (NULL == spi ) {
+        blog_error("not init.\r\n");
+        return -1;
+    }
+
+    if (spi->config.dma_enable) {
+        blog_error("unsupport.\r\n");
+        return -1;
+    }
+    SPI_DeInit(spi->port);
+    return 0;
+}
+
+int hosal_spi_send(hosal_spi_dev_t *spi, const uint8_t *data, uint32_t size, uint32_t timeout)
+{
+    int ret;
+
+    if (NULL == spi || data == NULL) {
+        blog_error("not init.\r\n");
+        return -1;
+    }
+
+    if (spi->config.dma_enable) {
+        blog_error("unsupport.\r\n");
+        ret = -1;
+    } else {
+        ret = hosal_spi_trans(spi, (uint8_t *)data, NULL, size, timeout);
+    }
+    return ret;
+}
+
+int hosal_spi_recv(hosal_spi_dev_t *spi, uint8_t *data, uint16_t size, uint32_t timeout)
+{
+    int ret;
+
+    if (NULL == spi || data == NULL) {
+        blog_error("not init.\r\n");
+        return -1;
+    }
+
+    if (spi->config.dma_enable) {
+        blog_error("unsupport.\r\n");
+        ret = -1;
+    } else {
+        ret = hosal_spi_trans(spi, NULL, data, size, timeout);
+    }
+    return ret;
+}
+
+int hosal_spi_send_recv(hosal_spi_dev_t *spi, uint8_t *tx_data, uint8_t *rx_data, uint16_t size, uint32_t timeout)
+{
+    int ret;
+
+    if (NULL == spi || tx_data == NULL || rx_data == NULL) {
+        blog_error("not init.\r\n");
+        return -1;
+    }
+
+    if (spi->config.dma_enable) {
+        blog_error("unsupport.\r\n");
+        ret = -1;
+    } else {
+        ret = hosal_spi_trans(spi, tx_data, rx_data, size, timeout);
+    }
+    return ret;
+}
+

+ 557 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/hosal_uart.c

@@ -0,0 +1,557 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+//FIXME no BL808/BL606p header file including is Allowed here
+#ifdef BL808
+#include <bl808_uart.h>
+#include <bl808_glb.h>
+#elif defined(BL606P)
+#include <bl606p_uart.h>
+#include <bl606p_glb.h>
+#else
+#error "Use CHIP BL808/BL606P for this module"
+#endif
+
+
+#include "bl_uart.h"
+#include "bl_irq.h"
+#include "hosal_uart.h"
+#include "blog.h"
+
+// static const uint32_t g_uart_addr[2] = {UART0_BASE, UART1_BASE};
+
+static void gpio_init(uint8_t id, uint8_t tx_pin, uint8_t rx_pin, uint8_t cts_pin, uint8_t rts_pin)
+{
+    GLB_GPIO_Cfg_Type cfg;
+    GLB_UART_SIG_FUN_Type tx_sigfun, rx_sigfun;
+
+    cfg.drive = 1;
+    cfg.smtCtrl = 1;
+    cfg.gpioFun = 7;
+
+    cfg.gpioPin = rx_pin;
+    cfg.gpioMode = GPIO_MODE_AF;
+    cfg.pullType = GPIO_PULL_UP;
+    GLB_GPIO_Init(&cfg);
+
+    cfg.gpioPin = tx_pin;
+    cfg.gpioMode = GPIO_MODE_AF;
+    cfg.pullType = GPIO_PULL_UP;
+    GLB_GPIO_Init(&cfg);
+
+    /* select uart gpio function */
+    if (id == 0) {
+        tx_sigfun = GLB_UART_SIG_FUN_UART0_TXD;
+        rx_sigfun = GLB_UART_SIG_FUN_UART0_RXD;
+    } else {
+        tx_sigfun = GLB_UART_SIG_FUN_UART1_TXD;
+        rx_sigfun = GLB_UART_SIG_FUN_UART1_RXD;
+    }
+
+    // clk
+    //GLB_Set_UART_CLK(1, HBN_UART_CLK_160M, 0);
+
+    GLB_UART_Fun_Sel(tx_pin%12, tx_sigfun);
+    GLB_UART_Fun_Sel(rx_pin%12, rx_sigfun);
+}
+
+static void __uart_rx_irq(void *p_arg)
+{
+    hosal_uart_dev_t *uart = (hosal_uart_dev_t *)p_arg;
+    if (uart->rx_cb) {
+        uart->rx_cb(uart->p_rxarg);
+    }
+}
+
+static void __uart_tx_irq(void *p_arg)
+{
+    hosal_uart_dev_t *uart = (hosal_uart_dev_t *)p_arg;
+    if (uart->tx_cb) {
+        uart->tx_cb(uart->p_txarg);
+    }
+}
+#if 0
+static void __uart_rx_dma_irq(void *p_arg, uint32_t flag)
+{
+    hosal_uart_dev_t *uart = (hosal_uart_dev_t *)p_arg;
+
+    if (flag != HOSAL_DMA_INT_TRANS_COMPLETE) {
+    	blog_error("DMA RX TRANS ERROR\r\n");
+    }
+
+    if (uart->rxdma_cb) {
+    	uart->rxdma_cb(uart->p_rxdma_arg);
+    }
+}
+
+static void __uart_tx_dma_irq(void *p_arg, uint32_t flag)
+{
+    hosal_uart_dev_t *uart = (hosal_uart_dev_t *)p_arg;
+
+    if (flag != HOSAL_DMA_INT_TRANS_COMPLETE) {
+    	blog_error("DMA TX TRANS ERROR\r\n");
+    }
+
+    if (uart->txdma_cb) {
+    	uart->txdma_cb(uart->p_txdma_arg);
+    }
+}
+
+static int __uart_dma_txcfg(hosal_uart_dev_t *uart, hosal_uart_dma_cfg_t *dma_cfg)
+{
+	if (dma_cfg->dma_buf == NULL || dma_cfg->dma_buf_size == 0) {
+		return -1;
+	}
+	DMA_Channel_Cfg_Type txchCfg = {
+	    (uint32_t)dma_cfg->dma_buf,
+		g_uart_addr[uart->port] + UART_FIFO_WDATA_OFFSET,
+		dma_cfg->dma_buf_size,
+	    DMA_TRNS_M2P,
+		DMA_CH0,
+	    DMA_TRNS_WIDTH_8BITS,
+	    DMA_TRNS_WIDTH_8BITS,
+	    DMA_BURST_SIZE_4,
+	    DMA_BURST_SIZE_4,
+	    DMA_MINC_ENABLE,
+	    DMA_PINC_DISABLE,
+	    DMA_REQ_NONE,
+	    DMA_REQ_UART0_TX,
+	};
+    UART_FifoCfg_Type fifoCfg =
+    {
+        .txFifoDmaThreshold     = 0x10,
+        .rxFifoDmaThreshold     = 0x10,
+        .txFifoDmaEnable        = ENABLE,
+        .rxFifoDmaEnable        = DISABLE,
+    };
+
+    if (uart->dma_tx_chan >= 0) {
+    	DMA_Channel_Update_SrcMemcfg(uart->dma_tx_chan,
+    			(uint32_t)dma_cfg->dma_buf, dma_cfg->dma_buf_size);
+    	return 0;
+    }
+
+	uart->dma_tx_chan = hosal_dma_chan_request(0);
+	if (uart->dma_tx_chan < 0) {
+		blog_error("dma_tx_chan request failed !\r\n");
+		return -1;
+	}
+
+	hosal_dma_chan_stop(uart->dma_tx_chan);
+
+    /* FIFO Config*/
+	fifoCfg.rxFifoDmaEnable = (uart->dma_rx_chan < 0) ? DISABLE : ENABLE;
+    UART_FifoConfig(uart->port, &fifoCfg);
+
+	txchCfg.ch = uart->dma_tx_chan;
+	txchCfg.dstPeriph = (uart->port == 0) ? DMA_REQ_UART0_TX : DMA_REQ_UART1_TX;
+	DMA_Channel_Init(&txchCfg);
+	hosal_dma_irq_callback_set(uart->dma_tx_chan, __uart_tx_dma_irq, (void *)uart);
+
+	return 0;
+}
+
+static int __uart_dma_rxcfg(hosal_uart_dev_t *uart, hosal_uart_dma_cfg_t *dma_cfg)
+{
+	if (dma_cfg->dma_buf == NULL || dma_cfg->dma_buf_size == 0) {
+		return -1;
+	}
+
+	DMA_Channel_Cfg_Type rxchCfg = {
+		g_uart_addr[uart->port] + UART_FIFO_RDATA_OFFSET,
+		(uint32_t)dma_cfg->dma_buf,
+		dma_cfg->dma_buf_size,
+	    DMA_TRNS_P2M,
+		DMA_CH0,
+	    DMA_TRNS_WIDTH_8BITS,
+	    DMA_TRNS_WIDTH_8BITS,
+	    DMA_BURST_SIZE_16,
+	    DMA_BURST_SIZE_16,
+	    DMA_PINC_DISABLE,
+	    DMA_MINC_ENABLE,
+	    DMA_REQ_UART0_RX,
+	    DMA_REQ_NONE,
+	};
+    UART_FifoCfg_Type fifoCfg =
+    {
+        .txFifoDmaThreshold     = 0x10,
+        .rxFifoDmaThreshold     = 0x10,
+        .txFifoDmaEnable        = DISABLE,
+        .rxFifoDmaEnable        = ENABLE,
+    };
+
+    if (uart->dma_rx_chan >= 0) {
+    	DMA_Channel_Update_DstMemcfg(uart->dma_rx_chan,
+    			(uint32_t)dma_cfg->dma_buf, dma_cfg->dma_buf_size);
+    	return 0;
+    }
+
+	uart->dma_rx_chan = hosal_dma_chan_request(0);
+	if (uart->dma_rx_chan < 0) {
+		blog_error("dma_rx_chan request failed !\r\n");
+		return -1;
+	}
+
+	hosal_dma_chan_stop(uart->dma_rx_chan);
+
+    /* FIFO Config*/
+	fifoCfg.txFifoDmaEnable = (uart->dma_tx_chan < 0) ? DISABLE : ENABLE;
+    UART_FifoConfig(uart->port, &fifoCfg);
+
+	rxchCfg.ch = uart->dma_rx_chan;
+	rxchCfg.srcPeriph = (uart->port == 0) ? DMA_REQ_UART0_RX : DMA_REQ_UART1_RX;
+
+	DMA_Channel_Init(&rxchCfg);
+	hosal_dma_irq_callback_set(uart->dma_rx_chan, __uart_rx_dma_irq, (void *)uart);
+
+	return 0;
+}
+#endif
+static void __uart_config_set(hosal_uart_dev_t *uart, const hosal_uart_config_t *cfg)
+{
+    const uint8_t uart_div = 3;
+    uint8_t id = uart->port;
+
+#if 0
+    UART_CFG_Type uartCfg =
+    {
+        80*1000*1000,                                       /* UART clock */
+        2000000,                                              /* UART Baudrate */
+        UART_DATABITS_8,                                     /* UART data bits length */
+        UART_STOPBITS_1,                                     /* UART data stop bits length */
+        UART_PARITY_NONE,                                    /* UART no parity */
+        DISABLE,                                             /* Disable auto flow control */
+        DISABLE,                                             /* Disable rx input de-glitch function */
+        DISABLE,                                             /* Disable RTS output SW control mode */
+        UART_LSB_FIRST                                       /* UART each data byte is send out LSB-first */
+    };
+
+    uartCfg.baudRate = cfg->baud_rate;
+    uartCfg.dataBits = (UART_DataBits_Type)cfg->data_width;
+    uartCfg.parity = (UART_Parity_Type)cfg->parity;
+
+    if (cfg->flow_control == HOSAL_FLOW_CONTROL_CTS) {
+    	uartCfg.ctsFlowControl = 1;
+    	uartCfg.rtsSoftwareControl = 0;
+    } else if (cfg->flow_control == HOSAL_FLOW_CONTROL_RTS) {
+    	uartCfg.ctsFlowControl = 0;
+    	uartCfg.rtsSoftwareControl = 1;
+    } else if (cfg->flow_control == HOSAL_FLOW_CONTROL_CTS_RTS) {
+    	uartCfg.ctsFlowControl = 1;
+    	uartCfg.rtsSoftwareControl = 1;
+    } else {
+    	uartCfg.ctsFlowControl = 0;
+    	uartCfg.rtsSoftwareControl = 0;
+    }
+
+    //uartCfg.uartClk = (160 * 1000 * 1000) / (uart_div + 1);
+
+    /* Disable uart before config */
+    UART_Disable(id, UART_TXRX);
+
+    /* UART init */
+    UART_Init(id, &uartCfg);
+#endif
+    if (cfg->mode == HOSAL_UART_MODE_INT) {
+    	bl_uart_int_tx_notify_register(uart->port, __uart_tx_irq, uart);
+    	bl_uart_int_rx_notify_register(uart->port, __uart_rx_irq, uart);
+    	bl_uart_int_enable(uart->port);
+    	bl_uart_int_tx_disable(uart->port);
+    } else {
+    	bl_uart_int_disable(uart->port);
+    }
+
+    /* Enable uart */
+    UART_Enable(id, UART_TXRX);
+}
+
+int hosal_uart_init(hosal_uart_dev_t *uart)
+{
+    static uint8_t uart_clk_init = 0;
+    const uint8_t uart_div = 3;
+    hosal_uart_config_t *cfg = &uart->config;
+    uint8_t id;
+
+    UART_CFG_Type uartCfg =
+    {
+        80*1000*1000,                                        /* UART clock */
+        2000000,                                              /* UART Baudrate */
+        UART_DATABITS_8,                                     /* UART data bits length */
+        UART_STOPBITS_1,                                     /* UART data stop bits length */
+        UART_PARITY_NONE,                                    /* UART no parity */
+        DISABLE,                                             /* Disable auto flow control */
+        DISABLE,                                             /* Disable rx input de-glitch function */
+        DISABLE,                                             /* Disable RTS output SW control mode */
+        UART_LSB_FIRST                                       /* UART each data byte is send out LSB-first */
+    };
+    UART_FifoCfg_Type fifoCfg =
+    {
+        .txFifoDmaThreshold     = 0x10,
+        .rxFifoDmaThreshold     = 0x10,
+        .txFifoDmaEnable        = DISABLE,
+        .rxFifoDmaEnable        = DISABLE,
+    };
+
+    /* enable clk */
+
+#if 0
+    if (0 == uart_clk_init) {
+        GLB_Set_UART_CLK(1, HBN_UART_CLK_160M, uart_div);
+        uart_clk_init = 1;
+    }
+#endif
+
+    uart->dma_rx_chan = -1;
+    uart->dma_tx_chan = -1;
+    id = cfg->uart_id;
+    uart->port = cfg->uart_id;
+
+    /* gpio init */
+    //gpio_init(id, cfg->tx_pin, cfg->rx_pin, cfg->cts_pin, cfg->rts_pin);
+
+    uartCfg.baudRate = cfg->baud_rate;
+    uartCfg.dataBits = (UART_DataBits_Type)cfg->data_width;
+    uartCfg.parity = (UART_Parity_Type)cfg->parity;
+
+    if (cfg->flow_control == HOSAL_FLOW_CONTROL_CTS) {
+    	uartCfg.ctsFlowControl = 1;
+    	uartCfg.rtsSoftwareControl = 0;
+    } else if (cfg->flow_control == HOSAL_FLOW_CONTROL_RTS) {
+    	uartCfg.ctsFlowControl = 0;
+    	uartCfg.rtsSoftwareControl = 1;
+    } else if (cfg->flow_control == HOSAL_FLOW_CONTROL_CTS_RTS) {
+    	uartCfg.ctsFlowControl = 1;
+    	uartCfg.rtsSoftwareControl = 1;
+    } else {
+    	uartCfg.ctsFlowControl = 0;
+    	uartCfg.rtsSoftwareControl = 0;
+    }
+
+    //uartCfg.uartClk = (40 * 1000 * 1000) / (uart_div + 1);
+
+    /* Disable all interrupt */
+    UART_IntMask(id, UART_INT_ALL, MASK);
+
+    /* Disable uart before config */
+    UART_Disable(id, UART_TXRX);
+
+    if (UART_GetRxBusBusyStatus(id) == SET) {
+        UART_DeInit(id);
+    }
+
+    /* UART init */
+    UART_Init(id, &uartCfg);
+
+    /* Enable tx free run mode */
+    UART_TxFreeRun(id, ENABLE);
+
+    /* FIFO Config*/
+    UART_FifoConfig(id, &fifoCfg);
+
+    if (cfg->mode == HOSAL_UART_MODE_INT) {
+    	bl_uart_int_tx_notify_register(uart->port, __uart_tx_irq, uart);
+    	bl_uart_int_rx_notify_register(uart->port, __uart_rx_irq, uart);
+    	bl_uart_int_enable(uart->port);
+    	bl_uart_int_tx_disable(uart->port);
+    } else {
+    	bl_uart_int_disable(uart->port);
+    }
+
+    /* Enable uart */
+    UART_Enable(id, UART_TXRX);
+    return 0;
+}
+
+int hosal_uart_receive(hosal_uart_dev_t *uart, void *data, uint32_t expect_size)
+{
+    int ch;
+    uint32_t counter = 0;
+
+    while (counter < expect_size) {
+        if ((ch = bl_uart_data_recv(uart->port)) < 0) {
+            break;
+        }
+        ((uint8_t*)data)[counter] = ch;
+        counter++;
+    }
+    return counter;
+}
+
+int hosal_uart_send(hosal_uart_dev_t *uart, const void *data, uint32_t size)
+{
+    uint32_t i = 0;
+
+    while (i < size) {
+        bl_uart_data_send(uart->port, ((uint8_t*)data)[i]);
+        i++;
+    }
+    return i;
+}
+
+int hosal_uart_ioctl(hosal_uart_dev_t *uart, int ctl, void *p_arg)
+{
+#if 0
+	hosal_uart_dma_cfg_t *dma_cfg;
+#endif
+
+    switch (ctl) {
+    case HOSAL_UART_BAUD_SET:
+        uart->config.baud_rate = (uint32_t)p_arg;
+        __uart_config_set(uart, &uart->config);
+        break;
+    case HOSAL_UART_BAUD_GET:
+        if (p_arg) {
+            *(uint32_t *)p_arg = uart->config.baud_rate;
+        }
+        break;
+    case HOSAL_UART_DATA_WIDTH_SET:
+        uart->config.data_width = (hosal_uart_data_width_t)p_arg;
+        __uart_config_set(uart, &uart->config);
+        break;
+    case HOSAL_UART_DATA_WIDTH_GET:
+        if (p_arg) {
+            *(hosal_uart_data_width_t *)p_arg = uart->config.data_width;
+        }
+        break;
+    case HOSAL_UART_STOP_BITS_SET:
+        uart->config.stop_bits = (hosal_uart_stop_bits_t)p_arg;
+        __uart_config_set(uart, &uart->config);
+        break;
+    case HOSAL_UART_STOP_BITS_GET:
+        if (p_arg) {
+            *(hosal_uart_stop_bits_t *)p_arg = uart->config.stop_bits;
+        }
+        break;
+    case HOSAL_UART_FLOWMODE_SET:
+        uart->config.flow_control = (hosal_uart_flow_control_t)p_arg;
+        __uart_config_set(uart, &uart->config);
+        break;
+    case HOSAL_UART_FLOWSTAT_GET:
+        if (p_arg) {
+            *(hosal_uart_flow_control_t *)p_arg = uart->config.flow_control;
+        }
+        break;
+    case HOSAL_UART_PARITY_SET:
+        uart->config.parity = (hosal_uart_parity_t)p_arg;
+        __uart_config_set(uart, &uart->config);
+        break;
+    case HOSAL_UART_PARITY_GET:
+        if (p_arg) {
+            *(hosal_uart_parity_t *)p_arg = uart->config.parity;
+        }
+        break;
+    case HOSAL_UART_MODE_SET:
+        uart->config.mode = (hosal_uart_mode_t)p_arg;
+        __uart_config_set(uart, &uart->config);
+        break;
+    case HOSAL_UART_MODE_GET:
+        if (p_arg) {
+            *(hosal_uart_mode_t *)p_arg = uart->config.mode;
+        }
+        break;
+    case HOSAL_UART_FREE_TXFIFO_GET:
+        if (p_arg) {
+            *(uint32_t *)p_arg = UART_GetTxFifoCount(uart->port);
+        }
+        break;
+    case HOSAL_UART_FREE_RXFIFO_GET:
+        if (p_arg) {
+            *(uint32_t *)p_arg = UART_GetRxFifoCount(uart->port);
+        }
+        break;
+    case HOSAL_UART_FLUSH:
+        bl_uart_flush(uart->port);
+        break;
+    case HOSAL_UART_TX_TRIGGER_ON:
+    	bl_uart_int_tx_enable(uart->port);
+    	break;
+    case HOSAL_UART_TX_TRIGGER_OFF:
+    	bl_uart_int_tx_disable(uart->port);
+    	break;
+#if 0
+    case HOSAL_UART_DMA_TX_START:
+    	dma_cfg = (hosal_uart_dma_cfg_t *)p_arg;
+    	if (__uart_dma_txcfg(uart, dma_cfg) != 0) {
+    		return -1;
+    	}
+    	hosal_dma_chan_start(uart->dma_tx_chan);
+    	break;
+    case HOSAL_UART_DMA_RX_START:
+    	dma_cfg = (hosal_uart_dma_cfg_t *)p_arg;
+    	if (__uart_dma_rxcfg(uart, dma_cfg) != 0) {
+    		return -1;
+    	}
+    	hosal_dma_chan_start(uart->dma_rx_chan);
+    	break;
+#endif
+    default :
+        return -1;
+    }
+    return 0;
+}
+
+int hosal_uart_callback_set(hosal_uart_dev_t *uart,
+                          int callback_type,
+                          hosal_uart_callback_t pfn_callback,
+                          void *arg)
+{
+    if (callback_type == HOSAL_UART_TX_CALLBACK) {
+        uart->tx_cb = pfn_callback;
+        uart->p_txarg = arg;
+    } else if (callback_type == HOSAL_UART_RX_CALLBACK) {
+        uart->rx_cb = pfn_callback;
+        uart->p_rxarg = arg;
+    }
+#if 0
+    else if (callback_type == HOSAL_UART_TX_DMA_CALLBACK) {
+        uart->txdma_cb = pfn_callback;
+        uart->p_txdma_arg = arg;
+    } else if (callback_type == HOSAL_UART_RX_DMA_CALLBACK) {
+        uart->rxdma_cb = pfn_callback;
+        uart->p_rxdma_arg = arg;
+    }
+#endif
+    return 0;
+}
+
+int hosal_uart_finalize(hosal_uart_dev_t *uart)
+{
+    bl_uart_int_disable(uart->port);
+    UART_Disable(uart->port, UART_TXRX);
+#if 0
+    if (uart->dma_rx_chan > 0) {
+    	hosal_dma_chan_release(uart->dma_rx_chan);
+    }
+    if (uart->dma_tx_chan > 0) {
+    	hosal_dma_chan_release(uart->dma_tx_chan);
+    }
+#endif
+    return 0;
+}

+ 419 - 0
bsp/bl808/m0/libraries/platform/hosal/bl808_e907_hal/phy_8720.c

@@ -0,0 +1,419 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <string.h>
+#include "hal_emac.h"
+#include "ethernet_phy.h"
+
+/* LAN8720 PHY Address*/
+#define EMAC_PHY_ADDRESS          0x00U
+#define PHY_LINK_TO               ((uint32_t)0x00000FFFU)
+#define PHY_AUTONEGO_COMPLETED_TO ((uint32_t)0x00000FFFU)
+/* Section 3: Common PHY Registers */
+#define PHY_BCR                     ((uint16_t)0x00U) /*!< Transceiver Basic Control Register   */
+#define PHY_BSR                     ((uint16_t)0x01U) /*!< Transceiver Basic Status Register    */
+#define PHY_BSR_100BASETXFULL       (1 << 14)
+#define PHY_BSR_100BASETXHALF       (1 << 13)
+#define PHY_BSR_10BASETXFULL        (1 << 12)
+#define PHY_BSR_10BASETXHALF        (1 << 11)
+#define PHY_RESET                   ((uint16_t)0x8000U) /*!< PHY Reset */
+#define PHY_LOOPBACK                ((uint16_t)0x4000U) /*!< Select loop-back mode */
+#define PHY_FULLDUPLEX_100M         ((uint16_t)0x2100U) /*!< Set the full-duplex mode at 100 Mb/s */
+#define PHY_HALFDUPLEX_100M         ((uint16_t)0x2000U) /*!< Set the half-duplex mode at 100 Mb/s */
+#define PHY_FULLDUPLEX_10M          ((uint16_t)0x0100U) /*!< Set the full-duplex mode at 10 Mb/s  */
+#define PHY_HALFDUPLEX_10M          ((uint16_t)0x0000U) /*!< Set the half-duplex mode at 10 Mb/s  */
+#define PHY_AUTONEGOTIATION         ((uint16_t)0x1000U) /*!< Enable auto-negotiation function     */
+#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200U) /*!< Restart auto-negotiation function    */
+#define PHY_POWERDOWN               ((uint16_t)0x0800U) /*!< Select the power down mode           */
+#define PHY_ISOLATE                 ((uint16_t)0x0400U) /*!< Isolate PHY from MII                 */
+#define PHY_AUTONEGO_COMPLETE       ((uint16_t)0x0020U) /*!< Auto-Negotiation process completed   */
+#define PHY_LINKED_STATUS           ((uint16_t)0x0004U) /*!< Valid link established               */
+#define PHY_JABBER_DETECTION        ((uint16_t)0x0002U) /*!< Jabber condition detected            */
+
+#define PHY_PHYID1                  ((uint16_t)0x02U) /*!< PHY ID 1    */
+#define PHY_PHYID2                  ((uint16_t)0x03U) /*!< PHY ID 2    */
+#define PHY_ADVERTISE               ((uint16_t)0x04U) /*!< Auto-negotiation advertisement       */
+#define PHY_ADVERTISE_100BASETXFULL (1 << 8)
+#define PHY_ADVERTISE_100BASETXHALF (1 << 7)
+#define PHY_ADVERTISE_10BASETXFULL  (1 << 6)
+#define PHY_ADVERTISE_10BASETXHALF  (1 << 5)
+#define PHY_ADVERTISE_8023          (1 << 0)
+#define PHY_LPA                     ((uint16_t)0x05U) /*!< Auto-negotiation link partner base page ability    */
+#define PHY_EXPANSION               ((uint16_t)0x06U) /*!< Auto-negotiation expansion           */
+/* Section 4: Extended PHY Registers */
+#define PHY_CTRL_STATUS           ((uint16_t)17U) /*!< PHY MODE CONTROL/STATUS REGISTER Offset     */
+#define PHY_CTRL_STATUS_EDPWRDOWN (1 << 13)       /*!< EDPWRDOWN */
+#define PHY_CTRL_STATUS_ENERGYON  (1 << 1)        /*!< ENERGYON */
+
+#define PHY_SPECIAL_MODES              ((uint16_t)18U) /*!< PHY SPECIAL MODES REGISTER Offset     */
+#define PHY_SPECIAL_MODES_MODE         (7 << 5)        /*!< Transceiver mode of operation */
+#define PHY_SPECIAL_MODES_MODE_PWRDOWN (6 << 5)        /*!< All capable. Auto-negotiation enabled */
+#define PHY_SPECIAL_MODES_MODE_ALL     (7 << 5)        /*!< All capable. Auto-negotiation enabled */
+#define PHY_SPECIAL_MODES_PHYAD        (0x1F << 0)     /*!< PHY Address */
+
+#define PHY_SR                                  ((uint16_t)0x1FU) /*!< PHY special control/ status register Offset     */
+#define PHY_SR_SPEED_OFFSET                     (2)
+#define PHY_SR_SPEED_MASK                       (0x7 << PHY_SR_SPEED_OFFSET)
+#define PHY_SR_SPEED_10BASETXHALF               (0x1 << PHY_SR_SPEED_OFFSET)
+#define PHY_SR_SPEED_10BASETXFULL               (0x5 << PHY_SR_SPEED_OFFSET)
+#define PHY_SR_SPEED_100BASETXHALF              (0x2 << PHY_SR_SPEED_OFFSET)
+#define PHY_SR_SPEED_100BASETXFULL              (0x6 << PHY_SR_SPEED_OFFSET)
+#define PHY_SR_SPEED_MODE_COMPARE(status, mode) (!!(mode == (status & PHY_SR_SPEED_MASK)))
+#define PHY_SPEED_STATUS                        ((uint16_t)0x0004U) /*!< PHY Speed mask                                  */
+#define PHY_DUPLEX_STATUS                       ((uint16_t)0x0010U) /*!< PHY Duplex mask                                 */
+#define PHY_ISFR                                ((uint16_t)0x1DU)   /*!< PHY Interrupt Source Flag register Offset       */
+#define PHY_ISFR_INT4                           ((uint16_t)0x0010U) /*!< PHY Link down inturrupt                         */
+
+static emac_phy_cfg_t *phy_8720_cfg = NULL;
+
+int phy_8720_reset(void)
+{
+    int timeout = 1000;
+    uint16_t regval = PHY_RESET;
+
+    /* pull the PHY from power down mode if it is in */
+    if (0 != emac_phy_reg_read(PHY_SPECIAL_MODES, &regval)) {
+        return -1;
+    }
+
+    if (PHY_SPECIAL_MODES_MODE_PWRDOWN == (regval & PHY_SPECIAL_MODES_MODE)) {
+        if (emac_phy_reg_write(PHY_SPECIAL_MODES, regval | PHY_SPECIAL_MODES_MODE_ALL) != 0) {
+            return -1;
+        }
+    }
+
+    /* disable energy detect powerdown mode for cable detect, this increase the power by 220mW */
+    if (0 != emac_phy_reg_read(PHY_CTRL_STATUS, &regval)) {
+        return -1;
+    }
+
+    if (emac_phy_reg_write(PHY_CTRL_STATUS, regval & (~PHY_CTRL_STATUS_EDPWRDOWN)) != 0) {
+        return -1;
+    }
+
+    /* do sw reset */
+    if (emac_phy_reg_write(PHY_BCR, PHY_RESET) != 0) {
+        return -1;
+    }
+
+    for (; timeout; timeout--) {
+        if (0 != emac_phy_reg_read(PHY_BCR, &regval)) {
+            return -1;
+        }
+
+        if (!(regval & PHY_RESET)) {
+            return 0;
+        }
+
+        arch_delay_ms(1);
+    }
+
+    return -1;
+}
+
+int phy_8720_auto_negotiate(emac_phy_cfg_t *cfg)
+{
+    uint16_t regval = 0;
+    uint16_t phyid1 = 0, phyid2 = 0;
+    uint16_t advertise = 0;
+    uint16_t lpa = 0;
+    uint32_t timeout = 100; //10s,in 100ms
+
+    if (0 != emac_phy_reg_read(PHY_PHYID1, &phyid1)) {
+        // MSG("read emac phy id 1 error\r\n");
+        return -1;
+    }
+
+    if (0 != emac_phy_reg_read(PHY_PHYID2, &phyid2)) {
+        MSG("read emac phy id 2 error\r\n");
+        return -1;
+    }
+    MSG("emac phy id 1 =%08x\r\n",(unsigned int )phyid1);
+    MSG("emac phy id 2 =%08x\r\n",(unsigned int )phyid2);
+    if (cfg->phy_id != (((phyid1 << 16) | phyid2) & 0x000FFFF0)) {
+        /* ID error */
+        return -1;
+    } else {
+        cfg->phy_id = (phyid1 << 16) | phyid2;
+    }
+
+    if (0 != emac_phy_reg_read(PHY_BCR, &regval)) {
+        return -1;
+    }
+
+    regval &= ~PHY_AUTONEGOTIATION;
+    regval &= ~(PHY_LOOPBACK | PHY_POWERDOWN);
+    regval |= PHY_ISOLATE;
+
+    if (emac_phy_reg_write(PHY_BCR, regval) != 0) {
+        return -1;
+    }
+
+    /* set advertisement mode */
+    advertise = PHY_ADVERTISE_100BASETXFULL | PHY_ADVERTISE_100BASETXHALF |
+                PHY_ADVERTISE_10BASETXFULL | PHY_ADVERTISE_10BASETXHALF |
+                PHY_ADVERTISE_8023;
+
+    if (emac_phy_reg_write(PHY_ADVERTISE, advertise) != 0) {
+        return -1;
+    }
+
+    arch_delay_ms(16);
+
+    if (0 != emac_phy_reg_read(PHY_BCR, &regval)) {
+        return -1;
+    }
+
+    arch_delay_ms(16);
+    regval |= (PHY_FULLDUPLEX_100M | PHY_AUTONEGOTIATION);
+
+    if (emac_phy_reg_write(PHY_BCR, regval) != 0) {
+        return -1;
+    }
+
+    arch_delay_ms(16);
+    regval |= PHY_RESTART_AUTONEGOTIATION;
+    regval &= ~PHY_ISOLATE;
+
+    if (emac_phy_reg_write(PHY_BCR, regval) != 0) {
+        return -1;
+    }
+
+    arch_delay_ms(100);
+
+    while (1) {
+        if (0 != emac_phy_reg_read(PHY_BSR, &regval)) {
+            return -1;
+        }
+
+        if (regval & PHY_AUTONEGO_COMPLETE) {
+            /* complete */
+            break;
+        }
+
+        if (!(--timeout)) {
+            return -1;
+        }
+
+        arch_delay_ms(100);
+    }
+
+    arch_delay_ms(100);
+
+    if (0 != emac_phy_reg_read(PHY_LPA, &lpa)) {
+        return -1;
+    }
+
+    if (((advertise & lpa) & PHY_ADVERTISE_100BASETXFULL) != 0) {
+        /* 100BaseTX and Full Duplex */
+        cfg->full_duplex = 1;
+        cfg->speed = 100;
+        cfg->phy_state = PHY_STATE_READY;
+    } else if (((advertise & lpa) & PHY_ADVERTISE_10BASETXFULL) != 0) {
+        /* 10BaseT and Full Duplex */
+        cfg->full_duplex = 1;
+        cfg->speed = 10;
+        cfg->phy_state = PHY_STATE_READY;
+    } else if (((advertise & lpa) & PHY_ADVERTISE_100BASETXHALF) != 0) {
+        /* 100BaseTX and half Duplex */
+        cfg->full_duplex = 0;
+        cfg->speed = 100;
+        cfg->phy_state = PHY_STATE_READY;
+    } else if (((advertise & lpa) & PHY_ADVERTISE_10BASETXHALF) != 0) {
+        /* 10BaseT and half Duplex */
+        cfg->full_duplex = 0;
+        cfg->speed = 10;
+        cfg->phy_state = PHY_STATE_READY;
+    }
+
+    return 0;
+}
+
+int phy_8720_link_up(emac_phy_cfg_t *cfg)
+{
+    uint16_t phy_bsr = 0;
+    uint16_t phy_sr = 0;
+
+    arch_delay_ms(16);
+
+    if (0 != emac_phy_reg_read(PHY_BSR, &phy_bsr)) {
+        return -1;
+    }
+
+    arch_delay_ms(16);
+
+    if (!(PHY_LINKED_STATUS & phy_bsr)) {
+        return ERROR;
+    }
+
+    arch_delay_ms(16);
+
+    if (0 != emac_phy_reg_read(PHY_SR, &phy_sr)) {
+        return -1;
+    }
+
+    if ((phy_bsr & PHY_BSR_100BASETXFULL) && PHY_SR_SPEED_MODE_COMPARE(phy_sr, PHY_SR_SPEED_100BASETXFULL)) {
+        /* 100BaseTX and Full Duplex */
+        cfg->full_duplex = 1;
+        cfg->speed = 100;
+        cfg->phy_state = PHY_STATE_UP;
+    } else if ((phy_bsr & PHY_BSR_10BASETXFULL) && PHY_SR_SPEED_MODE_COMPARE(phy_sr, PHY_SR_SPEED_10BASETXFULL)) {
+        /* 10BaseT and Full Duplex */
+        cfg->full_duplex = 1;
+        cfg->speed = 10;
+        cfg->phy_state = PHY_STATE_UP;
+    } else if ((phy_bsr & PHY_BSR_100BASETXHALF) && PHY_SR_SPEED_MODE_COMPARE(phy_sr, PHY_SR_SPEED_100BASETXHALF)) {
+        /* 100BaseTX and half Duplex */
+        cfg->full_duplex = 0;
+        cfg->speed = 100;
+        cfg->phy_state = PHY_STATE_UP;
+    } else if ((phy_bsr & PHY_BSR_10BASETXHALF) && PHY_SR_SPEED_MODE_COMPARE(phy_sr, PHY_SR_SPEED_10BASETXHALF)) {
+        /* 10BaseT and half Duplex */
+        cfg->full_duplex = 0;
+        cfg->speed = 10;
+        cfg->phy_state = PHY_STATE_UP;
+    } else {
+        /* 10BaseT and half Duplex */
+        cfg->full_duplex = -1;
+        cfg->speed = -1;
+        cfg->phy_state = PHY_STATE_DOWN;
+        return -1;
+    }
+
+    return 0;
+}
+
+/******************************************************************************
+ * @brief  Use energy detector for cable plug in/out detect.
+ *
+ * @param  cfg: EMAC PHY configuration pointer
+ *
+ * @return SUCCESS or ERROR
+ *
+*******************************************************************************/
+int phy_8720_poll_cable_status(emac_phy_cfg_t *cfg)
+{
+    uint16_t phy_regval = 0;
+
+    CHECK_PARAM(NULL != phy_8720_cfg);
+
+    if (0 != emac_phy_reg_read(PHY_CTRL_STATUS, &phy_regval)) {
+        return -1;
+    }
+
+    phy_8720_cfg->phy_state = (PHY_CTRL_STATUS_ENERGYON & phy_regval) ?
+                                  PHY_STATE_UP :
+                                  PHY_STATE_DOWN;
+
+    return !!(PHY_CTRL_STATUS_ENERGYON & phy_regval);
+}
+
+/****************************************************************************/ /**
+ * @brief  Initialize EMAC PHY module
+ *
+ * @param  cfg: EMAC PHY configuration pointer
+ *
+ * @return SUCCESS or ERROR
+ *
+*******************************************************************************/
+int emac_phy_init(emac_phy_cfg_t *cfg)
+{
+    uint16_t phyReg;
+
+    CHECK_PARAM(NULL != cfg);
+
+    phy_8720_cfg = cfg;
+
+    emac_phy_set_address(cfg->phy_address);
+
+    if (0 != phy_8720_reset()) {
+        return -1;
+    }
+
+    if (cfg->auto_negotiation) {
+        /*
+        uint32_t cnt=0;
+        do{
+            if(emac_phy_reg_read(PHY_BSR, &phyReg) != SUCCESS){
+                return ERROR;
+            }
+            cnt++;
+            if(cnt>PHY_LINK_TO){
+                return ERROR;
+            }
+        }while((phyReg & PHY_LINKED_STATUS) != PHY_LINKED_STATUS);
+        */
+        if (0 != phy_8720_auto_negotiate(cfg)) {
+            return -1;
+        }
+    } else {
+        if (emac_phy_reg_read(PHY_BCR, &phyReg) != 0) {
+            return -1;
+        }
+
+        phyReg &= (~PHY_FULLDUPLEX_100M);
+
+        if (cfg->speed == 10) {
+            if (cfg->full_duplex == 1) {
+                phyReg |= PHY_FULLDUPLEX_10M;
+            } else {
+                phyReg |= PHY_HALFDUPLEX_10M;
+            }
+        } else {
+            if (cfg->full_duplex == 1) {
+                phyReg |= PHY_FULLDUPLEX_100M;
+            } else {
+                phyReg |= PHY_HALFDUPLEX_100M;
+            }
+        }
+
+        if ((emac_phy_reg_write(PHY_BCR, phyReg)) != 0) {
+            return -1;
+        }
+    }
+
+    emac_phy_config_full_duplex(cfg->full_duplex);
+
+    return phy_8720_link_up(cfg);
+}
+
+emac_phy_status_t ethernet_phy_status_get()
+{
+    CHECK_PARAM(NULL != phy_8720_cfg);
+
+    if ((100 == phy_8720_cfg->speed) &&
+        (phy_8720_cfg->full_duplex) &&
+        (PHY_STATE_UP == phy_8720_cfg->phy_state)) {
+        return EMAC_PHY_STAT_100MBITS_FULLDUPLEX;
+    } else if (PHY_STATE_UP == phy_8720_cfg->phy_state) {
+        return EMAC_PHY_STAT_LINK_UP;
+    } else {
+        return EMAC_PHY_STAT_LINK_DOWN;
+    }
+}

+ 238 - 0
bsp/bl808/m0/libraries/platform/hosal/include/hosal_adc.h

@@ -0,0 +1,238 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __HOSAL_ADC_H_
+#define __HOSAL_ADC_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include "hosal_dma.h"
+
+/** @addtogroup hosal_adc ADC
+ *  HOSAL ADC API
+ *
+ *  @{
+ */
+
+#define HOSAL_WAIT_FOREVER        0xFFFFFFFFU  /**< @brief Define the wait forever timeout macro */
+
+/**
+ * @brief ADC interrupt events
+ */
+typedef enum __ADC_INT_EVENTS__{
+    HOSAL_ADC_INT_OV,         /**< @brief Overrun error */
+    HOSAL_ADC_INT_EOS,        /**< @brief End of sample */
+    HOSAL_ADC_INT_DMA_TRH,    /**< @brief DMA transceive half */
+    HOSAL_ADC_INT_DMA_TRC,    /**< @brief DMA transceive complete */
+    HOSAL_ADC_INT_DMA_TRE,    /**< @briefDMA transceive error */
+} hosal_adc_event_t;
+
+/**
+ * @brief ADC data type
+ */
+typedef struct {
+    uint32_t size;  /**< @brief sampled data size */
+    void *data;     /**< @brief sampled data, aligned with resolution (until the next power of two) */
+} hosal_adc_data_t;
+
+/**
+ * @brief ADC MODE type
+ */
+typedef enum {
+    HOSAL_ADC_ONE_SHOT,       /**< @brief Single time sampling */
+    HOSAL_ADC_CONTINUE        /**< @brief Continuous sampling */
+} hosal_adc_sample_mode_t;
+
+/**
+ * @brief Define ADC config args
+ */
+typedef struct {
+    uint32_t sampling_freq;             /**< @brief sampling frequency in Hz */
+    uint32_t pin;                        /**< @brief adc pin */
+    hosal_adc_sample_mode_t mode;       /**< @brief adc sampling mode */
+    uint8_t sample_resolution;          /**< @brief adc sampling resolution */
+} hosal_adc_config_t;
+
+/**
+ * @brief ADC interrupt function
+ *
+ *@param[in] parg  Set the custom parameters specified
+ *
+ */
+typedef void (*hosal_adc_irq_t)(void *parg);
+
+/**
+ * @brief Define ADC dev hosal handle
+ */
+typedef struct {
+    uint8_t port;                    /**< @brief adc port */
+    hosal_adc_config_t config;        /**< @brief adc config */
+    hosal_dma_chan_t dma_chan;        /**< @brief adc dma channel */ 
+    hosal_adc_irq_t cb;               /**< @brief adc callback */
+    void *p_arg;                      /**< @brief p_arg data */
+    void *priv;                       /**< @brief priv data */
+} hosal_adc_dev_t;
+
+/**
+ * @brief ADC interrupt callback
+ *
+ * @param[in] parg  Set the custom parameters specified when the callback function is set
+ *
+ */
+typedef void (*hosal_adc_cb_t)(hosal_adc_event_t event, void *data, uint32_t size);
+
+/**
+ * @brief Initialises an ADC interface, Prepares an ADC hardware interface for sampling
+ *
+ * @param[in]  adc  the interface which should be initialised
+ *
+ * @return  
+ *	- 0    on success
+ *	- EIO  if an error occurred with any step
+ */
+int hosal_adc_init(hosal_adc_dev_t *adc);
+
+/**
+ * @brief Add a channel to an ADC interface
+ *
+ * @param[in]   adc      the interface which should be sampled
+ * @param[in]   channel  adc channel
+ *
+ * @return  
+ *	- 0    on success
+ *	- EIO  if an error occurred with any step
+ */
+int hosal_adc_add_channel(hosal_adc_dev_t *adc, uint32_t channel);
+
+/**
+ * @brief Remove a channel to an ADC interface
+ *
+ * @param[in]   adc      the interface which should be sampled
+ * @param[in]   channel  adc channel
+ *
+ * @return  
+ *	- 0    on success
+ *	- EIO  if an error occurred with any step
+ */
+int hosal_adc_remove_channel(hosal_adc_dev_t *adc, uint32_t channel);
+
+/**
+ * @brief Takes adc device handle from an ADC interface
+ *
+ * @return  
+ *	- other  get adc device success
+ *	- NULL   if an error occurred with any step
+ */
+hosal_adc_dev_t *hosal_adc_device_get(void);
+
+/**
+ * @brief Takes a single sample from an ADC interface
+ *
+ * @param[in]   adc      the interface which should be sampled
+ * @param[in]   channel  adc channel
+ * @param[in]   timeout  ms timeout
+ *
+ * @return  
+ *	- other  get adc data success
+ *	- -1     if an error occurred with any step
+ */
+int hosal_adc_value_get(hosal_adc_dev_t *adc, uint32_t channel, uint32_t timeout);
+
+/**
+ * @brief Takes a tsen sample from an ADC interface
+ *
+ * @param[in]   adc      the interface which should be sampled
+ *
+ * @return  
+ *	- other  get adc data success
+ *	- -1     if an error occurred with any step
+ */
+int hosal_adc_tsen_value_get(hosal_adc_dev_t *adc);
+
+/**
+ * @brief ADC sampling cb register
+ *
+ * @param [in]   adc          the ADC interface
+ * @param [in]   cb           Non-zero pointer is the sample callback handler
+ *                            NULL pointer for send unregister operation
+ *                            adc in cb must be the same pointer with adc pointer passed to hosal_adc_sample_cb_reg
+ *                            driver must notify upper layer by calling cb if ADC data is ready in HW or memory(DMA)
+ *
+ * @return  
+ *	- 0    on success
+ *	- EIO  if an error occurred with any step
+ */
+int hosal_adc_sample_cb_reg(hosal_adc_dev_t *adc, hosal_adc_cb_t cb);
+
+/**
+ * @brief ADC sampling start
+ *
+ * @param[in]   adc             the ADC interface
+ * @param[in]   data            adc data buffer
+ * @param[in]   size            data buffer size aligned with resolution (until the next power of two)
+ *
+ * @return  
+ *	- 0    on success
+ *	- EIO  if an error occurred with any step
+ */
+int hosal_adc_start(hosal_adc_dev_t *adc, void *data, uint32_t size);
+
+/**
+ * @brief ADC sampling stop
+ *
+ * @param[in]   adc             the ADC interface
+ *
+ * @return  
+ *	- 0    on success
+ *	- EIO  if an error occurred with any step
+ */
+int hosal_adc_stop(hosal_adc_dev_t *adc);
+
+/**
+ * @brief De-initialises an ADC interface, Turns off an ADC hardware interface
+ *
+ * @param[in]  adc  the interface which should be de-initialised
+ *
+ * @return  
+ *	- 0    on success
+ *	- EIO  if an error occurred with any step
+ */
+int hosal_adc_finalize(hosal_adc_dev_t *adc);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __HOSAL_ADC_H_ */
+
+/* end of file */

+ 187 - 0
bsp/bl808/m0/libraries/platform/hosal/include/hosal_dac.h

@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __HOSAL_DAC_H_
+#define __HOSAL_DAC_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include "hosal_dma.h"
+
+/** @addtogroup hosal_dac DAC
+ *  HOSAL DAC API
+ *
+ *  @{
+ */
+
+/**
+ * @brief hosal dac callback
+ *
+ * @param[in] arg Set the custom parameters specified when the callback function is set
+ *
+ */
+typedef void (*hosal_dac_cb_t)(void *arg);
+
+/**
+ * @brief This struct define dac config args
+ */
+typedef struct {
+    uint8_t  dma_enable;        /**< @brief 1: use dma, 0: no dma */
+    uint32_t  pin;              /**< @brief dac pin */
+    uint32_t  freq;             /**< @brief dac freq */
+} hosal_dac_config_t;
+
+/**
+ * @brief This struct define dac device type
+ */
+typedef struct {
+    uint8_t  port;                    /**< @brief dac id */
+    hosal_dac_config_t config;        /**< @brief dac config */
+    hosal_dac_cb_t cb;                /**< @brief dma callback */
+    hosal_dma_chan_t dma_chan;        /**< @brief dac dma channel */
+    void    *arg;                     /**< @brief arg data */
+    void    *priv;                    /**< @brief priv data */
+} hosal_dac_dev_t;
+
+/**
+ * @brief Initialises an dac interface
+ *
+ * @param[in]  dac  the interface which should be initialised
+ *
+ * @return  
+ *	- 0    on success
+ *	- EIO  if an error occurred with any step
+ */
+int hosal_dac_init(hosal_dac_dev_t *dac);
+
+/**
+ * @brief De-initialises an dac interface, Turns off an dac hardware interface
+ *
+ * @param[in]  dac  the interface which should be de-initialised
+ *
+ * @return  
+ *	- 0    on success
+ *	- EIO  if an error occurred with any step
+ */
+int hosal_dac_finalize(hosal_dac_dev_t *dac);
+
+/**
+ * @brief Start output dac (no DMA mode)
+ *
+ * @param[in]   dac      the interface which should be started
+ *
+ * @return  
+ *	- 0    on success
+ *	- EIO  if an error occurred with any step
+ */
+int hosal_dac_start(hosal_dac_dev_t *dac);
+
+/**
+ * @brief Stop output dac
+ *
+ * @param[in]   dac      the interface which should be stopped
+ *
+ * @return  
+ *	- 0    on success
+ *	- EIO  if an error occurred with any step
+ */
+int hosal_dac_stop(hosal_dac_dev_t *dac);
+
+/**
+ * @brief Output a value to an dac interface
+ *
+ * @param[in]   dac      the interface to set value
+ *
+ * @param[in]   data     the value to output, output unit: μV 
+ *
+ * @return  
+ *	- 0    on success
+ *	- EIO  if an error occurred with any step
+ */
+int hosal_dac_set_value(hosal_dac_dev_t *dac, uint32_t data);
+
+/**
+ * @brief Returns the last data output value of the selected dac channel
+ *
+ * @param[in]   dac      the interface to get value
+ *
+ * @return  dac output value, output unit: μV
+ */
+int hosal_dac_get_value(hosal_dac_dev_t *dac);
+
+/**
+ *  @brief DAC cb register
+ *
+ * @param [in]   dac          the DAC interface
+ * @param [in]   callback     callback handler
+ * @param [in]   arg          callback arg
+ * 
+ * @return  
+ *	- 0    on success
+ *	- EIO  if an error occurred with any step
+ */
+int hosal_dac_dma_cb_reg(hosal_dac_dev_t *dac, hosal_dac_cb_t callback, void *arg);
+
+/**
+ * @brief DAC use DMA mode
+ *   
+ * @param[in]   adc           the DAC interface
+ * @param[in]   data          dac data buffer
+ * @param[in]   size          data buffer size
+ *        
+ * @return  
+ *	- 0    on success
+ *	- EIO  if an error occurred with any step
+ */
+int hosal_dac_dma_start(hosal_dac_dev_t *dac, uint32_t *data, uint32_t size);
+
+/**
+ * @brief Stop output dac
+ *
+ * @param[in]   dac      the interface which should be stopped
+ *
+ * @return  
+ *	- 0    on success
+ *	- EIO  if an error occurred with any step
+ */
+int hosal_dac_dma_stop(hosal_dac_dev_t *dac);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __HOSAL_DAC_H_ */
+
+/* end of file */
+
+

+ 152 - 0
bsp/bl808/m0/libraries/platform/hosal/include/hosal_dma.h

@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __HOSAL_DMA_H__
+#define __HOSAL_DMA_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @addtogroup hosal_dma DMA
+ *  HOSAL DMA API
+ *
+ *  @{
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+
+/**
+ * @brief DMA irq callback function flag
+ */
+#define HOSAL_DMA_INT_TRANS_COMPLETE      0
+#define HOSAL_DMA_INT_TRANS_ERROR         1
+
+/**
+ * @brief DMA irq callback function
+ */
+typedef void (*hosal_dma_irq_t)(void *p_arg, uint32_t flag);
+
+/**
+ * @brief DMA channel describe
+ */
+struct hosal_dma_chan {
+    uint8_t used;
+    hosal_dma_irq_t callback;
+    void *p_arg;
+};
+
+/**
+ * @brief DMA device type
+ */
+typedef struct hosal_dma_dev {
+    int max_chans;
+    struct hosal_dma_chan *used_chan;
+    void *priv;
+} hosal_dma_dev_t;
+
+/**
+ * @brief DMA channel
+ */
+typedef int hosal_dma_chan_t;
+
+/**
+ * @brief Initialises a DMA interface
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int hosal_dma_init(void);
+
+/**
+ * @brief Request a DMA channel
+ *
+ * @param[in] flag : DMA CHAN REQUEST FLAG
+ *
+ * @return  < 0 : an error occurred with any step, otherwise is DMA channel number
+ */
+hosal_dma_chan_t hosal_dma_chan_request(int flag);
+
+/**
+ * @brief Release a DMA channel
+ *
+ * @param[in]  chan  DMA channel number
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int hosal_dma_chan_release(hosal_dma_chan_t chan);
+
+/**
+ * @brief DMA channel trans start
+ *
+ * @param[in]  chan  DMA channel number
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int hosal_dma_chan_start(hosal_dma_chan_t chan);
+
+/**
+ * @brief DMA channel trans stop
+ *
+ * @param[in]  chan  DMA channel number
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int hosal_dma_chan_stop(hosal_dma_chan_t chan);
+
+/**
+ * @brief DMA irq callback set
+ *
+ * @param[in] chan : DMA channel number
+ * @param[in] pfn : callback function
+ * @param[in] arg : callback function parameter
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int hosal_dma_irq_callback_set(hosal_dma_chan_t chan, hosal_dma_irq_t pfn, void *p_arg);
+
+/**
+ * @brief Deinitialises a DMA interface
+ *
+ * @param[in]  DMA the interface which should be deinitialised
+ *
+ * @return  0 : on success, EIO : if an error occurred with any step
+ */
+int hosal_dma_finalize(void);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __HOSAL_DMA_H__ */
+
+/* end of file */

+ 70 - 0
bsp/bl808/m0/libraries/platform/hosal/include/hosal_efuse.h

@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __HOSAL_EFUSE_H__
+#define __HOSAL_EFUSE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Read data from efuse
+ *
+ * @param[in]   addr     efuse address
+ * @param[in]   data     store data
+ * @param[in]   len      data length 
+ *
+ * @return  
+ *	- 0    on success
+ *	- EIO  if an error occurred with any step
+ */
+int hosal_efuse_read(uint32_t addr, uint32_t *data, uint32_t len);
+
+/**
+ * @brief Write data to efuse
+ *
+ * @param[in]   addr     efuse address
+ * @param[in]   data     store data
+ * @param[in]   len      data length 
+ *
+ * @return  
+ *	- 0    on success
+ *	- EIO  if an error occurred with any step
+ */
+int hosal_efuse_write(uint32_t addr, uint32_t *data, uint32_t len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __HOSAL_EFUSE_H__ */
+
+/* end of file */

+ 229 - 0
bsp/bl808/m0/libraries/platform/hosal/include/hosal_flash.h

@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __HOSAL_FLASH_H__
+#define __HOSAL_FLASH_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @addtogroup hosal_flash FLASH
+ *  HOSAL FLASH API
+ *
+ *  @{
+ */
+
+#include <stdint.h>
+
+#define HOSAL_FLASH_FLAG_ADDR_0      0  /**< @brief Open flash prtition address 0 in prtition table */
+
+#define HOSAL_FLASH_FLAG_ADDR_1      (1 << 0) /**< @brief Open flash prtition address 1 in prtition table */
+
+/**
+ * Open the partition table and use the bus physical address of flash.
+ * (If it is not set, the offset address set in the partition table is used by default.)
+ */
+#define HOSAL_FLASH_FLAG_BUSADDR     (1 << 1)
+
+/**
+ * @brief Hal flash partition device
+ */
+typedef struct hosal_flash_dev {
+    void *flash_dev;    /**< @brief flash device */
+} hosal_flash_dev_t;
+
+/**
+ * @brief Hal flash partition manage struct
+ */
+typedef struct {
+    const char  *partition_description; /**< @brief name */
+    uint32_t     partition_start_addr;  /**< @brief start addr */
+    uint32_t     partition_length;      /**< @brief length */
+    uint32_t     partition_options;     /**< @brief options */
+} hosal_logic_partition_t;
+
+/**
+ * @brief Open a flash partition device
+ *
+ * @param[in]  name     flash partition name
+ * @param[in]  flags    flash flags
+ *               - HOSAL_FLASH_FLAG_ADDR_0
+ *               - HOSAL_FLASH_FLAG_ADDR_1
+ *               - HOSAL_FLASH_FLAG_BUSADDR
+ *
+ * @return
+ *  - NULL flash open error
+ *  - otherwise is flash partition device
+ */
+hosal_flash_dev_t *hosal_flash_open(const char *name, unsigned int flags);
+
+/**
+ * @brief Get the information of the specified flash area
+ *
+ * @param[in]  p_dev     The target flash logical partition device
+ * @param[out] partition The buffer to store partition info
+ *
+ * @return
+ *  - 0 On success
+ *  - otherwise is error
+ */
+int hosal_flash_info_get(hosal_flash_dev_t *p_dev, hosal_logic_partition_t *partition);
+
+/**
+ * @brief Erase an area on a Flash logical partition
+ *
+ * @note  Erase on an address will erase all data on a sector that the
+ *        address is belonged to, this function does not save data that
+ *        beyond the address area but in the affected sector, the data
+ *        will be lost.
+ *
+ * @param[in]  p_dev         The target flash logical partition which should be erased
+ * @param[in]  off_set       Start address of the erased flash area
+ * @param[in]  size          Size of the erased flash area
+ *
+ * @return
+ *  - 0 On success
+ *  - otherwise is error
+ */
+int hosal_flash_erase(hosal_flash_dev_t *p_dev, uint32_t off_set, uint32_t size);
+
+/**
+ * @brief Write data to an area on a flash logical partition without erase
+ *
+ * @param[in]  p_dev           The target flash logical partition which should be read which should be written
+ * @param[in/out]  off_set     Point to the start address that the data is written to, and
+ *                             point to the last unwritten address after this function is
+ *                             returned, so you can call this function serval times without
+ *                             update this start address.
+ * @param[in]  in_buf          point to the data buffer that will be written to flash
+ * @param[in]  in_buf_size     The size of the buffer
+ *
+ * @return
+ *  - 0 On success
+ *  - otherwise is error
+ */
+int hosal_flash_write(hosal_flash_dev_t *p_dev, uint32_t *off_set,
+                    const void *in_buf, uint32_t in_buf_size);
+
+/**
+ * @brief Write data to an area on a flash logical partition with erase first
+ *
+ * @param[in]  p_dev           The target flash logical partition which should be read which should be written
+ * @param[in/out]  off_set     Point to the start address that the data is written to, and
+ *                             point to the last unwritten address after this function is
+ *                             returned, so you can call this function serval times without
+ *                             update this start address.
+ * @param[in]  in_buf          point to the data buffer that will be written to flash
+ * @param[in]  in_buf_size     The length of the buffer
+ *
+ * @return
+ *  - 0 On success
+ *  - otherwise is error
+ */
+int hosal_flash_erase_write(hosal_flash_dev_t *p_dev, uint32_t *off_set,
+                          const void *in_buf, uint32_t in_buf_size);
+
+/**
+ * @brief Read data from an area on a Flash to data buffer in RAM
+ *
+ * @param[in]  p_dev           The target flash logical partition which should be read
+ * @param[in/out]  off_set     Point to the start address that the data is read, and
+ *                             point to the last unread address after this function is
+ *                             returned, so you can call this function serval times without
+ *                             update this start address.
+ * @param[in]  out_buf         Point to the data buffer that stores the data read from flash
+ * @param[in]  out_buf_size    The length of the buffer
+ *
+ * @return
+ *  - 0 On success
+ *  - otherwise is error
+ */
+int hosal_flash_read(hosal_flash_dev_t *p_dev, uint32_t *off_set,
+                   void *out_buf, uint32_t out_buf_size);
+
+/**
+ * @brief Close a flash partition device
+ *
+ * @param[in]  p_dev     flash partition device
+ *
+ * @return
+ *  - 0 On success
+ *  - otherwise is error
+ */
+int hosal_flash_close(hosal_flash_dev_t *p_dev);
+
+/**
+ * @brief Read data from a row address on a Flash to data buffer in RAM
+ *
+ * @param[in]  buffer          Point to the data buffer that stores the data read from flash
+ * @param[in]  address         Address on flash to read from
+ * @param[in]  length          Length (in bytes) of data to read
+ *
+ * @return
+ *  - 0 On success
+ *  - otherwise is error
+ */
+int hosal_flash_raw_read(void *buffer, uint32_t address, uint32_t length);
+
+/**
+ * @brief Write data to a row address on a Flash
+ *
+ * @param[in]  buffer          Point to the data buffer that will be written to flash
+ * @param[in]  address         Address on flash to write to
+ * @param[in]  length          Length (in bytes) of data to write
+ *
+ * @return
+ *  - 0 On success
+ *  - otherwise is error
+ */
+int hosal_flash_raw_write(void *buffer, uint32_t address, uint32_t length);
+
+/**
+ * @brief Erase a region of the flash
+ *
+ * @param[in]  start_addr      Address to start erasing flash.
+ * @param[in]  length          Length of region to erase.
+ *
+ * @return
+ *  - 0 On success
+ *  - otherwise is error
+ */
+int hosal_flash_raw_erase(uint32_t start_addr, uint32_t length); 
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __HOSAL_FLASH_H__ */
+
+/* end of file */

+ 186 - 0
bsp/bl808/m0/libraries/platform/hosal/include/hosal_gpio.h

@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __HOSAL_GPIO_H_
+#define __HOSAL_GPIO_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+/** @addtogroup hosal_gpio GPIO
+ *  HOSAL GPIO API
+ *
+ *  @{
+ */
+
+/**
+ * @brief gpio config struct
+ */
+typedef enum {
+    ANALOG_MODE,               /**< @brief Used as a function pin, input and output analog */
+    INPUT_PULL_UP,             /**< @brief Input with an internal pull-up resistor - use with devices that actively drive the signal low - e.g. button connected to ground */
+    INPUT_PULL_DOWN,           /**< @brief Input with an internal pull-down resistor - use with devices that actively drive the signal high - e.g. button connected to a power rail */
+    INPUT_HIGH_IMPEDANCE,      /**< @brief Input - must always be driven, either actively or by an external pullup resistor */
+    OUTPUT_PUSH_PULL,          /**< @brief Output actively driven high and actively driven low - must not be connected to other active outputs - e.g. LED output */
+    OUTPUT_OPEN_DRAIN_NO_PULL, /**< @brief Output actively driven low but is high-impedance when set high - can be connected to other open-drain/open-collector outputs.  Needs an external pull-up resistor */
+    OUTPUT_OPEN_DRAIN_PULL_UP, /**< @brief Output actively driven low and is pulled high with an internal resistor when set high - can be connected to other open-drain/open-collector outputs. */
+    OUTPUT_OPEN_DRAIN_AF,      /**< @brief Alternate Function Open Drain Mode. */
+    OUTPUT_PUSH_PULL_AF,       /**< @brief Alternate Function Push Pull Mode. */
+} hosal_gpio_config_t;
+
+/**
+ * @brief GPIO interrupt trigger
+ */
+typedef enum {
+    HOSAL_IRQ_TRIG_NEG_PULSE,        /**< @brief GPIO negedge pulse trigger interrupt */
+    HOSAL_IRQ_TRIG_POS_PULSE,        /**< @brief GPIO posedge pulse trigger interrupt */
+    HOSAL_IRQ_TRIG_NEG_LEVEL,        /**< @brief  GPIO negedge level trigger interrupt (32k 3T)*/
+    HOSAL_IRQ_TRIG_POS_LEVEL,        /**< @brief  GPIO posedge level trigger interrupt (32k 3T)*/
+} hosal_gpio_irq_trigger_t;
+
+/**
+ * @brief GPIO interrupt callback handler
+ *
+ *@param[in] parg  :Set the custom parameters specified
+ */
+typedef void (*hosal_gpio_irq_handler_t)(void *arg);
+
+/**
+ * @brief hosal gpio ctx, use for multi gpio irq
+ */
+typedef struct hosal_gpio_ctx {
+    struct hosal_gpio_ctx *next;
+    hosal_gpio_irq_handler_t handle;
+    void *arg;
+    uint8_t pin;
+    uint8_t intCtrlMod;
+    uint8_t intTrigMod;
+}hosal_gpio_ctx_t;
+
+/**
+ * @brief GPIO dev struct
+ */
+typedef struct {
+    uint8_t        port;         /**< @brief gpio port */
+    hosal_gpio_config_t  config; /**< @brief gpio config */
+    void          *priv;         /**< @brief priv data */
+} hosal_gpio_dev_t;
+
+/**
+ * @brief Initialises a GPIO pin
+ *
+ * @note  Prepares a GPIO pin for use.
+ *
+ * @param[in]  gpio           the gpio pin which should be initialised
+ *
+ * @return  
+ *	- 0    on success
+ *	- EIO  if an error occurred with any step
+ */
+int hosal_gpio_init(hosal_gpio_dev_t *gpio);
+
+/**
+ * @brief Set GPIO output high or low
+ *
+ * @note  Using this function on a gpio pin which is set to input mode is undefined.
+ *
+ * @param[in]  gpio  the gpio pin which should be set 
+ * @param[in]  value 0 : output low | >0 : output high
+ *
+ * @return  
+ *	- 0    on success
+ *	- EIO  if an error occurred with any step
+ */
+int hosal_gpio_output_set(hosal_gpio_dev_t *gpio, uint8_t value);
+
+/**
+ * @brief Get the state of an input GPIO pin. Using this function on a
+ * gpio pin which is set to output mode will return an undefined value.
+ *
+ * @param[in]  gpio   the gpio pin which should be read
+ * @param[out] value  gpio value
+ *
+ * @return  
+ *	- 0    on success
+ *	- EIO  if an error occurred with any step
+ */
+int hosal_gpio_input_get(hosal_gpio_dev_t *gpio, uint8_t *value);
+
+/**
+ * @brief Enables an interrupt trigger for an input GPIO pin.
+ * Using this function on a gpio pin which is set to
+ * output mode is undefined.
+ *
+ * @param[in]  gpio     the gpio pin which will provide the interrupt trigger
+ * @param[in]  trigger  the type of trigger (rising/falling edge or both)
+ * @param[in]  handler  a function pointer to the interrupt handler
+ * @param[in]  arg      an argument that will be passed to the interrupt handler
+ *
+ * @return  
+ *	- 0    on success
+ *	- EIO  if an error occurred with any step
+ */
+int hosal_gpio_irq_set(hosal_gpio_dev_t *gpio, hosal_gpio_irq_trigger_t trigger_type, hosal_gpio_irq_handler_t handler, void *arg);
+
+/**
+ * @brief Clear an interrupt status for an input GPIO pin.
+ * Using this function on a gpio pin which has generated a interrupt.
+ *
+ * @param[in]  gpio  the gpio pin which provided the interrupt trigger
+ * @param[in]  mask  0 : mask | 1 : umask
+ *
+ * @return  
+ *	- 0    on success
+ *	- EIO  if an error occurred with any step
+ */
+int hosal_gpio_irq_mask(hosal_gpio_dev_t *gpio, uint8_t mask);
+
+/**
+ * @brief Set a GPIO pin in default state.
+ *
+ * @param[in]  gpio  the gpio pin which should be deinitialised
+ *
+ * @return  
+ *	- 0    on success
+ *	- EIO  if an error occurred with any step
+ */
+int hosal_gpio_finalize(hosal_gpio_dev_t *gpio);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_GPIO_H */
+

+ 212 - 0
bsp/bl808/m0/libraries/platform/hosal/include/hosal_i2c.h

@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __HOSAL_I2C_H_
+#define __HOSAL_I2C_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @addtogroup hosal_i2c I2C
+ *  HOSAL I2C API
+ *
+ *  @{
+ */
+
+#include <stdint.h>
+
+#define HOSAL_WAIT_FOREVER 0xFFFFFFFFU /**< @brief i2c wait time */
+
+#define HOSAL_I2C_MODE_MASTER 1     /**< @brief i2c communication is master mode */
+#define HOSAL_I2C_MODE_SLAVE  2     /**< @brief i2c communication is slave mode */
+
+#define HOSAL_I2C_MEM_ADDR_SIZE_8BIT  1 /**< @brief i2c memory address size 8bit */
+#define HOSAL_I2C_MEM_ADDR_SIZE_16BIT 2 /**< @brief i2c memory address size 16bit */
+#define HOSAL_I2C_MEM_ADDR_SIZE_24BIT 3 /**< @brief i2c memory address size 24bit */
+#define HOSAL_I2C_MEM_ADDR_SIZE_32BIT 4 /**< @brief i2c memory address size 32bit */
+
+#define HOSAL_I2C_ADDRESS_WIDTH_7BIT  0   /**< @brief 7 bit mode */
+#define HOSAL_I2C_ADDRESS_WIDTH_10BIT 1   /**< @brief 10 bit mode */
+
+/**
+ * @brief I2C configuration
+ */
+typedef struct {
+    uint32_t address_width; /**< @brief Addressing mode: 7 bit or 10 bit */
+    uint32_t freq;          /**< @brief CLK freq */
+    uint8_t  scl;           /**< @brief i2c clk pin */
+    uint8_t  sda;           /**< @brief i2c data pin */
+    uint8_t  mode;          /**< @brief master or slave mode */
+} hosal_i2c_config_t;
+
+/**
+ * @brief I2C device type
+ */
+typedef struct {
+    uint8_t       port;             /**< @brief i2c port */
+    hosal_i2c_config_t  config;     /**< @brief i2c config */
+    void         *priv;             /**< @brief priv data */
+} hosal_i2c_dev_t;
+
+/**
+ * @brief Initialises an I2C interface
+ *
+ * @param[in]  i2c  the device for which the i2c port should be initialised
+ *
+ * @return  
+ *  - 0  on success
+ *  - EIO  if an error occurred with any step
+ */
+int hosal_i2c_init(hosal_i2c_dev_t *i2c);
+
+/**
+ * @brief I2c master send
+ *
+ * @param[in]  i2c       the i2c device
+ * @param[in]  dev_addr  device address
+ * @param[in]  data      i2c send data
+ * @param[in]  size      i2c send data size
+ * @param[in]  timeout   timeout in milisecond, set this value to HAL_WAIT_FOREVER
+ *                       if you want to wait forever
+ *
+ * @return
+ *  - 0  on success
+ *  - EIO  if an error occurred with any step
+ */
+int hosal_i2c_master_send(hosal_i2c_dev_t *i2c, uint16_t dev_addr, const uint8_t *data,
+                            uint16_t size, uint32_t timeout);
+
+/**
+ * @brief I2c master recv
+ *
+ * @param[in]   i2c       the i2c device
+ * @param[in]   dev_addr  device address
+ * @param[out]  data      i2c receive data
+ * @param[in]   size      i2c receive data size
+ * @param[in]   timeout   timeout in milisecond, set this value to HAL_WAIT_FOREVER
+ *                        if you want to wait forever
+ *
+ * @return
+ *  - 0  on success
+ *  - EIO  if an error occurred with any step
+ */
+int hosal_i2c_master_recv(hosal_i2c_dev_t *i2c, uint16_t dev_addr, uint8_t *data,
+                            uint16_t size, uint32_t timeout);
+/**
+ * @brief I2c slave send
+ *
+ * @param[in]  i2c      the i2c device
+ * @param[in]  data     i2c slave send data
+ * @param[in]  size     i2c slave send data size
+ * @param[in]  timeout  timeout in milisecond, set this value to HAL_WAIT_FOREVER
+ *                      if you want to wait forever
+ *
+ * @return
+ *  - 0  on success
+ *  - EIO  if an error occurred with any step
+ */
+int hosal_i2c_slave_send(hosal_i2c_dev_t *i2c, const uint8_t *data, uint16_t size, uint32_t timeout);
+
+/**
+ * @brief I2c slave receive
+ *
+ * @param[in]   i2c      tthe i2c device
+ * @param[out]  data     i2c slave receive data
+ * @param[in]   size     i2c slave receive data size
+ * @param[in]  timeout   timeout in milisecond, set this value to HAL_WAIT_FOREVER
+ *                       if you want to wait forever
+ *
+ * @return
+ *  - 0  on success
+ *  - EIO  if an error occurred with any step
+ */
+int hosal_i2c_slave_recv(hosal_i2c_dev_t *i2c, uint8_t *data, uint16_t size, uint32_t timeout);
+
+/**
+ * @brief I2c mem write
+ *
+ * @param[in]  i2c            the i2c device
+ * @param[in]  dev_addr       device address
+ * @param[in]  mem_addr       mem address
+ * @param[in]  mem_addr_size  mem address
+ * @param[in]  data           i2c master send data
+ * @param[in]  size           i2c master send data size
+ * @param[in]  timeout        timeout in milisecond, set this value to HAL_WAIT_FOREVER
+ *                            if you want to wait forever
+ *
+ * @return
+ *  - 0  on success
+ *  - EIO  if an error occurred with any step
+ */
+int hosal_i2c_mem_write(hosal_i2c_dev_t *i2c, uint16_t dev_addr, uint32_t mem_addr,
+                          uint16_t mem_addr_size, const uint8_t *data, uint16_t size,
+                          uint32_t timeout);
+
+/**
+ * @brief I2c master mem read
+ *
+ * @param[in]   i2c            the i2c device
+ * @param[in]   dev_addr       device address
+ * @param[in]   mem_addr       mem address
+ * @param[in]   mem_addr_size  mem address
+ * @param[out]  data           i2c master send data
+ * @param[in]   size           i2c master send data size
+ * @param[in]  timeout         timeout in milisecond, set this value to HAL_WAIT_FOREVER
+ *                             if you want to wait forever
+ *
+ * @return
+ *  - 0  on success
+ *  - EIO  if an error occurred with any step
+ */
+int hosal_i2c_mem_read(hosal_i2c_dev_t *i2c, uint16_t dev_addr, uint32_t mem_addr,
+                         uint16_t mem_addr_size, uint8_t *data, uint16_t size,
+                         uint32_t timeout);
+
+/**
+ * @brief Deinitialises an I2C device
+ *
+ * @param[in]  i2c  the i2c device
+ *
+ * @return
+ *  - 0  on success
+ *  - EIO  if an error occurred with any step
+ */
+int hosal_i2c_finalize(hosal_i2c_dev_t *i2c);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __HOSAL_I2C_H_ */
+
+/* end of file */

+ 175 - 0
bsp/bl808/m0/libraries/platform/hosal/include/hosal_pwm.h

@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __HOSAL_PWM_H__
+#define __HOSAL_PWM_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @addtogroup hosal_pwm PWM
+ *  HOSAL PWM API
+ *
+ *  @{
+ */
+
+#include <stdint.h>
+/**
+ * @brief pwm config struct
+ *
+ */
+typedef struct {
+    uint8_t    pin;        /**< pwm pin  */
+    uint32_t   duty_cycle; /**< the pwm duty_cycle 0 ~ 10000(0 ~ 100%)*/
+    uint32_t   freq;       /**< the pwm freq,range is between 0 and 40M */
+} hosal_pwm_config_t;
+
+/**
+ * @brief pwm dev struct
+ *
+ */
+typedef struct {
+    uint8_t       port;         /**< pwm port */
+    hosal_pwm_config_t  config; /**< pwm config */
+    void         *priv;         /**< priv data */
+} hosal_pwm_dev_t;
+
+/**
+ * @brief Initialises a PWM pin
+ *
+ * @param[in]  pwm  the PWM device
+ *
+ * @return  
+ *     -  0 : success
+ *     - other: fail
+ */
+int hosal_pwm_init(hosal_pwm_dev_t *pwm);
+
+/**
+ * @brief Starts Pulse-Width Modulation signal output on a PWM pin
+ *
+ * @param[in]  pwm  the PWM device
+ *
+ * @return  
+ *     - 0 : success
+ *     - other : fail 
+ */
+int hosal_pwm_start(hosal_pwm_dev_t *pwm);
+
+/**
+ * @brief Stops output on a PWM pin
+ *
+ * @param[in]  pwm  the PWM device
+ *
+ * @return  
+ *     -  0 : success
+ *     - other: fail
+ */
+int hosal_pwm_stop(hosal_pwm_dev_t *pwm);
+
+/**
+ * @change the para of pwm
+ *
+ * @param[in]  pwm   the PWM device
+ * @param[in]  para  the para of pwm
+ *
+ * @return  
+ *     -  0 : success
+ *     - other: fail
+ */
+int hosal_pwm_para_chg(hosal_pwm_dev_t *pwm, hosal_pwm_config_t para);
+
+/**
+ * @brief update PWM frequency
+ *
+ * @param[in]  pwm   the PWM device
+ * @param[in]  freq  the PWM frequency (0~40M under limited duty)
+ *
+ * @return  
+ *     -  0 : success
+ *     - other: fail
+ */
+int hosal_pwm_freq_set(hosal_pwm_dev_t *pwm, uint32_t freq);
+
+/**
+ * @brief get PWM frequency
+ *
+ * @param[in]  pwm   the PWM device
+ * @param[out] p_freq  the pointer to memory frequency
+ *
+ * @return  
+ *     -  0 : success
+ *     - other: fail
+ */
+int hosal_pwm_freq_get(hosal_pwm_dev_t *pwm, uint32_t *p_freq);
+
+/**
+ * @brief set PWM duty
+ *
+ * @param[in]  pwm   the PWM device
+ * @param[in]  duty        the PWM duty (original duty * 100)
+ *
+ * @return  
+ *     -  0 : success
+ *     - other: fail
+ */
+int hosal_pwm_duty_set(hosal_pwm_dev_t *pwm, uint32_t duty);
+
+/**
+ * @brief get PWM duty
+ *
+ * @param[in]  pwm   the PWM device
+ * @param[out] p_duty  the pointer to memory duty(original duty * 100)
+ *
+ * @return  
+ *     -  0 : success
+ *     - other: fail
+ */
+int hosal_pwm_duty_get(hosal_pwm_dev_t *pwm, uint32_t *p_duty);
+
+/**
+ * @brief De-initialises an PWM interface, Turns off an PWM hardware interface
+ *
+ * @param[in]  pwm  the interface which should be de-initialised
+ *
+ * @return  
+ *     -  0 : success
+ *     - other: fail
+ */
+int hosal_pwm_finalize(hosal_pwm_dev_t *pwm);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_PWM_H */
+

+ 74 - 0
bsp/bl808/m0/libraries/platform/hosal/include/hosal_rng.h

@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef HAL_RNG_H
+#define HAL_RNG_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @addtogroup hosal_rng RNG
+ *  HOSAL RNG API
+ *
+ *  @{
+ */
+
+#include <stdint.h>
+
+/**
+ * @brief init rng
+ *
+ * @return  
+ *     -  0 : success
+ *     - other: fail
+ */
+int hosal_rng_init(void);
+
+/**
+ * @brief Fill in a memory buffer with random data
+ *
+ * @param[out]  buf          Point to a valid memory buffer, this function will fill
+ *                           in this memory with random numbers after executed
+ * @param[in]   bytes        Length of the memory buffer (bytes)
+ *
+ * @return  
+ *     -  0 : success
+ *     - other: fail
+ */
+int hosal_random_num_read(void *buf, uint32_t bytes);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_RNG_H */
+

+ 146 - 0
bsp/bl808/m0/libraries/platform/hosal/include/hosal_rtc.h

@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __HAL_RTC_H__
+#define __HAL_RTC_H__
+
+/** @addtogroup hal_rtc RTC
+ *  rtc hal API.
+ *
+ *  @{
+ */
+
+#include <stdint.h>
+
+#define HOSAL_RTC_FORMAT_DEC 1 /**< RTC DEC format */
+#define HOSAL_RTC_FORMAT_BCD 2 /**< RTC BCD format */
+
+/**
+ * @brief rtc config struct
+ */
+typedef struct {
+    uint8_t format; /**< time formart DEC or BCD */
+} hosal_rtc_config_t;
+
+/**
+ * @brief rtc dev struct
+ */
+typedef struct {
+    uint8_t       port;   /**< rtc port */
+    hosal_rtc_config_t  config; /**< rtc config */
+    void         *priv;   /**< priv data */
+} hosal_rtc_dev_t;
+
+/**
+ * @brief RTC time struct
+ */
+typedef struct {
+    uint8_t sec;     /**< DEC format:value range from 0 to 59, BCD format:value range from 0x00 to 0x59 */
+    uint8_t min;     /**< DEC format:value range from 0 to 59, BCD format:value range from 0x00 to 0x59 */
+    uint8_t hr;      /**< DEC format:value range from 0 to 23, BCD format:value range from 0x00 to 0x23 */
+    uint8_t date;    /**< DEC format:value range from 1 to 31, BCD format:value range from 0x01 to 0x31 */
+    uint8_t month;   /**< DEC format:value range from 1 to 12, BCD format:value range from 0x01 to 0x12 */
+    uint16_t year;   /**< DEC format:value range from 0 to 9999, BCD format:value range from 0x0000 to 0x9999 */
+} hosal_rtc_time_t;
+
+/**
+ * @brief This function will initialize the on board CPU real time clock
+ *
+ *
+ * @param[in]  rtc  rtc device
+ *
+ * @return  
+ *     - 0 : success
+ *     - other : fail 
+ */
+int hosal_rtc_init(hosal_rtc_dev_t *rtc);
+
+/**
+ * @brief This function will set MCU RTC time to a new value.
+ *
+ * @param[in]   rtc   rtc device
+ * @param[in]   time  pointer to a time structure
+ *
+ * @return  
+ *     - 0 : success
+ *     - other : fail 
+ */
+int hosal_rtc_set_time(hosal_rtc_dev_t *rtc, const hosal_rtc_time_t *time);
+
+/**
+ * @brief This function will return the value of time read from the on board CPU real time clock.
+ *
+ * @param[in]   rtc   rtc device
+ * @param[out]  time  pointer to a time structure
+ *
+ * @return  
+ *     - 0 : success
+ *     - other : fail 
+ */
+int hosal_rtc_get_time(hosal_rtc_dev_t *rtc, hosal_rtc_time_t *time);
+
+/**
+ * @brief This function will set MCU RTC time to a new value.
+ *
+ * @param[in]   rtc   rtc device
+ * @param[in]   time_stamp  new time value
+ *
+ * @return  
+ *     - 0 : success
+ *     - other : fail 
+ */
+int hosal_rtc_set_count(hosal_rtc_dev_t *rtc, uint64_t *time_stamp);
+
+/**
+ * @brief This function will return the value of time read from the on board CPU real time clock.
+ *
+ * @param[in]   rtc   rtc device
+ * @param[in]   time_stamp new time value 
+ *
+ * @return  
+ *     - 0 : success
+ *     - other : fail 
+ */
+int hosal_rtc_get_count(hosal_rtc_dev_t *rtc, uint64_t *time_stamp);
+
+/**
+ * @brief De-initialises an RTC interface, Turns off an RTC hardware interface
+ *
+ * @param[in]  RTC  the interface which should be de-initialised
+ *
+ * @return  
+ *     - 0 : success
+ *     - other : fail 
+ */
+int hosal_rtc_finalize(hosal_rtc_dev_t *rtc);
+
+/** @} */
+
+#endif /* HAL_RTC_H */
+

+ 178 - 0
bsp/bl808/m0/libraries/platform/hosal/include/hosal_spi.h

@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef HAL_SPI_H
+#define HAL_SPI_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @addtogroup hosal_spi SPI 
+ *  HOSAL SPI API
+ *
+ *  @{
+ */
+
+#include <stdint.h>
+#include <FreeRTOS.h>
+#include <event_groups.h>
+
+#define HOSAL_SPI_MODE_MASTER 0  /**< spi communication is master mode */
+#define HOSAL_SPI_MODE_SLAVE  1  /**< spi communication is slave mode */
+#define HOSAL_WAIT_FOREVER  0xFFFFFFFFU /**< DMA transmission timeout */
+
+typedef void (*hosal_spi_irq_t)(void *parg); /**< spi irq callback function */
+
+/** 
+ * @brief Define spi config args 
+ */
+typedef struct {
+    uint8_t mode;           /**< spi communication mode */
+    uint8_t dma_enable;     /**< enable dma tansmission or not */
+    uint8_t polar_phase;    /**< spi polar and phase */
+    uint32_t freq;          /**< communication frequency Hz */
+    uint8_t pin_clk;        /**< spi clk pin */
+    uint8_t pin_mosi;       /**< spi mosi pin */
+    uint8_t pin_miso;       /**< spi miso pin */
+} hosal_spi_config_t;
+
+/** 
+ * @brief Define spi dev handle
+ */
+typedef struct {
+    uint8_t port;               /**< spi port */
+    hosal_spi_config_t  config; /**< spi config */
+    hosal_spi_irq_t cb;         /**< spi interrupt callback */
+    void *p_arg;                /**< arg pass to callback */
+    void *priv;                 /**< priv data */
+} hosal_spi_dev_t;
+
+/**
+ * @brief Initialises the SPI interface for a given SPI device
+ *
+ * @param[in]  spi  the spi device
+ *
+ * @return  
+ *       - 0 : on success 
+ *       - other : error
+ */
+int hosal_spi_init(hosal_spi_dev_t *spi);
+
+/**
+ * @brief Spi send
+ *
+ * @param[in]  spi      the spi device
+ * @param[in]  data     spi send data
+ * @param[in]  size     spi send data size
+ * @param[in]  timeout  timeout in milisecond, set this value to HAL_WAIT_FOREVER
+ *                      if you want to wait forever
+ *
+ * @return  
+ *       - 0 : on success  
+ *       - other : error
+ */
+int hosal_spi_send(hosal_spi_dev_t *spi, const uint8_t *data, uint32_t size, uint32_t timeout);
+
+/**
+ * @brief Spi recv
+ *
+ * @param[in]   spi      the spi device
+ * @param[out]  data     spi recv data
+ * @param[in]   size     spi recv data size
+ * @param[in]   timeout  timeout in milisecond, set this value to HAL_WAIT_FOREVER
+ *                       if you want to wait forever
+ *
+ * @return  
+ *       - 0 : success
+ *       - other : error
+ */
+int hosal_spi_recv(hosal_spi_dev_t *spi, uint8_t *data, uint16_t size, uint32_t timeout);
+
+/**
+ * @brief spi send data and recv
+ *
+ * @param[in]  spi      the spi device
+ * @param[in]  tx_data  spi send data
+ * @param[out] rx_data  spi recv data
+ * @param[in]  size     spi data to be sent and recived
+ * @param[in]  timeout  timeout in milisecond, set this value to HAL_WAIT_FOREVER
+ *                      if you want to wait forever
+ *
+ * @return  
+ *        - 0 : success 
+ *        - other : error
+ */
+int hosal_spi_send_recv(hosal_spi_dev_t *spi, uint8_t *tx_data, uint8_t *rx_data, uint16_t size, uint32_t timeout);
+
+/*
+ * @brief set spi irq callback
+ *
+ * @param spi the spi device
+ * @param pfn callback function
+ * @param p_arg callback function parameter
+ *
+ * @return 
+ *       - 0 : success
+ *       - othe : error
+ */
+int hosal_spi_irq_callback_set(hosal_spi_dev_t *spi, hosal_spi_irq_t pfn, void *p_arg);
+
+/**
+ * @brief spi software set cs pin high/low only for master device
+ *
+ * @param[in] pin    cs pin
+ * @param[in] value  0 or 1
+ *
+ * @return  
+ *       - 0 : success
+ *       - other : error
+ */
+int hosal_spi_set_cs(uint8_t pin, uint8_t value);
+
+/**
+ * @brief De-initialises a SPI interface
+ *
+ *
+ * @param[in]  spi  the SPI device to be de-initialised
+ *
+ * @return 
+ *       - 0 : success 
+ *       - other : error
+ */
+int hosal_spi_finalize(hosal_spi_dev_t *spi);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_SPI_H */
+

+ 118 - 0
bsp/bl808/m0/libraries/platform/hosal/include/hosal_timer.h

@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef HOSAL_TIMER_H
+#define HOSAL_TIMER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @addtogroup hal_timer TIMER
+ *  timer hal API.
+ *
+ *  @{
+ */
+
+#include <stdint.h>
+
+#define TIMER_RELOAD_PERIODIC 1 /**< timer reload automatic */
+#define TIMER_RELOAD_ONCE     2 /**< timer reload once and need to reload manually */
+
+typedef void (*hosal_timer_cb_t)(void *arg); /**< Define timer handle function type */
+
+/**
+ * Define timer config args 
+ */
+typedef struct {
+    uint32_t          period;         /**< timer period, us */
+    uint8_t           reload_mode;    /**< auto reload or not */
+    hosal_timer_cb_t  cb;             /**< timer handle when expired */
+    void              *arg;           /**< timer handle args */
+} hosal_timer_config_t;
+
+/** 
+ * Define timer dev handle 
+ */
+typedef struct {
+    int8_t                port;   /**< timer port */
+    hosal_timer_config_t  config; /**< timer config */
+    void                  *priv;   /**< priv data */
+} hosal_timer_dev_t;
+
+/**
+ * init a hardware timer
+ *
+ * @param[in]  tim  timer device
+ *
+ * @return  
+ *       - 0 : success 
+ *       - other :error
+ */
+int hosal_timer_init(hosal_timer_dev_t *tim);
+
+/**
+ * start a hardware timer
+ *
+ * @param[in]  tim  timer device
+ *
+ * @return
+ *       - 0 : success 
+ *       - other : error
+ */
+int hosal_timer_start(hosal_timer_dev_t *tim);
+
+/**
+ * stop a hardware timer
+ *
+ * @param[in]  tim  timer device
+ *
+ * @return  none
+ */
+void hosal_timer_stop(hosal_timer_dev_t *tim);
+
+/**
+ * De-initialises an TIMER interface, Turns off an TIMER hardware interface
+ *
+ * @param[in]  tim  timer device
+ *
+ * @return  
+ *       - 0 : success
+ *       - other : error
+ */
+int hosal_timer_finalize(hosal_timer_dev_t *tim);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_TIMER_H */
+

+ 356 - 0
bsp/bl808/m0/libraries/platform/hosal/include/hosal_uart.h

@@ -0,0 +1,356 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __HOSAL_UART_H__
+#define __HOSAL_UART_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @addtogroup hosal_uart UART
+ *  HOSAL UART API
+ *
+ *  @{
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include "hosal_dma.h"
+
+#define HOSAL_UART_AUTOBAUD_0X55     1   /**< @brief UART auto baudrate detection using codeword 0x55 */
+#define HOSAL_UART_AUTOBAUD_STARTBIT 2   /**< @brief UART auto baudrate detection using start bit */
+
+#define HOSAL_UART_TX_CALLBACK       1   /**< @brief UART tx idle interrupt callback */
+#define HOSAL_UART_RX_CALLBACK       2   /**< @brief UART rx complete callback */
+#define HOSAL_UART_TX_DMA_CALLBACK   3   /**< @brief UART tx DMA trans complete callback */
+#define HOSAL_UART_RX_DMA_CALLBACK   4   /**< @brief UART rx DMA trans complete callback */
+
+#define HOSAL_UART_BAUD_SET          1   /**< @brief UART baud set */
+#define HOSAL_UART_BAUD_GET          2   /**< @brief UART baud get */
+#define HOSAL_UART_DATA_WIDTH_SET    3   /**< @brief UART data width set */
+#define HOSAL_UART_DATA_WIDTH_GET    4   /**< @brief UART data width get */
+#define HOSAL_UART_STOP_BITS_SET     5   /**< @brief UART stop bits set */
+#define HOSAL_UART_STOP_BITS_GET     6   /**< @brief UART stop bits get */
+#define HOSAL_UART_FLOWMODE_SET      7   /**< @brief UART flow mode set */
+#define HOSAL_UART_FLOWSTAT_GET      8   /**< @brief UART flow state get */
+#define HOSAL_UART_PARITY_SET        9   /**< @brief UART flow mode set */
+#define HOSAL_UART_PARITY_GET       10   /**< @brief UART flow state get */
+#define HOSAL_UART_MODE_SET         11   /**< @brief UART mode set */
+#define HOSAL_UART_MODE_GET         12   /**< @brief UART mode get */
+#define HOSAL_UART_FREE_TXFIFO_GET  13   /**< @brief UART free tx fifo get */
+#define HOSAL_UART_FREE_RXFIFO_GET  14   /**< @brief UART free rx fifo get */
+#define HOSAL_UART_FLUSH            15   /**< @brief Wait for the send to complete */
+#define HOSAL_UART_TX_TRIGGER_ON    16   /**< @brief UART TX trigger on */
+#define HOSAL_UART_TX_TRIGGER_OFF   17   /**< @brief UART TX trigger off */
+#define HOSAL_UART_DMA_TX_START     18   /**< @brief UART DMA TX start trans */
+#define HOSAL_UART_DMA_RX_START     19   /**< @brief UART DMA RX start trans */
+
+/**
+ * @brief hosal uart callback
+ *
+ * @param[in] p_arg  Set the custom parameters specified when the callback function is set
+ *
+ * @return
+ *  - 0 : on success
+ *  - EIO : if an error occurred with any step
+ */
+typedef int (*hosal_uart_callback_t)(void *p_arg);
+
+/**
+ * @brief UART data width
+ */
+typedef enum {
+    HOSAL_DATA_WIDTH_5BIT,
+    HOSAL_DATA_WIDTH_6BIT,
+    HOSAL_DATA_WIDTH_7BIT,
+    HOSAL_DATA_WIDTH_8BIT,
+    HOSAL_DATA_WIDTH_9BIT
+} hosal_uart_data_width_t;
+
+/**
+ * @brief UART stop bits
+ */
+typedef enum {
+    HOSAL_STOP_BITS_1 = 1,
+    HOSAL_STOP_BITS_2 = 3
+} hosal_uart_stop_bits_t;
+
+/**
+ * @brief UART flow control
+ */
+typedef enum {
+    HOSAL_FLOW_CONTROL_DISABLED,
+    HOSAL_FLOW_CONTROL_RTS,
+    HOSAL_FLOW_CONTROL_CTS,
+    HOSAL_FLOW_CONTROL_CTS_RTS
+} hosal_uart_flow_control_t;
+
+/**
+ * @brief UART parity
+ */
+typedef enum {
+    HOSAL_NO_PARITY,
+    HOSAL_ODD_PARITY,
+    HOSAL_EVEN_PARITY
+} hosal_uart_parity_t;
+
+/**
+ * @brief UART mode
+ */
+typedef enum {
+    HOSAL_UART_MODE_POLL,            /**< @brief UART poll mode (default mode) */
+    HOSAL_UART_MODE_INT_TX,          /**< @brief UART TX int mode */
+    HOSAL_UART_MODE_INT_RX,          /**< @brief UART RX int mode */
+    HOSAL_UART_MODE_INT,             /**< @brief UART TX and RX int mode */
+} hosal_uart_mode_t;
+
+/**
+ * @brief UART DMA configuration
+ */
+typedef struct {
+    /**
+     * @brief UART DMA trans buffer
+     * When the transmission is TX, the address is the src address
+     * When the transmission is RX, the address is the dest address
+     */
+    uint8_t *dma_buf;
+
+    uint32_t dma_buf_size; 	/**< @brief UART DMA trans buffer size */
+} hosal_uart_dma_cfg_t;
+
+/**
+ * @brief UART configuration
+ */
+typedef struct {
+    uint8_t                   uart_id;	/**< @brief UART id */
+    uint8_t                   tx_pin;		/**< @brief UART tx pin */
+    uint8_t                   rx_pin;		/**< @brief UART rx pin */
+    uint8_t                   cts_pin;	/**< @brief UART cts pin */
+    uint8_t                   rts_pin;	/**< @brief UART rts pin */
+    uint32_t                  baud_rate;	/**< @brief UART baud rate */
+    hosal_uart_data_width_t   data_width;	/**< @brief UART data width */
+    hosal_uart_parity_t       parity;		/**< @brief UART parity bit */
+    hosal_uart_stop_bits_t    stop_bits;	/**< @brief UART stop btis */
+    hosal_uart_flow_control_t flow_control;	/**< @brief UART flow control */
+    hosal_uart_mode_t         mode;		/**< @brief UART int or pull mode */
+} hosal_uart_config_t;
+
+/**
+ * @brief UART device type
+ */
+typedef struct {
+    uint8_t       port;			/**< @brief UART port */
+    hosal_uart_config_t config;		/**< @brief UART config */
+    hosal_uart_callback_t tx_cb;		/**< @brief UART tx callback */
+    void *p_txarg;				/**< @brief UART tx callback arg */
+    hosal_uart_callback_t rx_cb;		/**< @brief UART rx callback */
+    void *p_rxarg;				/**< @brief UART rx callback arg */
+    hosal_uart_callback_t txdma_cb;		/**< @brief UART tx dma callback */
+    void *p_txdma_arg;				/**< @brief UART tx dma callback arg */
+    hosal_uart_callback_t rxdma_cb;		/**< @brief UART rx dma callback */
+    void *p_rxdma_arg;				/**< @brief UART rx dma callback arg */
+    hosal_dma_chan_t dma_tx_chan;		/**< @brief UART dma tx channel */
+    hosal_dma_chan_t dma_rx_chan;		/**< @brief UART dma rx channel */
+    void         *priv;			/**< @brief UART private data */
+} hosal_uart_dev_t;
+
+/**
+ * @brief define a UART default config
+ *
+ * @param[in] cfg  config define
+ * @param[in] id  uart id
+ * @param[in] tx  uart tx pin
+ * @param[in] rx  uart rx pin
+ * @param[in] baud  uart baud
+ *
+ */
+#define HOSAL_UART_CFG_DECL(cfg, id, tx, rx, baud) \
+    hosal_uart_config_t cfg =  {                   \
+        .uart_id = id,                             \
+        .tx_pin = tx,                              \
+        .rx_pin = rx,                              \
+        .cts_pin = 255,                            \
+        .rts_pin = 255,                            \
+        .baud_rate = baud,                         \
+        .data_width = HOSAL_DATA_WIDTH_8BIT,       \
+        .parity = HOSAL_NO_PARITY,                 \
+        .stop_bits = HOSAL_STOP_BITS_1,            \
+        .mode = HOSAL_UART_MODE_POLL,              \
+    };
+
+/**
+ * @brief define a UART device
+ *
+ * @param[in] dev  uart device
+ * @param[in] id  uart id
+ * @param[in] tx  uart tx pin
+ * @param[in] rx  uart rx pin
+ * @param[in] baud  uart baud
+ */
+#define HOSAL_UART_DEV_DECL(dev, id, tx, rx, baud) \
+    hosal_uart_dev_t dev = {                       \
+        .config =  {                               \
+            .uart_id = id,                         \
+            .tx_pin = tx,                          \
+            .rx_pin = rx,                          \
+            .cts_pin = 255,                        \
+            .rts_pin = 255,                        \
+            .baud_rate = baud,                     \
+            .data_width = HOSAL_DATA_WIDTH_8BIT,   \
+            .parity = HOSAL_NO_PARITY,             \
+            .stop_bits = HOSAL_STOP_BITS_1,        \
+            .mode = HOSAL_UART_MODE_POLL,          \
+        },                                         \
+    };
+/**
+ * @brief Get auto baudrate on a UART interface
+ *
+ * @param[in]  uart    the UART interface
+ * @param[in]  mode    auto baudrate detection mode(codeword 0x55 or start bit)
+ *
+ * @return  
+ *	- = 0    on success
+ *	- EIO  if an error occurred with any step
+ */
+int hosal_uart_abr_get(hosal_uart_dev_t *uart, uint8_t mode);
+
+/**
+ * @brief Initialises a UART interface
+ *
+ * @param[in]  uart  the interface which should be initialised
+ *
+ * @return  
+ *	- 0    on success
+ *	- EIO  if an error occurred with any step
+ */
+int hosal_uart_init(hosal_uart_dev_t *uart);
+
+/**
+ * @brief Poll transmit data on a UART interface
+ *
+ * @param[in]  uart     the UART interface
+ * @param[in]  txbuf    pointer to the start of data
+ * @param[in]  size     number of bytes to transmit
+ *
+ * @return  
+ *	- > 0  on success
+ *	- EIO  if an error occurred with any step
+ */
+int hosal_uart_send(hosal_uart_dev_t *uart, const void *txbuf, uint32_t size);
+
+/**
+ * @brief Poll receive data on a UART interface
+ *
+ * @param[in]   uart         the UART interface
+ * @param[out]  rxbuf        pointer to the buffer which will store incoming data
+ * @param[in]   expect_size  expect number of bytes to receive
+ *
+ * @return  
+ *	- > 0  number of bytes to receive
+ *	- EIO  if an error occurred with any step
+ */
+int hosal_uart_receive(hosal_uart_dev_t *uart, void *data, uint32_t expect_size);
+
+/**
+ * @brief hal uart ioctl
+ *
+ * @param[in] uart   the UART interface
+ * @param[in] ctl  Control request
+ *   - HOSAL_UART_BAUD_SET : baud set, p_arg is baud
+ *   - HOSAL_UART_BAUD_GET : baud get, p_arg is baud's pointer
+ *   - HOSAL_UART_DATA_WIDTH_SET : set data width,p_arg is hosal_uart_data_width_t
+ *   - HOSAL_UART_DATA_WIDTH_GET : get data width,p_arg is hosal_uart_data_width_t's pointer
+ *   - HOSAL_UART_STOP_BITS_SET : set stop bits, p_arg is hosal_uart_stop_bits_t
+ *   - HOSAL_UART_STOP_BITS_GET : get stop bits, p_arg is hosal_uart_stop_bits_t's pointer
+ *   - HOSAL_UART_PARITY_SET : set parity, p_arg is hosal_uart_parity_t
+ *   - HOSAL_UART_PARITY_GET : get parity, p_arg is hosal_uart_parity_t's pointer
+ *   - HOSAL_UART_MODE_SET : UART mode set, p_arg is hosal_uart_mode_t
+ *   - HOSAL_UART_MODE_GET : UART mode get, p_arg is hosal_uart_mode_t's pointer
+ *   - HOSAL_UART_FLOWMODE_SET : UART flow mode set, p_arg is hosal_uart_flow_control_t
+ *   - HOSAL_UART_FLOWSTAT_GET : UART flow state get, p_arg is hosal_uart_flow_control_t's pointer
+ *   - HOSAL_UART_FREE_TXFIFO_GET : get uart free tx fifo size (bytes)
+ *   - HOSAL_UART_FREE_RXFIFO_GET : get uart free rx fifo size (bytes)
+ *   - HOSAL_UART_FLUSH : Wait for the send to complete
+ *   - HOSAL_UART_TX_TRIGGER_ON : UART TX trigger on
+ *   - HOSAL_UART_TX_TRIGGER_OFF : UART TX trigger off
+ *   - HOSAL_UART_DMA_CONFIG : p_arg is hosal_uart_dma_cfg_t's pointer
+ *   - HOSAL_UART_DMA_TX_START : UART DMA TX start trans p_arg is hosal_uart_dma_cfg_t's pointer
+ *   - HOSAL_UART_DMA_RX_START : UART DMA RX start trans p_arg is hosal_uart_dma_cfg_t's pointer
+ *
+ * @param[in,out] p_arg  parameter
+ *
+ * @return  
+ *	- 0    on success
+ *	- EIO  if an error occurred with any step
+ */
+int hosal_uart_ioctl (hosal_uart_dev_t *uart, int ctl, void *p_arg);
+
+/**
+ * @brief hal uart callback set
+ *
+ * @param[in]  uart     the UART interface
+ * @param[in] callback_type   callback type
+ *            - HOSAL_UART_TX_CALLBACK
+ *            - HOSAL_UART_RX_CALLBACK
+ *            - HOSAL_UART_TX_DMA_CALLBACK
+ *            - HOSAL_UART_RX_DMA_CALLBACK
+ * @param[in] pfn_callback  callback function
+ * @param[in] arg  callback function parameter
+ *
+ * @return  
+ *	- 0    on success
+ *	- EIO  if an error occurred with any step
+ */
+int hosal_uart_callback_set (hosal_uart_dev_t *uart,
+                           int callback_type,
+                           hosal_uart_callback_t pfn_callback,
+                           void *arg);
+
+/**
+ * @brief Deinitialises a UART interface
+ *
+ * @param[in]  uart  the interface which should be deinitialised
+ *
+ * @return  
+ *	- 0    on success
+ *	- EIO  if an error occurred with any step
+ */
+int hosal_uart_finalize(hosal_uart_dev_t *uart);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __HOSAL_UART_H__ */
+
+/* end of file */

+ 99 - 0
bsp/bl808/m0/libraries/platform/hosal/include/hosal_wdg.h

@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef HAL_WDG_H
+#define HAL_WDG_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @addtogroup hosal_wdg WATCHDOG 
+ *  HOSAL WATCHDOG API
+ *
+ *  @{
+ */
+
+#include <stdint.h>
+
+/**
+ * @brief wdg config struct
+ *
+ */
+typedef struct {
+    uint32_t timeout; /*!< Watchdag timeout in ms*/
+} hosal_wdg_config_t;
+
+/**
+ * @brief wdg dev struct
+ *
+ */
+typedef struct {
+    uint8_t       port;   /**< wdg port */
+    hosal_wdg_config_t  config; /**< wdg config */
+    void         *priv;   /**< priv data */
+} hosal_wdg_dev_t;
+
+/**
+ * @brief This function will initialize the on board CPU hardware watch dog
+ *
+ * @param[in]  wdg  the watch dog device
+ *
+ * @return  
+ *     -  0 : success
+ *     - other: fail
+ */
+int hosal_wdg_init(hosal_wdg_dev_t *wdg);
+
+/**
+ * @brief Reload watchdog counter.
+ *
+ * @param[in]  wdg  the watch dog device
+ */
+void hosal_wdg_reload(hosal_wdg_dev_t *wdg);
+
+/**
+ * @brief This function performs any platform-specific cleanup needed for hardware watch dog.
+ *
+ * @param[in]  wdg  the watch dog device
+ *
+ * @return  
+ *     -  0 : success
+ *     - other: fail
+ */
+int hosal_wdg_finalize(hosal_wdg_dev_t *wdg);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAL_WDG_H */
+

+ 251 - 0
bsp/bl808/m0/libraries/platform/hosal/platform_hal/platform_hal_device.cpp

@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <platform_hal_device.h>
+
+extern "C" void* operator new(size_t size) 
+{
+    /* printf("[C++] new %d\r\n", size); */
+    return pvPortMalloc(size); 
+}
+
+extern "C" void* operator new[](size_t size) 
+{
+    /* printf("[C++] new[] %d\r\n", size); */
+    return pvPortMalloc(size); 
+}
+
+extern "C" void operator delete(void* ptr) {
+    /* printf("[C++] delete %p\r\n", ptr); */
+    vPortFree(ptr);
+}
+
+extern "C" void operator delete[](void* ptr) {
+    /* printf("[C++] delete[] %p\r\n", ptr); */
+    vPortFree(ptr);
+}
+
+BLLinkedItem::BLLinkedItem() 
+{
+    this->next = NULL;
+}
+
+BLLinkedItem* BLLinkedItem::attach(class BLLinkedItem &item)
+{
+    /*assert when next is NOT NULL*/
+    if (this->next) {
+        printf("[ERR] next is NOT NULL. %p -->> %p\r\n", this->next, &item);
+        return NULL;
+    } else if (this == &item) {
+        printf("[ERR] linked to self. %p -->> %p\r\n", this, &item);
+        return NULL;
+    }
+    this->next = &item;
+    return this;
+}
+
+BLLinkedItem* BLLinkedItem::detach()
+{
+    BLLinkedItem *tmp;
+
+    tmp = this->next;
+    this->next = NULL;
+
+    return tmp;
+}
+
+BLLinkedList::BLLinkedList() 
+{
+    this->head = NULL;
+    this->tail = NULL;
+}
+
+BLLinkedList* BLLinkedList::push(class BLLinkedItem &item) 
+{
+    printf("[BLLinkedList] push %p\r\n", &item);
+
+    if (NULL == this->head) {
+        printf("new push\r\n");
+        this->head = &item;
+        this->tail = &item;
+        return this;
+    }
+    /*tail should NOT be NULL, assert here if tail is NULL?*/
+    printf("continue push\r\n");
+    if (NULL == this->tail->attach(item)) {
+        return NULL;
+    }
+    this->tail = &item;
+
+    return this;
+}
+
+BLLinkedItem* BLLinkedList::pop() 
+{
+    BLLinkedItem *item;
+
+    if (NULL == this->head) {
+        printf("NULL HEAD\r\n");
+        return NULL;
+    }
+    item = this->head;
+    this->head = item->detach();
+
+    printf("[POP] POP %p\r\n", item);
+
+    return item;
+}
+
+BLAesRequest::BLAesRequest()
+{
+    memset(this->key, 0, sizeof(this->key));
+    memset(this->iv, 0, sizeof(this->iv));
+    this->src = NULL;
+    this->dst = NULL;
+    this->len = 0;
+    this->first_use = 0;
+}
+
+BLAesRequest::BLAesRequest(uint8_t *key, uint8_t *iv, uint8_t *src, uint8_t *dst, int len)
+{
+    memcpy(this->key, key, sizeof(this->key));
+    if (iv) {
+        memcpy(this->iv, iv, sizeof(this->iv));
+    }
+    this->src = src;
+    this->dst = dst;
+    this->len = len;
+    this->first_use = 0;
+}
+
+int BLAesRequest::done_pre(int use_encryption)
+{
+    this->task_handle = xTaskGetCurrentTaskHandle();
+    this->done = 0;
+    this->is_encryption = use_encryption;
+
+    return 0;
+}
+
+int BLAesRequest::done_wait()
+{
+    while (0 == this->done) {
+        ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
+    }
+    return 0;
+}
+
+int BLAesRequest::done_set()
+{
+    this->done = 1;
+    xTaskNotifyGive(this->task_handle);
+
+    return 0;
+}
+
+int BLAesRequest::done_set_auto()
+{
+    this->done = 1;
+    //TODO 
+    printf("[C++] [%s] ongoing...\r\n", __PRETTY_FUNCTION__);
+
+    return 0;
+}
+
+int BLAesRequest::done_set_FromISR()
+{
+    BaseType_t xHigherPriorityTaskWoken;
+
+    this->done = 1;
+    vTaskNotifyGiveFromISR(this->task_handle, &xHigherPriorityTaskWoken);
+    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
+
+    return 0;
+}
+
+int BLAesEngine::encryption(BLAesRequest &req)
+{
+    printf("%s %p...\r\n", __PRETTY_FUNCTION__, &req);
+
+    /*request prepare*/
+    req.done_pre(1);
+    /*push to queue and trigger if necessary*/
+    if (NULL == this->push(req)) {
+        return -1;
+    }
+    this->encryption_trigger();
+    /*request wait*/
+    req.done_wait();
+
+    return 0;
+}
+
+void BLAesEngine::encryption_trigger()
+{
+    /*Trigger SOFTIRQ if necessary*/
+    return;
+}
+
+void BLAesEngine::decryption_trigger()
+{
+    /*Trigger SOFTIRQ if necessary*/
+    return;
+}
+
+int BLAesEngine::decryption(BLAesRequest &req)
+{
+    printf("%s %p...\r\n", __PRETTY_FUNCTION__, &req);
+
+    /*request prepare*/
+    req.done_pre(0);
+    /*push to queue and trigger if necessary*/
+    if (NULL == this->push(req)) {
+        return -1;
+    }
+    this->decryption_trigger();
+    /*request wait*/
+    req.done_wait();
+
+    return 0;
+}
+
+static class BLAesEngine *aes_engine;
+extern "C" int platform_hal_device_init(void)
+{
+    class BLAesRequest *aes_request = new BLAesRequest[6];
+    aes_engine = new BLAesEngine();
+
+    (void)aes_request;
+#if 0
+    aes_engine->encryption(aes_request[0]);
+#endif
+
+    return 0;
+}

+ 109 - 0
bsp/bl808/m0/libraries/platform/hosal/platform_hal/platform_hal_device.h

@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2016-2022 Bouffalolab.
+ *
+ * This file is part of
+ *     *** Bouffalolab Software Dev Kit ***
+ *      (see www.bouffalolab.com).
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of Bouffalo Lab nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __PLATFORM_HAL_DEVICE_H__
+#define __PLATFORM_HAL_DEVICE_H__
+#include <FreeRTOS.h>
+#include <task.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+int platform_hal_device_init(void);
+
+/*TMP solution for getting API from c scope*/
+int printf(const char *fmt, ...);
+void *memcpy(void *dst, const void *src, size_t n);
+void *memset(void *s, int c, size_t n);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#ifdef __cplusplus
+#include <stdint.h>
+
+class BLLinkedItem {
+private:
+    class BLLinkedItem *next;
+public:
+    BLLinkedItem();
+    class BLLinkedItem* attach(class BLLinkedItem &item);
+    class BLLinkedItem* detach();
+};
+
+class BLAesRequest : public BLLinkedItem {
+public:
+    uint32_t key[4];
+    uint32_t iv[4];
+    uint8_t *src;
+    uint8_t *dst;
+    size_t len;
+    int first_use;
+
+    int is_encryption;//0 for encryption, 1 for decryption
+    /*section for task control*/
+    TaskHandle_t task_handle;
+    int done;
+public:
+    BLAesRequest();
+    BLAesRequest(uint8_t *key, uint8_t *iv, uint8_t *src, uint8_t *dst, int len);
+    int done_pre(int use_encryption);
+    int done_wait();
+    int done_set();
+    int done_set_auto();
+    int done_set_FromISR();
+};
+
+class BLLinkedList {
+protected:
+    class BLLinkedItem *head;
+    class BLLinkedItem *tail;
+public:
+    BLLinkedList();
+    class BLLinkedList* push(class BLLinkedItem &item);
+    class BLLinkedItem* pop();
+    class BLLinkedList* dump();
+};
+
+class BLAesEngine : public BLLinkedList {
+private:
+    class BLLinkedList head;
+
+    void encryption_trigger();
+    void decryption_trigger();
+public:
+    int encryption(BLAesRequest &req);
+    int decryption(BLAesRequest &req);
+};
+
+#endif
+
+#endif

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