
每当提到 3D 第一人称射击游戏,大家很自然就会联想到高性能独显,以及几个G甚至几十G的硬盘存储空间,那么有没有可能在 STM32F103RC 这样一块只有 256KB Flash 的小板子上保存一个大型第一人称射击游戏呢? ![]() 当我们用 USB 线把这块开发板连接到电脑上,就可以看到出现了一个只有100多KB的U盘,这就是 STM32 的片上 Flash 了。9 G! b: Q$ C' K# w; c/ F ![]() ![]() 如果我们双击它就启动了一个 STM32 上的第一人称射击游戏。: {% [ R! |9 C) Q4 e2 A0 C 9 R# w" ?" Y, w7 r7 }' G% _* m这是完整的演示视频:如果你也有兴趣把这个游戏保存在 STM32 上,可以跟着后面的教程,或者也可以在这个项目里直接找到编译好的固件、游戏和项目源码。* n4 D: p0 h8 u0 h) M 链接地址:http://github.com/wuhanstudio/stm32-ufun-3d-game * J, x; F2 b F: Z1 T+ V9 d0 g1. 运行 RT-ThreadRT-Thread 在 Github 上是开源的,源码可以在这里(链接:http://github.com/rt-Thread/rt-thread/)找到,官网文档也很丰富这里就不重复了,总结一下需要的工具:
如果觉得从 github 上面下载 RT-Thread 源码比较慢,可以先从 gitee 上面下载,然后修改项目地址。 1git clone https://gitee.com/rtthread/rt-thread2cd rt-thread 3git remote rm origin* M: Y" j' v* j6 f* H 4git remote add origin https://github.com/RT-Thread/rt-thread * q8 X- b! w% Q, Y 5git pull origin master 2. 片上 Flash 文件系统准备好第一步里面的工具后,首先我们需要把 STM32 的片上 flash 挂载为文件系统,首先需要在 CubeMX 里使能 USB。 ![]() 打开 USB 后在时钟配置里确认外部晶振和板子上的晶振是一致的,并且 USB 的时钟是 48MHz,就可以点击生成代码了。由于我们修改了时钟,需要把 board/CubeMX_Config/Src/main.c 里面的 void SystemClock_Config(void) 函数复制到 board/board.c 里面替换。 接下来修改 bsp 下 board 目录里的 Kconfig 文件。1config BSP_USING_ON_CHIP_FLASH2 bool "Enable on-chip FLASH" 3 default n 4/ @* l+ D! h5 [: G3 t5 c 5config BSP_USING_USBD_FS0 \0 i! F; }5 y3 F: D/ | 6 bool "Enable USBD as USB device"4 x' ~/ D( T. j 7 select RT_USING_USB_DEVICE# p/ T3 c9 R7 ] 8 default n 这样再在 bsp 目录下右键 ConEmu Here 就可以看到配置界面 (Env 教程:http://www.rt-thread.org/document/site/tutorial/env-video/),依次选中下面几个选项:
![]()
![]()
![]()
![]() 保存配置退出,在 env 里面输入命令就可以自动生成 Keil 项目了: 1pkgs --update 2scons --target=mdk5 -s ! [# ^0 y! \3 p9 W2 k 我们需要先对 flash 进行规划,STM32F103RC 一共有 256KB,可以把最后的 128KB 作为文件系统使用,于是新建一个 fal_cfg.h: 1extern const struct fal_flash_dev stm32_onchip_flash;3 N% p6 `% R! Z2 3#define FAL_FLASH_DEV_TABLE \ 4{ \# \. [: w" g" X4 `. c7 y% c 5 &stm32_onchip_flash, \ 6} 7 8#define FAL_PART_TABLE \ 9{ \ 10 {FAL_PART_MAGIC_WROD, "app", "onchip_flash", 0, 128*1024, 0}, \ 11 {FAL_PART_MAGIC_WROD, "flash0", "onchip_flash", 128*1024, 128*1024, 0}, \# Q+ a& y- t- J/ w 12}* r9 _. D, w: t- n4 S3 E- }$ ~ 再修改 main.c 挂载文件系统: 1#include <rtthread.h>2#include <rtdevice.h>( `* F* G9 }/ Z 3#include <board.h> 4#include <fal.h> 5#include <dfs_posix.h>9 C. A* y/ j& y 6. ?$ ~9 a9 e- ]5 M2 V% a: p! l 7/* defined the LED0 pin: PC13 */ 8#define LED0_PIN GET_PIN(C, 13)3 g- b* t# J$ D8 g 9 10#define FS_PARTITION_NAME "flash0" 11 12int main(void) 13{ 14 int count = 1; 15 /* set LED0 pin mode to output */ 16 rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT);0 b, R- x6 \9 G% C0 g 17$ `) ]% w1 I$ M: O 18 fal_init();# H. q' `1 N& n, b6 ` 192 p c1 w" E3 Y, K: { 20#ifdef RT_USB_DEVICE_MSTORAGE6 I/ d: H0 U, Q 21 struct rt_device *flash_dev = fal_blk_device_create(FS_PARTITION_NAME); 22#else8 s7 V/ T& C* {+ l7 L! r 23 struct rt_device *flash_dev = fal_mtd_nor_device_create(FS_PARTITION_NAME);" s# \0 k# ] k. _! e 24#endif1 W& D" u" M2 ]; Z0 a) o 253 s! k5 F a5 h2 c; e/ N 26 if (flash_dev == NULL) 27 {) N6 p* X* E: a# [- g; H 28 rt_kprintf("Can't create a block device on '%s' partition.\n", FS_PARTITION_NAME); 29 } 30 else2 j# y4 p/ i1 S0 U* Y' ~ 31 {* B* w. w! y" q 32 rt_kprintf("Create a block device on the %s partition of flash successful.\n", FS_PARTITION_NAME); 33 }1 {0 r% Q8 [5 S9 u* Y& ^0 I { 34 35 while (count++)- ~, z7 f' u+ P# ~/ q 36 {$ M0 ~, }' j. |$ w5 e 37#ifndef RT_USB_DEVICE_MSTORAGE" B3 F3 W T" y2 E i 38 if(rt_device_find(FS_PARTITION_NAME) != RT_NULL) 39 { e: p8 W. M6 b6 k% J& j 40 dfs_mkfs("lfs", FS_PARTITION_NAME);8 I& e+ F2 S* G3 f' f9 N- ^ n 41 42 if (dfs_mount(FS_PARTITION_NAME, "/", "lfs", 0, 0) == RT_EOK)& e1 v% S ]6 g 43 { 44 rt_kprintf("sd card mount to '/'\n"); 45 break;( l. s* V+ _& R) u5 \- @& { 46 } 47 else 48 { 49 rt_kprintf("sd card mount to '/' failed!\n"); 50 } 51 }% ^( v5 Z% u8 i8 Y- n7 W 52#endif 53 rt_pin_write(LED0_PIN, PIN_HIGH); y; q8 r+ i# k; t$ \0 T- T 54 rt_thread_mdelay(500);1 N, l2 F1 Q, R% d" s ] 55 rt_pin_write(LED0_PIN, PIN_LOW);4 _0 f' k/ k7 m, b' d- { j 56 rt_thread_mdelay(500);* |8 Q) I0 j% h1 e1 j( J 57 } 58 59 return RT_EOK;9 _- o+ h! G) O% N) I, S 60}+ @- ^ M* J& N$ D3 n6 |: w4 g , k; J6 S1 A9 j) z* _ 项目编译下载到板子上,串口连接上去在 msh 里输入 fal probe 应当就可以看到分区表了: ![]() Linux 下常用的命令 ls ,cat,mkdir,cd 也都是支持的,这样我们就把 stm32 的片上 flash 挂载为文件系统了, 下一步就是让它识别为 U盘。 / b2 m. |0 Q: [0 x0 g5 M3. 挂载片上 Flash 为 U盘同样的,我们在 env 的配置目录里面依次选中:
![]()
![]() ![]() 这样保存配置,在 env 下生成项目文件: 1scons --target=mdk5 -s) O; I: W8 ?1 Q* T' e! L7 J, c% l编译上传到板子上,接上 USB 到电脑,例如 STM32F103 的 USB 引脚是 PA11 和 PA12,就可以看到电脑识别到一个新的 U盘了,第一次使用可能需要先格式化。 ![]() |
![]() |
我还以为能运行呢 |