你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

在STM32F1片上 Flash 保存第一人称 3D 射击游戏

[复制链接]
eefishing 发布时间:2019-11-28 23:18
每当提到 3D 第一人称射击游戏,大家很自然就会联想到高性能独显,以及几个G甚至几十G的硬盘存储空间,那么有没有可能在 STM32F103RC 这样一块只有 256KB Flash 的小板子上保存一个大型第一人称射击游戏呢?
1.jpg
当我们用 USB 线把这块开发板连接到电脑上,就可以看到出现了一个只有100多KB的U盘,这就是 STM32 的片上 Flash 了。
% X! Y; @7 {4 b6 D
2.jpg
然后可以看到U盘里有一个 90KB 的游戏。
3.jpg
如果我们双击它就启动了一个 STM32 上的第一人称射击游戏。
% P. z$ {1 |- r! [* O" N6 ]% v
3 Z; _  {6 e" L% e) h9 v
这是完整的演示视频:如果你也有兴趣把这个游戏保存在 STM32 上,可以跟着后面的教程,或者也可以在这个项目里直接找到编译好的固件、游戏和项目源码。
# ^" C( g* M4 S' L' a5 i; k) a
链接地址:http://github.com/wuhanstudio/stm32-ufun-3d-game
" `/ R" M5 r% c3 z5 Y
1. 运行 RT-ThreadRT-Thread 在 Github 上是开源的,源码可以在这里(链接:http://github.com/rt-Thread/rt-thread/找到,官网文档也很丰富这里就不重复了,总结一下需要的工具:
  • Git Bash
  • Keil 开发环境
  • STM32 开发板
  • RT-Thread 源码
  • env 工具
    2 ^' d5 e* ?  O1 \1 \4 S% d
如果觉得从 github 上面下载 RT-Thread 源码比较慢,可以先从 gitee 上面下载,然后修改项目地址。
1git clone https://gitee.com/rtthread/rt-thread
" p% m# _6 Z+ }$ A% @. h9 r) k2cd rt-thread
3 D1 D* [. Z4 ?8 M' N3git remote rm origin) l6 K+ S7 q/ H, ]
4git remote add origin https://github.com/RT-Thread/rt-thread
+ l: m6 p1 ^1 S5git pull origin master
) b& t" \5 Y, ]* z; V% [  `$ ^  [6 U. B
2. 片上 Flash 文件系统准备好第一步里面的工具后,首先我们需要把 STM32 的片上 flash 挂载为文件系统,首先需要在 CubeMX 里使能 USB。
4.jpg
打开 USB 后在时钟配置里确认外部晶振和板子上的晶振是一致的,并且 USB 的时钟是 48MHz,就可以点击生成代码了。由于我们修改了时钟,需要把 board/CubeMX_Config/Src/main.c 里面的 void SystemClock_Config(void) 函数复制到 board/board.c 里面替换。
接下来修改 bsp 下 board 目录里的 Kconfig 文件。1config BSP_USING_ON_CHIP_FLASH7 [7 v" S3 w; D4 P3 J. {8 r
2    bool "Enable on-chip FLASH"
2 v' d  i1 R8 Z* M  _: ?" v; a. I( L3    default n
  Y0 H- |; D& w( U4
. O' x* F: v' p* I; }* {5config BSP_USING_USBD_FS
; [) D) m0 z) X) U  q5 Y6    bool "Enable USBD as USB device"3 s" a) c) [; {: g9 [( I( ]9 o
7    select RT_USING_USB_DEVICE+ m& m/ ~/ ?5 x! I
8    default n
( f, k! a$ J' |& ^8 K5 q
这样再在 bsp 目录下右键 ConEmu Here 就可以看到配置界面 (Env 教程:http://www.rt-thread.org/document/site/tutorial/env-video/),依次选中下面几个选项:
  • Hardware Drivers Config --> Enable on-chip Flash
    8 p  r3 O$ N8 X5 C( ~8 r8 `
5.jpg

6 }3 |$ m! o- w& A7 |. n# p
  • RT-thread Components --> Device Drivers --> Using MTD Nor Flash device drivers
    ) ~* a/ C" U+ W- U& y* Y
6.jpg
( n3 a% f6 b/ A1 t9 f
  • RT-Thread online packages --> system packages 选中 fal 和 Littlefs2 O1 u) ?0 f! t! A! O3 Z8 Z% ~
7.jpg

; h7 _$ h- j$ b: D8 O) g
  • RT-Thread Components --> Device virtual file system
    $ q/ |) l3 ?6 p  T* `4 ]( k
8.jpg

; I$ f) R* v5 O) |
保存配置退出,在 env 里面输入命令就可以自动生成 Keil 项目了:
) U3 {& ]6 o" D# G6 c/ {& c8 \
1pkgs --update
. T+ Q( k# C" _2scons --target=mdk5 -s7 S0 t4 z. C3 {* s

, s# E: L' c5 Q
我们需要先对 flash 进行规划,STM32F103RC 一共有 256KB,可以把最后的 128KB 作为文件系统使用,于是新建一个 fal_cfg.h 1extern const struct fal_flash_dev stm32_onchip_flash;0 y9 k) N0 @) ]5 I) a4 ^2 [
2
  ~% s- F. S6 v 3#define FAL_FLASH_DEV_TABLE                                          \; w; x* L/ q6 z! y9 H
4{                                                                    \
$ }5 ^0 Y# i9 O% W( |& _9 @. [ 5    &stm32_onchip_flash,                                           \
1 _: D% i+ `0 i4 `% O 6}
: [/ A5 [: x3 q5 K. B$ K% F  h
7
; z" _! [' S6 u- g! b* q 8#define FAL_PART_TABLE                                                          \
1 O% u2 d3 W9 K! { 9{                                                                               \
: b$ r* b  ^9 f' w! n1 b. r" j10    {FAL_PART_MAGIC_WROD,       "app", "onchip_flash",         0,   128*1024, 0}, \
* ^2 c- t. V1 ?7 }+ m11    {FAL_PART_MAGIC_WROD,      "flash0", "onchip_flash",   128*1024,  128*1024, 0}, \
' q* y/ |: G. M3 B0 V. X/ r( I  `% r12}

- S2 w! [0 Y1 C# B  E$ q: n
; ^9 e3 p9 d( l5 w. z& w8 G
再修改 main.c 挂载文件系统:
1#include <rtthread.h>
% M6 M0 I- Z  W* Z/ X5 k  h 2#include <rtdevice.h>
4 ?$ ]0 B$ K% V9 c$ T 3#include <board.h>5 Z: o; c+ V. m5 q% m' _0 U
4#include <fal.h>
2 C/ n( l" j- u5 H4 w, a 5#include <dfs_posix.h>
/ j+ R$ [2 d- ?+ l 6
8 b; _/ x& {/ J( Q$ |, h  p- |: D 7/* defined the LED0 pin: PC13 */
6 y  Y  Z- `& D* i 8#define LED0_PIN    GET_PIN(C, 13)
2 l; w4 ?/ |% a0 u 9% h6 r  z% f7 [0 `$ Q
10#define FS_PARTITION_NAME  "flash0"$ S+ P$ \2 [3 n* U3 H3 i
11
  A0 O- c# ~+ s2 J% H# H. ]: e12int main(void)9 x; n  c' @$ n: e6 O! O+ j
13
{& P/ B1 \7 {( ~
14    int count = 1;$ |& p9 s% v0 J# T
15    /* set LED0 pin mode to output */- V6 l  K  J. o& c2 Z
16    rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT);
8 t; t' Z7 y% k- c- R. ?17
1 A* _; Q* _5 _) B  a18    fal_init();8 Y: A  B5 H+ @6 |% V( b
19
1 u0 v7 r* n& @! I$ X: b" t20#ifdef RT_USB_DEVICE_MSTORAGE
$ e3 k% V) z. V$ |$ `$ u8 H21    struct rt_device *flash_dev = fal_blk_device_create(FS_PARTITION_NAME);' z, K9 W- j5 U
22#else
' ?4 d( v& r2 V( Y: ^1 l! z7 q23    struct rt_device *flash_dev = fal_mtd_nor_device_create(FS_PARTITION_NAME);) s& ]: @# L2 S) M
24#endif+ i: Y3 G. d8 l% @; _/ H. F
25
6 _0 |0 w) M* l26    if (flash_dev == NULL)$ H) L- ]" r% J; ?- ~) J0 a' Y
27    {9 x4 R$ m0 f. d9 ~( K2 @) l) A
28        rt_kprintf("Can't create a block device on '%s' partition.\n", FS_PARTITION_NAME);8 y2 M8 k- ^& d% I# Z5 }0 ^8 h( Y( A
29    }# _) C% W+ J  D9 ^! D5 q4 N5 j- G
30    else
+ h: D. |! c$ S7 _7 n31    {- D( @$ M9 B8 U% [+ w+ V
32        rt_kprintf("Create a block device on the %s partition of flash successful.\n", FS_PARTITION_NAME);
! @" E0 T! x  i# l# U3 [33    }
# t; O) x* w1 \" a6 l34
( i; U1 n2 s9 s, N2 D( T. a4 F35    while (count++)6 m" _+ }9 J) T
36    {
3 Z* d# p. i* u$ e4 ?1 t37#ifndef RT_USB_DEVICE_MSTORAGE
7 Z7 z0 h. U: {, x3 W38        if(rt_device_find(FS_PARTITION_NAME) != RT_NULL)7 k" K" E) O) ~! {+ e
39        {9 ?- w* e6 Q3 h) P0 Q# K
40            dfs_mkfs("lfs", FS_PARTITION_NAME);
3 _; n: m4 {) P, e  [, v41, Q$ a9 ~* i- ?' }1 q
42            if (dfs_mount(FS_PARTITION_NAME, "/", "lfs", 0, 0) == RT_EOK)3 s4 j; r4 s( U. I( q
43            {4 @# `5 d. c  V
44                rt_kprintf("sd card mount to '/'\n");
2 Y% V% Q7 \( r, U6 {45                break;' R0 t* [  K; r4 A, P! x# v
46            }) c! f4 d9 y" G0 d6 W: a5 `: k. |
47            else  n! g1 n$ a( A6 C
48            {
$ R7 s, ~2 W& z# A/ {8 R& N49                rt_kprintf("sd card mount to '/' failed!\n");9 j, r+ W4 N  e) _* X0 ?" N3 q
50            }/ h1 W3 S, a9 K" y1 e- ]0 K
51        }4 t: E7 S* Z% T0 h$ E4 S+ g
52#endif
8 }/ C& ]5 e% `53        rt_pin_write(LED0_PIN, PIN_HIGH);
* V# g5 m2 h1 X; @54        rt_thread_mdelay(500);
5 y& D: m! @3 J55        rt_pin_write(LED0_PIN, PIN_LOW);
, s1 ^* Q+ e( Y, [- n4 F56        rt_thread_mdelay(500);
2 Q! N' [+ n. G6 H$ [) D% w57    }+ _4 I' _# C$ |! }) H) ]# |
58* C/ c8 z. j& X/ V9 ]
59    return RT_EOK;& E6 V) y  D8 Y% W1 J. k- A; J
60}
" z: T7 B- _9 l# E# G. K. A  Q% a, k
项目编译下载到板子上,串口连接上去在 msh 里输入 fal probe 应当就可以看到分区表了:
9.jpg
Linux 下常用的命令 lscatmkdircd 也都是支持的,这样我们就把 stm32 的片上 flash 挂载为文件系统了, 下一步就是让它识别为 U盘。

/ w# s; Q3 v* k& k+ O7 P$ G  K; o3. 挂载片上 Flash 为 U盘同样的,我们在 env 的配置目录里面依次选中:
  • Hardware Drivers Config --> On-chip Peripheral Drivers! Y* j/ b. o3 K, l; ]2 P
10.jpg
  • RT-Thread Components --> Device Drivers --> Using USB
      S' P0 U* J  z
11.jpg
12.jpg
这样保存配置,在 env 下生成项目文件:
1scons --target=mdk5 -s! e+ j6 d- |& O5 w* p' u
编译上传到板子上,接上 USB 到电脑,例如 STM32F103 的 USB 引脚是 PA11 和 PA12,就可以看到电脑识别到一个新的 U盘了,第一次使用可能需要先格式化。
13.jpg
最后其实就只是把高压的游戏复制进去,就把它装进 STM32 的片上 flash 了,其实还是挺简单的。完整的项目地址在这里:http://github.com/wuhanstudio/stm32-ufun-3d-game
收藏 评论2 发布时间:2019-11-28 23:18

举报

2个回答
qianfan 回答时间:2019-11-29 08:46:45
这不就是做了个U盘,跟游戏有毛线关系
李康1202 回答时间:2019-11-29 08:48:45
我还以为能运行呢
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版