浏览代码

Merge pull request #3988 from bigmagic123/add_raspi4_watchdog

Add raspi4 watchdog&hdmi&sdio driver
Bernard Xiong 4 年之前
父节点
当前提交
d854416dd7

+ 67 - 7
bsp/raspberry-pi/raspi4-32/.config

@@ -112,7 +112,23 @@ CONFIG_DFS_FILESYSTEMS_MAX=2
 CONFIG_DFS_FILESYSTEM_TYPES_MAX=2
 CONFIG_DFS_FILESYSTEM_TYPES_MAX=2
 CONFIG_DFS_FD_MAX=16
 CONFIG_DFS_FD_MAX=16
 # CONFIG_RT_USING_DFS_MNTTABLE is not set
 # CONFIG_RT_USING_DFS_MNTTABLE is not set
-# CONFIG_RT_USING_DFS_ELMFAT is not set
+CONFIG_RT_USING_DFS_ELMFAT=y
+
+#
+# elm-chan's FatFs, Generic FAT Filesystem Module
+#
+CONFIG_RT_DFS_ELM_CODE_PAGE=437
+CONFIG_RT_DFS_ELM_WORD_ACCESS=y
+# CONFIG_RT_DFS_ELM_USE_LFN_0 is not set
+# CONFIG_RT_DFS_ELM_USE_LFN_1 is not set
+# CONFIG_RT_DFS_ELM_USE_LFN_2 is not set
+CONFIG_RT_DFS_ELM_USE_LFN_3=y
+CONFIG_RT_DFS_ELM_USE_LFN=3
+CONFIG_RT_DFS_ELM_MAX_LFN=255
+CONFIG_RT_DFS_ELM_DRIVES=2
+CONFIG_RT_DFS_ELM_MAX_SECTOR_SIZE=512
+# CONFIG_RT_DFS_ELM_USE_ERASE is not set
+CONFIG_RT_DFS_ELM_REENTRANT=y
 CONFIG_RT_USING_DFS_DEVFS=y
 CONFIG_RT_USING_DFS_DEVFS=y
 # CONFIG_RT_USING_DFS_ROMFS is not set
 # CONFIG_RT_USING_DFS_ROMFS is not set
 # CONFIG_RT_USING_DFS_RAMFS is not set
 # CONFIG_RT_USING_DFS_RAMFS is not set
@@ -140,14 +156,20 @@ CONFIG_RT_USING_PIN=y
 # CONFIG_RT_USING_MTD_NAND is not set
 # CONFIG_RT_USING_MTD_NAND is not set
 # CONFIG_RT_USING_PM is not set
 # CONFIG_RT_USING_PM is not set
 # CONFIG_RT_USING_RTC is not set
 # CONFIG_RT_USING_RTC is not set
-# CONFIG_RT_USING_SDIO is not set
+CONFIG_RT_USING_SDIO=y
+CONFIG_RT_SDIO_STACK_SIZE=512
+CONFIG_RT_SDIO_THREAD_PRIORITY=15
+CONFIG_RT_MMCSD_STACK_SIZE=1024
+CONFIG_RT_MMCSD_THREAD_PREORITY=22
+CONFIG_RT_MMCSD_MAX_PARTITION=16
+# CONFIG_RT_SDIO_DEBUG is not set
 CONFIG_RT_USING_SPI=y
 CONFIG_RT_USING_SPI=y
 # CONFIG_RT_USING_QSPI is not set
 # CONFIG_RT_USING_QSPI is not set
 # CONFIG_RT_USING_SPI_MSD is not set
 # CONFIG_RT_USING_SPI_MSD is not set
 # CONFIG_RT_USING_SFUD is not set
 # CONFIG_RT_USING_SFUD is not set
 # CONFIG_RT_USING_ENC28J60 is not set
 # CONFIG_RT_USING_ENC28J60 is not set
 # CONFIG_RT_USING_SPI_WIFI is not set
 # CONFIG_RT_USING_SPI_WIFI is not set
-# CONFIG_RT_USING_WDT is not set
+CONFIG_RT_USING_WDT=y
 # CONFIG_RT_USING_AUDIO is not set
 # CONFIG_RT_USING_AUDIO is not set
 # CONFIG_RT_USING_SENSOR is not set
 # CONFIG_RT_USING_SENSOR is not set
 # CONFIG_RT_USING_TOUCH is not set
 # CONFIG_RT_USING_TOUCH is not set
@@ -170,6 +192,7 @@ CONFIG_RT_USING_LIBC=y
 CONFIG_RT_USING_POSIX=y
 CONFIG_RT_USING_POSIX=y
 # CONFIG_RT_USING_POSIX_MMAP is not set
 # CONFIG_RT_USING_POSIX_MMAP is not set
 # CONFIG_RT_USING_POSIX_TERMIOS is not set
 # CONFIG_RT_USING_POSIX_TERMIOS is not set
+# CONFIG_RT_USING_POSIX_GETLINE is not set
 # CONFIG_RT_USING_POSIX_AIO is not set
 # CONFIG_RT_USING_POSIX_AIO is not set
 # CONFIG_RT_USING_MODULE is not set
 # CONFIG_RT_USING_MODULE is not set
 
 
@@ -216,7 +239,9 @@ CONFIG_RT_USING_POSIX=y
 #
 #
 # IoT - internet of things
 # IoT - internet of things
 #
 #
+# CONFIG_PKG_USING_LORAWAN_DRIVER is not set
 # CONFIG_PKG_USING_PAHOMQTT 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_WEBCLIENT is not set
 # CONFIG_PKG_USING_WEBNET is not set
 # CONFIG_PKG_USING_WEBNET is not set
 # CONFIG_PKG_USING_MONGOOSE is not set
 # CONFIG_PKG_USING_MONGOOSE is not set
@@ -262,7 +287,7 @@ CONFIG_RT_USING_POSIX=y
 # CONFIG_PKG_USING_GAGENT_CLOUD is not set
 # CONFIG_PKG_USING_GAGENT_CLOUD is not set
 # CONFIG_PKG_USING_ALI_IOTKIT is not set
 # CONFIG_PKG_USING_ALI_IOTKIT is not set
 # CONFIG_PKG_USING_AZURE is not set
 # CONFIG_PKG_USING_AZURE is not set
-# CONFIG_PKG_USING_TENCENT_IOTHUB is not set
+# CONFIG_PKG_USING_TENCENT_IOT_EXPLORER is not set
 # CONFIG_PKG_USING_JIOT-C-SDK is not set
 # CONFIG_PKG_USING_JIOT-C-SDK is not set
 # CONFIG_PKG_USING_UCLOUD_IOT_SDK is not set
 # CONFIG_PKG_USING_UCLOUD_IOT_SDK is not set
 # CONFIG_PKG_USING_JOYLINK is not set
 # CONFIG_PKG_USING_JOYLINK is not set
@@ -284,6 +309,10 @@ CONFIG_RT_USING_POSIX=y
 # CONFIG_PKG_USING_CAPNP is not set
 # CONFIG_PKG_USING_CAPNP is not set
 # CONFIG_PKG_USING_RT_CJSON_TOOLS is not set
 # CONFIG_PKG_USING_RT_CJSON_TOOLS is not set
 # CONFIG_PKG_USING_AGILE_TELNET is not set
 # CONFIG_PKG_USING_AGILE_TELNET is not set
+# CONFIG_PKG_USING_NMEALIB is not set
+# CONFIG_PKG_USING_AGILE_JSMN is not set
+# CONFIG_PKG_USING_PDULIB is not set
+# CONFIG_PKG_USING_BTSTACK is not set
 
 
 #
 #
 # security packages
 # security packages
@@ -292,6 +321,7 @@ CONFIG_RT_USING_POSIX=y
 # CONFIG_PKG_USING_libsodium is not set
 # CONFIG_PKG_USING_libsodium is not set
 # CONFIG_PKG_USING_TINYCRYPT is not set
 # CONFIG_PKG_USING_TINYCRYPT is not set
 # CONFIG_PKG_USING_TFM is not set
 # CONFIG_PKG_USING_TFM is not set
+# CONFIG_PKG_USING_YD_CRYPTO is not set
 
 
 #
 #
 # language packages
 # language packages
@@ -308,6 +338,7 @@ CONFIG_RT_USING_POSIX=y
 # CONFIG_PKG_USING_STEMWIN is not set
 # CONFIG_PKG_USING_STEMWIN is not set
 # CONFIG_PKG_USING_WAVPLAYER is not set
 # CONFIG_PKG_USING_WAVPLAYER is not set
 # CONFIG_PKG_USING_TJPGD is not set
 # CONFIG_PKG_USING_TJPGD is not set
+# CONFIG_PKG_USING_HELIX is not set
 
 
 #
 #
 # tools packages
 # tools packages
@@ -326,7 +357,9 @@ CONFIG_RT_USING_POSIX=y
 # CONFIG_PKG_USING_CHINESE_FONT_LIBRARY is not set
 # CONFIG_PKG_USING_CHINESE_FONT_LIBRARY is not set
 # CONFIG_PKG_USING_LUNAR_CALENDAR is not set
 # CONFIG_PKG_USING_LUNAR_CALENDAR is not set
 # CONFIG_PKG_USING_BS8116A 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_URLENCODE is not set
+# CONFIG_PKG_USING_UMCN is not set
 
 
 #
 #
 # system packages
 # system packages
@@ -337,6 +370,7 @@ CONFIG_RT_USING_POSIX=y
 # CONFIG_PKG_USING_LWEXT4 is not set
 # CONFIG_PKG_USING_LWEXT4 is not set
 # CONFIG_PKG_USING_PARTITION is not set
 # CONFIG_PKG_USING_PARTITION is not set
 # CONFIG_PKG_USING_FAL is not set
 # CONFIG_PKG_USING_FAL is not set
+# CONFIG_PKG_USING_FLASHDB is not set
 # CONFIG_PKG_USING_SQLITE is not set
 # CONFIG_PKG_USING_SQLITE is not set
 # CONFIG_PKG_USING_RTI is not set
 # CONFIG_PKG_USING_RTI is not set
 # CONFIG_PKG_USING_LITTLEVGL2RTT is not set
 # CONFIG_PKG_USING_LITTLEVGL2RTT is not set
@@ -349,6 +383,11 @@ CONFIG_RT_USING_POSIX=y
 # CONFIG_PKG_USING_SYSWATCH is not set
 # CONFIG_PKG_USING_SYSWATCH is not set
 # CONFIG_PKG_USING_SYS_LOAD_MONITOR is not set
 # CONFIG_PKG_USING_SYS_LOAD_MONITOR is not set
 # CONFIG_PKG_USING_PLCCORE 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_UCOSIII_WRAPPER is not set
+# CONFIG_PKG_USING_PPOOL is not set
 
 
 #
 #
 # peripheral libraries and drivers
 # peripheral libraries and drivers
@@ -386,6 +425,7 @@ CONFIG_RT_USING_POSIX=y
 # CONFIG_PKG_USING_RPLIDAR is not set
 # CONFIG_PKG_USING_RPLIDAR is not set
 # CONFIG_PKG_USING_AS608 is not set
 # CONFIG_PKG_USING_AS608 is not set
 # CONFIG_PKG_USING_RC522 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_EMBARC_BSP is not set
 # CONFIG_PKG_USING_EXTERN_RTC_DRIVERS is not set
 # CONFIG_PKG_USING_EXTERN_RTC_DRIVERS is not set
 # CONFIG_PKG_USING_MULTI_RTIMER is not set
 # CONFIG_PKG_USING_MULTI_RTIMER is not set
@@ -393,6 +433,15 @@ CONFIG_RT_USING_POSIX=y
 # CONFIG_PKG_USING_BEEP is not set
 # CONFIG_PKG_USING_BEEP is not set
 # CONFIG_PKG_USING_EASYBLINK is not set
 # CONFIG_PKG_USING_EASYBLINK is not set
 # CONFIG_PKG_USING_PMS_SERIES 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_PAJ7620 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
 
 
 #
 #
 # miscellaneous packages
 # miscellaneous packages
@@ -429,6 +478,11 @@ CONFIG_RT_USING_POSIX=y
 # CONFIG_PKG_USING_VT100 is not set
 # CONFIG_PKG_USING_VT100 is not set
 # CONFIG_PKG_USING_ULAPACK is not set
 # CONFIG_PKG_USING_ULAPACK is not set
 # CONFIG_PKG_USING_UKAL is not set
 # CONFIG_PKG_USING_UKAL is not set
+# CONFIG_PKG_USING_CRCLIB is not set
+# CONFIG_PKG_USING_THREES is not set
+# CONFIG_PKG_USING_2048 is not set
+# CONFIG_PKG_USING_LWGPS is not set
+# CONFIG_PKG_USING_TENSORFLOWLITEMICRO is not set
 
 
 #
 #
 # Privated Packages of RealThread
 # Privated Packages of RealThread
@@ -461,6 +515,10 @@ CONFIG_RT_USING_POSIX=y
 # CONFIG_PKG_USING_ZBAR is not set
 # CONFIG_PKG_USING_ZBAR is not set
 # CONFIG_PKG_USING_MCF is not set
 # CONFIG_PKG_USING_MCF is not set
 # CONFIG_PKG_USING_URPC is not set
 # CONFIG_PKG_USING_URPC is not set
+# CONFIG_PKG_USING_BSAL is not set
+# CONFIG_PKG_USING_DCM is not set
+# CONFIG_PKG_USING_EMQ is not set
+# CONFIG_PKG_USING_CFGM is not set
 CONFIG_BCM2711_SOC=y
 CONFIG_BCM2711_SOC=y
 # CONFIG_BSP_SUPPORT_FPU is not set
 # CONFIG_BSP_SUPPORT_FPU is not set
 
 
@@ -487,11 +545,13 @@ CONFIG_BSP_USING_SPI0_DEVICE0=y
 # CONFIG_BSP_USING_SPI0_DEVICE1 is not set
 # CONFIG_BSP_USING_SPI0_DEVICE1 is not set
 CONFIG_BSP_USING_CORETIMER=y
 CONFIG_BSP_USING_CORETIMER=y
 # CONFIG_BSP_USING_SYSTIMER is not set
 # CONFIG_BSP_USING_SYSTIMER is not set
-# CONFIG_BSP_USING_WDT is not set
+CONFIG_BSP_USING_WDT=y
 # CONFIG_BSP_USING_RTC is not set
 # CONFIG_BSP_USING_RTC is not set
-# CONFIG_BSP_USING_SDIO is not set
+CONFIG_BSP_USING_SDIO=y
+CONFIG_BSP_USING_SDIO0=y
 
 
 #
 #
 # Board Peripheral Drivers
 # Board Peripheral Drivers
 #
 #
-# CONFIG_BSP_USING_HDMI is not set
+CONFIG_BSP_USING_HDMI=y
+CONFIG_BSP_USING_HDMI_DISPLAY=y

+ 83 - 22
bsp/raspberry-pi/raspi4-32/README.md

@@ -20,45 +20,99 @@ scons
 来编译这个板级支持包。如果编译正确无误,会产生rtthread.elf、kernel7.img文件。
 来编译这个板级支持包。如果编译正确无误,会产生rtthread.elf、kernel7.img文件。
 
 
 
 
-## 3. 执行
+## 3. 环境搭建
+### 3.1 准备好串口线
 
 
-### 3.1 下载**Raspberry Pi Imager**,生成可以运行的raspbian SD卡
+目前版本是使用raspi4的 GPIO 14, GPIO 15来作路口输出,连线情况如下图所示:
 
 
-首先下载镜像
+![raspi2](../raspi3-32/figures/raspberrypi-console.png)
 
 
-* [Raspberry Pi Imager for Ubuntu](https://downloads.raspberrypi.org/imager/imager_amd64.deb)
-* [Raspberry Pi Imager for Windows](https://downloads.raspberrypi.org/imager/imager.exe)
-* [Raspberry Pi Imager for macOS](https://downloads.raspberrypi.org/imager/imager.dmg)
+串口参数: 115200 8N1 ,硬件和软件流控为关。
 
 
-### 3.2 准备好串口线
+### 3.2 RTT固件放在SD卡运行
 
 
-目前版本是使用raspi4的 GPIO 14, GPIO 15来作路口输出,连线情况如下图所示:
+首先需要准备一张空的32GB以下的SD卡,如果不想自己制作启动固件,可以直接从百度网盘上下载boot的固件。
 
 
-![raspi2](../raspi3-32/figures/raspberrypi-console.png)
+```
+链接:https://pan.baidu.com/s/1PxgvXAChUIOgueNXhgMs8w 
+提取码:pioj 
+```
 
 
-串口参数: 115200 8N1 ,硬件和软件流控为关。
+解压后将sd目录下的文件拷贝到sd卡即可。以后每次编译后,将生成的kernel7.img进行替换即可。上电后可以看到程序正常运行。
+
+### 3.3 RTT程序用uboot加载
 
 
-### 3.3 程序下载
+为了调试方便,已经将uboot引导程序放入uboot目录下,直接将这些文件放到sd卡中即可。
 
 
-当编译生成了rtthread.bin文件后,我们可以将该文件放到sd卡上,并修改sd卡中的`config.txt`文件如下:
+需要注意的以下步骤:
+
+**1.电脑上启动tftp服务器**
+
+windows系统电脑上可以安装tftpd搭建tftp服务器。将目录指定到`bsp\raspberry-pi\raspi4-32`。
+
+**2.修改设置uboot**
+
+在控制台输入下列命令:
 
 
 ```
 ```
-enable_uart=1
-arm_64bit=0
-kernel_addr=0x8000
-kernel=kernel7.img
-core_freq=250
+setenv bootcmd "dhcp 0x00200000 x.x.x.x:kernel7.img;dcache flush;go 0x00200000"
+saveenv
+reset
 ```
 ```
 
 
-按上面的方法做好SD卡后,插入树莓派4,通电可以在串口上看到如下所示的输出信息:
+其中`x.x.x.x`为tftp服务器的pc的ip地址。
 
 
-```text
-heap: 0x00044270 - 0x04044270
+**3.修改链接脚本**
+
+将树莓派`bsp\raspberry-pi\raspi4-32\link.ld`的文件链接地址改为`0x200000`。
+
+```
+SECTIONS
+{
+    . = 0x8000;
+    . = ALIGN(4096);
+    .
+    .
+    .
+}
+```
+
+改为
+
+```
+SECTIONS
+{
+    . = 0x200000;
+    . = ALIGN(4096);
+    .
+    .
+    .
+}
+```
+
+重新编译程序:
+
+```
+scons -c
+scons
+```
+
+**3.插入网线**
+
+上述准备完成后,将网线插入,保证开发板和tftp服务器在同一个网段的路由器上。上电后uboot可以自动从tftp服务器上获取固件,然后开始执行了。
+
+完成后可以看到串口的输出信息
+
+```
+heap: 0x000607e8 - 0x040607e8
 
 
  \ | /
  \ | /
 - RT -     Thread Operating System
 - RT -     Thread Operating System
- / | \     4.0.3 build May 25 2020
+ / | \     4.0.3 build Oct 27 2020
  2006 - 2020 Copyright by rt-thread team
  2006 - 2020 Copyright by rt-thread team
+[I/SDIO] SD card capacity 31205376 KB.
+found part[0], begin: 1048576, size: 29.777GB
+file system initialization done!
 Hi, this is RT-Thread!!
 Hi, this is RT-Thread!!
 msh />
 msh />
 ```
 ```
@@ -71,8 +125,15 @@ msh />
 | GPIO | 支持 | - |
 | GPIO | 支持 | - |
 | SPI | 支持 | SPI0 |
 | SPI | 支持 | SPI0 |
 | MAILBOX | 支持 | - |
 | MAILBOX | 支持 | - |
+| WATCHDOG | 支持 | - |
+| HDMI | 支持 | - |
+| SDIO | 支持 | - |
+
+## 5. 注意事项
+
+目前rt-thread程序可以使用的内存在100MB以内,可以通过调整`board.c`中`platform_mem_desc`表的数据进行相关内存的映射以及修改`board.h`来确定程序使用的堆栈大小。目前在地址`0x08000000`处的1M空间被映射成非cache区供树莓派4的CPU与GPU通信的消息管道。若需要扩大系统内存使用,可自行修改代码进行调整。
 
 
-## 5. 联系人信息
+## 6. 联系人信息
 
 
 维护人:[bernard][5]
 维护人:[bernard][5]
 
 

+ 13 - 1
bsp/raspberry-pi/raspi4-32/applications/main.c

@@ -12,8 +12,20 @@
 #include <rtdevice.h>
 #include <rtdevice.h>
 #include <board.h>
 #include <board.h>
 
 
+#define     ACTLED      (42)
+
 int main(int argc, char** argv)
 int main(int argc, char** argv)
 {
 {
     rt_kprintf("Hi, this is RT-Thread!!\n");
     rt_kprintf("Hi, this is RT-Thread!!\n");
-    return 0;
+    
+    rt_pin_mode(ACTLED, PIN_MODE_OUTPUT);
+
+    while(1)
+    {
+        rt_pin_write(ACTLED, PIN_HIGH);
+        rt_thread_mdelay(1000);
+        rt_pin_write(ACTLED, PIN_LOW);
+        rt_thread_mdelay(1000);
+    }
+    return RT_EOK;
 }
 }

+ 27 - 0
bsp/raspberry-pi/raspi4-32/applications/mnt.c

@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2006-2019, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2017-5-30     bernard       the first version
+ */
+
+#include <rtthread.h>
+
+#ifdef BSP_USING_SDIO0
+#include <dfs_fs.h>
+
+int mnt_init(void)
+{
+    rt_thread_delay(RT_TICK_PER_SECOND);
+    if (dfs_mount("sd0", "/", "elm", 0, 0) == 0)
+    {
+        rt_kprintf("file system initialization done!\n");
+    }
+
+    return 0;
+}
+INIT_ENV_EXPORT(mnt_init);
+#endif

+ 4 - 2
bsp/raspberry-pi/raspi4-32/driver/board.c

@@ -19,8 +19,10 @@
 
 
 struct mem_desc platform_mem_desc[] = {
 struct mem_desc platform_mem_desc[] = {
     {0x0, 0x6400000, 0x0, NORMAL_MEM},
     {0x0, 0x6400000, 0x0, NORMAL_MEM},
-    {0xFE000000, 0xFE400000, 0xFE000000, DEVICE_MEM},//uart gpio
-    {0xFF800000, 0xFFA00000, 0xFF800000, DEVICE_MEM} //gic
+    {0x8000000, 0x8100000, 0x8000000, DEVICE_MEM},    //mbox msg
+    {0x0EA00000, 0x0EE00000, 0x0EA00000, DEVICE_MEM}, //framebuffer
+    {0xFE000000, 0xFE400000, 0xFE000000, DEVICE_MEM}, //peripheral
+    {0xFF800000, 0xFFA00000, 0xFF800000, DEVICE_MEM}  //gic
 };
 };
 
 
 const rt_uint32_t platform_mem_desc_size = sizeof(platform_mem_desc)/sizeof(platform_mem_desc[0]);
 const rt_uint32_t platform_mem_desc_size = sizeof(platform_mem_desc)/sizeof(platform_mem_desc[0]);

+ 309 - 0
bsp/raspberry-pi/raspi4-32/driver/drv_hdmi.c

@@ -0,0 +1,309 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author         Notes
+ * 2020-10-26     bigmagic       first version
+ */
+
+#include <stdint.h>
+#include <rtthread.h>
+#include "mbox.h"
+#include "drv_hdmi.h"
+
+#ifdef BSP_USING_HDMI
+#define LCD_WIDTH     (800)
+#define LCD_HEIGHT    (480)
+#define LCD_DEPTH     (32)
+#define LCD_BPP       (32)
+
+#define TAG_ALLOCATE_BUFFER         0x00040001
+#define TAG_SET_PHYS_WIDTH_HEIGHT   0x00048003
+#define TAG_SET_VIRT_WIDTH_HEIGHT   0x00048004
+#define TAG_SET_DEPTH               0x00048005
+#define TAG_SET_PIXEL_ORDER         0x00048006
+#define TAG_GET_PITCH               0x00040008
+#define TAG_SET_VIRT_OFFSET         0x00048009
+#define TAG_END                     0x00000000
+
+
+enum {
+    MBOX_TAG_FB_GET_GPIOVIRT        = 0x00040010,
+    MBOX_TAG_FB_ALLOCATE_BUFFER     = 0x00040001,
+    MBOX_TAG_FB_RELEASE_BUFFER      = 0x00048001,
+    MBOX_TAG_FB_BLANK_SCREEN        = 0x00040002,
+    MBOX_TAG_FB_GET_PHYS_WH         = 0x00040003,
+    MBOX_TAG_FB_TEST_PHYS_WH        = 0x00044003,
+    MBOX_TAG_FB_SET_PHYS_WH         = 0x00048003,
+    MBOX_TAG_FB_GET_VIRT_WH         = 0x00040004,
+    MBOX_TAG_FB_TEST_VIRT_WH        = 0x00044004,
+    MBOX_TAG_FB_SET_VIRT_WH         = 0x00048004,
+    MBOX_TAG_FB_GET_DEPTH           = 0x00040005,
+    MBOX_TAG_FB_TEST_DEPTH          = 0x00044005,
+    MBOX_TAG_FB_SET_DEPTH           = 0x00048005,
+    MBOX_TAG_FB_GET_PIXEL_ORDER     = 0x00040006,
+    MBOX_TAG_FB_TEST_PIXEL_ORDER    = 0x00044006,
+    MBOX_TAG_FB_SET_PIXEL_ORDER     = 0x00048006,
+    MBOX_TAG_FB_GET_ALPHA_MODE      = 0x00040007,
+    MBOX_TAG_FB_TEST_ALPHA_MODE     = 0x00044007,
+    MBOX_TAG_FB_SET_ALPHA_MODE      = 0x00048007,
+    MBOX_TAG_FB_GET_PITCH           = 0x00040008,
+    MBOX_TAG_FB_GET_VIRT_OFFSET     = 0x00040009,
+    MBOX_TAG_FB_TEST_VIRT_OFFSET    = 0x00044009,
+    MBOX_TAG_FB_SET_VIRT_OFFSET     = 0x00048009,
+    MBOX_TAG_FB_GET_OVERSCAN        = 0x0004000a,
+    MBOX_TAG_FB_TEST_OVERSCAN       = 0x0004400a,
+    MBOX_TAG_FB_SET_OVERSCAN        = 0x0004800a,
+    MBOX_TAG_FB_GET_PALETTE         = 0x0004000b,
+    MBOX_TAG_FB_TEST_PALETTE        = 0x0004400b,
+    MBOX_TAG_FB_SET_PALETTE         = 0x0004800b,
+};
+
+#define LCD_DEVICE(dev)    (struct rt_hdmi_fb_device*)(dev)
+
+static struct rt_hdmi_fb_device _hdmi;
+
+typedef rt_uint16_t color_t;
+
+rt_err_t hdmi_fb_open(rt_device_t dev, rt_uint16_t oflag)
+{
+    return RT_EOK;
+}
+
+rt_err_t hdmi_fb_close(rt_device_t dev)
+{
+    return RT_EOK;
+}
+
+rt_size_t hdmi_fb_read(rt_device_t dev, rt_off_t pos, void *buf, rt_size_t size)
+{
+    return 0;
+}
+
+rt_size_t hdmi_fb_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
+{
+    return size;
+}
+
+rt_err_t hdmi_fb_control(rt_device_t dev, int cmd, void *args)
+{
+    struct rt_hdmi_fb_device *lcd = LCD_DEVICE(dev);
+    switch (cmd)
+    {
+    case RTGRAPHIC_CTRL_RECT_UPDATE:
+        {
+            struct rt_device_rect_info *info = (struct rt_device_rect_info*)args;
+            info = info;
+        }
+        break;
+
+    case RTGRAPHIC_CTRL_GET_INFO:
+        {
+           struct rt_device_graphic_info* info = (struct rt_device_graphic_info*)args;
+
+            RT_ASSERT(info != RT_NULL);
+            info->pixel_format  = RTGRAPHIC_PIXEL_FORMAT_RGB888;
+            info->bits_per_pixel= LCD_DEPTH;
+            info->width         = lcd->width;
+            info->height        = lcd->height;
+            info->framebuffer   = lcd->fb;
+        }
+        break;
+    }
+    return RT_EOK;
+}
+
+#ifdef RT_USING_DEVICE_OPS
+const static struct rt_device_ops hdmi_fb_ops = 
+{
+    RT_NULL,
+    hdmi_fb_open,
+    hdmi_fb_close,
+    hdmi_fb_read,
+    hdmi_fb_write,
+    hdmi_fb_control,
+};
+#endif
+
+rt_err_t rt_hdmi_fb_device_init(struct rt_hdmi_fb_device *hdmi_fb, const char *name)
+{
+    struct rt_device *device;
+    RT_ASSERT(hdmi_fb != RT_NULL);
+
+    device = &hdmi_fb->parent;
+
+    /* set device type */
+    device->type = RT_Device_Class_Graphic;
+    /* initialize device interface */
+#ifdef RT_USING_DEVICE_OPS
+    device->ops = &hdmi_fb_ops;
+#else
+    device->init = RT_NULL;
+    device->open = hdmi_fb_open;
+    device->close = hdmi_fb_close;
+    device->read = hdmi_fb_read;
+    device->write = hdmi_fb_write;
+    device->control = hdmi_fb_control;
+#endif
+
+    /* register to device manager */
+    rt_device_register(device, name, RT_DEVICE_FLAG_RDWR);
+
+    return RT_EOK;
+}
+
+rt_uint32_t bcm271x_mbox_fb_get_gpiovirt(void)
+{
+    mbox[0] = 8*4;                      // length of the message
+    mbox[1] = MBOX_REQUEST;             // this is a request message
+    
+    mbox[2] = MBOX_TAG_FB_GET_GPIOVIRT;
+    mbox[3] = 4;                        // buffer size
+    mbox[4] = 0;                        // len
+
+    mbox[5] = 0;                        // id
+    mbox[6] = 0;
+
+    mbox[7] = MBOX_TAG_LAST;
+    mbox_call(8, MMU_DISABLE);
+    return (mbox[5] & 0x3fffffff);
+}
+
+rt_uint32_t bcm271x_mbox_fb_get_pitch(void)
+{
+    mbox[0] = 8*4;                  // length of the message
+    mbox[1] = MBOX_REQUEST;         // this is a request message
+    
+    mbox[2] = MBOX_TAG_FB_GET_PITCH;
+    mbox[3] = 4;                    // buffer size
+    mbox[4] = 0;                    // len
+
+    mbox[5] = 0;                    // id
+    mbox[6] = 0;
+
+    mbox[7] = MBOX_TAG_LAST;
+    mbox_call(8, MMU_DISABLE);
+    return mbox[5];
+}
+
+void bcm271x_mbox_fb_set_porder(int rgb)
+{
+    mbox[0] = 8*4;                      // length of the message
+    mbox[1] = MBOX_REQUEST;             // this is a request message
+    
+    mbox[2] = MBOX_TAG_FB_SET_PIXEL_ORDER;
+    mbox[3] = 4;                        // buffer size
+    mbox[4] = 4;                        // len
+
+    mbox[5] = rgb;                      // id
+    mbox[6] = 0;
+
+    mbox[7] = MBOX_TAG_LAST;
+    mbox_call(8, MMU_DISABLE);
+}
+
+void bcm271x_mbox_fb_setoffset(int xoffset, int yoffset)
+{
+    mbox[0] = 8*4;                      // length of the message
+    mbox[1] = MBOX_REQUEST;             // this is a request message
+    
+    mbox[2] = MBOX_TAG_FB_SET_VIRT_OFFSET;
+    mbox[3] = 8;                        // buffer size
+    mbox[4] = 8;                        // len
+
+    mbox[5] = xoffset;                  // id
+    mbox[6] = yoffset;
+
+    mbox[7] = MBOX_TAG_LAST;
+    mbox_call(8, MMU_DISABLE);
+}
+
+
+void bcm271x_mbox_fb_setalpha(int alpha)
+{
+
+    mbox[0] = 8*4;                      // length of the message
+    mbox[1] = MBOX_REQUEST;             // this is a request message
+    
+    mbox[2] = MBOX_TAG_FB_SET_ALPHA_MODE;
+    mbox[3] = 4;                        // buffer size
+    mbox[4] = 4;                        // len
+
+    mbox[5] = alpha;                    // id
+    mbox[6] = 0;
+
+    mbox[7] = MBOX_TAG_LAST;
+    mbox_call(8, MMU_DISABLE);
+}
+
+void *bcm271x_mbox_fb_alloc(int width, int height, int bpp, int nrender)
+{
+    mbox[0] = 4 * 35;
+    mbox[1] = MBOX_REQUEST;
+
+    mbox[2] = TAG_ALLOCATE_BUFFER;//get framebuffer, gets alignment on request
+    mbox[3] = 8;                  //size
+    mbox[4] = 4;                  //len
+    mbox[5] = 4096;               //The design of MBOX driver forces us to give the virtual address 0x3C100000
+    mbox[6] = 0;                  //FrameBufferInfo.size
+
+    mbox[7] = TAG_SET_PHYS_WIDTH_HEIGHT;
+    mbox[8] = 8;
+    mbox[9] = 8;
+    mbox[10] = width;
+    mbox[11] = height;
+
+    mbox[12] = TAG_SET_VIRT_WIDTH_HEIGHT;
+    mbox[13] = 8;
+    mbox[14] = 8;
+    mbox[15] = width;
+    mbox[16] = height * nrender;
+
+    mbox[17] = TAG_SET_DEPTH;
+    mbox[18] = 4;
+    mbox[19] = 4;
+    mbox[20] = bpp;
+
+    mbox[21] = TAG_SET_PIXEL_ORDER;
+    mbox[22] = 4;
+    mbox[23] = 0;
+    mbox[24] = 0;                    //RGB, not BGR preferably
+
+    mbox[25] = TAG_GET_PITCH;
+    mbox[26] = 4;
+    mbox[27] = 0;
+    mbox[28] = 0;
+
+    mbox[29] = TAG_SET_VIRT_OFFSET;
+    mbox[30] = 8;
+    mbox[31] = 8;
+    mbox[32] = 0;
+    mbox[33] = 0;
+
+    mbox[34] = TAG_END;
+
+    mbox_call(8, MMU_DISABLE);
+    return (void *)((rt_uint32_t)(mbox[5] & 0x3fffffff));
+}
+
+int hdmi_fb_init(void)
+{
+    _hdmi.fb = (rt_uint8_t *)bcm271x_mbox_fb_alloc(LCD_WIDTH, LCD_HEIGHT, LCD_BPP, 1);
+    bcm271x_mbox_fb_setoffset(0, 0);
+    bcm271x_mbox_fb_set_porder(0);
+    _hdmi.width = LCD_WIDTH;
+    _hdmi.height = LCD_HEIGHT;
+    _hdmi.depth = LCD_DEPTH;
+    _hdmi.pitch = 0;
+    _hdmi.pixel_format = RTGRAPHIC_PIXEL_FORMAT_RGB888;
+
+    //rt_kprintf("_hdmi.fb is %p\n", _hdmi.fb);
+    rt_hdmi_fb_device_init(&_hdmi, "lcd");
+
+    return 0;
+}
+
+INIT_DEVICE_EXPORT(hdmi_fb_init);
+#endif /*BSP_USING_HDMI */

+ 27 - 0
bsp/raspberry-pi/raspi4-32/driver/drv_hdmi.h

@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author         Notes
+ * 2020-10-26     bigmagic       first version
+ */
+#ifndef __DRV_HDMI_H__
+#define __DRV_HDMI_H__
+
+#define RGB(r, g, b) ((((r))<<16) | (((g))<<8) | ((b)))
+
+struct rt_hdmi_fb_device
+{
+    struct rt_device parent;
+
+    rt_uint32_t width;
+    rt_uint32_t height;
+    rt_uint32_t depth;
+    rt_uint32_t pitch;
+    rt_uint32_t pixel_format;
+
+    rt_uint8_t *fb;
+};
+#endif/* __DRV_HDMI_H__ */

+ 656 - 0
bsp/raspberry-pi/raspi4-32/driver/drv_sdio.c

@@ -0,0 +1,656 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author         Notes
+ * 2020-10-27     bigmagic       first version
+ */
+
+#include "mbox.h"
+#include "raspi4.h"
+#include "drv_sdio.h"
+
+static rt_uint32_t mmc_base_clock = 0;
+
+static rt_uint32_t sdCommandTable[] = {
+    SD_CMD_INDEX(0),
+    SD_CMD_RESERVED(1),
+    SD_CMD_INDEX(2) | SD_RESP_R2,
+    SD_CMD_INDEX(3) | SD_RESP_R1,
+    SD_CMD_INDEX(4),
+    SD_CMD_RESERVED(5), //SD_CMD_INDEX(5) | SD_RESP_R4,
+    SD_CMD_INDEX(6) | SD_RESP_R1,
+    SD_CMD_INDEX(7) | SD_RESP_R1b,
+    SD_CMD_INDEX(8) | SD_RESP_R1,
+    SD_CMD_INDEX(9) | SD_RESP_R2,
+    SD_CMD_INDEX(10) | SD_RESP_R2,
+    SD_CMD_INDEX(11) | SD_RESP_R1,
+    SD_CMD_INDEX(12) | SD_RESP_R1b | SD_CMD_TYPE_ABORT,
+    SD_CMD_INDEX(13) | SD_RESP_R1,
+    SD_CMD_RESERVED(14),
+    SD_CMD_INDEX(15),
+    SD_CMD_INDEX(16) | SD_RESP_R1,
+    SD_CMD_INDEX(17) | SD_RESP_R1 | SD_DATA_READ,
+    SD_CMD_INDEX(18) | SD_RESP_R1 | SD_DATA_READ | SD_CMD_MULTI_BLOCK | SD_CMD_BLKCNT_EN,
+    SD_CMD_INDEX(19) | SD_RESP_R1 | SD_DATA_READ,
+    SD_CMD_INDEX(20) | SD_RESP_R1b,
+    SD_CMD_RESERVED(21),
+    SD_CMD_RESERVED(22),
+    SD_CMD_INDEX(23) | SD_RESP_R1,
+    SD_CMD_INDEX(24) | SD_RESP_R1 | SD_DATA_WRITE,
+    SD_CMD_INDEX(25) | SD_RESP_R1 | SD_DATA_WRITE | SD_CMD_MULTI_BLOCK | SD_CMD_BLKCNT_EN,
+    SD_CMD_INDEX(26) | SD_RESP_R1 | SD_DATA_WRITE, //add
+    SD_CMD_INDEX(27) | SD_RESP_R1 | SD_DATA_WRITE,
+    SD_CMD_INDEX(28) | SD_RESP_R1b,
+    SD_CMD_INDEX(29) | SD_RESP_R1b,
+    SD_CMD_INDEX(30) | SD_RESP_R1 | SD_DATA_READ,
+    SD_CMD_RESERVED(31),
+    SD_CMD_INDEX(32) | SD_RESP_R1,
+    SD_CMD_INDEX(33) | SD_RESP_R1,
+    SD_CMD_RESERVED(34),
+    SD_CMD_INDEX(35) | SD_RESP_R1, //add
+    SD_CMD_INDEX(36) | SD_RESP_R1, //add
+    SD_CMD_RESERVED(37),
+    SD_CMD_INDEX(38) | SD_RESP_R1b,
+    SD_CMD_INDEX(39) | SD_RESP_R4, //add
+    SD_CMD_INDEX(40) | SD_RESP_R5, //add
+    SD_CMD_INDEX(41) | SD_RESP_R3, //add, mov from harbote
+    SD_CMD_RESERVED(42) | SD_RESP_R1,
+    SD_CMD_RESERVED(43),
+    SD_CMD_RESERVED(44),
+    SD_CMD_RESERVED(45),
+    SD_CMD_RESERVED(46),
+    SD_CMD_RESERVED(47),
+    SD_CMD_RESERVED(48),
+    SD_CMD_RESERVED(49),
+    SD_CMD_RESERVED(50),
+    SD_CMD_INDEX(51) | SD_RESP_R1 | SD_DATA_READ,
+    SD_CMD_RESERVED(52),
+    SD_CMD_RESERVED(53),
+    SD_CMD_RESERVED(54),
+    SD_CMD_INDEX(55) | SD_RESP_R3,
+    SD_CMD_INDEX(56) | SD_RESP_R1 | SD_CMD_ISDATA,
+    SD_CMD_RESERVED(57),
+    SD_CMD_RESERVED(58),
+    SD_CMD_RESERVED(59),
+    SD_CMD_RESERVED(60),
+    SD_CMD_RESERVED(61),
+    SD_CMD_RESERVED(62),
+    SD_CMD_RESERVED(63)
+};
+
+static inline rt_uint32_t read32(rt_uint32_t addr)
+{
+    return (*((volatile unsigned int*)(addr)));
+}
+
+static inline void write32(rt_uint32_t addr, rt_uint32_t value)
+{
+    (*((volatile unsigned int*)(addr))) = value;
+}
+
+rt_err_t sd_int(struct sdhci_pdata_t * pdat, rt_uint32_t mask)
+{
+    rt_uint32_t r;
+    rt_uint32_t m = mask | INT_ERROR_MASK;
+    int cnt = 1000000;
+    while (!(read32(pdat->virt + EMMC_INTERRUPT) & (m | INT_ERROR_MASK)) && cnt--)
+        DELAY_MICROS(1);
+    r = read32(pdat->virt + EMMC_INTERRUPT);
+    if (cnt <= 0 || (r & INT_CMD_TIMEOUT) || (r & INT_DATA_TIMEOUT))
+    {
+        write32(pdat->virt + EMMC_INTERRUPT, r);
+        //qemu maybe can not use sdcard
+        //rt_kprintf("send cmd/data timeout wait for %x int: %x, status: %x\n",mask, r, read32(pdat->virt + EMMC_STATUS));
+        //return -RT_ETIMEOUT;
+    }
+    else if (r & INT_ERROR_MASK)
+    {
+        write32(pdat->virt + EMMC_INTERRUPT, r);
+        rt_kprintf("send cmd/data error %x -> %x\n",r, read32(pdat->virt + EMMC_INTERRUPT));
+        return -RT_ERROR;
+    }
+    write32(pdat->virt + EMMC_INTERRUPT, mask);
+    return RT_EOK;
+}
+
+rt_err_t sd_status(struct sdhci_pdata_t * pdat, unsigned int mask)
+{
+    int cnt = 500000;
+    while ((read32(pdat->virt + EMMC_STATUS) & mask) && !(read32(pdat->virt + EMMC_INTERRUPT) & INT_ERROR_MASK) && cnt--)
+        DELAY_MICROS(1);
+    if (cnt <= 0)
+    {
+        return -RT_ETIMEOUT;
+    }
+    else if (read32(pdat->virt + EMMC_INTERRUPT) & INT_ERROR_MASK)
+    {
+        return  -RT_ERROR;
+    } 
+
+    return RT_EOK;
+}
+
+static rt_err_t raspi_transfer_command(struct sdhci_pdata_t * pdat, struct sdhci_cmd_t * cmd)
+{
+    rt_uint32_t cmdidx;
+    rt_err_t ret = RT_EOK;
+    ret = sd_status(pdat, SR_CMD_INHIBIT);
+    if (ret)
+    {
+        rt_kprintf("ERROR: EMMC busy %d\n", ret);
+        return ret;
+    }
+
+    cmdidx = sdCommandTable[cmd->cmdidx];
+    if (cmdidx == 0xFFFFFFFF)
+        return -RT_EINVAL;
+    if (cmd->datarw == DATA_READ)
+        cmdidx |= SD_DATA_READ;
+    if (cmd->datarw == DATA_WRITE)
+        cmdidx |= SD_DATA_WRITE;
+    mmcsd_dbg("transfer cmd %x(%d) %x %x\n", cmdidx, cmd->cmdidx, cmd->cmdarg, read32(pdat->virt + EMMC_INTERRUPT));
+    write32(pdat->virt + EMMC_INTERRUPT,read32(pdat->virt + EMMC_INTERRUPT));
+    write32(pdat->virt + EMMC_ARG1, cmd->cmdarg);
+    write32(pdat->virt + EMMC_CMDTM, cmdidx);
+    if (cmd->cmdidx == SD_APP_OP_COND)
+        DELAY_MICROS(1000);
+    else if ((cmd->cmdidx == SD_SEND_IF_COND) || (cmd->cmdidx == APP_CMD))
+        DELAY_MICROS(100);
+
+    ret = sd_int(pdat, INT_CMD_DONE);
+    if (ret)
+    {
+        return ret;
+    }
+    if (cmd->resptype & RESP_MASK)
+    {
+
+        if (cmd->resptype & RESP_R2)
+        {
+            rt_uint32_t resp[4];
+            resp[0] = read32(pdat->virt + EMMC_RESP0);
+            resp[1] = read32(pdat->virt + EMMC_RESP1);
+            resp[2] = read32(pdat->virt + EMMC_RESP2);
+            resp[3] = read32(pdat->virt + EMMC_RESP3);
+            if (cmd->resptype == RESP_R2)
+            {
+                cmd->response[0] = resp[3]<<8 |((resp[2]>>24)&0xff);
+                cmd->response[1] = resp[2]<<8 |((resp[1]>>24)&0xff);
+                cmd->response[2] = resp[1]<<8 |((resp[0]>>24)&0xff);
+                cmd->response[3] = resp[0]<<8 ;
+            }
+            else
+            {
+                cmd->response[0] = resp[0];
+                cmd->response[1] = resp[1];
+                cmd->response[2] = resp[2];
+                cmd->response[3] = resp[3];
+            }
+        }
+        else
+            cmd->response[0] = read32(pdat->virt + EMMC_RESP0);
+    }
+    mmcsd_dbg("response: %x: %x %x %x %x (%x, %x)\n", cmd->resptype, cmd->response[0], cmd->response[1], cmd->response[2], cmd->response[3], read32(pdat->virt + EMMC_STATUS),read32(pdat->virt + EMMC_INTERRUPT));
+    return ret;
+}
+
+static rt_err_t read_bytes(struct sdhci_pdata_t * pdat, rt_uint32_t * buf, rt_uint32_t blkcount, rt_uint32_t blksize)
+{
+    int c = 0;
+    rt_err_t ret;
+    int d;
+    while (c < blkcount)
+    {
+        if ((ret = sd_int(pdat, INT_READ_RDY)))
+        {
+            rt_kprintf("timeout happens when reading block %d\n",c);
+            return ret;
+        }
+        for (d=0; d < blksize / 4; d++)
+            if (read32(pdat->virt + EMMC_STATUS) & SR_READ_AVAILABLE)
+                buf[d] = read32(pdat->virt + EMMC_DATA);
+        c++;
+        buf += blksize / 4;
+    }
+    return RT_EOK;
+}
+
+static rt_err_t write_bytes(struct sdhci_pdata_t * pdat, rt_uint32_t * buf, rt_uint32_t blkcount, rt_uint32_t blksize)
+{
+    int c = 0;
+    rt_err_t ret;
+    int d;
+    while (c < blkcount)
+    {
+        if ((ret = sd_int(pdat, INT_WRITE_RDY)))
+        {
+            return ret;
+        }
+        for (d=0; d < blksize / 4; d++)
+            write32(pdat->virt + EMMC_DATA, buf[d]);
+        c++;
+        buf += blksize / 4;
+    }
+
+    if ((ret = sd_int(pdat, INT_DATA_DONE)))
+    {
+        return ret;
+    }
+    return RT_EOK;
+}
+
+static rt_err_t raspi_transfer_data(struct sdhci_pdata_t * pdat, struct sdhci_cmd_t * cmd, struct sdhci_data_t * dat)
+{
+    rt_uint32_t dlen = (rt_uint32_t)(dat->blkcnt * dat->blksz);
+    rt_err_t ret = sd_status(pdat, SR_DAT_INHIBIT);
+    if (ret)
+    {
+        rt_kprintf("ERROR: EMMC busy\n");
+        return ret;
+    }
+    if (dat->blkcnt > 1)
+    {
+        struct sdhci_cmd_t newcmd;
+        newcmd.cmdidx = SET_BLOCK_COUNT;
+        newcmd.cmdarg = dat->blkcnt;
+        newcmd.resptype = RESP_R1;
+        ret = raspi_transfer_command(pdat, &newcmd);
+        if (ret) return ret;
+    }
+
+    if(dlen < 512)
+    {
+        write32(pdat->virt + EMMC_BLKSIZECNT, dlen | 1 << 16);
+    }
+    else
+    {
+        write32(pdat->virt + EMMC_BLKSIZECNT, 512 | (dat->blkcnt) << 16);
+    }
+    if (dat->flag & DATA_DIR_READ)
+    {
+        cmd->datarw = DATA_READ;
+        ret = raspi_transfer_command(pdat, cmd);
+        if (ret) return ret;
+        mmcsd_dbg("read_block %d, %d\n", dat->blkcnt, dat->blksz );
+        ret = read_bytes(pdat, (rt_uint32_t *)dat->buf, dat->blkcnt, dat->blksz);
+    }
+    else if (dat->flag & DATA_DIR_WRITE)
+    {
+        cmd->datarw = DATA_WRITE;
+        ret = raspi_transfer_command(pdat, cmd);
+        if (ret) return ret;
+        mmcsd_dbg("write_block %d, %d", dat->blkcnt, dat->blksz );
+        ret = write_bytes(pdat, (rt_uint32_t *)dat->buf, dat->blkcnt, dat->blksz);
+    }
+    return ret;
+}
+
+static rt_err_t sdhci_transfer(struct sdhci_t * sdhci, struct sdhci_cmd_t * cmd, struct sdhci_data_t * dat)
+{
+    struct sdhci_pdata_t * pdat = (struct sdhci_pdata_t *)sdhci->priv;
+    if (!dat)
+        return raspi_transfer_command(pdat, cmd);
+
+    return raspi_transfer_data(pdat, cmd, dat);
+}
+
+static void mmc_request_send(struct rt_mmcsd_host *host, struct rt_mmcsd_req *req)
+{
+    struct sdhci_t *sdhci = (struct sdhci_t *)host->private_data;
+    struct sdhci_cmd_t cmd;
+    struct sdhci_cmd_t stop;
+    struct sdhci_data_t dat;
+    rt_memset(&cmd, 0, sizeof(struct sdhci_cmd_t));
+    rt_memset(&stop, 0, sizeof(struct sdhci_cmd_t));
+    rt_memset(&dat, 0, sizeof(struct sdhci_data_t));
+
+    cmd.cmdidx = req->cmd->cmd_code;
+    cmd.cmdarg = req->cmd->arg;
+    cmd.resptype =resp_type(req->cmd);
+    if (req->data)
+    {
+        dat.buf = (rt_uint8_t *)req->data->buf;
+        dat.flag = req->data->flags;
+        dat.blksz = req->data->blksize;
+        dat.blkcnt = req->data->blks;
+
+        req->cmd->err = sdhci_transfer(sdhci, &cmd, &dat);
+    }
+    else
+    {
+        req->cmd->err = sdhci_transfer(sdhci, &cmd, RT_NULL);
+    }
+
+    req->cmd->resp[3] = cmd.response[3];
+    req->cmd->resp[2] = cmd.response[2];
+    req->cmd->resp[1] = cmd.response[1];
+    req->cmd->resp[0] = cmd.response[0];
+
+    if (req->stop)
+    {
+        stop.cmdidx = req->stop->cmd_code;
+        stop.cmdarg = req->stop->arg;
+        cmd.resptype =resp_type(req->stop);
+        req->stop->err = sdhci_transfer(sdhci, &stop, RT_NULL);
+    }
+
+    mmcsd_req_complete(host);
+}
+
+rt_int32_t mmc_card_status(struct rt_mmcsd_host *host)
+{
+    return 0;
+}
+
+static rt_err_t sdhci_detect(struct sdhci_t * sdhci)
+{
+    return RT_EOK;
+}
+
+static rt_err_t sdhci_setwidth(struct sdhci_t * sdhci, rt_uint32_t width)
+{
+    rt_uint32_t temp = 0;
+    struct sdhci_pdata_t * pdat = (struct sdhci_pdata_t *)sdhci->priv;
+    if (width == MMCSD_BUS_WIDTH_4)
+    {
+        temp = read32((pdat->virt + EMMC_CONTROL0));
+        temp |= C0_HCTL_HS_EN;
+        temp |= C0_HCTL_DWITDH;   // always use 4 data lines:
+        write32((pdat->virt + EMMC_CONTROL0), temp);
+    }
+    return RT_EOK;
+}
+
+
+static uint32_t sd_get_clock_divider(rt_uint32_t sdHostVer ,rt_uint32_t base_clock, rt_uint32_t target_rate)
+{
+    rt_uint32_t targetted_divisor = 0;
+    rt_uint32_t freq_select = 0;
+    rt_uint32_t upper_bits = 0;
+    rt_uint32_t ret = 0;
+
+    if(target_rate > base_clock)
+        targetted_divisor = 1;
+    else
+    {
+        targetted_divisor = base_clock / target_rate;
+        rt_uint32_t mod = base_clock % target_rate;
+        if(mod)
+            targetted_divisor--;
+    }
+
+    // Decide on the clock mode to use
+
+    // Currently only 10-bit divided clock mode is supported
+
+    // HCI version 3 or greater supports 10-bit divided clock mode
+    // This requires a power-of-two divider
+
+    // Find the first bit set
+    int divisor = -1;
+    for(int first_bit = 31; first_bit >= 0; first_bit--)
+    {
+        rt_uint32_t bit_test = (1 << first_bit);
+        if(targetted_divisor & bit_test)
+        {
+            divisor = first_bit;
+            targetted_divisor &= ~bit_test;
+            if(targetted_divisor)
+            {
+                // The divisor is not a power-of-two, increase it
+                divisor++;
+            }
+            break;
+        }
+    }
+
+    if(divisor == -1)
+        divisor = 31;
+    if(divisor >= 32)
+        divisor = 31;
+
+    if(divisor != 0)
+        divisor = (1 << (divisor - 1));
+
+    if(divisor >= 0x400)
+        divisor = 0x3ff;
+
+    freq_select = divisor & 0xff;
+    upper_bits = (divisor >> 8) & 0x3;
+    ret = (freq_select << 8) | (upper_bits << 6) | (0 << 5);
+
+    return ret;
+}
+
+static rt_err_t sdhci_setclock(struct sdhci_t * sdhci, rt_uint32_t clock)
+{
+    rt_uint32_t temp = 0;
+    rt_uint32_t sdHostVer = 0;
+    int count = 100000;
+    struct sdhci_pdata_t * pdat = (struct sdhci_pdata_t *)(sdhci->priv);
+
+    while ((read32(pdat->virt + EMMC_STATUS) & (SR_CMD_INHIBIT | SR_DAT_INHIBIT)) && (--count))
+        DELAY_MICROS(1);
+    if (count <= 0)
+    {
+        rt_kprintf("EMMC: Set clock: timeout waiting for inhibit flags. Status %08x.\n",read32(pdat->virt + EMMC_STATUS));
+        return RT_ERROR;
+    }
+
+    // Switch clock off.
+    temp = read32((pdat->virt + EMMC_CONTROL1));
+    temp &= ~C1_CLK_EN;
+    write32((pdat->virt + EMMC_CONTROL1),temp);
+    DELAY_MICROS(10);
+    // Request the new clock setting and enable the clock
+    temp = read32(pdat->virt + EMMC_SLOTISR_VER);
+    sdHostVer = (temp & HOST_SPEC_NUM) >> HOST_SPEC_NUM_SHIFT;
+    int cdiv = sd_get_clock_divider(sdHostVer, mmc_base_clock, clock);
+    temp = read32((pdat->virt + EMMC_CONTROL1));
+    temp |= 1;    
+    temp |= cdiv;
+    temp |= (7 << 16);
+
+    temp = (temp & 0xffff003f) | cdiv;
+    write32((pdat->virt + EMMC_CONTROL1),temp);
+    DELAY_MICROS(10);
+
+    // Enable the clock.
+    temp = read32(pdat->virt + EMMC_CONTROL1);
+    temp |= C1_CLK_EN;
+    write32((pdat->virt + EMMC_CONTROL1),temp);
+    DELAY_MICROS(10);
+
+    // Wait for clock to be stable.
+    count = 10000;
+    while (!(read32(pdat->virt + EMMC_CONTROL1) & C1_CLK_STABLE) && count--)
+        DELAY_MICROS(10);
+    if (count <= 0)
+    {
+        rt_kprintf("EMMC: ERROR: failed to get stable clock %d.\n", clock);
+        return RT_ERROR;
+    }
+
+    mmcsd_dbg("set stable clock %d.\n", clock);
+    return RT_EOK;
+}
+
+static void mmc_set_iocfg(struct rt_mmcsd_host *host, struct rt_mmcsd_io_cfg *io_cfg)
+{
+    struct sdhci_t * sdhci = (struct sdhci_t *)host->private_data;
+    sdhci_setclock(sdhci, io_cfg->clock);
+    sdhci_setwidth(sdhci, io_cfg->bus_width);
+}
+
+static const struct rt_mmcsd_host_ops ops =
+{
+    mmc_request_send,
+    mmc_set_iocfg,
+    RT_NULL,
+    RT_NULL,
+};
+
+static rt_err_t reset_emmc(struct sdhci_pdata_t * pdat)
+{
+    rt_uint32_t control1;
+
+    //Reset the controller
+    control1 = read32((pdat->virt + EMMC_CONTROL1));
+    control1 |= (1 << 24);
+    // Disable clock
+    control1 &= ~(1 << 2);
+    control1 &= ~(1 << 0);
+    //temp |= C1_CLK_INTLEN | C1_TOUNIT_MAX;
+    write32((pdat->virt + EMMC_CONTROL1),control1);
+    int cnt = 10000;
+    do
+    {
+        DELAY_MICROS(10);
+        cnt = cnt - 1;
+        if(cnt == 0)
+        {
+            break;
+        }
+    } while ((read32(pdat->virt + EMMC_CONTROL1) & (0x7 << 24)) != 0);
+
+    // Enable SD Bus Power VDD1 at 3.3V
+    rt_uint32_t control0 = read32(pdat->virt + EMMC_CONTROL0);
+    control0 |= 0x0F << 8;
+    write32(pdat->virt + EMMC_CONTROL0, control0);
+
+    rt_thread_delay(100);
+    //usleep(2000);
+
+
+    // Check for a valid card
+    mmcsd_dbg("EMMC: checking for an inserted card\n");
+    cnt = 10000;
+    do
+    {
+        DELAY_MICROS(10);
+        cnt = cnt - 1;
+        if(cnt == 0)
+        {
+            break;
+        }
+    } while ((read32(pdat->virt + EMMC_STATUS) & (0x1 << 16)) == 0);
+
+    rt_uint32_t status_reg = read32(pdat->virt + EMMC_STATUS);
+
+    if((status_reg & (1 << 16)) == 0)
+    {
+        rt_kprintf("EMMC: no card inserted\n");
+        return -1;
+    }
+    else
+    {
+        mmcsd_dbg("EMMC: status: %08x\n", status_reg);
+    }
+
+    // Clear control2
+    write32(pdat->virt + EMMC_CONTROL2, 0);
+
+    // Get the base clock rate
+    mmc_base_clock = bcm271x_mbox_clock_get_rate(12);
+    if(mmc_base_clock == 0)
+    {
+        rt_kprintf("EMMC: assuming clock rate to be 100MHz\n");
+        mmc_base_clock = 100000000;
+    }
+    mmcsd_dbg("EMMC: setting clock rate is %d\n", mmc_base_clock);
+    return RT_EOK;
+}
+
+#ifdef RT_MMCSD_DBG
+void dump_registers(struct sdhci_pdata_t * pdat)
+{
+    rt_kprintf("EMMC registers:");
+    int i = EMMC_ARG2;
+    for (; i <= EMMC_CONTROL2; i += 4)
+        rt_kprintf("\t%x:%x\n", i, read32(pdat->virt + i));
+    rt_kprintf("\t%x:%x\n", 0x50, read32(pdat->virt + 0x50));
+    rt_kprintf("\t%x:%x\n", 0x70, read32(pdat->virt + 0x70));
+    rt_kprintf("\t%x:%x\n", 0x74, read32(pdat->virt + 0x74));
+    rt_kprintf("\t%x:%x\n", 0x80, read32(pdat->virt + 0x80));
+    rt_kprintf("\t%x:%x\n", 0x84, read32(pdat->virt + 0x84));
+    rt_kprintf("\t%x:%x\n", 0x88, read32(pdat->virt + 0x88));
+    rt_kprintf("\t%x:%x\n", 0x8c, read32(pdat->virt + 0x8c));
+    rt_kprintf("\t%x:%x\n", 0x90, read32(pdat->virt + 0x90));
+    rt_kprintf("\t%x:%x\n", 0xf0, read32(pdat->virt + 0xf0));
+    rt_kprintf("\t%x:%x\n", 0xfc, read32(pdat->virt + 0xfc));
+}
+#endif
+
+int raspi_sdmmc_init(void)
+{
+    rt_uint32_t virt;
+    struct rt_mmcsd_host * host = RT_NULL;
+    struct sdhci_pdata_t * pdat = RT_NULL;
+    struct sdhci_t * sdhci = RT_NULL;
+
+#ifdef BSP_USING_SDIO0
+    host = mmcsd_alloc_host();
+    if (!host)
+    {
+        rt_kprintf("alloc host failed");
+        goto err;
+    }
+
+    sdhci = rt_malloc(sizeof(struct sdhci_t));
+    if (!sdhci)
+    {
+        rt_kprintf("alloc sdhci failed");
+        goto err;
+    }
+    rt_memset(sdhci, 0, sizeof(struct sdhci_t));
+
+    virt = MMC2_BASE_ADDR;
+
+    pdat = (struct sdhci_pdata_t *)rt_malloc(sizeof(struct sdhci_pdata_t));
+    RT_ASSERT(pdat != RT_NULL);
+
+    pdat->virt = (rt_uint32_t)virt;
+    reset_emmc(pdat);
+
+    sdhci->name = "sd0";
+    sdhci->voltages = VDD_33_34;
+    sdhci->width = MMCSD_BUSWIDTH_4;
+    sdhci->clock = 250 * 1000 * 1000;
+    sdhci->removeable = RT_TRUE;
+
+    sdhci->detect = sdhci_detect;
+    sdhci->setwidth = sdhci_setwidth;
+    sdhci->setclock = sdhci_setclock;
+    sdhci->transfer = sdhci_transfer;
+    sdhci->priv = pdat;
+    host->ops = &ops;
+    host->freq_min = 400000;
+    host->freq_max = 50000000;
+    host->valid_ocr = VDD_32_33 | VDD_33_34;
+    host->flags = MMCSD_MUTBLKWRITE | MMCSD_SUP_HIGHSPEED | MMCSD_SUP_SDIO_IRQ | MMCSD_BUSWIDTH_4;
+    host->max_seg_size = 2048;
+    host->max_dma_segs = 10;
+    host->max_blk_size = 512;
+    host->max_blk_count = 4096;
+
+    host->private_data = sdhci;
+
+    write32((pdat->virt + EMMC_IRPT_EN),0xffffffff);
+    write32((pdat->virt + EMMC_IRPT_MASK),0xffffffff);
+#ifdef RT_MMCSD_DBG
+    dump_registers(pdat);
+#endif
+    mmcsd_change(host);
+#endif
+    return RT_EOK;   
+err:
+    if (host)  rt_free(host);
+    if (sdhci) rt_free(sdhci);
+
+    return -RT_EIO;
+}
+
+INIT_DEVICE_EXPORT(raspi_sdmmc_init);

+ 253 - 0
bsp/raspberry-pi/raspi4-32/driver/drv_sdio.h

@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author         Notes
+ * 2020-10-27     bigmagic       first version
+ */
+
+#ifndef __DRV_SDIO_H__
+#define __DRV_SDIO_H__
+
+#include <rtthread.h>
+#include <rtdevice.h>
+#include <drivers/mmcsd_core.h>
+
+#include "board.h"
+#include "raspi4.h"
+
+/* Struct for Intrrrupt Information */
+#define SDXC_CmdDone       BIT(0)
+#define SDXC_DataDone      BIT(1)
+#define SDXC_BlockGap      BIT(2)
+#define SDXC_WriteRdy      BIT(4)
+#define SDXC_ReadRdy       BIT(5)
+#define SDXC_Card          BIT(8)
+#define SDXC_Retune        BIT(12)
+#define SDXC_BootAck       BIT(13)
+#define SDXC_EndBoot       BIT(14)
+#define SDXC_Err           BIT(15)
+#define SDXC_CTOErr        BIT(16)
+#define SDXC_CCRCErr       BIT(17)
+#define SDXC_CENDErr       BIT(18)
+#define SDXC_CBADErr       BIT(19)
+#define SDXC_DTOErr        BIT(20)
+#define SDXC_DCRCErr       BIT(21)
+#define SDXC_DENDErr       BIT(22)
+#define SDXC_ACMDErr       BIT(24)
+
+#define SDXC_BLKCNT_EN          BIT(1)
+#define SDXC_AUTO_CMD12_EN      BIT(2)
+#define SDXC_AUTO_CMD23_EN      BIT(3)
+#define SDXC_DAT_DIR            BIT(4)   //from card to host
+#define SDXC_MULTI_BLOCK        BIT(5)
+#define SDXC_CMD_RSPNS_136      BIT(16)
+#define SDXC_CMD_RSPNS_48       BIT(17)
+#define SDXC_CMD_RSPNS_48busy   BIT(16)|BIT(17)
+#define SDXC_CHECK_CRC_CMD      BIT(19)
+#define SDXC_CMD_IXCHK_EN       BIT(20)
+#define SDXC_CMD_ISDATA         BIT(21)
+#define SDXC_CMD_SUSPEND        BIT(22)
+#define SDXC_CMD_RESUME         BIT(23)
+#define SDXC_CMD_ABORT          BIT(23)|BIT(22)
+
+#define SDXC_CMD_INHIBIT        BIT(0)
+#define SDXC_DAT_INHIBIT        BIT(1)
+#define SDXC_DAT_ACTIVE         BIT(2)
+#define SDXC_WRITE_TRANSFER     BIT(8)
+#define SDXC_READ_TRANSFER      BIT(9)
+
+struct sdhci_cmd_t
+{
+    rt_uint32_t cmdidx;
+    rt_uint32_t cmdarg;
+    rt_uint32_t resptype;
+    rt_uint32_t datarw;
+#define DATA_READ 1
+#define DATA_WRITE 2
+    rt_uint32_t response[4];
+};
+
+struct sdhci_data_t
+{
+    rt_uint8_t * buf;
+    rt_uint32_t flag;
+    rt_uint32_t blksz;
+    rt_uint32_t blkcnt;
+};
+
+struct sdhci_t
+{
+    char * name;
+    rt_uint32_t voltages;
+    rt_uint32_t width;
+    rt_uint32_t clock;
+    rt_err_t removeable;
+    void * sdcard; 
+
+    rt_err_t (*detect)(struct sdhci_t * sdhci);
+    rt_err_t (*setwidth)(struct sdhci_t * sdhci, rt_uint32_t width);
+    rt_err_t (*setclock)(struct sdhci_t * sdhci, rt_uint32_t clock);
+    rt_err_t (*transfer)(struct sdhci_t * sdhci, struct sdhci_cmd_t * cmd, struct sdhci_data_t * dat);
+    void * priv;
+};
+
+struct sdhci_pdata_t
+{
+    rt_uint32_t virt;
+};
+
+// EMMC command flags
+#define CMD_TYPE_NORMAL  (0x00000000)
+#define CMD_TYPE_SUSPEND (0x00400000)
+#define CMD_TYPE_RESUME  (0x00800000)
+#define CMD_TYPE_ABORT   (0x00c00000)
+#define CMD_IS_DATA      (0x00200000)
+#define CMD_IXCHK_EN     (0x00100000)
+#define CMD_CRCCHK_EN    (0x00080000)
+#define CMD_RSPNS_NO     (0x00000000)
+#define CMD_RSPNS_136    (0x00010000)
+#define CMD_RSPNS_48     (0x00020000)
+#define CMD_RSPNS_48B    (0x00030000)
+#define TM_MULTI_BLOCK   (0x00000020)
+#define TM_DAT_DIR_HC    (0x00000000)
+#define TM_DAT_DIR_CH    (0x00000010)
+#define TM_AUTO_CMD23    (0x00000008)
+#define TM_AUTO_CMD12    (0x00000004)
+#define TM_BLKCNT_EN     (0x00000002)
+#define TM_MULTI_DATA    (CMD_IS_DATA|TM_MULTI_BLOCK|TM_BLKCNT_EN)
+
+#define RCA_NO              (1)
+#define RCA_YES             (2)
+
+// INTERRUPT register settings
+#define INT_AUTO_ERROR   (0x01000000)
+#define INT_DATA_END_ERR (0x00400000)
+#define INT_DATA_CRC_ERR (0x00200000)
+#define INT_DATA_TIMEOUT (0x00100000)
+#define INT_INDEX_ERROR  (0x00080000)
+#define INT_END_ERROR    (0x00040000)
+#define INT_CRC_ERROR    (0x00020000)
+#define INT_CMD_TIMEOUT  (0x00010000)
+#define INT_ERR          (0x00008000)
+#define INT_ENDBOOT      (0x00004000)
+#define INT_BOOTACK      (0x00002000)
+#define INT_RETUNE       (0x00001000)
+#define INT_CARD         (0x00000100)
+#define INT_READ_RDY     (0x00000020)
+#define INT_WRITE_RDY    (0x00000010)
+#define INT_BLOCK_GAP    (0x00000004)
+#define INT_DATA_DONE    (0x00000002)
+#define INT_CMD_DONE     (0x00000001)
+#define INT_ERROR_MASK   (INT_CRC_ERROR|INT_END_ERROR|INT_INDEX_ERROR| \
+                          INT_DATA_TIMEOUT|INT_DATA_CRC_ERR|INT_DATA_END_ERR| \
+                          INT_ERR|INT_AUTO_ERROR)
+#define INT_ALL_MASK     (INT_CMD_DONE|INT_DATA_DONE|INT_READ_RDY|INT_WRITE_RDY|INT_ERROR_MASK)
+
+#define EMMC_ARG2               (0x00)
+#define EMMC_BLKSIZECNT         (0x04)
+#define EMMC_ARG1               (0x08)
+#define EMMC_CMDTM              (0x0c)
+#define EMMC_RESP0              (0x10)
+#define EMMC_RESP1              (0x14)
+#define EMMC_RESP2              (0x18)
+#define EMMC_RESP3              (0x1c)
+#define EMMC_DATA               (0x20)
+#define EMMC_STATUS             (0x24)
+#define EMMC_CONTROL0           (0x28)
+#define EMMC_CONTROL1           (0x2c)
+#define EMMC_INTERRUPT          (0x30)
+#define EMMC_IRPT_MASK          (0x34)
+#define EMMC_IRPT_EN            (0x38)
+#define EMMC_CONTROL2           (0x3c)
+#define EMMC_CAPABILITIES_0     (0x40)
+#define EMMC_CAPABILITIES_1     (0x44)
+#define EMMC_BOOT_TIMEOUT       (0x70)
+#define EMMC_EXRDFIFO_EN        (0x84)
+#define EMMC_SPI_INT_SPT        (0xf0)
+#define EMMC_SLOTISR_VER        (0xfc)
+
+// CONTROL register settings
+#define C0_SPI_MODE_EN          (0x00100000)
+#define C0_HCTL_HS_EN           (0x00000004)
+#define C0_HCTL_DWITDH          (0x00000002)
+
+#define C1_SRST_DATA            (0x04000000)
+#define C1_SRST_CMD             (0x02000000)
+#define C1_SRST_HC              (0x01000000)
+#define C1_TOUNIT_DIS           (0x000f0000)
+#define C1_TOUNIT_MAX           (0x000e0000)
+#define C1_CLK_GENSEL           (0x00000020)
+#define C1_CLK_EN               (0x00000004)
+#define C1_CLK_STABLE           (0x00000002)
+#define C1_CLK_INTLEN           (0x00000001)
+
+#define FREQ_SETUP           (400000)  // 400 Khz
+#define FREQ_NORMAL        (25000000)  // 25 Mhz
+
+// SLOTISR_VER values
+#define HOST_SPEC_NUM              0x00ff0000
+#define HOST_SPEC_NUM_SHIFT        16
+#define HOST_SPEC_V3               2
+#define HOST_SPEC_V2               1
+#define HOST_SPEC_V1               0
+
+// STATUS register settings
+#define SR_DAT_LEVEL1        (0x1e000000)
+#define SR_CMD_LEVEL         (0x01000000)
+#define SR_DAT_LEVEL0        (0x00f00000)
+#define SR_DAT3              (0x00800000)
+#define SR_DAT2              (0x00400000)
+#define SR_DAT1              (0x00200000)
+#define SR_DAT0              (0x00100000)
+#define SR_WRITE_PROT        (0x00080000)  // From SDHC spec v2, BCM says reserved
+#define SR_READ_AVAILABLE    (0x00000800)  // ???? undocumented
+#define SR_WRITE_AVAILABLE   (0x00000400)  // ???? undocumented
+#define SR_READ_TRANSFER     (0x00000200)
+#define SR_WRITE_TRANSFER    (0x00000100)
+#define SR_DAT_ACTIVE        (0x00000004)
+#define SR_DAT_INHIBIT       (0x00000002)
+#define SR_CMD_INHIBIT       (0x00000001)
+
+#define CONFIG_MMC_USE_DMA
+#define DMA_ALIGN            (32U)
+
+#define SD_CMD_INDEX(a)         ((a) << 24)
+#define SD_CMD_RESERVED(a)      (0xffffffff)
+#define SD_CMD_INDEX(a)         ((a) << 24)
+#define SD_CMD_TYPE_NORMAL      (0x0)
+#define SD_CMD_TYPE_SUSPEND     (1 << 22)
+#define SD_CMD_TYPE_RESUME      (2 << 22)
+#define SD_CMD_TYPE_ABORT       (3 << 22)
+#define SD_CMD_TYPE_MASK        (3 << 22)
+#define SD_CMD_ISDATA           (1 << 21)
+#define SD_CMD_IXCHK_EN         (1 << 20)
+#define SD_CMD_CRCCHK_EN        (1 << 19)
+#define SD_CMD_RSPNS_TYPE_NONE  (0)              // For no response
+#define SD_CMD_RSPNS_TYPE_136   (1 << 16)        // For response R2 (with CRC), R3,4 (no CRC)
+#define SD_CMD_RSPNS_TYPE_48    (2 << 16)        // For responses R1, R5, R6, R7 (with CRC)
+#define SD_CMD_RSPNS_TYPE_48B   (3 << 16)        // For responses R1b, R5b (with CRC)
+#define SD_CMD_RSPNS_TYPE_MASK  (3 << 16)
+#define SD_CMD_MULTI_BLOCK      (1 << 5)
+#define SD_CMD_DAT_DIR_HC       (0)
+#define SD_CMD_DAT_DIR_CH       (1 << 4)
+#define SD_CMD_AUTO_CMD_EN_NONE     (0)
+#define SD_CMD_AUTO_CMD_EN_CMD12    (1 << 2)
+#define SD_CMD_AUTO_CMD_EN_CMD23    (2 << 2)
+#define SD_CMD_BLKCNT_EN            (1 << 1)
+#define SD_CMD_DMA                  (1)
+#define SD_RESP_NONE                SD_CMD_RSPNS_TYPE_NONE
+#define SD_RESP_R1                  (SD_CMD_RSPNS_TYPE_48)            // | SD_CMD_CRCCHK_EN)
+#define SD_RESP_R1b                 (SD_CMD_RSPNS_TYPE_48B)           // | SD_CMD_CRCCHK_EN)
+#define SD_RESP_R2                  (SD_CMD_RSPNS_TYPE_136)           // | SD_CMD_CRCCHK_EN)
+#define SD_RESP_R3                  SD_CMD_RSPNS_TYPE_48
+#define SD_RESP_R4                  SD_CMD_RSPNS_TYPE_136
+#define SD_RESP_R5                  (SD_CMD_RSPNS_TYPE_48 | SD_CMD_CRCCHK_EN)
+#define SD_RESP_R5b                 (SD_CMD_RSPNS_TYPE_48B | SD_CMD_CRCCHK_EN)
+#define SD_RESP_R6                  (SD_CMD_RSPNS_TYPE_48 | SD_CMD_CRCCHK_EN)
+#define SD_RESP_R7                  (SD_CMD_RSPNS_TYPE_48 | SD_CMD_CRCCHK_EN)
+#define SD_DATA_READ                (SD_CMD_ISDATA | SD_CMD_DAT_DIR_CH)
+#define SD_DATA_WRITE               (SD_CMD_ISDATA | SD_CMD_DAT_DIR_HC)
+#endif

+ 135 - 0
bsp/raspberry-pi/raspi4-32/driver/drv_wdt.c

@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author         Notes
+ * 2020-10-26     bigmagic       first version
+ */
+#include <rthw.h>
+#include "drv_wdt.h"
+#include "raspi4.h"
+
+#ifdef BSP_USING_WDT
+
+#define SECS_TO_WDOG_TICKS(x) ((x) << 16)
+#define WDOG_TICKS_TO_SECS(x) ((x) >> 16)
+
+static struct raspi_wdt_driver bcm_wdt;
+
+void raspi_watchdog_init(rt_uint32_t time_init)
+{
+    bcm_wdt.timeout = time_init;
+}
+
+void raspi_watchdog_start()
+{
+    volatile rt_uint32_t cur;
+    PM_WDOG = PM_PASSWORD | (SECS_TO_WDOG_TICKS(bcm_wdt.timeout) & PM_WDOG_TIME_SET);
+    cur = (PM_RSTC);
+    PM_RSTC = PM_PASSWORD | (cur & PM_RSTC_WRCFG_CLR) | PM_RSTC_WRCFG_FULL_RESET;
+}
+
+void raspi_watchdog_stop()
+{
+    PM_RSTC = PM_PASSWORD | PM_RSTC_RESET;
+}
+
+void raspi_watchdog_clr()
+{
+    bcm_wdt.timeout = 0;
+}
+
+void raspi_watchdog_set_timeout(rt_uint32_t timeout_us)
+{
+    bcm_wdt.timeout = timeout_us;
+}
+
+rt_uint64_t raspi_watchdog_get_timeout()
+{
+    return bcm_wdt.timeout;
+}
+
+rt_uint64_t raspi_watchdog_get_timeleft()
+{
+    rt_uint32_t ret = (PM_WDOG);
+    return WDOG_TICKS_TO_SECS(ret & PM_WDOG_TIME_SET);
+}
+
+static rt_err_t raspi_wdg_init(rt_watchdog_t *wdt)
+{
+    /*init for 10S*/
+    raspi_watchdog_init(1000000);
+    raspi_watchdog_start();
+    raspi_watchdog_stop();
+    return RT_EOK;
+}
+
+static rt_err_t raspi_wdg_control(rt_watchdog_t *wdt, int cmd, void *arg)
+{
+    rt_uint64_t  timeout_us = 0;
+    switch (cmd)
+    {
+    case RT_DEVICE_CTRL_WDT_SET_TIMEOUT:
+        timeout_us = *((rt_uint32_t *)arg) * 1000000;
+        if (timeout_us >= 0xFFFFFFFF)
+            timeout_us = 0xFFFFFFFF;
+        raspi_watchdog_set_timeout((rt_uint32_t)timeout_us);
+        break;
+    case RT_DEVICE_CTRL_WDT_GET_TIMEOUT:
+        timeout_us = raspi_watchdog_get_timeout();
+        *((rt_uint32_t *)arg) = timeout_us / 1000000;
+        break;
+    case RT_DEVICE_CTRL_WDT_GET_TIMELEFT:
+        timeout_us = raspi_watchdog_get_timeleft();
+        *((rt_uint32_t *)arg) = timeout_us / 1000000;
+        break;
+    case RT_DEVICE_CTRL_WDT_KEEPALIVE:
+        raspi_watchdog_clr();
+        break;
+    case RT_DEVICE_CTRL_WDT_START:
+        raspi_watchdog_start();
+        break;
+    case RT_DEVICE_CTRL_WDT_STOP:
+        raspi_watchdog_stop();
+        break;
+    default:
+        return RT_EIO;
+    }
+    return RT_EOK;
+}
+
+static const struct rt_watchdog_ops raspi_wdg_pos =
+{
+    raspi_wdg_init,
+    raspi_wdg_control,
+};
+
+static rt_watchdog_t raspi_wdg;
+
+int rt_hw_wdt_init(void)
+{
+    raspi_wdg.ops = &raspi_wdg_pos;
+    rt_hw_watchdog_register(&raspi_wdg, "wdg", 0, RT_NULL);
+    return RT_EOK;
+}
+INIT_DEVICE_EXPORT(rt_hw_wdt_init);
+
+void reboot(void)
+{
+    unsigned int r;
+
+    rt_kprintf("reboot system...\n");
+    rt_thread_mdelay(100);
+    r = PM_RSTS;
+    // trigger a restart by instructing the GPU to boot from partition 0
+    r &= ~0xfffffaaa;
+    PM_RSTS |= (PM_PASSWORD | r);   // boot from partition 0
+    PM_WDOG |= (PM_PASSWORD | 0x0A);
+    PM_RSTC |= (PM_PASSWORD | PM_RSTC_WRCFG_FULL_RESET);
+    
+    while (1);
+}
+MSH_CMD_EXPORT(reboot,reboot system...);
+#endif /*BSP_USING_WDT */

+ 25 - 0
bsp/raspberry-pi/raspi4-32/driver/drv_wdt.h

@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2006-2020, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author         Notes
+ * 2020-10-26     bigmagic       first version
+ */
+#ifndef __DRV_WDT_H__
+#define __DRV_WDT_H__
+
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#include "board.h"
+
+struct raspi_wdt_driver
+{
+    rt_uint32_t timeout;
+};
+
+int rt_hw_wdt_init(void);
+
+#endif

+ 46 - 0
bsp/raspberry-pi/raspi4-32/driver/mbox.c

@@ -49,6 +49,52 @@ int mbox_call(unsigned char ch, int mmu_enable)
     return 0;
     return 0;
 }
 }
 
 
+int bcm271x_notify_reboot(void)
+{
+    mbox[0] = 7*4;                          // length of the message
+    mbox[1] = MBOX_REQUEST;                 // this is a request message
+    mbox[2] = MBOX_TAG_NOTIFY_REBOOT;       // (the tag id)
+    mbox[3] = 0x00000004;                   // length + 4
+    mbox[4] = 0x00000000;                   // size of the data
+    mbox[5] = 0x00000000;                   // request
+
+    mbox[6] = MBOX_TAG_LAST; 
+    mbox_call(8, MMU_DISABLE);
+    return 0;
+}
+
+int bcm271x_notify_xhci_reset(void)
+{
+    mbox[0] = 7*4;                          // length of the message
+    mbox[1] = MBOX_REQUEST;                 // this is a request message
+    mbox[2] = MBOX_TAG_NOTIFY_XHCI_RESET;   // (the tag id)
+    mbox[3] = 0x00000004;                   // length + 4
+    mbox[4] = 0x00000004;                   // size of the data
+    mbox[5] = 0x00100000;                   // request
+    mbox[6] = MBOX_TAG_LAST; 
+    mbox_call(8, MMU_DISABLE);
+    return 0;
+}
+
+int bcm271x_gpu_enable(void)
+{
+    mbox[0] = 12*4;                          // length of the message
+    mbox[1] = MBOX_REQUEST;                  // this is a request message
+    
+    mbox[2] = MBOX_TAG_CLOCK_SET_RATE;
+    mbox[3] = 0x00000008;                   // (the tag id)
+    mbox[4] = 0x00000008;                   // (the tag id)
+    mbox[5] = 5;                            // V3D
+    mbox[6] = 250 * 1000 * 1000;
+    mbox[7] = MBOX_TAG_ENABLE_QPU;                   // (the tag id)
+    mbox[8] = 0x00000004;                   // (size of the buffer)
+    mbox[9] = 0x00000004;                   // (size of the data)
+    mbox[10] = 0x00000001;
+    mbox[11] = MBOX_TAG_LAST;               // end tag
+    mbox_call(8, MMU_DISABLE);
+    return mbox[1];
+}
+
 int bcm271x_mbox_hardware_get_model(void)
 int bcm271x_mbox_hardware_get_model(void)
 {
 {
     mbox[0] = 8*4;                          // length of the message
     mbox[0] = 8*4;                          // length of the message

+ 43 - 10
bsp/raspberry-pi/raspi4-32/driver/mbox.h

@@ -35,7 +35,7 @@ extern volatile unsigned int* mbox;
 /* tags */
 /* tags */
 #define MBOX_TAG_SETPOWER       0x28001
 #define MBOX_TAG_SETPOWER       0x28001
 #define MBOX_TAG_SETCLKRATE     0x38002
 #define MBOX_TAG_SETCLKRATE     0x38002
-#define MBOX_GET_MAC_ADDRESS	0x10003
+#define MBOX_GET_MAC_ADDRESS    0x10003
 #define MBOX_TAG_LAST           0
 #define MBOX_TAG_LAST           0
 
 
 #define MMIO_BASE       0xFE000000
 #define MMIO_BASE       0xFE000000
@@ -50,14 +50,14 @@ extern volatile unsigned int* mbox;
 #define MBOX_FULL       0x80000000
 #define MBOX_FULL       0x80000000
 #define MBOX_EMPTY      0x40000000
 #define MBOX_EMPTY      0x40000000
 
 
-#define DEVICE_ID_SD_CARD	0
-#define DEVICE_ID_USB_HCD	3
-#define POWER_STATE_OFF		(0 << 0)
-#define POWER_STATE_ON		(1 << 0)
-#define POWER_STATE_WAIT	(1 << 1)
-#define POWER_STATE_NO_DEVICE	(1 << 1)	// in response
-#define MMU_ENABLE 1
-#define MMU_DISABLE 0
+#define DEVICE_ID_SD_CARD        (0)
+#define DEVICE_ID_USB_HCD        (3)
+#define POWER_STATE_OFF          (0 << 0)
+#define POWER_STATE_ON           (1 << 0)
+#define POWER_STATE_WAIT         (1 << 1)
+#define POWER_STATE_NO_DEVICE    (1 << 1)    // in response
+#define MMU_ENABLE               (1)
+#define MMU_DISABLE              (0)
 
 
 /*
 /*
  * raspi hardware info
  * raspi hardware info
@@ -102,9 +102,42 @@ enum {
     MBOX_TAG_TEMP_GET_MAX   = 0x0003000A,
     MBOX_TAG_TEMP_GET_MAX   = 0x0003000A,
 };
 };
 
 
-#define MBOX_ADDR 0xc00000
+/*
+ * raspi Memory
+ */
+enum {
+    MBOX_TAG_ALLOCATE_MEMORY = 0x0003000C, // Memory: Allocates Contiguous Memory On The GPU (Response: Handle)
+    MBOX_TAG_LOCK_MEMORY     = 0x0003000D, // Memory: Unlock Buffer (Response: Status)
+    MBOX_TAG_UNLOCK_MEMORY   = 0x0003000E, // Memory: Unlock Buffer (Response: Status)
+    MBOX_TAG_RELEASE_MEMORY  = 0x0003000F, // Memory: Free The Memory Buffer (Response: Status)
+    MBOX_TAG_EXECUTE_CODE    = 0x00030010, // Memory: Calls The Function At Given (Bus) Address And With Arguments Given
+};
+
+/*
+ * raspi GPU
+ */
+enum {
+    MBOX_TAG_EXECUTE_QPU = 0x00030011, // QPU: Calls The QPU Function At Given (Bus) Address And With Arguments Given (Response: Number Of QPUs, Control, No Flush, Timeout In ms)
+    MBOX_TAG_ENABLE_QPU  = 0x00030012, // QPU: Enables The QPU (Response: Enable State)
+};
+
+/*
+ * raspi HDMI
+ */
+#define MBOX_TAG_GET_EDID_BLOCK        0x00030020 // HDMI: Read Specificed EDID Block From Attached HDMI/DVI Device (Response: Block Number, Status, EDID Block (128 Bytes))
+
+/*
+ * raspi NOTIFY
+ */
+#define MBOX_TAG_NOTIFY_REBOOT         0x00030048
+#define MBOX_TAG_NOTIFY_XHCI_RESET     0x00030058
+
+#define MBOX_ADDR 0x08000000
 
 
 int mbox_call(unsigned char ch, int mmu_enable);
 int mbox_call(unsigned char ch, int mmu_enable);
+int bcm271x_notify_reboot(void);
+int bcm271x_notify_xhci_reset(void);
+int bcm271x_gpu_enable(void);
 int bcm271x_mbox_hardware_get_model(void);
 int bcm271x_mbox_hardware_get_model(void);
 int bcm271x_mbox_hardware_get_revison(void);
 int bcm271x_mbox_hardware_get_revison(void);
 int bcm271x_mbox_hardware_get_mac_address(uint8_t * mac);
 int bcm271x_mbox_hardware_get_mac_address(uint8_t * mac);

+ 33 - 0
bsp/raspberry-pi/raspi4-32/driver/raspi4.h

@@ -119,6 +119,39 @@ typedef enum {
 
 
 #define GIC_ACK_INTID_MASK  0x000003ff
 #define GIC_ACK_INTID_MASK  0x000003ff
 
 
+//watchdog
+#define PM_RSTC         HWREG32(PER_BASE + 0x0010001c)
+#define PM_RSTS         HWREG32(PER_BASE + 0x00100020)
+#define PM_WDOG         HWREG32(PER_BASE + 0x00100024)
+
+#define PM_PASSWORD                 (0x5A000000)
+#define PM_WDOG_TIME_SET            (0x000fffff)
+#define PM_RSTS_HADWRH_SET          (0x00000040)
+#define PM_RSTC_WRCFG_FULL_RESET    (0x00000020)
+#define PM_RSTC_WRCFG_CLR           (0xffffffcf)
+#define PM_RSTC_RESET               (0x00000102)
+
+//timer
+#define ST_BASE_OFFSET     (0x003000)
+#define STIMER_BASE  (PER_BASE  + ST_BASE_OFFSET)
+#define STIMER_CS    __REG32(STIMER_BASE + 0x0000)
+#define STIMER_CLO   __REG32(STIMER_BASE + 0x0004)
+#define STIMER_CHI   __REG32(STIMER_BASE + 0x0008)
+#define STIMER_C0    __REG32(STIMER_BASE + 0x000C)
+#define STIMER_C1    __REG32(STIMER_BASE + 0x0010)
+#define STIMER_C2    __REG32(STIMER_BASE + 0x0014)
+#define STIMER_C3    __REG32(STIMER_BASE + 0x0018)
+
+#define DELAY_MICROS(micros) \
+    do{ \
+ rt_uint32_t compare = STIMER_CLO + micros * 25; \
+ while (STIMER_CLO < compare); \
+    } while (0) \
+
+//External Mass Media Controller (SD Card)
+#define MMC0_BASE_ADDR		(PER_BASE+0x300000)   
+#define MMC2_BASE_ADDR		(PER_BASE+0x340000)  
+
 /* the basic constants and interfaces needed by gic */
 /* the basic constants and interfaces needed by gic */
 rt_inline rt_uint32_t platform_get_gic_dist_base(void)
 rt_inline rt_uint32_t platform_get_gic_dist_base(void)
 {
 {

+ 24 - 0
bsp/raspberry-pi/raspi4-32/rtconfig.h

@@ -76,6 +76,18 @@
 #define DFS_FILESYSTEMS_MAX 2
 #define DFS_FILESYSTEMS_MAX 2
 #define DFS_FILESYSTEM_TYPES_MAX 2
 #define DFS_FILESYSTEM_TYPES_MAX 2
 #define DFS_FD_MAX 16
 #define DFS_FD_MAX 16
+#define RT_USING_DFS_ELMFAT
+
+/* elm-chan's FatFs, Generic FAT Filesystem Module */
+
+#define RT_DFS_ELM_CODE_PAGE 437
+#define RT_DFS_ELM_WORD_ACCESS
+#define RT_DFS_ELM_USE_LFN_3
+#define RT_DFS_ELM_USE_LFN 3
+#define RT_DFS_ELM_MAX_LFN 255
+#define RT_DFS_ELM_DRIVES 2
+#define RT_DFS_ELM_MAX_SECTOR_SIZE 512
+#define RT_DFS_ELM_REENTRANT
 #define RT_USING_DFS_DEVFS
 #define RT_USING_DFS_DEVFS
 
 
 /* Device Drivers */
 /* Device Drivers */
@@ -86,7 +98,14 @@
 #define RT_SERIAL_USING_DMA
 #define RT_SERIAL_USING_DMA
 #define RT_SERIAL_RB_BUFSZ 64
 #define RT_SERIAL_RB_BUFSZ 64
 #define RT_USING_PIN
 #define RT_USING_PIN
+#define RT_USING_SDIO
+#define RT_SDIO_STACK_SIZE 512
+#define RT_SDIO_THREAD_PRIORITY 15
+#define RT_MMCSD_STACK_SIZE 1024
+#define RT_MMCSD_THREAD_PREORITY 22
+#define RT_MMCSD_MAX_PARTITION 16
 #define RT_USING_SPI
 #define RT_USING_SPI
+#define RT_USING_WDT
 
 
 /* Using USB */
 /* Using USB */
 
 
@@ -178,8 +197,13 @@
 #define BSP_USING_SPI0_BUS
 #define BSP_USING_SPI0_BUS
 #define BSP_USING_SPI0_DEVICE0
 #define BSP_USING_SPI0_DEVICE0
 #define BSP_USING_CORETIMER
 #define BSP_USING_CORETIMER
+#define BSP_USING_WDT
+#define BSP_USING_SDIO
+#define BSP_USING_SDIO0
 
 
 /* Board Peripheral Drivers */
 /* Board Peripheral Drivers */
 
 
+#define BSP_USING_HDMI
+#define BSP_USING_HDMI_DISPLAY
 
 
 #endif
 #endif