Compare commits

...

650 Commits

Author SHA1 Message Date
547abf0cf2
Switch fallthrough missing break usbdfu
usbdfu should be updated later...
2023-01-04 23:41:07 +01:00
06b21b6d82
Fixed bad libopencm3 linker file 2023-01-04 23:27:32 +01:00
dragonmux
ad1868f8d4 command: Cleaned up and refactored cmd_rtt
# Conflicts:
#	src/command.c
2022-08-11 19:56:31 -07:00
dragonmux
c712a54cbc rtt: Cleanup and fixes for the RTT over serial support as per #954 2022-08-11 19:45:58 -07:00
Koen De Vleeschauwer
a51d90ba2d rtt
# Conflicts:
#	src/gdb_main.c
2022-08-11 19:45:44 -07:00
Jason Kotzin
f67a4e421d merge fixes and selective optimizations 2022-08-11 19:28:10 -07:00
Jason Kotzin
8fc7a559b2 Merge commit '5cd430647ecfb6dab4a2ed858fb98567723de699' into stable 2022-08-11 19:15:01 -07:00
Jason Kotzin
c9a0be19cb Merge commit '5e3cadec20a5fa3ec6eef53f23520707d0db5380' into sam-update 2022-08-10 22:33:40 -07:00
Jason Kotzin
2ca08f8511 Merge commit '84311b38881ec4a0934686579fec1054feaf5394' into sam-update 2022-08-10 22:32:18 -07:00
Jason Kotzin
3ae3095499 Merge commit 'c4869a54733ae92099a7316954e34d1ab7b6097c' into sam-update 2022-08-10 22:31:16 -07:00
Jason Kotzin
2a792399ca Merge commit 'e535f53981da1fe80137504c761bc854ea8be356' into sam-update 2022-08-10 22:30:11 -07:00
Jason Kotzin
576f575871 Merge commit '7c120ecb582afb588cb391ab32614c4409a2671d' into sam-update 2022-08-10 22:28:35 -07:00
Jason Kotzin
e43b07172b Merge commit 'a3feae60aab1fb85fe44b33123e020a9d7c8e18c' into sam-update 2022-08-10 22:26:37 -07:00
Jason Kotzin
e0f1d29d41 compile fix 2022-08-10 22:26:10 -07:00
Jason Kotzin
2a00dd88ec Merge commit 'b59ca5142ad3a654dc173d598b826f5f453ae52b' into sam-update 2022-08-10 22:21:29 -07:00
Jason Kotzin
c121da06c8 Merge commit 'a0c77e216d268f2e1caa3442db02cf21f36fad91' into sam-update 2022-08-10 22:20:36 -07:00
Jason Kotzin
542c157955 Merge commit 'd9ef3ff14711457eaf0ea7152067c95b4bb45c03' into sam-update 2022-08-10 22:19:41 -07:00
Jason Kotzin
d4dd288426 Merge commit 'bba2bfdcf49695cb9b88482c7ed3db69db58b082' into sam-update 2022-08-10 22:18:39 -07:00
Jason Kotzin
b096e95488 Merge commit 'cedd9f9ac4fc02cc5ac152eb67024f714c6f95ab' into sam-update 2022-08-10 22:17:50 -07:00
Jason Kotzin
7bd7c3d0f5 Merge commit '8fb3b7b1a8d1cb2ac8b54204f452106939eb2ab7' into sam-update
# Conflicts:
#	src/target/adiv5_swdp.c
2022-08-10 22:17:33 -07:00
Jason Kotzin
82673b5e7b Merge commit '82c41cb739e3281e89319bd2fb9627d1a22c803b' into sam-update 2022-08-10 22:09:23 -07:00
Jason Kotzin
9542cd1cfb Merge commit '48c6db19635a804621c7e08e5e3c705aa50e5e9d' into sam-update 2022-08-10 22:08:46 -07:00
Jason Kotzin
328be18288 Merge commit 'd259d5c5110d5867031a9d9ceaaf3725ce242857' into sam-update 2022-08-10 22:07:38 -07:00
Jason Kotzin
03331b3fff Merge commit '4fe8fd8944ad49e40a46287e2286328af6871226' into sam-update 2022-08-10 22:06:28 -07:00
Jason Kotzin
ca1c0acb27 Merge commit '23534ab174ffadd63bbdb2e0626770753eff7c3b' into sam-update 2022-08-10 22:05:07 -07:00
Jason Kotzin
b4af0f5145 Merge commit '7d2afcff06f1ccd9fe583d562ddd81e04a17e166' into sam-update 2022-08-10 20:40:24 -07:00
Jason Kotzin
e174c5b503 Merge commit 'd594b42976e3b9640b64ef1cb2da3f74067930b8' into sam-update
# Conflicts:
#	README.md
#	src/platforms/common/cdcacm.c
#	src/target/adiv5_swdp.c
2022-08-10 20:39:54 -07:00
Jason Kotzin
c91322e38e fix stack compile warning 2022-08-10 20:37:14 -07:00
Jason Kotzin
85fc728293 Merge commit '59dc2255687436d7a21458615e4eb2e563ca64c1' into sam-update 2022-08-10 20:32:50 -07:00
Jason Kotzin
6727e74daf Merge commit '28623e6b275b90817894ddcbf915dbb8c6686433' into sam-update 2022-08-10 20:31:54 -07:00
Jason Kotzin
d7bf91d039 Merge commit '7ccbdd98c0bd18c2a672ed50aa1f96aff97dd4af' into sam-update 2022-08-10 20:31:11 -07:00
Jason Kotzin
878dc379b9 updates for merge 2022-08-10 20:30:57 -07:00
Jason Kotzin
4f97627b02 Merge commit '64f756d62791e16728e6c9d7877ce2ab620b9c1c' into sam-update 2022-08-10 20:25:30 -07:00
Jason Kotzin
56858650cb Merge commit '88cce08ce47b7b6f6f40b404fa79c6be687ab7e3' into sam-update 2022-08-10 20:24:43 -07:00
Jason Kotzin
dcbb1657b4 Merge commit 'da15cc3cb75cc2a9f604436402f6a81d42b27dce' into sam-update 2022-08-10 20:23:40 -07:00
Jason Kotzin
9dc79becc2 Merge commit '35687018eb634ea329609c86d9ed476bb79c0e91' into sam-update
# Conflicts:
#	src/platforms/common/cdcacm.c
#	src/target/adiv5_swdp.c
2022-08-10 20:19:55 -07:00
Jason Kotzin
9ec6693e4d Merge commit '2a0d608b07487300a63908baa62e73a51a11e811' into sam-update 2022-08-10 20:14:55 -07:00
Jason Kotzin
a2f6776bf8 Merge commit '8089e05a0018a040251ec5de145bccca0977bf78' into sam-update 2022-08-10 20:13:59 -07:00
Jason Kotzin
cb1ef7d616 Merge commit '1330288271bea7b6224bac5bc8e1438305eec44a' into sam-update 2022-08-10 20:09:58 -07:00
Jason Kotzin
def176b240 Merge commit '8da2dee0c41eead0c2b4f466fbc889ef413cf7e9' into sam-update 2022-08-10 20:08:13 -07:00
Jason Kotzin
d5a8717bb0 stack bug fix 2022-08-10 20:08:05 -07:00
Jason Kotzin
8acda14170 Merge commit '23f942ac8c7553f743128d9f96f0d2aa61fbc4bd' into sam-update 2022-08-10 20:07:25 -07:00
Jason Kotzin
c1e34792f4 Merge commit '04d1c9805b80b50b4f1cd33b08503b73e80c0ed3' into sam-update 2022-08-10 20:06:04 -07:00
Jason Kotzin
c5b6f066b8 Merge commit 'b6fbf86743509559fce4c56345e8fdc16df14a08' into sam-update 2022-08-10 19:55:26 -07:00
Jason Kotzin
f109bc2e98 Merge commit '61e237ec87c525876817e72fc82ce28b2a4951ae' into sam-update 2022-08-10 19:53:14 -07:00
Jason Kotzin
d36213b7d0 Merge commit 'be3bfc48a8be7cd4d84709e98c5def13259d49f6' into sam-update
# Conflicts:
#	README.md
2022-08-10 19:49:50 -07:00
Jason Kotzin
389bb03fc0 Merge commit 'db17f2caa8dcbf229670ba03b46be274656c6d72' into sam-update 2022-08-10 19:48:49 -07:00
Jason Kotzin
78837173a4 Merge commit 'e6a9a1a3665e83e25d5d4077a33aa5b0110646b8' into sam-update
# Conflicts:
#	.gitignore
2022-08-10 19:48:21 -07:00
Jason Kotzin
4328e8a4c1 Merge commit 'aa0d8f4b5de13f4fb7324a690a4bb7aa411e767f' into sam-update 2022-08-10 19:46:16 -07:00
Jason Kotzin
646fbcb21f fixes for upstream 2022-08-10 19:46:01 -07:00
Jason Kotzin
9da2d298c3 Merge commit '1ca9f234f7527396da91bfc1f98cb05c305c6472' into sam-update 2022-08-10 19:30:49 -07:00
Jason Kotzin
95a4ebf836 Merge commit '7365a44989c7c8561c583f75ff30f7277e712ff3' into sam-update 2022-08-10 19:30:16 -07:00
Jason Kotzin
3024cc1bfe minor update to libopencm3, only build samd to speed up merge 2022-08-10 19:28:12 -07:00
Jason Kotzin
7340b0065d Merge commit '93d4c659481c918b43c0068e69050ef1ad4ca91e' into sam-update 2022-08-10 19:08:37 -07:00
Jason Kotzin
dd01fe9ad3 upstream compile fixes 2022-08-10 19:08:35 -07:00
Jason Kotzin
336797363b Merge commit '98b4ec58bc566591943c9123dd4ca0c8dcfd521e' into sam-update
# Conflicts:
#	libopencm3
2022-08-10 19:08:25 -07:00
Jason Kotzin
046cc359ba Merge commit 'dd6aadc54d00cee92e14bf7538d3ece3d3ab298f' into sam-update 2022-08-10 18:37:14 -07:00
Jason Kotzin
9e02c5f0cd Merge commit 'cda83d308490738b54df0405cca3c0c048809664' into sam-update
# Conflicts:
#	src/Makefile
2022-08-10 18:36:23 -07:00
Jason Kotzin
c73329f7d4 Merge commit '59dc1b7eb4f3a0fda23d2c8624c3ecd26515fec8' into sam-update
# Conflicts:
#	src/platforms/common/cdcacm.c
2022-08-10 18:33:59 -07:00
Jason Kotzin
d90c207c50 adding cscope files to git ignore 2022-08-10 18:24:35 -07:00
Jason Kotzin
b87091a59b Merge commit 'dc8924a2bc0110287c1b289002efb52926daccb0' into sam-update
# Conflicts:
#	README.md
2022-08-10 18:24:25 -07:00
Jason Kotzin
f8aff4bf4b upstream fixes 2022-08-10 18:19:15 -07:00
Jason Kotzin
50b9a4ceb6 Merge commit '77231e8972fa22cb233354ba5aed694dff4a9e24' into sam-update 2022-08-10 17:40:26 -07:00
Jason Kotzin
93cf62d944 Merge commit '8289862b55e2a0dc658c3c7e2f6ab9878d0527fa' into sam-update
# Conflicts:
#	README.md
#	src/platforms/common/cdcacm.c
2022-08-10 17:40:24 -07:00
Jason Kotzin
09e45cea5b Merge commit 'a4cdd6b3103cdf6c1f8454fb81558ff98a8d912d' into sam-update 2022-08-10 17:36:48 -07:00
Jason Kotzin
65c95fb413 Merge commit 'f5e305e237aba0ab8bf2f42e75505ef468f47d82' into sam-update
# Conflicts:
#	README.md
2022-08-10 17:36:47 -07:00
Jason Kotzin
c643726c9d Merge commit 'da45281696b05089d694e6e9c7734968b9496865' into sam-update 2022-08-10 17:35:15 -07:00
Jason Kotzin
eda19bc28d Merge commit 'ef816e318391c64014554140be65a5cafc6c8be2' into sam-update
# Conflicts:
#	.gitignore
2022-08-10 17:34:55 -07:00
Jason Kotzin
9b145c8398 compatibility to upstream 2022-08-10 17:27:05 -07:00
Jason Kotzin
53c6821734 Merge commit '9969c984f3ca67f38677b061e2f91a1fb50cd310' into sam-update 2022-08-10 15:57:56 -07:00
Jason Kotzin
842a0b4193 compatibility with merge changes 2022-08-10 15:57:41 -07:00
Jason Kotzin
8a37449f8a Merge commit 'e34a27f72c9689850e97df74c499538d7f18518d' into sam-update
# Conflicts:
#	src/include/swdptap.h
#	src/platforms/common/swdptap.c
2022-08-10 15:57:29 -07:00
Jason Kotzin
21989d4142 Merge commit '1e10b96b03da71b1a101c108ca9511c8a613666e' into sam-update 2022-08-09 22:17:14 -07:00
Jason Kotzin
63449912e2 Merge commit 'f3790b90e5ecf44525dc05f05a4e72f74baea411' into sam-update 2022-08-09 22:11:55 -07:00
Jason Kotzin
1661396951 Merge commit '05adcd9bf5b36d099627aff6b73e463030ee417f' into sam-update 2022-08-09 22:06:01 -07:00
Jason Kotzin
fd6610bdae samd fix USB max packet size 2022-08-09 17:31:30 -07:00
Jason Kotzin
19e01abf70 Merge commit '16967b43288028dcdc2759bb2a25a53472571162' into sam-update 2022-08-09 17:25:16 -07:00
Jason Kotzin
a89b2ead47 Merge commit '541861e978ba88c80e7e2a0cbcd7ce55d574c97b' into sam-update
# Conflicts:
#	README.md
2022-08-09 17:23:48 -07:00
Jason Kotzin
81cfa0a380 Merge commit '1a83bc68920ad20ad044e9110c3599e3ac1f76c0' into sam-update
# Conflicts:
#	src/command.c
2022-08-09 17:22:19 -07:00
Jason Kotzin
41449370b4 Merge commit 'd63e870e82ecbd73af2d14e6794d2985cb9bd0ad' into sam-update 2022-08-09 17:13:06 -07:00
Jason Kotzin
73285885b3 Merge commit 'a0e42e229b99dad09f3c2eaf1455cbefc776cbe8' into sam-update 2022-08-09 17:11:21 -07:00
Jason Kotzin
b71213522a change spec to decrease code size 2022-08-08 21:14:10 -07:00
Jason Kotzin
c0c5255103 libopencm3 regression fix 2022-08-08 21:06:18 -07:00
Jason Kotzin
a2cdb32f14 Merge commit '2e185ba578cf996a9e6cd7b6a0321a2448064e52' into sam-update 2022-08-02 09:35:57 -07:00
Jason Kotzin
1930380e16 Merge commit '0b6f393d5b1ab03fc0dcd8b172261e7a52bdd3d8' into sam-update 2022-08-02 09:35:19 -07:00
Jason Kotzin
5509264a2b Merge commit 'ea779d13725f1c2c580c5c11c47267af09b6b007' into sam-update 2022-08-02 09:35:09 -07:00
Jason Kotzin
6f902bcfe7 optimization flag for jeff probe 2022-08-02 09:35:01 -07:00
Jason Kotzin
fdce017311 Merge commit 'f89542c79f6edb0d64e7dfa483501718113f45b5' into sam-update 2022-08-02 09:28:24 -07:00
Jason Kotzin
96a980b682 Merge commit '286b987822a685f6ff86f6522da3733a0c9d7757' into sam-update
# Conflicts:
#	src/command.c
2022-08-02 09:28:14 -07:00
Jason Kotzin
cedcd1a832 Merge commit '71b8a4e0818026fa25e9fa95b2cd3c0dd407b3a2' into sam-update 2022-08-02 09:21:00 -07:00
Jason Kotzin
1737788a92 Merge commit 'd1ee827b4df710a0f693f6df7808cb5d75b2530c' into sam-update 2022-08-02 09:20:50 -07:00
Jason Kotzin
f65793582d Merge commit '5704c2fb5a07bbe7982a368e6ab7762a6866988f' into sam-update
# Conflicts:
#	src/Makefile
2022-08-02 09:20:27 -07:00
Jason Kotzin
90a7ecaaf1 Merge commit 'e8bd066fe96f72c6998aea7c0d80d6de019b825d' into sam-update
# Conflicts:
#	README.md
2022-08-02 01:31:38 -07:00
Jason Kotzin
b6896898c2 Merge commit '82be49f05212d36733ab99c6f83ef93a7ff444d1' into sam-update 2022-08-02 01:31:04 -07:00
Jason Kotzin
81bb75bba6 Merge commit '443ced62d4e47d73da13746a836369d8421b4fe8' into sam-update
# Conflicts:
#	libopencm3
2022-08-02 01:23:28 -07:00
Jason Kotzin
6661871707 Merge commit 'fbf196378e5bbeffad02439fa974f6142a78d6a2' into sam-update 2022-08-01 21:46:52 -07:00
Jason Kotzin
885fdcc354 Merge commit '5107a29699904fb4e60907d1e9b2438592f6a3ff' into sam-update 2022-08-01 21:46:24 -07:00
Jason Kotzin
16261813ca Merge commit 'e29f2b4fb95601291afced3af3731385be343988' into sam-update
# Conflicts:
#	.gitignore
#	src/include/swdptap.h
#	src/target/swdptap_generic.c
2022-08-01 21:45:01 -07:00
Jason Kotzin
fcf5b74542 Merge commit '067956266c886d377231ffdd89e630e41aeb2783' into sam-update 2022-08-01 20:43:02 -07:00
Jason Kotzin
539fba02ac Merge commit '9e898cc4b8f3e1a5844a3693412a9977a65a0a63' into sam-update 2022-08-01 20:30:35 -07:00
Jason Kotzin
4a2a121e89 Merge commit 'dd3cb193f3a83e99b5a915e9942c295b9d9715d7' into sam-update 2022-08-01 20:30:04 -07:00
Jason Kotzin
16b827e4e4 Merge commit 'c44cb904b0d345753b40ac9649bb4c611855a5c4' into sam-update
# Conflicts:
#	src/target/adiv5.c
2022-08-01 20:29:58 -07:00
Jason Kotzin
a9197e67ea Merge commit '205fce20e5ade52b6331e315ccd0700293f51aac' into sam-update 2022-08-01 20:22:28 -07:00
Jason Kotzin
ab63700a80 Merge commit '9ed26645d332dbd1d725ccef64199ef13604686c' into sam-update 2022-08-01 20:22:07 -07:00
Jason Kotzin
0993a8ae28 Merge commit 'fd3af639b0f8eb816d4efc860f549e8c01454826' into sam-update 2022-08-01 20:21:48 -07:00
Jason Kotzin
a7c4a0c108 Merge commit 'bd530c8951f8393e8d799d25f233c77051b10561' into sam-update 2022-08-01 20:21:34 -07:00
Jason Kotzin
bb97e35f82 Merge commit '5aebef4f64d0fd4c19f794fb9725686c39a7e395' into sam-update 2022-08-01 20:21:13 -07:00
Jason Kotzin
cbed6c911f Merge commit 'df7458e35a67abb216d9816c59f218cad45f1c44' into sam-update 2022-08-01 20:20:38 -07:00
Jason Kotzin
272b461b3e Merge commit 'b4c680bb150b815df401c98c45f03ff45e5a231f' into sam-update 2022-08-01 20:18:49 -07:00
Jason Kotzin
a29d53cb31 Merge commit '600bc9f0294f07a5572511c98041710d80d95769' into sam-update 2022-08-01 20:18:03 -07:00
Jason Kotzin
4947f0f747 Merge commit '61e9607594586fe5018157f566b8b79a398444b7' into sam-update
# Conflicts:
#	src/Makefile
2022-08-01 20:17:24 -07:00
Jason Kotzin
a6f8944afe Merge commit '88ec55768389c6c4de69ecd6e101f6b136c25a8f' into sam-update 2022-08-01 20:10:32 -07:00
Jason Kotzin
33c0319263 Merge commit '2b4000b2b44ca629d18d96a803413c71ab7b8e52' into sam-update 2022-08-01 20:09:50 -07:00
Jason Kotzin
93cad1ca5a Merge commit 'cdb04a4214cfd1d94a7fe2fd1837b91ec099db28' into sam-update 2022-08-01 20:09:24 -07:00
Jason Kotzin
9a9fac2e83 Merge commit '02c1934c03eb86901634ed63e0cc9b13eb743fa8' into sam-update 2022-08-01 20:08:54 -07:00
Jason Kotzin
a285b2ac17 Merge commit '7032abd2b00d4548d41f7f1abbdf0837bc283def' into sam-update
# Conflicts:
#	src/Makefile
2022-08-01 20:08:51 -07:00
Jason Kotzin
4b4d0fcfcf Merge commit 'a65ce77466077b4259d99232d6f3c168b476ce79' into sam-update 2022-08-01 20:05:36 -07:00
Jason Kotzin
6b2b1aa4c3 Merge commit '525b90d4e5d07f431a1d0f4e5d2abf9e6c691e10' into sam-update 2022-08-01 20:04:51 -07:00
Jason Kotzin
fce7dd2957 Merge commit '7f947d724c552f896d5394f3ebbf6b47de9eb5a6' into sam-update 2022-08-01 20:04:01 -07:00
Jason Kotzin
6b2f0aeb63 Merge commit 'db544e9b671719e553bb6aec9e2e39294c3ee027' into sam-update 2022-08-01 20:03:40 -07:00
Jason Kotzin
4cae565ef3 Merge commit 'a988bba035824ddc97b2cf3aadc457dcd85aaad0' into sam-update 2022-08-01 20:02:30 -07:00
Jason Kotzin
d76fd844c9 Merge commit '05518094752e450708aced3397cb26146e8ce0d3' into sam-update 2022-08-01 19:59:54 -07:00
Jason Kotzin
27a099a94b Merge commit '46b681e050bbfb27acafab88a3b67bda292825ca' into sam-update 2022-08-01 19:58:15 -07:00
Jason Kotzin
9c33ce7979 Merge commit '7a7266a0f7e38a9359f84fe1fb34453e8b2b16ae' into sam-update
# Conflicts:
#	src/platforms/common/swdptap.c
2022-08-01 19:57:12 -07:00
Jason Kotzin
1612eacab2 Merge commit '5548d54626a658b65f1f963cd5af54ddaf93fbf7' into sam-update
# Conflicts:
#	src/platforms/common/swdptap.c
2022-08-01 19:56:08 -07:00
Jason Kotzin
f1f59d3c1d Merge commit '7e3fe352ad4aed89522d808d76dbe868a470412e' into sam-update
# Conflicts:
#	src/platforms/common/swdptap.c
2022-08-01 19:54:44 -07:00
Jason Kotzin
a42fc8904d Merge commit 'e54a826745ae298a4eb555f3d76dfcdd571211b9' into sam-update
# Conflicts:
#	src/platforms/common/swdptap.c
2022-08-01 19:52:55 -07:00
Jason Kotzin
f62c9db5af Merge commit 'd4d24c256c2c9a858ae6fc134ee34ba03cb65565' into sam-update 2022-08-01 19:21:49 -07:00
Jason Kotzin
1ba83f3283 Merge commit '17b817f37bca85c9b469470742ecdeedf02f7b3e' into sam-update 2022-08-01 19:21:27 -07:00
Jason Kotzin
c33a447210 Merge commit '9e365a58f77a9096b0203a5f012bb7bfb08fbc95' into sam-update 2022-08-01 19:21:10 -07:00
Jason Kotzin
81fafae68d Merge commit '44fc24e0e747293fa05b62ed7439501553829b0b' into sam-update 2022-08-01 19:20:52 -07:00
Jason Kotzin
447bdc50a0 Merge commit '66e357d51762f3bf93b549a5626554b2f8de4379' into sam-update
# Conflicts:
#	src/target/adiv5.c
2022-08-01 19:20:32 -07:00
Jason Kotzin
b91712214f Merge commit '1799ea3b7102ac1e2a86d78cdbde0f5b809b0be1' into sam-update 2022-08-01 19:03:03 -07:00
Jason Kotzin
5574a14aee Merge commit 'b7a59afc5920caf1e83cd470aee67f665d0e7197' into sam-update 2022-08-01 19:01:41 -07:00
Jason Kotzin
a82ab6a45d Merge commit '80f003ff4b6edc9d0d2b98b4ca65d610d86efc74' into sam-update 2022-08-01 19:01:18 -07:00
Jason Kotzin
40ea78d57b Merge commit '48d232807ee6096bfa839d91b1708252db0e1a59' into sam-update 2022-08-01 18:59:50 -07:00
Jason Kotzin
eab16ef39f Merge commit '0f2f1d74a2446275ee31ed582f1f4d98dff24d61' into sam-update 2022-08-01 18:57:07 -07:00
Jason Kotzin
da701aff6d Merge commit '455e0a74d2a77f2ae1f0acf53b778e41b890523e' into sam-update 2022-08-01 18:56:50 -07:00
Jason Kotzin
aece87bf3e Merge commit 'cfaa5ea9633fb8719da9455f6c04908810395abe' into sam-update 2022-08-01 18:54:48 -07:00
Jason Kotzin
2931169dd1 Merge commit '0c659f49cd03c7154bfb92c621df523aa8540f72' into sam-update 2022-08-01 18:52:34 -07:00
Jason Kotzin
95655b838e Merge commit '231d42d58172a2169d99c6e618192ac0d514d3b9' into sam-update 2022-08-01 18:50:19 -07:00
Jason Kotzin
1846795844 Merge commit '19e58a7205e2dfe849b5ac42e470ff489e4ab10d' into sam-update 2022-08-01 18:36:22 -07:00
Jason Kotzin
76c2f5e39c Merge commit 'eb46994bc95ba308f8eb96d42366abbdae7c5ab7' into sam-update 2022-08-01 18:35:43 -07:00
Jason Kotzin
51f2b79437 Merge commit '1ee1f441d581b6473526a4870f4c3aa201a18af6' into sam-update 2022-08-01 18:34:34 -07:00
Jason Kotzin
02eafe9883 Merge commit 'c7bc51d1919bce00c341b2b2e1e617adcf189be9' into sam-update 2022-08-01 18:33:40 -07:00
Jason Kotzin
05a42576c2 Merge commit 'a4bb2c6e3ea8404641325638a040e3295b7afe30' into sam-update 2022-08-01 18:33:13 -07:00
Jason Kotzin
39949eefe2 Merge commit 'fd467269eb82783c09a69763c46df4de2d494ef4' into sam-update 2022-08-01 18:32:42 -07:00
Jason Kotzin
d7afc92b5f Merge commit '539d9e14ec553c77b2c3387b4719d8f07401d6a7' into sam-update 2022-08-01 18:32:18 -07:00
Jason Kotzin
44b5eed7ca Merge commit '261be9864c8ce77c857a996784ac65ed3203b03a' into sam-update 2022-08-01 18:31:34 -07:00
Jason Kotzin
4346fb2405 Merge commit '98a4f8e31872d3f72e47aba8b01a167503144c1e' into sam-update 2022-08-01 18:31:06 -07:00
Jason Kotzin
9c95dfb712 adding adiv5 support 2022-08-01 17:45:49 -07:00
Jason Kotzin
f99fe59ce8 updating libopencm3 with samd i2c support 2022-08-01 17:45:30 -07:00
dragonmux
5cd430647e
gdb_main: Fixed a small DEBUG_GDB regression for vFlashErase and vFlashWrite debugging 2022-07-21 07:14:47 +01:00
dragonmux
fc55400aad
gdb_main: Implemented a notification to GDB that the "process" has exited when the user runs a new bus scan while attached to a target 2022-07-21 05:45:23 +01:00
dragonmux
d2370f780f
gdb_packet: Implement notification packets 2022-07-21 05:45:23 +01:00
dragonmux
f254e86511
gdb_main: Add some output in the scan commands to indicate when still attached that you aren't after the command, despite what GDB thinks 2022-07-21 05:45:22 +01:00
dragonmux
3cc6aa1236
gdb_main: Implemented qfThreadInfo and qsThreadInfo for GDB 11+ 2022-07-21 05:45:22 +01:00
dragonmux
65ac074410
gdb_main: Implemented vKill as it's required for GDB 11+ 2022-07-21 05:45:22 +01:00
dragonmux
c6d1bcb352
gdb_main: Cleaned up the naming in the 'g' and 'G' packet handlers 2022-07-21 05:45:22 +01:00
dragonmux
eb9d9893f8
hex_utils: Cleaned up and fixed the type confusion that was going on 2022-07-21 05:45:22 +01:00
dragonmux
8db1d30852
gdb_main: Reply to vAttach with TID 1 because GDB 11 and 12 are terminally broken otherwise 2022-07-21 05:45:21 +01:00
dragonmux
1f22c72634
gdb_main: Implemented support for qC queries 2022-07-21 05:45:21 +01:00
dragonmux
7322bb3ffa
gdb_main: More type confusion fixes and cleanup 2022-07-21 05:45:19 +01:00
dragonmux
17ba28c44b
gdb_main: Implemented H[m|M|g|G|c] packet support 2022-07-21 05:44:21 +01:00
dragonmux
47c84fac85
gdb_packet: Done a spring pass on the types situation and cleaned things up 2022-07-21 05:43:55 +01:00
Piotr Esden-Tempski
1cf1ba1ddb stm32f4: Fixes erase_mass command return error.
The final erase_mass command check is looking for the EOP (End of
OPeration) bit to be set. This bit is only set when the EOP interrupts
(EOPIE = 1) are enabled. We are not enabling those on the target so this
bit will never get set. As we are monitoring the BSY flag to make sure
the erase_mass operation is still ongoing and finished it is enough if
we just check the error flags.
2022-07-13 21:06:53 -07:00
dragonmux
34696c0fec
target: Make the buffers used to program a target's Flash better bounded in lifetime and memory usage 2022-07-13 22:28:33 -04:00
Piotr Esden-Tempski
a067e801d7
BMP V2.3: Fix outdated ADC reads.
We are using GD32F103 on the BMP V2.3 hardware. The GD32F103 has an
errata for the ADC where the end of conversion (EOC) bit is not reset
when reading the ADC result. This resulted in us not waiting for the new
value to be acquired and reading an old value instead. The solution for
that is resetting the EOC bit manually after reading the ADC result, so
that on the next acquisision we wait for the conversion to finish.

This patch also increases the sampling time as the GD32 have lower ADC
impedance than the STM32 and this should help us read a more accuarate
target voltage.
2022-07-13 20:54:14 -04:00
dragonmux
d01acd8030
kinetis: Clean up how kl_gen_flash_done builds the command buffers to send to ensure the security byte is OK 2022-07-11 20:17:53 -04:00
dragonmux
0dffd2ffd2
kinetis: Fixed the flash write command generation for K64 devices 2022-07-11 20:17:52 -04:00
dragonmux
0f1006bf08
kinetis: Try to be safer about our FCCOB writes so the Flash controller's less likely to get mad 2022-07-11 20:17:52 -04:00
Rafael Silva
f69ed07ba7
kinetis: macro organization and clearer function naming
Signed-off-by: Rafael Silva <perigoso@riseup.net>
2022-07-09 19:12:05 -04:00
dragonmux
9591649ec6
kinetis: Run clang-format on the code 2022-07-09 19:10:40 -04:00
dragonmux
e9abd83412
kinetis: Refactored out some common code from kinetis_probe for the S32K14 lineup 2022-07-09 19:10:39 -04:00
dragonmux
4de54fbee6
kinetis: General formatting and readability cleanup 2022-07-09 19:10:39 -04:00
dragonmux
77a83f4ffc
ch32f1: Fixed another broken debug print that made assumptions about %x and %d that are wrong 2022-06-26 17:34:22 -04:00
dragonmux
d613d29839
cortexm: Added additional debug information for part probing 2022-06-26 17:34:22 -04:00
dragonmux
c7c5f68a84
ch32f1: Re-ordered a couple of the operation in ch32f1_probe so it plays nicer with the STM32 parts 2022-06-26 17:34:22 -04:00
dragonmux
d9f4d069e6
ch32f1: Further formatting and layout cleanup 2022-06-26 17:34:22 -04:00
dragonmux
eb8bb01c57
ch32f1: Fixed the probe routine distrubing state for other parts wrt t->idcode
The CH32F1 routine now reads the IDCode into a local.
If the part number matches and appears to be the chip (based on Flash locking), it only then writes the IDCode into `t->idcode`, which is at the point we can only `return true` from the probe routine anyway.
2022-06-26 17:34:22 -04:00
dragonmux
7e91c401d3
ch32f1: formatting cleanup to bring things closer to inline with the rest of the codebase 2022-06-26 17:34:09 -04:00
Maciej Musiał
54790f032e
cortexm: fixed an issue with watchpoint handling and a register sanity check 2022-06-26 17:32:19 -04:00
dragonmux
08956eb4fb
gdb_main: Fix a formatting bug that breaks, among other things, breakpoints 2022-06-26 17:31:13 -04:00
Mikaela Szekely
289d963ba5 Complete the version string migration from 5e3cade, fixing HOSTED_BMP_ONLY 2022-06-03 14:45:16 -07:00
Piotr Esden-Tempski
5e3cadec20 Updated Copyright and Vendor strings to Black Magic Debug.
The project is not part of Black Sphere Technologies any more. It was
renamed to Black Magic Debug instead.
2022-05-30 15:09:55 -07:00
Piotr Esden-Tempski
84311b3888 docs: Corrected org in links to blackmagic-debug 2022-05-30 14:32:36 -07:00
Piotr Esden-Tempski
9b5b6fab5b upgrade: Changed copyright to BMD and allowed more vendor strings. 2022-05-30 14:30:06 -07:00
Piotr Esden-Tempski
e4d692bf7a driver: Updated vendor name to Black Magic Debug. Closes #1009 2022-05-30 14:30:00 -07:00
dragonmux
434a23b478
misc: Corrected the patreon link in FUNDING.yml 2022-05-25 18:57:38 -04:00
dragonmux
0ee03080c3
misc: Added Esden's patreon to FUNDING.yml 2022-05-25 16:31:33 -04:00
dragonmux
754d65ad54
misc: Added GitHub funding configuration for the project 2022-05-25 14:37:55 -04:00
dragonmux
29dc94c3d6 hosted: with mubes help, fixes some issues with how we talk CMSIS-DAP 2022-05-17 15:46:33 -07:00
dragonmux
c4869a5473 hosted/stlinkv2: Cleaned up the new error messages as they weren't outputting nicely 2022-04-16 18:22:14 -04:00
dragonmux
a27661cd0b hosted/platform: Formatting consistency improvements 2022-04-16 18:22:14 -04:00
dragonmux
ba8ed132a8 hosted/stlinkv2: Fix !found causing hosted to continue on anyway, and improved the error reporting from the device finder loop 2022-04-16 18:22:14 -04:00
dragonmux
4287f1ba0e hosted/stlinkv2: Rewrote the serial number readering logic to not violate the USB spec and properly handle libusb errors 2022-04-16 18:22:14 -04:00
dragonmux
94e9281404 hosted/bmp_libusb: Rewrote the string reader logic to not violate the USB spec and properly handle libusb errors 2022-04-16 18:22:14 -04:00
dragonmux
c7eba0a439 hosted/bmp_libusb: Fixed some signed/unsigned issues and UB in send_recv 2022-04-16 18:22:14 -04:00
dragonmux
c5dbf851f6 hosted/bmp_libusb: Formatting cleanup 2022-04-16 18:22:14 -04:00
Nicolas Schodet
6c700f7b6c scripts: bootprog.py: use bytes literals 2022-04-15 11:59:40 -07:00
Michal Moskal
6b465d6a77 Temporarily enable DBG clock in stm32g0_detach(); fixes #1003 2022-04-12 05:39:14 -04:00
mean
e535f53981 remove static vars 2022-04-10 23:40:44 -04:00
mean
7c120ecb58 put ch32f1 in its own file 2022-04-10 23:40:44 -04:00
mean
a3feae60aa cleanup tabs 2022-04-10 23:40:44 -04:00
mean
844ca65a8f cosmetic 2022-04-10 23:40:44 -04:00
mean
04eb33e039 rename to comply to naming scheme 2022-04-10 23:40:44 -04:00
mean
fb216a2a98 tabify 2022-04-10 23:40:44 -04:00
mean
17dca6f791 tabify 2022-04-10 23:40:44 -04:00
mean
e12939582c revert function clones_probe 2022-04-10 23:40:44 -04:00
mean
9b23265dde add support for ch32 flash write, it is a bit hackish 2022-04-10 23:40:44 -04:00
mean
733cf12663 cleanup 2022-04-10 23:40:44 -04:00
mean
83e3d9c135 disable verification 2022-04-10 23:40:44 -04:00
mean
90d15e6633 add probe for ch32 + make room for other clones 2022-04-10 23:40:44 -04:00
mean
17d7dca9ae build ch32 in its own file 2022-04-10 23:40:44 -04:00
dragonmux
be83c2861e
gdb_packet: Formatting cleanup 2022-03-31 14:11:38 -04:00
dragonmux
e424859ecb
gdb_main: Formatting cleanup 2022-03-31 14:03:29 -04:00
dragonmux
804a1a4f43
stm32f4: Attach logic cleanup by making sure we only set the extra bits needed when writing DBGMCU_CR 2022-03-31 13:46:29 -04:00
Uwe Bonnes
eed1cc81ff STM32F4: Move DBGMCU_handling to target specific code. Apply for F4 too. 2022-03-31 13:43:52 -04:00
Piotr Esden-Tempski
b59ca5142a pc hosted: Don't try to report memory usage.
When building on a pc gcc does not have that parameter and clang fails
with an error. This caused a build regression on Mac.
2022-03-29 16:45:08 -07:00
dragonmux
a0c77e216d adiv5_swdp: Changed the low-level access code to retry till timeout (partial revert of 61efe26)
Proper initialisation of the ack value also fixes a potential use-before-init UB
2022-03-29 15:33:23 -07:00
dragonmux
d9ef3ff147 adiv5_swdp: Formatting consistency cleanup 2022-03-29 15:33:23 -07:00
dragonmux
bba2bfdcf4 advi5: Raise the access timeouts as 20ms is too low in some cases 2022-03-29 15:33:23 -07:00
mean
cedd9f9ac4 follow function naming scheme 2022-03-22 10:10:33 -04:00
mean
8fb3b7b1a8 reuse exception to avoid using the stack 2022-03-22 10:10:33 -04:00
mean
82c41cb739 add putpacket2 to send two sub messages merged as one 2022-03-22 10:10:33 -04:00
mean
9007c40954 revert temp patch on platform.h 2022-03-22 10:10:33 -04:00
mean
8b52bbd9a9 fix unused var / naming 2022-03-22 10:10:33 -04:00
mean
b82ee6bc90 prototype for gdb_putpacket2 2022-03-22 10:10:33 -04:00
Mike Ditto
48c6db1963 Remove duplicate definition of USBUSART_DMA_TX_ISR 2022-03-22 10:02:52 -04:00
Piotr Esden-Tempski
e82d4f2eda native: Fixes an hw version issue with some older BMP.
The BMP with hardware version 4 and newer, use option bytes instead of
physical GPIO to encode the hardware version. In some older BMP there is
a chance that the user option byte is set to 255 (0x00FF pattern). This
can throw off the hardware version detection routine.
2022-03-15 23:45:32 -07:00
Piotr Esden-Tempski
bcba3ee4a9 native: Fixed hw6 USBUSART support. 2022-03-15 23:45:32 -07:00
Piotr Esden-Tempski
06f24d3269 native: Added blocks to the ISR templates. 2022-03-15 23:45:32 -07:00
Piotr Esden-Tempski
bb761e4b38 native: Initial addition of hw 6 support. 2022-03-15 23:45:32 -07:00
Piotr Esden-Tempski
2d63021344 native: Improved pinout legend comment block. 2022-03-15 23:45:32 -07:00
Piotr Esden-Tempski
e7982d594e native: Added HW5 AUX interface definitions. 2022-03-15 23:45:32 -07:00
Piotr Esden-Tempski
655014ac9c native: hw rev 5 has the usb vbus sense pin on PA15.
We had to move the pin to free up the SPI SCLK pin.
2022-03-15 23:45:32 -07:00
Piotr Esden-Tempski
9ffa923bc1 native: Update hwversion detection for hw rev 4 and newer.
The hw rev 4 and 5 both have the version stored in the Data1 user option
byte. This frees up the hw rev strapping pins for other uses, ie swtrace
decoding using USART1 RX, and additional peripherals on the SPI bus,
like bulk flash storage and displays.
2022-03-15 23:45:32 -07:00
Piotr Esden-Tempski
d259d5c511 build: Only build the locm3 libraries needed.
We don't need to build all the locm3 libraries. We just need those that
are required by the supported platforms.
2022-03-15 13:33:51 -07:00
Fabrice Prost-Boucle
488df7e6f7 sscanf cleanup in GDB Z packet handling function.
Tested working with arm-none-eabi-gcc 10.2.1
2022-03-15 13:18:00 -07:00
Piotr Esden-Tempski
e0619ca7d5 Added a linker flag to output memory usage. 2022-03-15 11:41:31 -07:00
Piotr Esden-Tempski
4b92415442 ghactions: Added libhidapi dependency installation. 2022-03-14 23:01:32 -07:00
Piotr Esden-Tempski
501fd09228 ghactions: Added libftdi1 dependency installation. 2022-03-14 21:55:05 -07:00
Piotr Esden-Tempski
0d97871893 The pull request github action now also builds hosted.
This will help catch some more build errors.
2022-03-14 21:46:15 -07:00
dragonmux
4fe8fd8944 samd: Fixed the hosted build as the code from #987 assumed unsigned long was 32-bit 2022-03-14 21:38:45 -07:00
dragonmux
23534ab174 target: Cleanup in target_new() for the check_error callback 2022-03-14 21:37:44 -07:00
dragonmux
7d2afcff06 Revert "jtag: Make jtag_devs argument to jtag_handler."
This reverts commit 6308506276d09cde14be2985c0c5a59adc0addc6.
2022-03-14 21:37:44 -07:00
dragonmux
e271c16f6c Removal of MFR descriptions as requested in #978 2022-03-14 21:37:44 -07:00
dragonmux
361dc9c234 Revert "adiv5_swdp_scan: If SWD scan fails, try a JTAG scan."
This reverts commit 3df692ecb247fdc7c62f3c3dc622030ad12817e6.
2022-03-14 21:37:44 -07:00
dragonmux
024152b03e Revert "jtag_scan: Deliver full idcode to the handler."
This reverts commit 1845d71f00dda59849254bbddb3c4c00f556d35c.
2022-03-14 21:37:44 -07:00
dragonmux
c30e165c1c crc32: Fix the launchpad-icdi build as that was broken 2022-03-14 21:37:44 -07:00
dragonmux
54f577a970 hosted/dap: Partial revert of 5c8e277, taking into account that division may not be available on platforms 'hosted' might see itself built 2022-03-14 21:37:44 -07:00
dragonmux
02d9a1d3cf Revert "jtag_scan: Rework chain detection"
This reverts commit 2d4a50313596081a64bd1397017985641fd8cad0.
2022-03-14 21:37:44 -07:00
dragonmux
3bb8c2bf19 jtag_scan: Cleaned up the ones array to use a more correct syntax 2022-03-14 21:37:44 -07:00
dragonmux
d1c9d94174 jtag_scan: Remove the now redundant IDCode parameter from the handlers 2022-03-14 21:37:44 -07:00
dragonmux
75e786da11 jtag_devs: Added a few more parts based on 0170aff and cleaned up the description wording for the existing ones 2022-03-14 21:37:44 -07:00
dragonmux
27c143a3a3 jtag_scan: Properly fixed the wrong IDCode getting to the handlers 2022-03-14 21:37:44 -07:00
arpadbuermen
4045406ed8 Added support for fine-grained bootloader and flash locking in samd.c
lock_flash and lock_bootprot currently support only locking the whole flash and locking the maximal leading flash chunk (32k). 
An optional numerical parameter is added. It can be specified in decimal or 0x prefixed hexadecimal. 
For samd21 'lock_bootprot 0' locks the first 32k of flash while 'lock_bootprot 6' locks the first 512 bytes. 'lock_bootprot 0' is equivalent to 'unlock_bootprot'.  
Similarly, 'lock_flash <number>' locks the flash segments corresponding to zeros in the binary representation of the given number. 
'lock_flash 0xffff' is equivalent to 'unlock_flash'. 
If the optional parameter is not given both commands work as previously.
2022-03-14 00:26:31 -07:00
Uwe Bonnes
c1a12edbe9 kinetis: Clarify arguments to kl_gen_command
gcc11 chokes on the old setup
2022-03-13 19:48:38 -07:00
Qyriad
91a63fe0e6 Upload builds on push, and test that PRs build, with GH Actions 2022-02-27 17:11:43 -08:00
Nicolas Schodet
2dd3c7bae2 scripts: gdb.py: fix error messages 2022-02-13 15:31:12 -08:00
Nicolas Schodet
de834264ab scripts: hexprog.py: minor fixes
Unused import and useless semicolon.
2022-02-13 15:31:12 -08:00
Nicolas Schodet
f8f2ab2016 scripts: stm32_mem.py: change some formatting, remove unused imports 2022-02-13 15:31:12 -08:00
Nicolas Schodet
eafc634eba scripts: more conversion to Python 3, change the shebang line 2022-02-13 15:31:12 -08:00
Nicolas Schodet
d9cce4d5e8 scripts: convert bootprog.py to Python 3
Tested with a stm32f100 bootloader.
2022-02-13 15:31:12 -08:00
Nicolas Schodet
ca9d8cd0ae scripts: fix dfu-convert.py for Python 3 and drop Python 2 support 2022-02-13 15:31:12 -08:00
Paul Mulders
ed156076a2 swlink README: correct SWO/RX2 header location for blue pill 2022-01-30 11:48:12 +01:00
Uwe Bonnes
6a9b2b8224 hosted/ftdi: Fix bad length calculation in MPSSE case of swdptap_seq_in() 2022-01-25 11:40:55 -05:00
Uwe Bonnes
266fe17461 bmp_libusb: Restrict scope of variable 2022-01-25 11:40:55 -05:00
Uwe Bonnes
e3804183f7 bmp_libusb: Fix crash with FTDI devices as outdated variable was used.
Triggered by 7b1eb6e6e3.
2022-01-25 11:40:55 -05:00
Uwe Bonnes
b1ed55a18f hosted/firmware/jtag: Fix unhandled exception introduced with da15cc3cb75cc2a9f.
Write in endianess independant way.
2022-01-22 23:46:52 -08:00
Uwe Bonnes
d594b42976 Cortexm: With connect under reset, keep the device halted until attach. 2022-01-22 14:07:42 +01:00
Piotr Esden-Tempski
d6440d716c Updated github org references to blackmagic-debug. 2022-01-21 22:09:35 -08:00
Nicolas Schodet
5c07d6170f scripts: remove import from future which imports from the past
There is no point to support Python 2.
2022-01-04 00:57:48 -08:00
Nicolas Schodet
946ccab778 scripts: stm32_mem cosmetic changes
Add a newline to avoid overwriting the last "Programming memory..."
message.

Remove inline tabs.
2022-01-04 00:57:48 -08:00
Nicolas Schodet
ad6c1eb11b scripts: fix stm32_mem.py for python 3
Python 3 does not accept a characters string where a bytes string is
needed.
2022-01-04 00:57:48 -08:00
Frank Kunz
8def28dee9 Add option bit support for STM32WLxx
Support for read/write/erase option bits.

Signed-off-by: Frank Kunz <mailinglists@kunz-im-inter.net>
2022-01-02 12:29:03 +01:00
Sean Cross
c832cb04e7 samd: add support for SAMD09
The SAMD09 CPU is used in boards such as the Adafruit Seesaw. It has a
smaller amount of memory and flash than other SAMD ports.

This was tested with an Adafruit Seesaw. These boards come with preloaded
firmware. As a test, the firmware was dumped and flash was erased. Then,
flash was verified to be all zeroes. Finally, the firmware was loaded
back in:

	(gdb) p/x *(unsigned int *)0@32
	$8 = {0x20000f88, 0x1db, 0x1d1, 0x1d9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1d9, 0x0, 0x0, 0xf5, 0x1081, 0x1d9, 0x1d9, 0x1d9, 0x1d9, 0x1d9, 0x1d9, 0x1d9, 0x0, 0x1d9, 0x1d9, 0x25e9, 0x0,
	  0x0, 0x1d9, 0x1d9, 0x1d9}
	(gdb) dump ihex memory flash.ihex 0 8192
	(gdb) mon erase_mass
	Erase successful!
	(gdb) p/x *(unsigned int *)0@32
	$9 = {0xffffffff <repeats 32 times>}
	(gdb) load flash.ihex
	Loading section .sec1, size 0x2000 lma 0x0
	Start address 0x00000000, load size 8192
	Transfer rate: 5 KB/sec, 910 bytes/write.
	(gdb) p/x *(unsigned int *)0@32
	$10 = {0x20000f88, 0x1db, 0x1d1, 0x1d9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1d9, 0x0, 0x0, 0xf5, 0x1081, 0x1d9, 0x1d9, 0x1d9, 0x1d9, 0x1d9, 0x1d9, 0x1d9, 0x0, 0x1d9, 0x1d9, 0x25e9, 0x0,
	  0x0, 0x1d9, 0x1d9, 0x1d9}
	(gdb)

Signed-off-by: Sean Cross <sean@xobs.io>
2021-12-29 15:25:51 +01:00
Sean Cross
d00607f71a samd: parameterize memory and flash sizes
Various SAMD devices have different amounts of memory. Up until now, all
SAMD devices have had the same amount, and therefore this value was
hardcoded to 32k of RAM and 256k of flash.

Add a parameter to the description field and set it to default to the
previous values. Use this description field when adding memories to the
target definition.

Signed-off-by: Sean Cross <sean@xobs.io>
2021-12-29 15:25:51 +01:00
Sean Cross
8039e2b26a crc32: define start_time when debug is enabled
The variable `start_time` indicates when a CRC32 operation began. This
variable is used to benchmark the speed of the CRC32 function.

Currently, this is tied to `PC_HOSTED`. However, the actual usage is
tied to `DEBUG_WARN`. This means that the variable is undefined when
`DEBUG_WARN` is defined and we're not configured for `PC_HOSTED` mode.

Add macro guards around this variable so that it is defined when
debugging is enabled, rather than only when building on `PC_HOSTED`.

Signed-off-by: Sean Cross <sean@xobs.io>
2021-12-28 00:25:31 -08:00
Mark Rages
f43101fd9f Port gdb.py and hexprog.py to Python 3.
Unfortunately, the serial data are not 7-bit clean (see write_mem()).
So getpacket() and putpacket() use bytes objects rather than strings.
2021-12-19 14:45:51 -08:00
Piotr Esden-Tempski
fcb2a609fc scripts: Updated nrf51 id script for py3 and to parse newer oocd header. 2021-12-19 14:45:51 -08:00
Piotr Esden-Tempski
728e955193 scripts: Updated bootprog to run on python3 2021-12-19 14:45:45 -08:00
Uwe Bonnes
3f28e728e9 cdcacm: Lower usage of magic numbers. 2021-12-18 21:44:18 -08:00
Uwe Bonnes
98e3858f7c bmp_libusb: Exclude Wireless class too. 2021-11-23 20:54:59 +01:00
Koen De Vleeschauwer
bb4151377f type of ‘assert’ defaults to ‘int’ 2021-11-22 19:51:10 +01:00
Koen De Vleeschauwer
d4cd81fa36 start_time undeclared if ENABLE_DEBUG=1 2021-11-21 12:57:30 +01:00
Uwe Bonnes
73b4612ec7 adiv5_swdp: Initialize a volatile variable
GCC did not warn about possibly missing initialization and so for gdb target
was not recognized.
2021-11-20 22:38:35 +01:00
Uwe Bonnes
5cb501049a adiv5_swdp/scan: Handle parity errors, seen with NRF52 with SYSTEMOFF #381/#949 2021-11-18 22:59:17 +01:00
UweBonnes
efa889156f
Merge pull request #948 from fabalthazar/STM32G0-OTP
STM32G0 OTP area programming and hosted monitor command allowed as preliminary action
2021-11-16 14:23:20 +01:00
fabalthazar
b4ac52d1f5 Hosted monitor command allowed as preliminary command 2021-11-15 21:20:38 +01:00
fabalthazar
71b67beb98 Fix: assert flashing succeeded or failed (hosted) once the last buffer has been written 2021-11-15 21:19:08 +01:00
fabalthazar
92d6056711 STM32G0 OTP area programming 2021-11-15 21:19:08 +01:00
Koen De Vleeschauwer
73624826b6 semihosting exit code 2021-11-14 12:03:33 +01:00
UweBonnes
59dc225568
Merge pull request #937 from UweBonnes/CMSIS-DAP
CMSIS-DAP/ADIv5 fixes for #936 and #925
2021-11-11 22:06:02 +01:00
Uwe Bonnes
1d0e45bdbb cmsis_dap: Transfersize of block commands needs to cope with word.
Checkme: Dragonprobe bulk hangs on transfers with 15 words.
2021-11-02 18:17:12 +01:00
Uwe Bonnes
8970160f1d cmsis_dap: Timeout and start of error handling for bulk transfers. 2021-11-02 18:17:12 +01:00
Uwe Bonnes
2bc2db1140 cmsis_da: Add timeout to bulk commands. 2021-11-02 18:17:12 +01:00
Uwe Bonnes
a4caec29b9 dap_swdptap_seq_out: Write only needed data
Dragonprobe (origin/cmsisdap-fixes, 211031) hanged on additional byes in the
SWJ_Sequence request.
2021-11-02 18:17:03 +01:00
Uwe Bonnes
181466549b adiv5: Progressive incrementing TRNCNT for the DHCSR write when trying to halt
Workaround for CMSIS-DAP/Bulk debugger orbtrace  that returns NO_ACK
with high values of TRNCNT. Perhaps only STM32F767 needs write to DHCSR
with high occupancy to catch the device in a moment not sleeping.
2021-10-31 12:55:41 +01:00
Uwe Bonnes
07b4e5726e CMSIS-DAP: Run time detect DAP_SWD_SEQUENCE
Some dongles in the making like orbtrace may not yet support.
2021-10-31 12:55:41 +01:00
Uwe Bonnes
88e44d1c12 cmsis: use exception in wait_word(). 2021-10-31 12:55:41 +01:00
Uwe Bonnes
a1d4649795 SWD: Use dp_low_write to allow multidrop scan. 2021-10-31 12:55:41 +01:00
Uwe Bonnes
4f36c1ddf8 Remove dp_low_read() and use exception protected dp_read() 2021-10-31 12:55:41 +01:00
Uwe Bonnes
f9d343af3e cmsis: AP reads are posted. Read from RDBUFF. 2021-10-31 12:55:41 +01:00
Uwe Bonnes
d4ae308f9f cmsis: implement srst_set_val() 2021-10-31 12:55:41 +01:00
Uwe Bonnes
166eb3ee3e cmsis_dap: Always transfer 65 bytes with hid_read|write()
CMSIS-DAP Dragonprobe works on some devices. E.g. it does not work
on NUCLEO-F103
2021-10-31 12:55:41 +01:00
Uwe Bonnes
b343ebe06f cmsis-dap/linux: Link against libhidapi-hidraw
libhidapi-libusb detaches a kernel module but does not reattach again.
This may wrack interaction with other programs using hidapi.
2021-10-31 12:55:41 +01:00
Uwe Bonnes
d144f9d54b adiv5: CMSIS DAP transactions are slow but work in principle
Slowness results in strange STM32F767 DHCSR implementation to nearly never
halt in the given 2 second period when F767 is sleeping most of the time.
2021-10-31 12:55:41 +01:00
Uwe Bonnes
761e0230d4 cmsis-dap: Print messages when transfers fail.
Expect signal integrity errors when using jumper cables. Often probes switch
the SWJ GPIO with highest speed, resulting in possible reflections. Additional
ground wires may help. If there is isolation between probe and targets,
additional ground wires are a must or ground shift will wrack the transfer!
2021-10-31 12:55:41 +01:00
Uwe Bonnes
39fbffd3d2 stlinkv2: Fix low access to AP registers. 2021-10-31 12:55:41 +01:00
Uwe Bonnes
c13778139f adiv5/hosted: Export the BMP_TYPE in DP. 2021-10-31 12:55:41 +01:00
Uwe Bonnes
b7e7aa3f9a adiv5: Either use only LL functions in cortexm_initial_halt or no LL at all.
Platform implementation may disturb ADIV5_AP_DRW and so low_read DHCSR may
give values other from registers
2021-10-31 12:55:41 +01:00
Uwe Bonnes
485105221e dap: Always work on a copy of the buffer when calling dbg_dap_cmd() in a loop
A better solution would use seperate buffers for dbg_dap_cmd. But as WAIT is
already handled in DAP, cahnces are low that loop re-entry is needed.
2021-10-31 12:55:41 +01:00
Uwe Bonnes
397fbd5749 cmsis: Only cmsis internal use must differentiate between HID and Bulk access
Missing DAP_SWD_SEQUENCE may eventually need a distinction visible from
outside later.
2021-10-31 12:55:41 +01:00
Uwe Bonnes
7b1eb6e6e3 bmp_libusb: reset type on every device. 2021-10-31 12:53:47 +01:00
Uwe Bonnes
80064c18a9 bmp_libusb: Fix CMSIS-DAP related memory leak. 2021-10-31 11:13:34 +01:00
Uwe Bonnes
8845a22226 stm32l4: Use targetid when available.
Fixes STM32U5 from crashing.
2021-10-31 11:13:34 +01:00
Uwe Bonnes
c4b6b42dcf stlinkv2: Read targetid on DPv2 devices. 2021-10-31 11:13:34 +01:00
Uwe Bonnes
5dafc0828c SWD: Remove excessive line resets. 2021-10-31 11:12:46 +01:00
Uwe Bonnes
e7e1bfdb53 mpsse: Fix using 60 MHz clock on fast devices. 2021-10-30 13:55:57 +02:00
Uwe Bonnes
99a5fdb6f8 bmp_remote: Better error propagation.
Negative values from platform_buffer_read are errors too!
2021-10-30 13:55:57 +02:00
Uwe Bonnes
f4117aa1b4 cdcacm: Use the USB strings. 2021-10-30 13:55:57 +02:00
Uwe Bonnes
f28f05952f stlink: Add another STLINK-V3 ID. 2021-10-30 13:55:57 +02:00
SG
7307f086c6
Support for STM32WB55 (#942)
* add STM32WB55 support
2021-10-30 13:01:06 +02:00
Uwe Bonnes
e1a928beb1 Fixes to compile with gcc11 #925
Target code changes are pure for formal correctness and not tested!
2021-10-10 15:59:57 +02:00
UweBonnes
28623e6b27
Merge pull request #939 from fabalthazar/hosted-return-val
Consistent return value and output of hosted blackmagic + HOSTED_BMP_ONLY=0 on Linux
2021-10-10 12:54:48 +02:00
fabalthazar
e2d3161442 Removed -S message as debugger selection option since it is used for reading bytes 2021-10-09 21:38:48 +02:00
fabalthazar
59282b6f66 Fixed typography 2021-10-09 21:18:52 +02:00
fabalthazar
7274f55ff4 Fixed return value of hosted blackmagic in erase mode 2021-10-09 21:17:58 +02:00
fabalthazar
3f54fba986 HOSTED_BMP_ONLY=0 by default on Linux.
The user is warned about missing dependencies.
2021-10-09 21:14:52 +02:00
Vegard Storheil Eriksen
7ccbdd98c0 hosted/dap: Copy command buffer in wait/retry loop.
The same buffer is used for both command and response, causing part of
the command to be overwritten before it’s retried. Solve this by saving
and restoring a copy of the command before retrying.
2021-10-05 23:21:07 +02:00
Jeff Lutgen
f69f29a660 f4discovery/blackpill: fix usbusart 2021-10-01 00:10:03 +02:00
Uwe Bonnes
b076d5cea1 stm32f1: Check if unlock failed and propagate error. 2021-09-22 21:41:43 +02:00
Uwe Bonnes
554e34517e Better reporting when monitor command fails. 2021-09-22 21:41:43 +02:00
Uwe Bonnes
9e98cfa220 adiv5: Remove leftover debug output. 2021-09-22 21:41:43 +02:00
Thiadmer Riemersma
64f756d627 Test voltage on VREF before enabling target power (mon tpwr), to avoid potential power conflict. 2021-09-22 20:45:18 +02:00
Uwe Bonnes
88cce08ce4 hosted: Fix "monitor version" 2021-09-22 15:16:20 +02:00
Uwe Bonnes
da15cc3cb7 remote_jtagtap: Fix memory corruption in jtagtap_tdi_tdo_seq 2021-09-22 15:16:20 +02:00
Uwe Bonnes
356325f563 ftdi_bmp: Fix bit select. 2021-09-22 15:16:20 +02:00
Uwe Bonnes
a93e57e112 ftdi: Fixed wrong direction report in DEBUG. 2021-09-22 15:16:20 +02:00
Uwe Bonnes
79066c950f bmp_libusb: Remove duplicated libusb_init.
Thanks to Red Liu for noticing
2021-09-22 15:16:20 +02:00
Uwe Bonnes
9de69bb3ab Adiv5/Initial halt: More fixes for dd28fa5743. #925
Stlink does not like low level access and aborts with STLINK_SWD_DP_ERROR.
Either our implementation still has faults or stlink can not handle

MINDP devices with BMP/Firmware also seemm not to like low level access,
either du to some hidden error in BMP or by design
2021-09-22 15:16:20 +02:00
Uwe Bonnes
9ebc44bcea Make more functions static. 2021-09-22 15:16:20 +02:00
Uwe Bonnes
db1f13db25 remote: Packets may be larger than 256 bytes. 2021-09-22 15:16:20 +02:00
Uwe Bonnes
a9854e9b37 adiv5: Fix the MINDP case introduced with dd28fa5743 #925 2021-09-16 12:39:26 +02:00
Andy Makovec
01583560cd hosted: Update Readme.md to use HOSTED_BMP_ONLY 2021-09-16 11:02:31 +02:00
dpc
f66caa0d29 add some more nxp s32k14x variants
the sdid bits correspond to s32k14x as well as s32k11x but i only have
access to the k14x variants so didn't bother w/ the k11x variants.
the memory/flash sizes also can come from the sdid bits, but the
splits still need to come from a lookup.
2021-09-13 23:01:05 +02:00
dpc
95288bcf75 fix a size format warning 2021-09-13 23:01:05 +02:00
Uwe Bonnes
e58b7d623b crc32: Abort generic_crc32 with error from target_mem_read
Use larger chunks for hosted to speed up. Send pure NULL as line keep-alive.
2021-09-07 10:57:17 +02:00
Uwe Bonnes
ff79108f66 cl_utils: Increase worksize for increased speed.
H743 reads 2 MB in ~23 vs 27 seconds
2021-09-07 10:57:17 +02:00
Uwe Bonnes
a76a559656 pc/platform_delay: Wait ms and not us! 2021-09-07 10:57:17 +02:00
Uwe Bonnes
dd28fa5743 adiv5: Tighten up loop to initial halt cortexm
Use TRNCNT when available.

Now the F767 with the NutOS 300 ms sleep example  with the one ms tick is
halted even in hosted after few ms.
2021-09-04 21:15:07 +02:00
Uwe Bonnes
a297c8c8ad hosted/Makefile.inc: Use gcc to build hosted, if not advised otherwise 2021-09-04 21:15:07 +02:00
Uwe Bonnes
698cfeb1f4 bmp_serial: Nag MACOS programmer to implement find_debuggers! 2021-09-04 21:15:07 +02:00
Thiadmer Riemersma
35687018eb Escape '*' in responses of the Remote Serial Protocol, to avoid that it is interpreted as the start of an RLE sequence 2021-08-31 15:44:17 +02:00
Jason Kotzin
a6f9701368 Adding schematic, use adobe, has a 3D step built in 2021-08-15 22:22:09 -07:00
Jason Kotzin
237d6b89f6 Updating Readme 2021-08-15 22:18:41 -07:00
Jason Kotzin
2b89a07dae samd: adding bootprotect and unlock commands 2021-08-15 21:50:54 -07:00
Uwe Bonnes
863a41daac adiv5_swdp: Initialize initial_dp with the definition 2021-08-15 16:43:29 +02:00
Uwe Bonnes
49122b50b6 hosted: Make HOSTED_BMP_ONLY the default.
Hopefully more people will use it when reporting errors!
2021-08-15 16:43:29 +02:00
Uwe Bonnes
2fcd4a878a ftdi_bmp.h: Fix error when compiling with HOSTED_BMP_ONLY=1 2021-08-15 16:43:29 +02:00
Uwe Bonnes
6308506276 jtag: Make jtag_devs argument to jtag_handler. 2021-08-15 16:43:29 +02:00
Uwe Bonnes
6dff2a9f31 target: target_error_check now defaults to not indicate error.
Remove unneeded nop_function from efm32
2021-08-15 16:43:29 +02:00
Uwe Bonnes
f7670fcd44 ftdi_bmp: Add verbosity for libftdi_jtagtap_tdi_tdo_seq() 2021-08-15 16:43:29 +02:00
Uwe Bonnes
3df692ecb2 adiv5_swdp_scan: If SWD scan fails, try a JTAG scan. 2021-08-15 16:43:29 +02:00
Uwe Bonnes
5c8e277663 hosted/dap: Fix tdi_tdo_seq. 2021-08-15 16:43:29 +02:00
Uwe Bonnes
2d4a503135 jtag_scan: Rework chain detection
Fixme: stlinkv2/hosted probably does only handle STM devices. Check if
jtag_devs.c really needed.
2021-08-15 16:43:29 +02:00
Uwe Bonnes
e1a1865de9 remote/jtagtap_tdi_tdo_seq: Split up large transactions.
FIXME: One remote transaction still can only do up to 64 ticks, leaving
room for speed enhancement with larger transactions.
Firmware assumes  (1LL << 65) == 0LL !
2021-08-15 16:43:29 +02:00
Uwe Bonnes
8084a75634 cl_utils: Allow Hardware reset from the command line 2021-08-15 16:43:29 +02:00
Uwe Bonnes
36836d0746 ftdi_bmp: Fix setting bits and FTDIJTAG srst. 2021-08-15 16:43:29 +02:00
Uwe Bonnes
cfdf55855e ftdi_bmp: Export and use reset functions. 2021-08-15 16:43:29 +02:00
Uwe Bonnes
1845d71f00 jtag_scan: Deliver full idcode to the handler. 2021-08-15 16:43:29 +02:00
Uwe Bonnes
0d78331149 remote/jtag_tdi_tdo_seq: Fix wrong bitmask calculation. 2021-08-15 16:43:29 +02:00
Thiadmer Riemersma
c7bc4b6a5d Bug fix in Flash erase function for LPC MCUs. 2021-08-13 16:18:53 +02:00
aam335
5eb43a1ddb platforms: stm32f4x1 blackpillv2 as variant of f4discovery
Compile as make PROBE_HOST=f4discovery BLACKPILL=1
2021-08-13 16:18:05 +02:00
Thiadmer Riemersma
be534a9c5e Turn error LED off after successful attach to target (error LED blinks on 'target lost'). 2021-08-13 16:10:37 +02:00
Thiadmer Riemersma
72bd825a60 Add support for NXP LPC11xx XL series, add 'readuid' command for some MCUs of the LPC11xx series where it was missing; add comments mapping Device IDs to part descriptions. 2021-07-31 16:08:34 +02:00
Uwe Bonnes
6d6a67b44b timeout: Make sure we wait at least the period requested (#900, #902)
Fixes bug introduced with last commit( Recover from bad AP access)

Let STM32 timers run at 100 Hz against 10 Hz before.

Programming STM32F103 failed random (#900) with 20 ms timeout requested
against the 100 ms timeout granularity provided up to now.

STM32 Firmware only ticked at 10 hertz, so the sequence "low_access",
"set timeout", "send out 8 bit command", "read 3 bit result" when
reading "wait" and timer increment tick happening during that sequence
will already hits the timeout even so only mininal time has elapsed
and not the requested timeout.
2021-07-27 10:59:03 +02:00
Uwe Bonnes
0c63903071 adiv5: Recover from bad AP access.
E.g. AP1 on a STM32WLE5 points to a ROM table, but access to the ROM table
via AP1 hangs forever.
- Substantial reduce timeout when wait for a response. Valid access should
  succeed fast.
- Abort AP access to free DP for other accesses
- Don't throw exception, only set dp->fault
- React on higher level
2021-07-15 15:06:54 +02:00
Uwe Bonnes
b887a8d355 stm32: Portability changes
Allow to compile on STM32F0 platform too.
2021-07-15 15:06:54 +02:00
UweBonnes
41719c5559
Merge pull request #897 from UweBonnes/fixes
bmp_libusb: Check only for cmsis_dap if no cable has been found yet.
2021-06-18 12:13:19 +02:00
Uwe Bonnes
3cfd8226ba bmp_libusb: Check only for cmsis_dap if no cable has been found yet. 2021-06-18 11:44:50 +02:00
UweBonnes
a0dbb2a787
Merge pull request #896 from RadinnAB/for-upstream
Add nRF51 erase UICR command and fix some warnings
2021-06-07 17:43:56 +02:00
fabalthazar
ea4b232996 Fix de83dbb: duplicate BMP_MODE_FLASH_VERIFY -> BMP_MODE_FLASH_WRITE_VERIFY 2021-06-07 17:29:41 +02:00
Björn Mellström
5ea01030e2 Add nRF51 command for (only) erasing the UICR registers
Original implementation by: Benjamin Vedder <benjamin@vedder.se>
2021-06-07 13:50:36 +02:00
Björn Mellström
d987a8dd8c Add define to allow platform override of debug printf function 2021-06-04 06:58:29 +02:00
Björn Mellström
4b8c4990dc Fix warning about unused variable in adiv5.c
This happens if the platform has debugging support but debugging
is not enabled.
2021-06-03 12:56:41 +02:00
Björn Mellström
711a87f7ba Fix some warnings when compiling with -Wshadow
There are still a few more places that would need to be corrected
before -Wshadow could be added by default.
2021-06-03 12:55:28 +02:00
Björn Mellström
53f022d29b Require semicolon after debug log statements
This also fixes a warning about an empty body in cortexm.c
if PLATFORM_HAS_DEBUG is defined but debugging is not enabled:

    if (platform_timeout_is_expired(&to))
        DEBUG_WARN("Reset seem to be stuck low!\n");
2021-06-03 12:52:07 +02:00
Björn Mellström
04eab8e1f8 Add guard around _GNU_SOURCE define
This avoids warnings if the define has already been set by the
build system.
2021-06-03 12:51:27 +02:00
Uwe Bonnes
2a0d608b07 hosted: Fix last commit
-Wno-format-truncation may not be understood by all systems
2021-06-01 18:42:37 +02:00
Uwe Bonnes
1b49823f64 Fix hosted compile on MacOS. hidapi-libusb has a different name 2021-06-01 16:58:25 +02:00
Uwe Bonnes
de83dbb7e2 cl-utils: Fix bug introduced with 5288eef6171b9cff194fbeb087bc942bad08d9db
Always use the file size for write and verify.
2021-06-01 16:23:19 +02:00
Uwe Bonnes
c0437e7b25 bmp_serial: Autodetect more BMP string variants. 2021-06-01 16:23:19 +02:00
Uwe Bonnes
891633322a lpc: Care for protected pages on LPC80x devices. 2021-06-01 16:23:19 +02:00
Uwe Bonnes
f7b4697280 lpc11xx/lpc8c04: Do not expose two top system flash sectors. 2021-06-01 16:23:19 +02:00
Uwe Bonnes
42ebcac329 efm32_devices: Rearrange struct efm32_device_t to save flash space. 2021-06-01 16:23:19 +02:00
Uwe Bonnes
21a702dc1e lpc: More verbosity and more definitions 2021-06-01 16:23:19 +02:00
Uwe Bonnes
6454d0bc96 bmp_libusb: Invalidate manufacturer and product in case libusb_get_string_descriptor_ascii fails.
Prevent more false detections
2021-05-20 12:06:56 +02:00
Uwe Bonnes
df575eb090 stm32_mem.py: Wait longer for device to appear. 2021-05-20 12:06:56 +02:00
Uwe Bonnes
7f1a560288 stm32/usbuart: Clear USART_ICR if provided.
Otherwise endless interrupts happened.
2021-05-20 12:06:56 +02:00
Uwe Bonnes
90534b3cf6 stm32: portability enhancements
Needed for e.g. stlinkv3
2021-05-20 12:06:56 +02:00
Uwe Bonnes
87acd99fe4 cortexm: For Cortex-M0+ devices, probe also for lpc11 to detect LPC80 #884 2021-05-18 12:24:00 +02:00
Uwe Bonnes
cb4cff2c71 hosted/ftdi: Compare only for length of the string given in the header
Devices may have added version like "Tigard V1.1" vs "Tigard"
2021-05-18 12:24:00 +02:00
Uwe Bonnes
c3fd198f0d bmp_libusb: Reject non-BMP devices with VID 1d50. 2021-05-18 12:24:00 +02:00
Uwe Bonnes
36ad6efc6f cmsis_dap.h: Fix wrong leftover argument. 2021-05-16 17:17:33 +02:00
Uwe Bonnes
f0dd8c9517 cl_utils: List -l option in the help. 2021-05-16 17:17:33 +02:00
Uwe Bonnes
517d5b5b31 rp: Show spinner only when called from monitor command. 2021-05-16 11:26:14 +02:00
James Turton
0ab10fee0b rp: Increase timeout for flash_range_program
If the RP2040 is using the ring oscilator (ROSC) rather than the crystal
oscilator (XOSC) then flashing program will take much longer. As the XOSC is not
enabled at boot we should not assume it will be enabled before the debugger is
connected (or indeed at all), thus should use the longer timeout during load
commands.
2021-05-16 11:26:14 +02:00
James Turton
ff30259354 rp: Add more debug logging during flash 2021-05-16 11:26:14 +02:00
James Turton
e453740aca rp: Increase spinner timeout to 500ms
Increasing spinner timeout to 500 means `tc_printf` is not called during
the `_flash_range_erase`. This is important as `_flash_range_erase` is
used when loading. This fixes the issue:
https://github.com/blacksphere/blackmagic/issues/875
Also adding spinner timeout counter to reduce bus traffic.
2021-05-16 11:26:14 +02:00
James Turton
67c9003522 rp: Flush cache after erase and write
The RP2040 datasheet suggests that _flash_flush_cache and _flash_enter_cmd_xip
should be called after erasing and writing to flash.
2021-05-16 11:26:14 +02:00
James Turton
f880734050 Fix compiling for native probe 2021-05-16 11:26:14 +02:00
Uwe Bonnes
e4421799ba More header cleanup 2021-05-15 12:54:51 +02:00
Uwe Bonnes
8e438b9e5f Add missing headers and remove double typedef. 2021-05-14 19:58:16 +02:00
Uwe Bonnes
cfbe9f1c94 pc/gdb_if.c: More verbosity for Error messages #873
Thanks to "pshri" for dissecting and adding messages, as  problems with
Hpyer-V and port permissions happened on Win10
2021-05-09 11:49:32 +02:00
UweBonnes
8089e05a00
Merge pull request #871 from zyp/cmsis_dap
CMSIS-DAP improvements
2021-04-30 13:06:49 +02:00
Vegard Storheil Eriksen
f121350fc9 hosted/cmsis_dap: Verify that a v2 interface has endpoints. 2021-04-27 11:39:43 +02:00
Vegard Storheil Eriksen
494524dd85 hosted/cmsis_dap: Add v2 support. 2021-04-27 10:26:06 +02:00
Vegard Storheil Eriksen
4f52a7b235 hosted/cmsis_dap: Add discovery by interface string and prepare for v2 support. 2021-04-26 21:56:24 +02:00
Vegard Storheil Eriksen
c4874fdf44 hosted/dap: Add parentheses around bitwise operator. 2021-04-26 21:54:38 +02:00
Uwe Bonnes
f9414d5826 cmsis-dap: Handle ADI DP22 devices on probes not multidrop capable. 2021-04-26 18:18:18 +02:00
Uwe Bonnes
923edc7f7e cmsis-dap: Fix wrong handling when reading data not word-aligned 2021-04-26 15:08:09 +02:00
UweBonnes
96bec7e3fb
Merge pull request #868 from UweBonnes/fixes
Revert "cmsis_dap: Always write full reportsize + 1 buffers"
2021-04-25 23:14:34 +02:00
Uwe Bonnes
877a6e694c Revert "cmsis_dap: Always write full reportsize + 1 buffers"
This reverts commit 61e237ec87c525876817e72fc82ce28b2a4951ae.
This makes a CMSIS-DAP probe with version < 1.2 work again on DP V1 devices.
Status of other combination unknown:
    DP  V1 V2 V2/Multidrop
Probe
<  1.2  ok ok --
>= 1.2   ? ?  ?
2021-04-25 22:53:40 +02:00
UweBonnes
da2fb7f210
Merge pull request #867 from UweBonnes/clean-static-from_probe
Clean static from probe

Some target probe functions used static RAM variables. This will fail if several of the same targets are in the JTAG/SWD chain and unnecessary remove RAM form the RAM pool if the target is not used. If the target needs more than one word, it allocated priv_storage is used. For a single needed word, one word has been added to the target structure as a union to allow decent naming.
2021-04-25 16:25:19 +02:00
Uwe Bonnes
1f67bab475 nxpke04: Move unsafe_enables to target bool union. 2021-04-25 16:03:23 +02:00
Uwe Bonnes
f87dff8d83 kinetis: Remove static variables, add word union to target_s.
Add a word union to target structure to hold a single word variable.
2021-04-25 16:03:23 +02:00
Uwe Bonnes
ac7c1057cc efm32/samd/samx5x: Remove static allocates strings. Allocate in priv_storage.
Static allocated variables in the different targets eat up common RAM and
will collide in chains with multiple similar targets.
2021-04-25 16:03:23 +02:00
Uwe Bonnes
cddf02f174 samx5: Verbose error reports on protected devices. 2021-04-25 16:03:23 +02:00
Uwe Bonnes
1330288271 firmware: Unify serial number handling
Use one file in dfu and server
For STM32, provide 3 ways to handle
- BMP way (8 bytes)
- DFU way (12 Bytes)
- Full unique id (24 Bytes), as with STLINK(V3) Bootloader
2021-04-25 16:02:20 +02:00
Uwe Bonnes
8c8aa980cf adiv5: Detect unprotected SAMD5x only once 2021-04-25 16:02:20 +02:00
Uwe Bonnes
f98b7274b4 hosted/stlinkv3: Detect STlinkV3 in bootloader mode. 2021-04-25 16:02:20 +02:00
Uwe Bonnes
a83700d1cf stm32/usbuart: DMA stream handling is not STM32F4 specific 2021-04-25 16:02:20 +02:00
UweBonnes
8da2dee0c4
Merge pull request #857 from UweBonnes/rp
Support the Raspberry Pico RP2040

    Implement multi-drop
    Recognize , erase, flash and usb_reset
    Attach to the rescue DP will reset but attach itself fails.
2021-04-25 15:48:35 +02:00
Uwe Bonnes
1b26ff560d rp.c: Add reset_usb_boot as monitor command 2021-04-24 14:48:58 +02:00
Uwe Bonnes
52bffa70cf rp: Handle flash.
- Beware, after reset, only a valid flash payload get mapped to XIP!
  Only 0 is read from flash when flash image is not valid
2021-04-21 21:55:03 +02:00
Uwe Bonnes
2b0e255c40 cortexm: timeout and debug for run_stub() 2021-04-21 21:50:38 +02:00
Uwe Bonnes
61efe26348 swdp_scan: Break infinite loop after Dormant->SWD transition. 2021-04-21 21:50:38 +02:00
Uwe Bonnes
fa5e69e3be RP 2040: Special handling for rescue DP
As the rescue DP provided no AP, trigger the reset with attach().
However attach will indicate failure also reset/halt has succeeded.
2021-04-21 21:50:38 +02:00
Uwe Bonnes
ea92c8b8c8 cmsis-dap: Allow to use adiv5_swdp_scan. 2021-04-21 21:50:38 +02:00
Uwe Bonnes
23f942ac8c Raspberry RP2040: Recognize. No flash handling yet. 2021-04-21 21:50:35 +02:00
Uwe Bonnes
04d1c9805b swd: Remove swd_proc and swdptap.h. 2021-04-21 21:50:04 +02:00
Uwe Bonnes
b6fbf86743 Extend ADIv5_DP_t for low level routines needed for multi-drop.
Will replace swd_proc
2021-04-21 21:50:04 +02:00
Uwe Bonnes
61e237ec87 cmsis_dap: Always write full reportsize + 1 buffers
Expect short reads and other errors else
2021-04-21 21:50:04 +02:00
Uwe Bonnes
d6ade4d94e cmsis-dap: Use SWD_SEQUENCE if available. 2021-04-21 21:50:04 +02:00
Uwe Bonnes
5abb288c7a hosted: Provide the DP functions in swd_proc. 2021-04-21 21:50:04 +02:00
Uwe Bonnes
fa561c8d66 adiv5_swdp: Starting point to handle multi-drop
- RP2040 show both DPs
- Multidrop test with STM32L552 and STM32H745 allows selection
  with "-m 0x4500041" (H7), "-m 1" (L552) or "-m 0x01002927" (RP2040)
2021-04-21 21:50:04 +02:00
Uwe Bonnes
be3bfc48a8 cortexm: M33 has up to 8 hardware breakpoints 2021-04-21 21:22:59 +02:00
Uwe Bonnes
65f08cd46d README.md(top): Mention hosted build for BMP only. 2021-04-21 21:22:59 +02:00
Uwe Bonnes
b1ac4187b9 Fix some formatting strings for 32-bit compile 2021-04-21 21:22:59 +02:00
Uwe Bonnes
637d76b585 cl_utils.c: Try jtag scan if swd scan did not give results. 2021-04-21 21:22:59 +02:00
Uwe Bonnes
5288eef617 cl_utils: With no size given, read the size of the lowest block. 2021-04-20 18:48:27 +02:00
Fabio Baltieri
beaccf2714 target: stm32l4: add support for STM32WLxx
This adds support for the STM32WL series in stm32l4.c. These parts have
the same flash registers layout as the L4 series, but a different base.
Since there are already two sets of registers in this target file, this
adds support for register maps that can be customized for each device
ID.
2021-04-20 18:42:36 +02:00
Uwe Bonnes
21b80949ff Compile with -Os as default. Change like "make OPT_FLAGS=..."
SWD/JTAG Bitbang is compiled with -O3 for good bitbang speed.
2021-04-20 18:20:41 +02:00
Fabio Baltieri
f55ad67b1b adiv5: catch timeout on adiv5_ap_read_id and abort
This adds a TRY_CATCH around the adiv5_ap_read_id() in
adiv5_component_probe() and resets the DP when that happens.
It seems like the STM32WLE5 comes with the AP of the inactive core
enabled in a way that does not make it detectable, and the current code
times out and leaves the whole device hanging.

Catching the timeout and calling adiv5_dp_abort() seems to restore the
device to a useable state.

Tested on Seed LoRa-E5 (STM32E5JC).
2021-04-19 16:57:13 +02:00
Vestrel
806787529f Use DMA for USBUSART TX/RX 2021-04-17 17:57:08 +02:00
Uwe Bonnes
cf5b4afb38 bmp_serial/linux: Honor opt_list_only (-l). 2021-04-17 16:19:57 +02:00
fabalthazar
d6b24c00c8 Fixed STM32G43x/G44x option bytes support
Previously took L4 values so FLASH_SEC1R was not applied
2021-04-17 14:44:30 +02:00
fabalthazar
99f9557cc0 Support for STM32G49x/G4Ax (category 4) 2021-04-17 14:44:30 +02:00
fabalthazar
c85c946ce3 PRIx32 fix 2021-04-17 14:44:30 +02:00
Stoyan Shopov
9ec7d05d8d Put null terminating characters when scanning for BMP probes on linux
This patch puts null terminating characters for the 'type',
'version', and 'serial' strings extracted from blackmagic probe
id strings on linux systems.
2021-04-17 14:41:28 +02:00
Uwe Bonnes
2d293ec755 travis: Use bionic instead of trusty.
No more need to compile libftdi1.
2021-04-17 13:35:21 +02:00
Uwe Bonnes
299da8627c libftdi: Remove unneeded explicit path. 2021-04-17 13:35:21 +02:00
Uwe Bonnes
a6a8606edb STM32L55: Detect, memory map, read and flash write. Options handling missing.
Only non-secure states considered!
2021-04-04 17:26:31 +02:00
UweBonnes
db17f2caa8
Merge pull request #847 from fabalthazar/bugfix-845-hosted_verify
Bugfix 845 - hosted verify right after programming
2021-04-02 16:23:50 +02:00
fabalthazar
739941dc5f Verify right after programming 2021-03-31 13:06:52 +02:00
fabalthazar
2982888b66 BMP_MODE_FLASH_WRITE_VERIFY combined operation 2021-03-31 12:07:53 +02:00
fabalthazar
f85c54be97 Prepared -w option 2021-03-31 12:07:53 +02:00
fabalthazar
6d6cfd6c98 Comprehensive STM32G03/4/5/6/7/8/B/C driver 2021-03-29 21:42:40 +02:00
UweBonnes
fb8492a7e5
Merge pull request #846 from UweBonnes/cortexm_halt
Cortexm halt
2021-03-26 20:38:31 +01:00
Uwe Bonnes
58f153e12b cortexm: Always halt and release reset before romtable scan
Only release from halt once after romtable scan
Should fix #836.
2021-03-26 17:43:11 +01:00
Uwe Bonnes
a025c9a7bd Revert "stm32f1: On ST parts there is no need to read IDCODE again."
Romtable partno is not unique for devices, e.g. in STM32F0
This reverts commit f89b07d892c6034ea68494a72e047b2c437754f7.
2021-03-26 17:35:00 +01:00
Uwe Bonnes
f89b07d892 stm32f1: On ST parts there is no need to read IDCODE again.
IDCODE is already known from the Romtable
Probably this has the same effect as #836
2021-03-12 20:45:34 +01:00
Uwe Bonnes
e6a9a1a366 cmsis-dap: Get the firmware version. 2021-03-06 13:30:09 +01:00
Uwe Bonnes
7859a2aabd adiv5_swd: Factor out creation of packet request. 2021-03-06 13:30:09 +01:00
Uwe Bonnes
cfb784d428 adiv5: Fix comments and debug output 2021-03-05 16:49:19 +01:00
Uwe Bonnes
3aa6f16964 serial_unix: Split timeout in seconds and microseconds
Macos exposed errors when tv_usec was > 1000000.
2021-03-05 16:49:19 +01:00
Uwe Bonnes
43770736f1 cl_utils: Rework Flash/Ram printout 2021-03-05 16:49:19 +01:00
Thiadmer Riemersma
560a046a22 Add support for NXP LPC802, LPC804, LPC832 and LPC834 2021-02-22 19:37:46 +01:00
Uwe Bonnes
aeae9f7cde UsingSWO: Revisit Baudrate calculation and limits.
There are more SWO frequency options than the old documents indicated
2021-02-19 18:48:02 +01:00
Uwe Bonnes
0df44e205b ADIv5: Abort Romtable scan also if CIDR0 is invalid after halting #832
STM32WLE5 has the same dual core chip as STM32WL5. For the second
core, the additional AP can be see, but access to e.g. CIDR0 for that
Romtable fails.
Aborting the scan too if again the second read of CIDR0 fails makes
sense anyways!
2021-02-19 18:48:02 +01:00
Uwe Bonnes
d70fa8c7f6 hosted: Remove restrictions when gathering information on the debugger
That way, we find RPI Pico pico-debug.
2021-02-15 17:47:29 +01:00
Uwe Bonnes
c776e7a9a6 swd_scan: Add '-m' as targetid argument to swd_scan to prepare multi-drop.
In a real multi-drop setup, the device to use must be specified.
2021-02-15 17:47:29 +01:00
Uwe Bonnes
8e2f6937d5 hosted: Run target specific monitor commands with -M "command" .
Lists available commands: "blackmagic -M help"
Quote multi argument monitor commands, e.g. STM32F1: blackmagic -M "option help"
2021-02-15 17:47:29 +01:00
Uwe Bonnes
165560edd8 cl_utils: target selection '-n' argument needs optarg.
foreach now returns the number of targets.
2021-02-15 17:47:29 +01:00
Uwe Bonnes
4eb336277c native: Remove high current draw (#814)
Special iRST_SENSE handling does not apply at least for BMP 2.1c.
On V2.1c, iRST_SENSE was set as output high and xRST high shorted
iRST_SENSE to ground via Q2
FIXME: Check for older versions!
2021-02-15 15:00:19 +01:00
Martin
3b8502c2e5 add space in USB product string (be consistent with ../stm32/dfucore.c)
This changes the USB identification from
"Black Magic Probe(STLINK/V2) v..." to
"Black Magic Probe (STLINK/V2) v..."

Signed-off-by: Martin <Ho-Ro@users.noreply.github.com>
2021-01-29 14:47:28 +01:00
Martin
d4dc3b2717 The USB CDC is no modem and does not use the AT protocol
Signed-off-by: Martin <Ho-Ro@users.noreply.github.com>
2021-01-29 14:47:28 +01:00
Alex Norman
42f590ce0b fixing some memory map errors for stm32h7, PR #821 2020-12-23 20:10:39 +01:00
Uwe Bonnes
09c000eca8 hosted: Really handle setting tpwr on remote on the command line #817
Expect the command to fail, due to old firmware or remote not implementing
the power switch.
2020-12-19 16:36:09 +01:00
Sean Cross
c49c895f39 gitattributes: add attributes file
On different platforms, line endings can differ. Git tries to
intelligently convert source code to match native line endings when
doing a checkout, unless a particular configuration flag is set.

An alternate approach is to create a `.gitattributes` file and manually
specify various types of files. This ensures files are properly handled.
It also prevents git from creating patches that consist of nothing more
than replacing line endings.

Signed-off-by: Sean Cross <sean@xobs.io>
2020-12-16 12:51:09 +01:00
Sean Cross
2b06f045c4 target: kinetis: add S32K148
This adds support for the NXP S32K148. This is an automotive-grade part
that is derived from the Kinetis line, so it has a very similar
interface to other parts in the family.

Signed-off-by: Sean Cross <sean@xobs.io>
2020-12-16 12:49:23 +01:00
Sean Cross
5f76169b95 hosted: remove ftdi include when built with BMP_ONLY #811
Signed-off-by: Sean Cross <sean@xobs.io>
2020-12-16 11:30:42 +01:00
Uwe Bonnes
98c92a6d18 hosted: Really fix the case of no serial number (#807) 2020-12-13 14:12:05 +01:00
Noah Pendleton
272a45df12 add src/artifacts to .gitignore
This folder is generated when running `make -C src all_platforms`. Add
it to ignored files.
Ignore .gdb_history too.
2020-12-12 21:40:17 +01:00
UweBonnes
aa0d8f4b5d
Merge pull request #783 from UweBonnes/frequency
Frequency
2020-12-12 19:50:53 +01:00
Noah Pendleton
020600aa56 target/lpc546xx: fix lpc546xx flash support (#801)
**Summary**
Modifications to fix flash support on the lpc546xx:

- fix IAP entrypoint to be `0x03000204`, not the value at that address
- add a reset and attach sequence before erasing flash sectors. there's
little documentation around this, but experimentally, erasing sector 0
fails when the ROM bootloader is mapped to it (on reset). stepping the
chip once and attaching is enough to snap the chip out of it, permitting
flash erase on sector 0.
- add a few test commands to the lpc546xx table (read_uid, erase/write
sector, etc).
- write the magic CRC value when writing to sector 0
(`lpc_flash_write_magic_vect`).
- move the lpc546xx probe to before the lpc43xx probe, to prevent
getting the lpc546xx into Lockup when reading an illegal memory location
during lpc43xx probing

Fixes #786.

I don't 100% understand the reset/load sequence of this part, but these
changes are sufficient to program and debug the part now.

I didn't do a detailed analysis of what pyocd (via st-link hardware
adapter) and segger jlink do to handle the same, but both of those
worked without modification, so there's some difference in the
sequence they're using.

**Testing**
Verified I can now successfully erase and write an executable in sector
0 (and other sectors).
Verified the new commands work correctly.
2020-12-12 19:48:05 +01:00
Uwe Bonnes
1ca9f234f7 Infrastructure for setting maximum SWJ frequency.
Implement for BMP/firmware on STM32.
2020-12-12 18:33:09 +01:00
Uwe Bonnes
7365a44989 hosted: Implement SWJ test mode (-T).
Continious read/write-back some core register as NOP operation to allow scope
measurement of SWJ timing.
2020-12-12 18:33:09 +01:00
Uwe Bonnes
6dbb5ff7ee Frequency: Implementing for jlink.
SWD frequency is fixed for jlink according to the docs from 2010.
2020-12-12 18:33:09 +01:00
Uwe Bonnes
fdc654cfb3 stlink: Implementation of frequency setting. 2020-12-12 18:33:09 +01:00
Uwe Bonnes
de26ba6f73 hosted: Add is_jtag to the info structure
Needed for different frequency setting procedures on some platforms.
2020-12-12 18:33:09 +01:00
Uwe Bonnes
28a966a3e6 frequency: Implement for ftdi.
For all 2232H types, use undivided 60 Mhz.
FIXME: Check FT2322C/D for unsymetric clock at 6 MHz!
2020-12-12 18:33:09 +01:00
Uwe Bonnes
13e8a262e4 SWJ Frequency: Implement for cmsis-dap 2020-12-12 18:33:09 +01:00
Uwe Bonnes
f796b774bd hosted: Fix info.serial if USB device has no serial number #807 2020-12-12 18:32:15 +01:00
Aaron Lindsay
518529a772 Support GD32E23x 2020-12-12 18:29:30 +01:00
Uwe Bonnes
14498decd9 HOSTED_BMP_ONLY/linux: Fix case when no serial device is connected #806 2020-12-12 15:06:26 +01:00
Noah Pendleton
93d4c65948 Fix building with newer GNU make(#804)
More recent versions of GNU make remove the `-` prefix from
`$(MAKEFLAGS)`, which breaks the build:

```bash
 # output truncated to interesting parts
> make -C src --trace all_platforms
set -e ;\
mkdir -p artifacts/v1.7.1-91-g98b4ec5 ;\
echo "<html><body><ul>" > artifacts/index.html ;\
for i in platforms/*/Makefile.inc ; do \
        ...\
        make w --trace --no-print-directory clean ;\
        make w --trace --no-print-directory;\
        ...\
done ;\
echo "</ul></body></html>" >> artifacts/index.html ;\
cp artifacts/*.bin artifacts/v1.7.1-91-g98b4ec5
Building for hardware platform: f4discovery
make[1]: *** No rule to make target 'w'.  Stop.
```

Per the
[documentation](https://www.gnu.org/software/make/manual/html_node/Options_002fRecursion.html),
there's no need to manually apply insert `$(MAKEFLAGS)`, it should be
automatically included when using `$(MAKE)` when recursing.

I tested on my machine (make 4.2.1) and a docker image based on
ubuntu:trusty (make 3.81), both behaved the same (directories were not
printed when recursing by default);
2020-12-12 14:39:52 +01:00
UweBonnes
3cec441833
Merge pull request #805 from UweBonnes/bmp_only
Provide a compile time option (HOSTED_BMP_ONLY=1) for easier compilation of hosted
2020-12-12 13:39:51 +01:00
Stoyan Shopov
b5172cf6df Implement the 'find_debuggers()' function for hosted BMP on windows. 2020-12-11 18:36:48 +01:00
Stoyan Shopov
01f8628aed Bugfix in detecting BMP probes by usb serial number. 2020-12-11 18:36:48 +01:00
Stoyan Shopov
170fe0c368 Remove spurious comment. 2020-12-11 18:36:16 +01:00
Uwe Bonnes
4c5ce0b16a Hosted: Handle devices w/o serial number, e.g. GigaDevices GD-Link ARM/CMSIS-DAP 2020-12-11 18:36:16 +01:00
Uwe Bonnes
0f1fe9e438 hosted/linux: Find BMP devices without libusb. 2020-12-11 18:36:09 +01:00
Uwe Bonnes
bd5f4c6ed5 hosted: Consolidate ident output. 2020-12-11 17:55:31 +01:00
Uwe Bonnes
0870b778c0 hosted: Allow to build without libusb, libftdi and hidapi with HOSTED_BMP_ONLY=1 2020-12-11 17:50:16 +01:00
Uwe Bonnes
32db38ecf2 hosted/libusb: Move platform.c libusb related functions to own file. 2020-12-11 17:35:43 +01:00
Uwe Bonnes
41788f923b ftdi/stlink/jlink: Provide dummy functions in the HOSTED_BMP_ONLY case
Do not allow multiple inclusion by not declaring the functions as static to
help keep code clean.
2020-12-11 17:31:25 +01:00
Uwe Bonnes
98b4ec58bc Update to recent libopencm3 to undo unwanted change. 2020-12-07 21:51:22 +01:00
Emilio Lopes
633c6a2e81 Recognize "J-Trace Cortex-M PRO V2" in hosted mode 2020-12-07 11:52:33 +01:00
Uwe Bonnes
dd6aadc54d jtag: Add verbosity about devices found. 2020-12-06 15:18:08 +01:00
Uwe Bonnes
e65ee7124b stm32_mem: Handle utf8 for print and compare. 2020-12-06 15:18:08 +01:00
Uwe Bonnes
0a7bfd5923 dfu_f4: Fix sector_erase. 2020-12-06 15:18:08 +01:00
Uwe Bonnes
17dfec3572 dfu/cdcacm: Consolidate usage of ST vs BMP serial number. 2020-12-06 15:18:08 +01:00
Uwe Bonnes
5c7e0eedb0 command.c: Consolidate "mon version" output 2020-12-06 15:18:08 +01:00
Uwe Bonnes
07c3699225 version.h: Remove from platform.h files
- Consolidate ident string generation
- Recompile only needed files
2020-12-06 15:18:08 +01:00
Stoyan Shopov
e318f884bf Change the type of 'cortexm_wait_timeout' to unsigned.
It makes sense that the timeout value is unsigned, it also
resolves build errors on some platforms.
2020-12-04 11:44:50 +01:00
Stoyan Shopov
c9a419e44b Correct loss of sync protocol error #787 2020-12-04 11:33:23 +01:00
mean
e3fd12ebc6 gd32f1/f3 detection and ram/flash autoset 2020-12-03 11:16:47 +01:00
Jonathan Giles
575c25e570 Add support for STM32F1 clone with new AP_DESIGNER id 2020-12-01 10:23:16 +01:00
Uwe Bonnes
48a79ff9da adiv5: More checks for a sensible DPIDR. 2020-11-29 21:11:11 +01:00
Uwe Bonnes
752bc26536 adiv5: Fix memleak with duplicated base. 2020-11-29 21:11:11 +01:00
Uwe Bonnes
acec489647 adiv5_jtagdp: Always set idcode. 2020-11-29 21:11:11 +01:00
Uwe Bonnes
9e1b7fdac0 jlink/swd_low_access: Fix data direction during response read phase. 2020-11-29 15:48:50 +01:00
Uwe Bonnes
8903026c14 jlink/swd: swd frequency is fixed, not need to set. 2020-11-29 15:48:50 +01:00
Uwe Bonnes
f45c56af83 adiv5/swdp: Check early for valid DP idcode. 2020-11-29 15:48:50 +01:00
Uwe Bonnes
3b6432912d jlink: Catch another error with no target connected. 2020-11-29 15:48:50 +01:00
Uwe Bonnes
7df314e265 Firmware/Jlink: Fix double free when debug power-up fails (#780) 2020-11-29 15:48:50 +01:00
Uwe Bonnes
e1329499de platform_adiv5_swdp_scan: Do not double free with early errors.
adiv5_dp_init() clean up itself if errors happen
2020-11-29 15:48:50 +01:00
Stefan Agner
77025d4b6b Make dfu-convert.py Python 3 capable 2020-11-29 15:45:08 +01:00
Uwe Bonnes
cda83d3084 Fix memleaks.
Happened e.g. when Stlink could not enter debug or when cortexm_prepare timed out.
2020-11-27 22:26:48 +01:00
Uwe Bonnes
bf548e92c0 swd: After write low_access, always append 8 clk to move data through SW-DP.
Especially needed when leaving the debugger or during debug unit power-up.

ARM Debug Interface Architecture Specification ADIv5.0 to ADIv5.2
tells to clock the data through SW-DP to either :
- immediate start a new transaction
- continue to drive idle cycles
- or clock at least 8 idle cycles

Implement last option to favour correctness over slight speed decrease

Implement only for adapters where we assemble the seq_out_parity in our code,
as on firmware, ftdi and jlink. Hopefully the high level adapters do it right.

Reverts 2c33cde63fe779d3019fe8f63dd4420cb960bbfe and
cde7726b8730242cd40a9974d129b46af80c68af
2020-11-27 22:26:48 +01:00
Uwe Bonnes
9ac5adfcef adiv5: Additional decoding. 2020-11-27 22:26:48 +01:00
Uwe Bonnes
139e5d7e22 f4discovery: Compile time option to compile with ST bootloader
Just to keep things active. Prepare for F72 bootloader.
2020-11-27 22:26:48 +01:00
Uwe Bonnes
d78d7838d3 stm32f1: Always read DBGMCU_IDCODE for t->idcode (#770)
At least STM32F042 has 0x440 as romtable partno vs 0x445 as DBGMCU_IDCODE.
Thanks to Andrey Melnikov(aam335) for pointing out!
2020-11-27 22:26:48 +01:00
Uwe Bonnes
636bcee355 stlink/swlink: Remove the DFU upgrade utility.
Hopefully no old bootloaders are around. If otherwise, revert to last
commit before this and update the DFU bootloader.
2020-11-27 22:26:48 +01:00
Uwe Bonnes
653d486ee2 cortexm: Store CPUID in target structure. 2020-11-27 22:26:48 +01:00
Uwe Bonnes
03a7b06eb8 Makefile: Remove no longer needed code pathes. 2020-11-27 22:26:48 +01:00
Uwe Bonnes
824a1d8abc hosted/find_debuggers: Do not check hubs. Print class of devices unable to open. 2020-11-27 22:26:48 +01:00
Uwe Bonnes
27ef4569ca stm32/dfucore.c: Use libopencm3 provided defines and functions. 2020-11-27 22:26:48 +01:00
Uwe Bonnes
e68dd25813 cl_utils: Clarify -d option is BMP/firmware only and deprecate -d. 2020-11-27 22:26:48 +01:00
Uwe Bonnes
9d55128ab8 cl_utils: Get voltage only once. 2020-11-27 22:26:48 +01:00
Uwe Bonnes
f71e18948a GPIO for SWD: Slow down edges on more platforms. 2020-11-27 22:26:48 +01:00
Uwe Bonnes
e6823f39de Hosted: Print version with "-h" and "-t" option. 2020-11-27 22:26:48 +01:00
Uwe Bonnes
80154c5c7a adiv5_swdp: Fix more memory leak. 2020-11-27 22:26:48 +01:00
Uwe Bonnes
3ee31473c6 cortexm.c: LPC15xx has designer 43b and Partno 4c3
Thanks to JojoS!
2020-11-27 22:26:48 +01:00
Uwe Bonnes
62d9f60f03 hosted/firmware: Waits for read response as long as cortexm_wait_timeout. 2020-11-27 22:26:48 +01:00
Uwe Bonnes
26a23dd1cb stlinkv2: Try harder to open an AP.
Problem seen on STM32L0 with probably long sleep periods.
2020-11-27 22:26:48 +01:00
Uwe Bonnes
19e1fddba2 adiv5: Remove unnescessary read. 2020-11-27 22:26:48 +01:00
Noah Pendleton
35bcb4f7c6 Switch on the lpc546xx target
Enable the lpc546xx target. Tested on the LPCXpresso54628 dev board,
able to flash and debug.
2020-11-24 21:32:39 +01:00
Sean Cross
e9c02296f2 target: kinetis: add S32K118
This adds support for the NXP S32K118. This is an automotive-grade part
that is derived from the Kinetis line, so it has a very similar
interface to other parts in the family.

Signed-off-by: Sean Cross <sean@xobs.io>
2020-11-14 13:06:23 +01:00
jbuonagurio
f18be6ef7a Add support for Kinetis K12 and placeholders for other K-series MCUs 2020-11-07 12:44:05 +01:00
Uwe Bonnes
2c33cde63f cortexm.c/cortexm_halt_resume: Add some clock cycles to always get CPU going (#768) 2020-11-01 21:53:23 +01:00
Uwe Bonnes
d75f3124b9 ftdi_bmp.c: Reapply fix from #715: Check for libftdi 1.5 2020-11-01 12:09:27 +01:00
Stoyan Shopov
99142d1c0e Add documentation details for building PC-hosted BMP in msys2. 2020-11-01 11:33:54 +01:00
Uwe Bonnes
59dc1b7eb4 cortex-m7: Give hint about buggy core revision. 2020-10-23 09:40:15 +02:00
Uwe Bonnes
1f7a716710 adiv5.c: Run cortexm_prepare on all suspected CortexM instances.
Gets all debug units of the second CPU of a STM32H745 visible.
2020-10-23 09:40:15 +02:00
Uwe Bonnes
976c763747 jtag remote: Start fixing handling M0 (second jtag) for LPC4322 in high-level
- LPC11: Only print none-null unknown idcodes.
2020-10-23 09:40:15 +02:00
Uwe Bonnes
18673d9a56 adiv5: Rework DP/AP refcounting.
ASAN non longer reports leaks with the STM32H745.
2020-10-23 09:40:15 +02:00
Uwe Bonnes
0995fe1288 cmsis-dap: Various fixes
- decrease report size to 64, otherwise MIMRXT10x0-EVK crashed when
  reading larger memory block
- dp_read_reg acts direct, fixing CortexM core register read.
- length of data to write with read_block.
2020-10-23 09:40:15 +02:00
Uwe Bonnes
f76a7c4e92 adiv5: Release devices after scan.
Before, scanning only kept device stopped until POR or attach/detach cycle.
2020-10-23 09:40:15 +02:00
Uwe Bonnes
f15b1d7763 cl_utils: Clip opt_flash_start only when not set. 2020-10-23 09:40:15 +02:00
Uwe Bonnes
73e6b540b2 command: When debug channel is available, print morse messages readable. 2020-10-23 09:40:15 +02:00
Uwe Bonnes
c161521c26 cortexm: Designer ARM must be in the default path when probing. 2020-10-23 09:40:15 +02:00
Uwe Bonnes
776861c6a0 Makefile: Fix version.h generation for make all_platforms
Same fix as 0ae65cc10fd2.
2020-10-23 09:40:15 +02:00
Uwe Bonnes
cdd07544d5 Cortexm: Allow pure debug on devices not yet handled for flashing
- Recognize STM32L552 and MIMXRT10XX
- Fix another PIDR
- Fix bad debug print string.
2020-10-23 09:40:15 +02:00
Uwe Bonnes
80ddafc2f8 Jtag/High Level : Transfer dp->dp_jd_index with every HL command.
- Add REMOTE_HL_VERSION, now at 1. Fall back to hosted/low-level
  when wrong version is found and give hint to user.
2020-10-23 09:40:15 +02:00
Uwe Bonnes
3270138ec2 Revert 69e577c9243ce027b628e96881ce2416213fef43
What was thought to be a typo is apsel = 0xff for a dp access.
2020-10-23 09:40:15 +02:00
Uwe Bonnes
77c4f9d702 stlink: Rework README.md
- Document flashing BMP Firmware and reverting to ST firmware
- Consistant nameing
2020-10-19 14:13:29 +02:00
Uwe Bonnes
9cd3193a89 bmp_remote.c: Fix bug introduced with 8b929c12c9e. 2020-10-17 12:49:37 +02:00
Uwe Bonnes
0ffb4f7b18 cortexm: Fix protected SAM detection
- Only run cortex_prepare() if reading cidr fails
- With Atmel DSU detected, run cortexm_probe()
2020-10-17 12:49:37 +02:00
Uwe Bonnes
5bc743d221 samd: Propagate security after setting security by chip reset. 2020-10-17 12:49:37 +02:00
UweBonnes
1d707efa47
Merge pull request #757 from UweBonnes/hosted
Hosted/Firmware: Fix Jtag high level #756
2020-10-16 20:11:12 +02:00
Uwe Bonnes
8b929c12c9 hosted/jtag: Transfer jtag_devs to firmware. 2020-10-16 20:03:03 +02:00
Uwe Bonnes
3d92b82678 jtag: Use index and not device structure for jtag_dev_write_ir and jtag_dev_shift_dr 2020-10-16 20:03:03 +02:00
Uwe Bonnes
6e2a074064 bmp_remote: Deny high level JTAG for now.
jtag_devs and jtag_dev_count needs to be known on th firmware side
and remote_dp->dev needs to be filled with jtag_dev_t.
2020-10-16 20:03:03 +02:00
Uwe Bonnes
0f5fb6b9a0 remote: Initialise dp_read and low_access with SWD_INIT.
Before "mon s" after "mon j" failed.
2020-10-16 20:03:03 +02:00
Uwe Bonnes
752d14ca3e remote.c: Add comments. 2020-10-16 20:03:03 +02:00
Uwe Bonnes
ba26adce53 remote.h: Remove typo. 2020-10-16 20:03:03 +02:00
Uwe Bonnes
7ccf0d3e03 jtag_dev_t: Make dev, idcode and desc less generic.
No codechange intended.
2020-10-16 20:03:03 +02:00
Uwe Bonnes
87b546777a nrf51: Be more verbose about the protection status. 2020-10-16 12:16:33 +02:00
Richard Meadows
4108b649c2 stm32h7: Add support for new product lines
Add support for:
* STM32H7B3/B0/A3 (RM0455)
* STM32H723/33/25/35/30 (RM0468)

Successfully tested with:
* STM32H7A3ZIT (RM0455)
* STM32H747XIH (check for regressions)
2020-10-10 22:09:34 +02:00
UweBonnes
817c62d7fd
Merge pull request #507 from UweBonnes/cortexm_romtable
Cortexm romtable
2020-10-08 10:53:17 +02:00
Uwe Bonnes
877b4be8ee cortexm: Restrict probing by using the ap_designer.
More designers need to be observed and reported by users and added.
Request users to send needed data.
2020-10-07 20:12:35 +02:00
Uwe Bonnes
91d1ef8bf6 target/stm32: Use t->idcode with probe. 2020-10-07 20:12:35 +02:00
Uwe Bonnes
44bfb62715 Adiv5: Print Designer/Partno when device is not recognized
t->idcode is now 16 bit.
2020-10-07 20:12:35 +02:00
Uwe Bonnes
c456fc7f61 adiv5: Store AP designer and partno in the AP structure. 2020-10-07 20:12:32 +02:00
Uwe Bonnes
159196c2ad Cortexm: Remove forced_halt. 2020-10-07 20:11:33 +02:00
Uwe Bonnes
9bb2807706 adiv5/romtable: Prepare CortexM devices to read the ROMTABLE
It seems, writing to DHCSR fails silent when the device is sleeping.
Reading DHCS during sleep may return nonsense.
Repeated write may at some point catch the device running and succeed.
With devices sleeping for long time and running on faster clock the
chance for a successful hotplug gets smaller.

- Try hard to halt a sleeping device
- Prepare vector catch and enable all debug units by TRACENA
- Release reset
- Apply device specific fixes
-- STM32F7: Store old value of DBGMCU_CR, enable debug in sleep in
   DBGMCU before reading PIDR and restore DBGMCU on detach.

Signed-off-by: Uwe Bonnes <bon@elektron.ikp.physik.tu-darmstadt.de>
2020-10-07 20:11:17 +02:00
David A. Aguirre Morales
a254bc6308 Fix icdi usb error https://github.com/blacksphere/blackmagic/issues/740 https://github.com/blacksphere/blackmagic/pull/748 2020-10-07 18:08:04 +02:00
Uwe Bonnes
ceaee2a11e hosted: Hint about BMPs in bootloader mode. 2020-10-07 17:12:22 +02:00
Gareth McMullin
dc8924a2bc
stm32h7: Don't tc_printf from flash functions (#747)
* stm32h7: Don't tc_printf from flash functions

Receving an 'O' packet while flashing confuses GDB and then
weird stuff happens.

* Replace tc_printf with DEBUG_WARN
2020-10-05 10:45:18 +02:00
Uwe Bonnes
9bba3165fb swdptap: Turnaround immediate after a reading with parity.
Thanks to JojoS.
Probably mostly cosmetic, but is keeps the device from driving SWDIO
until the next commands.
2020-10-02 10:51:14 +02:00
Uwe Bonnes
4d18496a6f hosted: Allow to disable high level commands for BMP.
Useful for tracking low level problems on native with hosted.
2020-10-01 15:49:21 +02:00
Uwe Bonnes
014abf6cc9 adiv5.c: Reduce number of errors if reading cidr fails. 2020-10-01 15:33:28 +02:00
Uwe Bonnes
be40d2b851 adiv5: Check Debug Base Address early
Reduces printout when scanning the romtable
2020-10-01 15:22:17 +02:00
Uwe Bonnes
747336e927 f4discovery: Slow done JTAG pin slew rate to avoid ringing #742 2020-10-01 15:06:16 +02:00
Eivind Alexander Bergem
38bc5bbf82 Add LPC546xx support #741 #553 2020-09-30 12:56:53 +02:00
Uwe Bonnes
2fdd94adeb STM32F7: Add another missing Arch ID. 2020-09-24 16:20:34 +02:00
Uwe Bonnes
0ae65cc10f src/Makefile: Fix version.h generation.
It seems, some git behaviour change got by unnoticed.
2020-09-22 19:02:26 +02:00
Uwe Bonnes
c5a0271e4c README.md: Toolchain and OS specific remarks. 2020-09-22 18:21:48 +02:00
Uwe Bonnes
61d919c1ac libftdi: Remove no longer needed workaround for travis CI. 2020-09-20 14:10:37 +02:00
Uwe Bonnes
77231e8972 serial_no: Fix error with "mon trace" #732
launchpad-icdi: Allow to set a serial number with make
2020-09-20 13:23:52 +02:00
Uwe Bonnes
bdb351a6ea adiv5_swdp: On ACK_FAULT, error() and try again once #731
when writing CSW.
2020-09-18 20:07:32 +02:00
jxltom
a4a934f461 Add comments for hardware revision of v2.1 2020-09-17 11:54:19 +02:00
jxltom
75b5e72a00 Fix typo 2020-09-16 18:41:56 +02:00
Raghu
de01a75ca9 Fix broken link to bluepill pinout. 2020-09-15 20:58:10 +02:00
Uwe Bonnes
6d18a61b2e hosted: Make ASAN build optional.
Use ASAN=1 on the make command line to activate,
2020-09-11 15:23:13 +02:00
Jason Kotzin
a01642e480 samd: create a copy that’s named with the version 2019-05-31 00:33:57 -07:00
Jason Kotzin
6b9b502354 tag correctly if we are on a branch 2019-05-31 00:07:20 -07:00
Jason Kotzin
8606b78b9e updating gitignore file 2019-05-18 14:55:31 -07:00
Ryan
cd325dfe52 samd: convert_tdio requires enable/disable 2019-05-16 13:18:05 -07:00
Ryan
c1b3d0c629 samd: bug fix on uart newlines 2019-04-10 17:38:16 -07:00
Jason Kotzin
94238fd95b samd: ability to printout entire serial number 2019-03-29 16:34:12 -07:00
Ryan
5c835bc0f6 samd: srst_get_val now actually works 2019-02-22 18:21:13 -08:00
Ryan
100fc2e7d4 samd: added command to toggle srst pin when not used 2019-02-11 16:15:03 -08:00
Jason Kotzin
880e977fb6 samd: custom serial string for easy opening on mac 2019-02-09 13:48:04 -08:00
Ryan
3a9b0eee7a samd: added tpwr support 2019-02-04 18:19:28 -08:00
Jason Kotzin
6baf90ac4c samd: adding dfu bootloader, compile support, and combined image 2018-12-20 13:35:45 -08:00
Ryan
77064754ad samd: fixed first-scan failure 2018-10-17 15:08:08 -07:00
Ryan
92ed79e68e samd: button code updated for libopencm3 2018-10-04 14:24:18 -07:00
Ryan
b91a975d56 samd: button must hold for 5 seconds now 2018-10-03 16:04:32 -07:00
Ryan
84b6818982 samd: convert_tdio command cleaned up 2018-09-28 14:54:31 -07:00
Ryan
4aee9fe2a3 samd: enter_bootldr command, bootldr button 2018-09-28 14:37:33 -07:00
Ryan
4847e0d1e6 samd: uart ports updated for bm-sam hw 2018-09-05 15:52:04 -07:00
Ryan
a599b989cf samd: TDI/O conversion, usart line coding 2018-09-05 12:10:43 -07:00
Ryan
50658a5c0a samd: small fixes to uart 2018-08-27 16:22:48 -07:00
Ryan
f828fc1ac1 samd voltage detection and line coding 2018-08-07 14:32:00 -07:00
Jason Kotzin
bd71ca2a3c Minor updates to help with speed, temporarily disabling uart 2018-08-01 19:10:01 -07:00
Ryan
2d38c9614e fixed typo in jeff/platform.h 2018-08-01 16:22:03 -07:00
Jason Kotzin
7ce265f2cf Adding queue.h file and fixing some compile errors 2018-08-01 14:26:31 -07:00
Jason Kotzin
638299534b samd: updates for jeff probe pcb 2018-07-13 23:48:52 -07:00
Jason Kotzin
919a005b65 debug flags only if we are debugging, speeds up firmware slightly 2018-07-12 19:19:39 -07:00
Jason Kotzin
58865ca5ec samd: uart support 2018-07-12 18:54:13 -07:00
Jason Kotzin
d62d82bb2f M0 SWDIO 2x performance improvements 2018-07-10 16:18:05 -07:00
Jason Kotzin
f1ecd66283 Initial support for samd hardware and jeff ‘probe’ 2018-07-10 15:42:44 -07:00
Jason Kotzin
fd2cb4b8d2 Updating submodule to use flirc samd branch 2018-07-10 14:01:03 -07:00
Jason Kotzin
1cc3e05c11 Force USB connect 2018-07-10 13:36:00 -07:00
Jason Kotzin
d5b6d4ab12 Allow support for older chip architectures 2018-07-10 13:35:45 -07:00
174 changed files with 12184 additions and 3609 deletions

40
.gitattributes vendored Normal file
View File

@ -0,0 +1,40 @@
# Text for humans
LICENSE text eol=lf
HACKING text eol=lf
COPYING text eol=lf
UsingSWO text eol=lf
README.* text eol=lf
# Source code
Makefile text eol=lf
*.mk text eol=lf
*.mak text eol=lf
*.inc text eol=lf
*.py text eol=lf
*.sh text eol=lf
*.c text eol=lf
*.S text eol=lf
*.s text eol=lf
*.h text eol=lf
*.ld text eol=lf
*.yml text eol=lf
*.rules text eol=lf
# Git control files
.gitattributes eol=lf
.gitignore eol=lf
.gitmodules eol=lf
# Windows source code uses CRLF
*.vcxproj text eol=crlf
*.props text eol=crlf
*.bat text eol=crlf
*.ps1 text eol=crlf
*.inf text eol=crlf
# Other binary files
*.png binary
*.jpg binary
*.bin binary
*.elf binary
*.bin binary

2
.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1,2 @@
github: [esden, dragonmux]
patreon: 1bitsquared

36
.github/workflows/build-and-upload.yml vendored Normal file
View File

@ -0,0 +1,36 @@
name: build and upload
# Controls when the workflow will run
on:
# Triggers the workflow on push or pull request events but only for the main branch
push:
branches: [ master ]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "build"
build:
# The type of runner that the job will run on
runs-on: ubuntu-latest
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v2
# Use embedded toolchain
- uses: numworks/setup-arm-toolchain@2020-q4
# Runs a single command using the runners shell
- name: Build
run: make
- name: Archive firmware build artifacts as a zip
uses: actions/upload-artifact@v2.2.4
with:
name: blackmagic-firmware.zip
path: src/blackmagic*
if-no-files-found: error

38
.github/workflows/build-pr.yml vendored Normal file
View File

@ -0,0 +1,38 @@
name: build PR
# Controls when the workflow will run
on:
# Triggers the workflow on push or pull request events but only for the main branch
pull_request:
branches: [ master ]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "build"
build:
# The type of runner that the job will run on
runs-on: ubuntu-latest
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v2
# Use embedded toolchain
- uses: numworks/setup-arm-toolchain@2020-q4
# Run some of the most common build types
- name: Build native fw
run: make
- name: Clean
run: make clean
- name: Install BMP PC hosted dependencies
run: sudo apt-get -y install libftdi1-dev libhidapi-dev
- name: Build PC hosted binary
run: make PROBE_HOST=hosted

5
.gitignore vendored
View File

@ -16,5 +16,10 @@ tags
*.b#*
blackmagic_upgrade
*.exe
.DS_Store
*.elf
.vscode
cscope.out
cscope.files
.gdb_history
src/artifacts/

2
.gitmodules vendored
View File

@ -1,3 +1,3 @@
[submodule "libopencm3"]
path = libopencm3
url = https://github.com/libopencm3/libopencm3.git
url = https://github.com/flirc/libopencm3.git

View File

@ -1,42 +1,11 @@
dist: trusty
dist: bionic
sudo: required
before_install:
- sudo add-apt-repository -y ppa:team-gcc-arm-embedded/ppa
- sudo apt-get update -qq
- pip install --user intelhex
- gpg --recv-keys 3CEA9B8868BC3852618EB5B4707F91A424F006F5
- wget http://www.intra2net.com/en/developer/libftdi/download/libftdi1-1.2.tar.bz2
- wget http://www.intra2net.com/en/developer/libftdi/download/libftdi1-1.2.tar.bz2.sig
- gpg --trust-model always --verify libftdi1-1.2.tar.bz2.sig
- tar -xjf libftdi1-1.2.tar.bz2
- sudo apt-get install -y build-essential libboost-all-dev gcc-arm-embedded libusb-1.0-0-dev libhidapi-dev
install:
- cd libftdi1-1.2
- if [ "$TRAVIS_OS_NAME" = "linux" ];
then
sudo apt-get update -qq;
if [ "$ARCH" = "x86_64" ];
then
sudo apt-get install -qq libusb-1.0-0-dev;
elif [ "$ARCH" = "i386" ];
then
sudo apt-get install -qq gcc-multilib libusb-1.0-0-dev:i386 pkg-config:i386;
export CFLAGS="-m32";
fi
fi
- if [ "$TRAVIS_OS_NAME" = "osx" ];
then
brew update;
brew install libusb;
fi
- mkdir build
- cd build
- cmake ../
- make
- sudo make install
- cd ../../
- sudo apt-get install -y build-essential libboost-all-dev gcc-arm-embedded libusb-1.0-0-dev libhidapi-dev libftdi1 libftdi1-dev
script:
- make -C libopencm3 lib

View File

@ -1 +1 @@
See https://github.com/blacksphere/blackmagic/wiki/Hacking
See https://github.com/blackmagic-debug/blackmagic/wiki/Hacking

View File

@ -5,14 +5,6 @@ endif
PC_HOSTED =
NO_LIBOPENCM3 =
ifeq ($(PROBE_HOST), libftdi)
PC_HOSTED = true
NO_LIBOPENCM3 = true
endif
ifeq ($(PROBE_HOST), pc-stlinkv2)
PC_HOSTED = true
NO_LIBOPENCM3 = true
endif
ifeq ($(PROBE_HOST), hosted)
PC_HOSTED = true
NO_LIBOPENCM3 = true
@ -25,13 +17,23 @@ ifndef NO_LIBOPENCM3
git submodule init ;\
git submodule update ;\
fi
$(Q)$(MAKE) $(MFLAGS) -C libopencm3 lib
$(Q)$(MAKE) $(MFLAGS) -C libopencm3 lib/sam/d
endif
$(Q)$(MAKE) $(MFLAGS) -C src
all_platforms:
$(Q)$(MAKE) $(MFLAGS) -C src $@
clean:
ifndef NO_LIBOPENCM3
$(Q)$(MAKE) $(MFLAGS) -C libopencm3 $@
endif
$(Q)$(MAKE) $(MFLAGS) -C src $@
clang-tidy:
$(Q)scripts/run-clang-tidy.py -s "$(PWD)"
clang-format:
$(Q)$(MAKE) $(MFLAGS) -C src $@
.PHONY: clean all_platforms clang-tidy clang-format

139
README.md
View File

@ -1,97 +1,54 @@
Black Magic Probe
=================
Jeff Probe
==========
[![Build Status](https://travis-ci.org/blacksphere/blackmagic.svg?branch=master)](https://travis-ci.org/blacksphere/blackmagic)
[![Discord](https://img.shields.io/discord/613131135903596547?logo=discord)](https://discord.gg/P7FYThy)
[![Donate](https://img.shields.io/badge/paypal-donate-blue.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=N84QYNAM2JJQG)
[![Kickstarter](https://img.shields.io/badge/kickstarter-back%20us-14e16e.svg)](https://www.kickstarter.com/projects/esden/1bitsy-and-black-magic-probe-demystifying-arm-prog)
This is a fork of the [original Black Magic Probe](https://github.com/blacksphere/blackmagic).
Firmware for the Black Magic Debug Probe.
The original is arguably better, faster and wider supported. However, this
project was a way to offer an affordable version and I'll rely on community
support and pull requests.
The Black Magic Probe is a modern, in-application debugging tool for
embedded microprocessors. It allows you see what is going on 'inside' an
application running on an embedded microprocessor while it executes. It is
able to control and examine the state of the target microprocessor using a
JTAG or Serial Wire Debugging (SWD) port and on-chip debug logic provided
by the microprocessor. The probe connects to a host computer using a
standard USB interface. The user is able to control exactly what happens
using the GNU source level debugging software, GDB.
Serial Wire Output (SWO) allows the target to write tracing and logging to the host
without using usb or serial port. Decoding SWO in the probe itself
makes [SWO viewing as simple as connecting to a serial port](https://github.com/blacksphere/blackmagic/wiki/Serial-Wire-Output).
One urguably better funncton is the ability to do DEBUG and Serial communication
over a single JTAG cable when paired with a device that uses single wire JTAG.
Normally, the serial header can be used on a target for the serial port, and
shows up as the second serial device on the system, however, we can dynamically
change the pins to use the ones on the JTAG cable with the following command:
``` bash
$ mon convert_tdio enable
```
Compilation
---
Newer toolchains can cause issues. I usually work 4_9-2014q4-20141203 found [here.](https://launchpad.net/gcc-arm-embedded/4.9/4.9-2014-q4-major/+download/gcc-arm-none-eabi-4_9-2014q4-20141203-mac.tar.bz2)
the versionfollowing version
```bash
$ make clean
$ make PROBE_HOST=jeff CUSTOM_SER=1
$ dfu-util --device ,1d50:6017 -s 0x00002000:leave -D src/blackmagic.bin
```
CUSTOM OPTIONS
---
On mac, our device shows up with a serial number /dev/tty.cuJEFF123HDC
This can be annoy if we want to autocnnect with a gith script. We can override
the use of a serial number by doing a custom compliation such that our device
shows up with the following: /dev/cu.usbmodemJEFF1 and /dev/cu.usbmodemJEFF3
```bash
$ make PROBE_HOST=jeff CUSTOM_SER=1
```
More
---
More helpful information can be found on the black magic probe [readme](https://github.com/blacksphere/blackmagic/blob/master/README.md#black-magic-probe), which is relevant.
See online documentation at https://github.com/blacksphere/blackmagic/wiki
Binaries from the latest automated build are at http://builds.blacksphere.co.nz/blackmagic
Sample Session
=============
```console
> arm-none-eabi-gdb gpio.elf
...<GDB Copyright message>
(gdb) tar ext /dev/ttyACM0
Remote debugging using /dev/ttyACM0
(gdb) mon s
Target voltage: 2.94V
Available Targets:
No. Att Driver
1 STM32F40x M3/M4
(gdb) att 1
Attaching to program: /devel/en_apps/gpio/f4_discovery/gpio.elf, Remote target
0x08002298 in UsartIOCtl ()
(gdb) load
Loading section .text, size 0x5868 lma 0x8000000
Loading section .data, size 0x9e0 lma 0x8005868
Loading section .rodata, size 0x254 lma 0x8006248
Start address 0x800007c, load size 25756
Transfer rate: 31 KB/sec, 919 bytes/write.
(gdb) b main
Breakpoint 1 at 0x80000e8: file /devel/en_apps/gpio/f4_discovery/../gpio.c, line 70.
(gdb) r
Starting program: /devel/en_apps/gpio/f4_discovery/gpio.elf
Note: automatically using hardware breakpoints for read-only addresses.
Breakpoint 1, main () at /devel/en_apps/gpio/f4_discovery/../gpio.c:70
70 {
```
BLACKMAGIC
==========
You can also build blackmagic as a PC hosted application
"make PROBE_HOST=hosted"
This builds the same GDB server, that is running on the Black Magic Probe.
While connection to the Black Magic Probe GDB server is via serial line,
connection to the PC-Hosted GDB server is via TCP port 2000 for the first
GDB server and higher for more invokations. Use "tar(get) ext(ented) :2000"
to connect.
PC-hosted BMP GDB server can talk to
- Black Magic Probe firmware probes via the USB-serial port
- ST-LinkV2 and V3 with recent firmware
- CMSIS-DAP compatible probes
- JLINK probes
- FTDI MPSSE based probe.
When connected to a single BMP supported probe, starting "blackmagic" w/o any
arguments starts the server. When several BMP supported probes are connected,
their types, position and serial number is displayed and the program exits.
Add "-P (position)" to the next invocation to select one.
For the setup from the sample session above:
In another terminal:
```console
> blackmagic
Using 1d50:6018 E2E489E7 Black Sphere Technologies Black Magic Probe (STLINK), (Firmware v1.6.1-477-g70bb131-dirty)
Remote is Black Magic Probe (STLINK), (Firmware v1.6.1-477-g70bb131-dirty) v1.6.1-477-g70bb131-dirty
Listening on TCP: 2000
And in the GDB terminal:
(gdb) target ext :2000
Remote debugging using :2000
(gdb) mon s
...
```
PC hosted BMP also allows to flash, read and verify a binary file, by default
starting at lowest flash address. The "-t" argument displays information about the
connected target. Use "-h " to get a list of supported options.
Binaries from the latest automated build can be found on the release page.

271
UsingRTT.md Normal file
View File

@ -0,0 +1,271 @@
# Using RTT
When debugging arm processors, there are three ways for the target to print debug messages on the host: Semihosting, Serial Wire Output SWO, and Real-Time Transfer RTT.
[Black Magic Probe](https://github.com/blacksphere/blackmagic) (BMP) is an open source debugger probe that already implements Semihosting and Single Wire Output. This patch adds Real-Time Transfer RTT output to usb serial port.
- RTT is implemented, not as a user program, but as a serial port device. To read RTT output, use a terminal emulator and connect to the serial port.
- A novel way to detect RTT automatically, fast and convenient.
## Use
This example uses linux as operating system. For Windows and MacOS see the *Operating Systems* section.
In one window open a terminal emulator (minicom, putty) and connect to the usb uart:
```
$ minicom -c on -D /dev/ttyBmpTarg
```
In another window open a debugger:
```
$ gdb
(gdb) target extended-remote /dev/ttyBmpGdb
(gdb) monitor swdp_scan
(gdb) attach 1
(gdb) monitor rtt
(gdb) run
^C
(gdb) monitor rtt status
rtt: on found: yes ident: off halt: off channels: auto 0 1 3
max poll ms: 256 min poll ms: 8 max errs: 10
```
The terminal emulator displays RTT output from the target,
and characters typed in the terminal emulator are sent via RTT to the target.
## gdb commands
The following new gdb commands are available:
- ``monitor rtt``
switch rtt on
- ``monitor rtt enable``
switch rtt on
- ``monitor rtt disable``
switch rtt off
- ``monitor rtt poll `` max_poll_ms min_poll_ms max_errs
sets maximum time between polls, minimum time between polls, and the maximum number of errors before RTT disconnects from the target. Times in milliseconds. It is best if max_poll_ms/min_poll_ms is a power of two. As an example, if you wish to check for RTT output between once per second to eight times per second: ``monitor rtt poll 1000 125 10``.
- ``monitor rtt status``
show status.
rtt|found|state
---|---|---
rtt: off|found: no|rtt inactive
rtt: on|found: no|searching for rtt control block
rtt: on|found: yes|rtt active
rtt: off|found: yes|corrupt rtt control block, or target memory access error
A status of `rtt: on found: no` indicates bmp is still searching for the rtt control block in target ram, but has not found anything yet. A status of `rtt: on found: yes` indicates the control block has been found and rtt is active.
- ``monitor rtt channel``
enables the first two output channels, and the first input channel. (default)
- ``monitor rtt channel number...``
enables the given RTT channel numbers. Channels are numbers from 0 to 15, inclusive. Eg. ``monitor rtt channel 0 1 4`` to enable channels 0, 1, and 4.
- ``monitor rtt ident string``
sets RTT ident to *string*. If *string* contains a space, replace the space with an underscore _. Setting ident string is optional, RTT works fine without.
- ``monitor rtt ident``
clears ident string. (default)
- ``monitor rtt cblock``
shows rtt control block data, and which channels are enabled. This is an example control block:
```
(gdb) mon rtt cb
cbaddr: 0x200000a0
ch ena cfg i/o buf@ size head@ tail@ flg
0 y y out 0x20000148 1024 0x200000c4 0x200000c8 2
1 y n out 0x00000000 0 0x200000dc 0x200000e0 0
2 n n out 0x00000000 0 0x200000f4 0x200000f8 0
3 y y in 0x20000548 16 0x2000010c 0x20000110 0
4 n n in 0x00000000 0 0x20000124 0x20000128 0
5 n n in 0x00000000 0 0x2000013c 0x20000140 0
6 n n in 0x00000000 0 0x00000000 0x00000000 0
7 n n in 0x00000000 0 0x00000000 0x00000000 0
8 n n in 0x00000000 0 0x00000000 0x00000000 0
9 n n in 0x00000000 0 0x00000000 0x00000000 0
10 n n in 0x00000000 0 0x00000000 0x00000000 0
11 n n in 0x00000000 0 0x00000000 0x00000000 0
12 n n in 0x00000000 0 0x00000000 0x00000000 0
13 n n in 0x00000000 0 0x00000000 0x00000000 0
14 n n in 0x00000000 0 0x00000000 0x00000000 0
15 n n in 0x00000000 0 0x00000000 0x00000000 0
```
Channels are listed, one channel per line. The columns are: channel, enabled, configured, input/output, buffer address, buffer size, address of head pointer, address of tail pointer, flag. Each channel is a circular buffer with head and tail pointer.
Note the columns `ena` for enabled, `cfg` for configured.
Configured channels have a non-zero buffer address and non-zero size. Configured channels are marked yes `y` in the column `cfg` . What channels are configured depends upon target software.
Channels the user wants to see are marked yes `y` in the column enabled `ena`. The user can change which channels are shown with the `monitor rtt channel` command.
Output channels are displayed, and Input channels receive keyboard input, if they are marked yes in both *enabled* and *configured*.
The control block is cached for speed. In an interrupted program, `monitor rtt` will force a reload of the control block when the program continues.
## Identifier string
It is possible to set an RTT identifier string.
As an example, if the RTT identifier is "IDENT STR":
```
$ gdb
(gdb) target extended-remote /dev/ttyBmpGdb
(gdb) monitor swdp_scan
(gdb) attach 1
(gdb) monitor rtt ident IDENT_STR
(gdb) monitor rtt
(gdb) run
^C
(gdb) monitor rtt status
rtt: on found: yes ident: "IDENT STR" halt: off channels: auto 0 1 3
max poll ms: 256 min poll ms: 8 max errs: 10
```
Note replacing space with underscore _ in *monitor rtt ident*.
Setting an identifier string is optional. RTT gives the same output at the same speed, with or without specifying identifier string.
## Operating systems
[Configuration](https://github.com/blacksphere/blackmagic/wiki/Getting-Started) instructions for windows, linux and macos.
### Windows
After configuration, Black Magic Probe shows up in Windows as two _USB Serial (CDC)_ ports.
Connect arm-none-eabi-gdb, the gnu debugger for arm processors, to the lower numbered of the two COM ports. Connect an ansi terminal emulator to the higher numbered of the two COM ports.
Sample gdb session:
```
(gdb) target extended-remote COM3
(gdb) monitor swdp_scan
(gdb) attach 1
(gdb) monitor rtt
(gdb) run
```
For COM port COM10 and higher, add the prefix `\\.\`, e.g.
```
target extended-remote \\.\COM10
```
Target RTT output will appear in the terminal, and what you type in the terminal will be sent to the RTT input of the target.
### linux
On linux, install [udev rules](https://github.com/blacksphere/blackmagic/blob/master/driver/99-blackmagic.rules). Disconnect and re-connect the BMP. Check the device shows up in /dev/ :
```
$ ls -l /dev/ttyBmp*
lrwxrwxrwx 1 root root 7 Dec 13 07:29 /dev/ttyBmpGdb -> ttyACM0
lrwxrwxrwx 1 root root 7 Dec 13 07:29 /dev/ttyBmpTarg -> ttyACM2
```
Connect terminal emulator to /dev/ttyBmpTarg and gdb to /dev/ttyBmpGdb .
In one window:
```
minicom -c on -D /dev/ttyBmpTarg
```
In another window :
```
gdb
(gdb) target extended-remote /dev/ttyBmpGdb
(gdb) monitor swdp_scan
(gdb) attach 1
(gdb) monitor rtt
(gdb) run
```
### MacOS
On MacOS the tty devices have different names than on linux. On connecting blackmagic to the computer 4 devices are created, 2 'tty' and 2 'cu' devices. Gdb connects to the first cu device (e.g.: `target extended-remote /dev/cu.usbmodemDDCEC9EC1`), while RTT is connected to the second tty device (`minicom -c on -D /dev/tty.usbmodemDDCEC9EC3`). In full:
In one Terminal window, connect a terminal emulator to /dev/tty.usbmodemDDCEC9EC3 :
```
minicom -c on -D /dev/tty.usbmodemDDCEC9EC3
```
In another Terminal window, connect gdb to /dev/cu.usbmodemDDCEC9EC1 :
```
gdb
(gdb) target extended-remote /dev/cu.usbmodemDDCEC9EC1
(gdb) monitor swdp_scan
(gdb) attach 1
(gdb) monitor rtt
(gdb) run
```
RTT input/output is in the window running _minicom_.
## Notes
- Design goal was smallest, simplest implementation that has good practical use.
- RTT code size is 3.5 kbyte - the whole debugger 110 kbyte.
- Because RTT is implemented as a serial port device, there is no need to write and maintain software for different host operating systems. A serial port works everywhere - linux, windows and mac. You can even use an Android mobile phone as RTT terminal.
- Because polling occurs between debugger probe and target, the load on the host is small. There is no constant usb traffic, there are no real-time requirements on the host.
- RTT polling frequency is adaptive and goes up and down with RTT activity. Use *monitor rtt poll* to balance response speed and target load for your use.
- Detects RTT automatically, very convenient.
- When using RTT as a terminal, sending data from host to target, you may need to change local echo, carriage return and/or line feed settings in your terminal emulator.
- Architectures such as risc-v may not allow the debugger access to target memory while the target is running. As a workaround, on these architectures RTT briefly halts the target during polling. If the target is halted during polling, `monitor rtt status` shows `halt: on`.
- Measured RTT speed.
| debugger | char/s |
| ------------------------- | ------ |
| bmp stm32f723 stlinkv3 | 49811 |
| bmp stm32f411 black pill | 50073 |
| bmp stm32f103 blue pill | 50142 |
This is the speed at which characters can be sent from target to debugger probe, in reasonable circumstances. Test target is an stm32f103 blue pill running an [Arduino sketch](https://github.com/koendv/Arduino-RTTStream/blob/main/examples/SpeedTest/SpeedTest.ino). Default *monitor rtt poll* settings on debugger. Default RTT buffer size in target and debugger. Overhead for printf() calls included.
## Compiling firmware
To compile with RTT support, add *ENABLE_RTT=1*.
Eg. for STM32F103 blue pill:
```
make clean
make PROBE_HOST=stlink ENABLE_RTT=1
```
or for the STM32F411 *[Black Pill](https://www.aliexpress.com/item/1005001456186625.html)*:
```
make clean
make PROBE_HOST=f4discovery BLACKPILL=1 ENABLE_RTT=1
```
Setting an ident string is optional. But if you wish, you can set the default RTT ident at compile time.
For STM32F103 *Blue Pill*:
```
make clean
make PROBE_HOST=stlink ENABLE_RTT=1 "RTT_IDENT=IDENT\ STR"
```
or for STM32F411 *Black Pill*:
```
make clean
make PROBE_HOST=f4discovery BLACKPILL=1 ENABLE_RTT=1 "RTT_IDENT=IDENT\ STR"
```
Note the backslash \\ before the space.
## Links
- [OpenOCD](https://openocd.org/doc/html/General-Commands.html#Real-Time-Transfer-_0028RTT_0029)
- [probe-rs](https://probe.rs/) and [rtt-target](https://github.com/mvirkkunen/rtt-target) for the _rust_ programming language.
- [RTT Stream](https://github.com/koendv/Arduino-RTTStream) for Arduino on arm processors
- [\[WIP\] RTT support - PR from katyo](https://github.com/blacksphere/blackmagic/pull/833)

View File

@ -14,24 +14,28 @@ monitor traceswo 115200
We are constrained on maximum input speed by both the capabilities of the
BMP STM32F103 USART and the ability to get the packets back out over the USB
link. The UART baudrate is set by b=(72x10^6)/(16*d)...so for d=1 that means
a maximum speed of 4.5Mbps. For continious streaming that turns out to be
_too_ fast for the USB link, so the next available option is the 2.25Mbps
that we use. ....you can safely use the 4.5Mbps setting if your debug data
link. The UART baudrate is set by b=(72x10^6)/d...with d >= 16 or
a maximum speed of 4.5Mbps UART1 and 2.25 Mbps on UART2.
For continious streaming that turns out to be_too_ fast for the USB
link, so the next available option is the 2.25Mbps that we use. ....
You can safely use the 4.5Mbps setting if your debug data
is bursty, or if you're using a different CPU to the STM32F103 as your BMP
host, but you potentially run the risk of losing packets if you have long
runs of sending which the usb cannot flush in time (there's a 12K buffer, so
the it is a pretty long run before it becomes a problem).
Note that the baudrate equation means there are only certain speeds
available. The highest half dozen are;
SWO uses USART1(stlink) USART2(swlink)
1 4.50 Mbps 2.25 Mbps
2 2.25 Mbps 1.125 Mbps
3 1.50 Mbps 0.75 Mbps
4 1.125 Mbps 0.5635 Mbps
5 0.900 Mbps 0.45 Mbps
6 0.750 Mbps 0.375 Mbps
available. The highest:
BRR USART1(stlink) USART2(swlink)
16 4.50 Mbps 2.25 Mbps
17 4.235 Mbps 2.118 Mbps
18 4.000 Mbps 2.0 Mbps
19 3.789 Mbps 1.895 Mbps
20 3.600 Mbps 1.8 Mbps
...
24 3.0 Mbps 1.5 Mbps
...
36 2.0 Mbps 1.0 Mbps
...the USART will cope with some timing slip, but it's advisible to stay as
close to these values as you can. As the speed comes down the spread between

View File

@ -1,6 +1,7 @@
# Black Magic Probe
# there are two connections, one for GDB and one for UART debugging
# copy this to /etc/udev/rules.d/99-blackmagic.rules
# and run /usr/sbin/udevadm control --reload-rules
SUBSYSTEM=="tty", ACTION=="add", ATTRS{interface}=="Black Magic GDB Server", SYMLINK+="ttyBmpGdb"
SUBSYSTEM=="tty", ACTION=="add", ATTRS{interface}=="Black Magic UART Port", SYMLINK+="ttyBmpTarg"
SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ATTR{idVendor}=="1d50", ATTR{idProduct}=="6017", MODE="0666"

View File

@ -13,17 +13,17 @@
Signature="$Windows NT$"
Class=Ports
ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318}
Provider=%BLACKSPHERE%
Provider=%BLACKMAGIC%
DriverVer=28/12/2011,0.0.1.1
[Manufacturer]
%VendorName%=DeviceList, NTamd64
[Strings]
VendorName = "Black Sphere Technologies"
VendorName = "Black Magic Debug"
BLACKMAGICGDB = "Black Magic GDB Server"
BLACKMAGICUART = "Black Magic UART Port"
BLACKSPHERE_DISPLAY_NAME = "Black Magic Probe Driver"
BLACKMAGIC_DISPLAY_NAME = "Black Magic Probe Driver"
[DeviceList]
%BLACKMAGICGDB%=DriverInstall, USB\VID_1d50&PID_6018&Rev_0100&MI_00
@ -55,7 +55,7 @@ HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider"
AddService = usbser,0x0002,DriverService.nt
[DriverService.nt]
DisplayName = %BLACKSPHERE_DISPLAY_NAME%
DisplayName = %BLACKMAGIC_DISPLAY_NAME%
ServiceType = 1 ; SERVICE_KERNEL_DRIVER
StartType = 3 ; SERVICE_DEMAND_START
ErrorControl = 1 ; SERVICE_ERROR_NORMAL
@ -80,7 +80,7 @@ HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider"
AddService = usbser,0x0002,DriverService.NTamd64
[DriverService.NTamd64]
DisplayName = %BLACKSPHERE_DISPLAY_NAME%
DisplayName = %BLACKMAGIC_DISPLAY_NAME%
ServiceType = 1 ; SERVICE_KERNEL_DRIVER
StartType = 3 ; SERVICE_DEMAND_START
ErrorControl = 1 ; SERVICE_ERROR_NORMAL

View File

@ -4,7 +4,7 @@
DeviceName = "Black Magic Firmware Upgrade"
DeviceNameDFU = "Black Magic Probe (Upgrade)"
DeviceNameTPA = "Black Magic Trace Capture"
VendorName = "Black Sphere Technologies"
VendorName = "Black Magic Debug"
SourceName = "Black Magic Firmware Upgrade Install Disk"
DeviceID = "VID_1d50&PID_6018&Rev_0100&MI_04"
DeviceIDDFU= "VID_1d50&PID_6017&Rev_0100"

@ -1 +1 @@
Subproject commit 89074d6a13ed7febba04d3c421ce7bf2b7972156
Subproject commit 63573143ef7e1b037d1f0c5baedc5264e12562b8

BIN
schematic/bm-sam-a04.pdf Normal file

Binary file not shown.

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
#
# bootprog.py: STM32 SystemMemory Production Programmer -- version 1.1
# Copyright (C) 2011 Black Sphere Technologies
@ -23,107 +23,105 @@ from time import sleep
class stm32_boot:
def __init__(self, port, baud=115200):
self.serial = serial.Serial(port, baud, 8, 'E', 1,
self.serial = serial.Serial(port, baud, 8, 'E', 1,
timeout=1)
# Turn on target device in SystemMemory boot mode
self.serial.setDTR(1)
sleep(0.1);
sleep(0.1)
self._sync()
def _sync(self):
# Send sync byte
#print "sending sync byte"
self.serial.write("\x7F")
#print("sending sync byte")
self.serial.write(b"\x7f")
self._checkack()
def _sendcmd(self, cmd):
if type(cmd) == int:
cmd = chr(cmd)
cmd += chr(ord(cmd) ^ 0xff)
#print "sendcmd:", repr(cmd)
cmd = ord(cmd)
cmd = bytes((cmd, cmd ^ 0xff))
#print("sendcmd:", repr(cmd))
self.serial.write(cmd)
def _send(self, data):
csum = 0
for c in data: csum ^= ord(c)
data = data + chr(csum)
#print "sending:", repr(data)
for c in data: csum ^= c
data = data + bytes((csum,))
#print("sending:", repr(data))
self.serial.write(data)
def _checkack(self):
ACK = "\x79"
ACK = b"\x79"
b = self.serial.read(1)
if b != ACK: raise Exception("Invalid ack: %r" % b)
#print "got ack!"
#print("got ack!")
def get(self):
self._sendcmd("\x00")
self._sendcmd(b"\x00")
self._checkack()
num = ord(self.serial.read(1))
num = self.serial.read(1)[0]
data = self.serial.read(num+1)
self._checkack()
return data
def eraseall(self):
# Send erase cmd
self._sendcmd("\x43")
self._sendcmd(b"\x43")
self._checkack()
# Global erase
self._sendcmd("\xff")
self._sendcmd(b"\xff")
self._checkack()
def read(self, addr, len):
# Send read cmd
self._sendcmd("\x11")
self._sendcmd(b"\x11")
self._checkack()
# Send address
self._send(struct.pack(">L", addr))
self._checkack()
# Send length
self._sendcmd(chr(len-1))
self._sendcmd(bytes((len-1,)))
self._checkack()
return self.serial.read(len)
def write(self, addr, data):
# Send write cmd
self._sendcmd("\x31")
self._sendcmd(b"\x31")
self._checkack()
# Send address
self._send(struct.pack(">L", addr))
self._checkack()
# Send data
self._send(chr(len(data)-1) + data)
self._send(bytes((len(data)-1,)) + data)
self._checkack()
def write_protect(self, sectors):
# Send WP cmd
self._sendcmd("\x63")
self._sendcmd(b"\x63")
self._checkack()
# Send sector list
self._send(chr(len(sectors)-1) + "".join(chr(i) for i in sectors))
self._send(bytes((len(sectors)-1,)) + bytes(sectors))
self._checkack()
# Resync after system reset
self._sync()
def write_unprotect(self):
self._sendcmd("\x73")
self._sendcmd(b"\x73")
self._checkack()
self._checkack()
self._sync()
def read_protect(self):
self._sendcmd("\x82")
self._sendcmd(b"\x82")
self._checkack()
self._checkack()
self._sync()
def read_unprotect(self):
self._sendcmd("\x92")
self._sendcmd(b"\x92")
self._checkack()
self._checkack()
self._sync()
@ -133,12 +131,12 @@ if __name__ == "__main__":
from sys import stdout, argv, platform
from getopt import getopt
if platform == "linux2":
print "\x1b\x5b\x48\x1b\x5b\x32\x4a" # clear terminal screen
print "STM32 SystemMemory Production Programmer -- version 1.1"
print "Copyright (C) 2011 Black Sphere Technologies"
print "License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>"
print
if platform == "linux":
print("\x1b\x5b\x48\x1b\x5b\x32\x4a") # clear terminal screen
print("STM32 SystemMemory Production Programmer -- version 1.1")
print("Copyright (C) 2011 Black Sphere Technologies")
print("License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>")
print()
dev = "COM1" if platform == "win32" else "/dev/ttyUSB0"
baud = 115200
@ -152,38 +150,38 @@ if __name__ == "__main__":
progfile = args[0]
except:
print "Usage %s [-d <dev>] [-b <baudrate>] [-a <address>] <filename>" % argv[0]
print "\t-d : Use target on interface <dev> (default: %s)" % dev
print "\t-b : Set device baudrate (default: %d)" % baud
print "\t-a : Set programming address (default: 0x%X)" % addr
print
print("Usage %s [-d <dev>] [-b <baudrate>] [-a <address>] <filename>" % argv[0])
print("\t-d : Use target on interface <dev> (default: %s)" % dev)
print("\t-b : Set device baudrate (default: %d)" % baud)
print("\t-a : Set programming address (default: 0x%X)" % addr)
print()
exit(-1)
prog = open(progfile, "rb").read()
boot = stm32_boot(dev, baud)
cmds = boot.get()
print "Target bootloader version: %d.%d\n" % (ord(cmds[0]) >> 4, ord(cmds[0]) % 0xf)
print("Target bootloader version: %d.%d\n" % (cmds[0] >> 4, cmds[0] % 0xf))
print "Removing device protection..."
print("Removing device protection...")
boot.read_unprotect()
boot.write_unprotect()
print "Erasing target device..."
print("Erasing target device...")
boot.eraseall()
addr = 0x8000000
while prog:
print ("Programming address 0x%08X..0x%08X...\r" % (addr, addr + min(len(prog), 255))),
stdout.flush();
print("Programming address 0x%08X..0x%08X...\r" % (addr, addr + min(len(prog), 255)), end=' ')
stdout.flush()
boot.write(addr, prog[:256])
addr += 256
prog = prog[256:]
print
print "Enabling device protection..."
print("Enabling device protection...")
boot.write_protect(range(0,2))
#boot.read_protect()
print "All operations completed."
print("All operations completed.")
print

53
scripts/dfu-convert.py Normal file → Executable file
View File

@ -1,4 +1,4 @@
#!/usr/bin/python2
#!/usr/bin/env python3
# Written by Antonio Galea - 2010/11/18
# Distributed under Gnu LGPL 3.0
@ -16,57 +16,64 @@ def consume(fmt,data,names):
n = struct.calcsize(fmt)
return named(struct.unpack(fmt,data[:n]),names),data[n:]
def cstring(string):
return string.split('\0',1)[0]
return string.split(b'\0',1)[0]
def compute_crc(data):
return 0xFFFFFFFF & -zlib.crc32(data) -1
def parse(file,dump_images=False):
print 'File: "%s"' % file
print('File: "%s"' % file)
data = open(file,'rb').read()
crc = compute_crc(data[:-4])
prefix, data = consume('<5sBIB',data,'signature version size targets')
print '%(signature)s v%(version)d, image size: %(size)d, targets: %(targets)d' % prefix
print('%(signature)r v%(version)d, image size: %(size)d, targets: %(targets)d' % prefix)
for t in range(prefix['targets']):
tprefix, data = consume('<6sBI255s2I',data,'signature altsetting named name size elements')
tprefix['num'] = t
if tprefix['named']:
tprefix['name'] = cstring(tprefix['name'])
else:
tprefix['name'] = ''
print '%(signature)s %(num)d, alt setting: %(altsetting)s, name: "%(name)s", size: %(size)d, elements: %(elements)d' % tprefix
tprefix['name'] = b''
print('%(signature)r %(num)d, alt setting: %(altsetting)r, name: %(name)r, size: %(size)d, elements: %(elements)d' % tprefix)
tsize = tprefix['size']
target, data = data[:tsize], data[tsize:]
for e in range(tprefix['elements']):
eprefix, target = consume('<2I',target,'address size')
eprefix['num'] = e
print ' %(num)d, address: 0x%(address)08x, size: %(size)d' % eprefix
print(' %(num)d, address: 0x%(address)08x, size: %(size)d' % eprefix)
esize = eprefix['size']
image, target = target[:esize], target[esize:]
if dump_images:
out = '%s.target%d.image%d.bin' % (file,t,e)
open(out,'wb').write(image)
print ' DUMPED IMAGE TO "%s"' % out
print(' DUMPED IMAGE TO "%s"' % out)
if len(target):
print "target %d: PARSE ERROR" % t
print("target %d: PARSE ERROR" % t)
suffix = named(struct.unpack('<4H3sBI',data[:16]),'device product vendor dfu ufd len crc')
print 'usb: %(vendor)04x:%(product)04x, device: 0x%(device)04x, dfu: 0x%(dfu)04x, %(ufd)s, %(len)d, 0x%(crc)08x' % suffix
print('usb: %(vendor)04x:%(product)04x, device: 0x%(device)04x, dfu: 0x%(dfu)04x, %(ufd)r, %(len)d, 0x%(crc)08x' % suffix)
if crc != suffix['crc']:
print "CRC ERROR: computed crc32 is 0x%08x" % crc
print("CRC ERROR: computed crc32 is 0x%08x" % crc)
data = data[16:]
if data:
print "PARSE ERROR"
print("PARSE ERROR")
def build(file,targets,device=DEFAULT_DEVICE):
data = ''
data = b''
for t,target in enumerate(targets):
tdata = ''
tdata = b''
for image in target:
tdata += struct.pack('<2I',image['address'],len(image['data']))+image['data']
tdata = struct.pack('<6sBI255s2I','Target',0,1,'ST...',len(tdata),len(target)) + tdata
trgt = b'Target'
st = b'ST...'
tdata = struct.pack('<6sBI255s2I',trgt,0,1,st,len(tdata),len(target)) + tdata
data += tdata
data = struct.pack('<5sBIB','DfuSe',1,len(data)+11,len(targets)) + data
dfu_se = b'DfuSe'
ufd = b'UFD'
data = struct.pack('<5sBIB',dfu_se,1,len(data)+11,len(targets)) + data
v,d=map(lambda x: int(x,0) & 0xFFFF, device.split(':',1))
data += struct.pack('<4H3sB',0,d,v,0x011a,'UFD',16)
data += struct.pack('<4H3sB',0,d,v,0x011a,ufd,16)
crc = compute_crc(data)
data += struct.pack('<I',crc)
open(file,'wb').write(data)
@ -96,15 +103,15 @@ if __name__=="__main__":
try:
address,binfile = arg.split(':',1)
except ValueError:
print "Address:file couple '%s' invalid." % arg
print("Address:file couple '%s' invalid." % arg)
sys.exit(1)
try:
address = int(address,0) & 0xFFFFFFFF
except ValueError:
print "Address %s invalid." % address
print("Address %s invalid." % address)
sys.exit(1)
if not os.path.isfile(binfile):
print "Unreadable file '%s'." % binfile
print("Unreadable file '%s'." % binfile)
sys.exit(1)
target.append({ 'address': address, 'data': open(binfile,'rb').read() })
@ -116,7 +123,7 @@ if __name__=="__main__":
try:
address = address & 0xFFFFFFFF
except ValueError:
print "Address %s invalid." % address
print("Address %s invalid." % address)
sys.exit(1)
target.append({ 'address': address, 'data': data })
@ -127,13 +134,13 @@ if __name__=="__main__":
try:
v,d=map(lambda x: int(x,0) & 0xFFFF, device.split(':',1))
except:
print "Invalid device '%s'." % device
print("Invalid device '%s'." % device)
sys.exit(1)
build(outfile,[target],device)
elif len(args)==1:
infile = args[0]
if not os.path.isfile(infile):
print "Unreadable file '%s'." % infile
print("Unreadable file '%s'." % infile)
sys.exit(1)
parse(infile, dump_images=options.dump_images)
else:

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
#
# dfu.py: Access USB DFU class devices
# Copyright (C) 2009 Black Sphere Technologies
@ -62,7 +62,7 @@ DFU_STATUS_ERROR_POR = 0x0d
DFU_STATUS_ERROR_UNKNOWN = 0x0e
DFU_STATUS_ERROR_STALLEDPKT = 0x0f
class dfu_status(object):
class dfu_status:
def __init__(self, buf):
self.bStatus = buf[0]
self.bwPollTimeout = buf[1] + (buf[2]<<8) + (buf[3]<<16)
@ -70,7 +70,7 @@ class dfu_status(object):
self.iString = buf[5]
class dfu_device(object):
class dfu_device:
def __init__(self, dev, conf, iface):
self.dev = dev
self.conf = conf

View File

@ -1,9 +1,9 @@
#!/usr/bin/env python
#!/usr/bin/env python3
#
# gdb.py: Python module for low level GDB protocol implementation
# Copyright (C) 2009 Black Sphere Technologies
# Written by Gareth McMullin <gareth@blacksphere.co.nz>
#
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
@ -24,24 +24,18 @@ import struct
import time
def hexify(s):
"""Convert a binary string into hex representation"""
ret = ''
for c in s:
ret += "%02X" % ord(c)
return ret
"""Convert a bytes object into hex bytes representation"""
return s.hex().encode()
def unhexify(s):
"""Convert a hex string into binary representation"""
ret = ''
for i in range(0, len(s), 2):
ret += chr(int(s[i:i+2], 16))
return ret
"""Convert a hex-encoded bytes into bytes object"""
return bytes.fromhex(s.decode())
class FakeSocket:
"""Emulate socket functions send and recv on a file object"""
def __init__(self, file):
self.file = file
def send(self, data):
self.file.write(data)
@ -52,148 +46,186 @@ class Target:
def __init__(self, sock):
if "send" in dir(sock):
self.sock = sock
else:
else:
self.sock = FakeSocket(sock)
self.PacketSize=0x100 # default
def getpacket(self):
"""Return the first correctly received packet from GDB target"""
while True:
while self.sock.recv(1) != '$': pass
while self.sock.recv(1) != b'$':
pass
csum = 0
packet = ''
packet = [] # list-of-small-int
while True:
c = self.sock.recv(1)
if c == '#': break
c, = self.sock.recv(1)
if c == ord('#'):
break
if c == '$':
packet = ''
if c == ord('$'):
packet = []
csum = 0
continue
if c == '}':
c = self.sock.recv(1)
csum += ord(c) + ord('}')
packet += chr(ord(c) ^ 0x20)
continue
if c == ord('}'):
c, = self.sock.recv(1)
csum += c + ord('}')
packet.append(c ^ 0x20)
continue
packet += c
csum += ord(c)
packet.append(c)
csum += c
if (csum & 0xFF) == int(self.sock.recv(2),16): break
if (csum & 0xFF) == int(self.sock.recv(2),16):
break
self.sock.send('-')
self.sock.send('+')
return packet
self.sock.send(b'-')
self.sock.send(b'+')
return bytes(packet)
def putpacket(self, packet):
"""Send packet to GDB target and wait for acknowledge"""
"""Send packet to GDB target and wait for acknowledge
packet is bytes or string"""
if type(packet) == str:
packet = packet.encode()
while True:
self.sock.send('$')
csum = 0
out = []
for c in packet:
if (c == '$') or (c == '#') or (c == '}'):
self.sock.send('}')
self.sock.send(chr(ord(c) ^ 0x20))
csum += (ord(c) ^ 0x20) + ord('}')
if (c in b'$#}'):
out.append(ord('}'))
out.append(c ^ 0x20)
else:
self.sock.send(c)
csum += ord(c)
self.sock.send('#')
self.sock.send("%02X" % (csum & 0xFF))
if self.sock.recv(1) == '+': break
out.append(c)
csum = sum(out)
outb = b'$'+bytes(out)+b'#%02X' % (csum & 0xff)
self.sock.send(outb)
if self.sock.recv(1) == b'+':
break
def monitor(self, cmd):
"""Send gdb "monitor" command to target"""
if type(cmd) == str:
cmd = cmd.encode()
ret = []
self.putpacket("qRcmd," + hexify(cmd))
self.putpacket(b"qRcmd," + hexify(cmd))
while True:
s = self.getpacket()
if s == '': return None
if s == 'OK': return ret
if s.startswith('O'): ret.append(unhexify(s[1:]))
if s == b'':
return None
if s == b'OK':
return ret
if s.startswith(b'O'):
ret.append(unhexify(s[1:]))
else:
raise Exception('Invalid GDB stub response')
raise Exception('Invalid GDB stub response %r'%s.decode())
def attach(self, pid):
"""Attach to target process (gdb "attach" command)"""
self.putpacket("vAttach;%08X" % pid)
self.putpacket(b"vAttach;%08X" % pid)
reply = self.getpacket()
if (len(reply) == 0) or (reply[0] == 'E'):
if (reply == b'') or (reply[:1] == b'E'):
raise Exception('Failed to attach to remote pid %d' % pid)
def detach(self):
"""Detach from target process (gdb "detach" command)"""
self.putpacket("D")
if self.getpacket() != 'OK':
self.putpacket(b"D")
if self.getpacket() != b'OK':
raise Exception("Failed to detach from remote process")
def reset(self):
"""Reset the target system"""
self.putpacket("r")
self.putpacket(b"r")
def read_mem(self, addr, length):
"""Read length bytes from target at address addr"""
self.putpacket("m%08X,%08X" % (addr, length))
reply = self.getpacket()
if (len(reply) == 0) or (reply[0] == 'E'):
raise Exception('Error reading memory at 0x%08X' % addr)
try:
data = unhexify(reply)
except Excpetion:
raise Exception('Invalid response to memory read packet: %r' % reply)
return data
ret = b''
while length:
# print("Read")
packlen = min(length,self.PacketSize//2)
self.putpacket(b"m%08X,%08X" % (addr, packlen))
reply = self.getpacket()
if (reply == b'') or (reply[:1] == b'E'):
raise Exception('Error reading memory at 0x%08X' % addr)
try:
data = unhexify(reply)
except Exception:
raise Exception('Invalid response to memory read packet: %r' % reply)
ret += data
length -= packlen
addr += packlen
return ret
def write_mem(self, addr, data):
"""Write data to target at address addr"""
self.putpacket("X%08X,%08X:%s" % (addr, len(data), data))
if self.getpacket() != 'OK':
raise Exception('Error writing to memory at 0x%08X' % addr)
data = bytes(data)
while data:
d = data[:self.PacketSize-44]
data = data[len(d):]
#print("Writing %d bytes at 0x%X" % (len(d), addr))
pack = b"X%08X,%08X:%s" % (addr, len(d), d)
self.putpacket(pack)
if self.getpacket() != b'OK':
raise Exception('Error writing to memory at 0x%08X' % addr)
addr += len(d)
def read_regs(self):
"""Read target core registers"""
self.putpacket("g")
self.putpacket(b"g")
reply = self.getpacket()
if (len(reply) == 0) or (reply[0] == 'E'):
raise Exception('Error reading memory at 0x%08X' % addr)
if (reply == b'') or (reply[:1] == b'E'):
raise Exception('Error reading target core registers')
try:
data = unhexify(reply)
except Excpetion:
raise Exception('Invalid response to memory read packet: %r' % reply)
return struct.unpack("=20L", data)
except Exception:
raise Exception('Invalid response to registers read packet: %r' % reply)
ret = array.array('I',data)
return ret
def write_regs(self, *regs):
"""Write target core registers"""
data = struct.pack("=%dL" % len(regs), *regs)
self.putpacket("G" + hexify(data))
if self.getpacket() != 'OK':
self.putpacket(b"G" + hexify(data))
if self.getpacket() != b'OK':
raise Exception('Error writing to target core registers')
def memmap_read(self):
"""Read the XML memory map from target"""
offset = 0
ret = ''
ret = b''
while True:
self.putpacket("qXfer:memory-map:read::%08X,%08X" % (offset, 512))
self.putpacket(b"qXfer:memory-map:read::%08X,%08X" % (offset, 512))
reply = self.getpacket()
if (reply[0] == 'm') or (reply[0] == 'l'):
if (reply[0] in b'ml'):
offset += len(reply) - 1
ret += reply[1:]
else:
raise Exception("Invalid GDB stub response")
raise Exception('Invalid GDB stub response %r'%reply)
if reply[:1] == b'l':
return ret
if reply[0] == 'l': return ret
def resume(self):
"""Resume target execution"""
self.putpacket("c")
self.putpacket(b'c')
def interrupt(self):
"""Interrupt target execution"""
self.sock.send("\x03")
self.sock.send(b'\x03')
def run_stub(self, stub, address, *args):
"""Execute a binary stub at address, passing args in core registers."""
@ -205,11 +237,19 @@ class Target:
regs[15] = address
self.write_regs(*regs)
self.resume()
reply = self.getpacket()
reply = None
while not reply:
reply = self.getpacket()
if not reply.startswith("T05"):
raise Exception("Invalid stop response: %r" % reply)
if not reply.startswith(b"T05"):
message = "Invalid stop response: %r" % reply
try:
message += {'T02':' (SIGINT)',
'T05':' (SIGTRAP)',
'T0B':' (SIGSEGV)',
'T1D':' (SIGLOST)'}[reply]
except KeyError:
pass
raise Exception(message)
class FlashMemory:
def __init__(self, target, offset, length, blocksize):
@ -217,27 +257,30 @@ class Target:
self.offset = offset
self.length = length
self.blocksize = blocksize
self.blocks = list(None for i in range(length / blocksize))
self.blocks = list(None for i in range(length // blocksize))
def prog(self, offset, data):
assert ((offset >= self.offset) and
assert type(data)==bytes
assert ((offset >= self.offset) and
(offset + len(data) <= self.offset + self.length))
while data:
index = (offset - self.offset) / self.blocksize
index = (offset - self.offset) // self.blocksize
bloffset = (offset - self.offset) % self.blocksize
bldata = data[:self.blocksize-bloffset]
data = data[len(bldata):]; offset += len(bldata)
if self.blocks[index] is None: # Initialize a clear block
self.blocks[index] = "".join(chr(0xff) for i in range(self.blocksize))
self.blocks[index] = (self.blocks[index][:bloffset] + bldata +
self.blocks[index] = bytes(0xff for i in range(self.blocksize))
self.blocks[index] = (self.blocks[index][:bloffset] + bldata +
self.blocks[index][bloffset+len(bldata):])
def commit(self, progress_cb=None):
totalblocks = 0
for b in self.blocks:
if b is not None: totalblocks += 1
if b is not None:
totalblocks += 1
block = 0
for i in range(len(self.blocks)):
block += 1
@ -247,35 +290,37 @@ class Target:
# Erase the block
data = self.blocks[i]
addr = self.offset + self.blocksize * i
if data is None: continue
#print "Erasing flash at 0x%X" % (self.offset + self.blocksize*i)
self.target.putpacket("vFlashErase:%08X,%08X" %
if data is None:
continue
#print("Erasing flash at 0x%X" % (self.offset + self.blocksize*i))
self.target.putpacket(b"vFlashErase:%08X,%08X" %
(self.offset + self.blocksize*i, self.blocksize))
if self.target.getpacket() != 'OK':
if self.target.getpacket() != b'OK':
raise Exception("Failed to erase flash")
while data:
d = data[0:980]
data = data[len(d):]
#print "Writing %d bytes at 0x%X" % (len(d), addr)
self.target.putpacket("vFlashWrite:%08X:%s" % (addr, d))
#print("Writing %d bytes at 0x%X" % (len(d), addr))
self.target.putpacket(b"vFlashWrite:%08X:%s" % (addr, d))
addr += len(d)
if self.target.getpacket() != 'OK':
if self.target.getpacket() != b'OK':
raise Exception("Failed to write flash")
self.target.putpacket("vFlashDone")
if self.target.getpacket() != 'OK':
self.target.putpacket(b"vFlashDone")
if self.target.getpacket() != b'OK':
raise Exception("Failed to commit")
self.blocks = list(None for i in range(self.length / self.blocksize))
self.blocks = list(None for i in range(self.length // self.blocksize))
def flash_probe(self):
self.mem = []
xmldom = parseString(self.memmap_read())
for memrange in xmldom.getElementsByTagName("memory"):
if memrange.getAttribute("type") != "flash": continue
if memrange.getAttribute("type") != "flash":
continue
offset = eval(memrange.getAttribute("start"))
length = eval(memrange.getAttribute("length"))
for property in memrange.getElementsByTagName("property"):
@ -297,5 +342,3 @@ class Target:
def flash_commit(self, progress_cb=None):
for m in self.mem:
m.commit(progress_cb)

View File

@ -1,60 +1,56 @@
#!/usr/bin/python
#!/usr/bin/env python3
"""Pulls nRF51 IDs from openocd's nrf51.c in a form suitable for
pasting into blackmagic's nrf51.c
"""
import subprocess,re
import subprocess
import re
import io
cmd = 'git archive --remote=git://git.code.sf.net/p/openocd/code HEAD src/flash/nor/nrf51.c | tar -xO'
cmd = 'git archive --remote=git://git.code.sf.net/p/openocd/code HEAD src/flash/nor/nrf5.c | tar -xO'
class Spec():
def __repr__(self):
return "0x%04X: /* %s %s %s */"%(self.hwid,self.comment, self.variant,self.build_code)
fd = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE).stdout
proc = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE)
specdict={}
specs=[]
spec=Spec()
for line in fd.read().split('\n'):
m=re.search('/\*(.*)\*/',line)
specdict = {}
specs = []
spec = Spec()
for line in io.TextIOWrapper(proc.stdout, encoding="utf-8"):
m = re.search(r'/\*(.*)\*/',line)
if m:
lastcomment=m.group(1)
m=re.search('.hwid.*=\s*(0x[0-9A-F]*),',line)
m = re.search(r'NRF51_DEVICE_DEF\((0x[0-9A-F]*),\s*"(.*)",\s*"(.*)",\s*"(.*)",\s*([0-9]*)\s*\),', line)
if m:
spec.hwid=int(m.group(1),base=0)
m=re.search('.variant.*=\s*"(.*)",',line)
if m:
spec.variant=m.group(1)
m=re.search('.build_code.*=\s*"(.*)",',line)
if m:
spec.build_code=m.group(1)
m=re.search('.flash_size_kb.*=\s*([0-9]*),',line)
if m:
spec.flash_size_kb=int(m.group(1),base=0)
ram,flash = {'AA':(16,256),
'AB':(16,128),
'AC':(32,256)}[spec.variant[-2:]]
assert flash==spec.flash_size_kb
spec.hwid = int(m.group(1), base=0)
spec.variant = m.group(3)
spec.build_code = m.group(4)
spec.flash_size_kb = int(m.group(5), base=0)
ram, flash = {'AA':(16,256),
'AB':(16,128),
'AC':(32,256)}[spec.variant[-2:]]
assert flash == spec.flash_size_kb
spec.ram_size_kb = ram
nicecomment =lastcomment.strip().replace('IC ','').replace('Devices ','').replace('.','')
spec.comment=nicecomment
nicecomment = lastcomment.strip().replace('IC ','').replace('Devices ','').replace('.','')
spec.comment = nicecomment
specdict.setdefault((ram,flash),[]).append(spec)
specs.append(spec)
spec=Spec()
for (ram,flash),specs in specdict.iteritems():
for (ram,flash),specs in specdict.items():
specs.sort(key=lambda x:x.hwid)
for spec in specs:
print "\tcase",spec
print '\t\tt->driver = "Nordic nRF51";'
print '\t\ttarget_add_ram(t, 0x20000000, 0x%X);'%(1024*ram)
print '\t\tnrf51_add_flash(t, 0x00000000, 0x%X, NRF51_PAGE_SIZE);'%(1024*flash)
print '\t\tnrf51_add_flash(t, NRF51_UICR, 0x100, 0x100);'
print '\t\ttarget_add_commands(t, nrf51_cmd_list, "nRF51");'
print '\t\treturn true;'
print("\tcase",spec)
print('\t\tt->driver = "Nordic nRF51";')
print('\t\ttarget_add_ram(t, 0x20000000, 0x%X);'%(1024*ram))
print('\t\tnrf51_add_flash(t, 0x00000000, 0x%X, NRF51_PAGE_SIZE);'%(1024*flash))
print('\t\tnrf51_add_flash(t, NRF51_UICR, 0x100, 0x100);')
print('\t\ttarget_add_commands(t, nrf51_cmd_list, "nRF51");')
print('\t\treturn true;')

View File

@ -1,9 +1,9 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# hexprog.py: Python application to flash a target with an Intel hex file
# Copyright (C) 2011 Black Sphere Technologies
# Written by Gareth McMullin <gareth@blacksphere.co.nz>
#
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
@ -18,7 +18,6 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import gdb
import struct
import time
# Microcode sequence to erase option bytes
@ -31,15 +30,16 @@ def flash_write_hex(target, hexfile, progress_cb=None):
f = open(hexfile)
addrhi = 0
for line in f:
if line[0] != ':': raise Exception("Error in hex file")
if line[0] != ':':
raise Exception("Error in hex file")
reclen = int(line[1:3], 16)
addrlo = int(line[3:7], 16)
rectype = int(line[7:9], 16);
if sum(ord(x) for x in gdb.unhexify(line[1:11+reclen*2])) & 0xff != 0:
raise Exception("Checksum error in hex file")
rectype = int(line[7:9], 16)
if sum(x for x in bytes.fromhex(line[1:11+reclen*2])) & 0xff != 0:
raise Exception("Checksum error in hex file")
if rectype == 0: # Data record
addr = (addrhi << 16) + addrlo
data = gdb.unhexify(line[9:9+reclen*2])
data = bytes.fromhex(line[9:9+reclen*2])
target.flash_write_prepare(addr, data)
pass
elif rectype == 4: # High address record
@ -48,27 +48,27 @@ def flash_write_hex(target, hexfile, progress_cb=None):
elif rectype == 5: # Entry record
pass
elif rectype == 1: # End of file record
break
break
else:
raise Exception("Invalid record in hex file")
try:
target.flash_commit(progress_cb)
except:
print "Flash write failed! Is device protected?\n"
print("Flash write failed! Is device protected?\n")
exit(-1)
if __name__ == "__main__":
from serial import Serial, SerialException
from sys import argv, platform, stdout
from getopt import getopt
if platform == "linux2":
print ("\x1b\x5b\x48\x1b\x5b\x32\x4a") # clear terminal screen
if platform == "linux":
print("\x1b\x5b\x48\x1b\x5b\x32\x4a") # clear terminal screen
print("Black Magic Probe -- Target Production Programming Tool -- version 1.0")
print "Copyright (C) 2011 Black Sphere Technologies"
print "License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>"
print("Copyright (C) 2011 Black Sphere Technologies")
print("License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>")
print("")
dev = "COM1" if platform == "win32" else "/dev/ttyACM0"
@ -80,13 +80,20 @@ if __name__ == "__main__":
try:
opts, args = getopt(argv[1:], "sd:b:t:rR")
for opt in opts:
if opt[0] == "-s": scan = "swdp_scan"
elif opt[0] == "-b": baud = int(opt[1])
elif opt[0] == "-d": dev = opt[1]
elif opt[0] == "-t": targetno = int(opt[1])
elif opt[0] == "-r": unprot = True
elif opt[0] == "-R": prot = True
else: raise Exception()
if opt[0] == "-s":
scan = "swdp_scan"
elif opt[0] == "-b":
baud = int(opt[1])
elif opt[0] == "-d":
dev = opt[1]
elif opt[0] == "-t":
targetno = int(opt[1])
elif opt[0] == "-r":
unprot = True
elif opt[0] == "-R":
prot = True
else:
raise Exception()
hexfile = args[0]
except:
@ -101,39 +108,44 @@ if __name__ == "__main__":
exit(-1)
try:
s = Serial(dev, baud, timeout=3)
s.setDTR(1)
while s.read(1024):
pass
s = Serial(dev) #, baud, timeout=0.1)
#s.setDTR(1)
#s.flushInput()
#while s.read(1024):
# pass
target = gdb.Target(s)
except SerialException, e:
except SerialException as e:
print("FATAL: Failed to open serial device!\n%s\n" % e[0])
exit(-1)
try:
r = target.monitor("version")
for s in r: print s,
except SerialException, e:
for s in r:
print(s.decode(), end=' ')
except SerialException as e:
print("FATAL: Serial communication failure!\n%s\n" % e[0])
exit(-1)
except: pass
#except: pass
print "Target device scan:"
print("Target device scan:")
targetlist = None
r = target.monitor(scan)
for s in r:
print s,
print
for s in r:
print(s.decode(), end=' ')
print()
r = target.monitor("targets")
for s in r:
if s.startswith("No. Att Driver"): targetlist = []
for s in r:
if s.startswith(b"No. Att Driver"):
targetlist = []
try:
if type(targetlist) is list:
if type(targetlist) is list:
targetlist.append(int(s[:2]))
except: pass
except:
pass
#if not targetlist:
# print("FATAL: No usable targets found!\n")
@ -161,7 +173,7 @@ if __name__ == "__main__":
print("FLASH memory -- Offset: 0x%X BlockSize:0x%X\n" % (m.offset, m.blocksize))
def progress(percent):
print ("Progress: %d%%\r" % percent),
print("Progress: %d%%\r" % percent, end=' ')
stdout.flush()
print("Programming target")
@ -179,4 +191,3 @@ if __name__ == "__main__":
target.detach()
print("\nAll operations complete!\n")

View File

@ -1,8 +1,8 @@
#!/usr/bin/env python
#!/usr/bin/env python3
#
# stm32_mem.py: STM32 memory access using USB DFU class
# Copyright (C) 2011 Black Sphere Technologies
# Copyright (C) 2017 Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de)
# Copyright (C) 2017, 2020 Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de)
# Written by Gareth McMullin <gareth@blacksphere.co.nz>
#
# This program is free software: you can redistribute it and/or modify
@ -18,14 +18,12 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from __future__ import print_function
from time import sleep
import struct
import os
from sys import stdout, argv
from sys import stdout
import argparse
import usb
import dfu
CMD_GETCOMMANDS = 0x00
@ -72,7 +70,7 @@ def stm32_read(dev):
return data
def stm32_manifest(dev):
dev.download(0, "")
dev.download(0, b"")
while True:
try:
status = dev.get_status()
@ -87,7 +85,7 @@ def stm32_scan(args, test):
bmp_devs = []
bmp = 0
if not devs:
if test == True:
if test:
return
print("No DFU devices found!")
@ -108,37 +106,37 @@ def stm32_scan(args, test):
bmp_devs.append(dev)
if bmp == 0:
if test == True:
if test:
return
print("No compatible device found\n")
exit(-1)
if bmp > 1 and not args.serial_target:
if test == True:
if test:
return
print("Found multiple devices:\n")
for dev in bmp_devs:
dfudev = dfu.dfu_device(*dev)
man = dfudev.handle.getString(dfudev.dev.iManufacturer, 30)
product = dfudev.handle.getString(dfudev.dev.iProduct, 96)
serial_no = dfudev.handle.getString(dfudev.dev.iSerialNumber, 30)
man = dfudev.handle.getString(dfudev.dev.iManufacturer, 30).decode('utf8')
product = dfudev.handle.getString(dfudev.dev.iProduct, 96).decode('utf8')
serial_no = dfudev.handle.getString(dfudev.dev.iSerialNumber, 30).decode('utf8')
print("Device ID:\t %04x:%04x" % (dfudev.dev.idVendor, dfudev.dev.idProduct))
print("Manufacturer:\t %s" % man)
print("Product:\t %s" % product)
print("Serial:\t\t %s\n" % serial_no)
print("Select device with serial number!")
exit (-1)
exit(-1)
for dev in bmp_devs:
dfudev = dfu.dfu_device(*dev)
man = dfudev.handle.getString(dfudev.dev.iManufacturer, 30)
product = dfudev.handle.getString(dfudev.dev.iProduct, 96)
serial_no = dfudev.handle.getString(dfudev.dev.iSerialNumber, 30)
man = dfudev.handle.getString(dfudev.dev.iManufacturer, 30).decode('utf8')
product = dfudev.handle.getString(dfudev.dev.iProduct, 96).decode('utf8')
serial_no = dfudev.handle.getString(dfudev.dev.iSerialNumber, 30).decode('utf8')
if args.serial_target:
if man == "Black Sphere Technologies" and serial_no == args.serial_target:
if man == "Black Sphere Technologies" and serial_no == args.serial_target:
break
else:
if man == "Black Sphere Technologies":
@ -150,7 +148,7 @@ def stm32_scan(args, test):
print("Serial:\t\t %s" % serial_no)
if args.serial_target and serial_no != args.serial_target:
print("Serial number doesn't match!\n")
print("Serial number doesn't match %s vs %s!\n" % (serial_no, args.serial_target))
exit(-2)
return dfudev
@ -172,7 +170,7 @@ if __name__ == "__main__":
try:
state = dfudev.get_state()
except:
if args.manifest : exit(0)
if args.manifest: exit(0)
print("Failed to read device state! Assuming APP_IDLE")
state = dfu.STATE_APP_IDLE
if state == dfu.STATE_APP_IDLE:
@ -183,15 +181,15 @@ if __name__ == "__main__":
dfudev.release()
print("Invoking DFU Device")
timeout = 0
while True :
sleep(0.5)
while True:
sleep(1)
timeout = timeout + 0.5
dfudev = stm32_scan(args, True)
if dfudev: break
if timeout > 5 :
if timeout > 5:
print("Error: DFU device did not appear")
exit(-1)
if args.manifest :
if args.manifest:
stm32_manifest(dfudev)
print("Invoking Application Device")
exit(0)
@ -203,17 +201,17 @@ if __name__ == "__main__":
bin = file.read()
product = dfudev.handle.getString(dfudev.dev.iProduct, 64)
if args.address :
product = dfudev.handle.getString(dfudev.dev.iProduct, 64).decode('utf8')
if args.address:
start = int(args.address, 0)
else :
if b"F4" in product:
else:
if "F4" in product or "STLINK-V3" in product:
start = 0x8004000
else:
start = 0x8002000
addr = start
while bin:
print ("Programming memory at 0x%08X" % addr, end="\r")
print("Programming memory at 0x%08X" % addr, end="\r")
stdout.flush()
try:
# STM DFU bootloader erases always.
@ -236,7 +234,7 @@ if __name__ == "__main__":
bin = file.read()
len = len(bin)
addr = start
print("-")
print("\n-")
while bin:
try:
stm32_set_address(dfudev, addr)
@ -244,19 +242,19 @@ if __name__ == "__main__":
except:
# Abort silent if bootloader does not support upload
break
print ("Verifying memory at 0x%08X" % addr, end="\r")
print("Verifying memory at 0x%08X" % addr, end="\r")
stdout.flush()
if len > 1024 :
if len > 1024:
size = 1024
else :
else:
size = len
if bin[:size] != bytearray(data[:size]) :
print ("\nMitmatch in block at 0x%08X" % addr)
break;
if bin[:size] != bytearray(data[:size]):
print("\nMismatch in block at 0x%08X" % addr)
break
bin = bin[1024:]
addr += 1024
len -= 1024
if len <= 0 :
if len <= 0:
print("\nVerified!")
stm32_manifest(dfudev)

View File

@ -9,7 +9,7 @@ Q := @
endif
CFLAGS += -Wall -Wextra -Werror -Wno-char-subscripts \
-std=gnu99 -g3 -MD -I./target \
-std=gnu99 -MD -I./target \
-I. -Iinclude -I$(PLATFORM_DIR)
ifeq ($(ENABLE_DEBUG), 1)
@ -39,6 +39,7 @@ SRC = \
lpc17xx.c \
lpc15xx.c \
lpc43xx.c \
lpc546xx.c \
kinetis.c \
main.c \
morse.c \
@ -47,20 +48,24 @@ SRC = \
nxpke04.c \
platform.c \
remote.c \
rp.c \
sam3x.c \
sam4l.c \
samd.c \
samx5x.c \
stm32f1.c \
ch32f1.c \
stm32f4.c \
stm32h7.c \
stm32l0.c \
stm32l4.c \
stm32g0.c \
target.c \
include $(PLATFORM_DIR)/Makefile.inc
OPT_FLAGS ?= -Og
OPT_FLAGS ?= -Os
CFLAGS += $(OPT_FLAGS)
LDFLAGS += $(OPT_FLAGS)
@ -85,8 +90,28 @@ VPATH += platforms/common
CFLAGS += -Iplatforms/common
endif
ifeq ($(ENABLE_RTT), 1)
CFLAGS += -DENABLE_RTT
SRC += rtt.c rtt_if.c
endif
ifdef RTT_IDENT
CFLAGS += -DRTT_IDENT=$(RTT_IDENT)
endif
OBJ = $(patsubst %.S,%.o,$(patsubst %.c,%.o,$(SRC)))
OPTIMIZE := swdptap.o jtagtap.o \
adiv5_jtagdp.o adiv5_swdp.o adiv5.o \
cortexa.o cortexm.o \
gdb_if.o gdb_main.o gdb_hostio.o gdb_packet.o \
jtag_devs.o jtag_scan.o \
crc32.o main.o \
cdcacm.o jeff.o timing.o traceswo.o usbuart.o \
$(OPTIMIZE):: CFLAGS := $(filter-out -Os, $(CFLAGS))
$(OPTIMIZE):: CFLAGS += -O3
$(TARGET): include/version.h $(OBJ)
@echo " LD $@"
$(Q)$(CC) -o $@ $(OBJ) $(LDFLAGS)
@ -102,14 +127,14 @@ $(TARGET): include/version.h $(OBJ)
ifndef PC_HOSTED
%.bin: %.elf
@echo " OBJCOPY $@"
$(Q)$(OBJCOPY) -O binary $^ $@
$(Q)$(OBJCOPY) $(OBJCOPY_FLAGS) -O binary $^ $@
%.hex: %.elf
@echo " OBJCOPY $@"
$(Q)$(OBJCOPY) -O ihex $^ $@
endif
.PHONY: clean host_clean all_platforms FORCE
.PHONY: clean host_clean all_platforms clang-format FORCE
clean: host_clean
$(Q)echo " CLEAN"
@ -117,16 +142,27 @@ clean: host_clean
-$(Q)$(RM) platforms/*/*.o platforms/*/*.d mapfile include/version.h
all_platforms:
$(Q)if [ ! -f ../libopencm3/Makefile ]; then \
echo "Initialising git submodules..." ;\
git submodule init ;\
git submodule update ;\
fi
$(Q)$(MAKE) $(MFLAGS) -C ../libopencm3 lib/stm32/f1 lib/stm32/f4 lib/lm4f
$(Q)set -e ;\
mkdir -p artifacts/$(shell git describe --always) ;\
mkdir -p artifacts/$(shell git describe --always --dirty --tags) ;\
echo "<html><body><ul>" > artifacts/index.html ;\
$(MAKE) clean ;\
for i in platforms/*/Makefile.inc ; do \
export DIRNAME=`dirname $$i` ;\
export PROBE_HOST=`basename $$DIRNAME` ;\
export CFLAGS=-Werror ;\
echo "Building for hardware platform: $$PROBE_HOST" ;\
$(MAKE) $(MAKEFLAGS) clean ;\
$(MAKE) $(MAKEFLAGS);\
$(MAKE);\
if [ -f blackmagic ]; then \
mv blackmagic artifacts/blackmagic-$$PROBE_HOST ;\
echo "<li><a href='blackmagic-$$PROBE_HOST'>$$PROBE_HOST</a></li>"\
>> artifacts/index.html ;\
fi ;\
if [ -f blackmagic.bin ]; then \
mv blackmagic.bin artifacts/blackmagic-$$PROBE_HOST.bin ;\
echo "<li><a href='blackmagic-$$PROBE_HOST.bin'>$$PROBE_HOST</a></li>"\
@ -137,13 +173,31 @@ all_platforms:
echo "<li><a href='blackmagic_dfu-$$PROBE_HOST.bin'>$$PROBE_HOST DFU</a></li>"\
>> artifacts/index.html ;\
fi ;\
$(MAKE) clean ;\
done ;\
echo "</ul></body></html>" >> artifacts/index.html ;\
cp artifacts/*.bin artifacts/$(shell git describe --always)
cp artifacts/blackmagic* artifacts/$(shell git describe --always --dirty --tags)
command.c: include/version.h
GIT_VERSION := $(shell git describe --always --dirty --tags)
VERSION_HEADER := \#define FIRMWARE_VERSION "$(GIT_VERSION)"
include/version.h: FORCE
$(Q)echo " GIT include/version.h"
$(Q)echo "#define FIRMWARE_VERSION \"$(shell git describe --always --dirty)\"" > $@
@# If git isn't found then GIT_VERSION will be an empty string.
ifeq ($(GIT_VERSION),)
@echo Git not found, assuming up to date include/version.h
else
@# Note that when we echo the version to the header file, echo writes a final newline
@# to the file. This is fine and probably makes the file more human-readable, but
@# also means we have to account for that newline in this comparison.
$(Q)if [ ! -f $@ ] || [ "$$(cat $@)" != "$$(echo '$(VERSION_HEADER)\n')" ]; then \
echo " GEN $@"; \
echo '$(VERSION_HEADER)' > $@; \
fi
endif
clang-format:
$(Q)clang-format -i *.c */*.c */*/*.c *.h */*.h */*/*.h
-include *.d

View File

@ -3,6 +3,8 @@
*
* Copyright (C) 2011 Black Sphere Technologies Ltd.
* Written by Gareth McMullin <gareth@blacksphere.co.nz>
* Copyright (C) 2021 Uwe Bonnes
* (bon@elektron.ikp.physik.tu-darmstadt.de)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -27,27 +29,28 @@
#include "command.h"
#include "gdb_packet.h"
#include "target.h"
#include "target_internal.h"
#include "morse.h"
#include "version.h"
#include "serialno.h"
#ifdef ENABLE_RTT
#include "rtt.h"
#endif
#ifdef PLATFORM_HAS_TRACESWO
# include "traceswo.h"
#endif
typedef bool (*cmd_handler)(target *t, int argc, const char **argv);
struct command_s {
const char *cmd;
cmd_handler handler;
const char *help;
};
static bool cmd_version(target *t, int argc, char **argv);
#ifdef PLATFORM_HAS_PRINTSERIAL
static bool cmd_serial(target *t, int argc, char **argv);
#endif
static bool cmd_help(target *t, int argc, char **argv);
static bool cmd_jtag_scan(target *t, int argc, char **argv);
static bool cmd_swdp_scan(target *t, int argc, char **argv);
static bool cmd_frequency(target *t, int argc, char **argv);
static bool cmd_targets(target *t, int argc, char **argv);
static bool cmd_morse(target *t, int argc, char **argv);
static bool cmd_halt_timeout(target *t, int argc, const char **argv);
@ -60,15 +63,29 @@ static bool cmd_target_power(target *t, int argc, const char **argv);
static bool cmd_traceswo(target *t, int argc, const char **argv);
#endif
static bool cmd_heapinfo(target *t, int argc, const char **argv);
#ifdef ENABLE_RTT
static bool cmd_rtt(target *t, int argc, const char **argv);
#endif
#if defined(PLATFORM_HAS_DEBUG) && (PC_HOSTED == 0)
static bool cmd_debug_bmp(target *t, int argc, const char **argv);
#endif
#ifdef PLATFORM_HAS_UART_WHEN_SWDP
static bool cmd_convert_tdio(target *t, int argc, const char **argv);
static bool cmd_set_srst(target *t, int argc, const char **argv);
#endif
#ifdef PLATFORM_HAS_BOOTLOADER
static bool cmd_enter_bootldr(target *t, int argc, const char **argv);
#endif
const struct command_s cmd_list[] = {
{"version", (cmd_handler)cmd_version, "Display firmware version info"},
#ifdef PLATFORM_HAS_PRINTSERIAL
{"serial", (cmd_handler)cmd_serial, "Display firmware serial number"},
#endif
{"help", (cmd_handler)cmd_help, "Display help for monitor commands"},
{"jtag_scan", (cmd_handler)cmd_jtag_scan, "Scan JTAG chain for devices" },
{"swdp_scan", (cmd_handler)cmd_swdp_scan, "Scan SW-DP for devices" },
{"frequency", (cmd_handler)cmd_frequency, "set minimum high and low times" },
{"targets", (cmd_handler)cmd_targets, "Display list of available targets" },
{"morse", (cmd_handler)cmd_morse, "Display morse error message" },
{"halt_timeout", (cmd_handler)cmd_halt_timeout, "Timeout (ms) to wait until Cortex-M is halted: (Default 2000)" },
@ -77,6 +94,9 @@ const struct command_s cmd_list[] = {
#ifdef PLATFORM_HAS_POWER_SWITCH
{"tpwr", (cmd_handler)cmd_target_power, "Supplies power to the target: (enable|disable)"},
#endif
#ifdef ENABLE_RTT
{"rtt", (cmd_handler)cmd_rtt, "enable|disable|status|channel 0..15|ident (str)|cblock|poll maxms minms maxerr" },
#endif
#ifdef PLATFORM_HAS_TRACESWO
#if defined TRACESWO_PROTOCOL && TRACESWO_PROTOCOL == 2
{"traceswo", (cmd_handler)cmd_traceswo, "Start trace capture, NRZ mode: (baudrate) (decode channel ...)" },
@ -87,6 +107,13 @@ const struct command_s cmd_list[] = {
{"heapinfo", (cmd_handler)cmd_heapinfo, "Set semihosting heapinfo" },
#if defined(PLATFORM_HAS_DEBUG) && (PC_HOSTED == 0)
{"debug_bmp", (cmd_handler)cmd_debug_bmp, "Output BMP \"debug\" strings to the second vcom: (enable|disable)"},
#endif
#ifdef PLATFORM_HAS_UART_WHEN_SWDP
{"convert_tdio", (cmd_handler)cmd_convert_tdio,"Switch TDI/O pins to UART TX/RX functions"},
{"set_srst", (cmd_handler)cmd_set_srst,"Set output state of SRST pin (enable|disable)"},
#endif
#ifdef PLATFORM_HAS_BOOTLOADER
{"enter_bootldr", (cmd_handler)cmd_enter_bootldr,"Force BMP into bootloader mode"},
#endif
{NULL, NULL, NULL}
};
@ -95,7 +122,7 @@ bool connect_assert_srst;
#if defined(PLATFORM_HAS_DEBUG) && (PC_HOSTED == 0)
bool debug_bmp;
#endif
long cortexm_wait_timeout = 2000; /* Timeout to wait for Cortex to react on halt command. */
unsigned cortexm_wait_timeout = 2000; /* Timeout to wait for Cortex to react on halt command. */
int command_process(target *t, char *cmd)
{
@ -130,20 +157,24 @@ int command_process(target *t, char *cmd)
return target_command(t, argc, argv);
}
#define BOARD_IDENT "Black Magic Probe" PLATFORM_IDENT FIRMWARE_VERSION
bool cmd_version(target *t, int argc, char **argv)
{
(void)t;
(void)argc;
(void)argv;
#if PC_HOSTED == 1
gdb_outf("Black Magic Probe, PC-Hosted for " PLATFORM_IDENT()
", Version " FIRMWARE_VERSION "\n");
char ident[256];
gdb_ident(ident, sizeof(ident));
DEBUG_WARN("%s\n", ident);
#else
gdb_outf("Black Magic Probe (Firmware " FIRMWARE_VERSION ") (Hardware Version %d)\n", platform_hwversion());
#endif
gdb_out("Copyright (C) 2015 Black Sphere Technologies Ltd.\n");
gdb_out(BOARD_IDENT);
gdb_outf(", Hardware Version %d\n", platform_hwversion());
gdb_out("Copyright (C) 2022 Black Magic Debug Project\n");
gdb_out("License GPLv3+: GNU GPL version 3 or later "
"<http://gnu.org/licenses/gpl.html>\n\n");
#endif
return true;
}
@ -154,10 +185,11 @@ bool cmd_help(target *t, int argc, char **argv)
(void)argv;
const struct command_s *c;
gdb_out("General commands:\n");
for(c = cmd_list; c->cmd; c++)
gdb_outf("\t%s -- %s\n", c->cmd, c->help);
if (!t || t->tc->destroy_callback) {
gdb_out("General commands:\n");
for(c = cmd_list; c->cmd; c++)
gdb_outf("\t%s -- %s\n", c->cmd, c->help);
}
if (!t)
return -1;
@ -215,8 +247,9 @@ static bool cmd_jtag_scan(target *t, int argc, char **argv)
bool cmd_swdp_scan(target *t, int argc, char **argv)
{
(void)t;
(void)argc;
(void)argv;
volatile uint32_t targetid = 0;
if (argc > 1)
targetid = strtol(argv[1], NULL, 0);
if (platform_target_voltage())
gdb_outf("Target voltage: %s\n", platform_target_voltage());
@ -227,9 +260,9 @@ bool cmd_swdp_scan(target *t, int argc, char **argv)
volatile struct exception e;
TRY_CATCH (e, EXCEPTION_ALL) {
#if PC_HOSTED == 1
devs = platform_adiv5_swdp_scan();
devs = platform_adiv5_swdp_scan(targetid);
#else
devs = adiv5_swdp_scan();
devs = adiv5_swdp_scan(targetid);
#endif
}
switch (e.type) {
@ -253,12 +286,46 @@ bool cmd_swdp_scan(target *t, int argc, char **argv)
}
bool cmd_frequency(target *t, int argc, char **argv)
{
(void)t;
if (argc == 2) {
char *p;
uint32_t frequency = strtol(argv[1], &p, 10);
switch(*p) {
case 'k':
frequency *= 1000;
break;
case 'M':
frequency *= 1000*1000;
break;
}
platform_max_frequency_set(frequency);
}
uint32_t freq = platform_max_frequency_get();
if (freq == FREQ_FIXED)
gdb_outf("SWJ freq fixed\n");
else
gdb_outf("Max SWJ freq %08" PRIx32 "\n", freq);
return true;
}
static void display_target(int i, target *t, void *context)
{
(void)context;
gdb_outf("%2d %c %s %s\n", i, target_attached(t)?'*':' ',
target_driver_name(t),
(target_core_name(t)) ? target_core_name(t): "");
if (!strcmp(target_driver_name(t), "ARM Cortex-M")) {
gdb_outf("***%2d%sUnknown %s Designer %3x Partno %3x %s\n",
i, target_attached(t)?" * ":" ",
target_driver_name(t),
target_designer(t),
target_idcode(t),
(target_core_name(t)) ? target_core_name(t): "");
} else {
gdb_outf("%2d %c %s %s\n", i, target_attached(t)?'*':' ',
target_driver_name(t),
(target_core_name(t)) ? target_core_name(t): "");
}
}
bool cmd_targets(target *t, int argc, char **argv)
@ -281,8 +348,10 @@ bool cmd_morse(target *t, int argc, char **argv)
(void)t;
(void)argc;
(void)argv;
if(morse_msg)
if(morse_msg) {
gdb_outf("%s\n", morse_msg);
DEBUG_WARN("%s\n", morse_msg);
}
return true;
}
@ -354,8 +423,15 @@ static bool cmd_target_power(target *t, int argc, const char **argv)
} else if (argc == 2) {
bool want_enable = false;
if (parse_enable_or_disable(argv[1], &want_enable)) {
platform_target_set_power(want_enable);
gdb_outf("%s target power\n", want_enable ? "Enabling" : "Disabling");
if (want_enable
&& !platform_target_get_power()
&& platform_target_voltage_sense() > POWER_CONFLICT_THRESHOLD) {
/* want to enable target power, but VREF > 0.5V sensed -> cancel */
gdb_outf("Target already powered (%s)\n", platform_target_voltage());
} else {
platform_target_set_power(want_enable);
gdb_outf("%s target power\n", want_enable ? "Enabling" : "Disabling");
}
}
} else {
gdb_outf("Unrecognized command format\n");
@ -364,10 +440,86 @@ static bool cmd_target_power(target *t, int argc, const char **argv)
}
#endif
#ifdef ENABLE_RTT
static const char *on_or_off(const bool value)
{
return value ? "on" : "off";
}
static bool cmd_rtt(target *t, int argc, const char **argv)
{
(void)t;
const size_t command_len = strlen(argv[1]);
if (argc == 1 || (argc == 2 && !strncmp(argv[1], "enabled", command_len))) {
rtt_enabled = true;
rtt_found = false;
} else if ((argc == 2) && !strncmp(argv[1], "disabled", command_len)) {
rtt_enabled = false;
rtt_found = false;
} else if ((argc == 2) && !strncmp(argv[1], "status", command_len)) {
gdb_outf("rtt: %s found: %s ident: \"%s\"", on_or_off(rtt_enabled), rtt_found ? "yes" : "no",
rtt_ident[0] == '\0' ? "off" : rtt_ident);
gdb_outf(" halt: %s", on_or_off(target_no_background_memory_access(t)));
gdb_out(" channels: ");
if (rtt_auto_channel)
gdb_out("auto ");
for (size_t i = 0; i < MAX_RTT_CHAN; i++) {
if (rtt_channel[i].is_enabled)
gdb_outf("%d ", i);
}
gdb_outf(
"\nmax poll ms: %u min poll ms: %u max errs: %u\n", rtt_max_poll_ms, rtt_min_poll_ms, rtt_max_poll_errs);
} else if (argc >= 2 && !strncmp(argv[1], "channel", command_len)) {
/* mon rtt channel switches to auto rtt channel selection
mon rtt channel number... selects channels given */
for (size_t i = 0; i < MAX_RTT_CHAN; i++)
rtt_channel[i].is_enabled = false;
if (argc == 2)
rtt_auto_channel = true;
else {
rtt_auto_channel = false;
for (size_t i = 2; i < (size_t)argc; ++i) {
const uint32_t channel = strtoul(argv[i], NULL, 0);
if (channel < MAX_RTT_CHAN)
rtt_channel[channel].is_enabled = true;
}
}
} else if (argc == 2 && !strncmp(argv[1], "ident", command_len))
rtt_ident[0] = '\0';
else if (argc == 2 && !strncmp(argv[1], "poll", command_len))
gdb_outf("%u %u %u\n", rtt_max_poll_ms, rtt_min_poll_ms, rtt_max_poll_errs);
else if (argc == 2 && !strncmp(argv[1], "cblock", command_len)) {
gdb_outf("cbaddr: 0x%x\n", rtt_cbaddr);
gdb_out("ch ena cfg i/o buf@ size head@ tail@ flg\n");
for (size_t i = 0; i < MAX_RTT_CHAN; ++i) {
gdb_outf("%2zu %c %c %s 0x%08x %5d 0x%08x 0x%08x %d\n", i, rtt_channel[i].is_enabled ? 'y' : 'n',
rtt_channel[i].is_configured ? 'y' : 'n', rtt_channel[i].is_output ? "out" : "in ",
rtt_channel[i].buf_addr, rtt_channel[i].buf_size, rtt_channel[i].head_addr, rtt_channel[i].tail_addr,
rtt_channel[i].flag);
}
} else if (argc == 3 && !strncmp(argv[1], "ident", command_len)) {
strncpy(rtt_ident, argv[2], sizeof(rtt_ident));
rtt_ident[sizeof(rtt_ident) - 1] = '\0';
for (size_t i = 0; i < sizeof(rtt_ident); i++) {
if (rtt_ident[i] == '_')
rtt_ident[i] = ' ';
}
} else if (argc == 5 && !strncmp(argv[1], "poll", command_len)) {
/* set polling params */
rtt_max_poll_ms = strtoul(argv[2], NULL, 0);
rtt_min_poll_ms = strtoul(argv[3], NULL, 0);
rtt_max_poll_errs = strtoul(argv[4], NULL, 0);
} else
gdb_out("what?\n");
return true;
}
#endif
#ifdef PLATFORM_HAS_TRACESWO
static bool cmd_traceswo(target *t, int argc, const char **argv)
{
extern char *serial_no;
char serial_no[DFU_SERIAL_LENGTH];
(void)t;
#if TRACESWO_PROTOCOL == 2
uint32_t baudrate = SWO_DEFAULT_BAUD;
@ -413,6 +565,7 @@ static bool cmd_traceswo(target *t, int argc, const char **argv)
#else
traceswo_init(swo_channelmask);
#endif
serial_no_read(serial_no);
gdb_outf("%s:%02X:%02X\n", serial_no, 5, 0x85);
return true;
}
@ -440,6 +593,66 @@ static bool cmd_debug_bmp(target *t, int argc, const char **argv)
return true;
}
#endif
#ifdef PLATFORM_HAS_UART_WHEN_SWDP
static bool cmd_convert_tdio(target *t, int argc, const char **argv)
{
(void)t;
uint8_t val;
if (argc > 1) {
val = (!strcmp(argv[1], "enable")) ? true : false;
usbuart_convert_tdio(val);
} else {
gdb_outf("Convert_tdio: %s\n",(usbuart_convert_tdio_enabled()) ?
"enabled" : "disabled");
}
return true;
}
static bool cmd_set_srst(target *t, int argc, const char **argv)
{
(void) t;
uint8_t val;
if (argc > 1) {
val = (!strcmp(argv[1], "enable")) ? true : false;
platform_srst_set_val(val);
} else {
gdb_outf("SRST: %s\n",(platform_srst_get_val()) ?
"enabled" : "disabled");
}
return true;
}
#endif
#ifdef PLATFORM_HAS_BOOTLOADER
static bool cmd_enter_bootldr(target *t, int argc, const char **argv)
{
(void) t;
(void) argc;
(void) argv;
scb_reset_system();
return true;
}
#endif
#ifdef PLATFORM_HAS_PRINTSERIAL
bool cmd_serial(target *t, int argc, char **argv)
{
(void) t;
(void) argc;
(void) argv;
print_serial();
return true;
}
#endif
static bool cmd_heapinfo(target *t, int argc, const char **argv)
{
if (t == NULL) gdb_out("not attached\n");

View File

@ -20,6 +20,7 @@
#include "general.h"
#include "target.h"
#include "gdb_if.h"
#if !defined(STM32F0) && !defined(STM32F1) && !defined(STM32F2) && \
!defined(STM32F3) && !defined(STM32F4) && !defined(STM32F7) && \
@ -97,14 +98,33 @@ static uint32_t crc32_calc(uint32_t crc, uint8_t data)
return (crc << 8) ^ crc32_table[((crc >> 24) ^ data) & 255];
}
uint32_t generic_crc32(target *t, uint32_t base, size_t len)
int generic_crc32(target *t, uint32_t *crc_res, uint32_t base, size_t len)
{
uint32_t crc = -1;
#if PC_HOSTED == 1
/* Reading a 2 MByte on a H743 takes about 80 s@128, 28s @ 1k,
* 22 s @ 4k and 21 s @ 64k
*/
uint8_t bytes[0x1000];
#else
uint8_t bytes[128];
#endif
#if defined(ENABLE_DEBUG)
uint32_t start_time = platform_time_ms();
#endif
uint32_t last_time = platform_time_ms();
while (len) {
uint32_t actual_time = platform_time_ms();
if ( actual_time > last_time + 1000) {
last_time = actual_time;
gdb_if_putchar(0, true);
}
size_t read_len = MIN(sizeof(bytes), len);
target_mem_read(t, bytes, base, read_len);
if (target_mem_read(t, bytes, base, read_len)) {
DEBUG_WARN("generic_crc32 error around address 0x%08" PRIx32 "\n",
base);
return -1;
}
for (unsigned i = 0; i < read_len; i++)
crc = crc32_calc(crc, bytes[i]);
@ -112,20 +132,32 @@ uint32_t generic_crc32(target *t, uint32_t base, size_t len)
base += read_len;
len -= read_len;
}
return crc;
DEBUG_WARN("%" PRIu32 " ms\n", platform_time_ms() - start_time);
*crc_res = crc;
return 0;
}
#else
#include <libopencm3/stm32/crc.h>
uint32_t generic_crc32(target *t, uint32_t base, size_t len)
int generic_crc32(target *t, uint32_t *crc_res, uint32_t base, size_t len)
{
uint8_t bytes[128];
uint32_t crc;
CRC_CR |= CRC_CR_RESET;
uint32_t last_time = platform_time_ms();
while (len > 3) {
uint32_t actual_time = platform_time_ms();
if ( actual_time > last_time + 1000) {
last_time = actual_time;
gdb_if_putchar(0, true);
}
size_t read_len = MIN(sizeof(bytes), len) & ~3;
target_mem_read(t, bytes, base, read_len);
if (target_mem_read(t, bytes, base, read_len)) {
DEBUG_WARN("generic_crc32 error around address 0x%08" PRIx32 "\n",
base);
return -1;
}
for (unsigned i = 0; i < read_len; i += 4)
CRC_DR = __builtin_bswap32(*(uint32_t*)(bytes+i));
@ -136,7 +168,11 @@ uint32_t generic_crc32(target *t, uint32_t base, size_t len)
crc = CRC_DR;
target_mem_read(t, bytes, base, len);
if (target_mem_read(t, bytes, base, len)) {
DEBUG_WARN("generic_crc32 error around address 0x%08" PRIx32 "\n",
base);
return -1;
}
uint8_t *data = bytes;
while (len--) {
crc ^= *data++ << 24;
@ -147,7 +183,8 @@ uint32_t generic_crc32(target *t, uint32_t base, size_t len)
crc <<= 1;
}
}
return crc;
*crc_res = crc;
return 0;
}
#endif

View File

@ -26,7 +26,6 @@ struct exception *innermost_exception;
void raise_exception(uint32_t type, const char *msg)
{
struct exception *e;
DEBUG_WARN("Exception: %s\n", msg);
for (e = innermost_exception; e; e = e->outer) {
if (e->mask & type) {
e->type = type;
@ -35,6 +34,7 @@ void raise_exception(uint32_t type, const char *msg)
longjmp(e->jmpbuf, type);
}
}
DEBUG_WARN("Unhandled exception: %s\n", msg);
abort();
}

View File

@ -130,4 +130,3 @@ int hostio_system(struct target_controller *tc,
gdb_putpacket_f("Fsystem,%08X/%X", cmd, cmd_len);
return gdb_main_loop(tc, true);
}

View File

@ -35,6 +35,9 @@
#include "command.h"
#include "crc32.h"
#include "morse.h"
#ifdef ENABLE_RTT
#include "rtt.h"
#endif
enum gdb_signal {
GDB_SIGINT = 2,
@ -43,25 +46,37 @@ enum gdb_signal {
GDB_SIGLOST = 29,
};
#define BUF_SIZE 1024
#define BUF_SIZE 1024U
#define ERROR_IF_NO_TARGET() \
if(!cur_target) { gdb_putpacketz("EFF"); break; }
static char pbuf[BUF_SIZE+1];
typedef struct
{
const char *cmd_prefix;
void (*func)(const char *packet, size_t len);
} cmd_executer;
static char pbuf[BUF_SIZE + 1U];
static target *cur_target;
static target *last_target;
static bool gdb_needs_detach_notify = false;
static void handle_q_packet(char *packet, int len);
static void handle_v_packet(char *packet, int len);
static void handle_z_packet(char *packet, int len);
static void handle_q_packet(char *packet, size_t len);
static void handle_v_packet(char *packet, size_t len);
static void handle_z_packet(char *packet, size_t len);
static void handle_kill_target(void);
static void gdb_target_destroy_callback(struct target_controller *tc, target *t)
{
(void)tc;
if (cur_target == t)
if (cur_target == t) {
gdb_put_notificationz("%Stop:W00");
gdb_out("You are now detached from the previous target.\n");
cur_target = NULL;
gdb_needs_detach_notify = true;
}
if (last_target == t)
last_target = NULL;
@ -94,24 +109,22 @@ static struct target_controller gdb_controller = {
int gdb_main_loop(struct target_controller *tc, bool in_syscall)
{
int size;
bool single_step = false;
/* GDB protocol main loop */
while(1) {
while (1) {
SET_IDLE_STATE(1);
size = gdb_getpacket(pbuf, BUF_SIZE);
size_t size = gdb_getpacket(pbuf, BUF_SIZE);
SET_IDLE_STATE(0);
switch(pbuf[0]) {
switch (pbuf[0]) {
/* Implementation of these is mandatory! */
case 'g': { /* 'g': Read general registers */
ERROR_IF_NO_TARGET();
uint8_t arm_regs[target_regs_size(cur_target)];
target_regs_read(cur_target, arm_regs);
gdb_putpacket(hexify(pbuf, arm_regs, sizeof(arm_regs)),
sizeof(arm_regs) * 2);
uint8_t gp_regs[target_regs_size(cur_target)];
target_regs_read(cur_target, gp_regs);
gdb_putpacket(hexify(pbuf, gp_regs, sizeof(gp_regs)), sizeof(gp_regs) * 2U);
break;
}
}
case 'm': { /* 'm addr,len': Read len bytes from addr */
uint32_t addr, len;
ERROR_IF_NO_TARGET();
@ -126,19 +139,20 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall)
if (target_mem_read(cur_target, mem, addr, len))
gdb_putpacketz("E01");
else
gdb_putpacket(hexify(pbuf, mem, len), len*2);
gdb_putpacket(hexify(pbuf, mem, len), len * 2U);
break;
}
}
case 'G': { /* 'G XX': Write general registers */
ERROR_IF_NO_TARGET();
uint8_t arm_regs[target_regs_size(cur_target)];
unhexify(arm_regs, &pbuf[1], sizeof(arm_regs));
target_regs_write(cur_target, arm_regs);
uint8_t gp_regs[target_regs_size(cur_target)];
unhexify(gp_regs, &pbuf[1], sizeof(gp_regs));
target_regs_write(cur_target, gp_regs);
gdb_putpacketz("OK");
break;
}
}
case 'M': { /* 'M addr,len:XX': Write len bytes to addr */
uint32_t addr, len;
uint32_t addr = 0;
uint32_t len = 0;
int hex;
ERROR_IF_NO_TARGET();
sscanf(pbuf, "M%" SCNx32 ",%" SCNx32 ":%n", &addr, &len, &hex);
@ -155,12 +169,25 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall)
else
gdb_putpacketz("OK");
break;
}
}
/* '[m|M|g|G|c][thread-id]' : Set the thread ID for the given subsequent operation
* (we don't actually care which as we only care about the TID for whether to send OK or an error)
*/
case 'H': {
char operation = 0;
uint32_t thread_id = 0;
sscanf(pbuf, "H%c%" SCNx32, &operation, &thread_id);
if (thread_id <= 1)
gdb_putpacketz("OK");
else
gdb_putpacketz("E01");
break;
}
case 's': /* 's [addr]': Single step [start at addr] */
single_step = true;
/* fall through */
case 'c': /* 'c [addr]': Continue [at addr] */
if(!cur_target) {
if (!cur_target) {
gdb_putpacketz("X1D");
break;
}
@ -175,7 +202,7 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall)
target_addr watch;
enum target_halt_reason reason;
if(!cur_target) {
if (!cur_target) {
/* Report "target exited" if no target */
gdb_putpacketz("W00");
break;
@ -183,10 +210,13 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall)
/* Wait for target halt */
while(!(reason = target_halt_poll(cur_target, &watch))) {
unsigned char c = gdb_if_getchar_to(0);
if((c == '\x03') || (c == '\x04')) {
char c = (char)gdb_if_getchar_to(0);
if(c == '\x03' || c == '\x04') {
target_halt_request(cur_target);
}
#ifdef ENABLE_RTT
if (rtt_enabled) poll_rtt(cur_target);
#endif
}
SET_RUN_STATE(0);
@ -209,7 +239,7 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall)
gdb_putpacket_f("T%02X", GDB_SIGTRAP);
}
break;
}
}
/* Optional GDB packet support */
case 'p': { /* Read single register */
@ -218,32 +248,31 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall)
sscanf(pbuf, "p%" SCNx32, &reg);
uint8_t val[8];
size_t s = target_reg_read(cur_target, reg, val, sizeof(val));
if (s > 0) {
if (s > 0)
gdb_putpacket(hexify(pbuf, val, s), s * 2);
} else {
else
gdb_putpacketz("EFF");
}
break;
}
}
case 'P': { /* Write single register */
ERROR_IF_NO_TARGET();
uint32_t reg;
int n;
sscanf(pbuf, "P%" SCNx32 "=%n", &reg, &n);
uint8_t val[strlen(&pbuf[n])/2];
// TODO: FIXME, VLAs considered harmful.
uint8_t val[strlen(&pbuf[n]) / 2];
unhexify(val, pbuf + n, sizeof(val));
if (target_reg_write(cur_target, reg, val, sizeof(val)) > 0) {
if (target_reg_write(cur_target, reg, val, sizeof(val)) > 0)
gdb_putpacketz("OK");
} else {
else
gdb_putpacketz("EFF");
}
break;
}
}
case 'F': /* Semihosting call finished */
if (in_syscall) {
if (in_syscall)
return hostio_reply(tc, pbuf, size);
} else {
else {
DEBUG_GDB("*** F packet when not in syscall! '%s'\n", pbuf);
gdb_putpacketz("");
}
@ -269,12 +298,7 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall)
break;
case 'k': /* Kill the target */
if(cur_target) {
target_reset(cur_target);
target_detach(cur_target);
last_target = cur_target;
cur_target = NULL;
}
handle_kill_target();
break;
case 'r': /* Reset the target system */
@ -284,6 +308,8 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall)
else if(last_target) {
cur_target = target_attach(last_target,
&gdb_controller);
if(cur_target)
morse(NULL, false);
target_reset(cur_target);
}
break;
@ -299,18 +325,18 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall)
}
DEBUG_GDB("X packet: addr = %" PRIx32 ", len = %" PRIx32 "\n",
addr, len);
if (target_mem_write(cur_target, addr, pbuf+bin, len))
if (target_mem_write(cur_target, addr, pbuf + bin, len))
gdb_putpacketz("E01");
else
gdb_putpacketz("OK");
break;
}
}
case 'q': /* General query packet */
handle_q_packet(pbuf, size);
break;
case 'v': /* General query packet */
case 'v': /* Verbose command packet */
handle_v_packet(pbuf, size);
break;
@ -328,182 +354,292 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall)
}
}
static void
handle_q_string_reply(const char *str, const char *param)
static bool exec_command(char *packet, const size_t length, const cmd_executer *exec)
{
unsigned long addr, len;
while (exec->cmd_prefix) {
const size_t prefix_length = strlen(exec->cmd_prefix);
if (!strncmp(packet, exec->cmd_prefix, prefix_length)) {
exec->func(packet + prefix_length, length - prefix_length);
return true;
}
++exec;
}
return false;
}
if (sscanf(param, "%08lx,%08lx", &addr, &len) != 2) {
static void exec_q_rcmd(const char *packet, const size_t length)
{
/* calculate size and allocate buffer for command */
const size_t datalen = length / 2U;
char *data = alloca(datalen + 1);
/* dehexify command */
unhexify(data, packet, datalen);
data[datalen] = 0; /* add terminating null */
const int c = command_process(cur_target, data);
if (c < 0)
gdb_putpacketz("");
else if (c == 0)
gdb_putpacketz("OK");
else
gdb_putpacket(hexify(pbuf, "Failed\n", strlen("Failed\n")),
2 * strlen("Failed\n"));
}
static void handle_q_string_reply(const char *reply, const char *param)
{
const size_t reply_length = strlen(reply);
uint32_t addr = 0;
uint32_t len = 0;
if (sscanf(param, "%08" PRIx32 ",%08" PRIx32, &addr, &len) != 2) {
gdb_putpacketz("E01");
return;
}
if (addr < strlen (str)) {
char reply[len+2];
reply[0] = 'm';
strncpy (reply + 1, &str[addr], len);
if(len > strlen(&str[addr]))
len = strlen(&str[addr]);
gdb_putpacket(reply, len + 1);
} else if (addr == strlen (str)) {
gdb_putpacketz("l");
} else
if (addr > reply_length) {
gdb_putpacketz("E01");
return;
}
if (addr == reply_length) {
gdb_putpacketz("l");
return;
}
size_t output_len = reply_length - addr;
if (output_len > len)
output_len = len;
gdb_putpacket2("m", 1U, reply + addr, output_len);
}
static void
handle_q_packet(char *packet, int len)
static void exec_q_supported(const char *packet, const size_t length)
{
uint32_t addr, alen;
(void)packet;
(void)length;
gdb_putpacket_f("PacketSize=%X;qXfer:memory-map:read+;qXfer:features:read+", BUF_SIZE);
}
if(!strncmp(packet, "qRcmd,", 6)) {
char *data;
int datalen;
static void exec_q_memory_map(const char *packet, const size_t length)
{
(void)packet;
(void)length;
/* Read target XML memory map */
if ((!cur_target) && last_target) {
/* Attach to last target if detached. */
cur_target = target_attach(last_target,
&gdb_controller);
}
if (!cur_target) {
gdb_putpacketz("E01");
return;
}
char buf[1024];
target_mem_map(cur_target, buf, sizeof(buf)); /* Fixme: Check size!*/
handle_q_string_reply(buf, packet);
}
/* calculate size and allocate buffer for command */
datalen = (len - 6) / 2;
data = alloca(datalen+1);
/* dehexify command */
unhexify(data, packet+6, datalen);
data[datalen] = 0; /* add terminating null */
static void exec_q_feature_read(const char *packet, const size_t length)
{
(void)length;
/* Read target description */
if ((!cur_target) && last_target) {
/* Attach to last target if detached. */
cur_target = target_attach(last_target, &gdb_controller);
}
if (!cur_target) {
gdb_putpacketz("E01");
return;
}
handle_q_string_reply(target_tdesc(cur_target), packet);
}
int c = command_process(cur_target, data);
if(c < 0)
gdb_putpacketz("");
else if(c == 0)
gdb_putpacketz("OK");
static void exec_q_crc(const char *packet, const size_t length)
{
(void)length;
uint32_t addr;
uint32_t addr_length;
if (sscanf(packet, "%" PRIx32 ",%" PRIx32, &addr, &addr_length) == 2) {
if (!cur_target) {
gdb_putpacketz("E01");
return;
}
uint32_t crc;
if (generic_crc32(cur_target, &crc, addr, addr_length))
gdb_putpacketz("E03");
else
gdb_putpacketz("E");
} else if (!strncmp (packet, "qSupported", 10)) {
/* Query supported protocol features */
gdb_putpacket_f("PacketSize=%X;qXfer:memory-map:read+;qXfer:features:read+", BUF_SIZE);
} else if (strncmp (packet, "qXfer:memory-map:read::", 23) == 0) {
/* Read target XML memory map */
if((!cur_target) && last_target) {
/* Attach to last target if detached. */
cur_target = target_attach(last_target,
&gdb_controller);
}
if (!cur_target) {
gdb_putpacketz("E01");
return;
}
char buf[1024];
target_mem_map(cur_target, buf, sizeof(buf)); /* Fixme: Check size!*/
handle_q_string_reply(buf, packet + 23);
} else if (strncmp (packet, "qXfer:features:read:target.xml:", 31) == 0) {
/* Read target description */
if((!cur_target) && last_target) {
/* Attach to last target if detached. */
cur_target = target_attach(last_target,
&gdb_controller);
}
if (!cur_target) {
gdb_putpacketz("E01");
return;
}
handle_q_string_reply(target_tdesc(cur_target), packet + 31);
} else if (sscanf(packet, "qCRC:%" PRIx32 ",%" PRIx32, &addr, &alen) == 2) {
if(!cur_target) {
gdb_putpacketz("E01");
return;
}
gdb_putpacket_f("C%lx", generic_crc32(cur_target, addr, alen));
} else {
DEBUG_GDB("*** Unsupported packet: %s\n", packet);
gdb_putpacket("", 0);
gdb_putpacket_f("C%lx", crc);
}
}
static void
handle_v_packet(char *packet, int plen)
/*
* qC queries are for the current thread. We don't support threads but GDB 11 and 12 require this,
* so we always answer that the current thread is thread 1.
*/
static void exec_q_c(const char *packet, const size_t length)
{
unsigned long addr, len;
(void)packet;
(void)length;
gdb_putpacketz("QC1");
}
/*
* qfThreadInfo queries are required in GDB 11 and 12 as these GDBs require the server to support
* threading even when there's only the possiblity for one thread to exist. In this instance,
* we have to tell GDB that there is a single active thread so it doesn't think the "thread" died.
* qsThreadInfo will always follow qfThreadInfo when we reply as we have to specify 'l' at the
* end to terminate the list.. GDB doesn't like this not happening.
*/
static void exec_q_thread_info(const char *packet, const size_t length)
{
(void)length;
if (packet[-11] == 'f')
gdb_putpacketz("m1");
else
gdb_putpacketz("l");
}
static const cmd_executer q_commands[]=
{
{"qRcmd,", exec_q_rcmd},
{"qSupported", exec_q_supported},
{"qXfer:memory-map:read::", exec_q_memory_map},
{"qXfer:features:read:target.xml:",exec_q_feature_read},
{"qCRC:", exec_q_crc},
{"qC", exec_q_c},
{"qfThreadInfo", exec_q_thread_info},
{"qsThreadInfo", exec_q_thread_info},
{NULL, NULL},
};
static void handle_kill_target(void)
{
if (cur_target) {
target_reset(cur_target);
target_detach(cur_target);
last_target = cur_target;
cur_target = NULL;
}
}
static void handle_q_packet(char *packet, const size_t length)
{
if (exec_command(packet, length, q_commands))
return;
DEBUG_GDB("*** Unsupported packet: %s\n", packet);
gdb_putpacket("", 0);
}
static void handle_v_packet(char *packet, const size_t plen)
{
uint32_t addr = 0;
uint32_t len = 0;
int bin;
static uint8_t flash_mode = 0;
if (sscanf(packet, "vAttach;%08lx", &addr) == 1) {
if (sscanf(packet, "vAttach;%08" PRIx32, &addr) == 1) {
/* Attach to remote target processor */
cur_target = target_attach_n(addr, &gdb_controller);
if(cur_target)
gdb_putpacketz("T05");
else
if(cur_target) {
morse(NULL, false);
/*
* We don't actually support threads, but GDB 11 and 12 can't work without
* us saying we attached to thread 1.. see the following for the low-down of this:
* https://sourceware.org/bugzilla/show_bug.cgi?id=28405
* https://sourceware.org/bugzilla/show_bug.cgi?id=28874
* https://sourceware.org/pipermail/gdb-patches/2021-December/184171.html
* https://sourceware.org/pipermail/gdb-patches/2022-April/188058.html
* https://sourceware.org/pipermail/gdb-patches/2022-July/190869.html
*/
gdb_putpacketz("T05thread:1;");
} else
gdb_putpacketz("E01");
} else if (!strncmp(packet, "vKill;", 6)) {
/* Kill the target - we don't actually care about the PID that follows "vKill;" */
handle_kill_target();
gdb_putpacketz("OK");
} else if (!strncmp(packet, "vRun", 4)) {
/* Parse command line for get_cmdline semihosting call */
char cmdline[83];
char *pbuf = cmdline;
char *pcmdline = cmdline;
char *tok = packet + 4;
if (*tok == ';') tok++;
*cmdline='\0';
if (*tok == ';')
++tok;
cmdline[0] = '\0';
while(*tok != '\0') {
if(strlen(cmdline)+3 >= sizeof(cmdline)) break;
if (strlen(cmdline) + 3 >= sizeof(cmdline))
break;
if (*tok == ';') {
*pbuf++=' ';
*pbuf='\0';
*pcmdline++ = ' ';
pcmdline[0] = '\0';
tok++;
continue;
}
if (isxdigit(*tok) && isxdigit(*(tok+1))) {
unhexify(pbuf, tok, 2);
if ((*pbuf == ' ') || (*pbuf == '\\')) {
*(pbuf+1)=*pbuf;
*pbuf++='\\';
if (isxdigit(tok[0]) && isxdigit(tok[1])) {
unhexify(pcmdline, tok, 2);
if ((*pcmdline == ' ') || (*pcmdline == '\\')) {
pcmdline[1] = *pcmdline;
*pcmdline++ = '\\';
}
pbuf++;
tok+=2;
*pbuf='\0';
pcmdline++;
tok += 2;
pcmdline[0] = '\0';
continue;
}
break;
}
#ifdef ENABLE_RTT
/* force searching rtt control block */
rtt_found = false;
#endif
/* Run target program. For us (embedded) this means reset. */
if(cur_target) {
if (cur_target) {
target_set_cmdline(cur_target, cmdline);
target_reset(cur_target);
gdb_putpacketz("T05");
} else if(last_target) {
} else if (last_target) {
cur_target = target_attach(last_target,
&gdb_controller);
/* If we were able to attach to the target again */
if (cur_target) {
/* If we were able to attach to the target again */
if (cur_target) {
target_set_cmdline(cur_target, cmdline);
target_reset(cur_target);
gdb_putpacketz("T05");
} else gdb_putpacketz("E01");
target_reset(cur_target);
morse(NULL, false);
gdb_putpacketz("T05");
} else
gdb_putpacketz("E01");
} else gdb_putpacketz("E01");
} else
gdb_putpacketz("E01");
} else if (sscanf(packet, "vFlashErase:%08lx,%08lx", &addr, &len) == 2) {
} else if (sscanf(packet, "vFlashErase:%08" PRIx32 ",%08" PRIx32, &addr, &len) == 2) {
/* Erase Flash Memory */
DEBUG_GDB("Flash Erase %08lX %08lX\n", addr, len);
if(!cur_target) { gdb_putpacketz("EFF"); return; }
DEBUG_GDB("Flash Erase %08" PRIX32 " %08" PRIX32 "\n", addr, len);
if (!cur_target) {
gdb_putpacketz("EFF");
return;
}
if(!flash_mode) {
if (!flash_mode) {
/* Reset target if first flash command! */
/* This saves us if we're interrupted in IRQ context */
target_reset(cur_target);
flash_mode = 1;
}
if(target_flash_erase(cur_target, addr, len) == 0) {
if (target_flash_erase(cur_target, addr, len) == 0)
gdb_putpacketz("OK");
} else {
else {
flash_mode = 0;
gdb_putpacketz("EFF");
}
} else if (sscanf(packet, "vFlashWrite:%08lx:%n", &addr, &bin) == 1) {
} else if (sscanf(packet, "vFlashWrite:%08" PRIx32 ":%n", &addr, &bin) == 1) {
/* Write Flash Memory */
len = plen - bin;
DEBUG_GDB("Flash Write %08lX %08lX\n", addr, len);
if(cur_target && target_flash_write(cur_target, addr, (void*)packet + bin, len) == 0) {
const uint32_t count = plen - bin;
DEBUG_GDB("Flash Write %08" PRIX32 " %08" PRIX32 "\n", addr, count);
if (cur_target && target_flash_write(cur_target, addr, (void*)packet + bin, count) == 0)
gdb_putpacketz("OK");
} else {
else {
flash_mode = 0;
gdb_putpacketz("EFF");
}
@ -513,39 +649,40 @@ handle_v_packet(char *packet, int plen)
gdb_putpacketz(target_flash_done(cur_target) ? "EFF" : "OK");
flash_mode = 0;
} else if (!strcmp(packet, "vStopped")) {
if (gdb_needs_detach_notify) {
gdb_putpacketz("W00");
gdb_needs_detach_notify = false;
} else
gdb_putpacketz("OK");
} else {
DEBUG_GDB("*** Unsupported packet: %s\n", packet);
gdb_putpacket("", 0);
}
}
static void
handle_z_packet(char *packet, int plen)
static void handle_z_packet(char *packet, const size_t plen)
{
(void)plen;
uint8_t set = (packet[0] == 'Z') ? 1 : 0;
int type, len;
uint32_t type;
uint32_t len;
uint32_t addr;
int ret;
sscanf(packet, "%*[zZ]%" PRIu32 ",%08" PRIx32 ",%" PRIu32, &type, &addr, &len);
/* I have no idea why this doesn't work. Seems to work
* with real sscanf() though... */
//sscanf(packet, "%*[zZ]%hhd,%08lX,%hhd", &type, &addr, &len);
type = packet[1] - '0';
sscanf(packet + 2, ",%" PRIx32 ",%d", &addr, &len);
if(set)
int ret = 0;
if (packet[0] == 'Z')
ret = target_breakwatch_set(cur_target, type, addr, len);
else
ret = target_breakwatch_clear(cur_target, type, addr, len);
if (ret < 0) {
if (ret < 0)
gdb_putpacketz("E01");
} else if (ret > 0) {
else if (ret > 0)
gdb_putpacketz("");
} else {
else
gdb_putpacketz("OK");
}
}
void gdb_main(void)

View File

@ -30,143 +30,196 @@
#include <stdarg.h>
int gdb_getpacket(char *packet, int size)
size_t gdb_getpacket(char *packet, size_t size)
{
unsigned char c;
unsigned char csum;
char recv_csum[3];
int i;
size_t offset = 0;
while(1) {
while (1) {
/* Wait for packet start */
do {
/* Spin waiting for a start of packet character - either a gdb
* start ('$') or a BMP remote packet start ('!').
*/
do {
packet[0] = gdb_if_getchar();
if (packet[0]==0x04) return 1;
/* Smells like bad code */
packet[0] = (char)gdb_if_getchar();
if (packet[0] == 0x04)
return 1;
} while ((packet[0] != '$') && (packet[0] != REMOTE_SOM));
#if PC_HOSTED == 0
if (packet[0]==REMOTE_SOM) {
if (packet[0] == REMOTE_SOM) {
/* This is probably a remote control packet
* - get and handle it */
i=0;
bool gettingRemotePacket=true;
offset = 0;
bool gettingRemotePacket = true;
while (gettingRemotePacket) {
c=gdb_if_getchar();
/* Smells like bad code */
const char c = (char)gdb_if_getchar();
switch (c) {
case REMOTE_SOM: /* Oh dear, packet restarts */
i=0;
offset = 0;
break;
case REMOTE_EOM: /* Complete packet for processing */
packet[i]=0;
remotePacketProcess(i,packet);
gettingRemotePacket=false;
packet[offset] = 0;
remotePacketProcess(offset, packet);
gettingRemotePacket = false;
break;
case '$': /* A 'real' gdb packet, best stop squatting now */
packet[0]='$';
gettingRemotePacket=false;
packet[0] = '$';
gettingRemotePacket = false;
break;
default:
if (i<size) {
packet[i++]=c;
if (offset < size) {
packet[offset++] = c;
} else {
/* Who knows what is going on...return to normality */
gettingRemotePacket=false;
gettingRemotePacket = false;
}
break;
}
}
/* Reset the packet buffer start character to zero, because function
* 'remotePacketProcess()' above overwrites this buffer, and
* an arbitrary character may have been placed there. If this is a '$'
* character, this will cause this loop to be terminated, which is wrong.
*/
packet[0] = 0;
}
#endif
} while (packet[0] != '$');
i = 0; csum = 0;
offset = 0;
csum = 0;
char c;
/* Capture packet data into buffer */
while((c = gdb_if_getchar()) != '#') {
while ((c = (char)gdb_if_getchar()) != '#') {
if(i == size) break; /* Oh shit */
/* If we run out of buffer space, exit early */
if (offset == size)
break;
if(c == '$') { /* Restart capture */
i = 0;
if (c == '$') { /* Restart capture */
offset = 0;
csum = 0;
continue;
}
if(c == '}') { /* escaped char */
if (c == '}') { /* escaped char */
c = gdb_if_getchar();
csum += c + '}';
packet[i++] = c ^ 0x20;
packet[offset++] = c ^ 0x20;
continue;
}
csum += c;
packet[i++] = c;
packet[offset++] = c;
}
recv_csum[0] = gdb_if_getchar();
recv_csum[1] = gdb_if_getchar();
recv_csum[0] = (char)gdb_if_getchar();
recv_csum[1] = (char)gdb_if_getchar();
recv_csum[2] = 0;
/* return packet if checksum matches */
if(csum == strtol(recv_csum, NULL, 16)) break;
if (csum == strtol(recv_csum, NULL, 16))
break;
/* get here if checksum fails */
gdb_if_putchar('-', 1); /* send nack */
}
gdb_if_putchar('+', 1); /* send ack */
packet[i] = 0;
packet[offset] = 0;
#if PC_HOSTED == 1
DEBUG_GDB_WIRE("%s : ", __func__);
for(int j = 0; j < i; j++) {
c = packet[j];
if ((c >= 32) && (c < 127))
for (size_t j = 0; j < offset; j++) {
const char c = packet[j];
if (c >= ' ' && c < 0x7F)
DEBUG_GDB_WIRE("%c", c);
else
DEBUG_GDB_WIRE("\\x%02X", c);
}
DEBUG_GDB_WIRE("\n");
#endif
return i;
return offset;
}
void gdb_putpacket(const char *packet, int size)
static void gdb_next_char(char c, unsigned char *csum)
{
#if PC_HOSTED == 1
if ((c >= 32) && (c < 127))
DEBUG_GDB_WIRE("%c", c);
else
DEBUG_GDB_WIRE("\\x%02X", c);
#endif
if ((c == '$') || (c == '#') || (c == '}') || (c == '*')) {
gdb_if_putchar('}', 0);
gdb_if_putchar(c ^ 0x20, 0);
*csum += '}' + (c ^ 0x20);
}
else {
gdb_if_putchar(c, 0);
*csum += c;
}
}
void gdb_putpacket2(const char *packet1, size_t size1, const char *packet2, size_t size2)
{
int i;
unsigned char csum;
unsigned char c;
char xmit_csum[3];
int tries = 0;
size_t tries = 0;
do {
DEBUG_GDB_WIRE("%s : ", __func__);
csum = 0;
DEBUG_GDB_WIRE("%s: ", __func__);
unsigned char csum = 0;
gdb_if_putchar('$', 0);
for(i = 0; i < size; i++) {
c = packet[i];
#if PC_HOSTED == 1
if ((c >= 32) && (c < 127))
DEBUG_GDB_WIRE("%c", c);
else
DEBUG_GDB_WIRE("\\x%02X", c);
#endif
if((c == '$') || (c == '#') || (c == '}')) {
gdb_if_putchar('}', 0);
gdb_if_putchar(c ^ 0x20, 0);
csum += '}' + (c ^ 0x20);
} else {
gdb_if_putchar(c, 0);
csum += c;
}
}
for (size_t i = 0; i < size1; ++i)
gdb_next_char(packet1[i], &csum);
for (size_t i = 0; i < size2; ++i)
gdb_next_char(packet2[i], &csum);
gdb_if_putchar('#', 0);
snprintf(xmit_csum, sizeof(xmit_csum), "%02X", csum);
gdb_if_putchar(xmit_csum[0], 0);
gdb_if_putchar(xmit_csum[1], 1);
DEBUG_GDB_WIRE("\n");
} while((gdb_if_getchar_to(2000) != '+') && (tries++ < 3));
} while (gdb_if_getchar_to(2000) != '+' && tries++ < 3);
}
void gdb_putpacket(const char *packet, size_t size)
{
char xmit_csum[3];
size_t tries = 0;
do {
DEBUG_GDB_WIRE("%s: ", __func__);
unsigned char csum = 0;
gdb_if_putchar('$', 0);
for (size_t i = 0; i < size; ++i)
gdb_next_char(packet[i], &csum);
gdb_if_putchar('#', 0);
snprintf(xmit_csum, sizeof(xmit_csum), "%02X", csum);
gdb_if_putchar(xmit_csum[0], 0);
gdb_if_putchar(xmit_csum[1], 1);
DEBUG_GDB_WIRE("\n");
} while (gdb_if_getchar_to(2000) != '+' && tries++ < 3);
}
void gdb_put_notification(const char *const packet, const size_t size)
{
char xmit_csum[3];
DEBUG_GDB_WIRE("%s: ", __func__);
uint8_t csum = 0;
gdb_if_putchar('%', 0);
for (size_t i = 0; i < size; ++i)
gdb_next_char(packet[i], &csum);
gdb_if_putchar('#', 0);
snprintf(xmit_csum, sizeof(xmit_csum), "%02X", csum);
gdb_if_putchar(xmit_csum[0], 0);
gdb_if_putchar(xmit_csum[1], 1);
DEBUG_GDB_WIRE("\n");
}
void gdb_putpacket_f(const char *fmt, ...)
@ -184,13 +237,13 @@ void gdb_putpacket_f(const char *fmt, ...)
void gdb_out(const char *buf)
{
char *hexdata;
int i;
hexdata = alloca((i = strlen(buf)*2 + 1) + 1);
hexdata[0] = 'O';
hexify(hexdata+1, buf, strlen(buf));
gdb_putpacket(hexdata, i);
int l = strlen(buf);
char *hexdata = calloc(1, 2 * l + 1);
if (!hexdata)
return;
hexify(hexdata, buf, l);
gdb_putpacket2("O", 1, hexdata, 2 * l);
free(hexdata);
}
void gdb_voutf(const char *fmt, va_list ap)

View File

@ -26,16 +26,16 @@
static const char hexdigits[] = "0123456789abcdef";
char * hexify(char *hex, const void *buf, size_t size)
char *hexify(char *hex, const void *buf, const size_t size)
{
char *tmp = hex;
const uint8_t *b = buf;
char *dst = hex;
const uint8_t *const src = buf;
while (size--) {
*tmp++ = hexdigits[*b >> 4];
*tmp++ = hexdigits[*b++ & 0xF];
for (size_t idx = 0; idx < size; ++idx) {
*dst++ = hexdigits[src[idx] >> 4];
*dst++ = hexdigits[src[idx] & 0xF];
}
*tmp++ = 0;
*dst++ = 0;
return hex;
}
@ -43,20 +43,18 @@ char * hexify(char *hex, const void *buf, size_t size)
static uint8_t unhex_digit(char hex)
{
uint8_t tmp = hex - '0';
if(tmp > 9)
if (tmp > 9)
tmp -= 'A' - '0' - 10;
if(tmp > 16)
if (tmp > 16)
tmp -= 'a' - 'A';
return tmp;
}
char * unhexify(void *buf, const char *hex, size_t size)
char *unhexify(void *buf, const char *hex, const size_t size)
{
uint8_t *b = buf;
while (size--) {
*b = unhex_digit(*hex++) << 4;
*b++ |= unhex_digit(*hex++);
uint8_t *const dst = buf;
for (size_t idx = 0; idx < size; ++idx, hex += 2) {
dst[idx] = (unhex_digit(hex[0]) << 4) | unhex_digit(hex[1]);
}
return buf;
}

View File

@ -21,6 +21,6 @@
#ifndef __CRC32_H
#define __CRC32_H
uint32_t generic_crc32(target *t, uint32_t base, int len);
int generic_crc32(target *t, uint32_t *crc, uint32_t base, int len);
#endif

View File

@ -29,6 +29,8 @@ void gdb_usb_out_cb(usbd_device *dev, uint8_t ep);
int gdb_if_init(void);
unsigned char gdb_if_getchar(void);
unsigned char gdb_if_getchar_to(int timeout);
/* sending gdb_if_putchar(0, true) seems to work as keep alive */
void gdb_if_putchar(unsigned char c, int flush);
#endif

View File

@ -21,17 +21,19 @@
#ifndef __GDB_PACKET_H
#define __GDB_PACKET_H
#include <stddef.h>
#include <stdarg.h>
int gdb_getpacket(char *packet, int size);
void gdb_putpacket(const char *packet, int size);
size_t gdb_getpacket(char *packet, size_t size);
void gdb_putpacket(const char *packet, size_t size);
void gdb_putpacket2(const char *packet1, size_t size1, const char *packet2, size_t size2);
#define gdb_putpacketz(packet) gdb_putpacket((packet), strlen(packet))
void gdb_putpacket_f(const char *packet, ...);
void gdb_put_notification(const char *packet, size_t size);
#define gdb_put_notificationz(packet) gdb_put_notification((packet), strlen(packet))
void gdb_out(const char *buf);
void gdb_voutf(const char *fmt, va_list);
void gdb_outf(const char *fmt, ...);
#endif

View File

@ -21,7 +21,9 @@
#ifndef __GENERAL_H
#define __GENERAL_H
#define _GNU_SOURCE
#if !defined(_GNU_SOURCE)
# define _GNU_SOURCE
#endif
#if !defined(__USE_MINGW_ANSI_STDIO)
# define __USE_MINGW_ANSI_STDIO 1
#endif
@ -37,6 +39,8 @@
#include "platform.h"
#include "platform_support.h"
extern uint32_t delay_cnt;
enum BMP_DEBUG {
BMP_DEBUG_NONE = 0,
BMP_DEBUG_INFO = 1,
@ -48,23 +52,28 @@ enum BMP_DEBUG {
BMP_DEBUG_STDOUT = 0x8000,
};
#define FREQ_FIXED 0xffffffff
#if PC_HOSTED == 0
/* For BMP debug output on a firmware BMP platform, using
* BMP PC-Hosted is the preferred way. Printing DEBUG_WARN
* and DEBUG_INFO is kept for comptibiluty.
*/
# if defined(ENABLE_DEBUG)
# define DEBUG_WARN printf
# define DEBUG_INFO printf
# else
# define DEBUG_WARN(...)
# define DEBUG_INFO(...)
# if !defined(PLATFORM_PRINTF)
# define PLATFORM_PRINTF printf
# endif
# define DEBUG_GDB(...)
# define DEBUG_TARGET(...)
# define DEBUG_PROBE(...)
# define DEBUG_WIRE(...)
# define DEBUG_GDB_WIRE(...)
# if defined(ENABLE_DEBUG)
# define DEBUG_WARN PLATFORM_PRINTF
# define DEBUG_INFO PLATFORM_PRINTF
# else
# define DEBUG_WARN(...) do {} while(0)
# define DEBUG_INFO(...) do {} while(0)
# endif
# define DEBUG_GDB(...) do {} while(0)
# define DEBUG_TARGET(...) do {} while(0)
# define DEBUG_PROBE(...) do {} while(0)
# define DEBUG_WIRE(...) do {} while(0)
# define DEBUG_GDB_WIRE(...) do {} while(0)
#else
# include <stdarg.h>
extern int cl_debuglevel;
@ -155,5 +164,11 @@ static inline void DEBUG_WIRE(const char *format, ...)
#undef MAX
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
#if !defined(SYSTICKHZ)
# define SYSTICKHZ 100
#endif
#define SYSTICKMS (1000 / SYSTICKHZ)
#define MORSECNT ((SYSTICKHZ / 10) - 1)
#endif

View File

@ -37,7 +37,9 @@ void platform_timeout_set(platform_timeout *t, uint32_t ms);
bool platform_timeout_is_expired(platform_timeout *t);
void platform_delay(uint32_t ms);
#define POWER_CONFLICT_THRESHOLD 5 /* in 0.1V, so 5 stands for 0.5V */
extern bool connect_assert_srst;
uint32_t platform_target_voltage_sense(void);
const char *platform_target_voltage(void);
int platform_hwversion(void);
void platform_srst_set_val(bool assert);
@ -45,6 +47,8 @@ bool platform_srst_get_val(void);
bool platform_target_get_power(void);
void platform_target_set_power(bool power);
void platform_request_boot(void);
void platform_max_frequency_set(uint32_t frequency);
uint32_t platform_max_frequency_get(void);
#endif

85
src/include/queue.h Normal file
View File

@ -0,0 +1,85 @@
/*
* Copyright 2018 Robert C. Curtis. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY ROBERT C. CURTIS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ROBERT C. CURTIS OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* The views and conclusions contained in the software and documentation
* are those of the authors and should not be interpreted as representing
* official policies, either expressed or implied, of Robert C. Curtis.
*/
/** @file util/queue.h
* Static queue primitives.
*
* This file contains a set of static queue primitives that are common among
* all of the low level queue implementations. The primitives are inline
* functions, and will be optimal if size is a constant power of 2.
*/
#ifndef I__QUEUE_H__
#define I__QUEUE_H__
/** Increment a queue index.
* @param[in] idx Queue index
* @param[in] size Queue size
* @returns The new queue index value
*/
static inline size_t qinc(size_t idx, size_t size)
{
return ((idx + 1) % size);
}
/** Decrement a queue index.
* @param[in] idx Queue index
* @param[in] size Queue size
* @returns The new queue index value
*/
static inline size_t qdec(size_t idx, size_t size)
{
return ((idx - 1) % size);
}
/** Tests if a queue is full.
* @param[in] head Head index
* @param[in] tail Tail index
* @param[in] size Queue size
*/
static inline int qfull(size_t head, size_t tail, size_t size)
{
size_t next_head = qinc(head, size);
return (next_head == tail);
}
/** Tests if a queue is empty.
* @param[in] head Head index
* @param[in] tail Tail index
*/
static inline int qempty(size_t head, size_t tail)
{
return (head == tail);
}
#endif /* I__QUEUE_H__ */

34
src/include/rtt.h Normal file
View File

@ -0,0 +1,34 @@
#ifndef RTT_H
#define RTT_H
#include <target.h>
#define MAX_RTT_CHAN 16
extern char rtt_ident[16]; // string
extern bool rtt_enabled; // rtt on/off
extern bool rtt_found; // control block found
extern uint32_t rtt_cbaddr; // control block address
extern uint32_t rtt_min_poll_ms; // min time between polls (ms)
extern uint32_t rtt_max_poll_ms; // max time between polls (ms)
extern uint32_t rtt_max_poll_errs; // max number of errors before disconnect
extern bool rtt_auto_channel; // manual or auto channel selection
extern bool rtt_flag_skip; // skip if host-to-target fifo full
extern bool rtt_flag_block; // block if host-to-target fifo full
struct rtt_channel_struct {
bool is_enabled; // does user want to see this channel?
bool is_configured; // is channel configured in control block?
bool is_output;
uint32_t buf_addr;
uint32_t buf_size;
uint32_t head_addr;
uint32_t tail_addr;
uint32_t flag;
};
extern struct rtt_channel_struct rtt_channel[MAX_RTT_CHAN];
// true if target memory access does not work when target running
extern bool target_no_background_memory_access(target *cur_target);
extern void poll_rtt(target *cur_target);
#endif

36
src/include/rtt_if.h Normal file
View File

@ -0,0 +1,36 @@
#ifndef RTT_IF_H
#define RTT_IF_H
/* rtt i/o to terminal */
/* default buffer sizes, 8 bytes added to up buffer for alignment and padding */
/* override RTT_UP_BUF_SIZE and RTT_DOWN_BUF_SIZE in platform.h if needed */
#if !defined(RTT_UP_BUF_SIZE) || !defined(RTT_DOWN_BUF_SIZE)
#if (PC_HOSTED == 1)
#define RTT_UP_BUF_SIZE (4096 + 8)
#define RTT_DOWN_BUF_SIZE (512)
#elif defined(STM32F7)
#define RTT_UP_BUF_SIZE (4096 + 8)
#define RTT_DOWN_BUF_SIZE (2048)
#elif defined(STM32F4)
#define RTT_UP_BUF_SIZE (2048 + 8)
#define RTT_DOWN_BUF_SIZE (256)
#else /* stm32f103 */
#define RTT_UP_BUF_SIZE (1024 + 8)
#define RTT_DOWN_BUF_SIZE (256)
#endif
#endif
/* hosted initialisation */
extern int rtt_if_init(void);
/* hosted teardown */
extern int rtt_if_exit(void);
/* target to host: write len bytes from the buffer starting at buf. return number bytes written */
extern uint32_t rtt_write(const char *buf, uint32_t len);
/* host to target: read one character, non-blocking. return character, -1 if no character */
extern int32_t rtt_getchar();
/* host to target: true if no characters available for reading */
extern bool rtt_nodata();
#endif

View File

@ -20,7 +20,7 @@
#ifndef __SERIALNO_H
#define __SERIALNO_H
char *serialno_read(char *s);
char *serial_no_read(char *s);
#endif

View File

@ -35,13 +35,13 @@ typedef uint32_t target_addr;
struct target_controller;
#if PC_HOSTED == 1
int platform_adiv5_swdp_scan(void);
int platform_adiv5_swdp_scan(uint32_t targetid);
int platform_jtag_scan(const uint8_t *lrlens);
#endif
int adiv5_swdp_scan(void);
int adiv5_swdp_scan(uint32_t targetid);
int jtag_scan(const uint8_t *lrlens);
bool target_foreach(void (*cb)(int i, target *t, void *context), void *context);
int target_foreach(void (*cb)(int i, target *t, void *context), void *context);
void target_list_free(void);
/* Attach/detach functions */
@ -51,6 +51,8 @@ void target_detach(target *t);
bool target_attached(target *t);
const char *target_driver_name(target *t);
const char *target_core_name(target *t);
unsigned int target_designer(target *t);
unsigned int target_idcode(target *t);
/* Memory access functions */
bool target_mem_map(target *t, char *buf, size_t len);

View File

@ -24,6 +24,7 @@ struct platform_timeout {
uint32_t time;
};
extern int32_t swj_delay_cnt;
uint32_t platform_time_ms(void);
#endif /* __TIMING_H */

View File

@ -64,7 +64,7 @@ void morse(const char *msg, char repeat)
DEBUG_WARN("%s\n", msg);
(void) repeat;
#else
morse_msg = morse_ptr = msg;
morse_msg = morse_ptr = msg;
morse_repeat = repeat;
#endif
}

View File

@ -24,6 +24,18 @@
* field firmware upgrade.
*
* The device's unique id is used as the USB serial number string.
*
* Endpoint Usage
*
* 0 Control Endpoint
* IN 1 GDB CDC DATA
* OUT 1 GDB CDC DATA
* IN 2 GDB CDC CTR
* IN 3 UART CDC DATA
* OUT 3 UART CDC DATA
* OUT 4 UART CDC CTRL
* In 5 Trace Capture
*
*/
#include "general.h"
@ -34,15 +46,23 @@
#endif
#include "usbuart.h"
#include "serialno.h"
#include "version.h"
#include <libopencm3/cm3/nvic.h>
#include <libopencm3/usb/usbd.h>
#include <libopencm3/usb/cdc.h>
#include <libopencm3/cm3/scb.h>
#include <libopencm3/usb/dfu.h>
#include <stdlib.h>
#define DFU_IF_NO 4
#define GDB_IF_NO 0
#define UART_IF_NO 2
#define DFU_IF_NO 4
#if defined(PLATFORM_HAS_TRACESWO)
# define TRACE_IF_NO 5
# define TOTAL_INTERFACES 6
#else
# define TOTAL_INTERFACES 5
#endif
usbd_device * usbdev;
@ -51,14 +71,18 @@ static int cdcacm_gdb_dtr = 1;
static void cdcacm_set_modem_state(usbd_device *dev, int iface, bool dsr, bool dcd);
static const struct usb_device_descriptor dev = {
static const struct usb_device_descriptor dev_desc = {
.bLength = USB_DT_DEVICE_SIZE,
.bDescriptorType = USB_DT_DEVICE,
.bcdUSB = 0x0200,
.bDeviceClass = 0xEF, /* Miscellaneous Device */
.bDeviceSubClass = 2, /* Common Class */
.bDeviceProtocol = 1, /* Interface Association */
#if defined(SAMD21E17) || defined(LM4F)
.bMaxPacketSize0 = 64, /*Fixed for icdi*/
#else
.bMaxPacketSize0 = 32,
#endif
.idVendor = 0x1D50,
.idProduct = 0x6018,
.bcdDevice = 0x0100,
@ -74,7 +98,7 @@ static const struct usb_device_descriptor dev = {
static const struct usb_endpoint_descriptor gdb_comm_endp[] = {{
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = 0x82,
.bEndpointAddress = (CDCACM_GDB_ENDPOINT + 1) | USB_REQ_TYPE_IN,
.bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT,
.wMaxPacketSize = 16,
.bInterval = 255,
@ -83,14 +107,14 @@ static const struct usb_endpoint_descriptor gdb_comm_endp[] = {{
static const struct usb_endpoint_descriptor gdb_data_endp[] = {{
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = 0x01,
.bEndpointAddress = CDCACM_GDB_ENDPOINT,
.bmAttributes = USB_ENDPOINT_ATTR_BULK,
.wMaxPacketSize = CDCACM_PACKET_SIZE,
.bInterval = 1,
}, {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = 0x81,
.bEndpointAddress = CDCACM_GDB_ENDPOINT | USB_REQ_TYPE_IN,
.bmAttributes = USB_ENDPOINT_ATTR_BULK,
.wMaxPacketSize = CDCACM_PACKET_SIZE,
.bInterval = 1,
@ -114,7 +138,7 @@ static const struct {
.bDescriptorType = CS_INTERFACE,
.bDescriptorSubtype = USB_CDC_TYPE_CALL_MANAGEMENT,
.bmCapabilities = 0,
.bDataInterface = 1,
.bDataInterface = GDB_IF_NO + 1,
},
.acm = {
.bFunctionLength = sizeof(struct usb_cdc_acm_descriptor),
@ -126,8 +150,8 @@ static const struct {
.bFunctionLength = sizeof(struct usb_cdc_union_descriptor),
.bDescriptorType = CS_INTERFACE,
.bDescriptorSubtype = USB_CDC_TYPE_UNION,
.bControlInterface = 0,
.bSubordinateInterface0 = 1,
.bControlInterface = GDB_IF_NO,
.bSubordinateInterface0 = GDB_IF_NO + 1,
}
};
@ -139,7 +163,7 @@ static const struct usb_interface_descriptor gdb_comm_iface[] = {{
.bNumEndpoints = 1,
.bInterfaceClass = USB_CLASS_CDC,
.bInterfaceSubClass = USB_CDC_SUBCLASS_ACM,
.bInterfaceProtocol = USB_CDC_PROTOCOL_AT,
.bInterfaceProtocol = USB_CDC_PROTOCOL_NONE,
.iInterface = 4,
.endpoint = gdb_comm_endp,
@ -151,7 +175,7 @@ static const struct usb_interface_descriptor gdb_comm_iface[] = {{
static const struct usb_interface_descriptor gdb_data_iface[] = {{
.bLength = USB_DT_INTERFACE_SIZE,
.bDescriptorType = USB_DT_INTERFACE,
.bInterfaceNumber = 1,
.bInterfaceNumber = GDB_IF_NO + 1,
.bAlternateSetting = 0,
.bNumEndpoints = 2,
.bInterfaceClass = USB_CLASS_DATA,
@ -165,19 +189,19 @@ static const struct usb_interface_descriptor gdb_data_iface[] = {{
static const struct usb_iface_assoc_descriptor gdb_assoc = {
.bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE,
.bDescriptorType = USB_DT_INTERFACE_ASSOCIATION,
.bFirstInterface = 0,
.bFirstInterface = GDB_IF_NO,
.bInterfaceCount = 2,
.bFunctionClass = USB_CLASS_CDC,
.bFunctionSubClass = USB_CDC_SUBCLASS_ACM,
.bFunctionProtocol = USB_CDC_PROTOCOL_AT,
.iFunction = 0,
.bFunctionProtocol = USB_CDC_PROTOCOL_NONE,
.iFunction = 4,
};
/* Serial ACM interface */
static const struct usb_endpoint_descriptor uart_comm_endp[] = {{
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = 0x84,
.bEndpointAddress = (CDCACM_UART_ENDPOINT + 1) | USB_REQ_TYPE_IN,
.bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT,
.wMaxPacketSize = 16,
.bInterval = 255,
@ -186,14 +210,14 @@ static const struct usb_endpoint_descriptor uart_comm_endp[] = {{
static const struct usb_endpoint_descriptor uart_data_endp[] = {{
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = 0x03,
.bEndpointAddress = CDCACM_UART_ENDPOINT,
.bmAttributes = USB_ENDPOINT_ATTR_BULK,
.wMaxPacketSize = CDCACM_PACKET_SIZE / 2,
.bInterval = 1,
}, {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = 0x83,
.bEndpointAddress = CDCACM_UART_ENDPOINT | USB_REQ_TYPE_IN,
.bmAttributes = USB_ENDPOINT_ATTR_BULK,
.wMaxPacketSize = CDCACM_PACKET_SIZE,
.bInterval = 1,
@ -217,7 +241,7 @@ static const struct {
.bDescriptorType = CS_INTERFACE,
.bDescriptorSubtype = USB_CDC_TYPE_CALL_MANAGEMENT,
.bmCapabilities = 0,
.bDataInterface = 3,
.bDataInterface = UART_IF_NO + 1,
},
.acm = {
.bFunctionLength = sizeof(struct usb_cdc_acm_descriptor),
@ -229,20 +253,20 @@ static const struct {
.bFunctionLength = sizeof(struct usb_cdc_union_descriptor),
.bDescriptorType = CS_INTERFACE,
.bDescriptorSubtype = USB_CDC_TYPE_UNION,
.bControlInterface = 2,
.bSubordinateInterface0 = 3,
.bControlInterface = UART_IF_NO,
.bSubordinateInterface0 = UART_IF_NO + 1,
}
};
static const struct usb_interface_descriptor uart_comm_iface[] = {{
.bLength = USB_DT_INTERFACE_SIZE,
.bDescriptorType = USB_DT_INTERFACE,
.bInterfaceNumber = 2,
.bInterfaceNumber = UART_IF_NO,
.bAlternateSetting = 0,
.bNumEndpoints = 1,
.bInterfaceClass = USB_CLASS_CDC,
.bInterfaceSubClass = USB_CDC_SUBCLASS_ACM,
.bInterfaceProtocol = USB_CDC_PROTOCOL_AT,
.bInterfaceProtocol = USB_CDC_PROTOCOL_NONE,
.iInterface = 5,
.endpoint = uart_comm_endp,
@ -254,7 +278,7 @@ static const struct usb_interface_descriptor uart_comm_iface[] = {{
static const struct usb_interface_descriptor uart_data_iface[] = {{
.bLength = USB_DT_INTERFACE_SIZE,
.bDescriptorType = USB_DT_INTERFACE,
.bInterfaceNumber = 3,
.bInterfaceNumber = UART_IF_NO + 1,
.bAlternateSetting = 0,
.bNumEndpoints = 2,
.bInterfaceClass = USB_CLASS_DATA,
@ -268,12 +292,12 @@ static const struct usb_interface_descriptor uart_data_iface[] = {{
static const struct usb_iface_assoc_descriptor uart_assoc = {
.bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE,
.bDescriptorType = USB_DT_INTERFACE_ASSOCIATION,
.bFirstInterface = 2,
.bFirstInterface = UART_IF_NO,
.bInterfaceCount = 2,
.bFunctionClass = USB_CLASS_CDC,
.bFunctionSubClass = USB_CDC_SUBCLASS_ACM,
.bFunctionProtocol = USB_CDC_PROTOCOL_AT,
.iFunction = 0,
.bFunctionProtocol = USB_CDC_PROTOCOL_NONE,
.iFunction = 5,
};
const struct usb_dfu_descriptor dfu_function = {
@ -303,7 +327,7 @@ const struct usb_interface_descriptor dfu_iface = {
static const struct usb_iface_assoc_descriptor dfu_assoc = {
.bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE,
.bDescriptorType = USB_DT_INTERFACE_ASSOCIATION,
.bFirstInterface = 4,
.bFirstInterface = DFU_IF_NO,
.bInterfaceCount = 1,
.bFunctionClass = 0xFE,
.bFunctionSubClass = 1,
@ -315,7 +339,7 @@ static const struct usb_iface_assoc_descriptor dfu_assoc = {
static const struct usb_endpoint_descriptor trace_endp[] = {{
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = 0x85,
.bEndpointAddress = TRACE_ENDPOINT | USB_REQ_TYPE_IN,
.bmAttributes = USB_ENDPOINT_ATTR_BULK,
.wMaxPacketSize = 64,
.bInterval = 0,
@ -324,7 +348,7 @@ static const struct usb_endpoint_descriptor trace_endp[] = {{
const struct usb_interface_descriptor trace_iface = {
.bLength = USB_DT_INTERFACE_SIZE,
.bDescriptorType = USB_DT_INTERFACE,
.bInterfaceNumber = 5,
.bInterfaceNumber = TRACE_IF_NO,
.bAlternateSetting = 0,
.bNumEndpoints = 1,
.bInterfaceClass = 0xFF,
@ -338,7 +362,7 @@ const struct usb_interface_descriptor trace_iface = {
static const struct usb_iface_assoc_descriptor trace_assoc = {
.bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE,
.bDescriptorType = USB_DT_INTERFACE_ASSOCIATION,
.bFirstInterface = 5,
.bFirstInterface = TRACE_IF_NO,
.bInterfaceCount = 1,
.bFunctionClass = 0xFF,
.bFunctionSubClass = 0xFF,
@ -377,11 +401,7 @@ static const struct usb_config_descriptor config = {
.bLength = USB_DT_CONFIGURATION_SIZE,
.bDescriptorType = USB_DT_CONFIGURATION,
.wTotalLength = 0,
#if defined(PLATFORM_HAS_TRACESWO)
.bNumInterfaces = 6,
#else
.bNumInterfaces = 5,
#endif
.bNumInterfaces = TOTAL_INTERFACES,
.bConfigurationValue = 1,
.iConfiguration = 0,
.bmAttributes = 0x80,
@ -389,20 +409,17 @@ static const struct usb_config_descriptor config = {
.interface = ifaces,
};
static char serial_no[DFU_SERIAL_LENGTH];
#if defined(STM32L0) || defined(STM32F3) || defined(STM32F4)
char serial_no[13];
#else
char serial_no[9];
#endif
#define BOARD_IDENT "Black Magic Probe " PLATFORM_IDENT FIRMWARE_VERSION
static const char *usb_strings[] = {
"Black Sphere Technologies",
"Black Magic Debug",
BOARD_IDENT,
serial_no,
"Black Magic GDB Server",
"Black Magic UART Port",
DFU_IDENT,
"Black Magic DFU",
#if defined(PLATFORM_HAS_TRACESWO)
"Black Magic Trace Capture",
#endif
@ -416,7 +433,11 @@ static void dfu_detach_complete(usbd_device *dev, struct usb_setup_data *req)
platform_request_boot();
/* Reset core to enter bootloader */
#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
scb_reset_core();
#else
scb_reset_system();
#endif
}
static enum usbd_request_return_codes cdcacm_control_request(usbd_device *dev,
@ -432,7 +453,7 @@ static enum usbd_request_return_codes cdcacm_control_request(usbd_device *dev,
case USB_CDC_REQ_SET_CONTROL_LINE_STATE:
cdcacm_set_modem_state(dev, req->wIndex, true, true);
/* Ignore if not for GDB interface */
if(req->wIndex != 0)
if(req->wIndex != GDB_IF_NO)
return USBD_REQ_HANDLED;
cdcacm_gdb_dtr = req->wValue & 1;
@ -443,10 +464,10 @@ static enum usbd_request_return_codes cdcacm_control_request(usbd_device *dev,
return USBD_REQ_NOTSUPP;
switch(req->wIndex) {
case 2:
case UART_IF_NO:
usbuart_set_line_coding((struct usb_cdc_line_coding*)*buf);
return USBD_REQ_HANDLED;
case 0:
case GDB_IF_NO:
return USBD_REQ_HANDLED; /* Ignore on GDB Port */
default:
return USBD_REQ_NOTSUPP;
@ -496,6 +517,7 @@ static void cdcacm_set_modem_state(usbd_device *dev, int iface, bool dsr, bool d
notif->wLength = 2;
buf[8] = (dsr ? 2 : 0) | (dcd ? 1 : 0);
buf[9] = 0;
/* FIXME: Remove magic numbers */
usbd_ep_write_packet(dev, 0x82 + iface, buf, 10);
}
@ -504,27 +526,30 @@ static void cdcacm_set_config(usbd_device *dev, uint16_t wValue)
configured = wValue;
/* GDB interface */
#if defined(STM32F4) || defined(LM4F)
usbd_ep_setup(dev, 0x01, USB_ENDPOINT_ATTR_BULK,
#if defined(STM32F4) || defined(LM4F) || defined(SAMD)
usbd_ep_setup(dev, CDCACM_GDB_ENDPOINT, USB_ENDPOINT_ATTR_BULK,
CDCACM_PACKET_SIZE, gdb_usb_out_cb);
#else
usbd_ep_setup(dev, 0x01, USB_ENDPOINT_ATTR_BULK,
usbd_ep_setup(dev, CDCACM_GDB_ENDPOINT, USB_ENDPOINT_ATTR_BULK,
CDCACM_PACKET_SIZE, NULL);
#endif
usbd_ep_setup(dev, 0x81, USB_ENDPOINT_ATTR_BULK,
CDCACM_PACKET_SIZE, NULL);
usbd_ep_setup(dev, 0x82, USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL);
usbd_ep_setup(dev, CDCACM_GDB_ENDPOINT | USB_REQ_TYPE_IN,
USB_ENDPOINT_ATTR_BULK, CDCACM_PACKET_SIZE, NULL);
usbd_ep_setup(dev, (CDCACM_GDB_ENDPOINT + 1) | USB_REQ_TYPE_IN,
USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL);
/* Serial interface */
usbd_ep_setup(dev, 0x03, USB_ENDPOINT_ATTR_BULK,
usbd_ep_setup(dev, CDCACM_UART_ENDPOINT, USB_ENDPOINT_ATTR_BULK,
CDCACM_PACKET_SIZE / 2, usbuart_usb_out_cb);
usbd_ep_setup(dev, 0x83, USB_ENDPOINT_ATTR_BULK,
usbd_ep_setup(dev, CDCACM_UART_ENDPOINT | USB_REQ_TYPE_IN,
USB_ENDPOINT_ATTR_BULK,
CDCACM_PACKET_SIZE, usbuart_usb_in_cb);
usbd_ep_setup(dev, 0x84, USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL);
usbd_ep_setup(dev, (CDCACM_UART_ENDPOINT + 1) | USB_REQ_TYPE_IN,
USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL);
#if defined(PLATFORM_HAS_TRACESWO)
/* Trace interface */
usbd_ep_setup(dev, 0x85, USB_ENDPOINT_ATTR_BULK,
usbd_ep_setup(dev, TRACE_ENDPOINT | USB_REQ_TYPE_IN, USB_ENDPOINT_ATTR_BULK,
64, trace_buf_drain);
#endif
@ -536,8 +561,8 @@ static void cdcacm_set_config(usbd_device *dev, uint16_t wValue)
/* Notify the host that DCD is asserted.
* Allows the use of /dev/tty* devices on *BSD/MacOS
*/
cdcacm_set_modem_state(dev, 0, true, true);
cdcacm_set_modem_state(dev, 2, true, true);
cdcacm_set_modem_state(dev, GDB_IF_NO, true, true);
cdcacm_set_modem_state(dev, UART_IF_NO, true, true);
}
/* We need a special large control buffer for this device: */
@ -547,9 +572,9 @@ void cdcacm_init(void)
{
void exti15_10_isr(void);
serialno_read(serial_no);
serial_no_read(serial_no);
usbdev = usbd_init(&USB_DRIVER, &dev, &config, usb_strings,
usbdev = usbd_init(&USB_DRIVER, &dev_desc, &config, usb_strings,
sizeof(usb_strings)/sizeof(char *),
usbd_control_buffer, sizeof(usbd_control_buffer));
@ -557,6 +582,7 @@ void cdcacm_init(void)
nvic_set_priority(USB_IRQ, IRQ_PRI_USB);
nvic_enable_irq(USB_IRQ);
usbd_disconnect(usbdev, false);
}
void USB_ISR(void)

View File

@ -34,6 +34,7 @@
#define CDCACM_GDB_ENDPOINT 1
#define CDCACM_UART_ENDPOINT 3
#define TRACE_ENDPOINT 5
extern usbd_device *usbdev;

View File

@ -70,12 +70,15 @@ static void jtagtap_reset(void)
static uint8_t jtagtap_next(uint8_t dTMS, uint8_t dTDI)
{
uint16_t ret;
register volatile int32_t cnt;
gpio_set_val(TMS_PORT, TMS_PIN, dTMS);
gpio_set_val(TDI_PORT, TDI_PIN, dTDI);
gpio_set(TCK_PORT, TCK_PIN);
for(cnt = swd_delay_cnt -2 ; cnt > 0; cnt--);
ret = gpio_get(TDO_PORT, TDO_PIN);
gpio_clear(TCK_PORT, TCK_PIN);
for(cnt = swd_delay_cnt - 2; cnt > 0; cnt--);
//DEBUG("jtagtap_next(TMS = %d, TDI = %d) = %d\n", dTMS, dTDI, ret);
@ -86,13 +89,27 @@ static void jtagtap_tms_seq(uint32_t MS, int ticks)
{
gpio_set_val(TDI_PORT, TDI_PIN, 1);
int data = MS & 1;
while(ticks) {
gpio_set_val(TMS_PORT, TMS_PIN, data);
gpio_set(TCK_PORT, TCK_PIN);
MS >>= 1;
data = MS & 1;
ticks--;
gpio_clear(TCK_PORT, TCK_PIN);
register volatile int32_t cnt;
if (swd_delay_cnt) {
while(ticks) {
gpio_set_val(TMS_PORT, TMS_PIN, data);
gpio_set(TCK_PORT, TCK_PIN);
for(cnt = swd_delay_cnt -2 ; cnt > 0; cnt--);
MS >>= 1;
data = MS & 1;
ticks--;
gpio_clear(TCK_PORT, TCK_PIN);
for(cnt = swd_delay_cnt -2 ; cnt > 0; cnt--);
}
} else {
while(ticks) {
gpio_set_val(TMS_PORT, TMS_PIN, data);
gpio_set(TCK_PORT, TCK_PIN);
MS >>= 1;
data = MS & 1;
ticks--;
gpio_clear(TCK_PORT, TCK_PIN);
}
}
}
@ -102,42 +119,81 @@ static void jtagtap_tdi_tdo_seq(
uint8_t index = 1;
gpio_set_val(TMS_PORT, TMS_PIN, 0);
uint8_t res = 0;
while(ticks > 1) {
gpio_set_val(TDI_PORT, TDI_PIN, *DI & index);
gpio_set(TCK_PORT, TCK_PIN);
if (gpio_get(TDO_PORT, TDO_PIN)) {
res |= index;
register volatile int32_t cnt;
if (swd_delay_cnt) {
while(ticks > 1) {
gpio_set_val(TDI_PORT, TDI_PIN, *DI & index);
gpio_set(TCK_PORT, TCK_PIN);
for(cnt = swd_delay_cnt -2 ; cnt > 0; cnt--);
if (gpio_get(TDO_PORT, TDO_PIN)) {
res |= index;
}
if(!(index <<= 1)) {
*DO = res;
res = 0;
index = 1;
DI++; DO++;
}
ticks--;
gpio_clear(TCK_PORT, TCK_PIN);
for(cnt = swd_delay_cnt -2 ; cnt > 0; cnt--);
}
if(!(index <<= 1)) {
*DO = res;
res = 0;
index = 1;
DI++; DO++;
} else {
while(ticks > 1) {
gpio_set_val(TDI_PORT, TDI_PIN, *DI & index);
gpio_set(TCK_PORT, TCK_PIN);
if (gpio_get(TDO_PORT, TDO_PIN)) {
res |= index;
}
if(!(index <<= 1)) {
*DO = res;
res = 0;
index = 1;
DI++; DO++;
}
ticks--;
gpio_clear(TCK_PORT, TCK_PIN);
}
ticks--;
gpio_clear(TCK_PORT, TCK_PIN);
}
gpio_set_val(TMS_PORT, TMS_PIN, final_tms);
gpio_set_val(TDI_PORT, TDI_PIN, *DI & index);
gpio_set(TCK_PORT, TCK_PIN);
for(cnt = swd_delay_cnt -2 ; cnt > 0; cnt--);
if (gpio_get(TDO_PORT, TDO_PIN)) {
res |= index;
}
*DO = res;
gpio_clear(TCK_PORT, TCK_PIN);
for(cnt = swd_delay_cnt -2 ; cnt > 0; cnt--);
}
static void jtagtap_tdi_seq(const uint8_t final_tms, const uint8_t *DI, int ticks)
{
uint8_t index = 1;
while(ticks--) {
gpio_set_val(TMS_PORT, TMS_PIN, ticks? 0 : final_tms);
gpio_set_val(TDI_PORT, TDI_PIN, *DI & index);
gpio_set(TCK_PORT, TCK_PIN);
if(!(index <<= 1)) {
index = 1;
DI++;
register volatile int32_t cnt;
if (swd_delay_cnt) {
while(ticks--) {
gpio_set_val(TMS_PORT, TMS_PIN, ticks? 0 : final_tms);
gpio_set_val(TDI_PORT, TDI_PIN, *DI & index);
gpio_set(TCK_PORT, TCK_PIN);
for(cnt = swd_delay_cnt -2 ; cnt > 0; cnt--);
if(!(index <<= 1)) {
index = 1;
DI++;
}
gpio_clear(TCK_PORT, TCK_PIN);
for(cnt = swd_delay_cnt -2 ; cnt > 0; cnt--);
}
} else {
while(ticks--) {
gpio_set_val(TMS_PORT, TMS_PIN, ticks? 0 : final_tms);
gpio_set_val(TDI_PORT, TDI_PIN, *DI & index);
gpio_set(TCK_PORT, TCK_PIN);
if(!(index <<= 1)) {
index = 1;
DI++;
}
gpio_clear(TCK_PORT, TCK_PIN);
}
gpio_clear(TCK_PORT, TCK_PIN);
}
}

View File

@ -21,7 +21,8 @@
/* This file implements the SW-DP interface. */
#include "general.h"
#include "swdptap.h"
#include "timing.h"
#include "adiv5.h"
enum {
SWDIO_STATUS_FLOAT = 0,
@ -39,6 +40,7 @@ static void swdptap_seq_out_parity(uint32_t MS, int ticks)
static void swdptap_turnaround(int dir)
{
static int olddir = SWDIO_STATUS_FLOAT;
register volatile int32_t cnt;
/* Don't turnaround if direction not changing */
if(dir == olddir) return;
@ -51,10 +53,9 @@ static void swdptap_turnaround(int dir)
if(dir == SWDIO_STATUS_FLOAT)
SWDIO_MODE_FLOAT();
gpio_set(SWCLK_PORT, SWCLK_PIN);
gpio_set(SWCLK_PORT, SWCLK_PIN);
gpio_set(SWCLK_PORT, SWCLK_PIN);
gpio_set(SWCLK_PORT, SWCLK_PIN);
for(cnt = swd_delay_cnt; --cnt > 0;);
gpio_clear(SWCLK_PORT, SWCLK_PIN);
for(cnt = swd_delay_cnt; --cnt > 0;);
if(dir == SWDIO_STATUS_DRIVE)
SWDIO_MODE_DRIVE();
}
@ -64,21 +65,30 @@ static uint32_t swdptap_seq_in(int ticks)
uint32_t index = 1;
uint32_t ret = 0;
int len = ticks;
register volatile int32_t cnt;
swdptap_turnaround(SWDIO_STATUS_FLOAT);
while (len--) {
int res;
res = gpio_get(SWDIO_PORT, SWDIO_PIN);
gpio_set(SWCLK_PORT, SWCLK_PIN);
gpio_set(SWCLK_PORT, SWCLK_PIN);
gpio_set(SWCLK_PORT, SWCLK_PIN);
gpio_set(SWCLK_PORT, SWCLK_PIN);
if (res)
ret |= index;
index <<= 1;
gpio_clear(SWCLK_PORT, SWCLK_PIN);
if (swd_delay_cnt) {
while (len--) {
int res;
res = gpio_get(SWDIO_PORT, SWDIO_PIN);
gpio_set(SWCLK_PORT, SWCLK_PIN);
for(cnt = swd_delay_cnt; --cnt > 0;);
ret |= (res) ? index : 0;
index <<= 1;
gpio_clear(SWCLK_PORT, SWCLK_PIN);
for(cnt = swd_delay_cnt; --cnt > 0;);
}
} else {
volatile int res;
while (len--) {
res = gpio_get(SWDIO_PORT, SWDIO_PIN);
gpio_set(SWCLK_PORT, SWCLK_PIN);
ret |= (res) ? index : 0;
index <<= 1;
gpio_clear(SWCLK_PORT, SWCLK_PIN);
}
}
#ifdef DEBUG_SWD_BITS
for (int i = 0; i < len; i++)
DEBUG("%d", (ret & (1 << i)) ? 1 : 0);
@ -92,31 +102,42 @@ static bool swdptap_seq_in_parity(uint32_t *ret, int ticks)
uint32_t res = 0;
bool bit;
int len = ticks;
register volatile int32_t cnt;
swdptap_turnaround(SWDIO_STATUS_FLOAT);
while (len--) {
bit = gpio_get(SWDIO_PORT, SWDIO_PIN);
gpio_set(SWCLK_PORT, SWCLK_PIN);
gpio_set(SWCLK_PORT, SWCLK_PIN);
gpio_set(SWCLK_PORT, SWCLK_PIN);
if (bit)
res |= index;
index <<= 1;
gpio_clear(SWCLK_PORT, SWCLK_PIN);
if (swd_delay_cnt) {
while (len--) {
bit = gpio_get(SWDIO_PORT, SWDIO_PIN);
gpio_set(SWCLK_PORT, SWCLK_PIN);
for(cnt = swd_delay_cnt; --cnt > 0;);
res |= (bit) ? index : 0;
index <<= 1;
gpio_clear(SWCLK_PORT, SWCLK_PIN);
for(cnt = swd_delay_cnt; --cnt > 0;);
}
} else {
while (len--) {
bit = gpio_get(SWDIO_PORT, SWDIO_PIN);
gpio_set(SWCLK_PORT, SWCLK_PIN);
res |= (bit) ? index : 0;
index <<= 1;
gpio_clear(SWCLK_PORT, SWCLK_PIN);
}
}
int parity = __builtin_popcount(res);
bit = gpio_get(SWDIO_PORT, SWDIO_PIN);
gpio_set(SWCLK_PORT, SWCLK_PIN);
if (bit)
parity++;
else
gpio_set(SWCLK_PORT, SWCLK_PIN);
for(cnt = swd_delay_cnt; --cnt > 0;);
parity += (bit) ? 1 : 0;
gpio_clear(SWCLK_PORT, SWCLK_PIN);
for(cnt = swd_delay_cnt; --cnt > 0;);
#ifdef DEBUG_SWD_BITS
for (int i = 0; i < len; i++)
DEBUG("%d", (res & (1 << i)) ? 1 : 0);
#endif
*ret = res;
/* Terminate the read cycle now */
swdptap_turnaround(SWDIO_STATUS_DRIVE);
return (parity & 1);
}
@ -126,14 +147,25 @@ static void swdptap_seq_out(uint32_t MS, int ticks)
for (int i = 0; i < ticks; i++)
DEBUG("%d", (MS & (1 << i)) ? 1 : 0);
#endif
register volatile int32_t cnt;
swdptap_turnaround(SWDIO_STATUS_DRIVE);
gpio_set_val(SWDIO_PORT, SWDIO_PIN, MS & 1);
while (ticks--) {
gpio_set(SWCLK_PORT, SWCLK_PIN);
MS >>= 1;
gpio_set_val(SWDIO_PORT, SWDIO_PIN, MS & 1);
gpio_clear(SWCLK_PORT, SWCLK_PIN);
gpio_clear(SWCLK_PORT, SWCLK_PIN);
if (swd_delay_cnt) {
while (ticks--) {
gpio_set(SWCLK_PORT, SWCLK_PIN);
for(cnt = swd_delay_cnt; --cnt > 0;);
MS >>= 1;
gpio_set_val(SWDIO_PORT, SWDIO_PIN, MS & 1);
gpio_clear(SWCLK_PORT, SWCLK_PIN);
for(cnt = swd_delay_cnt; --cnt > 0;);
}
} else {
while (ticks--) {
gpio_set(SWCLK_PORT, SWCLK_PIN);
MS >>= 1;
gpio_set_val(SWDIO_PORT, SWDIO_PIN, MS & 1);
gpio_clear(SWCLK_PORT, SWCLK_PIN);
}
}
}
@ -144,30 +176,40 @@ static void swdptap_seq_out_parity(uint32_t MS, int ticks)
for (int i = 0; i < ticks; i++)
DEBUG("%d", (MS & (1 << i)) ? 1 : 0);
#endif
register volatile int32_t cnt;
swdptap_turnaround(SWDIO_STATUS_DRIVE);
gpio_set_val(SWDIO_PORT, SWDIO_PIN, MS & 1);
MS >>= 1;
while (ticks--) {
gpio_set(SWCLK_PORT, SWCLK_PIN);
gpio_set_val(SWDIO_PORT, SWDIO_PIN, MS & 1);
MS >>= 1;
gpio_clear(SWCLK_PORT, SWCLK_PIN);
if (swd_delay_cnt) {
while (ticks--) {
gpio_set(SWCLK_PORT, SWCLK_PIN);
for(cnt = swd_delay_cnt; --cnt > 0;);
gpio_set_val(SWDIO_PORT, SWDIO_PIN, MS & 1);
MS >>= 1;
gpio_clear(SWCLK_PORT, SWCLK_PIN);
for(cnt = swd_delay_cnt; --cnt > 0;);
}
} else {
while (ticks--) {
gpio_set(SWCLK_PORT, SWCLK_PIN);
gpio_set_val(SWDIO_PORT, SWDIO_PIN, MS & 1);
MS >>= 1;
gpio_clear(SWCLK_PORT, SWCLK_PIN);
}
}
gpio_set_val(SWDIO_PORT, SWDIO_PIN, parity & 1);
gpio_set(SWCLK_PORT, SWCLK_PIN);
gpio_set(SWCLK_PORT, SWCLK_PIN);
gpio_set(SWCLK_PORT, SWCLK_PIN);
for(cnt = swd_delay_cnt; --cnt > 0;);
gpio_clear(SWCLK_PORT, SWCLK_PIN);
for(cnt = swd_delay_cnt; --cnt > 0;);
}
swd_proc_t swd_proc;
int swdptap_init(void)
int swdptap_init(ADIv5_DP_t *dp)
{
swd_proc.swdptap_seq_in = swdptap_seq_in;
swd_proc.swdptap_seq_in_parity = swdptap_seq_in_parity;
swd_proc.swdptap_seq_out = swdptap_seq_out;
swd_proc.swdptap_seq_out_parity = swdptap_seq_out_parity;
dp->seq_in = swdptap_seq_in;
dp->seq_in_parity = swdptap_seq_in_parity;
dp->seq_out = swdptap_seq_out;
dp->seq_out_parity = swdptap_seq_out_parity;
return 0;
}

View File

@ -1,18 +1,35 @@
CROSS_COMPILE ?= arm-none-eabi-
BMP_BOOTLOADER ?=
CC = $(CROSS_COMPILE)gcc
OBJCOPY = $(CROSS_COMPILE)objcopy
CFLAGS += -Istm32/include -mcpu=cortex-m4 -mthumb \
-mfloat-abi=hard -mfpu=fpv4-sp-d16 \
-DSTM32F4 -DF4DISCOVERY -I../libopencm3/include \
-DSTM32F4 -I../libopencm3/include \
-Iplatforms/stm32
LDFLAGS = -lopencm3_stm32f4 \
-Wl,-T,platforms/stm32/f4discovery.ld -nostartfiles -lc -lnosys \
ifeq ($(BLACKPILL), 1)
LINKER_SCRIPT=platforms/stm32/blackpillv2.ld
CFLAGS += -DBLACKPILL=1
else
LINKER_SCRIPT=platforms/stm32/f4discovery.ld
endif
LDFLAGS_BOOT = -lopencm3_stm32f4 \
-Wl,-T,$(LINKER_SCRIPT) -nostartfiles -lc -lnosys \
-Wl,-Map=mapfile -mthumb -mcpu=cortex-m4 -Wl,-gc-sections \
-mfloat-abi=hard -mfpu=fpv4-sp-d16 \
-L../libopencm3/lib
ifeq ($(BMP_BOOTLOADER), 1)
$(info Load address 0x08004000 for BMPBootloader)
LDFLAGS = $(LDFLAGS_BOOT) -Wl,-Ttext=0x8004000
CFLAGS += -DDFU_SERIAL_LENGTH=9
else
LDFLAGS += $(LDFLAGS_BOOT)
CFLAGS += -DDFU_SERIAL_LENGTH=13
endif
VPATH += platforms/stm32
SRC += cdcacm.c \
@ -23,7 +40,18 @@ SRC += cdcacm.c \
timing.c \
timing_stm32.c \
ifneq ($(BMP_BOOTLOADER), 1)
all: blackmagic.bin
else
all: blackmagic.bin blackmagic_dfu.bin blackmagic_dfu.hex
blackmagic_dfu: usbdfu.o dfucore.o dfu_f4.o serialno.o
$(CC) $^ -o $@ $(LDFLAGS_BOOT)
blackmagic_dfu.bin: blackmagic_dfu
$(OBJCOPY) -O binary $^ $@
blackmagic_dfu.hex: blackmagic_dfu
$(OBJCOPY) -O ihex $^ $@
endif
host_clean:
-$(Q)$(RM) blackmagic.bin

View File

@ -11,3 +11,55 @@ PC6: TDO/TRACESWO<br>
PC1: TRST<br>
PC8: SRST<br>
# Alternate build for stm32f401 stm32f411 MiniF4 aka BlackPillV2 boards.
https://github.com/WeActTC/MiniSTM32F4x1
## Connections:
* JTAG/SWD
* PA1: TDI
* PA13: TMS/SWDIO
* PA14: TCK/SWCLK
* PB3: TDO/TRACESWO
* PB5: TRST
* PB4: SRST
* USB USART
* PB6: USART1 TX (usbuart_xxx)
* PB7: USART1 RX (usbuart_xxx)
* +3V3.
* PB8 - turn on IRLML5103 transistor
How to Build
========================================
```
cd blackmagic
make clean
make PROBE_HOST=f4discovery BLACKPILL=1
```
How to Flash with dfu
========================================
* After build:
* 1) `apt install dfu-util`
* 2) Force the F4 into system bootloader mode by jumpering "BOOT0" to "3V3" and "PB2/BOOT1" to "GND" and reset (RESET button). System bootloader should appear.
* 3) `dfu-util -a 0 --dfuse-address 0x08000000 -D blackmagic.bin`
To exit from dfu mode press a "key" and "reset", release reset. BMP firmware should appear
10 pin male from pins
========================================
| PB3/TDO | PB7/RX | PB6/TX | X | PA1/TDI |
| -------- | ----------- | ---------- | ---------- | ------- |
| PB4/SRST | +3V3/PB8 SW | PA13/SWDIO | PA14/SWCLK | GND |
SWJ frequency setting
====================================
https://github.com/blackmagic-debug/blackmagic/pull/783#issue-529197718
`mon freq 900k` helps at most

View File

@ -27,7 +27,7 @@
#include "usbuart.h"
#include "morse.h"
#include <libopencm3/stm32/f4/rcc.h>
#include <libopencm3/stm32/rcc.h>
#include <libopencm3/cm3/scb.h>
#include <libopencm3/cm3/nvic.h>
#include <libopencm3/stm32/exti.h>
@ -37,20 +37,32 @@
#include <libopencm3/cm3/systick.h>
#include <libopencm3/cm3/cortex.h>
#ifdef BLACKPILL
#include <libopencm3/usb/dwc/otg_fs.h>
#endif
jmp_buf fatal_error_jmpbuf;
extern char _ebss[];
void platform_init(void)
{
volatile uint32_t *magic = (uint32_t *)_ebss;
/* Check the USER button*/
/* Enable GPIO peripherals */
rcc_periph_clock_enable(RCC_GPIOA);
rcc_periph_clock_enable(RCC_GPIOC);
#ifdef BLACKPILL
rcc_periph_clock_enable(RCC_GPIOB);
#else
rcc_periph_clock_enable(RCC_GPIOD);
#endif
/* Check the USER button*/
if (gpio_get(GPIOA, GPIO0) ||
((magic[0] == BOOTMAGIC0) && (magic[1] == BOOTMAGIC1))) {
((magic[0] == BOOTMAGIC0) && (magic[1] == BOOTMAGIC1)))
{
magic[0] = 0;
magic[1] = 0;
/* Assert blue LED as indicator we are in the bootloader */
rcc_periph_clock_enable(RCC_GPIOD);
gpio_mode_setup(LED_PORT, GPIO_MODE_OUTPUT,
GPIO_PUPD_NONE, LED_BOOTLOADER);
gpio_set(LED_PORT, LED_BOOTLOADER);
@ -58,41 +70,65 @@ void platform_init(void)
As we just come out of reset, no other deinit is needed!*/
rcc_periph_clock_enable(RCC_SYSCFG);
SYSCFG_MEMRM &= ~3;
SYSCFG_MEMRM |= 1;
SYSCFG_MEMRM |= 1;
scb_reset_core();
}
#ifdef BLACKPILL
rcc_clock_setup_pll(&rcc_hse_25mhz_3v3[RCC_CLOCK_3V3_84MHZ]);
#else
rcc_clock_setup_pll(&rcc_hse_8mhz_3v3[RCC_CLOCK_3V3_168MHZ]);
#endif
/* Enable peripherals */
rcc_periph_clock_enable(RCC_OTGFS);
rcc_periph_clock_enable(RCC_GPIOC);
rcc_periph_clock_enable(RCC_GPIOD);
rcc_periph_clock_enable(RCC_CRC);
/* Set up USB Pins and alternate function*/
gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO11 | GPIO12);
gpio_set_af(GPIOA, GPIO_AF10, GPIO11 | GPIO12);
gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO9 | GPIO11 | GPIO12);
gpio_set_af(GPIOA, GPIO_AF10, GPIO9 | GPIO10 | GPIO11 | GPIO12);
GPIOC_OSPEEDR &=~0xF30;
#ifdef BLACKPILL
GPIOA_OSPEEDR &= 0x3C00000C;
GPIOA_OSPEEDR |= 0x28000008;
#else
GPIOC_OSPEEDR &= ~0xF30;
GPIOC_OSPEEDR |= 0xA20;
gpio_mode_setup(JTAG_PORT, GPIO_MODE_OUTPUT,
GPIO_PUPD_NONE,
TCK_PIN | TDI_PIN);
gpio_mode_setup(JTAG_PORT, GPIO_MODE_INPUT,
GPIO_PUPD_NONE, TMS_PIN);
#endif
gpio_mode_setup(JTAG_PORT, GPIO_MODE_OUTPUT,
GPIO_PUPD_NONE,
TCK_PIN | TDI_PIN);
gpio_mode_setup(JTAG_PORT, GPIO_MODE_INPUT,
GPIO_PUPD_NONE, TMS_PIN);
gpio_set_output_options(JTAG_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_2MHZ,
TCK_PIN | TDI_PIN | TMS_PIN);
gpio_mode_setup(TDO_PORT, GPIO_MODE_INPUT,
GPIO_PUPD_NONE,
TDO_PIN);
GPIO_PUPD_NONE,
TDO_PIN);
gpio_set_output_options(TDO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_2MHZ,
TDO_PIN | TMS_PIN);
gpio_mode_setup(LED_PORT, GPIO_MODE_OUTPUT,
GPIO_PUPD_NONE,
LED_UART | LED_IDLE_RUN | LED_ERROR | LED_BOOTLOADER);
GPIO_PUPD_NONE,
LED_IDLE_RUN | LED_ERROR | LED_BOOTLOADER);
gpio_mode_setup(LED_PORT_UART, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LED_UART);
#ifdef PLATFORM_HAS_POWER_SWITCH
gpio_set(PWR_BR_PORT, PWR_BR_PIN);
gpio_mode_setup(PWR_BR_PORT, GPIO_MODE_OUTPUT,
GPIO_PUPD_NONE,
PWR_BR_PIN);
#endif
platform_timing_init();
usbuart_init();
cdcacm_init();
#ifdef BLACKPILL
// https://github.com/libopencm3/libopencm3/pull/1256#issuecomment-779424001
OTG_FS_GCCFG |= OTG_GCCFG_NOVBUSSENS | OTG_GCCFG_PWRDWN;
OTG_FS_GCCFG &= ~(OTG_GCCFG_VBUSBSEN | OTG_GCCFG_VBUSASEN);
#endif
}
void platform_srst_set_val(bool assert) { (void)assert; }
@ -105,8 +141,20 @@ const char *platform_target_voltage(void)
void platform_request_boot(void)
{
uint32_t *magic = (uint32_t *) &_ebss;
uint32_t *magic = (uint32_t *)&_ebss;
magic[0] = BOOTMAGIC0;
magic[1] = BOOTMAGIC1;
scb_reset_system();
}
#ifdef PLATFORM_HAS_POWER_SWITCH
bool platform_target_get_power(void)
{
return !gpio_get(PWR_BR_PORT, PWR_BR_PIN);
}
void platform_target_set_power(bool power)
{
gpio_set_val(PWR_BR_PORT, PWR_BR_PIN, !power);
}
#endif

View File

@ -27,13 +27,80 @@
#include "gpio.h"
#include "timing.h"
#include "timing_stm32.h"
#include "version.h"
#include <setjmp.h>
#define PLATFORM_HAS_TRACESWO
#define BOARD_IDENT "Black Magic Probe (F4Discovery), (Firmware " FIRMWARE_VERSION ")"
#define DFU_IDENT "Black Magic Firmware Upgrade (F4Discovery)"
#ifdef BLACKPILL
#define PLATFORM_IDENT "(F4Discovery/BlackPillV2) "
/* Important pin mappings for STM32 implementation:
* JTAG/SWD
* PA1: TDI<br>
* PA13: TMS/SWDIO<br>
* PA14: TCK/SWCLK<br>
* PB3: TDO/TRACESWO<br>
* PB5: TRST<br>
* PB4: SRST<br>
* USB USART
* PB6: USART1 TX
* PB7: USART1 RX
* +3V3
* PB8 - turn on IRLML5103 transistor
* Force DFU mode button: PA0
*/
/* Hardware definitions... */
#define JTAG_PORT GPIOA
#define TDI_PORT JTAG_PORT
#define TMS_PORT JTAG_PORT
#define TCK_PORT JTAG_PORT
#define TDO_PORT GPIOB
#define TDI_PIN GPIO1
#define TMS_PIN GPIO13
#define TCK_PIN GPIO14
#define TDO_PIN GPIO3
#define SWDIO_PORT JTAG_PORT
#define SWCLK_PORT JTAG_PORT
#define SWDIO_PIN TMS_PIN
#define SWCLK_PIN TCK_PIN
#define TRST_PORT GPIOB
#define TRST_PIN GPIO5
#define SRST_PORT GPIOB
#define SRST_PIN GPIO4
#define PWR_BR_PORT GPIOB
#define PWR_BR_PIN GPIO8
#define LED_PORT GPIOC
#define LED_PORT_UART GPIOA
#define LED_UART GPIO1
#define LED_IDLE_RUN GPIO15
#define LED_ERROR GPIO14
#define LED_BOOTLOADER GPIO13
#define USBUSART USART1
#define USBUSART_CR1 USART1_CR1
#define USBUSART_DR USART1_DR
#define USBUSART_IRQ NVIC_USART1_IRQ
#define USBUSART_CLK RCC_USART1
#define USBUSART_PORT GPIOB
#define USBUSART_TX_PIN GPIO6
#define USBUSART_RX_PIN GPIO7
#define USBUSART_ISR(x) usart1_isr(x)
#define USBUSART_DMA_BUS DMA2
#define USBUSART_DMA_CLK RCC_DMA2
#define USBUSART_DMA_TX_CHAN DMA_STREAM7
#define USBUSART_DMA_TX_IRQ NVIC_DMA2_STREAM7_IRQ
#define USBUSART_DMA_TX_ISR(x) dma2_stream7_isr(x)
#define USBUSART_DMA_RX_CHAN DMA_STREAM5
#define USBUSART_DMA_RX_IRQ NVIC_DMA2_STREAM5_IRQ
#define USBUSART_DMA_RX_ISR(x) dma2_stream5_isr(x)
/* For STM32F4 DMA trigger source must be specified */
#define USBUSART_DMA_TRG DMA_SxCR_CHSEL_4
#else
#define PLATFORM_IDENT "(F4Discovery) "
/* Important pin mappings for STM32 implementation:
*
@ -80,6 +147,28 @@
#define LED_IDLE_RUN GPIO13
#define LED_ERROR GPIO14
#define LED_BOOTLOADER GPIO15
#define USBUSART USART3
#define USBUSART_CR1 USART3_CR1
#define USBUSART_DR USART3_DR
#define USBUSART_IRQ NVIC_USART3_IRQ
#define USBUSART_CLK RCC_USART3
#define USBUSART_PORT GPIOD
#define USBUSART_TX_PIN GPIO8
#define USBUSART_RX_PIN GPIO9
#define USBUSART_ISR(x) usart3_isr(x)
#define USBUSART_DMA_BUS DMA1
#define USBUSART_DMA_CLK RCC_DMA1
#define USBUSART_DMA_TX_CHAN DMA_STREAM3
#define USBUSART_DMA_TX_IRQ NVIC_DMA1_STREAM3_IRQ
#define USBUSART_DMA_TX_ISR(x) dma1_stream3_isr(x)
#define USBUSART_DMA_RX_CHAN DMA_STREAM1
#define USBUSART_DMA_RX_IRQ NVIC_DMA1_STREAM1_IRQ
#define USBUSART_DMA_RX_ISR(x) dma1_stream1_isr(x)
/* For STM32F4 DMA trigger source must be specified */
#define USBUSART_DMA_TRG DMA_SxCR_CHSEL_4
#endif
#define BOOTMAGIC0 0xb007da7a
#define BOOTMAGIC1 0xbaadfeed
@ -93,47 +182,35 @@
#define SWDIO_MODE_DRIVE() \
gpio_mode_setup(SWDIO_PORT, GPIO_MODE_OUTPUT, \
GPIO_PUPD_NONE, SWDIO_PIN);
#define UART_PIN_SETUP() do { \
gpio_mode_setup(USBUSART_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, \
USBUSART_TX_PIN); \
gpio_set_output_options(USBUSART_PORT, GPIO_OTYPE_PP, \
GPIO_OSPEED_100MHZ, USBUSART_TX_PIN); \
gpio_set_af(USBUSART_PORT, GPIO_AF7, USBUSART_TX_PIN); \
gpio_mode_setup(USBUSART_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, \
USBUSART_RX_PIN); \
gpio_set_output_options(USBUSART_PORT, GPIO_OTYPE_OD, \
GPIO_OSPEED_100MHZ, USBUSART_RX_PIN); \
gpio_set_af(USBUSART_PORT, GPIO_AF7, USBUSART_RX_PIN); \
} while(0)
#define USB_DRIVER stm32f107_usb_driver
#define USB_IRQ NVIC_OTG_FS_IRQ
#define USB_ISR otg_fs_isr
#define USB_ISR(x) otg_fs_isr(x)
/* Interrupt priorities. Low numbers are high priority.
* For now USART1 preempts USB which may spin while buffer is drained.
* TIM3 is used for traceswo capture and must be highest priority.
*/
#define IRQ_PRI_USB (2 << 4)
#define IRQ_PRI_USBUSART (1 << 4)
#define IRQ_PRI_USBUSART_TIM (3 << 4)
#define IRQ_PRI_USB (1 << 4)
#define IRQ_PRI_USBUSART (2 << 4)
#define IRQ_PRI_USBUSART_DMA (2 << 4)
#define IRQ_PRI_TRACE (0 << 4)
#define USBUSART USART3
#define USBUSART_CR1 USART3_CR1
#define USBUSART_IRQ NVIC_USART3_IRQ
#define USBUSART_CLK RCC_USART3
#define USBUSART_TX_PORT GPIOD
#define USBUSART_TX_PIN GPIO8
#define USBUSART_RX_PORT GPIOD
#define USBUSART_RX_PIN GPIO9
#define USBUSART_ISR usart3_isr
#define USBUSART_TIM TIM4
#define USBUSART_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM4)
#define USBUSART_TIM_IRQ NVIC_TIM4_IRQ
#define USBUSART_TIM_ISR tim4_isr
#define UART_PIN_SETUP() do { \
gpio_mode_setup(USBUSART_TX_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, \
USBUSART_TX_PIN); \
gpio_mode_setup(USBUSART_RX_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, \
USBUSART_RX_PIN); \
gpio_set_af(USBUSART_TX_PORT, GPIO_AF7, USBUSART_TX_PIN); \
gpio_set_af(USBUSART_RX_PORT, GPIO_AF7, USBUSART_RX_PIN); \
} while(0)
#define TRACE_TIM TIM3
#define TRACE_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM3)
#define TRACE_IRQ NVIC_TIM3_IRQ
#define TRACE_ISR tim3_isr
#define TRACE_ISR(x) tim3_isr(x)
#define gpio_set_val(port, pin, val) do { \
if(val) \

View File

@ -27,59 +27,47 @@
#include "general.h"
#include "platform.h"
uint32_t app_address = 0x08000000;
static uint16_t led_upgrade;
static uint32_t led2_state = 0;
extern uint32_t _stack;
static uint32_t rev;
uint32_t app_address = 0x08004000;
extern char _ebss[];
void dfu_detach(void)
{
platform_request_boot();
scb_reset_core();
scb_reset_system();
}
int main(void)
{
rev = detect_rev();
rcc_clock_setup_in_hse_8mhz_out_72mhz();
if (rev == 0)
led_upgrade = GPIO8;
else
led_upgrade = GPIO9;
volatile uint32_t *magic = (uint32_t *)_ebss;
rcc_periph_clock_enable(RCC_GPIOA);
if (gpio_get(GPIOA, GPIO0) ||
((magic[0] == BOOTMAGIC0) && (magic[1] == BOOTMAGIC1))) {
magic[0] = 0;
magic[1] = 0;
} else {
dfu_jump_app_if_valid();
}
rcc_clock_setup_pll(&rcc_hse_8mhz_3v3[RCC_CLOCK_3V3_168MHZ]);
systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8);
systick_set_reload(900000);
/* Assert blue LED as indicator we are in the bootloader */
rcc_periph_clock_enable(RCC_GPIOD);
gpio_mode_setup(LED_PORT, GPIO_MODE_OUTPUT,
GPIO_PUPD_NONE, LED_BOOTLOADER);
gpio_set(LED_PORT, LED_BOOTLOADER);
dfu_protect(UPD_MODE);
/* Enable peripherals */
rcc_periph_clock_enable(RCC_OTGFS);
systick_interrupt_enable();
systick_counter_enable();
if (rev > 1) /* Reconnect USB */
gpio_set(GPIOA, GPIO15);
dfu_init(&st_usbfs_v1_usb_driver, UPD_MODE);
/* Set up USB Pins and alternate function*/
gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO11 | GPIO12);
gpio_set_af(GPIOA, GPIO_AF10, GPIO11 | GPIO12);
dfu_protect(false);
dfu_init(&USB_DRIVER);
dfu_main();
}
void dfu_event(void)
{
}
void sys_tick_handler(void)
{
if (rev == 0) {
gpio_toggle(GPIOA, led_upgrade);
} else {
if (led2_state & 1) {
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, led_upgrade);
gpio_set(GPIOA, led_upgrade);
} else {
gpio_set_mode(GPIOA, GPIO_MODE_INPUT,
GPIO_CNF_INPUT_ANALOG, led_upgrade);
}
led2_state++;
}
}

View File

@ -1,17 +1,39 @@
CC ?= gcc
SYS = $(shell $(CC) -dumpmachine)
CFLAGS += -DENABLE_DEBUG -DPLATFORM_HAS_DEBUG
CFLAGS += -DUSE_USB_VERSION_BIT
CFLAGS +=-I ./target -I./platforms/pc
# Define HOSTED_BMP_ONLY to '0' in order to build the hosted blackmagic
# executable with support for other probes beside BMP. Default HOSTED_BMP_ONLY
# == 1 on Windows makes linking against the libftdi and libusb libraries
# unnecessary.
# This can be useful to minimize external dependencies, and make building on
# windows systems easier and is default now.
ifneq (, $(findstring linux, $(SYS)))
HOSTED_BMP_ONLY ?= 0
else
HOSTED_BMP_ONLY ?= 1
endif
CFLAGS += -DHOSTED_BMP_ONLY=$(HOSTED_BMP_ONLY)
ifneq (, $(findstring linux, $(SYS)))
SRC += serial_unix.c
CFLAGS += -fsanitize=address
HIDAPILIB = hidapi-hidraw
ifeq ($(ASAN), 1)
CFLAGS += -fsanitize=address -Wno-format-truncation
LDFLAGS += -lasan
endif
else ifneq (, $(findstring mingw, $(SYS)))
# Build for windows versions Vista, and above, where the
# 'SetupDiGetDevicePropertyW()' function is available
CFLAGS += -D_WIN32_WINNT=0x600
SRC += serial_win.c
LDFLAGS += -lws2_32
LDFLAGS += -lsetupapi
else ifneq (, $(findstring cygwin, $(SYS)))
# Build for windows versions Vista, and above, where the
# 'SetupDiGetDevicePropertyW()' function is available
CFLAGS += -D_WIN32_WINNT=0x600
SRC += serial_win.c
LDFLAGS += -lws2_32
LDFLAGS += -lsetupapi
@ -21,29 +43,43 @@ SRC += serial_unix.c
LDFLAGS += -lhidapi
LDFLAGS += -framework CoreFoundation
CFLAGS += -Ihidapi/hidapi
HIDAPILIB = hidapi
endif
LDFLAGS += -lusb-1.0
CFLAGS += $(shell pkg-config --cflags libftdi1)
LDFLAGS += $(shell pkg-config --libs libftdi1)
CFLAGS += -Wno-missing-field-initializers
ifneq ($(HOSTED_BMP_ONLY), 1)
$(shell pkg-config --exists libftdi1)
ifneq ($(.SHELLSTATUS), 0)
$(error Please install libftdi1 dependency or set HOSTED_BMP_ONLY to 1)
endif
LDFLAGS += -lusb-1.0
CFLAGS += $(shell pkg-config --cflags libftdi1)
LDFLAGS += $(shell pkg-config --libs libftdi1)
CFLAGS += -Wno-missing-field-initializers
endif
ifneq (, $(findstring mingw, $(SYS)))
SRC += cmsis_dap.c dap.c hid.c
ifneq ($(HOSTED_BMP_ONLY), 1)
CFLAGS += -DCMSIS_DAP
else
ifeq ($(shell pkg-config --exists hidapi-libusb && echo 0), 0)
CFLAGS += $(shell pkg-config --cflags hidapi-libusb)
LDFLAGS += $(shell pkg-config --libs hidapi-libusb)
CFLAGS += -DCMSIS_DAP
SRC += cmsis_dap.c dap.c
SRC += cmsis_dap.c dap.c
ifneq (, $(findstring mingw, $(SYS)))
SRC += hid.c
else
$(shell pkg-config --exists $(HIDAPILIB))
ifneq ($(.SHELLSTATUS), 0)
$(error Please install $(HIDAPILIB) dependency or set HOSTED_BMP_ONLY to 1)
endif
CFLAGS += $(shell pkg-config --cflags $(HIDAPILIB))
LDFLAGS += $(shell pkg-config --libs $(HIDAPILIB))
endif
endif
VPATH += platforms/pc
SRC += timing.c cl_utils.c utils.c libusb_utils.c
SRC += stlinkv2.c
SRC += timing.c cl_utils.c utils.c
SRC += bmp_remote.c remote_swdptap.c remote_jtagtap.c
ifneq ($(HOSTED_BMP_ONLY), 1)
SRC += bmp_libusb.c stlinkv2.c
SRC += ftdi_bmp.c libftdi_swdptap.c libftdi_jtagtap.c
SRC += jlink.c jlink_adiv5_swdp.c jlink_jtagtap.c
else
SRC += bmp_serial.c
endif
PC_HOSTED = 1

View File

@ -1,5 +1,7 @@
# PC-Hosted BMP
Compile in src with "make PROBE_HOST=hosted"
Compile in src with "make PROBE_HOST=hosted". This needs minimal external
support. "make PROBE_HOST=hosted HOSTED_BMP_ONLY=0" will compile support for FTDI,
STLink, CMSIS-DAP and JLINK probes, but requires external libraries.
## Description
PC-hosted BMP run on the PC and compiles as "blackmagic". When started,
@ -8,7 +10,7 @@ if either only one probe is attached to the PC or enough information is
given on the command line to select one of several probes.
When started without any other argument beside the probe selection, a
GDB server is started as port 2000 and up. Connect to the server as you would
GDB server is started on port 2000 and up. Connect to the server as you would
connect to the BMP with the CDCACM GDB serial server. GDB functionality
is the same, monitor option may vary.
@ -36,23 +38,51 @@ blackmagic -V <file>.bin
```
### Show more options
```
blackmagic -h"
blackmagic -h
```
## Used libraries:
### Show available monitor commands
```
blackmagic -M help
```
### Show available monitor commands on second target
```
blackmagic -n 2 -M help
```
### Monitor commands with multiple arguments, e.g.Stm32F1:
```
blackmagic -M "option help"
```
## Used shared libraries:
### libusb
### libftdi, for FTDI support
## Other used libraries:
### hidapi-libusb, for CMSIS-DAP support
## Compiling on windows
You can crosscompile blackmagic for windows with mingw or on windows
with cygwin. For compilation, headers for libftdi1 and libusb-1.0 are
needed. For running, libftdi1.dll and libusb-1.0.dll are needed and
the executable must be able to find them. Mingw on cygwin does not provide
with cygwin. For suppport of other probes beside BMP, headers for libftdi1 and
libusb-1.0 are needed. For running, libftdi1.dll and libusb-1.0.dll are needed
and the executable must be able to find them. Mingw on cygwin does not provide
a libftdi package yet.
To prepare libusb access to the ftdi device, run zadig https://zadig.akeo.ie/.
Choose WinUSB(libusb-1.0) for the BMP Ftdi device.
PC-hosted BMP for windows can also be built with [MSYS2](https://www.msys2.org/),
in windows. Make sure to use the `mingw64` shell from msys2, otherwise,
you may get compilation errors. You will need to install the libusb
and libftdi libraries, and have the correct mingw compiler.
You can use these commands to install dependencies, and build PC-hosted BMP
from a mingw64 shell, from within the `src` directory:
```
pacman -S mingw-w64-x86_64-libusb --needed
pacman -S mingw-w64-x86_64-libftdi --needed
pacman -S mingw-w64-x86_64-gcc --needed
PROBE_HOST=hosted make
```
For suppport of other probes beside BMP, libusb access is needed. To prepare
libusb access to the ftdi/stlink/jlink/cmsis-dap devices, run zadig
https://zadig.akeo.ie/. Choose WinUSB(libusb-1.0).
Running cygwin/blackmagic in a cygwin console, the program does not react
on ^C. In another console, run "ps ax" to find the WINPID of the process
@ -64,6 +94,7 @@ REMOTE_BMP is a "normal" BMP usb connected
| Debugger | Speed | Remarks
| ------------ | ----- | ------
| REMOTE_BMP | +++ | Requires recent firmware for decent speed
Probes below only when compiled with HOSTED_BMP_ONLY=0
| ST-Link V3 | ++++ | Requires recent firmware, Only STM32 devices supported!
| ST-Link V2 | +++ | Requires recent firmware, No CDCACM uart! Cortex only!
| ST-Link V2/1 | +++ | Requires recent firmware, Cortex only!
@ -140,7 +171,7 @@ cables already listed and propose other cable. A link to the schematics
is welcome.
## Feedback
### Issues and Pull request on https://github.com/blacksphere/blackmagic/
### Issues and Pull request on https://github.com/blackmagic-debug/blackmagic/
### Discussions on Discord.
You can find the Discord link here: https://1bitsquared.com/pages/chat
### Blackmagic mailing list http://sourceforge.net/mail/?group_id=407419

View File

@ -0,0 +1,52 @@
#if !defined(__BMP_LIBUSB_H)
#define __BMP_LIBUSB_H
#include "cl_utils.h"
#if HOSTED_BMP_ONLY != 1
# include <libusb-1.0/libusb.h>
struct trans_ctx {
#define TRANS_FLAGS_IS_DONE (1 << 0)
#define TRANS_FLAGS_HAS_ERROR (1 << 1)
volatile unsigned long flags;
};
typedef struct usb_link_s {
libusb_context *ul_libusb_ctx;
libusb_device_handle *ul_libusb_device_handle;
unsigned char ep_tx;
unsigned char ep_rx;
struct libusb_transfer* req_trans;
struct libusb_transfer* rep_trans;
void *priv;
} usb_link_t;
int send_recv(usb_link_t *link, uint8_t *txbuf, size_t txsize,
uint8_t *rxbuf, size_t rxsize);
#endif
typedef struct bmp_info_s {
bmp_type_t bmp_type;
char dev;
char serial[64];
char manufacturer[512];
char product[256];
char version[256];
bool is_jtag;
#if HOSTED_BMP_ONLY != 1
libusb_context *libusb_ctx;
struct ftdi_context *ftdic;
usb_link_t *usb_link;
unsigned int vid;
unsigned int pid;
uint8_t interface_num;
uint8_t in_ep;
uint8_t out_ep;
#endif
} bmp_info_t;
extern bmp_info_t info;
void bmp_ident(bmp_info_t *info);
int find_debuggers(BMP_CL_OPTIONS_t *cl_opts,bmp_info_t *info);
void libusb_exit_function(bmp_info_t *info);
#endif

View File

@ -0,0 +1,473 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright(C) 2020 - 2022 Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* Find all known usb connected debuggers */
#include "general.h"
#include "libusb-1.0/libusb.h"
#include "cl_utils.h"
#include "ftdi_bmp.h"
#include "version.h"
#define NO_SERIAL_NUMBER "<no serial number>"
void bmp_ident(bmp_info_t *info)
{
DEBUG_INFO("BMP hosted %s\n for ST-Link V2/3, CMSIS_DAP, JLINK and "
"LIBFTDI/MPSSE\n", FIRMWARE_VERSION);
if (info && info->vid && info->pid)
DEBUG_INFO("Using %04x:%04x %s %s\n %s\n", info->vid, info->pid,
(info->serial[0]) ? info->serial : NO_SERIAL_NUMBER,
info->manufacturer,
info->product);
}
void libusb_exit_function(bmp_info_t *info)
{
if (!info->usb_link)
return;
libusb_free_transfer(info->usb_link->req_trans);
libusb_free_transfer(info->usb_link->rep_trans);
if (info->usb_link->ul_libusb_device_handle) {
libusb_release_interface (
info->usb_link->ul_libusb_device_handle, 0);
libusb_close(info->usb_link->ul_libusb_device_handle);
}
}
static bmp_type_t find_cmsis_dap_interface(libusb_device *dev,bmp_info_t *info) {
bmp_type_t type = BMP_TYPE_NONE;
struct libusb_config_descriptor *conf;
char interface_string[128];
int res = libusb_get_active_config_descriptor(dev, &conf);
if (res < 0) {
DEBUG_WARN( "WARN: libusb_get_active_config_descriptor() failed: %s",
libusb_strerror(res));
return type;
}
libusb_device_handle *handle;
res = libusb_open(dev, &handle);
if (res != LIBUSB_SUCCESS) {
DEBUG_INFO("INFO: libusb_open() failed: %s\n",
libusb_strerror(res));
libusb_free_config_descriptor(conf);
return type;
}
for (int i = 0; i < conf->bNumInterfaces; i++) {
const struct libusb_interface_descriptor *interface = &conf->interface[i].altsetting[0];
if (!interface->iInterface) {
continue;
}
res = libusb_get_string_descriptor_ascii(
handle, interface->iInterface, (uint8_t*)interface_string,
sizeof(interface_string));
if (res < 0) {
DEBUG_WARN( "WARN: libusb_get_string_descriptor_ascii() failed: %s\n",
libusb_strerror(res));
continue;
}
if (!strstr(interface_string, "CMSIS")) {
continue;
}
type = BMP_TYPE_CMSIS_DAP;
if (interface->bInterfaceClass == 0xff && interface->bNumEndpoints == 2) {
info->interface_num = interface->bInterfaceNumber;
for (int j = 0; j < interface->bNumEndpoints; j++) {
uint8_t n = interface->endpoint[j].bEndpointAddress;
if (n & 0x80) {
info->in_ep = n;
} else {
info->out_ep = n;
}
}
/* V2 is preferred, return early. */
break;
}
}
libusb_free_config_descriptor(conf);
return type;
}
int find_debuggers(BMP_CL_OPTIONS_t *cl_opts, bmp_info_t *info)
{
libusb_device **devs;
int res = libusb_init(&info->libusb_ctx);
if (res) {
DEBUG_WARN( "Fatal: Failed to get USB context: %s\n",
libusb_strerror(res));
exit(-1);
}
if (cl_opts->opt_cable) {
if (!strcmp(cl_opts->opt_cable, "list") ||
!strcmp(cl_opts->opt_cable, "l")) {
cable_desc_t *cable = cable_desc;
DEBUG_WARN("Available cables:\n");
for (; cable->name; ++cable) {
DEBUG_WARN("\t%s\n", cable->name);
}
exit(0);
}
info->bmp_type = BMP_TYPE_LIBFTDI;
}
int n_devs = libusb_get_device_list(info->libusb_ctx, &devs);
if (n_devs < 0) {
DEBUG_WARN( "WARN:libusb_get_device_list() failed");
return -1;
}
bool report = false;
int found_debuggers;
struct libusb_device_descriptor desc;
char serial[64];
char manufacturer[128];
char product[128];
bool access_problems = false;
char *active_cable = NULL;
bool ftdi_unknown = false;
rescan:
found_debuggers = 0;
serial[0] = 0;
manufacturer[0] = 0;
product[0] = 0;
access_problems = false;
active_cable = NULL;
ftdi_unknown = false;
for (size_t i = 0; devs[i]; ++i) {
bmp_type_t type = BMP_TYPE_NONE;
libusb_device *dev = devs[i];
int res = libusb_get_device_descriptor(dev, &desc);
if (res < 0) {
DEBUG_WARN( "WARN: libusb_get_device_descriptor() failed: %s",
libusb_strerror(res));
libusb_free_device_list(devs, 1);
continue;
}
/* Exclude hubs from testing. Probably more classes could be excluded here!*/
switch (desc.bDeviceClass) {
case LIBUSB_CLASS_HUB:
case LIBUSB_CLASS_WIRELESS:
continue;
}
libusb_device_handle *handle = NULL;
res = libusb_open(dev, &handle);
if (res != LIBUSB_SUCCESS) {
if (!access_problems) {
DEBUG_INFO("INFO: Open USB %04x:%04x class %2x failed\n",
desc.idVendor, desc.idProduct, desc.bDeviceClass);
access_problems = true;
}
continue;
}
/* If the device even has a serial number string, fetch it */
if (desc.iSerialNumber) {
res = libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber,
(uint8_t *)serial, sizeof(serial));
/* If the call fails and it's not because the device gave us STALL, continue to the next one */
if (res < 0 && res != LIBUSB_ERROR_PIPE) {
libusb_close(handle);
continue;
}
/* Device has no serial and that's ok. */
else if (res <= 0)
serial[0] = '\0';
}
else
serial[0] = '\0';
if (cl_opts->opt_serial && !strstr(serial, cl_opts->opt_serial)) {
libusb_close(handle);
continue;
}
/* Attempt to get the manufacturer string */
if (desc.iManufacturer) {
res = libusb_get_string_descriptor_ascii(handle, desc.iManufacturer,
(uint8_t *)manufacturer, sizeof(manufacturer));
/* If the call fails and it's not because the device gave us STALL, continue to the next one */
if (res < 0 && res != LIBUSB_ERROR_PIPE) {
DEBUG_WARN("WARN: libusb_get_string_descriptor_ascii() call to fetch manufacturer string failed: %s\n",
libusb_strerror(res));
libusb_close(handle);
continue;
}
/* Device has no manufacturer string and that's ok. */
else if (res <= 0)
manufacturer[0] = '\0';
}
else
manufacturer[0] = '\0';
/* Attempt to get the product string */
if (desc.iProduct) {
res = libusb_get_string_descriptor_ascii(handle, desc.iProduct,
(uint8_t *)product, sizeof(product));
/* If the call fails and it's not because the device gave us STALL, continue to the next one */
if (res < 0 && res != LIBUSB_ERROR_PIPE) {
DEBUG_WARN("WARN: libusb_get_string_descriptor_ascii() call to fetch product string failed: %s\n",
libusb_strerror(res));
libusb_close(handle);
continue;
}
/* Device has no product string and that's ok. */
else if (res <= 0)
product[0] = '\0';
}
else
product[0] = '\0';
libusb_close(handle);
if (cl_opts->opt_ident_string) {
char *match_manu = NULL;
char *match_product = NULL;
match_manu = strstr(manufacturer, cl_opts->opt_ident_string);
match_product = strstr(product, cl_opts->opt_ident_string);
if (!match_manu && !match_product)
continue;
}
/* Either serial and/or ident_string match or are not given.
* Check type.*/
if (desc.idVendor == VENDOR_ID_BMP) {
if (desc.idProduct == PRODUCT_ID_BMP)
type = BMP_TYPE_BMP;
else {
if (desc.idProduct == PRODUCT_ID_BMP_BL)
DEBUG_WARN("BMP in bootloader mode found. Restart or reflash!\n");
continue;
}
} else if (type == BMP_TYPE_NONE &&
(type = find_cmsis_dap_interface(dev, info)) != BMP_TYPE_NONE) {
/* find_cmsis_dap_interface has set valid type*/
} else if (strstr(manufacturer, "CMSIS") || strstr(product, "CMSIS"))
type = BMP_TYPE_CMSIS_DAP;
else if (desc.idVendor == VENDOR_ID_STLINK) {
if (desc.idProduct == PRODUCT_ID_STLINKV2 ||
desc.idProduct == PRODUCT_ID_STLINKV21 ||
desc.idProduct == PRODUCT_ID_STLINKV21_MSD ||
desc.idProduct == PRODUCT_ID_STLINKV3_NO_MSD ||
desc.idProduct == PRODUCT_ID_STLINKV3_BL ||
desc.idProduct == PRODUCT_ID_STLINKV3 ||
desc.idProduct == PRODUCT_ID_STLINKV3E)
type = BMP_TYPE_STLINKV2;
else {
if (desc.idProduct == PRODUCT_ID_STLINKV1)
DEBUG_WARN( "INFO: STLINKV1 not supported\n");
continue;
}
} else if (desc.idVendor == VENDOR_ID_SEGGER)
type = BMP_TYPE_JLINK;
else {
cable_desc_t *cable = cable_desc;
for (; cable->name; ++cable) {
bool found = false;
if (cable->vendor != desc.idVendor || cable->product != desc.idProduct)
continue; /* VID/PID do not match*/
if (cl_opts->opt_cable) {
if (strncmp(cable->name, cl_opts->opt_cable, strlen(cable->name)))
continue; /* cable names do not match*/
else
found = true;
}
if (cable->description) {
if (strncmp(cable->description, product, strlen(cable->description)))
continue; /* discriptions do not match*/
else
found = true;
} else { /* VID/PID fits, but no cl_opts->opt_cable and no description*/
if (cable->vendor == 0x0403 && /* FTDI*/
(cable->product == 0x6010 || /* FT2232C/D/H*/
cable->product == 0x6011 || /* FT4232H Quad HS USB-UART/FIFO IC */
cable->product == 0x6014)) { /* FT232H Single HS USB-UART/FIFO IC */
ftdi_unknown = true;
continue; /* Cable name is needed */
}
}
if (found) {
active_cable = cable->name;
type = BMP_TYPE_LIBFTDI;
break;
}
}
if (!cable->name)
continue;
}
if (report) {
DEBUG_WARN("%2d: %s, %s, %s\n", found_debuggers + 1,
serial[0] ? serial : NO_SERIAL_NUMBER,
manufacturer,product);
}
info->vid = desc.idVendor;
info->pid = desc.idProduct;
info->bmp_type = type;
strncpy(info->serial, serial, sizeof(info->serial));
strncpy(info->product, product, sizeof(info->product));
strncpy(info->manufacturer, manufacturer, sizeof(info->manufacturer));
if (cl_opts->opt_position &&
cl_opts->opt_position == found_debuggers + 1) {
found_debuggers = 1;
break;
} else
++found_debuggers;
}
if (found_debuggers == 0 && ftdi_unknown)
DEBUG_WARN("Generic FTDI MPSSE VID/PID found. Please specify exact type with \"-c <cable>\" !\n");
if (found_debuggers == 1 && !cl_opts->opt_cable && info->bmp_type == BMP_TYPE_LIBFTDI)
cl_opts->opt_cable = active_cable;
if (!found_debuggers && cl_opts->opt_list_only)
DEBUG_WARN("No usable debugger found\n");
if (found_debuggers > 1 ||
(found_debuggers == 1 && cl_opts->opt_list_only)) {
if (!report) {
if (found_debuggers > 1)
DEBUG_WARN("%d debuggers found!\nSelect with -P <pos> "
"or -s <(partial)serial no.>\n",
found_debuggers);
report = true;
goto rescan;
} else {
if (found_debuggers > 0)
access_problems = false;
found_debuggers = 0;
}
}
if (!found_debuggers && access_problems)
DEBUG_WARN(
"No debugger found. Please check access rights to USB devices!\n");
libusb_free_device_list(devs, 1);
return found_debuggers == 1 ? 0 : -1;
}
static void LIBUSB_CALL on_trans_done(struct libusb_transfer *trans)
{
struct trans_ctx * const ctx = trans->user_data;
if (trans->status != LIBUSB_TRANSFER_COMPLETED)
{
DEBUG_WARN("on_trans_done: ");
if (trans->status == LIBUSB_TRANSFER_TIMED_OUT)
DEBUG_WARN(" Timeout\n");
else if (trans->status == LIBUSB_TRANSFER_CANCELLED)
DEBUG_WARN(" cancelled\n");
else if (trans->status == LIBUSB_TRANSFER_NO_DEVICE)
DEBUG_WARN(" no device\n");
else
DEBUG_WARN(" unknown\n");
ctx->flags |= TRANS_FLAGS_HAS_ERROR;
}
ctx->flags |= TRANS_FLAGS_IS_DONE;
}
static int submit_wait(usb_link_t *link, struct libusb_transfer *trans) {
struct trans_ctx trans_ctx;
enum libusb_error error;
trans_ctx.flags = 0;
/* brief intrusion inside the libusb interface */
trans->callback = on_trans_done;
trans->user_data = &trans_ctx;
if ((error = libusb_submit_transfer(trans))) {
DEBUG_WARN("libusb_submit_transfer(%d): %s\n", error,
libusb_strerror(error));
exit(-1);
}
uint32_t start_time = platform_time_ms();
while (trans_ctx.flags == 0) {
struct timeval timeout;
timeout.tv_sec = 1;
timeout.tv_usec = 0;
if (libusb_handle_events_timeout(link->ul_libusb_ctx, &timeout)) {
DEBUG_WARN("libusb_handle_events()\n");
return -1;
}
uint32_t now = platform_time_ms();
if (now - start_time > 1000) {
libusb_cancel_transfer(trans);
DEBUG_WARN("libusb_handle_events() timeout\n");
return -1;
}
}
if (trans_ctx.flags & TRANS_FLAGS_HAS_ERROR) {
DEBUG_WARN("libusb_handle_events() | has_error\n");
return -1;
}
return 0;
}
/* One USB transaction */
int send_recv(usb_link_t *link,
uint8_t *txbuf, size_t txsize,
uint8_t *rxbuf, size_t rxsize)
{
int res = 0;
if (txsize) {
libusb_fill_bulk_transfer(link->req_trans,
link->ul_libusb_device_handle,
link->ep_tx | LIBUSB_ENDPOINT_OUT,
txbuf, txsize,
NULL, NULL, 0);
size_t i = 0;
DEBUG_WIRE(" Send (%3zu): ", txsize);
for (; i < txsize; ++i) {
DEBUG_WIRE("%02x", txbuf[i]);
if ((i & 7U) == 7U)
DEBUG_WIRE(".");
if ((i & 31U) == 31U)
DEBUG_WIRE("\n ");
}
if (!(i & 31U))
DEBUG_WIRE("\n");
if (submit_wait(link, link->req_trans)) {
libusb_clear_halt(link->ul_libusb_device_handle, link->ep_tx);
return -1;
}
}
/* send_only */
if (rxsize != 0) {
/* read the response */
libusb_fill_bulk_transfer(link->rep_trans, link->ul_libusb_device_handle,
link->ep_rx | LIBUSB_ENDPOINT_IN,
rxbuf, rxsize, NULL, NULL, 0);
if (submit_wait(link, link->rep_trans)) {
DEBUG_WARN("clear 1\n");
libusb_clear_halt(link->ul_libusb_device_handle, link->ep_rx);
return -1;
}
res = link->rep_trans->actual_length;
if (res > 0) {
const size_t rxlen = (size_t)res;
DEBUG_WIRE(" Rec (%zu/%zu)", rxsize, rxlen);
for (size_t i = 0; i < rxlen && i < 32 ; ++i) {
if (i && ((i & 7U) == 0U))
DEBUG_WIRE(".");
DEBUG_WIRE("%02x", rxbuf[i]);
}
}
}
DEBUG_WIRE("\n");
return res;
}

View File

@ -22,7 +22,6 @@
#include "general.h"
#include "gdb_if.h"
#include "version.h"
#include "platform.h"
#include "remote.h"
#include "target.h"
#include "bmp_remote.h"
@ -33,25 +32,23 @@
#include <sys/time.h>
#include <sys/time.h>
#include <errno.h>
#include <string.h>
#include "adiv5.h"
int remote_init(bool verbose)
int remote_init(void)
{
char construct[REMOTE_MAX_MSG_SIZE];
int c = snprintf(construct, REMOTE_MAX_MSG_SIZE, "%s", REMOTE_START_STR);
platform_buffer_write((uint8_t *)construct, c);
c = platform_buffer_read((uint8_t *)construct, REMOTE_MAX_MSG_SIZE);
if ((!c) || (construct[0] == REMOTE_RESP_ERR)) {
if ((c < 1) || (construct[0] == REMOTE_RESP_ERR)) {
DEBUG_WARN("Remote Start failed, error %s\n",
c ? (char *)&(construct[1]) : "unknown");
return -1;
}
if (verbose)
DEBUG_WARN("Remote is %s\n", &construct[1]);
return 0;
DEBUG_PROBE("Remote is %s\n", &construct[1]);
return 0;
}
bool remote_target_get_power(void)
@ -65,7 +62,7 @@ bool remote_target_get_power(void)
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((!s) || (construct[0] == REMOTE_RESP_ERR)) {
if ((s < 1) || (construct[0] == REMOTE_RESP_ERR)) {
DEBUG_WARN(" platform_target_get_power failed, error %s\n",
s ? (char *)&(construct[1]) : "unknown");
exit (-1);
@ -74,7 +71,7 @@ bool remote_target_get_power(void)
return (construct[1] == '1');
}
void remote_target_set_power(bool power)
bool remote_target_set_power(bool power)
{
uint8_t construct[REMOTE_MAX_MSG_SIZE];
int s;
@ -85,11 +82,12 @@ void remote_target_set_power(bool power)
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((!s) || (construct[0] == REMOTE_RESP_ERR)) {
if ((s < 1) || (construct[0] == REMOTE_RESP_ERR)) {
DEBUG_WARN("platform_target_set_power failed, error %s\n",
s ? (char *)&(construct[1]) : "unknown");
exit(-1);
return false;
}
return true;
}
void remote_srst_set_val(bool assert)
@ -103,7 +101,7 @@ void remote_srst_set_val(bool assert)
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((!s) || (construct[0] == REMOTE_RESP_ERR)) {
if ((s < 1) || (construct[0] == REMOTE_RESP_ERR)) {
DEBUG_WARN("platform_srst_set_val failed, error %s\n",
s ? (char *)&(construct[1]) : "unknown");
exit(-1);
@ -121,7 +119,7 @@ bool remote_srst_get_val(void)
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((!s) || (construct[0] == REMOTE_RESP_ERR)) {
if ((s < 1) || (construct[0] == REMOTE_RESP_ERR)) {
DEBUG_WARN("platform_srst_set_val failed, error %s\n",
s ? (char *)&(construct[1]) : "unknown");
exit(-1);
@ -129,6 +127,40 @@ bool remote_srst_get_val(void)
return (construct[1] == '1');
}
void remote_max_frequency_set(uint32_t freq)
{
uint8_t construct[REMOTE_MAX_MSG_SIZE];
int s;
s = snprintf((char *)construct, REMOTE_MAX_MSG_SIZE, REMOTE_FREQ_SET_STR,
freq);
platform_buffer_write(construct, s);
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((s < 1) || (construct[0] == REMOTE_RESP_ERR)) {
DEBUG_WARN("Update Firmware to allow to set max SWJ frequency\n");
}
}
uint32_t remote_max_frequency_get(void)
{
uint8_t construct[REMOTE_MAX_MSG_SIZE];
int s;
s = snprintf((char *)construct, REMOTE_MAX_MSG_SIZE,"%s",
REMOTE_FREQ_GET_STR);
platform_buffer_write(construct, s);
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((s < 1) || (construct[0] == REMOTE_RESP_ERR))
return FREQ_FIXED;
uint32_t freq[1];
unhexify(freq, (const char*)&construct[1], 4);
return freq[0];
}
const char *remote_target_voltage(void)
{
static uint8_t construct[REMOTE_MAX_MSG_SIZE];
@ -140,7 +172,7 @@ const char *remote_target_voltage(void)
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((!s) || (construct[0] == REMOTE_RESP_ERR)) {
if ((s < 1) || (construct[0] == REMOTE_RESP_ERR)) {
DEBUG_WARN("platform_target_voltage failed, error %s\n",
s ? (char *)&(construct[1]) : "unknown");
exit(- 1);
@ -153,10 +185,10 @@ static uint32_t remote_adiv5_dp_read(ADIv5_DP_t *dp, uint16_t addr)
(void)dp;
uint8_t construct[REMOTE_MAX_MSG_SIZE];
int s = snprintf((char *)construct, REMOTE_MAX_MSG_SIZE, REMOTE_DP_READ_STR,
addr);
dp->dp_jd_index, addr);
platform_buffer_write(construct, s);
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((!s) || (construct[0] == REMOTE_RESP_ERR)) {
if ((s < 1) || (construct[0] == REMOTE_RESP_ERR)) {
DEBUG_WARN("%s error %d\n", __func__, s);
}
uint32_t dest[1];
@ -171,10 +203,10 @@ static uint32_t remote_adiv5_low_access(
(void)dp;
uint8_t construct[REMOTE_MAX_MSG_SIZE];
int s = snprintf((char *)construct, REMOTE_MAX_MSG_SIZE,
REMOTE_LOW_ACCESS_STR, RnW, addr, value);
REMOTE_LOW_ACCESS_STR, dp->dp_jd_index, RnW, addr, value);
platform_buffer_write(construct, s);
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((!s) || (construct[0] == REMOTE_RESP_ERR)) {
if ((s < 1) || (construct[0] == REMOTE_RESP_ERR)) {
DEBUG_WARN("%s error %d\n", __func__, s);
}
uint32_t dest[1];
@ -186,10 +218,10 @@ static uint32_t remote_adiv5_ap_read(ADIv5_AP_t *ap, uint16_t addr)
{
uint8_t construct[REMOTE_MAX_MSG_SIZE];
int s = snprintf((char *)construct, REMOTE_MAX_MSG_SIZE,REMOTE_AP_READ_STR,
ap->apsel, addr);
ap->dp->dp_jd_index, ap->apsel, addr);
platform_buffer_write(construct, s);
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((!s) || (construct[0] == REMOTE_RESP_ERR)) {
if ((s < 1) || (construct[0] == REMOTE_RESP_ERR)) {
DEBUG_WARN("%s error %d\n", __func__, s);
}
uint32_t dest[1];
@ -201,10 +233,10 @@ static void remote_adiv5_ap_write(ADIv5_AP_t *ap, uint16_t addr, uint32_t value)
{
uint8_t construct[REMOTE_MAX_MSG_SIZE];
int s = snprintf((char *)construct, REMOTE_MAX_MSG_SIZE,REMOTE_AP_WRITE_STR,
ap->apsel, addr, value);
ap->dp->dp_jd_index, ap->apsel, addr, value);
platform_buffer_write(construct, s);
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((!s) || (construct[0] == REMOTE_RESP_ERR)) {
if ((s < 1) || (construct[0] == REMOTE_RESP_ERR)) {
DEBUG_WARN("%s error %d\n", __func__, s);
}
return;
@ -267,7 +299,7 @@ static void remote_ap_mem_read(
if (count > batchsize)
count = batchsize;
s = snprintf(construct, REMOTE_MAX_MSG_SIZE,
REMOTE_AP_MEM_READ_STR, ap->apsel, ap->csw, src, count);
REMOTE_AP_MEM_READ_STR, ap->dp->dp_jd_index, ap->apsel, ap->csw, src, count);
platform_buffer_write((uint8_t*)construct, s);
s = platform_buffer_read((uint8_t*)construct, REMOTE_MAX_MSG_SIZE);
if ((s > 0) && (construct[0] == REMOTE_RESP_OK)) {
@ -307,7 +339,7 @@ static void remote_ap_mem_write_sized(
count = batchsize;
int s = snprintf(construct, REMOTE_MAX_MSG_SIZE,
REMOTE_AP_MEM_WRITE_SIZED_STR,
ap->apsel, ap->csw, align, dest, count);
ap->dp->dp_jd_index, ap->apsel, ap->csw, align, dest, count);
char *p = construct + s;
hexify(p, src, count);
p += 2 * count;
@ -340,7 +372,8 @@ void remote_adiv5_dp_defaults(ADIv5_DP_t *dp)
REMOTE_HL_CHECK_STR);
platform_buffer_write(construct, s);
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((!s) || (construct[0] == REMOTE_RESP_ERR)) {
if ((s < 1) || (construct[0] == REMOTE_RESP_ERR) ||
((construct[1] - '0') < REMOTE_HL_VERSION)) {
DEBUG_WARN(
"Please update BMP firmware for substantial speed increase!\n");
return;
@ -352,3 +385,20 @@ void remote_adiv5_dp_defaults(ADIv5_DP_t *dp)
dp->mem_read = remote_ap_mem_read;
dp->mem_write_sized = remote_ap_mem_write_sized;
}
void remote_add_jtag_dev(int i, const jtag_dev_t *jtag_dev)
{
uint8_t construct[REMOTE_MAX_MSG_SIZE];
int s = snprintf((char *)construct, REMOTE_MAX_MSG_SIZE,
REMOTE_JTAG_ADD_DEV_STR,
i,
jtag_dev->dr_prescan,
jtag_dev->dr_postscan,
jtag_dev->ir_len,
jtag_dev->ir_prescan,
jtag_dev->ir_postscan,
jtag_dev->current_ir);
platform_buffer_write(construct, s);
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
/* No check for error here. Done in remote_adiv5_dp_defaults!*/
}

View File

@ -18,7 +18,6 @@
*/
#if !defined(__BMP_REMOTE_H_)
#define __BMP_REMOTE_H_
#include "swdptap.h"
#include "jtagtap.h"
#include "adiv5.h"
#include "target.h"
@ -29,15 +28,18 @@
int platform_buffer_write(const uint8_t *data, int size);
int platform_buffer_read(uint8_t *data, int size);
int remote_init(bool verbose);
int remote_swdptap_init(swd_proc_t *swd_proc);
int remote_init(void);
int remote_swdptap_init(ADIv5_DP_t *dp);
int remote_jtagtap_init(jtag_proc_t *jtag_proc);
bool remote_target_get_power(void);
const char *remote_target_voltage(void);
void remote_target_set_power(bool power);
bool remote_target_set_power(bool power);
void remote_srst_set_val(bool assert);
bool remote_srst_get_val(void);
void remote_max_frequency_set(uint32_t freq);
uint32_t remote_max_frequency_get(void);
const char *platform_target_voltage(void);
void remote_adiv5_dp_defaults(ADIv5_DP_t *dp);
void remote_add_jtag_dev(int i, const jtag_dev_t *jtag_dev);
#define __BMP_REMOTE_H_
#endif

View File

@ -0,0 +1,296 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2020 Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* Find all known serial connected debuggers */
#include "general.h"
#include <dirent.h>
#include <errno.h>
#include "bmp_hosted.h"
#include "version.h"
void bmp_ident(bmp_info_t *info)
{
if (!info)
return;
DEBUG_INFO("BMP hosted (BMP Only) %s\n", FIRMWARE_VERSION);
DEBUG_INFO("Using:\n %s %s %s\n", info->manufacturer, info->version, info->serial);
}
void libusb_exit_function(bmp_info_t *info) {(void)info;};
#ifdef __APPLE__
int find_debuggers(BMP_CL_OPTIONS_t *cl_opts, bmp_info_t *info)
{
DEBUG_WARN("Please implement find_debuggers for MACOS!\n");
(void)cl_opts;
(void)info;
return -1;
}
#elif defined(__WIN32__) || defined(__CYGWIN__)
/* This source has been used as an example:
* https://stackoverflow.com/questions/3438366/setupdigetdeviceproperty-usage-example */
#include <windows.h>
#include <setupapi.h>
#include <cfgmgr32.h> // for MAX_DEVICE_ID_LEN, CM_Get_Parent and CM_Get_Device_ID
#include <tchar.h>
#include <stdio.h>
/* include DEVPKEY_Device_BusReportedDeviceDesc from WinDDK\7600.16385.1\inc\api\devpropdef.h */
#ifdef DEFINE_DEVPROPKEY
#undef DEFINE_DEVPROPKEY
#endif
#define DEFINE_DEVPROPKEY(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8, pid) const DEVPROPKEY DECLSPEC_SELECTANY name = { { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }, pid }
/* include DEVPKEY_Device_BusReportedDeviceDesc from WinDDK\7600.16385.1\inc\api\devpkey.h */
DEFINE_DEVPROPKEY(DEVPKEY_Device_BusReportedDeviceDesc, 0x540b947e, 0x8b40, 0x45bc, 0xa8, 0xa2, 0x6a, 0x0b, 0x89, 0x4c, 0xbd, 0xa2, 4); // DEVPROP_TYPE_STRING
/* List all USB devices with some additional information.
* Unfortunately, this code is quite ugly. */
int find_debuggers(BMP_CL_OPTIONS_t *cl_opts, bmp_info_t *info)
{
unsigned i;
DWORD dwSize;
DEVPROPTYPE ulPropertyType;
CONFIGRET status;
HDEVINFO hDevInfo;
SP_DEVINFO_DATA DeviceInfoData;
TCHAR szDeviceInstanceID [MAX_DEVICE_ID_LEN];
WCHAR busReportedDeviceSesc[4096];
int probes_found = 0;
bool is_printing_probes_info = cl_opts->opt_list_only != 0;
info->bmp_type = BMP_TYPE_BMP;
hDevInfo = SetupDiGetClassDevs (0, "USB", NULL, DIGCF_ALLCLASSES | DIGCF_PRESENT);
if (hDevInfo == INVALID_HANDLE_VALUE)
return -1;
print_probes_info:
for (i = 0; ; i++) {
char serial_number[sizeof info->serial];
DeviceInfoData.cbSize = sizeof (DeviceInfoData);
if (!SetupDiEnumDeviceInfo(hDevInfo, i, &DeviceInfoData))
break;
status = CM_Get_Device_ID(DeviceInfoData.DevInst, szDeviceInstanceID , MAX_PATH, 0);
if (status != CR_SUCCESS)
continue;
if (!sscanf(szDeviceInstanceID, "USB\\VID_1D50&PID_6018\\%s", serial_number))
continue;
if (SetupDiGetDevicePropertyW (hDevInfo, &DeviceInfoData, &DEVPKEY_Device_BusReportedDeviceDesc,
&ulPropertyType, (BYTE*)busReportedDeviceSesc, sizeof busReportedDeviceSesc, &dwSize, 0))
{
probes_found ++;
if (is_printing_probes_info)
{
DEBUG_WARN("%2d: %s, %ls\n", probes_found,
serial_number, busReportedDeviceSesc);
}
else
{
bool probe_identified = true;
if ((cl_opts->opt_serial && strstr(serial_number, cl_opts->opt_serial)) ||
(cl_opts->opt_position && cl_opts->opt_position == probes_found) ||
/* Special case for the very first probe found. */
(probe_identified = false, probes_found == 1)) {
strncpy(info->serial, serial_number, sizeof info->serial);
strncpy(info->manufacturer, "BMP", sizeof info->manufacturer);
snprintf(info->product, sizeof info->product, "%ls", busReportedDeviceSesc);
/* Don't bother to parse the version string. It is a part of the
* product description string. It seems that at the moment it
* is only being used to print a version string in response
* to the 'monitor version' command, so it doesn't really matter
* if the version string is printed as a part of the product string,
* or as a separate string, the result is pretty much the same. */
info->version[0] = 0;
if (probe_identified)
return 0;
}
}
}
}
if (is_printing_probes_info)
return 1;
if (probes_found == 1)
/* Exactly one probe found. Its information has already been filled
* in the detection loop, so use this probe. */
return 0;
if (probes_found < 1) {
DEBUG_WARN("No BMP probe found\n");
return -1;
}
/* Otherwise, if this line is reached, then more than one probe has been found,
* and no probe was identified as selected by the user.
* Restart the identification loop, this time printing the probe information,
* and then return. */
DEBUG_WARN("%d debuggers found!\nSelect with -P <pos>, or "
"-s <(partial)serial no.>\n",
probes_found);
probes_found = 0;
is_printing_probes_info = true;
goto print_probes_info;
}
#else
/* Old ID: Black_Sphere_Technologies_Black_Magic_Probe_BFE4D6EC-if00
* Recent: Black_Sphere_Technologies_Black_Magic_Probe_v1.7.1-212-g212292ab_7BAE7AB8-if00
* usb-Black_Sphere_Technologies_Black_Magic_Probe__SWLINK__v1.7.1-155-gf55ad67b-dirty_DECB8811-if00
*/
#define BMP_IDSTRING_BLACKSPHERE "usb-Black_Sphere_Technologies_Black_Magic_Probe"
#define BMP_IDSTRING_BLACKMAGIC "usb-Black_Magic_Debug_Black_Magic_Probe"
#define BMP_IDSTRING_1BITSQUARED "usb-1BitSquared_Black_Magic_Probe"
#define DEVICE_BY_ID "/dev/serial/by-id/"
/*
* Extract type, version and serial from /dev/serial/by_id
* Return 0 on success
*
* Old versions have different strings. Try to cope!
*/
static int scan_linux_id(char *name, char *type, char *version, char *serial)
{
name += strlen(BMP_IDSTRING_BLACKSPHERE) + 1;
while (*name == '_')
name++;
if (!*name) {
DEBUG_WARN("Unexpected end\n");
return -1;
}
char *p = name;
char *delims[4] = {0,0,0,0};
int underscores = 0;
while (*p) {
if (*p == '_') {
while (p[1] == '_')
p++; /* remove multiple underscores */
if (underscores > 2)
return -1;
delims[underscores] = p;
underscores ++;
}
p++;
}
if (underscores == 0) { /* Old BMP native */
int res;
res = sscanf(name, "%8s-if00", serial);
if (res != 1)
return -1;
strcpy(type, "Native");
strcpy(version, "Unknown");
} else if (underscores == 2) {
strncpy(type, name, delims[0] - name - 1);
strncpy(version, delims[0] + 1, delims[1] - delims[0] - 1);
int res = sscanf(delims[1] + 1, "%8s-if00", serial);
if (!res)
return -1;
} else {
int res = sscanf(delims[0] + 1, "%8s-if00", serial);
if (!res)
return -1;
if (name[0] == 'v') {
strcpy(type, "Unknown");
strncpy(version, name, delims[0] - name - 1);
} else {
strncpy(type, name, delims[0] - name);
strcpy(type, "Unknown");
}
}
return 0;
}
int find_debuggers(BMP_CL_OPTIONS_t *cl_opts, bmp_info_t *info)
{
if (cl_opts->opt_device)
return 1;
info->bmp_type = BMP_TYPE_BMP;
DIR *dir = opendir(DEVICE_BY_ID);
if (!dir) /* No serial device connected!*/
return 0;
int found_bmps = 0;
struct dirent *dp;
int i = 0;
while ((dp = readdir(dir)) != NULL) {
if ((strstr(dp->d_name, BMP_IDSTRING_BLACKMAGIC) ||
strstr(dp->d_name, BMP_IDSTRING_BLACKSPHERE) ||
strstr(dp->d_name, BMP_IDSTRING_1BITSQUARED)) &&
(strstr(dp->d_name, "-if00"))) {
i++;
char type[256], version[256], serial[256];
if (scan_linux_id(dp->d_name, type, version, serial)) {
DEBUG_WARN("Unexpected device name found \"%s\"\n",
dp->d_name);
}
if ((cl_opts->opt_serial && strstr(serial, cl_opts->opt_serial)) ||
(cl_opts->opt_position && cl_opts->opt_position == i)) {
/* With serial number given and partial match, we are done!*/
strncpy(info->serial, serial, sizeof(info->serial));
int res = snprintf(info->manufacturer, sizeof(info->manufacturer), "Black Magic Probe (%s)", type);
if (res)
DEBUG_WARN("Overflow\n");
strncpy(info->version, version, sizeof(info->version));
found_bmps = 1;
break;
} else {
found_bmps++;
}
}
}
closedir(dir);
if (found_bmps < 1) {
DEBUG_WARN("No BMP probe found\n");
return -1;
} else if ((found_bmps > 1) || cl_opts->opt_list_only) {
DEBUG_WARN("Available Probes:\n");
}
dir = opendir(DEVICE_BY_ID);
i = 0;
while ((dp = readdir(dir)) != NULL) {
if ((strstr(dp->d_name, BMP_IDSTRING_BLACKMAGIC) ||
strstr(dp->d_name, BMP_IDSTRING_BLACKSPHERE) ||
strstr(dp->d_name, BMP_IDSTRING_1BITSQUARED)) &&
(strstr(dp->d_name, "-if00"))) {
i++;
char type[256], version[256], serial[256];
if (scan_linux_id(dp->d_name, type, version, serial)) {
DEBUG_WARN("Unexpected device name found \"%s\"\n",
dp->d_name);
} else if ((found_bmps == 1) && (!cl_opts->opt_list_only)) {
strncpy(info->serial, serial, sizeof(info->serial));
found_bmps = 1;
strncpy(info->serial, serial, sizeof(info->serial));
snprintf(info->manufacturer, sizeof(info->manufacturer), "Black Magic Probe (%s)", type);
strncpy(info->version, version, sizeof(info->version));
break;
} else if (found_bmps > 0) {
DEBUG_WARN("%2d: %s, Black Magic Debug, Black Magic "
"Probe (%s), %s\n", i, serial, type, version);
}
}
}
closedir(dir);
return (found_bmps == 1 && !cl_opts->opt_list_only) ? 0 : 1;
}
#endif

View File

@ -1,7 +1,7 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2019-20 Uwe Bonnes <bon@elektron,ikp.physik.tu-darmstadt.de>
* Copyright (C) 2019-2021 Uwe Bonnes <bon@elektron.ikp.physik.tu-darmstadt.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -34,6 +34,7 @@
#include <hidapi.h>
#include <wchar.h>
#include "bmp_hosted.h"
#include "dap.h"
#include "cmsis_dap.h"
@ -44,48 +45,101 @@
uint8_t dap_caps;
uint8_t mode;
typedef enum cmsis_type_s {
CMSIS_TYPE_NONE = 0,
CMSIS_TYPE_HID,
CMSIS_TYPE_BULK
} cmsis_type_t;
/*- Variables ---------------------------------------------------------------*/
static cmsis_type_t type;
static libusb_device_handle *usb_handle = NULL;
static uint8_t in_ep;
static uint8_t out_ep;
static hid_device *handle = NULL;
static uint8_t hid_buffer[1024 + 1];
static int report_size = 512 + 1; // TODO: read actual report size
static uint8_t buffer[1024 + 1];
static int report_size = 64 + 1; // TODO: read actual report size
static bool has_swd_sequence = false;
/* LPC845 Breakout Board Rev. 0 report invalid response with > 65 bytes */
int dap_init(bmp_info_t *info)
{
printf("dap_init\n");
if (hid_init())
return -1;
int size = strlen(info->serial);
wchar_t serial[size + 1], *wc = serial;
for (int i = 0; i < size; i++)
*wc++ = info->serial[i];
*wc = 0;
/* Blacklist devices that do not wirk with 513 byte report length
* FIXME: Find a solution to decipher from the device.
*/
if ((info->vid == 0x1fc9) && (info->pid == 0x0132)) {
DEBUG_WARN("Blacklist\n");
report_size = 64 + 1;
type = (info->in_ep && info->out_ep) ? CMSIS_TYPE_BULK : CMSIS_TYPE_HID;
int size;
if (type == CMSIS_TYPE_HID) {
DEBUG_INFO("Using hid transfer\n");
if (hid_init())
return -1;
size = strlen(info->serial);
wchar_t serial[64] = {0}, *wc = serial;
for (int i = 0; i < size; i++)
*wc++ = info->serial[i];
*wc = 0;
/* Blacklist devices that do not work with 513 byte report length
* FIXME: Find a solution to decipher from the device.
*/
if ((info->vid == 0x1fc9) && (info->pid == 0x0132)) {
DEBUG_WARN("Blacklist\n");
report_size = 64 + 1;
}
handle = hid_open(info->vid, info->pid, (serial[0]) ? serial : NULL);
if (!handle) {
DEBUG_WARN("hid_open failed\n");
return -1;
}
} else if (type == CMSIS_TYPE_BULK) {
DEBUG_INFO("Using bulk transfer\n");
usb_handle = libusb_open_device_with_vid_pid(info->libusb_ctx, info->vid, info->pid);
if (!usb_handle) {
DEBUG_WARN("WARN: libusb_open_device_with_vid_pid() failed\n");
return -1;
}
if (libusb_claim_interface(usb_handle, info->interface_num) < 0) {
DEBUG_WARN("WARN: libusb_claim_interface() failed\n");
return -1;
}
in_ep = info->in_ep;
out_ep = info->out_ep;
}
handle = hid_open(info->vid, info->pid, serial);
if (!handle)
return -1;
dap_disconnect();
size = dap_info(DAP_INFO_CAPABILITIES, hid_buffer, sizeof(hid_buffer));
dap_caps = hid_buffer[0];
DEBUG_INFO(" Cap (0x%2x): %s%s%s", hid_buffer[0],
(hid_buffer[0] & 1)? "SWD" : "",
((hid_buffer[0] & 3) == 3) ? "/" : "",
(hid_buffer[0] & 2)? "JTAG" : "");
if (hid_buffer[0] & 4)
size = dap_info(DAP_INFO_FW_VER, buffer, sizeof(buffer));
if (size) {
DEBUG_INFO("Ver %s, ", buffer);
int major = -1, minor = -1, sub = -1;
if (sscanf((const char *)buffer, "%d.%d.%d",
&major, &minor, &sub)) {
if (sub == -1) {
if (minor >= 10) {
minor /= 10;
sub = 0;
}
}
has_swd_sequence = ((major > 1 ) || ((major > 0 ) && (minor > 1)));
}
}
size = dap_info(DAP_INFO_CAPABILITIES, buffer, sizeof(buffer));
dap_caps = buffer[0];
DEBUG_INFO("Cap (0x%2x): %s%s%s", dap_caps,
(dap_caps & 1)? "SWD" : "",
((dap_caps & 3) == 3) ? "/" : "",
(dap_caps & 2)? "JTAG" : "");
if (dap_caps & 4)
DEBUG_INFO(", SWO_UART");
if (hid_buffer[0] & 8)
if (dap_caps & 8)
DEBUG_INFO(", SWO_MANCHESTER");
if (hid_buffer[0] & 0x10)
if (dap_caps & 0x10)
DEBUG_INFO(", Atomic Cmds");
if (has_swd_sequence)
DEBUG_INFO(", DAP_SWD_Sequence");
DEBUG_INFO("\n");
return 0;
}
void dap_srst_set_val(bool assert)
{
dap_reset_pin(!assert);
}
static void dap_dp_abort(ADIv5_DP_t *dp, uint32_t abort)
{
/* DP Write to Reg 0.*/
@ -94,6 +148,7 @@ static void dap_dp_abort(ADIv5_DP_t *dp, uint32_t abort)
static uint32_t dap_dp_error(ADIv5_DP_t *dp)
{
/* Not used for SWD debugging, so no TARGETID switch needed!*/
uint32_t ctrlstat = dap_read_reg(dp, ADIV5_DP_CTRLSTAT);
uint32_t err = ctrlstat &
(ADIV5_DP_CTRLSTAT_STICKYORUN | ADIV5_DP_CTRLSTAT_STICKYCMP |
@ -129,23 +184,23 @@ static uint32_t dap_dp_low_access(struct ADIv5_DP_s *dp, uint8_t RnW,
static uint32_t dap_dp_read_reg(ADIv5_DP_t *dp, uint16_t addr)
{
uint32_t res;
if (addr & ADIV5_APnDP) {
dap_dp_low_access(dp, ADIV5_LOW_READ, addr, 0);
res = dap_dp_low_access(dp, ADIV5_LOW_READ,
ADIV5_DP_RDBUFF, 0);
} else {
res = dap_dp_low_access(dp, ADIV5_LOW_READ, addr, 0);
}
uint32_t res = dap_dp_low_access(dp, ADIV5_LOW_READ, addr, 0);
DEBUG_PROBE("dp_read %04x %08" PRIx32 "\n", addr, res);
return res;
}
void dap_exit_function(void)
{
if (handle) {
dap_disconnect();
hid_close(handle);
if (type == CMSIS_TYPE_HID) {
if (handle) {
dap_disconnect();
hid_close(handle);
}
} else if (type == CMSIS_TYPE_BULK) {
if (usb_handle) {
dap_disconnect();
libusb_close(usb_handle);
}
}
}
@ -158,40 +213,56 @@ int dbg_dap_cmd(uint8_t *data, int size, int rsize)
{
char cmd = data[0];
int res;
int res = -1;
memset(hid_buffer, 0xff, report_size + 1);
memset(buffer, 0xff, report_size + 1);
hid_buffer[0] = 0x00; // Report ID??
memcpy(&hid_buffer[1], data, rsize);
buffer[0] = 0x00; // Report ID??
memcpy(&buffer[1], data, rsize);
DEBUG_WIRE("cmd : ");
for(int i = 0; (i < 16) && (i < rsize + 1); i++)
DEBUG_WIRE("%02x.", hid_buffer[i]);
for(int i = 0; (i < 32) && (i < rsize + 1); i++)
DEBUG_WIRE("%02x.", buffer[i]);
DEBUG_WIRE("\n");
res = hid_write(handle, hid_buffer, rsize + 1);
if (res < 0) {
DEBUG_WARN( "Error: %ls\n", hid_error(handle));
exit(-1);
}
if (size) {
res = hid_read(handle, hid_buffer, report_size + 1);
if (type == CMSIS_TYPE_HID) {
res = hid_write(handle, buffer, 65);
if (res < 0) {
DEBUG_WARN( "Error: %ls\n", hid_error(handle));
exit(-1);
}
res = hid_read_timeout(handle, buffer, 65, 1000);
if (res < 0) {
DEBUG_WARN( "debugger read(): %ls\n", hid_error(handle));
exit(-1);
} else if (res == 0) {
DEBUG_WARN( "timeout\n");
exit(-1);
}
if (size && hid_buffer[0] != cmd) {
DEBUG_WARN("cmd %02x invalid response received %02x\n",
cmd, hid_buffer[0]);
}
res--;
memcpy(data, &hid_buffer[1], (size < res) ? size : res);
DEBUG_WIRE("cmd res:");
for(int i = 0; (i < 16) && (i < size + 4); i++)
DEBUG_WIRE("%02x.", hid_buffer[i]);
DEBUG_WIRE("\n");
}
} else if (type == CMSIS_TYPE_BULK) {
int transferred = 0;
res = libusb_bulk_transfer(usb_handle, out_ep, data, rsize, &transferred, 500);
if (res < 0) {
DEBUG_WARN("OUT error: %d\n", res);
return res;
}
res = libusb_bulk_transfer(usb_handle, in_ep, buffer, report_size, &transferred, 500);
if (res < 0) {
DEBUG_WARN("IN error: %d\n", res);
return res;
}
res = transferred;
}
DEBUG_WIRE("cmd res:");
for(int i = 0; (i < 16) && (i < size + 1); i++)
DEBUG_WIRE("%02x.", buffer[i]);
DEBUG_WIRE("\n");
if (buffer[0] != cmd) {
DEBUG_WARN("cmd %02x not implemented\n", cmd);
buffer[1] = 0xff /*DAP_ERROR*/;
}
if (size)
memcpy(data, &buffer[1], (size < res) ? size : res);
return res;
}
#define ALIGNOF(x) (((x) & 3) == 0 ? ALIGN_WORD : \
@ -208,7 +279,7 @@ static void dap_mem_read(ADIv5_AP_t *ap, void *dest, uint32_t src, size_t len)
return dap_read_single(ap, dest, src, align);
/* One word transfer for every byte/halfword/word
* Total number of bytes in transfer*/
unsigned int max_size = (dbg_get_report_size() - 5) >> (2 - align);
unsigned int max_size = ((dbg_get_report_size() - 6) >> (2 - align)) & ~3;
while (len) {
dap_ap_mem_access_setup(ap, src, align);
/* Calculate length until next access setup is needed */
@ -245,7 +316,7 @@ static void dap_mem_write_sized(
dest, len, align, *(uint32_t *)src);
if (((unsigned)(1 << align)) == len)
return dap_write_single(ap, dest, src, align);
unsigned int max_size = (dbg_get_report_size() - 5) >> (2 - align);
unsigned int max_size = ((dbg_get_report_size() - 6) >> (2 - align) & ~3);
while (len) {
dap_ap_mem_access_setup(ap, dest, align);
unsigned int blocksize = (dest | 0x3ff) - dest + 1;
@ -271,27 +342,6 @@ static void dap_mem_write_sized(
DEBUG_WIRE("memwrite done\n");
}
int dap_enter_debug_swd(ADIv5_DP_t *dp)
{
target_list_free();
if (!(dap_caps & DAP_CAP_SWD))
return -1;
mode = DAP_CAP_SWD;
dap_swj_clock(2000000);
dap_transfer_configure(2, 128, 128);
dap_swd_configure(0);
dap_connect(false);
dap_led(0, 1);
dap_reset_link(false);
dp->idcode = dap_read_idcode(dp);
dp->dp_read = dap_dp_read_reg;
dp->error = dap_dp_error;
dp->low_access = dap_dp_low_access;
dp->abort = dap_dp_abort; /* DP Write to Reg 0.*/
return 0;
}
void dap_adiv5_dp_defaults(ADIv5_DP_t *dp)
{
if ((mode == DAP_CAP_JTAG) && dap_jtag_configure())
@ -320,7 +370,7 @@ static void cmsis_dap_jtagtap_tdi_tdo_seq(uint8_t *DO, const uint8_t final_tms,
const uint8_t *DI, int ticks)
{
dap_jtagtap_tdi_tdo_seq(DO, (final_tms), NULL, DI, ticks);
DEBUG_PROBE("jtagtap_tdi_tdo_seq %d, %02x-> %02x\n", ticks, DI[0], DO[0]);
DEBUG_PROBE("jtagtap_tdi_tdo_seq %d, %02x-> %02x\n", ticks, DI[0], (DO)? DO[0] : 0);
}
static void cmsis_dap_jtagtap_tdi_seq(const uint8_t final_tms,
@ -346,13 +396,12 @@ int cmsis_dap_jtagtap_init(jtag_proc_t *jtag_proc)
mode = DAP_CAP_JTAG;
dap_disconnect();
dap_connect(true);
dap_swj_clock(2000000);
dap_reset_link(true);
jtag_proc->jtagtap_reset = cmsis_dap_jtagtap_reset;
jtag_proc->jtagtap_next = cmsis_dap_jtagtap_next;
jtag_proc->jtagtap_tms_seq = cmsis_dap_jtagtap_tms_seq;
jtag_proc->jtagtap_tdi_tdo_seq = cmsis_dap_jtagtap_tdi_tdo_seq;
jtag_proc->jtagtap_tdi_seq = cmsis_dap_jtagtap_tdi_seq;
dap_reset_link(true);
return 0;
}
@ -365,3 +414,57 @@ int dap_jtag_dp_init(ADIv5_DP_t *dp)
return true;
}
#define SWD_SEQUENCE_IN 0x80
#define DAP_SWD_SEQUENCE 0x1d
static bool dap_dp_low_write(ADIv5_DP_t *dp, uint16_t addr, const uint32_t data)
{
DEBUG_PROBE("dap_dp_low_write %08" PRIx32 "\n", data);
(void)dp;
unsigned int paket_request = make_packet_request(ADIV5_LOW_WRITE, addr);
uint8_t buf[32] = {
DAP_SWD_SEQUENCE,
5,
8,
paket_request,
4 + SWD_SEQUENCE_IN, /* one turn-around + read 3 bit ACK */
1, /* one bit turn around to drive SWDIO */
0,
32, /* write 32 bit data */
(data >> 0) & 0xff,
(data >> 8) & 0xff,
(data >> 16) & 0xff,
(data >> 24) & 0xff,
1, /* write parity biT */
__builtin_parity(data)
};
dbg_dap_cmd(buf, sizeof(buf), 14);
if (buf[0])
DEBUG_WARN("dap_dp_low_write failed\n");
uint32_t ack = (buf[1] >> 1) & 7;
return (ack != SWDP_ACK_OK);
}
int dap_swdptap_init(ADIv5_DP_t *dp)
{
if (!(dap_caps & DAP_CAP_SWD))
return 1;
mode = DAP_CAP_SWD;
dap_transfer_configure(2, 128, 128);
dap_swd_configure(0);
dap_connect(false);
dap_led(0, 1);
dap_reset_link(false);
if ((has_swd_sequence) && dap_sequence_test()) {
/* DAP_SWD_SEQUENCE does not do auto turnaround, use own!*/
dp->dp_low_write = dap_dp_low_write;
} else {
dp->dp_low_write = NULL;
}
dp->seq_out = dap_swdptap_seq_out;
dp->dp_read = dap_dp_read_reg;
/* For error() use the TARGETID switching firmware_swdp_error */
dp->low_access = dap_dp_low_access;
dp->abort = dap_dp_abort;
return 0;
}

View File

@ -1,7 +1,7 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2019 Uwe Bonnes
* Copyright (C) 2019 - 2021 Uwe Bonnes(bon@elektron.ikp.physik.tu-darmstadt.de)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -24,11 +24,14 @@
#if defined(CMSIS_DAP)
int dap_init(bmp_info_t *info);
int dap_enter_debug_swd(ADIv5_DP_t *dp);
void dap_exit_function(void);
void dap_adiv5_dp_defaults(ADIv5_DP_t *dp);
int cmsis_dap_jtagtap_init(jtag_proc_t *jtag_proc);
int dap_swdptap_init(ADIv5_DP_t *dp);
int dap_jtag_dp_init(ADIv5_DP_t *dp);
uint32_t dap_swj_clock(uint32_t clock);
void dap_swd_configure(uint8_t cfg);
void dap_srst_set_val(bool assert);
#else
int dap_init(bmp_info_t *info)
{
@ -36,19 +39,17 @@ int dap_init(bmp_info_t *info)
(void)info;
return -1;
}
int dap_enter_debug_swd(ADIv5_DP_t *dp) {(void)dp; return -1;}
void dap_exit_function(void) {return;};
void dap_adiv5_dp_defaults(ADIv5_DP_t *dp) {(void)dp; return; }
int cmsis_dap_jtagtap_init(jtag_proc_t *jtag_proc)
{
(void)jtag_proc;
return -1;
}
int dap_jtag_dp_init(ADIv5_DP_t *dp)
{
(void)dp;
return -1;
}
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wunused-parameter"
uint32_t dap_swj_clock(uint32_t clock) {return 0;}
void dap_exit_function(void) {};
void dap_adiv5_dp_defaults(ADIv5_DP_t *dp) {};
int cmsis_dap_jtagtap_init(jtag_proc_t *jtag_proc) {return -1;}
int dap_swdptap_init(ADIv5_DP_t *dp) {return -1;}
int dap_jtag_dp_init(ADIv5_DP_t *dp) {return -1;}
void dap_swd_configure(uint8_t cfg) {};
void dap_srst_set_val(bool assert) {};
# pragma GCC diagnostic pop
#endif

View File

@ -27,12 +27,12 @@
*/
/* Modified for Blackmagic Probe
* Copyright (c) 2020 Uwe Bonnes bon@elektron.ikp.physik.tu-darmstadt.de
* Copyright (c) 2020-21 Uwe Bonnes bon@elektron.ikp.physik.tu-darmstadt.de
*/
/*- Includes ----------------------------------------------------------------*/
#include <general.h>
#include <stdlib.h>
#include "exception.h"
#include "dap.h"
#include "jtag_scan.h"
@ -57,6 +57,7 @@ enum
ID_DAP_JTAG_SEQUENCE = 0x14,
ID_DAP_JTAG_CONFIGURE = 0x15,
ID_DAP_JTAG_IDCODE = 0x16,
ID_DAP_SWD_SEQUENCE = 0x1D,
};
enum
@ -197,24 +198,33 @@ void dap_connect(bool jtag)
//-----------------------------------------------------------------------------
void dap_disconnect(void)
{
uint8_t buf[1];
uint8_t buf[65];
buf[0] = ID_DAP_DISCONNECT;
dbg_dap_cmd(buf, sizeof(buf), 1);
}
//-----------------------------------------------------------------------------
void dap_swj_clock(uint32_t clock)
static uint32_t swj_clock;
/* Set/Get JTAG/SWD clock frequency
*
* With clock == 0, return last set value.
*/
uint32_t dap_swj_clock(uint32_t clock)
{
if (clock == 0)
return swj_clock;
uint8_t buf[5];
buf[0] = ID_DAP_SWJ_CLOCK;
buf[1] = clock & 0xff;
buf[2] = (clock >> 8) & 0xff;
buf[3] = (clock >> 16) & 0xff;
buf[4] = (clock >> 24) & 0xff;
dbg_dap_cmd(buf, sizeof(buf), 5);
if (buf[0])
DEBUG_WARN("dap_swj_clock failed\n");
else
swj_clock = clock;
return swj_clock;
}
//-----------------------------------------------------------------------------
@ -268,9 +278,9 @@ void dap_reset_pin(int state)
buf[1] = state ? DAP_SWJ_nRESET : 0; // Value
buf[2] = DAP_SWJ_nRESET; // Select
buf[3] = 0; // Wait
buf[4] = 0;
buf[5] = 0;
buf[6] = 0;
buf[4] = 0; // Wait
buf[5] = 0; // Wait
buf[6] = 0; // Wait
dbg_dap_cmd(buf, sizeof(buf), 7);
}
@ -314,20 +324,22 @@ static void dap_line_reset(void)
static uint32_t wait_word(uint8_t *buf, int size, int len, uint8_t *dp_fault)
{
uint8_t cmd_copy[len];
memcpy(cmd_copy, buf, len);
do {
memcpy(buf, cmd_copy, len);
dbg_dap_cmd(buf, size, len);
if (buf[1] < DAP_TRANSFER_WAIT)
break;
} while (buf[1] == DAP_TRANSFER_WAIT);
if (buf[1] > DAP_TRANSFER_WAIT) {
// DEBUG_WARN("dap_read_reg fault\n");
if(buf[1] == SWDP_ACK_FAULT) {
*dp_fault = 1;
return 0;
}
if (buf[1] == DAP_TRANSFER_ERROR) {
DEBUG_WARN("dap_read_reg, protocoll error\n");
dap_line_reset();
}
if(buf[1] != SWDP_ACK_OK)
raise_exception(EXCEPTION_ERROR, "SWDP invalid ACK");
uint32_t res =
((uint32_t)buf[5] << 24) | ((uint32_t)buf[4] << 16) |
((uint32_t)buf[3] << 8) | (uint32_t)buf[2];
@ -339,8 +351,7 @@ uint32_t dap_read_reg(ADIv5_DP_t *dp, uint8_t reg)
{
uint8_t buf[8];
uint8_t dap_index = 0;
if (dp->dev)
dap_index = dp->dev->dev;
dap_index = dp->dp_jd_index;
buf[0] = ID_DAP_TRANSFER;
buf[1] = dap_index;
buf[2] = 0x01; // Request size
@ -358,8 +369,7 @@ void dap_write_reg(ADIv5_DP_t *dp, uint8_t reg, uint32_t data)
buf[0] = ID_DAP_TRANSFER;
uint8_t dap_index = 0;
if (dp->dev)
dap_index = dp->dev->dev;
dap_index = dp->dp_jd_index;
buf[1] = dap_index;
buf[2] = 0x01; // Request size
buf[3] = reg & ~DAP_TRANSFER_RnW;;
@ -367,7 +377,10 @@ void dap_write_reg(ADIv5_DP_t *dp, uint8_t reg, uint32_t data)
buf[5] = (data >> 8) & 0xff;
buf[6] = (data >> 16) & 0xff;
buf[7] = (data >> 24) & 0xff;
uint8_t cmd_copy[8];
memcpy(cmd_copy, buf, 8);
do {
memcpy(buf, cmd_copy, 8);
dbg_dap_cmd(buf, sizeof(buf), 8);
if (buf[1] < DAP_TRANSFER_WAIT)
break;
@ -390,17 +403,16 @@ unsigned int dap_read_block(ADIv5_AP_t *ap, void *dest, uint32_t src,
uint8_t buf[1024];
unsigned int sz = len >> align;
uint8_t dap_index = 0;
if (ap->dp->dev)
dap_index = ap->dp->dev->dev;
dap_index = ap->dp->dp_jd_index;
buf[0] = ID_DAP_TRANSFER_BLOCK;
buf[1] = dap_index;
buf[2] = sz & 0xff;
buf[3] = (sz >> 8) & 0xff;
buf[4] = SWD_AP_DRW | DAP_TRANSFER_RnW;
dbg_dap_cmd(buf, 1023, 5 + 1);
dbg_dap_cmd(buf, 1023, 5);
unsigned int transferred = buf[0] + (buf[1] << 8);
if (buf[2] >= DAP_TRANSFER_FAULT) {
DEBUG_WARN("dap_read_block @ %08 "PRIx32 " fault -> line reset\n", src);
DEBUG_WARN("dap_read_block @ %08" PRIx32 " fault -> line reset\n", src);
dap_line_reset();
}
if (sz != transferred) {
@ -413,7 +425,6 @@ unsigned int dap_read_block(ADIv5_AP_t *ap, void *dest, uint32_t src,
dest = extract(dest, src, *p, align);
p++;
src += (1 << align);
dest += (1 << align);
sz--;
}
}
@ -426,8 +437,7 @@ unsigned int dap_write_block(ADIv5_AP_t *ap, uint32_t dest, const void *src,
uint8_t buf[1024];
unsigned int sz = len >> align;
uint8_t dap_index = 0;
if (ap->dp->dev)
dap_index = ap->dp->dev->dev;
dap_index = ap->dp->dp_jd_index;
buf[0] = ID_DAP_TRANSFER_BLOCK;
buf[1] = dap_index;
buf[2] = sz & 0xff;
@ -527,8 +537,7 @@ static uint8_t *mem_access_setup(ADIv5_AP_t *ap, uint8_t *p,
break;
}
uint8_t dap_index = 0;
if (ap->dp->dev)
dap_index = ap->dp->dev->dev;
dap_index = ap->dp->dp_jd_index;
*p++ = ID_DAP_TRANSFER;
*p++ = dap_index;
*p++ = 3; /* Nr transfers */
@ -559,12 +568,11 @@ void dap_ap_mem_access_setup(ADIv5_AP_t *ap, uint32_t addr, enum align align)
uint32_t dap_ap_read(ADIv5_AP_t *ap, uint16_t addr)
{
DEBUG_PROBE("dap_ap_read_start\n");
DEBUG_PROBE("dap_ap_read_start addr %x\n", addr);
uint8_t buf[63], *p = buf;
buf[0] = ID_DAP_TRANSFER;
uint8_t dap_index = 0;
if (ap->dp->dev)
dap_index = ap->dp->dev->dev;
dap_index = ap->dp->dp_jd_index;
*p++ = ID_DAP_TRANSFER;
*p++ = dap_index;
*p++ = 2; /* Nr transfers */
@ -576,6 +584,9 @@ uint32_t dap_ap_read(ADIv5_AP_t *ap, uint16_t addr)
*p++ = (addr & 0x0c) | DAP_TRANSFER_RnW |
((addr & 0x100) ? DAP_TRANSFER_APnDP : 0);
uint32_t res = wait_word(buf, 63, p - buf, &ap->dp->fault);
if ((buf[0] != 2) || (buf[1] != 1)) {
DEBUG_WARN("dap_ap_read error %x\n", buf[1]);
}
return res;
}
@ -584,8 +595,7 @@ void dap_ap_write(ADIv5_AP_t *ap, uint16_t addr, uint32_t value)
DEBUG_PROBE("dap_ap_write addr %04x value %08x\n", addr, value);
uint8_t buf[63], *p = buf;
uint8_t dap_index = 0;
if (ap->dp->dev)
dap_index = ap->dp->dev->dev;
dap_index = ap->dp->dp_jd_index;
*p++ = ID_DAP_TRANSFER;
*p++ = dap_index;
*p++ = 2; /* Nr transfers */
@ -600,6 +610,9 @@ void dap_ap_write(ADIv5_AP_t *ap, uint16_t addr, uint32_t value)
*p++ = (value >> 16) & 0xff;
*p++ = (value >> 24) & 0xff;
dbg_dap_cmd(buf, sizeof(buf), p - buf);
if ((buf[0] != 2) || (buf[1] != 1)) {
DEBUG_WARN("dap_ap_write error %x\n", buf[1]);
}
}
void dap_read_single(ADIv5_AP_t *ap, void *dest, uint32_t src, enum align align)
@ -607,7 +620,8 @@ void dap_read_single(ADIv5_AP_t *ap, void *dest, uint32_t src, enum align align)
uint8_t buf[63];
uint8_t *p = mem_access_setup(ap, buf, src, align);
*p++ = SWD_AP_DRW | DAP_TRANSFER_RnW;
buf[2] = 4;
*p++ = SWD_DP_R_RDBUFF | DAP_TRANSFER_RnW;
buf[2] = 5;
uint32_t tmp = wait_word(buf, 63, p - buf, &ap->dp->fault);
dest = extract(dest, src, tmp, align);
}
@ -643,15 +657,16 @@ void dap_write_single(ADIv5_AP_t *ap, uint32_t dest, const void *src,
void dap_jtagtap_tdi_tdo_seq(uint8_t *DO, bool final_tms, const uint8_t *TMS,
const uint8_t *DI, int ticks)
{
DEBUG_PROBE("dap_jtagtap_tdi_tdo_seq %s %d ticks\n",
(final_tms) ? "final" : "", ticks);
uint8_t buf[64];
const uint8_t *din = DI;
uint8_t *dout = DO;
if (!TMS) {
int last_byte = 0;
int last_bit = 0;
if (final_tms) {
last_byte = ticks >> 3;
last_bit = ticks & 7;
int last_byte = last_byte = (ticks - 1) >> 3;
int last_bit = (ticks - 1) & 7;
if (final_tms)
ticks --;
}
while (ticks) {
int transfers = ticks;
if (transfers > 64)
@ -659,11 +674,12 @@ void dap_jtagtap_tdi_tdo_seq(uint8_t *DO, bool final_tms, const uint8_t *TMS,
uint8_t *p = buf;
*p++ = ID_DAP_JTAG_SEQUENCE;
*p++ = 1;
*p++ = transfers | ((DO) ? DAP_JTAG_TDO_CAPTURE : 0);
*p++ = ((transfers == 64) ? 0 : transfers) |
((DO) ? DAP_JTAG_TDO_CAPTURE : 0);
int n_di_bytes = (transfers + 7) >> 3;
if (DI) {
p = memcpy(p, DI, n_di_bytes);
DI += n_di_bytes;
if (din) {
p = memcpy(p, din, n_di_bytes);
din += n_di_bytes;
} else {
p = memset(p, 0xff, n_di_bytes);
}
@ -671,9 +687,9 @@ void dap_jtagtap_tdi_tdo_seq(uint8_t *DO, bool final_tms, const uint8_t *TMS,
dbg_dap_cmd(buf, sizeof(buf), p - buf);
if (buf[0] != DAP_OK)
DEBUG_WARN("dap_jtagtap_tdi_tdo_seq failed %02x\n", buf[0]);
if (DO) {
memcpy(DO, &buf[1], (transfers + 7) >> 3);
DO += (transfers + 7) >> 3;
if (dout) {
memcpy(dout, &buf[1], (transfers + 7) >> 3);
dout += (transfers + 7) >> 3;
}
ticks -= transfers;
}
@ -681,8 +697,8 @@ void dap_jtagtap_tdi_tdo_seq(uint8_t *DO, bool final_tms, const uint8_t *TMS,
uint8_t *p = buf;
*p++ = ID_DAP_JTAG_SEQUENCE;
*p++ = 1;
*p++ = 1 | ((DO) ? DAP_JTAG_TDO_CAPTURE : 0) | DAP_JTAG_TMS;
if (DI) {
*p++ = 1 | ((dout) ? DAP_JTAG_TDO_CAPTURE : 0) | DAP_JTAG_TMS;
if (din) {
*p++ = ((DI[last_byte] & (1 << last_bit)) ? 1 : 0);
} else {
*p++ = 0;
@ -690,7 +706,7 @@ void dap_jtagtap_tdi_tdo_seq(uint8_t *DO, bool final_tms, const uint8_t *TMS,
dbg_dap_cmd(buf, sizeof(buf), p - buf);
if (buf[0] == DAP_ERROR)
DEBUG_WARN("dap_jtagtap_tdi_tdo_seq failed %02x\n", buf[0]);
if (DO) {
if (dout) {
if (buf[1] & 1)
DO[last_byte] |= (1 << last_bit);
else
@ -708,11 +724,11 @@ void dap_jtagtap_tdi_tdo_seq(uint8_t *DO, bool final_tms, const uint8_t *TMS,
*p++ = transfers;
for (int i = 0; i < transfers; i++) {
*p++ = 1 | ((DO) ? DAP_JTAG_TDO_CAPTURE : 0) |
((TMS[i >> 8] & (1 << (i & 7))) ? DAP_JTAG_TMS : 0);
((TMS[i >> 3] & (1 << (i & 7))) ? DAP_JTAG_TMS : 0);
if (DI)
*p++ = (DI[i >> 8] & (1 << (i & 7))) ? 1 : 0;
*p++ = (DI[i >> 3] & (1 << (i & 7))) ? 1 : 0;
else
*p++ = 0x55;
*p++ = 1;
}
dbg_dap_cmd(buf, sizeof(buf), p - buf);
if (buf[0] == DAP_ERROR)
@ -720,9 +736,9 @@ void dap_jtagtap_tdi_tdo_seq(uint8_t *DO, bool final_tms, const uint8_t *TMS,
if (DO) {
for (int i = 0; i < transfers; i++) {
if (buf[i + 1])
DO[i >> 8] |= (1 << (i & 7));
DO[i >> 3] |= (1 << (i & 7));
else
DO[i >> 8] &= ~(1 << (i & 7));
DO[i >> 3] &= ~(1 << (i & 7));
}
}
ticks -= transfers;
@ -748,3 +764,86 @@ int dap_jtag_configure(void)
DEBUG_WARN("dap_jtag_configure Failed %02x\n", buf[0]);
return 0;
}
void dap_swdptap_seq_out(uint32_t MS, int ticks)
{
uint8_t buf[64] = {
ID_DAP_SWJ_SEQUENCE,
ticks,
(MS >> 0) & 0xff,
(MS >> 8) & 0xff,
(MS >> 16) & 0xff,
(MS >> 24) & 0xff
};
dbg_dap_cmd(buf, 64, 2 + ((ticks +7) >> 3));
if (buf[0])
DEBUG_WARN("dap_swdptap_seq_out error\n");
}
void dap_swdptap_seq_out_parity(uint32_t MS, int ticks)
{
uint8_t buf[] = {
ID_DAP_SWJ_SEQUENCE,
ticks + 1,
(MS >> 0) & 0xff,
(MS >> 8) & 0xff,
(MS >> 16) & 0xff,
(MS >> 24) & 0xff,
__builtin_parity(MS) & 1
};
dbg_dap_cmd(buf, 1, sizeof(buf));
if (buf[0])
DEBUG_WARN("dap_swdptap_seq_out error\n");
}
bool dap_sequence_test(void)
{
uint8_t buf[4] = {
ID_DAP_SWD_SEQUENCE,
0x1,
0x81, /* Read one bit */
0 /* one idle cycle */
};
dbg_dap_cmd(buf, sizeof(buf), 3);
return (buf[0] == DAP_OK);
}
#define SWD_SEQUENCE_IN 0x80
uint32_t dap_swdptap_seq_in(int ticks)
{
uint8_t buf[5] = {
ID_DAP_SWD_SEQUENCE,
1,
ticks + SWD_SEQUENCE_IN
};
dbg_dap_cmd(buf, 2 + ((ticks + 7) >> 3), 3);
uint32_t res = 0;
int len = (ticks + 7) >> 3;
while (len--) {
res <<= 8;
res += buf[len + 1];
}
return res;
}
bool dap_swdptap_seq_in_parity(uint32_t *ret, int ticks)
{
(void)ticks;
uint8_t buf[8] = {
ID_DAP_SWD_SEQUENCE,
1,
33 + SWD_SEQUENCE_IN,
};
dbg_dap_cmd(buf, 7, 4);
uint32_t res = 0;
int len = 4;
while (len--) {
res <<= 8;
res += buf[len + 1];
}
*ret = res;
unsigned int parity = __builtin_parity(res) & 1;
parity ^= (buf[5] % 1);
DEBUG_WARN("Res %08" PRIx32" %d\n", *ret, parity & 1);
return (!(parity & 1));
}

View File

@ -65,11 +65,11 @@ enum
void dap_led(int index, int state);
void dap_connect(bool jtag);
void dap_disconnect(void);
void dap_swj_clock(uint32_t clock);
void dap_transfer_configure(uint8_t idle, uint16_t count, uint16_t retry);
void dap_swd_configure(uint8_t cfg);
int dap_info(int info, uint8_t *data, int size);
void dap_reset_target(void);
void dap_srst_set_val(bool assert);
void dap_trst_reset(void);
void dap_reset_target_hw(int state);
void dap_reset_pin(int state);
@ -91,4 +91,7 @@ int dbg_dap_cmd(uint8_t *data, int size, int rsize);
void dap_jtagtap_tdi_tdo_seq(uint8_t *DO, bool final_tms, const uint8_t *TMS,
const uint8_t *DI, int ticks);
int dap_jtag_configure(void);
void dap_swdptap_seq_out(uint32_t MS, int ticks);
void dap_swdptap_seq_out_parity(uint32_t MS, int ticks);
bool dap_sequence_test(void);
#endif // _DAP_H_

View File

@ -20,8 +20,6 @@
*/
#include "general.h"
#include "gdb_if.h"
#include "version.h"
#include "platform.h"
#include "target.h"
#include <assert.h>
@ -29,6 +27,7 @@
#include <sys/time.h>
#include "ftdi_bmp.h"
#include <ftdi.h>
struct ftdi_context *ftdic;
@ -124,8 +123,8 @@ cable_desc_t cable_desc[] = {
.init.ddr_low = PIN4,
.init.data_high = PIN4 | PIN3 | PIN2,
.init.ddr_high = PIN4 | PIN3 | PIN2 | PIN1 | PIN0,
.assert_srst.data_high = ~PIN2,
.deassert_srst.data_high = PIN2,
.assert_srst.data_high = ~PIN3,
.deassert_srst.data_high = PIN3,
.srst_get_port_cmd = GET_BITS_LOW,
.srst_get_pin = PIN6,
.description = "FTDIJTAG",
@ -270,7 +269,7 @@ int ftdi_bmp_init(BMP_CL_OPTIONS_t *cl_opts, bmp_info_t *info)
int err;
cable_desc_t *cable = &cable_desc[0];
for(; cable->name; cable++) {
if (strcmp(cable->name, cl_opts->opt_cable) == 0)
if (strncmp(cable->name, cl_opts->opt_cable, strlen(cable->name)) == 0)
break;
}
@ -282,7 +281,7 @@ int ftdi_bmp_init(BMP_CL_OPTIONS_t *cl_opts, bmp_info_t *info)
active_cable = cable;
memcpy(&active_state, &active_cable->init, sizeof(data_desc_t));
/* If swd_(read|write) is not given for the selected cable and
the 'r' command line argument is give, assume resistor SWD
the 'e' command line argument is give, assume resistor SWD
connection.*/
if (cl_opts->external_resistor_swd &&
(active_cable->mpsse_swd_read.set_data_low == 0) &&
@ -341,23 +340,27 @@ int ftdi_bmp_init(BMP_CL_OPTIONS_t *cl_opts, bmp_info_t *info)
goto error_2;
}
assert(ftdic != NULL);
err = ftdi_usb_purge_buffers(ftdic);
#ifdef _Ftdi_Pragma
err = ftdi_tcioflush(ftdic);
#else
err = ftdi_usb_purge_buffers(ftdic);
#endif
if (err != 0) {
fprintf(stderr, "ftdi_usb_purge_buffer: %d: %s\n",
DEBUG_WARN("ftdi_tcioflush(ftdi_usb_purge_buffer): %d: %s\n",
err, ftdi_get_error_string(ftdic));
goto error_2;
}
/* Reset MPSSE controller. */
err = ftdi_set_bitmode(ftdic, 0, BITMODE_RESET);
if (err != 0) {
fprintf(stderr, "ftdi_set_bitmode: %d: %s\n",
DEBUG_WARN("ftdi_set_bitmode: %d: %s\n",
err, ftdi_get_error_string(ftdic));
goto error_2;
}
/* Enable MPSSE controller. Pin directions are set later.*/
err = ftdi_set_bitmode(ftdic, 0, BITMODE_MPSSE);
if (err != 0) {
fprintf(stderr, "ftdi_set_bitmode: %d: %s\n",
DEBUG_WARN("ftdi_set_bitmode: %d: %s\n",
err, ftdi_get_error_string(ftdic));
goto error_2;
}
@ -372,6 +375,18 @@ int ftdi_bmp_init(BMP_CL_OPTIONS_t *cl_opts, bmp_info_t *info)
}
int index = 0;
ftdi_init[index++]= LOOPBACK_END; /* FT2232D gets upset otherwise*/
switch(ftdic->type) {
case TYPE_2232H:
case TYPE_4232H:
case TYPE_232H:
ftdi_init[index++] = DIS_DIV_5;
break;
case TYPE_2232C:
break;
default:
DEBUG_WARN("FTDI Chip has no MPSSE\n");
goto error_2;
}
ftdi_init[index++]= TCK_DIVISOR;
/* Use CLK/2 for about 50 % SWDCLK duty cycle on FT2232c.*/
ftdi_init[index++]= 1;
@ -406,11 +421,11 @@ static void libftdi_set_data(data_desc_t* data)
if ((data->data_low) || (data->ddr_low)) {
if (data->data_low > 0)
active_state.data_low |= (data->data_low & 0xff);
else
else if (data->data_low < 0)
active_state.data_low &= (data->data_low & 0xff);
if (data->ddr_low > 0)
active_state.ddr_low |= (data->ddr_low & 0xff);
else
else if (data->ddr_low < 0)
active_state.ddr_low &= (data->ddr_low & 0xff);
cmd[index++] = SET_BITS_LOW;
cmd[index++] = active_state.data_low;
@ -419,11 +434,11 @@ static void libftdi_set_data(data_desc_t* data)
if ((data->data_high) || (data->ddr_high)) {
if (data->data_high > 0)
active_state.data_high |= (data->data_high & 0xff);
else
else if (data->data_high < 0)
active_state.data_high &= (data->data_high & 0xff);
if (data->ddr_high > 0)
active_state.ddr_high |= (data->ddr_high & 0xff);
else
else if (data->ddr_high < 0)
active_state.ddr_high &= (data->ddr_high & 0xff);
cmd[index++] = SET_BITS_HIGH;
cmd[index++] = active_state.data_high;
@ -537,7 +552,8 @@ void libftdi_jtagtap_tdi_tdo_seq(
if(!ticks) return;
if (!DI && !DO) return;
// printf("ticks: %d\n", ticks);
DEBUG_WIRE("libftdi_jtagtap_tdi_tdo_seq %s ticks: %d\n",
(DI && DO) ? "read/write" : ((DI) ? "write" : "read"), ticks);
if(final_tms) ticks--;
rticks = ticks & 7;
ticks >>= 3;
@ -567,7 +583,7 @@ void libftdi_jtagtap_tdi_tdo_seq(
MPSSE_LSB | MPSSE_BITMODE | MPSSE_WRITE_NEG;
data[index++] = 0;
if (DI)
data[index++] = (DI[ticks]) >> rticks?0x81 : 0x01;
data[index++] = (DI[ticks] & (1 << rticks)) ? 0x81 : 0x01;
}
if (index)
libftdi_buffer_write(data, index);
@ -578,7 +594,6 @@ void libftdi_jtagtap_tdi_tdo_seq(
if(final_tms) rsize--;
while(rsize--) {
/*if(rsize) printf("%02X ", tmp[index]);*/
*DO++ = tmp[index++];
}
if (rticks == 0)
@ -591,7 +606,6 @@ void libftdi_jtagtap_tdi_tdo_seq(
if(rticks) {
*DO >>= (8-rticks);
}
/*printf("%02X\n", *DO);*/
}
}
@ -614,3 +628,34 @@ const char *libftdi_target_voltage(void)
}
return NULL;
}
static uint16_t divisor;
void libftdi_max_frequency_set(uint32_t freq)
{
uint32_t clock;
if (ftdic->type == TYPE_2232C)
clock = 12 * 1000 * 1000;
else
/* Undivided clock set during startup*/
clock = 60 * 1000 * 1000;
uint32_t div = (clock + 2 * freq - 1)/ freq;
if ((div < 4) && (ftdic->type = TYPE_2232C))
div = 4; /* Avoid bad unsymetrict FT2232C clock at 6 MHz*/
divisor = div / 2 - 1;
uint8_t buf[3];
buf[0] = TCK_DIVISOR;
buf[1] = divisor & 0xff;
buf[2] = (divisor >> 8) & 0xff;
libftdi_buffer_write(buf, 3);
}
uint32_t libftdi_max_frequency_get(void)
{
uint32_t clock;
if (ftdic->type == TYPE_2232C)
clock = 12 * 1000 * 1000;
else
/* Undivided clock set during startup*/
clock = 60 * 1000 * 1000;
return clock/ ( 2 *(divisor + 1));
}

View File

@ -23,9 +23,10 @@
#define __FTDI_BMP_H
#include "cl_utils.h"
#include "swdptap.h"
#include "jtagtap.h"
#include "bmp_hosted.h"
typedef struct data_desc_s {
int16_t data_low;
int16_t ddr_low;
@ -98,14 +99,33 @@ typedef struct cable_desc_s {
char * name;
}cable_desc_t;
#if HOSTED_BMP_ONLY == 1
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wunused-parameter"
int ftdi_bmp_init(BMP_CL_OPTIONS_t *cl_opts, bmp_info_t *info) {return -1;};
int libftdi_swdptap_init(ADIv5_DP_t *dp) {return -1;};
int libftdi_jtagtap_init(jtag_proc_t *jtag_proc) {return 0;};
void libftdi_buffer_flush(void) {};
int libftdi_buffer_write(const uint8_t *data, int size) {return size;};
int libftdi_buffer_read(uint8_t *data, int size) {return size;};
const char *libftdi_target_voltage(void) {return "ERROR";};
void libftdi_jtagtap_tdi_tdo_seq(
uint8_t *DO, const uint8_t final_tms, const uint8_t *DI, int ticks) {};
bool libftdi_swd_possible(bool *do_mpsse, bool *direct_bb_swd) {return false;};
void libftdi_max_frequency_set(uint32_t freq) {};
uint32_t libftdi_max_frequency_get(void) {return 0;};
void libftdi_srst_set_val(bool assert){};
bool libftdi_srst_get_val(void) { return false;};
# pragma GCC diagnostic pop
#else
#include <ftdi.h>
extern cable_desc_t cable_desc[];
extern cable_desc_t *active_cable;
extern struct ftdi_context *ftdic;
extern data_desc_t active_state;
int ftdi_bmp_init(BMP_CL_OPTIONS_t *cl_opts, bmp_info_t *info);
int libftdi_swdptap_init(swd_proc_t *swd_proc);
int libftdi_swdptap_init(ADIv5_DP_t *dp);
int libftdi_jtagtap_init(jtag_proc_t *jtag_proc);
void libftdi_buffer_flush(void);
int libftdi_buffer_write(const uint8_t *data, int size);
@ -114,6 +134,11 @@ const char *libftdi_target_voltage(void);
void libftdi_jtagtap_tdi_tdo_seq(
uint8_t *DO, const uint8_t final_tms, const uint8_t *DI, int ticks);
bool libftdi_swd_possible(bool *do_mpsse, bool *direct_bb_swd);
void libftdi_max_frequency_set(uint32_t freq);
uint32_t libftdi_max_frequency_get(void);
void libftdi_srst_set_val(bool assert);
bool libftdi_srst_get_val(void);
#endif
#define MPSSE_SK 1
#define PIN0 1

View File

@ -38,15 +38,21 @@
/* Only two devices PIDS tested so long */
#define USB_VID_SEGGER_0101 0x0101
#define USB_VID_SEGGER_0105 0x0105
#define USB_VID_SEGGER_1020 0x1020
static uint32_t emu_caps;
static uint32_t emu_speed_kHz;
static uint16_t emu_min_divisor;
static uint16_t emu_current_divisor;
static void jlink_print_caps(bmp_info_t *info)
{
uint8_t cmd[1] = {CMD_GET_CAPS};
uint8_t res[4];
send_recv(info->usb_link, cmd, 1, res, sizeof(res));
uint32_t caps = res[0] | (res[1] << 8) | (res[2] << 16) | (res[3] << 24);
DEBUG_INFO("Caps %" PRIx32 "\n", caps);
if (caps & JLINK_CAP_GET_HW_VERSION) {
emu_caps = res[0] | (res[1] << 8) | (res[2] << 16) | (res[3] << 24);
DEBUG_INFO("Caps %" PRIx32 "\n", emu_caps);
if (emu_caps & JLINK_CAP_GET_HW_VERSION) {
uint8_t cmd[1] = {CMD_GET_HW_VERSION};
send_recv(info->usb_link, cmd, 1, NULL, 0);
send_recv(info->usb_link, NULL, 0, res, sizeof(res));
@ -56,13 +62,15 @@ static void jlink_print_caps(bmp_info_t *info)
}
static void jlink_print_speed(bmp_info_t *info)
{
uint8_t cmd[1] = {CMD_GET_SPEED};
uint8_t cmd[1] = {CMD_GET_SPEEDS};
uint8_t res[6];
send_recv(info->usb_link, cmd, 1, res, sizeof(res));
uint32_t speed = res[0] | (res[1] << 8) | (res[2] << 16) | (res[3] << 24);
double freq_mhz = speed / 1000000.0;
uint16_t divisor = res[4] | (res[5] << 8);
DEBUG_INFO("Emulator speed %3.1f MHz, Mindiv %d\n", freq_mhz, divisor);
emu_speed_kHz = (res[0] | (res[1] << 8) | (res[2] << 16) | (res[3] << 24)) /
1000;
emu_min_divisor = res[4] | (res[5] << 8);
DEBUG_INFO("Emulator speed %d kHz, Mindiv %d%s\n", emu_speed_kHz,
emu_min_divisor,
(emu_caps & JLINK_CAP_GET_SPEEDS) ? "" : ", fixed");
}
static void jlink_print_version(bmp_info_t *info)
@ -90,15 +98,15 @@ static void jlink_print_interfaces(bmp_info_t *info)
DEBUG_INFO(", %s available\n",
(other_interface == JLINK_IF_SWD) ? "SWD": "JTAG");
else
DEBUG_WARN(", %s not available\n",
DEBUG_INFO(", %s not available\n",
((res[0] + 1) == JLINK_IF_SWD) ? "JTAG": "SWD");
}
static void jlink_info(bmp_info_t *info)
{
jlink_print_version(info);
jlink_print_speed(info);
jlink_print_caps(info);
jlink_print_speed(info);
jlink_print_interfaces(info);
}
@ -175,7 +183,8 @@ int jlink_init(bmp_info_t *info)
if (desc.idVendor != USB_PID_SEGGER)
continue;
if ((desc.idProduct != USB_VID_SEGGER_0101) &&
(desc.idProduct != USB_VID_SEGGER_0105))
(desc.idProduct != USB_VID_SEGGER_0105) &&
(desc.idProduct != USB_VID_SEGGER_1020))
continue;
int res = libusb_open(dev, &jl->ul_libusb_device_handle);
if (res != LIBUSB_SUCCESS)
@ -212,7 +221,7 @@ int jlink_init(bmp_info_t *info)
const char *jlink_target_voltage(bmp_info_t *info)
{
uint8_t cmd[1] = {CMD_GET_HW_STATUS};
uint8_t res[8];
uint8_t res[8];
send_recv(info->usb_link, cmd, 1, res, sizeof(res));
uint16_t mVolt = res[0] | (res[1] << 8);
static char ret[7];
@ -236,3 +245,27 @@ bool jlink_srst_get_val(bmp_info_t *info) {
send_recv(info->usb_link, cmd, 1, res, sizeof(res));
return !(res[6]);
}
void jlink_max_frequency_set(bmp_info_t *info, uint32_t freq)
{
if (!(emu_caps & JLINK_CAP_GET_SPEEDS))
return;
if (!info->is_jtag)
return;
uint16_t freq_kHz = freq /1000;
uint16_t divisor = (emu_speed_kHz + freq_kHz - 1) / freq_kHz;
if (divisor < emu_min_divisor)
divisor = emu_min_divisor;
emu_current_divisor = divisor;
uint16_t speed_kHz = emu_speed_kHz / divisor;
uint8_t cmd[3] = {CMD_SET_SPEED, speed_kHz & 0xff, speed_kHz >> 8};
DEBUG_WARN("Set Speed %d\n", speed_kHz);
send_recv(info->usb_link, cmd, 3, NULL, 0);
}
uint32_t jlink_max_frequency_get(bmp_info_t *info)
{
if ((emu_caps & JLINK_CAP_GET_SPEEDS) && (info->is_jtag))
return (emu_speed_kHz * 1000L)/ emu_current_divisor;
return FREQ_FIXED;
}

View File

@ -19,12 +19,14 @@
#if !defined(__JLINK_H_)
#define __JLINK_H_
#include "bmp_hosted.h"
#include "jtagtap.h"
/** @cond PRIVATE */
#define CMD_GET_VERSION 0x01
#define CMD_SET_SPEED 0x05
#define CMD_GET_HW_STATUS 0x07
#define CMD_GET_SPEED 0xc0
#define CMD_GET_SPEEDS 0xc0
#define CMD_GET_SELECT_IF 0xc7
#define CMD_HW_JTAG3 0xcf
#define CMD_HW_RESET0 0xdc
@ -36,13 +38,63 @@
#define JLINK_IF_GET_ACTIVE 0xfe
#define JLINK_IF_GET_AVAILABLE 0xff
#define JLINK_CAP_GET_HW_VERSION 2
#define JLINK_CAP_GET_SPEEDS (1 << 9)
#define JLINK_CAP_GET_HW_VERSION (1 << 1)
#define JLINK_IF_JTAG 1
#define JLINK_IF_SWD 2
#define SELECT_IF_JTAG 0
#define SELECT_IF_SWD 1
#if HOSTED_BMP_ONLY == 1
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wunused-parameter"
int jlink_init(bmp_info_t *info) {return -1;};
int jlink_swdp_scan(bmp_info_t *info) {return 0;};
int jlink_jtagtap_init(bmp_info_t *info, jtag_proc_t *jtag_proc) {return 0;};
const char *jlink_target_voltage(bmp_info_t *info) {return "ERROR";};
void jlink_srst_set_val(bmp_info_t *info, bool assert) {};
bool jlink_srst_get_val(bmp_info_t *info) {return true;};
void jlink_max_frequency_set(bmp_info_t *info, uint32_t freq) {};
uint32_t jlink_max_frequency_get(bmp_info_t *info) {return 0;};
# pragma GCC diagnostic pop
#else
/** Device capabilities. (from openocd*/
enum jaylink_device_capability {
/** Device supports retrieval of the hardware version. */
JAYLINK_DEV_CAP_GET_HW_VERSION = 1,
/** Device supports adaptive clocking. */
JAYLINK_DEV_CAP_ADAPTIVE_CLOCKING = 3,
/** Device supports reading configuration data. */
JAYLINK_DEV_CAP_READ_CONFIG = 4,
/** Device supports writing configuration data. */
JAYLINK_DEV_CAP_WRITE_CONFIG = 5,
/** Device supports retrieval of target interface speeds. */
JAYLINK_DEV_CAP_GET_SPEEDS = 9,
/** Device supports retrieval of free memory size. */
JAYLINK_DEV_CAP_GET_FREE_MEMORY = 11,
/** Device supports retrieval of hardware information. */
JAYLINK_DEV_CAP_GET_HW_INFO = 12,
/** Device supports the setting of the target power supply. */
JAYLINK_DEV_CAP_SET_TARGET_POWER = 13,
/** Device supports target interface selection. */
JAYLINK_DEV_CAP_SELECT_TIF = 17,
/** Device supports retrieval of counter values. */
JAYLINK_DEV_CAP_GET_COUNTERS = 19,
/** Device supports capturing of SWO trace data. */
JAYLINK_DEV_CAP_SWO = 23,
/** Device supports file I/O operations. */
JAYLINK_DEV_CAP_FILE_IO = 26,
/** Device supports registration of connections. */
JAYLINK_DEV_CAP_REGISTER = 27,
/** Device supports retrieval of extended capabilities. */
JAYLINK_DEV_CAP_GET_EXT_CAPS = 31,
/** Device supports EMUCOM. */
JAYLINK_DEV_CAP_EMUCOM = 33,
/** Device supports ethernet connectivity. */
JAYLINK_DEV_CAP_ETHERNET = 38
};
int jlink_init(bmp_info_t *info);
int jlink_swdp_scan(bmp_info_t *info);
@ -50,4 +102,7 @@ int jlink_jtagtap_init(bmp_info_t *info, jtag_proc_t *jtag_proc);
const char *jlink_target_voltage(bmp_info_t *info);
void jlink_srst_set_val(bmp_info_t *info, bool assert);
bool jlink_srst_get_val(bmp_info_t *info);
void jlink_max_frequency_set(bmp_info_t *info, uint32_t freq);
uint32_t jlink_max_frequency_get(bmp_info_t *info);
#endif
#endif

View File

@ -3,7 +3,7 @@
*
* Copyright (C) 2011 Black Sphere Technologies Ltd.
* Written by Gareth McMullin <gareth@blacksphere.co.nz>
* Copyright (C) 2019 - 2020 Uwe Bonnes
* Copyright (C) 2019 - 2021 Uwe Bonnes
* (bon@elektron.ikp.physik.tu-darmstadt.de)
*
* This program is free software: you can redistribute it and/or modify
@ -103,7 +103,7 @@ static int line_reset(bmp_info_t *info)
return 0;
}
static int swdptap_init(bmp_info_t *info)
static int jlink_swdptap_init(bmp_info_t *info)
{
uint8_t cmd[2] = {CMD_GET_SELECT_IF, JLINK_IF_GET_AVAILABLE};
uint8_t res[4];
@ -113,20 +113,14 @@ static int swdptap_init(bmp_info_t *info)
cmd[1] = SELECT_IF_SWD;
send_recv(info->usb_link, cmd, 2, res, sizeof(res));
platform_delay(10);
/* Set speed 256 kHz*/
unsigned int speed = 2000;
uint8_t jtag_speed[3] = {5, speed & 0xff, speed >> 8};
send_recv(info->usb_link, jtag_speed, 3, NULL, 0);
/* SWD speed is fixed. Do not set it here*/
return 0;
}
int jlink_swdp_scan(bmp_info_t *info)
{
swdptap_init(info);
jlink_swdptap_init(info);
target_list_free();
ADIv5_DP_t *dp = (void*)calloc(1, sizeof(*dp));
if (!dp) /* calloc failed: heap exhaustion */
return 0;
uint8_t cmd[44];
cmd[0] = CMD_HW_JTAG3;
cmd[1] = 0;
@ -178,7 +172,18 @@ int jlink_swdp_scan(bmp_info_t *info)
DEBUG_WARN( "Line reset failed\n");
return 0;
}
dp->idcode = jlink_adiv5_swdp_low_access(dp, 1, ADIV5_DP_IDCODE, 0);
ADIv5_DP_t *dp = (void*)calloc(1, sizeof(*dp));
if (!dp) /* calloc failed: heap exhaustion */
return 0;
volatile struct exception e;
TRY_CATCH (e, EXCEPTION_ALL) {
dp->idcode = jlink_adiv5_swdp_low_access(dp, 1, ADIV5_DP_IDCODE, 0);
}
if (e.type) {
DEBUG_WARN("DP not responding for IDCODE! Reset stuck low?\n");
free(dp);
return 0;
}
dp->dp_read = jlink_adiv5_swdp_read;
dp->error = jlink_adiv5_swdp_error;
dp->low_access = jlink_adiv5_swdp_low_access;
@ -247,20 +252,26 @@ static uint32_t jlink_adiv5_swdp_low_access(ADIv5_DP_t *dp, uint8_t RnW,
uint8_t res[8];
cmd[0] = CMD_HW_JTAG3;
cmd[1] = 0;
cmd[2] = 13;
/* It seems, JLINK samples read data at end of previous clock.
* So target data read must start at the 12'th clock, while
* write starts as expected at the 14'th clock (8 cmd, 3 response,
* 2 turn around.
*/
cmd[2] = (RnW) ? 11 : 13;
cmd[3] = 0;
cmd[4] = 0xff;
cmd[5] = 0xe3;
cmd[6] = request << 2;
cmd[7] = request >> 6;
cmd[4] = 0xff; /* 8 bits command OUT */
cmd[5] = 0xf0; /* one IN bit to turn around to read, read 2
(read) or 3 (write) IN bits for response and
and one OUT bit to turn around to write on write*/
cmd[6] = request;
cmd[7] = 0x00;
platform_timeout_set(&timeout, 2000);
do {
send_recv(info.usb_link, cmd, 8, res, 2);
send_recv(info.usb_link, NULL, 0, res, 1);
if (res[0] != 0)
send_recv(info.usb_link, NULL, 0, res + 2 , 1);
if (res[2] != 0)
raise_exception(EXCEPTION_ERROR, "Low access setup failed");
ack = res[1] >> 2;
ack &= 7;
ack = res[1] & 7;
} while (ack == SWDP_ACK_WAIT && !platform_timeout_is_expired(&timeout));
if (ack == SWDP_ACK_WAIT)
raise_exception(EXCEPTION_TIMEOUT, "SWDP ACK timeout");
@ -274,17 +285,15 @@ static uint32_t jlink_adiv5_swdp_low_access(ADIv5_DP_t *dp, uint8_t RnW,
if(ack != SWDP_ACK_OK) {
if (cl_debuglevel & BMP_DEBUG_TARGET)
DEBUG_WARN( "Protocol\n");
DEBUG_WARN( "Protocol %d\n", ack);
line_reset(&info);
return 0;
}
cmd[3] = 0;
/* Always prepend an idle cycle (SWDIO = 0)!*/
/* Always append 8 idle cycle (SWDIO = 0)!*/
if(RnW) {
memset(cmd + 4, 0, 10);
cmd[2] = 34;
cmd[2] = 33 + 2; /* 2 idle cycles */
cmd[8] = 0xfe;
cmd[13] = 0;
send_recv(info.usb_link, cmd, 14, res, 5);
send_recv(info.usb_link, NULL, 0, res + 5, 1);
if (res[5] != 0)
@ -292,19 +301,19 @@ static uint32_t jlink_adiv5_swdp_low_access(ADIv5_DP_t *dp, uint8_t RnW,
response = res[0] | res[1] << 8 | res[2] << 16 | res[3] << 24;
int parity = res[4] & 1;
int bit_count = __builtin_popcount (response) + parity;
if (bit_count & 1) /* Give up on parity error */
if (bit_count & 1) /* Give up on parity error */
raise_exception(EXCEPTION_ERROR, "SWDP Parity error");
} else {
cmd[2] = 35;
memset(cmd + 4, 0xff, 5);
cmd[ 9] = ((value << 2) & 0xfc);
cmd[10] = ((value >> 6) & 0xff);
cmd[11] = ((value >> 14) & 0xff);
cmd[12] = ((value >> 22) & 0xff);
cmd[13] = ((value >> 30) & 0x03);
cmd[2] = 33 + 8; /* 8 idle cycle to move data through SW-DP */
memset(cmd + 4, 0xff, 6);
cmd[10] = ((value >> 0) & 0xff);
cmd[11] = ((value >> 8) & 0xff);
cmd[12] = ((value >> 16) & 0xff);
cmd[13] = ((value >> 24) & 0xff);
int bit_count = __builtin_popcount(value);
cmd[13] |= ((bit_count & 1) ? 4 : 0);
send_recv(info.usb_link, cmd, 14, res, 5);
cmd[14] = bit_count & 1;
cmd[15] = 0;
send_recv(info.usb_link, cmd, 16, res, 6);
send_recv(info.usb_link, NULL, 0, res, 1);
if (res[0] != 0)
raise_exception(EXCEPTION_ERROR, "Low access write failed");

View File

@ -21,13 +21,10 @@
*
*/
#include <stdio.h>
#include "general.h"
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include "general.h"
#include "exception.h"
#include "jlink.h"

View File

@ -22,15 +22,13 @@
*
*/
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include "general.h"
#include <unistd.h>
#include <assert.h>
#include <ftdi.h>
#include "ftdi_bmp.h"
extern cable_desc_t *active_cable;
extern struct ftdi_context *ftdic;

View File

@ -1,8 +1,7 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2018 Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de)
* Written by Gareth McMullin <gareth@blacksphere.co.nz>
* Copyright(C) 2018 - 2021 Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -22,10 +21,10 @@
* Speed is sensible.
*/
#include <stdio.h>
#include "general.h"
#include <assert.h>
#include "general.h"
#include <ftdi.h>
#include "ftdi_bmp.h"
enum swdio_status{
@ -166,7 +165,7 @@ bool libftdi_swd_possible(bool *do_mpsse, bool *direct_bb_swd)
return true;
}
int libftdi_swdptap_init(swd_proc_t *swd_proc)
int libftdi_swdptap_init(ADIv5_DP_t *dp)
{
if (!libftdi_swd_possible(&do_mpsse, &direct_bb_swd)) {
DEBUG_WARN("SWD not possible or missing item in cable description.\n");
@ -206,11 +205,14 @@ int libftdi_swdptap_init(swd_proc_t *swd_proc)
libftdi_buffer_flush();
olddir = SWDIO_STATUS_FLOAT;
swd_proc->swdptap_seq_in = swdptap_seq_in;
swd_proc->swdptap_seq_in_parity = swdptap_seq_in_parity;
swd_proc->swdptap_seq_out = swdptap_seq_out;
swd_proc->swdptap_seq_out_parity = swdptap_seq_out_parity;
dp->seq_in = swdptap_seq_in;
dp->seq_in_parity = swdptap_seq_in_parity;
dp->seq_out = swdptap_seq_out;
dp->seq_out_parity = swdptap_seq_out_parity;
dp->dp_read = firmware_swdp_read;
dp->error = firmware_swdp_error;
dp->low_access = firmware_swdp_low_access;
dp->abort = firmware_swdp_abort;
return 0;
}
@ -303,7 +305,10 @@ static uint32_t swdptap_seq_in(int ticks)
if (do_mpsse) {
uint8_t DO[4];
libftdi_jtagtap_tdi_tdo_seq(DO, 0, NULL, ticks);
for (int i = 0; i < (ticks >> 3) + (ticks & 7)? 1: 0; i++) {
int bytes = ticks >> 3;
if (ticks & 7)
bytes++;
for (int i = 0; i < bytes; i++) {
result |= DO[i] << (8 * i);
}
} else {
@ -361,9 +366,19 @@ static void swdptap_seq_out(uint32_t MS, int ticks)
}
}
/* ARM Debug Interface Architecture Specification ADIv5.0 to ADIv5.2
* tells to clock the data through SW-DP to either :
* - immediate start a new transaction
* - continue to drive idle cycles
* - or clock at least 8 idle cycles
*
* Implement last option to favour correctness over
* slight speed decrease
*/
static void swdptap_seq_out_parity(uint32_t MS, int ticks)
{
int parity = __builtin_parity(MS & ((1LL << ticks) - 1)) & 1;
(void) ticks;
int parity = __builtin_parity(MS) & 1;
unsigned int index = 0;
swdptap_turnaround(SWDIO_STATUS_DRIVE);
if (do_mpsse) {
@ -373,26 +388,26 @@ static void swdptap_seq_out_parity(uint32_t MS, int ticks)
DI[2] = (MS >> 16) & 0xff;
DI[3] = (MS >> 24) & 0xff;
DI[4] = parity;
libftdi_jtagtap_tdi_tdo_seq(NULL, 0, DI, ticks + 1);
DI[5] = 0;
libftdi_jtagtap_tdi_tdo_seq(NULL, 0, DI, 32 + 1 + 8);
} else {
uint8_t cmd[32];
int steps = ticks;
while (steps) {
cmd[index++] = MPSSE_TMS_SHIFT;
cmd[index++] = 6;
if (steps >= 7) {
cmd[index++] = 6;
cmd[index++] = MS & 0x7f;
MS >>= 7;
steps -= 7;
} else {
cmd[index++] = steps - 1;
cmd[index++] = MS & 0x7f;
cmd[index++] = (MS & 0x7f) | (parity << 4);
steps = 0;
}
}
cmd[index++] = MPSSE_TMS_SHIFT;
cmd[index++] = 4;
cmd[index++] = 0;
cmd[index++] = parity;
libftdi_buffer_write(cmd, index);
}
}

View File

@ -1,7 +1,7 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2020 Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de)
* Copyright (C) 2020- 2021 Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -21,7 +21,6 @@
*/
#include "general.h"
#include "swdptap.h"
#include "jtagtap.h"
#include "target.h"
#include "target_internal.h"
@ -31,40 +30,31 @@
#include "gdb_if.h"
#include <signal.h>
#ifdef ENABLE_RTT
#include "rtt_if.h"
#endif
#include "bmp_remote.h"
#include "bmp_hosted.h"
#include "stlinkv2.h"
#include "ftdi_bmp.h"
#include "jlink.h"
#include "cmsis_dap.h"
#define VENDOR_ID_STLINK 0x0483
#define PRODUCT_ID_STLINK_MASK 0xffe0
#define PRODUCT_ID_STLINK_GROUP 0x3740
#define PRODUCT_ID_STLINKV1 0x3744
#define PRODUCT_ID_STLINKV2 0x3748
#define PRODUCT_ID_STLINKV21 0x374b
#define PRODUCT_ID_STLINKV21_MSD 0x3752
#define PRODUCT_ID_STLINKV3 0x374f
#define PRODUCT_ID_STLINKV3E 0x374e
#define VENDOR_ID_SEGGER 0x1366
#include "cl_utils.h"
bmp_info_t info;
swd_proc_t swd_proc;
jtag_proc_t jtag_proc;
void gdb_ident(char *p, int count)
{
snprintf(p, count, "%s (%s), %s", info.manufacturer, info.product,
info.version);
}
static void exit_function(void)
{
if(info.usb_link) {
libusb_free_transfer(info.usb_link->req_trans);
libusb_free_transfer(info.usb_link->rep_trans);
if (info.usb_link->ul_libusb_device_handle) {
libusb_release_interface (
info.usb_link->ul_libusb_device_handle, 0);
libusb_close(info.usb_link->ul_libusb_device_handle);
}
}
libusb_exit_function(&info);
switch (info.bmp_type) {
case BMP_TYPE_CMSIS_DAP:
dap_exit_function();
@ -72,6 +62,9 @@ static void exit_function(void)
default:
break;
}
#ifdef ENABLE_RTT
rtt_if_exit();
#endif
fflush(stdout);
}
@ -82,232 +75,31 @@ static void sigterm_handler(int sig)
exit(0);
}
static int find_debuggers( BMP_CL_OPTIONS_t *cl_opts,bmp_info_t *info)
{
libusb_device **devs;
int n_devs = libusb_get_device_list(info->libusb_ctx, &devs);
if (n_devs < 0) {
DEBUG_WARN( "WARN:libusb_get_device_list() failed");
return -1;
}
bool report = false;
int found_debuggers;
struct libusb_device_descriptor desc;
char serial[64];
char manufacturer[128];
char product[128];
bmp_type_t type = BMP_TYPE_NONE;
bool access_problems = false;
char *active_cable = NULL;
bool ftdi_unknown = false;
rescan:
found_debuggers = 0;
for (int i = 0; devs[i]; i++) {
libusb_device *dev = devs[i];
int res = libusb_get_device_descriptor(dev, &desc);
if (res < 0) {
DEBUG_WARN( "WARN: libusb_get_device_descriptor() failed: %s",
libusb_strerror(res));
libusb_free_device_list(devs, 1);
continue;
}
libusb_device_handle *handle;
res = libusb_open(dev, &handle);
if (res != LIBUSB_SUCCESS) {
if (!access_problems) {
DEBUG_INFO("INFO: Open USB %04x:%04x failed\n",
desc.idVendor, desc.idProduct);
access_problems = true;
}
continue;
}
res = libusb_get_string_descriptor_ascii(
handle, desc.iSerialNumber, (uint8_t*)serial,
sizeof(serial));
if (res <= 0) {
/* This can fail for many devices. Continue silent!*/
libusb_close(handle);
continue;
}
if (cl_opts->opt_serial && !strstr(serial, cl_opts->opt_serial)) {
libusb_close(handle);
continue;
}
res = libusb_get_string_descriptor_ascii(
handle, desc.iManufacturer, (uint8_t*)manufacturer,
sizeof(manufacturer));
if (res > 0) {
res = libusb_get_string_descriptor_ascii(
handle, desc.iProduct, (uint8_t*)product,
sizeof(product));
if (res <= 0) {
DEBUG_WARN( "WARN:"
"libusb_get_string_descriptor_ascii "
"for ident_string failed: %s\n",
libusb_strerror(res));
libusb_close(handle);
continue;
}
}
libusb_close(handle);
if (cl_opts->opt_ident_string) {
char *match_manu = NULL;
char *match_product = NULL;
match_manu = strstr(manufacturer, cl_opts->opt_ident_string);
match_product = strstr(product, cl_opts->opt_ident_string);
if (!match_manu && !match_product) {
continue;
}
}
/* Either serial and/or ident_string match or are not given.
* Check type.*/
if ((desc.idVendor == VENDOR_ID_BMP) &&
(desc.idProduct == PRODUCT_ID_BMP)) {
type = BMP_TYPE_BMP;
} else if ((strstr(manufacturer, "CMSIS")) || (strstr(product, "CMSIS"))) {
type = BMP_TYPE_CMSIS_DAP;
} else if (desc.idVendor == VENDOR_ID_STLINK) {
if ((desc.idProduct == PRODUCT_ID_STLINKV2) ||
(desc.idProduct == PRODUCT_ID_STLINKV21) ||
(desc.idProduct == PRODUCT_ID_STLINKV21_MSD) ||
(desc.idProduct == PRODUCT_ID_STLINKV3) ||
(desc.idProduct == PRODUCT_ID_STLINKV3E)) {
type = BMP_TYPE_STLINKV2;
} else {
if (desc.idProduct == PRODUCT_ID_STLINKV1)
DEBUG_WARN( "INFO: STLINKV1 not supported\n");
continue;
}
} else if (desc.idVendor == VENDOR_ID_SEGGER) {
type = BMP_TYPE_JLINK;
} else {
cable_desc_t *cable = &cable_desc[0];
for (; cable->name; cable++) {
bool found = false;
if ((cable->vendor != desc.idVendor) || (cable->product != desc.idProduct))
continue; /* VID/PID do not match*/
if (cl_opts->opt_cable) {
if (strcmp(cable->name, cl_opts->opt_cable))
continue; /* cable names do not match*/
else
found = true;
}
if (cable->description) {
if (strcmp(cable->description, product))
continue; /* discriptions do not match*/
else
found = true;
} else { /* VID/PID fits, but no cl_opts->opt_cable and no description*/
if ((cable->vendor == 0x0403) && /* FTDI*/
((cable->product == 0x6010) || /* FT2232C/D/H*/
(cable->product == 0x6011) || /* FT4232H Quad HS USB-UART/FIFO IC */
(cable->product == 0x6014))) { /* FT232H Single HS USB-UART/FIFO IC */
ftdi_unknown = true;
continue; /* Cable name is needed */
}
}
if (found) {
active_cable = cable->name;
type = BMP_TYPE_LIBFTDI;
break;
}
}
if (!cable->name)
continue;
}
if (report) {
DEBUG_WARN("%2d: %s, %s, %s\n", found_debuggers + 1,
serial,
manufacturer,product);
}
info->vid = desc.idVendor;
info->pid = desc.idProduct;
info->bmp_type = type;
strncpy(info->serial, serial, sizeof(info->serial));
strncpy(info->product, product, sizeof(info->product));
strncpy(info->manufacturer, manufacturer, sizeof(info->manufacturer));
if (cl_opts->opt_position &&
(cl_opts->opt_position == (found_debuggers + 1))) {
found_debuggers = 1;
break;
} else {
found_debuggers++;
}
}
if ((found_debuggers == 0) && ftdi_unknown)
DEBUG_WARN("Generic FTDI MPSSE VID/PID found. Please specify exact type with \"-c <cable>\" !\n");
if ((found_debuggers == 1) && !cl_opts->opt_cable && (type == BMP_TYPE_LIBFTDI))
cl_opts->opt_cable = active_cable;
if (!found_debuggers && cl_opts->opt_list_only)
DEBUG_WARN("No usable debugger found\n");
if ((found_debuggers > 1) ||
((found_debuggers == 1) && (cl_opts->opt_list_only))) {
if (!report) {
if (found_debuggers > 1)
DEBUG_WARN("%d debuggers found!\nSelect with -P <pos>, "
"-s <(partial)serial no.> "
"and/or -S <(partial)description>\n",
found_debuggers);
report = true;
goto rescan;
} else {
if (found_debuggers > 0)
access_problems = false;
found_debuggers = 0;
}
}
if (!found_debuggers && access_problems)
DEBUG_WARN(
"No debugger found. Please check access rights to USB devices!\n");
libusb_free_device_list(devs, 1);
return (found_debuggers == 1) ? 0 : -1;
}
static BMP_CL_OPTIONS_t cl_opts;
void platform_init(int argc, char **argv)
{
BMP_CL_OPTIONS_t cl_opts = {0};
cl_opts.opt_idstring = "Blackmagic PC-Hosted";
cl_init(&cl_opts, argc, argv);
atexit(exit_function);
signal(SIGTERM, sigterm_handler);
signal(SIGINT, sigterm_handler);
int res = libusb_init(&info.libusb_ctx);
if (res) {
DEBUG_WARN( "Fatal: Failed to get USB context: %s\n",
libusb_strerror(res));
exit(-1);
}
if (cl_opts.opt_device) {
if (cl_opts.opt_device)
info.bmp_type = BMP_TYPE_BMP;
} else if (cl_opts.opt_cable) {
if ((!strcmp(cl_opts.opt_cable, "list")) ||
(!strcmp(cl_opts.opt_cable, "l"))) {
cable_desc_t *cable = &cable_desc[0];
DEBUG_WARN("Available cables:\n");
for (; cable->name; cable++) {
DEBUG_WARN("\t%s\n", cable->name);
}
exit(0);
}
info.bmp_type = BMP_TYPE_LIBFTDI;
} else if (find_debuggers(&cl_opts, &info)) {
else if (find_debuggers(&cl_opts, &info))
exit(-1);
}
DEBUG_WARN("Using %04x:%04x %s %s %s\n", info.vid, info.pid, info.serial,
info.manufacturer,
info.product);
bmp_ident(&info);
switch (info.bmp_type) {
case BMP_TYPE_BMP:
if (serial_open(&cl_opts, info.serial))
exit(-1);
remote_init(true);
remote_init();
break;
case BMP_TYPE_STLINKV2:
if (stlink_init( &info))
if (stlink_init(&info))
exit(-1);
break;
case BMP_TYPE_CMSIS_DAP:
if (dap_init( &info))
if (dap_init(&info))
exit(-1);
break;
case BMP_TYPE_LIBFTDI:
@ -321,45 +113,38 @@ void platform_init(int argc, char **argv)
default:
exit(-1);
}
int ret = -1;
if (cl_opts.opt_mode != BMP_MODE_DEBUG) {
ret = cl_execute(&cl_opts);
} else {
if (cl_opts.opt_mode != BMP_MODE_DEBUG)
exit(cl_execute(&cl_opts));
else {
gdb_if_init();
#ifdef ENABLE_RTT
rtt_if_init();
#endif
return;
}
exit(ret);
}
int platform_adiv5_swdp_scan(void)
int platform_adiv5_swdp_scan(uint32_t targetid)
{
info.is_jtag = false;
platform_max_frequency_set(cl_opts.opt_max_swj_frequency);
switch (info.bmp_type) {
case BMP_TYPE_BMP:
case BMP_TYPE_LIBFTDI:
return adiv5_swdp_scan();
case BMP_TYPE_CMSIS_DAP:
return adiv5_swdp_scan(targetid);
break;
case BMP_TYPE_STLINKV2:
{
target_list_free();
ADIv5_DP_t *dp = (void*)calloc(1, sizeof(*dp));
if (!stlink_enter_debug_swd(&info, dp)) {
if (stlink_enter_debug_swd(&info, dp)) {
free(dp);
} else {
adiv5_dp_init(dp);
if (target_list)
return 1;
}
free(dp);
break;
}
case BMP_TYPE_CMSIS_DAP:
{
target_list_free();
ADIv5_DP_t *dp = (void*)calloc(1, sizeof(*dp));
if (!dap_enter_debug_swd(dp)) {
adiv5_dp_init(dp);
if (target_list)
return 1;
}
free(dp);
break;
}
case BMP_TYPE_JLINK:
@ -370,25 +155,34 @@ int platform_adiv5_swdp_scan(void)
return 0;
}
int platform_swdptap_init(void)
int swdptap_init(ADIv5_DP_t *dp)
{
switch (info.bmp_type) {
case BMP_TYPE_BMP:
return remote_swdptap_init(&swd_proc);
case BMP_TYPE_STLINKV2:
return remote_swdptap_init(dp);
case BMP_TYPE_CMSIS_DAP:
return dap_swdptap_init(dp);
case BMP_TYPE_STLINKV2:
case BMP_TYPE_JLINK:
return 0;
case BMP_TYPE_LIBFTDI:
return libftdi_swdptap_init(&swd_proc);
return libftdi_swdptap_init(dp);
default:
return -1;
}
return -1;
}
void platform_add_jtag_dev(int i, const jtag_dev_t *jtag_dev)
{
if (info.bmp_type == BMP_TYPE_BMP)
remote_add_jtag_dev(i, jtag_dev);
}
int platform_jtag_scan(const uint8_t *lrlens)
{
info.is_jtag = true;
platform_max_frequency_set(cl_opts.opt_max_swj_frequency);
switch (info.bmp_type) {
case BMP_TYPE_BMP:
case BMP_TYPE_LIBFTDI:
@ -424,8 +218,13 @@ int platform_jtagtap_init(void)
void platform_adiv5_dp_defaults(ADIv5_DP_t *dp)
{
dp->dp_bmp_type = info.bmp_type;
switch (info.bmp_type) {
case BMP_TYPE_BMP:
if (cl_opts.opt_no_hl) {
DEBUG_WARN("Not using HL commands\n");
return;
}
return remote_adiv5_dp_defaults(dp);
case BMP_TYPE_STLINKV2:
return stlink_adiv5_dp_defaults(dp);
@ -498,6 +297,10 @@ void platform_srst_set_val(bool assert)
return remote_srst_set_val(assert);
case BMP_TYPE_JLINK:
return jlink_srst_set_val(&info, assert);
case BMP_TYPE_LIBFTDI:
return libftdi_srst_set_val(assert);
case BMP_TYPE_CMSIS_DAP:
return dap_srst_set_val(assert);
default:
break;
}
@ -512,12 +315,83 @@ bool platform_srst_get_val(void)
return stlink_srst_get_val();
case BMP_TYPE_JLINK:
return jlink_srst_get_val(&info);
case BMP_TYPE_LIBFTDI:
return libftdi_srst_get_val();
default:
break;
}
return false;
}
void platform_max_frequency_set(uint32_t freq)
{
if (!freq)
return;
switch (info.bmp_type) {
case BMP_TYPE_BMP:
remote_max_frequency_set(freq);
break;
case BMP_TYPE_CMSIS_DAP:
dap_swj_clock(freq);
break;
case BMP_TYPE_LIBFTDI:
libftdi_max_frequency_set(freq);
break;
case BMP_TYPE_STLINKV2:
stlink_max_frequency_set(&info, freq);
break;
case BMP_TYPE_JLINK:
jlink_max_frequency_set(&info, freq);
break;
default:
DEBUG_WARN("Setting max SWJ frequency not yet implemented\n");
break;
}
uint32_t max_freq = platform_max_frequency_get();
if (max_freq == FREQ_FIXED)
DEBUG_INFO("Device has fixed frequency for %s\n",
(info.is_jtag) ? "JTAG" : "SWD" );
else
DEBUG_INFO("Speed set to %7.4f MHz for %s\n",
platform_max_frequency_get() / 1000000.0,
(info.is_jtag) ? "JTAG" : "SWD" );
}
uint32_t platform_max_frequency_get(void)
{
switch (info.bmp_type) {
case BMP_TYPE_BMP:
return remote_max_frequency_get();
case BMP_TYPE_CMSIS_DAP:
return dap_swj_clock(0);
break;
case BMP_TYPE_LIBFTDI:
return libftdi_max_frequency_get();
case BMP_TYPE_STLINKV2:
return stlink_max_frequency_get(&info);
case BMP_TYPE_JLINK:
return jlink_max_frequency_get(&info);
default:
DEBUG_WARN("Reading max SWJ frequency not yet implemented\n");
break;
}
return false;
}
void platform_target_set_power(bool power)
{
switch (info.bmp_type) {
case BMP_TYPE_BMP:
if (remote_target_set_power(power))
DEBUG_INFO("Powering up device!\n");
else
DEBUG_WARN("Powering up device unimplemented or failed\n");
break;
default:
break;
}
}
void platform_buffer_flush(void)
{
switch (info.bmp_type) {

View File

@ -1,22 +1,35 @@
#ifndef __PLATFORM_H
#define __PLATFORM_H
#include <libusb-1.0/libusb.h>
#include "libusb_utils.h"
#include <libftdi1/ftdi.h>
#include "timing.h"
char *platform_ident(void);
void platform_buffer_flush(void);
#define PLATFORM_IDENT() "NONE"
#define PLATFORM_IDENT "(PC-Hosted) "
#define SET_IDLE_STATE(x)
#define SET_RUN_STATE(x)
#define SYSTICKHZ 1000
#define VENDOR_ID_BMP 0x1d50
#define PRODUCT_ID_BMP_BL 0x6017
#define PRODUCT_ID_BMP 0x6018
#define VENDOR_ID_STLINK 0x0483
#define PRODUCT_ID_STLINK_MASK 0xffe0
#define PRODUCT_ID_STLINK_GROUP 0x3740
#define PRODUCT_ID_STLINKV1 0x3744
#define PRODUCT_ID_STLINKV2 0x3748
#define PRODUCT_ID_STLINKV21 0x374b
#define PRODUCT_ID_STLINKV21_MSD 0x3752
#define PRODUCT_ID_STLINKV3_NO_MSD 0x3754
#define PRODUCT_ID_STLINKV3_BL 0x374d
#define PRODUCT_ID_STLINKV3 0x374f
#define PRODUCT_ID_STLINKV3E 0x374e
#define VENDOR_ID_SEGGER 0x1366
typedef enum bmp_type_s {
BMP_TYPE_NONE = 0,
BMP_TYPE_BMP,
@ -26,19 +39,5 @@ typedef enum bmp_type_s {
BMP_TYPE_JLINK
} bmp_type_t;
typedef struct bmp_info_s {
bmp_type_t bmp_type;
libusb_context *libusb_ctx;
struct ftdi_context *ftdic;
usb_link_t *usb_link;
unsigned int vid;
unsigned int pid;
char dev;
char serial[64];
char manufacturer[128];
char product[128];
} bmp_info_t;
extern bmp_info_t info;
void gdb_ident(char *p, int count);
#endif

View File

@ -26,13 +26,11 @@
* Should share interface with swdptap.c or at least clean up...
*/
#include <stdio.h>
#include "general.h"
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include "general.h"
#include "remote.h"
#include "jtagtap.h"
#include "bmp_remote.h"
@ -106,35 +104,58 @@ static void jtagtap_tms_seq(uint32_t MS, int ticks)
}
}
/* At least up to v1.7.1-233, remote handles only up to 32 ticks in one
* call. Break up large calls.
*
* FIXME: Provide and test faster call and keep fallback
* for old firmware
*/
static void jtagtap_tdi_tdo_seq(
uint8_t *DO, const uint8_t final_tms, const uint8_t *DI, int ticks)
{
uint8_t construct[REMOTE_MAX_MSG_SIZE];
int s;
uint64_t DIl=*(uint64_t *)DI;
if(!ticks || (!DI && !DO))
return;
while (ticks) {
int chunk;
if (ticks < 65)
chunk = ticks;
else {
chunk = 64;
}
ticks -= chunk;
uint64_t di = 0;
int bytes = (chunk + 7) >> 3;
int i = 0;
if (DI) {
for (; i < bytes; i++) {
di |= *DI << (i * 8);
DI++;
}
}
/* PRIx64 differs with system. Use it explicit in the format string*/
s = snprintf((char *)construct, REMOTE_MAX_MSG_SIZE,
"!J%c%02x%" PRIx64 "%c",
(!ticks && final_tms) ?
REMOTE_TDITDO_TMS : REMOTE_TDITDO_NOTMS,
chunk, di, REMOTE_EOM);
platform_buffer_write(construct,s);
if(!ticks || !DI) return;
/* Reduce the length of DI according to the bits we're transmitting */
DIl &= (1LL << (ticks + 1))-1;
s = snprintf((char *)construct, REMOTE_MAX_MSG_SIZE,
REMOTE_JTAG_TDIDO_STR,
final_tms ? REMOTE_TDITDO_TMS : REMOTE_TDITDO_NOTMS,
ticks, DIl);
platform_buffer_write(construct,s);
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((!s) || (construct[0] == REMOTE_RESP_ERR)) {
DEBUG_WARN("jtagtap_tms_seq failed, error %s\n",
s ? (char *)&(construct[1]) : "unknown");
exit(-1);
}
if (DO) {
uint64_t DOl = remotehston(-1, (char *)&construct[1]);
*(uint64_t *)DO = DOl;
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((!s) || (construct[0] == REMOTE_RESP_ERR)) {
DEBUG_WARN("jtagtap_tms_seq failed, error %s\n",
s ? (char *)&(construct[1]) : "unknown");
exit(-1);
}
if (DO) {
uint64_t res = remotehston(-1, (char *)&construct[1]);
for (i = bytes; i > 0; i--) {
*DO++ = res & 0xff;
res >>= 8;
}
}
}
}

View File

@ -3,7 +3,7 @@
*
* Written by Gareth McMullin <gareth@blacksphere.co.nz>
* Modified by Dave Marples <dave@marples.net>
* Modification (C) 2020 Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de)
* Modified 2020 - 2021 by Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -35,7 +35,7 @@ static uint32_t swdptap_seq_in(int ticks);
static void swdptap_seq_out(uint32_t MS, int ticks);
static void swdptap_seq_out_parity(uint32_t MS, int ticks);
int remote_swdptap_init(swd_proc_t *swd_proc)
int remote_swdptap_init(ADIv5_DP_t *dp)
{
DEBUG_WIRE("remote_swdptap_init\n");
uint8_t construct[REMOTE_MAX_MSG_SIZE];
@ -50,11 +50,14 @@ int remote_swdptap_init(swd_proc_t *swd_proc)
exit(-1);
}
swd_proc->swdptap_seq_in = swdptap_seq_in;
swd_proc->swdptap_seq_in_parity = swdptap_seq_in_parity;
swd_proc->swdptap_seq_out = swdptap_seq_out;
swd_proc->swdptap_seq_out_parity = swdptap_seq_out_parity;
dp->seq_in = swdptap_seq_in;
dp->seq_in_parity = swdptap_seq_in_parity;
dp->seq_out = swdptap_seq_out;
dp->seq_out_parity = swdptap_seq_out_parity;
dp->dp_read = firmware_swdp_read;
dp->error = firmware_swdp_error;
dp->low_access = firmware_swdp_low_access;
dp->abort = firmware_swdp_abort;
return 0;
}

View File

@ -0,0 +1,127 @@
/*
* This file is part of the Black Magic Debug project.
*
* MIT License
*
* Copyright (c) 2021 Koen De Vleeschauwer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <general.h>
#include <unistd.h>
#include <fcntl.h>
#include <rtt_if.h>
/* maybe rewrite this as tcp server */
#ifndef WIN32
#include <termios.h>
/* linux */
static struct termios saved_ttystate;
static bool tty_saved = false;
/* set up and tear down */
int rtt_if_init()
{
struct termios ttystate;
tcgetattr(STDIN_FILENO, &saved_ttystate);
tty_saved = true;
tcgetattr(STDIN_FILENO, &ttystate);
ttystate.c_lflag &= ~ICANON;
ttystate.c_lflag &= ~ECHO;
ttystate.c_cc[VMIN] = 1;
tcsetattr(STDIN_FILENO, TCSANOW, &ttystate);
int flags = fcntl(0, F_GETFL, 0);
fcntl(0, F_SETFL, flags | O_NONBLOCK);
return 0;
}
int rtt_if_exit()
{
if (tty_saved)
tcsetattr(STDIN_FILENO, TCSANOW, &saved_ttystate);
return 0;
}
/* write buffer to terminal */
uint32_t rtt_write(const char *buf, uint32_t len)
{
write(1, buf, len);
return len;
}
/* read character from terminal */
int32_t rtt_getchar()
{
char ch;
int len;
len = read(0, &ch, 1);
if (len == 1) return ch;
return -1;
}
/* true if no characters available */
bool rtt_nodata()
{
return false;
}
#else
/* windows, output only */
int rtt_if_init()
{
return 0;
}
int rtt_if_exit()
{
return 0;
}
/* write buffer to terminal */
uint32_t rtt_write(const char *buf, uint32_t len)
{
write(1, buf, len);
return len;
}
/* read character from terminal */
int32_t rtt_getchar()
{
return -1;
}
/* true if no characters available */
bool rtt_nodata()
{
return false;
}
#endif

View File

@ -27,10 +27,12 @@
#include "general.h"
#include "gdb_if.h"
#include "adiv5.h"
#include "bmp_hosted.h"
#include "stlinkv2.h"
#include "exception.h"
#include "jtag_devs.h"
#include "target.h"
#include "cortexm.h"
#include <assert.h>
#include <unistd.h>
@ -40,16 +42,6 @@
#include "cl_utils.h"
#define VENDOR_ID_STLINK 0x483
#define PRODUCT_ID_STLINK_MASK 0xffe0
#define PRODUCT_ID_STLINK_GROUP 0x3740
#define PRODUCT_ID_STLINKV1 0x3744
#define PRODUCT_ID_STLINKV2 0x3748
#define PRODUCT_ID_STLINKV21 0x374b
#define PRODUCT_ID_STLINKV21_MSD 0x3752
#define PRODUCT_ID_STLINKV3 0x374f
#define PRODUCT_ID_STLINKV3E 0x374e
#define STLINK_SWIM_ERR_OK 0x00
#define STLINK_SWIM_BUSY 0x01
#define STLINK_DEBUG_ERR_OK 0x80
@ -198,7 +190,6 @@ typedef struct {
libusb_context* libusb_ctx;
uint16_t vid;
uint16_t pid;
uint8_t transport_mode;
bool srst;
uint8_t dap_select;
uint8_t ep_tx;
@ -348,7 +339,8 @@ static int stlink_send_recv_retry(uint8_t *txbuf, size_t txsize,
if (res == STLINK_ERROR_OK)
return res;
uint32_t now = platform_time_ms();
if (((now - start) > 1000) || (res != STLINK_ERROR_WAIT)) {
if (((now - start) > cortexm_wait_timeout) ||
(res != STLINK_ERROR_WAIT)) {
DEBUG_WARN("write_retry failed. ");
return res;
}
@ -397,6 +389,9 @@ static int write_retry(uint8_t *cmdbuf, size_t cmdsize,
return res;
}
/* Version data is at 0x080103f8 with STLINKV3 bootloader flashed with
* STLinkUpgrade_v3[3|5].jar
*/
static void stlink_version(bmp_info_t *info)
{
if (Stlink.ver_hw == 30) {
@ -434,7 +429,8 @@ static void stlink_version(bmp_info_t *info)
Stlink.ver_swim = (version >> 0) & 0x3f;
}
}
DEBUG_INFO("V%dJ%d",Stlink.ver_stlink, Stlink.ver_jtag);
DEBUG_INFO("STLink firmware version: V%dJ%d",Stlink.ver_stlink,
Stlink.ver_jtag);
if (Stlink.ver_hw == 30) {
DEBUG_INFO("M%dB%dS%d", Stlink.ver_mass, Stlink.ver_bridge, Stlink.ver_swim);
} else if (Stlink.ver_hw == 20) {
@ -514,23 +510,39 @@ int stlink_init(bmp_info_t *info)
bool found = false;
while ((dev = devs[i++]) != NULL) {
struct libusb_device_descriptor desc;
int r = libusb_get_device_descriptor(dev, &desc);
if (r < 0) {
int result = libusb_get_device_descriptor(dev, &desc);
if (result != LIBUSB_SUCCESS) {
DEBUG_WARN("libusb_get_device_descriptor failed %s",
libusb_strerror(r));
libusb_strerror(result));
return -1;
}
if ((desc.idVendor != info->vid) ||
(desc.idProduct != info->pid) ||
(libusb_open(dev, &sl->ul_libusb_device_handle)
!= LIBUSB_SUCCESS)) {
if (desc.idVendor != info->vid ||
desc.idProduct != info->pid) {
continue;
}
if ((result = libusb_open(dev, &sl->ul_libusb_device_handle)) != LIBUSB_SUCCESS)
{
DEBUG_WARN("Failed to open STLink device %04x:%04x - %s\n",
desc.idVendor, desc.idProduct, libusb_strerror(result));
DEBUG_WARN("Are you sure the permissions on the device are set correctly?\n");
continue;
}
char serial[64];
r = libusb_get_string_descriptor_ascii(
sl->ul_libusb_device_handle, desc.iSerialNumber,
(uint8_t*)serial,sizeof(serial));
if (r <= 0 || !strstr(serial, info->serial)) {
if (desc.iSerialNumber) {
int result = libusb_get_string_descriptor_ascii(sl->ul_libusb_device_handle,
desc.iSerialNumber, (uint8_t *)serial, sizeof(serial));
/* If the call fails and it's not because the device gave us STALL, continue to the next one */
if (result < 0 && result != LIBUSB_ERROR_PIPE) {
libusb_close(sl->ul_libusb_device_handle);
continue;
}
else if (result <= 0)
serial[0] = '\0';
}
else
serial[0] = '\0';
/* Likewise, if the serial number returned doesn't match the one in info, go to next */
if (!strstr(serial, info->serial)) {
libusb_close(sl->ul_libusb_device_handle);
continue;
}
@ -539,21 +551,31 @@ int stlink_init(bmp_info_t *info)
}
libusb_free_device_list(devs, 1);
if (!found)
return 1;
if (info->vid != VENDOR_ID_STLINK)
return 0;
if (info->pid == PRODUCT_ID_STLINKV2) {
switch (info->pid) {
case PRODUCT_ID_STLINKV2:
Stlink.ver_hw = 20;
info->usb_link->ep_tx = 2;
Stlink.ep_tx = 2;
} else if ((info->pid == PRODUCT_ID_STLINKV21)||
(info->pid == PRODUCT_ID_STLINKV21_MSD)) {
break;
case PRODUCT_ID_STLINKV21 :
case PRODUCT_ID_STLINKV21_MSD:
Stlink.ver_hw = 21;
info->usb_link->ep_tx = 1;
Stlink.ep_tx = 1;
} else if ((info->pid == PRODUCT_ID_STLINKV3) ||
(info->pid == PRODUCT_ID_STLINKV3E)) {
break;
case PRODUCT_ID_STLINKV3_BL:
case PRODUCT_ID_STLINKV3:
case PRODUCT_ID_STLINKV3E:
case PRODUCT_ID_STLINKV3_NO_MSD:
Stlink.ver_hw = 30;
info->usb_link->ep_tx = 1;
Stlink.ep_tx = 1;
break;
default:
DEBUG_INFO("Unhandled STM32 device\n");
}
info->usb_link->ep_rx = 1;
int config;
@ -625,44 +647,6 @@ bool stlink_srst_get_val(void)
return Stlink.srst;
}
static bool stlink_set_freq_divisor(bmp_info_t *info, uint16_t divisor)
{
uint8_t cmd[16] = {STLINK_DEBUG_COMMAND,
STLINK_DEBUG_APIV2_SWD_SET_FREQ,
divisor & 0xff, divisor >> 8};
uint8_t data[2];
send_recv(info->usb_link, cmd, 16, data, 2);
if (stlink_usb_error_check(data, false))
return false;
return true;
}
static bool stlink3_set_freq_divisor(bmp_info_t *info, uint16_t divisor)
{
uint8_t cmd[16] = {STLINK_DEBUG_COMMAND,
STLINK_APIV3_GET_COM_FREQ,
Stlink.transport_mode};
uint8_t data[52];
send_recv(info->usb_link, cmd, 16, data, 52);
stlink_usb_error_check(data, true);
int size = data[8];
if (divisor > size)
divisor = size;
uint8_t *p = data + 12 + divisor * sizeof(uint32_t);
uint32_t freq = p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24;
DEBUG_INFO("Selected %" PRId32 " khz\n", freq);
cmd[1] = STLINK_APIV3_SET_COM_FREQ;
cmd[2] = Stlink.transport_mode;
cmd[3] = 0;
p = data + 12 + divisor * sizeof(uint32_t);
cmd[4] = p[0];
cmd[5] = p[1];
cmd[6] = p[2];
cmd[7] = p[3];
send_recv(info->usb_link, cmd, 16, data, 8);
return true;
}
int stlink_hwversion(void)
{
return Stlink.ver_stlink;
@ -671,16 +655,10 @@ int stlink_hwversion(void)
static int stlink_enter_debug_jtag(bmp_info_t *info)
{
stlink_leave_state(info);
Stlink.transport_mode = STLINK_MODE_JTAG;
if (Stlink.ver_stlink == 3)
stlink3_set_freq_divisor(info, 4);
else
stlink_set_freq_divisor(info, 1);
uint8_t cmd[16] = {STLINK_DEBUG_COMMAND,
STLINK_DEBUG_APIV2_ENTER,
STLINK_DEBUG_ENTER_JTAG_NO_RESET};
uint8_t data[2];
DEBUG_INFO("Enter JTAG\n");
send_recv(info->usb_link, cmd, 16, data, 2);
return stlink_usb_error_check(data, true);
}
@ -802,9 +780,10 @@ uint32_t stlink_dp_low_access(ADIv5_DP_t *dp, uint8_t RnW,
int res;
if (RnW) {
res = stlink_read_dp_register(
STLINK_DEBUG_PORT_ACCESS, addr, &response);
(addr < 0x100) ? STLINK_DEBUG_PORT_ACCESS : 0, addr, &response);
} else {
res = stlink_write_dp_register(STLINK_DEBUG_PORT_ACCESS, addr, value);
res = stlink_write_dp_register(
(addr < 0x100) ? STLINK_DEBUG_PORT_ACCESS : 0, addr, value);
}
if (res == STLINK_ERROR_WAIT)
raise_exception(EXCEPTION_TIMEOUT, "DP ACK timeout");
@ -829,8 +808,8 @@ static bool stlink_ap_setup(int ap)
ap,
};
uint8_t data[2];
send_recv(info.usb_link, cmd, 16, data, 2);
DEBUG_PROBE("Open AP %d\n", ap);
stlink_send_recv_retry(cmd, 16, data, 2);
int res = stlink_usb_error_check(data, true);
if (res) {
if (Stlink.ver_hw == 30) {
@ -1041,13 +1020,13 @@ int jtag_scan_stlinkv2(bmp_info_t *info, const uint8_t *irlens)
jtag_dev_count = stlink_read_idcodes(info, idcodes);
/* Check for known devices and handle accordingly */
for(int i = 0; i < jtag_dev_count; i++)
jtag_devs[i].idcode = idcodes[i];
jtag_devs[i].jd_idcode = idcodes[i];
for(int i = 0; i < jtag_dev_count; i++)
for(int j = 0; dev_descr[j].idcode; j++)
if((jtag_devs[i].idcode & dev_descr[j].idmask) ==
if((jtag_devs[i].jd_idcode & dev_descr[j].idmask) ==
dev_descr[j].idcode) {
if(dev_descr[j].handler)
dev_descr[j].handler(&jtag_devs[i]);
dev_descr[j].handler(i);
break;
}
@ -1081,19 +1060,13 @@ void stlink_adiv5_dp_defaults(ADIv5_DP_t *dp)
int stlink_enter_debug_swd(bmp_info_t *info, ADIv5_DP_t *dp)
{
stlink_leave_state(info);
Stlink.transport_mode = STLINK_MODE_SWD;
if (Stlink.ver_stlink == 3)
stlink3_set_freq_divisor(info, 2);
else
stlink_set_freq_divisor(info, 1);
uint8_t cmd[16] = {STLINK_DEBUG_COMMAND,
STLINK_DEBUG_APIV2_ENTER,
STLINK_DEBUG_ENTER_SWD_NO_RESET};
uint8_t data[2];
DEBUG_INFO("Enter SWD\n");
stlink_send_recv_retry(cmd, 16, data, 2);
if (stlink_usb_error_check(data, true))
return -1;
exit( -1);
dp->idcode = stlink_read_coreid();
dp->dp_read = stlink_dp_read;
dp->error = stlink_dp_error;
@ -1101,5 +1074,117 @@ int stlink_enter_debug_swd(bmp_info_t *info, ADIv5_DP_t *dp)
dp->abort = stlink_dp_abort;
stlink_dp_error(dp);
if ((dp->idcode & ADIV5_DP_VERSION_MASK) == ADIV5_DPv2) {
adiv5_dp_write(dp, ADIV5_DP_SELECT, 2);
dp->targetid = adiv5_dp_read(dp, ADIV5_DP_CTRLSTAT);
adiv5_dp_write(dp, ADIV5_DP_SELECT, 0);
DEBUG_INFO("TARGETID 0x%08" PRIx32 "\n", dp->targetid);
}
return 0;
}
#define V2_USED_SWD_CYCLES 20
#define V2_CYCLES_PER_CNT 20
#define V2_CLOCK_RATE (72*1000*1000)
/* Above values reproduce the known values for V2
#include <stdio.h>
int main(void)
{
int divs[] = {0, 1,2,3,7,15,31,40,79,158,265,798};
for (int i = 0; i < (sizeof(divs) /sizeof(divs[0])); i++) {
float ret = 72.0 * 1000 * 1000 / (20 + 20 * divs[i]);
printf("%3d: %6.4f MHz\n", divs[i], ret/ 1000000);
}
return 0;
}
*/
static int divisor;
static unsigned int v3_freq[2];
void stlink_max_frequency_set(bmp_info_t *info, uint32_t freq)
{
if (Stlink.ver_hw == 30) {
uint8_t cmd[16] = {STLINK_DEBUG_COMMAND,
STLINK_APIV3_GET_COM_FREQ,
info->is_jtag ? STLINK_MODE_JTAG : STLINK_MODE_SWD};
uint8_t data[52];
send_recv(info->usb_link, cmd, 16, data, 52);
stlink_usb_error_check(data, true);
volatile uint8_t *p = data + 12;
int i;
unsigned int last_freq = 0;
DEBUG_INFO("Available speed settings: ");
for (i = 0; i < STLINK_V3_MAX_FREQ_NB; i++) {
unsigned int new_freq = *p++;
new_freq |= *p++ << 8;
new_freq |= *p++ << 16;
new_freq |= *p++ << 24;
if (!new_freq)
break;
else
last_freq = new_freq;
DEBUG_INFO("%s%d", (i)? "/": "", last_freq);
if ((freq / 1000) >= last_freq)
break;
}
DEBUG_INFO(" kHz for %s\n", (info->is_jtag) ? "JTAG" : "SWD");
cmd[1] = STLINK_APIV3_SET_COM_FREQ;
cmd[3] = 0;
cmd[4] = (last_freq >> 0) & 0xff;
cmd[5] = (last_freq >> 8) & 0xff;
cmd[6] = (last_freq >> 16) & 0xff;
cmd[7] = (last_freq >> 24) & 0xff;
send_recv(info->usb_link, cmd, 16, data, 8);
stlink_usb_error_check(data, true);
v3_freq[(info->is_jtag) ? 1 : 0] = last_freq * 1000;
} else {
uint8_t cmd[16];
cmd[0] = STLINK_DEBUG_COMMAND;
if (info->is_jtag) {
cmd[1] = STLINK_DEBUG_APIV2_JTAG_SET_FREQ;
/* V2_CLOCK_RATE / (4, 8, 16, ... 256)*/
int div = (V2_CLOCK_RATE + (2 * freq) - 1) / (2 * freq);
if (div & (div -1)) {/* Round up */
int clz = __builtin_clz(div);
divisor = 1 << (32 - clz);
} else
divisor = div;
if (divisor < 4)
divisor = 4;
else if (divisor > 256)
divisor = 256;
} else {
cmd[1] = STLINK_DEBUG_APIV2_SWD_SET_FREQ;
divisor = V2_CLOCK_RATE + freq - 1;
divisor /= freq;
divisor -= V2_USED_SWD_CYCLES;
if (divisor < 0)
divisor = 0;
divisor /= V2_CYCLES_PER_CNT;
}
DEBUG_WARN("Divisor for %6.4f MHz is %" PRIu32 "\n",
freq/1000000.0, divisor);
cmd[2] = divisor & 0xff;
cmd[3] = (divisor >> 8) & 0xff;
uint8_t data[2];
send_recv(info->usb_link, cmd, 16, data, 2);
if (stlink_usb_error_check(data, false))
DEBUG_WARN("Set frequency failed!\n");
}
}
uint32_t stlink_max_frequency_get(bmp_info_t *info)
{
uint32_t ret = 0;
if (Stlink.ver_hw == 30) {
ret = v3_freq[(info->is_jtag) ? STLINK_MODE_JTAG : STLINK_MODE_SWD];
} else {
ret = V2_CLOCK_RATE;
if (info->is_jtag)
ret /= (2 * divisor);
else
ret /= (V2_USED_SWD_CYCLES + (V2_CYCLES_PER_CNT * divisor));
}
return ret;
}

View File

@ -24,16 +24,34 @@
#define STLINK_DEBUG_PORT_ACCESS 0xffff
#if HOSTED_BMP_ONLY == 1
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wunused-parameter"
int stlink_init(bmp_info_t *info) {return -1;};
int stlink_hwversion(void) {return -1;};
const char *stlink_target_voltage(bmp_info_t *info) {return "ERROR";};
void stlink_srst_set_val(bmp_info_t *info, bool assert) {};
bool stlink_srst_get_val(void) {return true;};
int stlink_enter_debug_swd(bmp_info_t *info, ADIv5_DP_t *dp) {return -1;};
void stlink_adiv5_dp_defaults(ADIv5_DP_t *dp) {};
int stlink_jtag_dp_init(ADIv5_DP_t *dp) {return false;};
int jtag_scan_stlinkv2(bmp_info_t *info, const uint8_t *irlens) {return 0;};
void stlink_exit_function(bmp_info_t *info) {};
void stlink_max_frequency_set(bmp_info_t *info, uint32_t freq) {};
uint32_t stlink_max_frequency_get(bmp_info_t *info) {return 0;};
# pragma GCC diagnostic pop
#else
int stlink_init(bmp_info_t *info);
int stlink_hwversion(void);
const char *stlink_target_voltage(bmp_info_t *info);
void stlink_srst_set_val(bmp_info_t *info, bool assert);
bool stlink_srst_get_val(void);
int stlink_enter_debug_swd(bmp_info_t *info, ADIv5_DP_t *dp);
const char *stlink_target_voltage(bmp_info_t *info);
void stlink_adiv5_dp_defaults(ADIv5_DP_t *dp);
int stlink_jtag_dp_init(ADIv5_DP_t *dp);
int jtag_scan_stlinkv2(bmp_info_t *info, const uint8_t *irlens);
void stlink_exit_function(bmp_info_t *info);
void stlink_max_frequency_set(bmp_info_t *info, uint32_t freq);
uint32_t stlink_max_frequency_get(bmp_info_t *info);
#endif
#endif

View File

@ -4,8 +4,8 @@ OBJCOPY = $(CROSS_COMPILE)objcopy
CFLAGS += -Istm32/include -mcpu=cortex-m4 -mthumb \
-mfloat-abi=hard -mfpu=fpv4-sp-d16 \
-DSTM32F4 -DHYDRABUS -I../libopencm3/include \
-Iplatforms/stm32
-DSTM32F4 -I../libopencm3/include \
-Iplatforms/stm32 -DDFU_SERIAL_LENGTH=9
LDFLAGS = -lopencm3_stm32f4 \
-Wl,-T,platforms/stm32/f4discovery.ld -nostartfiles -lc -lnosys \
@ -27,7 +27,7 @@ all: blackmagic.bin blackmagic.hex
blackmagic.dfu: blackmagic.hex
@echo Creating $@
@python ../scripts/dfu-convert.py -i $< $@
@python3 ../scripts/dfu-convert.py -i $< $@
host_clean:
-$(Q)$(RM) blackmagic.bin blackmagic.hex blackmagic.dfu

View File

@ -27,7 +27,7 @@
#include "usbuart.h"
#include "morse.h"
#include <libopencm3/stm32/f4/rcc.h>
#include <libopencm3/stm32/rcc.h>
#include <libopencm3/cm3/scb.h>
#include <libopencm3/cm3/nvic.h>
#include <libopencm3/stm32/exti.h>

View File

@ -28,14 +28,11 @@
#include "gpio.h"
#include "timing.h"
#include "timing_stm32.h"
#include "version.h"
#include <setjmp.h>
#define PLATFORM_HAS_TRACESWO
#define BOARD_IDENT "Black Magic Probe (HydraBus), (Firmware " FIRMWARE_VERSION ")"
#define BOARD_IDENT_DFU "Black Magic (Upgrade) for HydraBus, (Firmware " FIRMWARE_VERSION ")"
#define DFU_IDENT "Black Magic Firmware Upgrade (HydraBus)"
#define PLATFORM_IDENT " (HydraBus))"
/* Important pin mappings for STM32 implementation:
*
@ -93,47 +90,54 @@
#define SWDIO_MODE_DRIVE() \
gpio_mode_setup(SWDIO_PORT, GPIO_MODE_OUTPUT, \
GPIO_PUPD_NONE, SWDIO_PIN);
#define UART_PIN_SETUP() do { \
gpio_mode_setup(USBUSART_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, \
USBUSART_TX_PIN); \
gpio_set_output_options(USBUSART_PORT, GPIO_OTYPE_PP, \
GPIO_OSPEED_100MHZ, USBUSART_TX_PIN); \
gpio_set_af(USBUSART_PORT, GPIO_AF7, USBUSART_TX_PIN); \
gpio_mode_setup(USBUSART_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, \
USBUSART_RX_PIN); \
gpio_set_output_options(USBUSART_PORT, GPIO_OTYPE_OD, \
GPIO_OSPEED_100MHZ, USBUSART_RX_PIN); \
gpio_set_af(USBUSART_PORT, GPIO_AF7, USBUSART_RX_PIN); \
} while(0)
#define USB_DRIVER stm32f107_usb_driver
#define USB_IRQ NVIC_OTG_FS_IRQ
#define USB_ISR otg_fs_isr
#define USB_ISR(x) otg_fs_isr(x)
/* Interrupt priorities. Low numbers are high priority.
* For now USART1 preempts USB which may spin while buffer is drained.
* TIM3 is used for traceswo capture and must be highest priority.
*/
#define IRQ_PRI_USB (2 << 4)
#define IRQ_PRI_USBUSART (1 << 4)
#define IRQ_PRI_USBUSART_TIM (3 << 4)
#define IRQ_PRI_USB (1 << 4)
#define IRQ_PRI_USBUSART (2 << 4)
#define IRQ_PRI_USBUSART_DMA (2 << 4)
#define IRQ_PRI_TRACE (0 << 4)
#define USBUSART USART1
#define USBUSART_CR1 USART1_CR1
#define USBUSART_DR USART1_DR
#define USBUSART_IRQ NVIC_USART1_IRQ
#define USBUSART_CLK RCC_USART1
#define USBUSART_TX_PORT GPIOA
#define USBUSART_TX_PIN GPIO9
#define USBUSART_RX_PORT GPIOA
#define USBUSART_RX_PIN GPIO10
#define USBUSART_ISR usart1_isr
#define USBUSART_TIM TIM4
#define USBUSART_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM4)
#define USBUSART_TIM_IRQ NVIC_TIM4_IRQ
#define USBUSART_TIM_ISR tim4_isr
#define UART_PIN_SETUP() do { \
gpio_mode_setup(USBUSART_TX_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, \
USBUSART_TX_PIN); \
gpio_mode_setup(USBUSART_RX_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, \
USBUSART_RX_PIN); \
gpio_set_af(USBUSART_TX_PORT, GPIO_AF7, USBUSART_TX_PIN); \
gpio_set_af(USBUSART_RX_PORT, GPIO_AF7, USBUSART_RX_PIN); \
} while(0)
#define USBUSART_PORT GPIOA
#define USBUSART_TX_PIN GPIO9
#define USBUSART_RX_PIN GPIO10
#define USBUSART_ISR(x) usart1_isr(x)
#define USBUSART_DMA_BUS DMA2
#define USBUSART_DMA_CLK RCC_DMA2
#define USBUSART_DMA_TX_CHAN DMA_STREAM7
#define USBUSART_DMA_TX_IRQ NVIC_DMA2_STREAM7_IRQ
#define USBUSART_DMA_TX_ISR(x) dma2_stream7_isr(x)
#define USBUSART_DMA_RX_CHAN DMA_STREAM5
#define USBUSART_DMA_RX_IRQ NVIC_DMA2_STREAM5_IRQ
#define USBUSART_DMA_RX_ISR(x) dma2_stream5_isr(x)
/* For STM32F4 DMA trigger source must be specified */
#define USBUSART_DMA_TRG DMA_SxCR_CHSEL_4
#define TRACE_TIM TIM3
#define TRACE_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM3)
#define TRACE_IRQ NVIC_TIM3_IRQ
#define TRACE_ISR tim3_isr
#define TRACE_ISR(x) tim3_isr(x)
#define gpio_set_val(port, pin, val) do { \
if(val) \
@ -185,4 +189,3 @@ static inline int platform_hwversion(void)
#endif
#endif

View File

@ -0,0 +1,61 @@
CROSS_COMPILE ?= arm-none-eabi-
CC = $(CROSS_COMPILE)gcc
OBJCOPY = $(CROSS_COMPILE)objcopy
OPT_FLAGS := -Os
ifeq ($(ENABLE_DEBUG), 1)
CFLAGS += -DDEBUG_ME
CFLAGS += -DENABLE_DEBUG
endif
ifeq ($(CUSTOM_SER), 1)
CFLAGS += -DCUSTOM_SER
endif
ifeq ($(CONSOLE_NO_AUTO_CRLF), 1)
CFLAGS += -DCONSOLE_NO_AUTO_CRLF
endif
ifeq ($(ENABLE_DEBUG), 1)
CFLAGS += -g3 -ggdb
endif
CFLAGS += -mthumb -mcpu=cortex-m0plus -DDFU_SERIAL_LENGTH=9 \
-DSAMD -DSAMD21E17 -DBLACKMAGIC -I../libopencm3/include \
-Iplatforms/samd -msoft-float -ffunction-sections -fdata-sections -MD
LINKER_SCRIPT="platforms/samd/samd.ld"
LDFLAGS = -mthumb -mcpu=cortex-m0plus -msoft-float -nostartfiles -lc \
$(CPU_FLAGS) -T$(LINKER_SCRIPT) -Wl,--gc-sections \
-L../libopencm3/lib -lopencm3_samd -lnosys -lm -lgcc
ifeq ($(ENABLE_DEBUG), 1)
LDFLAGS += --specs=rdimon.specs
else
LDFLAGS += --specs=nano.specs
endif
VPATH += platforms/samd
SRC += cdcacm.c \
timing.c \
traceswo.o \
usbuart.c \
all: blackmagic_full.bin blackmagic.bin blackmagic_dfu.bin blackmagic_dfu.hex
blackmagic_dfu.bin : OBJCOPY_FLAGS := --pad-to 0x00002000 --gap-fill 0xFF -j .text -j .data
blackmagic_dfu.bin : LINKER_SCRIPT := "platforms/samd/samd_boot.ld"
blackmagic_dfu.elf: usbdfu.o
@echo " LD $@"
$(Q)$(CC) $^ -o $@ $(LDFLAGS)
blackmagic_full.bin: blackmagic_dfu.bin blackmagic.bin
@echo " CAT $@"
$(Q)cp blackmagic.bin jeff-$(shell git describe --tags --always --dirty).bin
$(Q)cat $^ > $@
host_clean:
$(Q)$(RM) -f blackmagic.bin blackmagic_full.bin blackmagic_dfu blackmagic_dfu.bin blackmagic_dfu.hex jeff*.bin

View File

@ -0,0 +1,346 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2018 Flirc Inc.
* Written by Jason Kotzin <jasonkotzin@gmail.com>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "general.h"
#include "gdb_if.h"
#include "cdcacm.h"
#include "usbuart.h"
#include "gdb_packet.h"
#include <libopencm3/sam/d/nvic.h>
#include <libopencm3/sam/d/port.h>
#include <libopencm3/sam/d/gclk.h>
#include <libopencm3/sam/d/pm.h>
#include <libopencm3/sam/d/uart.h>
#include <libopencm3/sam/d/adc.h>
#include <libopencm3/cm3/systick.h>
#include <libopencm3/cm3/scb.h>
#include <libopencm3/sam/d/tc.h>
#include <libopencm3/sam/d/eic.h>
static struct gclk_hw clock = {
.gclk0 = SRC_DFLL48M,
.gclk1 = SRC_OSC8M,
.gclk1_div = 30, /* divide clock for ADC */
.gclk2 = SRC_OSC8M,
.gclk2_div = 100, /* divide clock for TC */
.gclk3 = SRC_DFLL48M,
.gclk4 = SRC_DFLL48M,
.gclk5 = SRC_DFLL48M,
.gclk6 = SRC_DFLL48M,
.gclk7 = SRC_DFLL48M,
};
extern void trace_tick(void);
uint8_t running_status;
static volatile uint32_t time_ms;
uint8_t button_pressed;
uint8_t tpwr_enabled;
void sys_tick_handler(void)
{
if(running_status)
gpio_toggle(LED_PORT, LED_IDLE_RUN);
time_ms += 10;
uart_pop();
}
uint32_t platform_time_ms(void)
{
return time_ms;
}
static void usb_setup(void)
{
/* Enable USB */
INSERTBF(PM_APBBMASK_USB, 1, PM->apbbmask);
/* enable clocking to usb */
set_periph_clk(GCLK0, GCLK_ID_USB);
periph_clk_en(GCLK_ID_USB, 1);
gpio_config_special(PORTA, GPIO24, SOC_GPIO_PERIPH_G);
gpio_config_special(PORTA, GPIO25, SOC_GPIO_PERIPH_G);
}
static uint32_t timing_init(void)
{
uint32_t cal = 0;
systick_set_clocksource(STK_CSR_CLKSOURCE_AHB);
systick_set_reload(4800); /* Interrupt us at 10 Hz */
systick_interrupt_enable();
systick_counter_enable();
return cal;
}
static void adc_init(void)
{
gpio_config_special(ADC_PORT, ADC_POS_PIN, SOC_GPIO_PERIPH_B); /* +input */
gpio_config_special(ADC_PORT, ADC_REF_PIN, SOC_GPIO_PERIPH_B); /* reference */
set_periph_clk(GCLK1, GCLK_ID_ADC);
periph_clk_en(GCLK_ID_ADC, 1);
adc_enable(ADC_REFCTRL_VREFA,0,ADC_INPUTCTRL_GND,ADC_MUXPOS);
}
static void counter_init(void)
{
/* enable bus and clock */
INSERTBF(PM_APBCMASK_TC3, 1, PM->apbcmask);
set_periph_clk(GCLK2, GCLK_ID_TC3);
periph_clk_en(GCLK_ID_TC3, 1);
/* reset */
tc_reset(3);
/* set CTRLA.PRESCALER and CTRLA.PRESYNC */
tc_config_ctrla(3,1,(7<<8));
/* set CC0 (approx. 5 seconds delay) */
tc_set_cc(3,0,1000);
/* enable MC0 interrupt */
tc_enable_interrupt(3,(1<<4));
nvic_enable_irq(NVIC_TC3_IRQ);
}
static void button_init(void)
{
gpio_config_special(BUTTON_PORT, BUTTON_PIN, SOC_GPIO_PERIPH_A);
/* enable bus and clock */
INSERTBF(PM_APBAMASK_EIC, 1, PM->apbamask);
set_periph_clk(GCLK0, GCLK_ID_EIC);
periph_clk_en(GCLK_ID_EIC, 1);
/* configure r/f edge, enable filtering */
eic_set_config(15, 1, EIC_FALL);
/* enable the IEC */
eic_enable(1);
/* enable interrupts */
eic_enable_interrupt((1<<15));
nvic_enable_irq(NVIC_EIC_IRQ);
}
void platform_init(void)
{
gclk_init(&clock);
usb_setup();
gpio_config_output(LED_PORT, LED_IDLE_RUN, 0);
gpio_config_output(TMS_PORT, TMS_PIN, 0);
gpio_config_output(TCK_PORT, TCK_PIN, 0);
gpio_config_output(TDI_PORT, TDI_PIN, 0);
gpio_config_output(TMS_PORT, TMS_DIR_PIN, 0);
gpio_set(TMS_PORT, TMS_DIR_PIN);
/* enable both input and output with pullup disabled by default */
PORT_DIRSET(SWDIO_PORT) = SWDIO_PIN;
PORT_PINCFG(SWDIO_PORT, SWDIO_PIN_NUM) |= GPIO_PINCFG_INEN | GPIO_PINCFG_PULLEN;
gpio_clear(SWDIO_PORT, SWDIO_PIN);
/* configure swclk_pin as output */
gpio_config_output(SWCLK_PORT, SWCLK_PIN, 0);
gpio_clear(SWCLK_PORT, SWCLK_PIN);
gpio_config_input(TDO_PORT, TDO_PIN, 0);
gpio_config_output(SRST_PORT, SRST_PIN, GPIO_OUT_FLAG_DEFAULT_HIGH);
gpio_clear(SRST_PORT, SRST_PIN);
/* setup uart led, disable by default*/
gpio_config_output(LED_PORT_UART, LED_UART, 0);//GPIO_OUT_FLAG_DEFAULT_HIGH);
gpio_clear(LED_PORT_UART, LED_UART);
/* set up TPWR */
gpio_set(PWR_BR_PORT, PWR_BR_PIN);
gpio_config_output(PWR_BR_PORT, PWR_BR_PIN, GPIO_OUT_FLAG_DEFAULT_HIGH);
timing_init();
usbuart_init();
cdcacm_init();
adc_init();
counter_init();
button_init();
}
uint8_t srst_state;
void platform_srst_set_val(bool assert)
{
volatile int i;
if (!assert) {
gpio_clear(SRST_PORT, SRST_PIN);
for(i = 0; i < 10000; i++) asm("nop");
srst_state = 0;
} else {
gpio_set(SRST_PORT, SRST_PIN);
srst_state = 1;
}
}
bool platform_srst_get_val(void)
{
//return gpio_get(SRST_PORT, SRST_PIN) != 0;
return srst_state;
}
bool platform_target_get_power(void)
{
//return !gpio_get(PWR_BR_PORT, PWR_BR_PIN);
return tpwr_enabled;
}
void platform_target_set_power(bool power)
{
gpio_set_val(PWR_BR_PORT, PWR_BR_PIN, !power);
tpwr_enabled = power;
}
void platform_delay(uint32_t ms)
{
platform_timeout timeout;
platform_timeout_set(&timeout, ms);
while (!platform_timeout_is_expired(&timeout));
}
uint32_t platform_target_voltage_sense(void)
{
uint32_t val;
adc_start();
while (!(1&(ADC->intflag)));
val = ((485*adc_result())>>12); /* 330 without divider, 485 with it */
return val;
}
const char *platform_target_voltage(void)
{
uint32_t voltage;
static char out[] = "0.0V";
adc_start();
voltage = platform_target_voltage_sense();
out[0] = '0' + (char)(voltage/100);
out[2] = '0' + (char)((voltage/10) % 10);
return out;
}
char *serial_no_read(char *s)
{
#ifdef CUSTOM_SER
s[0] = 'J';
s[1] = 'E';
s[2] = 'F';
s[3] = 'F';
return s;
#else
int i;
volatile uint32_t unique_id = *(volatile uint32_t *)0x0080A00C +
*(volatile uint32_t *)0x0080A040 +
*(volatile uint32_t *)0x0080A044 +
*(volatile uint32_t *)0x0080A048;
/* Fetch serial number from chip's unique ID */
for(i = 0; i < 8; i++) {
s[7-i] = ((unique_id >> (4*i)) & 0xF) + '0';
}
for(i = 0; i < 8; i++)
if(s[i] > '9')
s[i] += 'A' - '9' - 1;
s[8] = 0;
return s;
#endif
}
void print_serial(void)
{
gdb_outf("0x%08X%08X%08X%08X\n", *(volatile uint32_t *)0x0080A048,
*(volatile uint32_t *)0x0080A044,
*(volatile uint32_t *)0x0080A040,
*(volatile uint32_t *)0x0080A00C);
}
void platform_request_boot(void)
{
}
void eic_isr(void)
{
if (!button_pressed){
/* set to rising-edge detection */
eic_set_config(15, 1, EIC_RISE);
/* enable counter */
tc_enable(3,1);
button_pressed = 1;
} else {
/* set to falling-edge detection */
eic_set_config(15, 1, EIC_FALL);
/* disable and reset counter */
tc_enable(3,0);
button_pressed = 0;
}
/* clear the interrupt */
eic_clr_interrupt((1<<15));
}
void tc3_isr(void)
{
if (tc_interrupt_flag(3) & 16)
scb_reset_system();
}
uint32_t swd_delay_cnt = 0;
void platform_max_frequency_set(uint32_t freq)
{
(void)freq;
}
uint32_t platform_max_frequency_get(void)
{
return 0;
}

View File

@ -0,0 +1,227 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2018 Flirc Inc.
* Written by Jason Kotzin <jasonkotzin@gmail.com>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __PLATFORM_H
#define __PLATFORM_H
#include <libopencm3/sam/d/port.h>
#include <libopencm3/usb/usbd.h>
#include <libopencm3/cm3/scb.h>
#include <libopencm3/sam/d/nvmctrl.h>
#include "timing.h"
#include "version.h"
//#define PLATFORM_HAS_DEBUG
//#define USBUART_DEBUG
#define PLATFORM_HAS_UART_WHEN_SWDP
#define PLATFORM_HAS_POWER_SWITCH
#define PLATFORM_HAS_BOOTLOADER
#define PLATFORM_HAS_PRINTSERIAL
//#define BOARD_IDENT "Black Magic Probe (SAMD), (Firmware " FIRMWARE_VERSION ")"
#define BOARD_IDENT_DFU "Black Magic (Upgrade) for Launchpad, (Firmware " FIRMWARE_VERSION ")"
//#define DFU_IDENT "Black Magic Firmware Upgrade (SAMD)"
#define DFU_IFACE_STRING "hid"
#define BOARD_IDENT_UPD "Black Magic (DFU Upgrade), SAMD21, (Firmware " FIRMWARE_VERSION ")"
#define UPD_IFACE_STRING "@Internal Flash /0x00000000/1*008Ka,15*8Kg"
#define PLATFORM_IDENT " "
extern uint8_t running_status;
extern uint32_t swd_delay_cnt;
#ifdef DEBUG_ME
#define LED_PORT PORTA
#define LED_IDLE_RUN GPIO11
#define LED_ERROR GPIO10
#define TMS_PORT PORTA
#define TMS_PIN GPIO1
#define TMS_DIR_PIN GPIO5
#define TCK_PORT PORTA
#define TCK_PIN GPIO2
#define TDI_PORT PORTA
#define TDI_PIN GPIO16
#define TDO_PORT PORTA
#define TDO_PIN GPIO19
#define SWO_PORT PORTA
#define SWO_PIN GPIO6
#define SWDIO_PORT PORTA
#define SWDIO_PIN TMS_PIN
#define SWDIO_PIN_NUM 1
#define SWCLK_PORT PORTA
#define SWCLK_PIN TCK_PIN
#define SRST_PORT PORTA
#define SRST_PIN GPIO7
#define LED_PORT_UART PORTA
#define LED_UART GPIO12
#define UART_TX_PIN GPIO8
#define UART_RX_PIN GPIO9
#define UART_PERIPH SOC_GPIO_PERIPH_C
#define UART_PERIPH_2 SOC_GPIO_PERIPH_C
#define ADC_PORT PORTA
#define ADC_REF_PIN GPIO3
#define ADC_POS_PIN GPIO4
#define ADC_MUXPOS 4
#define BUTTON_PORT PORTA
#define BUTTON_PIN GPIO27
#else
/* Hardware definitions... */
#define JTAG_PORT PORTA
#define TDI_PORT JTAG_PORT
#define TMS_DIR_PORT JTAG_PORT
#define TMS_PORT JTAG_PORT
#define TCK_PORT JTAG_PORT
#define TDO_PORT JTAG_PORT
#define TMS_DIR_PIN GPIO15
#define TMS_PIN GPIO0
#define TCK_PIN GPIO6
#define TDI_PIN GPIO16
#define TDO_PIN GPIO19
#define SWDIO_DIR_PORT JTAG_PORT
#define SWDIO_PORT JTAG_PORT
#define SWCLK_PORT JTAG_PORT
#define SWDIO_DIR_PIN TMS_DIR_PIN
#define SWDIO_PIN TMS_PIN
#define SWDIO_PIN_NUM 0
#define SWCLK_PIN TCK_PIN
#define TRST_PORT PORTA
#define TRST_PIN GPIO27
#define PWR_BR_PORT PORTA
#define PWR_BR_PIN GPIO28
#define SRST_PORT PORTA
#define SRST_PIN GPIO8
#define SRST_SENSE_PORT GPIOA
#define SRST_SENSE_PIN GPIO9
#define TRGT_SENSE GPIO2
#define LED_PORT PORTA
#define LED_PORT_UART PORTA
#define LED_0 GPIO10
#define LED_1 GPIO11
#define LED_2 GPIO14
//#define LED_2 GPIO13
#define LED_UART LED_1 /* Orange */
#define LED_IDLE_RUN LED_0 /* Yellow */
#define LED_ERROR LED_2 /* Red */
#define UART_TX_PIN GPIO4
#define UART_RX_PIN GPIO7
#define UART_PERIPH SOC_GPIO_PERIPH_D
#define UART_PERIPH_2 SOC_GPIO_PERIPH_C
#define SWO_PORT JTAG_PORT
#define SWO_PIN SWD_PIN
#define ADC_PORT PORTA
#define ADC_REF_PIN GPIO3
#define ADC_POS_PIN GPIO2
#define ADC_MUXPOS 0
#define BUTTON_PORT PORTA
#define BUTTON_PIN GPIO27
#endif
#define TMS_SET_MODE() { \
gpio_config_output(TMS_PORT, TMS_PIN, 0); \
gpio_set(TMS_PORT, TMS_DIR_PIN); \
}
#define SWDIO_MODE_FLOAT() do { \
PORT_DIRCLR(SWDIO_PORT) = SWDIO_PIN; \
gpio_set(SWDIO_PORT, SWDIO_PIN); \
gpio_clear(TMS_PORT, TMS_DIR_PIN); \
} while(0)
#define SWDIO_MODE_DRIVE() do { \
PORT_DIRSET(SWDIO_PORT) = SWDIO_PIN; \
gpio_set(TMS_PORT, TMS_DIR_PIN); \
} while(0)
/* extern usbd_driver samd21_usb_driver; */
#define USB_DRIVER samd21_usb_driver
#define USB_IRQ NVIC_USB_IRQ
#define USB_ISR usb_isr
#define IRQ_PRI_USB (2 << 4)
#define INLINE_GPIO
#define gpio_set_val(port, pin, val) do { \
if(val) \
_gpio_set((port), (pin)); \
else \
_gpio_clear((port), (pin)); \
} while(0)
#ifdef INLINE_GPIO
static inline void _gpio_set(uint32_t gpioport, uint32_t gpios)
{
PORT_OUTSET(gpioport) = gpios;
}
#define gpio_set _gpio_set
static inline void _gpio_clear(uint32_t gpioport, uint32_t gpios)
{
PORT_OUTCLR(gpioport) = gpios;
}
#define gpio_clear _gpio_clear
static inline uint16_t _gpio_get(uint32_t gpioport, uint32_t gpios)
{
return (uint32_t)PORT_IN(gpioport) & gpios;
}
#define gpio_get _gpio_get
#endif
#define DEBUG(...)
#define SET_RUN_STATE(state) {running_status = (state);}
#define SET_IDLE_STATE(state) {gpio_set_val(LED_PORT, LED_IDLE_RUN, state);}
#define SET_ERROR_STATE(state) {gpio_set_val(LED_PORT, LED_ERROR, state);}
static inline int platform_hwversion(void)
{
return 0;
}
void uart_pop(void);
int usbuart_convert_tdio(uint32_t arg);
int usbuart_convert_tdio_enabled(void);
void print_serial(void);
#endif

351
src/platforms/jeff/usbdfu.c Normal file
View File

@ -0,0 +1,351 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2010 Gareth McMullin <gareth@blacksphere.co.nz>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include <libopencm3/sam/d/gclk.h>
#include <libopencm3/sam/d/port.h>
#include <libopencm3/sam/d/nvmctrl.h>
#include <libopencm3/cm3/scb.h>
#include <libopencm3/usb/usbd.h>
#include <libopencm3/usb/dfu.h>
#include <libopencm3/sam/d/nvic.h>
#include <libopencm3/sam/d/pm.h>
#include <libopencm3/sam/d/bitfield.h>
#include <libopencm3/sam/d/usb.h>
//#define APP_ADDRESS 0x08002000
//#define APP_ADDRESS 0x00002000
#define APP_ADDRESS 0x00002000
//#define APP_ADDRESS 0x00004000
/* Commands sent with wBlockNum == 0 as per ST implementation. */
#define CMD_SETADDR 0x21
#define CMD_ERASE 0x41
#define BUTTON_PORT PORTA
#define BUTTON_PIN GPIO27
#define BUF_SIZE 4096
static struct gclk_hw clock = {
.gclk0 = SRC_DFLL48M,
.gclk1 = SRC_OSC8M,
/* clock 1 has 8 divider, clock should be over 1khz for 1ms timer */
.gclk1_div = 100,
.gclk2 = SRC_DFLL48M,
.gclk3 = SRC_DFLL48M,
.gclk3_div = 1,
.gclk4 = SRC_OSC8M,
.gclk4_div = 1,
.gclk5 = SRC_DFLL48M,
.gclk6 = SRC_DFLL48M,
.gclk7 = SRC_DFLL48M,
};
/* We need a special large control buffer for this device: */
uint8_t usbd_control_buffer[BUF_SIZE];
static enum dfu_state usbdfu_state = STATE_DFU_IDLE;
static struct {
uint8_t buf[sizeof(usbd_control_buffer)];
uint16_t len;
uint32_t addr;
uint16_t blocknum;
} prog;
const struct usb_device_descriptor dev = {
.bLength = USB_DT_DEVICE_SIZE,
.bDescriptorType = USB_DT_DEVICE,
.bcdUSB = 0x0200,
.bDeviceClass = 0,
.bDeviceSubClass = 0,
.bDeviceProtocol = 0,
.bMaxPacketSize0 = 64,
.idVendor = 0x1D50,
.idProduct = 0x6017,
.bcdDevice = 0x0200,
.iManufacturer = 1,
.iProduct = 2,
.iSerialNumber = 3,
.bNumConfigurations = 1,
};
const struct usb_dfu_descriptor dfu_function = {
.bLength = sizeof(struct usb_dfu_descriptor),
.bDescriptorType = DFU_FUNCTIONAL,
.bmAttributes = USB_DFU_CAN_DOWNLOAD | USB_DFU_WILL_DETACH,
.wDetachTimeout = 255,
.wTransferSize = BUF_SIZE,
.bcdDFUVersion = 0x011A,
};
const struct usb_interface_descriptor iface = {
.bLength = USB_DT_INTERFACE_SIZE,
.bDescriptorType = USB_DT_INTERFACE,
.bInterfaceNumber = 0,
.bAlternateSetting = 0,
.bNumEndpoints = 0,
.bInterfaceClass = 0xFE, /* Device Firmware Upgrade */
.bInterfaceSubClass = 1,
.bInterfaceProtocol = 2,
/* The ST Microelectronics DfuSe application needs this string.
* The format isn't documented... */
.iInterface = 4,
.extra = &dfu_function,
.extralen = sizeof(dfu_function),
};
const struct usb_interface ifaces[] = {{
.num_altsetting = 1,
.altsetting = &iface,
}};
const struct usb_config_descriptor config = {
.bLength = USB_DT_CONFIGURATION_SIZE,
.bDescriptorType = USB_DT_CONFIGURATION,
.wTotalLength = 0,
.bNumInterfaces = 1,
.bConfigurationValue = 1,
.iConfiguration = 0,
.bmAttributes = 0xC0,
.bMaxPower = 0x32,
.interface = ifaces,
};
static const char *usb_strings[] = {
"Black Sphere Technologies",
"DFU Demo",
"DEMO",
/* This string is used by ST Microelectronics' DfuSe utility. */
//"@Internal Flash /0x08000000/8*001Ka,56*001Kg",
"@Internal Flash /0x00000000/1*008Ka,15*008Kg",
//"@Internal Flash /0x00000000/1*0016Ka,15*0016Kg",
};
static uint8_t usbdfu_getstatus(uint32_t *bwPollTimeout)
{
switch (usbdfu_state) {
case STATE_DFU_DNLOAD_SYNC:
usbdfu_state = STATE_DFU_DNBUSY;
*bwPollTimeout = 100;
return DFU_STATUS_OK;
case STATE_DFU_MANIFEST_SYNC:
/* Device will reset when read is complete. */
usbdfu_state = STATE_DFU_MANIFEST;
return DFU_STATUS_OK;
default:
return DFU_STATUS_OK;
}
}
static void usbdfu_getstatus_complete(usbd_device *usbd_dev, struct usb_setup_data *req)
{
int i;
(void)req;
(void)usbd_dev;
switch (usbdfu_state) {
case STATE_DFU_DNBUSY:
//flash_unlock();
if (prog.blocknum == 0) {
switch (prog.buf[0]) {
case CMD_ERASE:
{
uint32_t *dat = (uint32_t *)(prog.buf + 1);
nvmctrl_erase_row(*dat); //flash_erase_page(*dat);
}
break;
case CMD_SETADDR:
{
uint32_t *dat = (uint32_t *)(prog.buf + 1);
prog.addr = *dat;
}
break;
}
} else {
//uint32_t baseaddr = prog.addr + ((prog.blocknum - 2) *
// dfu_function.wTransferSize);
uint32_t baseaddr = prog.addr;
//for (i = 0; i < prog.len; i += 2) {
//uint16_t *dat = (uint16_t *)(prog.buf + i);
//flash_program_half_word(baseaddr + i,
// *dat);
for (i = 0; i < BUF_SIZE; i += 256){
nvmctrl_erase_row(baseaddr+i);
nvmctrl_write_row(baseaddr+i, prog.buf+i);
}
//}
}
//flash_lock();
/* Jump straight to dfuDNLOAD-IDLE, skipping dfuDNLOAD-SYNC. */
usbdfu_state = STATE_DFU_DNLOAD_IDLE;
return;
case STATE_DFU_MANIFEST:
/* reset USB */
INSERTBF(USB_CTRLA_SWRST, 1, USB->ctrla);
/* jump to app */
if ((*(volatile uint32_t *)APP_ADDRESS & 0x2FFE0000) == 0x20000000) {
/* Set vector table base address. */
//SCB_VTOR = APP_ADDRESS & 0xFFFF;
SCB_VTOR = APP_ADDRESS;
/* Initialise master stack pointer. */
asm volatile("msr msp, %0"::"g"
(*(volatile uint32_t *)APP_ADDRESS));
/* Jump to application. */
(*(void (**)())(APP_ADDRESS + 4))();
}
//scb_reset_system();
return; /* Will never return. */
default:
return;
}
}
static enum usbd_request_return_codes usbdfu_control_request(usbd_device *dev,
struct usb_setup_data *req, uint8_t **buf, uint16_t *len,
void (**complete)(usbd_device *dev, struct usb_setup_data *req))
{
(void)dev;
if ((req->bmRequestType & 0x7F) != 0x21)
return 0; /* Only accept class request. */
switch (req->bRequest) {
case DFU_DNLOAD:
if ((len == NULL) || (*len == 0)) {
usbdfu_state = STATE_DFU_MANIFEST_SYNC;
return 1;
} else {
/* Copy download data for use on GET_STATUS. */
prog.blocknum = req->wValue;
prog.len = *len;
memcpy(prog.buf, *buf, *len);
usbdfu_state = STATE_DFU_DNLOAD_SYNC;
return 1;
}
case DFU_CLRSTATUS:
/* Clear error and return to dfuIDLE. */
if (usbdfu_state == STATE_DFU_ERROR)
usbdfu_state = STATE_DFU_IDLE;
return 1;
case DFU_ABORT:
/* Abort returns to dfuIDLE state. */
usbdfu_state = STATE_DFU_IDLE;
return 1;
case DFU_UPLOAD:
/* Upload not supported for now. */
return 0;
case DFU_GETSTATUS: {
uint32_t bwPollTimeout = 0; /* 24-bit integer in DFU class spec */
(*buf)[0] = usbdfu_getstatus(&bwPollTimeout);
(*buf)[1] = bwPollTimeout & 0xFF;
(*buf)[2] = (bwPollTimeout >> 8) & 0xFF;
(*buf)[3] = (bwPollTimeout >> 16) & 0xFF;
(*buf)[4] = usbdfu_state;
(*buf)[5] = 0; /* iString not used here */
*len = 6;
*complete = usbdfu_getstatus_complete;
return 1;
}
case DFU_GETSTATE:
/* Return state with no state transision. */
*buf[0] = usbdfu_state;
*len = 1;
return 1;
}
return 0;
}
static void usbdfu_set_config(usbd_device *usbd_dev, uint16_t wValue)
{
(void)wValue;
usbd_register_control_callback(
usbd_dev,
USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE,
USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT,
usbdfu_control_request);
}
static void usb_setup(void)
{
/* Enable USB */
INSERTBF(PM_APBBMASK_USB, 1, PM->apbbmask);
/* enable clocking to usb */
set_periph_clk(GCLK0, GCLK_ID_USB);
periph_clk_en(GCLK_ID_USB, 1);
gpio_config_special(PORTA, GPIO24, SOC_GPIO_PERIPH_G);
gpio_config_special(PORTA, GPIO25, SOC_GPIO_PERIPH_G);
}
int main(void)
{
usbd_device *usbd_dev;
gclk_init(&clock);
//rcc_periph_clock_enable(RCC_GPIOA);
//gpio_config_input(BUTTON_PORT,BUTTON_PIN,GPIO_IN_FLAG_PULLUP);
gpio_config_input(BUTTON_PORT,BUTTON_PIN,0);
nvmctrl_init(0,0);
usb_setup();
if (PM->rcause != (1<<6))
if (gpio_get(BUTTON_PORT, BUTTON_PIN)) {
//if (gpio_get(PORTA, GPIO27)) {
/* Boot the application if it's valid. */
if ((*(volatile uint32_t *)APP_ADDRESS & 0x2FFE0000) == 0x20000000) {
/* Set vector table base address. */
//SCB_VTOR = APP_ADDRESS & 0xFFFF;
SCB_VTOR = APP_ADDRESS;
/* Initialise master stack pointer. */
asm volatile("msr msp, %0"::"g"
(*(volatile uint32_t *)APP_ADDRESS));
/* Jump to application. */
(*(void (**)())(APP_ADDRESS + 4))();
}
}
usbd_dev = usbd_init(&samd21_usb_driver, &dev, &config, usb_strings, 4, usbd_control_buffer, sizeof(usbd_control_buffer));
usbd_register_set_config_callback(usbd_dev, usbdfu_set_config);
//nvic_enable_irq(NVIC_USB_IRQ);
/* Connect USB cable */
usbd_disconnect(usbd_dev, false);
//gpio_clear(GPIOC, GPIO11);
while (1)
usbd_poll(usbd_dev);
}

View File

@ -1,11 +1,13 @@
CROSS_COMPILE ?= arm-none-eabi-
SERIAL_NO ?= 1
CC = $(CROSS_COMPILE)gcc
OBJCOPY = $(CROSS_COMPILE)objcopy
INCLUDES = -I../libopencm3/include
CPU_FLAGS = -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard
CFLAGS += $(INCLUDES) $(CPU_FLAGS) -DTARGET_IS_BLIZZARD_RB1 -DLM4F -DPART_TM4C123GH6PM
CFLAGS += $(INCLUDES) $(CPU_FLAGS) -DSERIAL_NO=$(SERIAL_NO) -DTARGET_IS_BLIZZARD_RB1 -DLM4F -DPART_TM4C123GH6PM
CFLAGS += -DDFU_SERIAL_LENGTH=9
LINKER_SCRIPT="platforms/tm4c/tm4c.ld"
LDFLAGS = -nostartfiles -lc $(CPU_FLAGS) -nodefaultlibs -T$(LINKER_SCRIPT) -Wl,--gc-sections \

View File

@ -25,9 +25,6 @@
#include <libopencm3/cm3/systick.h>
#include <libopencm3/lm4f/usb.h>
#define SYSTICKHZ 100
#define SYSTICKMS (1000 / SYSTICKHZ)
#define PLL_DIV_80MHZ 5
#define PLL_DIV_25MHZ 16
@ -37,6 +34,8 @@ volatile platform_timeout * volatile head_timeout;
uint8_t running_status;
static volatile uint32_t time_ms;
uint32_t swd_delay_cnt = 0;
void sys_tick_handler(void)
{
trace_tick();
@ -118,20 +117,20 @@ const char *platform_target_voltage(void)
return NULL;
}
char *serialno_read(char *s)
char *serial_no_read(char *s)
{
/* FIXME: Store a unique serial number somewhere and retreive here */
uint32_t unique_id = 1;
uint32_t unique_id = SERIAL_NO;
int i;
/* Fetch serial number from chip's unique ID */
for(i = 0; i < 8; i++) {
s[7-i] = ((unique_id >> (4*i)) & 0xF) + '0';
}
for(i = 0; i < 8; i++)
for(i = 0; i < DFU_SERIAL_LENGTH - 1; i++)
if(s[i] > '9')
s[i] += 'A' - '9' - 1;
s[8] = 0;
s[DFU_SERIAL_LENGTH - 1] = 0;
return s;
}
@ -140,3 +139,12 @@ void platform_request_boot(void)
{
}
void platform_max_frequency_set(uint32_t freq)
{
(void)freq;
}
uint32_t platform_max_frequency_get(void)
{
return 0;
}

View File

@ -21,14 +21,11 @@
#include <libopencm3/usb/usbd.h>
#include "timing.h"
#include "version.h"
#define BOARD_IDENT "Black Magic Probe (Launchpad ICDI), (Firmware " FIRMWARE_VERSION ")"
#define BOARD_IDENT_DFU "Black Magic (Upgrade) for Launchpad, (Firmware " FIRMWARE_VERSION ")"
#define DFU_IDENT "Black Magic Firmware Upgrade (Launchpad)"
#define DFU_IFACE_STRING "lolwut"
#define PLATFORM_IDENT "(Launchpad ICDI) "
extern uint8_t running_status;
extern uint32_t swd_delay_cnt;
#define TMS_PORT GPIOA_BASE
#define TMS_PIN GPIO3

View File

@ -4,7 +4,7 @@ OBJCOPY = $(CROSS_COMPILE)objcopy
CFLAGS += -Istm32/include -mcpu=cortex-m3 -mthumb \
-DSTM32F1 -DBLACKMAGIC -I../libopencm3/include \
-Iplatforms/stm32
-Iplatforms/stm32 -DDFU_SERIAL_LENGTH=9
LDFLAGS_BOOT := $(LDFLAGS) --specs=nano.specs -lopencm3_stm32f1 \
-Wl,-T,platforms/stm32/blackmagic.ld -nostartfiles -lc \
@ -30,7 +30,7 @@ SRC += cdcacm.c \
all: blackmagic.bin blackmagic_dfu.bin blackmagic_dfu.hex
blackmagic_dfu.elf: usbdfu.o dfucore.o dfu_f1.o
blackmagic_dfu.elf: usbdfu.o dfucore.o dfu_f1.o serialno.o
@echo " LD $@"
$(Q)$(CC) $^ -o $@ $(LDFLAGS_BOOT)

View File

@ -27,22 +27,50 @@
#include "usbuart.h"
#include "morse.h"
#include <libopencm3/stm32/f1/rcc.h>
#include <libopencm3/stm32/rcc.h>
#include <libopencm3/cm3/scb.h>
#include <libopencm3/cm3/scs.h>
#include <libopencm3/cm3/nvic.h>
#include <libopencm3/stm32/exti.h>
#include <libopencm3/stm32/usart.h>
#include <libopencm3/usb/usbd.h>
#include <libopencm3/stm32/f1/adc.h>
#include <libopencm3/stm32/adc.h>
#include <libopencm3/stm32/flash.h>
static void adc_init(void);
static void setup_vbus_irq(void);
/* Starting with hardware version 4 we are storing the hardware version in the
* flash option user Data1 byte.
* The hardware version 4 was the transition version that had it's hardware
* pins strapped to 3 but contains version 4 in the Data1 byte.
* The hardware 4 is backward compatible with V3 but provides the new jumper
* connecting STRACE target pin to the UART1 pin.
* Hardware version 5 does not have the physically strapped version encoding
* any more and the hardware version has to be read out of the option bytes.
* This means that older firmware versions that don't do the detection won't
* work on the newer hardware.
*/
#define BMP_HWVERSION_BYTE FLASH_OPTION_BYTE_2
/* Pins PB[7:5] are used to detect hardware revision.
* 000 - Original production build.
* 001 - Mini production build.
* 010 - Mini V2.0e and later.
* User option byte Data1 is used starting with hardware revision 4.
* Pin - OByte - Rev - Description
* 000 - 0xFFFF - 0 - Original production build.
* 001 - 0xFFFF - 1 - Mini production build.
* 010 - 0xFFFF - 2 - Mini V2.0e and later.
* 011 - 0xFFFF - 3 - Mini V2.1a and later.
* 011 - 0xFB04 - 4 - Mini V2.1d and later.
* xxx - 0xFB05 - 5 - Mini V2.2a and later.
* xxx - 0xFB06 - 6 - Mini V2.3a and later.
*
* This function will return -2 if the version number does not make sense.
* This can happen when the Data1 byte contains "garbage". For example a
* hardware revision that is <4 or the high byte is not the binary inverse of
* the lower byte.
* Note: The high byte of the Data1 option byte should always be the binary
* inverse of the lower byte unless the byte is not set, then all bits in both
* high and low byte are 0xFF.
*/
int platform_hwversion(void)
{
@ -50,7 +78,26 @@ int platform_hwversion(void)
uint16_t hwversion_pins = GPIO7 | GPIO6 | GPIO5;
uint16_t unused_pins = hwversion_pins ^ 0xFFFF;
/* Only check for version if this is the first time. */
/* Check if the hwversion is set in the user option byte. */
if (hwversion == -1) {
if ((BMP_HWVERSION_BYTE != 0xFFFF) &&
(BMP_HWVERSION_BYTE != 0x00FF)) {
/* Check if the data is valid.
* When valid it should only have values 4 and higher.
*/
if (((BMP_HWVERSION_BYTE >> 8) !=
(~BMP_HWVERSION_BYTE & 0xFF)) ||
((BMP_HWVERSION_BYTE & 0xFF) < 4)) {
return -2;
} else {
hwversion = BMP_HWVERSION_BYTE & 0xFF;
}
}
}
/* If the hwversion is not set in option bytes check
* the hw pin strapping.
*/
if (hwversion == -1) {
/* Configure the hardware version pins as input pull-up/down */
gpio_set_mode(GPIOB, GPIO_MODE_INPUT,
@ -96,7 +143,7 @@ void platform_init(void)
initialise_monitor_handles();
#endif
rcc_clock_setup_in_hse_8mhz_out_72mhz();
rcc_clock_setup_pll(&rcc_hse_configs[RCC_CLOCK_HSE8_72MHZ]);
/* Enable peripherals */
rcc_periph_clock_enable(RCC_USB);
@ -130,10 +177,6 @@ void platform_init(void)
GPIO_CNF_OUTPUT_PUSHPULL,
LED_UART | LED_IDLE_RUN | LED_ERROR);
/* FIXME: This pin in intended to be input, but the TXS0108 fails
* to release the device from reset if this floats. */
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO7);
/* Enable SRST output. Original uses a NPN to pull down, so setting the
* output HIGH asserts. Mini is directly connected so use open drain output
* and set LOW to assert.
@ -145,7 +188,17 @@ void platform_init(void)
? GPIO_CNF_OUTPUT_PUSHPULL
: GPIO_CNF_OUTPUT_OPENDRAIN),
SRST_PIN);
/* FIXME: Gareth, Esden, what versions need this fix? */
if (platform_hwversion() < 3) {
/* FIXME: This pin in intended to be input, but the TXS0108 fails
* to release the device from reset if this floats. */
gpio_set_mode(SRST_SENSE_PORT, GPIO_MODE_OUTPUT_2_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, SRST_SENSE_PIN);
} else {
gpio_set(SRST_SENSE_PORT, SRST_SENSE_PIN);
gpio_set_mode(SRST_SENSE_PORT, GPIO_MODE_INPUT,
GPIO_CNF_INPUT_PULL_UPDOWN, SRST_SENSE_PIN);
}
/* Enable internal pull-up on PWR_BR so that we don't drive
TPWR locally or inadvertently supply power to the target. */
if (platform_hwversion () == 1) {
@ -232,7 +285,7 @@ static void adc_init(void)
adc_set_single_conversion_mode(ADC1);
adc_disable_external_trigger_regular(ADC1);
adc_set_right_aligned(ADC1);
adc_set_sample_time_on_all_channels(ADC1, ADC_SMPR_SMP_28DOT5CYC);
adc_set_sample_time_on_all_channels(ADC1, ADC_SMPR_SMP_239DOT5CYC);
adc_power_on(ADC1);
@ -244,12 +297,16 @@ static void adc_init(void)
adc_calibrate(ADC1);
}
const char *platform_target_voltage(void)
uint32_t platform_target_voltage_sense(void)
{
/* returns the voltage in volt scaled by 10 (so 33 means 3.3V), except
* for hardware version 1
* this function is only needed for implementations that allow the
* target to be powered from the debug probe
*/
if (platform_hwversion() == 0)
return gpio_get(GPIOB, GPIO0) ? "OK" : "ABSENT!";
return 0;
static char ret[] = "0.0V";
const uint8_t channel = 8;
adc_set_regular_sequence(ADC1, 1, (uint8_t*)&channel);
@ -258,9 +315,21 @@ const char *platform_target_voltage(void)
/* Wait for end of conversion. */
while (!adc_eoc(ADC1));
uint32_t val = adc_read_regular(ADC1) * 99; /* 0-4095 */
ret[0] = '0' + val / 81910;
ret[2] = '0' + (val / 8191) % 10;
uint32_t val = adc_read_regular(ADC1); /* 0-4095 */
/* Clear EOC bit. The GD32F103 does not automatically reset it on ADC read. */
ADC_SR(ADC1) &= ~ADC_SR_EOC;
return (val * 99) / 8191;
}
const char *platform_target_voltage(void)
{
if (platform_hwversion() == 0)
return gpio_get(GPIOB, GPIO0) ? "OK" : "ABSENT!";
static char ret[] = "0.0V";
uint32_t val = platform_target_voltage_sense();
ret[0] = '0' + val / 10;
ret[2] = '0' + val % 10;
return ret;
}
@ -278,7 +347,18 @@ void platform_request_boot(void)
void exti15_10_isr(void)
{
if (gpio_get(USB_VBUS_PORT, USB_VBUS_PIN)) {
uint32_t usb_vbus_port;
uint16_t usb_vbus_pin;
if (platform_hwversion() < 5) {
usb_vbus_port = USB_VBUS_PORT;
usb_vbus_pin = USB_VBUS_PIN;
} else {
usb_vbus_port = USB_VBUS5_PORT;
usb_vbus_pin = USB_VBUS5_PIN;
}
if (gpio_get(usb_vbus_port, usb_vbus_pin)) {
/* Drive pull-up high if VBUS connected */
gpio_set_mode(USB_PU_PORT, GPIO_MODE_OUTPUT_10_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, USB_PU_PIN);
@ -288,24 +368,35 @@ void exti15_10_isr(void)
GPIO_CNF_INPUT_FLOAT, USB_PU_PIN);
}
exti_reset_request(USB_VBUS_PIN);
exti_reset_request(usb_vbus_pin);
}
static void setup_vbus_irq(void)
{
uint32_t usb_vbus_port;
uint16_t usb_vbus_pin;
if (platform_hwversion() < 5) {
usb_vbus_port = USB_VBUS_PORT;
usb_vbus_pin = USB_VBUS_PIN;
} else {
usb_vbus_port = USB_VBUS5_PORT;
usb_vbus_pin = USB_VBUS5_PIN;
}
nvic_set_priority(USB_VBUS_IRQ, IRQ_PRI_USB_VBUS);
nvic_enable_irq(USB_VBUS_IRQ);
gpio_set(USB_VBUS_PORT, USB_VBUS_PIN);
gpio_set(usb_vbus_port, usb_vbus_pin);
gpio_set(USB_PU_PORT, USB_PU_PIN);
gpio_set_mode(USB_VBUS_PORT, GPIO_MODE_INPUT,
GPIO_CNF_INPUT_PULL_UPDOWN, USB_VBUS_PIN);
gpio_set_mode(usb_vbus_port, GPIO_MODE_INPUT,
GPIO_CNF_INPUT_PULL_UPDOWN, usb_vbus_pin);
/* Configure EXTI for USB VBUS monitor */
exti_select_source(USB_VBUS_PIN, USB_VBUS_PORT);
exti_set_trigger(USB_VBUS_PIN, EXTI_TRIGGER_BOTH);
exti_enable_request(USB_VBUS_PIN);
exti_select_source(usb_vbus_pin, usb_vbus_port);
exti_set_trigger(usb_vbus_pin, EXTI_TRIGGER_BOTH);
exti_enable_request(usb_vbus_pin);
exti15_10_isr();
}

View File

@ -38,33 +38,69 @@ extern bool debug_bmp;
int usbuart_debug_write(const char *buf, size_t len);
#endif
#define BOARD_IDENT "Black Magic Probe"
#define BOARD_IDENT_DFU "Black Magic Probe (Upgrade)"
#define BOARD_IDENT_UPD "Black Magic Probe (DFU Upgrade)"
#define DFU_IDENT "Black Magic Firmware Upgrade"
#define PLATFORM_IDENT " "
#define UPD_IFACE_STRING "@Internal Flash /0x08000000/8*001Kg"
/* Hardware version switcher helper
* when the hardware version is smaller than ver
* it outputs opt1, otherwise opt2 */
#define HW_SWITCH(ver, opt1, opt2) \
((platform_hwversion() < (ver))?(opt1):(opt2))
/* Important pin mappings for STM32 implementation:
*
* LED0 = PB2 (Yellow LED : Running)
* LED1 = PB10 (Yellow LED : Idle)
* LED2 = PB11 (Red LED : Error)
* LED0 = PB2 (Yellow LED : Running)
* LED1 = PB10 (Orange LED : Idle)
* LED2 = PB11 (Red LED : Error)
*
* TPWR = RB0 (input) -- analogue on mini design ADC1, ch8
* nTRST = PB1 (output) [blackmagic]
* PWR_BR = PB1 (output) [blackmagic_mini] -- supply power to the target, active low
* TMS_DIR = PA1 (output) [blackmagic_mini v2.1] -- choose direction of the TCK pin, input low, output high
* SRST_OUT = PA2 (output)
* TDI = PA3 (output)
* TMS = PA4 (input/output for SWDIO)
* TCK = PA5 (output SWCLK)
* TDO = PA6 (input)
* nSRST = PA7 (input)
* TPWR = PB0 (input) -- analogue on mini design ADC1, CH8
* nTRST = PB1 (output) [blackmagic]
* PWR_BR = PB1 (output) [blackmagic_mini] -- supply power to the target, active low
* TMS_DIR = PA1 (output) [blackmagic_mini v2.1] -- choose direction of the TCK pin, input low, output high
* SRST_OUT = PA2 (output) -- Hardware 5 and older
* = PA9 (output) -- Hardware 6 and newer
* TDI = PA3 (output) -- Hardware 5 and older
* = PA7 (output) -- Hardware 6 and newer
* TMS = PA4 (input/output for SWDIO)
* TCK = PA5 (output SWCLK)
* TDO = PA6 (input)
* TRACESWO = PB7 (input) -- To allow trace decoding using USART1
* Hardware 4 has a normally open jumper between TDO and TRACESWO
* Hardware 5 has hardwired connection between TDO and TRACESWO
* = PA10 (input) -- Hardware 6 and newer
* nSRST = PA7 (input) -- Hardware 5 and older
* = PC13 (input) -- Hardware 6 and newer
*
* USB cable pull-up: PA8
* USB VBUS detect: PB13 -- New on mini design.
* Enable pull up for compatibility.
* Force DFU mode button: PB12
* USB_PU = PA8 (output)
* USB_VBUS = PB13 (input) -- New on mini design.
* Enable pull up for compatibility.
* Hardware 4 and older. (we needed the pin for SPI on 5)
* = PA15 (input) -- Hardware 5 and newer.
* BTN1 = PB12 (input) -- Force DFU bootloader when pressed during powerup.
*
* UART_TX = PA9 (output) -- USART1 Hardware 5 and older
* = PA2 (output) -- USART2 Hardware 6 and newer
* UART_RX = PA10 (input) -- USART1 Hardware 5 and older
* = PA3 (input) -- USART2 Hardware 6 and newer
*
* On Board OTG Flash: -- Optional on Hardware 5 and newer, since Hardware 6 can be on the main board
* FLASH_CS = PB5 (output)
* SCLK = PB13 (output)
* COPI = PB15 (output)
* CIPO = PB14 (input)
*
* AUX Interface: -- Hardware 5 and newer
* SCLK = PB13 (output)
* COPI = PB15 (output)
* CIPO = PB14 (input)
* FLASH_CS = PB5 (output) -- Only Hardware 5
* SD_CS = PB6 (output) -- Hardware 6 and newer
* DISPLAY_CS = PB6 (output) -- OnlyHardware 5
* = PB7 (output) -- Hardware 6 and newer
* DISPLAY_DC = PB8 (output)
* BTN1 = PB12 (input) -- Shared with the DFU bootloader button
* BTN2 = PB9 (input)
* VBAT = PA0 (input) -- Battery voltage sense ADC2, CH0
*/
/* Hardware definitions... */
@ -74,7 +110,7 @@ int usbuart_debug_write(const char *buf, size_t len);
#define TMS_PORT JTAG_PORT
#define TCK_PORT JTAG_PORT
#define TDO_PORT JTAG_PORT
#define TDI_PIN GPIO3
#define TDI_PIN HW_SWITCH(6, GPIO3, GPIO7)
#define TMS_DIR_PIN GPIO1
#define TMS_PIN GPIO4
#define TCK_PIN GPIO5
@ -92,17 +128,23 @@ int usbuart_debug_write(const char *buf, size_t len);
#define PWR_BR_PORT GPIOB
#define PWR_BR_PIN GPIO1
#define SRST_PORT GPIOA
#define SRST_PIN GPIO2
#define SRST_PIN HW_SWITCH(6, GPIO2, GPIO9)
#define SRST_SENSE_PORT GPIOA
#define SRST_SENSE_PIN GPIO7
#define SRST_SENSE_PIN HW_SWITCH(6, GPIO7, GPIO13)
#define USB_PU_PORT GPIOA
#define USB_PU_PIN GPIO8
/* For HW Rev 4 and older */
#define USB_VBUS_PORT GPIOB
#define USB_VBUS_PIN GPIO13
/* IRQ stays the same for all hw revisions. */
#define USB_VBUS_IRQ NVIC_EXTI15_10_IRQ
/* For HW Rev 5 and newer */
#define USB_VBUS5_PORT GPIOA
#define USB_VBUS5_PIN GPIO15
#define LED_PORT GPIOB
#define LED_PORT_UART GPIOB
#define LED_0 GPIO2
@ -112,6 +154,37 @@ int usbuart_debug_write(const char *buf, size_t len);
#define LED_IDLE_RUN LED_1
#define LED_ERROR LED_2
/* OTG Flash HW Rev 5 and newer */
#define OTG_PORT GPIOB
#define OTG_CS GPIO5
#define OTG_SCLK GPIO13
#define OTG_COPI GPIO15
#define OTG_CIPO GPIO14
/* AUX Port HW Rev 5 and newer */
#define AUX_PORT GPIOB
#define AUX_SCLK_PORT AUX_PORT
#define AUX_COPI_PORT AUX_PORT
#define AUX_CIPO_PORT AUX_PORT
#define AUX_FCS_PORT AUX_PORT
#define AUX_SDCS_PORT AUX_PORT
#define AUX_DCS_PORT AUX_PORT
#define AUX_DDC_PORT AUX_PORT
#define AUX_BTN1_PORT AUX_PORT
#define AUX_BTN2_PORT AUX_PORT
#define AUX_VBAT_PORT GPIOA
#define AUX_SCLK GPIO13
#define AUX_COPI GPIO15
#define AUX_CIPO GPIO14
#define AUX_FCS GPIO5
#define AUX_SDCS GPIO6
#define AUX_DCS GPIO6
#define AUX_DCS6 GPIO7
#define AUX_DDC GPIO8
#define AUX_BTN1 GPIO12
#define AUX_BTN2 GPIO9
#define AUX_VBAT GPIO0
# define SWD_CR GPIO_CRL(SWDIO_PORT)
# define SWD_CR_MULT (1 << (4 << 2))
@ -135,39 +208,63 @@ int usbuart_debug_write(const char *buf, size_t len);
SWD_CR = cr; \
} while(0)
#define UART_PIN_SETUP() do { \
gpio_set_mode(USBUSART_PORT, GPIO_MODE_OUTPUT_2_MHZ, \
gpio_set_mode(USBUSART_PORT, GPIO_MODE_OUTPUT_50_MHZ, \
GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, USBUSART_TX_PIN); \
gpio_set_mode(USBUSART_PORT, GPIO_MODE_INPUT, \
GPIO_CNF_INPUT_PULL_UPDOWN, USBUSART_RX_PIN); \
gpio_set(USBUSART_PORT, USBUSART_RX_PIN); \
} while(0)
#define USB_DRIVER st_usbfs_v1_usb_driver
#define USB_IRQ NVIC_USB_LP_CAN_RX0_IRQ
#define USB_ISR usb_lp_can_rx0_isr
#define USB_ISR(x) usb_lp_can_rx0_isr(x)
/* Interrupt priorities. Low numbers are high priority.
* For now USART1 preempts USB which may spin while buffer is drained.
* TIM3 is used for traceswo capture and must be highest priority.
*/
#define IRQ_PRI_USB (2 << 4)
#define IRQ_PRI_USBUSART (1 << 4)
#define IRQ_PRI_USBUSART_TIM (3 << 4)
#define IRQ_PRI_USB (1 << 4)
#define IRQ_PRI_USBUSART (2 << 4)
#define IRQ_PRI_USBUSART_DMA (2 << 4)
#define IRQ_PRI_USB_VBUS (14 << 4)
#define IRQ_PRI_TRACE (0 << 4)
#define USBUSART USART1
#define USBUSART_CR1 USART1_CR1
#define USBUSART_IRQ NVIC_USART1_IRQ
#define USBUSART_CLK RCC_USART1
#define USBUSART HW_SWITCH(6, USBUSART1, USBUSART2)
#define USBUSART_IRQ HW_SWITCH(6, NVIC_USART1_IRQ, NVIC_USART2_IRQ)
#define USBUSART_CLK HW_SWITCH(6, RCC_USART1, RCC_USART2)
#define USBUSART_PORT GPIOA
#define USBUSART_TX_PIN GPIO9
#define USBUSART_ISR usart1_isr
#define USBUSART_TIM TIM4
#define USBUSART_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM4)
#define USBUSART_TIM_IRQ NVIC_TIM4_IRQ
#define USBUSART_TIM_ISR tim4_isr
#define USBUSART_TX_PIN HW_SWITCH(6, GPIO9, GPIO2)
#define USBUSART_RX_PIN HW_SWITCH(6, GPIO10, GPIO3)
#define USBUSART_DMA_BUS DMA1
#define USBUSART_DMA_CLK RCC_DMA1
#define USBUSART_DMA_TX_CHAN HW_SWITCH(6, USBUSART1_DMA_TX_CHAN, USBUSART2_DMA_TX_CHAN)
#define USBUSART_DMA_RX_CHAN HW_SWITCH(6, USBUSART1_DMA_RX_CHAN, USBUSART2_DMA_RX_CHAN)
#define USBUSART_DMA_TX_IRQ HW_SWITCH(6, USBUSART1_DMA_TX_IRQ, USBUSART2_DMA_TX_IRQ)
#define USBUSART_DMA_RX_IRQ HW_SWITCH(6, USBUSART1_DMA_RX_IRQ, USBUSART2_DMA_RX_IRQ)
#define USBUSART1 USART1
#define USBUSART1_IRQ NVIC_USART1_IRQ
#define USBUSART1_ISR(x) usart1_isr(x)
#define USBUSART1_DMA_TX_CHAN DMA_CHANNEL4
#define USBUSART1_DMA_TX_IRQ NVIC_DMA1_CHANNEL4_IRQ
#define USBUSART1_DMA_TX_ISR(x) dma1_channel4_isr(x)
#define USBUSART1_DMA_RX_CHAN DMA_CHANNEL5
#define USBUSART1_DMA_RX_IRQ NVIC_DMA1_CHANNEL5_IRQ
#define USBUSART1_DMA_RX_ISR(x) dma1_channel5_isr(x)
#define USBUSART2 USART2
#define USBUSART2_IRQ NVIC_USART2_IRQ
#define USBUSART2_ISR(x) usart2_isr(x)
#define USBUSART2_DMA_TX_CHAN DMA_CHANNEL7
#define USBUSART2_DMA_TX_IRQ NVIC_DMA1_CHANNEL7_IRQ
#define USBUSART2_DMA_TX_ISR(x) dma1_channel7_isr(x)
#define USBUSART2_DMA_RX_CHAN DMA_CHANNEL6
#define USBUSART2_DMA_RX_IRQ NVIC_DMA1_CHANNEL6_IRQ
#define USBUSART2_DMA_RX_ISR(x) dma1_channel6_isr(x)
#define TRACE_TIM TIM3
#define TRACE_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM3)
#define TRACE_IRQ NVIC_TIM3_IRQ
#define TRACE_ISR tim3_isr
#define TRACE_ISR(x) tim3_isr(x)
#define SET_RUN_STATE(state) {running_status = (state);}
#define SET_IDLE_STATE(state) {gpio_set_val(LED_PORT, LED_IDLE_RUN, state);}

View File

@ -42,9 +42,9 @@ int main(void)
if(gpio_get(GPIOB, GPIO12))
dfu_jump_app_if_valid();
dfu_protect(DFU_MODE);
dfu_protect(false);
rcc_clock_setup_in_hse_8mhz_out_72mhz();
rcc_clock_setup_pll(&rcc_hse_configs[RCC_CLOCK_HSE8_72MHZ]);
systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8);
systick_set_reload(900000);
@ -60,7 +60,7 @@ int main(void)
gpio_set_mode(LED_PORT, GPIO_MODE_OUTPUT_2_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, LED_0 | LED_1 | LED_2);
dfu_init(&st_usbfs_v1_usb_driver, DFU_MODE);
dfu_init(&st_usbfs_v1_usb_driver);
/* Configure the USB pull up pin. */
gpio_set(GPIOA, GPIO8);

View File

@ -1,7 +1,7 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2019 - 2020 Uwe Bonnes
* Copyright (C) 2019 - 2021 Uwe Bonnes
* (bon@elektron.ikp.physik.tu-darmstadt.de)
*
* This program is free software: you can redistribute it and/or modify
@ -24,15 +24,17 @@
#include "general.h"
#include <unistd.h>
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include "target.h"
#include "version.h"
#include "target_internal.h"
#include "cortexm.h"
#include "command.h"
#include "cl_utils.h"
#include "bmp_hosted.h"
#ifndef O_BINARY
#define O_BINARY 0
@ -43,6 +45,18 @@
# include <sys/mman.h>
#endif
static void cl_target_printf(struct target_controller *tc,
const char *fmt, va_list ap)
{
(void)tc;
vprintf(fmt, ap);
}
static struct target_controller cl_controller = {
.printf = cl_target_printf,
};
struct mmap_data {
void *data;
size_t size;
@ -113,17 +127,21 @@ static void bmp_munmap(struct mmap_data *map)
#endif
}
static void cl_help(char **argv, BMP_CL_OPTIONS_t *opt)
static void cl_help(char **argv)
{
DEBUG_WARN("%s for: \n", opt->opt_idstring);
DEBUG_WARN("\tBMP Firmware, ST-Link V2/3, CMSIS_DAP, JLINK and "
"LIBFTDI/MPSSE\n\n");
bmp_ident(NULL);
DEBUG_WARN("Usage: %s [options]\n", argv[0]);
DEBUG_WARN("\t-h\t\t: This help.\n");
DEBUG_WARN("\t-v[bitmask]\t: Increasing verbosity. Bitmask:\n");
DEBUG_WARN("\t\t\t 1 = INFO, 2 = GDB, 4 = TARGET, 8 = PROBE, 16 = WIRE\n");
DEBUG_WARN("\t-l\t\t: List available probes\n");
DEBUG_WARN("Probe selection arguments:\n");
DEBUG_WARN("\t-d \"path\"\t: Use serial device at \"path\"\n");
DEBUG_WARN("\t-d \"path\"\t: Use serial BMP device at <path>");
#if HOSTED_BMP_ONLY == 1 && defined(__APPLE__)
DEBUG_WARN("\n");
#else
DEBUG_WARN(". Deprecated!\n");
#endif
DEBUG_WARN("\t-P <pos>\t: Use debugger found at position <pos>\n");
DEBUG_WARN("\t-n <num>\t: Use target device found at position <num>\n");
DEBUG_WARN("\t-s \"serial\"\t: Use dongle with (partial) "
@ -133,16 +151,25 @@ static void cl_help(char **argv, BMP_CL_OPTIONS_t *opt)
DEBUG_WARN("Run mode related options:\n");
DEBUG_WARN("\tDefault mode is to start the debug server at :2000\n");
DEBUG_WARN("\t-j\t\t: Use JTAG. SWD is default.\n");
DEBUG_WARN("\t-C\t\t: Connect under reset\n");
DEBUG_WARN("\t-f\t\t: Set minimum high and low times of SWJ waveform.\n");
DEBUG_WARN("\t-C\t\t: Connect under hardware reset\n");
DEBUG_WARN("\t-t\t\t: Scan SWD or JTAG and display information about \n"
"\t\t\t connected devices\n");
DEBUG_WARN("\t-T\t\t: Continuous read/write-back some value to allow\n"
"\t\t\t timing insection of SWJ. Abort with ^C\n");
DEBUG_WARN("\t-e\t\t: Assume \"resistor SWD connection\" on FTDI: TDI\n"
"\t\t\t connected to TMS, TDO to TDI with eventual resistor\n");
DEBUG_WARN("\t-E\t\t: Erase flash until flash end or for given size\n");
DEBUG_WARN("\t-V\t\t: Verify flash against binary file\n");
DEBUG_WARN("\t-w\t\t: Write binary file to target flash (default).\n");
DEBUG_WARN("\t-V\t\t: Verify flash against binary file. Can be combined\n"
"\t\t\t with -w to verify right after programming.\n");
DEBUG_WARN("\t-r\t\t: Read flash and write to binary file\n");
DEBUG_WARN("\t-p\t\t: Supplies power to the target (where applicable)\n");
DEBUG_WARN("\t-R\t\t: Reset device\n");
DEBUG_WARN("\t-R[h]\t\t: Reset device. Default via SWJ or by hardware(h)\n");
DEBUG_WARN("\t-H\t\t: Do not use high level commands (BMP-Remote)\n");
DEBUG_WARN("\t-m <target>\t: Use (target)id for SWD multi-drop.\n");
DEBUG_WARN("\t-M <string>\t: Run target specific monitor commands. Quote multi\n");
DEBUG_WARN("\t\t\t word strings. Run \"-M help\" for help.\n");
DEBUG_WARN("Flash operation modifiers options:\n");
DEBUG_WARN("\tDefault action with given file is to write to flash\n");
DEBUG_WARN("\t-a <addr>\t: Start flash operation at flash address <addr>\n"
@ -156,15 +183,21 @@ void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv)
{
int c;
opt->opt_target_dev = 1;
opt->opt_flash_size = 16 * 1024 *1024;
while((c = getopt(argc, argv, "eEhv:d:s:I:c:CnltVta:S:jpP:rR")) != -1) {
opt->opt_flash_size = 0xffffffff;
opt->opt_flash_start = 0xffffffff;
opt->opt_max_swj_frequency = 4000000;
while((c = getopt(argc, argv, "eEhHv:d:f:s:I:c:Cln:m:M:wVtTa:S:jpP:rR::")) != -1) {
switch(c) {
case 'c':
if (optarg)
opt->opt_cable = optarg;
break;
case 'h':
cl_help(argv, opt);
cl_debuglevel = 3;
cl_help(argv);
break;
case 'H':
opt->opt_no_hl = true;
break;
case 'v':
if (optarg)
@ -187,6 +220,21 @@ void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv)
if (optarg)
opt->opt_device = optarg;
break;
case 'f':
if (optarg) {
char *p;
uint32_t frequency = strtol(optarg, &p, 10);
switch(*p) {
case 'k':
frequency *= 1000;
break;
case 'M':
frequency *= 1000*1000;
break;
}
opt->opt_max_swj_frequency = frequency;
}
break;
case 's':
if (optarg)
opt->opt_serial = optarg;
@ -202,14 +250,29 @@ void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv)
opt->opt_mode = BMP_MODE_TEST;
cl_debuglevel |= BMP_DEBUG_INFO | BMP_DEBUG_STDOUT;
break;
case 'T':
opt->opt_mode = BMP_MODE_SWJ_TEST;
break;
case 'w':
if (opt->opt_mode == BMP_MODE_FLASH_VERIFY)
opt->opt_mode = BMP_MODE_FLASH_WRITE_VERIFY;
else
opt->opt_mode = BMP_MODE_FLASH_WRITE;
break;
case 'V':
opt->opt_mode = BMP_MODE_FLASH_VERIFY;
if (opt->opt_mode == BMP_MODE_FLASH_WRITE)
opt->opt_mode = BMP_MODE_FLASH_WRITE_VERIFY;
else
opt->opt_mode = BMP_MODE_FLASH_VERIFY;
break;
case 'r':
opt->opt_mode = BMP_MODE_FLASH_READ;
break;
case 'R':
opt->opt_mode = BMP_MODE_RESET;
if ((optarg) && (tolower(optarg[0]) == 'h'))
opt->opt_mode = BMP_MODE_RESET_HW;
else
opt->opt_mode = BMP_MODE_RESET;
break;
case 'p':
opt->opt_tpwr = true;
@ -222,6 +285,14 @@ void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv)
if (optarg)
opt->opt_target_dev = strtol(optarg, NULL, 0);
break;
case 'm':
if (optarg)
opt->opt_targetid = strtol(optarg, NULL, 0);
break;
case 'M':
if (optarg)
opt->opt_monitor = optarg;
break;
case 'P':
if (optarg)
opt->opt_position = atoi(optarg);
@ -249,10 +320,16 @@ void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv)
if (opt->opt_mode == BMP_MODE_DEBUG)
opt->opt_mode = BMP_MODE_FLASH_WRITE;
opt->opt_flash_file = argv[optind];
} else if ((opt->opt_mode == BMP_MODE_DEBUG) &&
(opt->opt_monitor)) {
opt->opt_mode = BMP_MODE_MONITOR; // To avoid DEBUG mode
}
/* Checks */
if ((opt->opt_flash_file) && ((opt->opt_mode == BMP_MODE_TEST ) ||
(opt->opt_mode == BMP_MODE_RESET))) {
(opt->opt_mode == BMP_MODE_SWJ_TEST) ||
(opt->opt_mode == BMP_MODE_RESET) ||
(opt->opt_mode == BMP_MODE_RESET_HW))) {
DEBUG_WARN("Ignoring filename in reset/test mode\n");
opt->opt_flash_file = NULL;
}
@ -261,104 +338,131 @@ void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv)
static void display_target(int i, target *t, void *context)
{
(void)context;
DEBUG_INFO("*** %2d %c %s %s\n", i, target_attached(t)?'*':' ',
target_driver_name(t),
(target_core_name(t)) ? target_core_name(t): "");
if (!strcmp(target_driver_name(t), "ARM Cortex-M")) {
DEBUG_INFO("***%2d%sUnknown %s Designer %3x Partno %3x %s\n",
i, target_attached(t)?" * ":" ",
target_driver_name(t),
target_designer(t),
target_idcode(t),
(target_core_name(t)) ? target_core_name(t): "");
} else {
DEBUG_INFO("*** %2d %c %s %s\n", i, target_attached(t)?'*':' ',
target_driver_name(t),
(target_core_name(t)) ? target_core_name(t): "");
}
}
int cl_execute(BMP_CL_OPTIONS_t *opt)
{
int res = -1;
int res = 0;
int num_targets;
#if defined(PLATFORM_HAS_POWER_SWITCH)
if (opt->opt_tpwr) {
DEBUG_INFO("Powering up device");
platform_target_set_power(true);
platform_delay(500);
}
#endif
if (opt->opt_mode == BMP_MODE_RESET_HW) {
platform_srst_set_val(true);
platform_delay(1);
platform_srst_set_val(false);
return res;
}
if (opt->opt_connect_under_reset)
DEBUG_INFO("Connecting under reset\n");
connect_assert_srst = opt->opt_connect_under_reset;
platform_srst_set_val(opt->opt_connect_under_reset);
if (opt->opt_mode == BMP_MODE_TEST)
DEBUG_INFO("Running in Test Mode\n");
if (platform_target_voltage())
DEBUG_INFO("Target voltage: %s Volt\n", platform_target_voltage());
DEBUG_INFO("Target voltage: %s Volt\n", platform_target_voltage());
if (opt->opt_usejtag) {
num_targets = platform_jtag_scan(NULL);
} else {
num_targets = platform_adiv5_swdp_scan();
num_targets = platform_adiv5_swdp_scan(opt->opt_targetid);
if (!num_targets) {
DEBUG_INFO("Scan SWD failed, trying JTAG!\n");
num_targets = platform_jtag_scan(NULL);
}
}
if (!num_targets) {
DEBUG_WARN("No target found\n");
return res;
return -1;
} else {
target_foreach(display_target, NULL);
num_targets = target_foreach(display_target, &num_targets);
}
if (opt->opt_target_dev > num_targets) {
DEBUG_WARN("Given target nummer %d not available\n",
opt->opt_target_dev);
return res;
DEBUG_WARN("Given target number %d not available max %d\n",
opt->opt_target_dev, num_targets);
return -1;
}
target *t = target_attach_n(opt->opt_target_dev, NULL);
target *t = target_attach_n(opt->opt_target_dev, &cl_controller);
if (!t) {
DEBUG_WARN("Can not attach to target %d\n", opt->opt_target_dev);
res = -1;
goto target_detach;
}
/* List each defined RAM */
int n_ram = 0;
for (struct target_ram *r = t->ram; r; r = r->next)
n_ram++;
for (int n = n_ram; n >= 0; n --) {
struct target_ram *r = t->ram;
for (int i = 1; r; r = r->next, i++)
if (i == n)
DEBUG_INFO("RAM Start: 0x%08" PRIx32 " length = 0x%" PRIx32 "\n",
r->start, (uint32_t)r->length);
}
/* Always scan memory map to find lowest flash */
char memory_map [1024], *p = memory_map;
uint32_t flash_start = 0xffffffff;
if (target_mem_map(t, memory_map, sizeof(memory_map))) {
while (*p && (*p == '<')) {
unsigned int start, size;
char *res;
int match;
match = strncmp(p, "<memory-map>", strlen("<memory-map>"));
if (!match) {
p += strlen("<memory-map>");
continue;
}
match = strncmp(p, "<memory type=\"flash\" ", strlen("<memory type=\"flash\" "));
if (!match) {
unsigned int blocksize;
if (sscanf(p, "<memory type=\"flash\" start=\"%x\" length=\"%x\">"
"<property name=\"blocksize\">%x</property></memory>",
&start, &size, &blocksize)) {
if (opt->opt_mode == BMP_MODE_TEST)
DEBUG_INFO("Flash Start: 0x%08x, length %#9x, "
"blocksize %#8x\n", start, size, blocksize);
if (start < flash_start)
flash_start = start;
/* List each defined Flash */
uint32_t lowest_flash_start = 0xffffffff;
uint32_t lowest_flash_size = 0;
int n_flash = 0;
for (struct target_flash *f = t->flash; f; f = f->next)
n_flash++;
for (int n = n_flash; n >= 0; n --) {
struct target_flash *f = t->flash;
for (int i = 1; f; f = f->next, i++)
if (i == n) {
DEBUG_INFO("Flash Start: 0x%08" PRIx32 " length = 0x%" PRIx32
" blocksize 0x%" PRIx32 "\n",
f->start, (uint32_t)f->length, (uint32_t)f->blocksize);
if (f->start < lowest_flash_start) {
lowest_flash_start = f->start;
lowest_flash_size = f->length;
}
res = strstr(p, "</memory>");
p = res + strlen("</memory>");
continue;
}
match = strncmp(p, "<memory type=\"ram\" ", strlen("<memory type=\"ram\" "));
if (!match) {
if (sscanf(p, "<memory type=\"ram\" start=\"%x\" length=\"%x\"/",
&start, &size))
if (opt->opt_mode == BMP_MODE_TEST)
DEBUG_INFO("Ram Start: 0x%08x, length %#9x\n",
start, size);
res = strstr(p, "/>");
p = res + strlen("/>");
continue;
}
if (opt->opt_flash_start == 0xffffffff)
opt->opt_flash_start = lowest_flash_start;
if ((opt->opt_flash_size == 0xffffffff) &&
(opt->opt_mode != BMP_MODE_FLASH_WRITE) &&
(opt->opt_mode != BMP_MODE_FLASH_VERIFY) &&
(opt->opt_mode != BMP_MODE_FLASH_WRITE_VERIFY))
opt->opt_flash_size = lowest_flash_size;
if (opt->opt_mode == BMP_MODE_SWJ_TEST) {
switch (t->core[0]) {
case 'M':
DEBUG_WARN("Continuous read/write-back DEMCR. Abort with ^C\n");
while(1) {
uint32_t demcr;
target_mem_read(t, &demcr, CORTEXM_DEMCR, 4);
target_mem_write32(t, CORTEXM_DEMCR, demcr);
platform_delay(1); /* To allow trigger*/
}
break;
default:
DEBUG_WARN("No test for this core type yet\n");
}
}
if (opt->opt_flash_start < flash_start)
opt->opt_flash_start = flash_start;
if (opt->opt_mode == BMP_MODE_TEST)
if ((opt->opt_mode == BMP_MODE_TEST) ||
(opt->opt_mode == BMP_MODE_SWJ_TEST))
goto target_detach;
int read_file = -1;
if ((opt->opt_mode == BMP_MODE_FLASH_WRITE) ||
(opt->opt_mode == BMP_MODE_FLASH_VERIFY)) {
(opt->opt_mode == BMP_MODE_FLASH_VERIFY) ||
(opt->opt_mode == BMP_MODE_FLASH_WRITE_VERIFY)) {
int mmap_res = bmp_mmap(opt->opt_flash_file, &map);
if (mmap_res) {
DEBUG_WARN("Can not map file: %s. Aborting!\n", strerror(errno));
res = -1;
goto target_detach;
}
} else if (opt->opt_mode == BMP_MODE_FLASH_READ) {
@ -368,12 +472,18 @@ int cl_execute(BMP_CL_OPTIONS_t *opt)
if (read_file == -1) {
DEBUG_WARN("Error opening flashfile %s for read: %s\n",
opt->opt_flash_file, strerror(errno));
return res;
res = -1;
goto target_detach;
}
}
if (opt->opt_flash_size < map.size)
/* restrict to size given on command line */
map.size = opt->opt_flash_size;
if (opt->opt_monitor) {
res = command_process(t, opt->opt_monitor);
if (res)
DEBUG_WARN("Command \"%s\" failed\n", opt->opt_monitor);
}
if (opt->opt_mode == BMP_MODE_RESET) {
target_reset(t);
} else if (opt->opt_mode == BMP_MODE_FLASH_ERASE) {
@ -382,18 +492,21 @@ int cl_execute(BMP_CL_OPTIONS_t *opt)
unsigned int erased = target_flash_erase(t, opt->opt_flash_start,
opt->opt_flash_size);
if (erased) {
DEBUG_WARN("Erased failed!\n");
DEBUG_WARN("Erasure failed!\n");
res = -1;
goto free_map;
}
target_reset(t);
} else if (opt->opt_mode == BMP_MODE_FLASH_WRITE) {
} else if ((opt->opt_mode == BMP_MODE_FLASH_WRITE) ||
(opt->opt_mode == BMP_MODE_FLASH_WRITE_VERIFY)) {
DEBUG_INFO("Erase %zu bytes at 0x%08" PRIx32 "\n", map.size,
opt->opt_flash_start);
uint32_t start_time = platform_time_ms();
unsigned int erased = target_flash_erase(t, opt->opt_flash_start,
map.size);
if (erased) {
DEBUG_WARN("Erased failed!\n");
DEBUG_WARN("Erasure failed!\n");
res = -1;
goto free_map;
} else {
DEBUG_INFO("Flashing %zu bytes at 0x%08" PRIx32 "\n",
@ -401,25 +514,34 @@ int cl_execute(BMP_CL_OPTIONS_t *opt)
unsigned int flashed = target_flash_write(t, opt->opt_flash_start,
map.data, map.size);
/* Buffered write cares for padding*/
if (!flashed)
flashed = target_flash_done(t);
if (flashed) {
DEBUG_WARN("Flashing failed!\n");
res = -1;
goto free_map;
} else {
DEBUG_INFO("Success!\n");
res = 0;
}
}
target_flash_done(t);
target_reset(t);
uint32_t end_time = platform_time_ms();
DEBUG_WARN("Flash Write succeeded for %d bytes, %8.3f kiB/s\n",
(int)map.size, (((map.size * 1.0)/(end_time - start_time))));
} else {
#define WORKSIZE 1024
if (opt->opt_mode != BMP_MODE_FLASH_WRITE_VERIFY) {
target_reset(t);
goto free_map;
}
}
if ((opt->opt_mode == BMP_MODE_FLASH_READ) ||
(opt->opt_mode == BMP_MODE_FLASH_VERIFY) ||
(opt->opt_mode == BMP_MODE_FLASH_WRITE_VERIFY)) {
#define WORKSIZE 0x1000
uint8_t *data = alloca(WORKSIZE);
if (!data) {
DEBUG_WARN("Can not malloc memory for flash read/verify "
"operation\n");
return res;
res = -1;
goto free_map;
}
if (opt->opt_mode == BMP_MODE_FLASH_READ)
DEBUG_INFO("Reading flash from 0x%08" PRIx32 " for %zu"
@ -447,12 +569,14 @@ int cl_execute(BMP_CL_OPTIONS_t *opt)
} else {
bytes_read += worksize;
}
if (opt->opt_mode == BMP_MODE_FLASH_VERIFY) {
if ((opt->opt_mode == BMP_MODE_FLASH_VERIFY) ||
(opt->opt_mode == BMP_MODE_FLASH_WRITE_VERIFY)) {
int difference = memcmp(data, flash, worksize);
if (difference){
DEBUG_WARN("Verify failed at flash region 0x%08"
PRIx32 "\n", flash_src);
return -1;
res = -1;
goto free_map;
}
flash += worksize;
} else if (read_file != -1) {
@ -460,19 +584,21 @@ int cl_execute(BMP_CL_OPTIONS_t *opt)
if (written < worksize) {
DEBUG_WARN("Read failed at flash region 0x%08" PRIx32 "\n",
flash_src);
return -1;
res = -1;
goto free_map;
}
}
flash_src += worksize;
size -= worksize;
if (size <= 0)
res = 0;
}
uint32_t end_time = platform_time_ms();
if (read_file != -1)
close(read_file);
DEBUG_WARN("Read/Verify succeeded for %d bytes, %8.3f kiB/s\n",
bytes_read, (((bytes_read * 1.0)/(end_time - start_time))));
bytes_read,
(((bytes_read * 1.0)/(end_time - start_time))));
if (opt->opt_mode == BMP_MODE_FLASH_WRITE_VERIFY)
target_reset(t);
}
free_map:
if (map.size)
@ -480,5 +606,6 @@ int cl_execute(BMP_CL_OPTIONS_t *opt)
target_detach:
if (t)
target_detach(t);
target_list_free();
return res;
}

View File

@ -1,7 +1,7 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2019 - 2020 Uwe Bonnes
* Copyright (C) 2019 - 2021 Uwe Bonnes
* Written by Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de)
*
* This program is free software: you can redistribute it and/or modify
@ -24,16 +24,20 @@
#if !defined(__CL_UTILS_H)
#define __CL_UTILS_H
#define RESP_TIMEOUT (100)
#include "cortexm.h"
enum bmp_cl_mode {
BMP_MODE_DEBUG,
BMP_MODE_TEST,
BMP_MODE_RESET,
BMP_MODE_RESET_HW,
BMP_MODE_FLASH_ERASE,
BMP_MODE_FLASH_WRITE,
BMP_MODE_FLASH_WRITE_VERIFY,
BMP_MODE_FLASH_READ,
BMP_MODE_FLASH_VERIFY
BMP_MODE_FLASH_VERIFY,
BMP_MODE_SWJ_TEST,
BMP_MODE_MONITOR,
};
typedef struct BMP_CL_OPTIONS_s {
@ -43,17 +47,20 @@ typedef struct BMP_CL_OPTIONS_s {
bool opt_list_only;
bool opt_connect_under_reset;
bool external_resistor_swd;
bool opt_no_hl;
char *opt_flash_file;
char *opt_device;
char *opt_serial;
uint32_t opt_targetid;
char *opt_ident_string;
int opt_position;
char *opt_cable;
char *opt_monitor;
int opt_debuglevel;
int opt_target_dev;
uint32_t opt_flash_start;
uint32_t opt_max_swj_frequency;
size_t opt_flash_size;
char *opt_idstring;
}BMP_CL_OPTIONS_t;
void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv);

View File

@ -36,13 +36,11 @@
# include <fcntl.h>
#endif
#include <stdio.h>
#include "general.h"
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include "general.h"
#include "gdb_if.h"
static int gdb_if_serv, gdb_if_conn;
@ -51,8 +49,13 @@ static int gdb_if_serv, gdb_if_conn;
int gdb_if_init(void)
{
#if defined(_WIN32) || defined(__CYGWIN__)
int iResult;
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != NO_ERROR) {
DEBUG_WARN("WSAStartup failed with error: %ld\n", iResult);
exit(1);
}
#endif
struct sockaddr_in addr;
int opt;
@ -67,23 +70,47 @@ int gdb_if_init(void)
addr.sin_addr.s_addr = htonl(INADDR_ANY);
gdb_if_serv = socket(PF_INET, SOCK_STREAM, 0);
if (gdb_if_serv == -1)
if (gdb_if_serv == -1) {
DEBUG_WARN("PF_INET %d\n",gdb_if_serv);
continue;
}
opt = 1;
if (setsockopt(gdb_if_serv, SOL_SOCKET, SO_REUSEADDR, (void*)&opt, sizeof(opt)) == -1) {
#if defined(_WIN32) || defined(__CYGWIN__)
DEBUG_WARN("error setsockopt SOL_SOCKET : %d error: %d\n", gdb_if_serv,
WSAGetLastError());
#else
DEBUG_WARN("error setsockopt SOL_SOCKET : %d error: %d\n", gdb_if_serv,
strerror(errno));
#endif
close(gdb_if_serv);
continue;
}
if (setsockopt(gdb_if_serv, IPPROTO_TCP, TCP_NODELAY, (void*)&opt, sizeof(opt)) == -1) {
#if defined(_WIN32) || defined(__CYGWIN__)
DEBUG_WARN("error setsockopt IPPROTO_TCP : %d error: %d\n", gdb_if_serv,
WSAGetLastError());
#else
DEBUG_WARN("error setsockopt IPPROTO_TCP : %d error: %d\n", gdb_if_serv,
strerror(errno));
#endif
close(gdb_if_serv);
continue;
}
if (bind(gdb_if_serv, (void*)&addr, sizeof(addr)) == -1) {
#if defined(_WIN32) || defined(__CYGWIN__)
DEBUG_WARN("error when binding socket: %d error: %d\n", gdb_if_serv,
WSAGetLastError());
#else
DEBUG_WARN("error when binding socket: %d error: %d\n", gdb_if_serv,
strerror(errno));
#endif
close(gdb_if_serv);
continue;
}
if (listen(gdb_if_serv, 1) == -1) {
DEBUG_WARN("listen closed %d\n",gdb_if_serv);
close(gdb_if_serv);
continue;
}
@ -100,6 +127,7 @@ unsigned char gdb_if_getchar(void)
unsigned char ret;
int i = 0;
#if defined(_WIN32) || defined(__CYGWIN__)
int iResult;
unsigned long opt;
#else
int flags;
@ -108,7 +136,10 @@ unsigned char gdb_if_getchar(void)
if(gdb_if_conn <= 0) {
#if defined(_WIN32) || defined(__CYGWIN__)
opt = 1;
ioctlsocket(gdb_if_serv, FIONBIO, &opt);
iResult = ioctlsocket(gdb_if_serv, FIONBIO, &opt);
if (iResult != NO_ERROR) {
DEBUG_WARN("ioctlsocket failed with error: %ld\n", iResult);
}
#else
flags = fcntl(gdb_if_serv, F_GETFL);
fcntl(gdb_if_serv, F_SETFL, flags | O_NONBLOCK);

View File

@ -61,9 +61,7 @@ extern "C" {
} /* extern "C" */
#endif
#include <stdio.h>
#include <stdlib.h>
#include <general.h>
#include "hidapi.h"

View File

@ -1,138 +0,0 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2020 Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "general.h"
#include "cl_utils.h"
static void LIBUSB_CALL on_trans_done(struct libusb_transfer *trans)
{
struct trans_ctx * const ctx = trans->user_data;
if (trans->status != LIBUSB_TRANSFER_COMPLETED)
{
DEBUG_WARN("on_trans_done: ");
if(trans->status == LIBUSB_TRANSFER_TIMED_OUT) {
DEBUG_WARN(" Timeout\n");
} else if (trans->status == LIBUSB_TRANSFER_CANCELLED) {
DEBUG_WARN(" cancelled\n");
} else if (trans->status == LIBUSB_TRANSFER_NO_DEVICE) {
DEBUG_WARN(" no device\n");
} else {
DEBUG_WARN(" unknown\n");
}
ctx->flags |= TRANS_FLAGS_HAS_ERROR;
}
ctx->flags |= TRANS_FLAGS_IS_DONE;
}
static int submit_wait(usb_link_t *link, struct libusb_transfer *trans) {
struct trans_ctx trans_ctx;
enum libusb_error error;
trans_ctx.flags = 0;
/* brief intrusion inside the libusb interface */
trans->callback = on_trans_done;
trans->user_data = &trans_ctx;
if ((error = libusb_submit_transfer(trans))) {
DEBUG_WARN("libusb_submit_transfer(%d): %s\n", error,
libusb_strerror(error));
exit(-1);
}
uint32_t start_time = platform_time_ms();
while (trans_ctx.flags == 0) {
struct timeval timeout;
timeout.tv_sec = 1;
timeout.tv_usec = 0;
if (libusb_handle_events_timeout(link->ul_libusb_ctx, &timeout)) {
DEBUG_WARN("libusb_handle_events()\n");
return -1;
}
uint32_t now = platform_time_ms();
if (now - start_time > 1000) {
libusb_cancel_transfer(trans);
DEBUG_WARN("libusb_handle_events() timeout\n");
return -1;
}
}
if (trans_ctx.flags & TRANS_FLAGS_HAS_ERROR) {
DEBUG_WARN("libusb_handle_events() | has_error\n");
return -1;
}
return 0;
}
/* One USB transaction */
int send_recv(usb_link_t *link,
uint8_t *txbuf, size_t txsize,
uint8_t *rxbuf, size_t rxsize)
{
int res = 0;
if( txsize) {
int txlen = txsize;
libusb_fill_bulk_transfer(link->req_trans,
link->ul_libusb_device_handle,
link->ep_tx | LIBUSB_ENDPOINT_OUT,
txbuf, txlen,
NULL, NULL, 0);
int i = 0;
DEBUG_WIRE(" Send (%3d): ", txlen);
for (; i < txlen; i++) {
DEBUG_WIRE("%02x", txbuf[i]);
if ((i & 7) == 7)
DEBUG_WIRE(".");
if ((i & 31) == 31)
DEBUG_WIRE("\n ");
}
if (!(i & 31))
DEBUG_WIRE("\n");
if (submit_wait(link, link->req_trans)) {
libusb_clear_halt(link->ul_libusb_device_handle, link->ep_tx);
return -1;
}
}
/* send_only */
if (rxsize != 0) {
/* read the response */
libusb_fill_bulk_transfer(link->rep_trans, link->ul_libusb_device_handle,
link->ep_rx | LIBUSB_ENDPOINT_IN,
rxbuf, rxsize, NULL, NULL, 0);
if (submit_wait(link, link->rep_trans)) {
DEBUG_WARN("clear 1\n");
libusb_clear_halt(link->ul_libusb_device_handle, link->ep_rx);
return -1;
}
res = link->rep_trans->actual_length;
if (res >0) {
int i;
uint8_t *p = rxbuf;
DEBUG_WIRE(" Rec (%zu/%d)", rxsize, res);
for (i = 0; i < res && i < 32 ; i++) {
if ( i && ((i & 7) == 0))
DEBUG_WIRE(".");
DEBUG_WIRE("%02x", p[i]);
}
}
}
DEBUG_WIRE("\n");
return res;
}

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