Compare commits

...

1189 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
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
Damien Merenne
120b3134bb Add SAM4SD32C/B support. 2020-09-07 17:36:15 +02:00
Uwe Bonnes
8289862b55 gdb: Reset flash_mode with when erase or flash fails.
Thanks to Dave Marples <dave@marples.net>, extracted from  #607
2020-09-04 15:17:29 +02:00
Uwe Bonnes
58281ec232 SWD Timing: Enhance SWD high time with low speed loss.
On F103 no high time < 80 ns and no low time < 100 ns was seen with a scope
2020-09-04 14:45:34 +02:00
Thomas Jarosch
2641291874 stm32_mem: Fix python3 crash due to mix of tabs and spaces
Fixes this issue:

$ python3 ./stm32_mem.py blackmagic.bin
  File "./stm32_mem.py", line 199
    if (os.path.getsize(args.progfile) > 0x1f800):
                                                 ^
TabError: inconsistent use of tabs and spaces in indentation

and allows to run with python2 too.
2020-09-04 14:19:19 +02:00
Remco Stoutjesdijk
b51c9367fc Swolisten: Moving the library argument to the end of the command line #718 2020-09-04 12:35:03 +02:00
Uwe Bonnes
af3480e523 hosted: Update Readme.md 2020-09-04 11:49:13 +02:00
Uwe Bonnes
6650831243 ftdi: Get turtelizer (JTAG only FT2232D dongle) going
FT2232D seems to dislike "Set TCK/SK Divisor" or
"Set Data Bits Low Byte" as first command on a non-first run
- Add printout when garbage is found
- Add "Disconnect TDI to TDO for Loopback" as first MPSSE command
  (seemed to help!)
2020-09-04 11:49:13 +02:00
Uwe Bonnes
74b3baad1e ftdi_bmp : Another size fix and small rearrangement. 2020-09-04 11:49:13 +02:00
Uwe Bonnes
aeb97466b9 libftdi: Automatically switch to JTAG if SWD is not possible. 2020-09-04 11:49:13 +02:00
Uwe Bonnes
ae8cb8ab46 ftdi_bmp: Reject writes with no data.
Pending transfers made the MPSSE behaviour strange and unpredictable.
2020-09-04 11:49:13 +02:00
Uwe Bonnes
c41ab1738e ftdi/swdptap: Use parity builtin. Fix array width. 2020-09-04 11:49:13 +02:00
Uwe Bonnes
34d0f8a2a1 ftdi: Recognize bitbang SWDIO settings. 2020-09-04 11:49:13 +02:00
Uwe Bonnes
6ac0a25123 ftdi: Add UM232H as probe. 2020-09-04 11:49:13 +02:00
Uwe Bonnes
d73a6a3d29 platform/ftdi: Do not double initialize. 2020-09-04 11:49:13 +02:00
Uwe Bonnes
f0b0639189 ftdi: Output wire debug. 2020-09-04 11:49:13 +02:00
Uwe Bonnes
e95e5e3fba ftdijtag: Really enable TMS/TCK/TDI driver. 2020-09-04 11:49:13 +02:00
Uwe Bonnes
f4eed249eb hosted/ftdi: Allow to list supported cables. 2020-09-04 11:49:13 +02:00
Uwe Bonnes
8a2bce26f2 Hosted: Fix memory leak when platform_swdptap_init fails. 2020-09-04 11:49:13 +02:00
Uwe Bonnes
7b497302c0 hosted/ftdi: Autodetect ftdi cables with distinguishing feature. 2020-09-04 11:49:13 +02:00
Uwe Bonnes
a83e76bef9 libftdi: Add USBMATE. 2020-09-04 11:49:13 +02:00
Uwe Bonnes
c78066255d libftdi: Infrastructure to test for target voltage present. 2020-09-04 11:49:13 +02:00
Uwe Bonnes
aff624b6e0 libftfdi: Allow to specify external resistor SWD connection.
More explanations in src/platforms/hosted/Readme.md
2020-09-04 11:49:13 +02:00
Uwe Bonnes
eabf45357d libftdi: Reinitialize pins when switching JTAG/SWD. 2020-09-04 11:49:13 +02:00
Uwe Bonnes
05534e9b49 libftdi/swdptap: Provide SWD using generic MPSSE if hardware allows. 2020-09-04 11:49:13 +02:00
Uwe Bonnes
40ba261982 libftdi: Use asynchronous transfers if header indicate newer libftdi1.
This is a hack to keep travis happy. Setting up travis to use a recent
libftdi1 is a major issue.
2020-09-04 11:49:13 +02:00
Uwe Bonnes
9b6e19785e Implement SRST for libftdi.
Travis GCC needs -Wno-missing-field-initializers or will otherwise warn.
2020-09-04 11:49:13 +02:00
Matthew Skolaut
dea4be2539 Add ifdef to check for libftdi 1.5 to use ftdi_tcioflush instead of ftdi_usb_purge_buffers 2020-08-21 13:10:55 +02:00
Matthew Skolaut
7e1b0321e2 Cleanup Makefiles for hosted bmp on darwin 2020-08-21 11:28:17 +02:00
Matthew Skolaut
5908fc2da1 Add serial auto-connection to darwin target 2020-08-21 11:28:17 +02:00
Uwe Bonnes
e75eb19d78 cmsis_dap: Detect CMSIS-DAP before STLINK
Debugger may be realized with the ST USB Vendor ID.
2020-08-16 15:20:58 +02:00
Uwe Bonnes
998a9747f8 cmsis_dap: Make some errors more prominent. 2020-08-16 15:20:58 +02:00
Uwe Bonnes
c97c4a0960 hosted: Better decoding for ap_decode_access(). 2020-08-16 15:20:58 +02:00
Uwe Bonnes
badff20099 cmsis_dap.c: Fix dap_dp_read_reg. 2020-08-16 15:20:58 +02:00
David Lawrence
f65afb1588 Use correct IAP entry address for LPC84x 2020-08-14 20:00:18 +02:00
Uwe Bonnes
dd74ec8e6f stlinkv2: Detect fail mem_read on jtag too. 2020-08-05 16:20:52 +02:00
Uwe Bonnes
805cfbdcb5 Build hosted for widows with hidapi static linked. 2020-08-03 18:59:50 +02:00
Uwe Bonnes
fca8593d92 serial_win: Find BMP comport by serial number. 2020-08-03 18:59:50 +02:00
Uwe Bonnes
3eb51ce94f serial_win.c: Copy the enough of the device name. 2020-08-01 14:00:17 +02:00
Uwe Bonnes
11217f8a45 serial_win: GDB needs to handle DTR. 2020-08-01 14:00:17 +02:00
Uwe Bonnes
71e9d78210 adiv5.c: Add another ARCH_ID found STM32F205. 2020-08-01 14:00:17 +02:00
Uwe Bonnes
1b12e407fd adiv5: Add missing arch identifiers for Cortex-M7 ETM. 2020-07-31 11:53:15 +02:00
Uwe Bonnes
71e5b4d3cb hosted/stlinkv2.c: Fix bug introduced with #703 2020-07-29 13:42:07 +02:00
Uwe Bonnes
72387164eb hosted/stlinkv2.c: Handle AP_WAIT error when switching to SWD 2020-07-29 12:22:18 +02:00
Uwe Bonnes
a392480631 hosted/stlinkv2.c: Use V2 API to read coreid. 2020-07-29 12:22:18 +02:00
Francesco Valla
696daa8352 adiv5: fix debug print of dev_type
Since dev_type is an 8 bit unsigned integer, use the PRIx8 macro instead
of PRIx32.
2020-07-29 11:32:24 +02:00
Uwe Bonnes
64cf30e4cd Rework/update/add Readme.md in the platforms directories. 2020-07-29 10:32:49 +02:00
Uwe Bonnes
726d4b4496 adiv5.c: Add missing DEVTYPE and ARCHID to some existing PIDRs(#698,#699)
Probably more additions are needed.
2020-07-14 16:26:32 +02:00
Uwe Bonnes
52bfe538e3 cdcacm.c: Set bMaxPacketSize0 to 32 (#693, #697)
Smaller bMaxPacketSize0  resulted in delayed enumeration when BMP firmware
is started by the STLink bootloader.
2020-07-14 15:57:03 +02:00
Uwe Bonnes
09ceaea70f adiv5_swdp: Fix another memory leak. 2020-07-14 15:02:13 +02:00
UweBonnes
2ae62433d2
Merge pull request #690 from themadinventor/arm_v8m
Add ROM table support for Cortex-M33 and Cortex-M23
2020-07-13 10:56:03 +02:00
Aled Cuda
a673efc26b Remove extra definitions of jtag structures in the STLink hosted setup to support "gcc (GCC) 10.1.0" on Archlinux 2020-07-12 23:14:19 +02:00
Fredrik Ahlberg
7ebb94d134 cortexm: Add comment on CPUID register 2020-07-12 22:54:39 +02:00
Fredrik Ahlberg
4391851f4d adiv5: Change component descriptions from MTB to Micro Trace Buffer for consistency 2020-07-12 22:29:04 +02:00
Fredrik Ahlberg
0aadd0abce Adiv6: Add comment on DEVTYPE and ARCHID fields with references 2020-07-12 22:27:46 +02:00
Fredrik Ahlberg
fcd945a529 cortexm: Read CPUID to identify core version 2020-07-12 12:08:22 +02:00
Fredrik Ahlberg
39a20d78ff v8m: only check relevant bits in DHCSR when polling in cortexm_forced_halt 2020-07-12 12:07:12 +02:00
Fredrik Ahlberg
a35e9c8e5c Adiv6: Read DEVTYPE and ARCHID to identify Cortex-M23 and Cortex-M33 debug components 2020-07-12 12:00:31 +02:00
Uwe Bonnes
661f78033a stm32f1: Add F1 XL with dual bank handling, 2020-07-08 14:31:58 +02:00
Uwe Bonnes
fc6ca5bc06 Remote: Add procedure to test if high-level remote functions are available
Removes need for updated version string.
2020-07-08 14:15:35 +02:00
Uwe Bonnes
bfda64c656 stlink: Remove unused double defined variable "running_status"(#683) 2020-07-02 19:44:31 +02:00
Uwe Bonnes
85d35b75ce libftdi/jtagtap_tdi_tdo_seq: Remove dubious Null termination. 2020-07-02 14:56:10 +02:00
Uwe Bonnes
be6991344f README.md: Add sample session (#570) 2020-06-16 13:50:40 +02:00
Uwe Bonnes
a4cdd6b310 hosted: Report missing USB access rights only if no debugger found. 2020-06-07 16:29:19 +02:00
Uwe Bonnes
eabd69dcdb Adiv5: Protect DBG/SYSTEM Power-Up request with timeout too.
CMSIS-DAP without connected target looped infinite in that situation.
2020-06-07 13:14:32 +02:00
Uwe Bonnes
e35025d214 CMSIS_DAP: Warn when hidapi-libusb is not found. 2020-06-06 15:28:53 +02:00
Uwe Bonnes
5097a23196 jlink: Fix wrong sized array. 2020-06-06 15:28:53 +02:00
UweBonnes
dec431f869
Merge pull request #675 from UweBonnes/hydrabus
hydrabus: Disable DFU file generation untit somebody fixes dfu-conver…
2020-06-05 17:04:09 +02:00
Uwe Bonnes
4ede113ca7 hydrabus: Disable DFU file generation untit somebody fixes dfu-convert.py
This allows "make all_platforms" to succeed on python3 only systems.
2020-06-05 16:23:28 +02:00
UweBonnes
f5e305e237
Merge pull request #669 from blacksphere/v1.6.2-rc0
V1.6.2 rc0:
Unify PC-Hosted BMP

    Add CMSIS-DAP and Jlink
    Add high level BMP remote commands
    Clean up command line interface and debug messages
2020-06-05 15:57:25 +02:00
Uwe Bonnes
da45281696 GetTargetVoltage: Print info about voltage only when info is relevant. 2020-06-05 14:59:30 +02:00
Uwe Bonnes
ef816e3183 hosted: add libftdi implementation, remove old implementation. 2020-06-05 14:59:30 +02:00
Uwe Bonnes
9969c984f3 detour jtag primitives. 2020-06-05 14:59:30 +02:00
Uwe Bonnes
e34a27f72c Detour swd primitives. 2020-06-05 14:59:30 +02:00
Uwe Bonnes
1e10b96b03 Allow multiple scan routines. 2020-06-05 14:59:30 +02:00
Uwe Bonnes
f3790b90e5 command.c: Simplify usage of serial_no serial number string. 2020-06-05 14:59:30 +02:00
Uwe Bonnes
05adcd9bf5 remote.c: Compile only relevant functions.
Do no compile firmware functions when compiling pc-hosted.
2020-06-05 14:59:30 +02:00
Uwe Bonnes
16967b4328 adiv5: Remove only local dp_idcode used from ADIv5_DP_t struct. 2020-06-05 14:59:30 +02:00
Uwe Bonnes
aabd07738e cl_utils: Use start of flash in memory map as default flash start. 2020-06-05 14:59:30 +02:00
Uwe Bonnes
ab7991c3a6 hosted: Add bmp_remote, remove old pc-hosted platform. 2020-06-05 14:59:30 +02:00
Uwe Bonnes
b0cf7d24bd adiv5.c: Fix another leak. 2020-06-05 14:59:30 +02:00
Uwe Bonnes
966ac4036d target.c: Check for valid flash structure. 2020-06-05 14:59:30 +02:00
Uwe Bonnes
b8b34e7b1d adiv5: remove cfg for AP structure, cfg is only used local. 2020-06-05 14:59:30 +02:00
Uwe Bonnes
425002a38f hosted: Add -l argument to list only available debuggers and exit. 2020-06-05 14:59:30 +02:00
Uwe Bonnes
13c3c934d2 Hosted: Add Stlink, remove old pc-stlinkv2 platform 2020-06-05 14:59:30 +02:00
Uwe Bonnes
783ec377d9 adiv5: Export extract. 2020-06-05 14:59:30 +02:00
Uwe Bonnes
60f39f55b4 MSP432: Warn when hardware version not supported. 2020-06-05 14:59:30 +02:00
Uwe Bonnes
dc3fd2eb06 Classify debug messages
Firmware BMP with ENABLE_DEBUG=1 will print WARN and INFO as before.
PC-Hosted BMPwill alway print to stderr. Warn is printed unconditional,
INFO, GDB, TARGET, DONGLE and WIRE will print if their appropriate bit in
cl_debuglevel is set via the -v verbose command line argument.
INFO will go to stdout with -t or -l.
2020-06-05 14:59:30 +02:00
Uwe Bonnes
09602a9e74 serial_unix: Simplify timeout setting. 2020-06-05 14:59:30 +02:00
Uwe Bonnes
eee16cf08a platforms/tm4c/jtagtap.c: Remove unreferenced and incomplete file. 2020-06-05 14:59:30 +02:00
Uwe Bonnes
7956fbc361 cl-utils: Print memory map when test is specified. 2020-06-05 14:59:30 +02:00
Uwe Bonnes
c5c21bb958 README.md: Mention the PC-Hosted GDB server. 2020-06-05 14:59:30 +02:00
Uwe Bonnes
8fea3f6baa pc/serial_xx: Change arguments for the open call. 2020-06-05 14:59:30 +02:00
Uwe Bonnes
b5182e09d0 cl_utils: When reading from flash to file, truncate the file. 2020-06-05 14:59:30 +02:00
Uwe Bonnes
9ade8b24f7 hosted: Add Readme.md 2020-06-05 14:59:30 +02:00
Uwe Bonnes
a09104c281 Build firmware executables as *.elf file 2020-06-05 14:59:30 +02:00
Uwe Bonnes
8db979798c cl_utils.c: Report read/write speed. 2020-06-05 14:59:30 +02:00
Uwe Bonnes
4698a26bab common/swdptap: Slight speed increase and better setup time for write. 2020-06-05 14:59:30 +02:00
Uwe Bonnes
dd022fcb44 platforms/pc: Add common usb utilities. 2020-06-05 14:59:30 +02:00
Uwe Bonnes
c5d0902d4c cl_utils: Fix memory leak. 2020-06-05 14:59:30 +02:00
Uwe Bonnes
64f3dff8a8 PC-Hosted: Better debug output. 2020-06-05 14:59:30 +02:00
Uwe Bonnes
52739def01 Copy relevant stlink files. 2020-06-05 14:59:30 +02:00
Uwe Bonnes
815e09bb1b cl-utils: Add more arguments 2020-06-05 14:59:30 +02:00
Valmantas Paliksa
b06c0ba8d5 bmp_remote: Use high level functions.
Based on #570 (OpenOCD HLA interface driver for Blackmagic), but now
usefull for bmp-remote.
2020-06-05 14:59:30 +02:00
Uwe Bonnes
386a4bfce7 hosted: Device detection and selection. 2020-06-05 14:59:30 +02:00
Uwe Bonnes
921c23eb74 serial_unix: Return instead of exit in case of error. 2020-06-05 14:59:30 +02:00
Uwe Bonnes
3290def5f8 Add empty compilable project. 2020-06-05 14:59:30 +02:00
Uwe Bonnes
ef558eebb8 CMSIS-DAP support.
Thanks to edbg, pyocd and openocd for code and ideas.
2020-06-05 14:59:30 +02:00
Uwe Bonnes
c3d509e6c0 Clean up PLATFORM_HAS_DEBUG
Use only for firmware platforms.
2020-06-05 14:59:30 +02:00
Uwe Bonnes
4ba6afed28 Add jlink pc-hosted platform. 2020-06-05 14:59:30 +02:00
Uwe Bonnes
9a46c6fd25 Allow BOARD_IDENT as function 2020-06-05 14:59:30 +02:00
Uwe Bonnes
efce2ae892 Do not compile jtagtap and swdptap when not needed. 2020-06-05 14:59:30 +02:00
Uwe Bonnes
563df2d354 Detour ADIv5 high-level functions. 2020-06-05 14:59:30 +02:00
Stoyan Shopov
34a13723d8 Decrease the control USB pipe size on f103 blackmagic probes to 8 bytes
Rationale:
In USB device mode, the f103 chip provides 512 bytes
of memory for USB traffic. In the 'master' branch
of the blackmagic probe, the control endpoint pipe size
is set to 64 bytes, effectively consuming a quarter
(1 'in' endpoint, 1 'out' endpoint == 2 endpoints,
2 /* endpoints */ x 64 /* bytes per endpoint */ == 128 bytes
out of 512 /* bytes of precious usb packet memory */).
The USB standard, for full speed devices, does allow
a control endpoint size of 8 bytes.

I am not too aware of all the details of the USB standard,
but the USB standard seems to allow fragmented transactions
on the control USB pipe (endpoint 0), which libopencm3
apparently supports:
libopencm3/lib/usb/usb_control.c:usb_control_send_chunk()

I am using this change (from 64, to 8 bytes)
on a windows 10 machine, on an stlink hardware
('PROBE_HOST=stlink'). It works on my machine.

This change can potentially provide other USB endpoints
in the blackmagic firmware with more memory
2020-06-05 13:58:08 +02:00
Dömötör Gulyás
69e330849d fix flash map for STM32G431, as it is a special case different from the STM32G47x and STM32G48x chips 2020-06-05 13:41:18 +02:00
Thomas Bénéteau
f9f928e9d6 Add support for LPC8N04 2020-06-05 12:33:51 +02:00
Mark Rages
34c0d5a1c9 When timeout is 0, timeout_is_expired() should return immediately. 2020-06-05 12:33:24 +02:00
Koen De Vleeschauwer
6eb1b09c1c pc-hosted semihosting 2020-05-27 12:51:29 +02:00
Koen De Vleeschauwer
541861e978 traceswo decoding 2020-05-16 15:04:35 +02:00
Koen De Vleeschauwer
54ee00b0f6 set semihosting sys_clock time origin 2020-05-13 17:50:39 +02:00
Uwe Bonnes
499309f648 stm32f1: Tell user about STM32F10(3) clone. 2020-05-13 13:07:55 +02:00
Alexey Shvetsov
1a83bc6892
Rename variant_string in efm32 samd samx5x (#659)
* Rename variant_string

Files efm32 samd samx5x uses same function name that collides during
linking (checked with gcc10)

Signed-off-by: Alexey 'Alexxy' Shvetsov <alexxyum@gmail.com>

* Also make xxx_variant_string static

Signed-off-by: Alexey 'Alexxy' Shvetsov <alexxyum@gmail.com>
2020-05-12 17:47:04 +02:00
Alexey 'Alexxy' Shvetsov
805464db23 Fix redefinition of io function
Now it should work fine with any gcc version. Old one produces error
like in #657

Signed-off-by: Alexey 'Alexxy' Shvetsov <alexxyum@gmail.com>
2020-05-10 10:58:03 +02:00
Uwe Bonnes
9b939f4a3a stm32f4: Fix option byte handling (#654)
Option bytes are not accessible with level 1 protection, so
Use FLASH_OPTCR(x)
Fix crash with "mon opt write xxxx"
Handle option manipulation better when HW Watchdog fuse is set
Allow abbreviated "mon option x<yyy>" commands
2020-05-05 12:52:32 +02:00
Sid Price
923949d5dd Fixed variable/function name clash building on Windows 2020-05-03 15:45:31 +02:00
Koen De Vleeschauwer
9f8c7be360 semihosting 2020-05-02 12:55:29 +02:00
Vegard Storheil Eriksen
d63e870e82 cdcacm: Fix UART interface OUT endpoint MPS in descriptor.
3e3e450 reduced the buffer size for the UART interface OUT endpoint to
32B, but left wMaxPacketSize at 64B. This effectively configures the
hardware to receive packets up to 32B in size while telling the host it
can send larger packets. On reception of a larger packet, the usb core
treats it as an error, drops the packet and replies with a STALL
handshake.

This commit fixes the issue by updating the descriptor to match the
buffer configuration.

Fixes #538
2020-05-01 12:39:40 +02:00
Uwe Bonnes
08bb4d5775 pc-hosted: Make JTAG work. 2020-04-27 20:30:51 +02:00
Koen De Vleeschauwer
8851504a41 new semihosting commands 2020-04-23 09:43:46 +02:00
Uwe Bonnes
ada17ada23 stm32f4/7: Always use largest flashsize for device family (#633, #635, #644)
Do not care for the FLASHSIZE register. Leave it up to the user to abuse
flash area the ST did not announce.
2020-04-21 17:04:07 +02:00
Pieter du Preez
d55cea871d Fixed overrun and formatting, when dumping data in swolisten.
The swolisten program failed to print the cbw buffer correctly while
in dump mode. As printf() is used to print the dump, it is expected
that the cbw buffer is zero-terminated, which would only be
the case, if the cbw buffer is initialized with zeros, before filling it
with new data. One could set the entire cbw buffer to zero, but it
will be more efficient to only set the size-th byte to zero.

Furthermore, if a '%' character appears in the data, printf() will
attempt to format it, causing unexpected results.

This patch fixes the above 2 problems, by:

1. using the size variable to set the size-th byte of the cbw
buffer to zero, before passing it to printf().

2. calling printf() with a "%s" formatting string, followed by the
data buffer, cbw.
2020-04-20 00:19:30 +02:00
Uwe Bonnes
164eb43f00 NRF5: Do not reset target options. 2020-04-14 19:01:43 +02:00
Uwe Bonnes
bea8436561 NRF5: Always set CORTEXM_TOPT_INHIBIT_SRST(#230)
The problem also happens with NRF52840. Set CORTEXM_TOPT_INHIBIT_SRST
for all NRF5 device.
People should be more persistent!
2020-04-14 18:11:23 +02:00
mean
d1468530bd add basic support for LPC11U68 (and maybe LPC11U68) 2020-04-06 23:36:49 +02:00
Francesco Valla
846dadcc39 lmi: add support for TM4C1294NCPDT 2020-04-03 19:42:24 +02:00
Uwe Bonnes
58a8571d5b stlink: Print Target voltage
This adds about 600 bytes.
2020-04-03 16:19:20 +02:00
Francesco Valla
8a9980cd06 pc/serial_unix: bump device path buffer size to 4096 bytes
Since dp->d_name can be up to 255 bytes long and the 'name' buffer variable is
is a superset of it, bump the size of the latter to 4096 bytes (correspoding
to PATH_MAX on Linux systems).
2020-04-03 11:05:11 +02:00
Uwe Bonnes
b4ab9f328e pc-hosted: Put serial handling in own files for unix and implement for windows.
- If host provided /dev/serial/by-id, device must not be given and
  multiple devices may be selected with -s <(partial) serial number>
- On windows, device must by specifies with -d
2020-03-31 17:02:56 +02:00
Uwe Bonnes
18ae2bb50d cl_utils.c: Include <windows.h> for windows builds that work on files. 2020-03-31 17:02:56 +02:00
Uwe Bonnes
1a0cee4e9d pc-hosted: Clean up Makefile.inc. 2020-03-31 17:02:56 +02:00
Uwe Bonnes
bd73adf9c7 bmp/pc platforms: Deduplicate code. 2020-03-31 17:02:56 +02:00
Uwe Bonnes
9ca401497c stm32/timing_stm32.c: Remove fixed constants and direct SCB access 2020-03-31 16:54:04 +02:00
Uwe Bonnes
c4d7232223 Export function to read out PIDR and use for samd and samx5x. 2020-03-26 19:05:57 +01:00
Uwe Bonnes
a0e42e229b Make more things static.
No functional change intendend.
2020-03-26 18:44:19 +01:00
Uwe Bonnes
eca3a8dd8f pc-stlinkv2: Make stlink_usb_get_rw_status static and allow to suppress errors
This helps to not overflow the console.
2020-03-26 17:56:12 +01:00
Uwe Bonnes
91d7656d86 stlink/bootloader: Really allow to detach.
- To reenumerate, rcc_periph_reset_pulse(RST_USB) seems enough.
- Document bootloader entry and exit behaviour of ST-LINK V2
- Document bootloader entry on ST-LINK V2-1
2020-03-26 17:15:32 +01:00
Uwe Bonnes
890b494290 pc-stlinkv2: Update README.md 2020-03-26 12:21:22 +01:00
Uwe Bonnes
effd43ce38 Harden cortexm_reset() and remove double reset(#601)
Thanks to Dave Marples <dave@marples.net> for input.
- Issue only one reset. Start with SRST. Only if not seen, use SYSRESETREQ
- Wait for release of DHCSR_S_RESET_ST before issuing more commands
- Add timeout to catch reset line stuck low
- Remove AP errors
2020-03-25 11:22:14 +01:00
Uwe Bonnes
bc84d803ea libopencm3: Update to Head March 25 2020 to ease windows compilation #394
Last libopencm3 upgrade resulted in problems for libopencm3 build on
windows. Cross-mingw builds where no affected. Recent changes of
libopencm3 seem unrelated to libopencm3 functionality used by BMP
2020-03-25 11:04:01 +01:00
Uwe Bonnes
2e185ba578 BMP/PC: Allow to compile with mingw64 (#615)
__USE_MINGW_ANSI_STDIO 1 must be set befor any windows specific included.
2020-03-24 17:59:13 +01:00
Uwe Bonnes
e57792c95e stm32_mem: Check file size before flashing(#614)
stm32mem is only meant to flash BMP to a STM32F103x(8|B). No need to
decipher the DFU interface string.
2020-03-22 16:40:06 +01:00
Uwe Bonnes
2b76ec0ea3 dfucore: Reject erase outside the allowed range
An illegal erase request may get emitted as the DFU program may erase
first. Checking before flashing is not enough.
2020-03-22 16:38:54 +01:00
Uwe Bonnes
a7efe7cc14 cl-utils: Display targets found.
+ other small changes in DEBUG output.
2020-03-10 17:34:30 +01:00
Uwe Bonnes
65cb886bb6 Export connect_under_reset. 2020-03-10 11:44:53 +01:00
Uwe Bonnes
2065c70888 adiv5: Split PRIx64 into two PRIx32 as nanolib does not support PRIx64. 2020-03-10 10:56:42 +01:00
Uwe Bonnes
75186f7d50 ADIv5: More CoreSight device decoding:
- MTB-M0+ (Simple Execution  Trace)
- M33: Devices need finer decoding (DEVTYPE at offset 0xfcc)
2020-03-08 22:37:59 +01:00
Uwe Bonnes
c7e7bd61b6 stlink: Do not wait for the reaction on the reset line.
pc-hosted will abort, if the reset line is held externally to some value.
As assert is either driven or driven open drain, we can assume assert
immediate. For deassert, logic levels differences between the debugger and
the debuggee may apply and other ways to check the result are needed, like
CORTEXM_DHCSR_S_RESET_ST.
2020-03-08 16:27:03 +01:00
Uwe Bonnes
e48d9ebc92 cl_utils: Allow to connect under reset. 2020-03-06 23:15:56 +01:00
Uwe Bonnes
919d9320fd Remove unrelated files. 2020-03-06 19:33:20 +01:00
Uwe Bonnes
05dc2e239e pc-hosted: Disable TPWR when blackmagic command line interaction terminates. 2020-03-06 17:16:33 +01:00
Extreme kefir
c94a03af48 STM32F1 High density devices DFU support(#587) 2020-03-05 19:58:55 +01:00
Uwe Bonnes
288620551f adiv5: Print out SYSROM PIDR.
We need to know more about what devices indicate proper PIDR and what
devices fail to do so.
2020-03-04 19:02:07 +01:00
Uwe Bonnes
8c959defca efm32: Make local functions static. 2020-03-04 18:44:40 +01:00
Uwe Bonnes
13b9fe1efc cl_utils: There is no need for a (dummy) target controller.
Fix for #593.
2020-03-04 16:57:05 +01:00
Uwe Bonnes
03d84d0d5c command line tools: Allow to set power. 2020-02-20 12:12:26 +01:00
zvova7890
7a595ead25 fixup F103x8 flash size before build dfu iface string
we handle F103x8 as F103xB with 128k flash
2020-01-22 16:01:39 +01:00
Uwe Bonnes
45fb12f9b6 cl-utils: Care for -j (JTAG) argument in test mode. 2020-01-21 11:49:45 +01:00
Sid Price
1a1cabc90b Remove explicit include of rcc.h and allow common file to steer the right file
Clean up DFU files with MCU explicit includes
2020-01-14 00:09:20 +01:00
Ondrej Mikle
2137e775a4 stlink: update docs on how ti reflash BMP back to STLink original firmware (#572)
* stlink: update docs on how ti reflash BMP back to STLink original firmware

* stlink: specify v2 in docs on reflashing back
2020-01-11 16:52:22 +01:00
Sid Price
ee553c9a50 Corrected error checking for socket functions (#577) 2020-01-11 16:47:02 +01:00
Uwe Bonnes
c3a3f7737f Hosted: Allow command line interaction. 2019-12-13 14:59:42 +01:00
Uwe Bonnes
ee316431f5 stlink for st-bootloader: Reset with platform_request_boot()
Both V2 and V21 switch to (ST) bootloader with powered reset.
2019-12-13 14:59:42 +01:00
Uwe Bonnes
470c8e8cf1 target_flash_erase: Do not crash when requesting erase of unavailable flash.
Allow to erase from command line.
2019-12-13 14:59:42 +01:00
Uwe Bonnes
b9eb467ecf Command line: Restrict verify to length of binary file. 2019-12-13 14:59:42 +01:00
Uwe Bonnes
269d38ce65 cl_utils: Allow to issue reset.
Issue reset only when flashing or when reset was requested.
2019-12-13 14:59:42 +01:00
UweBonnes
0b6f393d5b
Merge pull request #561 from UweBonnes/pc_prog
Command line interaction for pc-hosted platforms.
2019-12-08 16:57:58 +01:00
Uwe Bonnes
da5a0cd3f5 Infrastructure for command line interface to target
- Program, read and verify flash
- Test mode: Probe and attach to device and exit
2019-12-08 16:43:19 +01:00
Uwe Bonnes
ab396f9745 Allow %z specifier in windows builds. Supercedes #562. 2019-12-08 16:43:19 +01:00
Uwe Bonnes
1bef51e145 adiv5: Abort scanning APs after 8 void APs. 2019-12-08 16:43:19 +01:00
Uwe Bonnes
6d01c3c55b stlinkv2: Propagate AP errors
Needed when reading some memory region of unknown size.
2019-12-08 16:43:19 +01:00
Uwe Bonnes
bdd76de517 Erase: Fix endless erase when erase-area did not end on (page|block) boarder. 2019-12-08 16:43:19 +01:00
Uwe Bonnes
25d24e5c34 efm32: Allow to compile with -Og. 2019-12-08 16:43:19 +01:00
UweBonnes
ea779d1372
Merge pull request #567 from UweBonnes/438
Rebase EFM patch #438, compiling fine in all intermediate steps
2019-12-08 16:42:22 +01:00
Richard Meadows
5943552a6b [efm32] Probe for the EFM32 Authentication Access Port (AAP)
Supported functionality through this AP:
* Issuing a DEVICEERASE command
2019-12-08 16:21:02 +01:00
Richard Meadows
260fc88d8f [efm32] Add command to set and print bootloader enable status
This is a bit in the Lock Bit (LB) flash page, so it can only be
cleared by this routine
2019-12-08 16:17:02 +01:00
Richard Meadows
7f0d5febc3 [efm32] Print MSC Interrupt Flags to DEBUG after each flash write 2019-12-08 16:16:55 +01:00
Richard Meadows
e85df763b7 [efm32] add new devices PG12B, JG12B, GG11B, TG11B, GG12B
Rework MSC layout check
2019-12-08 15:55:12 +01:00
UweBonnes
f89542c79f
Merge pull request #203 from dlaw/master
Add LPC11xx command to read out unique ID from target. Restore Ram and registers after call.
2019-12-08 15:45:49 +01:00
Roland Ruckerbauer
5ec12e4103 Support arbitrary bit counts jtagtap_tdi_tdo_seq pc-hosted 2019-12-08 14:34:35 +01:00
Roland Ruckerbauer
d42477ebc5 Fix infinite loop in jtagtap_tdi_tdo_seq 2019-12-08 14:34:35 +01:00
Uwe Bonnes
f10ccfd83e f4discovery: Fix error with GCC9 being more picky with sizes. 2019-12-05 19:36:05 +01:00
Artur Maciuszonek
8a07f44435 Add support for the kinetis KL16Zxx devices. Tested on KL16Z128VFM4 custom hardware 2019-11-21 20:37:13 +01:00
Thiadmer Riemersma
1924aa4999 Make baudrate parameter of traceswo command mandatory for stlink/swlink, and superfluous on other platforms; change help message accordingly. 2019-11-19 20:20:13 +01:00
Uwe Bonnes
e7e34600a4 lpc11: Only print Idcode if not zero and not yet handled.
Otherwise for all Cortex-M not yet handled this LPC messages appears.
2019-11-17 13:24:39 +01:00
Ken Healy
9198c951bb Reduce flash space required for SAM D51/E5x driver
* Reuse functions that are common with the SAM D1x/D2x driver
* Only include the mbist and write8/16/32 user commands if
  SAMX5X_EXTRA_CMDS is defined
2019-11-17 12:45:49 +01:00
Ken Healy
d3c330ea1a Fix issues with Travis CI build
It appears the Travis version of gcc-arm-none-eabi doesn't allow the %x
printf format specifier for size_t arguments, in contrast with the
version I'm running on Ubuntu 18.04 (15:6.3.1+svn253039-1build1).
2019-11-17 12:45:49 +01:00
Ken Healy
26216beaab Microchip SAM D51 / E5x support
Adds a target driver for Microchip SAM D51 / E5x family.

Tested on SAMD51G19A and SAMD51J19A. According to the datasheet, the
D51 / E5x family share the same core feature set, differing only in the
addition of CAN (E51) or ethernet controllers (E53/54). All members of
the family should be equivalent from a debug and programming perspective.
2019-11-17 12:45:49 +01:00
Uwe Bonnes
5a05cedd7d pc-hosted/jtagtap.c: Handle DO as bytes (PR #552)
Fixes #540/#542
2019-11-10 17:36:58 +01:00
Kirill Zhumarin
28f0ced97e Support NXP LPC1343 2019-11-09 18:47:07 +01:00
dpslwk
67f9d26644 samd: Add support for L21 & L22 (PR #345) 2019-11-09 13:59:37 +01:00
Uwe Bonnes
04d9749f25 Makefile: Publish DFU binaries with the daily build. (#549)
Fixes #548.
2019-10-28 16:37:41 +01:00
Uwe Bonnes
76f9a6ad42 stm32: Portability changes. 2019-10-20 22:20:06 +02:00
Uwe Bonnes
b9249fe104 adiv5: Activate DP reset sequence, guarded with timeouts.
While not working on most STM32, it succeeds on STM32G474.
Thanks to Dave Marples <dave@marples.net>
2019-10-20 22:15:28 +02:00
Uwe Bonnes
c6f43cf23f Stlinkv2: Always call stlink_leave_state() first.
V2 devices after power on are in DFU mode. It is needed to leave DFU before
doing anything else.
2019-10-19 20:57:26 +02:00
Roland Ruckerbauer
58febdff79 Fixed tokenization of gdb monitor commands. 2019-10-19 13:25:26 +02:00
Daniel O'Connor
2eef202ee1 Use pkg-config to get CFLAGS & LDFLAGS for libftdi1
Pull request #535
2019-10-14 19:22:53 +02:00
Daniel O'Connor
0aedff6623 Set the accepted to socket to be blocking as that is what the code expects.
This is necessary on OSX (and probably BSDs) where they default to non blocking which causes recv() to return -1 with errno set to EAGAIN.
2019-10-14 12:45:10 +02:00
Thomas Bénéteau
4a8cba0e9c Add support for LPC1114/333 (LPC1100XL series)
This is not given in the user manual but the register immediately
following DEVICE_ID does apparently contain the correct part ID.
2019-10-13 13:01:19 +02:00
Ken Healy
5c805c7d35 Fix buffer overflow in adiv5_component_probe() 2019-10-12 11:44:08 +02:00
Dave Marples
90df8172ca Addition of pc-hosted variant and extensions to other targets to support it. 2019-10-08 19:16:12 +02:00
Uwe Bonnes
8a1d8bfba3 Stlink: Variant for Stlink V2 that works with the original ST bootloader.
Use https://github.com/jeanthom/stlink-tool.git for encrypted upload and
switch to BMP.
2019-10-08 18:18:19 +02:00
Uwe Bonnes
0ae7cea1ae Add LPC84 from UM11029, Rev. 1.4, tested on LPC845 Breakout board. 2019-10-08 18:17:43 +02:00
UweBonnes
286b987822
Merge pull request #527 from UweBonnes/fixes
Fixes
2019-09-29 16:59:54 +02:00
Uwe Bonnes
12a2659671 pc-stlinkv2: StlinkV3 seems only to work with STM devices, 2019-09-29 16:48:42 +02:00
Uwe Bonnes
0599d2161c pc-stlinkv2: Recognize another error and try to handle failing memread. 2019-09-29 16:48:31 +02:00
Uwe Bonnes
1cf0b8ac13 Make all arguments for all commands (struct *t, int argc, const char **argv).
-Wall on gcc8 otherwise warns without -Wno-cast-function-type but older
GCCs/CLang choke on that argument:
error: unknown warning option '-Wno-cast-function-type'; did you mean
 '-Wno-bad-function-cast'? [-Werror,-Wunknown-warning-option]

This adds 24 byte to the binary, as some functions are now called with
additional dummy arguments:
"Pushing and popping garbage to keep the system happy"
2019-09-29 12:44:55 +02:00
Uwe Bonnes
f010a567bd adiv5: Reject APs duplicating last AP.
Seen with TM4C129 on black MSP432R401 Launchpad. Scanning of APs is aborted,
so valid APs after duplicated APs are ignored.
2019-09-29 12:44:37 +02:00
Uwe Bonnes
fc3abf26ef stm32_mem: Fix native crashing in dfu-detach when repeatedly flashed. 2019-09-28 21:28:35 +02:00
Uwe Bonnes
afbde05cd3 Linker: Recent libopencm3 linker already sets the stack.
Thanks to Sid Price for noticing #520.
2019-09-23 22:48:21 +02:00
Uwe Bonnes
fae2966b72 Target: Default to nop-function() for all exported target functions.
Fixes #522.
2019-09-23 17:42:29 +02:00
UweBonnes
3a6947a68f
stlink: Check for baite variant. (#519)
If PC13/14 float and PB11 is pulled high, recognize as baite.
Handle as rev.1 board. Deciphered from:
http://www.avrki.ru/picture/articles/samodelniy_st_link_v2/shemf_st_link_v2.jpg
2019-09-05 20:37:16 +02:00
UweBonnes
609e6b135d
nrf51: Add nop_function as halt_poll. (#517)
Otherwise "tar  ext ...; mon s; att 2; quit", start new gdb "tar ext ..."
crashes, at least on pc-hosted platforms.
2019-09-04 13:50:13 +02:00
UweBonnes
6663da7ff5
cortexm.c: Fix DWT Mask (#516)
See #513
2019-09-04 13:28:55 +02:00
UweBonnes
00937348b3
Fixes to compile "make ENABLE_DEBUG=1 all_platforms" (#515) 2019-09-04 13:09:43 +02:00
UweBonnes
7dcb3295c6
Native: Link against nanolib. (#514)
This frees about 13 kB or 30 kB with ENABLE_DEBUG=1
2019-09-04 12:51:30 +02:00
Gareth McMullin
e6504e149b cortexm: Implement single register read/write 2019-09-01 20:38:38 +02:00
Gareth McMullin
7bcf7f4924 cortexa: Implement single register read/write 2019-09-01 20:38:38 +02:00
Gareth McMullin
20cad17ce3 target: Implement generic multi-register read/write 2019-09-01 20:38:38 +02:00
Gareth McMullin
19a8078f99 gdb: Implement 'p' and 'P' register access 2019-09-01 20:38:38 +02:00
Gareth McMullin
9f4cf4124e target: Add new methods for read/write individual regs. 2019-09-01 20:38:38 +02:00
UweBonnes
71b8a4e081
Merge pull request #511 from UweBonnes/pc-stlinkv2
Pc stlinkv2
2019-09-01 13:07:35 +02:00
Uwe Bonnes
1d868bfffb pc-stlinkv2: Detect stlink detach.
As libusb has no real async callback, we need to call libusb_handle_events()
in different places. While waiting for the gdb connection, we set the
socket to non-blocking and check additional for usb events in that loop. That
way, detach is also detected while waiting for connection. With debugger
attached, SET_IDLE_STATE ist missused for checking for usb events.
2019-09-01 12:19:14 +02:00
Uwe Bonnes
6f1cae9203 pc-stlinkv2: Wait for device attach. 2019-09-01 12:19:07 +02:00
Uwe Bonnes
86d0be9708 pc-hosted: Display morse message on controlling terminal. 2019-09-01 12:11:51 +02:00
Uwe Bonnes
80a9fd51ca Clarify STM32F103x8 Flashsize handling.
Should finally fix #471.
2019-09-01 12:11:51 +02:00
Uwe Bonnes
d39dc34382 pc-stlinkv2: Fix reg_read|write
- Fix wrong placed brace in cortexm_regs_write()
- Start writing with r0
- With register read, save only registers listed
2019-09-01 12:11:37 +02:00
Uwe Bonnes
d1ee827b4d pc-stlinkv2: STLINK_SWD_DP_ERROR seem unrecoverable. Throw exception. 2019-08-31 11:20:17 +02:00
Uwe Bonnes
0d61106f90 pc-stlinkv2: Remove redundant read of CoreID. 2019-08-31 11:20:17 +02:00
Uwe Bonnes
aef055bb6f adiv5: If setup AP0 fails, fail immediate. 2019-08-31 11:20:17 +02:00
Uwe Bonnes
a01109543e pc-stlinkv2: Return failure if STLINK_DEBUG_APIV2_INIT_AP fails. 2019-08-31 11:20:17 +02:00
Uwe Bonnes
d994565f2e pc-stlinkv2: Fix crash with serial given not matching connected devices. 2019-08-31 11:19:13 +02:00
Theodor M
052b5f830a Made script executable with python3.
Added braces for compatibility with python3, should still be valid python2 which interpretes these braces as a tuple with a single element and simplifies it to that element.
Replaced whitespaces with tabs as required by python3, since indentation must be uniform (either whitespaces or tabs).
Removed trailing whitespaces.

Tested by flashing various STM32 boards with blackmagic firmware using python3.7.
2019-08-30 15:09:35 +02:00
UweBonnes
5704c2fb5a
Merge pull request #508 from UweBonnes/swlink
swlink: Remove redundant conditional usbart_init().
2019-08-28 12:37:12 +02:00
Uwe Bonnes
2b7d4c5ade swlink: Remove redundant conditional usbart_init().
Noticed in #506.
2019-08-28 11:39:03 +02:00
Sid Price
35cb4e51e4 Windows Build Fixes GNU make 4.2.1 (#502)
After update of GNU make the tests for Windows OS are no longer needed. Note that GNU make 4.2.1 is used to build BMP under Windows OS.
Make native working

Again, the newer version of GCC make does not need the OS tests.
2019-08-28 10:45:41 +02:00
UweBonnes
e8bd066fe9
Merge pull request #505 from UweBonnes/pc-stlinkv2
Pc stlinkv2
2019-08-27 15:23:18 +02:00
Uwe Bonnes
82be49f052 Stlink: Add a README.md, mostly deprecating reflashing Stlinkv2/1. 2019-08-27 15:13:26 +02:00
Uwe Bonnes
5d59338de5 pc-stlinkv2: Try first to reset device if we read a strange version number. 2019-08-27 15:13:26 +02:00
Uwe Bonnes
5fbb3a44fd PC-STLINKV2/Libftdi: Better version string. 2019-08-27 15:13:26 +02:00
Uwe Bonnes
44f471db53 pc-stlinkv2: READMEM_8BIT needs to read 2 bytes for 1 byte requested.
Fix as seen in openocd.
SYSROM_PIDR2 has only 3 bits for the JEP106 identity code field, bits [6:4].
2019-08-27 15:13:26 +02:00
Uwe Bonnes
fa27649f87 Remove debug_bmp command on PC hosted platforms. 2019-08-27 15:13:26 +02:00
Uwe Bonnes
6bf4fd3598 pc-stlinkv2: CPU register read and write must be done with the AP set.
FIXME: Writing CPU registers on M4 of STM32H745 seems not to work.
2019-08-27 15:13:15 +02:00
Piotr Esden-Tempski
ebf3e9da04
Changed the Gitter chat link to Discord. 2019-08-26 17:22:02 -07:00
UweBonnes
e52e2f56c5
Merge pull request #500 from btashton/update_libopencm3
Target latest libopencm3 version
2019-08-15 10:16:13 +02:00
Brennan Ashton
443ced62d4 Target latest libopencm3
Required fixes:
 * use usbd_request_return_codes -- commit 54b117c5a5767df8dc114612dfd8e8cb88b72c6b
 * drop deprecated timer_reset() -- commit 034dbf20ff8c54dcbee5238390b37a0d35180f44
 * drop 48 & 120 MHz configs -- commit a9dde2832eb8039b9e0d21a50b9b991ddbfc4e2d
 * ld scripts: drop duplication of standard sections -- commit 9a05dcb6c0aef712052d337457838f6041ffd57a
2019-08-14 00:57:15 -07:00
UweBonnes
c9c8b089f7
Merge pull request #499 from smunaut/minor_enhancements
Minor enhancements
2019-08-13 19:58:26 +02:00
Sylvain Munaut
4289788e0b src: Replace sprintf with snprintf
snprintf is needed anyway, that's one less function to have :p
And it's bad practice anyway.

Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
2019-08-05 15:43:33 +02:00
Sylvain Munaut
1d4152a36f target: Make sure variant_string is consistent in size
It's a global symbol and LTO will complain if the one in this file and
the one in EFM32 target are inconsistent.

Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
2019-08-05 15:42:29 +02:00
Sylvain Munaut
544bcd9845 build: Allow support for .S assembly file in SRC
Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
2019-08-05 15:41:46 +02:00
Sylvain Munaut
804ec24df9 build: Apply OPT_FLAGS after platform Makefile.inc include
This allows the platform to specify another optimization level than
the default (like -Os if space is limited)

Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
2019-08-05 15:29:00 +02:00
Sylvain Munaut
ef372d0161 build: Use a separate NO_LIBOPENCM3 flag to disable libopencm3
This prepares to allow other architectures than pc
that don't use libopencm3.

Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
2019-08-05 15:24:16 +02:00
UweBonnes
fbf196378e
Merge pull request #496 from UweBonnes/stlinkv2
Stlinkv2
2019-07-28 16:45:20 +02:00
Uwe Bonnes
06078a8a98 stlinkv2.c: Ignore zero length memory transactions. 2019-07-28 16:28:18 +02:00
Uwe Bonnes
d92635b6a3 stlinkv2: Use stlink_usb_get_rw_status() where possible. 2019-07-28 16:27:52 +02:00
UweBonnes
5107a29699
Merge pull request #495 from UweBonnes/451
Fix upgrade compiling (by extending #451)
2019-07-20 14:32:09 +02:00
Uwe Bonnes
1b3acf3b8a pc-stlinkv2: Print serial number of V20 devices readable. 2019-07-20 13:34:21 +02:00
Uwe Bonnes
6323409fec upgrade: Honnor the PROBE_HOST make argument. 2019-07-19 18:42:06 +02:00
Uwe Bonnes
d98703e022 Do not download/build/clean libopencm3 directory when compiling for PC-hosted platforms. 2019-07-19 18:41:55 +02:00
Uwe Bonnes
8f6b266c54 Upgrade: Download needs to set the address. 2019-07-19 10:51:02 +02:00
Jeremy Elson
1c5ee1f11f Add blackmagic.bin as dependency of bindata.o so that running make
in upgrade will correctly rebuild the upgrade tool if the main binary
has changed.
2019-07-19 10:51:02 +02:00
UweBonnes
c19ca20e36
Merge pull request #493 from UweBonnes/weak
Remove weak attribute for less hassle with windows compiles
2019-07-18 23:49:24 +02:00
Uwe Bonnes
e29f2b4fb9 jtag/swd: Rename defines/make variables to allow removal of weak attribute
jtagtap.c is libopencm3 generic. Move to common.
2019-07-18 20:54:10 +02:00
Uwe Bonnes
067956266c Adiv5: Remove weak attribute to ease windows compile. 2019-07-18 18:16:19 +02:00
Uwe Bonnes
9e898cc4b8 adiv5: Add more coresight part numbers found on STM32MP157c-DK2 (#492).
Only print corename if not NULL.
2019-07-18 17:39:48 +02:00
UweBonnes
5176c38491
Merge pull request #466 from UweBonnes/stlinkv2
Add a new platform, running on the USB host and talking to an unmodified StlinkV2/3
2019-07-17 17:45:56 +02:00
Uwe Bonnes
dd3cb193f3 Indicate the Core in the Target list. 2019-07-17 17:38:21 +02:00
Uwe Bonnes
c44cb904b0 adiv5.c: Format debug output more tense. 2019-07-17 17:38:21 +02:00
Uwe Bonnes
205fce20e5 stlinkv2: mem_[read|write] needs to honor AP. 2019-07-17 17:38:21 +02:00
Uwe Bonnes
b9249ca8a6 stlinkv2: Recognize V21_MSD, e.g. on STM32MP157C-DK2. 2019-07-17 17:38:21 +02:00
Uwe Bonnes
634c07c432 adiv5: Add TSGEN. 2019-07-17 17:38:21 +02:00
Uwe Bonnes
82424b100b stlinkv2: Require STLINK V3 Rev > 2 as revision 1 can not read TARGETID. 2019-07-17 17:38:21 +02:00
Uwe Bonnes
9b764534e6 stlinkv2: Recognize Stlink V3E 2019-07-17 17:38:21 +02:00
Uwe Bonnes
3388e48d92 stlinkv2: Do not loop endless when Read DP fails. 2019-07-17 17:38:21 +02:00
Uwe Bonnes
9ed26645d3 Add pc_stlinkv2 platform, running on host, talking to original StlinkV2/3.
Stlink firmware needs to be recent.
2019-07-17 17:38:01 +02:00
Uwe Bonnes
fd3af639b0 Clean up some includes.
Includes #465, noticed by Sid Price.
2019-07-17 17:26:00 +02:00
Uwe Bonnes
bd530c8951 adiv5.c: Make functions weak where high level platforms may implement different. 2019-07-17 17:26:00 +02:00
Uwe Bonnes
5aebef4f64 Makefile: Indicate high level SWD/JTAG implemenatation. 2019-07-17 17:26:00 +02:00
Uwe Bonnes
df7458e35a Build-Infrastructure: Allow a different target name. 2019-07-17 17:26:00 +02:00
Uwe Bonnes
32d2b2c4bf jtag: Move device list to it's own file to allow reuse. 2019-07-17 17:26:00 +02:00
Uwe Bonnes
3b75cb9a5a gdb-server: Allow multiple instance. 2019-07-17 17:26:00 +02:00
Uwe Bonnes
9075411c93 Move gdb_if.c for stand-alone servers to common. 2019-07-17 17:26:00 +02:00
Stephen Roe
b4c680bb15 Add STM32G4
Based on #488 Stephen Roe, done as #491.
Fixes ID of STM32G03.
2019-07-17 17:24:23 +02:00
Simon Rasmussen
5a7ffe7a40 Fixed SAM3X8C large file flashing.
The datasheet specifies the EEFC_BASE(0) is at `0x400E0A00` and EEFC_BASE(1) is at `0x400E0C00` which means they're spaced 0x200 bytes apart rather than 0x400.
2019-07-17 14:37:07 +02:00
David R. Piegdon
02b2fdb2ae fix overwriting of still-needed value (refs #487)
this fixes a bug that was introduced in blackmagic PR #475 which lead to
firmware crashes when connecting to a BMP more than once without a
power-cycle.
2019-06-24 16:45:18 +02:00
Uwe Bonnes
589d297d20 stm32l0: Fix crash when only "monitor option" was requested.
PR #485
2019-06-12 12:54:29 +02:00
Alexander Zhang
880613d641 lpc_common: restore RAM and registers after IAP call
Restore the RAM and registers which are clobbered by an LPC IAP call.
This does not restore any additional RAM which might be clobbered
by a *particular* IAP call. (For example, flash programming always
clobbers the last page of RAM.)
2019-05-30 14:01:27 -04:00
David Lawrence
d3979a57b6 Add LPC command to read out unique ID from target.
This commit modifies lpc_iap_call() to work with IAP commands that
return additional data. If the "result" argument is non-null, 16
bytes of data (the maximum returned by any IAP command) are copied
to the specified address.
2019-05-30 14:01:12 -04:00
Sid Price
21434d6fbb Remove redundant include file 2019-05-26 23:27:32 +02:00
Richard Meadows
600bc9f029 Generate DEBUG warnings and return if malloc/calloc fail.
This is will make debugging earier if this does happen, rather than
dereferencing the null pointer (or passing it to memcpy, or worse).

blackmagic PR #475
2019-05-26 18:56:12 +02:00
Richard Meadows
61e9607594 [adiv5] Improvements in ADIv5
* Reference latest version of the ARM specification
* ROM tables - more debug information, including printing SYSMEM bit
* MEM-AP - reject when Debug Base Address entry is not
  present/invalid. These would only have errored in
  adiv5_component_probe.
* Fix maximum number of entries in Class 0x1 ROM Table to 960. See ARM
  IHI 0031E Table D3-1 ROM Table register summary.
* Resolve note in STM32H7 driver with explaination

blackmagic PR #474
2019-05-24 22:00:44 +02:00
Uwe Bonnes
703f88a969 gdb_main: Always release CPU when detaching.
Fixes Issue #413 and released as PR #477.
2019-05-23 13:17:54 +02:00
Richard Meadows
24a7b8b2bf [stm32h7] add revision command which reads the DBGMCU_IDC register
blackmagic PR #476
2019-05-21 23:20:13 +02:00
Richard Meadows
c336c300a3 [stm32h7,bugfix] Fix bug: target_add_flash called in attach
When `target_add_flash` or `target_add_ram` are called in an attach
function they may be added multiple times. This very much confuses
GDB. This issue has already been reported and fixed for `stm32l4` (See
Issue #455 ).

`stm32f4` and `stm32l4` are the only other cortexm drivers that
implement this pattern. These are both fine.
2019-05-21 22:38:16 +02:00
UweBonnes
2e1503f988
Merge pull request #467 from UweBonnes/stm32g03
Add Stm32G03 from reference manual Rev.2
2019-05-12 20:21:44 +02:00
Uwe Bonnes
984813a29d Add Stm32G03 from reference manual Rev.2
Not yet tested on a real part.
2019-04-24 12:29:58 +02:00
UweBonnes
7cb1858aca
Merge pull request #463 from sidprice/bmp_windows_build
Native Windows builds
2019-04-07 18:44:20 +02:00
Sid Price
2108bb7137 Native Windows builds
All except hydrabus and launchpad-icdi building in PowerShell.
2019-04-07 10:26:45 -06:00
UweBonnes
302ff20a6d
Merge pull request #434 from UweBonnes/nrf5
Nrf5
2019-03-21 19:43:29 +01:00
UweBonnes
88ec557683
Merge pull request #450 from jelson/prefix-fix-2
Improve parsing of commands that require enable or disable arguments
2019-03-20 11:23:11 +01:00
Jeremy Elson
3235fa2005 Improve parsing of commands that require enable or disable arguments:
* Accept prefixes of the words 'enable' and 'disable'
* Prevent silent failures on parse errors
* Print status after flag changes
* Fix missing includes
2019-03-19 12:56:44 -07:00
Boris Sorochkin
691ada17e9 Implement read device info for NRF5x 2019-03-10 21:45:47 +01:00
Uwe Bonnes
3f89fed32e nrf51: Use buffered direct write to flash. 2019-03-10 21:45:47 +01:00
Uwe Bonnes
4ecd13a9a3 nrf51: Fix crash with not argument given to "mon read". 2019-03-10 21:45:47 +01:00
Uwe Bonnes
db2f403417 sam4l: Remove noisy debug message. 2019-03-10 21:45:47 +01:00
Uwe Bonnes
a336ac2084 NRF5: New detection scheme. 2019-03-10 21:45:47 +01:00
UweBonnes
2b4000b2b4
Merge pull request #456 from newbrain/STM32L4memmap
Correction of #445 attach-detach problem
2019-03-03 17:06:25 +01:00
newbrain
6887628eaa Correction of #445 attach-detach problem
Memory map is now completely freed and rebuilt in the separate attach
function.
It was previoulsy split beween probe and attach and never released,
causing problems when reattaching to the same target.
2019-03-03 15:55:40 +01:00
UweBonnes
da62cbaa3d
Merge pull request #449 from jelson/width-fix
Use 32-bit variable for 32-bit read
2019-02-25 13:21:55 +01:00
Jeremy Elson
86ed86c2a2 Use 32-bit variable for 32-bit read. (Also fixes DEBUG compile
error due to mismatch of format and argument.)
2019-02-24 17:49:30 -08:00
UweBonnes
dcd20ef08c
Merge pull request #446 from UweBonnes/stm32f730_h750
Handle STM32F730 and STM32H750.
2019-02-21 20:18:19 +01:00
Uwe Bonnes
56fb0f7766 Handle STM32F730 and STM32H750.
Flash sector calculation was wrong with small flash sizes.
2019-02-21 19:19:10 +01:00
UweBonnes
a3bbdc26c0
Merge pull request #445 from UweBonnes/#432
Fixing stm32l4 target to allow probing w/o halting. Cleaned up from #432 from anyn99.
2019-02-21 19:17:00 +01:00
anyn99
3f8c40d3f5 Fixing stm32l4 target to allow probing w/o halting 2019-02-21 18:06:38 +01:00
UweBonnes
22265243ab
Merge pull request #360 from newbrain/ke04support
Kinetis KE04: Flash and debug support
2019-02-18 13:07:32 +01:00
newbrain
8de1b45c85 Kinetis KE04: Flash and debug support
Support for Kinetis KE04 8KiB, 64KiB and 128KiB variants in nxpke04.c
Target monitor commands for sector and mass erase.
Changes to kinetis.c MDM-AP target to support KE04.
Only KE04Z8 tested in HW.
2019-02-17 22:48:23 +01:00
UweBonnes
cdb04a4214
Merge pull request #442 from r0ck3tAKATrashPanda/master
Added ability to lock and unlock boot rom for samd controllers
2019-02-14 16:15:09 +01:00
Carl
02c1934c03 Added ability to lock and unlock boot rom for samd controllers 2019-02-13 16:33:07 -08:00
UweBonnes
7032abd2b0
Merge pull request #433 from UweBonnes/gcc8
Makefile: Add -Wnocast-function-type for compilation on gcc8.
2019-01-28 21:25:33 +01:00
Uwe Bonnes
a6b75bb4ef Makefile: Add -Wnocast-function-type for compilation on gcc8.
Older GCC versions do not warn for disabled warnings they do not know yet.
This is needed to compile with gcc8.
2019-01-16 23:17:17 +01:00
Richard Meadows
0b28232f72 [efm32] Assume Device Identification (DI) version 1 if we don't know the OUI (#402)
* [efm32] Assume Device Identification (DI) version 1 if we don't know the OUI

Silabs are using some additional OUIs we don't know about. Reported in issue #389
These should use a DI version 1 layout, so assume version 1 layout for OUIs we don't
know. However do print a notice about this on DEBUG() as suggested by @UweBonnes

The IDCODE value is sufficient to make a positive identification of an EFM32 device.
See AN0062 Section 2.2. Therefore accepting any OUI is reasonable behaviour.
Additionally the part familiy is checked, and the target rejected if not in the
`efm32_devices` table. This commit makes that rejection explicit, although it does
not change the logical behaviour here.

Note that the important registers (part number, part family, flash size) are at the
same addresses in both layouts anyhow. Currently only `efm32_cmd_serial` and
`efm32_cmd_efm_info` functions use registers that differ between DI versions.

* [efm32] tidy format warning about portability UB

* [efm32] Simplify OUI checking

* Only read the OUI once
* Accept the device even if the OU is unknown, as silabs have been using
  a variety of OUIs
* Perform fewer register reads before checking the device family is valid
2019-01-16 09:58:59 +13:00
UweBonnes
488436c46a
Merge pull request #428 from UweBonnes/stm32g0
Stm32 functional additions and fix
2019-01-09 17:17:56 +01:00
Uwe Bonnes
7cc02867ae stm32f4: Fix problems with small flash sizes creating overflow or empty regions.
Thanks to "DerMeisteRR" for pointing out.
2019-01-09 12:23:49 +01:00
Uwe Bonnes
47fad2bf7f Add Stm32L41x. 2019-01-09 12:23:49 +01:00
Uwe Bonnes
f0c6e2bbd2 Add STM32G07x. 2019-01-09 12:23:49 +01:00
UweBonnes
a65ce77466
Merge pull request #427 from UweBonnes/mingw_ftdi
libftdi: Allow to compile with mingw and cygwin and use recent libftdi1.
2019-01-08 22:29:36 +01:00
Uwe Bonnes
0793dac2cf libftdi: Allow to compile with mingw and cygwin and use recent libftdi1.
Tested with x86_64-w64-mingw32-gcc-8.2.0 and cygwin gcc (GCC) 7.3.0.
Use libftdi1 unconditionally.
Try to convice github travis to use libftdi1.
Remove unportable "uint ". Thanks to jacereda for pointing out in #400.
2019-01-07 15:31:57 +01:00
Ingmar Jager
3f0c9ccee1 Fix support for LPC1115 and LPC1115XL devices (#415)
* Add support for LPC11U3X devices.

The DeviceID register has a different address from the LPC11XX devices.
But it is shared with the LPC8XX family.

* Fix support for LPC1115 and LPC1115XL devices

* Fix whitespace
2019-01-07 13:34:00 +13:00
Manoel Brunnen
7cfeb61399 Add udev rules 2019-01-07 13:32:58 +13:00
Josh Robson Chase
02b9d5f1ac Add delay to cortexm_reset 2019-01-07 13:32:17 +13:00
Josh Robson Chase
d7e2923990 Debug on stm32f1_flash_erase errors 2019-01-07 13:32:17 +13:00
Uwe Bonnes
525b90d4e5 cortexm: Only force halt before probe() if probe was forced. 2019-01-07 13:22:01 +13:00
Uwe Bonnes
6df793dbf0 Revert "Allow to specificy if SRST is asserted and when it is released."
This reverts commit 44fc24e0e747293fa05b62ed7439501553829b0b.
2019-01-07 13:22:01 +13:00
Uwe Bonnes
da75acf015 adiv5: Only force cortexm_probe() once. 2019-01-07 13:22:01 +13:00
Uwe Bonnes
9ce05ae67b stm32h7/f7: Store DBGMCU_CR on attach() and restore on detach().
On STM32[FH]7, DBG_SLEEP must be set for debugging.
2019-01-07 13:22:01 +13:00
Uwe Bonnes
489f24584b adiv5: Read TARGETID on DPv2 devices. 2019-01-07 13:22:01 +13:00
Uwe Bonnes
8d6092b73f cortexm_forced_halt: Only release SRST after "Halt on reset" command.
This should make life easier if program remaps JTAG/SWD pins so that
with program running, JTAG/SWD access is impossible.
2019-01-07 13:22:01 +13:00
Uwe Bonnes
cde7726b87 cortexm: detach still needs extra cycles. 2019-01-07 13:22:01 +13:00
Uwe Bonnes
3ebf049424 cortexm: Only force halt before probe if idcode is unknown and ROM TABLE unreadable. 2019-01-07 13:22:01 +13:00
Uwe Bonnes
6633f74d95 stm32h7/f7: Write DBGMCU_CR only on attach.
Split probe/attach for STM32H7.
2019-01-07 13:22:01 +13:00
Uwe Bonnes
8575d3e7a6 stm32f7/h7: Use the DPv2 provided idcode for MCU identification. 2019-01-07 13:22:01 +13:00
Ingmar Jager
14bedcc441 Add support for LPC11U3X devices.
The DeviceID register has a different address from the LPC11XX devices.
But it is shared with the LPC8XX family.
2018-10-04 08:53:05 -07:00
Benjamin Vernoux
771d81a5f0 Fix link for windows_dfu_util 2018-10-03 15:20:09 -07:00
Uwe Bonnes
d8b01ff61f swlink: Enable UART2 for SWO.
Stlink on STM8S-Disco needs additional wiring for SWO.
2018-10-03 15:19:33 -07:00
Uwe Bonnes
7cafc44bd9 swlink: Allow to enable debug on second VCOM. 2018-10-03 15:19:33 -07:00
Uwe Bonnes
0d246fb31a swlink: Measure voltage on VDD pin of Stlink/Stm8s. 2018-10-03 15:19:33 -07:00
Uwe Bonnes
184ef991bf swlink: Handle LED. 2018-10-03 15:19:33 -07:00
Uwe Bonnes
06272e0a59 swlink: Implement dfu_upgrade. 2018-10-03 15:19:33 -07:00
Uwe Bonnes
530d1e5c28 swlink: Handle force boot on bluepill. 2018-10-03 15:19:33 -07:00
Uwe Bonnes
b744d8b0c9 swlink: Implement NRST. 2018-10-03 15:19:33 -07:00
Uwe Bonnes
1263d185a6 swlink: Distinguish between Stlink on STM8-Disco and "blue pill". 2018-10-03 15:19:33 -07:00
Nikolay Dimitrov
29386aee14 scripts/stm32_mem: Fix issue with scanning USB DFU devices
While scanning the USB bus for devices, stm32_scan() can find a device that it
doesn't have permissions to access it, dfu/usb class raises an exception and
stm32_scan() stops the scan completely.

This fix resolves the scan issue, by allowing the scan loop to continue.
While at it, there are cosmetic fixes related with tabs/spaces and readability.

Signed-off-by: Nikolay Dimitrov <nikolay.dimitrov@retrohub.org>
2018-09-17 14:36:28 +12:00
Gareth McMullin
7f947d724c
Merge pull request #393 from markrages/add_id_2
Another nRF52 ID.
2018-09-14 11:21:04 +12:00
Mark Rages
91dd879dac Another nRF52 ID. 2018-09-13 16:18:29 -06:00
Gareth McMullin
3a598a0cf3
Merge pull request #384 from rikvdh/feature/readable-reset-stlink
Change the ST-Link SRST reset function
2018-09-07 08:13:48 +12:00
Gareth McMullin
f328ca5181
Merge pull request #391 from UweBonnes/swd_cycles
adiv5_swdp: Add extra idle cycles with write transactions.
2018-09-07 07:58:41 +12:00
Uwe Bonnes
f5cf6d4497 adiv5_swdp: Add extra idle cycles with write transactions.
These extra cycles are needed by some CPU, e.g. STM32L0x1 to cross the SWCLK
/HCLK domains. Revert insufficient #373 also tackling that problem.

Thanks to Thorsten von Eicken for pointing out.
2018-09-06 17:29:20 +02:00
Gareth McMullin
db544e9b67
Merge pull request #390 from rikvdh/feature/lpc_with_iap_down
Move the LPC17xx probe function down
2018-09-06 08:15:54 +12:00
Rik van der Heijden
95053b3b4e Change the ST-Link SRST function to use libopencm3 helper functions and fix waiting for the pin-state, change init to use the SRST function for reset de-assertion 2018-09-05 20:28:02 +02:00
Rik van der Heijden
f39701c4c8 Move the LPC17xx probe function down since it performs an IAP call which can hang when performed on other devices than a LPC17xx 2018-09-05 17:40:02 +02:00
Gareth McMullin
c5c0783337
Merge pull request #378 from markrages/nordic_unlock
Add extra port for mass erasing / unprotecting nRF52 with APPROTECT set.
2018-07-28 14:56:03 +12:00
Mark Rages
d0a8ce0819 Add extra port for mass erasing / unprotecting nRF52 with APPROTECT set.
Mostly copied from the equivalent in kinetis.c and
https://devzone.nordicsemi.com/f/nordic-q-a/12484/approtect-and-dap/47301
2018-07-27 16:07:19 -06:00
Gareth McMullin
6fd3ede5c7
Merge pull request #377 from markrages/add_id_2
Another chip ID for Nordic nRF52832.
2018-07-28 09:53:00 +12:00
Gareth McMullin
8f9a9c4d71
Merge pull request #286 from UweBonnes/h7
stm32h7: Start of support.
2018-07-28 09:51:47 +12:00
Mark Rages
cb8596b0b2 Another chip ID for Nordic nRF52832. 2018-07-27 15:09:14 -06:00
Uwe Bonnes
5918608156 STM32F7: Debug does not work with WFI without DBG_SLEEP 2018-07-27 10:59:54 +02:00
Uwe Bonnes
2c1c913213 adiv5.c: Add units found on M7. 2018-07-27 10:59:54 +02:00
Uwe Bonnes
f234074099 stm32h7: Start of support.
Implement probe, memory map, erase, write, uid, crc, parallelism.
2018-07-27 10:59:54 +02:00
Gareth McMullin
a988bba035
Merge pull request #372 from richardeoin/efm32-1
[efm32] Add support for EFM32 devices with different DI and MSC layouts
2018-07-27 11:41:58 +12:00
Gareth McMullin
d7b173ab39
Merge pull request #310 from UweBonnes/stm32l4r
arget/stm32l4.c: Add stm32l4r series and clean up.
2018-07-27 10:32:00 +12:00
Gareth McMullin
833407d299
Merge pull request #376 from miek/nrf52840-qiaa-c0
Add nRF52 QIAA C0
2018-07-27 10:25:45 +12:00
Mike Walters
b4dc666aca Add nRF52 QIAA C0 2018-07-26 23:13:38 +01:00
Uwe Bonnes
4a312c7697 target/stm32l4.c: Add stm32l4r series and clean up. 2018-07-22 15:44:00 +02:00
Uwe Bonnes
7034d0bb94 stm32l4: Option byte loader must be started with flash unlocked!
Warn user that device will loose connection.
2018-07-22 15:44:00 +02:00
Uwe Bonnes
83f9655f6e stm32l4: Fix wrong default for WRP2A option halfword. 2018-07-22 15:44:00 +02:00
Gareth McMullin
0551809475
Merge pull request #373 from UweBonnes/fixes
Fixes for detach and stm32mem
2018-07-20 08:36:12 +12:00
Uwe Bonnes
139707c5c0 cortexm/detach: Add a dummy transaction after cleaning DHCSR.
This replaces the seemingly superflous swdptap_seq_out() at
the end of adiv5_swdp_low_access() needed to continue after detach.
2018-07-19 10:57:41 +02:00
Uwe Bonnes
7908ba526b stm32_mem: Guard dfu.dfu_device with try/except. 2018-07-18 23:31:55 +02:00
Richard Meadows
a7106bd346 [efm32] Add support for flashing User Data (UD) and Bootloader (BL) regions
* UD region on all devices, some devices also have BL region
* Fix page size for EZR32HG
2018-07-18 08:57:01 +00:00
Richard Meadows
55bb96cfdb [efm32] tidy compiler warning 2018-07-16 20:47:24 +00:00
Richard Meadows
98faaceb70 [efm32] Add support for EFM32 devices with different DI and MSC layouts
* DI layout is identified by attempting to read OUI from both layouts
* MSC address is passed to flashstub in r3

Retested EZR32LG230 (EZR Leopard Gecko M3)
Tested EFR32BG13P532F512GM32 (EFR Blue Gecko)

Achieves aims of PR #264 (I think) Thanks to @dholth and @ryankurte for inspiration
Fixes Issue #226
2018-07-16 20:18:36 +00:00
Gareth McMullin
667cce7d17
Merge pull request #370 from sinihappo/alo-stm32f0x-option-erase-fix
Fixes option erase for STM32F070x6 STM32F070xB STM32F030xC
2018-07-11 11:51:14 +12:00
Antti Louko
59d6eca8f0 Fixes option erase for STM32F070x6 STM32F070xB STM32F030xC 2018-07-10 18:44:05 +03:00
Gareth McMullin
c5713ea8d3
Merge pull request #366 from UweBonnes/f7_fix
stm32f4.c: F76x also has large sector by default.
2018-07-07 13:03:14 +12:00
Gareth McMullin
1b51c4961e
Merge pull request #363 from korken89/master
Removed debug bits for F4/F7 target, same as all other MCUs now
2018-07-07 13:01:05 +12:00
Gareth McMullin
46b681e050
Merge pull request #361 from UweBonnes/gpio_swd
Speed up bitbanging SWD/JTAG
2018-07-07 13:00:32 +12:00
Uwe Bonnes
50514ccc31 stm32f4.c: F76x also has large sector by default. 2018-07-05 13:29:43 +02:00
Emil Fresk
5e8c8cae10 Removed debug bits for F4/F7 target, same as all other MCUs now 2018-06-28 16:31:34 +02:00
Uwe Bonnes
7a7266a0f7 Speed up JTAG. 2018-06-26 19:50:14 +02:00
Uwe Bonnes
5548d54626 common/swdptap: some clean up.
Remove superfluous transaction.
Use native variable size.
2018-06-26 19:50:14 +02:00
Uwe Bonnes
7e3fe352ad adiv5_swdp.c: Use swdptap_seq_out for initialiation sequence. 2018-06-26 19:50:14 +02:00
Uwe Bonnes
e54a826745 common/swdptap.c: Speed up by "unrolling" swd.._seq_...() for GPIO.
Try to have sensible setup/hold times by evenntually duplicated or
logically useless port commands.
Loading code to RAM on a STM32L476 got up from 46 to 83 kB/sec.
2018-06-26 19:50:14 +02:00
Uwe Bonnes
59e03dea27 Keep TMS floating until scanning.
NRF5x shares nRST with SWDIO and otherwise does not run until scan is done.
2018-06-26 19:50:14 +02:00
Uwe Bonnes
97561fc5cc stlink: Decrease delay with SWD turn around for native,stlink and swlink. 2018-06-26 19:50:14 +02:00
Gareth McMullin
d4d24c256c
Merge pull request #362 from UweBonnes/fix_ftdi
libftdi/jtagtap.c: Fix error introduced with commit de33473
2018-06-26 10:36:06 -07:00
Uwe Bonnes
633af5bb85 libftdi/jtagtap.c: Fix error introduced with commit de33473
Seen when scanning e.g. Zync with mon jtag 6 4.
2018-06-26 17:43:06 +02:00
Gareth McMullin
b2defad844
Merge pull request #356 from UweBonnes/probe_halted
Probe halted
2018-06-21 10:06:56 -07:00
Gareth McMullin
1799ea3b71
Merge pull request #357 from UweBonnes/write_access_size1
Write access size1
2018-06-21 10:05:45 -07:00
Uwe Bonnes
b59bbac0b2 stm32l4: Use buffered direct write to flash. 2018-06-16 13:30:53 +02:00
Uwe Bonnes
891d6de8eb stm32f1.c: Use buffered direct write to flash with half word access. 2018-06-16 13:30:53 +02:00
Uwe Bonnes
f1752c7a1a stm32f4: Allow DWORD parallelism.
Needs external VPP!
2018-06-16 13:30:53 +02:00
Uwe Bonnes
15312eb86c stm32f4: Honor parallelism also for erase. 2018-06-16 13:30:53 +02:00
Uwe Bonnes
bfeb6f0db9 stm32f4: Use buffered direct flash write with choosen size. 2018-06-16 13:30:53 +02:00
Uwe Bonnes
54f73858f9 Provide a target function to write with given size. 2018-06-16 13:30:08 +02:00
Uwe Bonnes
17b817f37b cortexm: Allow to set timeout to wait for halt.
This allows to gain access to devices spending long time in WFI without
the need for a reset, at the expense of possible long waiting times.
Using Reset means loosing the device runtime context.
2018-06-13 14:03:50 +02:00
Uwe Bonnes
9e365a58f7 Cortex-M: Try harder to halt devices in WFI.
E.g. STM32F7 and L0 need multiple C_DEBUG and C_HALT commands to halt
the device.
2018-06-13 14:02:43 +02:00
Uwe Bonnes
44fc24e0e7 Allow to specificy if SRST is asserted and when it is released.
E.g. for STM32L0 and F7, IDCODE register can not be read while device is
under Reset.
2018-06-13 13:46:07 +02:00
Uwe Bonnes
66e357d517 Cortex-M: Probe Cortex-M even if ROM table read fails.
Rom table in some devices (e.g. STM32L0/F7) can not be read while
device is in WFI. The Cortex-M SWD signature is however available.
If we know by that signature, that we have a Cortex-M, force a
probe for Cortex-M devices.
2018-06-13 13:04:17 +02:00
newbrain
ae6f0eadc9 Support for MSP432 TI MCUs (#353)
Introduces flashing and debugging support for Texas Instruments MSP432
series of MCUs
2018-06-07 08:34:21 +12:00
Gareth McMullin
b7a59afc59
Merge pull request #349 from esden/stm32f247-strings
Setting the stm32f247 driver string on scan.
2018-06-05 10:37:25 +12:00
Piotr Esden-Tempski
077e455a94 Setting the driver string on scan.
This way swdp_scan and jtag_scan commands will show the chip that was
detected instead of the generic STM32F4 string. The generic name is
most confusing when attaching to an STM32F7 target.
2018-06-01 12:46:14 -07:00
Gareth McMullin
80f003ff4b
Merge pull request #347 from UweBonnes/ftdi
libftdi platform improvements
2018-05-31 10:16:34 +12:00
Uwe Bonnes
2657aa6fbb libftdi: Allow more flexible Swd Read/Write Switching. 2018-05-30 19:21:03 +02:00
Uwe Bonnes
df05d7ce7b libftdi: Allow device specific port/pin to read SWD bitbanged.
Gracefully abort swd scan if devices can not do SWD.
Best effort to indicated SWD capability on existing cables and
add descriptions for the cables.
2018-05-30 19:21:03 +02:00
Uwe Bonnes
fce25b9fd5 libftdi/swdptap.c: Substantial speed increase for bitbanging SWD.
Provide the swd sequences unrolled.
2018-05-30 19:21:03 +02:00
Uwe Bonnes
992ccf91a9 libftdi/swdptap.c: Use MPSSE Mode for bitbanging SWD. 2018-05-30 19:21:03 +02:00
Uwe Bonnes
f3cacba219 libftdi: Flush buffer with detach. 2018-05-30 19:21:03 +02:00
Uwe Bonnes
2ec078cfcf libftdi/jtagtap.c: Allow NULL as one DI/DO argument jtagtap_tdi_tdo_seq.
Implement jtagtap_tdi_seq() by calling jtagtap_tdi_tdo_seq().
2018-05-30 19:21:03 +02:00
Uwe Bonnes
de33473535 libftdi/jtagtap: Copy DI direct into the write buffer. 2018-05-30 19:21:03 +02:00
Uwe Bonnes
aa938c6dae libftdi/jtagtap: Try harder to initialize Ftdi MPSSE jtag mode.
After "mon s" at least the second "mon j" now succeeds again.
2018-05-30 19:21:03 +02:00
Uwe Bonnes
c548e307fe libftdi/jtagtap: Clean up code. 2018-05-30 19:21:03 +02:00
Uwe Bonnes
7d45bd4869 ibftdi/jtagtap: Remove magic numbers. 2018-05-30 19:21:03 +02:00
Uwe Bonnes
6f0a46d9c1 libftdi: Export active cable description. 2018-05-30 19:21:03 +02:00
Uwe Bonnes
68c7180376 libftdi: Add ftdiswd variant. 2018-05-30 19:21:03 +02:00
Uwe Bonnes
f4bc6f9ddd libftdi/platform.c: Issue SEND_IMMEDIATE before reading. 2018-05-30 19:21:03 +02:00
Uwe Bonnes
744deb678d libftdi/platform.c: Only set bit direction with MPSSE SET_BIT_XXXX. 2018-05-30 19:21:03 +02:00
Gareth McMullin
48d232807e
Merge pull request #337 from adamgreig/stm32f4-ram-size
Update maximum RAM sizes for F4 and F7 devices
2018-04-26 13:38:11 +12:00
Gareth McMullin
0f2f1d74a2
Merge pull request #334 from gsmcmullin/split_probe_attach
Split probe and attach
2018-04-26 13:28:08 +12:00
Adam Greig
e1cefb2031 Update maximum RAM sizes for F4 and F7 devices 2018-04-24 11:06:07 +01:00
Uwe Bonnes
93f3b14b68 stm32f1(f0): Do not read normal device registers during probe.
Device may not be halted and memory map setup may fail.
2018-04-23 11:06:08 +12:00
Uwe Bonnes
a0596a0dcc stm32l4: Build Memory Map during attach.
Reading target registers while target not halted may fail and result in
invalid memory map.
2018-04-23 11:06:08 +12:00
Uwe Bonnes
5f404cdbc0 Construct memory map on the stack
The memory map uses 1k of SRAM and is only needed during attach. Release
after use lowers pressure on SRAM.
2018-04-23 10:51:04 +12:00
Uwe Bonnes
6127a6431e stlink: Check nRST line level when setting SRST.
Problem: On some boards flashing hanged.
Cause: Releasing SRST caused a slow rise of nRST and flashing
started while the target still was in reset.
Attention: platform_delay(ms) only resolved 0.1 s.
Nucleo-P boards have SRST unconnected to target nRST by default.
2018-04-23 10:48:05 +12:00
Gareth McMullin
63967346cd stm32f4: Don't duplicate resources on reattach. 2018-04-23 10:48:05 +12:00
Gareth McMullin
00decb3718 target: Separate function to free memory map. 2018-04-23 10:48:05 +12:00
Gareth McMullin
1fd2a24c2d stm32f4: Only construct memory map at attach. 2018-04-23 10:48:05 +12:00
Uwe Bonnes
72c1498ae1 stlink: Make SWO Trace Buffer smaller.
Changes for delayed memory map setup otherwise overflow SRAM silently.
2018-04-23 10:48:05 +12:00
Gareth McMullin
455e0a74d2
Merge pull request #302 from gsmcmullin/always_buffer_flash
Only support buffered flash writes
2018-04-23 10:45:25 +12:00
Gareth McMullin
9d7925792f Merge branch 'master' into always_buffer_flash 2018-04-23 10:40:20 +12:00
Gareth McMullin
28bd4fc0ce
Merge pull request #305 from UweBonnes/swo_async
Use async SWO from the bluepill pull request.
2018-04-09 08:27:49 +12:00
Mike Walters
fa62403ee3 nrf51: Add nRF51802 device id. (#331) 2018-04-03 10:45:56 +12:00
Uwe Bonnes
29cdba0d70 SWO: Some explanations and a test program. 2018-03-27 13:40:49 +02:00
Uwe Bonnes
fc25a3339a traceswoasync: Implement async swo for stm32.
Use for stlink.
Uses dma with large buffer.
Pull up swo to provide idle level on unconnected swo pin.
2018-03-27 13:40:49 +02:00
Uwe Bonnes
93bc3a155a traceswo: Provide command option for async swo. 2018-03-27 13:40:49 +02:00
Uwe Bonnes
3e3e450408 cdcacm.c: Use less buffer for the usb_uart buffers and reallocate.
With 128 bytes for both usb_uart buffers, traceswo gives errors!
Keep the size for the receive buffer and diminisch the transmit buffer,
as there is no flow control to the device.
Probably related to https://github.com/libopencm3/libopencm3/issues/477
2018-03-27 13:40:49 +02:00
Gareth McMullin
cfaa5ea963 Merge branch 'korken89-master' 2018-03-27 13:01:06 +13:00
Gareth McMullin
76bfb4929d Use lowercase register names. 2018-03-27 13:00:39 +13:00
Gareth McMullin
90f7bdcd09 Merge branch 'konsgn-master' 2018-03-27 08:08:02 +13:00
Gareth McMullin
a3f855ce5c Merge branch 'master' of https://github.com/konsgn/blackmagic into konsgn-master 2018-03-27 08:03:03 +13:00
Christopher Woodall
31965a5bbc Added support for k64 (#301) 2018-03-25 14:43:33 -07:00
Akila Ravihansa Perera
471ce2547c Added LPC17xx support (#317) 2018-03-25 12:53:30 -07:00
Mark Rages
a41d8cb97a Another nRF52 device id. (#315) 2018-03-25 12:37:51 -07:00
Gareth McMullin
0c659f49cd
Merge pull request #322 from jrwhite/master
hexprog.hex fails due to divide-by-zero
2018-03-25 12:35:52 -07:00
Emil Fresk
1ee6d4503e Update to split 'special' into its sane parts (update from @mubes) 2018-03-24 16:44:59 +01:00
jrwhite
0ddd8b55d7 divide-by-zero fix 2018-03-11 14:35:38 -05:00
Konsgn
04fbabb299 mkl27 support 2018-01-21 23:43:01 -05:00
konsgn
1fe870b8df added MKL27<128kB support 2018-01-16 13:23:36 -05:00
Gareth McMullin
a9219c3616
Merge pull request #314 from adamheinrich/usbuart-ignore-noise
platforms/stm32: Ignore noise errors on USBUART
2018-01-15 08:29:18 +13:00
Adam Heinrich
f5cac4c78d platforms/stm32: Ignore noise errors on USBUART 2018-01-13 21:11:17 +01:00
Gareth McMullin
dd055b675e
Merge pull request #313 from UweBonnes/stm32f3_ccm
stm32f1.c: Add missing fall through statement needed by GCC7.
2017-12-18 10:33:08 -08:00
Uwe Bonnes
922f857de7 stm32f1.c: Add missing fall through statement needed by GCC7. 2017-12-18 13:56:59 +01:00
Gareth McMullin
a3484e3d3b
Merge pull request #311 from UweBonnes/f3_ccm
stm32f1.c: Export CCM RAM of F303.
2017-12-12 14:49:21 -08:00
Uwe Bonnes
1f3c235205 src/target/stm32f1.c: Add CCM Ram of STM32F303 devices. 2017-12-08 13:39:24 +01:00
Gareth McMullin
568655063f
Merge pull request #300 from gsmcmullin/m7-cache
Cache support for Cortex-M7
2017-11-07 08:44:56 +13:00
Gareth McMullin
048e8447a5 target: Only support buffered flash writes 2017-10-13 08:58:37 +13:00
Gareth McMullin
c53a12bfd1 cortexm: Better cache support for Cortex-M7
- On probe, read CTR for cache presence and minimum line length
- Make D-Cache clean a function
- Clean before memory reads
- Clean and invalidate before memory writes
- Flush all I-Cache before resume
2017-10-12 09:26:01 +13:00
Nick Downing
0e5b3ab00e Make Cortex M driver write DCCIMVAC (Data cache clean and invalidate by address to the PoC=Point of Coherency) prior to reading or writing each 32 bytes of RAM 2017-10-12 08:41:58 +13:00
Gareth McMullin
9a5b31c37b Fix fallthrough warnings on gcc 7 2017-10-09 11:07:29 +13:00
Gareth McMullin
231d42d581 Merge pull request #297 from UweBonnes/write_size
target: Fix calculation of erase size.
2017-10-06 19:40:02 +13:00
Uwe Bonnes
120a2d9378 target: Fix calculation of erase size. 2017-10-05 22:11:01 +02:00
Gareth McMullin
5950d8f56c Merge pull request #293 from UweBonnes/write_size
target: Fix wrong size calculation for write.
2017-10-05 09:07:18 +13:00
Gareth McMullin
ed8366813d Merge pull request #294 from UweBonnes/stm32_mem
stm32_mem: Really wait 5 seconds for DFU device to appear.
2017-10-05 09:03:09 +13:00
Uwe Bonnes
dc29e45606 stm32_mem: Really wait 5 seconds for DFU device to appear. 2017-10-04 21:53:53 +02:00
Uwe Bonnes
a7815fff3d target.c: No need to split write while still in same flash block. 2017-10-04 21:52:29 +02:00
Uwe Bonnes
25610e5ec5 target: Fix unconsistant use of tmplen. 2017-10-04 21:52:29 +02:00
Gareth McMullin
72c86f939e Merge pull request #296 from gsmcmullin/libftdi_tdi_tdo_fix
libftdi: Fix tdi_tdo_seq result unpacking
2017-10-05 08:32:08 +13:00
Gareth McMullin
f27f3bad5c libftdi: Fix tdi_tdo_seq result unpacking 2017-10-05 08:26:33 +13:00
Gareth McMullin
2db42ba8e5 Merge pull request #287 from gsmcmullin/update_libopencm3
Update libopencm3
2017-10-04 10:58:44 +13:00
Gareth McMullin
19e58a7205 Merge pull request #284 from UweBonnes/stm32_mem
stm32_mem.py: Print longer strings and small formatting changes.
2017-10-03 10:41:04 +13:00
Uwe Bonnes
2b2b6d8f31 stm32_mem.py: Allow to set start address. 2017-10-02 21:30:56 +02:00
Uwe Bonnes
7cc9ee9d7a stm32_mem.py: Verify after write when bootloader supports upload
This should help people using STM32F103C8 above 64 k.
2017-10-02 21:30:56 +02:00
Uwe Bonnes
613208c939 stm32_mem: Allow to switch from dfu to application without flashing. 2017-10-02 21:30:56 +02:00
Uwe Bonnes
c41dfaef9a stm32_mem.py: Run automatically after switching to DFU mode. 2017-10-02 21:30:56 +02:00
Uwe Bonnes
4f3f4cb898 stm32_mem.py: Deny to work with the STM DFU bootloader
To support the STM DFU bootloader, the interface descriptor needs to be
evaluated. Erase may only be called once per sector.
2017-10-02 21:30:56 +02:00
Uwe Bonnes
4c6f735452 stm32_mem.py: Handle multiple devices. 2017-10-02 21:30:56 +02:00
Gareth McMullin
eb7547111a Merge pull request #285 from UweBonnes/f4_rework
F4 rework
2017-10-03 07:23:52 +13:00
Uwe Bonnes
0aa47113f3 stm32f4: Fix F4 dual bank OPTCR1 to option byte mapping. 2017-10-02 16:22:14 +02:00
Uwe Bonnes
c4d3712b39 stm32f4.c: Rework flash structure recognition.
Dual bank devices do not have sectors (8)12..15 !
Dual banks devices need to MER1 set for mass erase.
F72x has different FLASHSIZE_BASE
2017-10-02 16:22:14 +02:00
Gareth McMullin
0ed66547d5 Fix libopencm3 breakage 2017-09-25 11:17:03 +13:00
Gareth McMullin
f345cd24dc Update libopencm3 pointer 2017-09-25 10:04:05 +13:00
Gareth McMullin
ad71db05b9 Merge pull request #283 from UweBonnes/rdi
Make ENABLE_DEBUG infrastucture available  and use for st- and swlink
2017-09-25 08:12:23 +13:00
Uwe Bonnes
4966168802 s[t|w]link: Implement ENABLE_DEBUG. 2017-09-23 16:40:28 +02:00
Uwe Bonnes
ce1ef6e41b stm32: Move rdi handling to common stm32 code. 2017-09-23 16:39:35 +02:00
Gareth McMullin
98ab873784 Merge pull request #281 from UweBonnes/nucleo144
stlink: Use common initialization and detect V2.1 boards.
2017-09-23 10:36:46 +12:00
Uwe Bonnes
203f6702d8 Flashsize_F103: Options for BMP on STM32F103C8 devices 2017-09-21 23:05:20 +02:00
Uwe Bonnes
963df9febc stlink: Use common initialization and detect V2.1 boards.
Factor out hardware revision detection, USB detach and power settings, as
all three program (bootloader, bmp and dfu-upgrade) need it.
2017-09-21 18:43:06 +02:00
Gareth McMullin
16f99238b1 Merge pull request #279 from gsmcmullin/cortexa-softbreak-fault-check
cortexa: Check for fault on set/clear soft breakpoint.
2017-09-20 11:30:33 +12:00
Gareth McMullin
259f1b90df cortexa: Check for fault on set/clear soft breakpoint. 2017-09-20 11:16:36 +12:00
Gareth McMullin
eaaa7d2cc2 Merge pull request #276 from gsmcmullin/cortexa-remove-ahb
cortexa: Remove problematic code for AHB access.
2017-09-20 08:13:04 +12:00
Gareth McMullin
1cb4271749 cortexa: Remove problematic code for AHB access.
The old code for 'fast' memory accesses using the AHB directly
has problems with data consitency.  Until this can be resolved, I'm
removing the affected code.
2017-09-19 09:13:22 +12:00
Gareth McMullin
eb46994bc9 Merge pull request #277 from gsmcmullin/travis_pip
Travis: Call pip with `--user`
2017-09-12 13:03:49 +12:00
Gareth McMullin
4af7a05249 Travis: Call pip with --user 2017-09-12 12:57:51 +12:00
Gareth McMullin
2df0c7d6a7 Merge pull request #261 from cpavlina/tm4c
lm3s/tm4c: add TM4C1230C3PM
2017-09-06 15:34:42 +12:00
Gareth McMullin
fd9efa2711 Merge pull request #271 from dpiegdon/master
Add nRF52840 support (PCA10056, nrf52840 PDK)
2017-09-06 15:01:13 +12:00
Gareth McMullin
a648967b9e Merge pull request #252 from UweBonnes/stm32_mem
stm32_mem.py: Set address before writing to inhibit bootloader overwr…
2017-09-06 14:49:07 +12:00
Gareth McMullin
0fe746feca Merge pull request #272 from gsmcmullin/build_update
Update CI
2017-09-06 14:44:32 +12:00
Gareth McMullin
d33a8e31b4 Run pip without sudo 2017-09-06 14:33:40 +12:00
Gareth McMullin
41025f55ea Specify Trusty for Travis build 2017-09-06 11:01:43 +12:00
David R. Piegdon
46e363393f Add nRF52840 support (PCA10056, nrf52840 PDK) 2017-09-03 23:05:29 +00:00
Gareth McMullin
11c1af542c Merge pull request #270 from carlsa/master
Added NRF51_FICR_CONFIGID for nRF51822 QFAA H2
2017-08-31 08:40:32 +12:00
Carl Sandström
37f9623de2 Added NRF51_FICR_CONFIGID for nRF51822 QFAA H2 2017-08-30 17:14:52 +02:00
Gareth McMullin
9d898f4aa2 Merge pull request #268 from UweBonnes/f03
STM32F0: Several STM32F0[3|7]0 have same ID as other STM32F0X0.
2017-08-29 09:08:10 +12:00
Uwe Bonnes
37bb86267a STM32F0: Several STM32F0[3|7]0 have same ID as other STM32F0X0. 2017-08-28 22:58:59 +02:00
Uwe Bonnes
1be9c6e9c5 stm32_mem.py: Set address before writing to inhibit bootloader overwrite. 2017-07-22 13:25:48 +02:00
Chris Pavlina
a0b0b8a716 lm3s/tm4c: add TM4C1230C3PM 2017-07-21 13:29:41 -06:00
Gareth McMullin
7663794fdf Merge pull request #247 from schodet/stm32f4-x8-x32
Allow programming STM32F4 when using a low voltage
2017-07-09 14:33:06 -07:00
Nicolas Schodet
3846ea4708 stm32f4: allow selection of flash programming parallelism 2017-07-09 23:26:49 +02:00
Gareth McMullin
09f49b469d Merge pull request #256 from nar0909/patch-1
New Device Id update - QFAA G1
2017-07-09 13:45:52 -07:00
Gareth McMullin
7d474eae7f Merge pull request #251 from therealprof/features/support-LCP1112_102
Identify and support LPC1112/102 MCU as well
2017-07-09 13:45:37 -07:00
nar0909
43ac4a04f7 New Device Id update - QFAA G1
New device Id - for NRF51822 QFAA G1 1529AM.
2017-07-04 12:32:39 +10:00
Daniel Egger
f036be8cb2 Identify and support LPC1112/102 MCU as well
Signed-off-by: Daniel Egger <daniel@eggers-club.de>
2017-06-23 21:52:13 +02:00
Gareth McMullin
984f8b3d94 Merge pull request #248 from schodet/typo
stm32f4: fix typo in target name
2017-06-22 18:35:29 -07:00
Gareth McMullin
40ac8e1004 Merge pull request #241 from gsmcmullin/no_magic_vtor
Use vector_table symbol for assignment of SCB_VTOR.
2017-06-22 16:31:09 -07:00
Gareth McMullin
e9cdd5ec56 Merge pull request #245 from schodet/stm32f469
stm32f4: add support for STM32F4[67]9
2017-06-22 14:52:19 -07:00
Nicolas Schodet
02ce5e23b6 stm32f4: fix typo in target name 2017-06-19 10:56:20 +02:00
Nicolas Schodet
680aa30d52 stm32f4: add support for STM32F4[67]9 2017-06-19 10:41:38 +02:00
Gareth McMullin
63a2e74948 Merge pull request #244 from schodet/gdb-py-fix
Fix gdb.py to program last chunk of a memory range
2017-06-18 15:02:33 -07:00
Gareth McMullin
c7bc51d191 Merge pull request #235 from UweBonnes/stm32f2_4_7
Stm32f2_4_7
2017-06-18 14:42:13 -07:00
Gordon Smith
1ee1f441d5 stm32f4: write flash using byte access 2017-06-16 14:45:16 +02:00
Nicolas Schodet
73ac700c6f Fix gdb.py to program last chunk of a memory range 2017-06-15 16:20:02 +02:00
Uwe Bonnes
408c5a9df2 stm32f4: Try to handle option bytes for more devices.
Correct the table for the OPTCRx values from errors in documentation and
error when entering the values.
2017-06-09 13:03:26 +02:00
Uwe Bonnes
8a7455f63e src/target/stm32f4.c: Add STM32F7[2|3]x. 2017-06-09 13:03:26 +02:00
Uwe Bonnes
84e036a804 target/stm32f4: Document FLASH_OPTCR(1|2) registers. 2017-06-09 13:03:26 +02:00
Uwe Bonnes
2216587b39 src/target/stm32f4.c: Remove missleading DTCM comment.
Use different command string for F74x and F76x.
2017-06-09 13:03:26 +02:00
Uwe Bonnes
dc1c7611a9 src/target/stm32f4.c: All STM32F7 devs have option bytes at 0x1fff0000. 2017-06-09 13:03:26 +02:00
Uwe Bonnes
e43017d0a6 src/target/stm32f4.c: Add STM32F412 and F413.
F413 needs its own clause, as there is memory > 1 MB but no second bank.
2017-06-09 13:03:26 +02:00
Uwe Bonnes
24ed65d6b6 src/target/stm32f4.c: Declare CCMRAM only for devices with CCMRAM. 2017-06-09 13:03:26 +02:00
Gareth McMullin
2eb2f8edd7 Use vector_table symbol for assignment of SCB_VTOR. 2017-06-09 13:07:06 +12:00
Gareth McMullin
a4bb2c6e3e Merge pull request #240 from UweBonnes/cleanup
stlink/swlink: Remove missleading comments.
2017-06-08 12:35:28 -07:00
Uwe Bonnes
a7771fa23f stlink/swlink: Remove missleading comments. 2017-06-08 18:25:43 +02:00
Gareth McMullin
aaa7b0e38e Merge pull request #217 from UweBonnes/stm32l4
Stm32l4
2017-05-23 12:22:04 -07:00
Gareth McMullin
fd467269eb Merge pull request #233 from gsmcmullin/parallel_make_fix
Fix parallel build.
2017-05-23 12:20:21 -07:00
Gareth McMullin
539d9e14ec Merge pull request #223 from gsmcmullin/nrf51_c_stub
nrf51: Replace stub with C version and pass params in registers
2017-05-23 12:00:08 -07:00
Gareth McMullin
ecc0d9807d Fix parallel build.
Add explicit dependency of command.c on version.h
Remove version.h on make clean.
2017-05-23 11:57:35 -07:00
Uwe Bonnes
91839f3aee stm32l4.c: Handle options. 2017-05-11 23:31:43 +02:00
Uwe Bonnes
289be4d9db stm32l4.c: Add STM32L43/L44/L45/L46/L49/L4A. 2017-05-11 23:31:43 +02:00
Gareth McMullin
261be9864c Merge pull request #210 from UweBonnes/f4_discovery
F4 discovery
2017-05-12 09:15:55 +12:00
Uwe Bonnes
8cc2c44dbf f4discovery: Use Magic constant in RAM for Bootloader entry. 2017-05-11 22:21:38 +02:00
Uwe Bonnes
a0e47c392b f4_discovery: Clean up platform.h and Readme. 2017-05-11 21:53:01 +02:00
Uwe Bonnes
814eb0e3a2 f4discovery: Make DFU work (again?) 2017-05-11 21:52:24 +02:00
Uwe Bonnes
f5dd3006fb STM32: Generate same serial number as internal DFU bootloader. 2017-05-11 21:52:24 +02:00
Gareth McMullin
98a4f8e318 Merge pull request #205 from UweBonnes/stlink_flashsize
stlink: Announce 124 kiB flash size in DFU to commplement #204.
2017-05-12 04:20:34 +12:00
Uwe Bonnes
b7235da97f dfucore.c: Announce no writable bootloader pages when device is read proteced
or bootloader is write protected.

Device read protection or write protection on first 4 bootloader pages
can only be removed by mass erase. Triggering mass erase with a program
running from flash is doomed for failure.
User can force bootloader update, at their own risk to brick the device.
2017-05-07 13:19:37 +02:00
Uwe Bonnes
b09a522f37 STM32F103: Use flash size from device for DFU string.
Complements #204.
STLinkV2-1 has F103CB on board! F103C8 on older Stlinks can use upper flash
with hopefully acceptable error rate.
For F103C8 devices, user has to give the force option to dfu-utils.
2017-05-07 13:19:37 +02:00
Gareth McMullin
f450b1745d Merge branch 'v1.6-branch' 2017-05-06 15:25:50 -07:00
Gareth McMullin
94c822cb62 nrf51: Replace stub with C version and pass params in registers 2017-05-03 13:10:01 -07:00
Gareth McMullin
6b592b4118 Merge pull request #218 from stoyan-shopov/breakpoint-removal-bugfix
fixed a bug in the breakpoint removal code
2017-05-03 12:11:50 -07:00
Gareth McMullin
bfce31f26a Merge pull request #219 from UweBonnes/dfu_update
dfu_f1/dfu_upgrade: Do not set read protection.
2017-05-03 10:39:13 -07:00
Uwe Bonnes
5af76a1b74 dfu_f1/dfu_upgrade: Do not set read protection.
As the first 4 pages of the bootloader will always keep write protection
once read protection is applied, with the second update of the bootloader
only the higher pages where updated effectivly.
In most cases this resulted in an inaccessible device!
2017-04-29 14:58:41 +02:00
stoyan shopov
01e3582525 fixed a bug in the breakpoint removal code 2017-04-28 13:22:59 +03:00
Gareth McMullin
b10971b19b Merge pull request #206 from UweBonnes/dfu-upload
Dfu upload
2017-04-27 10:07:37 -07:00
Gareth McMullin
146c0b83b5 Merge pull request #214 from falstaff84/const-strings-and-structs
Constify strings and constant structs
2017-04-27 10:02:53 -07:00
Stefan Agner
3c06396c8e Constify strings and constant structs 2017-04-22 13:50:04 -07:00
Uwe Bonnes
d796571438 Implement DFU_UPLOAD. 2017-04-15 14:26:03 +02:00
Uwe Bonnes
1d8ebcd75f Handle SET_ADDRESS according to DFUSE specs. 2017-04-14 15:16:59 +02:00
213 changed files with 28783 additions and 4888 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

@ -17,4 +17,9 @@ tags
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 = git@github.com:flirc/libopencm3.git
url = https://github.com/flirc/libopencm3.git

View File

@ -1,12 +1,11 @@
dist: bionic
sudo: required
before_install:
- sudo add-apt-repository -y ppa:team-gcc-arm-embedded/ppa
- sudo apt-get update -qq
- sudo apt-get install -y build-essential libftdi-dev gcc-arm-embedded
- sudo pip install intelhex
install: true
- pip install --user intelhex
- 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

@ -3,16 +3,37 @@ MFLAGS += --no-print-dir
Q := @
endif
PC_HOSTED =
NO_LIBOPENCM3 =
ifeq ($(PROBE_HOST), hosted)
PC_HOSTED = true
NO_LIBOPENCM3 = true
endif
all:
ifndef NO_LIBOPENCM3
$(Q)if [ ! -f libopencm3/Makefile ]; then \
echo "Initialising git submodules..." ;\
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
clean:
$(Q)$(MAKE) $(MFLAGS) -C libopencm3 $@
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

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)

260
UsingSWO Normal file
View File

@ -0,0 +1,260 @@
SWO is a datastream that comes out of a single pin when the debug interface
is in SWD mode. It can be encoded either using NRZ (UART) or RZ (Manchester)
formats. The pin is a dedicated one that would be used for TDO when the
debug interface is in JTAG mode. On the STM32 it's port PB3.
When in NRZ mode the SWO data rate that comes out of the chip _must_ match
the rate that the debugger expects. By default on BMP the baudrate is
2.25MBps but that can be changed as an optional parameter to the monitor
traceswo command, like this;
monitor traceswo 115200
....would set the swo output at the low speed of 115kbps.
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)/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:
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
each valid value so mis-timing is less of an issue. The 'monitor traceswo
<x>' command will automatically find the closest divisor to the value you
set for the speed, so be aware the error could be significant.
Depending on what you're using to wake up SWO on the target side, you may
need code to get it into the correct mode and emitting data. You can do that
via gdb direct memory accesses, or from program code.
An example for a STM32F103 for the UART (NRZ) data format that we use;
/* STM32 specific configuration to enable the TRACESWO IO pin */
RCC->APB2ENR |= RCC_APB2ENR_AFIOEN;
AFIO->MAPR |= (2 << 24); // Disable JTAG to release TRACESWO
DBGMCU->CR |= DBGMCU_CR_TRACE_IOEN; // Enable IO trace pins
TPI->ACPR = 31; // Output bits at 72000000/(31+1)=2.25MHz.
TPI->SPPR = 2; // Use Async mode (1 for RZ/Manchester)
TPI-FFCR = 0; // Disable formatter
/* Configure instrumentation trace macroblock */
ITM->LAR = 0xC5ACCE55;
ITM->TCR = 1 << ITM_TCR_TraceBusID_Pos | ITM_TCR_SYNCENA_Msk |
ITM_TCR_ITMENA_Msk;
ITM->TER = 0xFFFFFFFF; // Enable all stimulus ports
Code for the STM32L476 might look like:
#define BAUDRATE 115200
DBGMCU->CR |= DBGMCU_CR_TRACE_IOEN; /* Enable IO pins for Async trace */
uint32_t divisor, clk_frequency;
clk_frequency = NutGetCpuClock();
divisor = clk_frequency / BAUDRATE;
divisor--;
TPI->CSPSR = 1; /* port size = 1 bit */
TPI->ACPR = divisor;
TPI->SPPR = 2; /*Use Async mode pin protocol */
TPI->FFCR = 0x00; /* Bypass the TPIU formatter and send output directly*/
/* Configure Trace Port Interface Unit */
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; // Enable access to registers
DWT->CTRL = 0x400003FE; // DWT needs to provide sync for ITM
ITM->LAR = 0xC5ACCE55; // Allow access to the Control Register
ITM->TPR = 0x0000000F; // Trace access privilege from user level code, please
ITM->TCR = 0x0001000D; // ITM_TCR_TraceBusID_Msk | ITM_TCR_DWTENA_Msk | ITM_TCR_SYNCENA_Msk | ITM_TCR_ITMENA_Msk
ITM->TER = 1; // Only Enable stimulus port 1
while(1) {
for (uint32_t i = 'A'; i <= 'Z'; i++) {
ITM_SendChar(i);
NutSleep(1);
}
}
If you're using RZ mode (e.g. on a genuine BMP) then you will need the trace
output speed to be quite a lot lower...in the order of 200kHz by means of
changing the divisor to something like 359. That's because the STM32F103
doesn't have a dedicated RZ decoder so it all has to be done in
software. The advantage of RZ is that the probe can adapt to the speed of
the target, so you don't have to set the speed on the probe in the monitor
traceswo command, and it will be tolerant of different speeds.
The SWO data appears on USB Interface 5, Endpoint 5.
SWOListen
=========
A program swolisten.c is found in ./scripts which will listen to this
endpoint, decode the datastream, and output it to a set of unix fifos which
can then be used as the input to other programs (e.g. cat, or something more
sophisticated like gnuplot, octave or whatever). This program doesn't care
if the data originates from a RZ or NRZ port, or at what speed.
Note that swolisten can be used with either BMP firmware, or with a
conventional TTL serial dongle. See at the bottom of this file for
information on how to use a dongle.
The command line to build the swolisten tool may look like:
E.g. for Ubuntu
gcc -I /usr/local/include/libusb-1.0 -L /usr/local/lib swolisten.c -o swolisten -lusb-1.0
E.g. For Opensuse:
gcc -I /usr/include/libusb-1.0 swolisten.c swolisten -std=gnu99 -g -Og -lusb-1.0
...you will obviously need to change the paths to your libusb files.
Attach to BMP to your PC:
Start gdb: "arm-none-eabi-gdb"
Choose bmp as target, like:
"target extended /dev/ttyACM0(*)"
Start SWO output: "mon traceswo"
If async SWO is used, give the baudrate your device sends
out as argument. 2.25 MBaud is the default, for the STM32L476 example above
the command would be: "mon traceswo 115200(*)".
Scan the SWD "mon swdp_scan"
Attach to the device: : "attach 1"
Start the program: "r".
(*) Your milage may vary
Now start swolisten without further options.
By default the tool will create fifos for the first 32 channels in a
directory swo (which you will need to create) as follows;
>ls swo/
chan00 chan02 chan04 chan06 chan08 chan0A chan0C chan0E chan10 chan12 chan14
chan16 chan18 chan1A chan1C chan1E chan01 chan03 chan05 chan07 chan09 chan0B
chan0D chan0F chan11 chan13 chan15 chan17 chan19 chan1B chan1D chan1F
>cat swo/channel0
<<OUTPUT FROM ITM Channel 0>>
With the F103 and L476 examples above, an endless stream of
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" should be seen. During reset of the target
device, no output will appear, but with release of reset output restarts.
Information about command line options can be found with the -h option.
swolisten is specifically designed to be 'hardy' to probe and target
disconnects and restarts (y'know, like you get in the real world). The
intention being to give you streams whenever it can get them. It does _not_
require gdb to be running. For the time being traceswo is not turned on by
default in the BMP to avoid possible interactions and making the overall
thing less reliable so You do need gdb to send the initial 'monitor
traceswo' to the probe, but beyond that there's no requirement for gdb to be
present.
Reliability
===========
A whole chunk of work has gone into making sure the dataflow over the SWO
link is reliable. The TL;DR is that the link _is_ reliable. There are
factors outside of our control (i.e. the USB bus you connect to) that could
potentially break the reliabilty but there's not too much we can do about
that since the SWO link is unidirectional (no opportunity for
re-transmits). The following section provides evidence for the claim that
the link is good;
A test 'mule' sends data flat out to the link at the maximum data rate of
2.25Mbps using a loop like the one below;
while (1)
{
for (uint32_t r=0; r<26; r++)
{
for (uint32_t g=0; g<31; g++)
{
ITM_SendChar('A'+r);
}
ITM_SendChar('\n');
}
}
100MB of data (more than 200MB of actual SWO packets, due to the encoding) was sent from the mule to the BMP where the
output from swolisten chan00 was cat'ted into a file;
>cat swo/chan00 > o
....this process was interrupted once the file had grown to 100MB. The first
and last lines were removed from it (these represent previously buffered
data and an incomplete packet at the point where the capture was
interrupted) and the resulting file analysed for consistency;
> sort o | uniq -c
The output was;
126462 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
126462 BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
126462 CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
126462 DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
126461 EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
126461 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
126461 GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
126461 HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
126461 IIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
126461 JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ
126461 KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
126461 LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL
126461 MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
126461 NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
126461 OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
126461 PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP
126461 QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
126461 RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
126461 SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS
126461 TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT
126461 UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU
126461 VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
126461 WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
126461 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
126461 YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY
126461 ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
(On inspection, the last line of recorded data was indeed a 'D' line).
Swolisten, using a TTL Serial Dongle
====================================
The NRZ data that comes out of the SWO is just UART formatted, but in a
frame. swolisten has been extended to accomodate TTL Serial Dongles that
can pick this up. Success has been had with CP2102 dongles at up to 921600
baud.
To use this mode just connect SWO to the RX pin of your dongle, and start
swolisten with parameters representing the speed and port. An example;
>./swolisten -p /dev/cu.SLAB_USBtoUART -v -b swo/ -s 921600
Any individual dongle will only support certain baudrates (Generally
multiples of 115200) so you may have to experiment to find the best
supported ones. For the CP2102 dongle 1.3824Mbps wasn't supported and
1.8432Mbps returned corrupted data.
Please email dave@marples.net with information about dongles you find work
well and at what speed.
Further information
===================
SWO is a wide field. Read e.g. the blogs around SWD on
http://shadetail.com/blog/swo-starting-the-steroids/
An open source program suite for SWO under active development is
https://github.com/mubes/orbuculum

View File

@ -0,0 +1,8 @@
# 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"
SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ATTR{idVendor}=="1d50", ATTR{idProduct}=="6018", 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 832eb832fff85d0ecab461310466cf18b2f6006d
Subproject commit 63573143ef7e1b037d1f0c5baedc5264e12562b8

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,7 +1,7 @@
#!/usr/bin/env python
#!/usr/bin/env python3
#
# dfu.py: Access USB DFU class devices
# Copyright (C) 2009 Black Sphere Technologies
# 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
@ -17,12 +17,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/>.
import usb
DFU_DETACH_TIMEOUT = 1000
# DFU Requests
# DFU Requests
DFU_DETACH = 0x00
DFU_DNLOAD = 0x01
DFU_UPLOAD = 0x02
@ -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
@ -84,41 +84,43 @@ class dfu_device(object):
self.index = self.iface.interfaceNumber
else: self.index = self.iface
def release(self):
self.handle.releaseInterface()
def detach(self, wTimeout=255):
self.handle.controlMsg(usb.ENDPOINT_OUT | usb.TYPE_CLASS |
usb.RECIP_INTERFACE, DFU_DETACH,
self.handle.controlMsg(usb.ENDPOINT_OUT | usb.TYPE_CLASS |
usb.RECIP_INTERFACE, DFU_DETACH,
None, value=wTimeout, index=self.index)
def download(self, wBlockNum, data):
self.handle.controlMsg(usb.ENDPOINT_OUT | usb.TYPE_CLASS |
usb.RECIP_INTERFACE, DFU_DNLOAD,
data, value=wBlockNum, index=self.index)
data, value=wBlockNum, index=self.index)
def upload(self, wBlockNum, length):
return self.handle.controlMsg(usb.ENDPOINT_IN |
return self.handle.controlMsg(usb.ENDPOINT_IN |
usb.TYPE_CLASS | usb.RECIP_INTERFACE, DFU_UPLOAD,
length, value=wBlockNum, index=self.index)
length, value=wBlockNum, index=self.index)
def get_status(self):
buf = self.handle.controlMsg(usb.ENDPOINT_IN |
buf = self.handle.controlMsg(usb.ENDPOINT_IN |
usb.TYPE_CLASS | usb.RECIP_INTERFACE, DFU_GETSTATUS,
6, index=self.index)
6, index=self.index)
return dfu_status(buf)
def clear_status(self):
self.handle.controlMsg(usb.ENDPOINT_OUT | usb.TYPE_CLASS |
usb.RECIP_INTERFACE, DFU_CLRSTATUS,
self.handle.controlMsg(usb.ENDPOINT_OUT | usb.TYPE_CLASS |
usb.RECIP_INTERFACE, DFU_CLRSTATUS,
"", index=0)
def get_state(self):
buf = self.handle.controlMsg(usb.ENDPOINT_IN |
buf = self.handle.controlMsg(usb.ENDPOINT_IN |
usb.TYPE_CLASS | usb.RECIP_INTERFACE, DFU_GETSTATE,
1, index=self.index)
1, index=self.index)
return buf[0]
def abort(self):
self.handle.controlMsg(usb.ENDPOINT_OUT | usb.TYPE_CLASS |
usb.RECIP_INTERFACE, DFU_ABORT,
self.handle.controlMsg(usb.ENDPOINT_OUT | usb.TYPE_CLASS |
usb.RECIP_INTERFACE, DFU_ABORT,
None, index=self.index)
@ -136,7 +138,7 @@ class dfu_device(object):
if status.bState == STATE_DFU_IDLE:
return True
if ((status.bState == STATE_DFU_DOWNLOAD_SYNC) or
if ((status.bState == STATE_DFU_DOWNLOAD_SYNC) or
(status.bState == STATE_DFU_DOWNLOAD_IDLE) or
(status.bState == STATE_DFU_MANIFEST_SYNC) or
(status.bState == STATE_DFU_UPLOAD_IDLE) or
@ -155,7 +157,7 @@ class dfu_device(object):
if ((status.bState == STATE_APP_DETACH) or
(status.bState == STATE_DFU_MANIFEST_WAIT_RESET)):
usb.reset(self.handle)
usb.reset(self.handle)
return False
raise Exception
@ -176,16 +178,16 @@ def finddevs():
if __name__ == "__main__":
devs = finddevs()
if not devs:
print "No devices found!"
print("No devices found!")
exit(-1)
for dfu in devs:
handle = dfu[0].open()
man = handle.getString(dfu[0].iManufacturer, 30)
product = handle.getString(dfu[0].iProduct, 30)
print "Device %s: ID %04x:%04x %s - %s" % (dfu[0].filename,
dfu[0].idVendor, dfu[0].idProduct, man, product)
print "%r, %r" % (dfu[1], dfu[2])
print("Device %s: ID %04x:%04x %s - %s" % (dfu[0].filename,
dfu[0].idVendor, dfu[0].idProduct, man, product))
print("%r, %r" % (dfu[1], dfu[2]))

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,65 +257,70 @@ 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
if callable(progress_cb):
if callable(progress_cb) and totalblocks > 0:
progress_cb(block*100/totalblocks)
# 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"):
@ -291,11 +336,9 @@ class Target:
def flash_write_prepare(self, address, data):
for m in self.mem:
if (address >= m.offset) and (address + len(data) < m.offset + m.length):
if (address >= m.offset) and (address + len(data) <= m.offset + m.length):
m.prog(address, data)
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,7 +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) 2011 Black Sphere Technologies
# 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
@ -19,15 +20,15 @@
from time import sleep
import struct
from sys import stdout, argv
import os
from sys import stdout
import argparse
import usb
import dfu
CMD_GETCOMMANDS = 0x00
CMD_SETADDRESSPOINTER = 0x21
CMD_ERASE = 0x41
CMD_GETCOMMANDS = 0x00
CMD_SETADDRESSPOINTER = 0x21
CMD_ERASE = 0x41
def stm32_erase(dev, addr):
erase_cmd = struct.pack("<BL", CMD_ERASE, addr)
@ -39,6 +40,16 @@ def stm32_erase(dev, addr):
if status.bState == dfu.STATE_DFU_DOWNLOAD_IDLE:
break
def stm32_set_address(dev, addr):
set_address_cmd = struct.pack("<BL", CMD_SETADDRESSPOINTER, addr)
dev.download(0, set_address_cmd)
while True:
status = dev.get_status()
if status.bState == dfu.STATE_DFU_DOWNLOAD_BUSY:
sleep(status.bwPollTimeout / 1000.0)
if status.bState == dfu.STATE_DFU_DOWNLOAD_IDLE:
break
def stm32_write(dev, data):
dev.download(2, data)
while True:
@ -47,9 +58,19 @@ def stm32_write(dev, data):
sleep(status.bwPollTimeout / 1000.0)
if status.bState == dfu.STATE_DFU_DOWNLOAD_IDLE:
break
def stm32_read(dev):
data = dev.upload(2, 1024)
while True:
status = dev.get_status()
if status.bState == dfu.STATE_DFU_DOWNLOAD_BUSY:
sleep(status.bwPollTimeout / 1000.0)
if status.bState == dfu.STATE_DFU_UPLOAD_IDLE:
break
return data
def stm32_manifest(dev):
dev.download(0, "")
dev.download(0, b"")
while True:
try:
status = dev.get_status()
@ -59,72 +80,182 @@ def stm32_manifest(dev):
if status.bState == dfu.STATE_DFU_MANIFEST:
break
def stm32_scan(args, test):
devs = dfu.finddevs()
bmp_devs = []
bmp = 0
if not devs:
if test:
return
print("No DFU devices found!")
exit(-1)
for dev in devs:
try:
dfudev = dfu.dfu_device(*dev)
except:
# Exceptions are raised when current user doesn't have permissions
# for the specified USB device, but the device scan needs to
# continue
continue
man = dfudev.handle.getString(dfudev.dev.iManufacturer, 30)
if man == b"Black Sphere Technologies":
bmp = bmp + 1
bmp_devs.append(dev)
if bmp == 0:
if test:
return
print("No compatible device found\n")
exit(-1)
if bmp > 1 and not args.serial_target:
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).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)
for dev in bmp_devs:
dfudev = dfu.dfu_device(*dev)
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:
break
else:
if man == "Black Sphere Technologies":
break
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" % serial_no)
if args.serial_target and serial_no != args.serial_target:
print("Serial number doesn't match %s vs %s!\n" % (serial_no, args.serial_target))
exit(-2)
return dfudev
if __name__ == "__main__":
print
print "USB Device Firmware Upgrade - Host Utility -- version 1.2"
print "Copyright (C) 2011 Black Sphere Technologies"
print "License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>"
print
print("-")
print("USB Device Firmware Upgrade - Host Utility -- version 1.2")
print("Copyright (C) 2011 Black Sphere Technologies")
print("License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>")
print("-")
parser = argparse.ArgumentParser()
parser.add_argument("progfile", help="Binary file to program")
parser.add_argument("-s", "--serial_target", help="Match Serial Number")
parser.add_argument("-a", "--address", help="Start address for firmware")
parser.add_argument("-m", "--manifest", help="Start application, if in DFU mode", action='store_true')
args = parser.parse_args()
devs = dfu.finddevs()
if not devs:
print "No devices found!"
exit(-1)
for dev in devs:
dfudev = dfu.dfu_device(*dev)
man = dfudev.handle.getString(dfudev.dev.iManufacturer, 30)
product = dfudev.handle.getString(dfudev.dev.iProduct, 64)
serial_no = dfudev.handle.getString(dfudev.dev.iSerialNumber, 30)
if args.serial_target:
if man == "Black Sphere Technologies" and serial_no == args.serial_target: break
if man == "STMicroelectronics" and serial_no == args.serial_target: break
else:
if man == "Black Sphere Technologies": break
if man == "STMicroelectronics": break
print "Device %s: ID %04x:%04x %s - %s\n\tSerial %s" % (
dfudev.dev.filename, dfudev.dev.idVendor,
dfudev.dev.idProduct, man, product, serial_no)
if args.serial_target and serial_no != args.serial_target:
print "Serial number doesn't match!\n"
exit(-2)
dfudev = stm32_scan(args, False)
try:
state = dfudev.get_state()
except:
print "Failed to read device state! Assuming APP_IDLE"
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:
dfudev.detach()
print "Run again to upgrade firmware."
try:
dfudev.detach()
except:
pass
dfudev.release()
print("Invoking DFU Device")
timeout = 0
while True:
sleep(1)
timeout = timeout + 0.5
dfudev = stm32_scan(args, True)
if dfudev: break
if timeout > 5:
print("Error: DFU device did not appear")
exit(-1)
if args.manifest:
stm32_manifest(dfudev)
print("Invoking Application Device")
exit(0)
dfudev.make_idle()
file = open(args.progfile, "rb")
if (os.path.getsize(args.progfile) > 0x1f800):
print("File too large")
exit(0)
bin = open(args.progfile, "rb").read()
bin = file.read()
if "F4" in product:
addr = 0x8004000
product = dfudev.handle.getString(dfudev.dev.iProduct, 64).decode('utf8')
if args.address:
start = int(args.address, 0)
else:
addr = 0x8002000
if "F4" in product or "STLINK-V3" in product:
start = 0x8004000
else:
start = 0x8002000
addr = start
while bin:
print ("Programming memory at 0x%08X\r" % addr),
print("Programming memory at 0x%08X" % addr, end="\r")
stdout.flush()
try:
# STM DFU bootloader erases always.
# BPM Bootloader only erases once per sector
# To support the STM DFU bootloader, the interface descriptor must
# get evaluated and erase called only once per sector!
stm32_erase(dfudev, addr)
except:
print "\nErase Timed out\n"
except:
print("\nErase Timed out\n")
break
try:
stm32_set_address(dfudev, addr)
except:
print("\nSet Address Timed out\n")
break
stm32_write(dfudev, bin[:1024])
bin = bin[1024:]
addr += 1024
file.seek(0)
bin = file.read()
len = len(bin)
addr = start
print("\n-")
while bin:
try:
stm32_set_address(dfudev, addr)
data = stm32_read(dfudev)
except:
# Abort silent if bootloader does not support upload
break
print("Verifying memory at 0x%08X" % addr, end="\r")
stdout.flush()
if len > 1024:
size = 1024
else:
size = len
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:
print("\nVerified!")
stm32_manifest(dfudev)
print "\nAll operations complete!\n"
print("All operations complete!\n")

547
scripts/swolisten.c Normal file
View File

@ -0,0 +1,547 @@
/*
* SWO Splitter for Blackmagic Probe and others.
* =============================================
*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2017 Dave Marples <dave@marples.net>
*
* 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 <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <ctype.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <stdio.h>
#include <string.h>
#include <libusb.h>
#include <stdint.h>
#include <limits.h>
#include <termios.h>
#include <signal.h>
#define VID (0x1d50)
#define PID (0x6018)
#define INTERFACE (5)
#define ENDPOINT (0x85)
#define TRANSFER_SIZE (64)
#define NUM_FIFOS 32
#define MAX_FIFOS 128
#define CHANNELNAME "chan"
#define BOOL char
#define FALSE (0)
#define TRUE (!FALSE)
// Record for options, either defaults or from command line
struct
{
BOOL verbose;
BOOL dump;
int nChannels;
char *chanPath;
char *port;
int speed;
} options = {.nChannels=NUM_FIFOS, .chanPath="", .speed=115200};
// Runtime state
struct
{
int fifo[MAX_FIFOS];
} _r;
// ====================================================================================================
// ====================================================================================================
// ====================================================================================================
// Internals
// ====================================================================================================
// ====================================================================================================
// ====================================================================================================
static BOOL _runFifo(int portNo, int listenHandle, char *fifoName)
{
int pid,fifo;
int readDataLen, writeDataLen;
if (mkfifo(fifoName,0666)<0)
{
return FALSE;
}
pid=fork();
if (pid==0)
{
char rxdata[TRANSFER_SIZE];
int fifo;
/* Don't kill this sub-process when any reader or writer evaporates */
signal(SIGPIPE, SIG_IGN);
while (1)
{
/* This is the child */
fifo=open(fifoName,O_WRONLY);
while (1)
{
readDataLen=read(listenHandle,rxdata,TRANSFER_SIZE);
if (readDataLen<=0)
{
exit(0);
}
writeDataLen=write(fifo,rxdata,readDataLen);
if (writeDataLen<=0)
{
break;
}
}
close(fifo);
}
}
else if (pid<0)
{
/* The fork failed */
return FALSE;
}
return TRUE;
}
// ====================================================================================================
static BOOL _makeFifoTasks(void)
/* Create each sub-process that will handle a port */
{
char fifoName[PATH_MAX];
int f[2];
for (int t=0; t<options.nChannels; t++)
{
if (pipe(f)<0)
return FALSE;
fcntl(f[1],F_SETFL,O_NONBLOCK);
_r.fifo[t]=f[1];
sprintf(fifoName,"%s%s%02X",options.chanPath,CHANNELNAME,t);
if (!_runFifo(t,f[0],fifoName))
{
return FALSE;
}
}
return TRUE;
}
// ====================================================================================================
static void _removeFifoTasks(void)
/* Destroy the per-port sub-processes */
{
int statloc;
int remainingProcesses=0;
char fifoName[PATH_MAX];
for (int t=0; t<options.nChannels; t++)
{
if (_r.fifo[t]>0)
{
close(_r.fifo[t]);
sprintf(fifoName,"%s%s%02X",options.chanPath,CHANNELNAME,t);
unlink(fifoName);
remainingProcesses++;
}
}
while (remainingProcesses--)
{
waitpid(-1,&statloc,0);
}
}
// ====================================================================================================
// ====================================================================================================
// ====================================================================================================
// Handlers for each message type
// ====================================================================================================
// ====================================================================================================
// ====================================================================================================
void _handleSWIT(uint8_t addr, uint8_t length, uint8_t *d)
{
if (addr<options.nChannels)
write(_r.fifo[addr],d,length);
// if (addr==0)
// fprintf(stdout,"%c",*d);
}
// ====================================================================================================
void _handleTS(uint8_t length, uint8_t *d)
{
}
// ====================================================================================================
// ====================================================================================================
// ====================================================================================================
// Protocol pump for decoding messages
// ====================================================================================================
// ====================================================================================================
// ====================================================================================================
enum _protoState {ITM_IDLE, ITM_SYNCING, ITM_TS, ITM_SWIT};
#ifdef PRINT_TRANSITIONS
static char *_protoNames[]={"IDLE", "SYNCING","TS","SWIT"};
#endif
void _protocolPump(uint8_t *c)
{
static enum _protoState p;
static int targetCount, currentCount, srcAddr;
static uint8_t rxPacket[5];
#ifdef PRINT_TRANSITIONS
printf("%02x %s --> ",*c,_protoNames[p]);
#endif
switch (p)
{
// -----------------------------------------------------
case ITM_IDLE:
if (*c==0b01110000)
{
/* This is an overflow packet */
if (options.verbose)
fprintf(stderr,"Overflow!\n");
break;
}
// **********
if (*c==0)
{
/* This is a sync packet - expect to see 4 more 0's followed by 0x80 */
targetCount=4;
currentCount=0;
p=ITM_SYNCING;
break;
}
// **********
if (!(*c&0x0F))
{
currentCount=1;
/* This is a timestamp packet */
rxPacket[0]=*c;
if (!(*c&0x80))
{
/* A one byte output */
_handleTS(currentCount,rxPacket);
}
else
{
p=ITM_TS;
}
break;
}
// **********
if ((*c&0x0F) == 0x04)
{
/* This is a reserved packet */
break;
}
// **********
if (!(*c&0x04))
{
/* This is a SWIT packet */
if ((targetCount=*c&0x03)==3)
targetCount=4;
srcAddr=(*c&0xF8)>>3;
currentCount=0;
p=ITM_SWIT;
break;
}
// **********
if (options.verbose)
fprintf(stderr,"Illegal packet start in IDLE state\n");
break;
// -----------------------------------------------------
case ITM_SWIT:
rxPacket[currentCount]=*c;
currentCount++;
if (currentCount>=targetCount)
{
p=ITM_IDLE;
_handleSWIT(srcAddr, targetCount, rxPacket);
}
break;
// -----------------------------------------------------
case ITM_TS:
rxPacket[currentCount++]=*c;
if (!(*c&0x80))
{
/* We are done */
_handleTS(currentCount,rxPacket);
}
else
{
if (currentCount>4)
{
/* Something went badly wrong */
p=ITM_IDLE;
}
break;
}
// -----------------------------------------------------
case ITM_SYNCING:
if ((*c==0) && (currentCount<targetCount))
{
currentCount++;
}
else
{
if (*c==0x80)
{
p=ITM_IDLE;
}
else
{
/* This should really be an UNKNOWN state */
p=ITM_IDLE;
}
}
break;
// -----------------------------------------------------
}
#ifdef PRINT_TRANSITIONS
printf("%s\n",_protoNames[p]);
#endif
}
// ====================================================================================================
void intHandler(int dummy)
{
exit(0);
}
// ====================================================================================================
void _printHelp(char *progName)
{
printf("Useage: %s <dhnv> <b basedir> <p port> <s speed>\n",progName);
printf(" b: <basedir> for channels\n");
printf(" h: This help\n");
printf(" d: Dump received data without further processing\n");
printf(" n: <Number> of channels to populate\n");
printf(" p: <serialPort> to use\n");
printf(" s: <serialSpeed> to use\n");
printf(" v: Verbose mode\n");
}
// ====================================================================================================
int _processOptions(int argc, char *argv[])
{
int c;
while ((c = getopt (argc, argv, "vdn:b:hp:s:")) != -1)
switch (c)
{
case 'v':
options.verbose = 1;
break;
case 'd':
options.dump = 1;
break;
case 'p':
options.port=optarg;
break;
case 's':
options.speed=atoi(optarg);
break;
case 'h':
_printHelp(argv[0]);
return FALSE;
case 'n':
options.nChannels=atoi(optarg);
if ((options.nChannels<1) || (options.nChannels>MAX_FIFOS))
{
fprintf(stderr,"Number of channels out of range (1..%d)\n",MAX_FIFOS);
return FALSE;
}
break;
case 'b':
options.chanPath = optarg;
break;
case '?':
if (optopt == 'b')
fprintf (stderr, "Option '%c' requires an argument.\n", optopt);
else if (!isprint (optopt))
fprintf (stderr,"Unknown option character `\\x%x'.\n", optopt);
return FALSE;
default:
return FALSE;
}
if (options.verbose)
{
fprintf(stdout,"Verbose: TRUE\nBasePath: %s\n",options.chanPath);
if (options.port)
{
fprintf(stdout,"Serial Port: %s\nSerial Speed: %d\n",options.port,options.speed);
}
}
return TRUE;
}
// ====================================================================================================
int usbFeeder(void)
{
unsigned char cbw[TRANSFER_SIZE];
libusb_device_handle *handle;
libusb_device *dev;
int size;
while (1)
{
if (libusb_init(NULL) < 0)
{
fprintf(stderr,"Failed to initalise USB interface\n");
return (-1);
}
while (!(handle = libusb_open_device_with_vid_pid(NULL, VID, PID)))
{
usleep(500000);
}
if (!(dev = libusb_get_device(handle)))
continue;
if (libusb_claim_interface (handle, INTERFACE)<0)
continue;
while (0==libusb_bulk_transfer(handle, ENDPOINT, cbw, TRANSFER_SIZE, &size, 10))
{
unsigned char *c=cbw;
if (options.dump)
{
cbw[size] = 0;
printf("%s", (char*)cbw);
}
else
while (size--)
_protocolPump(c++);
}
libusb_close(handle);
}
}
// ====================================================================================================
int serialFeeder(void)
{
int f;
unsigned char cbw[TRANSFER_SIZE];
ssize_t t;
struct termios settings;
while (1)
{
while ((f=open(options.port,O_RDONLY))<0)
{
if (options.verbose)
{
fprintf(stderr,"Can't open serial port\n");
}
usleep(500000);
}
if (options.verbose)
{
fprintf(stderr,"Port opened\n");
}
if (tcgetattr(f, &settings) <0)
{
perror("tcgetattr");
return(-3);
}
if (cfsetspeed(&settings, options.speed)<0)
{
perror("Setting input speed");
return -3;
}
settings.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
settings.c_cflag &= ~PARENB; /* no parity */
settings.c_cflag &= ~CSTOPB; /* 1 stop bit */
settings.c_cflag &= ~CSIZE;
settings.c_cflag |= CS8 | CLOCAL; /* 8 bits */
settings.c_oflag &= ~OPOST; /* raw output */
if (tcsetattr(f, TCSANOW, &settings)<0)
{
fprintf(stderr,"Unsupported baudrate\n");
exit(-3);
}
tcflush(f, TCOFLUSH);
while ((t=read(f,cbw,TRANSFER_SIZE))>0)
{
unsigned char *c=cbw;
while (t--)
_protocolPump(c++);
}
if (options.verbose)
{
fprintf(stderr,"Read failed\n");
}
close(f);
}
}
// ====================================================================================================
int main(int argc, char *argv[])
{
if (!_processOptions(argc,argv))
{
exit(-1);
}
atexit(_removeFifoTasks);
/* This ensures the atexit gets called */
signal(SIGINT, intHandler);
if (!_makeFifoTasks())
{
fprintf(stderr,"Failed to make channel devices\n");
exit(-1);
}
/* Using the exit construct rather than return ensures the atexit gets called */
if (!options.port)
exit(usbFeeder());
else
exit(serialFeeder());
fprintf(stderr,"Returned\n");
exit(0);
}
// ====================================================================================================

View File

@ -1,6 +1,6 @@
PROBE_HOST ?= native
PLATFORM_DIR = platforms/$(PROBE_HOST)
VPATH += $(PLATFORM_DIR) platforms/common target
VPATH += $(PLATFORM_DIR) target
ENABLE_DEBUG ?=
ifneq ($(V), 1)
@ -8,15 +8,12 @@ MAKEFLAGS += --no-print-dir
Q := @
endif
OPT_FLAGS ?= -O2
CFLAGS += -Wall -Wextra -Werror -Wno-char-subscripts\
$(OPT_FLAGS) -std=gnu99 -MD \
-I. -Iinclude -Iplatforms/common -I$(PLATFORM_DIR)
LDFLAGS += $(OPT_FLAGS)
CFLAGS += -Wall -Wextra -Werror -Wno-char-subscripts \
-std=gnu99 -MD -I./target \
-I. -Iinclude -I$(PLATFORM_DIR)
ifeq ($(ENABLE_DEBUG), 1)
CFLAGS += -DENABLE_DEBUG -g3 -ggdb
CFLAGS += -DENABLE_DEBUG
endif
SRC = \
@ -34,35 +31,88 @@ SRC = \
gdb_hostio.c \
gdb_packet.c \
hex_utils.c \
jtag_devs.c \
jtag_scan.c \
jtagtap.c \
jtagtap_generic.c \
lmi.c \
lpc_common.c \
lpc11xx.c \
lpc17xx.c \
lpc15xx.c \
lpc43xx.c \
lpc546xx.c \
kinetis.c \
main.c \
morse.c \
msp432.c \
nrf51.c \
nxpke04.c \
platform.c \
remote.c \
rp.c \
sam3x.c \
sam4l.c \
sam4l.c \
samd.c \
samx5x.c \
stm32f1.c \
ch32f1.c \
stm32f4.c \
stm32h7.c \
stm32l0.c \
stm32l4.c \
swdptap.c \
swdptap_generic.c \
stm32g0.c \
target.c \
include $(PLATFORM_DIR)/Makefile.inc
OBJ = $(SRC:.c=.o)
OPT_FLAGS ?= -Os
CFLAGS += $(OPT_FLAGS)
LDFLAGS += $(OPT_FLAGS)
blackmagic: include/version.h $(OBJ)
ifndef TARGET
ifdef PC_HOSTED
TARGET = blackmagic
else
TARGET = blackmagic.elf
endif
endif
ifdef NO_OWN_LL
SRC += jtagtap_generic.c swdptap_generic.c
endif
ifdef PC_HOSTED
CFLAGS += -DPC_HOSTED=1
else
SRC += swdptap.c jtagtap.c
CFLAGS += -DPC_HOSTED=0
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)
@ -70,44 +120,84 @@ blackmagic: include/version.h $(OBJ)
@echo " CC $<"
$(Q)$(CC) $(CFLAGS) -c $< -o $@
%.bin: %
%.o: %.S
@echo " AS $<"
$(Q)$(CC) $(CFLAGS) -c $< -o $@
ifndef PC_HOSTED
%.bin: %.elf
@echo " OBJCOPY $@"
$(Q)$(OBJCOPY) $(OBJCOPY_FLAGS) -O binary $^ $@
%.hex: %
%.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"
-$(Q)$(RM) -f *.o *.d *~ blackmagic $(HOSTFILES)
-$(Q)$(RM) -f platforms/*/*.o platforms/*/*.d mapfile
-$(Q)$(RM) *.o *.d *.elf *~ $(TARGET) $(HOSTFILES)
-$(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 --tags --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>"\
>> artifacts/index.html ;\
fi ;\
if [ -f blackmagic_dfu.bin ]; then \
mv blackmagic_dfu.bin artifacts/blackmagic_dfu-$$PROBE_HOST.bin ;\
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 --tags --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 \"`git describe --tags --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,39 +29,44 @@
#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(void);
static bool cmd_serial(void);
static bool cmd_help(target *t);
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(void);
static bool cmd_targets(void);
static bool cmd_morse(void);
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);
static bool cmd_connect_srst(target *t, int argc, const char **argv);
static bool cmd_hard_srst(void);
static bool cmd_hard_srst(target *t, int argc, const char **argv);
#ifdef PLATFORM_HAS_POWER_SWITCH
static bool cmd_target_power(target *t, int argc, const char **argv);
#endif
#ifdef PLATFORM_HAS_TRACESWO
static bool cmd_traceswo(void);
static bool cmd_traceswo(target *t, int argc, const char **argv);
#endif
#ifdef PLATFORM_HAS_DEBUG
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
@ -78,17 +85,27 @@ const struct command_s cmd_list[] = {
{"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)" },
{"connect_srst", (cmd_handler)cmd_connect_srst, "Configure connect under SRST: (enable|disable)" },
{"hard_srst", (cmd_handler)cmd_hard_srst, "Force a pulse on the hard SRST line - disconnects target" },
#ifdef PLATFORM_HAS_POWER_SWITCH
{"tpwr", (cmd_handler)cmd_target_power, "Supplies power to the target: (enable|disable)"},
#endif
#ifdef PLATFORM_HAS_TRACESWO
{"traceswo", (cmd_handler)cmd_traceswo, "Start trace capture" },
#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_DEBUG
#ifdef PLATFORM_HAS_TRACESWO
#if defined TRACESWO_PROTOCOL && TRACESWO_PROTOCOL == 2
{"traceswo", (cmd_handler)cmd_traceswo, "Start trace capture, NRZ mode: (baudrate) (decode channel ...)" },
#else
{"traceswo", (cmd_handler)cmd_traceswo, "Start trace capture, Manchester mode: (decode channel ...)" },
#endif
#endif
{"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
@ -101,16 +118,18 @@ const struct command_s cmd_list[] = {
{NULL, NULL, NULL}
};
static bool connect_assert_srst;
#ifdef PLATFORM_HAS_DEBUG
bool connect_assert_srst;
#if defined(PLATFORM_HAS_DEBUG) && (PC_HOSTED == 0)
bool debug_bmp;
#endif
unsigned cortexm_wait_timeout = 2000; /* Timeout to wait for Cortex to react on halt command. */
int command_process(target *t, char *cmd)
{
const struct command_s *c;
int argc = 0;
int argc = 1;
const char **argv;
const char *part;
/* Initial estimate for argc */
for(char *s = cmd; *s; s++)
@ -119,8 +138,9 @@ int command_process(target *t, char *cmd)
argv = alloca(sizeof(const char *) * argc);
/* Tokenize cmd to find argv */
for(argc = 0, argv[argc] = strtok(cmd, " \t");
argv[argc]; argv[++argc] = strtok(NULL, " \t"));
argc = 0;
for (part = strtok(cmd, " \t"); part; part = strtok(NULL, " \t"))
argv[argc++] = part;
/* Look for match and call handler */
for(c = cmd_list; c->cmd; c++) {
@ -137,24 +157,39 @@ int command_process(target *t, char *cmd)
return target_command(t, argc, argv);
}
bool cmd_version(void)
#define BOARD_IDENT "Black Magic Probe" PLATFORM_IDENT FIRMWARE_VERSION
bool cmd_version(target *t, int argc, char **argv)
{
gdb_outf("Black Magic Probe (Firmware " FIRMWARE_VERSION ") (Hardware Version %d)\n", platform_hwversion());
gdb_out("Copyright (C) 2015 Black Sphere Technologies Ltd.\n");
(void)t;
(void)argc;
(void)argv;
#if PC_HOSTED == 1
char ident[256];
gdb_ident(ident, sizeof(ident));
DEBUG_WARN("%s\n", ident);
#else
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;
}
bool cmd_help(target *t)
bool cmd_help(target *t, int argc, char **argv)
{
(void)argc;
(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;
@ -168,7 +203,8 @@ static bool cmd_jtag_scan(target *t, int argc, char **argv)
(void)t;
uint8_t irlens[argc];
gdb_outf("Target voltage: %s\n", platform_target_voltage());
if (platform_target_voltage())
gdb_outf("Target voltage: %s\n", platform_target_voltage());
if (argc > 1) {
/* Accept a list of IR lengths on command line */
@ -183,7 +219,11 @@ static bool cmd_jtag_scan(target *t, int argc, char **argv)
int devs = -1;
volatile struct exception e;
TRY_CATCH (e, EXCEPTION_ALL) {
#if PC_HOSTED == 1
devs = platform_jtag_scan(argc > 1 ? irlens : NULL);
#else
devs = jtag_scan(argc > 1 ? irlens : NULL);
#endif
}
switch (e.type) {
case EXCEPTION_TIMEOUT:
@ -199,14 +239,19 @@ static bool cmd_jtag_scan(target *t, int argc, char **argv)
gdb_out("JTAG device scan failed!\n");
return false;
}
cmd_targets();
cmd_targets(NULL, 0, NULL);
morse(NULL, false);
return true;
}
bool cmd_swdp_scan(void)
bool cmd_swdp_scan(target *t, int argc, char **argv)
{
gdb_outf("Target voltage: %s\n", platform_target_voltage());
(void)t;
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());
if(connect_assert_srst)
platform_srst_set_val(true); /* will be deasserted after attach */
@ -214,8 +259,12 @@ bool cmd_swdp_scan(void)
int devs = -1;
volatile struct exception e;
TRY_CATCH (e, EXCEPTION_ALL) {
devs = adiv5_swdp_scan();
}
#if PC_HOSTED == 1
devs = platform_adiv5_swdp_scan(targetid);
#else
devs = adiv5_swdp_scan(targetid);
#endif
}
switch (e.type) {
case EXCEPTION_TIMEOUT:
gdb_outf("Timeout during scan. Is target stuck in WFI?\n");
@ -231,20 +280,59 @@ bool cmd_swdp_scan(void)
return false;
}
cmd_targets();
cmd_targets(NULL, 0, NULL);
morse(NULL, false);
return true;
}
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\n", i, target_attached(t)?'*':' ', target_driver_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(void)
bool cmd_targets(target *t, int argc, char **argv)
{
(void)t;
(void)argc;
(void)argv;
gdb_out("Available Targets:\n");
gdb_out("No. Att Driver\n");
if (!target_foreach(display_target, NULL)) {
@ -255,26 +343,70 @@ bool cmd_targets(void)
return true;
}
bool cmd_morse(void)
bool cmd_morse(target *t, int argc, char **argv)
{
if(morse_msg)
(void)t;
(void)argc;
(void)argv;
if(morse_msg) {
gdb_outf("%s\n", morse_msg);
DEBUG_WARN("%s\n", morse_msg);
}
return true;
}
bool parse_enable_or_disable(const char *s, bool *out) {
if (strlen(s) == 0) {
gdb_outf("'enable' or 'disable' argument must be provided\n");
return false;
} else if (!strncmp(s, "enable", strlen(s))) {
*out = true;
return true;
} else if (!strncmp(s, "disable", strlen(s))) {
*out = false;
return true;
} else {
gdb_outf("Argument '%s' not recognized as 'enable' or 'disable'\n", s);
return false;
}
}
static bool cmd_connect_srst(target *t, int argc, const char **argv)
{
(void)t;
if (argc == 1)
bool print_status = false;
if (argc == 1) {
print_status = true;
} else if (argc == 2) {
if (parse_enable_or_disable(argv[1], &connect_assert_srst)) {
print_status = true;
}
} else {
gdb_outf("Unrecognized command format\n");
}
if (print_status) {
gdb_outf("Assert SRST during connect: %s\n",
connect_assert_srst ? "enabled" : "disabled");
else
connect_assert_srst = !strcmp(argv[1], "enable");
}
return true;
}
static bool cmd_hard_srst(void)
static bool cmd_halt_timeout(target *t, int argc, const char **argv)
{
(void)t;
if (argc > 1)
cortexm_wait_timeout = atol(argv[1]);
gdb_outf("Cortex-M timeout to wait for device haltes: %d\n",
cortexm_wait_timeout);
return true;
}
static bool cmd_hard_srst(target *t, int argc, const char **argv)
{
(void)t;
(void)argc;
(void)argv;
target_list_free();
platform_srst_set_val(true);
platform_srst_set_val(false);
@ -285,34 +417,179 @@ static bool cmd_hard_srst(void)
static bool cmd_target_power(target *t, int argc, const char **argv)
{
(void)t;
if (argc == 1)
if (argc == 1) {
gdb_outf("Target Power: %s\n",
platform_target_get_power() ? "enabled" : "disabled");
else
platform_target_set_power(!strncmp(argv[1], "enable", strlen(argv[1])));
} else if (argc == 2) {
bool want_enable = false;
if (parse_enable_or_disable(argv[1], &want_enable)) {
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");
}
return true;
}
#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(void)
static bool cmd_traceswo(target *t, int argc, const char **argv)
{
extern char serial_no[9];
traceswo_init();
char serial_no[DFU_SERIAL_LENGTH];
(void)t;
#if TRACESWO_PROTOCOL == 2
uint32_t baudrate = SWO_DEFAULT_BAUD;
#endif
uint32_t swo_channelmask = 0; /* swo decoding off */
uint8_t decode_arg = 1;
#if TRACESWO_PROTOCOL == 2
/* argument: optional baud rate for async mode */
if ((argc > 1) && (*argv[1] >= '0') && (*argv[1] <= '9')) {
baudrate = atoi(argv[1]);
if (baudrate == 0) baudrate = SWO_DEFAULT_BAUD;
decode_arg = 2;
}
#endif
/* argument: 'decode' literal */
if((argc > decode_arg) && !strncmp(argv[decode_arg], "decode", strlen(argv[decode_arg]))) {
swo_channelmask = 0xFFFFFFFF; /* decoding all channels */
/* arguments: channels to decode */
if (argc > decode_arg + 1) {
swo_channelmask = 0x0;
for (int i = decode_arg+1; i < argc; i++) { /* create bitmask of channels to decode */
int channel = atoi(argv[i]);
if ((channel >= 0) && (channel <= 31))
swo_channelmask |= (uint32_t)0x1 << channel;
}
}
}
#if defined(PLATFORM_HAS_DEBUG) && (PC_HOSTED == 0) && defined(ENABLE_DEBUG)
if (debug_bmp) {
#if TRACESWO_PROTOCOL == 2
gdb_outf("baudrate: %lu ", baudrate);
#endif
gdb_outf("channel mask: ");
for (int8_t i=31;i>=0;i--) {
uint8_t bit = (swo_channelmask >> i) & 0x1;
gdb_outf("%u", bit);
}
gdb_outf("\n");
}
#endif
#if TRACESWO_PROTOCOL == 2
traceswo_init(baudrate, swo_channelmask);
#else
traceswo_init(swo_channelmask);
#endif
serial_no_read(serial_no);
gdb_outf("%s:%02X:%02X\n", serial_no, 5, 0x85);
return true;
}
#endif
#ifdef PLATFORM_HAS_DEBUG
#if defined(PLATFORM_HAS_DEBUG) && (PC_HOSTED == 0)
static bool cmd_debug_bmp(target *t, int argc, const char **argv)
{
(void)t;
if (argc > 1) {
debug_bmp = !strcmp(argv[1], "enable");
bool print_status = false;
if (argc == 1) {
print_status = true;
} else if (argc == 2) {
if (parse_enable_or_disable(argv[1], &debug_bmp)) {
print_status = true;
}
} else {
gdb_outf("Unrecognized command format\n");
}
if (print_status) {
gdb_outf("Debug mode is %s\n",
debug_bmp ? "enabled" : "disabled");
}
gdb_outf("Debug mode is %s\n",
debug_bmp ? "enabled" : "disabled");
return true;
}
#endif
@ -365,9 +642,28 @@ static bool cmd_enter_bootldr(target *t, int argc, const char **argv)
#endif
#ifdef PLATFORM_HAS_PRINTSERIAL
bool cmd_serial(void)
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");
else if (argc == 5) {
target_addr heap_base = strtoul(argv[1], NULL, 16);
target_addr heap_limit = strtoul(argv[2], NULL, 16);
target_addr stack_base = strtoul(argv[3], NULL, 16);
target_addr stack_limit = strtoul(argv[4], NULL, 16);
gdb_outf("heapinfo heap_base: %p heap_limit: %p stack_base: %p stack_limit: %p\n",
heap_base, heap_limit, stack_base, stack_limit);
target_set_heapinfo(t, heap_base, heap_limit, stack_base, stack_limit);
} else gdb_outf("heapinfo heap_base heap_limit stack_base stack_limit\n");
return true;
}

View File

@ -20,8 +20,12 @@
#include "general.h"
#include "target.h"
#include "gdb_if.h"
#if !defined(STM32F1) && !defined(STM32F4)
#if !defined(STM32F0) && !defined(STM32F1) && !defined(STM32F2) && \
!defined(STM32F3) && !defined(STM32F4) && !defined(STM32F7) && \
!defined(STM32L0) && !defined(STM32L1) && !defined(STM32F4) && \
!defined(STM32G0) && !defined(STM32G4)
static const uint32_t crc32_table[] = {
0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9,
0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005,
@ -94,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]);
@ -109,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));
@ -133,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;
@ -144,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("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

@ -25,6 +25,7 @@
*/
#include "general.h"
#include "ctype.h"
#include "hex_utils.h"
#include "gdb_if.h"
#include "gdb_packet.h"
@ -34,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,
@ -42,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;
@ -93,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();
@ -119,24 +133,26 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall)
gdb_putpacketz("E02");
break;
}
DEBUG("m packet: addr = %" PRIx32 ", len = %" PRIx32 "\n", addr, len);
DEBUG_GDB("m packet: addr = %" PRIx32 ", len = %" PRIx32 "\n",
addr, len);
uint8_t mem[len];
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);
@ -144,7 +160,8 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall)
gdb_putpacketz("E02");
break;
}
DEBUG("M packet: addr = %" PRIx32 ", len = %" PRIx32 "\n", addr, len);
DEBUG_GDB("M packet: addr = %" PRIx32 ", len = %" PRIx32 "\n",
addr, len);
uint8_t mem[len];
unhexify(mem, pbuf + hex, len);
if (target_mem_write(cur_target, addr, mem, len))
@ -152,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 to resume target
/* fall through */
case 'c': /* 'c [addr]': Continue [at addr] */
if(!cur_target) {
if (!cur_target) {
gdb_putpacketz("X1D");
break;
}
@ -165,14 +195,14 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall)
target_halt_resume(cur_target, single_step);
SET_RUN_STATE(1);
single_step = false;
// Fall through to wait for target halt
/* fall through */
case '?': { /* '?': Request reason for target halt */
/* This packet isn't documented as being mandatory,
* but GDB doesn't work without it. */
target_addr watch;
enum target_halt_reason reason;
if(!cur_target) {
if (!cur_target) {
/* Report "target exited" if no target */
gdb_putpacketz("W00");
break;
@ -180,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);
@ -206,17 +239,45 @@ 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 */
ERROR_IF_NO_TARGET();
uint32_t reg;
sscanf(pbuf, "p%" SCNx32, &reg);
uint8_t val[8];
size_t s = target_reg_read(cur_target, reg, val, sizeof(val));
if (s > 0)
gdb_putpacket(hexify(pbuf, val, s), s * 2);
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);
// 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)
gdb_putpacketz("OK");
else
gdb_putpacketz("EFF");
break;
}
case 'F': /* Semihosting call finished */
if (in_syscall) {
if (in_syscall)
return hostio_reply(tc, pbuf, size);
} else {
DEBUG("*** F packet when not in syscall! '%s'\n", pbuf);
else {
DEBUG_GDB("*** F packet when not in syscall! '%s'\n", pbuf);
gdb_putpacketz("");
}
break;
/* Optional GDB packet support */
case '!': /* Enable Extended GDB Protocol. */
/* This doesn't do anything, we support the extended
* protocol anyway, but GDB will never send us a 'R'
@ -227,20 +288,17 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall)
case 0x04:
case 'D': /* GDB 'detach' command. */
if(cur_target)
if(cur_target) {
SET_RUN_STATE(1);
target_detach(cur_target);
}
last_target = cur_target;
cur_target = NULL;
gdb_putpacketz("OK");
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 */
@ -250,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;
@ -263,19 +323,20 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall)
gdb_putpacketz("E02");
break;
}
DEBUG("X packet: addr = %" PRIx32 ", len = %" PRIx32 "\n", addr, len);
if (target_mem_write(cur_target, addr, pbuf+bin, len))
DEBUG_GDB("X packet: addr = %" PRIx32 ", len = %" PRIx32 "\n",
addr, 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;
@ -287,199 +348,344 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall)
break;
default: /* Packet not implemented */
DEBUG("*** Unsupported packet: %s\n", pbuf);
DEBUG_GDB("*** Unsupported packet: %s\n", pbuf);
gdb_putpacketz("");
}
}
}
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;
}
handle_q_string_reply(target_mem_map(cur_target), 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("*** 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 (!strcmp(packet, "vRun;")) {
} 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 *pcmdline = cmdline;
char *tok = packet + 4;
if (*tok == ';')
++tok;
cmdline[0] = '\0';
while(*tok != '\0') {
if (strlen(cmdline) + 3 >= sizeof(cmdline))
break;
if (*tok == ';') {
*pcmdline++ = ' ';
pcmdline[0] = '\0';
tok++;
continue;
}
if (isxdigit(tok[0]) && isxdigit(tok[1])) {
unhexify(pcmdline, tok, 2);
if ((*pcmdline == ' ') || (*pcmdline == '\\')) {
pcmdline[1] = *pcmdline;
*pcmdline++ = '\\';
}
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) {
target_reset(cur_target);
gdb_putpacketz("T05");
} else gdb_putpacketz("E01");
/* If we were able to attach to the target again */
if (cur_target) {
target_set_cmdline(cur_target, cmdline);
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("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("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");
}
} else if (!strcmp(packet, "vFlashDone")) {
/* Commit flash operations. */
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("*** Unsupported packet: %s\n", packet);
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)
{
gdb_main_loop(&gdb_controller, false);
}

View File

@ -26,107 +26,200 @@
#include "gdb_if.h"
#include "gdb_packet.h"
#include "hex_utils.h"
#include "remote.h"
#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) {
/* Wait for packet start */
while((packet[0] = gdb_if_getchar()) != '$')
if(packet[0] == 0x04) return 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 {
/* 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) {
/* This is probably a remote control packet
* - get and handle it */
offset = 0;
bool gettingRemotePacket = true;
while (gettingRemotePacket) {
/* Smells like bad code */
const char c = (char)gdb_if_getchar();
switch (c) {
case REMOTE_SOM: /* Oh dear, packet restarts */
offset = 0;
break;
i = 0; csum = 0;
case REMOTE_EOM: /* Complete packet for processing */
packet[offset] = 0;
remotePacketProcess(offset, packet);
gettingRemotePacket = false;
break;
case '$': /* A 'real' gdb packet, best stop squatting now */
packet[0] = '$';
gettingRemotePacket = false;
break;
default:
if (offset < size) {
packet[offset++] = c;
} else {
/* Who knows what is going on...return to normality */
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] != '$');
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;
#ifdef DEBUG_GDBPACKET
DEBUG("%s : ", __func__);
for(int j = 0; j < i; j++) {
c = packet[j];
if ((c >= 32) && (c < 127))
DEBUG("%c", c);
#if PC_HOSTED == 1
DEBUG_GDB_WIRE("%s : ", __func__);
for (size_t j = 0; j < offset; j++) {
const char c = packet[j];
if (c >= ' ' && c < 0x7F)
DEBUG_GDB_WIRE("%c", c);
else
DEBUG("\\x%02X", c);
DEBUG_GDB_WIRE("\\x%02X", c);
}
DEBUG("\n");
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 {
#ifdef DEBUG_GDBPACKET
DEBUG("%s : ", __func__);
#endif
csum = 0;
DEBUG_GDB_WIRE("%s: ", __func__);
unsigned char csum = 0;
gdb_if_putchar('$', 0);
for(i = 0; i < size; i++) {
c = packet[i];
#ifdef DEBUG_GDBPACKET
if ((c >= 32) && (c < 127))
DEBUG("%c", c);
else
DEBUG("\\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);
sprintf(xmit_csum, "%02X", csum);
snprintf(xmit_csum, sizeof(xmit_csum), "%02X", csum);
gdb_if_putchar(xmit_csum[0], 0);
gdb_if_putchar(xmit_csum[1], 1);
#ifdef DEBUG_GDBPACKET
DEBUG("\n");
#endif
} while((gdb_if_getchar_to(2000) != '+') && (tries++ < 3));
DEBUG_GDB_WIRE("\n");
} 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, ...)
@ -144,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,9 +21,19 @@
#ifndef __COMMAND_H
#define __COMMAND_H
#include <stdbool.h>
#include "target.h"
int command_process(target *t, char *cmd);
/*
* Attempts to parse a string as either being "enable" or "disable".
* If the parse is successful, returns true and sets the out param to
* indicate what was parsed. If not successful, emits a warning to the
* gdb port, returns false and leaves out untouched.
*/
bool parse_enable_or_disable(const char *s, bool *out);
#endif

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

@ -21,7 +21,7 @@
#ifndef __GDB_IF_H
#define __GDB_IF_H
#if !defined(LIBFTDI)
#if PC_HOSTED == 0
#include <libopencm3/usb/usbd.h>
void gdb_usb_out_cb(usbd_device *dev, uint8_t ep);
#endif
@ -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,12 @@
#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
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
@ -29,18 +34,141 @@
#include <stdio.h>
#include <stddef.h>
#include <inttypes.h>
#include <sys/types.h>
#include "platform.h"
#include "platform_support.h"
#ifndef DEBUG
#include <stdio.h>
#define DEBUG printf
extern uint32_t delay_cnt;
enum BMP_DEBUG {
BMP_DEBUG_NONE = 0,
BMP_DEBUG_INFO = 1,
BMP_DEBUG_GDB = 2,
BMP_DEBUG_TARGET = 4,
BMP_DEBUG_PROBE = 8,
BMP_DEBUG_WIRE = 0x10,
BMP_DEBUG_MAX = 0x20,
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(PLATFORM_PRINTF)
# define PLATFORM_PRINTF printf
# endif
# 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;
static inline void DEBUG_WARN(const char *format, ...)
{
va_list ap;
va_start(ap, format);
vfprintf(stderr, format, ap);
va_end(ap);
return;
}
static inline void DEBUG_INFO(const char *format, ...)
{
if (~cl_debuglevel & BMP_DEBUG_INFO)
return;
va_list ap;
va_start(ap, format);
if (cl_debuglevel & BMP_DEBUG_STDOUT)
vfprintf(stdout, format, ap);
else
vfprintf(stderr, format, ap);
va_end(ap);
return;
}
static inline void DEBUG_GDB(const char *format, ...)
{
if (~cl_debuglevel & BMP_DEBUG_GDB)
return;
va_list ap;
va_start(ap, format);
vfprintf(stderr, format, ap);
va_end(ap);
return;
}
static inline void DEBUG_GDB_WIRE(const char *format, ...)
{
if ((cl_debuglevel & (BMP_DEBUG_GDB | BMP_DEBUG_WIRE)) !=
(BMP_DEBUG_GDB | BMP_DEBUG_WIRE))
return;
va_list ap;
va_start(ap, format);
vfprintf(stderr, format, ap);
va_end(ap);
return;
}
static inline void DEBUG_TARGET(const char *format, ...)
{
if (~cl_debuglevel & BMP_DEBUG_TARGET)
return;
va_list ap;
va_start(ap, format);
vfprintf(stderr, format, ap);
va_end(ap);
return;
}
static inline void DEBUG_PROBE(const char *format, ...)
{
if (~cl_debuglevel & BMP_DEBUG_PROBE)
return;
va_list ap;
va_start(ap, format);
vfprintf(stderr, format, ap);
va_end(ap);
return;
}
static inline void DEBUG_WIRE(const char *format, ...)
{
if (~cl_debuglevel & BMP_DEBUG_WIRE)
return;
va_list ap;
va_start(ap, format);
vfprintf(stderr, format, ap);
va_end(ap);
return;
}
#endif
#define ALIGN(x, n) (((x) + (n) - 1) & ~((n) - 1))
#undef MIN
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
#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

@ -21,13 +21,12 @@
#ifndef __JTAGTAP_H
#define __JTAGTAP_H
typedef struct jtag_proc_s {
/* Note: Signal names are as for the device under test. */
int jtagtap_init(void);
void (*jtagtap_reset)(void);
void jtagtap_reset(void);
uint8_t jtagtap_next(const uint8_t TMS, const uint8_t TDI);
uint8_t (*jtagtap_next)(const uint8_t TMS, const uint8_t TDI);
/* tap_next executes one state transision in the JTAG TAP state machine:
* - Ensure TCK is low
* - Assert the values of TMS and TDI
@ -36,30 +35,39 @@ uint8_t jtagtap_next(const uint8_t TMS, const uint8_t TDI);
* - Release TCK.
*/
void jtagtap_tms_seq(uint32_t MS, int ticks);
void jtagtap_tdi_tdo_seq(uint8_t *DO, const uint8_t final_tms, const uint8_t *DI, int ticks);
void jtagtap_tdi_seq(const uint8_t final_tms, const uint8_t *DI, int ticks);
void (*jtagtap_tms_seq)(uint32_t MS, int ticks);
void (*jtagtap_tdi_tdo_seq)
(uint8_t *DO, const uint8_t final_tms, const uint8_t *DI, int ticks);
/* Shift out a sequence on MS and DI, capture data to DO.
* - This is not endian safe: First byte will always be first shifted out.
* - DO may be NULL to ignore captured data.
* - DO may be point to the same address as DI.
*/
void (*jtagtap_tdi_seq)
(const uint8_t final_tms, const uint8_t *DI, int ticks);
} jtag_proc_t;
extern jtag_proc_t jtag_proc;
/* generic soft reset: 1, 1, 1, 1, 1, 0 */
#define jtagtap_soft_reset() \
jtagtap_tms_seq(0x1F, 6)
jtag_proc.jtagtap_tms_seq(0x1F, 6)
/* Goto Shift-IR: 1, 1, 0, 0 */
#define jtagtap_shift_ir() \
jtagtap_tms_seq(0x03, 4)
jtag_proc.jtagtap_tms_seq(0x03, 4)
/* Goto Shift-DR: 1, 0, 0 */
#define jtagtap_shift_dr() \
jtagtap_tms_seq(0x01, 3)
jtag_proc.jtagtap_tms_seq(0x01, 3)
/* Goto Run-test/Idle: 1, 1, 0 */
#define jtagtap_return_idle() \
jtagtap_tms_seq(0x01, 2)
jtag_proc.jtagtap_tms_seq(0x01, 2)
# if PC_HOSTED == 1
int platform_jtagtap_init(void);
# else
int jtagtap_init(void);
# endif
#endif

View File

@ -24,7 +24,9 @@
# error "Include 'general.h' instead"
#endif
#if defined(LIBFTDI)
#include "target.h"
#if PC_HOSTED == 1
void platform_init(int argc, char **argv);
#else
void platform_init(void);
@ -35,6 +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);
@ -42,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

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

@ -26,15 +26,22 @@
#define __TARGET_H
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <sys/types.h>
typedef struct target_s target;
typedef uint32_t target_addr;
struct target_controller;
int adiv5_swdp_scan(void);
#if PC_HOSTED == 1
int platform_adiv5_swdp_scan(uint32_t targetid);
int platform_jtag_scan(const uint8_t *lrlens);
#endif
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 */
@ -43,9 +50,12 @@ target *target_attach_n(int n, struct target_controller *);
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 */
const char *target_mem_map(target *t);
bool target_mem_map(target *t, char *buf, size_t len);
int target_mem_read(target *t, void *dest, target_addr src, size_t len);
int target_mem_write(target *t, target_addr dest, const void *src, size_t len);
/* Flash memory access functions */
@ -58,6 +68,8 @@ size_t target_regs_size(target *t);
const char *target_tdesc(target *t);
void target_regs_read(target *t, void *data);
void target_regs_write(target *t, const void *data);
ssize_t target_reg_read(target *t, int reg, void *data, size_t max);
ssize_t target_reg_write(target *t, int reg, const void *data, size_t size);
/* Halt/resume functions */
enum target_halt_reason {
@ -74,6 +86,9 @@ void target_reset(target *t);
void target_halt_request(target *t);
enum target_halt_reason target_halt_poll(target *t, target_addr *watch);
void target_halt_resume(target *t, bool step);
void target_set_cmdline(target *t, char *cmdline);
void target_set_heapinfo(target *t, target_addr heap_base, target_addr heap_limit,
target_addr stack_base, target_addr stack_limit);
/* Break-/watchpoint functions */
enum target_breakwatch {
@ -90,11 +105,12 @@ int target_breakwatch_clear(target *t, enum target_breakwatch, target_addr, size
void target_command_help(target *t);
int target_command(target *t, int argc, const char *argv[]);
/* keep target_errno in sync with errno values in gdb/include/gdb/fileio.h */
enum target_errno {
TARGET_EPERM = 1,
TARGET_ENOENT = 2,
TARGET_EINTR = 4,
TARGET_EIO = 5,
TARGET_EBADF = 9,
TARGET_EACCES = 13,
TARGET_EFAULT = 14,
@ -104,13 +120,15 @@ enum target_errno {
TARGET_ENOTDIR = 20,
TARGET_EISDIR = 21,
TARGET_EINVAL = 22,
TARGET_EMFILE = 24,
TARGET_ENFILE = 23,
TARGET_EMFILE = 24,
TARGET_EFBIG = 27,
TARGET_ENOSPC = 28,
TARGET_ESPIPE = 29,
TARGET_EROFS = 30,
TARGET_ENAMETOOLONG = 36,
TARGET_ENOSYS = 88,
TARGET_ENAMETOOLONG = 91,
TARGET_EUNKNOWN = 9999,
};
enum target_open_flags {

View File

@ -24,7 +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

@ -33,7 +33,7 @@
int
main(int argc, char **argv)
{
#if defined(LIBFTDI)
#if PC_HOSTED == 1
platform_init(argc, argv);
#else
(void) argc;

View File

@ -59,8 +59,14 @@ static char morse_repeat;
void morse(const char *msg, char repeat)
{
#if PC_HOSTED == 1
if (msg)
DEBUG_WARN("%s\n", msg);
(void) repeat;
#else
morse_msg = morse_ptr = msg;
morse_repeat = repeat;
#endif
}
bool morse_update(void)

23
src/platforms/Readme.md Normal file
View File

@ -0,0 +1,23 @@
# Platforms and platform support files
This directory contains the implementation of platforms and support file
used by (multiple) platforms.
## Implementation directories
native : Firmware for original Black Magic Probe<br>
stlink : Firmware for STLINK-V2 and V21<br>
swlink : Firmware for STLINK-V1 and Bluepill<br>
hydrabus : Firmware https://hydrabus.com/ <br>
f4discovery : Firmware for STM32F407DISCO<br>
launchpad-icdi :<br>
tm4c: <br>
hosted: PC-hosted BMP running as PC application talking to firmware BMPs,
STLINK-V2/21/3, FTDI MPSSE probes, CMSIS-DAP and JLINK
## Support directories
common: libopencm3 based support for firmware BMPs<br>
stm32: STM32 specific libopencm3 based support for firmware BMPs<br>
pc: Support for PC-hosted BMPs.<br>

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 */
.bMaxPacketSize0 = 64,
#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,
.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,16 +409,17 @@ static const struct usb_config_descriptor config = {
.interface = ifaces,
};
static char serial_no[DFU_SERIAL_LENGTH];
char serial_no[9];
#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
@ -419,7 +440,7 @@ static void dfu_detach_complete(usbd_device *dev, struct usb_setup_data *req)
#endif
}
static int cdcacm_control_request(usbd_device *dev,
static enum usbd_request_return_codes cdcacm_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))
{
@ -432,23 +453,24 @@ static int 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)
return 1;
if(req->wIndex != GDB_IF_NO)
return USBD_REQ_HANDLED;
cdcacm_gdb_dtr = req->wValue & 1;
return 1;
return USBD_REQ_HANDLED;
case USB_CDC_REQ_SET_LINE_CODING:
if(*len < sizeof(struct usb_cdc_line_coding))
return 0;
return USBD_REQ_NOTSUPP;
switch(req->wIndex) {
case 2:
case UART_IF_NO:
usbuart_set_line_coding((struct usb_cdc_line_coding*)*buf);
case 0:
return 1; /* Ignore on GDB Port */
return USBD_REQ_HANDLED;
case GDB_IF_NO:
return USBD_REQ_HANDLED; /* Ignore on GDB Port */
default:
return 0;
return USBD_REQ_NOTSUPP;
}
case DFU_GETSTATUS:
if(req->wIndex == DFU_IF_NO) {
@ -460,16 +482,17 @@ static int cdcacm_control_request(usbd_device *dev,
(*buf)[5] = 0; /* iString not used here */
*len = 6;
return 1;
return USBD_REQ_HANDLED;
}
return USBD_REQ_NOTSUPP;
case DFU_DETACH:
if(req->wIndex == DFU_IF_NO) {
*complete = dfu_detach_complete;
return 1;
return USBD_REQ_HANDLED;
}
return 0;
return USBD_REQ_NOTSUPP;
}
return 0;
return USBD_REQ_NOTSUPP;
}
int cdcacm_get_config(void)
@ -494,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);
}
@ -503,26 +527,29 @@ static void cdcacm_set_config(usbd_device *dev, uint16_t wValue)
/* GDB interface */
#if defined(STM32F4) || defined(LM4F) || defined(SAMD)
usbd_ep_setup(dev, 0x01, USB_ENDPOINT_ATTR_BULK,
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,
CDCACM_PACKET_SIZE, usbuart_usb_out_cb);
usbd_ep_setup(dev, 0x83, 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, 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
@ -534,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: */
@ -545,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));
@ -562,4 +589,3 @@ void USB_ISR(void)
{
usbd_poll(usbdev);
}

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

@ -0,0 +1,199 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2011 Black Sphere Technologies Ltd.
* 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
* (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/>.
*/
/* This file implements the low-level JTAG TAP interface. */
#include <stdio.h>
#include "general.h"
#include "jtagtap.h"
#include "gdb_packet.h"
jtag_proc_t jtag_proc;
static void jtagtap_reset(void);
static void jtagtap_tms_seq(uint32_t MS, int ticks);
static void jtagtap_tdi_tdo_seq(
uint8_t *DO, const uint8_t final_tms, const uint8_t *DI, int ticks);
static void jtagtap_tdi_seq(
const uint8_t final_tms, const uint8_t *DI, int ticks);
static uint8_t jtagtap_next(uint8_t dTMS, uint8_t dTDI);
int jtagtap_init()
{
TMS_SET_MODE();
jtag_proc.jtagtap_reset = jtagtap_reset;
jtag_proc.jtagtap_next =jtagtap_next;
jtag_proc.jtagtap_tms_seq = jtagtap_tms_seq;
jtag_proc.jtagtap_tdi_tdo_seq = jtagtap_tdi_tdo_seq;
jtag_proc.jtagtap_tdi_seq = jtagtap_tdi_seq;
/* Go to JTAG mode for SWJ-DP */
for(int i = 0; i <= 50; i++) jtagtap_next(1, 0); /* Reset SW-DP */
jtagtap_tms_seq(0xE73C, 16); /* SWD to JTAG sequence */
jtagtap_soft_reset();
return 0;
}
static void jtagtap_reset(void)
{
#ifdef TRST_PORT
if (platform_hwversion() == 0) {
volatile int i;
gpio_clear(TRST_PORT, TRST_PIN);
for(i = 0; i < 10000; i++) asm("nop");
gpio_set(TRST_PORT, TRST_PIN);
}
#endif
jtagtap_soft_reset();
}
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);
return ret != 0;
}
static void jtagtap_tms_seq(uint32_t MS, int ticks)
{
gpio_set_val(TDI_PORT, TDI_PIN, 1);
int data = MS & 1;
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);
}
}
}
static void jtagtap_tdi_tdo_seq(
uint8_t *DO, const uint8_t final_tms, const uint8_t *DI, int ticks)
{
uint8_t index = 1;
gpio_set_val(TMS_PORT, TMS_PIN, 0);
uint8_t res = 0;
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--);
}
} 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);
}
}
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;
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);
}
}
}

View File

@ -18,9 +18,198 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* This file implements the low-level SW-DP interface. */
/* This file implements the SW-DP interface. */
#include "general.h"
#include "swdptap.h"
#include "timing.h"
#include "adiv5.h"
/* Optimized this by moving directly inline */
enum {
SWDIO_STATUS_FLOAT = 0,
SWDIO_STATUS_DRIVE
};
static void swdptap_turnaround(int dir) __attribute__ ((optimize(3)));
static uint32_t swdptap_seq_in(int ticks) __attribute__ ((optimize(3)));
static bool swdptap_seq_in_parity(uint32_t *ret, int ticks)
__attribute__ ((optimize(3)));
static void swdptap_seq_out(uint32_t MS, int ticks)
__attribute__ ((optimize(3)));
static void swdptap_seq_out_parity(uint32_t MS, int ticks)
__attribute__ ((optimize(3)));
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;
olddir = dir;
#ifdef DEBUG_SWD_BITS
DEBUG("%s", dir ? "\n-> ":"\n<- ");
#endif
if(dir == SWDIO_STATUS_FLOAT)
SWDIO_MODE_FLOAT();
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();
}
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);
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);
#endif
return ret;
}
static bool swdptap_seq_in_parity(uint32_t *ret, int ticks)
{
uint32_t index = 1;
uint32_t res = 0;
bool bit;
int len = ticks;
register volatile int32_t cnt;
swdptap_turnaround(SWDIO_STATUS_FLOAT);
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);
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);
}
static void swdptap_seq_out(uint32_t MS, int ticks)
{
#ifdef DEBUG_SWD_BITS
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);
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);
}
}
}
static void swdptap_seq_out_parity(uint32_t MS, int ticks)
{
int parity = __builtin_popcount(MS);
#ifdef DEBUG_SWD_BITS
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;
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);
for(cnt = swd_delay_cnt; --cnt > 0;);
gpio_clear(SWCLK_PORT, SWCLK_PIN);
for(cnt = swd_delay_cnt; --cnt > 0;);
}
int swdptap_init(ADIv5_DP_t *dp)
{
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

@ -22,7 +22,21 @@
#include <libopencm3/usb/usbd.h>
void traceswo_init(void);
#if defined TRACESWO_PROTOCOL && TRACESWO_PROTOCOL == 2
/* Default line rate, used as default for a request without baudrate */
#define SWO_DEFAULT_BAUD (2250000)
void traceswo_init(uint32_t baudrate, uint32_t swo_chan_bitmask);
#else
void traceswo_init(uint32_t swo_chan_bitmask);
#endif
void trace_buf_drain(usbd_device *dev, uint8_t ep);
/* set bitmask of swo channels to be decoded */
void traceswo_setmask(uint32_t mask);
/* print decoded swo packet on usb serial */
uint16_t traceswo_decode(usbd_device *usbd_dev, uint8_t addr,
const void *buf, uint16_t len);
#endif

View File

@ -1,28 +1,57 @@
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,--defsym,_stack=0x20006000 \
-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 \
traceswodecode.c \
traceswo.c \
usbuart.c \
serialno.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

@ -1,28 +0,0 @@
System vs BMP Bootloader
========================
For the BMP bootloader, flashing qas not reliable. So we use the system
bootloder unconditional.
Connections:
====================
PA0: User button to force system bootloader entry with reset
PA2/PA3 eventual connected to the STLINK/ STM32F103C8
PC2: TDI
PC4: TMS/SWDIO
PC5: TCK/SWCLK
PC6: TDO/TRACESWO
PC1: TRST
PC8: SRST
Blue Led: Indicator that system bootloader is entered via BMP
Bootstrapping the F4Discovery on-board ST-Link
==============================================
http://embdev.net/articles/STM_Discovery_as_Black_Magic_Probe has some hints
how to modify the F4Discovery on-board ST-Link. If you try to do so and hit
a problem that stands some test like that you load the right firmware to the
right device via the right BMP probe, explain, report and ask on the
blackmagic mailing list http://sourceforge.net/mail/?group_id=407419.

View File

@ -0,0 +1,65 @@
# Firmware BMP for STM32F407 DISCO boards
Kept for historical reasons to load BMP bootloader to the STM32F103 of the onboard STLINK or external STLINKs. As stlink-tool now allows to load BMP firmware via the original STLINK bootloader is no longer really needed.
## Connections:
PC2: TDI<br>
PC4: TMS/SWDIO<br>
PC5: TCK/SWCLK<br>
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,54 +27,108 @@
#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>
#include <libopencm3/stm32/usart.h>
#include <libopencm3/stm32/syscfg.h>
#include <libopencm3/usb/usbd.h>
#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;
/* 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*/
rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPAEN);
if(gpio_get(GPIOA, GPIO0)) {
platform_request_boot();
if (gpio_get(GPIOA, GPIO0) ||
((magic[0] == BOOTMAGIC0) && (magic[1] == BOOTMAGIC1)))
{
magic[0] = 0;
magic[1] = 0;
/* Assert blue LED as indicator we are in the bootloader */
gpio_mode_setup(LED_PORT, GPIO_MODE_OUTPUT,
GPIO_PUPD_NONE, LED_BOOTLOADER);
gpio_set(LED_PORT, LED_BOOTLOADER);
/* Jump to the built in bootloader by mapping System flash.
As we just come out of reset, no other deinit is needed!*/
rcc_periph_clock_enable(RCC_SYSCFG);
SYSCFG_MEMRM &= ~3;
SYSCFG_MEMRM |= 1;
scb_reset_core();
}
rcc_clock_setup_hse_3v3(&hse_8mhz_3v3[CLOCK_3V3_48MHZ]);
#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_peripheral_enable_clock(&RCC_AHB2ENR, RCC_AHB2ENR_OTGFSEN);
rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPCEN);
rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPDEN);
rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_CRCEN);
rcc_periph_clock_enable(RCC_OTGFS);
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,
TMS_PIN | TCK_PIN | TDI_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; }
@ -82,23 +136,25 @@ bool platform_srst_get_val(void) { return false; }
const char *platform_target_voltage(void)
{
return "ABSENT!";
return NULL;
}
void platform_request_boot(void)
{
/* Disconnect USB cable */
usbd_disconnect(usbdev, 1);
nvic_disable_irq(USB_IRQ);
/* Assert blue LED as indicator we are in the bootloader */
rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPDEN);
gpio_mode_setup(LED_PORT, GPIO_MODE_OUTPUT,
GPIO_PUPD_NONE, LED_BOOTLOADER);
gpio_set(LED_PORT, LED_BOOTLOADER);
/* Jump to the built in bootloader by mapping System flash */
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_SYSCFGEN);
SYSCFG_MEMRM &= ~3;
SYSCFG_MEMRM |= 1;
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,15 +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 BOARD_IDENT_DFU "Black Magic (Upgrade) for F4Discovery, (Firmware " FIRMWARE_VERSION ")"
#define DFU_IDENT "Black Magic Firmware Upgrade (F4Discovery"
#define DFU_IFACE_STRING "@Internal Flash /0x08000000/1*016Ka,3*016Kg,1*064Kg,7*128Kg"
#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:
*
@ -44,7 +109,6 @@
* LED2 = PD12 (Red LED : Error)
* LED3 = PD15 (Blue LED : Bootloader active)
*
* TPWR = XXX (input) -- analogue on mini design ADC1, ch8
* nTRST = PC1
* SRST_OUT = PC8
* TDI = PC2
@ -53,10 +117,7 @@
* TDO = PC6 (input for TRACESWO
* nSRST =
*
* USB cable pull-up: PA8
* USB VBUS detect: PB13 -- New on mini design.
* Enable pull up for compatibility.
* Force DFU mode button: PB12
* Force DFU mode button: PA0
*/
/* Hardware definitions... */
@ -87,6 +148,30 @@
#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
#define TMS_SET_MODE() \
gpio_mode_setup(TMS_PORT, GPIO_MODE_OUTPUT, \
GPIO_PUPD_NONE, TMS_PIN);
@ -97,49 +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 DEBUG(...)
#define TRACE_ISR(x) tim3_isr(x)
#define gpio_set_val(port, pin, val) do { \
if(val) \
@ -157,11 +228,37 @@ static inline int platform_hwversion(void)
return 0;
}
/* Use newlib provided integer only stdio functions */
#define sscanf siscanf
#define sprintf siprintf
#define vasprintf vasiprintf
#define snprintf sniprintf
/*
* Use newlib provided integer only stdio functions
*/
/* sscanf */
#ifdef sscanf
#undef sscanf
#define sscanf siscanf
#else
#define sscanf siscanf
#endif
/* sprintf */
#ifdef sprintf
#undef sprintf
#define sprintf siprintf
#else
#define sprintf siprintf
#endif
/* vasprintf */
#ifdef vasprintf
#undef vasprintf
#define vasprintf vasiprintf
#else
#define vasprintf vasiprintf
#endif
/* snprintf */
#ifdef snprintf
#undef snprintf
#define snprintf sniprintf
#else
#define snprintf sniprintf
#endif
#endif

View File

@ -17,59 +17,57 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "general.h"
#include "usbdfu.h"
#include <string.h>
#include <libopencm3/cm3/systick.h>
#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/gpio.h>
#include <libopencm3/cm3/scb.h>
#include "usbdfu.h"
#include "general.h"
#include "platform.h"
uint32_t app_address = 0x08004000;
extern char _ebss[];
void dfu_detach(void)
{
/* USB device must detach, we just reset... */
scb_reset_system();
}
int main(void)
{
/* Check the force bootloader pin*/
rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPAEN);
if(!gpio_get(GPIOA, GPIO0))
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]);
dfu_protect_enable();
/* 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);
/* Set up clock*/
rcc_clock_setup_hse_3v3(&hse_8mhz_3v3[CLOCK_3V3_168MHZ]);
systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8);
systick_set_reload(2100000);
systick_interrupt_enable();
systick_counter_enable();
/* Handle LEDs */
rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPDEN);
gpio_clear(GPIOD, GPIO12 | GPIO13 | GPIO14 |GPIO15);
gpio_mode_setup(GPIOD, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE,
GPIO12 | GPIO13 | GPIO14 |GPIO15);
/* Set up USB*/
rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPAEN);
rcc_peripheral_enable_clock(&RCC_AHB2ENR, RCC_AHB2ENR_OTGFSEN);
/* Enable peripherals */
rcc_periph_clock_enable(RCC_OTGFS);
/* Set up USB Pins and alternate function*/
gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE,
GPIO10 | GPIO11 | GPIO12);
gpio_set_af(GPIOA, GPIO_AF10, GPIO10 | GPIO11 | GPIO12);
dfu_init(&stm32f107_usb_driver);
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 sys_tick_handler(void)
void dfu_event(void)
{
gpio_toggle(GPIOD, GPIO12); /* Green LED on/off */
}

View File

@ -0,0 +1,85 @@
CC ?= gcc
SYS = $(shell $(CC) -dumpmachine)
CFLAGS += -DENABLE_DEBUG -DPLATFORM_HAS_DEBUG
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
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
#https://github.com/dmlc/xgboost/issues/1945 indicates macosx as indicator
else ifneq (filter, macosx darwin, $(SYS))
SRC += serial_unix.c
LDFLAGS += -lhidapi
LDFLAGS += -framework CoreFoundation
CFLAGS += -Ihidapi/hidapi
HIDAPILIB = hidapi
endif
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 ($(HOSTED_BMP_ONLY), 1)
CFLAGS += -DCMSIS_DAP
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
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

@ -0,0 +1,177 @@
# PC-Hosted BMP
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,
it either presents a list of available probes or starts the BMP process
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 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.
More arguments allow to
### Print information on the connected target
```
blackmagic -t
```
### Directly flash a binary file at lowest flash address
```
blackmagic <file.bin>
```
or with the -S argument at some other address
```
blackmagic -S 0x08002000 <file.bin>
```
### Read flash to binary file
```
blackmagic -r <file>.bin
```
### Verify flash against binary file
```
blackmagic -V <file>.bin
```
### Show more options
```
blackmagic -h
```
### 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 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.
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
and then "taskkill /F ?PID (WINPID)".
## Supported debuggers
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!
| CMSIS-DAP | +++ | Speed varies with MCU implementing CMSIS-DAP
| FTDI MPSSE | ++ | Requires a device descrition
| JLINK | - | Usefull to add BMP support for MCUs with built-in JLINK
## Device matching
As other USB dongles already connected to the host PC may use FTDI chips,
cable descriptions must be provided to match with the dongle.
To match the dongle, at least USB VID/PID that must match.
If a description is given, the USB device must provide that string. If a
serial number string is given on the command line, that number must match
with serial number in the USB descriptor of the device.
## FTDI connection possibilities:
| Direct Connection |
| ----------------------|
| MPSSE_SK --> JTAG_TCK |
| MPSSE_DO --> JTAG_TDI |
| MPSSE_DI <-- JTAG_TDO |
| MPSSE_CS <-> JTAG_TMS |
\+ JTAG and bitbanging SWD is possible<br>
\- No level translation, no buffering, no isolation<br>
Example: [Flossjtag](https://randomprojects.org/wiki/Floss-JTAG).
| Resistor SWD |
|------------------------|
| MPSSE_SK ---> JTAG_TCK |
| MPSSE_DO -R-> JTAG_TMS |
| MPSSE_DI <--- JTAG_TMS |
BMP would allow direct MPSSE_DO ->JTAG_TMS connections as BMP tristates DO
when reading. Resistor defeats contentions anyways. R is typical choosen
in the range of 470R
\+ MPSSE SWD possible<br>
\- No Jtag, no level translation, no buffering, no isolation<br>
|Direct buffered Connection|
|--------------------------|
| MPSSE_SK -B-> JTAG_TCK |
| MPSSE_DO -B-> JTAG_TDI |
| MPSSE_DI <-B- JTAG_TDO |
| MPSSE_CS -B-> JTAG_TMS |
\+ Only Jtag, buffered, possible level translation and isolation<br>
\- No SWD<br>
Example: [Turtelizer]http://www.ethernut.de/en/hardware/turtelizer/index.html)
[schematics](http://www.ethernut.de/pdf/turtelizer20c-schematic.pdf)
The 'r' command line arguments allows to specify an external SWD
resistor connection added to some existing cable. Jtag is not possible
together with the 'r' argument.
### Many variants possible
As the FTDI has more pins, these pins may be used to control
enables of buffers and multiplexer selection in many variants.
### FTDI SWD speed
SWD read needs two USB round trip, one for the acknowledge and one
round-trip after the data phase, while JTAG only needs one round-trip.
For that, SWD read speed is about half the JTAG read speed.
### Reset, Target voltage readback etc
The additional pins may also control Reset functionality, provide
information if target voltage is applied. etc.
### Cable descriptions
Please help to verify the cable description and give feedback on the
cables already listed and propose other cable. A link to the schematics
is welcome.
## Feedback
### 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

@ -0,0 +1,404 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2011 Black Sphere Technologies Ltd.
* Written by Gareth McMullin <gareth@blacksphere.co.nz>
* Additions by Dave Marples <dave@marples.net>
* Modifications (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 "gdb_if.h"
#include "version.h"
#include "remote.h"
#include "target.h"
#include "bmp_remote.h"
#include "cl_utils.h"
#include "hex_utils.h"
#include <assert.h>
#include <sys/time.h>
#include <sys/time.h>
#include <errno.h>
#include "adiv5.h"
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 < 1) || (construct[0] == REMOTE_RESP_ERR)) {
DEBUG_WARN("Remote Start failed, error %s\n",
c ? (char *)&(construct[1]) : "unknown");
return -1;
}
DEBUG_PROBE("Remote is %s\n", &construct[1]);
return 0;
}
bool remote_target_get_power(void)
{
uint8_t construct[REMOTE_MAX_MSG_SIZE];
int s;
s=snprintf((char *)construct, REMOTE_MAX_MSG_SIZE, "%s",
REMOTE_PWR_GET_STR);
platform_buffer_write(construct, s);
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
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);
}
return (construct[1] == '1');
}
bool remote_target_set_power(bool power)
{
uint8_t construct[REMOTE_MAX_MSG_SIZE];
int s;
s = snprintf((char *)construct, REMOTE_MAX_MSG_SIZE,REMOTE_PWR_SET_STR,
power ? '1' : '0');
platform_buffer_write(construct, s);
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((s < 1) || (construct[0] == REMOTE_RESP_ERR)) {
DEBUG_WARN("platform_target_set_power failed, error %s\n",
s ? (char *)&(construct[1]) : "unknown");
return false;
}
return true;
}
void remote_srst_set_val(bool assert)
{
uint8_t construct[REMOTE_MAX_MSG_SIZE];
int s;
s = snprintf((char *)construct, REMOTE_MAX_MSG_SIZE, REMOTE_SRST_SET_STR,
assert ? '1' : '0');
platform_buffer_write(construct, s);
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
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);
}
}
bool remote_srst_get_val(void)
{
uint8_t construct[REMOTE_MAX_MSG_SIZE];
int s;
s = snprintf((char *)construct, REMOTE_MAX_MSG_SIZE,"%s",
REMOTE_SRST_GET_STR);
platform_buffer_write(construct, s);
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
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);
}
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];
int s;
s = snprintf((char *)construct, REMOTE_MAX_MSG_SIZE," %s",
REMOTE_VOLTAGE_STR);
platform_buffer_write(construct, s);
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((s < 1) || (construct[0] == REMOTE_RESP_ERR)) {
DEBUG_WARN("platform_target_voltage failed, error %s\n",
s ? (char *)&(construct[1]) : "unknown");
exit(- 1);
}
return (char *)&construct[1];
}
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,
dp->dp_jd_index, addr);
platform_buffer_write(construct, s);
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((s < 1) || (construct[0] == REMOTE_RESP_ERR)) {
DEBUG_WARN("%s error %d\n", __func__, s);
}
uint32_t dest[1];
unhexify(dest, (const char*)&construct[1], 4);
DEBUG_PROBE("dp_read addr %04x: %08" PRIx32 "\n", dest[0]);
return dest[0];
}
static uint32_t remote_adiv5_low_access(
ADIv5_DP_t *dp, uint8_t RnW, uint16_t addr, uint32_t value)
{
(void)dp;
uint8_t construct[REMOTE_MAX_MSG_SIZE];
int s = snprintf((char *)construct, REMOTE_MAX_MSG_SIZE,
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 < 1) || (construct[0] == REMOTE_RESP_ERR)) {
DEBUG_WARN("%s error %d\n", __func__, s);
}
uint32_t dest[1];
unhexify(dest, (const char*)&construct[1], 4);
return dest[0];
}
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->dp->dp_jd_index, ap->apsel, addr);
platform_buffer_write(construct, s);
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((s < 1) || (construct[0] == REMOTE_RESP_ERR)) {
DEBUG_WARN("%s error %d\n", __func__, s);
}
uint32_t dest[1];
unhexify(dest, (const char*)&construct[1], 4);
return dest[0];
}
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->dp->dp_jd_index, ap->apsel, addr, value);
platform_buffer_write(construct, s);
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((s < 1) || (construct[0] == REMOTE_RESP_ERR)) {
DEBUG_WARN("%s error %d\n", __func__, s);
}
return;
}
#if 0
static void remote_mem_read(
ADIv5_AP_t *ap, void *dest, uint32_t src, size_t len)
{
(void)ap;
if (len == 0)
return;
DEBUG_WIRE("memread @ %" PRIx32 " len %ld, start: \n",
src, len);
uint8_t construct[REMOTE_MAX_MSG_SIZE];
int s;
int batchsize = (REMOTE_MAX_MSG_SIZE - 32) / 2;
while(len) {
int count = len;
if (count > batchsize)
count = batchsize;
s = snprintf(construct, REMOTE_MAX_MSG_SIZE,
REMOTE_MEM_READ_STR, src, count);
platform_buffer_write(construct, s);
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((s > 0) && (construct[0] == REMOTE_RESP_OK)) {
unhexify(dest, (const char*)&construct[1], count);
src += count;
dest += count;
len -= count;
continue;
} else {
if(construct[0] == REMOTE_RESP_ERR) {
ap->dp->fault = 1;
DEBUG_WARN("%s returned REMOTE_RESP_ERR at addr: 0x%08x\n",
__func__, src);
break;
} else {
DEBUG_WARN("%s error %d\n", __func__, s);
break;
}
}
}
}
#endif
static void remote_ap_mem_read(
ADIv5_AP_t *ap, void *dest, uint32_t src, size_t len)
{
(void)ap;
if (len == 0)
return;
char construct[REMOTE_MAX_MSG_SIZE];
int batchsize = (REMOTE_MAX_MSG_SIZE - 0x20) / 2;
while(len) {
int s;
int count = len;
if (count > batchsize)
count = batchsize;
s = snprintf(construct, REMOTE_MAX_MSG_SIZE,
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)) {
unhexify(dest, (const char*)&construct[1], count);
src += count;
dest += count;
len -= count;
continue;
} else {
if(construct[0] == REMOTE_RESP_ERR) {
ap->dp->fault = 1;
DEBUG_WARN("%s returned REMOTE_RESP_ERR at apsel %d, "
"addr: 0x%08" PRIx32 "\n", __func__, ap->apsel, src);
break;
} else {
DEBUG_WARN("%s error %d around 0x%08" PRIx32 "\n",
__func__, s, src);
break;
}
}
}
}
static void remote_ap_mem_write_sized(
ADIv5_AP_t *ap, uint32_t dest, const void *src, size_t len,
enum align align)
{
(void)ap;
if (len == 0)
return;
char construct[REMOTE_MAX_MSG_SIZE];
/* (5 * 1 (char)) + (2 * 2 (bytes)) + (3 * 8 (words)) */
int batchsize = (REMOTE_MAX_MSG_SIZE - 0x30) / 2;
while (len) {
int count = len;
if (count > batchsize)
count = batchsize;
int s = snprintf(construct, REMOTE_MAX_MSG_SIZE,
REMOTE_AP_MEM_WRITE_SIZED_STR,
ap->dp->dp_jd_index, ap->apsel, ap->csw, align, dest, count);
char *p = construct + s;
hexify(p, src, count);
p += 2 * count;
src += count;
dest += count;
len -= count;
*p++ = REMOTE_EOM;
*p = 0;
platform_buffer_write((uint8_t*)construct, p - construct);
s = platform_buffer_read((uint8_t*)construct, REMOTE_MAX_MSG_SIZE);
if ((s > 0) && (construct[0] == REMOTE_RESP_OK))
continue;
if ((s > 0) && (construct[0] == REMOTE_RESP_ERR)) {
ap->dp->fault = 1;
DEBUG_WARN("%s returned REMOTE_RESP_ERR at apsel %d, "
"addr: 0x%08x\n", __func__, ap->apsel, dest);
} else {
DEBUG_WARN("%s error %d around address 0x%08" PRIx32 "\n",
__func__, s, dest);
break;
}
}
}
void remote_adiv5_dp_defaults(ADIv5_DP_t *dp)
{
uint8_t construct[REMOTE_MAX_MSG_SIZE];
int s = snprintf((char *)construct, REMOTE_MAX_MSG_SIZE, "%s",
REMOTE_HL_CHECK_STR);
platform_buffer_write(construct, s);
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
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;
}
dp->low_access = remote_adiv5_low_access;
dp->dp_read = remote_adiv5_dp_read;
dp->ap_write = remote_adiv5_ap_write;
dp->ap_read = remote_adiv5_ap_read;
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

@ -0,0 +1,45 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2020 Uwe Bonnes
*
* 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/>.
*/
#if !defined(__BMP_REMOTE_H_)
#define __BMP_REMOTE_H_
#include "jtagtap.h"
#include "adiv5.h"
#include "target.h"
#include "target_internal.h"
#define REMOTE_MAX_MSG_SIZE (1024)
int platform_buffer_write(const uint8_t *data, int size);
int platform_buffer_read(uint8_t *data, int size);
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);
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

@ -0,0 +1,470 @@
/*
* This file is part of the Black Magic Debug project.
*
* 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
* 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/>.
*/
/* Modified from edbg.c
* Links between bmp and edbg
*
* https://arm-software.github.io/CMSIS_5/DAP/html/index.html
*/
#include "general.h"
#include "gdb_if.h"
#include "adiv5.h"
#include <assert.h>
#include <unistd.h>
#include <signal.h>
#include <ctype.h>
#include <sys/time.h>
#include <hidapi.h>
#include <wchar.h>
#include "bmp_hosted.h"
#include "dap.h"
#include "cmsis_dap.h"
#include "cl_utils.h"
#include "target.h"
#include "target_internal.h"
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 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)
{
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;
}
dap_disconnect();
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 (dap_caps & 8)
DEBUG_INFO(", SWO_MANCHESTER");
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.*/
dap_write_reg(dp, ADIV5_DP_ABORT, 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 |
ADIV5_DP_CTRLSTAT_STICKYERR | ADIV5_DP_CTRLSTAT_WDATAERR);
uint32_t clr = 0;
if(err & ADIV5_DP_CTRLSTAT_STICKYORUN)
clr |= ADIV5_DP_ABORT_ORUNERRCLR;
if(err & ADIV5_DP_CTRLSTAT_STICKYCMP)
clr |= ADIV5_DP_ABORT_STKCMPCLR;
if(err & ADIV5_DP_CTRLSTAT_STICKYERR)
clr |= ADIV5_DP_ABORT_STKERRCLR;
if(err & ADIV5_DP_CTRLSTAT_WDATAERR)
clr |= ADIV5_DP_ABORT_WDERRCLR;
dap_write_reg(dp, ADIV5_DP_ABORT, clr);
dp->fault = 0;
return err;
}
static uint32_t dap_dp_low_access(struct ADIv5_DP_s *dp, uint8_t RnW,
uint16_t addr, uint32_t value)
{
bool APnDP = addr & ADIV5_APnDP;
uint32_t res = 0;
uint8_t reg = (addr & 0xc) | ((APnDP)? 1 : 0);
if (RnW) {
res = dap_read_reg(dp, reg);
}
else {
dap_write_reg(dp, reg, value);
}
return res;
}
static uint32_t dap_dp_read_reg(ADIv5_DP_t *dp, uint16_t addr)
{
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 (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);
}
}
}
int dbg_get_report_size(void)
{
return report_size;
}
int dbg_dap_cmd(uint8_t *data, int size, int rsize)
{
char cmd = data[0];
int res = -1;
memset(buffer, 0xff, report_size + 1);
buffer[0] = 0x00; // Report ID??
memcpy(&buffer[1], data, rsize);
DEBUG_WIRE("cmd : ");
for(int i = 0; (i < 32) && (i < rsize + 1); i++)
DEBUG_WIRE("%02x.", buffer[i]);
DEBUG_WIRE("\n");
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);
}
} 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 : \
(((x) & 1) == 0 ? ALIGN_HALFWORD : ALIGN_BYTE))
static void dap_mem_read(ADIv5_AP_t *ap, void *dest, uint32_t src, size_t len)
{
if (len == 0)
return;
enum align align = MIN(ALIGNOF(src), ALIGNOF(len));
DEBUG_WIRE("memread @ %" PRIx32 " len %ld, align %d , start: \n",
src, len, align);
if (((unsigned)(1 << align)) == 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() - 6) >> (2 - align)) & ~3;
while (len) {
dap_ap_mem_access_setup(ap, src, align);
/* Calculate length until next access setup is needed */
unsigned int blocksize = (src | 0x3ff) - src + 1;
if (blocksize > len)
blocksize = len;
while (blocksize) {
unsigned int transfersize = blocksize;
if (transfersize > max_size)
transfersize = max_size;
unsigned int res = dap_read_block(ap, dest, src, transfersize,
align);
if (res) {
DEBUG_WIRE("mem_read failed %02x\n", res);
ap->dp->fault = 1;
return;
}
blocksize -= transfersize;
len -= transfersize;
dest += transfersize;
src += transfersize;
}
}
DEBUG_WIRE("memread res last data %08" PRIx32 "\n", ((uint32_t*)dest)[-1]);
}
static void dap_mem_write_sized(
ADIv5_AP_t *ap, uint32_t dest, const void *src,
size_t len, enum align align)
{
if (len == 0)
return;
DEBUG_WIRE("memwrite @ %" PRIx32 " len %ld, align %d , %08x start: \n",
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() - 6) >> (2 - align) & ~3);
while (len) {
dap_ap_mem_access_setup(ap, dest, align);
unsigned int blocksize = (dest | 0x3ff) - dest + 1;
if (blocksize > len)
blocksize = len;
while (blocksize) {
unsigned int transfersize = blocksize;
if (transfersize > max_size)
transfersize = max_size;
unsigned int res = dap_write_block(ap, dest, src, transfersize,
align);
if (res) {
DEBUG_WARN("mem_write failed %02x\n", res);
ap->dp->fault = 1;
return;
}
blocksize -= transfersize;
len -= transfersize;
dest += transfersize;
src += transfersize;
}
}
DEBUG_WIRE("memwrite done\n");
}
void dap_adiv5_dp_defaults(ADIv5_DP_t *dp)
{
if ((mode == DAP_CAP_JTAG) && dap_jtag_configure())
return;
dp->ap_read = dap_ap_read;
dp->ap_write = dap_ap_write;
dp->mem_read = dap_mem_read;
dp->mem_write_sized = dap_mem_write_sized;
}
static void cmsis_dap_jtagtap_reset(void)
{
jtagtap_soft_reset();
/* Is there a way to know if TRST is available?*/
}
static void cmsis_dap_jtagtap_tms_seq(uint32_t MS, int ticks)
{
uint8_t TMS[4] = {MS & 0xff, (MS >> 8) & 0xff, (MS >> 16) & 0xff,
(MS >> 24) & 0xff};
dap_jtagtap_tdi_tdo_seq(NULL, false, TMS, NULL, ticks);
DEBUG_PROBE("tms_seq DI %08x %d\n", MS, ticks);
}
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)? DO[0] : 0);
}
static void cmsis_dap_jtagtap_tdi_seq(const uint8_t final_tms,
const uint8_t *DI, int ticks)
{
dap_jtagtap_tdi_tdo_seq(NULL, (final_tms), NULL, DI, ticks);
DEBUG_PROBE("jtagtap_tdi_seq %d, %02x\n", ticks, DI[0]);
}
static uint8_t cmsis_dap_jtagtap_next(uint8_t dTMS, uint8_t dTDI)
{
uint8_t tdo[1];
dap_jtagtap_tdi_tdo_seq(tdo, false, &dTMS, &dTDI, 1);
DEBUG_PROBE("next tms %02x tdi %02x tdo %02x\n", dTMS, dTDI, tdo[0]);
return (tdo[0] & 1);
}
int cmsis_dap_jtagtap_init(jtag_proc_t *jtag_proc)
{
DEBUG_PROBE("jtap_init\n");
if (!(dap_caps & DAP_CAP_JTAG))
return -1;
mode = DAP_CAP_JTAG;
dap_disconnect();
dap_connect(true);
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;
return 0;
}
int dap_jtag_dp_init(ADIv5_DP_t *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;
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

@ -0,0 +1,56 @@
/*
* This file is part of the Black Magic Debug project.
*
* 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
* 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/>.
*/
#if !defined(__CMSIS_DAP_H_)
#define __CMSIS_DAP_H_
#include "adiv5.h"
#include "cl_utils.h"
#if defined(CMSIS_DAP)
int dap_init(bmp_info_t *info);
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)
{
DEBUG_WARN("FATAL: Missing hidapi-libusb\n");
(void)info;
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
#endif

849
src/platforms/hosted/dap.c Normal file
View File

@ -0,0 +1,849 @@
/*
* Copyright (c) 2013-2015, Alex Taradov <alex@taradov.com>
* 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.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT HOLDER 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.
*/
/* Modified for Blackmagic Probe
* Copyright (c) 2020-21 Uwe Bonnes bon@elektron.ikp.physik.tu-darmstadt.de
*/
/*- Includes ----------------------------------------------------------------*/
#include <general.h>
#include "exception.h"
#include "dap.h"
#include "jtag_scan.h"
/*- Definitions -------------------------------------------------------------*/
enum
{
ID_DAP_INFO = 0x00,
ID_DAP_LED = 0x01,
ID_DAP_CONNECT = 0x02,
ID_DAP_DISCONNECT = 0x03,
ID_DAP_TRANSFER_CONFIGURE = 0x04,
ID_DAP_TRANSFER = 0x05,
ID_DAP_TRANSFER_BLOCK = 0x06,
ID_DAP_TRANSFER_ABORT = 0x07,
ID_DAP_WRITE_ABORT = 0x08,
ID_DAP_DELAY = 0x09,
ID_DAP_RESET_TARGET = 0x0a,
ID_DAP_SWJ_PINS = 0x10,
ID_DAP_SWJ_CLOCK = 0x11,
ID_DAP_SWJ_SEQUENCE = 0x12,
ID_DAP_SWD_CONFIGURE = 0x13,
ID_DAP_JTAG_SEQUENCE = 0x14,
ID_DAP_JTAG_CONFIGURE = 0x15,
ID_DAP_JTAG_IDCODE = 0x16,
ID_DAP_SWD_SEQUENCE = 0x1D,
};
enum
{
DAP_TRANSFER_APnDP = 1 << 0,
DAP_TRANSFER_RnW = 1 << 1,
DAP_TRANSFER_A2 = 1 << 2,
DAP_TRANSFER_A3 = 1 << 3,
DAP_TRANSFER_MATCH_VALUE = 1 << 4,
DAP_TRANSFER_MATCH_MASK = 1 << 5,
};
enum
{
DAP_TRANSFER_INVALID = 0,
DAP_TRANSFER_OK = 1 << 0,
DAP_TRANSFER_WAIT = 1 << 1,
DAP_TRANSFER_FAULT = 1 << 2,
DAP_TRANSFER_ERROR = 1 << 3,
DAP_TRANSFER_MISMATCH = 1 << 4,
DAP_TRANSFER_NO_TARGET = 7,
};
enum
{
DAP_SWJ_SWCLK_TCK = 1 << 0,
DAP_SWJ_SWDIO_TMS = 1 << 1,
DAP_SWJ_TDI = 1 << 2,
DAP_SWJ_TDO = 1 << 3,
DAP_SWJ_nTRST = 1 << 5,
DAP_SWJ_nRESET = 1 << 7,
};
enum
{
DAP_OK = 0x00,
DAP_ERROR = 0xff,
};
enum
{
DAP_JTAG_TMS = 1 << 6,
DAP_JTAG_TDO_CAPTURE = 1 << 7,
};
enum
{
SWD_DP_R_IDCODE = 0x00,
SWD_DP_W_ABORT = 0x00,
SWD_DP_R_CTRL_STAT = 0x04,
SWD_DP_W_CTRL_STAT = 0x04, // When CTRLSEL == 0
SWD_DP_W_WCR = 0x04, // When CTRLSEL == 1
SWD_DP_R_RESEND = 0x08,
SWD_DP_W_SELECT = 0x08,
SWD_DP_R_RDBUFF = 0x0c,
};
enum
{
SWD_AP_CSW = 0x00 | DAP_TRANSFER_APnDP,
SWD_AP_TAR = 0x04 | DAP_TRANSFER_APnDP,
SWD_AP_DRW = 0x0c | DAP_TRANSFER_APnDP,
SWD_AP_DB0 = 0x00 | DAP_TRANSFER_APnDP, // 0x10
SWD_AP_DB1 = 0x04 | DAP_TRANSFER_APnDP, // 0x14
SWD_AP_DB2 = 0x08 | DAP_TRANSFER_APnDP, // 0x18
SWD_AP_DB3 = 0x0c | DAP_TRANSFER_APnDP, // 0x1c
SWD_AP_CFG = 0x04 | DAP_TRANSFER_APnDP, // 0xf4
SWD_AP_BASE = 0x08 | DAP_TRANSFER_APnDP, // 0xf8
SWD_AP_IDR = 0x0c | DAP_TRANSFER_APnDP, // 0xfc
};
#define DP_ABORT_DAPABORT (1 << 0)
#define DP_ABORT_STKCMPCLR (1 << 1)
#define DP_ABORT_STKERRCLR (1 << 2)
#define DP_ABORT_WDERRCLR (1 << 3)
#define DP_ABORT_ORUNERRCLR (1 << 4)
#define DP_CST_ORUNDETECT (1 << 0)
#define DP_CST_STICKYORUN (1 << 1)
#define DP_CST_TRNMODE_NORMAL (0 << 2)
#define DP_CST_TRNMODE_VERIFY (1 << 2)
#define DP_CST_TRNMODE_COMPARE (2 << 2)
#define DP_CST_STICKYCMP (1 << 4)
#define DP_CST_STICKYERR (1 << 5)
#define DP_CST_READOK (1 << 6)
#define DP_CST_WDATAERR (1 << 7)
#define DP_CST_MASKLANE(x) ((x) << 8)
#define DP_CST_TRNCNT(x) ((x) << 12)
#define DP_CST_CDBGRSTREQ (1 << 26)
#define DP_CST_CDBGRSTACK (1 << 27)
#define DP_CST_CDBGPWRUPREQ (1 << 28)
#define DP_CST_CDBGPWRUPACK (1 << 29)
#define DP_CST_CSYSPWRUPREQ (1 << 30)
#define DP_CST_CSYSPWRUPACK (1 << 31)
#define DP_SELECT_CTRLSEL (1 << 0)
#define DP_SELECT_APBANKSEL(x) ((x) << 4)
#define DP_SELECT_APSEL(x) ((x) << 24)
#define AP_CSW_SIZE_BYTE (0 << 0)
#define AP_CSW_SIZE_HALF (1 << 0)
#define AP_CSW_SIZE_WORD (2 << 0)
#define AP_CSW_ADDRINC_OFF (0 << 4)
#define AP_CSW_ADDRINC_SINGLE (1 << 4)
#define AP_CSW_ADDRINC_PACKED (2 << 4)
#define AP_CSW_DEVICEEN (1 << 6)
#define AP_CSW_TRINPROG (1 << 7)
#define AP_CSW_SPIDEN (1 << 23)
#define AP_CSW_PROT(x) ((x) << 24)
#define AP_CSW_DBGSWENABLE (1 << 31)
/*- Implementations ---------------------------------------------------------*/
//-----------------------------------------------------------------------------
void dap_led(int index, int state)
{
uint8_t buf[3];
buf[0] = ID_DAP_LED;
buf[1] = index;
buf[2] = state;
dbg_dap_cmd(buf, sizeof(buf), 3);
}
//-----------------------------------------------------------------------------
void dap_connect(bool jtag)
{
uint8_t buf[2];
buf[0] = ID_DAP_CONNECT;
buf[1] = (jtag) ? DAP_CAP_JTAG : DAP_CAP_SWD;
dbg_dap_cmd(buf, sizeof(buf), 2);
}
//-----------------------------------------------------------------------------
void dap_disconnect(void)
{
uint8_t buf[65];
buf[0] = ID_DAP_DISCONNECT;
dbg_dap_cmd(buf, sizeof(buf), 1);
}
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;
}
//-----------------------------------------------------------------------------
void dap_transfer_configure(uint8_t idle, uint16_t count, uint16_t retry)
{
uint8_t buf[6];
buf[0] = ID_DAP_TRANSFER_CONFIGURE;
buf[1] = idle;
buf[2] = count & 0xff;
buf[3] = (count >> 8) & 0xff;
buf[4] = retry & 0xff;
buf[5] = (retry >> 8) & 0xff;
dbg_dap_cmd(buf, sizeof(buf), 6);
}
//-----------------------------------------------------------------------------
void dap_swd_configure(uint8_t cfg)
{
uint8_t buf[2];
buf[0] = ID_DAP_SWD_CONFIGURE;
buf[1] = cfg;
dbg_dap_cmd(buf, sizeof(buf), 2);
}
//-----------------------------------------------------------------------------
int dap_info(int info, uint8_t *data, int size)
{
uint8_t buf[256];
int rsize;
buf[0] = ID_DAP_INFO;
buf[1] = info;
dbg_dap_cmd(buf, sizeof(buf), 2);
rsize = (size < buf[0]) ? size : buf[0];
memcpy(data, &buf[1], rsize);
if (rsize < size)
data[rsize] = 0;
return rsize;
}
void dap_reset_pin(int state)
{
uint8_t buf[7];
buf[0] = ID_DAP_SWJ_PINS;
buf[1] = state ? DAP_SWJ_nRESET : 0; // Value
buf[2] = DAP_SWJ_nRESET; // Select
buf[3] = 0; // Wait
buf[4] = 0; // Wait
buf[5] = 0; // Wait
buf[6] = 0; // Wait
dbg_dap_cmd(buf, sizeof(buf), 7);
}
void dap_trst_reset(void)
{
uint8_t buf[7];
buf[0] = ID_DAP_SWJ_PINS;
buf[1] = DAP_SWJ_nTRST;
buf[2] = 0;
buf[3] = 0;
buf[4] = 4; /* ~ 1 ms*/
buf[5] = 0;
buf[6] = 0;
dbg_dap_cmd(buf, sizeof(buf), 7);
buf[0] = ID_DAP_SWJ_PINS;
buf[1] = DAP_SWJ_nTRST;
buf[2] = DAP_SWJ_nTRST;
dbg_dap_cmd(buf, sizeof(buf), 7);
}
static void dap_line_reset(void)
{
uint8_t buf[] = {
ID_DAP_SWJ_SEQUENCE,
64,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0
};
dbg_dap_cmd(buf, sizeof(buf), 10);
if (buf[0])
DEBUG_WARN("line reset failed\n");
}
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] == SWDP_ACK_FAULT) {
*dp_fault = 1;
return 0;
}
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];
return res;
}
//-----------------------------------------------------------------------------
uint32_t dap_read_reg(ADIv5_DP_t *dp, uint8_t reg)
{
uint8_t buf[8];
uint8_t dap_index = 0;
dap_index = dp->dp_jd_index;
buf[0] = ID_DAP_TRANSFER;
buf[1] = dap_index;
buf[2] = 0x01; // Request size
buf[3] = reg | DAP_TRANSFER_RnW;
uint32_t res = wait_word(buf, 8, 4, &dp->fault);
DEBUG_WIRE("\tdap_read_reg %02x %08x\n", reg, res);
return res;
}
//-----------------------------------------------------------------------------
void dap_write_reg(ADIv5_DP_t *dp, uint8_t reg, uint32_t data)
{
uint8_t buf[8];
DEBUG_PROBE("\tdap_write_reg %02x %08x\n", reg, data);
buf[0] = ID_DAP_TRANSFER;
uint8_t dap_index = 0;
dap_index = dp->dp_jd_index;
buf[1] = dap_index;
buf[2] = 0x01; // Request size
buf[3] = reg & ~DAP_TRANSFER_RnW;;
buf[4] = data & 0xff;
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;
} while (buf[1] == DAP_TRANSFER_WAIT);
if (buf[1] > DAP_TRANSFER_WAIT) {
DEBUG_WARN("dap_write_reg %02x data %08x:fault\n", reg, data);
dp->fault = 1;
}
if (buf[1] == DAP_TRANSFER_ERROR) {
DEBUG_WARN("dap_write_reg %02x data %08x: protocoll error\n",
reg, data);
dap_line_reset();
}
}
unsigned int dap_read_block(ADIv5_AP_t *ap, void *dest, uint32_t src,
size_t len, enum align align)
{
uint8_t buf[1024];
unsigned int sz = len >> align;
uint8_t dap_index = 0;
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);
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);
dap_line_reset();
}
if (sz != transferred) {
return 1;
} else if (align > ALIGN_HALFWORD) {
memcpy(dest, &buf[3], len);
} else {
uint32_t *p = (uint32_t *)&buf[3];
while(sz) {
dest = extract(dest, src, *p, align);
p++;
src += (1 << align);
sz--;
}
}
return (buf[2] > DAP_TRANSFER_WAIT) ? 1 : 0;
}
unsigned int dap_write_block(ADIv5_AP_t *ap, uint32_t dest, const void *src,
size_t len, enum align align)
{
uint8_t buf[1024];
unsigned int sz = len >> align;
uint8_t dap_index = 0;
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;
if (align > ALIGN_HALFWORD) {
memcpy(&buf[5], src, len);
} else {
unsigned int size = len;
uint32_t *p = (uint32_t *)&buf[5];
while (size) {
uint32_t tmp = 0;
/* Pack data into correct data lane */
if (align == ALIGN_BYTE) {
tmp = ((uint32_t)*(uint8_t *)src) << ((dest & 3) << 3);
} else {
tmp = ((uint32_t)*(uint16_t *)src) << ((dest & 2) << 3);
}
src = src + (1 << align);
dest += (1 << align);
size--;
*p++ = tmp;
}
}
dbg_dap_cmd(buf, 1023, 5 + (sz << 2));
if (buf[2] > DAP_TRANSFER_FAULT) {
dap_line_reset();
}
return (buf[2] > DAP_TRANSFER_WAIT) ? 1 : 0;
}
//-----------------------------------------------------------------------------
void dap_reset_link(bool jtag)
{
uint8_t buf[128], *p = buf;
//-------------
*p++ = ID_DAP_SWJ_SEQUENCE;
p++;
*p++ = 0xff;
*p++ = 0xff;
*p++ = 0xff;
*p++ = 0xff;
*p++ = 0xff;
*p++ = 0xff;
*p++ = 0xff;
if (jtag) {
*p++ = 0x3c;
*p++ = 0xe7;
*p++ = 0x1f;
buf[1] = ((p - &buf[2]) * 8) - 2;
} else {
*p++ = 0x9e;
*p++ = 0xe7;
*p++ = 0xff;
*p++ = 0xff;
*p++ = 0xff;
*p++ = 0xff;
*p++ = 0xff;
*p++ = 0xff;
*p++ = 0xff;
*p++ = 0x00;
buf[1] = (p - &buf[2]) * 8;
}
dbg_dap_cmd(buf, sizeof(buf), p - buf);
if (!jtag) {
//-------------
buf[0] = ID_DAP_TRANSFER;
buf[1] = 0; // DAP index
buf[2] = 1; // Request size
buf[3] = SWD_DP_R_IDCODE | DAP_TRANSFER_RnW;
dbg_dap_cmd(buf, sizeof(buf), 4);
}
}
//-----------------------------------------------------------------------------
uint32_t dap_read_idcode(ADIv5_DP_t *dp)
{
return dap_read_reg(dp, SWD_DP_R_IDCODE);
}
static uint8_t *mem_access_setup(ADIv5_AP_t *ap, uint8_t *p,
uint32_t addr, enum align align)
{
uint32_t csw = ap->csw | ADIV5_AP_CSW_ADDRINC_SINGLE;
switch (align) {
case ALIGN_BYTE:
csw |= ADIV5_AP_CSW_SIZE_BYTE;
break;
case ALIGN_HALFWORD:
csw |= ADIV5_AP_CSW_SIZE_HALFWORD;
break;
case ALIGN_DWORD:
case ALIGN_WORD:
csw |= ADIV5_AP_CSW_SIZE_WORD;
break;
}
uint8_t dap_index = 0;
dap_index = ap->dp->dp_jd_index;
*p++ = ID_DAP_TRANSFER;
*p++ = dap_index;
*p++ = 3; /* Nr transfers */
*p++ = SWD_DP_W_SELECT;
*p++ = ADIV5_AP_CSW & 0xF0;
*p++ = 0;
*p++ = 0;
*p++ = ap->apsel & 0xff;
*p++ = SWD_AP_CSW;
*p++ = (csw >> 0) & 0xff;
*p++ = (csw >> 8) & 0xff;
*p++ = (csw >> 16) & 0xff;
*p++ = (csw >> 24) & 0xff;
*p++ = SWD_AP_TAR ;
*p++ = (addr >> 0) & 0xff;
*p++ = (addr >> 8) & 0xff;
*p++ = (addr >> 16) & 0xff;
*p++ = (addr >> 24) & 0xff;
return p;
}
void dap_ap_mem_access_setup(ADIv5_AP_t *ap, uint32_t addr, enum align align)
{
uint8_t buf[63];
uint8_t *p = mem_access_setup(ap, buf, addr, align);
dbg_dap_cmd(buf, sizeof(buf), p - buf);
}
uint32_t dap_ap_read(ADIv5_AP_t *ap, uint16_t addr)
{
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;
dap_index = ap->dp->dp_jd_index;
*p++ = ID_DAP_TRANSFER;
*p++ = dap_index;
*p++ = 2; /* Nr transfers */
*p++ = SWD_DP_W_SELECT;
*p++ = (addr & 0xF0);
*p++ = 0;
*p++ = 0;
*p++ = ap->apsel & 0xff;
*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;
}
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;
dap_index = ap->dp->dp_jd_index;
*p++ = ID_DAP_TRANSFER;
*p++ = dap_index;
*p++ = 2; /* Nr transfers */
*p++ = SWD_DP_W_SELECT;
*p++ = (addr & 0xF0);
*p++ = 0;
*p++ = 0;
*p++ = ap->apsel & 0xff;
*p++ = (addr & 0x0c) | ((addr & 0x100) ? DAP_TRANSFER_APnDP : 0);
*p++ = (value >> 0) & 0xff;
*p++ = (value >> 8) & 0xff;
*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)
{
uint8_t buf[63];
uint8_t *p = mem_access_setup(ap, buf, src, align);
*p++ = SWD_AP_DRW | DAP_TRANSFER_RnW;
*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);
}
void dap_write_single(ADIv5_AP_t *ap, uint32_t dest, const void *src,
enum align align)
{
uint8_t buf[63];
uint8_t *p = mem_access_setup(ap, buf, dest, align);
*p++ = SWD_AP_DRW;
uint32_t tmp = 0;
/* Pack data into correct data lane */
switch (align) {
case ALIGN_BYTE:
tmp = ((uint32_t)*(uint8_t *)src) << ((dest & 3) << 3);
break;
case ALIGN_HALFWORD:
tmp = ((uint32_t)*(uint16_t *)src) << ((dest & 2) << 3);
break;
case ALIGN_DWORD:
case ALIGN_WORD:
tmp = *(uint32_t *)src;
break;
}
*p++ = (tmp >> 0) & 0xff;
*p++ = (tmp >> 8) & 0xff;
*p++ = (tmp >> 16) & 0xff;
*p++ = (tmp >> 24) & 0xff;
buf[2] = 4;
dbg_dap_cmd(buf, sizeof(buf), p - buf);
}
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 = last_byte = (ticks - 1) >> 3;
int last_bit = (ticks - 1) & 7;
if (final_tms)
ticks --;
while (ticks) {
int transfers = ticks;
if (transfers > 64)
transfers = 64;
uint8_t *p = buf;
*p++ = ID_DAP_JTAG_SEQUENCE;
*p++ = 1;
*p++ = ((transfers == 64) ? 0 : transfers) |
((DO) ? DAP_JTAG_TDO_CAPTURE : 0);
int n_di_bytes = (transfers + 7) >> 3;
if (din) {
p = memcpy(p, din, n_di_bytes);
din += n_di_bytes;
} else {
p = memset(p, 0xff, n_di_bytes);
}
p += n_di_bytes;
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 (dout) {
memcpy(dout, &buf[1], (transfers + 7) >> 3);
dout += (transfers + 7) >> 3;
}
ticks -= transfers;
}
if (final_tms) {
uint8_t *p = buf;
*p++ = ID_DAP_JTAG_SEQUENCE;
*p++ = 1;
*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;
}
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 (dout) {
if (buf[1] & 1)
DO[last_byte] |= (1 << last_bit);
else
DO[last_byte] &= ~(1 << last_bit);
}
}
} else {
while(ticks) {
uint8_t *p = buf;
int transfers = ticks;
if (transfers > 64)
transfers = 64;
p = buf;
*p++ = ID_DAP_JTAG_SEQUENCE;
*p++ = transfers;
for (int i = 0; i < transfers; i++) {
*p++ = 1 | ((DO) ? DAP_JTAG_TDO_CAPTURE : 0) |
((TMS[i >> 3] & (1 << (i & 7))) ? DAP_JTAG_TMS : 0);
if (DI)
*p++ = (DI[i >> 3] & (1 << (i & 7))) ? 1 : 0;
else
*p++ = 1;
}
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) {
for (int i = 0; i < transfers; i++) {
if (buf[i + 1])
DO[i >> 3] |= (1 << (i & 7));
else
DO[i >> 3] &= ~(1 << (i & 7));
}
}
ticks -= transfers;
}
}
}
int dap_jtag_configure(void)
{
uint8_t buf[64], *p = &buf[2];
int i = 0;
for (; i < jtag_dev_count; i++) {
struct jtag_dev_s *jtag_dev = &jtag_devs[i];
*p++ = jtag_dev->ir_len;
DEBUG_PROBE("irlen %d\n", jtag_dev->ir_len);
}
if ((!i || i >= JTAG_MAX_DEVS))
return -1;
buf[0] = 0x15;
buf[1] = i;
dbg_dap_cmd(buf, sizeof(buf), p - buf);
if (buf[0] != DAP_OK)
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

@ -0,0 +1,97 @@
/*
* Copyright (c) 2013-2015, Alex Taradov <alex@taradov.com>
* 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.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT HOLDER 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.
*/
#ifndef _DAP_H_
#define _DAP_H_
/*- Includes ----------------------------------------------------------------*/
#include <stdint.h>
#include <stdbool.h>
#include "adiv5.h"
/*- Definitions -------------------------------------------------------------*/
enum
{
DAP_INFO_VENDOR = 0x01,
DAP_INFO_PRODUCT = 0x02,
DAP_INFO_SER_NUM = 0x03,
DAP_INFO_FW_VER = 0x04,
DAP_INFO_DEVICE_VENDOR = 0x05,
DAP_INFO_DEVICE_NAME = 0x06,
DAP_INFO_CAPABILITIES = 0xf0,
DAP_INFO_TDT = 0xf1,
DAP_INFO_SWO_BUF_SIZE = 0xfd,
DAP_INFO_PACKET_COUNT = 0xfe,
DAP_INFO_PACKET_SIZE = 0xff,
};
enum
{
DAP_CAP_SWD = (1 << 0),
DAP_CAP_JTAG = (1 << 1),
DAP_CAP_SWO_UART = (1 << 2),
DAP_CAP_SWO_MANCHESTER = (1 << 3),
DAP_CAP_ATOMIC_CMD = (1 << 4),
DAP_CAP_TDT = (1 << 5),
DAP_CAP_SWO_STREAMING = (1 << 6),
};
/*- Prototypes --------------------------------------------------------------*/
void dap_led(int index, int state);
void dap_connect(bool jtag);
void dap_disconnect(void);
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);
uint32_t dap_read_reg(ADIv5_DP_t *dp, uint8_t reg);
void dap_write_reg(ADIv5_DP_t *dp, uint8_t reg, uint32_t data);
void dap_reset_link(bool jtag);
uint32_t dap_read_idcode(ADIv5_DP_t *dp);
unsigned int dap_read_block(ADIv5_AP_t *ap, void *dest, uint32_t src,
size_t len, enum align align);
unsigned int dap_write_block(ADIv5_AP_t *ap, uint32_t dest, const void *src,
size_t len, enum align align);
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);
void dap_ap_write(ADIv5_AP_t *ap, uint16_t addr, uint32_t value);
void dap_read_single(ADIv5_AP_t *ap, void *dest, uint32_t src, enum align align);
void dap_write_single(ADIv5_AP_t *ap, uint32_t dest, const void *src,
enum align align);
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

@ -0,0 +1,661 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2011 Black Sphere Technologies Ltd.
* Copyright (C) 2018 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
* 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 "gdb_if.h"
#include "target.h"
#include <assert.h>
#include <unistd.h>
#include <sys/time.h>
#include "ftdi_bmp.h"
#include <ftdi.h>
struct ftdi_context *ftdic;
#define BUF_SIZE 4096
static uint8_t outbuf[BUF_SIZE];
static uint16_t bufptr = 0;
cable_desc_t *active_cable;
data_desc_t active_state;
cable_desc_t cable_desc[] = {
{
/* Direct connection from FTDI to Jtag/Swd.
Pin 6 direct connected to RST.*/
.vendor = 0x0403,
.product = 0x6014,
.interface = INTERFACE_A,
// No explicit reset
.bb_swdio_in_port_cmd = GET_BITS_LOW,
.bb_swdio_in_pin = MPSSE_CS,
.description = "UM232H",
.name = "um232h"
},
{
/* Direct connection from FTDI to Jtag/Swd.
Pin 6 direct connected to RST.*/
.vendor = 0x0403,
.product = 0x6010,
.interface = INTERFACE_A,
.init.data_low = PIN6, /* PULL nRST high*/
.bb_swdio_in_port_cmd = GET_BITS_LOW,
.bb_swdio_in_pin = MPSSE_CS,
.assert_srst.data_low = ~PIN6,
.assert_srst.ddr_low = PIN6,
.deassert_srst.data_low = PIN6,
.deassert_srst.ddr_low = ~PIN6,
.description = "FLOSS-JTAG",
.name = "flossjtag"
},
{
/* MPSSE_SK (DB0) ----------- SWDCK/JTCK
* MPSSE-DO (DB1) -- 470 R -- SWDIO/JTMS
* MPSSE-DI (DB2) ----------- SWDIO/JTMS
* DO is tristated with SWD read, so
* resistor is not necessary, but protects
* from contentions in case of errors.
* JTAG not possible
* PIN6 (DB6) ----------- NRST */
.vendor = 0x0403,
.product = 0x6010,/*FT2232H*/
.interface = INTERFACE_B,
.init.data_low = PIN4, /* Pull up pin 4 */
.init.ddr_low = PIN4, /* Pull up pin 4 */
.mpsse_swd_read.set_data_low = MPSSE_DO,
.mpsse_swd_write.set_data_low = MPSSE_DO,
.assert_srst.data_low = ~PIN6,
.assert_srst.ddr_low = PIN6,
.deassert_srst.data_low = PIN6,
.deassert_srst.ddr_low = ~PIN6,
.target_voltage_cmd = GET_BITS_LOW,
.target_voltage_pin = PIN4, /* Always read as target voltage present.*/
.description = "USBMATE",
.name = "usbmate"
},
{
/* MPSSE_SK (DB0) ----------- SWDCK/JTCK
* MPSSE-DO (DB1) -- 470 R -- SWDIO/JTMS
* MPSSE-DI (DB2) ----------- SWDIO/JTMS
* DO is tristated with SWD read, so
* resistor is not necessary, but protects
* from contentions in case of errors.
* JTAG not possible.*/
.vendor = 0x0403,
.product = 0x6014,/*FT232H*/
.interface = INTERFACE_A,
.mpsse_swd_read.set_data_low = MPSSE_DO,
.mpsse_swd_write.set_data_low = MPSSE_DO,
.name = "ft232h_resistor_swd"
},
{
/* Buffered connection from FTDI to Jtag/Swd.
* TCK and TMS not independant switchable!
* SWD not possible.
* PIN4 low enables buffers
* PIN5 Low indicates VRef applied
* PIN6 reads back SRST
* CBUS PIN1 Sets SRST
* CBUS PIN2 low drives SRST
*/
.vendor = 0x0403,
.product = 0x6010,
.interface = INTERFACE_A,
.init.ddr_low = PIN4,
.init.data_high = PIN4 | PIN3 | PIN2,
.init.ddr_high = PIN4 | PIN3 | PIN2 | PIN1 | PIN0,
.assert_srst.data_high = ~PIN3,
.deassert_srst.data_high = PIN3,
.srst_get_port_cmd = GET_BITS_LOW,
.srst_get_pin = PIN6,
.description = "FTDIJTAG",
.name = "ftdijtag"
},
{
/* UART/SWO on Interface A
* JTAG and control on INTERFACE_B
* Bit 5 high selects SWD-WRITE (TMS routed to MPSSE_DI)
* Bit 6 high selects JTAG vs SWD (TMS routed to MPSSE_CS)
* BCBUS 1 (Output) N_SRST
* BCBUS 2 (Input/ Internal Pull Up) V_ISO available
*
* For bitbanged SWD, set Bit 5 low and select SWD read with
* Bit 6 low. Read Connector TMS as MPSSE_DI.
*
* TDO is routed to Interface 0 RXD as SWO or with Uart
* Connector pin 10 pulled to ground will connect Interface 0 RXD
* to UART connector RXD
*/
.vendor = 0x0403,
.product = 0x6010,
.interface = INTERFACE_B,
.init.data_low = PIN6 | PIN5,
.init.ddr_low = PIN6 | PIN5,
.init.data_high = PIN1 | PIN2,
.assert_srst.data_high = ~PIN1,
.assert_srst.ddr_high = PIN1,
.deassert_srst.data_high = PIN1,
.deassert_srst.ddr_high = ~PIN1,
.mpsse_swd_read.clr_data_low = PIN5 | PIN6,
.mpsse_swd_write.set_data_low = PIN5,
.mpsse_swd_write.clr_data_low = PIN6,
.jtag.set_data_low = PIN6,
.target_voltage_cmd = GET_BITS_HIGH,
.target_voltage_pin = ~PIN2,
.name = "ftdiswd",
.description = "FTDISWD"
},
{
.vendor = 0x15b1,
.product = 0x0003,
.interface = INTERFACE_A,
.init.ddr_low = PIN5,
.name = "olimex"
},
{
/* Buffered connection from FTDI to Jtag/Swd.
* TCK and TMS not independant switchable!
* => SWD not possible.
* DBUS PIN4 / JTAGOE low enables buffers
* DBUS PIN5 / TRST high drives nTRST low OC
* DBUS PIN6 / RST high drives nSRST low OC
* CBUS PIN0 reads back SRST
*/
.vendor = 0x0403,
.product = 0xbdc8,
.interface = INTERFACE_A,
/* Drive low to activate JTAGOE and deassert TRST/RST.*/
.init.data_low = 0,
.init.ddr_low = PIN6 | PIN5 | PIN4,
.init.ddr_high = PIN2, /* ONE LED */
.assert_srst.data_low = PIN6,
.deassert_srst.data_low = ~PIN6,
.srst_get_port_cmd = GET_BITS_HIGH,
.srst_get_pin = PIN0,
.name = "turtelizer",
.description = "Turtelizer JTAG/RS232 Adapter"
},
{
/* https://reference.digilentinc.com/jtag_hs1/jtag_hs1
* No schmeatics available.
* Buffered from FTDI to Jtag/Swd announced
* Independant switch for TMS not known
* => SWD not possible. */
.vendor = 0x0403,
.product = 0xbdc8,
.interface = INTERFACE_A,
.name = "jtaghs1"
},
{
/* Direct connection from FTDI to Jtag/Swd assumed.*/
.vendor = 0x0403,
.product = 0xbdc8,
.interface = INTERFACE_A,
.init.data_low = MPSSE_CS | MPSSE_DO | MPSSE_DI,
.init.ddr_low = MPSSE_CS | MPSSE_DO | MPSSE_SK,
.bb_swdio_in_port_cmd = GET_BITS_LOW,
.bb_swdio_in_pin = MPSSE_CS,
.name = "ftdi"
},
{
/* Product name not unique! Assume SWD not possible.*/
.vendor = 0x0403,
.product = 0x6014,
.interface = INTERFACE_A,
.init.data_low = PIN7,
.init.ddr_low = PIN7,
.init.data_high = PIN5,
.init.ddr_high = PIN5 | PIN4 | PIN3 | PIN2 | PIN1 | PIN0,
.name = "digilent"
},
{
/* Direct connection from FTDI to Jtag/Swd assumed.*/
.vendor = 0x0403,
.product = 0x6014,
.interface = INTERFACE_A,
.init.data_low = MPSSE_CS | MPSSE_DO | MPSSE_DI,
.init.ddr_low = MPSSE_CS | MPSSE_DO | MPSSE_SK,
.bb_swdio_in_port_cmd = GET_BITS_LOW,
.bb_swdio_in_pin = MPSSE_CS,
.name = "ft232h"
},
{
/* Direct connection from FTDI to Jtag/Swd assumed.*/
.vendor = 0x0403,
.product = 0x6011,
.interface = INTERFACE_A,
.bb_swdio_in_port_cmd = GET_BITS_LOW,
.bb_swdio_in_pin = MPSSE_CS,
.name = "ft4232h"
},
{
/* http://www.olimex.com/dev/pdf/ARM-USB-OCD.pdf.
* DBUS 4 global enables JTAG Buffer.
* => TCK and TMS not independant switchable!
* => SWD not possible. */
.vendor = 0x15ba,
.product = 0x002b,
.interface = INTERFACE_A,
.init.ddr_low = PIN4,
.init.data_high = PIN3 | PIN1 | PIN0,
.init.ddr_high = PIN4 | PIN3 | PIN1 | PIN0,
.name = "arm-usb-ocd-h"
},
{
}
};
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 (strncmp(cable->name, cl_opts->opt_cable, strlen(cable->name)) == 0)
break;
}
if (!cable->name ) {
DEBUG_WARN( "No cable matching found for %s\n", cl_opts->opt_cable);
return -1;
}
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 '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) &&
(active_cable->mpsse_swd_read.clr_data_low == 0) &&
(active_cable->mpsse_swd_read.set_data_high == 0) &&
(active_cable->mpsse_swd_read.clr_data_high == 0) &&
(active_cable->mpsse_swd_write.set_data_low == 0) &&
(active_cable->mpsse_swd_write.clr_data_low == 0) &&
(active_cable->mpsse_swd_write.set_data_high == 0) &&
(active_cable->mpsse_swd_write.clr_data_high == 0)) {
DEBUG_INFO("Using external resistor SWD\n");
active_cable->mpsse_swd_read.set_data_low = MPSSE_DO;
active_cable->mpsse_swd_write.set_data_low = MPSSE_DO;
} else if (!libftdi_swd_possible(NULL, NULL) &&
!cl_opts->opt_usejtag) {
DEBUG_WARN("SWD with cable not possible, trying JTAG\n");
cl_opts->opt_usejtag = true;
}
if(ftdic) {
ftdi_usb_close(ftdic);
ftdi_free(ftdic);
ftdic = NULL;
}
if((ftdic = ftdi_new()) == NULL) {
DEBUG_WARN( "ftdi_new: %s\n",
ftdi_get_error_string(ftdic));
abort();
}
info->ftdic = ftdic;
if((err = ftdi_set_interface(ftdic, active_cable->interface)) != 0) {
DEBUG_WARN( "ftdi_set_interface: %d: %s\n",
err, ftdi_get_error_string(ftdic));
goto error_1;
}
if((err = ftdi_usb_open_desc(
ftdic, active_cable->vendor, active_cable->product,
active_cable->description, cl_opts->opt_serial)) != 0) {
DEBUG_WARN( "unable to open ftdi device: %d (%s)\n",
err, ftdi_get_error_string(ftdic));
goto error_1;
}
if((err = ftdi_set_latency_timer(ftdic, 1)) != 0) {
DEBUG_WARN( "ftdi_set_latency_timer: %d: %s\n",
err, ftdi_get_error_string(ftdic));
goto error_2;
}
if((err = ftdi_set_baudrate(ftdic, 1000000)) != 0) {
DEBUG_WARN( "ftdi_set_baudrate: %d: %s\n",
err, ftdi_get_error_string(ftdic));
goto error_2;
}
if((err = ftdi_write_data_set_chunksize(ftdic, BUF_SIZE)) != 0) {
DEBUG_WARN( "ftdi_write_data_set_chunksize: %d: %s\n",
err, ftdi_get_error_string(ftdic));
goto error_2;
}
assert(ftdic != NULL);
#ifdef _Ftdi_Pragma
err = ftdi_tcioflush(ftdic);
#else
err = ftdi_usb_purge_buffers(ftdic);
#endif
if (err != 0) {
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) {
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) {
DEBUG_WARN("ftdi_set_bitmode: %d: %s\n",
err, ftdi_get_error_string(ftdic));
goto error_2;
}
uint8_t ftdi_init[16];
/* Test for pending garbage.*/
int garbage = ftdi_read_data(ftdic, ftdi_init, sizeof(ftdi_init));
if (garbage > 0) {
DEBUG_WARN("FTDI init garbage at start:");
for (int i = 0; i < garbage; i++)
DEBUG_WARN(" %02x", ftdi_init[i]);
DEBUG_WARN("\n");
}
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;
ftdi_init[index++]= 0;
ftdi_init[index++]= SET_BITS_LOW;
ftdi_init[index++]= active_state.data_low;
ftdi_init[index++]= active_state.ddr_low;
ftdi_init[index++]= SET_BITS_HIGH;
ftdi_init[index++]= active_state.data_high;
ftdi_init[index++]= active_state.ddr_high;
libftdi_buffer_write(ftdi_init, index);
libftdi_buffer_flush();
garbage = ftdi_read_data(ftdic, ftdi_init, sizeof(ftdi_init));
if (garbage > 0) {
DEBUG_WARN("FTDI init garbage at end:");
for (int i = 0; i < garbage; i++)
DEBUG_WARN(" %02x", ftdi_init[i]);
DEBUG_WARN("\n");
} return 0;
error_2:
ftdi_usb_close(ftdic);
error_1:
ftdi_free(ftdic);
return -1;
}
static void libftdi_set_data(data_desc_t* data)
{
uint8_t cmd[6];
int index = 0;
if ((data->data_low) || (data->ddr_low)) {
if (data->data_low > 0)
active_state.data_low |= (data->data_low & 0xff);
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 if (data->ddr_low < 0)
active_state.ddr_low &= (data->ddr_low & 0xff);
cmd[index++] = SET_BITS_LOW;
cmd[index++] = active_state.data_low;
cmd[index++] = active_state.ddr_low;
}
if ((data->data_high) || (data->ddr_high)) {
if (data->data_high > 0)
active_state.data_high |= (data->data_high & 0xff);
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 if (data->ddr_high < 0)
active_state.ddr_high &= (data->ddr_high & 0xff);
cmd[index++] = SET_BITS_HIGH;
cmd[index++] = active_state.data_high;
cmd[index++] = active_state.ddr_high;
}
if (index) {
libftdi_buffer_write(cmd, index);
libftdi_buffer_flush();
}
}
void libftdi_srst_set_val(bool assert)
{
if (assert)
libftdi_set_data(&active_cable->assert_srst);
else
libftdi_set_data(&active_cable->deassert_srst);
}
bool libftdi_srst_get_val(void)
{
uint8_t cmd[1] = {0};
uint8_t pin = 0;
if (active_cable->srst_get_port_cmd && active_cable->srst_get_pin) {
cmd[0]= active_cable->srst_get_port_cmd;
pin = active_cable->srst_get_pin;
} else if (active_cable->assert_srst.data_low &&
active_cable->assert_srst.ddr_low) {
cmd[0]= GET_BITS_LOW;
pin = active_cable->assert_srst.data_low;
} else if (active_cable->assert_srst.data_high &&
active_cable->assert_srst.ddr_high) {
cmd[0]= GET_BITS_HIGH;
pin = active_cable->assert_srst.data_high;
}else {
return false;
}
libftdi_buffer_write(cmd, 1);
uint8_t data[1];
libftdi_buffer_read(data, 1);
bool res = false;
if (((pin < 0x7f) || (pin == PIN7)))
res = data[0] & pin;
else
res = !(data[0] & ~pin);
return res;
}
void libftdi_buffer_flush(void)
{
if (!bufptr)
return;
DEBUG_WIRE("Flush %d\n", bufptr);
#if defined(USE_USB_VERSION_BIT)
static struct ftdi_transfer_control *tc_write = NULL;
if (tc_write)
ftdi_transfer_data_done(tc_write);
tc_write = ftdi_write_data_submit(ftdic, outbuf, bufptr);
#else
assert(ftdi_write_data(ftdic, outbuf, bufptr) == bufptr);
DEBUG_WIRE("FT2232 libftdi_buffer flush: %d bytes\n", bufptr);
#endif
bufptr = 0;
}
int libftdi_buffer_write(const uint8_t *data, int size)
{
if((bufptr + size) / BUF_SIZE > 0) libftdi_buffer_flush();
DEBUG_WIRE("Write %d bytes:", size);
for (int i = 0; i < size; i++) {
DEBUG_WIRE(" %02x", data[i]);
if (i && ((i & 0xf) == 0xf))
DEBUG_WIRE("\n\t");
}
DEBUG_WIRE("\n");
memcpy(outbuf + bufptr, data, size);
bufptr += size;
return size;
}
int libftdi_buffer_read(uint8_t *data, int size)
{
#if defined(USE_USB_VERSION_BIT)
struct ftdi_transfer_control *tc;
outbuf[bufptr++] = SEND_IMMEDIATE;
libftdi_buffer_flush();
tc = ftdi_read_data_submit(ftdic, data, size);
ftdi_transfer_data_done(tc);
#else
int index = 0;
const uint8_t cmd[1] = {SEND_IMMEDIATE};
libftdi_buffer_write(cmd, 1);
libftdi_buffer_flush();
while((index += ftdi_read_data(ftdic, data + index, size-index)) != size);
#endif
DEBUG_WIRE("Read %d bytes:", size);
for (int i = 0; i < size; i++) {
DEBUG_WIRE(" %02x", data[i]);
if (i && ((i & 0xf) == 0xf))
DEBUG_WIRE("\n\t");
}
DEBUG_WIRE("\n");
return size;
}
void libftdi_jtagtap_tdi_tdo_seq(
uint8_t *DO, const uint8_t final_tms, const uint8_t *DI, int ticks)
{
int rsize, rticks;
if(!ticks) return;
if (!DI && !DO) return;
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;
uint8_t data[8];
uint8_t cmd = ((DO)? MPSSE_DO_READ : 0) |
((DI)? (MPSSE_DO_WRITE | MPSSE_WRITE_NEG) : 0) | MPSSE_LSB;
rsize = ticks;
if(ticks) {
data[0] = cmd;
data[1] = ticks - 1;
data[2] = 0;
libftdi_buffer_write(data, 3);
if (DI)
libftdi_buffer_write(DI, ticks);
}
int index = 0;
if(rticks) {
rsize++;
data[index++] = cmd | MPSSE_BITMODE;
data[index++] = rticks - 1;
if (DI)
data[index++] = DI[ticks];
}
if(final_tms) {
rsize++;
data[index++] = MPSSE_WRITE_TMS | ((DO)? MPSSE_DO_READ : 0) |
MPSSE_LSB | MPSSE_BITMODE | MPSSE_WRITE_NEG;
data[index++] = 0;
if (DI)
data[index++] = (DI[ticks] & (1 << rticks)) ? 0x81 : 0x01;
}
if (index)
libftdi_buffer_write(data, index);
if (DO) {
int index = 0;
uint8_t *tmp = alloca(rsize);
libftdi_buffer_read(tmp, rsize);
if(final_tms) rsize--;
while(rsize--) {
*DO++ = tmp[index++];
}
if (rticks == 0)
*DO++ = 0;
if(final_tms) {
rticks++;
*(--DO) >>= 1;
*DO |= tmp[index] & 0x80;
} else DO--;
if(rticks) {
*DO >>= (8-rticks);
}
}
}
const char *libftdi_target_voltage(void)
{
uint8_t pin = active_cable->target_voltage_pin;
if (active_cable->target_voltage_cmd && pin) {
libftdi_buffer_write(&active_cable->target_voltage_cmd, 1);
uint8_t data[1];
libftdi_buffer_read(data, 1);
bool res = false;
if (((pin < 0x7f) || (pin == PIN7)))
res = data[0] & pin;
else
res = !(data[0] & ~pin);
if (res)
return "Present";
else
return "Absent";
}
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

@ -0,0 +1,155 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2011 Black Sphere Technologies Ltd.
* Written by Gareth McMullin <gareth@blacksphere.co.nz>
* Copyright (C) 2018 Uwe Bonnes (non@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/>.
*/
#ifndef __FTDI_BMP_H
#define __FTDI_BMP_H
#include "cl_utils.h"
#include "jtagtap.h"
#include "bmp_hosted.h"
typedef struct data_desc_s {
int16_t data_low;
int16_t ddr_low;
int16_t data_high;
int16_t ddr_high;
}data_desc_t;
typedef struct pin_settings_s {
uint8_t set_data_low;
uint8_t clr_data_low;
uint8_t set_data_high;
uint8_t clr_data_high;
}pin_settings_t;
typedef struct cable_desc_s {
int vendor;
int product;
int interface;
/* Initial (C|D)(Bus|Ddr) values for additional pins.
* MPSSE_CS|DI|DO|SK are initialized accordig to mode.*/
data_desc_t init;
/* MPSSE command to read TMS/SWDIO in bitbanging SWD.
* In many cases this is the TMS port, so then use "GET_PIN_LOW".*/
uint8_t bb_swdio_in_port_cmd;
/* bus bit to read TMS/SWDIO in bitbanging SWD.
* In many cases this is the TMS port, so then use "MPSSE_CS".*/
uint8_t bb_swdio_in_pin;
/* Bus data to allow bitbanging switched SWD read.
* TMS is routed to bb_swdio_in_port/pin.*/
pin_settings_t bb_swd_read;
/* Bus data to allow bitbanging switched SWD write.
* TMS is routed to MPSSE_CS.*/
pin_settings_t bb_swd_write;
/* dbus_data, dbus_ddr, cbus_data, cbus_ddr value to assert SRST.
* E.g. with CBUS Pin 1 low,
* give data_high = ~PIN1, ddr_high = PIN1 */
data_desc_t assert_srst;
/* Bus_data, dbus_ddr, cbus_data, cbus_ddr value to release SRST.
* E.g. with CBUS Pin 1 floating with internal pull up,
* give data_high = PIN1, ddr_high = ~PIN1 */
data_desc_t deassert_srst;
/* Command to read back SRST. If 0, port from assert_srst is used*/
uint8_t srst_get_port_cmd;
/* PIN to read back as SRST. if 0 port from assert_srst is ised.
* Use PINX if active high, use Complement (~PINX) if active low*/
uint8_t srst_get_pin;
/* Bbus data for pure MPSSE SWD read.
* Use together with swd_write if by some bits on DBUS,
* SWDIO can be routed to TDI and TDO.
* If both mpsse_swd_read|write and
* bitbang_swd_dbus_read_data/bitbang_tms_in_port_cmd/bitbang_tms_in_pin
* are provided, pure MPSSE SWD is choosen.
* If neither a complete set of swd_read|write or
* bitbang_swd_dbus_read_data/bitbang_tms_in_port_cmd/bitbang_tms_in_pin
* are provided, SWD can not be done.
* swd_read.set_data_low == swd_write.set_data_low == MPSSE_DO
* indicated resistor SWD and inhibits Jtag.*/
pin_settings_t mpsse_swd_read;
/* dbus data for pure MPSSE SWD write.*/
pin_settings_t mpsse_swd_write;
/* dbus data for jtag.*/
pin_settings_t jtag;
/* Command to read port to check target voltage.*/
uint8_t target_voltage_cmd;
/* Pin to check target voltage.*/
uint8_t target_voltage_pin;
/* USB readable description of the device.*/
char *description;
/* Command line argument to -c option to select this device.*/
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(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);
int libftdi_buffer_read(uint8_t *data, int size);
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
#define MPSSE_DO 2
#define PIN1 2
#define MPSSE_DI 4
#define PIN2 4
#define MPSSE_CS 8
#define PIN3 8
#define PIN4 0x10
#define PIN5 0x20
#define PIN6 0x40
#define PIN7 0x80
#endif

View File

@ -0,0 +1,271 @@
/*
* 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/>.
*/
/* Base on code from git://repo.or.cz/libjaylink.git
* and https://github.com/afaerber/jlink.git*/
#include "general.h"
#include "gdb_if.h"
#include "adiv5.h"
#include "exception.h"
#include <assert.h>
#include <unistd.h>
#include <signal.h>
#include <ctype.h>
#include <sys/time.h>
#include "cl_utils.h"
#include "jlink.h"
#define USB_PID_SEGGER 0x1366
/* 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));
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));
DEBUG_INFO("HW: Type %d, Major %d, Minor %d, Rev %d\n",
res[3], res[2], res[1], res[0]);
}
}
static void jlink_print_speed(bmp_info_t *info)
{
uint8_t cmd[1] = {CMD_GET_SPEEDS};
uint8_t res[6];
send_recv(info->usb_link, cmd, 1, res, sizeof(res));
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)
{
uint8_t cmd[1] = {CMD_GET_VERSION};
uint8_t len_str[2];
send_recv(info->usb_link, cmd, 1, len_str, sizeof(len_str));
uint8_t version[0x70];
send_recv(info->usb_link, NULL, 0, version, sizeof(version));
DEBUG_INFO("%s\n", version );
}
static void jlink_print_interfaces(bmp_info_t *info)
{
uint8_t cmd[2] = {CMD_GET_SELECT_IF, JLINK_IF_GET_ACTIVE};
uint8_t res[4];
send_recv(info->usb_link, cmd, 2, res, sizeof(res));
cmd[1] = JLINK_IF_GET_AVAILABLE;
uint8_t res1[4];
send_recv(info->usb_link, cmd, 2, res1, sizeof(res1));
DEBUG_INFO("%s active", (res[0] == SELECT_IF_SWD) ? "SWD":
(res[0] == SELECT_IF_JTAG) ? "JTAG" : "NONE");
uint8_t other_interface = res1[0] - (res[0] + 1);
if (other_interface)
DEBUG_INFO(", %s available\n",
(other_interface == JLINK_IF_SWD) ? "SWD": "JTAG");
else
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_caps(info);
jlink_print_speed(info);
jlink_print_interfaces(info);
}
/* On success endpoints are set and return 0, !0 else */
static int initialize_handle(bmp_info_t *info, libusb_device *dev)
{
struct libusb_config_descriptor *config;
int ret = libusb_get_active_config_descriptor(dev, &config);
if (ret != LIBUSB_SUCCESS) {
DEBUG_WARN( "Failed to get configuration descriptor: %s.",
libusb_error_name(ret));
return -1;
}
const struct libusb_interface *interface;
bool found_interface = false;
const struct libusb_interface_descriptor *desc;
for (int i = 0; i < config->bNumInterfaces; i++) {
interface = &config->interface[i];
desc = &interface->altsetting[0];
if (desc->bInterfaceClass != LIBUSB_CLASS_VENDOR_SPEC)
continue;
if (desc->bInterfaceSubClass != LIBUSB_CLASS_VENDOR_SPEC)
continue;
if (desc->bNumEndpoints < 2)
continue;
found_interface = true;
if (libusb_claim_interface (
info->usb_link->ul_libusb_device_handle, i)) {
DEBUG_WARN( " Can not claim handle\n");
found_interface = false;
}
break;
}
if (!found_interface) {
DEBUG_WARN( "No suitable interface found.");
libusb_free_config_descriptor(config);
return -1;
}
for (int i = 0; i < desc->bNumEndpoints; i++) {
const struct libusb_endpoint_descriptor *epdesc = &desc->endpoint[i];
if (epdesc->bEndpointAddress & LIBUSB_ENDPOINT_IN) {
info->usb_link->ep_rx = epdesc->bEndpointAddress;
} else {
info->usb_link->ep_tx = epdesc->bEndpointAddress;
}
}
libusb_free_config_descriptor(config);
return 0;
}
/* Return 0 if single J-Link device connected or
* serial given matches one of several J-Link devices.
*/
int jlink_init(bmp_info_t *info)
{
usb_link_t *jl = calloc(1, sizeof(usb_link_t));
if (!jl)
return -1;
info->usb_link = jl;
jl->ul_libusb_ctx = info->libusb_ctx;
int ret = -1;
libusb_device **devs;
if (libusb_get_device_list(info->libusb_ctx, &devs) < 0) {
DEBUG_WARN( "libusb_get_device_list() failed");
return ret;
}
int i = 0;
for (; devs[i]; i++) {
libusb_device *dev = devs[i];
struct libusb_device_descriptor desc;
if (libusb_get_device_descriptor(dev, &desc) < 0) {
DEBUG_WARN( "libusb_get_device_descriptor() failed");
goto error;;
}
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_1020))
continue;
int res = libusb_open(dev, &jl->ul_libusb_device_handle);
if (res != LIBUSB_SUCCESS)
continue;
char buf[32];
res = libusb_get_string_descriptor_ascii(jl->ul_libusb_device_handle,
desc.iSerialNumber, (uint8_t*) buf, sizeof(buf));
if ((res <= 0) || (!strstr(buf, info->serial))) {
libusb_close(jl->ul_libusb_device_handle);
continue;
}
break;
}
if (!devs[i])
goto error;
if (initialize_handle(info, devs[i]))
goto error;
jl->req_trans = libusb_alloc_transfer(0);
jl->rep_trans = libusb_alloc_transfer(0);
if (!jl->req_trans || !jl->rep_trans ||
!jl->ep_tx || !jl->ep_rx) {
DEBUG_WARN("Device setup failed\n");
goto error;
}
libusb_free_device_list(devs, 1);
jlink_info(info);
return 0;
error:
libusb_free_device_list(devs, 1);
return -1;
}
const char *jlink_target_voltage(bmp_info_t *info)
{
uint8_t cmd[1] = {CMD_GET_HW_STATUS};
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];
sprintf(ret, "%2d.%03d", mVolt / 1000, mVolt % 1000);
return ret;
}
static bool srst_status = false;
void jlink_srst_set_val(bmp_info_t *info, bool assert)
{
uint8_t cmd[1];
cmd[0]= (assert)? CMD_HW_RESET0: CMD_HW_RESET1;
send_recv(info->usb_link, cmd, 1, NULL, 0);
platform_delay(2);
srst_status = assert;
}
bool jlink_srst_get_val(bmp_info_t *info) {
uint8_t cmd[1] = {CMD_GET_HW_STATUS};
uint8_t res[8];
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

@ -0,0 +1,108 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2019 Uwe Bonnes
*
* 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/>.
*/
#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_SPEEDS 0xc0
#define CMD_GET_SELECT_IF 0xc7
#define CMD_HW_JTAG3 0xcf
#define CMD_HW_RESET0 0xdc
#define CMD_HW_RESET1 0xdd
#define CMD_GET_CAPS 0xe8
#define CMD_GET_EXT_CAPS 0xed
#define CMD_GET_HW_VERSION 0xf0
#define JLINK_IF_GET_ACTIVE 0xfe
#define JLINK_IF_GET_AVAILABLE 0xff
#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);
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

@ -0,0 +1,327 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2011 Black Sphere Technologies Ltd.
* Written by Gareth McMullin <gareth@blacksphere.co.nz>
* 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
* 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/>.
*/
/* This file implements the SW-DP specific functions of the
* ARM Debug Interface v5 Architecure Specification, ARM doc IHI0031A.
*/
#include "general.h"
#include "exception.h"
#include "target.h"
#include "target_internal.h"
#include "adiv5.h"
#include "jlink.h"
#include "cl_utils.h"
#define SWDP_ACK_OK 0x01
#define SWDP_ACK_WAIT 0x02
#define SWDP_ACK_FAULT 0x04
static uint32_t jlink_adiv5_swdp_read(ADIv5_DP_t *dp, uint16_t addr);
static uint32_t jlink_adiv5_swdp_error(ADIv5_DP_t *dp);
static uint32_t jlink_adiv5_swdp_low_access(ADIv5_DP_t *dp, uint8_t RnW,
uint16_t addr, uint32_t value);
static void jlink_adiv5_swdp_abort(ADIv5_DP_t *dp, uint32_t abort);
enum {
SWDIO_WRITE = 0,
SWDIO_READ
};
/* Write at least 50 bits high, two bits low and read DP_IDR and put
* idle cyccles at the end*/
static int line_reset(bmp_info_t *info)
{
uint8_t cmd[44];
cmd[0] = CMD_HW_JTAG3;
cmd[1] = 0;
/* write 19 Bytes.*/
cmd[2] = 19 * 8;
cmd[3] = 0;
uint8_t *direction = cmd + 4;
direction[0] = 0;
direction[1] = 0;
direction[2] = 0;
direction[3] = 0;
direction[4] = 0;
direction[5] = 0xff;
direction[6] = 0xff;
direction[7] = 0xff;
direction[8] = 0xff;
direction[9] = 0xff;
direction[10] = 0xff;
direction[11] = 0xff;
direction[12] = 0xff;
direction[13] = 0xff;
direction[14] = 0x0;
direction[15] = 0x0;
direction[16] = 0x0;
direction[17] = 0x0;
direction[18] = 0xe0;
uint8_t *data = direction + 19;
data[5] = 0xff;
data[6] = 0xff;
data[7] = 0xff;
data[8] = 0xff;
data[9] = 0xff;
data[10] = 0xff;
data[11] = 0xff;
data[12] = 0;
data[13] = 0xa5;
data[18] = 0;
uint8_t res[19];
send_recv(info->usb_link, cmd, 42, res, 19);
send_recv(info->usb_link, NULL, 0, res, 1);
if (res[0] != 0) {
DEBUG_WARN( "Line reset failed\n");
return -1;
}
return 0;
}
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];
send_recv(info->usb_link, cmd, 2, res, sizeof(res));
if (!(res[0] & JLINK_IF_SWD))
return -1;
cmd[1] = SELECT_IF_SWD;
send_recv(info->usb_link, cmd, 2, res, sizeof(res));
platform_delay(10);
/* SWD speed is fixed. Do not set it here*/
return 0;
}
int jlink_swdp_scan(bmp_info_t *info)
{
jlink_swdptap_init(info);
target_list_free();
uint8_t cmd[44];
cmd[0] = CMD_HW_JTAG3;
cmd[1] = 0;
/* write 18 Bytes.*/
cmd[2] = 17 * 8;
cmd[3] = 0;
uint8_t *direction = cmd + 4;
direction[0] = 0xff;
direction[1] = 0xff;
direction[2] = 0xff;
direction[3] = 0xff;
direction[4] = 0xff;
direction[5] = 0xff;
direction[6] = 0xff;
direction[7] = 0xff;
direction[8] = 0xff;
direction[9] = 0xff;
direction[10] = 0xff;
direction[11] = 0xff;
direction[12] = 0xff;
direction[13] = 0xff;
direction[14] = 0xff;
direction[15] = 0xff;
direction[16] = 0xff;
uint8_t *data = direction + 17;
data[0] = 0xff;
data[1] = 0xff;
data[2] = 0xff;
data[3] = 0xff;
data[4] = 0xff;
data[5] = 0xff;
data[6] = 0xff;
data[7] = 0x9e;
data[8] = 0xe7;
data[9] = 0xff;
data[10] = 0xff;
data[11] = 0xff;
data[12] = 0xff;
data[13] = 0xff;
data[14] = 0xff;
data[15] = 0;
data[16] = 0;
uint8_t res[18];
send_recv(info->usb_link, cmd, 38, res, 17);
send_recv(info->usb_link, NULL, 0, res, 1);
if (res[0] != 0) {
DEBUG_WARN( "Line reset failed\n");
return 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;
dp->abort = jlink_adiv5_swdp_abort;
jlink_adiv5_swdp_error(dp);
adiv5_dp_init(dp);
return target_list?1:0;
}
static uint32_t jlink_adiv5_swdp_read(ADIv5_DP_t *dp, uint16_t addr)
{
if (addr & ADIV5_APnDP) {
adiv5_dp_low_access(dp, ADIV5_LOW_READ, addr, 0);
return adiv5_dp_low_access(dp, ADIV5_LOW_READ,
ADIV5_DP_RDBUFF, 0);
} else {
return jlink_adiv5_swdp_low_access(dp, ADIV5_LOW_READ, addr, 0);
}
}
static uint32_t jlink_adiv5_swdp_error(ADIv5_DP_t *dp)
{
uint32_t err, clr = 0;
err = jlink_adiv5_swdp_read(dp, ADIV5_DP_CTRLSTAT) &
(ADIV5_DP_CTRLSTAT_STICKYORUN | ADIV5_DP_CTRLSTAT_STICKYCMP |
ADIV5_DP_CTRLSTAT_STICKYERR | ADIV5_DP_CTRLSTAT_WDATAERR);
if(err & ADIV5_DP_CTRLSTAT_STICKYORUN)
clr |= ADIV5_DP_ABORT_ORUNERRCLR;
if(err & ADIV5_DP_CTRLSTAT_STICKYCMP)
clr |= ADIV5_DP_ABORT_STKCMPCLR;
if(err & ADIV5_DP_CTRLSTAT_STICKYERR)
clr |= ADIV5_DP_ABORT_STKERRCLR;
if(err & ADIV5_DP_CTRLSTAT_WDATAERR)
clr |= ADIV5_DP_ABORT_WDERRCLR;
if (clr)
adiv5_dp_write(dp, ADIV5_DP_ABORT, clr);
if (dp->fault)
err |= 0x8000;
dp->fault = 0;
return err;
}
static uint32_t jlink_adiv5_swdp_low_access(ADIv5_DP_t *dp, uint8_t RnW,
uint16_t addr, uint32_t value)
{
bool APnDP = addr & ADIV5_APnDP;
uint8_t addr8 = addr & 0xff;
uint8_t request = 0x81;
uint32_t response = 0;
uint8_t ack;
platform_timeout timeout;
if(APnDP && dp->fault) return 0;
if(APnDP) request ^= 0x22;
if(RnW) request ^= 0x24;
addr8 &= 0xC;
request |= (addr8 << 1) & 0x18;
if((addr8 == 4) || (addr8 == 8))
request ^= 0x20;
uint8_t cmd[16];
uint8_t res[8];
cmd[0] = CMD_HW_JTAG3;
cmd[1] = 0;
/* 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; /* 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 + 2 , 1);
if (res[2] != 0)
raise_exception(EXCEPTION_ERROR, "Low access setup failed");
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");
if(ack == SWDP_ACK_FAULT) {
if (cl_debuglevel & BMP_DEBUG_TARGET)
DEBUG_WARN( "Fault\n");
dp->fault = 1;
return 0;
}
if(ack != SWDP_ACK_OK) {
if (cl_debuglevel & BMP_DEBUG_TARGET)
DEBUG_WARN( "Protocol %d\n", ack);
line_reset(&info);
return 0;
}
/* Always append 8 idle cycle (SWDIO = 0)!*/
if(RnW) {
memset(cmd + 4, 0, 10);
cmd[2] = 33 + 2; /* 2 idle cycles */
cmd[8] = 0xfe;
send_recv(info.usb_link, cmd, 14, res, 5);
send_recv(info.usb_link, NULL, 0, res + 5, 1);
if (res[5] != 0)
raise_exception(EXCEPTION_ERROR, "Low access read failed");
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 */
raise_exception(EXCEPTION_ERROR, "SWDP Parity error");
} else {
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[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");
}
return response;
}
static void jlink_adiv5_swdp_abort(ADIv5_DP_t *dp, uint32_t abort)
{
adiv5_dp_write(dp, ADIV5_DP_ABORT, abort);
}

View File

@ -0,0 +1,182 @@
/*
* 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/>.
*/
/* Low level JTAG implementation using jlink.
*
*/
#include "general.h"
#include <unistd.h>
#include <assert.h>
#include "exception.h"
#include "jlink.h"
#include "cl_utils.h"
static void jtagtap_reset(void)
{
jtagtap_soft_reset();
}
static void jtagtap_tms_seq(uint32_t MS, int ticks)
{
DEBUG_PROBE("jtagtap_tms_seq 0x%08" PRIx32 ", ticks %d\n", MS, ticks);
int len = (ticks + 7) / 8;
uint8_t cmd[12];
cmd[0] = CMD_HW_JTAG3;
cmd[1] = 0;
cmd[2] = ticks;
cmd[3] = 0;
uint8_t *tms = cmd + 4;
for (int i = 0; i < len; i++) {
*tms = MS & 0xff;
*(tms + len) = *tms;
tms++;
MS >>= 8;
}
uint8_t res[4];
send_recv(info.usb_link, cmd, 4 + 2 * len, res, len);
send_recv(info.usb_link, NULL, 0, res, 1);
if (res[0] != 0)
raise_exception(EXCEPTION_ERROR, "tagtap_tms_seq failed");
}
static void jtagtap_tdi_tdo_seq(uint8_t *DO, const uint8_t final_tms,
const uint8_t *DI, int ticks)
{
if (!ticks)
return;
int len = (ticks + 7) / 8;
if (cl_debuglevel & BMP_DEBUG_PROBE) {
DEBUG_PROBE("jtagtap_tdi_tdo %s, ticks %d, DI: ",
(final_tms) ? "Final TMS" : "", ticks);
for (int i = 0; i < len; i++) {
DEBUG_PROBE("%02x", DI[i]);
}
DEBUG_PROBE("\n");
}
uint8_t *cmd = alloca(4 + 2 * len);
cmd[0] = CMD_HW_JTAG3;
cmd[1] = 0;
cmd[2] = ticks;
cmd[3] = 0;
uint8_t *tms = cmd + 4;
for (int i = 0; i < len; i++)
*tms++ = 0;
if (final_tms)
cmd[4 + (ticks - 1) / 8] |= (1 << ((ticks - 1) % 8));
uint8_t *tdi = tms;
if (DI)
for (int i = 0; i < len; i++)
*tdi++ = DI[i];
if (DO)
send_recv(info.usb_link, cmd, 4 + 2 * len, DO, len);
else
send_recv(info.usb_link, cmd, 4 + 2 * len, cmd, len);
uint8_t res[1];
send_recv(info.usb_link, NULL, 0, res, 1);
if (res[0] != 0)
raise_exception(EXCEPTION_ERROR, "jtagtap_tdi_tdi failed");
}
static void jtagtap_tdi_seq(const uint8_t final_tms, const uint8_t *DI,
int ticks)
{
if (cl_debuglevel & BMP_DEBUG_PROBE) {
DEBUG_PROBE("jtagtap_tdi_seq %s:", (final_tms)? "final_tms" : "");
const uint8_t *p = DI;
unsigned int i = (ticks & 7) & ~7 ;
if (i > 16)
i = 16;
while (i--)
DEBUG_PROBE(" %02x", *p++);
if (ticks > (16 * 8))
DEBUG_PROBE(" ...");
DEBUG_PROBE("\n");
}
return jtagtap_tdi_tdo_seq(NULL, final_tms, DI, ticks);
}
static uint8_t jtagtap_next(uint8_t dTMS, uint8_t dTDI)
{
DEBUG_PROBE("jtagtap_next TMS 0x%02x, TDI %02x\n", dTMS, dTDI);
uint8_t cmd[6];
cmd[0] = CMD_HW_JTAG3;
cmd[1] = 0;
cmd[2] = 1;
cmd[3] = 0;
cmd[4] = (dTMS) ? 0xff : 0;
cmd[5] = (dTDI) ? 0xff : 0;
uint8_t ret[1];
send_recv(info.usb_link, cmd, 6, ret, 1);
uint8_t res[1];
send_recv(info.usb_link, NULL, 0, res, 1);
if (res[0] != 0)
raise_exception(EXCEPTION_ERROR, "jtagtap_next failed");
return (ret[0] & 1);
}
int jlink_jtagtap_init(bmp_info_t *info, jtag_proc_t *jtag_proc)
{
DEBUG_PROBE("jtap_init\n");
uint8_t cmd_switch[2] = {CMD_GET_SELECT_IF, JLINK_IF_GET_AVAILABLE};
uint8_t res[4];
send_recv(info->usb_link, cmd_switch, 2, res, sizeof(res));
if (!(res[0] & JLINK_IF_JTAG)) {
DEBUG_WARN("JTAG not available\n");
return -1;
}
cmd_switch[1] = SELECT_IF_JTAG;
send_recv(info->usb_link, cmd_switch, 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);
uint8_t cmd[44];
cmd[0] = CMD_HW_JTAG3;
cmd[1] = 0;
/* write 8 Bytes.*/
cmd[2] = 9 * 8;
cmd[3] = 0;
uint8_t *tms = cmd + 4;
tms[0] = 0xff;
tms[1] = 0xff;
tms[2] = 0xff;
tms[3] = 0xff;
tms[4] = 0xff;
tms[5] = 0xff;
tms[6] = 0xff;
tms[7] = 0x3c;
tms[8] = 0xe7;
send_recv(info->usb_link, cmd, 4 + 2 * 9, cmd, 9);
send_recv(info->usb_link, NULL, 0, res, 1);
if (res[0] != 0) {
DEBUG_WARN("Switch to JTAG failed\n");
return 0;
}
jtag_proc->jtagtap_reset = jtagtap_reset;
jtag_proc->jtagtap_next =jtagtap_next;
jtag_proc->jtagtap_tms_seq = jtagtap_tms_seq;
jtag_proc->jtagtap_tdi_tdo_seq = jtagtap_tdi_tdo_seq;
jtag_proc->jtagtap_tdi_seq = jtagtap_tdi_seq;
return 0;
}

View File

@ -0,0 +1,129 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2008 Black Sphere Technologies Ltd.
* 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
* (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/>.
*/
/* Low level JTAG implementation using FT2232 with libftdi.
*
*/
#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;
static void jtagtap_reset(void);
static void jtagtap_tms_seq(uint32_t MS, int ticks);
static void jtagtap_tdi_seq(
const uint8_t final_tms, const uint8_t *DI, int ticks);
static uint8_t jtagtap_next(uint8_t dTMS, uint8_t dTDI);
int libftdi_jtagtap_init(jtag_proc_t *jtag_proc)
{
if ((active_cable->mpsse_swd_read.set_data_low == MPSSE_DO) &&
(active_cable->mpsse_swd_write.set_data_low == MPSSE_DO)) {
printf("Jtag not possible with resistor SWD!\n");
return -1;
}
jtag_proc->jtagtap_reset = jtagtap_reset;
jtag_proc->jtagtap_next =jtagtap_next;
jtag_proc->jtagtap_tms_seq = jtagtap_tms_seq;
jtag_proc->jtagtap_tdi_tdo_seq = libftdi_jtagtap_tdi_tdo_seq;
jtag_proc->jtagtap_tdi_seq = jtagtap_tdi_seq;
active_state.data_low |= active_cable->jtag.set_data_low |
MPSSE_CS | MPSSE_DI | MPSSE_DO;
active_state.data_low &= ~(active_cable->jtag.clr_data_low | MPSSE_SK);
active_state.ddr_low |= MPSSE_CS | MPSSE_DO | MPSSE_SK;
active_state.ddr_low &= ~(MPSSE_DI);
active_state.data_high |= active_cable->jtag.set_data_high;
active_state.data_high &= ~(active_cable->jtag.clr_data_high);
uint8_t gab[16];
int garbage = ftdi_read_data(ftdic, gab, sizeof(gab));
if (garbage > 0) {
DEBUG_WARN("FTDI JTAG init got garbage:");
for (int i = 0; i < garbage; i++)
DEBUG_WARN(" %02x", gab[i]);
DEBUG_WARN("\n");
}
uint8_t cmd_write[16] = {
SET_BITS_LOW, active_state.data_low,
active_state.ddr_low,
SET_BITS_HIGH, active_state.data_high, active_state.ddr_high};
libftdi_buffer_write(cmd_write, 6);
libftdi_buffer_flush();
/* Write out start condition and pull garbage from read buffer.
* FT2232D otherwise misbehaves on runs follwoing the first run.*/
garbage = ftdi_read_data(ftdic, cmd_write, sizeof(cmd_write));
if (garbage > 0) {
DEBUG_WARN("FTDI JTAG end init got garbage:");
for (int i = 0; i < garbage; i++)
DEBUG_WARN(" %02x", cmd_write[i]);
DEBUG_WARN("\n");
}
/* Go to JTAG mode for SWJ-DP */
for (int i = 0; i <= 50; i++)
jtag_proc->jtagtap_next(1, 0); /* Reset SW-DP */
jtag_proc->jtagtap_tms_seq(0xE73C, 16); /* SWD to JTAG sequence */
jtag_proc->jtagtap_tms_seq(0x1F, 6);
return 0;
}
static void jtagtap_reset(void)
{
jtagtap_soft_reset();
}
static void jtagtap_tms_seq(uint32_t MS, int ticks)
{
uint8_t tmp[3] = {
MPSSE_WRITE_TMS | MPSSE_LSB | MPSSE_BITMODE | MPSSE_WRITE_NEG, 0, 0};
while(ticks >= 0) {
tmp[1] = ticks<7?ticks-1:6;
tmp[2] = 0x80 | (MS & 0x7F);
libftdi_buffer_write(tmp, 3);
MS >>= 7; ticks -= 7;
}
}
static void jtagtap_tdi_seq(
const uint8_t final_tms, const uint8_t *DI, int ticks)
{
return libftdi_jtagtap_tdi_tdo_seq(NULL, final_tms, DI, ticks);
}
static uint8_t jtagtap_next(uint8_t dTMS, uint8_t dTDI)
{
uint8_t ret;
uint8_t tmp[3] = {MPSSE_WRITE_TMS | MPSSE_DO_READ | MPSSE_LSB |
MPSSE_BITMODE | MPSSE_WRITE_NEG, 0, 0};
tmp[2] = (dTDI?0x80:0) | (dTMS?0x01:0);
libftdi_buffer_write(tmp, 3);
libftdi_buffer_read(&ret, 1);
ret &= 0x80;
return ret;
}

View File

@ -0,0 +1,413 @@
/*
* This file is part of the Black Magic Debug project.
*
* 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
* 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/>.
*/
/* MPSSE bit-banging SW-DP interface over FTDI with loop unrolled.
* Speed is sensible.
*/
#include "general.h"
#include <assert.h>
#include <ftdi.h>
#include "ftdi_bmp.h"
enum swdio_status{
SWDIO_STATUS_DRIVE = 0,
SWDIO_STATUS_FLOAT,
};
static enum swdio_status olddir;
static bool do_mpsse;
static bool direct_bb_swd;
#define MPSSE_MASK (MPSSE_DO | MPSSE_DI | MPSSE_CS)
#define MPSSE_TD_MASK (MPSSE_DO | MPSSE_DI)
#define MPSSE_TMS_SHIFT (MPSSE_WRITE_TMS | MPSSE_LSB |\
MPSSE_BITMODE | MPSSE_WRITE_NEG)
#define MPSSE_TDO_SHIFT (MPSSE_DO_WRITE | MPSSE_LSB |\
MPSSE_BITMODE | MPSSE_WRITE_NEG)
static void swdptap_turnaround(enum swdio_status dir)
{
if (dir == olddir)
return;
olddir = dir;
DEBUG_PROBE("Turnaround %s\n", (dir == SWDIO_STATUS_FLOAT) ? "float": "drive");
if (do_mpsse) {
if (dir == SWDIO_STATUS_FLOAT) /* SWDIO goes to input */ {
active_state.data_low |= active_cable->mpsse_swd_read.set_data_low | MPSSE_DO;
active_state.data_low &= ~active_cable->mpsse_swd_read.clr_data_low;
active_state.ddr_low &= ~MPSSE_DO;
active_state.data_high |= active_cable->mpsse_swd_read.set_data_high;
active_state.data_high &= ~active_cable->mpsse_swd_read.clr_data_high;
uint8_t cmd_read[6] = {
SET_BITS_LOW, active_state.data_low,
active_state.ddr_low,
SET_BITS_HIGH, active_state.data_high, active_state.ddr_high};
libftdi_buffer_write(cmd_read, 6);
}
uint8_t cmd[] = {MPSSE_TDO_SHIFT, 0, 0}; /* One clock cycle */
libftdi_buffer_write(cmd, sizeof(cmd));
if (dir == SWDIO_STATUS_DRIVE) /* SWDIO goes to output */ {
active_state.data_low |= active_cable->mpsse_swd_write.set_data_low | MPSSE_DO;
active_state.data_low &= ~active_cable->mpsse_swd_write.clr_data_low;
active_state.ddr_low |= MPSSE_DO;
active_state.data_high |= active_cable->mpsse_swd_write.set_data_high;
active_state.data_high &= ~active_cable->mpsse_swd_write.clr_data_high;
uint8_t cmd_write[6] = {
SET_BITS_LOW, active_state.data_low,
active_state.ddr_low,
SET_BITS_HIGH, active_state.data_high, active_state.ddr_high};
libftdi_buffer_write(cmd_write, 6);
}
} else {
uint8_t cmd[9];
int index = 0;
if(dir == SWDIO_STATUS_FLOAT) { /* SWDIO goes to input */
if (direct_bb_swd) {
active_state.data_low |= MPSSE_CS;
active_state.ddr_low &= ~MPSSE_CS;
} else {
active_state.data_low |= active_cable->bb_swd_read.set_data_low;
active_state.data_low &= ~active_cable->bb_swd_read.clr_data_low;
active_state.data_high |= active_cable->bb_swd_read.set_data_high;
active_state.data_high &= ~active_cable->bb_swd_read.clr_data_high;
}
cmd[index++] = SET_BITS_LOW;
cmd[index++] = active_state.data_low;
cmd[index++] = active_state.ddr_low;
cmd[index++] = SET_BITS_HIGH;
cmd[index++] = active_state.data_high;
cmd[index++] = active_state.ddr_high;
}
/* One clock cycle */
cmd[index++] = MPSSE_TMS_SHIFT;
cmd[index++] = 0;
cmd[index++] = 0;
if (dir == SWDIO_STATUS_DRIVE) {
if (direct_bb_swd) {
active_state.data_low |= MPSSE_CS;
active_state.ddr_low |= MPSSE_CS;
} else {
active_state.data_low |= active_cable->bb_swd_write.set_data_low;
active_state.data_low &= ~active_cable->bb_swd_write.clr_data_low;
active_state.data_high |= active_cable->bb_swd_write.set_data_high;
active_state.data_high &= ~active_cable->bb_swd_write.clr_data_high;
}
cmd[index++] = SET_BITS_LOW;
cmd[index++] = active_state.data_low;
cmd[index++] = active_state.ddr_low;
cmd[index++] = SET_BITS_HIGH;
cmd[index++] = active_state.data_high;
cmd[index++] = active_state.ddr_high;
}
libftdi_buffer_write(cmd, index);
}
}
static bool swdptap_seq_in_parity(uint32_t *res, int ticks);
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);
bool libftdi_swd_possible(bool *do_mpsse, bool *direct_bb_swd)
{
bool swd_read =
active_cable->mpsse_swd_read.set_data_low ||
active_cable->mpsse_swd_read.clr_data_low ||
active_cable->mpsse_swd_read.set_data_high ||
active_cable->mpsse_swd_read.clr_data_high;
bool swd_write =
active_cable->mpsse_swd_write.set_data_low ||
active_cable->mpsse_swd_write.clr_data_low ||
active_cable->mpsse_swd_write.set_data_high ||
active_cable->mpsse_swd_write.clr_data_high;
bool mpsse = swd_read && swd_write;
if (do_mpsse)
*do_mpsse = mpsse;
if (!mpsse) {
bool bb_swd_read =
active_cable->bb_swd_read.set_data_low ||
active_cable->bb_swd_read.clr_data_low ||
active_cable->bb_swd_read.set_data_high ||
active_cable->bb_swd_read.clr_data_high;
bool bb_swd_write =
active_cable->bb_swd_write.set_data_low ||
active_cable->bb_swd_write.clr_data_low ||
active_cable->bb_swd_write.set_data_high ||
active_cable->bb_swd_write.clr_data_high;
bool bb_direct_possible =
active_cable->bb_swdio_in_port_cmd == GET_BITS_LOW &&
active_cable->bb_swdio_in_pin == MPSSE_CS;
if (!bb_swd_read && !bb_swd_write) {
if (!bb_direct_possible)
return false;
}
if (direct_bb_swd)
*direct_bb_swd = true;
}
return true;
}
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");
return -1;
}
active_state.data_low |= MPSSE_CS | MPSSE_DI | MPSSE_DO;
active_state.data_low &= MPSSE_SK;
active_state.ddr_low |= MPSSE_SK;
active_state.ddr_low &= ~(MPSSE_CS | MPSSE_DI | MPSSE_DO);
if (do_mpsse) {
DEBUG_INFO("Using genuine MPSSE for SWD.\n");
active_state.data_low |= active_cable->mpsse_swd_read.set_data_low;
active_state.data_low &= ~(active_cable->mpsse_swd_read.clr_data_low);
active_state.data_high |= active_cable->mpsse_swd_read.set_data_high;
active_state.data_high &= ~(active_cable->mpsse_swd_read.clr_data_high);
} else if (direct_bb_swd) {
DEBUG_INFO("Using direct bitbang with SWDIO %cBUS%d.\n",
(active_cable->bb_swdio_in_port_cmd == GET_BITS_LOW) ? 'C' : 'D',
__builtin_ctz(active_cable->bb_swdio_in_pin));
} else {
DEBUG_INFO("Using switched bitbang for SWD.\n");
active_state.data_low |= active_cable->bb_swd_read.set_data_low;
active_state.data_low &= ~(active_cable->bb_swd_read.clr_data_low);
active_state.data_high |= active_cable->bb_swd_read.set_data_high;
active_state.data_high &= ~(active_cable->bb_swd_read.clr_data_high);
active_state.ddr_low |= MPSSE_CS;
if (active_cable->bb_swdio_in_port_cmd == GET_BITS_LOW)
active_state.ddr_low &= ~active_cable->bb_swdio_in_pin;
else if (active_cable->bb_swdio_in_port_cmd == GET_BITS_HIGH)
active_state.ddr_high &= ~active_cable->bb_swdio_in_pin;
}
uint8_t cmd_write[6] = {
SET_BITS_LOW, active_state.data_low,
active_state.ddr_low,
SET_BITS_HIGH, active_state.data_high, active_state.ddr_high};
libftdi_buffer_write(cmd_write, 6);
libftdi_buffer_flush();
olddir = SWDIO_STATUS_FLOAT;
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;
}
bool swdptap_bit_in(void)
{
swdptap_turnaround(SWDIO_STATUS_FLOAT);
uint8_t cmd[4];
int index = 0;
bool result = false;
if (do_mpsse) {
uint8_t cmd[2] = {MPSSE_DO_READ | MPSSE_LSB | MPSSE_BITMODE, 0};
libftdi_buffer_write(cmd, sizeof(cmd));
uint8_t data[1];
libftdi_buffer_read(data, sizeof(data));
result = (data[0] & 0x80);
} else {
cmd[index++] = active_cable->bb_swdio_in_port_cmd;
cmd[index++] = MPSSE_TMS_SHIFT;
cmd[index++] = 0;
cmd[index++] = 0;
libftdi_buffer_write(cmd, index);
uint8_t data[1];
libftdi_buffer_read(data, sizeof(data));
result = (data[0] &= active_cable->bb_swdio_in_pin);
}
return result;
}
void swdptap_bit_out(bool val)
{
swdptap_turnaround(SWDIO_STATUS_DRIVE);
if (do_mpsse) {
uint8_t cmd[3] = {MPSSE_TDO_SHIFT, 0, (val)? 1:0};
libftdi_buffer_write(cmd, sizeof(cmd));
} else {
uint8_t cmd[3];
cmd[0] = MPSSE_TMS_SHIFT;
cmd[1] = 0;
cmd[2] = (val)? 1 : 0;
libftdi_buffer_write(cmd, sizeof(cmd));
}
}
bool swdptap_seq_in_parity(uint32_t *res, int ticks)
{
assert(ticks == 32);
swdptap_turnaround(SWDIO_STATUS_FLOAT);
unsigned int parity = 0;
unsigned int result = 0;
if (do_mpsse) {
uint8_t DO[5];
libftdi_jtagtap_tdi_tdo_seq(DO, 0, NULL, ticks + 1);
result = DO[0] + (DO[1] << 8) + (DO[2] << 16) + (DO[3] << 24);
parity = __builtin_parity(result & ((1LL << ticks) - 1)) & 1;
parity ^= DO[4] & 1;
} else {
int index = ticks + 1;
uint8_t cmd[4];
cmd[0] = active_cable->bb_swdio_in_port_cmd;
cmd[1] = MPSSE_TMS_SHIFT;
cmd[2] = 0;
cmd[3] = 0;
while (index--) {
libftdi_buffer_write(cmd, sizeof(cmd));
}
uint8_t data[33];
libftdi_buffer_read(data, ticks + 1);
if (data[ticks] & active_cable->bb_swdio_in_pin)
parity ^= 1;
index = ticks;
while (index--) {
if (data[index] & active_cable->bb_swdio_in_pin) {
parity ^= 1;
result |= (1 << index);
}
}
}
*res = result;
return parity;
}
static uint32_t swdptap_seq_in(int ticks)
{
if (!ticks)
return 0;
uint32_t result = 0;
swdptap_turnaround(SWDIO_STATUS_FLOAT);
if (do_mpsse) {
uint8_t DO[4];
libftdi_jtagtap_tdi_tdo_seq(DO, 0, NULL, ticks);
int bytes = ticks >> 3;
if (ticks & 7)
bytes++;
for (int i = 0; i < bytes; i++) {
result |= DO[i] << (8 * i);
}
} else {
int index = ticks;
uint8_t cmd[4];
cmd[0] = active_cable->bb_swdio_in_port_cmd;
cmd[1] = MPSSE_TMS_SHIFT;
cmd[2] = 0;
cmd[3] = 0;
while (index--) {
libftdi_buffer_write(cmd, sizeof(cmd));
}
uint8_t data[32];
libftdi_buffer_read(data, ticks);
index = ticks;
while (index--) {
if (data[index] & active_cable->bb_swdio_in_pin)
result |= (1 << index);
}
}
return result;
}
static void swdptap_seq_out(uint32_t MS, int ticks)
{
if (!ticks)
return;
swdptap_turnaround(SWDIO_STATUS_DRIVE);
if (do_mpsse) {
uint8_t DI[4];
DI[0] = (MS >> 0) & 0xff;
DI[1] = (MS >> 8) & 0xff;
DI[2] = (MS >> 16) & 0xff;
DI[3] = (MS >> 24) & 0xff;
libftdi_jtagtap_tdi_tdo_seq(NULL, 0, DI, ticks);
} else {
uint8_t cmd[16];
unsigned int index = 0;
while (ticks) {
cmd[index++] = MPSSE_TMS_SHIFT;
if (ticks >= 7) {
cmd[index++] = 6;
cmd[index++] = MS & 0x7f;
MS >>= 7;
ticks -= 7;
} else {
cmd[index++] = ticks - 1;
cmd[index++] = MS & 0x7f;
ticks = 0;
}
}
libftdi_buffer_write(cmd, index);
}
}
/* 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)
{
(void) ticks;
int parity = __builtin_parity(MS) & 1;
unsigned int index = 0;
swdptap_turnaround(SWDIO_STATUS_DRIVE);
if (do_mpsse) {
uint8_t DI[8];
DI[0] = (MS >> 0) & 0xff;
DI[1] = (MS >> 8) & 0xff;
DI[2] = (MS >> 16) & 0xff;
DI[3] = (MS >> 24) & 0xff;
DI[4] = parity;
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++] = MS & 0x7f;
MS >>= 7;
steps -= 7;
} else {
cmd[index++] = (MS & 0x7f) | (parity << 4);
steps = 0;
}
}
cmd[index++] = MPSSE_TMS_SHIFT;
cmd[index++] = 4;
cmd[index++] = 0;
libftdi_buffer_write(cmd, index);
}
}

View File

@ -0,0 +1,556 @@
/*
* This file is part of the Black Magic Debug project.
*
* 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
* 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/>.
*/
/* Handle different BMP pc-hosted platforms/
*/
#include "general.h"
#include "jtagtap.h"
#include "target.h"
#include "target_internal.h"
#include "adiv5.h"
#include "timing.h"
#include "cl_utils.h"
#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"
#include "cl_utils.h"
bmp_info_t info;
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)
{
libusb_exit_function(&info);
switch (info.bmp_type) {
case BMP_TYPE_CMSIS_DAP:
dap_exit_function();
break;
default:
break;
}
#ifdef ENABLE_RTT
rtt_if_exit();
#endif
fflush(stdout);
}
/* SIGTERM handler. */
static void sigterm_handler(int sig)
{
(void)sig;
exit(0);
}
static BMP_CL_OPTIONS_t cl_opts;
void platform_init(int argc, char **argv)
{
cl_init(&cl_opts, argc, argv);
atexit(exit_function);
signal(SIGTERM, sigterm_handler);
signal(SIGINT, sigterm_handler);
if (cl_opts.opt_device)
info.bmp_type = BMP_TYPE_BMP;
else if (find_debuggers(&cl_opts, &info))
exit(-1);
bmp_ident(&info);
switch (info.bmp_type) {
case BMP_TYPE_BMP:
if (serial_open(&cl_opts, info.serial))
exit(-1);
remote_init();
break;
case BMP_TYPE_STLINKV2:
if (stlink_init(&info))
exit(-1);
break;
case BMP_TYPE_CMSIS_DAP:
if (dap_init(&info))
exit(-1);
break;
case BMP_TYPE_LIBFTDI:
if (ftdi_bmp_init(&cl_opts, &info))
exit(-1);
break;
case BMP_TYPE_JLINK:
if (jlink_init(&info))
exit(-1);
break;
default:
exit(-1);
}
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;
}
}
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:
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)) {
free(dp);
} else {
adiv5_dp_init(dp);
if (target_list)
return 1;
}
break;
}
case BMP_TYPE_JLINK:
return jlink_swdp_scan(&info);
default:
return 0;
}
return 0;
}
int swdptap_init(ADIv5_DP_t *dp)
{
switch (info.bmp_type) {
case BMP_TYPE_BMP:
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(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:
case BMP_TYPE_JLINK:
case BMP_TYPE_CMSIS_DAP:
return jtag_scan(lrlens);
case BMP_TYPE_STLINKV2:
return jtag_scan_stlinkv2(&info, lrlens);
default:
return -1;
}
return -1;
}
int platform_jtagtap_init(void)
{
switch (info.bmp_type) {
case BMP_TYPE_BMP:
return remote_jtagtap_init(&jtag_proc);
case BMP_TYPE_STLINKV2:
return 0;
case BMP_TYPE_LIBFTDI:
return libftdi_jtagtap_init(&jtag_proc);
case BMP_TYPE_JLINK:
return jlink_jtagtap_init(&info, &jtag_proc);
case BMP_TYPE_CMSIS_DAP:
return cmsis_dap_jtagtap_init(&jtag_proc);
default:
return -1;
}
return -1;
}
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);
case BMP_TYPE_CMSIS_DAP:
return dap_adiv5_dp_defaults(dp);
default:
break;
}
}
int platform_jtag_dp_init(ADIv5_DP_t *dp)
{
switch (info.bmp_type) {
case BMP_TYPE_BMP:
case BMP_TYPE_LIBFTDI:
case BMP_TYPE_JLINK:
return 0;
case BMP_TYPE_STLINKV2:
return stlink_jtag_dp_init(dp);
case BMP_TYPE_CMSIS_DAP:
return dap_jtag_dp_init(dp);
default:
return 0;
}
return 0;
}
char *platform_ident(void)
{
switch (info.bmp_type) {
case BMP_TYPE_NONE:
return "NONE";
case BMP_TYPE_BMP:
return "BMP";
case BMP_TYPE_STLINKV2:
return "STLINKV2";
case BMP_TYPE_LIBFTDI:
return "LIBFTDI";
case BMP_TYPE_CMSIS_DAP:
return "CMSIS_DAP";
case BMP_TYPE_JLINK:
return "JLINK";
}
return NULL;
}
const char *platform_target_voltage(void)
{
switch (info.bmp_type) {
case BMP_TYPE_BMP:
return remote_target_voltage();
case BMP_TYPE_STLINKV2:
return stlink_target_voltage(&info);
case BMP_TYPE_LIBFTDI:
return libftdi_target_voltage();
case BMP_TYPE_JLINK:
return jlink_target_voltage(&info);
default:
break;
}
return NULL;
}
void platform_srst_set_val(bool assert)
{
switch (info.bmp_type) {
case BMP_TYPE_STLINKV2:
return stlink_srst_set_val(&info, assert);
case BMP_TYPE_BMP:
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;
}
}
bool platform_srst_get_val(void)
{
switch (info.bmp_type) {
case BMP_TYPE_BMP:
return remote_srst_get_val();
case BMP_TYPE_STLINKV2:
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) {
case BMP_TYPE_LIBFTDI:
return libftdi_buffer_flush();
default:
break;
}
}
static void ap_decode_access(uint16_t addr, uint8_t RnW)
{
if (RnW)
fprintf(stderr, "Read ");
else
fprintf(stderr, "Write ");
if (addr < 0x100) {
switch(addr) {
case 0x00:
if (RnW)
fprintf(stderr, "DP_DPIDR :");
else
fprintf(stderr, "DP_ABORT :");
break;
case 0x04: fprintf(stderr, "CTRL/STAT:");
break;
case 0x08:
if (RnW)
fprintf(stderr, "RESEND :");
else
fprintf(stderr, "DP_SELECT:");
break;
case 0x0c: fprintf(stderr, "DP_RDBUFF:");
break;
default: fprintf(stderr, "Unknown %02x :", addr);
}
} else {
fprintf(stderr, "AP 0x%02x ", addr >> 8);
switch (addr & 0xff) {
case 0x00: fprintf(stderr, "CSW :");
break;
case 0x04: fprintf(stderr, "TAR :");
break;
case 0x0c: fprintf(stderr, "DRW :");
break;
case 0x10: fprintf(stderr, "DB0 :");
break;
case 0x14: fprintf(stderr, "DB1 :");
break;
case 0x18: fprintf(stderr, "DB2 :");
break;
case 0x1c: fprintf(stderr, "DB3 :");
break;
case 0xf8: fprintf(stderr, "BASE :");
break;
case 0xf4: fprintf(stderr, "CFG :");
break;
case 0xfc: fprintf(stderr, "IDR :");
break;
default: fprintf(stderr, "RSVD%02x:", addr & 0xff);
}
}
}
void adiv5_dp_write(ADIv5_DP_t *dp, uint16_t addr, uint32_t value)
{
if (cl_debuglevel & BMP_DEBUG_TARGET) {
ap_decode_access(addr, ADIV5_LOW_WRITE);
fprintf(stderr, " 0x%08" PRIx32 "\n", value);
}
dp->low_access(dp, ADIV5_LOW_WRITE, addr, value);
}
uint32_t adiv5_dp_read(ADIv5_DP_t *dp, uint16_t addr)
{
uint32_t ret = dp->dp_read(dp, addr);
if (cl_debuglevel & BMP_DEBUG_TARGET) {
ap_decode_access(addr, ADIV5_LOW_READ);
fprintf(stderr, " 0x%08" PRIx32 "\n", ret);
}
return ret;
}
uint32_t adiv5_dp_error(ADIv5_DP_t *dp)
{
uint32_t ret = dp->error(dp);
DEBUG_TARGET( "DP Error 0x%08" PRIx32 "\n", ret);
return ret;
}
uint32_t adiv5_dp_low_access(struct ADIv5_DP_s *dp, uint8_t RnW,
uint16_t addr, uint32_t value)
{
uint32_t ret = dp->low_access(dp, RnW, addr, value);
if (cl_debuglevel & BMP_DEBUG_TARGET) {
ap_decode_access(addr, RnW);
fprintf(stderr, " 0x%08" PRIx32 "\n", (RnW)? ret : value);
}
return ret;
}
uint32_t adiv5_ap_read(ADIv5_AP_t *ap, uint16_t addr)
{
uint32_t ret = ap->dp->ap_read(ap, addr);
if (cl_debuglevel & BMP_DEBUG_TARGET) {
ap_decode_access(addr, ADIV5_LOW_READ);
fprintf(stderr, " 0x%08" PRIx32 "\n", ret);
}
return ret;
}
void adiv5_ap_write(ADIv5_AP_t *ap, uint16_t addr, uint32_t value)
{
if (cl_debuglevel & BMP_DEBUG_TARGET) {
ap_decode_access(addr, ADIV5_LOW_WRITE);
fprintf(stderr, " 0x%08" PRIx32 "\n", value);
}
return ap->dp->ap_write(ap, addr, value);
}
void adiv5_mem_read(ADIv5_AP_t *ap, void *dest, uint32_t src, size_t len)
{
ap->dp->mem_read(ap, dest, src, len);
if (cl_debuglevel & BMP_DEBUG_TARGET) {
fprintf(stderr, "ap_memread @ %" PRIx32 " len %" PRIx32 ":",
src, (uint32_t)len);
uint8_t *p = (uint8_t *) dest;
unsigned int i = len;
if (i > 16)
i = 16;
while (i--)
fprintf(stderr, " %02x", *p++);
if (len > 16)
fprintf(stderr, " ...");
fprintf(stderr, "\n");
}
return;
}
void adiv5_mem_write_sized( ADIv5_AP_t *ap, uint32_t dest, const void *src,
size_t len, enum align align)
{
if (cl_debuglevel & BMP_DEBUG_TARGET) {
fprintf(stderr, "ap_mem_write_sized @ %" PRIx32 " len %" PRIx32
", align %d:", dest, (uint32_t)len, 1 << align);
uint8_t *p = (uint8_t *) src;
unsigned int i = len;
if (i > 16)
i = 16;
while (i--)
fprintf(stderr, " %02x", *p++);
if (len > 16)
fprintf(stderr, " ...");
fprintf(stderr, "\n");
}
return ap->dp->mem_write_sized(ap, dest, src, len, align);
}
void adiv5_dp_abort(struct ADIv5_DP_s *dp, uint32_t abort)
{
DEBUG_TARGET("Abort: %08" PRIx32 "\n", abort);
return dp->abort(dp, abort);
}

View File

@ -0,0 +1,43 @@
#ifndef __PLATFORM_H
#define __PLATFORM_H
#include "timing.h"
char *platform_ident(void);
void platform_buffer_flush(void);
#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,
BMP_TYPE_STLINKV2,
BMP_TYPE_LIBFTDI,
BMP_TYPE_CMSIS_DAP,
BMP_TYPE_JLINK
} bmp_type_t;
void gdb_ident(char *p, int count);
#endif

View File

@ -0,0 +1,187 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2008 Black Sphere Technologies Ltd.
* Written by Gareth McMullin <gareth@blacksphere.co.nz>
* Modified by Dave Marples <dave@marples.net>
* Modified (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/>.
*/
/* Low level JTAG implementation using FT2232 with libftdi.
*
* Issues:
* Should share interface with swdptap.c or at least clean up...
*/
#include "general.h"
#include <unistd.h>
#include <assert.h>
#include "remote.h"
#include "jtagtap.h"
#include "bmp_remote.h"
static void jtagtap_reset(void);
static void jtagtap_tms_seq(uint32_t MS, int ticks);
static void jtagtap_tdi_tdo_seq(
uint8_t *DO, const uint8_t final_tms, const uint8_t *DI, int ticks);
static void jtagtap_tdi_seq(
const uint8_t final_tms, const uint8_t *DI, int ticks);
static uint8_t jtagtap_next(uint8_t dTMS, uint8_t dTDI);
int remote_jtagtap_init(jtag_proc_t *jtag_proc)
{
uint8_t construct[REMOTE_MAX_MSG_SIZE];
int s;
s = snprintf((char *)construct, REMOTE_MAX_MSG_SIZE, "%s",
REMOTE_JTAG_INIT_STR);
platform_buffer_write(construct, s);
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((!s) || (construct[0] == REMOTE_RESP_ERR)) {
DEBUG_WARN("jtagtap_init failed, error %s\n",
s ? (char *)&(construct[1]) : "unknown");
exit(-1);
}
jtag_proc->jtagtap_reset = jtagtap_reset;
jtag_proc->jtagtap_next =jtagtap_next;
jtag_proc->jtagtap_tms_seq = jtagtap_tms_seq;
jtag_proc->jtagtap_tdi_tdo_seq = jtagtap_tdi_tdo_seq;
jtag_proc->jtagtap_tdi_seq = jtagtap_tdi_seq;
return 0;
}
/* See remote.c/.h for protocol information */
static void jtagtap_reset(void)
{
uint8_t construct[REMOTE_MAX_MSG_SIZE];
int s;
s = snprintf((char *)construct, REMOTE_MAX_MSG_SIZE, "%s",
REMOTE_JTAG_RESET_STR);
platform_buffer_write(construct, s);
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((!s) || (construct[0] == REMOTE_RESP_ERR)) {
DEBUG_WARN("jtagtap_reset failed, error %s\n",
s ? (char *)&(construct[1]) : "unknown");
exit(-1);
}
}
static void jtagtap_tms_seq(uint32_t MS, int ticks)
{
uint8_t construct[REMOTE_MAX_MSG_SIZE];
int s;
s = snprintf((char *)construct, REMOTE_MAX_MSG_SIZE,
REMOTE_JTAG_TMS_STR, ticks, MS);
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);
}
}
/* 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;
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);
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;
}
}
}
}
static void jtagtap_tdi_seq(
const uint8_t final_tms, const uint8_t *DI, int ticks)
{
return jtagtap_tdi_tdo_seq(NULL, final_tms, DI, ticks);
}
static uint8_t jtagtap_next(uint8_t dTMS, uint8_t dTDI)
{
uint8_t construct[REMOTE_MAX_MSG_SIZE];
int s;
s = snprintf((char *)construct, REMOTE_MAX_MSG_SIZE, REMOTE_JTAG_NEXT,
dTMS ? '1' : '0', dTDI ? '1' : '0');
platform_buffer_write(construct, s);
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((!s) || (construct[0] == REMOTE_RESP_ERR)) {
DEBUG_WARN("jtagtap_next failed, error %s\n",
s ? (char *)&(construct[1]) : "unknown");
exit(-1);
}
return remotehston(-1, (char *)&construct[1]);
}

View File

@ -0,0 +1,139 @@
/*
* This file is part of the Black Magic Debug project.
*
* Written by Gareth McMullin <gareth@blacksphere.co.nz>
* Modified by Dave Marples <dave@marples.net>
* 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
* 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/>.
*/
/* MPSSE bit-banging SW-DP interface over FTDI with loop unrolled.
* Speed is sensible.
*/
#include <stdio.h>
#include <assert.h>
#include "general.h"
#include "remote.h"
#include "bmp_remote.h"
static bool swdptap_seq_in_parity(uint32_t *res, int ticks);
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(ADIv5_DP_t *dp)
{
DEBUG_WIRE("remote_swdptap_init\n");
uint8_t construct[REMOTE_MAX_MSG_SIZE];
int s;
s = sprintf((char *)construct,"%s", REMOTE_SWDP_INIT_STR);
platform_buffer_write(construct, s);
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((!s) || (construct[0] == REMOTE_RESP_ERR)) {
DEBUG_WARN("swdptap_init failed, error %s\n",
s ? (char *)&(construct[1]) : "unknown");
exit(-1);
}
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;
}
static bool swdptap_seq_in_parity(uint32_t *res, int ticks)
{
uint8_t construct[REMOTE_MAX_MSG_SIZE];
int s;
s = sprintf((char *)construct, REMOTE_SWDP_IN_PAR_STR, ticks);
platform_buffer_write(construct, s);
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((s<2) || (construct[0] == REMOTE_RESP_ERR)) {
DEBUG_WARN("swdptap_seq_in_parity failed, error %s\n",
s ? (char *)&(construct[1]) : "short response");
exit(-1);
}
*res=remotehston(-1, (char *)&construct[1]);
DEBUG_PROBE("swdptap_seq_in_parity %2d ticks: %08" PRIx32 " %s\n",
ticks, *res, (construct[0] != REMOTE_RESP_OK) ? "ERR" : "OK");
return (construct[0] != REMOTE_RESP_OK);
}
static uint32_t swdptap_seq_in(int ticks)
{
uint8_t construct[REMOTE_MAX_MSG_SIZE];
int s;
s = sprintf((char *)construct, REMOTE_SWDP_IN_STR, ticks);
platform_buffer_write(construct,s);
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((s<2) || (construct[0] == REMOTE_RESP_ERR)) {
DEBUG_WARN("swdptap_seq_in failed, error %s\n",
s ? (char *)&(construct[1]) : "short response");
exit(-1);
}
uint32_t res = remotehston(-1,(char *)&construct[1]);
DEBUG_PROBE("swdptap_seq_in %2d ticks: %08" PRIx32 "\n",
ticks, res);
return res;
}
static void swdptap_seq_out(uint32_t MS, int ticks)
{
uint8_t construct[REMOTE_MAX_MSG_SIZE];
int s;
DEBUG_PROBE("swdptap_seq_out %2d ticks: %08" PRIx32 "\n",
ticks, MS);
s = sprintf((char *)construct,REMOTE_SWDP_OUT_STR, ticks, MS);
platform_buffer_write(construct, s);
s=platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((s < 1) || (construct[0] == REMOTE_RESP_ERR)) {
DEBUG_WARN("swdptap_seq_out failed, error %s\n",
s ? (char *)&(construct[1]) : "short response");
exit(-1);
}
}
static void swdptap_seq_out_parity(uint32_t MS, int ticks)
{
uint8_t construct[REMOTE_MAX_MSG_SIZE];
int s;
DEBUG_PROBE("swdptap_seq_out_parity %2d ticks: %08" PRIx32 "\n",
ticks, MS);
s = sprintf((char *)construct, REMOTE_SWDP_OUT_PAR_STR, ticks, MS);
platform_buffer_write(construct, s);
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((s < 1) || (construct[1] == REMOTE_RESP_ERR)){
DEBUG_WARN("swdptap_seq_out_parity failed, error %s\n",
s ? (char *)&(construct[2]) : "short response");
exit(-1);
}
}

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

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,57 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2019 Uwe Bonnes
*
* 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/>.
*/
#if !defined(__STLINKV2_H_)
#define STLINK_ERROR_FAIL -1
#define STLINK_ERROR_OK 0
#define STLINK_ERROR_WAIT 1
#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);
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,10 +4,10 @@ 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,--defsym,_stack=0x20006000 \
LDFLAGS = -lopencm3_stm32f4 \
-Wl,-T,platforms/stm32/f4discovery.ld -nostartfiles -lc -lnosys \
-Wl,-Map=mapfile -mthumb -mcpu=cortex-m4 -Wl,-gc-sections \
-mfloat-abi=hard -mfpu=fpv4-sp-d16 \
@ -16,17 +16,18 @@ LDFLAGS = -lopencm3_stm32f4 -Wl,--defsym,_stack=0x20006000 \
VPATH += platforms/stm32
SRC += cdcacm.c \
traceswodecode.c \
traceswo.c \
usbuart.c \
serialno.c \
timing.c \
timing_stm32.c \
all: blackmagic.bin blackmagic.hex blackmagic.dfu
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 @@ make PROBE_HOST=hydrabus
How to Flash the firmware with Windows
========================================
* After build:
* 1) Download files from https://github.com/bvernoux/hydrafw/tree/master/update_fw_dfu_usb_hydrafw
* 1) Download files from https://github.com/hydrabus/hydrafw/tree/master/utils/windows_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) Run the command `DfuSeCommand.exe -c --de 0 -d --fn .\src\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>
@ -46,7 +46,7 @@ void platform_init(void)
scb_reset_core();
}
rcc_clock_setup_hse_3v3(&hse_8mhz_3v3[CLOCK_3V3_48MHZ]);
rcc_clock_setup_pll(&rcc_hse_8mhz_3v3[RCC_CLOCK_3V3_168MHZ]);
/* Enable peripherals */
rcc_peripheral_enable_clock(&RCC_AHB2ENR, RCC_AHB2ENR_OTGFSEN);
@ -63,7 +63,9 @@ void platform_init(void)
GPIOC_OSPEEDR |= 0xA20;
gpio_mode_setup(JTAG_PORT, GPIO_MODE_OUTPUT,
GPIO_PUPD_NONE,
TMS_PIN | TCK_PIN | TDI_PIN);
TCK_PIN | TDI_PIN);
gpio_mode_setup(JTAG_PORT, GPIO_MODE_INPUT,
GPIO_PUPD_NONE, TMS_PIN);
gpio_mode_setup(TDO_PORT, GPIO_MODE_INPUT,
GPIO_PUPD_NONE,
@ -83,7 +85,7 @@ bool platform_srst_get_val(void) { return false; }
const char *platform_target_voltage(void)
{
return "ABSENT!";
return NULL;
}
void platform_request_boot(void)
@ -103,4 +105,3 @@ void platform_request_boot(void)
SYSCFG_MEMRM &= ~3;
SYSCFG_MEMRM |= 1;
}

View File

@ -28,15 +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 DFU_IFACE_STRING "@Internal Flash /0x08000000/1*016Ka,3*016Kg,1*064Kg,7*128Kg"
#define PLATFORM_IDENT " (HydraBus))"
/* Important pin mappings for STM32 implementation:
*
@ -94,49 +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 DEBUG(...)
#define TRACE_ISR(x) tim3_isr(x)
#define gpio_set_val(port, pin, val) do { \
if(val) \
@ -154,11 +155,37 @@ static inline int platform_hwversion(void)
return 0;
}
/* Use newlib provided integer only stdio functions */
#define sscanf siscanf
#define sprintf siprintf
#define vasprintf vasiprintf
#define snprintf sniprintf
/*
* Use newlib provided integer only stdio functions
*/
/* sscanf */
#ifdef sscanf
#undef sscanf
#define sscanf siscanf
#else
#define sscanf siscanf
#endif
/* sprintf */
#ifdef sprintf
#undef sprintf
#define sprintf siprintf
#else
#define sprintf siprintf
#endif
/* vasprintf */
#ifdef vasprintf
#undef vasprintf
#define vasprintf vasiprintf
#else
#define vasprintf vasiprintf
#endif
/* snprintf */
#ifdef snprintf
#undef snprintf
#define snprintf sniprintf
#else
#define snprintf sniprintf
#endif
#endif

View File

@ -2,6 +2,8 @@ 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
@ -15,7 +17,11 @@ ifeq ($(CONSOLE_NO_AUTO_CRLF), 1)
CFLAGS += -DCONSOLE_NO_AUTO_CRLF
endif
CFLAGS += -mthumb -mcpu=cortex-m0plus \
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
@ -27,7 +33,7 @@ LDFLAGS = -mthumb -mcpu=cortex-m0plus -msoft-float -nostartfiles -lc \
ifeq ($(ENABLE_DEBUG), 1)
LDFLAGS += --specs=rdimon.specs
else
LDFLAGS += --specs=nosys.specs
LDFLAGS += --specs=nano.specs
endif
VPATH += platforms/samd
@ -42,7 +48,7 @@ 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: usbdfu.o
blackmagic_dfu.elf: usbdfu.o
@echo " LD $@"
$(Q)$(CC) $^ -o $@ $(LDFLAGS)

View File

@ -236,6 +236,16 @@ void platform_delay(uint32_t 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;
@ -243,8 +253,7 @@ const char *platform_target_voltage(void)
adc_start();
while (!(1&(ADC->intflag)));
voltage = ((485*adc_result())>>12); /* 330 without divider, 485 with it */
voltage = platform_target_voltage_sense();
out[0] = '0' + (char)(voltage/100);
out[2] = '0' + (char)((voltage/10) % 10);
@ -252,7 +261,7 @@ const char *platform_target_voltage(void)
return out;
}
char *serialno_read(char *s)
char *serial_no_read(char *s)
{
#ifdef CUSTOM_SER
s[0] = 'J';
@ -262,11 +271,12 @@ char *serialno_read(char *s)
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';
@ -322,3 +332,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

@ -36,16 +36,18 @@
#define PLATFORM_HAS_BOOTLOADER
#define PLATFORM_HAS_PRINTSERIAL
#define BOARD_IDENT "Black Magic Probe (SAMD), (Firmware " FIRMWARE_VERSION ")"
//#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_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

View File

@ -143,10 +143,8 @@ static const char *usb_strings[] = {
//"@Internal Flash /0x00000000/1*0016Ka,15*0016Kg",
};
static uint8_t usbdfu_getstatus(usbd_device *usbd_dev, uint32_t *bwPollTimeout)
static uint8_t usbdfu_getstatus(uint32_t *bwPollTimeout)
{
(void)usbd_dev;
switch (usbdfu_state) {
case STATE_DFU_DNLOAD_SYNC:
usbdfu_state = STATE_DFU_DNBUSY;
@ -177,11 +175,13 @@ static void usbdfu_getstatus_complete(usbd_device *usbd_dev, struct usb_setup_da
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) *
@ -225,9 +225,12 @@ static void usbdfu_getstatus_complete(usbd_device *usbd_dev, struct usb_setup_da
}
}
static int usbdfu_control_request(usbd_device *usbd_dev, struct usb_setup_data *req, uint8_t **buf,
uint16_t *len, void (**complete)(usbd_device *usbd_dev, struct usb_setup_data *req))
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. */
@ -258,7 +261,7 @@ static int usbdfu_control_request(usbd_device *usbd_dev, struct usb_setup_data *
return 0;
case DFU_GETSTATUS: {
uint32_t bwPollTimeout = 0; /* 24-bit integer in DFU class spec */
(*buf)[0] = usbdfu_getstatus(usbd_dev, &bwPollTimeout);
(*buf)[0] = usbdfu_getstatus(&bwPollTimeout);
(*buf)[1] = bwPollTimeout & 0xFF;
(*buf)[2] = (bwPollTimeout >> 8) & 0xFF;
(*buf)[3] = (bwPollTimeout >> 16) & 0xFF;

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();
@ -62,7 +61,7 @@ platform_init(void)
gpio_enable_ahb_aperture();
gpio_mode_setup(TMS_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, TMS_PIN);
gpio_mode_setup(TMS_PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, TMS_PIN);
gpio_mode_setup(TCK_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, TCK_PIN);
gpio_mode_setup(TDI_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, TDI_PIN);
gpio_mode_setup(TDO_PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, TDO_PIN);
@ -115,23 +114,23 @@ void platform_delay(uint32_t ms)
const char *platform_target_voltage(void)
{
return "not supported";
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
@ -68,7 +65,7 @@ extern uint8_t running_status;
gpio_set_output_config(SWDIO_PORT, GPIO_OTYPE_PP, GPIO_DRIVE_2MA, SWDIO_PIN); \
}
extern usbd_driver lm4f_usb_driver;
extern const usbd_driver lm4f_usb_driver;
#define USB_DRIVER lm4f_usb_driver
#define USB_IRQ NVIC_USB0_IRQ
#define USB_ISR usb0_isr
@ -98,8 +95,6 @@ extern usbd_driver lm4f_usb_driver;
#define vasprintf vasiprintf
#define snprintf sniprintf
#define DEBUG(...)
#define SET_RUN_STATE(state) {running_status = (state);}
#define SET_IDLE_STATE(state) {}
#define SET_ERROR_STATE(state) SET_IDLE_STATE(state)

View File

@ -1,4 +0,0 @@
CFLAGS += -DLIBFTDI
LDFLAGS += -lftdi -lusb
SRC += timing.c \

View File

@ -1,123 +0,0 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2011 Black Sphere Technologies Ltd.
* 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
* (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/>.
*/
/* This file implements a transparent channel over which the GDB Remote
* Serial Debugging protocol is implemented. This implementation for Linux
* uses a TCP server on port 2000.
*/
#include <stdio.h>
#ifndef WIN32
# include <sys/socket.h>
# include <netinet/in.h>
# include <netinet/tcp.h>
# include <sys/select.h>
#else
# include <winsock2.h>
# include <windows.h>
# include <ws2tcpip.h>
#endif
#include <assert.h>
#include "general.h"
#include "gdb_if.h"
static int gdb_if_serv, gdb_if_conn;
int gdb_if_init(void)
{
#ifdef WIN32
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
#endif
struct sockaddr_in addr;
int opt;
addr.sin_family = AF_INET;
addr.sin_port = htons(2000);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
assert((gdb_if_serv = socket(PF_INET, SOCK_STREAM, 0)) != -1);
opt = 1;
assert(setsockopt(gdb_if_serv, SOL_SOCKET, SO_REUSEADDR, (void*)&opt, sizeof(opt)) != -1);
assert(setsockopt(gdb_if_serv, IPPROTO_TCP, TCP_NODELAY, (void*)&opt, sizeof(opt)) != -1);
assert(bind(gdb_if_serv, (void*)&addr, sizeof(addr)) != -1);
assert(listen(gdb_if_serv, 1) != -1);
DEBUG("Listening on TCP:2000\n");
return 0;
}
unsigned char gdb_if_getchar(void)
{
unsigned char ret;
int i = 0;
while(i <= 0) {
if(gdb_if_conn <= 0) {
gdb_if_conn = accept(gdb_if_serv, NULL, NULL);
DEBUG("Got connection\n");
}
i = recv(gdb_if_conn, (void*)&ret, 1, 0);
if(i <= 0) {
gdb_if_conn = -1;
DEBUG("Dropped broken connection\n");
/* Return '+' in case we were waiting for an ACK */
return '+';
}
}
return ret;
}
unsigned char gdb_if_getchar_to(int timeout)
{
fd_set fds;
struct timeval tv;
if(gdb_if_conn == -1) return -1;
tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000;
FD_ZERO(&fds);
FD_SET(gdb_if_conn, &fds);
if(select(gdb_if_conn+1, &fds, NULL, NULL, &tv) > 0)
return gdb_if_getchar();
return -1;
}
void gdb_if_putchar(unsigned char c, int flush)
{
static uint8_t buf[2048];
static int bufsize = 0;
if (gdb_if_conn > 0) {
buf[bufsize++] = c;
if (flush || (bufsize == sizeof(buf))) {
send(gdb_if_conn, buf, bufsize, 0);
bufsize = 0;
}
}
}

View File

@ -1,204 +0,0 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2008 Black Sphere Technologies Ltd.
* 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
* (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/>.
*/
/* Low level JTAG implementation using FT2232 with libftdi.
*
* Issues:
* This code is old, rotten and unsupported.
* Magic numbers everywhere.
* Should share interface with swdptap.c or at least clean up...
*/
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <ftdi.h>
#include "general.h"
#define PROVIDE_GENERIC_TAP_SEQ
//#define PROVIDE_GENERIC_TAP_TMS_SEQ
//#define PROVIDE_GENERIC_TAP_TDI_TDO_SEQ
//#define PROVIDE_GENERIC_TAP_TDI_SEQ
#include "jtagtap.h"
#define ALL_ZERO 0xA0
#define TCK 0x01
#define TDI 0x02
#define TDO 0x04
#define TMS 0x08
#define nSRST 0x20
int jtagtap_init(void)
{
assert(ftdic != NULL);
/* Go to JTAG mode for SWJ-DP */
for (int i = 0; i <= 50; i++)
jtagtap_next(1, 0); /* Reset SW-DP */
jtagtap_tms_seq(0xE73C, 16); /* SWD to JTAG sequence */
jtagtap_soft_reset();
return 0;
}
void jtagtap_reset(void)
{
jtagtap_soft_reset();
}
#ifndef PROVIDE_GENERIC_TAP_TMS_SEQ
void
jtagtap_tms_seq(uint32_t MS, int ticks)
{
uint8_t tmp[3] = "\x4B";
while(ticks >= 0) {
//jtagtap_next(MS & 1, 1);
tmp[1] = ticks<7?ticks-1:6;
tmp[2] = 0x80 | (MS & 0x7F);
// assert(ftdi_write_data(ftdic, tmp, 3) == 3);
platform_buffer_write(tmp, 3);
MS >>= 7; ticks -= 7;
}
}
#endif
#ifndef PROVIDE_GENERIC_TAP_TDI_SEQ
void
jtagtap_tdi_seq(const uint8_t final_tms, const uint8_t *DI, int ticks)
{
uint8_t *tmp;
int index = 0;
int rticks;
if(!ticks) return;
if(final_tms) ticks--;
rticks = ticks & 7;
ticks >>= 3;
tmp = alloca(ticks + 9);
if(ticks) {
tmp[index++] = 0x19;
tmp[index++] = ticks - 1;
tmp[index++] = 0;
while(ticks--) tmp[index++] = *DI++;
}
if(rticks) {
tmp[index++] = 0x1B;
tmp[index++] = rticks - 1;
tmp[index++] = *DI;
}
if(final_tms) {
tmp[index++] = 0x4B;
tmp[index++] = 0;
tmp[index++] = (*DI)>>rticks?0x81:0x01;
}
// assert(ftdi_write_data(ftdic, tmp, index) == index);
platform_buffer_write(tmp, index);
}
#endif
#ifndef PROVIDE_GENERIC_TAP_TDI_TDO_SEQ
void
jtagtap_tdi_tdo_seq(uint8_t *DO, const uint8_t final_tms, const uint8_t *DI, int ticks)
{
uint8_t *tmp;
int index = 0, rsize;
int rticks;
if(!ticks) return;
// printf("ticks: %d\n", ticks);
if(final_tms) ticks--;
rticks = ticks & 7;
ticks >>= 3;
tmp = alloca(ticks + 9);
rsize = ticks;
if(ticks) {
tmp[index++] = 0x39;
tmp[index++] = ticks - 1;
tmp[index++] = 0;
while(ticks--) tmp[index++] = *DI++;
}
if(rticks) {
rsize++;
tmp[index++] = 0x3B;
tmp[index++] = rticks - 1;
tmp[index++] = *DI;
}
if(final_tms) {
rsize++;
tmp[index++] = 0x6B;
tmp[index++] = 0;
tmp[index++] = (*DI)>>rticks?0x81:0x01;
}
// assert(ftdi_write_data(ftdic, tmp, index) == index);
platform_buffer_write(tmp, index);
// index = 0;
// while((index += ftdi_read_data(ftdic, tmp + index, rsize-index)) != rsize);
platform_buffer_read(tmp, rsize);
/*for(index = 0; index < rsize; index++)
printf("%02X ", tmp[index]);
printf("\n");*/
index = 0;
if(final_tms) rsize--;
while(rsize--) {
/*if(rsize) printf("%02X ", tmp[index]);*/
*DO++ = tmp[index++];
}
if(final_tms) {
rticks++;
*(--DO) >>= 1;
*DO |= tmp[index] & 0x80;
} else DO--;
if(rticks) {
*DO >>= (8-rticks);
}
/*printf("%02X\n", *DO);*/
}
#endif
uint8_t jtagtap_next(uint8_t dTMS, uint8_t dTDI)
{
uint8_t ret;
uint8_t tmp[3] = "\x6B\x00\x00";
tmp[2] = (dTDI?0x80:0) | (dTMS?0x01:0);
// assert(ftdi_write_data(ftdic, tmp, 3) == 3);
// while(ftdi_read_data(ftdic, &ret, 1) != 1);
platform_buffer_write(tmp, 3);
platform_buffer_read(&ret, 1);
ret &= 0x80;
// DEBUG("jtagtap_next(TMS = %d, TDI = %d) = %02X\n", dTMS, dTDI, ret);
return ret;
}

View File

@ -1,293 +0,0 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2011 Black Sphere Technologies Ltd.
* 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
* (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 "gdb_if.h"
#include "version.h"
#include <assert.h>
#include <unistd.h>
#include <sys/time.h>
struct ftdi_context *ftdic;
#define BUF_SIZE 4096
static uint8_t outbuf[BUF_SIZE];
static uint16_t bufptr = 0;
static struct cable_desc_s {
int vendor;
int product;
int interface;
uint8_t dbus_data;
uint8_t dbus_ddr;
uint8_t cbus_data;
uint8_t cbus_ddr;
char *description;
char * name;
} cable_desc[] = {
{
.vendor = 0x0403,
.product = 0x6010,
.interface = INTERFACE_A,
.dbus_data = 0x08,
.dbus_ddr = 0x1B,
.description = "FLOSS-JTAG",
.name = "flossjtag"
},
{
.vendor = 0x0403,
.product = 0x6010,
.interface = INTERFACE_A,
.dbus_data = 0x08,
.dbus_ddr = 0x1B,
.description = "FTDIJTAG",
.name = "ftdijtag"
},
{
.vendor = 0x15b1,
.product = 0x0003,
.interface = INTERFACE_A,
.dbus_data = 0x08,
.dbus_ddr = 0x1B,
.name = "olimex"
},
{
.vendor = 0x0403,
.product = 0xbdc8,
.interface = INTERFACE_A,
.dbus_data = 0x08,
.dbus_ddr = 0x1B,
.name = "turtelizer"
},
{
.vendor = 0x0403,
.product = 0xbdc8,
.interface = INTERFACE_A,
.dbus_data = 0x08,
.dbus_ddr = 0x1B,
.name = "jtaghs1"
},
{
.vendor = 0x0403,
.product = 0xbdc8,
.interface = INTERFACE_A,
.dbus_data = 0xA8,
.dbus_ddr = 0xAB,
.name = "ftdi"
},
{
.vendor = 0x0403,
.product = 0x6014,
.interface = INTERFACE_A,
.dbus_data = 0x88,
.dbus_ddr = 0x8B,
.cbus_data = 0x20,
.cbus_ddr = 0x3f,
.name = "digilent"
},
{
.vendor = 0x0403,
.product = 0x6014,
.interface = INTERFACE_A,
.dbus_data = 0x08,
.dbus_ddr = 0x0B,
.name = "ft232h"
},
{
.vendor = 0x0403,
.product = 0x6011,
.interface = INTERFACE_A,
.dbus_data = 0x08,
.dbus_ddr = 0x0B,
.name = "ft4232h"
},
{
.vendor = 0x15ba,
.product = 0x002b,
.interface = INTERFACE_A,
.dbus_data = 0x08,
.dbus_ddr = 0x1B,
.cbus_data = 0x00,
.cbus_ddr = 0x08,
.name = "arm-usb-ocd-h"
},
};
void platform_init(int argc, char **argv)
{
int err;
int c;
unsigned index = 0;
char *serial = NULL;
char * cablename = "ftdi";
uint8_t ftdi_init[9] = {TCK_DIVISOR, 0x01, 0x00, SET_BITS_LOW, 0,0,
SET_BITS_HIGH, 0,0};
while((c = getopt(argc, argv, "c:s:")) != -1) {
switch(c) {
case 'c':
cablename = optarg;
break;
case 's':
serial = optarg;
break;
}
}
for(index = 0; index < sizeof(cable_desc)/sizeof(cable_desc[0]);
index++)
if (strcmp(cable_desc[index].name, cablename) == 0)
break;
if (index == sizeof(cable_desc)/sizeof(cable_desc[0])){
fprintf(stderr, "No cable matching %s found\n",cablename);
exit(-1);
}
if (cable_desc[index].dbus_data)
ftdi_init[4]= cable_desc[index].dbus_data;
if (cable_desc[index].dbus_ddr)
ftdi_init[5]= cable_desc[index].dbus_ddr;
if (cable_desc[index].cbus_data)
ftdi_init[7]= cable_desc[index].cbus_data;
if(cable_desc[index].cbus_ddr)
ftdi_init[8]= cable_desc[index].cbus_ddr;
printf("\nBlack Magic Probe (" FIRMWARE_VERSION ")\n");
printf("Copyright (C) 2015 Black Sphere Technologies Ltd.\n");
printf("License GPLv3+: GNU GPL version 3 or later "
"<http://gnu.org/licenses/gpl.html>\n\n");
if(ftdic) {
ftdi_usb_close(ftdic);
ftdi_free(ftdic);
ftdic = NULL;
}
if((ftdic = ftdi_new()) == NULL) {
fprintf(stderr, "ftdi_new: %s\n",
ftdi_get_error_string(ftdic));
abort();
}
if((err = ftdi_set_interface(ftdic, cable_desc[index].interface)) != 0) {
fprintf(stderr, "ftdi_set_interface: %d: %s\n",
err, ftdi_get_error_string(ftdic));
abort();
}
if((err = ftdi_usb_open_desc(
ftdic, cable_desc[index].vendor, cable_desc[index].product,
cable_desc[index].description, serial)) != 0) {
fprintf(stderr, "unable to open ftdi device: %d (%s)\n",
err, ftdi_get_error_string(ftdic));
abort();
}
if((err = ftdi_set_latency_timer(ftdic, 1)) != 0) {
fprintf(stderr, "ftdi_set_latency_timer: %d: %s\n",
err, ftdi_get_error_string(ftdic));
abort();
}
if((err = ftdi_set_baudrate(ftdic, 1000000)) != 0) {
fprintf(stderr, "ftdi_set_baudrate: %d: %s\n",
err, ftdi_get_error_string(ftdic));
abort();
}
if((err = ftdi_usb_purge_buffers(ftdic)) != 0) {
fprintf(stderr, "ftdi_set_baudrate: %d: %s\n",
err, ftdi_get_error_string(ftdic));
abort();
}
if((err = ftdi_write_data_set_chunksize(ftdic, BUF_SIZE)) != 0) {
fprintf(stderr, "ftdi_write_data_set_chunksize: %d: %s\n",
err, ftdi_get_error_string(ftdic));
abort();
}
if((err = ftdi_set_bitmode(ftdic, 0xAB, BITMODE_MPSSE)) != 0) {
fprintf(stderr, "ftdi_set_bitmode: %d: %s\n",
err, ftdi_get_error_string(ftdic));
abort();
}
assert(ftdi_write_data(ftdic, ftdi_init, 9) == 9);
assert(gdb_if_init() == 0);
}
void platform_srst_set_val(bool assert)
{
(void)assert;
platform_buffer_flush();
}
bool platform_srst_get_val(void) { return false; }
void platform_buffer_flush(void)
{
assert(ftdi_write_data(ftdic, outbuf, bufptr) == bufptr);
// printf("FT2232 platform_buffer flush: %d bytes\n", bufptr);
bufptr = 0;
}
int platform_buffer_write(const uint8_t *data, int size)
{
if((bufptr + size) / BUF_SIZE > 0) platform_buffer_flush();
memcpy(outbuf + bufptr, data, size);
bufptr += size;
return size;
}
int platform_buffer_read(uint8_t *data, int size)
{
int index = 0;
platform_buffer_flush();
while((index += ftdi_read_data(ftdic, data + index, size-index)) != size);
return size;
}
#ifdef WIN32
#warning "This vasprintf() is dubious!"
int vasprintf(char **strp, const char *fmt, va_list ap)
{
int size = 128, ret = 0;
*strp = malloc(size);
while(*strp && ((ret = vsnprintf(*strp, size, fmt, ap)) == size))
*strp = realloc(*strp, size <<= 1);
return ret;
}
#endif
const char *platform_target_voltage(void)
{
return "not supported";
}
void platform_delay(uint32_t ms)
{
usleep(ms * 1000);
}
uint32_t platform_time_ms(void)
{
struct timeval tv;
gettimeofday(&tv, NULL);
return (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
}

View File

@ -1,95 +0,0 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2011 Black Sphere Technologies Ltd.
* 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
* (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/>.
*/
/* Quick hack for bit-banging SW-DP interface over FT2232.
* Intended as proof of concept, not for production.
*/
#include <stdio.h>
#include <assert.h>
#include <ftdi.h>
#include "general.h"
#include "swdptap.h"
static uint8_t olddir = 0;
int swdptap_init(void)
{
int err;
assert(ftdic != NULL);
if((err = ftdi_set_bitmode(ftdic, 0xAB, BITMODE_BITBANG)) != 0) {
fprintf(stderr, "ftdi_set_bitmode: %d: %s\n",
err, ftdi_get_error_string(ftdic));
abort();
}
assert(ftdi_write_data(ftdic, (void*)"\xAB\xA8", 2) == 2);
olddir = 0;
return 0;
}
static void swdptap_turnaround(uint8_t dir)
{
platform_buffer_flush();
if (dir == olddir)
return;
olddir = dir;
if(dir) /* SWDIO goes to input */
assert(ftdi_set_bitmode(ftdic, 0xA3, BITMODE_BITBANG) == 0);
/* One clock cycle */
ftdi_write_data(ftdic, (void *)"\xAB\xA8", 2);
if(!dir) /* SWDIO goes to output */
assert(ftdi_set_bitmode(ftdic, 0xAB, BITMODE_BITBANG) == 0);
}
bool swdptap_bit_in(void)
{
uint8_t ret;
swdptap_turnaround(1);
ftdi_read_pins(ftdic, &ret);
ret &= 0x08;
ftdi_write_data(ftdic, (void *)"\xA1\xA0", 2);
return ret;
}
void swdptap_bit_out(bool val)
{
uint8_t buf[3] = "\xA0\xA1\xA0";
swdptap_turnaround(0);
if (val) {
for(int i = 0; i < 3; i++)
buf[i] |= 0x08;
}
platform_buffer_write(buf, 3);
}

View File

@ -4,9 +4,9 @@ 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) -lopencm3_stm32f1 -Wl,--defsym,_stack=0x20005000 \
LDFLAGS_BOOT := $(LDFLAGS) --specs=nano.specs -lopencm3_stm32f1 \
-Wl,-T,platforms/stm32/blackmagic.ld -nostartfiles -lc \
-Wl,-Map=mapfile -mthumb -mcpu=cortex-m3 -Wl,-gc-sections \
-L../libopencm3/lib
@ -21,6 +21,7 @@ endif
VPATH += platforms/stm32
SRC += cdcacm.c \
traceswodecode.c \
traceswo.c \
usbuart.c \
serialno.c \
@ -29,10 +30,9 @@ SRC += cdcacm.c \
all: blackmagic.bin blackmagic_dfu.bin blackmagic_dfu.hex
blackmagic_dfu: 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)
host_clean:
-$(Q)$(RM) -f blackmagic.bin blackmagic_dfu blackmagic_dfu.bin blackmagic_dfu.hex
-$(Q)$(RM) blackmagic.bin blackmagic_dfu blackmagic_dfu.bin blackmagic_dfu.hex

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