diff --git a/rt-thread-version/rt-thread-standard/_sidebar.md b/rt-thread-version/rt-thread-standard/_sidebar.md index 65d41314281bf2fdcd78dc8464819007003af925..91845058cbac7f3a6102071b2f5bd4295a5f094b 100644 --- a/rt-thread-version/rt-thread-standard/_sidebar.md +++ b/rt-thread-version/rt-thread-standard/_sidebar.md @@ -205,6 +205,8 @@ - [恩智浦FRDM-MCXN236开发实践指南](/rt-thread-version/rt-thread-standard/tutorial/make-bsp/MCX-N236/恩智浦FRDM-MCXN236实践指南.md) - [恩智浦FRDM-MCXA153开发实践指南](/rt-thread-version/rt-thread-standard/tutorial/make-bsp/MCX-A153/恩智浦FRDM-MCXA153实践指南.md) - [恩智浦FRDM-MCXA156开发实践指南](/rt-thread-version/rt-thread-standard/tutorial/make-bsp/MCX-A156/恩智浦FRDM-MCXA156实践指南.md) + - GD32系列 + - [兆易创新GD32F527I-EVAL开发实践指南](/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/兆易创新GD32F527I-EVAL开发实践指南.md) - 官方开发板 - [星火一号](/rt-thread-version/rt-thread-standard/hw-board/spark-1/spark-1.md) diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/025fd5eac6b193836218de79689c3ddc.png b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/025fd5eac6b193836218de79689c3ddc.png new file mode 100644 index 0000000000000000000000000000000000000000..3c2db146c85ffaec391895234cbbf6ca95d9231e Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/025fd5eac6b193836218de79689c3ddc.png differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/067b98f19920dea87052aaa61bd36090.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/067b98f19920dea87052aaa61bd36090.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..11df3e48a2261a310a5ff35b39116d3adf947002 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/067b98f19920dea87052aaa61bd36090.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/077a9813a04cc75668edfe96cc1da549.png b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/077a9813a04cc75668edfe96cc1da549.png new file mode 100644 index 0000000000000000000000000000000000000000..b4c73b92ad75bc2572c17b9bd450e27b8d283173 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/077a9813a04cc75668edfe96cc1da549.png differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/07a77ecdfdcc44763372331c213ca42e.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/07a77ecdfdcc44763372331c213ca42e.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..64c08cc0bd13bf17f65509013861594cc4e06a44 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/07a77ecdfdcc44763372331c213ca42e.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/07d38f5a3c7e1aa43add272c5d5e3ee9.png b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/07d38f5a3c7e1aa43add272c5d5e3ee9.png new file mode 100644 index 0000000000000000000000000000000000000000..6293ee6e6f7fcac3dfcc2c62206f164d878fc208 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/07d38f5a3c7e1aa43add272c5d5e3ee9.png differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/09235d744d7b00e37f423d7a07ec47fb.jpg.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/09235d744d7b00e37f423d7a07ec47fb.jpg.webp new file mode 100644 index 0000000000000000000000000000000000000000..639d342d2e8c587a1a98ecf9ba1f4c4c7a260a8c Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/09235d744d7b00e37f423d7a07ec47fb.jpg.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/0af836b802faca1822818d49ef053399.png b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/0af836b802faca1822818d49ef053399.png new file mode 100644 index 0000000000000000000000000000000000000000..b5105e6760d973c65b41ef45c4ade7f9d0ce3e3b Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/0af836b802faca1822818d49ef053399.png differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/0e2058426337f396274540d85bcc63e3.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/0e2058426337f396274540d85bcc63e3.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..337e2606329adc623481f8173e4c2fd64b64ae5b Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/0e2058426337f396274540d85bcc63e3.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/0f75ac19913ce132e791b0c60591a5f1.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/0f75ac19913ce132e791b0c60591a5f1.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..ea33ca73b107e563f5d67664a08e346e3f8c103d Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/0f75ac19913ce132e791b0c60591a5f1.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/1511c0cc14708170e143fb44fbcaa0db.png b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/1511c0cc14708170e143fb44fbcaa0db.png new file mode 100644 index 0000000000000000000000000000000000000000..442223fd5bcaddbc5c0cd506c6bf168e1055d476 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/1511c0cc14708170e143fb44fbcaa0db.png differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/15393c0220a0efddd7e160b1243016ac.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/15393c0220a0efddd7e160b1243016ac.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..6f9fcfa471fd55fc8e2d4181bcee6803ec6a140b Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/15393c0220a0efddd7e160b1243016ac.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/15af186db81a92b3f8b0308cb4d9fa86.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/15af186db81a92b3f8b0308cb4d9fa86.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..eefc382239e3a61a2097b679ca9561fa28adf95a Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/15af186db81a92b3f8b0308cb4d9fa86.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/16b610a5a4bb58e6441bccabb7638646.png b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/16b610a5a4bb58e6441bccabb7638646.png new file mode 100644 index 0000000000000000000000000000000000000000..d3eb3b75e37e597cb0a0118d33785a58666af9d1 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/16b610a5a4bb58e6441bccabb7638646.png differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/16b626fb433f1081c0fd2ebfbad70660.jpg.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/16b626fb433f1081c0fd2ebfbad70660.jpg.webp new file mode 100644 index 0000000000000000000000000000000000000000..920a0e5afc8c34a090d842ae36996d24fa0afbde Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/16b626fb433f1081c0fd2ebfbad70660.jpg.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/1704ad6994bfcf200f6910b4221fa3cd.jpg b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/1704ad6994bfcf200f6910b4221fa3cd.jpg new file mode 100644 index 0000000000000000000000000000000000000000..066e81e0780441ba7c2771f6d51dd6d3d0b53850 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/1704ad6994bfcf200f6910b4221fa3cd.jpg differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/1804bb3e05b66b90f46d86503110ae8b.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/1804bb3e05b66b90f46d86503110ae8b.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..ee751ab16e047eb574ca0e8ef3b2623c2812fda0 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/1804bb3e05b66b90f46d86503110ae8b.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/18b4b1b193019c378b300b1806465c7a.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/18b4b1b193019c378b300b1806465c7a.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..10fe0def0045a56c953ad6e465eced9064e5ff8d Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/18b4b1b193019c378b300b1806465c7a.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/1acbe569999f00a5f70e359d05482fa8.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/1acbe569999f00a5f70e359d05482fa8.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..7a629e2b7a8b29e7d9649d409c639cc197366ea4 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/1acbe569999f00a5f70e359d05482fa8.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/1ad91584375345904304bf4930782a56.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/1ad91584375345904304bf4930782a56.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..f40c8f6276f154d012c803857e8dbc1feef11cc4 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/1ad91584375345904304bf4930782a56.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/1de209e8a1af79343e74b57c889c9b01.png b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/1de209e8a1af79343e74b57c889c9b01.png new file mode 100644 index 0000000000000000000000000000000000000000..13a51c732b3f1eb3295e9e71abde8c2769c51344 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/1de209e8a1af79343e74b57c889c9b01.png differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/1e41667b05534cd5257d10a2fb3d84b1.png b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/1e41667b05534cd5257d10a2fb3d84b1.png new file mode 100644 index 0000000000000000000000000000000000000000..2a498dc8233bd640a4b344ece063a5435f8bf9b1 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/1e41667b05534cd5257d10a2fb3d84b1.png differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/1e88ddc6f4b7e35fd7716ce2fd9d10e9.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/1e88ddc6f4b7e35fd7716ce2fd9d10e9.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..cce877aa6f8b905f42791ef9544e4eccb1fc5c73 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/1e88ddc6f4b7e35fd7716ce2fd9d10e9.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/1faa7ec5c47a04140bcd716d3c4cbce6.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/1faa7ec5c47a04140bcd716d3c4cbce6.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..91b6e103037a53016975ec702ed080cb56b5f2db Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/1faa7ec5c47a04140bcd716d3c4cbce6.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/202510142104811.png b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/202510142104811.png new file mode 100644 index 0000000000000000000000000000000000000000..fd3a48f00f3a32f3f5271f0109c8280542340601 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/202510142104811.png differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/202510142104812.png b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/202510142104812.png new file mode 100644 index 0000000000000000000000000000000000000000..71f16ad180e8104d23952c2cb67e8891f4e31d3a Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/202510142104812.png differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/202510142104813.png b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/202510142104813.png new file mode 100644 index 0000000000000000000000000000000000000000..18b0fa8d090999606db7f5d66505f87df1302b4c Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/202510142104813.png differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/202510142104814.png b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/202510142104814.png new file mode 100644 index 0000000000000000000000000000000000000000..c9f0890bb30230207f5659c1941d812239209220 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/202510142104814.png differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/241334761618523f528f28b8f7d12473.png b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/241334761618523f528f28b8f7d12473.png new file mode 100644 index 0000000000000000000000000000000000000000..c29f56b9c684663f342a9b58e02f66bab63b543f Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/241334761618523f528f28b8f7d12473.png differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/24728b93aef26352f66388445ad85651.png b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/24728b93aef26352f66388445ad85651.png new file mode 100644 index 0000000000000000000000000000000000000000..2efa809990f9793bdf25ed098deb3a203e2f9d5b Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/24728b93aef26352f66388445ad85651.png differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/2635049030ee9a1df3d7c4a6de49addf.png b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/2635049030ee9a1df3d7c4a6de49addf.png new file mode 100644 index 0000000000000000000000000000000000000000..85b192e60307439c227203ff1878d882b5bea782 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/2635049030ee9a1df3d7c4a6de49addf.png differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/2657c28304f01daee344e73607b5d61c.png b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/2657c28304f01daee344e73607b5d61c.png new file mode 100644 index 0000000000000000000000000000000000000000..4d5408f37cd429afe5a0cf790e1adc2f69db4f4e Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/2657c28304f01daee344e73607b5d61c.png differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/2b9c505eae774068c95deb77b8919f45.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/2b9c505eae774068c95deb77b8919f45.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..de54b5d535ff22e0f474c92b946115279b83c66f Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/2b9c505eae774068c95deb77b8919f45.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/2c1b4c8372400bdd551c1ded7067edc6.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/2c1b4c8372400bdd551c1ded7067edc6.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..d6ccdb38a014aa6bbc131ed9004524ac5db2ee45 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/2c1b4c8372400bdd551c1ded7067edc6.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/2df0b2d3e8939fb64a0337f6dfaad1fd.jpg.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/2df0b2d3e8939fb64a0337f6dfaad1fd.jpg.webp new file mode 100644 index 0000000000000000000000000000000000000000..e3c6757d5aace9f25c8fd1acfccb7a17a225cd1e Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/2df0b2d3e8939fb64a0337f6dfaad1fd.jpg.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/2f8f51774894a38ce53ce84320ec2101.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/2f8f51774894a38ce53ce84320ec2101.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..e6bd4c8631eb2f10da302be272c939aad7bcb96a Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/2f8f51774894a38ce53ce84320ec2101.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/3153ddb66070e5948e67cea2839d1e11.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/3153ddb66070e5948e67cea2839d1e11.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..d1506be79d60c310b927121c8f5ce45531cdd9fa Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/3153ddb66070e5948e67cea2839d1e11.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/321dee167034832260864a187efe59eb.jpg.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/321dee167034832260864a187efe59eb.jpg.webp new file mode 100644 index 0000000000000000000000000000000000000000..46d8a073346b28f34412de918e481c3c1eed4a03 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/321dee167034832260864a187efe59eb.jpg.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/3386813c4edcc2e6902f74169a1278a2.png b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/3386813c4edcc2e6902f74169a1278a2.png new file mode 100644 index 0000000000000000000000000000000000000000..3eb72d1671fddf3e25801f7be17948b1767a7e28 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/3386813c4edcc2e6902f74169a1278a2.png differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/33bf40913601cc68c07f2c4eaa128460.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/33bf40913601cc68c07f2c4eaa128460.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..5f1bb7e9caa4dca1cc5e077a081231000ca5c81c Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/33bf40913601cc68c07f2c4eaa128460.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/356487daa1b90eacf4b7aec4379ada69.jpg.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/356487daa1b90eacf4b7aec4379ada69.jpg.webp new file mode 100644 index 0000000000000000000000000000000000000000..448fcb4c4b7e209907cf35e3824d452959e6e2f2 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/356487daa1b90eacf4b7aec4379ada69.jpg.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/36b8e7c5d6befde4e50bd521dda4cf96.jpg.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/36b8e7c5d6befde4e50bd521dda4cf96.jpg.webp new file mode 100644 index 0000000000000000000000000000000000000000..7b4cf2839b5232d94f49123eab994d77b1812ec8 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/36b8e7c5d6befde4e50bd521dda4cf96.jpg.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/38c4d590c583b5f5449bde7b01e4173a.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/38c4d590c583b5f5449bde7b01e4173a.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..b38a6fadb8b2a06098e4ebc0018d993a837185f6 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/38c4d590c583b5f5449bde7b01e4173a.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/398a131d4cffd833a5aa501f09a89798.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/398a131d4cffd833a5aa501f09a89798.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..0833374815f1b8a4ed4b75b41b233dcfb7843f06 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/398a131d4cffd833a5aa501f09a89798.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/3a3613be615157829e64e67458beea37.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/3a3613be615157829e64e67458beea37.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..9d37fca4945d53826a3bcc655ed4e419e10e0dee Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/3a3613be615157829e64e67458beea37.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/3c8e02ec1a2e76015843aad6ba862db9.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/3c8e02ec1a2e76015843aad6ba862db9.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..50fa51538f4755d22f7187a1b5d2d7f3503a4932 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/3c8e02ec1a2e76015843aad6ba862db9.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/3d74cec7537232e45998a808996f0df3.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/3d74cec7537232e45998a808996f0df3.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..20cbc7d6dc3c5a3c72aeb8426e1775a02996f027 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/3d74cec7537232e45998a808996f0df3.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/40919b7694173bb9f28c1c62004fde94.jpg.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/40919b7694173bb9f28c1c62004fde94.jpg.webp new file mode 100644 index 0000000000000000000000000000000000000000..8e55203345bf48e781fa4dceae6e3a94c256cc50 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/40919b7694173bb9f28c1c62004fde94.jpg.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/40d02ff936eed913023f7a8fe67886f8.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/40d02ff936eed913023f7a8fe67886f8.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..e27988603940611f1d99aa54e5ce1100647dec7c Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/40d02ff936eed913023f7a8fe67886f8.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/41c92068672b8d3bd5b0f3c071be06c7.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/41c92068672b8d3bd5b0f3c071be06c7.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..fc57167aeae584f2a3e9f6f2b8e0ddb3c7b53996 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/41c92068672b8d3bd5b0f3c071be06c7.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/42f51492adb52063b4c697974d802e17.gif b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/42f51492adb52063b4c697974d802e17.gif new file mode 100644 index 0000000000000000000000000000000000000000..80a0a170b9d0c825274deb27a55b7bfda2d7367a Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/42f51492adb52063b4c697974d802e17.gif differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/4325ead0a144794832cc2b65745a6d92.png b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/4325ead0a144794832cc2b65745a6d92.png new file mode 100644 index 0000000000000000000000000000000000000000..d63fb26fec64c374258b0c2603662b1d4c49a463 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/4325ead0a144794832cc2b65745a6d92.png differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/44be96b4e020f49db179d420f2f0b248.png b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/44be96b4e020f49db179d420f2f0b248.png new file mode 100644 index 0000000000000000000000000000000000000000..34e8315121d7b5aa0bb25cadf1ead7fcfb87f384 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/44be96b4e020f49db179d420f2f0b248.png differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/4568470b225d996eb5e912e15951037c.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/4568470b225d996eb5e912e15951037c.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..1242e9384d83dfaf7c54c9798d51c5794632ad1f Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/4568470b225d996eb5e912e15951037c.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/4a7555d6b9871420cc72d160c674d0f2.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/4a7555d6b9871420cc72d160c674d0f2.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..bbd48ad5c96356eded30dcaf4e2848267c8a0598 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/4a7555d6b9871420cc72d160c674d0f2.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/4cf9f8e7a3449f65e1f4099486fcfe5f.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/4cf9f8e7a3449f65e1f4099486fcfe5f.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..6fda35c6e5f0ae55fe60dc24f2d0bdfd364ff085 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/4cf9f8e7a3449f65e1f4099486fcfe5f.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/4eac6f4b95d7d3ab78482ff4e32a7990.png b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/4eac6f4b95d7d3ab78482ff4e32a7990.png new file mode 100644 index 0000000000000000000000000000000000000000..5d1d429c56b9bc3f24e46c6a430fb6eb8ed60d91 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/4eac6f4b95d7d3ab78482ff4e32a7990.png differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/56690ade1ee1feba51b5c5b7c596c71a.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/56690ade1ee1feba51b5c5b7c596c71a.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..8d5a2a187757b824d941871ec1d0a25388497069 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/56690ade1ee1feba51b5c5b7c596c71a.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/5722a196503e198c48012a39f6354c8d.png b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/5722a196503e198c48012a39f6354c8d.png new file mode 100644 index 0000000000000000000000000000000000000000..901577c64d7fcbbddaf85c39fbc888dc1afe4e14 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/5722a196503e198c48012a39f6354c8d.png differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/5a233202eda882393fa9a165a59699e3.jpg.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/5a233202eda882393fa9a165a59699e3.jpg.webp new file mode 100644 index 0000000000000000000000000000000000000000..411cff9dadade074c6b7bbf3c66577f03b530ab0 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/5a233202eda882393fa9a165a59699e3.jpg.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/618b987d84fa1e658cf9c735d40ebc3a.jpg.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/618b987d84fa1e658cf9c735d40ebc3a.jpg.webp new file mode 100644 index 0000000000000000000000000000000000000000..ff002c6900fa19aa2f197baca007108a2fbaaeb8 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/618b987d84fa1e658cf9c735d40ebc3a.jpg.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/61af0d35b799ea9f7781d0130f3cc462.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/61af0d35b799ea9f7781d0130f3cc462.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..82761d22353bdfec0361e16c2c6a71d93afdedbc Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/61af0d35b799ea9f7781d0130f3cc462.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/62f094ad31d96c9b55194bcce8bc5766.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/62f094ad31d96c9b55194bcce8bc5766.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..693b120e3ed55caa10b516d193f7a148e54d6328 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/62f094ad31d96c9b55194bcce8bc5766.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/6609f6e1d7fa98f8d092ab1295d350a0.png b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/6609f6e1d7fa98f8d092ab1295d350a0.png new file mode 100644 index 0000000000000000000000000000000000000000..9895be87fb49574e72deeaac8153782023471d46 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/6609f6e1d7fa98f8d092ab1295d350a0.png differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/6ad4f7b6c5102a36c39558c1c9f3e473.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/6ad4f7b6c5102a36c39558c1c9f3e473.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..69fe750654487c2afc4f77b492eaa922547360df Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/6ad4f7b6c5102a36c39558c1c9f3e473.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/6bdc4abc116dde34226c376264a90630.jpg.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/6bdc4abc116dde34226c376264a90630.jpg.webp new file mode 100644 index 0000000000000000000000000000000000000000..45718527054107d975ef71aeeb0b5fc20632d2d7 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/6bdc4abc116dde34226c376264a90630.jpg.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/6cc6046c594477a756487f48d69b877b.jpg.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/6cc6046c594477a756487f48d69b877b.jpg.webp new file mode 100644 index 0000000000000000000000000000000000000000..698f3eef075409c349f2602b8e7c64c9c49c9c0c Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/6cc6046c594477a756487f48d69b877b.jpg.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/6d773984d9caff0fef5aa4679d2e9169.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/6d773984d9caff0fef5aa4679d2e9169.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..6e6699d553d2c4a369378190b7ab0ab866d49fc2 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/6d773984d9caff0fef5aa4679d2e9169.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/6e888aaadc7c6b2babe7e878e9848ab3.jpg.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/6e888aaadc7c6b2babe7e878e9848ab3.jpg.webp new file mode 100644 index 0000000000000000000000000000000000000000..3c4c2f216a2b133f737531f2ff8a3ce39a71b8dc Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/6e888aaadc7c6b2babe7e878e9848ab3.jpg.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/743e1b3f8fce8aa65a863de9a0dd33d5.jpg b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/743e1b3f8fce8aa65a863de9a0dd33d5.jpg new file mode 100644 index 0000000000000000000000000000000000000000..07db268d743714e963c26f11a65d109d4d6ef683 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/743e1b3f8fce8aa65a863de9a0dd33d5.jpg differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/74cea2f706b552a9a09e144c00eb7b17.png b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/74cea2f706b552a9a09e144c00eb7b17.png new file mode 100644 index 0000000000000000000000000000000000000000..7cbb32407ac8c3276aabc4480f874bc9fd5e5888 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/74cea2f706b552a9a09e144c00eb7b17.png differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/757fc134e6c52adbcdd53299b6578907.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/757fc134e6c52adbcdd53299b6578907.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..56a98cbbac9a1977420dfb88a0eaa588432052b2 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/757fc134e6c52adbcdd53299b6578907.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/767ed45791951976af8c06d8648dfa01.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/767ed45791951976af8c06d8648dfa01.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..33c6207df16c09673124c66a955d9548766dc316 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/767ed45791951976af8c06d8648dfa01.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/768d263bae77e3e8df70ed193aa4c2d1.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/768d263bae77e3e8df70ed193aa4c2d1.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..5f0a5ab4b293c94cfb3ceacca4db8b68db4e0b3b Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/768d263bae77e3e8df70ed193aa4c2d1.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/77d178d537a57cc66c5a00f1e54c2694.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/77d178d537a57cc66c5a00f1e54c2694.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..c0e25d0feda3300f910e54b4ca9caf8ce0696d79 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/77d178d537a57cc66c5a00f1e54c2694.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/7904ab3ae704c567c7a2b91ecf61fd26.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/7904ab3ae704c567c7a2b91ecf61fd26.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..e5c5f23128b2d27440eaff848d31f06a4ca6bffd Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/7904ab3ae704c567c7a2b91ecf61fd26.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/7989ef2697ede7ed473534eb9c45f0f1.jpg.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/7989ef2697ede7ed473534eb9c45f0f1.jpg.webp new file mode 100644 index 0000000000000000000000000000000000000000..fe281786542342218bbd8611da561d5c976af896 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/7989ef2697ede7ed473534eb9c45f0f1.jpg.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/7b8594a0affb04576d3c2c734dcd7f2a.png b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/7b8594a0affb04576d3c2c734dcd7f2a.png new file mode 100644 index 0000000000000000000000000000000000000000..a6cfe67d01390de15d2ee3731ec71c46deaa83cb Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/7b8594a0affb04576d3c2c734dcd7f2a.png differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/80a557a9b4ff6e2b71526e6561f99e56.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/80a557a9b4ff6e2b71526e6561f99e56.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..21e8b53188dc3344ea78adb687ae3c937200a7cd Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/80a557a9b4ff6e2b71526e6561f99e56.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/81bf7b7cc2e2ca4e49fd2e55f1ff339a.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/81bf7b7cc2e2ca4e49fd2e55f1ff339a.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..8de94eef2f421399d366804febd352e8cc2bd165 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/81bf7b7cc2e2ca4e49fd2e55f1ff339a.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/86891aef9bd1b85cfff3342749c59861.jpg b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/86891aef9bd1b85cfff3342749c59861.jpg new file mode 100644 index 0000000000000000000000000000000000000000..aaa345a16ec7b79ad6541495f229cadf8ff5cb65 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/86891aef9bd1b85cfff3342749c59861.jpg differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/86e12495840206ada79ea758a69bd258.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/86e12495840206ada79ea758a69bd258.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..b659d95205e19652f29661c4e9ba23b77cfbf53d Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/86e12495840206ada79ea758a69bd258.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/88a869fe7bd0c2477c8869d1ac7936cd.png b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/88a869fe7bd0c2477c8869d1ac7936cd.png new file mode 100644 index 0000000000000000000000000000000000000000..50f712ed36445e076c45db6b4d0573ea1a5570bd Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/88a869fe7bd0c2477c8869d1ac7936cd.png differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/88cc0bd9f9266fc673554d15861a91bf.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/88cc0bd9f9266fc673554d15861a91bf.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..cca37d3007f93aacb62156c14fa634f897e3fb30 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/88cc0bd9f9266fc673554d15861a91bf.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/8913ed96d3a1899adeed3dc5c19f4415.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/8913ed96d3a1899adeed3dc5c19f4415.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..b84495de725ce0fe9ea4b5bd985cdc60537ba911 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/8913ed96d3a1899adeed3dc5c19f4415.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/8aec24eed73fe6c7fb1bc5358a27097e.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/8aec24eed73fe6c7fb1bc5358a27097e.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..d01a7d2bf667dd8c3e9abbe62685804511006956 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/8aec24eed73fe6c7fb1bc5358a27097e.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/90201352a4ff0e66e03476953e609322.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/90201352a4ff0e66e03476953e609322.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..ac368dfc7eee5e5dd606e2cd6fc628ff26222a3f Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/90201352a4ff0e66e03476953e609322.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/91c30fc3afeacd1fefe1e41cb5fc70ed.png b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/91c30fc3afeacd1fefe1e41cb5fc70ed.png new file mode 100644 index 0000000000000000000000000000000000000000..0a5413e9002b7a868b0c2ab2ee32ab65b7db53ba Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/91c30fc3afeacd1fefe1e41cb5fc70ed.png differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/92b4edc050a961400cfa478360562341.jpg.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/92b4edc050a961400cfa478360562341.jpg.webp new file mode 100644 index 0000000000000000000000000000000000000000..d544c10369c2d69f40c06806bf3b14bb77f70114 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/92b4edc050a961400cfa478360562341.jpg.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/92df6c4fcad6c7b25f42e004eff43ef8.jpg b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/92df6c4fcad6c7b25f42e004eff43ef8.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ae26218aa331da77dcd1493ec7b5110aad4bebde Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/92df6c4fcad6c7b25f42e004eff43ef8.jpg differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/95903f8bf12637fc78dbee912d6b4ed3.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/95903f8bf12637fc78dbee912d6b4ed3.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..3246f1049858233ec88bff86957f9b9eca23394f Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/95903f8bf12637fc78dbee912d6b4ed3.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/9628c68ec87f14a0ad2a538941fb89c3.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/9628c68ec87f14a0ad2a538941fb89c3.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..5e96d7ea742a333d0f9ed1cf7a0f9cd890c1ee86 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/9628c68ec87f14a0ad2a538941fb89c3.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/9ce37331f8e103c4a78e2bb4247f1c13.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/9ce37331f8e103c4a78e2bb4247f1c13.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..7d6d06e36b055fed4027d0e0878a823a364825d0 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/9ce37331f8e103c4a78e2bb4247f1c13.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/9d1964e84914f5a7f621c4f156c41a30.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/9d1964e84914f5a7f621c4f156c41a30.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..0d96593da80f1961d5a878165cac5dcce67b0b14 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/9d1964e84914f5a7f621c4f156c41a30.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/9e679caadfe5242a0f2934222276606a.png b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/9e679caadfe5242a0f2934222276606a.png new file mode 100644 index 0000000000000000000000000000000000000000..f24136aeb557dd9c956754bc6e22cd8e4011dd0e Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/9e679caadfe5242a0f2934222276606a.png differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/9f1c486e1574f92db4ef8de0cea19caa.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/9f1c486e1574f92db4ef8de0cea19caa.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..8c6ff25b89d12354fed9bb11eae5efcfad42bc1e Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/9f1c486e1574f92db4ef8de0cea19caa.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/9f58650e21f90dc59c816037f28eab06.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/9f58650e21f90dc59c816037f28eab06.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..ed15fce7d1399da8377943a9a063f4b4fdfabc94 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/9f58650e21f90dc59c816037f28eab06.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/a3535954fe4e2d1141b92dd4af137e46.png-1764739476112112.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/a3535954fe4e2d1141b92dd4af137e46.png-1764739476112112.webp new file mode 100644 index 0000000000000000000000000000000000000000..399894d8b73e02e88594b4ab8fb87cb090081071 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/a3535954fe4e2d1141b92dd4af137e46.png-1764739476112112.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/a3535954fe4e2d1141b92dd4af137e46.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/a3535954fe4e2d1141b92dd4af137e46.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..399894d8b73e02e88594b4ab8fb87cb090081071 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/a3535954fe4e2d1141b92dd4af137e46.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/a4c9f0517c2715f61afd9631476480e6.png b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/a4c9f0517c2715f61afd9631476480e6.png new file mode 100644 index 0000000000000000000000000000000000000000..12b7ec1929d725c976d7ce2e75ac3ece8b239043 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/a4c9f0517c2715f61afd9631476480e6.png differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/a4cd4b6764d3ba46ec9efd8a3b3d1638.jpg b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/a4cd4b6764d3ba46ec9efd8a3b3d1638.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ee8d4f7f5e1f80f99854a86894763cb53c682696 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/a4cd4b6764d3ba46ec9efd8a3b3d1638.jpg differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/a69cb2b504d255b5132a29d86891eb77.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/a69cb2b504d255b5132a29d86891eb77.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..b70de6e083598a14ebae728f74847af2d93a2869 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/a69cb2b504d255b5132a29d86891eb77.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/a90af5689f2c20565bb7cdf5ec2a1320.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/a90af5689f2c20565bb7cdf5ec2a1320.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..89d26db5e896d16d398f318e31c940d2d318da4a Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/a90af5689f2c20565bb7cdf5ec2a1320.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/aa3e9dbe7b44724ca68363adb54c781c.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/aa3e9dbe7b44724ca68363adb54c781c.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..833bce249a454220b0e464bada5f70b6f96d3a3a Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/aa3e9dbe7b44724ca68363adb54c781c.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/aab1c118290252486295cc749e36d75d.jpg b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/aab1c118290252486295cc749e36d75d.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f8794ddcd9a169b679531cbf58aba8fcb6ceb402 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/aab1c118290252486295cc749e36d75d.jpg differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/ac397300e634580e7825ef813758b19f.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/ac397300e634580e7825ef813758b19f.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..040f65edb317e1d551c2ef6bc30e74abe00098b6 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/ac397300e634580e7825ef813758b19f.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/ac410ffe6a693e01b2988dbfc1467c0e.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/ac410ffe6a693e01b2988dbfc1467c0e.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..70991a55eb97f20cbf0a0e1e2fc8b8aa8034e696 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/ac410ffe6a693e01b2988dbfc1467c0e.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/b176eaefe333731f002ecd9fd957732b.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/b176eaefe333731f002ecd9fd957732b.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..566f2e4bc94171d822756eaf5a66f384f4092c4b Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/b176eaefe333731f002ecd9fd957732b.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/b1a05d89aba1dd39cf622920c8c917fb.png b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/b1a05d89aba1dd39cf622920c8c917fb.png new file mode 100644 index 0000000000000000000000000000000000000000..8c1c1c2746bca64722653ebb02a2f80681110ae5 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/b1a05d89aba1dd39cf622920c8c917fb.png differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/b23f5215660c1aea9e6bf29c787c8d01.png b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/b23f5215660c1aea9e6bf29c787c8d01.png new file mode 100644 index 0000000000000000000000000000000000000000..7bc69b6454e295c470b9d805dddbc9971480ea40 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/b23f5215660c1aea9e6bf29c787c8d01.png differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/b36058e2fc12afee5f2659695ac5796a.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/b36058e2fc12afee5f2659695ac5796a.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..74c32cd3448da9e0cbad0e93b37e573ff45b2e7c Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/b36058e2fc12afee5f2659695ac5796a.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/b542e2b28f949b36a3346987be0d8dbd.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/b542e2b28f949b36a3346987be0d8dbd.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..1bd04b38ee11d75866cac182861950ea78a773a3 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/b542e2b28f949b36a3346987be0d8dbd.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/b66aadbf96f045731cded67b5c9af97e.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/b66aadbf96f045731cded67b5c9af97e.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..60f26b0b420704fae1dd2dd7b4fba53bf1b83a89 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/b66aadbf96f045731cded67b5c9af97e.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/b7b9dd9e26772d98eb51f453ec16adb3.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/b7b9dd9e26772d98eb51f453ec16adb3.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..1c20ba40b18cbe5fbad73199649e615a6354d065 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/b7b9dd9e26772d98eb51f453ec16adb3.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/b7c51e2f44045d75cd861b4ce7a9b05b.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/b7c51e2f44045d75cd861b4ce7a9b05b.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..bbde70e253a528b3dc4e6e5e8318cf48ab03dfaa Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/b7c51e2f44045d75cd861b4ce7a9b05b.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/b8052663a3cc35089277ff393a686ab9.png b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/b8052663a3cc35089277ff393a686ab9.png new file mode 100644 index 0000000000000000000000000000000000000000..b903e0f180c78a92c753e6167dccb632a7d97521 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/b8052663a3cc35089277ff393a686ab9.png differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/bb71192e39f25512d654be14348ec75e.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/bb71192e39f25512d654be14348ec75e.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..3accd12674d27b30af242ccc2a2b97deea44355b Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/bb71192e39f25512d654be14348ec75e.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/bbc5547cf258ddaf2581cc74a37d78a3.png b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/bbc5547cf258ddaf2581cc74a37d78a3.png new file mode 100644 index 0000000000000000000000000000000000000000..2743f8f27b98d1bb86b6a827f86de0dab78273c6 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/bbc5547cf258ddaf2581cc74a37d78a3.png differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/beda366a25e433bb5c45d510f08ad054.jpg.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/beda366a25e433bb5c45d510f08ad054.jpg.webp new file mode 100644 index 0000000000000000000000000000000000000000..4f0c6fdd6a87e27b28130d046c6170e7aa4725e5 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/beda366a25e433bb5c45d510f08ad054.jpg.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/bf7eb2d86b5b5726f54c28807493a7f0.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/bf7eb2d86b5b5726f54c28807493a7f0.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..d2bd296ed158b5d078e90c2917da3b98616b6ccd Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/bf7eb2d86b5b5726f54c28807493a7f0.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/c0a3b13a3fde923dfc9eb988970f307d.png b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/c0a3b13a3fde923dfc9eb988970f307d.png new file mode 100644 index 0000000000000000000000000000000000000000..c9d853f1a50736a06becbbaadc96b83434e2447d Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/c0a3b13a3fde923dfc9eb988970f307d.png differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/c24e57f274f6ade2847ea389fcade6ce.jpg.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/c24e57f274f6ade2847ea389fcade6ce.jpg.webp new file mode 100644 index 0000000000000000000000000000000000000000..ef8f6c95eae3a02c1df715961bd865f5e86870df Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/c24e57f274f6ade2847ea389fcade6ce.jpg.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/c52e7e6b393474823c62fcc1e483cd54.jpg.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/c52e7e6b393474823c62fcc1e483cd54.jpg.webp new file mode 100644 index 0000000000000000000000000000000000000000..ca404a1f6ea7d4c10532d7cceb1df271f8489f09 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/c52e7e6b393474823c62fcc1e483cd54.jpg.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/c695004bf50ed387359e82b4253673cc.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/c695004bf50ed387359e82b4253673cc.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..4290267312f8af39c9cfb3c4ed5a74d91f0b9652 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/c695004bf50ed387359e82b4253673cc.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/c8916c6adf783c97deb911161d140d4b.jpg.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/c8916c6adf783c97deb911161d140d4b.jpg.webp new file mode 100644 index 0000000000000000000000000000000000000000..e05df5b49f26f40ead84b3cc52af3e9faa1ee2b6 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/c8916c6adf783c97deb911161d140d4b.jpg.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/cb7f6d7ce186a7d780ff7c9b5bb6b6cb.png b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/cb7f6d7ce186a7d780ff7c9b5bb6b6cb.png new file mode 100644 index 0000000000000000000000000000000000000000..e67a7cd900a0d15c4e0bc358b6ef68a362eb511c Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/cb7f6d7ce186a7d780ff7c9b5bb6b6cb.png differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/cf6bb85712c3d748518b7bf587ecc530.png b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/cf6bb85712c3d748518b7bf587ecc530.png new file mode 100644 index 0000000000000000000000000000000000000000..3546991b539dd7785e2d8f18957c50cc89301812 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/cf6bb85712c3d748518b7bf587ecc530.png differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/cf88f6a6904630b8ca8687b0198a5508.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/cf88f6a6904630b8ca8687b0198a5508.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..6b0d8767452964c6393706c9341692d892550ffa Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/cf88f6a6904630b8ca8687b0198a5508.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/d2f38aea9e5d229b5e5a8a82381d6d09.jpg.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/d2f38aea9e5d229b5e5a8a82381d6d09.jpg.webp new file mode 100644 index 0000000000000000000000000000000000000000..104bf16bd2041e4243445a05d6f9fbd8420e033a Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/d2f38aea9e5d229b5e5a8a82381d6d09.jpg.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/d7955406ec71fe8d052a3dcd02962d0d.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/d7955406ec71fe8d052a3dcd02962d0d.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..aa098a01900f177cf6dd93c4ae345fd4b5ae5953 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/d7955406ec71fe8d052a3dcd02962d0d.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/d7f0feb2bc3da72993e3ed308e894dc8.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/d7f0feb2bc3da72993e3ed308e894dc8.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..a902afb2fd18411ab650abfc9a869cd63310a56e Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/d7f0feb2bc3da72993e3ed308e894dc8.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/d7fac99ca075aafb049123e218f4fe64.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/d7fac99ca075aafb049123e218f4fe64.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..a78d7b568332d0a03e603a4b3b65d7b37171ec77 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/d7fac99ca075aafb049123e218f4fe64.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/d94cd89c7c48ad2cce49d478c3a64260.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/d94cd89c7c48ad2cce49d478c3a64260.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..a3c49415b7ea3dceb96153da5e95cd7e66fd949a Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/d94cd89c7c48ad2cce49d478c3a64260.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/d9622ffedb4697c70aa65033b916b766.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/d9622ffedb4697c70aa65033b916b766.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..bbdbee15e12690e268a741a7ea4bb3eac0e8f341 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/d9622ffedb4697c70aa65033b916b766.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/de6517ddfec1cc131b7aac4da2b7ac01.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/de6517ddfec1cc131b7aac4da2b7ac01.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..d6ae6675a99c611df230b918664c0fb130b15b2b Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/de6517ddfec1cc131b7aac4da2b7ac01.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/e17111f1a0f722c85bd25cd09492f6e4.png b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/e17111f1a0f722c85bd25cd09492f6e4.png new file mode 100644 index 0000000000000000000000000000000000000000..aec42d7d14e7213262fe071b7d0b5a7bc11d40de Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/e17111f1a0f722c85bd25cd09492f6e4.png differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/e47f9ea068d9138ffb23ea8d2ef52458.png b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/e47f9ea068d9138ffb23ea8d2ef52458.png new file mode 100644 index 0000000000000000000000000000000000000000..10022211932d5df4e83bebc9b3850b976e43e4bb Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/e47f9ea068d9138ffb23ea8d2ef52458.png differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/e4ee21c9b2ee4bcc67e2e1e6504cc17f.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/e4ee21c9b2ee4bcc67e2e1e6504cc17f.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..83c8f36d9a3bc3ffde15e1102f2b888ad6e0aaee Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/e4ee21c9b2ee4bcc67e2e1e6504cc17f.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/e7021f7b30d8a731254d5d05f4115b54.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/e7021f7b30d8a731254d5d05f4115b54.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..d4bbe1bac68f5e8822ac572c37b9d3891c6ae4a1 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/e7021f7b30d8a731254d5d05f4115b54.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/e98149a0ce2bf29017a83610c69a6b56.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/e98149a0ce2bf29017a83610c69a6b56.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..4d7a9ce276fb396440fdcbe6e0b24c3b826060d7 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/e98149a0ce2bf29017a83610c69a6b56.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/ebc9b83bca96af1046a638585c928420.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/ebc9b83bca96af1046a638585c928420.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..a9b44d7b55291fc855387b30f2aea4e7e49f1c53 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/ebc9b83bca96af1046a638585c928420.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/ee66e5811e07d2fe2f57b6dd0e53ed69.jpg.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/ee66e5811e07d2fe2f57b6dd0e53ed69.jpg.webp new file mode 100644 index 0000000000000000000000000000000000000000..509143be21e73304ef9bb7a4a302f26aa1a49dc8 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/ee66e5811e07d2fe2f57b6dd0e53ed69.jpg.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/eea209e5cbca66ea9263bdfc01489c5e.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/eea209e5cbca66ea9263bdfc01489c5e.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..25a28acf50a11ae825d2fc80c417d8d20ecb0e1c Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/eea209e5cbca66ea9263bdfc01489c5e.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/f0aab93b7d3e86f9ae9fbfaa00224bd3.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/f0aab93b7d3e86f9ae9fbfaa00224bd3.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..f41bcb5ebadd9925af68e3b25e3c8656cfca43ba Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/f0aab93b7d3e86f9ae9fbfaa00224bd3.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/f0bdddae7046087f554ba7b1be942f41.png b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/f0bdddae7046087f554ba7b1be942f41.png new file mode 100644 index 0000000000000000000000000000000000000000..ab436083a15fc52a2b3bd6db34fa5f4d4a143604 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/f0bdddae7046087f554ba7b1be942f41.png differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/f2f00a42ff4416e661731aaf0e6674e2.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/f2f00a42ff4416e661731aaf0e6674e2.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..16c1c3f2b9d807a541229eeeb2e19c7fd298d994 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/f2f00a42ff4416e661731aaf0e6674e2.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/f3a846b06b548774f650b9108ece75dc.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/f3a846b06b548774f650b9108ece75dc.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..6c8ab894ba7948506bf47c8581e23a910ea30b6e Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/f3a846b06b548774f650b9108ece75dc.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/f4102b70e6d71b8e742858c53fcc1634.png b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/f4102b70e6d71b8e742858c53fcc1634.png new file mode 100644 index 0000000000000000000000000000000000000000..703c070d03beac771aaea9e012963b1ba187c3d0 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/f4102b70e6d71b8e742858c53fcc1634.png differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/f461639c7e1299e0ac4aec0f28dbcbc6.png b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/f461639c7e1299e0ac4aec0f28dbcbc6.png new file mode 100644 index 0000000000000000000000000000000000000000..0386d4a1898c493e1791286a418774817c4130c8 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/f461639c7e1299e0ac4aec0f28dbcbc6.png differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/f5efc242a2236d124e9e530a7f32fda1.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/f5efc242a2236d124e9e530a7f32fda1.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..8dfd7a9d4c1e5ce3b32975143e3dc45ec5f46760 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/f5efc242a2236d124e9e530a7f32fda1.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/f7e7ac946e494e3d8ff1e08913ff90c6.jpg.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/f7e7ac946e494e3d8ff1e08913ff90c6.jpg.webp new file mode 100644 index 0000000000000000000000000000000000000000..0721e83ff397aa0c07273b5ee15806375989ca3c Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/f7e7ac946e494e3d8ff1e08913ff90c6.jpg.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/f7ef1a13d45e2fd802cb672705d5eab7.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/f7ef1a13d45e2fd802cb672705d5eab7.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..ab28d0550444d3692714b5a2c371a76b7a89f9d7 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/f7ef1a13d45e2fd802cb672705d5eab7.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/f7f727c3c3bf20322a541c6c814b176c.png b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/f7f727c3c3bf20322a541c6c814b176c.png new file mode 100644 index 0000000000000000000000000000000000000000..c44972ab08e7bdcd4e91b0577b233cc74b4a845b Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/f7f727c3c3bf20322a541c6c814b176c.png differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/f98457f7dbcb83941bfe59060f9819b9.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/f98457f7dbcb83941bfe59060f9819b9.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..6d7e08bdfabca911412a6bcdf05d4a57b015ab1d Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/f98457f7dbcb83941bfe59060f9819b9.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/fa78f6125ab27f94edf777a395b9f808.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/fa78f6125ab27f94edf777a395b9f808.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..defac1f07076fb39bf149baf4c322bba676d7ddd Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/fa78f6125ab27f94edf777a395b9f808.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/fb12d2a9f3609084410daabdd4cd7805.jpg.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/fb12d2a9f3609084410daabdd4cd7805.jpg.webp new file mode 100644 index 0000000000000000000000000000000000000000..ccbdac765793ed13af56bec58e8fdb6347a81bef Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/fb12d2a9f3609084410daabdd4cd7805.jpg.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/fc86add56f36bb301ce91bf39d07fd3a.jpg b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/fc86add56f36bb301ce91bf39d07fd3a.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d273f0dbb6f23c5e289f4f3117a55870921a0c98 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/fc86add56f36bb301ce91bf39d07fd3a.jpg differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/fe7f385fccf4934e17060b0e854d9a8b.png.webp b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/fe7f385fccf4934e17060b0e854d9a8b.png.webp new file mode 100644 index 0000000000000000000000000000000000000000..20cb9d92e942dcbe34a465425f345f0e6983acc9 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/fe7f385fccf4934e17060b0e854d9a8b.png.webp differ diff --git a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/gd32f527i_eval.png b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/gd32f527i_eval.png new file mode 100644 index 0000000000000000000000000000000000000000..66bcca849913e74126c0349c77813fbb7a8922cf Binary files /dev/null and b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/figures/gd32f527i_eval.png differ diff --git "a/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/\345\205\206\346\230\223\345\210\233\346\226\260GD32F527I-EVAL\345\274\200\345\217\221\345\256\236\350\267\265\346\214\207\345\215\227.md" "b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/\345\205\206\346\230\223\345\210\233\346\226\260GD32F527I-EVAL\345\274\200\345\217\221\345\256\236\350\267\265\346\214\207\345\215\227.md" new file mode 100644 index 0000000000000000000000000000000000000000..7ce19add2602097eb89d22947d467000ece612e8 --- /dev/null +++ "b/rt-thread-version/rt-thread-standard/tutorial/make-bsp/gd32/\345\205\206\346\230\223\345\210\233\346\226\260GD32F527I-EVAL\345\274\200\345\217\221\345\256\236\350\267\265\346\214\207\345\215\227.md" @@ -0,0 +1,4726 @@ +# 兆易创新GD32F527I-EVAL开发实践指南 + +| **目录** | **作者** | +| ------------------------------- | ------------------------ | +| **零、实践指南说明** | **RT-Thread & 兆易创新** | +| **一、GD32F527上的UART实践** | **陈北斗** | +| **二、GD32F527上的GPIO实践** | **徐达勇** | +| **三、GD32F527上的RTC实践** | **李金磊** | +| **四、GD32F527上的ADC实践** | **马锡尧** | +| **五、GD32F527上的HWTimer实践** | **刘协泉** | +| **六、GD32F527上的SPI实践** | **刘建华** | +| **七、GD32F527上的PWM实践** | **赵瑞聪** | +| **八、GD32F527上的硬件IIC实践** | **董策** | +| **九、GD32F527上的ETH实践** | **麦欢艺** | +| **十、GD32F527上的CAN实践** | **吴艺彬、王凯** | +| **十一、GD32F527上的SDIO实践** | **戴凌祥、熊治坤** | +| **十二、GD32F527上的USB-D实践** | **吕阳、洪小玲** | +| **FAQ** | **RT-Thread & 兆易创新** | + +# 《兆易创新GD32F527I-EVAL开发实践指南》 零、实践指南说明 + +## 硬件介绍 + +1. 开发板描述:GD32F527I-EVAL 是兆易创新推出的基于 **GD32F527(Cortex-M33,200 MHz)高性能 MCU** 的官方评估板,板载以太网、USB OTG、QSPI Flash、SD 卡、LCD 接口、Arduino 扩展口等丰富外设,并集成调试接口,可用于快速评估 GD32F5 系列的计算性能、通信能力与图形显示等功能,非常适合工业控制、通信网关和人机界面等应用开发。 +2. 开发板外观如下图所示: + +![GD32F527I-EVAL](figures/gd32f527i_eval.png) + +3. 该开发板常用**板载资源**如下 + +- 微控制器 + - MCU 型号:GD32F527IST7 + - 内核:ARM® Cortex®‑M33 + - 主频:最高 200 MHz + - Flash:7.5MB Flash(含2MB零等待Code-Flash) + - SRAM:1MB SRAM(全空间ECC校验) + - 外设支持:ADC/DAC、多通道 SPI/I2C/UART/USART/I2S、CAN‑FD、USB OTG(FS/HS)、SDIO、EXMC、定时器、DMA、RTC 等 +- 连接性 + - USB:USB 2.0 OTG(Full Speed + High Speed) + - CAN:CAN‑FD + - 通讯接口:SPI / I2C / UART / USART / I2S / SDIO / EXMC + - 网络接口:Ethernet + - 显示接口:TFT‑LCD 控制器,支持 LCD/TFT 显示 + - 摄像头接口:DCI Camera 接口 + - 音频接口:SAI / I2S 支持音频输入/输出 + - 外部存储接口:SDIO / EXMC 支持 SDRAM / FLASH 扩展 +- 调试: + - 板载调试接口:SWD / JTAG + - 用户交互:板载 LED、复位按钮、用户按键 + - 调试器支持:GD-Link 或其他支持 SWD/JTAG 的调试器 +- 扩展选项: + - TFT-LCD 显示屏接口 + - 摄像头接口(DCI) + - CAN‑FD、Ethernet、USB 外设 + - 多路 SPI/I2C/UART/USART 扩展 + - 音频输入/输出接口 + - 外部存储扩展(SDRAM / Flash / SD 卡) + +**我有疑问:**[**RT-Thread 官方论坛**](https://gitee.com/link?target=https%3A%2F%2Fclub.rt-thread.org) + +# 一、GD32F527上的UART实践(陈北斗) + +## 1. 环境搭建 + +GD32F527的环境搭建可以参考已有大佬的文章 + +https://club.rt-thread.org/ask/article/cdb26510b5df0ff2.html + +## 2. Serial_v2 + +在 RT-Thread V5.2.1 之后,串口 V2 版本进行了重要更新: + +更低的资源占用 +更多的功能支持(超时设置,FLUSH,获取缓冲区数据大小等) +更多的 utest 例程,稳定性更有信心 +因此推荐直接使用 Serial_v2 版本。 + +GD32F527 已完整支持 Serial_v2 的全部功能,并通过了 DMA 模式 18 项 和 INT 模式 19 项 的 utest 测试,稳定性已经得到验证。 + +关于 Serial_v2 的介绍,可以查看 RTT 官方文档(目前已更新部分功能说明,后续还会补充更多使用示例): +[UART_V2版本介绍](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/device/uart/uart_v2/uart) + +[[修改] 为serial_v2版本增加新功能描述 · Pull Request !688 · RT-Thread/docs-online - Gitee.com](https://gitee.com/rtthread/docs-online/pulls/688/files) + +另外,还可以参考以下两个 PR 作为补充: + +https://github.com/RT-Thread/rt-thread/pull/10263 + +https://github.com/RT-Thread/rt-thread/pull/10603 + +## 3. 在Kconfig中添加UART配置 + +``` + config BSP_USING_UART3 + bool "Enable UART3" + default n + config BSP_UART3_RX_USING_DMA + bool "Enable UART3 RX DMA" + depends on BSP_USING_UART3 && RT_USING_SERIAL_V2 && RT_SERIAL_USING_DMA + default n + config BSP_UART3_TX_USING_DMA + bool "Enable UART3 TX DMA" + depends on BSP_USING_UART3 && RT_USING_SERIAL_V2 && RT_SERIAL_USING_DMA + default n + config BSP_UART3_DMA_PING_BUFSIZE + int "Set UART3 RX DMA ping-pong buffer size" + range 16 65535 + depends on BSP_USING_UART3 && RT_USING_SERIAL_V2 && BSP_UART3_RX_USING_DMA + default 64 + config BSP_UART3_RX_BUFSIZE + int "Set UART3 RX buffer size" + range 64 65535 + depends on BSP_USING_UART3 && RT_USING_SERIAL_V2 + default 128 + config BSP_UART3_TX_BUFSIZE + int "Set UART3 TX buffer size" + range 0 65535 + depends on BSP_USING_UART3 && RT_USING_SERIAL_V2 + default 128 +``` + +## 4. 对应 menuconfig 中配置如下所示 + +``` +Enable UART3 ---> + [*] Enable UART3 RX DMA (是否使能 RX DMA) + [*] Enable UART3 TX DMA (是否使能 TX DMA) + (128)Set UART3 RX DMA ping-pong buffer size (RX DMA的乒乓缓冲区) + (128)Set UART3 RX buffer size (rx 缓冲区大小) + (100)Set UART3 TX buffer size (tx 缓冲区大小。TX DMA下无效但必须大于0,请参考上面介绍) +``` + +## 5. 原文链接 + +原文链接:[RT-Thread-【GD32F527_EVAL】Serial_V2测试RT-Thread问答社区 - RT-Thread](https://club.rt-thread.org/ask/article/89e4d25dad02f3fa.html) + +# 二、GD32F527上的GPIO实践(徐达勇) +## 1. GPIO 输出控制LED + +### 1.1 硬件信息 +GD32F5系列芯片官网可以下载芯片的数据手册、固件包、示例代码、开发工具等软件包。 + +https://www.gigadevice.com.cn/product/mcu/high-performance-mcus/gd32f5xx-series/gd32f527 + +从开发板使用手册中可知GD32F527I-EVAL的芯片型号为GD32F527IST7,在芯片的[介绍页面](https://www.gigadevice.com.cn/product/mcu/mcus-product-selector/gd32f527ist7)可以了解到芯片内核为Cortex-M33、最高主频为200MHz、内部Flash为7680K Byte,片上SRAM为576k Byte。 + +![screenshot_mcu_paras.png](figures/b23f5215660c1aea9e6bf29c787c8d01.png) + +通过查看评估版的原理图可知,开发板上搭载的NNAND Flash芯片型号为GD9FU1G8F2AMG,有1Gbit的容量。 + +![screenshot_NAND Flash.png](figures/fa78f6125ab27f94edf777a395b9f808.png.webp) + +SDRAN的芯片型号为MT48LC16M16A2P-6AIT,存储容量为256Mbit。 + +![screenshot_SDRAM.png](figures/ac397300e634580e7825ef813758b19f.png.webp) + +强悍的性能加上丰富的外设资源,配合RTThread实时控制系统,能够实现资源的有效利用。 + +### 1.2 RT-Thread代码拉取以及环境配置 +从Gitee上拉取RTThread的源码 + +```shell +git clone https://gitee.com/rtthread/rt-thread +``` + +RTThread环境配置配置工具env可以从Gitee上拉取env-windows。 + +```shell +git clone --recursive --depth 1 https://gitee.com/mirrors_RT-Thread/env-windows.git +``` + +关于env工具的安装使用,可以查看以下文章中的介绍。 + +https://club.rt-thread.org/ask/article/af8952fcf0ca464b.html + +从GD32F5系列芯片的网站下载芯片的插件包。 + +![screenshot_GD32527_addon.png](figures/b66aadbf96f045731cded67b5c9af97e.png.webp) + +解压出来的文件中有用于Keil环境的芯片支持包。 + +![screenshot_keil_DFP.png](figures/b1a05d89aba1dd39cf622920c8c917fb.png) + +### 1.3 RTThread BSP代码编译和Keil工程生成 +在RTThread代码仓库中进入bsp/gd32/arm/gd32527I-eval文件夹中,通过右键菜单进入env工具的命令行界面, + +![screenshot_code_build_env_enter.png](figures/b542e2b28f949b36a3346987be0d8dbd.png.webp) + +首先在其中运行pkgs --upgrade和pkgs --update更新相关CMSIS固件包。 + +![screenshot_code_build_env_update_pkgs.png](figures/6609f6e1d7fa98f8d092ab1295d350a0.png) + +完成CMSIS固件支持包更新后,运行`scons -j128`编译BSP代码。 + +![screenshot_code_build_compile_bsp.png](figures/b8052663a3cc35089277ff393a686ab9.png) + +接下来运行`scons --target=mdk5`生成Keil5工程 + +![screenshot_code_build_keil_target.png](figures/e47f9ea068d9138ffb23ea8d2ef52458.png) + +使用Keil打开生成的project工程,编译工程后,使用Micro-USB线连接开发板下载程序到开发板。 + +![screenshot_code_build_keil_compile_download.png](figures/d7955406ec71fe8d052a3dcd02962d0d.png.webp) + +连接开发板的串口,进入开发板的Shell终端,可以调用内置的指令查看设备和线程信息。 + +![screenshot_rtthread_shell.png](figures/1de209e8a1af79343e74b57c889c9b01.png) + +### 1.4 RT-Thread GPIO驱动 +RT-Thread为兼容多种MCU,使用IO设备框架和管理接口对外设进行统一管理。 + +![screenshot_io-dev.png](figures/5722a196503e198c48012a39f6354c8d.png) + +系统在硬件初始化时,会创建包含外设信息、操作函数等的IO设备,注册到IO设备管理器中。应用程序使用外设时,通过调用IO设备管理框架的接口函数获取相应外设的控制,进行数据的读写和外设设置, + +![screenshot_io-call.png](figures/4325ead0a144794832cc2b65745a6d92.png) + +GPIO是MCU的基础外设,其基本功能可以分为三类; + +1. 通过读取引脚的电平检测引脚外部输入情况; +2. 设置引脚输出电平,控制外部设备的状态; +3. 检测外部中断,GPIO电平发生变化时,触发相应的中断。 + +RT-Thread以Pin设备抽象GPIO的基本功能,通过Pin设备对GPIO外设的初始化、电平读取和控制以及中断进行管理。在官方的文档中对Pin设备驱动的组成和使用有详细的说明。 + +https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/device/pin/pin + +RTThread使用IO设备框架驱动外设前,需要在工程配置中检测是否使能相关的配置,在env命令行中使用`menuconfig`指令进入代码配置界面,在Hardware Drivers Config->On-chip Peripheral Drivers中确认使能GPIO外设。 + +![screenshot_menucofing_GPIO_enable.png](figures/cf6bb85712c3d748518b7bf587ecc530.png) + +#### 1.4.1 Pin设备接口和硬件原理图 +应用程序通过RT-Thread的Pin设备管理接口来访问GPIO,相关的接口以及功能描述如下: + +| **函数** | **描述** | +| ------------------- | -------------------- | +| rt_pin_mode() | 设置引脚模式 | +| rt_pin_write() | 设置引脚电平 | +| rt_pin_read() | 读取引脚电平 | +| rt_pin_attach_irq() | 绑定引脚中断回调函数 | +| rt_pin_irq_enable() | 使能引脚中断 | +| rt_pin_detach_irq() | 脱离引脚中断回调函数 | + +在使用GPIO设备前,需要知道GPIO引脚的位置,通过查看GD32F527I-EVAL的原理图可知。开发板上的GPIO外设有LED。LED的原理图如下 + +![screenshot_led_pins.png](figures/f0bdddae7046087f554ba7b1be942f41.png) + +#### 1.4.2 Pin设备控制GPIO输出 +使用GPIO的输出功能可以设置GPIO的电平,控制LED外设的状态。在工程中添加以下代码,实现呼吸灯的效果。 + +```c +int main(void) +{ + int count = 1; + /* set LED1 pin mode to output */ + rt_pin_mode(LED1_PIN, PIN_MODE_OUTPUT); + rt_pin_mode(LED2_PIN, PIN_MODE_OUTPUT); + rt_pin_mode(LED3_PIN, PIN_MODE_OUTPUT); + rt_pin_mode(LED4_PIN, PIN_MODE_OUTPUT); + while (count++) + { + if(count%1==0) + rt_pin_write(LED1_PIN, PIN_HIGH); + if(count%2==0) + rt_pin_write(LED2_PIN, PIN_HIGH); + if(count%3==0) + rt_pin_write(LED3_PIN, PIN_HIGH); + if(count%5==0) + rt_pin_write(LED4_PIN, PIN_HIGH); + rt_thread_mdelay(500); + if(count%1==0) + rt_pin_write(LED1_PIN, PIN_LOW); + if(count%2==0) + rt_pin_write(LED2_PIN, PIN_LOW); + if(count%3==0) + rt_pin_write(LED3_PIN, PIN_LOW); + if(count%5==0) + rt_pin_write(LED4_PIN, PIN_LOW); + rt_thread_mdelay(500); + } + return RT_EOK; +} +``` + +开发板LED的运行状态如下 + +![screenshot_01_GPIO_LED.gif](figures/42f51492adb52063b4c697974d802e17.gif) + +### 1.5 原文链接 + +原文链接:[RT-Thread-【GD32F527I-EVAL运行RTThread】GPIO外设使用RT-Thread问答社区 - RT-Thread](https://club.rt-thread.org/ask/article/a3ca21216b6131b7.html) + +## 2. GPIO按键输入 + +### 2.1 Agile Button组件 + +Agile Button是RTThread的组件,在工程中使用该组件,需要在工程配置中将其激活。在env命令行工具中运行`menuconfig`指令,在RT-Thread online package->peripheral libraries and drivers路径下使用agile button组件,保存工程配置。 + +![screenshot_enable_agile_button_component.png](figures/c0a3b13a3fde923dfc9eb988970f307d.png) + +运行`pkgs --update`指令,下载Agile button软件包到本地,更新到BSP中。 + +![screenshot_update_packages.png](figures/077a9813a04cc75668edfe96cc1da549.png) + +### 2.2 Agile Button接口 + +Agile Button使用`agile_btn_t`结构体对按键相关的数据进行管理。围绕`agile_btn_t`结构体的接口函数用于实现按键的创建以及处理。 + +```c +#ifdef RT_USING_HEAP +agile_btn_t *agile_btn_create(uint32_t pin, uint32_t active_logic, uint32_t pin_mode); +int agile_btn_delete(agile_btn_t *btn); +#endif +int agile_btn_init(agile_btn_t *btn, uint32_t pin, uint32_t active_logic, uint32_t pin_mode); +int agile_btn_start(agile_btn_t *btn); +int agile_btn_stop(agile_btn_t *btn); +int agile_btn_set_elimination_time(agile_btn_t *btn, uint8_t elimination_time); +int agile_btn_set_hold_cycle_time(agile_btn_t *btn, uint32_t hold_cycle_time); +int agile_btn_set_event_cb(agile_btn_t *btn, enum agile_btn_event event, void (*event_cb)(agile_btn_t *btn)); +void agile_btn_process(void); +void agile_btn_env_init(void); +``` + +Agile Button 提供了 4 种事件: + +```c +BTN_PRESS_DOWN_EVENT +BTN_HOLD_EVENT +BTN_PRESS_UP_EVENT +BTN_CLICK_EVENT +``` + +可以通过 `agile_btn_set_event_cb` API 设置每个事件的触发回调。 + +### 2.3 Agile Button使用 + +在默认配置中,RTThread会自动创建一个线程,用于周期调用Agile Button的`agile_btn_process`函数,对创建的按键进行数据处理和回调函数调用。用户只需要创建按键,指定事件回调函数即可。 + +![screenshot_agile_button_config.png](figures/2635049030ee9a1df3d7c4a6de49addf.png) + +GD32F527I-EVAL有三个按键供用户使用。 + +![screenshot_key_pins.png](figures/1e41667b05534cd5257d10a2fb3d84b1.png) + +| 按键 | 引脚 | 有效电平 | +| ------ | ---- | -------- | +| Wakeup | PA0 | 高电平 | +| Tamper | PC13 | 低电平 | +| USER | PB14 | 低电平 | + +使用Agile Button的代码流程如下: + +1. 定义agile_btn_t类型的变量btn1和btn1 +2. 使用接口函数agile_btn_init对其进行初始化, +3. 调用agile_btn_set_event_cb指定按键事件对应的回调函数 +4. 调用agile_btn_start使能按键 + +```c +#include +#include +#define LED1_PIN GET_PIN(E, 3) +#define KEY1_PIN GET_PIN(C, 13) //Tamper引脚编号 +#define KEY2_PIN GET_PIN(A, 0) //Wakeup引脚编号 +static void btn1_click_event_cb(agile_btn_t *btn) +{ + rt_kprintf("[button click event] pin:%d repeat:%d, hold_time:%d\r\n", btn->pin, btn->repeat_cnt, btn->hold_time); + rt_pin_write(LED1_PIN,PIN_HIGH); +} +static void btn2_click_event_cb(agile_btn_t *btn) +{ + rt_kprintf("[button click event] pin:%d repeat:%d, hold_time:%d\r\n", btn->pin, btn->repeat_cnt, btn->hold_time); + rt_pin_write(LED1_PIN,PIN_LOW); +} +static agile_btn_t btn1; +static agile_btn_t btn2; +int main(void) +{ + int count = 1; + /* set LED1 pin mode to output */ + rt_pin_mode(LED1_PIN, PIN_MODE_OUTPUT); + agile_btn_stop(&btn1); + agile_btn_stop(&btn2); + agile_btn_init(&btn1, KEY1_PIN, PIN_LOW, PIN_MODE_INPUT_PULLUP); + agile_btn_init(&btn2, KEY2_PIN, PIN_HIGH, PIN_MODE_INPUT_PULLDOWN); + agile_btn_set_event_cb(&btn1, BTN_CLICK_EVENT, btn1_click_event_cb); + agile_btn_set_event_cb(&btn2, BTN_CLICK_EVENT, btn2_click_event_cb); + agile_btn_start(&btn1); + agile_btn_start(&btn2); + return RT_EOK; +} +``` + +编译时会遇到ALGN兼容性的问题,参考Agile Button仓库的解决办法,修改为rt_algin即可编译 + +![screenshot_RTThread_Compact_error.png](figures/e4ee21c9b2ee4bcc67e2e1e6504cc17f.png.webp) + +下载后,点击开发板上的按键,可以在串口通讯窗口,看到如下输出 + +![screenshot_console_output.png](figures/16b610a5a4bb58e6441bccabb7638646.png) + +### 2.4 原文链接 + +原文链接:[RT-Thread-【GD32F527I-EVAL运行RTThread】使用Agile Button 处理按键输入RT-Thread问答社区 - RT-Thread](https://club.rt-thread.org/ask/article/d365679f333ccc45.html) + +# 三、GD32F527上的RTC实践(李金磊) + +## 1. 项目介绍 + +* 环境搭建:拉取 rt-thread 官方源码、下载并安装 rt-thread-env-tool 等; +* 工程配置:使用 ENV 图形化功能配置工具,使能 RTC; +* 工程编译:打包并编译工程,生成对应的 Keil 程序,完成工程编译; +* 固件上传:关键驱动代码调试及固件上传; +* 效果演示:串口登录 RT-Thread 终端并打印系统时间。 + +## 2. 项目方案 +包括 menuconfig 工程配置、工程编译、RTC 驱动配置、固件上传等流程。 + +##3. 环境搭建 +* 拉取 [rt-thread](https://gitee.com/rtthread/rt-thread) 官方源码; +* 下载并安装 [rt-thread-env-tool](https://www.rt-thread.org/download.html#download-rt-thread-env-tool); + +详见: [【GD32F5 开发板】介绍、环境搭建、工程测试](https://club.rt-thread.org/ask/article/de42557193433427.html) . + +## 4. 工程配置 + +* 进入目标开发板 BSP 路径`.\rt-thread\bsp\gd32\arm\gd32527I-eval `; +* 在空白处右键,选择 `ConEmu Here`打开 Env 工具; + +![ConEmu.png](figures/e17111f1a0f722c85bd25cd09492f6e4.png) + +* 执行 `menuconfig` 指令,进入图形化配置界面; + +![menuconfig.jpg](figures/fb12d2a9f3609084410daabdd4cd7805.jpg.webp) + +* 依次进入 `Hardware Drivers Config` → `On-chip Peripheral Drivers` → `Enable RTC` ; + +![enable-RTC.jpg](figures/92b4edc050a961400cfa478360562341.jpg.webp) + +* 按 `Q` 键保存并退出图形化配置界面; + +## 5. 工程编译 + +* 运行指令 `pkgs --update` 使软件包配置生效; + +* 运行 `scons --target=mdk5` 指令,重新编译固件; + +![rtc_pkg_scons.jpg](figures/c8916c6adf783c97deb911161d140d4b.jpg.webp) + +## 6. 固件上传 + +* 双击 `project.uvprojx` 文件,使用 Keil 打开工程,可获取 RTC 驱动文件; + +![drv_rtc.jpg](figures/6cc6046c594477a756487f48d69b877b.jpg.webp) + +## 7. 驱动代码 + +代码结构 + +![flowchart_rtc_drive.png](figures/ebc9b83bca96af1046a638585c928420.png.webp) + + + +* 修改 `drv_rtc.c` 代码如下 + +```c +/* + * Copyright (c) 2006-2025, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-01-25 iysheng first version + * 2025-09-25 kurisaw adapt to rt_rtc_ops interface + * 2025-09-25 kurisaw add alarm interrupt support + */ +#include +#include +#include +#include +#define DBG_TAG "drv.rtc" +#define DBG_LVL DBG_INFO +#include +#ifdef RT_USING_RTC +#if defined(RT_USING_ALARM) +#if defined(BSP_USING_ALARM0) && defined(BSP_USING_ALARM1) +#error "Only supports using one alarm at a time." +#elif !defined(BSP_USING_ALARM0) && !defined(BSP_USING_ALARM1) +#error "Please Enable RTC alarm define (BSP_USING_ALARM0 | BSP_USING_ALARM1)" +#elif defined(BSP_USING_ALARM0) + #define BSP_ALARM_FLAG RTC_FLAG_ALRM0 + #define BSP_RTC_ALARM RTC_ALARM0 + #define BSP_RTC_INT_ALARM RTC_INT_ALARM0 +#elif defined(BSP_USING_ALARM1) + #define BSP_ALARM_FLAG RTC_FLAG_ALRM1 + #define BSP_RTC_ALARM RTC_ALARM1 + #define BSP_RTC_INT_ALARM RTC_INT_ALRM1 +#endif +#endif +#if defined(SOC_SERIES_GD32H7xx) || defined(SOC_SERIES_GD32F5xx) +#define rtc_year year +#define rtc_month month +#define rtc_date date +#define rtc_day_of_week day_of_week +#define rtc_hour hour +#define rtc_minute minute +#define rtc_second second +#define rtc_display_format display_format +#endif +static time_t get_rtc_timestamp(void); +static rt_err_t set_rtc_timestamp(time_t time_stamp); +/** + * @brief Helper function: Convert BCD value to binary. + * @param val: BCD value. + * @return Binary value. + */ +static rt_uint8_t bcd_to_bin(rt_uint8_t val) +{ + return (val & 0x0F) + ((val >> 4) & 0x0F) * 10; +} +/** + * @brief Helper function: Convert binary to BCD. + * @param val: Binary value. + * @return BCD value. + */ +static rt_uint8_t bin_to_bcd(rt_uint8_t val) +{ + return ((val / 10) << 4) | (val % 10); +} +#ifdef RT_USING_ALARM +/* RTC device for alarm callback */ +static rt_device_t g_rtc_device = RT_NULL; +/** + * @brief RTC Alarm Interrupt Handler + */ +void RTC_Alarm_IRQHandler(void) +{ + rt_interrupt_enter(); + /* Check if alarm interrupt occurred */ + if (rtc_flag_get(RTC_FLAG_ALRM0) != RESET) + { + /* Clear alarm flag */ + rtc_flag_clear(RTC_FLAG_ALRM0); + exti_flag_clear(EXTI_17); + /* Notify RTC framework about alarm event */ + if (g_rtc_device != RT_NULL) + { + rt_alarm_update(g_rtc_device, 1); + } + LOG_D("RTC Alarm0 triggered"); + } + if (rtc_flag_get(RTC_FLAG_ALRM1) != RESET) + { + /* Clear alarm flag */ + rtc_flag_clear(RTC_FLAG_ALRM1); + exti_flag_clear(EXTI_17); + /* Notify RTC framework about alarm event */ + if (g_rtc_device != RT_NULL) + { + rt_alarm_update(g_rtc_device, 1); + } + LOG_D("RTC Alarm1 triggered"); + } + rt_interrupt_leave(); +} +#endif /* RT_USING_ALARM */ +static rt_err_t gd_rtc_init(void) +{ + /* Enable PMU and backup domain clocks */ + rcu_periph_clock_enable(RCU_PMU); + pmu_backup_write_enable(); + /* Enable BKP and RTC clocks */ +#ifdef SOC_SERIES_GD32F10x + rcu_periph_clock_enable(RCU_BKPI); +#else + rcu_periph_clock_enable(RCU_RTC); +#endif + /* Check if RTC is already initialized by backup domain reset */ + if (RTC_STAT & RTC_STAT_INITF) + { + LOG_D("RTC already initialized"); + return RT_EOK; + } + /* Reset backup domain only if RTC is not running */ + if ((RTC_STAT & RTC_STAT_RSYNF) == 0) + { + rcu_bkp_reset_enable(); + rcu_bkp_reset_disable(); + /* Re-enable clocks after reset */ +#ifdef SOC_SERIES_GD32F10x + rcu_periph_clock_enable(RCU_BKPI); +#else + rcu_periph_clock_enable(RCU_RTC); +#endif + } + /* Use LSE (32.768kHz) as RTC clock source */ +#define PRESCALER_S 0xFF +#define PRESCALER_A 0x7F + rcu_osci_on(RCU_LXTAL); + if (rcu_osci_stab_wait(RCU_LXTAL) != SUCCESS) + { + LOG_E("LSE oscillator failed to stabilize"); + return -RT_ERROR; + } + rcu_rtc_clock_config(RCU_RTCSRC_LXTAL); + LOG_D("RTC clock source: LSE (32.768kHz)"); + /* Wait for RTC registers synchronization */ + if (rtc_register_sync_wait() != SUCCESS) + { + LOG_E("RTC register synchronization failed"); + return -RT_ERROR; + } + /* Set default time if RTC is not initialized */ + if ((RTC_DATE == 0) || (RTC_TIME == 0)) + { + time_t default_time = 1704067200; /* 2024-01-01 00:00:00 */ + if (set_rtc_timestamp(default_time) != RT_EOK) + { + LOG_E("Failed to set default RTC time"); + return -RT_ERROR; + } + LOG_D("RTC set to default time: 2024-01-01 00:00:00"); + } + LOG_D("RTC initialization successful"); + return RT_EOK; +} +static time_t get_rtc_timestamp(void) +{ + struct tm tm_new = {0}; + rtc_parameter_struct rtc_current_time; + /* Wait for register synchronization before reading */ + if (rtc_register_sync_wait() != SUCCESS) + { + LOG_E("RTC sync failed before reading time"); + return 0; + } + rtc_current_time_get(&rtc_current_time); + /* Convert BCD to binary and adjust year/month values */ + tm_new.tm_year = bcd_to_bin(rtc_current_time.rtc_year) + 100; /* RTC year starts from 2000 */ + tm_new.tm_mon = bcd_to_bin(rtc_current_time.rtc_month) - 1; /* tm_mon: 0-11 */ + tm_new.tm_mday = bcd_to_bin(rtc_current_time.rtc_date); + tm_new.tm_hour = bcd_to_bin(rtc_current_time.rtc_hour); + tm_new.tm_min = bcd_to_bin(rtc_current_time.rtc_minute); + tm_new.tm_sec = bcd_to_bin(rtc_current_time.rtc_second); + /* Convert weekday: RTC uses 1-7 (Monday-Sunday), tm uses 0-6 (Sunday-Saturday) */ + uint8_t rtc_wday = bcd_to_bin(rtc_current_time.rtc_day_of_week); + tm_new.tm_wday = (rtc_wday == 7) ? 0 : rtc_wday; /* Sunday conversion */ + /* Calculate day of year */ + tm_new.tm_yday = 0; /* Will be calculated by timegm */ + tm_new.tm_isdst = 0; /* No daylight saving */ + /* Use timegm instead of mktime to avoid timezone issues */ + return timegm(&tm_new); +} +static rt_err_t gd_get_secs(time_t *sec) +{ + if (sec == RT_NULL) + { + return -RT_EINVAL; + } + *sec = get_rtc_timestamp(); + LOG_D("RTC: get timestamp %lu", *sec); + return RT_EOK; +} +static rt_err_t set_rtc_timestamp(time_t time_stamp) +{ + struct tm now; + rtc_parameter_struct rtc_init_struct; + ErrStatus status; + /* Use gmtime_r for thread safety */ + gmtime_r(&time_stamp, &now); + if (now.tm_year < 100) + { + LOG_E("Year must be >= 2000"); + return -RT_ERROR; + } + /* Convert to BCD format */ + rtc_init_struct.rtc_year = bin_to_bcd(now.tm_year - 100); /* RTC year: 0-99 (2000-2099) */ + rtc_init_struct.rtc_month = bin_to_bcd(now.tm_mon + 1); /* RTC month: 1-12 */ + rtc_init_struct.rtc_date = bin_to_bcd(now.tm_mday); + /* Convert weekday: tm_wday 0-6 (Sun-Sat) to RTC 1-7 (Mon-Sun) */ + rtc_init_struct.rtc_day_of_week = bin_to_bcd(now.tm_wday == 0 ? 7 : now.tm_wday); + rtc_init_struct.rtc_hour = bin_to_bcd(now.tm_hour); + rtc_init_struct.rtc_minute = bin_to_bcd(now.tm_min); + rtc_init_struct.rtc_second = bin_to_bcd(now.tm_sec); + rtc_init_struct.rtc_display_format = RTC_24HOUR; + /* Use default prescaler values */ + rtc_init_struct.factor_asyn = PRESCALER_A; + rtc_init_struct.factor_syn = PRESCALER_S; + rtc_init_struct.am_pm = RTC_AM; + status = rtc_init(&rtc_init_struct); + if (status != SUCCESS) + { + LOG_E("RTC time set failed: %d", status); + return -RT_ERROR; + } + /* Wait for synchronization after setting time */ + if (rtc_register_sync_wait() != SUCCESS) + { + LOG_E("RTC sync failed after setting time"); + return -RT_ERROR; + } + LOG_D("RTC time set successfully: %lu", time_stamp); + return RT_EOK; +} +static rt_err_t gd_set_secs(time_t *sec) +{ + if (sec == RT_NULL) + { + return -RT_EINVAL; + } + rt_err_t result = set_rtc_timestamp(*sec); + if (result == RT_EOK) + { + LOG_D("RTC: set rtc_time %lu", *sec); + } + else + { + LOG_E("RTC: set rtc_time failed %lu", *sec); + } + return result; +} +#ifdef RT_USING_ALARM +static rt_err_t gd_get_alarm(struct rt_rtc_wkalarm *alarm) +{ + if (alarm == RT_NULL) + { + return -RT_EINVAL; + } + rtc_alarm_struct rtc_alarm; + /* Get current alarm configuration */ + rtc_alarm_get(BSP_RTC_ALARM, &rtc_alarm); + /* Convert RTC alarm to RT-Thread alarm format */ + alarm->tm_hour = bcd_to_bin(rtc_alarm.alarm_hour); + alarm->tm_min = bcd_to_bin(rtc_alarm.alarm_minute); + alarm->tm_sec = bcd_to_bin(rtc_alarm.alarm_second); + /* Check if alarm is enabled */ + alarm->enable = (RTC_CTL & (BSP_RTC_ALARM == RTC_ALARM0 ? RTC_CTL_ALRM0EN : RTC_CTL_ALRM1EN)) ? 1 : 0; + LOG_D("RTC: get alarm %02d:%02d:%02d, enable: %d", + alarm->tm_hour, alarm->tm_min, alarm->tm_sec, alarm->enable); + return RT_EOK; +} +static rt_err_t gd_set_alarm(struct rt_rtc_wkalarm *alarm) +{ + if (alarm == RT_NULL) + { + return -RT_EINVAL; + } + rtc_alarm_struct rtc_alarm; + rtc_alarm_disable(BSP_RTC_ALARM); + /* Initialize alarm structure */ + rtc_alarm.alarm_mask = RTC_ALARM_ALL_MASK; + rtc_alarm.weekday_or_date = RTC_ALARM_DATE_SELECTED; + rtc_alarm.alarm_day = 1; /* Not used when mask is set to ALL_MASK */ + rtc_alarm.alarm_hour = bin_to_bcd(alarm->tm_hour); + rtc_alarm.alarm_minute = bin_to_bcd(alarm->tm_min); + rtc_alarm.alarm_second = bin_to_bcd(alarm->tm_sec); + rtc_alarm.am_pm = RTC_AM; + /* Configure alarm */ + rtc_alarm_config(BSP_RTC_ALARM, &rtc_alarm); + /* Enable or disable alarm */ + if (alarm->enable) + { + /* Clear any pending alarm flag first */ + rtc_flag_clear(BSP_ALARM_FLAG); + /* Clear EXTI line 17 flag */ + exti_flag_clear(EXTI_17); + /* Enable RTC alarm interrupt */ + rtc_interrupt_enable(BSP_RTC_INT_ALARM); + /* Enable alarm */ + rtc_alarm_enable(BSP_RTC_ALARM); + /* Configure EXTI line 17 for RTC alarm interrupt */ + exti_init(EXTI_17, EXTI_INTERRUPT, EXTI_TRIG_RISING); + /* Enable RTC Alarm global interrupt in NVIC */ + nvic_irq_enable(RTC_Alarm_IRQn, 0, 0); + LOG_D("RTC Alarm enabled with interrupt"); + } + else + { + /* Disable alarm interrupt first */ + rtc_interrupt_disable(BSP_RTC_INT_ALARM); + /* Disable alarm */ + rtc_alarm_disable(BSP_RTC_ALARM); + /* Clear alarm flag */ + rtc_flag_clear(BSP_ALARM_FLAG); + exti_flag_clear(EXTI_17); + LOG_D("RTC Alarm disabled"); + } + LOG_D("RTC: set alarm %02d:%02d:%02d, enable: %d", + alarm->tm_hour, alarm->tm_min, alarm->tm_sec, alarm->enable); + return RT_EOK; +} +#endif /* RT_USING_ALARM */ +static const struct rt_rtc_ops gd_rtc_ops = +{ + .init = gd_rtc_init, + .get_secs = gd_get_secs, + .set_secs = gd_set_secs, +#ifdef RT_USING_ALARM + .set_alarm = gd_set_alarm, + .get_alarm = gd_get_alarm, +#endif +}; +static rt_rtc_dev_t gd_rtc_dev; +static int rt_hw_rtc_init(void) +{ + rt_err_t result; + gd_rtc_dev.ops = &gd_rtc_ops; + result = rt_hw_rtc_register(&gd_rtc_dev, "rtc", RT_DEVICE_FLAG_RDWR, RT_NULL); + if (result != RT_EOK) + { + LOG_E("RTC register failed: %d", result); + return result; + } +#ifdef RT_USING_ALARM + /* Store RTC device for alarm callback */ + g_rtc_device = rt_device_find("rtc"); + if (g_rtc_device == RT_NULL) + { + LOG_W("RTC device not found for alarm callback"); + } +#endif + LOG_D("RTC hardware init success"); + return RT_EOK; +} +INIT_DEVICE_EXPORT(rt_hw_rtc_init); +#endif /* RT_USING_RTC */ +``` + +* 配置 Debug 参数,编译固件; + +![build_out_rtc.jpg](figures/5a233202eda882393fa9a165a59699e3.jpg.webp) + +* 上传至开发板; + +![upload_rtc.jpg](figures/09235d744d7b00e37f423d7a07ec47fb.jpg.webp) + +## 8. 效果演示 + +* 检查 JP21 跳帽位置是否连接 USART ; + +![jp21_uart.jpg](figures/6e888aaadc7c6b2babe7e878e9848ab3.jpg.webp) + +* 连接板载 USART 接口,使用 MobaXterm 配置并打开串口; +* 短按板载 Reset 键,可获取 RT-Thread 输出信息; + +![uart_msh.jpg](figures/aab1c118290252486295cc749e36d75d.jpg) + +* 执行 `date` 指令即可获取当前时间; + +![rtc_shell_date.jpg](figures/fc86add56f36bb301ce91bf39d07fd3a.jpg) + +## 9. 原文链接 + +原文链接:[RT-Thread-【GD32F527-EVAL 评估板】RTC 测试RT-Thread问答社区 - RT-Thread](https://club.rt-thread.org/ask/article/71affca2d42cd87f.html) + +# 四、GD32F527上的ADC实践(马锡尧) + +## 1. 开发环境搭建 + +### 1.1 编译和构建工具的安装 +开发环境使用env+keil5,关于Keil5的安装这里就不再赘述,大家可以自行网上搜寻,建议安装5.28以上的版本即可。 +关于env工具的安装和源码拉取教程请查看 +【RSOC25】Day1 课程笔记:开发环境搭建与GIT使用(https://club.rt-thread.org/ask/article/91d48b98d44087f1.html) + +### 1.2 GD32烧录工具和芯片包 +因为我手上的jlink不太会用这次就用一下GD32官方的GD-Link进行下载程序,这里给大家打包好了大家自行下载即可,具体后面用到在讲解。 +通过网盘分享的文件:GD32 +链接: https://pan.baidu.com/s/1zYeIVOHa7dkEjlTUm98hLw?pwd=jsds 提取码: jsds + +![screenshot_image.png](figures/bb71192e39f25512d654be14348ec75e.png.webp) + +其中keil的软件包找到之后双击安装即可。 + +### 1.3 RTT示例工程烧录测试 + +这里我们进入到RT-thread文件的bsp目录找到我们的开发板gd32527I-eval然后在env工具中打开。 + +![screenshot_image.png](figures/cf88f6a6904630b8ca8687b0198a5508.png.webp) + +然后先更新拉取一下软件包 + +![screenshot_image.png](figures/38c4d590c583b5f5449bde7b01e4173a.png.webp) + +接着打开该目录下的keil工程 + +![screenshot_image.png](figures/88cc0bd9f9266fc673554d15861a91bf.png.webp) + +勾选输出hex文件然后编译 + +![screenshot_image.png](figures/b7b9dd9e26772d98eb51f453ec16adb3.png.webp) + +编译完成后打开我们的GD——link烧录工具左上角Open打开二进制文件 + +![screenshot_image.png](figures/62f094ad31d96c9b55194bcce8bc5766.png.webp) + +给开发板供电并且连接GD-link与电脑(miniUSB) + +![screenshot_cb79440d2b035553d423b32e0ea433e8.png](figures/1e88ddc6f4b7e35fd7716ce2fd9d10e9.png.webp) + +连接开发板 + +![screenshot_image.png](figures/40d02ff936eed913023f7a8fe67886f8.png.webp) + +等待烧录成功如下图 + +![screenshot_image.png](figures/a69cb2b504d255b5132a29d86891eb77.png.webp) + +最后将开发板的miniUSB与GD-link连接断开,切换到UART的那个接口(也就是他前面那个有丝印的自己看一下),ran’ho然后打开串口调试助手连接串口,按一下开发板上的reset键就可呀看到我们最喜欢的RT-thread的控制台了。 + +![screenshot_image.png](figures/d9622ffedb4697c70aa65033b916b766.png.webp) + +## 2. ADC外设的移植和使用 +### 2.1 ENV工程配置 +这里我们先回到env工具,将模板工程打包一份作为我们的基础工程使用 + +![screenshot_image.png](figures/f0aab93b7d3e86f9ae9fbfaa00224bd3.png.webp) + +然后输入 + +``` +menuconfig +``` + +找到芯片外设使能ADC + +![screenshot_image.png](figures/f3a846b06b548774f650b9108ece75dc.png.webp) + +同样的使能ADC0 + +![screenshot_0f4872124ab63bf9d9a447a5cd9970e8.png](figures/ac410ffe6a693e01b2988dbfc1467c0e.png.webp) + +### 2.2 代码修改适配 +这一小节一定要仔细看有很多要修改适配的地方,首先还是一样打开我们打包的keil工程或者直接在env里面编译一次,你会发现很多报错,别着急这是因为RTT官方目前ADC的外设对F5适配还不是很很好 + +![screenshot_869e4906f8b42935f16842f855364406.png](figures/77d178d537a57cc66c5a00f1e54c2694.png.webp) + +我们打开keil工程首先看一眼和adc有关的驱动有没有都被添加进来 + +![screenshot_847205b161d31b93baa265a491136c89.png](figures/2c1b4c8372400bdd551c1ded7067edc6.png.webp) + +然后打开drv_adc.c文件我们开始解决第一种报错就是现在编译出现的一些宏定义找不到的报错。找到一下几个地方。 + +![screenshot_b20a67d1286999b7df35adc37b67e09d.png](figures/1ad91584375345904304bf4930782a56.png.webp) + +![screenshot_45dac1236323656b1a5f449a85ccad61.png](figures/0f75ac19913ce132e791b0c60591a5f1.png.webp) + +![screenshot_72349c0392b9b99fd2cc6b8010bd3ade.png](figures/bf7eb2d86b5b5726f54c28807493a7f0.png.webp) + +修改如下 + +```c + gpio_mode_set(PIN_GDPORT(pin), GPIO_MODE_ANALOG, GPIO_PUPD_NONE, PIN_GDPIN(pin)); +``` + +![screenshot_40b073b07701dd19f96fd349d1c53b18.png](figures/07a77ecdfdcc44763372331c213ca42e.png.webp) + +```c +adc_channel_length_config(adc_periph, ADC_ROUTINE_CHANNEL, 1); +adc_external_trigger_source_config(adc_periph, ADC_ROUTINE_CHANNEL, ADC_EXTTRIG_ROUTINE_EXTI_11); +adc_external_trigger_config(adc_periph, ADC_ROUTINE_CHANNEL, ENABLE); +``` + +![screenshot_ce1c99e74b49badb3989a5d687fd90ae.png](figures/a3535954fe4e2d1141b92dd4af137e46.png.webp) + +```c +adc_routine_channel_config(adc_periph, channel,0, ADC_SAMPLETIME_480); +adc_software_trigger_enable(adc_periph, ADC_ROUTINE_CHANNEL); +``` + +![screenshot_ce1c99e74b49badb3989a5d687fd90ae.png](figures/a3535954fe4e2d1141b92dd4af137e46.png-1764739476112112.webp) + +然后再次编译发现还是报错这里是因为F4和F5的api函数有些不匹配如下图我圈出来的两个函数。 + +![screenshot_fcf239c487475182591661985c81612d.png](figures/4a7555d6b9871420cc72d160c674d0f2.png.webp) + +然后做出如下修改 + +```c +adc_routine_channel_config(adc_periph, channel,0, ADC_SAMPLETIME_480); +``` + +![screenshot_cef30e43d254bc18a53c5010d000ff54.png](figures/f98457f7dbcb83941bfe59060f9819b9.png.webp) + +```c + *value = adc_routine_data_read(ADC0); +``` + +![screenshot_e691956be74655b1031d31134ca2ae4d.png](figures/41c92068672b8d3bd5b0f3c071be06c7.png.webp) + +这时候在编译就发现可以通过了 + +### 2.3 ADC外设的适配和使用 +首先先查看原理图发现我们的ADC接口为ADC通道13 + +![screenshot_668a2970d363e39b7d8e9a764a9b834c.png](figures/3a3613be615157829e64e67458beea37.png.webp) + +在查看一下对应的枚举信息发现滴13个刚好是PC3也能对应不需要修改 + +![screenshot_48b9dcd940aca0c197d064948bc3e2fb.png](figures/2f8f51774894a38ce53ce84320ec2101.png.webp) + +在main.c种添加如下代码 + +![screenshot_15c0357aa5b90b143094844d1f76193b.png](figures/7904ab3ae704c567c7a2b91ecf61fd26.png.webp) + +```c +#define ADC_DEV_NAME "adc0" /* ADC 设备名称 */ +#define ADC_CHANNEL 13 /* ADC 通道 */ +static int adc_sample(int argc, char *argv[]) +{ + rt_adc_device_t adc_dev; + rt_uint32_t value; + rt_err_t ret = RT_EOK; + /* 查找ADC设备 */ + adc_dev = (rt_adc_device_t)rt_device_find(ADC_DEV_NAME); + if (adc_dev == RT_NULL) + { + rt_kprintf("adc sample run failed! can't find %s device.\n", ADC_DEV_NAME); + return RT_ERROR; + } + /* 打开ADC设备 */ + ret = rt_adc_enable(adc_dev, ADC_CHANNEL); + if (ret != RT_EOK) + { + rt_kprintf("adc sample run failed! enable %s channel %d failed.\n", ADC_DEV_NAME, ADC_CHANNEL); + return RT_ERROR; + } + /* 读取ADC值 */ + value = rt_adc_read(adc_dev, ADC_CHANNEL); + rt_kprintf("the value is :%d\n", value); + /* 关闭ADC设备 */ + ret = rt_adc_disable(adc_dev, ADC_CHANNEL); + if (ret != RT_EOK) + { + rt_kprintf("adc sample run failed! disable %s channel %d failed.\n", ADC_DEV_NAME, ADC_CHANNEL); + return RT_ERROR; + } + return ret; +} +/* 导出到 msh 命令列表中 */ +MSH_CMD_EXPORT(adc_sample, adc sample); +``` + +然后编译烧录连接开发板串口可以通过控制台查看设备和运行我们的adc例程运行结果如下: + +![screenshot_acb1df7d07fd5e2d9395163b7fef8985.png](figures/95903f8bf12637fc78dbee912d6b4ed3.png.webp) + +## 3. 原文链接 + +原文链接:[RT-Thread-【GD32F527_EVAL】ADC外设的使用和实践RT-Thread问答社区 - RT-Thread](https://club.rt-thread.org/ask/article/2b4ba9e45dc7c5b1.html) + +# 五、GD32F527上的HWTimer实践(刘协泉) + +## 1. 项目拉取 + +### 1.1 环境准备 + +#### 1.1.1 Keil + +安装方法没啥好说的,网上大把资料,只要保证是5.38以上的版本即可。另外DFP包可以在GD官网上下到,具体链接为:https://club.rt-thread.org/ask/article/gd32mcu.com/download/agree/box_id/13/document_id/558/path_type/1 + +#### 1.1.2 RTT环境搭建 + +主要是配置env,env可以在:https://club.rt-thread.org/ask/article/rt-thread.org/download.html#download-rt-thread-env-tool下到,配置方法可以参考: + +* [Env 用户手册](https://www.rt-thread.org/document/site/#/development-tools/env/env) + +### 1.2 源码拉取 + +在目标文件夹下,使用powershell输入以下命令拉取: + +```shell +git clone https://github.com/RT-Thread/rt-thread.git rt-thread +``` + +### 1.3 package更新 + +进入GD32F527工程目录:bsp/gd32/arm/gd32527I-eval,在此目录下启动conEmu(ENV命令行界面),输入以下命令更新工程: + +#### 1.3.1 更新packages库 +  pkgs —upgrade + +```shell +$ pkgs --upgrade +Error message:[Errno 2] No such file or directory: 'D:\\Works\\04-Project\\rtthread\\env-windows\\tools\\bin\\..\\..\\tools\\scripts\\cmds\\.config' +open .config failed +[Use Gitee server - auto decision based on IP location] +Begin to upgrade env packages. +From https://gitee.com/RT-Thread-Mirror/packages + * branch HEAD -> FETCH_HEAD +==============================> Env packages upgrade done +pkgs --update +``` + +#### 1.3.2 拉取bsp对应的package +  pkgs —update + +```shell +$ pkgs --update +[Use Gitee server - auto decision based on IP location] +D:\Works\04-Project\rtthread\rt-thread\bsp\gd32\arm\gd32527I-eval\packages\gd32-arm-cmsis-latest +==============================> gd32-arm-cmsis update done +remote: Enumerating objects: 8, done. +remote: Counting objects: 100% (8/8), done. +remote: Compressing objects: 100% (5/5), done. +remote: Total 5 (delta 3), reused 0 (delta 0), pack-reused 0 (from 0) +Unpacking objects: 100% (5/5), 1.22 KiB | 41.00 KiB/s, done. +From https://gitee.com/RT-Thread-Mirror/gd32-arm-series + 3cd2fb6..0578c15 master -> origin/master +error: Your local changes to the following files would be overwritten by merge: + GD32F5xx/SConscript +Please commit your changes or stash them before you merge. +Aborting +D:\Works\04-Project\rtthread\rt-thread\bsp\gd32\arm\gd32527I-eval\packages\gd32-arm-series-latest +==============================> gd32-arm-series update done +Operation completed successfully. +``` + +## 2. 代码修改 + +### 2.1 scons开关配置 + +#### 2.1.1 配置修改 + +##### 2.1.1.1 修改KConfig文件 + +打开文件`bsp\gd32\arm\gd32527I-eval\board\Kconfig`,修改其中BSP_USING_TIM包裹的内容如下: + +```python + menuconfig BSP_USING_TIM + bool "Enable timer" + default n + select RT_USING_HWTIMER + if BSP_USING_TIM + config BSP_USING_TIM0 + bool "Enable TIM0" + default n + config BSP_USING_TIM1 + bool "Enable TIM1" + default n + config BSP_USING_TIM2 + bool "Enable TIM2" + default n + config BSP_USING_TIM3 + bool "Enable TIM3" + default n + config BSP_USING_TIM4 + bool "Enable TIM4" + default n + config BSP_USING_TIM5 + bool "Enable TIM5" + default n + config BSP_USING_TIM6 + bool "Enable TIM6" + default n + config BSP_USING_TIM7 + bool "Enable TIM7" + default n + config BSP_USING_TIM8 + bool "Enable TIM8" + default n + config BSP_USING_TIM9 + bool "Enable TIM9" + default n + config BSP_USING_TIM10 + bool "Enable TIM10" + default n + config BSP_USING_TIM11 + bool "Enable TIM11" + default n + config BSP_USING_TIM12 + bool "Enable TIM12" + default n + config BSP_USING_TIM13 + bool "Enable TIM13" + default n + endif +``` + +##### 2.1.1.2 打开定时器 + +在conEmu上输入` scons -—menuconfig`,打开配置界面,进行如下配置: + +![screenshot_image.png](figures/1511c0cc14708170e143fb44fbcaa0db.png) + +保存并退出。 + +#### 2.1.2 package修改 + +GD的驱动库还没将硬件定时器的硬件模拟层代码加入编译,因此需手动将这部分文件加入编译(后面这个修改应该需要上到package库更新),具体修改方法为: +修改文件:bsp\gd32\arm\gd32527I-eval\packages\gd32-arm-series-latest\GD32F5xx\SConscript +在此文件中添加如下信息: + +``` +if GetDepend(['RT_USING_HWTIMER']): + src += ['GD32F5xx_standard_peripheral/Source/gd32f5xx_timer.c'] +``` + +#### 2.1.3 工程生成 + +在conEmu中运行以下命令生成工程: + +```shell +scons --target=mdk5 +``` + +### 2.2 驱动修改 + + GD32的硬件定时器部分3年前提交后就一直没有修改,里面很多部分都已经和其他平台的架构不统一了,最明显的是宏,已经和GD平台KConfig文件中的硬件定时器定义的宏对应不上了,需要修改后才能使用。 +  GD芯片的定时器计时规则: + +![screenshot_image.png](figures/f461639c7e1299e0ac4aec0f28dbcbc6.png) + +  其中:PSC对应prescaler,ARR对应 reloader,CK_TIMER对应芯片定时器的主时钟,在不倍频的情况下,GD32F5xx的时钟是100M。 +  看框架层的实现思路是,若硬件定时器更新频率高于1000000Hz,则使用1000000Hz,若不是,则使用硬件定时器支持的最低频率,因此驱动层尽量适配这套逻辑。 +  此外,在框架层上看,驱动支持的最低频率为1000Hz,也就是说,在RTT中,1000Hz的定时器任务,RTT更倾向于使用硬件定时器或者软件定时器的方式实现。但是呢,由于GD的prescale位数仅支持16bit,且定时器的时钟最小单元为100MHz(APB总线数据的2倍),因此换算下来,GD定时器支持的最小周期为100000000 / 65526 = 1526.9xxx,即支持的最小频率为1527Hz。 +  按照以上思路,硬件定时器代码编写如下(由于不确定能不能适配GD的其他ARM平台芯片,不敢直接提到主干上去,因此只能放在自己仓库使用,[仓库地址](https://github.com/oxlm/rt-thread/tree/branch_gd32f527i)): + +```c +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-02-25 iysheng first version + */ +#include +#include +#include +#ifdef BSP_USING_TIM +typedef struct { + uint32_t reg_base; + IRQn_Type irqn; + rcu_periph_enum rcu; +} gd32_hwtimer_data; +typedef struct { + char dev_name[RT_NAME_MAX]; + const gd32_hwtimer_data hw_data; + rt_hwtimer_t hwtimer_dev; + const struct rt_hwtimer_info hwtimer_info; +} gd32_hwtimer_device; +enum timer_index_E { +#ifdef BSP_USING_TIM0 + TIM0_INDEX, +#endif +#ifdef BSP_USING_TIM1 + TIM1_INDEX, +#endif +#ifdef BSP_USING_TIM2 + TIM2_INDEX, +#endif +#ifdef BSP_USING_TIM3 + TIM3_INDEX, +#endif +#ifdef BSP_USING_TIM4 + TIM4_INDEX, +#endif +#ifdef BSP_USING_TIM5 + TIM5_INDEX, +#endif +#ifdef BSP_USING_TIM6 + TIM6_INDEX, +#endif +#ifdef BSP_USING_TIM7 + TIM7_INDEX, +#endif +#ifdef BSP_USING_TIM8 + TIM8_INDEX, +#endif +#ifdef BSP_USING_TIM9 + TIM9_INDEX, +#endif +#ifdef BSP_USING_TIM10 + TIM10_INDEX, +#endif +#ifdef BSP_USING_TIM11 + TIM11_INDEX, +#endif +#ifdef BSP_USING_TIM12 + TIM12_INDEX, +#endif +#ifdef BSP_USING_TIM13 + TIM13_INDEX, +#endif +}; +/* + * static void __set_timerx_freq + * Set freq with timerx + * + * @param timerx the pointer of TIMER_TypeDef + * @param freq of the timer clock + * @retval None + */ +static rt_err_t __set_timerx_freq(uint32_t timerx, uint32_t freq) +{ + uint32_t ap1freq, ap2freq; + uint32_t prescaler; + uint32_t temp; + if (timerx == TIMER0 || timerx == TIMER7 || timerx == TIMER8 \ + || timerx == TIMER9 || timerx == TIMER10) + { + ap2freq = rcu_clock_freq_get(CK_APB2); + temp = RCU_CFG0 & RCU_CFG0_APB2PSC; + temp >>= 11; + /* whether should frequency doubling */ + temp = (temp < 4) ? 0 : 1; + prescaler = (ap2freq << temp) / freq; + } + else + { + ap1freq = rcu_clock_freq_get(CK_APB1); + temp = RCU_CFG0 & RCU_CFG0_APB1PSC; + temp >>= 8; + /* whether should frequency doubling */ + temp = (temp < 4) ? 0 : 1; + prescaler = (ap1freq << temp) / freq; + } + //rt_kprintf("prescaler %d\n", prescaler); + if(prescaler > 65536) + return -RT_EINVAL; + timer_interrupt_disable(timerx, TIMER_INT_UP); + timer_prescaler_config(timerx, (uint16_t)prescaler - 1, TIMER_PSC_RELOAD_NOW); + timer_interrupt_flag_clear(timerx, TIMER_INT_FLAG_UP); + timer_interrupt_enable(timerx, TIMER_INT_UP); + return RT_EOK; +} +static rt_err_t gd32_hwtimer_start(struct rt_hwtimer_device *timer, \ + rt_uint32_t cnt, rt_hwtimer_mode_t mode) +{ + uint32_t timer_base = (uint32_t)timer->parent.user_data; + //rt_kprintf("cnt %d\n", cnt); + if(((timer_base == TIMER1) || (timer_base == TIMER4)) && (cnt > 42979672)) + { + return -RT_EINVAL; + } + if (mode == HWTIMER_MODE_ONESHOT) + { + timer_single_pulse_mode_config(timer_base, TIMER_SP_MODE_SINGLE); + } + else if (mode == HWTIMER_MODE_PERIOD) + { + timer_single_pulse_mode_config(timer_base, TIMER_SP_MODE_REPETITIVE); + } + timer_disable(timer_base); + timer_counter_value_config(timer_base, 0); + if((timer_base == TIMER1) || (timer_base == TIMER4)) { + timer_autoreload_value_config(timer_base, (cnt * 100) - 1); + } else { + timer_autoreload_value_config(timer_base, cnt - 1); + } + timer_auto_reload_shadow_enable(timer_base); + timer_enable(timer_base); + return RT_EOK; +} +static void gd32_hwtimer_init(struct rt_hwtimer_device *timer, rt_uint32_t state) +{ + uint32_t timer_base = (uint32_t)timer->parent.user_data; + timer_parameter_struct initpara; + if (state) + { + timer_deinit(timer_base); + timer_interrupt_disable(timer_base, TIMER_INT_UP); + timer_interrupt_flag_clear(timer_base, TIMER_INT_FLAG_UP); + timer_internal_clock_config(timer_base); + timer_struct_para_init(&initpara); + initpara.period = timer->info->maxcnt; + timer_init(timer_base, &initpara); + gd32_hwtimer_start(timer, initpara.period, timer->mode); + } + else + { + timer_deinit(timer_base); + } +} +static void gd32_hwtimer_stop(struct rt_hwtimer_device *timer) +{ + uint32_t timer_base = (uint32_t)timer->parent.user_data; + timer_disable(timer_base); +} +static rt_uint32_t gd32_hwtimer_count_get(struct rt_hwtimer_device *timer) +{ + uint32_t timer_base = (uint32_t)timer->parent.user_data; + rt_uint32_t count; + count = timer_counter_read(timer_base); + return count; +} +static rt_err_t gd32_hwtimer_control(struct rt_hwtimer_device *timer, rt_uint32_t cmd, \ + void *args) +{ + int ret = RT_EOK; + rt_int32_t freq; + rt_hwtimer_mode_t mode; + switch (cmd) + { + case HWTIMER_CTRL_FREQ_SET: + freq = *(rt_uint32_t *)args; + return __set_timerx_freq((uint32_t)timer->parent.user_data, freq); + break; + default: + rt_kprintf("invalid cmd:%x\n", cmd); + ret = -RT_EINVAL; + break; + } + return ret; +} +static const struct rt_hwtimer_ops g_gd32_hwtimer_ops = { + gd32_hwtimer_init, + gd32_hwtimer_start, + gd32_hwtimer_stop, + gd32_hwtimer_count_get, + gd32_hwtimer_control, +}; +static gd32_hwtimer_device g_gd32_hwtimer[] = { +#ifdef BSP_USING_TIM0 + { + "timer0", + { + TIMER0, + TIMER0_UP_TIMER9_IRQn, + RCU_TIMER0, + }, + {0}, + { + 1000000, + 1527, + 0xFFFF, + 0, /* count up mode */ + } + }, +#endif +#ifdef BSP_USING_TIM1 + { + "timer1", + { + TIMER1, + TIMER1_IRQn, + RCU_TIMER1, + }, + {0}, + { + 1000000, + 1527, + 42979672, // (0xFFFFFFFF + 1) / 100 + 0, /* count up mode */ + } + }, +#endif +#ifdef BSP_USING_TIM2 + { + "timer2", + { + TIMER2, + TIMER2_IRQn, + RCU_TIMER2, + }, + {0}, + { + 1000000, + 1527, + 0xFFFF, + 0, /* count up mode */ + } + }, +#endif +#ifdef BSP_USING_TIM3 + { + "timer3", + { + TIMER3, + TIMER3_IRQn, + RCU_TIMER3, + }, + {0}, + { + 1000000, + 1527, + 0xFFFF, + 0, /* count up mode */ + } + }, +#endif +#ifdef BSP_USING_TIM4 + { + "timer4", + { + TIMER4, + TIMER4_IRQn, + RCU_TIMER4, + }, + {0}, + { + 1000000, + 1527, + 0xFFFF, + 0, /* count up mode */ + } + }, +#endif +#ifdef BSP_USING_TIM5 + { + "timer5", + { + TIMER5, + TIMER5_DAC_IRQn, + RCU_TIMER5, + }, + {0}, + { + 1000000, + 1527, + 0xFFFF, + 0, /* count up mode */ + } + }, +#endif +#ifdef BSP_USING_TIM6 + { + "timer6", + { + TIMER6, + TIMER6_IRQn, + RCU_TIMER6, + }, + {0}, + { + 1000000, + 1527, + 0xFFFF, + 0, /* count up mode */ + } + }, +#endif +#ifdef BSP_USING_TIM7 + { + "timer7", + { + TIMER7, + TIMER7_UP_TIMER12_IRQn, + RCU_TIMER7, + }, + {0}, + { + 1000000, + 1527, + 0xFFFF, + 0, /* count up mode */ + } + }, +#endif +#ifdef BSP_USING_TIM8 + { + "timer8", + { + TIMER8, + TIMER0_BRK_TIMER8_IRQn, + RCU_TIMER8, + }, + {0}, + { + 1000000, + 1527, + 0xFFFF, + 0, /* count up mode */ + } + }, +#endif +#ifdef BSP_USING_TIM9 + { + "timer9", + { + TIMER9, + TIMER0_UP_TIMER9_IRQn, + RCU_TIMER9, + }, + {0}, + { + 1000000, + 1527, + 0xFFFF, + 0, /* count up mode */ + } + }, +#endif +#ifdef BSP_USING_TIM10 + { + "timer10", + { + TIMER10, + TIMER0_TRG_CMT_TIMER10_IRQn, + RCU_TIMER10, + }, + {0}, + { + 1000000, + 1527, + 0xFFFF, + 0, /* count up mode */ + } + }, +#endif +#ifdef BSP_USING_TIM11 + { + "timer11", + { + TIMER11, + TIMER7_BRK_TIMER11_IRQn, + RCU_TIMER11, + }, + {0}, + { + 1000000, + 1527, + 0xFFFF, + 0, /* count up mode */ + } + }, +#endif +#ifdef BSP_USING_TIM12 + { + "timer12", + { + TIMER12, + TIMER7_UP_TIMER12_IRQn, + RCU_TIMER12, + }, + {0}, + { + 1000000, + 1527, + 0xFFFF, + 0, /* count up mode */ + } + }, +#endif +#ifdef BSP_USING_TIM13 + { + "timer13", + { + TIMER13, + TIMER7_TRG_CMT_TIMER13_IRQn, + RCU_TIMER13, + }, + {0}, + { + 1000000, + 1527, + 0xFFFF, + 0, /* count up mode */ + } + }, +#endif +}; +#ifdef BSP_USING_TIM1 +void TIMER1_IRQHandler(void) +{ + rt_interrupt_enter(); + if (timer_interrupt_flag_get( + (uint32_t)g_gd32_hwtimer[TIM1_INDEX].hw_data.reg_base, + TIMER_INT_FLAG_UP) == SET) { + timer_flag_clear( + (uint32_t)g_gd32_hwtimer[TIM1_INDEX].hw_data.reg_base, + TIMER_INT_UP); + rt_device_hwtimer_isr(&g_gd32_hwtimer[TIM1_INDEX].hwtimer_dev); + } + rt_interrupt_leave(); +} +#endif +#ifdef BSP_USING_TIM2 +void TIMER2_IRQHandler(void) +{ + rt_interrupt_enter(); + if (timer_interrupt_flag_get( + (uint32_t)g_gd32_hwtimer[TIM2_INDEX].hw_data.reg_base, + TIMER_INT_FLAG_UP) == SET) { + timer_flag_clear( + (uint32_t)g_gd32_hwtimer[TIM2_INDEX].hw_data.reg_base, + TIMER_INT_UP); + rt_device_hwtimer_isr(&g_gd32_hwtimer[TIM2_INDEX].hwtimer_dev); + } + rt_interrupt_leave(); +} +#endif +#ifdef BSP_USING_TIM3 +void TIMER3_IRQHandler(void) +{ + rt_interrupt_enter(); + if (timer_interrupt_flag_get( + (uint32_t)g_gd32_hwtimer[TIM3_INDEX].hw_data.reg_base, + TIMER_INT_FLAG_UP) == SET) { + timer_flag_clear( + (uint32_t)g_gd32_hwtimer[TIM3_INDEX].hw_data.reg_base, + TIMER_INT_UP); + rt_device_hwtimer_isr(&g_gd32_hwtimer[TIM3_INDEX].hwtimer_dev); + } + rt_interrupt_leave(); +} +#endif +#ifdef BSP_USING_TIM4 +void TIMER4_IRQHandler(void) +{ + rt_interrupt_enter(); + if (timer_interrupt_flag_get( + (uint32_t)g_gd32_hwtimer[TIM4_INDEX].hw_data.reg_base, + TIMER_INT_FLAG_UP) == SET) { + timer_flag_clear( + (uint32_t)g_gd32_hwtimer[TIM4_INDEX].hw_data.reg_base, + TIMER_INT_UP); + rt_device_hwtimer_isr(&g_gd32_hwtimer[TIM4_INDEX].hwtimer_dev); + } + rt_interrupt_leave(); +} +#endif +#ifdef BSP_USING_TIM5 +void TIMER5_DAC_IRQHandler(void) +{ + rt_interrupt_enter(); + if (timer_interrupt_flag_get( + (uint32_t)g_gd32_hwtimer[TIM5_INDEX].hw_data.reg_base, + TIMER_INT_FLAG_UP) == SET) { + timer_flag_clear( + (uint32_t)g_gd32_hwtimer[TIM5_INDEX].hw_data.reg_base, + TIMER_INT_UP); + rt_device_hwtimer_isr(&g_gd32_hwtimer[TIM5_INDEX].hwtimer_dev); + } + rt_interrupt_leave(); +} +#endif +#ifdef BSP_USING_TIM6 +void TIMER6_IRQHandler(void) +{ + rt_interrupt_enter(); + if (timer_interrupt_flag_get( + (uint32_t)g_gd32_hwtimer[TIM6_INDEX].hw_data.reg_base, + TIMER_INT_FLAG_UP) == SET) { + timer_flag_clear( + (uint32_t)g_gd32_hwtimer[TIM6_INDEX].hw_data.reg_base, + TIMER_INT_UP); + rt_device_hwtimer_isr(&g_gd32_hwtimer[TIM6_INDEX].hwtimer_dev); + } + rt_interrupt_leave(); +} +#endif +#ifdef BSP_USING_TIM8 +void TIMER0_BRK_TIMER8_IRQHandler(void) +{ + rt_interrupt_enter(); + if (timer_interrupt_flag_get( + (uint32_t)g_gd32_hwtimer[TIM8_INDEX].hw_data.reg_base, + TIMER_INT_FLAG_UP) == SET) { + timer_flag_clear( + (uint32_t)g_gd32_hwtimer[TIM8_INDEX].hw_data.reg_base, + TIMER_INT_UP); + rt_device_hwtimer_isr(&g_gd32_hwtimer[TIM8_INDEX].hwtimer_dev); + } + rt_interrupt_leave(); +} +#endif +#if defined(BSP_USING_TIM0) || defined(BSP_USING_TIM9) +void TIMER0_UP_TIMER9_IRQHandler(void) +{ + rt_interrupt_enter(); +#ifdef BSP_USING_TIM0 + if (timer_interrupt_flag_get( + (uint32_t)g_gd32_hwtimer[TIM0_INDEX].hw_data.reg_base, + TIMER_INT_FLAG_UP) == SET) { + timer_flag_clear( + (uint32_t)g_gd32_hwtimer[TIM0_INDEX].hw_data.reg_base, + TIMER_INT_UP); + rt_device_hwtimer_isr(&g_gd32_hwtimer[TIM0_INDEX].hwtimer_dev); + } +#endif +#ifdef BSP_USING_TIM9 + if (timer_interrupt_flag_get( + (uint32_t)g_gd32_hwtimer[TIM9_INDEX].hw_data.reg_base, + TIMER_INT_FLAG_UP) == SET) { + timer_flag_clear( + (uint32_t)g_gd32_hwtimer[TIM9_INDEX].hw_data.reg_base, + TIMER_INT_UP); + rt_device_hwtimer_isr(&g_gd32_hwtimer[TIM9_INDEX].hwtimer_dev); + } +#endif + rt_interrupt_leave(); +} +#endif +#ifdef BSP_USING_TIM10 +void TIMER0_TRG_CMT_TIMER10_IRQHandler(void) +{ + rt_interrupt_enter(); + if (timer_interrupt_flag_get( + (uint32_t)g_gd32_hwtimer[TIM10_INDEX].hw_data.reg_base, + TIMER_INT_FLAG_UP) == SET) { + timer_flag_clear( + (uint32_t)g_gd32_hwtimer[TIM10_INDEX].hw_data.reg_base, + TIMER_INT_UP); + rt_device_hwtimer_isr(&g_gd32_hwtimer[TIM10_INDEX].hwtimer_dev); + } + rt_interrupt_leave(); +} +#endif +#ifdef BSP_USING_TIM11 +void TIMER7_BRK_TIMER11_IRQHandler(void) +{ + rt_interrupt_enter(); + if (timer_interrupt_flag_get( + (uint32_t)g_gd32_hwtimer[TIM11_INDEX].hw_data.reg_base, + TIMER_INT_FLAG_UP) == SET) { + timer_flag_clear( + (uint32_t)g_gd32_hwtimer[TIM11_INDEX].hw_data.reg_base, + TIMER_INT_UP); + rt_device_hwtimer_isr(&g_gd32_hwtimer[TIM11_INDEX].hwtimer_dev); + } + rt_interrupt_leave(); +} +#endif +#if defined(BSP_USING_TIM7) || defined(BSP_USING_TIM12) +void TIMER7_UP_TIMER12_IRQHandler(void) +{ + rt_interrupt_enter(); +#ifdef BSP_USING_TIM7 + if (timer_interrupt_flag_get( + (uint32_t)g_gd32_hwtimer[TIM7_INDEX].hw_data.reg_base, + TIMER_INT_FLAG_UP) == SET) { + timer_flag_clear( + (uint32_t)g_gd32_hwtimer[TIM7_INDEX].hw_data.reg_base, + TIMER_INT_UP); + rt_device_hwtimer_isr(&g_gd32_hwtimer[TIM7_INDEX].hwtimer_dev); + } +#endif +#ifdef BSP_USING_TIM12 + if (timer_interrupt_flag_get( + (uint32_t)g_gd32_hwtimer[TIM12_INDEX].hw_data.reg_base, + TIMER_INT_FLAG_UP) == SET) { + timer_flag_clear( + (uint32_t)g_gd32_hwtimer[TIM12_INDEX].hw_data.reg_base, + TIMER_INT_UP); + rt_device_hwtimer_isr(&g_gd32_hwtimer[TIM12_INDEX].hwtimer_dev); + } +#endif + rt_interrupt_leave(); +} +#endif +#ifdef BSP_USING_TIM13 +void TIMER7_TRG_CMT_TIMER13_IRQHandler(void) +{ + rt_interrupt_enter(); + if (timer_interrupt_flag_get( + (uint32_t)g_gd32_hwtimer[TIM13_INDEX].hw_data.reg_base, + TIMER_INT_FLAG_UP) == SET) { + timer_flag_clear( + (uint32_t)g_gd32_hwtimer[TIM13_INDEX].hw_data.reg_base, + TIMER_INT_UP); + rt_device_hwtimer_isr(&g_gd32_hwtimer[TIM13_INDEX].hwtimer_dev); + } + rt_interrupt_leave(); +} +#endif +static int rt_hwtimer_init(void) +{ + int ret = 0, i = 0; + //rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL2); + for (; i < sizeof(g_gd32_hwtimer) / sizeof(g_gd32_hwtimer[0]); i++) + { + g_gd32_hwtimer[i].hwtimer_dev.ops = &g_gd32_hwtimer_ops; + g_gd32_hwtimer[i].hwtimer_dev.info = &g_gd32_hwtimer[i].hwtimer_info; + rcu_periph_clock_enable(g_gd32_hwtimer[i].hw_data.rcu); + nvic_irq_enable(g_gd32_hwtimer[i].hw_data.irqn, 1, 0); + ret = rt_device_hwtimer_register(&g_gd32_hwtimer[i].hwtimer_dev, \ + g_gd32_hwtimer[i].dev_name, (void *)g_gd32_hwtimer[i].hw_data.reg_base); + if (RT_EOK != ret) + { + rt_kprintf("failed register %s, err=%d\n", g_gd32_hwtimer[i].dev_name, \ + ret); + break; + } + } + return ret; +} +INIT_BOARD_EXPORT(rt_hwtimer_init); +#endif +``` + +### 2.3 上层代码编写 + +新增文件,还需要再运行一遍`scons —target=mdk5`才能将此文件添加至工程中。 + +```c +#include +#include +#include +#include +#define TIMER_NAME "timer" +int hw_timer_test(int argc, char **argv) +{ + rt_device_t d_timer; + rt_hwtimer_mode_t new_mode = HWTIMER_MODE_PERIOD; + rt_int32_t new_freq = 1000; + rt_hwtimerval_t timeout_s; + if (argc != 2) { + rt_kprintf("Usage: hw_timer_test timerx\n"); + return -1; + } else if (rt_strncmp(argv[1], TIMER_NAME, rt_strlen(TIMER_NAME)) != 0) { + rt_kprintf("Error: timer name should be %s[0 ~ 13]\n", TIMER_NAME); + return 0; + } + d_timer = rt_device_find(argv[1]); + if (d_timer == RT_NULL) { + rt_kprintf("find %s failed!\n", TIMER_NAME); + return -1; + } + if (rt_device_open(d_timer, RT_DEVICE_OFLAG_RDWR) != RT_EOK) { + rt_kprintf("open %s failed!\n", TIMER_NAME); + return -1; + } + rt_device_control(d_timer, HWTIMER_CTRL_MODE_SET, &new_mode); + for (new_freq = 1000; new_freq <= 1000000; new_freq *= 10) { + if (rt_device_control(d_timer, HWTIMER_CTRL_FREQ_SET, &new_freq) == RT_EOK) { + rt_kprintf("set freq %d Hz success\n", new_freq); + timeout_s.sec = 5; /* 秒 */ + timeout_s.usec = 0; /* 微秒 */ + rt_device_write(d_timer, 0, &timeout_s, sizeof(timeout_s)); + rt_thread_mdelay(2000); + /* 读取定时器当前值 */ + rt_device_read(d_timer, 0, &timeout_s, sizeof(timeout_s)); + rt_kprintf("Read: Sec = %d, Usec = %d\n", timeout_s.sec, timeout_s.usec); + } + } + rt_device_close(d_timer); + return 0; +} +MSH_CMD_EXPORT_ALIAS(hw_timer_test, hw_timer_test, hardware timer callback); +``` + +## 3. 硬件改动 + +JP21由FS功能跳接至UART功能(板卡默认串口对应的管脚跳接到了usb fs上了,不是串口功能) + +## 4. 效果验证 + +```shell + \ | / +- RT - Thread Operating System + / | \ 5.2.2 build Oct 2 2025 15:32:57 + 2006 - 2024 Copyright by RT-Thread team +msh />hw +hw_timer_test +msh />hw_timer_test timer1 +set freq 10000 Hz success +Read: Sec = 1, Usec = 999200 +set freq 100000 Hz success +Read: Sec = 1, Usec = 999040 +set freq 1000000 Hz success +Read: Sec = 1, Usec = 999956 +msh />hw_timer_test timer4 +set freq 10000 Hz success +Read: Sec = 1, Usec = 999900 +set freq 100000 Hz success +Read: Sec = 1, Usec = 999040 +set freq 1000000 Hz success +Read: Sec = 1, Usec = 999958 +msh /> +``` + +## 5. 总结 + +  以前使用硬件定时器,更多地是集中在应用层的使用,还没有真正直接写硬件定时器驱动,在编写硬件定时器驱动中,遇到了不少问题。 +  首先,GD的arm版硬件定时器代码上传后就没改过,一上来就发现打开后就被关闭了,原因是,库里面会更新数据更新事件,因为初始化时就产生了中断消息而导致定时器直接停止工作。解决办法是按照群友的思路,直接禁用更新事件中断,变更完毕后再去打开。 +  其次,GD的硬件定时器没有考虑数据溢出,导致部分频率设下去直接报错。解决办法是上报支持的频率时,限定有效的频率范围。另外,在设置时,也增加数据异常返回错误的操作。 +  最后,暂时验证通过的定时器仅有timer1和timer4,其他定时器仍然需要继续适配(目前注意到timer2和timer3,部分频率计时误差大。以及部分定时器的中断标记入口发生改变)。 +  在使用GD的芯片时,我有一个很明显的感觉,GD在技术支持资料的全面程度上,已经有向ST,TI等大厂靠齐的趋势了,比较重视文档质量,重视社区维护,这点值得点赞。 + +## 6. 后续进展 + +### 2025-10-05 + +* 定时器0~定时器13全部适配上,但由于定时器中断入口,定时器中断标记等与目前主线上存储的存在明显差异,且无法兼容现有的,不敢直接合并至主线,需官方看看怎么合并。 + +## 7. 原文链接 + +原文链接:[RT-Thread-【GD32F527_EVAL】硬件定时器适配和使用RT-Thread问答社区 - RT-Thread](https://club.rt-thread.org/ask/article/51ec33920a64f062.html) + +# 六、GD32F527上的SPI实践(刘建华) + +## 1. 环境搭建 + +1、下载rtthread源码 + +```powershell +PS D:\GD32\rtt_gitee> git clone https://gitee.com/rtthread/rt-thread.git +Cloning into 'rt-thread'... +remote: Enumerating objects: 295996, done. +remote: Counting objects: 100% (142/142), done. +remote: Compressing objects: 100% (124/124), done. +remote: Total 295996 (delta 29), reused 49 (delta 15), pack-reused 295854 (from 1) +Receiving objects: 100% (295996/295996), 875.11 MiB | 28.14 MiB/s, done. +Resolving deltas: 100% (217362/217362), done. +Updating files: 100% (36838/36838), done. +PS D:\GD32\rtt_gitee> +``` + +2、进入目录的bsp下面只留下gd32的目录,其余的删除。 + +![screenshot_image.png](figures/56690ade1ee1feba51b5c5b7c596c71a.png.webp) + +3、下入`arm/gd32f527`目录,打开env +执行`pkgs —update-force`下载完整的包 + +![screenshot_image.png](figures/3d74cec7537232e45998a808996f0df3.png.webp) + +4、打包独立工程以例以后使用,然后我就可复制dist目录下面的打包好的独立工程进行开发了。 + +![screenshot_image.png](figures/b7c51e2f44045d75cd861b4ce7a9b05b.png.webp) + +5、复制工程文件夹后,再次打开env,使用`scons —target=mdk5`来生成keil工程 +6、编译后下载到开发板,连上串口助手就可以看到成功运行rtt了 + +![screenshot_image.png](figures/6d773984d9caff0fef5aa4679d2e9169.png.webp) + +## 2. 移植spi + +1、在开发板上有板载的gd25q16,我们可以使用spi来读取并写入函数。 +查看开发板的数据手册: + +![screenshot_image.png](figures/8913ed96d3a1899adeed3dc5c19f4415.png.webp) + +他的spi是连接到spi5上面,使用的CS为PI8 +同时我们还需要把J13、J15、J17、 J19把跳线跳到对应的spi上。 +2、进入menuconfig打开spi5 + +![screenshot_image.png](figures/f2f00a42ff4416e661731aaf0e6674e2.png.webp) + +3、然后重新生成工程使用keil打开工程。 +4、在工程中,确认drv_spi已经加入到工程。 + +## 3. spi设备的挂载与配置 + +1、在drv_spi中,已经将spi5注册到了系统中,我们编译代码并下载到开发板,使用list device是可以确认有spi5这个设备了的。 + +![screenshot_image.png](figures/33bf40913601cc68c07f2c4eaa128460.png.webp) + +2、如何我们想使用gd25q16,还得将它挂载到spi5总线上。在RTT的使用说明中有如下描述: + +![screenshot_image.png](figures/80a557a9b4ff6e2b71526e6561f99e56.png.webp) + +3、从原理图中我们得到开发板使用PI8为CSpin。 +4、在drv_spi中,驱动重写了挂载函数: + +```c +rt_err_t rt_hw_spi_device_attach(const char *bus_name, const char *device_name, rt_base_t cs_pin) +{ + RT_ASSERT(bus_name != RT_NULL); + RT_ASSERT(device_name != RT_NULL); + rt_err_t result; + struct rt_spi_device *spi_device; + /* attach the device to spi bus*/ + spi_device = (struct rt_spi_device *)rt_malloc(sizeof(struct rt_spi_device)); + RT_ASSERT(spi_device != RT_NULL); + if(cs_pin != PIN_NONE) + { + /* initialize the cs pin && select the slave*/ + rt_pin_mode(cs_pin, PIN_MODE_OUTPUT); + rt_pin_write(cs_pin, PIN_HIGH); + } + result = rt_spi_bus_attach_device_cspin(spi_device, device_name, bus_name, cs_pin, RT_NULL); + if (result != RT_EOK) + { + LOG_E("%s attach to %s faild, %d\n", device_name, bus_name, result); + } + RT_ASSERT(result == RT_EOK); + LOG_D("%s attach to %s done", device_name, bus_name); + return result; +} +``` + +5、因此我们只需要传入spi总线名称,以及我们需要挂载的外设名称,以及cs的pin + +```c +/* BSP级 GET_PIN 宏定义方式 */ +rt_err_t err = rt_hw_spi_device_attach("spi5", "gd25q16", GET_PIN(I, 8)); +if(err != RT_EOK) +{ + LOG_E("err atach gd25q16"); +} +``` + +重新编译与下载后,就可以看到gd25q16已经成功的挂载到系统中了: + +![screenshot_image.png](figures/9ce37331f8e103c4a78e2bb4247f1c13.png.webp) + +## 4. 测试代码 + +```c +#define W25Q_SPI_DEVICE_NAME "gd25q16" +static void spi_gd25_sample(int argc, char *argv[]) +{ + struct rt_spi_device *spi_dev_gd25; + char name[RT_NAME_MAX]; + rt_uint8_t w25x_read_id = 0x9F; + rt_uint8_t id[5] = {0}; + if (argc == 2) + { + rt_strncpy(name, argv[1], RT_NAME_MAX); + } + else + { + rt_strncpy(name, W25Q_SPI_DEVICE_NAME, RT_NAME_MAX); + } + /* 查找 spi 设备获取设备句柄 */ + spi_dev_gd25 = (struct rt_spi_device *)rt_device_find(name); + if (!spi_dev_gd25) + { + rt_kprintf("spi sample run failed! can't find %s device!\n", name); + } + else + { + /* 方式1:使用 rt_spi_send_then_recv()发送命令读取ID */ + rt_spi_send_then_recv(spi_dev_gd25, &w25x_read_id, 1, id, 5); + rt_kprintf("use rt_spi_send_then_recv() read gd25 ID is:%x%x\n", id[3], id[4]); + /* 方式2:使用 rt_spi_transfer_message()发送命令读取ID */ + struct rt_spi_message msg1, msg2; + msg1.send_buf = &w25x_read_id; + msg1.recv_buf = RT_NULL; + msg1.length = 1; + msg1.cs_take = 1; + msg1.cs_release = 0; + msg1.next = &msg2; + msg2.send_buf = RT_NULL; + msg2.recv_buf = id; + msg2.length = 5; + msg2.cs_take = 0; + msg2.cs_release = 1; + msg2.next = RT_NULL; + rt_spi_transfer_message(spi_dev_gd25, &msg1); + rt_kprintf("use rt_spi_transfer_message() read gd25 ID is:%x%x\n", id[3], id[4]); + } +} +/* 导出到 msh 命令列表中 */ +MSH_CMD_EXPORT(spi_gd25_sample, spi gd25 sample); +``` + +下载到开发板后,已经有spi_gd25_sample的命令了。但是执行后确卡死了。究其原因,在spi总线的初始化时,没有初始gd25q16的其他三根数据线。因此,我做修补如下: +重新编写一下flash的初始化: + +```c +void spi_flash_init(void) +{ + #if 1 + spi_parameter_struct spi_init_struct; + rcu_periph_clock_enable(RCU_GPIOI); + rcu_periph_clock_enable(RCU_GPIOH); + rcu_periph_clock_enable(RCU_GPIOG); + rcu_periph_clock_enable(RCU_SPI5); + /* SPI5_CLK(PG13), SPI5_MISO(PG12), SPI5_MOSI(PG14), SPI5_IO2(PG10) and SPI5_IO3(PH4) GPIO pin configuration */ + gpio_af_set(GPIOG, GPIO_AF_5, GPIO_PIN_10 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14); + gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_10 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14); + gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, GPIO_PIN_10 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14); + gpio_af_set(GPIOH, GPIO_AF_13, GPIO_PIN_4); + gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_4); + gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, GPIO_PIN_4); + gpio_af_set(GPIOH, GPIO_AF_13, GPIO_PIN_4); + gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_4); + gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, GPIO_PIN_4); + /* SPI5_CS(PI8) GPIO pin configuration */ + gpio_mode_set(GPIOI, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_8); + gpio_output_options_set(GPIOI, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_8); + /* chip select invalid */ + SPI_FLASH_CS_HIGH(); + /* SPI5 parameter config */ + spi_init_struct.trans_mode = SPI_TRANSMODE_FULLDUPLEX; + spi_init_struct.device_mode = SPI_MASTER; + spi_init_struct.frame_size = SPI_FRAMESIZE_8BIT; + spi_init_struct.clock_polarity_phase = SPI_CK_PL_LOW_PH_1EDGE; + spi_init_struct.nss = SPI_NSS_SOFT; + spi_init_struct.prescale = SPI_PSC_32; + spi_init_struct.endian = SPI_ENDIAN_MSB; + spi_init(SPI5, &spi_init_struct); + /* quad wire SPI_IO2 and SPI_IO3 pin output enable */ + spi_quad_io23_output_enable(SPI5); + /* enable SPI5 */ + spi_enable(SPI5); +#endif + /* BSP级 GET_PIN 宏定义方式 */ + rt_err_t err = rt_hw_spi_device_attach("spi5", "gd25q16", GET_PIN(I, 8)); + if(err != RT_EOK) + { + LOG_E("err atach gd25q16"); + } +} +``` + +再次执行时,再执行测试示例就正常了,正常读取到gd25q16的ID,说明spi总线已经成功的驱动。 + +![screenshot_image.png](figures/d7fac99ca075aafb049123e218f4fe64.png.webp) + +## 5. 总结 +rtthread已经编写好了强大的drv_spi库,只需要开启spi5以及配置cs就可以轻松实现驱动自己的外设。 + +## 6. 原文链接 + +原文链接:[RT-Thread-【GD32F527_EVAL】spi外设移植RT-Thread问答社区 - RT-Thread](https://club.rt-thread.org/ask/article/d875c362b2b19131.html) + +# 七、GD32F527上的PWM实践(赵瑞聪) + +## 1. ENV环境搭建以及遇到的问题 + +官方[ENV用户手册](https://www.rt-thread.org/document/site/#/development-tools/env/env),编写的很详细 + +我在安装过程出现的问题如下所示: + +![7.png](figures/3386813c4edcc2e6902f74169a1278a2.png) + +刚刚下载了安装包,第一次使用就出现了上面的问题,然后再软件代码中,使用该软件时候也出现了下面的问题: + +![4.png](figures/9e679caadfe5242a0f2934222276606a.png) + +![5.png](figures/44be96b4e020f49db179d420f2f0b248.png) + +这种情况就是在软件安装的时候出现的问题,而且在安装的过程中,需要电脑可以登录国外的GITHUB,或者是使用离线的ENV开发工具(不过,笔者目前还没测试) + +## 2. 源码的拉取 + +### 2.1 下载代码方式: + +使用GIT直接拉取就可以 + +```shell +git clone https://gitee.com/rtthread/rt-thread.git +``` + +![9.png](figures/bbc5547cf258ddaf2581cc74a37d78a3.png) + +### 2.2 编译 + +下载的代码,发现软件包并不完整,如下所示: + +![11.png](figures/1804bb3e05b66b90f46d86503110ae8b.png.webp) + +### 2.3 打开ENV软件 + +重新配置一下支持包,过程如下所示: + +![12.png](figures/f7f727c3c3bf20322a541c6c814b176c.png) + +出现的问题,已经给出了提示,先执行`pkgs -—upgrade` ,出现如下提示 + +![13.png](figures/24728b93aef26352f66388445ad85651.png) + +等待执行成功之后,执行`pkgs —-update` + +![14.png](figures/cb7f6d7ce186a7d780ff7c9b5bb6b6cb.png) + +这里我是用的MDK5,进行软件软件代码的开发,这里我们将BSP里面的工程重新生成代码,再进行编译就可以了。 + +```shell +scons --target=mdk5 +``` + +![15.png](figures/88a869fe7bd0c2477c8869d1ac7936cd.png) + +这时候再次打开软件代码工程,编译就可以了,如下所示: + +![16.png](figures/f5efc242a2236d124e9e530a7f32fda1.png.webp) + +这里搭建env的开发工具也是遇到点问题,我这里从再官方下载了工具,然后系统环境变量没有正常添加,导致出现了莫名其妙的问题,然后在使用的过程中,代理过期出现了很多的问题。最后,也是咨询的其他的大佬,才解决。这里感谢一下。 + +## 3. PWM功能的实现 + +### 3.1 PWM知识分享: + PWM(Pulse Width Modulation 脉宽调制)是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。它是一种对模拟信号电平进行数字编码的方法。是指在一定时间内波形的高电平(即 1 状态)所占用的时间比例。通过高分辨率计数器的使用,方波占空比被调制用来对一个模拟信号的电平进行编码。PWM 信号任然是数字的,因为在给定的任何时刻,满幅值的直流供电要么完全有,要么完全无。比如我们的电压输出是 5V的,那么经过改变 PWM 的占空比,可以达到在一定时间内输出 3.3V 或者 1.3V 的效果。 + PWM是脉冲宽度调制,具有两个非常重要的参数:频率和占空比。 + 频率:PWM的频率是整个周期的倒数。 + 占空比:占空比是指一个周期内高电平所占的比例。 + +### 3.2 使用ENV软件配置一下定时器的底层驱动:过程如下: + +![17.png](figures/4eac6f4b95d7d3ab78482ff4e32a7990.png) + +![18.png](figures/025fd5eac6b193836218de79689c3ddc.png) + +![19.png](figures/f4102b70e6d71b8e742858c53fcc1634.png) + +不过,每次配置了的单片机的外设,需要重新生成一下工程,打开代码工程,,可以看到定时器文件,已经添加到工程里面了。 + +![20.png](figures/398a131d4cffd833a5aa501f09a89798.png.webp) + +### 3.3 参考官方的例程代码如下所示: + +手册地址如下所示: +[官方手册](https://www.rt-thread.org/document/api/group__pwm.html#ga3096d6e3cb9d68c8ecee9309d11c8a59) + +```c +rt_err_t rt_pwm_set(struct rt_device_pwm *device, + int channel, + rt_uint32_t period, + rt_uint32_t pulse) +``` + +设置PWM参数 +该函数可以设定指定PWM通道的周期和占空参数。 + +### 3.4 参考官方的控制代码如下所示: + +```c + rt_pin_mode(LED_PIN_NUM, PIN_MODE_OUTPUT); + /* 拉高LED引脚 */ + rt_pin_write(LED_PIN_NUM, PIN_HIGH); + /* 查找设备 */ + pwm_dev = (struct rt_device_pwm *)rt_device_find(PWM_DEV_NAME); + if (pwm_dev == RT_NULL) + { + rt_kprintf("pwm sample run failed! can't find %s device!\n", PWM_DEV_NAME); + return RT_ERROR; + } + /* 设置PWM周期和脉冲宽度默认值 */ + rt_pwm_set(pwm_dev, PWM_DEV_CHANNEL, period, pulse); + /* 使能设备 */ + rt_pwm_enable(pwm_dev, PWM_DEV_CHANNEL); +``` + +### 3.5 实物图片 + +如下所示: + +![1021-1.jpg](figures/c24e57f274f6ade2847ea389fcade6ce.jpg.webp) + +## 4. 后记 + +通过本次的测评活动,使用ENV软件配置一些底层参数,还是很方便的,当遇到问题的时候参考官方的手册,代码给自己的开发带来了很大的帮助。 + +## 5. 原文链接 + + 原文链接:[RT-Thread-【GD32F527I-EVAL】开发板测评,环境搭建,PWM输出RT-Thread问答社区 - RT-Thread](https://club.rt-thread.org/ask/article/6c11dbe74d61f5d9.html) + +# 八、GD32F527上的硬件IIC实践(董策) + +## 1. 准备工作 + +1. 安装 `env` 工具并获取 rt-thread 最新源码。具体步骤请参考 rt-thread 官方文档(此处保留对官方文档的引用说明,实际安装步骤按官方指南执行)。 + +2. 本次测评使用的 BSP 路径: + `read-master\rt-thread-master\bsp\gd32\arm\gd32527I-eval` + +3. 本次我们要使用的是**硬件 I²C(Hardware I2C)**。 + +## 2. 问题背景 +官方 BSP 默认未添加 I2C 选项(menuconfig 中没有启用硬件 I2C 的配置),所以需要手工将硬件 I²C 配置添加到 board 的 kconfig 中。 + +### 2.1 修改 kconfig(添加 I2C 配置) + +将以下代码添加到 `board/kconfig`(或相应 board 的 kconfig 文件): + +```yaml + menuconfig BSP_USING_I2C + bool "Enable I2C" + default n + if BSP_USING_I2C + menuconfig BSP_USING_HARD_I2C + bool "Enable Hardware I2C" + default n + select RT_USING_I2C + if BSP_USING_HARD_I2C + config BSP_USING_HARD_I2C0 + bool "Enable I2C0 Hardware BUS" + default n + config BSP_USING_HARD_I2C1 + bool "Enable I2C1 Hardware BUS" + default n + config BSP_USING_HARD_I2C2 + bool "Enable I2C2 Hardware BUS" + default n + config BSP_USING_HARD_I2C3 + bool "Enable I2C3 Hardware BUS" + default n + config BSP_USING_HARD_I2C4 + bool "Enable I2C4 Hardware BUS" + default n + config BSP_USING_HARD_I2C5 + bool "Enable I2C5 Hardware BUS" + default n + endif + endif +``` + +![screenshot_image.png](figures/de6517ddfec1cc131b7aac4da2b7ac01.png.webp) + +保存后重新打开 menuconfig,你应该能够看到 I2C 的选项。选择开启 `BSP_USING_I2C → BSP_USING_HARD_I2C`,然后启用你要使用的硬件 I2C 通道(例如 I2C0)。 + +在 `Keil/SConscript` 中添加驱动源文件 + +打开 Keil(或构建系统),确保驱动源文件被加入编译列表。 + +在 `packages\gd32-arm-series-latest\GD32F5xx\SConscript` 中添加: +`src += ['GD32F5xx_standard_peripheral/Source/gd32f5xx_i2c_add.c']` +重新 menuconfig(或重新生成工程)后,硬件 I2C 驱动会被添加进来(构建系统已包含该源文件)。 + +![screenshot_image-3.png](figures/0af836b802faca1822818d49ef053399.png) + +![screenshot_image-2.png](figures/86e12495840206ada79ea758a69bd258.png.webp) + +### 2.2 修改驱动 + +不知道为什么官方的bsp 硬件iic老死锁 我就魔改了一下 把官方的代码添加到了drv_hard_i2c.c + +```c +uint8_t eeprom_buffer_read_timeout(uint32_t i2c_periph,uint16_t dev_add,uint8_t *p_buffer, uint8_t read_address, uint16_t number_of_byte) +{ + uint8_t state = I2C_START; + uint8_t read_cycle = 0; + uint16_t timeout = 0; + uint8_t i2c_timeout_flag = 0; + /* enable acknowledge */ + i2c_ack_config(i2c_periph, I2C_ACK_ENABLE); + while(!(i2c_timeout_flag)) { + switch(state) { + case I2C_START: + if(RESET == read_cycle) { + /* i2c master sends start signal only when the bus is idle */ + while(i2c_flag_get(i2c_periph, I2C_FLAG_I2CBSY) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + if(timeout < I2C_TIME_OUT) { + /* whether to send ACK or not for the next byte */ + if(2 == number_of_byte) { + i2c_ackpos_config(i2c_periph, I2C_ACKPOS_NEXT); + } + } else { + //i2c_bus_reset(); + timeout = 0; + state = I2C_START; + rt_kprintf("i2c bus is busy in READ!\n"); + } + } + /* send the start signal */ + i2c_start_on_bus(i2c_periph); + timeout = 0; + state = I2C_SEND_ADDRESS; + break; + case I2C_SEND_ADDRESS: + /* i2c master sends START signal successfully */ + while((!i2c_flag_get(i2c_periph, I2C_FLAG_SBSEND)) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + if(timeout < I2C_TIME_OUT) { + if(RESET == read_cycle) { + i2c_master_addressing(i2c_periph, dev_add, I2C_TRANSMITTER); + state = I2C_CLEAR_ADDRESS_FLAG; + } else { + i2c_master_addressing(i2c_periph, dev_add, I2C_RECEIVER); + if(number_of_byte < 3) { + /* disable acknowledge */ + i2c_ack_config(i2c_periph, I2C_ACK_DISABLE); + } + state = I2C_CLEAR_ADDRESS_FLAG; + } + timeout = 0; + } else { + timeout = 0; + state = I2C_START; + read_cycle = 0; + rt_kprintf("i2c master sends start signal timeout in READ!\n"); + } + break; + case I2C_CLEAR_ADDRESS_FLAG: + /* address flag set means i2c slave sends ACK */ + while((!i2c_flag_get(i2c_periph, I2C_FLAG_ADDSEND)) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + if(timeout < I2C_TIME_OUT) { + i2c_flag_clear(i2c_periph, I2C_FLAG_ADDSEND); + if((SET == read_cycle) && (1 == number_of_byte)) { + /* send a stop condition to I2C bus */ + i2c_stop_on_bus(i2c_periph); + } + timeout = 0; + state = I2C_TRANSMIT_DATA; + } else { + timeout = 0; + state = I2C_START; + read_cycle = 0; + rt_kprintf("i2c master clears address flag timeout in READ!\n"); + } + break; + case I2C_TRANSMIT_DATA: + if(RESET == read_cycle) { + /* wait until the transmit data buffer is empty */ + while((! i2c_flag_get(i2c_periph, I2C_FLAG_TBE)) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + if(timeout < I2C_TIME_OUT) { + /* send the EEPROM's internal address to write to : only one byte address */ + i2c_data_transmit(i2c_periph, read_address); + timeout = 0; + } else { + timeout = 0; + state = I2C_START; + read_cycle = 0; + rt_kprintf("i2c master wait data buffer is empty timeout in READ!\n"); + } + /* wait until BTC bit is set */ + while((!i2c_flag_get(i2c_periph, I2C_FLAG_BTC)) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + if(timeout < I2C_TIME_OUT) { + timeout = 0; + state = I2C_START; + read_cycle++; + } else { + timeout = 0; + state = I2C_START; + read_cycle = 0; + rt_kprintf("i2c master sends EEPROM's internal address timeout in READ!\n"); + } + } else { + while(number_of_byte) { + timeout++; + if(3 == number_of_byte) { + /* wait until BTC bit is set */ + while(!i2c_flag_get(i2c_periph, I2C_FLAG_BTC)); + /* disable acknowledge */ + i2c_ack_config(i2c_periph, I2C_ACK_DISABLE); + } + if(2 == number_of_byte) { + /* wait until BTC bit is set */ + while(!i2c_flag_get(i2c_periph, I2C_FLAG_BTC)); + /* send a stop condition to I2C bus */ + i2c_stop_on_bus(i2c_periph); + } + /* wait until RBNE bit is set */ + if(i2c_flag_get(i2c_periph, I2C_FLAG_RBNE)) { + /* read a byte from the EEPROM */ + *p_buffer = i2c_data_receive(i2c_periph); + /* point to the next location where the byte read will be saved */ + p_buffer++; + /* decrement the read bytes counter */ + number_of_byte--; + timeout = 0; + } + if(timeout > I2C_TIME_OUT) { + timeout = 0; + state = I2C_START; + read_cycle = 0; + rt_kprintf("i2c master sends data timeout in READ!\n"); + } + } + timeout = 0; + state = I2C_STOP; + } + break; + case I2C_STOP: + /* i2c master sends STOP signal successfully */ + while((I2C_CTL0(i2c_periph) & I2C_CTL0_STOP) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + if(timeout < I2C_TIME_OUT) { + timeout = 0; + state = I2C_END; + i2c_timeout_flag = I2C_OK; + } else { + timeout = 0; + state = I2C_START; + read_cycle = 0; + rt_kprintf("i2c master sends stop signal timeout in READ!\n"); + } + break; + default: + state = I2C_START; + read_cycle = 0; + i2c_timeout_flag = I2C_OK; + timeout = 0; + rt_kprintf("i2c master sends start signal in READ.\n"); + break; + } + } + return I2C_END; +} +uint8_t eeprom_page_write_timeout(uint32_t i2c_periph ,uint16_t eeprom_address,uint8_t *p_buffer, uint8_t write_address, uint8_t number_of_byte) +{ + uint8_t state = I2C_START; + uint16_t timeout = 0; + uint8_t i2c_timeout_flag = 0; + /* enable acknowledge */ + i2c_ack_config(i2c_periph, I2C_ACK_ENABLE); + while(!(i2c_timeout_flag)) { + switch(state) { + case I2C_START: + /* i2c master sends start signal only when the bus is idle */ + while(i2c_flag_get(i2c_periph, I2C_FLAG_I2CBSY) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + if(timeout < I2C_TIME_OUT) { + i2c_start_on_bus(i2c_periph); + timeout = 0; + state = I2C_SEND_ADDRESS; + } else { + // i2c_bus_reset(); + timeout = 0; + state = I2C_START; + rt_kprintf("i2c bus is busy in WRITE!\n"); + } + break; + case I2C_SEND_ADDRESS: + /* i2c master sends START signal successfully */ + while((!i2c_flag_get(i2c_periph, I2C_FLAG_SBSEND)) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + if(timeout < I2C_TIME_OUT) { + i2c_master_addressing(i2c_periph, eeprom_address, I2C_TRANSMITTER); + timeout = 0; + state = I2C_CLEAR_ADDRESS_FLAG; + } else { + timeout = 0; + state = I2C_START; + rt_kprintf("i2c master sends start signal timeout in WRITE!\n"); + } + break; + case I2C_CLEAR_ADDRESS_FLAG: + /* address flag set means i2c slave sends ACK */ + while((!i2c_flag_get(i2c_periph, I2C_FLAG_ADDSEND)) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + if(timeout < I2C_TIME_OUT) { + i2c_flag_clear(i2c_periph, I2C_FLAG_ADDSEND); + timeout = 0; + state = I2C_TRANSMIT_DATA; + } else { + timeout = 0; + state = I2C_START; + rt_kprintf("i2c master clears address flag timeout in WRITE!\n"); + } + break; + case I2C_TRANSMIT_DATA: + /* wait until the transmit data buffer is empty */ + while((!i2c_flag_get(i2c_periph, I2C_FLAG_TBE)) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + if(timeout < I2C_TIME_OUT) { + /* send the EEPROM's internal address to write to : only one byte address */ + i2c_data_transmit(i2c_periph, write_address); + timeout = 0; + } else { + timeout = 0; + state = I2C_START; + rt_kprintf("i2c master sends EEPROM's internal address timeout in WRITE!\n"); + } + /* wait until BTC bit is set */ + while((!i2c_flag_get(i2c_periph, I2C_FLAG_BTC)) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + if(timeout < I2C_TIME_OUT) { + timeout = 0; + } else { + timeout = 0; + state = I2C_START; + rt_kprintf("i2c master sends data timeout in WRITE!\n"); + } + while(number_of_byte--) { + i2c_data_transmit(i2c_periph, *p_buffer); + /* point to the next byte to be written */ + p_buffer++; + /* wait until BTC bit is set */ + while((!i2c_flag_get(i2c_periph, I2C_FLAG_BTC)) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + if(timeout < I2C_TIME_OUT) { + timeout = 0; + } else { + timeout = 0; + state = I2C_START; + rt_kprintf("i2c master sends data timeout in WRITE!\n"); + } + } + timeout = 0; + state = I2C_STOP; + break; + case I2C_STOP: + /* send a stop condition to I2C bus */ + i2c_stop_on_bus(i2c_periph); + /* i2c master sends STOP signal successfully */ + while((I2C_CTL0(i2c_periph) & I2C_CTL0_STOP) && (timeout < I2C_TIME_OUT)) { + timeout++; + } + if(timeout < I2C_TIME_OUT) { + timeout = 0; + state = I2C_END; + i2c_timeout_flag = I2C_OK; + } else { + timeout = 0; + state = I2C_START; + rt_kprintf("i2c master sends stop signal timeout in WRITE!\n"); + } + break; + default: + state = I2C_START; + i2c_timeout_flag = I2C_OK; + timeout = 0; + rt_kprintf("i2c master sends start signal in WRITE.\n"); + break; + } + } + return I2C_END; +} +static rt_ssize_t gd32_i2c_master_xfer(struct rt_i2c_bus_device *bus, struct rt_i2c_msg msgs[], rt_uint32_t num) + { + rt_thread_mdelay(11); + struct gd32_i2c_bus *gd32_i2c = (struct gd32_i2c_bus *)bus->priv; + if(msgs[0].flags& RT_I2C_RD) + { + eeprom_buffer_read_timeout(gd32_i2c->i2c_periph,msgs[0].addr, msgs[0].buf, msgs[0].buf[0],msgs[0].len); + } + else{ + eeprom_page_write_timeout(gd32_i2c->i2c_periph ,msgs[0].addr,&msgs[0].buf[1], msgs[0].buf[0],msgs[0].len); + } + } +``` + +在main.c中添加代码 + +```c +/* + * Copyright (c) 2006-2023, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-08-20 BruceOu first implementation + * 2023-03-05 yuanzihao change the LED pins + */ +#include +#include +#include +#include +/* defined the LED1 pin: PE3 */ +#define LED1_PIN GET_PIN(E, 3) +#define I2C_BUS_NAME "hwi2c0" +#include "string.h" +void eeprom_write_one_byte(struct rt_i2c_bus_device *dev, rt_uint16_t addr, rt_uint8_t *data,rt_uint8_t len) +{ + struct rt_i2c_msg msgs; + rt_uint8_t temp[11]; + temp[0]=addr; + memcpy(&temp[1],data,len); + msgs.addr = 0xA0; + msgs.flags = RT_I2C_WR; + msgs.buf = temp; + msgs.len = len; +if(!rt_i2c_transfer(dev, &msgs, 1)) +{ + rt_kprintf("write error\n"); +} +} +rt_uint8_t eeprom_read(struct rt_i2c_bus_device *dev, rt_uint8_t addr,rt_uint8_t *data,uint8_t len) +{ + struct rt_i2c_msg msgs[2]; + msgs[0].addr = 0xA0; + msgs[0].flags = RT_I2C_RD; + msgs[0].buf = &addr; + msgs[0].len = len; + if (rt_i2c_transfer(dev, &msgs[0], 1) != 1) + { + } + memcpy(data,msgs[0].buf,len); +} +int main(void) +{ + struct rt_i2c_bus_device *dev =rt_i2c_bus_device_find(I2C_BUS_NAME); + if(NULL != dev) + { + rt_kprintf("eeprom_dev init success\n"); + } + uint8_t tx_data[4] ; + for(int a=0;a 主要有2个问题 +> 1.官方的bsp有点问题,读取之后会死锁。 +> 2.软件包的at24c02的设备地址传入A0之后会左移,GD的地址硬件做了读写操作,即使bsp没问题使用软件包也不行 + +## 3. 原文链接 + +原文链接:[RT-Thread-【GD32f527测评】---硬件IICRT-Thread问答社区 - RT-Thread](https://club.rt-thread.org/ask/article/8ccc041bcbaa0d33.html) + +# 九、GD32F527上的ETH实践(麦欢艺) + +## 1. 开发板资料 + +* gd32官网https://www.gigadevice.com.cn/product/mcu/high-performance-mcus/gd32f5xx-series + +## 2. 测试网口的设置 + +* 图片的红框的跳针要对应原理图设置好; + +![screenshot_微信图片_20251013141253_94_67.jpg](figures/7989ef2697ede7ed473534eb9c45f0f1.jpg.webp) + +## 3. 移植步骤 + +* 参考stm32的drv_eth.c和官方的demo编写驱动; + 1. 初始化gpio; + 2. 配置phy; + 3. 注册网卡; + +```c +rt_err_t rt_gd32_eth_tx(rt_device_t dev, struct pbuf *p) +{ + rt_err_t ret = -RT_ERROR; + struct pbuf *q; + int framelength = 0; + uint32_t bufferoffset = 0; + uint32_t byteslefttocopy = 0; + uint32_t payloadoffset = 0; + /* global transmit and receive descriptors pointers */ + extern enet_descriptors_struct *dma_current_txdesc; + enet_descriptors_struct *dma_txdesc = dma_current_txdesc; + uint8_t *buffer = (uint8_t *)(dma_txdesc->buffer1_addr); + /* copy frame from pbufs to driver buffers */ + for (q = p; q != NULL; q = q->next) + { + /* Is this buffer available? If not, goto error */ + if ((dma_txdesc->status & ENET_TDES0_DAV) != (uint32_t)RESET) + { + ret = RT_EOK; + goto _error; + } + rt_memcpy((uint8_t *)&buffer[framelength], q->payload, q->len); + framelength = framelength + q->len; + } + /* transmit descriptors to give to DMA */ + ENET_NOCOPY_FRAME_TRANSMIT(framelength); +#ifdef ETH_TX_DUMP + dump_hex(buffer, p->tot_len); +#endif + ret = RT_EOK; +_error: + return ret; +} +struct pbuf *rt_gd32_eth_rx(rt_device_t dev) +{ + struct pbuf *p, *q; + uint16_t len; + uint8_t *buffer; + uint32_t bufferoffset = 0; + uint32_t payloadoffset = 0; + uint32_t byteslefttocopy = 0; + extern enet_descriptors_struct *dma_current_rxdesc; + enet_descriptors_struct *dma_rxdesc = dma_current_rxdesc; + p = NULL; + /* obtain the size of the packet and put it into the "len" variable. */ + len = enet_desc_information_get(dma_rxdesc, RXDESC_FRAME_LENGTH); + buffer = (uint8_t *)(dma_rxdesc->buffer1_addr); + if (len > 0) + { + /* we allocate a pbuf chain of pbufs from the Lwip buffer pool */ + p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); + } +#ifdef ETH_RX_DUMP + dump_hex(buffer, p->tot_len); +#endif + if (p != NULL) + { + bufferoffset = 0; + for (q = p; q != NULL; q = q->next) + { + byteslefttocopy = q->len; + payloadoffset = 0; + /* Check if the length of bytes to copy in current pbuf is bigger than Rx buffer size */ + while ((byteslefttocopy + bufferoffset) > ENET_RXBUF_SIZE) + { + /* Copy data to pbuf */ + SMEMCPY((uint8_t *)((uint8_t *)q->payload + payloadoffset), (uint8_t *)((uint8_t *)buffer + bufferoffset), (ENET_RXBUF_SIZE - bufferoffset)); + /* Point to next descriptor */ + dma_rxdesc = (enet_descriptors_struct *)(dma_rxdesc->buffer2_next_desc_addr); + buffer = (uint8_t *)(dma_rxdesc->buffer1_addr); + byteslefttocopy = byteslefttocopy - (ENET_RXBUF_SIZE - bufferoffset); + payloadoffset = payloadoffset + (ENET_RXBUF_SIZE - bufferoffset); + bufferoffset = 0; + } + /* Copy remaining data in pbuf */ + SMEMCPY((uint8_t *)((uint8_t *)q->payload + payloadoffset), (uint8_t *)((uint8_t *)buffer + bufferoffset), byteslefttocopy); + bufferoffset = bufferoffset + byteslefttocopy; + } + } + ENET_NOCOPY_FRAME_RECEIVE(); + return p; +} +``` + +## 4. 移植遇到的问题及体验 + +* 按照官方的demo编写rt_gd32_eth_rx函数会一直触发中断,导致cpu占用率高; +* 发现没有插入网线启动会导致phy初始化失败(检测网线插入状态超时),导致网口没有正真初始化成功,当插入网线后会崩溃;(已提交PR,等待合并到主仓库中) + +## 5. 测试 + +![screenshot_image.png](figures/91c30fc3afeacd1fefe1e41cb5fc70ed.png) + +[测试视频链接](https://www.bilibili.com/video/BV19o4yzKE7r/?spm_id_from=333.1007.0.0&vd_source=18cb9a267685581c30c21ca670b18597) + +[测试代码(master)](https://github.com/Maihuanyi/rt-thread) + +## 6. 原文链接 + +原文链接:[RT-Thread-【GD32F527_EVAL】 ETH的使用RT-Thread问答社区 - RT-Thread](https://club.rt-thread.org/ask/article/db609411f2503d10.html) + +# 十、GD32F527上的CAN实践(吴艺彬、王凯) +## 1. 【GD32F527_EVAL】 CAN外设测试(王凯) + +### 1.1 GD32F527_EVAL开发板资料例程下载 + +网盘:https://pan.baidu.com/s/1zYeIVOHa7dkEjlTUm98hLw?pwd=jsds 提取码: jsds +官网:https://www.gigadevice.com.cn/product/mcu/high-performance-mcus/gd32f5xx-series + +![B_官网资料.JPG](figures/c52e7e6b393474823c62fcc1e483cd54.jpg.webp) + +### 1.2 开发板设置 + +![开发板设置.JPG](figures/1704ad6994bfcf200f6910b4221fa3cd.jpg) + +电源:选择用GDLINK调试口的USB供电,JP4的短接帽接56。 + +![供电选择.JPG](figures/a4cd4b6764d3ba46ec9efd8a3b3d1638.jpg) + +调试串口:开启调试串口需将JP21的短接帽接12。 + +![调试串口.JPG](figures/92df6c4fcad6c7b25f42e004eff43ef8.jpg) + +CAN:需将JP35和JP36的短接帽接23。 + +![CAN.JPG](figures/743e1b3f8fce8aa65a863de9a0dd33d5.jpg) + +### 1.3 GD CAN外设 + +支持普通CAN和CAN-FD,普通CAN通讯波特率最大1Mbit/s,CAN-FD通讯波特率最大6Mbit/s。 +接收有硬件FIFO + +![CAN外设.JPG](figures/86891aef9bd1b85cfff3342749c59861.jpg) + +### 1.4 CAN外设初始化 + +外设初始化主要分2块。配置CAN,包括包括波特率、seg、重传等。配置接收滤波方式和掩码。 +这里对例程做了点调整,因为测试的时候发现例程只能接收固定ID的CAN帧。CAN外设支持掩码模式和列表模式。这里使用掩码模式,且掩码设置为全0,即接收所有的ID的CAN帧数据。同时在接收中断中也有部分修改,后面会展开说。 + +```c +void can_networking_init(void) { + can_parameter_struct can_parameter; + can_filter_parameter_struct can_filter; + /* initialize CAN register */ + can_deinit(CAN0); + /* initialize CAN */ + can_parameter.time_triggered = DISABLE; + can_parameter.auto_bus_off_recovery = DISABLE; + can_parameter.auto_wake_up = DISABLE; + can_parameter.auto_retrans = ENABLE; + can_parameter.rec_fifo_overwrite = DISABLE; + can_parameter.trans_fifo_order = DISABLE; + can_parameter.working_mode = CAN_NORMAL_MODE; + can_parameter.resync_jump_width = CAN_BT_SJW_1TQ; + can_parameter.time_segment_1 = CAN_BT_BS1_7TQ; + can_parameter.time_segment_2 = CAN_BT_BS2_2TQ; + /* baudrate 1Mbps */ + can_parameter.prescaler = 5; + can_init(CAN0, &can_parameter); + /* initialize filter */ + /* CAN0 filter number */ + can_filter.filter_number = 0; + /* initialize filter */ + can_filter.filter_mode = CAN_FILTERMODE_MASK; + can_filter.filter_bits = CAN_FILTERBITS_32BIT; + /* configure filter ID, only the 0xaabb expand ID can be received */ + //can_filter.filter_list_high = (uint16_t)(DEV_CAN0_ID >> 13U); + //can_filter.filter_list_low = ((uint16_t)(DEV_CAN0_ID << 3U)) | (1U << 2); + /* configure filter mask */ + can_filter.filter_mask_high = 0x0000; + can_filter.filter_mask_low = 0x0000; + /* select receiver fifo */ + can_filter.filter_fifo_number = CAN_FIFO0; + can_filter.filter_number = 0; + can_filter.filter_enable = ENABLE; + can_filter_init(&can_filter); +} +``` + +### 1.5 CAN发送 + +CAN发送帧类型为扩展帧8个字节数据。 + +```c +/* initialize transmit message */ +can_struct_para_init(CAN_TX_MESSAGE_STRUCT, &transmit_message); +/* initialize transmit message */ +transmit_message.tx_sfid = 0x00; +transmit_message.tx_efid = 0x00; +transmit_message.tx_ft = CAN_FT_DATA; +transmit_message.tx_ff = CAN_FF_EXTENDED; +transmit_message.tx_dlen = 8; +/* initialize receive message */ +can_struct_para_init(CAN_RX_MESSAGE_STRUCT, &receive_message); +``` + +通过按键使能发送一帧CAN数据,并显示在调试串口上。 + +```c +/* waiting for the Tamper key pressed */ +while(0 == gd_eval_key_state_get(KEY_TAMPER)) { + transmit_message.tx_efid = DEV_CAN0_ID; + transmit_message.tx_data[0] = 0xA0; + transmit_message.tx_data[1] = 0xA1; + transmit_message.tx_data[2] = 0xA2; + transmit_message.tx_data[3] = 0xA3; + transmit_message.tx_data[4] = 0xA4; + transmit_message.tx_data[5] = 0xA5; + transmit_message.tx_data[6] = 0xA6; + transmit_message.tx_data[7] = 0xA7; + printf("\r\n can0 transmit data:"); + for(i = 0; i < transmit_message.tx_dlen; i++){ + printf(" %02x", transmit_message.tx_data[i]); + } + /* transmit message */ + can_message_transmit(CAN0, &transmit_message); + /* waiting for Tamper key up */ + while(0 == gd_eval_key_state_get(KEY_TAMPER)); +} +``` + +### 1.6 CAN接收 + +CAN的接收是通过中断的方式。这里做了点调整,例程中的CAN接收中断将接收到的帧存在全局的BUFF中,并设置FLAG,然后在主循环中检测这个FLAG,并通过串口打印接收到的数据。测试中若通过CAN分析仪连续发送多帧数据,串口打印出的帧数据不全。因此在接收中断中添加了一个软件FIFO,来缓冲接收CAN帧过快的影响。 + +```c +/* 定义CAN接收FIFO */ +can_receive_message_struct can0_rx_fifo[32] = {0}; +uint16_t can0_rx_fifo_head = 0; +uint16_t can0_rx_fifo_tail = 0; +uint32_t can0_rx_err_cnt = 0; +uint32_t can0_rx_over_cnt = 0; +``` + +```c +void CAN0_RX0_IRQHandler(void) { + uint16_t i = 0; + /* 将接收的CAN帧先存放在receive_message中 */ + can_message_receive(CAN0, CAN_FIFO0, &receive_message); + /* 判断接收的CAN帧是否有错误 */ + if (CAN_ERRN_0 == receive_message.fd_esi) { + /* 接收的CAN帧无错误 */ + /* 判断FIFO是否满 */ + if (((can0_rx_fifo_head + 1) % 32) != can0_rx_fifo_tail) { + /* 将CAN数据压到FIFO中 */ + can0_rx_fifo[can0_rx_fifo_head].rx_sfid = receive_message.rx_sfid; + can0_rx_fifo[can0_rx_fifo_head].rx_efid = receive_message.rx_efid; + can0_rx_fifo[can0_rx_fifo_head].rx_ff = receive_message.rx_ff; + can0_rx_fifo[can0_rx_fifo_head].rx_ft = receive_message.rx_ft; + can0_rx_fifo[can0_rx_fifo_head].rx_dlen = receive_message.rx_dlen; + for (i = 0; i < 64; i++) { + can0_rx_fifo[can0_rx_fifo_head].rx_data[i] = 0; + } + for (i = 0; (i < receive_message.rx_dlen) && (i < 64); i++) { + can0_rx_fifo[can0_rx_fifo_head].rx_data[i] = receive_message.rx_data[i]; + } + can0_rx_fifo[can0_rx_fifo_head].rx_fi = receive_message.rx_fi; + can0_rx_fifo[can0_rx_fifo_head].fd_flag = receive_message.fd_flag; + can0_rx_fifo[can0_rx_fifo_head].fd_brs = receive_message.fd_brs; + can0_rx_fifo[can0_rx_fifo_head].fd_esi = receive_message.fd_esi; + /* 将FIFO的头指向下一个BUFF */ + can0_rx_fifo_head = ((can0_rx_fifo_head + 1) % 32); + } else { + /* FIFO溢出 */ + can0_rx_over_cnt++; + } + } else { + /* 接收的CAN帧有错误 */ + can0_rx_err_cnt++; + } +} +``` + +```c +/* 检查FIFO中是否存在数据,并输出 */ +if (can0_rx_fifo_tail != can0_rx_fifo_head) { + /* print can rx data */ + printf("fram format: %xH\r\n", can0_rx_fifo[can0_rx_fifo_tail].rx_ff); + printf("fram type: %xH\r\n", can0_rx_fifo[can0_rx_fifo_tail].rx_ft); + printf("stand id: %xH\r\n", can0_rx_fifo[can0_rx_fifo_tail].rx_sfid); + printf("extend id: %xH\r\n", can0_rx_fifo[can0_rx_fifo_tail].rx_efid); + printf("data len: %xH\r\n", can0_rx_fifo[can0_rx_fifo_tail].rx_dlen); + printf("data: "); + for (j = 0; j < 8; j++) { + printf("%02xH, ", can0_rx_fifo[can0_rx_fifo_tail].rx_data[j]); + } printf("\r\n"); + printf("\r\n"); + /* 将FIFO的尾指针指向下一个BUFF */ + can0_rx_fifo_tail = (can0_rx_fifo_tail + 1) % 32; +} +``` + +### 1.7 测试 + +CAN发送:每按一次按键发送一帧CAN数据到CAN分析仪上。 + +![CAN发送.JPG](figures/f7e7ac946e494e3d8ff1e08913ff90c6.jpg.webp) + +CAN接收:CAN分析仪连续发送10帧ID和数据自增的帧。调试串口连续输出10帧CAN数据。 + +![CAN接收1.JPG](figures/40919b7694173bb9f28c1c62004fde94.jpg.webp) + +![CAN接收2.JPG](figures/36b8e7c5d6befde4e50bd521dda4cf96.jpg.webp) + +### 1.8 测试工程 + +* [GD32F527_CanTest_v1.rar](https://club.rt-thread.org/file_download/feaef28befd75553) + +### 1.9 心得体会 + +GD的官方库使用的是标准库,类似于ST前些年的标准库。每个人的喜好不同,多数人喜欢HAL库图形化界面配置简单易上手。但我个人比较喜欢GD的这种标准库,原因是简单明了,没有层层的调用,更没有冗长的宏定义,执行效率比较好。而图形化配置工具和工具的版本关联很大,有时打开不同的例程需要安装不同版本的工具。 + +### 1.10 原文链接 + +原文链接:[RT-Thread-【GD32F527_EVAL】 CAN外设测试RT-Thread问答社区 - RT-Thread](https://club.rt-thread.org/ask/article/b911235d33d5149b.html) + +## 2. 【GD32F527_EVAL】 CANFD测试(王凯) + +### 2.1 GD32F527_EVAL开发板资料例程下载 + +网盘:https://pan.baidu.com/s/1zYeIVOHa7dkEjlTUm98hLw?pwd=jsds 提取码: jsds +官网:https://www.gigadevice.com.cn/product/mcu/high-performance-mcus/gd32f5xx-series + +![B_官网资料.JPG](figures/c52e7e6b393474823c62fcc1e483cd54.jpg.webp) + +### 2.2 开发板设置 + +![开发板设置.JPG](figures/1704ad6994bfcf200f6910b4221fa3cd.jpg) + +电源:选择用GDLINK调试口的USB供电,JP4的短接帽接56。 + +![供电选择.JPG](figures/a4cd4b6764d3ba46ec9efd8a3b3d1638.jpg) + +调试串口:开启调试串口需将JP21的短接帽接12。 + +![调试串口.JPG](figures/92df6c4fcad6c7b25f42e004eff43ef8.jpg) + +CAN:需将JP35和JP36的短接帽接23。 + +![CAN.JPG](figures/743e1b3f8fce8aa65a863de9a0dd33d5.jpg) + +### 2.3 CANFD初始化 + +外设初始化主要分3块。配置CAN,包括包括波特率、seg、重传等。配置CANFD,配置接收滤波方式和掩码。 +CAN外设支持掩码模式和列表模式。这里使用掩码模式,且掩码设置为全0,即接收所有的ID的CAN帧数据。 + +```c +/* 初始化CANFD */ +void can_networking_init(void) { + can_parameter_struct can_parameter; + can_filter_parameter_struct can_filter; + can_fdframe_struct can_fd_parameter; + can_fd_tdc_struct can_fd_tdc_parameter; + /* initialize CAN register */ + can_deinit(CAN0); + /* initialize CAN */ + //can_struct_para_init(CAN_INIT_STRUCT, &can_parameter); + can_parameter.time_triggered = DISABLE; + can_parameter.auto_bus_off_recovery = DISABLE; + can_parameter.auto_wake_up = DISABLE; + can_parameter.auto_retrans = ENABLE; + can_parameter.rec_fifo_overwrite = DISABLE; + can_parameter.trans_fifo_order = DISABLE; + can_parameter.working_mode = CAN_NORMAL_MODE; + can_parameter.resync_jump_width = CAN_BT_SJW_1TQ; + can_parameter.time_segment_1 = CAN_BT_BS1_7TQ; + can_parameter.time_segment_2 = CAN_BT_BS2_2TQ; + can_parameter.prescaler = 5; + /* 波特率 = 外设时钟频率 / prescaler / (jump_width + segment_1 + segment_2) */ + /* 波特率 = 1MHz */ + can_init(CAN0, &can_parameter); + /* canfd init */ + can_struct_para_init(CAN_FD_FRAME_STRUCT, &can_fd_parameter); + can_fd_parameter.fd_frame = ENABLE; + can_fd_parameter.excp_event_detect = ENABLE; + can_fd_parameter.delay_compensation = ENABLE; + can_fd_tdc_parameter.tdc_filter = 0x04U; + can_fd_tdc_parameter.tdc_mode = CAN_TDCMOD_CALC_AND_OFFSET; + can_fd_tdc_parameter.tdc_offset = 0x04U; + can_fd_parameter.p_delay_compensation = &can_fd_tdc_parameter; + can_fd_parameter.iso_bosch = CAN_FDMOD_ISO; + can_fd_parameter.esi_mode = CAN_ESIMOD_HARDWARE; + can_fd_parameter.data_resync_jump_width = CAN_BT_SJW_1TQ; + can_fd_parameter.data_time_segment_1 = CAN_BT_BS1_7TQ; // TSG1 + can_fd_parameter.data_time_segment_2 = CAN_BT_BS2_2TQ; // TSG2 + can_fd_parameter.data_prescaler = 1; + /* FD加速波特率 = 外设时钟频率 / prescaler / (jump_width + segment_1 + segment_2) */ + /* FD加速波特率 = 5MHz */ + /* initialize CAN-FD */ + can_fd_init(CAN0, &can_fd_parameter); + /* initialize filter */ + /* CAN0 filter number */ + can_filter.filter_number = 0; + /* initialize filter */ + can_filter.filter_mode = CAN_FILTERMODE_MASK; + can_filter.filter_bits = CAN_FILTERBITS_32BIT; + /* configure filter ID, only the 0xaabb expand ID can be received */ + //can_filter.filter_list_high = (uint16_t)(DEV_CAN0_ID >> 13U); + //can_filter.filter_list_low = ((uint16_t)(DEV_CAN0_ID << 3U)) | (1U << 2); + /* configure filter mask */ + can_filter.filter_mask_high = 0x0000; + can_filter.filter_mask_low = 0x0000; + /* select receiver fifo */ + can_filter.filter_fifo_number = CAN_FIFO0; + can_filter.filter_number = 0; + can_filter.filter_enable = ENABLE; + can_filter_init(&can_filter); +} +``` + +### 2.4 CAN发送 + +```c +int can_send_message(can_trasnmit_message_struct *can_data) { + uint8_t i; + static can_trasnmit_message_struct can_tx_message; + /* 发送标准帧 */ + can_tx_message.tx_sfid = can_data->tx_sfid; + can_tx_message.tx_ft = CAN_FT_DATA; + can_tx_message.tx_ff = CAN_FF_STANDARD; + /* 发送扩展帧 */ +// can_tx_message.tx_efid = can_data->tx_efid; +// can_tx_message.tx_ft = CAN_FT_DATA; +// can_tx_message.tx_ff = CAN_FF_EXTENDED; + /* 发送普通CAN帧 */ +// can_tx_message.fd_flag = 0; +// can_tx_message.fd_brs = 0; + /* 发送CANFD帧 */ +// can_tx_message.fd_flag = 1; +// can_tx_message.fd_brs = 0; + /* 发送CANFD加速帧 */ + can_tx_message.fd_flag = 1; + can_tx_message.fd_brs = 1; + can_tx_message.fd_esi = 0; + for (i = 0; i < 64; i++) { + can_tx_message.tx_data[i] = can_data->tx_data[i]; + } + /* CANFD帧对数据长度有要求 */ + if (can_tx_message.fd_flag == 1) { + if(can_data->tx_dlen > 48) { + can_tx_message.tx_dlen = 64; + } else if(can_data->tx_dlen > 32) { + can_tx_message.tx_dlen = 48; + } else if(can_data->tx_dlen > 24) { + can_tx_message.tx_dlen = 32; + } else if(can_data->tx_dlen > 20) { + can_tx_message.tx_dlen = 24; + } else if(can_data->tx_dlen > 16) { + can_tx_message.tx_dlen = 20; + } else if(can_data->tx_dlen > 12) { + can_tx_message.tx_dlen = 16; + } else if(can_data->tx_dlen > 8) { + can_tx_message.tx_dlen = 12; + } else { + can_tx_message.tx_dlen = can_data->tx_dlen; + } + } else { + if(can_data->tx_dlen > 8) { + can_tx_message.tx_dlen = 8; + } else { + can_tx_message.tx_dlen = can_data->tx_dlen; + } + } +#if 1 + /* print can tx data */ + printf("can tx data:\r\n"); + printf("fram format: %xH (0:standard, 4:extended)\r\n", can_tx_message.tx_ff); + printf("fram type: %xH (0:data, 2:remote)\r\n", can_tx_message.tx_ft); + printf("fd flag: %xH (0:can, 1:canfd)\r\n", can_tx_message.fd_flag); + printf("fd brs: %xH (0:no speed, 1:speed)\r\n", can_tx_message.fd_brs); + printf("stand id: %xH\r\n", can_tx_message.tx_sfid); + printf("extend id: %xH\r\n", can_tx_message.tx_efid); + printf("data len: %xH\r\n", can_tx_message.tx_dlen); + printf("data: "); + for (i = 0; (i < 64) & (i < can_tx_message.tx_dlen); i++) { + if ((i != 0) && (i % 8 == 0)) { + printf ("\r\n "); + } + printf("%02xH, ", can_tx_message.tx_data[i]); + } printf("\r\n"); +#endif + /* transmit message */ + if(can_message_transmit(CAN0, &can_tx_message) == CAN_NOMAILBOX) { + return 1; + } + return 0; +} +``` + +### 2.5 CAN接收 + +CAN的接收是通过中断的方式,在接收中断中添加了一个软件FIFO,来缓冲接收CAN帧过快的影响。 + +```c +/* CAN接收FIFO定义 */ +can_receive_message_struct can0_rx_fifo[32] = {0}; +uint16_t can0_rx_fifo_head = 0; +uint16_t can0_rx_fifo_tail = 0; +uint32_t can0_rx_err_cnt = 0; +uint32_t can0_rx_over_cnt = 0; +``` + +```c +/* CAN接收中断 */ +void CAN0_RX0_IRQHandler(void) +{ + uint16_t i = 0; + /* check the receive message */ + can_message_receive(CAN0, CAN_FIFO0, &receive_message); + if (CAN_ERRN_0 == receive_message.fd_esi) { + /* no error */ + if (((can0_rx_fifo_head + 1) % 32) != can0_rx_fifo_tail) { + can0_rx_fifo[can0_rx_fifo_head].rx_sfid = receive_message.rx_sfid; + can0_rx_fifo[can0_rx_fifo_head].rx_efid = receive_message.rx_efid; + can0_rx_fifo[can0_rx_fifo_head].rx_ff = receive_message.rx_ff; + can0_rx_fifo[can0_rx_fifo_head].rx_ft = receive_message.rx_ft; + can0_rx_fifo[can0_rx_fifo_head].rx_dlen = receive_message.rx_dlen; + for (i = 0; i < 64; i++) { + can0_rx_fifo[can0_rx_fifo_head].rx_data[i] = 0; + } + for (i = 0; (i < receive_message.rx_dlen) && (i < 64); i++) { + can0_rx_fifo[can0_rx_fifo_head].rx_data[i] = receive_message.rx_data[i]; + } + can0_rx_fifo[can0_rx_fifo_head].rx_fi = receive_message.rx_fi; + can0_rx_fifo[can0_rx_fifo_head].fd_flag = receive_message.fd_flag; + can0_rx_fifo[can0_rx_fifo_head].fd_brs = receive_message.fd_brs; + can0_rx_fifo[can0_rx_fifo_head].fd_esi = receive_message.fd_esi; + /* head next */ + can0_rx_fifo_head = ((can0_rx_fifo_head + 1) % 32); + } else { + can0_rx_over_cnt++; + } + } else { + /* error */ + can0_rx_err_cnt++; + } +} +``` + +```c +/* CAN接收 */ +if (can0_rx_fifo_tail != can0_rx_fifo_head) { + /* print can rx data */ + printf("can rx data:\r\n"); + printf("fram format: %xH (0:standard, 4:extended)\r\n", can0_rx_fifo[can0_rx_fifo_tail].rx_ff); + printf("fram type: %xH (0:data, 2:remote)\r\n", can0_rx_fifo[can0_rx_fifo_tail].rx_ft); + printf("fd flag: %xH (0:can, 1:canfd)\r\n", can0_rx_fifo[can0_rx_fifo_tail].fd_flag); + printf("fd brs: %xH (0:no speed, 1:speed)\r\n", can0_rx_fifo[can0_rx_fifo_tail].fd_brs); + printf("stand id: %xH\r\n", can0_rx_fifo[can0_rx_fifo_tail].rx_sfid); + printf("extend id: %xH\r\n", can0_rx_fifo[can0_rx_fifo_tail].rx_efid); + printf("data len: %xH\r\n", can0_rx_fifo[can0_rx_fifo_tail].rx_dlen); + printf("data: "); + for (j = 0; (j < 64) && (j < can0_rx_fifo[can0_rx_fifo_tail].rx_dlen); j++) { + if ((j != 0) && (j % 8 == 0)) { + printf ("\r\n "); + } + printf("%02xH, ", can0_rx_fifo[can0_rx_fifo_tail].rx_data[j]); + } printf("\r\n"); + printf("\r\n"); + /* tail next */ + can0_rx_fifo_tail = (can0_rx_fifo_tail + 1) % 32; +} +``` + +### 2.6 测试CANFD发送 + +![CANFD发送1.JPG](figures/618b987d84fa1e658cf9c735d40ebc3a.jpg.webp) + +![CANFD发送2.JPG](figures/2df0b2d3e8939fb64a0337f6dfaad1fd.jpg.webp) + +### 2.7 测试CANFD接收 + +![CANFD接收1.JPG](figures/6bdc4abc116dde34226c376264a90630.jpg.webp) + +![CANFD接收2.JPG](figures/beda366a25e433bb5c45d510f08ad054.jpg.webp) + +### 2.8 测试CANFD加速发送 + +![CANFD加速发送1.JPG](figures/356487daa1b90eacf4b7aec4379ada69.jpg.webp) + +![CANFD加速发送2.JPG](figures/ee66e5811e07d2fe2f57b6dd0e53ed69.jpg.webp) + +### 2.9 测试CANFD加速接收 + +![CANFD加速接收1.JPG](figures/321dee167034832260864a187efe59eb.jpg.webp) + +![CANFD加速接收2.JPG](figures/16b626fb433f1081c0fd2ebfbad70660.jpg.webp) + +### 2.10 **代码** + +[GD32F527_CanFD_Test_v1.rar](https://club.rt-thread.org/file_download/90f50638a31dc73d) + +### 2.11 体会 +GD32F527的CAN外设支持CAN、CANFD和CANFD加速,把CAN外设配置为CANFD模式时,即可以发送普通CAN帧,也可以发送CANFD和CANFD加速帧,切换非常方便。接收也可以同时接收这3种CAN帧,通过标记识别很便捷。 +### 2.12 原文链接 + +原文链接:[RT-Thread-【GD32F527_EVAL】 CANFD测试RT-Thread问答社区 - RT-Thread](https://club.rt-thread.org/ask/article/25aa35c65c707ad8.html) + +## 3. GD32F527_EVAL RT-Thread CAN指南(吴艺彬) + +### 3.1 GD32F527_EVAL开发板资料例程下载 + +官网:https://www.gigadevice.com.cn/product/mcu/high-performance-mcus/gd32f5xx-series + +### 3.2 RT-Thread 仓库下载 + +```shell +git clone https://github.com/RT-Thread/rt-thread.git +``` + +### 3.3 准备工作 + +根据原理图把跳线帽JP35 JP36调整到can接口上,把JP21调整到串口上。 + +准备两条mini usb线用于连接串口和link。 + +### 3.4 CAN使用 + +找到对应板子的工程 + +![img](figures/202510142104811.png) + +打开ENV 拉取固件库软件包 + +```shell +pkgs --update +``` + +使能can接口,menuconfig + +![img](figures/202510142104812.png) + +![PixPin_2025-10-14_19-48-58](figures/202510142104813.png) + +生成MDK工程 + +``` +scons --target=mdk +``` + +### 3.5 例程源码 + +```c +#include +#include +#define CAN_DEV_NAME "can0" // The name of the CAN device +static rt_device_t can_dev; // CAN device handle +static struct rt_semaphore rx_sem; // Semaphore for message reception +// Callback function for CAN reception +static rt_err_t can_rx_callback(rt_device_t dev, rt_size_t size) +{ + // The CAN interrupt calls this callback when data is received. + // Release the semaphore to notify the receiving thread. + rt_sem_release(&rx_sem); + return RT_EOK; +} +static void can_rx_thread(void *parameter) +{ + rt_err_t res; + struct rt_can_msg rx_msg = {0}; + // Set the receive callback function + rt_device_set_rx_indicate(can_dev, can_rx_callback); +#ifdef RT_CAN_USING_HDR + // Example of configuring multiple hardware filters + struct rt_can_filter_item items[] = + { + // Filter 1: Match standard frames with IDs from 0x100 to 0x1FF. hdr_index will be -1. + RT_CAN_FILTER_ITEM_INIT(0x100, 0, 0, 0, 0x700, RT_NULL, RT_NULL), + // Filter 2: Match standard frames with IDs from 0x300 to 0x3FF. hdr_index will be -1. + RT_CAN_FILTER_ITEM_INIT(0x300, 0, 0, 0, 0x700, RT_NULL, RT_NULL), + // Filter 3: Exactly match standard frame with ID 0x211. hdr_index will be -1. + RT_CAN_FILTER_ITEM_INIT(0x211, 0, 0, 0, 0x7FF, RT_NULL, RT_NULL), + // Filter 4: Exactly match standard frame with ID 0x486 using a helper macro. hdr_index will be -1. + RT_CAN_FILTER_STD_INIT(0x486, RT_NULL, RT_NULL), + // Filter 5: Exactly match standard frame with ID 0x555 and explicitly assign it to filter bank #7. + // This uses direct struct initialization: {id, ide, rtr, mode, mask, hdr_bank}. + {0x555, 0, 0, 0, 0x7FF, 7} + }; + // Create the filter configuration structure with 5 active filters. + struct rt_can_filter_config cfg = {sizeof(items)/sizeof(items[0]), 1, items}; + // Set the hardware filters for the CAN device. + res = rt_device_control(can_dev, RT_CAN_CMD_SET_FILTER, &cfg); + RT_ASSERT(res == RT_EOK); +#endif + // Some drivers might require an explicit start command. + // This is driver-specific. + rt_uint32_t cmd_arg = 1; // Argument to enable the controller + res = rt_device_control(can_dev, RT_CAN_CMD_START, &cmd_arg); + RT_ASSERT(res == RT_EOK); + while (1) + { + // Block and wait for the semaphore, which is released by the receive callback. + rt_sem_take(&rx_sem, RT_WAITING_FOREVER); + // Read one frame of data from the CAN device's general message queue. + rx_msg.hdr_index = -1; + rt_device_read(can_dev, 0, &rx_msg, sizeof(rx_msg)); + // Print the received message's ID and data. + rt_kprintf("Received a message. ID: 0x%x, Data: ", rx_msg.id); + for (int i = 0; i < rx_msg.len; i++) + { + rt_kprintf("%02x ", rx_msg.data[i]); + } + rt_kprintf("\n"); + } +} +int can_sample(int argc, char *argv[]) +{ + rt_err_t res; + rt_thread_t thread; + char can_name[RT_NAME_MAX]; + // Allow specifying the CAN device name from the command line, e.g., "can_sample can2" + if (argc == 2) + { + rt_strncpy(can_name, argv[1], RT_NAME_MAX); + } + else + { + rt_strncpy(can_name, CAN_DEV_NAME, RT_NAME_MAX); + } + // Find the CAN device by name + can_dev = rt_device_find(can_name); + if (!can_dev) + { + rt_kprintf("find device %s failed!\n", can_name); + return -RT_ERROR; + } + // Initialize the receive semaphore + rt_sem_init(&rx_sem, "rx_sem", 0, RT_IPC_FLAG_FIFO); + // Open the CAN device in interrupt-driven TX/RX mode + res = rt_device_open(can_dev, RT_DEVICE_FLAG_INT_TX | RT_DEVICE_FLAG_INT_RX); + RT_ASSERT(res == RT_EOK); + // Create and start the data receiving thread + thread = rt_thread_create("can_rx", can_rx_thread, RT_NULL, 1024, 25, 10); + if (thread != RT_NULL) + { + rt_thread_startup(thread); + } + else + { + rt_kprintf("create can_rx thread failed!\n"); + return -RT_ERROR; + } + rt_kprintf("CAN device %s opened successfully.\n", can_name); + // --- Demonstrate Blocking Send --- + struct rt_can_msg blocking_msg = {0}; + blocking_msg.id = 0x78; + blocking_msg.ide = RT_CAN_STDID; + blocking_msg.rtr = RT_CAN_DTR; + blocking_msg.len = 8; + // The `nonblocking` flag is 0 by default for blocking mode. + for(int i = 0; i < 8; i++) blocking_msg.data[i] = i; + rt_kprintf("Attempting to send a message in BLOCKING mode...\n"); + if (rt_device_write(can_dev, 0, &blocking_msg, sizeof(blocking_msg)) == sizeof(blocking_msg)) + { + rt_kprintf("Blocking message sent successfully.\n"); + } + else + { + rt_kprintf("Blocking message send failed.\n"); + } + rt_thread_mdelay(100); // Wait a moment for clarity in the log + // --- Demonstrate Non-Blocking Send --- + struct rt_can_msg nonblocking_msg = {0}; + nonblocking_msg.id = 0x79; + nonblocking_msg.ide = RT_CAN_STDID; + nonblocking_msg.rtr = RT_CAN_DTR; + nonblocking_msg.len = 4; + nonblocking_msg.data[0] = 0xDE; + nonblocking_msg.data[1] = 0xAD; + nonblocking_msg.data[2] = 0xBE; + nonblocking_msg.data[3] = 0xEF; + nonblocking_msg.nonblocking = 1; // <-- Key: Set the non-blocking flag + rt_kprintf("Attempting to send a message in NON-BLOCKING mode...\n"); + if (rt_device_write(can_dev, 0, &nonblocking_msg, sizeof(nonblocking_msg)) == sizeof(nonblocking_msg)) + { + rt_kprintf("Non-blocking message was accepted (sent or enqueued).\n"); + } + else + { + rt_kprintf("Non-blocking send failed (buffer was full).\n"); + } + return res; +} +// Export the function to the MSH command line +MSH_CMD_EXPORT(can_sample, can device usage example); +``` + +编译烧录代码,这边使用HSCAN用来分析can的数据 + +![PixPin_2025-10-14_20-12-33](figures/202510142104814.png) + +在MSH中输入 can_sample。 + +就可以看到正常的输出 + +### 3.6 注意事项 + +请保证电源是5V输出 + +适配工作可以查看: + +https://github.com/RT-Thread/rt-thread/pull/10796 + +https://github.com/RT-Thread/rt-thread/pull/10737 + +### 3.7 原文链接 + +原文链接:[RT-Thread-GD32F527_EVAL RT-Thread CAN指南RT-Thread问答社区 - RT-Thread](https://club.rt-thread.org/ask/article/eea60f5bc6248fc0.html) + +# 十一、GD32F527上的SDIO实践(戴凌祥、熊治坤) + +## 1. 基于RT-Thread的GD32F527 SDIO评测(戴凌祥) + +### 1.1 SDIO接口 + +![schem.png](figures/d94cd89c7c48ad2cce49d478c3a64260.png.webp) + +💾测评对象:SDIO(最高支持48MHz 数据传输频率) + +连接模式:支持4位宽SD模式,理论传输速率更高 +应用目标:为后续文件系统、数据存储等应用提供硬件基础 + +### 1.2 硬件清单 📋 +* GD32F527I-EVAL开发板 x1 +* MicroSD卡(128MB、512MB、32GB) x3 +* Mini usb、DC电源线(5V) x 1 +* Jlink调试器(可选,板载GDLink) * 1 + +### 1.3 软件环境准备🛠️ + +本次开发采用RT-Thread Env工具 + MDK5的组合,因为我比较习惯KEIL的开发环境,所以没有用RT-Thread Studio,感兴趣的小伙伴可以去RT-Thread的文档中心找到相应的用户手册,RT-Thread给我的感觉对新手还是特别友好的,我也是第一次接触RT-Thread. +RT-Thread文档中心:https://www.rt-thread.org/document/site/#/ + +#### 1.3.1 基础软件环境 + +* 操作系统: Windows 10/11 +* 开发IDE: Keil MDK5 (ARM Compiler) +* 构建工具: RT-Thread Env 工具 +* 源码基础: GD32F527I-EVAL BSP包 (RT-Thread GitHub仓库) + +#### 1.3.2 工程目录结构准备 + +获取env环境: https://www.rt-thread.org/download.html#download-rt-thread-env-tool + +```shell +# 在Env环境中获取BSP +$ git clone https://github.com/RT-Thread/rt-thread.git +``` + +#### 1.3.3 生成MDK5工程 + +打开Env环境,执行以下命令: + +```shell +$ set rt_path="E:/xxx/rt-thread/bsp/gd32/arm/gd32527I-eval" #xxx前面是你自己的路径 +$ cd %rt_path% #进入工程目录 +$ scons dist --project-name=gd32f527_eval #打包工程 +$ cd dist/gd32f527_eval +$ scons --target=mkd5 #生成mdk5工程 +``` + +#### 1.3.4 Env环境配置 - 核心步骤 🔧 + +* 菜单配置:运行 menuconfig 命令,进入图形化配置界面 + +* 开启SDIO驱动: + +— 进入 Hardware Drivers Config → On-chip Peripheral Drivers → Enable SDIO + +![menu_sdio.png](figures/e7021f7b30d8a731254d5d05f4115b54.png.webp) + +— 进入 RT-Thread Components → Device Drivers → Using SD/MMC device drivers(这一项在启用SDIO以后似乎是默认打开的) + +![menu_sddevice.png](figures/2657c28304f01daee344e73607b5d61c.png) + +* 开启文件系统: + +— 进入 RT-Thread Components → DFS: device virtual file system → Enable DFS +— 选择 ElmChan FatFs 作为文件系统 + +![menu_dfs.png](figures/7b8594a0affb04576d3c2c734dcd7f2a.png) + +— 每次配置完菜单,需要重新运行一下`scons —target=mdk5`命令 + +### 1.4 SDIO驱动移植与适配 🔧 + +* RT-Thread SD卡驱动架构 其实就是I/O 设备模型框架里面的一种 + +![io设备模型.png](figures/c695004bf50ed387359e82b4253673cc.png.webp) + +RT-Thread其实已经把IO设备管理层、设备驱动框架层、设备驱动层都写好了。 +使用设备的流程如下: + +![usage.png](figures/9f1c486e1574f92db4ef8de0cea19caa.png.webp) + +但是实际需要我们做的只是在应用层调用接口,因为RT-Thread在初始化的时候已经帮我们注册了设备: + +![sdio_register.png](figures/e98149a0ce2bf29017a83610c69a6b56.png.webp) + +我们打开串口助手,我用的是electerm,可以看到RT-Thread的启动日志。 + +![rt_init.png](figures/067b98f19920dea87052aaa61bd36090.png.webp) + +因为我修改了rt_sdcard_control函数打印SD卡的信息,所以我们也可以看到SD卡的信息 + +### 1.5 虚拟文件系统🗂️ + +* 打开menuconfig,进入我们的RT-Thread Components->DFS:device virtual file system使能我们的DFS虚拟文件系统 + 重新生成工程以后,我们的虚拟文件系统就使能了,如果SD卡没有被格式化成指定文件系统,需要先使用mkfs命令格式化一下SD卡,然后再挂载我们的文件系统,RT-Thread官方文档有详细说明: + +![mkfs.png](figures/eea209e5cbca66ea9263bdfc01489c5e.png.webp) + +到此,我们的虚拟文件系统已经移植完毕,打开我们的串口终端,进行写入文件和读取文件内容的测试 + +![rt_rw.png](figures/241334761618523f528f28b8f7d12473.png) + +### 1.6 心得体会 + +我是第一次接触RT-Thread,给我的感觉是RT-Thread设备和驱动做的很好,是我喜欢的封装类型,只不过在某些平台相应的bsp还没有完善。我玩过一点Linux,它的设备模型借鉴了Linux,把各个硬件外设都归为设备一类,先在Drivers里面写好设备驱动,再去rt_device_regitser注册我们的设备,后面再通过rt_device_find查找设备,然后再是init,open,close等函数。所有的硬件外设都是我们的设备类的子类,不管你是UART、IIC、SPI还是SDIO,都具有设备属性。 +RT-Thread里面提供的DFS太方便了,都不用自己去找FATFS文件系统来移植,赞! + +### 1.7 源码链接 + +* https://gitee.com/dai-lingxiang/rtthread_gd32f527_sdio_test.git + +### 1.8 视频链接 + +* https://www.bilibili.com/video/BV1HnxUzWEwk + +### 1.9 原文链接 + +原文链接:[RT-Thread-基于RT-Thread的GD32F527 SDIO评测RT-Thread问答社区 - RT-Thread](https://club.rt-thread.org/ask/article/0d7bbb7c0032d19e.html) + +## 2. 小白从0到1手把手基于RT-Thread-5.2.2移植GD32F527i-EVAL的SDIO和DFS文件系统及验证(熊治坤) + +### 2.1 移植目标 + +1-建立RT-THread开发环境,基于ENV+Keil; +2-完成SDIO的SD(TF)卡驱动移植; +3-完成基于SD(TF)卡的文件系统移植; +4-完成TF卡的挂载、文件建立、文件读写等测试。 + +### 2.2 GD32F527I-EVAL硬件 + +官方说明如下: +https://www.gigadevice.com.cn/product/mcu/high-performance-mcus/gd32f5xx-series + +GD32F5系列高性能MCU具备显著扩容的存储空间、优异的处理能效和丰富的接口资源,该系列MCU符合系统级IEC61508 SC3(SIL2/SIL3)功能安全标准,并且提供完整的软硬件安全方案,能够满足工业市场对高可靠性和高安全性的需求。全面适配于能源电力、光伏储能、工业自动化、PLC、网络通讯设备、图形显示等应用场景。 +GD32F5 系列 MCU 搭载 RT-Thread,具备出色的性能与处理能力。该系列基于强劲的 Arm® Cortex®-M33 内核,最高可配备 7.5MB Flash 与 1MB SRAM,并支持 USB、I2C、ETH、CAN、LCD 等多种外设接口。依托 RT-Thread 实时内核,系统实现高效的处理器抽象与实时调度,结合丰富的设备驱动与中间件组件,为复杂算法运算和多任务处理提供强大算力,在高负载场景下依旧保持稳定高效运行。 + +### 2.3 本次开发需要的硬件管脚和接口 + +#### 2.3.1 SD卡管脚使用: + +![screenshot_image.png](figures/8aec24eed73fe6c7fb1bc5358a27097e.png.webp) + +#### 2.3.2 LED灯控制管脚: + +![screenshot_image.png](figures/15af186db81a92b3f8b0308cb4d9fa86.png.webp) + +#### 2.3.3 串口管脚: + +![screenshot_image.png](figures/3c8e02ec1a2e76015843aad6ba862db9.png.webp) + +### 2.4 代码git clone + +这个直接clone官方的仓库即可。这个过程可能十分漫长。由于我的网速等原因。下载了几十次,最终才成功。总之,有可能非常的慢。我这里一个多星期才下载成功。 +不要放弃,总会成功的。 +代码下载成功后,拷贝一份重新命名即可。防止出问题哦。 + +![screenshot_image.png](figures/61af0d35b799ea9f7781d0130f3cc462.png.webp) + +### 2.5 ENV配置 + +配置过程并不复杂,但是参数有可能一次配置不正确。 +编译过程可能会有很多提示错误,错误的过程这里就不再展示。 +这里只把修改的地方,截图分享出来,直接照搬就行: + +![screenshot_image.png](figures/0e2058426337f396274540d85bcc63e3.png.webp) + +![screenshot_image.png](figures/768d263bae77e3e8df70ed193aa4c2d1.png.webp) + +![screenshot_image.png](figures/15393c0220a0efddd7e160b1243016ac.png.webp) + +![screenshot_image.png](figures/4568470b225d996eb5e912e15951037c.png.webp) + +![screenshot_image.png](figures/18b4b1b193019c378b300b1806465c7a.png.webp) + +![screenshot_image.png](figures/767ed45791951976af8c06d8648dfa01.png.webp) + +配置完成后记得进行更新哦。 + +![screenshot_image.png](figures/3153ddb66070e5948e67cea2839d1e11.png.webp) + +![screenshot_image.png](figures/1faa7ec5c47a04140bcd716d3c4cbce6.png.webp) + +![screenshot_image.png](figures/fe7f385fccf4934e17060b0e854d9a8b.png.webp) + +### 2.6 MDK配置 + +若是使用其它配置可能会有编译报错哦。建议如下进行配置: + +![screenshot_image.png](figures/b36058e2fc12afee5f2659695ac5796a.png.webp) + +![screenshot_image.png](figures/f7ef1a13d45e2fd802cb672705d5eab7.png.webp) + +### 2.7 drv_sdio.c修改 + +编译可能会报错,我这里进行了如下修改: + +![screenshot_image.png](figures/90201352a4ff0e66e03476953e609322.png.webp) + +### 2.8 编译代码成功提示 + +![screenshot_image.png](figures/1acbe569999f00a5f70e359d05482fa8.png.webp) + +### 2.9 串口输出: + +![screenshot_image.png](figures/aa3e9dbe7b44724ca68363adb54c781c.png.webp) + +可以看到SD0了。成功的可以进行下一步了。 + +### 2.10 main.c代码修改与优化 + +这里经过验证和修改,以下代码可以正常运行: + +```c +#include +#include +#include +#include +#include +/* defined the LED1 pin: PE3 */ +#define LED1_PIN GET_PIN(E, 3) +#define DBG_TAG "main" +#define DBG_LVL DBG_LOG +#include +#define SD_MOUNT_POINT "/" +#define TEST_FILE_NAME "/rt_sd_test.txt" +#define TEST_CONTENT "RT-Thread SDIO Test: Write Success!\n" +static int onboard_sdcard_mount(void) +{ + if (dfs_mount("sd0", "/", "elm", 0, 0) == RT_EOK) + { + LOG_I("SD card mount to '/'"); + } + else + { + LOG_E("SD card mount to '/' failed!"); + } + return RT_EOK; +} +static rt_err_t sdcard_write_file(void) +{ + FILE *fp = fopen(TEST_FILE_NAME, "w"); + if (!fp) + { + rt_kprintf("Open %s failed! Errno: %d\n", TEST_FILE_NAME, errno); + return -RT_ERROR; + } + fwrite(TEST_CONTENT, 1, strlen(TEST_CONTENT), fp); + rt_kprintf("Write success: %s", TEST_CONTENT); + fclose(fp); + return RT_EOK; +} +static rt_err_t sdcard_read_file(void) +{ + FILE *fp = fopen(TEST_FILE_NAME, "r"); + char buf[128] = {0}; + if (!fp) + { + rt_kprintf("Open %s failed! Errno: %d\n", TEST_FILE_NAME, errno); + return -RT_ERROR; + } + fread(buf, 1, sizeof(buf)-1, fp); + rt_kprintf("Read success: %s", buf); + fclose(fp); + return RT_EOK; +} +static rt_err_t sdcard_unmount(void) +{ + rt_err_t ret = dfs_unmount(SD_MOUNT_POINT); + rt_kprintf(ret == RT_EOK ? "SD unmounted safely\n" : "Unmount failed! Err: %d\n", ret); + return ret; +} +int main(void) +{ + /* set LED1 pin mode to output */ + rt_pin_mode(LED1_PIN, PIN_MODE_OUTPUT); + rt_thread_mdelay(2000); + onboard_sdcard_mount(); + rt_thread_mdelay(500); + rt_kprintf("---write begin!\n"); + sdcard_write_file(); + rt_thread_mdelay(500); + rt_kprintf("---read begin!\n"); + sdcard_read_file(); + while (1) + { + rt_pin_write(LED1_PIN, PIN_HIGH); + rt_thread_mdelay(500); + rt_pin_write(LED1_PIN, PIN_LOW); + rt_thread_mdelay(500); + } + return 0; +} +``` + +### 2.11 实验验证 + +#### 2.11.1 代码编译成功: + +![screenshot_image.png](figures/9d1964e84914f5a7f621c4f156c41a30.png.webp) + +#### 2.11.2 串口输出: + +![screenshot_image.png](figures/757fc134e6c52adbcdd53299b6578907.png.webp) + +#### 2.11.3 ps指令 + +![screenshot_image.png](figures/9628c68ec87f14a0ad2a538941fb89c3.png.webp) + +#### 2.11.4 Help指令 + +![screenshot_image.png](figures/a90af5689f2c20565bb7cdf5ec2a1320.png.webp) + +#### 2.11.5 Ls指令 + +![screenshot_image.png](figures/d7f0feb2bc3da72993e3ed308e894dc8.png.webp) + +#### 2.11.6 sd目录和文件内容对比验证 + +![screenshot_image.png](figures/b176eaefe333731f002ecd9fd957732b.png.webp) + +### 2.12 总结 + +看起来容易做起来难。这次非常感谢群友热心帮助。 +过程虽然艰难,但是完成后的成功还是令人非常愉悦的。 +目前至少完成了基本的功能,这里分享出来希望能够期待抛砖引玉的作用。 +也希望大家少走弯路,至少我走过的坑大家不要再耽误时间了。 + +我这个编译器6.24版本导致无法进行跳转,希望后来的大佬解决一下。 + +![screenshot_image.png](figures/74cea2f706b552a9a09e144c00eb7b17.png) + +![screenshot_image.png](figures/a4c9f0517c2715f61afd9631476480e6.png) + +由于这个部分是灰色的,导致我遇到问题调试起来非常麻烦啊。 + +![screenshot_image.png](figures/4cf9f8e7a3449f65e1f4099486fcfe5f.png.webp) + +时间仓促,本人水平有限,不足之处请多包涵,也请各位不吝赐教。 + +### 2.13 原文链接 + +原文链接:[RT-Thread-小白从0到1手把手基于RT-Thread-5.2.2移植GD32F527i-EVAL的SDIO和DFS文件系统及验证RT-Thread问答社区 - RT-Thread](https://club.rt-thread.org/ask/article/0bcc27a01d282f06.html) + +# 十二、GD32F527上的USB-D实践(吕阳、洪小玲) + +## 1. 【GD32F527I_EVAL】 基于 RT-Thread 和GD32F527的 USB MSC 功能(洪小玲) + +### 1.1 GD32的 USB库 + +GD32的 USB 库已经非常完整,它包含了 +驱动层 drvusb.c -硬件抽象层 +设备核心:usbd_.c -USB设备栈协议 +MSC 类:usbdmsc*.c 大容量存储设备 +我们不需要重新实现 USB 协议栈,只需要将 GD32的 USB 库与 RT-Thread 的 USB 设备框架正确对接 + +### 1.2 项目架构设计 + +``` +applications/ +├── msc_sd_card.c # MSC SD卡应用层(待完善) +├── main.c +drivers/ +├── drv_usb.c # USB驱动层 +├── drv_usb.h +├── drv_sdio.c # SD卡驱动层 +├── drv_sdio.h +packages/ +└── gd32f5xx_usb_lib/ # GD32 USB库 +``` + +### 1.3 配置和集成 + +#### 1.3.1 drv_usb.c + +SConscript构建配置 + +```python +# add pwm drivers. +if GetDepend('RT_USING_PWM'): + src += ['drv_pwm.c'] +# add can drivers. +if GetDepend('RT_USING_CAN'): + src += ['drv_can.c'] +# add sdram drivers. +if GetDepend('BSP_USING_SDRAM'): + src += ['drv_sdram.c'] +# add sdram drivers. +if GetDepend('RT_USING_USB_DEVICE'): + src += ['drv_usb.c'] +path = [cwd] +group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path) +Return('group') +``` + +#### 1.3.2 board 文件夹下的 sconscript 修改 + +```python +import os +import rtconfig +from building import * +Import('SDK_LIB') +cwd = GetCurrentDir() +# add general drivers +src = Split(''' +board.c +gd32f527i_eval.c +''') +path = [cwd] +CPPDEFINES = ['GD32F527'] +group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path, CPPDEFINES = CPPDEFINES) +Return('group') +``` + +#### 1.3.3 board 文件夹下的 的 Kconfig配置 + +````python + config BSP_USING_USBD + bool "Enable USB Device" + select RT_USING_USB_DEVICE + default n + menuconfig BSP_USING_USBH + bool "Enable USB Host" + select RT_USING_USB_HOST + default n + if BSP_USING_USBH + menuconfig RT_USBH_MSTORAGE + bool "Enable Udisk Drivers" + default n + if RT_USBH_MSTORAGE + config UDISK_MOUNTPOINT + string "Udisk mount dir" + default "/" + endif + endif +```` + +#### 1.3.4 GD32 USB 库 sconscript 修改,D:\rtt_tool\rt-thread-master\bsp\gd32\arm\gd32527I-eval\packages\gd32-arm-series-latest\GD32F5xx sconscript +```python +if GetDepend(['BSP_USING_USBD']) or GetDepend(['BSP_USING_USBH']): + src += ['GD32F5xx_usb_library/device/class/msc/source/usbd_msc_bbb.c'] + src += ['GD32F5xx_usb_library/device/class/msc/source/usbd_msc_core.c'] + src += ['GD32F5xx_usb_library/device/class/msc/source/usbd_msc_scsi.c'] + src += ['GD32F5xx_usb_library/device/core/source/usbd_core.c'] + src += ['GD32F5xx_usb_library/device/core/source/usbd_enum.c'] + src += ['GD32F5xx_usb_library/device/core/source/usbd_transc.c'] + src += ['GD32F5xx_usb_library/driver/source/drv_usb_core.c'] + src += ['GD32F5xx_usb_library/driver/source/drv_usb_dev.c'] + src += ['GD32F5xx_usb_library/driver/source/drv_usbd_int.c'] +path = [ + cwd, + cwd + '/GD32F5xx_standard_peripheral/Include' +] +if GetDepend(['BSP_USING_USBD']) or GetDepend(['BSP_USING_USBH']): + path += [ + cwd + '/GD32F5xx_usb_library/device/class/msc/Include', + cwd + '/GD32F5xx_usb_library/device/core/Include', + cwd + '/GD32F5xx_usb_library/driver/Include', + cwd + '/GD32F5xx_usb_library/ustd/class/msc', + cwd + '/GD32F5xx_usb_library/ustd/common/' + ] +CPPDEFINES = ['USE_STDPERIPH_DRIVER'] +``` + +#### 1.3.5 drv_usb.c 的实现 + +```c +#include +#include +#include +#include +#include "gd32f5xx.h" +#ifdef RT_USING_USB_DEVICE +#define USB_LOG(fmt, ...) rt_kprintf("[USB] " fmt, ##__VA_ARGS__) +/* 包含GD32 USB库头文件 */ +#include "drv_usb_hw.h" +#include "drv_usb_core.h" +#include "drv_usbd_int.h" +#include "usbd_core.h" +#include "usbd_msc_core.h" +/* 添加缺失的函数声明 */ +void usb_mdelay(uint32_t n); +void usb_udelay(uint32_t n); +void pmu_to_deepsleepmode(uint32_t ldo, uint32_t lowdrive, uint8_t deepsleepmodecmd); +/* 实现缺失的函数 */ +void usb_mdelay(uint32_t n) +{ + rt_thread_mdelay(n); +} +void usb_udelay(uint32_t n) +{ + volatile uint32_t count; + for (count = 0; count < (n * 10); count++) { + __NOP(); + } +} +void pmu_to_deepsleepmode(uint32_t ldo, uint32_t lowdrive, uint8_t deepsleepmodecmd) +{ + USB_LOG("Enter deep sleep mode"); +} +/* 添加usbd_mem_fops的定义 */ +#include "usbd_msc_mem.h" +/* 存储操作函数 */ +static int8_t storage_init(uint8_t lun) { + USB_LOG("Storage init, LUN: %d", lun); + return 0; +} +static int8_t storage_is_ready(uint8_t lun) { + return 1; +} +static int8_t storage_is_write_protected(uint8_t lun) { + return 0; +} +static int8_t storage_read(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len) { + USB_LOG("Storage read, LUN: %d, addr: %lu, len: %d", lun, blk_addr, blk_len); + rt_memset(buf, 0, blk_len * 512); + return 0; +} +static int8_t storage_write(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len) { + USB_LOG("Storage write, LUN: %d, addr: %lu, len: %d", lun, blk_addr, blk_len); + return 0; +} +static int8_t storage_get_max_lun(void) { + return 0; +} +const int8_t storage_inquiry_data[] = { + 0x00, 0x80, 0x00, 0x01, 0x1F, 0x00, 0x00, 0x00, + 'G', 'D', '3', '2', ' ', ' ', ' ', ' ', + 'U', 'S', 'B', ' ', 'M', 'S', 'C', ' ', + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + '1', '.', '0', '0' +}; +usbd_mem_cb USBD_Internal_Storage_fops = { + .mem_init = storage_init, + .mem_ready = storage_is_ready, + .mem_protected = storage_is_write_protected, + .mem_read = storage_read, + .mem_write = storage_write, + .mem_maxlun = storage_get_max_lun, + .mem_inquiry_data = {(uint8_t *)storage_inquiry_data}, + .mem_block_size = {512}, + .mem_block_len = {1024} +}; +usbd_mem_cb *usbd_mem_fops = &USBD_Internal_Storage_fops; +/* USB设备实例 */ +static usb_core_driver usb_device_dev; +/* RT-Thread USB设备控制器 */ +static struct udcd usb_udcd; +static struct ep_id ep_pool[8]; +/* 预定义的端点映射 - 参考ST的实现方式 */ +static const struct { + rt_uint8_t logical_ep; + rt_uint8_t physical_ep; +} ep_mapping[] = { + {0x00, 0}, /* EP0 OUT */ + {0x80, 0}, /* EP0 IN */ + {0x01, 1}, /* EP1 OUT */ + {0x81, 1}, /* EP1 IN */ + {0x02, 2}, /* EP2 OUT */ + {0x82, 2}, /* EP2 IN */ +}; +/* 端点分配状态 */ +static rt_bool_t ep_allocated[8] = {0}; +/* 查找物理端点 */ +static rt_uint8_t find_physical_ep(rt_uint8_t logical_ep) +{ + for (int i = 0; i < sizeof(ep_mapping)/sizeof(ep_mapping[0]); i++) { + if (ep_mapping[i].logical_ep == logical_ep) { + return ep_mapping[i].physical_ep; + } + } + return 0xFF; /* 未找到 */ +} +/* 关键修复:端点分配函数 */ +static rt_err_t gd32_ep_assign(udcd_t dcd, uep_t ep) +{ + rt_uint8_t ep_addr = EP_ADDRESS(ep); + rt_uint8_t phys_ep = find_physical_ep(ep_addr); + USB_LOG("EP assign: logical=0x%02X, physical=%d\n", ep_addr, phys_ep); + if (phys_ep == 0xFF) { + USB_LOG("No physical EP available for logical EP 0x%02X\n", ep_addr); + return -RT_ERROR; + } + if (ep_allocated[phys_ep]) { + USB_LOG("Physical EP %d already allocated\n", phys_ep); + return -RT_ERROR; + } + /* 标记端点已分配 */ + ep_allocated[phys_ep] = RT_TRUE; + /* 设置端点的物理地址 */ + ep->ep_desc->bEndpointAddress = ep_addr; + USB_LOG("EP assigned successfully: logical=0x%02X -> physical=%d\n", ep_addr, phys_ep); + return RT_EOK; +} +/* 简化的DCD操作函数 */ +static rt_err_t gd32_dcd_set_address(rt_uint8_t address) +{ + USB_LOG("Set address: 0x%02X\n", address); + usbd_addr_set(&usb_device_dev, address); + return RT_EOK; +} +static rt_err_t gd32_dcd_set_config(rt_uint8_t address) +{ + USB_LOG("Set config: 0x%02X\n", address); + return RT_EOK; +} +static rt_err_t gd32_dcd_ep_set_stall(rt_uint8_t address) +{ + USB_LOG("EP set stall: 0x%02X\n", address); + usbd_ep_stall(&usb_device_dev, address); + return RT_EOK; +} +static rt_err_t gd32_dcd_ep_clear_stall(rt_uint8_t address) +{ + USB_LOG("EP clear stall: 0x%02X\n", address); + usbd_ep_stall_clear(&usb_device_dev, address); + return RT_EOK; +} +static rt_err_t gd32_dcd_ep_enable(struct uendpoint *ep) +{ + rt_uint8_t ep_addr = EP_ADDRESS(ep); + rt_uint16_t mps = EP_MAXPACKET(ep); + rt_uint8_t ep_type = ep->ep_desc->bmAttributes & 0x03U; + USB_LOG("EP enable: addr=0x%02X, mps=%d, type=%d\n", ep_addr, mps, ep_type); + /* 使用GD32库配置端点 */ + usb_desc_ep ep_desc = { + .header = { + .bLength = sizeof(usb_desc_ep), + .bDescriptorType = USB_DESCTYPE_EP + }, + .bEndpointAddress = ep_addr, + .bmAttributes = ep_type, + .wMaxPacketSize = mps, + .bInterval = 0 + }; + usbd_ep_setup(&usb_device_dev, &ep_desc); + return RT_EOK; +} +static rt_err_t gd32_dcd_ep_disable(struct uendpoint *ep) +{ + rt_uint8_t ep_addr = EP_ADDRESS(ep); + rt_uint8_t phys_ep = find_physical_ep(ep_addr); + USB_LOG("EP disable: 0x%02X (physical=%d)\n", ep_addr, phys_ep); + if (phys_ep != 0xFF) { + ep_allocated[phys_ep] = RT_FALSE; + } + usbd_ep_clear(&usb_device_dev, ep_addr); + return RT_EOK; +} +static rt_ssize_t gd32_dcd_ep_read_prepare(rt_uint8_t address, void *buffer, rt_size_t size) +{ + USB_LOG("EP read prepare: 0x%02X, size=%d\n", address, size); + return (rt_ssize_t)size; +} +static rt_ssize_t gd32_dcd_ep_read(rt_uint8_t address, void *buffer) +{ + USB_LOG("EP read: 0x%02X\n", address); + return 0; +} +static rt_ssize_t gd32_dcd_ep_write(rt_uint8_t address, void *buffer, rt_size_t size) +{ + USB_LOG("EP write: 0x%02X, size=%d\n", address, size); + return (rt_ssize_t)size; +} +static rt_err_t gd32_dcd_ep0_send_status(void) +{ + USB_LOG("EP0 send status\n"); + return RT_EOK; +} +static rt_err_t gd32_dcd_suspend(void) +{ + USB_LOG("USB suspend\n"); + return RT_EOK; +} +static rt_err_t gd32_dcd_wakeup(void) +{ + USB_LOG("USB wakeup\n"); + return RT_EOK; +} +/* DCD操作结构 */ +static struct udcd_ops dcd_ops = { + gd32_dcd_set_address, + gd32_dcd_set_config, + gd32_dcd_ep_set_stall, + gd32_dcd_ep_clear_stall, + gd32_dcd_ep_enable, + gd32_dcd_ep_disable, + gd32_dcd_ep_read_prepare, + gd32_dcd_ep_read, + gd32_dcd_ep_write, + gd32_dcd_ep0_send_status, + gd32_dcd_suspend, + gd32_dcd_wakeup +}; +/* 硬件初始化 */ +static void usb_hardware_init(void) +{ + USB_LOG("Configuring USB hardware...\n"); + /* 使能GPIOA时钟 */ + rcu_periph_clock_enable(RCU_GPIOA); + /* 重要:先使能IRC48M时钟 */ + USB_LOG("Enabling IRC48M clock...\n"); + rcu_osci_on(RCU_IRC48M); + /* 等待IRC48M稳定 */ + int wait_count = 0; + while (rcu_flag_get(RCU_FLAG_IRC48MSTB) == RESET) { + rt_thread_mdelay(1); + wait_count++; + if (wait_count > 100) { + USB_LOG("Warning: IRC48M stabilization timeout\n"); + break; + } + } + if (rcu_flag_get(RCU_FLAG_IRC48MSTB)) { + USB_LOG("IRC48M clock ready after %d ms\n", wait_count); + } else { + USB_LOG("IRC48M clock failed to stabilize\n"); + return; /* 如果时钟没有就绪,直接返回 */ + } + /* 使能USB时钟 */ + rcu_periph_clock_enable(RCU_USBFS); + /* 配置USB时钟源为IRC48M */ + rcu_ck48m_clock_config(RCU_CK48MSRC_IRC48M); + USB_LOG("USB clock source configured to IRC48M\n"); + /* 配置USB引脚 */ + gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_11 | GPIO_PIN_12); + gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_11 | GPIO_PIN_12); + gpio_af_set(GPIOA, GPIO_AF_10, GPIO_PIN_11 | GPIO_PIN_12); + gpio_mode_set(GPIOD, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_13); + gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_13); + gpio_bit_set(GPIOD, GPIO_PIN_13); + USB_LOG("USB pins configured: PA11(D-), PA12(D+)\n"); + /* 配置USB中断优先级 */ + nvic_irq_enable(USBFS_IRQn, 2, 0); + USB_LOG("USB hardware initialized successfully\n"); +} + void USBFS_IRQHandler(void) + { + rt_interrupt_enter(); + usbd_isr(&usb_device_dev); + rt_interrupt_leave(); + } +/* 初始化GD32 USB库 */ +static void gd32_usb_library_init(void) +{ + USB_LOG("Initializing GD32 USB library...\n"); + /* 使用GD32官方库初始化USB设备 */ + extern usb_desc gd32_msc_desc; + extern usb_class_core gd32_msc_class; + usbd_init(&usb_device_dev, USB_CORE_ENUM_FS, &gd32_msc_desc, &gd32_msc_class); + USB_LOG("GD32 USB library initialized\n"); +} +/* USB设备初始化 */ +static void usb_device_init(void) +{ + /* 初始化USB硬件 */ + usb_hardware_init(); + /* 初始化GD32 USB库 */ + gd32_usb_library_init(); + USB_LOG("USB device initialized\n"); +} +/* RT-Thread设备初始化 */ +static rt_err_t usbd_driver_init(rt_device_t dev) +{ + usb_device_init(); + return RT_EOK; +} +static rt_err_t usbd_control(rt_device_t dev, int cmd, void *args) +{ + return RT_EOK; +} +/* 简化版本:直接使用GD32 USB库,不通过RT-Thread USB设备栈 */ +/* 添加定时器回调函数 */ +static void usb_status_timer_callback(void *parameter) +{ + static int count = 0; + if (++count % 10 == 0) { // 每10秒打印一次状态 + USB_LOG("USB Status: addr=0x%02X, state=%d\n", + usb_device_dev.dev.dev_addr, + usb_device_dev.dev.cur_status); + } +} +int rt_hw_usbd_init(void) +{ + USB_LOG("=== Starting Direct USB MSC Initialization ===\n"); + /* 初始化硬件 */ + usb_hardware_init(); + /* 直接使用GD32官方的MSC描述符和类驱动 */ + USB_LOG("Initializing GD32 USB MSC directly...\n"); + /* 使用GD32官方的MSC描述符和类驱动 */ + extern usb_desc gd32_msc_desc; + extern usb_class_core gd32_msc_class; + usbd_init(&usb_device_dev, USB_CORE_ENUM_FS, &gd32_msc_desc, &gd32_msc_class); + /* 启用USB连接 */ + usbd_connect(&usb_device_dev); + USB_LOG("=== Direct USB MSC Initialization Complete ===\n"); + USB_LOG("USB MSC device should now be available\n"); + /* 添加USB状态监控 */ + static struct rt_timer usb_status_timer; + rt_timer_init(&usb_status_timer, "usb_stat", + usb_status_timer_callback, + RT_NULL, + 1000, RT_TIMER_FLAG_PERIODIC); + rt_timer_start(&usb_status_timer); + return RT_EOK; +} +INIT_DEVICE_EXPORT(rt_hw_usbd_init); +#endif +``` + +#### 1.3.6 日志输出 + +```shell + \ | / +- RT - Thread Operating System + / | \ 5.2.2 build Oct 22 2025 16:43:15 + 2006 - 2024 Copyright by RT-Thread team +[USB] === Starting Direct USB MSC Initialization === +[USB] Configuring USB hardware... +[USB] Enabling IRC48M clock... +[USB] IRC48M clock ready after 1 ms +[USB] USB clock source configured to IRC48M +[USB] USB pins configured: PA11(D-), PA12(D+) +[USB] USB hardware initialized successfully +[USB] Initializing GD32 USB MSC directly... +[USB] === Direct USB MSC Initialization Complete === +[USB] USB MSC device should now be available +msh /> +msh />[USB] USB Status: addr=0x00, state=1 +[USB] USB Status: addr=0x00, state=1 +[USB] Storage init, LUN: 0[USB] USB Status: addr=0x09, state=3 +[USB] USB Status: addr=0x09, state=3 +[USB] USB Status: addr=0x09, state=3 +[USB] USB Status: addr=0x09, state=3 +``` + +### 1.4 搭建环境及效果展示 +搭建环境 + +![搭建环境.jpg](figures/d2f38aea9e5d229b5e5a8a82381d6d09.jpg.webp) + +* 运行结果,通过评估板通过USB线连接电脑,被识别为大容量设备 + +![USB大容量设备.png](figures/2b9c505eae774068c95deb77b8919f45.png.webp) + +### 1.5 原文链接 + +原文链接:[RT-Thread-【GD32F527I_EVAL】 基于 RT-Thread 和GD32F527的 USB MSC 功能RT-Thread问答社区 - RT-Thread](https://club.rt-thread.org/ask/article/2f1ef58744ba7d25.html) + +## 2. 【GD32F527_EVAL】USB 驱动移植 和 USB CDC Device 接入PC实验(吕阳) + +### 2.1 已有资料梳理 + +#### 2.1.1 GD32F5xx_usb_library/ + +``` +├── driver/ # USB底层硬件驱动 +│ ├── Include/ +│ │ ├── drv_usb_core.h # USB核心驱动 +│ │ ├── drv_usb_dev.h # USB Device驱动 +│ │ ├── drv_usb_hw.h # USB硬件配置 +│ │ ├── drv_usb_regs.h # USB寄存器定义 +│ │ └── drv_usbd_int.h # USB Device中断 +│ └── Source/ +│ ├── drv_usb_core.c +│ ├── drv_usb_dev.c +│ └── drv_usbd_int.c +│ +├── device/ # USB Device功能层 +│ ├── core/ # Device核心 +│ │ ├── Include/ +│ │ │ ├── usbd_core.h +│ │ │ ├── usbd_enum.h # 枚举处理 +│ │ │ └── usbd_transc.h # 传输处理 +│ │ └── Source/ +│ │ ├── usbd_core.c +│ │ ├── usbd_enum.c +│ │ └── usbd_transc.c +│ │ +│ └── class/ # Device类驱动 +│ ├── cdc/ # 虚拟串口 +│ ├── msc/ # 大容量存储 +│ ├── hid/ # 人机接口 +│ ├── audio/ # 音频 +│ ├── dfu/ # 固件升级 +│ ├── iap/ # 在线编程 +│ └── printer/ # 打印机 +│ +└── ustd/ # USB标准定义 +├── common/usb_ch9_std.h # USB规范定义 +└── class/ # 类标准定义 +``` + +位置 - +`./gd32527I-eval/packages/gd32-arm-series-latest/GD32F5xx/、` + +备注 - + +* 这是GD官方固件库 +* 作用:提供底层硬件访问的HAL层 +* 包含:标准外设库和USB库 +* 特点:直接操作寄存器,不依赖操作系统 + +#### 2.1.2 RTT官方/社区已完成vs未完成 + +**已完成移植的驱动:** + +1. drv_adc - ADC驱动 +2. drv_can - CAN驱动 +3. drv_dma - DMA驱动 +4. drv_gpio - GPIO驱动 +5. drv_hard_i2c - 硬件I2C驱动 +6. drv_hwtimer - 硬件定时器驱动 +7. drv_pwm - PWM驱动(基于TIMER) +8. drv_rtc - RTC驱动 +9. drv_sdio - SDIO驱动 +10. drv_sdram - SDRAM驱动(基于EXMC) +11. drv_spi - SPI驱动 +12. drv_spi_flash - SPI Flash驱动 +13. drv_usart - USART驱动(含v2版本) +14. drv_wdt - 看门狗驱动(FWDGT) + +**尚未移植到RT-Thread的驱动:** + +1. CAU - 加密加速单元(AES/DES/TDES) +2. CRC - 循环冗余校验 +3. CTC - 时钟调整控制器 +4. DAC - 数模转换器 +5. DBG - 调试接口 +6. DCI - 数字摄像头接口 +7. ENET - 以太网控制器 +8. EXTI - 外部中断(可能集成在GPIO中) +9. FMC - Flash存储器控制器 +10. HAU - 哈希加速单元(SHA/MD5) +11. IPA - 图像像素加速器 +12. IREF - 内部参考电压 +13. MISC - 杂项功能 +14. PKCAU - 公钥加密加速单元 +15. PMU - 电源管理 +16. RCU - 复位和时钟单元(框架层可能已包含) +17. SAI - 串行音频接口 +18. SYSCFG - 系统配置 +19. TLI - TFT-LCD接口 +20. TRNG - 真随机数生成器 +21. WWDGT - 窗口看门狗 + +位置 - +`./libraries/gd32_drivers/` + +备注 - + +这是RT-Thread的驱动适配层, +作用:将GD芯片的硬件功能适配到RT-Thread的设备框架, +提供统一的RT-Thread API接口,如 rt_device_t、rt_spi_bus、rt_serial +包含:drv_xxx.c/h文件,它们实现了RT-Thread的设备ops接口 +特点:需要实现RT-Thread的设备注册、初始化、读写等标准接口 +通过`rt_hw_xxx_init()`注册到RT-Thread系统 + +### 2.2 USB驱动架构图 + +``` +┌─────────────────────────────────────────────────────────┐ +│ 应用层 (Application) │ +│ usb_cdc_test.c / 用户USB应用 │ +└───────────────────┬─────────────────────────────────────┘ + │ +┌───────────────────┴─────────────────────────────────────┐ +│ RT-Thread设备驱动框架 (Device Framework) │ +│ rt_device / rt_usb_device │ +└───────────────────┬─────────────────────────────────────┘ + │ +┌───────────────────┴─────────────────────────────────────┐ +│ RT-Thread USB适配层 (libraries/gd32_drivers/) │ +│ drv_usbd.c - USB Device适配驱动 │ +│ ? USB硬件初始化 │ +│ ? GPIO/时钟配置 │ +│ ? 中断处理 │ +│ ? RT-Thread设备注册 │ +└───────────────────┬─────────────────────────────────────┘ + │ 调用 +┌───────────────────┴─────────────────────────────────────┐ +│ GD32 USB库 (packages/.../GD32F5xx_usb_library/) │ +│ ┌─────────────────────────────────────────────────┐ │ +│ │ device/class/ - CDC/MSC/HID类驱动 │ │ +│ │ device/core/ - USB Device核心 │ │ +│ │ driver/ - USB底层硬件驱动 │ │ +│ │ ustd/ - USB标准定义 │ │ +│ └─────────────────────────────────────────────────┘ │ +└───────────────────┬─────────────────────────────────────┘ + │ 操作 +┌───────────────────┴─────────────────────────────────────┐ +│ GD32F527硬件寄存器 │ +│ USBFS / USBHS 外设 │ +└─────────────────────────────────────────────────────────┘ +``` + +### 2.3 驱动移植标准流程 + +#### 2.3.1 工具链 +在ConEmu中, + +更新软件包 - pkgs —update +生成MDK5工程 - scons —target=mdk5 +在Keil中,调试器选举openocd, +Rebuild All +Download +#### 2.3.2 确认芯片原厂官方bsp存在, +./gd32527I-eval/packages/gd32-arm-series-latest/GD32F5xx/usb_library/ +├── driver/ # USB底层驱动(已存在) +├── device/ # USB Device功能(已存在) +├── host/ # USB Host功能(已存在) +└── ustd/ # USB标准定义(已存在) + +#### 2.3.3 确认rt框架层驱动不存在,编写 - +usbd.h/c usbd_conf.h (USB通用); +usbd.h/c usbd_conf.h (USB Device通用); + +#### 2.3.4 添加编写的,构建文件 + +```python + .\libraries\gd32_drivers\SConscript + # add usb device drivers. + if GetDepend('BSP_USING_USBD'): + src += ['drv_usbd.c'] +``` + +#### 2.3.5 添加,对应构建包中,原厂package中,相关的文件 + +```python + .\gd32527I-eval\packages\gd32-arm-series-latest\GD32F5xx\SConscript +``` + +#### 2.3.6 添加,对应,menuconfig的,配置 + +`.\gd32527I-eval\board\Kconfig` + +#### 2.3.7 编写测试文件, + +`.\gd32527I-eval\applications\usb_cdc_test.c` + +#### 2.3.8 在menuconfig中配置,更新配置并重新生成工程,编译,下载,运行测试。 + +* **新增文件架构** + +gd32527I-eval/ +├── board/ +│ ├── usb_conf.h ? 新建 +│ ├── usbd_conf.h ? 新建 +│ └── SConscript ? 修改 +├── applications/ +│ └── usb_cdc_test.c ? 新建 +└── libraries/gd32_drivers/ +├── drv_usbd.h ? 新建 +├── drv_usbd.c ? 新建 +└── SConscript ? 修改 + +packages/gd32-arm-series-latest/GD32F5xx/ +└── SConscript ? 已修改 + +* **menuconfig中的菜单** + +``` +Hardware Drivers Config ---> + On-chip Peripheral Drivers ---> + [*] Enable USB Device ---> + USB Device Type (CDC (Virtual COM Port)) ---> + (X) CDC (Virtual COM Port) + ( ) MSC (Mass Storage) + ( ) HID (Keyboard/Mouse) + (0) USB Speed (0:FS, 1:HS) +``` + +#### 2.3.9 测试,debug; + +### 2.4 测试成功:USB-FS 虚拟串口枚举 + +Win11上,设备管理器,枚举成功。 + +![screenshot_image.png](figures/9f58650e21f90dc59c816037f28eab06.png.webp) + +设备的VID和PID与原厂一致 + +![screenshot_image.png](figures/81bf7b7cc2e2ca4e49fd2e55f1ff339a.png.webp) + +串口Log - + +![screenshot_{907B7AE8-6ACD-43E0-9F48-C44BD775468A}.png](figures/6ad4f7b6c5102a36c39558c1c9f3e473.png.webp) + +### 2.5 原文链接 + +原文链接:[RT-Thread-【GD32F527_EVAL】USB 驱动移植 和 USB CDC Device 接入PC实验RT-Thread问答社区 - RT-Thread](https://club.rt-thread.org/ask/article/d45be5efec633a69.html)