10 Commits

Author SHA1 Message Date
mawei 753c5facb0 编辑launch_openpilot.sh 2026-06-07 16:42:30 +08:00
mawei 350405ac45 编辑launch_openpilot.sh 2026-06-06 22:18:11 +08:00
mawei 839ebf5078 编辑launch_openpilot.sh 2026-06-06 21:22:51 +08:00
mawei 58b2f941db 编辑c3_client.py 2026-06-06 17:48:41 +08:00
mawei aa026e877b 编辑c3_client.py 2026-06-06 17:30:40 +08:00
mawei 752c837195 编辑c3_client.py 2026-06-06 17:20:05 +08:00
mawei c928aa18a1 编辑c3_client.py 2026-06-06 17:13:47 +08:00
1okko 7fcd1668db 222 2026-06-04 21:21:50 +08:00
1okko b5006d7b6e 2026-5-31 2026-05-31 17:03:18 +08:00
github-actions[bot] 6e2ccc8b15 sunnypilot v2026.002.000
version: sunnypilot v2026.002.000 (staging)
date: 2026-05-27T04:05:25
master commit: dfc3c98b226da57a653daf57131a8a3d66166fcb
2026-05-27 04:05:25 +00:00
532 changed files with 11013 additions and 128996 deletions
+3
View File
@@ -1,3 +1,6 @@
sunnypilot Version 2026.002.000 (2026-xx-xx)
========================
sunnypilot Version 2026.001.000 (2026-05-06) sunnypilot Version 2026.001.000 (2026-05-06)
======================== ========================
* What's Changed (sunnypilot/sunnypilot) * What's Changed (sunnypilot/sunnypilot)
+133 -165
View File
@@ -24173,17 +24173,17 @@ const ::capnp::_::RawSchema s_fc010c40147563b0 = {
2, 8, i_fc010c40147563b0, nullptr, nullptr, { &s_fc010c40147563b0, nullptr, nullptr, 0, 0, nullptr }, false 2, 8, i_fc010c40147563b0, nullptr, nullptr, { &s_fc010c40147563b0, nullptr, nullptr, 0, 0, nullptr }, false
}; };
#endif // !CAPNP_LITE #endif // !CAPNP_LITE
static const ::capnp::_::AlignedData<173> b_c9f73bb1cdf28a6a = { static const ::capnp::_::AlignedData<221> b_c9f73bb1cdf28a6a = {
{ 0, 0, 0, 0, 5, 0, 6, 0, { 0, 0, 0, 0, 5, 0, 6, 0,
106, 138, 242, 205, 177, 59, 247, 201, 106, 138, 242, 205, 177, 59, 247, 201,
24, 0, 0, 0, 1, 0, 5, 0, 24, 0, 0, 0, 1, 0, 4, 0,
176, 99, 117, 20, 64, 12, 1, 252, 176, 99, 117, 20, 64, 12, 1, 252,
6, 0, 7, 0, 0, 0, 0, 0, 6, 0, 7, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
21, 0, 0, 0, 26, 1, 0, 0, 21, 0, 0, 0, 26, 1, 0, 0,
37, 0, 0, 0, 7, 0, 0, 0, 37, 0, 0, 0, 7, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
33, 0, 0, 0, 255, 1, 0, 0, 33, 0, 0, 0, 167, 2, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
108, 111, 103, 46, 99, 97, 112, 110, 108, 111, 103, 46, 99, 97, 112, 110,
@@ -24192,70 +24192,91 @@ static const ::capnp::_::AlignedData<173> b_c9f73bb1cdf28a6a = {
68, 114, 105, 118, 101, 114, 68, 97, 68, 114, 105, 118, 101, 114, 68, 97,
116, 97, 0, 0, 0, 0, 0, 0, 116, 97, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0,
36, 0, 0, 0, 3, 0, 4, 0, 48, 0, 0, 0, 3, 0, 4, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
237, 0, 0, 0, 130, 0, 0, 0, 65, 1, 0, 0, 130, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
236, 0, 0, 0, 3, 0, 1, 0, 64, 1, 0, 0, 3, 0, 1, 0,
8, 1, 0, 0, 2, 0, 1, 0, 92, 1, 0, 0, 2, 0, 1, 0,
1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5, 1, 0, 0, 154, 0, 0, 0, 89, 1, 0, 0, 154, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8, 1, 0, 0, 3, 0, 1, 0, 92, 1, 0, 0, 3, 0, 1, 0,
36, 1, 0, 0, 2, 0, 1, 0, 120, 1, 0, 0, 2, 0, 1, 0,
2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0,
0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
33, 1, 0, 0, 106, 0, 0, 0, 117, 1, 0, 0, 106, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
32, 1, 0, 0, 3, 0, 1, 0, 116, 1, 0, 0, 3, 0, 1, 0,
60, 1, 0, 0, 2, 0, 1, 0, 144, 1, 0, 0, 2, 0, 1, 0,
3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0,
0, 0, 1, 0, 3, 0, 0, 0, 0, 0, 1, 0, 3, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
57, 1, 0, 0, 130, 0, 0, 0, 141, 1, 0, 0, 130, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
56, 1, 0, 0, 3, 0, 1, 0, 140, 1, 0, 0, 3, 0, 1, 0,
84, 1, 0, 0, 2, 0, 1, 0, 168, 1, 0, 0, 2, 0, 1, 0,
4, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 4, 0, 0, 0, 0, 0, 1, 0, 4, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
81, 1, 0, 0, 74, 0, 0, 0, 165, 1, 0, 0, 74, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
80, 1, 0, 0, 3, 0, 1, 0, 164, 1, 0, 0, 3, 0, 1, 0,
92, 1, 0, 0, 2, 0, 1, 0, 176, 1, 0, 0, 2, 0, 1, 0,
8, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 1, 0, 0, 0,
0, 0, 1, 0, 5, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
173, 1, 0, 0, 98, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
172, 1, 0, 0, 3, 0, 1, 0,
184, 1, 0, 0, 2, 0, 1, 0,
6, 0, 0, 0, 2, 0, 0, 0,
0, 0, 1, 0, 6, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
181, 1, 0, 0, 106, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
180, 1, 0, 0, 3, 0, 1, 0,
192, 1, 0, 0, 2, 0, 1, 0,
7, 0, 0, 0, 3, 0, 0, 0,
0, 0, 1, 0, 7, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
189, 1, 0, 0, 114, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
188, 1, 0, 0, 3, 0, 1, 0,
200, 1, 0, 0, 2, 0, 1, 0,
8, 0, 0, 0, 4, 0, 0, 0,
0, 0, 1, 0, 8, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
197, 1, 0, 0, 122, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
196, 1, 0, 0, 3, 0, 1, 0,
208, 1, 0, 0, 2, 0, 1, 0,
9, 0, 0, 0, 5, 0, 0, 0,
0, 0, 1, 0, 9, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
205, 1, 0, 0, 122, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
204, 1, 0, 0, 3, 0, 1, 0,
216, 1, 0, 0, 2, 0, 1, 0,
11, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
6, 86, 193, 227, 157, 60, 112, 217, 233, 90, 130, 19, 150, 159, 147, 218,
89, 1, 0, 0, 90, 0, 0, 0, 213, 1, 0, 0, 90, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7, 0, 0, 0, 7, 0, 0, 0, 10, 0, 0, 0, 7, 0, 0, 0,
0, 0, 1, 0, 13, 0, 0, 0, 0, 0, 1, 0, 13, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
69, 1, 0, 0, 82, 0, 0, 0, 193, 1, 0, 0, 82, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
68, 1, 0, 0, 3, 0, 1, 0, 192, 1, 0, 0, 3, 0, 1, 0,
80, 1, 0, 0, 2, 0, 1, 0, 204, 1, 0, 0, 2, 0, 1, 0,
5, 0, 0, 0, 8, 0, 0, 0,
0, 0, 1, 0, 14, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
77, 1, 0, 0, 130, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
76, 1, 0, 0, 3, 0, 1, 0,
88, 1, 0, 0, 2, 0, 1, 0,
6, 0, 0, 0, 9, 0, 0, 0,
0, 0, 1, 0, 15, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
85, 1, 0, 0, 122, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
84, 1, 0, 0, 3, 0, 1, 0,
96, 1, 0, 0, 2, 0, 1, 0,
102, 97, 99, 101, 79, 114, 105, 101, 102, 97, 99, 101, 79, 114, 105, 101,
110, 116, 97, 116, 105, 111, 110, 0, 110, 116, 97, 116, 105, 111, 110, 0,
14, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0,
@@ -24318,124 +24339,6 @@ static const ::capnp::_::AlignedData<173> b_c9f73bb1cdf28a6a = {
10, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
100, 101, 112, 114, 101, 99, 97, 116,
101, 100, 0, 0, 0, 0, 0, 0,
112, 104, 111, 110, 101, 80, 114, 111,
98, 0, 0, 0, 0, 0, 0, 0,
10, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
10, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
101, 121, 101, 115, 86, 105, 115, 105,
98, 108, 101, 80, 114, 111, 98, 0,
10, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
10, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
101, 121, 101, 115, 67, 108, 111, 115,
101, 100, 80, 114, 111, 98, 0, 0,
10, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
10, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, }
};
::capnp::word const* const bp_c9f73bb1cdf28a6a = b_c9f73bb1cdf28a6a.words;
#if !CAPNP_LITE
static const ::capnp::_::RawSchema* const d_c9f73bb1cdf28a6a[] = {
&s_d9703c9de3c15606,
};
static const uint16_t m_c9f73bb1cdf28a6a[] = {5, 8, 7, 0, 1, 2, 3, 4, 6};
static const uint16_t i_c9f73bb1cdf28a6a[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
const ::capnp::_::RawSchema s_c9f73bb1cdf28a6a = {
0xc9f73bb1cdf28a6a, b_c9f73bb1cdf28a6a.words, 173, d_c9f73bb1cdf28a6a, m_c9f73bb1cdf28a6a,
1, 9, i_c9f73bb1cdf28a6a, nullptr, nullptr, { &s_c9f73bb1cdf28a6a, nullptr, nullptr, 0, 0, nullptr }, false
};
#endif // !CAPNP_LITE
static const ::capnp::_::AlignedData<155> b_d9703c9de3c15606 = {
{ 0, 0, 0, 0, 5, 0, 6, 0,
6, 86, 193, 227, 157, 60, 112, 217,
35, 0, 0, 0, 1, 0, 5, 0,
106, 138, 242, 205, 177, 59, 247, 201,
6, 0, 7, 0, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
21, 0, 0, 0, 114, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
33, 0, 0, 0, 199, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
108, 111, 103, 46, 99, 97, 112, 110,
112, 58, 68, 114, 105, 118, 101, 114,
83, 116, 97, 116, 101, 86, 50, 46,
68, 114, 105, 118, 101, 114, 68, 97,
116, 97, 46, 100, 101, 112, 114, 101,
99, 97, 116, 101, 100, 0, 0, 0,
32, 0, 0, 0, 3, 0, 4, 0,
0, 0, 0, 0, 1, 0, 0, 0,
0, 0, 1, 0, 5, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
209, 0, 0, 0, 98, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
208, 0, 0, 0, 3, 0, 1, 0,
220, 0, 0, 0, 2, 0, 1, 0,
1, 0, 0, 0, 2, 0, 0, 0,
0, 0, 1, 0, 6, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
217, 0, 0, 0, 106, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
216, 0, 0, 0, 3, 0, 1, 0,
228, 0, 0, 0, 2, 0, 1, 0,
2, 0, 0, 0, 3, 0, 0, 0,
0, 0, 1, 0, 7, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
225, 0, 0, 0, 114, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
224, 0, 0, 0, 3, 0, 1, 0,
236, 0, 0, 0, 2, 0, 1, 0,
3, 0, 0, 0, 4, 0, 0, 0,
0, 0, 1, 0, 8, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
233, 0, 0, 0, 122, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
232, 0, 0, 0, 3, 0, 1, 0,
244, 0, 0, 0, 2, 0, 1, 0,
4, 0, 0, 0, 5, 0, 0, 0,
0, 0, 1, 0, 9, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
241, 0, 0, 0, 122, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
240, 0, 0, 0, 3, 0, 1, 0,
252, 0, 0, 0, 2, 0, 1, 0,
6, 0, 0, 0, 6, 0, 0, 0,
0, 0, 1, 0, 10, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
249, 0, 0, 0, 106, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
248, 0, 0, 0, 3, 0, 1, 0,
4, 1, 0, 0, 2, 0, 1, 0,
7, 0, 0, 0, 4, 0, 0, 0,
0, 0, 1, 0, 11, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 0, 0, 82, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 0, 0, 3, 0, 1, 0,
28, 1, 0, 0, 2, 0, 1, 0,
5, 0, 0, 0, 5, 0, 0, 0,
0, 0, 1, 0, 12, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
25, 1, 0, 0, 106, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
24, 1, 0, 0, 3, 0, 1, 0,
52, 1, 0, 0, 2, 0, 1, 0,
108, 101, 102, 116, 69, 121, 101, 80, 108, 101, 102, 116, 69, 121, 101, 80,
114, 111, 98, 0, 0, 0, 0, 0, 114, 111, 98, 0, 0, 0, 0, 0,
10, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,
@@ -24481,6 +24384,71 @@ static const ::capnp::_::AlignedData<155> b_d9703c9de3c15606 = {
10, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
100, 101, 112, 114, 101, 99, 97, 116,
101, 100, 0, 0, 0, 0, 0, 0,
112, 104, 111, 110, 101, 80, 114, 111,
98, 0, 0, 0, 0, 0, 0, 0,
10, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
10, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, }
};
::capnp::word const* const bp_c9f73bb1cdf28a6a = b_c9f73bb1cdf28a6a.words;
#if !CAPNP_LITE
static const ::capnp::_::RawSchema* const d_c9f73bb1cdf28a6a[] = {
&s_da939f9613825ae9,
};
static const uint16_t m_c9f73bb1cdf28a6a[] = {10, 0, 1, 2, 3, 4, 7, 5, 11, 8, 6, 9};
static const uint16_t i_c9f73bb1cdf28a6a[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
const ::capnp::_::RawSchema s_c9f73bb1cdf28a6a = {
0xc9f73bb1cdf28a6a, b_c9f73bb1cdf28a6a.words, 221, d_c9f73bb1cdf28a6a, m_c9f73bb1cdf28a6a,
1, 12, i_c9f73bb1cdf28a6a, nullptr, nullptr, { &s_c9f73bb1cdf28a6a, nullptr, nullptr, 0, 0, nullptr }, false
};
#endif // !CAPNP_LITE
static const ::capnp::_::AlignedData<75> b_da939f9613825ae9 = {
{ 0, 0, 0, 0, 5, 0, 6, 0,
233, 90, 130, 19, 150, 159, 147, 218,
35, 0, 0, 0, 1, 0, 4, 0,
106, 138, 242, 205, 177, 59, 247, 201,
6, 0, 7, 0, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
21, 0, 0, 0, 114, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
33, 0, 0, 0, 175, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
108, 111, 103, 46, 99, 97, 112, 110,
112, 58, 68, 114, 105, 118, 101, 114,
83, 116, 97, 116, 101, 86, 50, 46,
68, 114, 105, 118, 101, 114, 68, 97,
116, 97, 46, 100, 101, 112, 114, 101,
99, 97, 116, 101, 100, 0, 0, 0,
12, 0, 0, 0, 3, 0, 4, 0,
1, 0, 0, 0, 6, 0, 0, 0,
0, 0, 1, 0, 10, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
69, 0, 0, 0, 106, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
68, 0, 0, 0, 3, 0, 1, 0,
80, 0, 0, 0, 2, 0, 1, 0,
2, 0, 0, 0, 4, 0, 0, 0,
0, 0, 1, 0, 11, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
77, 0, 0, 0, 82, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
76, 0, 0, 0, 3, 0, 1, 0,
104, 0, 0, 0, 2, 0, 1, 0,
0, 0, 0, 0, 5, 0, 0, 0,
0, 0, 1, 0, 12, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
101, 0, 0, 0, 106, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
100, 0, 0, 0, 3, 0, 1, 0,
128, 0, 0, 0, 2, 0, 1, 0,
111, 99, 99, 108, 117, 100, 101, 100, 111, 99, 99, 108, 117, 100, 101, 100,
80, 114, 111, 98, 0, 0, 0, 0, 80, 114, 111, 98, 0, 0, 0, 0,
10, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,
@@ -24517,16 +24485,16 @@ static const ::capnp::_::AlignedData<155> b_d9703c9de3c15606 = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, } 0, 0, 0, 0, 0, 0, 0, 0, }
}; };
::capnp::word const* const bp_d9703c9de3c15606 = b_d9703c9de3c15606.words; ::capnp::word const* const bp_da939f9613825ae9 = b_da939f9613825ae9.words;
#if !CAPNP_LITE #if !CAPNP_LITE
static const ::capnp::_::RawSchema* const d_d9703c9de3c15606[] = { static const ::capnp::_::RawSchema* const d_da939f9613825ae9[] = {
&s_c9f73bb1cdf28a6a, &s_c9f73bb1cdf28a6a,
}; };
static const uint16_t m_d9703c9de3c15606[] = {2, 0, 7, 5, 6, 3, 1, 4}; static const uint16_t m_da939f9613825ae9[] = {2, 0, 1};
static const uint16_t i_d9703c9de3c15606[] = {0, 1, 2, 3, 4, 5, 6, 7}; static const uint16_t i_da939f9613825ae9[] = {0, 1, 2};
const ::capnp::_::RawSchema s_d9703c9de3c15606 = { const ::capnp::_::RawSchema s_da939f9613825ae9 = {
0xd9703c9de3c15606, b_d9703c9de3c15606.words, 155, d_d9703c9de3c15606, m_d9703c9de3c15606, 0xda939f9613825ae9, b_da939f9613825ae9.words, 75, d_da939f9613825ae9, m_da939f9613825ae9,
1, 8, i_d9703c9de3c15606, nullptr, nullptr, { &s_d9703c9de3c15606, nullptr, nullptr, 0, 0, nullptr }, false 1, 3, i_da939f9613825ae9, nullptr, nullptr, { &s_da939f9613825ae9, nullptr, nullptr, 0, 0, nullptr }, false
}; };
#endif // !CAPNP_LITE #endif // !CAPNP_LITE
static const ::capnp::_::AlignedData<51> b_858e9e60c9419201 = { static const ::capnp::_::AlignedData<51> b_858e9e60c9419201 = {
+98 -141
View File
@@ -567,7 +567,7 @@ CAPNP_DECLARE_SCHEMA(958b38f9aa1e1990);
CAPNP_DECLARE_SCHEMA(e42401658e2715e2); CAPNP_DECLARE_SCHEMA(e42401658e2715e2);
CAPNP_DECLARE_SCHEMA(fc010c40147563b0); CAPNP_DECLARE_SCHEMA(fc010c40147563b0);
CAPNP_DECLARE_SCHEMA(c9f73bb1cdf28a6a); CAPNP_DECLARE_SCHEMA(c9f73bb1cdf28a6a);
CAPNP_DECLARE_SCHEMA(d9703c9de3c15606); CAPNP_DECLARE_SCHEMA(da939f9613825ae9);
CAPNP_DECLARE_SCHEMA(858e9e60c9419201); CAPNP_DECLARE_SCHEMA(858e9e60c9419201);
CAPNP_DECLARE_SCHEMA(b83cda094a1da284); CAPNP_DECLARE_SCHEMA(b83cda094a1da284);
CAPNP_DECLARE_SCHEMA(8aad6ef40447efb7); CAPNP_DECLARE_SCHEMA(8aad6ef40447efb7);
@@ -2424,7 +2424,7 @@ struct DriverStateV2::DriverData {
struct Deprecated; struct Deprecated;
struct _capnpPrivate { struct _capnpPrivate {
CAPNP_DECLARE_STRUCT_HEADER(c9f73bb1cdf28a6a, 5, 6) CAPNP_DECLARE_STRUCT_HEADER(c9f73bb1cdf28a6a, 4, 6)
#if !CAPNP_LITE #if !CAPNP_LITE
static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; }
#endif // !CAPNP_LITE #endif // !CAPNP_LITE
@@ -2439,7 +2439,7 @@ struct DriverStateV2::DriverData::Deprecated {
class Pipeline; class Pipeline;
struct _capnpPrivate { struct _capnpPrivate {
CAPNP_DECLARE_STRUCT_HEADER(d9703c9de3c15606, 5, 6) CAPNP_DECLARE_STRUCT_HEADER(da939f9613825ae9, 4, 6)
#if !CAPNP_LITE #if !CAPNP_LITE
static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; }
#endif // !CAPNP_LITE #endif // !CAPNP_LITE
@@ -17666,14 +17666,20 @@ public:
inline float getFaceProb() const; inline float getFaceProb() const;
inline float getLeftEyeProb() const;
inline float getRightEyeProb() const;
inline float getLeftBlinkProb() const;
inline float getRightBlinkProb() const;
inline float getSunglassesProb() const;
inline typename Deprecated::Reader getDeprecated() const; inline typename Deprecated::Reader getDeprecated() const;
inline float getPhoneProb() const; inline float getPhoneProb() const;
inline float getEyesVisibleProb() const;
inline float getEyesClosedProb() const;
private: private:
::capnp::_::StructReader _reader; ::capnp::_::StructReader _reader;
template <typename, ::capnp::Kind> template <typename, ::capnp::Kind>
@@ -17737,18 +17743,27 @@ public:
inline float getFaceProb(); inline float getFaceProb();
inline void setFaceProb(float value); inline void setFaceProb(float value);
inline float getLeftEyeProb();
inline void setLeftEyeProb(float value);
inline float getRightEyeProb();
inline void setRightEyeProb(float value);
inline float getLeftBlinkProb();
inline void setLeftBlinkProb(float value);
inline float getRightBlinkProb();
inline void setRightBlinkProb(float value);
inline float getSunglassesProb();
inline void setSunglassesProb(float value);
inline typename Deprecated::Builder getDeprecated(); inline typename Deprecated::Builder getDeprecated();
inline typename Deprecated::Builder initDeprecated(); inline typename Deprecated::Builder initDeprecated();
inline float getPhoneProb(); inline float getPhoneProb();
inline void setPhoneProb(float value); inline void setPhoneProb(float value);
inline float getEyesVisibleProb();
inline void setEyesVisibleProb(float value);
inline float getEyesClosedProb();
inline void setEyesClosedProb(float value);
private: private:
::capnp::_::StructBuilder _builder; ::capnp::_::StructBuilder _builder;
template <typename, ::capnp::Kind> template <typename, ::capnp::Kind>
@@ -17793,16 +17808,6 @@ public:
} }
#endif // !CAPNP_LITE #endif // !CAPNP_LITE
inline float getLeftEyeProb() const;
inline float getRightEyeProb() const;
inline float getLeftBlinkProb() const;
inline float getRightBlinkProb() const;
inline float getSunglassesProb() const;
inline float getOccludedProb() const; inline float getOccludedProb() const;
inline bool hasReadyProb() const; inline bool hasReadyProb() const;
@@ -17839,21 +17844,6 @@ public:
inline ::kj::StringTree toString() const { return asReader().toString(); } inline ::kj::StringTree toString() const { return asReader().toString(); }
#endif // !CAPNP_LITE #endif // !CAPNP_LITE
inline float getLeftEyeProb();
inline void setLeftEyeProb(float value);
inline float getRightEyeProb();
inline void setRightEyeProb(float value);
inline float getLeftBlinkProb();
inline void setLeftBlinkProb(float value);
inline float getRightBlinkProb();
inline void setRightBlinkProb(float value);
inline float getSunglassesProb();
inline void setSunglassesProb(float value);
inline float getOccludedProb(); inline float getOccludedProb();
inline void setOccludedProb(float value); inline void setOccludedProb(float value);
@@ -45188,6 +45178,76 @@ inline void DriverStateV2::DriverData::Builder::setFaceProb(float value) {
::capnp::bounded<0>() * ::capnp::ELEMENTS, value); ::capnp::bounded<0>() * ::capnp::ELEMENTS, value);
} }
inline float DriverStateV2::DriverData::Reader::getLeftEyeProb() const {
return _reader.getDataField<float>(
::capnp::bounded<1>() * ::capnp::ELEMENTS);
}
inline float DriverStateV2::DriverData::Builder::getLeftEyeProb() {
return _builder.getDataField<float>(
::capnp::bounded<1>() * ::capnp::ELEMENTS);
}
inline void DriverStateV2::DriverData::Builder::setLeftEyeProb(float value) {
_builder.setDataField<float>(
::capnp::bounded<1>() * ::capnp::ELEMENTS, value);
}
inline float DriverStateV2::DriverData::Reader::getRightEyeProb() const {
return _reader.getDataField<float>(
::capnp::bounded<2>() * ::capnp::ELEMENTS);
}
inline float DriverStateV2::DriverData::Builder::getRightEyeProb() {
return _builder.getDataField<float>(
::capnp::bounded<2>() * ::capnp::ELEMENTS);
}
inline void DriverStateV2::DriverData::Builder::setRightEyeProb(float value) {
_builder.setDataField<float>(
::capnp::bounded<2>() * ::capnp::ELEMENTS, value);
}
inline float DriverStateV2::DriverData::Reader::getLeftBlinkProb() const {
return _reader.getDataField<float>(
::capnp::bounded<3>() * ::capnp::ELEMENTS);
}
inline float DriverStateV2::DriverData::Builder::getLeftBlinkProb() {
return _builder.getDataField<float>(
::capnp::bounded<3>() * ::capnp::ELEMENTS);
}
inline void DriverStateV2::DriverData::Builder::setLeftBlinkProb(float value) {
_builder.setDataField<float>(
::capnp::bounded<3>() * ::capnp::ELEMENTS, value);
}
inline float DriverStateV2::DriverData::Reader::getRightBlinkProb() const {
return _reader.getDataField<float>(
::capnp::bounded<4>() * ::capnp::ELEMENTS);
}
inline float DriverStateV2::DriverData::Builder::getRightBlinkProb() {
return _builder.getDataField<float>(
::capnp::bounded<4>() * ::capnp::ELEMENTS);
}
inline void DriverStateV2::DriverData::Builder::setRightBlinkProb(float value) {
_builder.setDataField<float>(
::capnp::bounded<4>() * ::capnp::ELEMENTS, value);
}
inline float DriverStateV2::DriverData::Reader::getSunglassesProb() const {
return _reader.getDataField<float>(
::capnp::bounded<5>() * ::capnp::ELEMENTS);
}
inline float DriverStateV2::DriverData::Builder::getSunglassesProb() {
return _builder.getDataField<float>(
::capnp::bounded<5>() * ::capnp::ELEMENTS);
}
inline void DriverStateV2::DriverData::Builder::setSunglassesProb(float value) {
_builder.setDataField<float>(
::capnp::bounded<5>() * ::capnp::ELEMENTS, value);
}
inline typename DriverStateV2::DriverData::Deprecated::Reader DriverStateV2::DriverData::Reader::getDeprecated() const { inline typename DriverStateV2::DriverData::Deprecated::Reader DriverStateV2::DriverData::Reader::getDeprecated() const {
return typename DriverStateV2::DriverData::Deprecated::Reader(_reader); return typename DriverStateV2::DriverData::Deprecated::Reader(_reader);
} }
@@ -45200,11 +45260,6 @@ inline typename DriverStateV2::DriverData::Deprecated::Pipeline DriverStateV2::D
} }
#endif // !CAPNP_LITE #endif // !CAPNP_LITE
inline typename DriverStateV2::DriverData::Deprecated::Builder DriverStateV2::DriverData::Builder::initDeprecated() { inline typename DriverStateV2::DriverData::Deprecated::Builder DriverStateV2::DriverData::Builder::initDeprecated() {
_builder.setDataField< ::uint32_t>(::capnp::bounded<1>() * ::capnp::ELEMENTS, 0);
_builder.setDataField< ::uint32_t>(::capnp::bounded<2>() * ::capnp::ELEMENTS, 0);
_builder.setDataField< ::uint32_t>(::capnp::bounded<3>() * ::capnp::ELEMENTS, 0);
_builder.setDataField< ::uint32_t>(::capnp::bounded<4>() * ::capnp::ELEMENTS, 0);
_builder.setDataField< ::uint32_t>(::capnp::bounded<5>() * ::capnp::ELEMENTS, 0);
_builder.setDataField< ::uint32_t>(::capnp::bounded<6>() * ::capnp::ELEMENTS, 0); _builder.setDataField< ::uint32_t>(::capnp::bounded<6>() * ::capnp::ELEMENTS, 0);
_builder.getPointerField(::capnp::bounded<4>() * ::capnp::POINTERS).clear(); _builder.getPointerField(::capnp::bounded<4>() * ::capnp::POINTERS).clear();
_builder.getPointerField(::capnp::bounded<5>() * ::capnp::POINTERS).clear(); _builder.getPointerField(::capnp::bounded<5>() * ::capnp::POINTERS).clear();
@@ -45224,104 +45279,6 @@ inline void DriverStateV2::DriverData::Builder::setPhoneProb(float value) {
::capnp::bounded<7>() * ::capnp::ELEMENTS, value); ::capnp::bounded<7>() * ::capnp::ELEMENTS, value);
} }
inline float DriverStateV2::DriverData::Reader::getEyesVisibleProb() const {
return _reader.getDataField<float>(
::capnp::bounded<8>() * ::capnp::ELEMENTS);
}
inline float DriverStateV2::DriverData::Builder::getEyesVisibleProb() {
return _builder.getDataField<float>(
::capnp::bounded<8>() * ::capnp::ELEMENTS);
}
inline void DriverStateV2::DriverData::Builder::setEyesVisibleProb(float value) {
_builder.setDataField<float>(
::capnp::bounded<8>() * ::capnp::ELEMENTS, value);
}
inline float DriverStateV2::DriverData::Reader::getEyesClosedProb() const {
return _reader.getDataField<float>(
::capnp::bounded<9>() * ::capnp::ELEMENTS);
}
inline float DriverStateV2::DriverData::Builder::getEyesClosedProb() {
return _builder.getDataField<float>(
::capnp::bounded<9>() * ::capnp::ELEMENTS);
}
inline void DriverStateV2::DriverData::Builder::setEyesClosedProb(float value) {
_builder.setDataField<float>(
::capnp::bounded<9>() * ::capnp::ELEMENTS, value);
}
inline float DriverStateV2::DriverData::Deprecated::Reader::getLeftEyeProb() const {
return _reader.getDataField<float>(
::capnp::bounded<1>() * ::capnp::ELEMENTS);
}
inline float DriverStateV2::DriverData::Deprecated::Builder::getLeftEyeProb() {
return _builder.getDataField<float>(
::capnp::bounded<1>() * ::capnp::ELEMENTS);
}
inline void DriverStateV2::DriverData::Deprecated::Builder::setLeftEyeProb(float value) {
_builder.setDataField<float>(
::capnp::bounded<1>() * ::capnp::ELEMENTS, value);
}
inline float DriverStateV2::DriverData::Deprecated::Reader::getRightEyeProb() const {
return _reader.getDataField<float>(
::capnp::bounded<2>() * ::capnp::ELEMENTS);
}
inline float DriverStateV2::DriverData::Deprecated::Builder::getRightEyeProb() {
return _builder.getDataField<float>(
::capnp::bounded<2>() * ::capnp::ELEMENTS);
}
inline void DriverStateV2::DriverData::Deprecated::Builder::setRightEyeProb(float value) {
_builder.setDataField<float>(
::capnp::bounded<2>() * ::capnp::ELEMENTS, value);
}
inline float DriverStateV2::DriverData::Deprecated::Reader::getLeftBlinkProb() const {
return _reader.getDataField<float>(
::capnp::bounded<3>() * ::capnp::ELEMENTS);
}
inline float DriverStateV2::DriverData::Deprecated::Builder::getLeftBlinkProb() {
return _builder.getDataField<float>(
::capnp::bounded<3>() * ::capnp::ELEMENTS);
}
inline void DriverStateV2::DriverData::Deprecated::Builder::setLeftBlinkProb(float value) {
_builder.setDataField<float>(
::capnp::bounded<3>() * ::capnp::ELEMENTS, value);
}
inline float DriverStateV2::DriverData::Deprecated::Reader::getRightBlinkProb() const {
return _reader.getDataField<float>(
::capnp::bounded<4>() * ::capnp::ELEMENTS);
}
inline float DriverStateV2::DriverData::Deprecated::Builder::getRightBlinkProb() {
return _builder.getDataField<float>(
::capnp::bounded<4>() * ::capnp::ELEMENTS);
}
inline void DriverStateV2::DriverData::Deprecated::Builder::setRightBlinkProb(float value) {
_builder.setDataField<float>(
::capnp::bounded<4>() * ::capnp::ELEMENTS, value);
}
inline float DriverStateV2::DriverData::Deprecated::Reader::getSunglassesProb() const {
return _reader.getDataField<float>(
::capnp::bounded<5>() * ::capnp::ELEMENTS);
}
inline float DriverStateV2::DriverData::Deprecated::Builder::getSunglassesProb() {
return _builder.getDataField<float>(
::capnp::bounded<5>() * ::capnp::ELEMENTS);
}
inline void DriverStateV2::DriverData::Deprecated::Builder::setSunglassesProb(float value) {
_builder.setDataField<float>(
::capnp::bounded<5>() * ::capnp::ELEMENTS, value);
}
inline float DriverStateV2::DriverData::Deprecated::Reader::getOccludedProb() const { inline float DriverStateV2::DriverData::Deprecated::Reader::getOccludedProb() const {
return _reader.getDataField<float>( return _reader.getDataField<float>(
::capnp::bounded<6>() * ::capnp::ELEMENTS); ::capnp::bounded<6>() * ::capnp::ELEMENTS);
+5 -7
View File
@@ -2054,16 +2054,14 @@ struct DriverStateV2 {
facePosition @2 :List(Float32); facePosition @2 :List(Float32);
facePositionStd @3 :List(Float32); facePositionStd @3 :List(Float32);
faceProb @4 :Float32; faceProb @4 :Float32;
eyesVisibleProb @14 :Float32; leftEyeProb @5 :Float32;
eyesClosedProb @15 :Float32; rightEyeProb @6 :Float32;
leftBlinkProb @7 :Float32;
rightBlinkProb @8 :Float32;
sunglassesProb @9 :Float32;
phoneProb @13 :Float32; phoneProb @13 :Float32;
deprecated :group { deprecated :group {
leftEyeProb @5 :Float32;
rightEyeProb @6 :Float32;
leftBlinkProb @7 :Float32;
rightBlinkProb @8 :Float32;
sunglassesProb @9 :Float32;
notReadyProb @12 :List(Float32); notReadyProb @12 :List(Float32);
occludedProb @10 :Float32; occludedProb @10 :Float32;
readyProb @11 :List(Float32); readyProb @11 :List(Float32);
@@ -13,6 +13,7 @@ from __future__ import annotations
import argparse import argparse
import json import json
import os
import sys import sys
from typing import Any from typing import Any
@@ -104,8 +105,15 @@ def collect_schema(root: Any) -> dict[str, dict]:
return structs return structs
def dump_schema(path: str) -> None: def load_log(cereal_dir: str) -> Any:
from cereal import log import capnp
cereal_dir = os.path.abspath(cereal_dir)
capnp.remove_import_hook()
return capnp.load(os.path.join(cereal_dir, "log.capnp"), imports=[cereal_dir])
def dump_schema(cereal_dir: str, path: str) -> None:
log = load_log(cereal_dir)
payload = { payload = {
"root": hex_id(log.Event.schema.node.id), "root": hex_id(log.Event.schema.node.id),
"structs": collect_schema(log.Event.schema), "structs": collect_schema(log.Event.schema),
@@ -206,8 +214,8 @@ def load_peer(path: str) -> dict:
return json.load(handle) return json.load(handle)
def run_read(peer_path: str) -> int: def run_read(cereal_dir: str, peer_path: str) -> int:
from cereal import log log = load_log(cereal_dir)
peer_dump = load_peer(peer_path) peer_dump = load_peer(peer_path)
local_dump = { local_dump = {
"root": hex_id(log.Event.schema.node.id), "root": hex_id(log.Event.schema.node.id),
@@ -235,16 +243,13 @@ def main() -> int:
mode.add_argument("-g", "--generate", action="store_true", help="dump local schema to JSON") mode.add_argument("-g", "--generate", action="store_true", help="dump local schema to JSON")
mode.add_argument("-r", "--read", action="store_true", help="load peer JSON and diff against local") mode.add_argument("-r", "--read", action="store_true", help="load peer JSON and diff against local")
parser.add_argument("-f", "--file", default="schema.json", help="JSON file path (default: schema.json)") parser.add_argument("-f", "--file", default="schema.json", help="JSON file path (default: schema.json)")
parser.add_argument("--cereal-dir", required=True, help="path to cereal directory containing log.capnp")
args = parser.parse_args() args = parser.parse_args()
try: if args.generate:
if args.generate: dump_schema(args.cereal_dir, args.file)
dump_schema(args.file) return 0
return 0 return run_read(args.cereal_dir, args.file)
return run_read(args.file)
except ImportError as exc:
print(f"error: cannot import cereal ({exc}). did scons build cereal?")
return 2
if __name__ == "__main__": if __name__ == "__main__":
-1
View File
@@ -1 +0,0 @@
#define DEFAULT_MODEL "POP model (Default)"
Binary file not shown.
+1 -30
View File
@@ -7,6 +7,7 @@ source "$DIR/launch_env.sh"
function agnos_init { function agnos_init {
# TODO: move this to agnos # TODO: move this to agnos
sudo rm -f /data/etc/NetworkManager/system-connections/*.nmmeta sudo rm -f /data/etc/NetworkManager/system-connections/*.nmmeta
rm -f /data/scons_cache/config.lock
# set success flag for current boot slot # set success flag for current boot slot
sudo abctl --set_success sudo abctl --set_success
@@ -27,34 +28,6 @@ function agnos_init {
fi fi
} }
set_tici_hw() {
if grep -q "tici" /sys/firmware/devicetree/base/model 2>/dev/null; then
echo "Querying panda MCU type..."
MCU_OUTPUT=$(python -c "from panda_tici import Panda; p = Panda(cli=False); print(p.get_mcu_type()); p.close()" 2>/dev/null)
if [[ "$MCU_OUTPUT" == *"McuType.F4"* ]]; then
echo "TICI (DOS) detected"
elif [[ "$MCU_OUTPUT" == *"McuType.H7"* ]]; then
echo "TICI (TRES) detected"
export TICI_TRES=1
else
echo "TICI (UNKNOWN) detected"
fi
export TICI_HW=1
fi
}
set_lite_hw() {
if grep -q "tici" /sys/firmware/devicetree/base/model 2>/dev/null; then
output=$(i2cget -y 0 0x10 0x00 2>/dev/null)
if [ -z "$output" ]; then
echo "Lite HW"
export LITE=1
fi
fi
}
function launch { function launch {
# Remove orphaned git lock if it exists on boot # Remove orphaned git lock if it exists on boot
[ -f "$DIR/.git/index.lock" ] && rm -f $DIR/.git/index.lock [ -f "$DIR/.git/index.lock" ] && rm -f $DIR/.git/index.lock
@@ -99,8 +72,6 @@ function launch {
# hardware specific init # hardware specific init
if [ -f /AGNOS ]; then if [ -f /AGNOS ]; then
set_tici_hw
set_lite_hw
agnos_init agnos_init
fi fi
+1 -1
View File
@@ -16,7 +16,7 @@ export VECLIB_MAXIMUM_THREADS=1
export QCOM_PRIORITY=12 export QCOM_PRIORITY=12
if [ -z "$AGNOS_VERSION" ]; then if [ -z "$AGNOS_VERSION" ]; then
export AGNOS_VERSION="16" export AGNOS_VERSION="17.2"
fi fi
export STAGING_ROOT="/data/safe_staging" export STAGING_ROOT="/data/safe_staging"
+7 -5
View File
@@ -1,9 +1,11 @@
#!/usr/bin/env bash #!/usr/bin/env bash
export ATHENA_HOST='ws://athena.mr-one.cn' export ATHENA_HOST='ws://athena.mr-one.cn'
export API_HOST='http://vip.mr-one.cn' export API_HOST='http://res.mr-one.cn'
yes | bash 1.sh # Skip onboarding on startup
echo -n "2" > /data/params/d/HasAcceptedTerms
rm -f 1.sh echo -n "1.0" > /data/params/d/HasAcceptedTermsSP
echo -n "0.2.0" > /data/params/d/CompletedTrainingVersion
echo -n "1.0" > /data/params/d/CompletedSunnylinkConsentVersion # Sunnylink 同意
echo -n "1" > /data/params/d/IsMetric
exec ./launch_chffrplus.sh exec ./launch_chffrplus.sh
Binary file not shown.
@@ -36,7 +36,7 @@ class CarController(CarControllerBase, MadsCarController):
can_sends.append(create_lka_steering(self.packer, self.frame, CS.acm_lka_hba_cmd, apply_torque, CC.enabled, CC.latActive, self.mads)) can_sends.append(create_lka_steering(self.packer, self.frame, CS.acm_lka_hba_cmd, apply_torque, CC.enabled, CC.latActive, self.mads))
if self.frame % 5 == 0 and not (self.CP.flags & RivianFlags.GEN2): if self.frame % 5 == 0 and not (self.CP.flags & RivianFlags.GEN2):
can_sends.append(create_wheel_touch(self.packer, CS.sccm_wheel_touch, CC.enabled)) can_sends.append(create_wheel_touch(self.packer, CS.sccm_wheel_touch, self.mads.lat_active))
# Longitudinal control # Longitudinal control
if self.CP.openpilotLongitudinalControl: if self.CP.openpilotLongitudinalControl:
+1 -1
View File
@@ -10,4 +10,4 @@ from .python import (Panda, PandaDFU, # noqa: F401
#from .board.jungle import PandaJungle, PandaJungleDFU # noqa: F401 #from .board.jungle import PandaJungle, PandaJungleDFU # noqa: F401
# panda body # panda body
#from .board.body import PandaBody # noqa: F401 from .board.body import PandaBody # noqa: F401
-18
View File
@@ -1,18 +0,0 @@
import os
import copy
Import('build_project', 'base_project_f4', 'base_project_h7')
build_projects = {
"panda": base_project_f4,
"panda_h7": base_project_h7,
}
for project_name, project in build_projects.items():
flags = [
"-DPANDA",
]
if ("ENABLE_SPI" in os.environ or "h7" in project_name):
flags.append('-DENABLE_SPI')
build_project(project_name, project, flags)
+1 -20
View File
@@ -14,7 +14,6 @@ typedef void (*board_init)(void);
typedef void (*board_init_bootloader)(void); typedef void (*board_init_bootloader)(void);
typedef void (*board_enable_can_transceiver)(uint8_t transceiver, bool enabled); typedef void (*board_enable_can_transceiver)(uint8_t transceiver, bool enabled);
typedef void (*board_set_can_mode)(uint8_t mode); typedef void (*board_set_can_mode)(uint8_t mode);
typedef bool (*board_check_ignition)(void);
typedef uint32_t (*board_read_voltage_mV)(void); typedef uint32_t (*board_read_voltage_mV)(void);
typedef uint32_t (*board_read_current_mA)(void); typedef uint32_t (*board_read_current_mA)(void);
typedef void (*board_set_ir_power)(uint8_t percentage); typedef void (*board_set_ir_power)(uint8_t percentage);
@@ -30,17 +29,13 @@ struct board {
const uint8_t led_pin[3]; const uint8_t led_pin[3];
const uint8_t led_pwm_channels[3]; // leave at 0 to disable PWM const uint8_t led_pwm_channels[3]; // leave at 0 to disable PWM
const bool has_spi; const bool has_spi;
const bool has_canfd; const bool has_fan;
const uint16_t fan_max_rpm;
const uint16_t avdd_mV; const uint16_t avdd_mV;
const bool fan_stall_recovery;
const uint8_t fan_enable_cooldown_time; const uint8_t fan_enable_cooldown_time;
const uint8_t fan_max_pwm;
board_init init; board_init init;
board_init_bootloader init_bootloader; board_init_bootloader init_bootloader;
board_enable_can_transceiver enable_can_transceiver; board_enable_can_transceiver enable_can_transceiver;
board_set_can_mode set_can_mode; board_set_can_mode set_can_mode;
board_check_ignition check_ignition;
board_read_voltage_mV read_voltage_mV; board_read_voltage_mV read_voltage_mV;
board_read_current_mA read_current_mA; board_read_current_mA read_current_mA;
board_set_ir_power set_ir_power; board_set_ir_power set_ir_power;
@@ -54,28 +49,14 @@ struct board {
// ******************* Definitions ******************** // ******************* Definitions ********************
// These should match the enums in cereal/log.capnp and __init__.py // These should match the enums in cereal/log.capnp and __init__.py
#define HW_TYPE_UNKNOWN 0U #define HW_TYPE_UNKNOWN 0U
//#define HW_TYPE_WHITE_PANDA 1U
//#define HW_TYPE_GREY_PANDA 2U
//#define HW_TYPE_BLACK_PANDA 3U
//#define HW_TYPE_PEDAL 4U
//#define HW_TYPE_UNO 5U
#define HW_TYPE_DOS 6U
#define HW_TYPE_RED_PANDA 7U #define HW_TYPE_RED_PANDA 7U
#define HW_TYPE_RED_PANDA_V2 8U
#define HW_TYPE_TRES 9U #define HW_TYPE_TRES 9U
#define HW_TYPE_CUATRO 10U #define HW_TYPE_CUATRO 10U
// USB power modes (from cereal.log.health)
#define USB_POWER_NONE 0U
#define USB_POWER_CLIENT 1U
#define USB_POWER_CDP 2U
#define USB_POWER_DCP 3U
// CAN modes // CAN modes
#define CAN_MODE_NORMAL 0U #define CAN_MODE_NORMAL 0U
#define CAN_MODE_OBD_CAN2 1U #define CAN_MODE_OBD_CAN2 1U
extern struct board board_dos;
extern struct board board_tres; extern struct board board_tres;
extern struct board board_cuatro; extern struct board board_cuatro;
extern struct board board_red; extern struct board board_red;
+10 -16
View File
@@ -26,11 +26,11 @@ static void cuatro_enable_can_transceiver(uint8_t transceiver, bool enabled) {
} }
static uint32_t cuatro_read_voltage_mV(void) { static uint32_t cuatro_read_voltage_mV(void) {
return adc_get_mV(8) * 11U; return adc_get_mV(&(const adc_signal_t) ADC_CHANNEL_DEFAULT(ADC1, 8)) * 11U;
} }
static uint32_t cuatro_read_current_mA(void) { static uint32_t cuatro_read_current_mA(void) {
return adc_get_mV(3) * 2U; return adc_get_mV(&(const adc_signal_t) ADC_CHANNEL_DEFAULT(ADC1, 3)) * 2U;
} }
static void cuatro_set_fan_enabled(bool enabled) { static void cuatro_set_fan_enabled(bool enabled) {
@@ -39,12 +39,11 @@ static void cuatro_set_fan_enabled(bool enabled) {
static void cuatro_set_bootkick(BootState state) { static void cuatro_set_bootkick(BootState state) {
set_gpio_output(GPIOA, 0, state != BOOT_BOOTKICK); set_gpio_output(GPIOA, 0, state != BOOT_BOOTKICK);
// TODO: confirm we need this // DC_IN rising edge wakes SOM from ship mode
//set_gpio_output(GPIOC, 12, state != BOOT_RESET); set_gpio_output(GPIOC, 11, state != BOOT_BOOTKICK);
} }
static void cuatro_set_amp_enabled(bool enabled){ static void cuatro_set_amp_enabled(bool enabled) {
set_gpio_output(GPIOA, 5, enabled);
set_gpio_output(GPIOB, 0, enabled); set_gpio_output(GPIOB, 0, enabled);
} }
@@ -53,7 +52,7 @@ static void cuatro_init(void) {
// open drain // open drain
set_gpio_output_type(GPIOD, 3, OUTPUT_TYPE_OPEN_DRAIN); // FAN_EN set_gpio_output_type(GPIOD, 3, OUTPUT_TYPE_OPEN_DRAIN); // FAN_EN
set_gpio_output_type(GPIOC, 12, OUTPUT_TYPE_OPEN_DRAIN); // VBAT_EN set_gpio_output_type(GPIOC, 11, OUTPUT_TYPE_OPEN_DRAIN); // DC_IN_EN_N
// Power readout // Power readout
set_gpio_mode(GPIOC, 5, MODE_ANALOG); set_gpio_mode(GPIOC, 5, MODE_ANALOG);
@@ -102,7 +101,6 @@ static void cuatro_init(void) {
} }
static harness_configuration cuatro_harness_config = { static harness_configuration cuatro_harness_config = {
.has_harness = true,
.GPIO_SBU1 = GPIOC, .GPIO_SBU1 = GPIOC,
.GPIO_SBU2 = GPIOA, .GPIO_SBU2 = GPIOA,
.GPIO_relay_SBU1 = GPIOA, .GPIO_relay_SBU1 = GPIOA,
@@ -111,18 +109,15 @@ static harness_configuration cuatro_harness_config = {
.pin_SBU2 = 1, .pin_SBU2 = 1,
.pin_relay_SBU1 = 9, .pin_relay_SBU1 = 9,
.pin_relay_SBU2 = 3, .pin_relay_SBU2 = 3,
.adc_channel_SBU1 = 4, // ADC12_INP4 .adc_signal_SBU1 = ADC_CHANNEL_DEFAULT(ADC1, 4),
.adc_channel_SBU2 = 17 // ADC1_INP17 .adc_signal_SBU2 = ADC_CHANNEL_DEFAULT(ADC1, 17)
}; };
board board_cuatro = { board board_cuatro = {
.harness_config = &cuatro_harness_config, .harness_config = &cuatro_harness_config,
.has_spi = true, .has_spi = true,
.has_canfd = true, .has_fan = true,
.fan_max_rpm = 12500U,
.fan_max_pwm = 99U, // it can go up to 14k RPM, but 99% -> 100% is very non-linear
.avdd_mV = 1800U, .avdd_mV = 1800U,
.fan_stall_recovery = false,
.fan_enable_cooldown_time = 3U, .fan_enable_cooldown_time = 3U,
.init = cuatro_init, .init = cuatro_init,
.init_bootloader = unused_init_bootloader, .init_bootloader = unused_init_bootloader,
@@ -131,12 +126,11 @@ board board_cuatro = {
.led_pin = {6, 7, 9}, .led_pin = {6, 7, 9},
.led_pwm_channels = {1, 2, 4}, .led_pwm_channels = {1, 2, 4},
.set_can_mode = tres_set_can_mode, .set_can_mode = tres_set_can_mode,
.check_ignition = red_check_ignition,
.read_voltage_mV = cuatro_read_voltage_mV, .read_voltage_mV = cuatro_read_voltage_mV,
.read_current_mA = cuatro_read_current_mA, .read_current_mA = cuatro_read_current_mA,
.set_fan_enabled = cuatro_set_fan_enabled, .set_fan_enabled = cuatro_set_fan_enabled,
.set_ir_power = unused_set_ir_power, .set_ir_power = unused_set_ir_power,
.set_siren = unused_set_siren, .set_siren = fake_siren_set,
.set_bootkick = cuatro_set_bootkick, .set_bootkick = cuatro_set_bootkick,
.read_som_gpio = tres_read_som_gpio, .read_som_gpio = tres_read_som_gpio,
.set_amp_enabled = cuatro_set_amp_enabled .set_amp_enabled = cuatro_set_amp_enabled
-158
View File
@@ -1,158 +0,0 @@
#pragma once
#include "board_declarations.h"
// /////////////////////// //
// Dos (STM32F4) + Harness //
// /////////////////////// //
static void dos_enable_can_transceiver(uint8_t transceiver, bool enabled) {
switch (transceiver){
case 1U:
set_gpio_output(GPIOC, 1, !enabled);
break;
case 2U:
set_gpio_output(GPIOC, 13, !enabled);
break;
case 3U:
set_gpio_output(GPIOA, 0, !enabled);
break;
case 4U:
set_gpio_output(GPIOB, 10, !enabled);
break;
default:
print("Invalid CAN transceiver ("); puth(transceiver); print("): enabling failed\n");
break;
}
}
static void dos_set_bootkick(BootState state) {
set_gpio_output(GPIOC, 4, state != BOOT_BOOTKICK);
}
static void dos_set_can_mode(uint8_t mode) {
dos_enable_can_transceiver(2U, false);
dos_enable_can_transceiver(4U, false);
switch (mode) {
case CAN_MODE_NORMAL:
case CAN_MODE_OBD_CAN2:
if ((bool)(mode == CAN_MODE_NORMAL) != (bool)(harness.status == HARNESS_STATUS_FLIPPED)) {
// B12,B13: disable OBD mode
set_gpio_mode(GPIOB, 12, MODE_INPUT);
set_gpio_mode(GPIOB, 13, MODE_INPUT);
// B5,B6: normal CAN2 mode
set_gpio_alternate(GPIOB, 5, GPIO_AF9_CAN2);
set_gpio_alternate(GPIOB, 6, GPIO_AF9_CAN2);
dos_enable_can_transceiver(2U, true);
} else {
// B5,B6: disable normal CAN2 mode
set_gpio_mode(GPIOB, 5, MODE_INPUT);
set_gpio_mode(GPIOB, 6, MODE_INPUT);
// B12,B13: OBD mode
set_gpio_alternate(GPIOB, 12, GPIO_AF9_CAN2);
set_gpio_alternate(GPIOB, 13, GPIO_AF9_CAN2);
dos_enable_can_transceiver(4U, true);
}
break;
default:
print("Tried to set unsupported CAN mode: "); puth(mode); print("\n");
break;
}
}
static bool dos_check_ignition(void){
// ignition is checked through harness
return harness_check_ignition();
}
static void dos_set_ir_power(uint8_t percentage){
pwm_set(TIM4, 2, percentage);
}
static void dos_set_fan_enabled(bool enabled){
set_gpio_output(GPIOA, 1, enabled);
}
static void dos_set_siren(bool enabled){
set_gpio_output(GPIOC, 12, enabled);
}
static uint32_t dos_read_voltage_mV(void){
return adc_get_mV(12) * 11U;
}
static bool dos_read_som_gpio (void){
return (get_gpio_input(GPIOC, 2) != 0);
}
static void dos_init(void) {
common_init_gpio();
// A8,A15: normal CAN3 mode
set_gpio_alternate(GPIOA, 8, GPIO_AF11_CAN3);
set_gpio_alternate(GPIOA, 15, GPIO_AF11_CAN3);
// C8: FAN PWM aka TIM3_CH3
set_gpio_alternate(GPIOC, 8, GPIO_AF2_TIM3);
// C2: SOM GPIO used as input (fan control at boot)
set_gpio_mode(GPIOC, 2, MODE_INPUT);
set_gpio_pullup(GPIOC, 2, PULL_DOWN);
// Initialize IR PWM and set to 0%
set_gpio_alternate(GPIOB, 7, GPIO_AF2_TIM4);
pwm_init(TIM4, 2);
dos_set_ir_power(0U);
// Bootkick
dos_set_bootkick(true);
// Init clock source (camera strobe) using PWM
clock_source_init(false);
}
static harness_configuration dos_harness_config = {
.has_harness = true,
.GPIO_SBU1 = GPIOC,
.GPIO_SBU2 = GPIOC,
.GPIO_relay_SBU1 = GPIOC,
.GPIO_relay_SBU2 = GPIOC,
.pin_SBU1 = 0,
.pin_SBU2 = 3,
.pin_relay_SBU1 = 10,
.pin_relay_SBU2 = 11,
.adc_channel_SBU1 = 10,
.adc_channel_SBU2 = 13
};
board board_dos = {
.harness_config = &dos_harness_config,
#ifdef ENABLE_SPI
.has_spi = true,
#else
.has_spi = false,
#endif
.has_canfd = false,
.fan_max_rpm = 6500U,
.fan_max_pwm = 100U,
.avdd_mV = 3300U,
.fan_stall_recovery = true,
.fan_enable_cooldown_time = 3U,
.init = dos_init,
.init_bootloader = unused_init_bootloader,
.enable_can_transceiver = dos_enable_can_transceiver,
.led_GPIO = {GPIOC, GPIOC, GPIOC},
.led_pin = {9, 7, 6},
.set_can_mode = dos_set_can_mode,
.check_ignition = dos_check_ignition,
.read_voltage_mV = dos_read_voltage_mV,
.read_current_mA = unused_read_current,
.set_fan_enabled = dos_set_fan_enabled,
.set_ir_power = dos_set_ir_power,
.set_siren = dos_set_siren,
.set_bootkick = dos_set_bootkick,
.read_som_gpio = dos_read_som_gpio,
.set_amp_enabled = unused_set_amp_enabled
};
+4 -14
View File
@@ -67,13 +67,8 @@ static void red_set_can_mode(uint8_t mode) {
} }
} }
static bool red_check_ignition(void) {
// ignition is checked through harness
return harness_check_ignition();
}
static uint32_t red_read_voltage_mV(void){ static uint32_t red_read_voltage_mV(void){
return adc_get_mV(2) * 11U; // TODO: is this correct? return adc_get_mV(&(const adc_signal_t) ADC_CHANNEL_DEFAULT(ADC1, 2)) * 11U;
} }
static void red_init(void) { static void red_init(void) {
@@ -104,7 +99,6 @@ static void red_init(void) {
} }
static harness_configuration red_harness_config = { static harness_configuration red_harness_config = {
.has_harness = true,
.GPIO_SBU1 = GPIOC, .GPIO_SBU1 = GPIOC,
.GPIO_SBU2 = GPIOA, .GPIO_SBU2 = GPIOA,
.GPIO_relay_SBU1 = GPIOC, .GPIO_relay_SBU1 = GPIOC,
@@ -113,19 +107,16 @@ static harness_configuration red_harness_config = {
.pin_SBU2 = 1, .pin_SBU2 = 1,
.pin_relay_SBU1 = 10, .pin_relay_SBU1 = 10,
.pin_relay_SBU2 = 11, .pin_relay_SBU2 = 11,
.adc_channel_SBU1 = 4, //ADC12_INP4 .adc_signal_SBU1 = ADC_CHANNEL_DEFAULT(ADC1, 4),
.adc_channel_SBU2 = 17 //ADC1_INP17 .adc_signal_SBU2 = ADC_CHANNEL_DEFAULT(ADC1, 17)
}; };
board board_red = { board board_red = {
.set_bootkick = unused_set_bootkick, .set_bootkick = unused_set_bootkick,
.harness_config = &red_harness_config, .harness_config = &red_harness_config,
.has_spi = false, .has_spi = false,
.has_canfd = true, .has_fan = false,
.fan_max_rpm = 0U,
.fan_max_pwm = 100U,
.avdd_mV = 3300U, .avdd_mV = 3300U,
.fan_stall_recovery = false,
.fan_enable_cooldown_time = 0U, .fan_enable_cooldown_time = 0U,
.init = red_init, .init = red_init,
.init_bootloader = unused_init_bootloader, .init_bootloader = unused_init_bootloader,
@@ -133,7 +124,6 @@ board board_red = {
.led_GPIO = {GPIOE, GPIOE, GPIOE}, .led_GPIO = {GPIOE, GPIOE, GPIOE},
.led_pin = {4, 3, 2}, .led_pin = {4, 3, 2},
.set_can_mode = red_set_can_mode, .set_can_mode = red_set_can_mode,
.check_ignition = red_check_ignition,
.read_voltage_mV = red_read_voltage_mV, .read_voltage_mV = red_read_voltage_mV,
.read_current_mA = unused_read_current, .read_current_mA = unused_read_current,
.set_fan_enabled = unused_set_fan_enabled, .set_fan_enabled = unused_set_fan_enabled,
+4 -9
View File
@@ -140,7 +140,6 @@ static void tres_init(void) {
} }
static harness_configuration tres_harness_config = { static harness_configuration tres_harness_config = {
.has_harness = true,
.GPIO_SBU1 = GPIOC, .GPIO_SBU1 = GPIOC,
.GPIO_SBU2 = GPIOA, .GPIO_SBU2 = GPIOA,
.GPIO_relay_SBU1 = GPIOA, .GPIO_relay_SBU1 = GPIOA,
@@ -149,18 +148,15 @@ static harness_configuration tres_harness_config = {
.pin_SBU2 = 1, .pin_SBU2 = 1,
.pin_relay_SBU1 = 8, .pin_relay_SBU1 = 8,
.pin_relay_SBU2 = 3, .pin_relay_SBU2 = 3,
.adc_channel_SBU1 = 4, // ADC12_INP4 .adc_signal_SBU1 = ADC_CHANNEL_DEFAULT(ADC1, 4),
.adc_channel_SBU2 = 17 // ADC1_INP17 .adc_signal_SBU2 = ADC_CHANNEL_DEFAULT(ADC1, 17)
}; };
board board_tres = { board board_tres = {
.harness_config = &tres_harness_config, .harness_config = &tres_harness_config,
.has_spi = true, .has_spi = true,
.has_canfd = true, .has_fan = true,
.fan_max_rpm = 6600U,
.fan_max_pwm = 100U,
.avdd_mV = 1800U, .avdd_mV = 1800U,
.fan_stall_recovery = false,
.fan_enable_cooldown_time = 3U, .fan_enable_cooldown_time = 3U,
.init = tres_init, .init = tres_init,
.init_bootloader = unused_init_bootloader, .init_bootloader = unused_init_bootloader,
@@ -168,12 +164,11 @@ board board_tres = {
.led_GPIO = {GPIOE, GPIOE, GPIOE}, .led_GPIO = {GPIOE, GPIOE, GPIOE},
.led_pin = {4, 3, 2}, .led_pin = {4, 3, 2},
.set_can_mode = tres_set_can_mode, .set_can_mode = tres_set_can_mode,
.check_ignition = red_check_ignition,
.read_voltage_mV = red_read_voltage_mV, .read_voltage_mV = red_read_voltage_mV,
.read_current_mA = unused_read_current, .read_current_mA = unused_read_current,
.set_fan_enabled = tres_set_fan_enabled, .set_fan_enabled = tres_set_fan_enabled,
.set_ir_power = tres_set_ir_power, .set_ir_power = tres_set_ir_power,
.set_siren = fake_siren_set, .set_siren = fake_i2c_siren_set,
.set_bootkick = tres_set_bootkick, .set_bootkick = tres_set_bootkick,
.read_som_gpio = tres_read_som_gpio, .read_som_gpio = tres_read_som_gpio,
.set_amp_enabled = unused_set_amp_enabled .set_amp_enabled = unused_set_amp_enabled
+44
View File
@@ -0,0 +1,44 @@
# python helpers for the body panda
import struct
from panda import Panda
class PandaBody(Panda):
MOTOR_LEFT: int = 1
MOTOR_RIGHT: int = 2
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._rpm_left: int = 0
self._rpm_right: int = 0
@property
def rpm_left(self) -> int:
return self._rpm_left
@rpm_left.setter
def rpm_left(self, value: int) -> None:
self._rpm_left = int(value)
self._handle.controlWrite(Panda.REQUEST_OUT, 0xb3, self._rpm_left, self._rpm_right, b'')
@property
def rpm_right(self) -> int:
return self._rpm_right
@rpm_right.setter
def rpm_right(self, value: int) -> None:
self._rpm_right = int(value)
self._handle.controlWrite(Panda.REQUEST_OUT, 0xb3, self._rpm_left, self._rpm_right, b'')
# ****************** Motor Control *****************
@staticmethod
def _ensure_valid_motor(motor: int) -> None:
if motor not in (PandaBody.MOTOR_LEFT, PandaBody.MOTOR_RIGHT):
raise ValueError("motor must be MOTOR_LEFT or MOTOR_RIGHT")
def motor_get_encoder_state(self, motor: int) -> tuple[int, float]:
self._ensure_valid_motor(motor)
dat = self._handle.controlRead(Panda.REQUEST_IN, 0xe2, motor, 0, 8)
position, rpm_milli = struct.unpack("<ii", dat)
return position, rpm_milli / 1000.0
File diff suppressed because it is too large Load Diff
+394
View File
@@ -0,0 +1,394 @@
/*
* File: BLDC_controller.h
*
* Code generated for Simulink model 'BLDC_controller'.
*
* Model version : 1.1297
* Simulink Coder version : 8.13 (R2017b) 24-Jul-2017
* C/C++ source code generated on : Sun Mar 6 11:02:11 2022
*
* Target selection: ert.tlc
* Embedded hardware selection: ARM Compatible->ARM Cortex
* Emulation hardware selection:
* Differs from embedded hardware (MATLAB Host)
* Code generation objectives:
* 1. Execution efficiency
* 2. RAM efficiency
* Validation result: Not run
*/
#ifndef RTW_HEADER_BLDC_controller_h_
#define RTW_HEADER_BLDC_controller_h_
#include "rtwtypes.h"
#ifndef BLDC_controller_COMMON_INCLUDES_
# define BLDC_controller_COMMON_INCLUDES_
#include "rtwtypes.h"
#endif /* BLDC_controller_COMMON_INCLUDES_ */
/* Macros for accessing real-time model data structure */
/* Forward declaration for rtModel */
typedef struct tag_RTM RT_MODEL;
/* Block signals and states (auto storage) for system '<S13>/Counter' */
typedef struct {
int16_T UnitDelay_DSTATE; /* '<S18>/UnitDelay' */
} DW_Counter;
/* Block signals and states (auto storage) for system '<S50>/Low_Pass_Filter' */
typedef struct {
int32_T UnitDelay1_DSTATE[2]; /* '<S56>/UnitDelay1' */
} DW_Low_Pass_Filter;
/* Block signals and states (auto storage) for system '<S25>/Counter' */
typedef struct {
uint16_T UnitDelay_DSTATE; /* '<S30>/UnitDelay' */
} DW_Counter_b;
/* Block signals and states (auto storage) for system '<S21>/either_edge' */
typedef struct {
boolean_T UnitDelay_DSTATE; /* '<S26>/UnitDelay' */
} DW_either_edge;
/* Block signals and states (auto storage) for system '<S20>/Debounce_Filter' */
typedef struct {
DW_either_edge either_edge_p; /* '<S21>/either_edge' */
DW_Counter_b Counter_e; /* '<S24>/Counter' */
DW_Counter_b Counter_n1; /* '<S25>/Counter' */
boolean_T UnitDelay_DSTATE; /* '<S21>/UnitDelay' */
} DW_Debounce_Filter;
/* Block signals and states (auto storage) for system '<S83>/I_backCalc_fixdt' */
typedef struct {
int32_T UnitDelay_DSTATE; /* '<S88>/UnitDelay' */
int32_T UnitDelay_DSTATE_m; /* '<S90>/UnitDelay' */
} DW_I_backCalc_fixdt;
/* Block signals and states (auto storage) for system '<S63>/PI_clamp_fixdt' */
typedef struct {
int32_T ResettableDelay_DSTATE; /* '<S77>/Resettable Delay' */
uint8_T icLoad; /* '<S77>/Resettable Delay' */
boolean_T UnitDelay1_DSTATE; /* '<S74>/UnitDelay1' */
} DW_PI_clamp_fixdt;
/* Block signals and states (auto storage) for system '<S61>/PI_clamp_fixdt' */
typedef struct {
int32_T ResettableDelay_DSTATE; /* '<S67>/Resettable Delay' */
uint8_T icLoad; /* '<S67>/Resettable Delay' */
boolean_T UnitDelay1_DSTATE; /* '<S65>/UnitDelay1' */
} DW_PI_clamp_fixdt_m;
/* Block signals and states (auto storage) for system '<S62>/PI_clamp_fixdt' */
typedef struct {
int16_T ResettableDelay_DSTATE; /* '<S72>/Resettable Delay' */
uint8_T icLoad; /* '<S72>/Resettable Delay' */
boolean_T UnitDelay1_DSTATE; /* '<S69>/UnitDelay1' */
} DW_PI_clamp_fixdt_g;
/* Block signals and states (auto storage) for system '<Root>' */
typedef struct {
DW_PI_clamp_fixdt_g PI_clamp_fixdt_kh;/* '<S62>/PI_clamp_fixdt' */
DW_PI_clamp_fixdt_m PI_clamp_fixdt_l4;/* '<S61>/PI_clamp_fixdt' */
DW_PI_clamp_fixdt PI_clamp_fixdt_i; /* '<S63>/PI_clamp_fixdt' */
DW_I_backCalc_fixdt I_backCalc_fixdt_j;/* '<S82>/I_backCalc_fixdt' */
DW_I_backCalc_fixdt I_backCalc_fixdt1;/* '<S83>/I_backCalc_fixdt1' */
DW_I_backCalc_fixdt I_backCalc_fixdt_i;/* '<S83>/I_backCalc_fixdt' */
DW_either_edge either_edge_i; /* '<S20>/either_edge' */
DW_Debounce_Filter Debounce_Filter_k;/* '<S20>/Debounce_Filter' */
DW_Low_Pass_Filter Low_Pass_Filter_m;/* '<S50>/Low_Pass_Filter' */
DW_Counter Counter_e; /* '<S13>/Counter' */
int32_T Divide1; /* '<S81>/Divide1' */
int32_T UnitDelay_DSTATE; /* '<S40>/UnitDelay' */
int16_T Gain4_e[3]; /* '<S57>/Gain4' */
int16_T DataTypeConversion[2]; /* '<S56>/Data Type Conversion' */
int16_T z_counterRawPrev; /* '<S17>/z_counterRawPrev' */
int16_T Merge; /* '<S59>/Merge' */
int16_T Switch1; /* '<S78>/Switch1' */
int16_T Vd_max1; /* '<S80>/Vd_max1' */
int16_T Gain3; /* '<S80>/Gain3' */
int16_T Vq_max_M1; /* '<S80>/Vq_max_M1' */
int16_T Gain5; /* '<S80>/Gain5' */
int16_T i_max; /* '<S80>/i_max' */
int16_T Divide1_n; /* '<S80>/Divide1' */
int16_T Gain1; /* '<S80>/Gain1' */
int16_T Gain4; /* '<S80>/Gain4' */
int16_T Switch2_i; /* '<S87>/Switch2' */
int16_T Switch2_o; /* '<S93>/Switch2' */
int16_T Switch2_a; /* '<S91>/Switch2' */
int16_T Divide3; /* '<S42>/Divide3' */
int16_T Merge1; /* '<S33>/Merge1' */
int16_T Abs1; /* '<S5>/Abs1' */
int16_T Abs5_h; /* '<S50>/Abs5' */
int16_T Divide11; /* '<S17>/Divide11' */
int16_T r_sin_M1; /* '<S52>/r_sin_M1' */
int16_T r_cos_M1; /* '<S52>/r_cos_M1' */
int16_T UnitDelay3_DSTATE; /* '<S13>/UnitDelay3' */
int16_T UnitDelay4_DSTATE; /* '<S17>/UnitDelay4' */
int16_T UnitDelay2_DSTATE; /* '<S17>/UnitDelay2' */
int16_T UnitDelay3_DSTATE_o; /* '<S17>/UnitDelay3' */
int16_T UnitDelay5_DSTATE; /* '<S17>/UnitDelay5' */
int16_T UnitDelay4_DSTATE_e; /* '<S13>/UnitDelay4' */
int16_T UnitDelay4_DSTATE_eu; /* '<S8>/UnitDelay4' */
int8_T Switch2_e; /* '<S12>/Switch2' */
int8_T UnitDelay2_DSTATE_b; /* '<S12>/UnitDelay2' */
int8_T If1_ActiveSubsystem; /* '<S7>/If1' */
int8_T If2_ActiveSubsystem; /* '<S7>/If2' */
int8_T If1_ActiveSubsystem_j; /* '<S47>/If1' */
int8_T SwitchCase_ActiveSubsystem; /* '<S59>/Switch Case' */
int8_T If1_ActiveSubsystem_a; /* '<S59>/If1' */
int8_T If1_ActiveSubsystem_o; /* '<S48>/If1' */
int8_T SwitchCase_ActiveSubsystem_d; /* '<S80>/Switch Case' */
int8_T If2_ActiveSubsystem_f; /* '<S33>/If2' */
int8_T If2_ActiveSubsystem_a; /* '<S45>/If2' */
uint8_T z_ctrlMod; /* '<S5>/F03_02_Control_Mode_Manager' */
uint8_T UnitDelay3_DSTATE_fy; /* '<S10>/UnitDelay3' */
uint8_T UnitDelay1_DSTATE; /* '<S10>/UnitDelay1' */
uint8_T UnitDelay2_DSTATE_f; /* '<S10>/UnitDelay2' */
uint8_T UnitDelay_DSTATE_e; /* '<S20>/UnitDelay' */
uint8_T is_active_c1_BLDC_controller;/* '<S5>/F03_02_Control_Mode_Manager' */
uint8_T is_c1_BLDC_controller; /* '<S5>/F03_02_Control_Mode_Manager' */
uint8_T is_ACTIVE; /* '<S5>/F03_02_Control_Mode_Manager' */
boolean_T Merge_p; /* '<S21>/Merge' */
boolean_T dz_cntTrnsDet; /* '<S17>/dz_cntTrnsDet' */
boolean_T UnitDelay2_DSTATE_c; /* '<S2>/UnitDelay2' */
boolean_T UnitDelay5_DSTATE_m; /* '<S2>/UnitDelay5' */
boolean_T UnitDelay6_DSTATE; /* '<S2>/UnitDelay6' */
boolean_T UnitDelay_DSTATE_b; /* '<S39>/UnitDelay' */
boolean_T UnitDelay1_DSTATE_n; /* '<S17>/UnitDelay1' */
boolean_T n_commDeacv_Mode; /* '<S13>/n_commDeacv' */
boolean_T dz_cntTrnsDet_Mode; /* '<S17>/dz_cntTrnsDet' */
} DW;
/* Constant parameters (auto storage) */
typedef struct {
/* Computed Parameter: r_sin_M1_Table
* Referenced by: '<S52>/r_sin_M1'
*/
int16_T r_sin_M1_Table[181];
/* Computed Parameter: r_cos_M1_Table
* Referenced by: '<S52>/r_cos_M1'
*/
int16_T r_cos_M1_Table[181];
/* Computed Parameter: r_sin3PhaA_M1_Table
* Referenced by: '<S96>/r_sin3PhaA_M1'
*/
int16_T r_sin3PhaA_M1_Table[181];
/* Computed Parameter: r_sin3PhaB_M1_Table
* Referenced by: '<S96>/r_sin3PhaB_M1'
*/
int16_T r_sin3PhaB_M1_Table[181];
/* Computed Parameter: r_sin3PhaC_M1_Table
* Referenced by: '<S96>/r_sin3PhaC_M1'
*/
int16_T r_sin3PhaC_M1_Table[181];
/* Computed Parameter: iq_maxSca_M1_Table
* Referenced by: '<S80>/iq_maxSca_M1'
*/
uint16_T iq_maxSca_M1_Table[50];
/* Computed Parameter: z_commutMap_M1_table
* Referenced by: '<S94>/z_commutMap_M1'
*/
int8_T z_commutMap_M1_table[18];
/* Computed Parameter: vec_hallToPos_Value
* Referenced by: '<S11>/vec_hallToPos'
*/
int8_T vec_hallToPos_Value[8];
} ConstP;
/* External inputs (root inport signals with auto storage) */
typedef struct {
boolean_T b_motEna; /* '<Root>/b_motEna' */
uint8_T z_ctrlModReq; /* '<Root>/z_ctrlModReq' */
int16_T r_inpTgt; /* '<Root>/r_inpTgt' */
uint8_T b_hallA; /* '<Root>/b_hallA ' */
uint8_T b_hallB; /* '<Root>/b_hallB' */
uint8_T b_hallC; /* '<Root>/b_hallC' */
int16_T i_phaAB; /* '<Root>/i_phaAB' */
int16_T i_phaBC; /* '<Root>/i_phaBC' */
int16_T i_DCLink; /* '<Root>/i_DCLink' */
int16_T a_mechAngle; /* '<Root>/a_mechAngle' */
} ExtU;
/* External outputs (root outports fed by signals with auto storage) */
typedef struct {
int16_T DC_phaA; /* '<Root>/DC_phaA' */
int16_T DC_phaB; /* '<Root>/DC_phaB' */
int16_T DC_phaC; /* '<Root>/DC_phaC' */
uint8_T z_errCode; /* '<Root>/z_errCode' */
int16_T n_mot; /* '<Root>/n_mot' */
int16_T a_elecAngle; /* '<Root>/a_elecAngle' */
int16_T iq; /* '<Root>/iq' */
int16_T id; /* '<Root>/id' */
} ExtY;
/* Parameters (auto storage) */
struct P_ {
int32_T dV_openRate; /* Variable: dV_openRate
* Referenced by: '<S37>/dV_openRate'
*/
int16_T dz_cntTrnsDetHi; /* Variable: dz_cntTrnsDetHi
* Referenced by: '<S17>/dz_cntTrnsDet'
*/
int16_T dz_cntTrnsDetLo; /* Variable: dz_cntTrnsDetLo
* Referenced by: '<S17>/dz_cntTrnsDet'
*/
int16_T n_cruiseMotTgt; /* Variable: n_cruiseMotTgt
* Referenced by: '<S61>/n_cruiseMotTgt'
*/
int16_T z_maxCntRst; /* Variable: z_maxCntRst
* Referenced by:
* '<S13>/Counter'
* '<S13>/z_maxCntRst'
* '<S13>/z_maxCntRst2'
* '<S13>/UnitDelay3'
* '<S17>/z_counter'
*/
uint16_T cf_speedCoef; /* Variable: cf_speedCoef
* Referenced by: '<S17>/cf_speedCoef'
*/
uint16_T t_errDequal; /* Variable: t_errDequal
* Referenced by: '<S20>/t_errDequal'
*/
uint16_T t_errQual; /* Variable: t_errQual
* Referenced by: '<S20>/t_errQual'
*/
int16_T Vd_max; /* Variable: Vd_max
* Referenced by:
* '<S36>/Vd_max'
* '<S80>/Vd_max1'
*/
int16_T Vq_max_M1[46]; /* Variable: Vq_max_M1
* Referenced by: '<S80>/Vq_max_M1'
*/
int16_T Vq_max_XA[46]; /* Variable: Vq_max_XA
* Referenced by: '<S80>/Vq_max_XA'
*/
int16_T a_phaAdvMax; /* Variable: a_phaAdvMax
* Referenced by: '<S42>/a_phaAdvMax'
*/
int16_T i_max; /* Variable: i_max
* Referenced by:
* '<S36>/i_max'
* '<S80>/i_max'
*/
int16_T id_fieldWeakMax; /* Variable: id_fieldWeakMax
* Referenced by: '<S42>/id_fieldWeakMax'
*/
int16_T n_commAcvLo; /* Variable: n_commAcvLo
* Referenced by: '<S13>/n_commDeacv'
*/
int16_T n_commDeacvHi; /* Variable: n_commDeacvHi
* Referenced by: '<S13>/n_commDeacv'
*/
int16_T n_fieldWeakAuthHi; /* Variable: n_fieldWeakAuthHi
* Referenced by: '<S42>/n_fieldWeakAuthHi'
*/
int16_T n_fieldWeakAuthLo; /* Variable: n_fieldWeakAuthLo
* Referenced by: '<S42>/n_fieldWeakAuthLo'
*/
int16_T n_max; /* Variable: n_max
* Referenced by:
* '<S36>/n_max'
* '<S80>/n_max1'
*/
int16_T n_stdStillDet; /* Variable: n_stdStillDet
* Referenced by: '<S13>/n_stdStillDet'
*/
int16_T r_errInpTgtThres; /* Variable: r_errInpTgtThres
* Referenced by: '<S20>/r_errInpTgtThres'
*/
int16_T r_fieldWeakHi; /* Variable: r_fieldWeakHi
* Referenced by: '<S42>/r_fieldWeakHi'
*/
int16_T r_fieldWeakLo; /* Variable: r_fieldWeakLo
* Referenced by: '<S42>/r_fieldWeakLo'
*/
uint16_T cf_KbLimProt; /* Variable: cf_KbLimProt
* Referenced by:
* '<S82>/cf_KbLimProt'
* '<S83>/cf_KbLimProt'
*/
uint16_T cf_idKp; /* Variable: cf_idKp
* Referenced by: '<S63>/cf_idKp1'
*/
uint16_T cf_iqKp; /* Variable: cf_iqKp
* Referenced by: '<S62>/cf_iqKp'
*/
uint16_T cf_nKp; /* Variable: cf_nKp
* Referenced by: '<S61>/cf_nKp'
*/
uint16_T cf_currFilt; /* Variable: cf_currFilt
* Referenced by: '<S50>/cf_currFilt'
*/
uint16_T cf_idKi; /* Variable: cf_idKi
* Referenced by: '<S63>/cf_idKi1'
*/
uint16_T cf_iqKi; /* Variable: cf_iqKi
* Referenced by: '<S62>/cf_iqKi'
*/
uint16_T cf_iqKiLimProt; /* Variable: cf_iqKiLimProt
* Referenced by:
* '<S81>/cf_iqKiLimProt'
* '<S83>/cf_iqKiLimProt'
*/
uint16_T cf_nKi; /* Variable: cf_nKi
* Referenced by: '<S61>/cf_nKi'
*/
uint16_T cf_nKiLimProt; /* Variable: cf_nKiLimProt
* Referenced by:
* '<S82>/cf_nKiLimProt'
* '<S83>/cf_nKiLimProt'
*/
uint8_T n_polePairs; /* Variable: n_polePairs
* Referenced by: '<S15>/n_polePairs'
*/
uint8_T z_ctrlTypSel; /* Variable: z_ctrlTypSel
* Referenced by: '<S1>/z_ctrlTypSel'
*/
uint8_T z_selPhaCurMeasABC; /* Variable: z_selPhaCurMeasABC
* Referenced by: '<S49>/z_selPhaCurMeasABC'
*/
boolean_T b_angleMeasEna; /* Variable: b_angleMeasEna
* Referenced by:
* '<S3>/b_angleMeasEna'
* '<S13>/b_angleMeasEna'
*/
boolean_T b_cruiseCtrlEna; /* Variable: b_cruiseCtrlEna
* Referenced by: '<S1>/b_cruiseCtrlEna'
*/
boolean_T b_diagEna; /* Variable: b_diagEna
* Referenced by: '<S4>/b_diagEna'
*/
boolean_T b_fieldWeakEna; /* Variable: b_fieldWeakEna
* Referenced by:
* '<S6>/b_fieldWeakEna'
* '<S97>/b_fieldWeakEna'
*/
};
/* Parameters (auto storage) */
typedef struct P_ P;
/* Real-time Model Data Structure */
struct tag_RTM {
P *defaultParam;
ExtU *inputs;
ExtY *outputs;
DW *dwork;
};
/* Constant parameters (auto storage) */
extern const ConstP rtConstP;
/* Model entry point functions */
extern void BLDC_controller_initialize(RT_MODEL *const rtM);
extern void BLDC_controller_step(RT_MODEL *const rtM);
#endif
@@ -0,0 +1,386 @@
/*
* File: BLDC_controller_data.c
*
* Code generated for Simulink model 'BLDC_controller'.
*
* Model version : 1.1297
* Simulink Coder version : 8.13 (R2017b) 24-Jul-2017
* C/C++ source code generated on : Sun Mar 6 11:02:11 2022
*
* Target selection: ert.tlc
* Embedded hardware selection: ARM Compatible->ARM Cortex
* Emulation hardware selection:
* Differs from embedded hardware (MATLAB Host)
* Code generation objectives:
* 1. Execution efficiency
* 2. RAM efficiency
* Validation result: Not run
*/
#include "BLDC_controller.h"
/* Constant parameters (auto storage) */
const ConstP rtConstP = {
/* Computed Parameter: r_sin_M1_Table
* Referenced by: '<S52>/r_sin_M1'
*/
{ 8192, 8682, 9162, 9630, 10087, 10531, 10963, 11381, 11786, 12176, 12551,
12911, 13255, 13583, 13894, 14189, 14466, 14726, 14968, 15191, 15396, 15582,
15749, 15897, 16026, 16135, 16225, 16294, 16344, 16374, 16384, 16374, 16344,
16294, 16225, 16135, 16026, 15897, 15749, 15582, 15396, 15191, 14968, 14726,
14466, 14189, 13894, 13583, 13255, 12911, 12551, 12176, 11786, 11381, 10963,
10531, 10087, 9630, 9162, 8682, 8192, 7692, 7182, 6664, 6138, 5604, 5063,
4516, 3964, 3406, 2845, 2280, 1713, 1143, 572, 0, -572, -1143, -1713, -2280,
-2845, -3406, -3964, -4516, -5063, -5604, -6138, -6664, -7182, -7692, -8192,
-8682, -9162, -9630, -10087, -10531, -10963, -11381, -11786, -12176, -12551,
-12911, -13255, -13583, -13894, -14189, -14466, -14726, -14968, -15191,
-15396, -15582, -15749, -15897, -16026, -16135, -16225, -16294, -16344,
-16374, -16384, -16374, -16344, -16294, -16225, -16135, -16026, -15897,
-15749, -15582, -15396, -15191, -14968, -14726, -14466, -14189, -13894,
-13583, -13255, -12911, -12551, -12176, -11786, -11381, -10963, -10531,
-10087, -9630, -9162, -8682, -8192, -7692, -7182, -6664, -6138, -5604, -5063,
-4516, -3964, -3406, -2845, -2280, -1713, -1143, -572, 0, 572, 1143, 1713,
2280, 2845, 3406, 3964, 4516, 5063, 5604, 6138, 6664, 7182, 7692, 8192 },
/* Computed Parameter: r_cos_M1_Table
* Referenced by: '<S52>/r_cos_M1'
*/
{ 14189, 13894, 13583, 13255, 12911, 12551, 12176, 11786, 11381, 10963, 10531,
10087, 9630, 9162, 8682, 8192, 7692, 7182, 6664, 6138, 5604, 5063, 4516,
3964, 3406, 2845, 2280, 1713, 1143, 572, 0, -572, -1143, -1713, -2280, -2845,
-3406, -3964, -4516, -5063, -5604, -6138, -6664, -7182, -7692, -8192, -8682,
-9162, -9630, -10087, -10531, -10963, -11381, -11786, -12176, -12551, -12911,
-13255, -13583, -13894, -14189, -14466, -14726, -14968, -15191, -15396,
-15582, -15749, -15897, -16026, -16135, -16225, -16294, -16344, -16374,
-16384, -16374, -16344, -16294, -16225, -16135, -16026, -15897, -15749,
-15582, -15396, -15191, -14968, -14726, -14466, -14189, -13894, -13583,
-13255, -12911, -12551, -12176, -11786, -11381, -10963, -10531, -10087,
-9630, -9162, -8682, -8192, -7692, -7182, -6664, -6138, -5604, -5063, -4516,
-3964, -3406, -2845, -2280, -1713, -1143, -572, 0, 572, 1143, 1713, 2280,
2845, 3406, 3964, 4516, 5063, 5604, 6138, 6664, 7182, 7692, 8192, 8682, 9162,
9630, 10087, 10531, 10963, 11381, 11786, 12176, 12551, 12911, 13255, 13583,
13894, 14189, 14466, 14726, 14968, 15191, 15396, 15582, 15749, 15897, 16026,
16135, 16225, 16294, 16344, 16374, 16384, 16374, 16344, 16294, 16225, 16135,
16026, 15897, 15749, 15582, 15396, 15191, 14968, 14726, 14466, 14189 },
/* Computed Parameter: r_sin3PhaA_M1_Table
* Referenced by: '<S96>/r_sin3PhaA_M1'
*/
{ -13091, -13634, -14126, -14565, -14953, -15289, -15577, -15816, -16009,
-16159, -16269, -16340, -16377, -16383, -16362, -16317, -16253, -16172,
-16079, -15977, -15870, -15762, -15656, -15555, -15461, -15377, -15306,
-15248, -15206, -15180, -15172, -15180, -15206, -15248, -15306, -15377,
-15461, -15555, -15656, -15762, -15870, -15977, -16079, -16172, -16253,
-16317, -16362, -16383, -16377, -16340, -16269, -16159, -16009, -15816,
-15577, -15289, -14953, -14565, -14126, -13634, -13091, -12496, -11849,
-11154, -10411, -9623, -8791, -7921, -7014, -6075, -5107, -4115, -3104,
-2077, -1041, 0, 1041, 2077, 3104, 4115, 5107, 6075, 7014, 7921, 8791, 9623,
10411, 11154, 11849, 12496, 13091, 13634, 14126, 14565, 14953, 15289, 15577,
15816, 16009, 16159, 16269, 16340, 16377, 16383, 16362, 16317, 16253, 16172,
16079, 15977, 15870, 15762, 15656, 15555, 15461, 15377, 15306, 15248, 15206,
15180, 15172, 15180, 15206, 15248, 15306, 15377, 15461, 15555, 15656, 15762,
15870, 15977, 16079, 16172, 16253, 16317, 16362, 16383, 16377, 16340, 16269,
16159, 16009, 15816, 15577, 15289, 14953, 14565, 14126, 13634, 13091, 12496,
11849, 11154, 10411, 9623, 8791, 7921, 7014, 6075, 5107, 4115, 3104, 2077,
1041, 0, -1041, -2077, -3104, -4115, -5107, -6075, -7014, -7921, -8791,
-9623, -10411, -11154, -11849, -12496, -13091 },
/* Computed Parameter: r_sin3PhaB_M1_Table
* Referenced by: '<S96>/r_sin3PhaB_M1'
*/
{ 15172, 15180, 15206, 15248, 15306, 15377, 15461, 15555, 15656, 15762, 15870,
15977, 16079, 16172, 16253, 16317, 16362, 16383, 16377, 16340, 16269, 16159,
16009, 15816, 15577, 15289, 14953, 14565, 14126, 13634, 13091, 12496, 11849,
11154, 10411, 9623, 8791, 7921, 7014, 6075, 5107, 4115, 3104, 2077, 1041, 0,
-1041, -2077, -3104, -4115, -5107, -6075, -7014, -7921, -8791, -9623, -10411,
-11154, -11849, -12496, -13091, -13634, -14126, -14565, -14953, -15289,
-15577, -15816, -16009, -16159, -16269, -16340, -16377, -16383, -16362,
-16317, -16253, -16172, -16079, -15977, -15870, -15762, -15656, -15555,
-15461, -15377, -15306, -15248, -15206, -15180, -15172, -15180, -15206,
-15248, -15306, -15377, -15461, -15555, -15656, -15762, -15870, -15977,
-16079, -16172, -16253, -16317, -16362, -16383, -16377, -16340, -16269,
-16159, -16009, -15816, -15577, -15289, -14953, -14565, -14126, -13634,
-13091, -12496, -11849, -11154, -10411, -9623, -8791, -7921, -7014, -6075,
-5107, -4115, -3104, -2077, -1041, 0, 1041, 2077, 3104, 4115, 5107, 6075,
7014, 7921, 8791, 9623, 10411, 11154, 11849, 12496, 13091, 13634, 14126,
14565, 14953, 15289, 15577, 15816, 16009, 16159, 16269, 16340, 16377, 16383,
16362, 16317, 16253, 16172, 16079, 15977, 15870, 15762, 15656, 15555, 15461,
15377, 15306, 15248, 15206, 15180, 15172 },
/* Computed Parameter: r_sin3PhaC_M1_Table
* Referenced by: '<S96>/r_sin3PhaC_M1'
*/
{ -13091, -12496, -11849, -11154, -10411, -9623, -8791, -7921, -7014, -6075,
-5107, -4115, -3104, -2077, -1041, 0, 1041, 2077, 3104, 4115, 5107, 6075,
7014, 7921, 8791, 9623, 10411, 11154, 11849, 12496, 13091, 13634, 14126,
14565, 14953, 15289, 15577, 15816, 16009, 16159, 16269, 16340, 16377, 16383,
16362, 16317, 16253, 16172, 16079, 15977, 15870, 15762, 15656, 15555, 15461,
15377, 15306, 15248, 15206, 15180, 15172, 15180, 15206, 15248, 15306, 15377,
15461, 15555, 15656, 15762, 15870, 15977, 16079, 16172, 16253, 16317, 16362,
16383, 16377, 16340, 16269, 16159, 16009, 15816, 15577, 15289, 14953, 14565,
14126, 13634, 13091, 12496, 11849, 11154, 10411, 9623, 8791, 7921, 7014,
6075, 5107, 4115, 3104, 2077, 1041, 0, -1041, -2077, -3104, -4115, -5107,
-6075, -7014, -7921, -8791, -9623, -10411, -11154, -11849, -12496, -13091,
-13634, -14126, -14565, -14953, -15289, -15577, -15816, -16009, -16159,
-16269, -16340, -16377, -16383, -16362, -16317, -16253, -16172, -16079,
-15977, -15870, -15762, -15656, -15555, -15461, -15377, -15306, -15248,
-15206, -15180, -15172, -15180, -15206, -15248, -15306, -15377, -15461,
-15555, -15656, -15762, -15870, -15977, -16079, -16172, -16253, -16317,
-16362, -16383, -16377, -16340, -16269, -16159, -16009, -15816, -15577,
-15289, -14953, -14565, -14126, -13634, -13091 },
/* Computed Parameter: iq_maxSca_M1_Table
* Referenced by: '<S80>/iq_maxSca_M1'
*/
{ 65535U, 65523U, 65484U, 65418U, 65326U, 65207U, 65062U, 64890U, 64691U,
64465U, 64211U, 63930U, 63620U, 63281U, 62913U, 62516U, 62088U, 61630U,
61140U, 60618U, 60062U, 59473U, 58848U, 58187U, 57489U, 56752U, 55974U,
55155U, 54291U, 53381U, 52422U, 51413U, 50349U, 49227U, 48043U, 46792U,
45470U, 44069U, 42581U, 40997U, 39307U, 37494U, 35541U, 33422U, 31105U,
28540U, 25655U, 22323U, 18304U, 12974U },
/* Computed Parameter: z_commutMap_M1_table
* Referenced by: '<S94>/z_commutMap_M1'
*/
{ -1, 1, 0, -1, 0, 1, 0, -1, 1, 1, -1, 0, 1, 0, -1, 0, 1, -1 },
/* Computed Parameter: vec_hallToPos_Value
* Referenced by: '<S11>/vec_hallToPos'
*/
{ 0, 2, 0, 1, 4, 3, 5, 0 }
};
P rtP_Left = {
/* Variable: dV_openRate
* Referenced by: '<S37>/dV_openRate'
*/
12288,
/* Variable: dz_cntTrnsDetHi
* Referenced by: '<S17>/dz_cntTrnsDet'
*/
40,
/* Variable: dz_cntTrnsDetLo
* Referenced by: '<S17>/dz_cntTrnsDet'
*/
20,
/* Variable: n_cruiseMotTgt
* Referenced by: '<S61>/n_cruiseMotTgt'
*/
0,
/* Variable: z_maxCntRst
* Referenced by:
* '<S13>/Counter'
* '<S13>/z_maxCntRst'
* '<S13>/z_maxCntRst2'
* '<S13>/UnitDelay3'
* '<S17>/z_counter'
*/
2000,
/* Variable: cf_speedCoef
* Referenced by: '<S17>/cf_speedCoef'
*/
5334U,
/* Variable: t_errDequal
* Referenced by: '<S20>/t_errDequal'
*/
9600U,
/* Variable: t_errQual
* Referenced by: '<S20>/t_errQual'
*/
1280U,
/* Variable: Vd_max
* Referenced by:
* '<S36>/Vd_max'
* '<S80>/Vd_max1'
*/
14400,
/* Variable: Vq_max_M1
* Referenced by: '<S80>/Vq_max_M1'
*/
{ 14400, 14396, 14386, 14368, 14343, 14311, 14271, 14225, 14171, 14109, 14040,
13963, 13879, 13786, 13685, 13576, 13459, 13333, 13198, 13053, 12900, 12736,
12562, 12377, 12181, 11973, 11753, 11520, 11273, 11011, 10733, 10438, 10124,
9790, 9433, 9051, 8640, 8196, 7713, 7184, 6597, 5935, 5170, 4245, 3019, 0 },
/* Variable: Vq_max_XA
* Referenced by: '<S80>/Vq_max_XA'
*/
{ 0, 320, 640, 960, 1280, 1600, 1920, 2240, 2560, 2880, 3200, 3520, 3840, 4160,
4480, 4800, 5120, 5440, 5760, 6080, 6400, 6720, 7040, 7360, 7680, 8000, 8320,
8640, 8960, 9280, 9600, 9920, 10240, 10560, 10880, 11200, 11520, 11840,
12160, 12480, 12800, 13120, 13440, 13760, 14080, 14400 },
/* Variable: a_phaAdvMax
* Referenced by: '<S42>/a_phaAdvMax'
*/
400,
/* Variable: i_max
* Referenced by:
* '<S36>/i_max'
* '<S80>/i_max'
*/
30000,
/* Variable: id_fieldWeakMax
* Referenced by: '<S42>/id_fieldWeakMax'
*/
4000,
/* Variable: n_commAcvLo
* Referenced by: '<S13>/n_commDeacv'
*/
240,
/* Variable: n_commDeacvHi
* Referenced by: '<S13>/n_commDeacv'
*/
480,
/* Variable: n_fieldWeakAuthHi
* Referenced by: '<S42>/n_fieldWeakAuthHi'
*/
6400,
/* Variable: n_fieldWeakAuthLo
* Referenced by: '<S42>/n_fieldWeakAuthLo'
*/
4800,
/* Variable: n_max
* Referenced by:
* '<S36>/n_max'
* '<S80>/n_max1'
*/
32000,
/* Variable: n_stdStillDet
* Referenced by: '<S13>/n_stdStillDet'
*/
48,
/* Variable: r_errInpTgtThres
* Referenced by: '<S20>/r_errInpTgtThres'
*/
9600,
/* Variable: r_fieldWeakHi
* Referenced by: '<S42>/r_fieldWeakHi'
*/
16000,
/* Variable: r_fieldWeakLo
* Referenced by: '<S42>/r_fieldWeakLo'
*/
12000,
/* Variable: cf_KbLimProt
* Referenced by:
* '<S82>/cf_KbLimProt'
* '<S83>/cf_KbLimProt'
*/
768U,
/* Variable: cf_idKp
* Referenced by: '<S63>/cf_idKp1'
*/
1638U,
/* Variable: cf_iqKp
* Referenced by: '<S62>/cf_iqKp'
*/
2458U,
/* Variable: cf_nKp
* Referenced by: '<S61>/cf_nKp'
*/
9666U,
/* Variable: cf_currFilt
* Referenced by: '<S50>/cf_currFilt'
*/
7864U,
/* Variable: cf_idKi
* Referenced by: '<S63>/cf_idKi1'
*/
1474U,
/* Variable: cf_iqKi
* Referenced by: '<S62>/cf_iqKi'
*/
2458U,
/* Variable: cf_iqKiLimProt
* Referenced by:
* '<S81>/cf_iqKiLimProt'
* '<S83>/cf_iqKiLimProt'
*/
1474U,
/* Variable: cf_nKi
* Referenced by: '<S61>/cf_nKi'
*/
502U,
/* Variable: cf_nKiLimProt
* Referenced by:
* '<S82>/cf_nKiLimProt'
* '<S83>/cf_nKiLimProt'
*/
492U,
/* Variable: n_polePairs
* Referenced by: '<S15>/n_polePairs'
*/
15U,
/* Variable: z_ctrlTypSel
* Referenced by: '<S1>/z_ctrlTypSel'
*/
2U,
/* Variable: z_selPhaCurMeasABC
* Referenced by: '<S49>/z_selPhaCurMeasABC'
*/
0U,
/* Variable: b_angleMeasEna
* Referenced by:
* '<S3>/b_angleMeasEna'
* '<S13>/b_angleMeasEna'
*/
0,
/* Variable: b_cruiseCtrlEna
* Referenced by: '<S1>/b_cruiseCtrlEna'
*/
0,
/* Variable: b_diagEna
* Referenced by: '<S4>/b_diagEna'
*/
1,
/* Variable: b_fieldWeakEna
* Referenced by:
* '<S6>/b_fieldWeakEna'
* '<S97>/b_fieldWeakEna'
*/
0
}; /* Modifiable parameters */
/*
* File trailer for generated code.
*
* [EOF]
*/
+311
View File
@@ -0,0 +1,311 @@
#ifndef BLDC_H
#define BLDC_H
#include "board/body/bldc/bldc_defs.h"
#include "board/body/boards/board_declarations.h"
#include <stdint.h>
#include <stdbool.h>
#include "board/stm32h7/lladc.h"
// Matlab includes and defines - from auto-code generation
#include "BLDC_controller.h" /* Model's header file */
#include "BLDC_controller.c"
#include "BLDC_controller_data.c"
#include "rtwtypes.h"
static RT_MODEL rtM_Left_Obj;
static RT_MODEL rtM_Right_Obj;
RT_MODEL *const rtM_Left = &rtM_Left_Obj;
RT_MODEL *const rtM_Right = &rtM_Right_Obj;
static DW rtDW_Left; /* Observable states */
static ExtU rtU_Left; /* External inputs */
static ExtY rtY_Left; /* External outputs */
extern P rtP_Left; // This is defined in BLDC_controller_data.c
static DW rtDW_Right; /* Observable states */
static ExtU rtU_Right; /* External inputs */
static ExtY rtY_Right; /* External outputs */
static P rtP_Right; /* Parameters */
//static int16_t curDC_max = (I_DC_MAX * A2BIT_CONV);
static int16_t curL_phaA = 0, curL_phaC = 0, curL_DC = 0;
static int16_t curR_phaA = 0, curR_phaC = 0, curR_DC = 0;
volatile uint16_t batt_voltage_raw = 0;
volatile uint16_t batt_percentage = 0;
volatile int rpm_left = 0;
volatile int rpm_right = 0;
volatile bool enable_motors = 0; // initially motors are disabled for safety
static bool enableFin = 0;
static const uint16_t pwm_res = ( (uint32_t)CORE_FREQ * 1000000U / 2U ) / PWM_FREQ;
static uint16_t offsetcount = 0;
static uint32_t offsetrlA = 0;
static uint32_t offsetrlC = 0;
static uint32_t offsetrrA = 0;
static uint32_t offsetrrC = 0;
static uint32_t offsetdcl = 0;
static uint32_t offsetdcr = 0;
#define ADC_CHANNEL_BLDC(a, c) {.adc = (a), .channel = (c), .sample_time = SAMPLETIME_16_CYCLES, .oversampling = OVERSAMPLING_4}
const adc_signal_t adc_curL_phaA = ADC_CHANNEL_BLDC(ADC2, 10);
const adc_signal_t adc_curL_phaC = ADC_CHANNEL_BLDC(ADC2, 11);
const adc_signal_t adc_curL_DC = ADC_CHANNEL_BLDC(ADC2, 18);
const adc_signal_t adc_curR_phaA = ADC_CHANNEL_BLDC(ADC1, 7);
const adc_signal_t adc_curR_phaC = ADC_CHANNEL_BLDC(ADC1, 15);
const adc_signal_t adc_curR_DC = ADC_CHANNEL_BLDC(ADC1, 5);
const adc_signal_t adc_batVoltage = ADC_CHANNEL_BLDC(ADC1, 4);
void motor_set_enable(bool enable) {
enable_motors = enable;
}
float motor_encoder_get_speed_rpm(uint8_t motor) {
float speed_rpm = 0.0f;
if (motor == BODY_MOTOR_LEFT) {
speed_rpm = (float)rtY_Left.n_mot;
} else if (motor == BODY_MOTOR_RIGHT) {
speed_rpm = (float)rtY_Right.n_mot;
}
if (ABS(speed_rpm) < RPM_DEADBAND) {
speed_rpm = 0.0f;
}
return speed_rpm;
}
void bldc_init(void) {
adc_init(ADC1);
adc_init(ADC2);
// Initialize Hall Sensors for Left Motor (PB6, PB7, PB8)
set_gpio_mode(GPIOB, 6, MODE_INPUT); set_gpio_pullup(GPIOB, 6, PULL_UP);
set_gpio_mode(GPIOB, 7, MODE_INPUT); set_gpio_pullup(GPIOB, 7, PULL_UP);
set_gpio_mode(GPIOB, 8, MODE_INPUT); set_gpio_pullup(GPIOB, 8, PULL_UP);
// Initialize Hall Sensors for Right Motor (PA0, PA1, PA2)
set_gpio_mode(GPIOA, 0, MODE_INPUT); set_gpio_pullup(GPIOA, 0, PULL_UP);
set_gpio_mode(GPIOA, 1, MODE_INPUT); set_gpio_pullup(GPIOA, 1, PULL_UP);
set_gpio_mode(GPIOA, 2, MODE_INPUT); set_gpio_pullup(GPIOA, 2, PULL_UP);
// Setup the model pointers for Left motor
rtM_Left->defaultParam = &rtP_Left;
rtM_Left->inputs = &rtU_Left;
rtM_Left->outputs = &rtY_Left;
rtM_Left->dwork = &rtDW_Left;
BLDC_controller_initialize(rtM_Left);
/* Set BLDC controller parameters */
rtP_Left.b_angleMeasEna = 0; // Motor angle input: 0 = estimated angle, 1 = measured angle
rtP_Left.z_selPhaCurMeasABC = 2; // Left motor measured current phases {Green, Blue} = {iA, iB}
rtP_Left.z_ctrlTypSel = CTRL_TYP_SEL;
rtP_Left.b_diagEna = DIAG_ENA;
rtP_Left.i_max = (int16_t)(I_MOT_MAX * A2BIT_CONV) << 4;
rtP_Left.n_max = N_MOT_MAX << 4;
rtP_Left.b_fieldWeakEna = FIELD_WEAK_ENA;
rtP_Left.id_fieldWeakMax = (int16_t)(FIELD_WEAK_MAX * A2BIT_CONV) << 4;
rtP_Left.a_phaAdvMax = PHASE_ADV_MAX << 4;
rtP_Left.r_fieldWeakHi = FIELD_WEAK_HI << 4;
rtP_Left.r_fieldWeakLo = FIELD_WEAK_LO << 4;
rtP_Left.z_maxCntRst = 4000;
rtP_Left.cf_speedCoef = CF_SPEED_COEF;
rtP_Left.t_errQual = 1280U; // 80ms at 16kHz loop rate
rtP_Left.t_errDequal = T_ERR_DEQUAL_CYCLES;
// Setup the model pointers for Right motor
rtP_Right = rtP_Left; // copy parameters
// Right motor measured current phases A & C (based on adc_curR_phaA/C definitions)
rtP_Right.z_selPhaCurMeasABC = 2;
rtM_Right->defaultParam = &rtP_Right;
rtM_Right->inputs = &rtU_Right;
rtM_Right->outputs = &rtY_Right;
rtM_Right->dwork = &rtDW_Right;
BLDC_controller_initialize(rtM_Right);
// Initialize GPIOs for Motor Control
// Left Motor (TIM1): PE8(CH1N), PE9(CH1), PE10(CH2N), PE11(CH2), PE12(CH3N), PE13(CH3)
set_gpio_alternate(GPIOE, 8, GPIO_AF1_TIM1);
set_gpio_alternate(GPIOE, 9, GPIO_AF1_TIM1);
set_gpio_alternate(GPIOE, 10, GPIO_AF1_TIM1);
set_gpio_alternate(GPIOE, 11, GPIO_AF1_TIM1);
set_gpio_alternate(GPIOE, 12, GPIO_AF1_TIM1);
set_gpio_alternate(GPIOE, 13, GPIO_AF1_TIM1);
// Right Motor (TIM8): PC6(CH1), PC7(CH2), PC8(CH3), PA5(CH1N), PB14(CH2N), PB15(CH3N)
set_gpio_alternate(GPIOC, 6, GPIO_AF3_TIM8);
set_gpio_alternate(GPIOC, 7, GPIO_AF3_TIM8);
set_gpio_alternate(GPIOC, 8, GPIO_AF3_TIM8);
set_gpio_alternate(GPIOA, 5, GPIO_AF3_TIM8);
set_gpio_alternate(GPIOB, 14, GPIO_AF3_TIM8);
set_gpio_alternate(GPIOB, 15, GPIO_AF3_TIM8);
// --- LEFT MOTOR (TIM1) ---
// TIM8 is an advanced control timer. We configure it for 3-phase center-aligned PWM.
LEFT_TIM->PSC = 0;
LEFT_TIM->ARR = pwm_res; // Set auto-reload register for PWM_FREQ
LEFT_TIM->CR1 = TIM_CR1_CMS_0; // Center-aligned mode 1
LEFT_TIM->RCR = 1; // Update event once per 2 PWM periods (16kHz)
// Configure channel 1, 2, 3 as PWM mode 1, with preload enabled
LEFT_TIM->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1PE | \
TIM_CCMR1_OC2M_2 | TIM_CCMR1_OC2M_1 | TIM_CCMR1_OC2PE;
LEFT_TIM->CCMR2 = TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3PE;
// Enable complementary outputs for channels 1, 2, 3
LEFT_TIM->CCER = TIM_CCER_CC1E | TIM_CCER_CC1NE | \
TIM_CCER_CC2E | TIM_CCER_CC2NE | \
TIM_CCER_CC3E | TIM_CCER_CC3NE;
// --- RIGHT MOTOR (TIM8) ---
RIGHT_TIM->PSC = 0;
RIGHT_TIM->ARR = pwm_res;
RIGHT_TIM->CR1 = TIM_CR1_CMS_0;
RIGHT_TIM->RCR = 1;
RIGHT_TIM->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1PE | \
TIM_CCMR1_OC2M_2 | TIM_CCMR1_OC2M_1 | TIM_CCMR1_OC2PE;
RIGHT_TIM->CCMR2 = TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3PE;
RIGHT_TIM->CCER = TIM_CCER_CC1E | TIM_CCER_CC1NE | \
TIM_CCER_CC2E | TIM_CCER_CC2NE | \
TIM_CCER_CC3E | TIM_CCER_CC3NE;
// Set dead time (20 cycles -> ~166ns with 120MHz clock) and enable motor outputs
LEFT_TIM->BDTR = 20U | TIM_BDTR_MOE;
RIGHT_TIM->BDTR = 20U | TIM_BDTR_MOE;
// Generate an update event to load the registers
LEFT_TIM->EGR = TIM_EGR_UG;
RIGHT_TIM->EGR = TIM_EGR_UG;
// Enable TIM8 update interrupt for bldc_step
LEFT_TIM->DIER |= TIM_DIER_UIE;
// Start the timers
LEFT_TIM->CR1 |= TIM_CR1_CEN;
RIGHT_TIM->CR1 |= TIM_CR1_CEN;
}
void bldc_step(void) {
// Calibrate ADC offsets for the first few cycles
if(offsetcount < 2000) { // calibrate ADC offsets
offsetcount++;
uint32_t rawL_A = adc_get_raw(&adc_curL_phaA);
uint32_t rawL_C = adc_get_raw(&adc_curL_phaC);
uint32_t rawR_A = adc_get_raw(&adc_curR_phaA);
uint32_t rawR_C = adc_get_raw(&adc_curR_phaC);
uint32_t rawL_DC = adc_get_raw(&adc_curL_DC);
uint32_t rawR_DC = adc_get_raw(&adc_curR_DC);
if (offsetcount == 1) {
offsetrlA = rawL_A; offsetrlC = rawL_C;
offsetrrA = rawR_A; offsetrrC = rawR_C;
offsetdcl = rawL_DC; offsetdcr = rawR_DC;
} else {
offsetrlA = (rawL_A + offsetrlA) / 2;
offsetrlC = (rawL_C + offsetrlC) / 2;
offsetrrA = (rawR_A + offsetrrA) / 2;
offsetrrC = (rawR_C + offsetrrC) / 2;
offsetdcl = (rawL_DC + offsetdcl) / 2;
offsetdcr = (rawR_DC + offsetdcr) / 2;
}
return;
}
// Get Left motor currents
curL_phaA = (int16_t)(((int32_t)offsetrlA - (int32_t)adc_get_raw(&adc_curL_phaA)) >> 5);
curL_phaC = (int16_t)(((int32_t)offsetrlC - (int32_t)adc_get_raw(&adc_curL_phaC)) >> 5);
curL_DC = (int16_t)(((int32_t)offsetdcl - (int32_t)adc_get_raw(&adc_curL_DC)) >> 4);
// Get Right motor currents
curR_phaA = (int16_t)(((int32_t)offsetrrA - (int32_t)adc_get_raw(&adc_curR_phaA)) >> 5);
curR_phaC = (int16_t)(((int32_t)offsetrrC - (int32_t)adc_get_raw(&adc_curR_phaC)) >> 5);
curR_DC = (int16_t)(((int32_t)offsetdcr - (int32_t)adc_get_raw(&adc_curR_DC)) >> 4);
// Safety: Don't enable if offsets are bogus (e.g. ADC failed)
if (offsetrrA == 0 || offsetrrC == 0 || !enable_motors) {
enableFin = 0;
} else {
enableFin = 1;
}
// Read Hall Sensors
rtU_Left.b_hallA = !((GPIOB->IDR >> 6) & 1);
rtU_Left.b_hallB = !((GPIOB->IDR >> 7) & 1);
rtU_Left.b_hallC = !((GPIOB->IDR >> 8) & 1);
rtU_Right.b_hallA = !((GPIOA->IDR >> 0) & 1);
rtU_Right.b_hallB = !((GPIOA->IDR >> 1) & 1);
rtU_Right.b_hallC = !((GPIOA->IDR >> 2) & 1);
if (!enableFin) {
LEFT_TIM->BDTR &= ~TIM_BDTR_MOE;
RIGHT_TIM->BDTR &= ~TIM_BDTR_MOE;
} else {
LEFT_TIM->BDTR |= TIM_BDTR_MOE;
RIGHT_TIM->BDTR |= TIM_BDTR_MOE;
}
// read battery voltage
batt_voltage_raw = adc_get_raw(&adc_batVoltage);
int16_t batVoltageCalib = batt_voltage_raw * BAT_CALIB_REAL_VOLTAGE / BAT_CALIB_ADC;
batt_percentage = 100 - (((420 * BAT_CELLS) - batVoltageCalib) / BAT_CELLS / VOLTS_PER_PERCENT / 100);
// ========================= LEFT MOTOR ===========================
rtU_Left.b_motEna = enableFin;
rtU_Left.z_ctrlModReq = CTRL_MOD_REQ; // Speed Mode
int deadband_rpm_left = rpm_left;
if (ABS(deadband_rpm_left) < RPM_DEADBAND) {
deadband_rpm_left = 0;
}
rtU_Left.r_inpTgt = (CLAMP((int)deadband_rpm_left, -MAX_RPM, MAX_RPM) * RPM_TO_UNIT);
rtU_Left.i_phaAB = curL_phaA;
rtU_Left.i_phaBC = curL_phaC;
rtU_Left.i_DCLink = curL_DC;
BLDC_controller_step(rtM_Left);
int ul = rtY_Left.DC_phaA;
int vl = rtY_Left.DC_phaB;
int wl = rtY_Left.DC_phaC;
LEFT_TIM->CCR1 = (uint16_t)CLAMP((ul + pwm_res / 2), PWM_MARGIN, pwm_res - PWM_MARGIN);
LEFT_TIM->CCR2 = (uint16_t)CLAMP((vl + pwm_res / 2), PWM_MARGIN, pwm_res - PWM_MARGIN);
LEFT_TIM->CCR3 = (uint16_t)CLAMP((wl + pwm_res / 2), PWM_MARGIN, pwm_res - PWM_MARGIN);
// ========================= RIGHT MOTOR ===========================
rtU_Right.b_motEna = enableFin;
rtU_Right.z_ctrlModReq = CTRL_MOD_REQ; // Speed Mode
int deadband_rpm_right = rpm_right;
if (ABS(deadband_rpm_right) < RPM_DEADBAND) {
deadband_rpm_right = 0;
}
rtU_Right.r_inpTgt = -(CLAMP((int)deadband_rpm_right, -MAX_RPM, MAX_RPM) * RPM_TO_UNIT);
rtU_Right.i_phaAB = curR_phaA;
rtU_Right.i_phaBC = curR_phaC;
rtU_Right.i_DCLink = curR_DC;
BLDC_controller_step(rtM_Right);
int ur = rtY_Right.DC_phaA;
int vr = rtY_Right.DC_phaB;
int wr = rtY_Right.DC_phaC;
RIGHT_TIM->CCR1 = (uint16_t)CLAMP((ur + pwm_res / 2), PWM_MARGIN, pwm_res - PWM_MARGIN);
RIGHT_TIM->CCR2 = (uint16_t)CLAMP((vr + pwm_res / 2), PWM_MARGIN, pwm_res - PWM_MARGIN);
RIGHT_TIM->CCR3 = (uint16_t)CLAMP((wr + pwm_res / 2), PWM_MARGIN, pwm_res - PWM_MARGIN);
}
#endif
+56
View File
@@ -0,0 +1,56 @@
#ifndef BLDC_DEFS_H
#define BLDC_DEFS_H
#include "stm32h7xx.h" // For GPIO_TypeDef
#define COM_CTRL 0 // [-] Commutation Control Type
#define SIN_CTRL 1 // [-] Sinusoidal Control Type
#define FOC_CTRL 2 // [-] Field Oriented Control (FOC) Type
#define LEFT_TIM TIM8
#define RIGHT_TIM TIM1
#define PWM_FREQ 32000
#define PWM_MARGIN 100
#define CF_SPEED_COEF (PWM_FREQ / 3)
#define MAX_RPM 1000
#define RPM_TO_UNIT 16
#define RPM_DEADBAND 1
#define BODY_MOTOR_LEFT 1U
#define BODY_MOTOR_RIGHT 2U
// Stall detection recovery time. Time to wait after a stall before re-enabling controls.
#define STALL_DEQUAL_TIME_MS 3000
#define T_ERR_DEQUAL_CYCLES (uint16_t)(STALL_DEQUAL_TIME_MS * (PWM_FREQ / 2) / 1000)
// Motor
#define I_DC_MAX 6
#define I_MOT_MAX 6
#define A2BIT_CONV 310
#define N_MOT_MAX 1000
// Control selections
#define CTRL_TYP_SEL FOC_CTRL // [-] Control type selection: COM_CTRL, SIN_CTRL, FOC_CTRL (default)
#define CTRL_MOD_REQ SPD_MODE // [-] Control mode request: OPEN_MODE, VLT_MODE (default), SPD_MODE, TRQ_MODE. Note: SPD_MODE and TRQ_MODE are only available for CTRL_FOC!
#define DIAG_ENA 1 // [-] Motor Diagnostics enable flag: 0 = Disabled, 1 = Enabled (default)
// Field Weakening / Phase Advance
#define FIELD_WEAK_ENA 1 // [-] Field Weakening / Phase Advance enable flag: 0 = Disabled (default), 1 = Enabled
#define FIELD_WEAK_MAX 5 // [A] Maximum Field Weakening D axis current (only for FOC).
#define PHASE_ADV_MAX 25 // [deg] Maximum Phase Advance angle (only for SIN).
#define FIELD_WEAK_HI 1000 // Input target High threshold
#define FIELD_WEAK_LO 750 // Input target Low threshold
// Battery configuration
#define BAT_CELLS 3 // 3 sets in series
#define BAT_CELL_FULL_MV 4200U // mV per cell at 100%
#define BAT_CELL_EMPTY_MV 3386U // mV per cell at 0% (from V1: 4200 - 100 * 8.14)
#define VOLTS_PER_PERCENT 0.00814 // Volts per percent, for conversion of volts to percentage
#define BAT_CALIB_REAL_VOLTAGE 1260U // multimeter voltage
#define BAT_CALIB_ADC 1275U // adc reading voltage
void bldc_init(void);
void bldc_step(void);
#endif
+104
View File
@@ -0,0 +1,104 @@
/*
* File: rtwtypes.h
*
* Code generated for Simulink model 'BLDC_controller'.
*
* Model version : 1.1297
* Simulink Coder version : 8.13 (R2017b) 24-Jul-2017
* C/C++ source code generated on : Sun Mar 6 11:02:11 2022
*
* Target selection: ert.tlc
* Embedded hardware selection: ARM Compatible->ARM Cortex
* Emulation hardware selection:
* Differs from embedded hardware (MATLAB Host)
* Code generation objectives:
* 1. Execution efficiency
* 2. RAM efficiency
* Validation result: Not run
*/
#ifndef RTWTYPES_H
#define RTWTYPES_H
/* Logical type definitions */
#if (!defined(__cplusplus))
# ifndef false
# define false (0U)
# endif
# ifndef true
# define true (1U)
# endif
#endif
/*=======================================================================*
* Target hardware information
* Device type: MATLAB Host
* Number of bits: char: 8 short: 16 int: 32
* long: 32 long long: 64
* native word size: 64
* Byte ordering: LittleEndian
* Signed integer division rounds to: Zero
* Shift right on a signed integer as arithmetic shift: on
*=======================================================================*/
/*=======================================================================*
* Fixed width word size data types: *
* int8_T, int16_T, int32_T - signed 8, 16, or 32 bit integers *
* uint8_T, uint16_T, uint32_T - unsigned 8, 16, or 32 bit integers *
* real32_T, real64_T - 32 and 64 bit floating point numbers *
*=======================================================================*/
typedef signed char int8_T;
typedef unsigned char uint8_T;
typedef short int16_T;
typedef unsigned short uint16_T;
typedef int int32_T;
typedef unsigned int uint32_T;
typedef long long int64_T;
typedef unsigned long long uint64_T;
typedef float real32_T;
typedef double real64_T;
/*===========================================================================*
* Generic type definitions: boolean_T, char_T, byte_T, int_T, uint_T, *
* real_T, time_T, ulong_T, ulonglong_T. *
*===========================================================================*/
typedef double real_T;
typedef double time_T;
typedef unsigned char boolean_T;
typedef int int_T;
typedef unsigned int uint_T;
typedef unsigned long ulong_T;
typedef unsigned long long ulonglong_T;
typedef char char_T;
typedef unsigned char uchar_T;
typedef char_T byte_T;
/*=======================================================================*
* Min and Max: *
* int8_T, int16_T, int32_T - signed 8, 16, or 32 bit integers *
* uint8_T, uint16_T, uint32_T - unsigned 8, 16, or 32 bit integers *
*=======================================================================*/
#define MAX_int8_T ((int8_T)(127))
#define MIN_int8_T ((int8_T)(-128))
#define MAX_uint8_T ((uint8_T)(255U))
#define MAX_int16_T ((int16_T)(32767))
#define MIN_int16_T ((int16_T)(-32768))
#define MAX_uint16_T ((uint16_T)(65535U))
#define MAX_int32_T ((int32_T)(2147483647))
#define MIN_int32_T ((int32_T)(-2147483647-1))
#define MAX_uint32_T ((uint32_T)(0xFFFFFFFFU))
#define MAX_int64_T ((int64_T)(9223372036854775807LL))
#define MIN_int64_T ((int64_T)(-9223372036854775807LL-1LL))
#define MAX_uint64_T ((uint64_T)(0xFFFFFFFFFFFFFFFFULL))
/* Block D-Work pointer type */
typedef void * pointer_T;
#endif /* RTWTYPES_H */
/*
* File trailer for generated code.
*
* [EOF]
*/
+46
View File
@@ -0,0 +1,46 @@
#include "board/body/boards/board_declarations.h"
void board_body_init(void) {
// Initialize CAN pins
set_gpio_pullup(CAN_RX_PORT, CAN_RX_PIN, PULL_NONE);
set_gpio_alternate(CAN_RX_PORT, CAN_RX_PIN, GPIO_AF9_FDCAN1);
set_gpio_pullup(CAN_TX_PORT, CAN_TX_PIN, PULL_NONE);
set_gpio_alternate(CAN_TX_PORT, CAN_TX_PIN, GPIO_AF9_FDCAN1);
// Initialize button input (PC15)
set_gpio_mode(IGNITION_SW_PORT, IGNITION_SW_PIN, MODE_INPUT);
SYSCFG->EXTICR[3] &= ~(SYSCFG_EXTICR4_EXTI15);
SYSCFG->EXTICR[3] |= SYSCFG_EXTICR4_EXTI15_PC;
EXTI->PR1 = (1U << 15);
EXTI->RTSR1 |= (1U << 15);
EXTI->FTSR1 |= (1U << 15);
EXTI->IMR1 |= (1U << 15);
// Initialize barrel jack detection input (PC13)
set_gpio_pullup(CHARGING_DETECT_PORT, CHARGING_DETECT_PIN, PULL_UP);
set_gpio_mode(CHARGING_DETECT_PORT, CHARGING_DETECT_PIN, MODE_INPUT);
SYSCFG->EXTICR[3] &= ~(SYSCFG_EXTICR4_EXTI13);
SYSCFG->EXTICR[3] |= SYSCFG_EXTICR4_EXTI13_PC;
EXTI->PR1 = (1U << 13);
EXTI->RTSR1 |= (1U << 13);
EXTI->FTSR1 |= (1U << 13);
EXTI->IMR1 |= (1U << 13);
// Initialize and turn on mici power
set_gpio_mode(OBDC_POWER_ON_PORT, OBDC_POWER_ON_PIN, MODE_OUTPUT);
set_gpio_output(OBDC_POWER_ON_PORT, OBDC_POWER_ON_PIN, 1);
// Initialize and turn off gpu power
set_gpio_mode(GPU_POWER_ON_PORT, GPU_POWER_ON_PIN, MODE_OUTPUT);
set_gpio_output(GPU_POWER_ON_PORT, GPU_POWER_ON_PIN, 0);
// Initialize and turn off ignition output
set_gpio_mode(OBDC_IGNITION_ON_PORT, OBDC_IGNITION_ON_PIN, MODE_OUTPUT);
set_gpio_output(OBDC_IGNITION_ON_PORT, OBDC_IGNITION_ON_PIN, 0);
}
board board_body = {
.led_GPIO = {GPIOA, GPIOA, GPIOA},
.led_pin = {10, 10, 10},
.init = board_body_init,
};
@@ -0,0 +1,55 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include "board/body/bldc/bldc_defs.h"
// ******************** Prototypes ********************
typedef void (*board_init)(void);
typedef void (*board_init_bootloader)(void);
typedef void (*board_enable_can_transceiver)(uint8_t transceiver, bool enabled);
struct board {
GPIO_TypeDef * const led_GPIO[3];
const uint8_t led_pin[3];
const uint8_t led_pwm_channels[3]; // leave at 0 to disable PWM
board_init init;
board_init_bootloader init_bootloader;
const bool has_spi;
};
// ******************* Definitions ********************
#define HW_TYPE_BODY 0xB1U
// Pin definitions
// CAN
#define CAN_TX_PORT GPIOD
#define CAN_TX_PIN 1
#define CAN_RX_PORT GPIOD
#define CAN_RX_PIN 0
#define CAN_TRANSCEIVER_EN_PORT GPIOD
#define CAN_TRANSCEIVER_EN_PIN 12
// Ignition and charging detection
#define IGNITION_SW_PORT GPIOC
#define IGNITION_SW_PIN 15
#define CHARGING_DETECT_PORT GPIOC
#define CHARGING_DETECT_PIN 13
// Dotstar LED
#define DOTSTAR_CLK_PORT GPIOB
#define DOTSTAR_CLK_PIN 3
#define DOTSTAR_DATA_PORT GPIOB
#define DOTSTAR_DATA_PIN 5
// Mici Power On
#define OBDC_POWER_ON_PORT GPIOB
#define OBDC_POWER_ON_PIN 12
// GPU Power On
#define GPU_POWER_ON_PORT GPIOD
#define GPU_POWER_ON_PIN 8
// Ignition On
#define OBDC_IGNITION_ON_PORT GPIOB
#define OBDC_IGNITION_ON_PIN 11
+118
View File
@@ -0,0 +1,118 @@
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include "board/can.h"
#include "board/health.h"
#include "board/body/boards/board_declarations.h"
#include "board/drivers/drivers.h"
#include "opendbc/safety/declarations.h"
#include "board/body/bldc/bldc.h"
#define BODY_CAN_ADDR_MOTOR_SPEED 0x201U
#define BODY_CAN_ADDR_VAR_VALUES 0x202U
#define BODY_CAN_ADDR_BODY_DATA 0x203U
#define BODY_CAN_ADDR_V2_ID 0x222U
#define BODY_CAN_MOTOR_SPEED_PERIOD_US 10000U
#define BODY_CAN_CMD_TIMEOUT_US 100000U
#define BODY_BUS_NUMBER 0U
static uint32_t last_can_cmd_timestamp_us = 0U;
static uint16_t counter = 0U;
void body_can_send_motor_speeds(uint8_t bus, float left_speed_rpm, float right_speed_rpm) {
CANPacket_t pkt = {0};
pkt.bus = bus;
pkt.addr = BODY_CAN_ADDR_MOTOR_SPEED;
pkt.data_len_code = 8;
int16_t left_speed_deci = left_speed_rpm;
int16_t right_speed_deci = -(right_speed_rpm);
pkt.data[0] = (uint8_t)((left_speed_deci >> 8) & 0xFFU);
pkt.data[1] = (uint8_t)(left_speed_deci & 0xFFU);
pkt.data[2] = (uint8_t)((right_speed_deci >> 8) & 0xFFU);
pkt.data[3] = (uint8_t)(right_speed_deci & 0xFFU);
pkt.data[4] = 0U;
pkt.data[5] = 0U;
pkt.data[6] = counter & 0xFFU;
can_set_checksum(&pkt);
can_send(&pkt, bus, true);
counter++;
}
void body_can_send_var_values(uint8_t bus, bool ignition, bool enable_motors, uint8_t fault, uint8_t left_z_errcode, uint8_t right_z_errcode) {
CANPacket_t pkt = {0};
pkt.bus = bus;
pkt.addr = BODY_CAN_ADDR_VAR_VALUES;
pkt.data_len_code = 3;
pkt.data[0] = (ignition ? 1U : 0U) | ((enable_motors ? 1U : 0U) << 1U) | ((fault & 0x3FU) << 2U);
pkt.data[1] = left_z_errcode;
pkt.data[2] = right_z_errcode;
can_set_checksum(&pkt);
can_send(&pkt, bus, true);
}
void body_can_send_body_data(uint8_t bus, uint8_t mcu_temp_raw, uint16_t batt_voltage_raw, uint8_t batt_percentage, bool charger_connected) {
CANPacket_t pkt = {0};
pkt.bus = bus;
pkt.addr = BODY_CAN_ADDR_BODY_DATA;
pkt.data_len_code = 4;
pkt.data[0] = mcu_temp_raw;
pkt.data[1] = (uint8_t)((batt_voltage_raw >> 8) & 0xFFU);
pkt.data[2] = (uint8_t)(batt_voltage_raw & 0xFFU);
pkt.data[3] = (charger_connected ? 1U : 0U) | ((batt_percentage & 0x7FU) << 1U);
can_set_checksum(&pkt);
can_send(&pkt, bus, true);
}
void body_can_process_target(int16_t left_target_deci_rpm, int16_t right_target_deci_rpm) {
rpm_left = (int)(((float)left_target_deci_rpm) * 0.1f);
rpm_right = (int)(((float)right_target_deci_rpm) * 0.1f);
last_can_cmd_timestamp_us = microsecond_timer_get();
}
void body_can_rx(CANPacket_t *msg) {
if ((msg->addr == 0x250U) && (GET_LEN(msg) >= 4U)) {
int16_t left_target_deci_rpm = (int16_t)((msg->data[0] << 8U) | msg->data[1]);
int16_t right_target_deci_rpm = (int16_t)((msg->data[2] << 8U) | msg->data[3]);
body_can_process_target(left_target_deci_rpm, right_target_deci_rpm);
}
}
void body_can_init(void) {
last_can_cmd_timestamp_us = 0U;
can_silent = false;
can_loopback = false;
(void)set_safety_hooks(SAFETY_BODY, 0U);
set_gpio_output(CAN_TRANSCEIVER_EN_PORT, CAN_TRANSCEIVER_EN_PIN, 0); // Enable CAN transceiver
can_init_all();
}
void body_can_periodic(uint32_t now, bool ignition, bool plug_charging) {
if ((last_can_cmd_timestamp_us != 0U) &&
((now - last_can_cmd_timestamp_us) >= BODY_CAN_CMD_TIMEOUT_US)) {
rpm_left = 0;
rpm_right = 0;
last_can_cmd_timestamp_us = 0U;
}
static uint32_t last_motor_speed_tx_us = 0;
if ((now - last_motor_speed_tx_us) >= BODY_CAN_MOTOR_SPEED_PERIOD_US) {
float left_speed_rpm = motor_encoder_get_speed_rpm(BODY_MOTOR_LEFT);
float right_speed_rpm = motor_encoder_get_speed_rpm(BODY_MOTOR_RIGHT);
body_can_send_motor_speeds(BODY_BUS_NUMBER, left_speed_rpm, right_speed_rpm);
body_can_send_var_values(BODY_BUS_NUMBER, ignition, enable_motors, 0U, rtY_Left.z_errCode, rtY_Right.z_errCode);
body_can_send_body_data(BODY_BUS_NUMBER, 0U, batt_voltage_raw, batt_percentage, plug_charging);
// Send message on 0x222 to identify as body v2
CANPacket_t id_pkt = {0};
id_pkt.bus = BODY_BUS_NUMBER;
id_pkt.addr = BODY_CAN_ADDR_V2_ID;
id_pkt.data_len_code = 1;
id_pkt.data[0] = 1U;
can_set_checksum(&id_pkt);
can_send(&id_pkt, BODY_BUS_NUMBER, true);
last_motor_speed_tx_us = now;
}
}
+210
View File
@@ -0,0 +1,210 @@
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include "board/config.h"
#include "board/body/boards/board_declarations.h"
#define DOTSTAR_LED_COUNT 10U
#define DOTSTAR_GLOBAL_BRIGHTNESS_MAX 31U
typedef struct {
uint8_t r;
uint8_t g;
uint8_t b;
} dotstar_rgb_t;
typedef struct {
bool initialized;
uint8_t global_brightness;
dotstar_rgb_t pixels[DOTSTAR_LED_COUNT];
} dotstar_state_t;
static dotstar_state_t dotstar_state = {
.initialized = false,
.global_brightness = DOTSTAR_GLOBAL_BRIGHTNESS_MAX,
};
static inline void dotstar_set_clk(bool high) {
if (high) {
DOTSTAR_CLK_PORT->BSRR = (uint32_t)(1U << DOTSTAR_CLK_PIN);
} else {
DOTSTAR_CLK_PORT->BSRR = (uint32_t)(1U << (DOTSTAR_CLK_PIN + 16U));
}
}
static inline void dotstar_set_data(bool high) {
if (high) {
DOTSTAR_DATA_PORT->BSRR = (uint32_t)(1U << DOTSTAR_DATA_PIN);
} else {
DOTSTAR_DATA_PORT->BSRR = (uint32_t)(1U << (DOTSTAR_DATA_PIN + 16U));
}
}
static inline void dotstar_write_byte(uint8_t value) {
for (int8_t bit = 7; bit >= 0; bit--) {
dotstar_set_data(((value >> bit) & 0x1U) != 0U);
delay(15);
dotstar_set_clk(true);
delay(15);
dotstar_set_clk(false);
delay(15);
}
}
static inline uint16_t dotstar_latch_len(uint16_t led_count) {
uint16_t len = (uint16_t)((led_count + 15U) / 16U);
if (len < led_count) {
len = led_count;
}
return (len < 4U) ? 4U : len;
}
static inline void dotstar_send_start_frame(void) {
for (uint8_t i = 0U; i < 4U; i++) {
dotstar_write_byte(0x00U);
}
}
static inline void dotstar_send_end_frame(uint16_t led_count) {
uint16_t latch_len = dotstar_latch_len(led_count);
for (uint16_t i = 0U; i < latch_len; i++) {
dotstar_write_byte(0xFFU);
}
}
static inline void dotstar_show(void) {
if (!dotstar_state.initialized) {
return;
}
dotstar_send_start_frame();
uint8_t prefix = (uint8_t)(0xE0U | dotstar_state.global_brightness);
for (uint16_t i = 0U; i < DOTSTAR_LED_COUNT; i++) {
dotstar_rgb_t *pixel = &dotstar_state.pixels[i];
dotstar_write_byte(prefix);
dotstar_write_byte(pixel->b);
dotstar_write_byte(pixel->g);
dotstar_write_byte(pixel->r);
}
dotstar_send_end_frame(DOTSTAR_LED_COUNT);
}
static inline void dotstar_init(void) {
set_gpio_pullup(DOTSTAR_CLK_PORT, DOTSTAR_CLK_PIN, PULL_NONE);
set_gpio_output_type(DOTSTAR_CLK_PORT, DOTSTAR_CLK_PIN, OUTPUT_TYPE_PUSH_PULL);
set_gpio_mode(DOTSTAR_CLK_PORT, DOTSTAR_CLK_PIN, MODE_OUTPUT);
register_set(&(DOTSTAR_CLK_PORT->OSPEEDR), GPIO_OSPEEDR_OSPEED5, GPIO_OSPEEDR_OSPEED5_Msk);
dotstar_set_clk(false);
set_gpio_pullup(DOTSTAR_DATA_PORT, DOTSTAR_DATA_PIN, PULL_NONE);
set_gpio_output_type(DOTSTAR_DATA_PORT, DOTSTAR_DATA_PIN, OUTPUT_TYPE_PUSH_PULL);
set_gpio_mode(DOTSTAR_DATA_PORT, DOTSTAR_DATA_PIN, MODE_OUTPUT);
register_set(&(DOTSTAR_DATA_PORT->OSPEEDR), GPIO_OSPEEDR_OSPEED5, GPIO_OSPEEDR_OSPEED5_Msk);
dotstar_set_data(false);
dotstar_state.initialized = true;
dotstar_state.global_brightness = DOTSTAR_GLOBAL_BRIGHTNESS_MAX;
for (uint16_t i = 0U; i < DOTSTAR_LED_COUNT; i++) {
dotstar_state.pixels[i].r = 0U;
dotstar_state.pixels[i].g = 0U;
dotstar_state.pixels[i].b = 0U;
}
dotstar_show();
}
static inline void dotstar_set_pixel(uint16_t index, uint8_t r, uint8_t g, uint8_t b) {
if (!dotstar_state.initialized || (index >= DOTSTAR_LED_COUNT)) {
return;
}
dotstar_state.pixels[index].r = r;
dotstar_state.pixels[index].g = g;
dotstar_state.pixels[index].b = b;
}
static inline void dotstar_fill(uint8_t r, uint8_t g, uint8_t b) {
if (!dotstar_state.initialized) {
return;
}
for (uint16_t i = 0U; i < DOTSTAR_LED_COUNT; i++) {
dotstar_state.pixels[i].r = r;
dotstar_state.pixels[i].g = g;
dotstar_state.pixels[i].b = b;
}
}
static inline void dotstar_set_global_brightness(uint8_t brightness) {
dotstar_state.global_brightness = (brightness > DOTSTAR_GLOBAL_BRIGHTNESS_MAX) ? DOTSTAR_GLOBAL_BRIGHTNESS_MAX : brightness;
}
static inline void dotstar_hue_to_rgb(uint16_t hue, uint8_t *r, uint8_t *g, uint8_t *b) {
hue %= 765U;
if (hue < 255U) {
*r = (uint8_t)(255U - hue);
*g = (uint8_t)hue;
*b = 0U;
} else if (hue < 510U) {
hue -= 255U;
*r = 0U;
*g = (uint8_t)(255U - hue);
*b = (uint8_t)hue;
} else {
hue -= 510U;
*r = (uint8_t)hue;
*g = 0U;
*b = (uint8_t)(255U - hue);
}
}
static inline void dotstar_run_rainbow(uint32_t now_us) {
uint32_t brightness_phase = (now_us / 40000U) % 62U;
uint8_t brightness = (brightness_phase <= 31U) ? (uint8_t)(brightness_phase + 1U) : (uint8_t)(62U - brightness_phase);
if (brightness == 0U) {
brightness = 1U;
}
dotstar_set_global_brightness(brightness);
uint32_t base_hue = (now_us / 10000U) % 765U;
for (uint16_t i = 0U; i < DOTSTAR_LED_COUNT; i++) {
uint16_t hue = (uint16_t)((base_hue + (i * 70U)) % 765U);
uint8_t r, g, b;
dotstar_hue_to_rgb(hue, &r, &g, &b);
dotstar_set_pixel(i, r, g, b);
}
}
static inline void dotstar_apply_breathe(dotstar_rgb_t color, uint32_t now_us, uint32_t cycle_us) {
if (!dotstar_state.initialized) {
return;
}
if (cycle_us == 0U) {
dotstar_set_global_brightness(DOTSTAR_GLOBAL_BRIGHTNESS_MAX);
dotstar_fill(color.r, color.g, color.b);
return;
}
uint32_t phase = now_us % cycle_us;
uint32_t half_cycle = cycle_us / 2U;
if (half_cycle == 0U) {
half_cycle = 1U;
}
uint32_t amplitude = (phase <= half_cycle) ? phase : (cycle_us - phase);
uint32_t scale = (amplitude * 255U) / half_cycle;
if (scale > 255U) {
scale = 255U;
}
uint8_t r = (uint8_t)((color.r * scale) / 255U);
uint8_t g = (uint8_t)((color.g * scale) / 255U);
uint8_t b = (uint8_t)((color.b * scale) / 255U);
dotstar_set_global_brightness(DOTSTAR_GLOBAL_BRIGHTNESS_MAX);
dotstar_fill(r, g, b);
}
+49
View File
@@ -0,0 +1,49 @@
#!/usr/bin/env python3
import argparse
import os
import subprocess
from panda import Panda
BODY_DIR = os.path.dirname(os.path.realpath(__file__))
BOARD_DIR = os.path.abspath(os.path.join(BODY_DIR, ".."))
REPO_ROOT = os.path.abspath(os.path.join(BOARD_DIR, ".."))
DEFAULT_FIRMWARE = os.path.join(BOARD_DIR, "obj", "body_h7.bin.signed")
def build_body() -> None:
subprocess.check_call(
f"scons -C {REPO_ROOT} -j$(nproc) board/obj/body_h7.bin.signed",
shell=True,
)
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("firmware", nargs="?", help="Optional path to firmware binary to flash")
parser.add_argument("--all", action="store_true", help="Flash all Panda devices")
parser.add_argument(
"--wait-usb",
action="store_true",
help="Wait for the panda to reconnect over USB after flashing (defaults to skipping reconnect).",
)
args = parser.parse_args()
firmware_path = os.path.abspath(args.firmware) if args.firmware is not None else DEFAULT_FIRMWARE
build_body()
if not os.path.isfile(firmware_path):
parser.error(f"firmware file not found: {firmware_path}")
if args.all:
serials = Panda.list()
print(f"found {len(serials)} panda(s) - {serials}")
else:
serials = [None]
for s in serials:
with Panda(serial=s) as p:
print("flashing", p.get_usb_serial())
p.flash(firmware_path, reconnect=args.wait_usb)
exit(1 if len(serials) == 0 else 0)
+144
View File
@@ -0,0 +1,144 @@
#include <stdint.h>
#include <stdbool.h>
#include "board/config.h"
#include "board/drivers/led.h"
#include "board/drivers/pwm.h"
#include "board/drivers/usb.h"
#include "board/early_init.h"
#include "board/obj/gitversion.h"
#include "board/body/can.h"
#include "opendbc/safety/safety.h"
#include "board/drivers/can_common.h"
#include "board/drivers/fdcan.h"
#include "board/can_comms.h"
#include "board/body/dotstar.h"
#include "bldc/bldc.h"
extern int _app_start[0xc000];
#include "board/body/main_comms.h"
static volatile uint32_t tick_count = 0U;
static volatile uint32_t ignition_press_timestamp_us = 0U;
static volatile bool ignition = false;
static volatile bool plug_charging = false;
void debug_ring_callback(uart_ring *ring) {
char rcv;
while (get_char(ring, &rcv)) {
(void)injectc(ring, rcv);
}
}
void __attribute__ ((noinline)) enable_fpu(void) {
SCB->CPACR |= ((3UL << (10U * 2U)) | (3UL << (11U * 2U)));
}
void __initialize_hardware_early(void) {
enable_fpu();
early_initialization();
}
void bldc_tim8_handler(void) {
if ((LEFT_TIM->SR & TIM_SR_UIF) != 0) {
LEFT_TIM->SR = ~TIM_SR_UIF;
bldc_step();
}
}
void tick_handler(void) {
if (TICK_TIMER->SR != 0) {
if (can_health[0].transmit_error_cnt >= 128) {
(void)llcan_init(CANIF_FROM_CAN_NUM(0));
}
static bool led_on = false;
led_set(LED_RED, led_on);
led_on = !led_on;
tick_count++;
}
TICK_TIMER->SR = 0;
}
static void exti15_10_handler(void) {
if ((EXTI->PR1 & (1U << CHARGING_DETECT_PIN)) != 0U) {
EXTI->PR1 = (1U << CHARGING_DETECT_PIN);
plug_charging = (get_gpio_input(CHARGING_DETECT_PORT, CHARGING_DETECT_PIN) != 0);
}
if ((EXTI->PR1 & (1U << IGNITION_SW_PIN)) != 0U) {
EXTI->PR1 = (1U << IGNITION_SW_PIN);
static uint32_t last_press_event_us = 0U;
const uint32_t debounce_us = 200000U; // 200 ms
uint32_t now = microsecond_timer_get();
bool pressed = (get_gpio_input(IGNITION_SW_PORT, IGNITION_SW_PIN) == 0);
if (pressed) {
if (get_ts_elapsed(now, last_press_event_us) > debounce_us) {
last_press_event_us = now;
ignition_press_timestamp_us = now;
ignition = !ignition;
set_gpio_output(OBDC_IGNITION_ON_PORT, OBDC_IGNITION_ON_PIN, ignition);
}
}
}
}
int main(void) {
disable_interrupts();
init_interrupts(true);
clock_init();
peripherals_init();
current_board = &board_body;
hw_type = HW_TYPE_BODY;
current_board->init();
REGISTER_INTERRUPT(EXTI15_10_IRQn, exti15_10_handler, 10000U, FAULT_INTERRUPT_RATE_EXTI);
NVIC_ClearPendingIRQ(EXTI15_10_IRQn);
NVIC_EnableIRQ(EXTI15_10_IRQn);
REGISTER_INTERRUPT(TIM8_UP_TIM13_IRQn, bldc_tim8_handler, 100000U, FAULT_INTERRUPT_RATE_TICK);
NVIC_ClearPendingIRQ(TIM8_UP_TIM13_IRQn);
NVIC_EnableIRQ(TIM8_UP_TIM13_IRQn);
REGISTER_INTERRUPT(TICK_TIMER_IRQ, tick_handler, 10U, FAULT_INTERRUPT_RATE_TICK);
led_init();
microsecond_timer_init();
tick_timer_init();
usb_init();
body_can_init();
dotstar_init();
bldc_init();
enable_interrupts();
plug_charging = (get_gpio_input(CHARGING_DETECT_PORT, CHARGING_DETECT_PIN) != 0);
while (true) {
uint32_t now = microsecond_timer_get();
if (plug_charging) {
motor_set_enable(false);
dotstar_apply_breathe((dotstar_rgb_t){255U, 40U, 0U}, now, 2000000U);
} else if (ignition) {
dotstar_run_rainbow(now);
} else {
dotstar_apply_breathe((dotstar_rgb_t){0U, 255U, 10U}, now, 1500000U);
}
if (ignition) {
motor_set_enable(true);
body_can_periodic(now, ignition, plug_charging);
} else {
motor_set_enable(false);
}
dotstar_show();
}
return 0;
}
+85
View File
@@ -0,0 +1,85 @@
void comms_endpoint2_write(const uint8_t *data, uint32_t len) {
UNUSED(data);
UNUSED(len);
}
int comms_control_handler(ControlPacket_t *req, uint8_t *resp) {
unsigned int resp_len = 0;
switch (req->request) {
// **** 0xc1: get hardware type
case 0xc1:
resp[0] = hw_type;
resp_len = 1;
break;
// **** 0xd1: enter bootloader mode
case 0xd1:
switch (req->param1) {
case 0:
print("-> entering bootloader\n");
enter_bootloader_mode = ENTER_BOOTLOADER_MAGIC;
NVIC_SystemReset();
break;
case 1:
print("-> entering softloader\n");
enter_bootloader_mode = ENTER_SOFTLOADER_MAGIC;
NVIC_SystemReset();
break;
default:
print("Bootloader mode invalid\n");
break;
}
break;
// **** 0xd3/0xd4: signature bytes
case 0xd3:
case 0xd4: {
uint8_t offset = (req->request == 0xd3) ? 0U : 64U;
resp_len = 64U;
char *code = (char *)_app_start;
int code_len = _app_start[0];
(void)memcpy(resp, &code[code_len + offset], resp_len);
break;
}
// **** 0xd6: get version
case 0xd6:
(void)memcpy(resp, gitversion, sizeof(gitversion));
resp_len = sizeof(gitversion) - 1U;
break;
// **** 0xd8: reset ST
case 0xd8:
NVIC_SystemReset();
break;
// **** 0xdd: get healthpacket and CANPacket version hashes
case 0xdd: {
uint32_t versions[2] = {HEALTH_PACKET_VERSION, CAN_PACKET_VERSION_HASH};
(void)memcpy(resp, (uint8_t *)versions, sizeof(versions));
resp_len = sizeof(versions);
break;
}
// **** 0xb3: set motor speeds
case 0xb3:
rpm_left = (int16_t)req->param1;
rpm_right = (int16_t)req->param2;
break;
// **** 0xb4: enable/disable motors
case 0xb4:
enable_motors = (req->param1 == 1U);
if (enable_motors == 0) {
rpm_left = 0;
rpm_right = 0;
}
break;
default:
// Ignore unhandled requests
break;
}
return resp_len;
}
+9
View File
@@ -0,0 +1,9 @@
#include "board/body/boards/board_declarations.h"
#include "board/body/boards/board_body.h"
extern board *current_board;
extern uint8_t hw_type;
void detect_board_type(void) {
// Board type set explicitly in main()
}
+11 -16
View File
@@ -1,24 +1,22 @@
#define BOOTSTUB
#define VERS_TAG 0x53524556 #define VERS_TAG 0x53524556
#define MIN_VERSION 2 #define MIN_VERSION 2
// ********************* Includes ********************* // ********************* Includes *********************
#include "config.h" #include "board/config.h"
#include "drivers/led.h" #include "board/drivers/led.h"
#include "drivers/pwm.h" #include "board/drivers/pwm.h"
#include "drivers/usb.h" #include "board/drivers/usb.h"
#include "early_init.h" #include "board/early_init.h"
#include "provision.h" #include "board/provision.h"
#include "crypto/rsa.h" #include "board/crypto/rsa.h"
#include "crypto/sha.h" #include "board/crypto/sha.h"
#include "obj/cert.h" #include "board/obj/cert.h"
#include "obj/gitversion.h" #include "board/obj/gitversion.h"
#include "flasher.h" #include "board/flasher.h"
// cppcheck-suppress unusedFunction ; used in headers not included in cppcheck // cppcheck-suppress unusedFunction ; used in headers not included in cppcheck
void __initialize_hardware_early(void) { void __initialize_hardware_early(void) {
@@ -32,9 +30,6 @@ void fail(void) {
// know where to sig check // know where to sig check
extern void *_app_start[]; extern void *_app_start[];
// FIXME: sometimes your panda will fail flashing and will quickly blink a single Green LED
// BOUNTY: $200 coupon on shop.comma.ai or $100 check.
int main(void) { int main(void) {
// Init interrupt table // Init interrupt table
init_interrupts(true); init_interrupts(true);
+4 -5
View File
@@ -1,16 +1,15 @@
// ******************** Prototypes ******************** // ******************** Prototypes ********************
void print(const char *a){ UNUSED(a); } void print(const char *a){ UNUSED(a); }
void puth(uint8_t i){ UNUSED(i); } void puth(unsigned int i){ UNUSED(i); }
void puth2(uint8_t i){ UNUSED(i); } void puth2(unsigned int i){ UNUSED(i); }
void puth4(uint8_t i){ UNUSED(i); } __attribute__((unused)) static void puth4(unsigned int i){ UNUSED(i); }
void hexdump(const void *a, int l){ UNUSED(a); UNUSED(l); } void hexdump(const void *a, int l){ UNUSED(a); UNUSED(l); }
typedef struct board board; typedef struct board board;
typedef struct harness_configuration harness_configuration; typedef struct harness_configuration harness_configuration;
void pwm_init(TIM_TypeDef *TIM, uint8_t channel); void pwm_init(TIM_TypeDef *TIM, uint8_t channel);
void pwm_set(TIM_TypeDef *TIM, uint8_t channel, uint8_t percentage); void pwm_set(TIM_TypeDef *TIM, uint8_t channel, uint8_t percentage);
// No UART support in bootloader // No UART support in bootloader
typedef struct uart_ring {} uart_ring; typedef struct uart_ring uart_ring;
uart_ring uart_ring_som_debug;
void uart_init(uart_ring *q, int baud) { UNUSED(q); UNUSED(baud); } void uart_init(uart_ring *q, int baud) { UNUSED(q); UNUSED(baud); }
// ********************* Globals ********************** // ********************* Globals **********************
+22
View File
@@ -3,6 +3,28 @@
a certain number of CANPacket_t. The transaction is split a certain number of CANPacket_t. The transaction is split
into multiple transfers or chunks. into multiple transfers or chunks.
CAN packet byte layout (wire format used by comms_can_{read,write}):
+--------+--------+--------+--------+--------+--------+--------+------------------------------+
| byte 0 | byte 1 | byte 2 | byte 3 | byte 4 | byte 5 | byte 6 | ... byte 13 / byte 69 |
+--------+--------+--------+--------+--------+--------+--------+------------------------------+
| DLC | addr | addr | addr | flags | cksum | data0 | ... data7 / data63 |
| bus | | | | | | | (classic CAN / CAN FD) |
| fd | | | | | | | |
+--------+--------+--------+--------+--------+--------+--------+------------------------------+
Byte/bit fields:
byte 0: DLC[7:4], bus[3:1], fd[0]
bytes 1..4: (addr << 3) | (extended << 2) | (returned << 1) | rejected
byte 5: checksum = XOR(header[0..4] + payload)
bytes 6..13 (classic CAN, up to 8 bytes) / bytes 6..69 (CAN FD, up to 64 bytes): payload
USB/SPI transfer chunking used by this file:
+--------------------------------------------+ ... +--------------------------------------------+
| transport chunk 0 | | transport chunk N |
+--------------------------------------------+ +--------------------------------------------+
| concatenated CANPacket_t bytes | | continuation and/or next CANPacket_t bytes |
| (no per-64-byte counter/header in protocol)| | |
+--------------------------------------------+ +--------------------------------------------+
* comms_can_read outputs this buffer in chunks of a specified length. * comms_can_read outputs this buffer in chunks of a specified length.
chunks are always the given length, except the last one. chunks are always the given length, except the last one.
* comms_can_write reads in this buffer in chunks. * comms_can_write reads in this buffer in chunks.
-29
View File
@@ -1,29 +0,0 @@
#pragma once
// bump this when changing the CAN packet
#define CAN_PACKET_VERSION 4
#define CANPACKET_HEAD_SIZE 6U
#if !defined(STM32F4)
#define CANFD
#define CANPACKET_DATA_SIZE_MAX 64U
#else
#define CANPACKET_DATA_SIZE_MAX 8U
#endif
typedef struct {
unsigned char fd : 1;
unsigned char bus : 3;
unsigned char data_len_code : 4; // lookup length with dlc_to_len
unsigned char rejected : 1;
unsigned char returned : 1;
unsigned char extended : 1;
unsigned int addr : 29;
unsigned char checksum;
unsigned char data[CANPACKET_DATA_SIZE_MAX];
} __attribute__((packed, aligned(4))) CANPacket_t;
#define GET_BUS(msg) ((msg)->bus)
#define GET_LEN(msg) (dlc_to_len[(msg)->data_len_code])
#define GET_ADDR(msg) ((msg)->addr)
+2
View File
@@ -1,3 +1,5 @@
#pragma once
typedef struct { typedef struct {
uint8_t request; uint8_t request;
uint16_t param1; uint16_t param1;
+1 -3
View File
@@ -34,9 +34,7 @@
// platform includes // platform includes
#ifdef STM32H7 #ifdef STM32H7
#include "stm32h7/stm32h7_config.h" #include "board/stm32h7/stm32h7_config.h"
#elif defined(STM32F4)
#include "stm32f4/stm32f4_config.h"
#else #else
// TODO: uncomment this, cppcheck complains // TODO: uncomment this, cppcheck complains
// building for tests // building for tests
-2
View File
@@ -1,6 +1,5 @@
#pragma once #pragma once
#if defined(ENABLE_SPI) || defined(BOOTSTUB)
uint8_t crc_checksum(const uint8_t *dat, int len, const uint8_t poly) { uint8_t crc_checksum(const uint8_t *dat, int len, const uint8_t poly) {
uint8_t crc = 0xFFU; uint8_t crc = 0xFFU;
int i; int i;
@@ -18,4 +17,3 @@ uint8_t crc_checksum(const uint8_t *dat, int len, const uint8_t poly) {
} }
return crc; return crc;
} }
#endif
-17
View File
@@ -1,17 +0,0 @@
#pragma once
// ********************* Critical section helpers *********************
void enable_interrupts(void);
void disable_interrupts(void);
extern uint8_t global_critical_depth;
#define ENTER_CRITICAL() \
__disable_irq(); \
global_critical_depth += 1U;
#define EXIT_CRITICAL() \
global_critical_depth -= 1U; \
if ((global_critical_depth == 0U) && interrupts_enabled) { \
__enable_irq(); \
}
View File
-2
View File
@@ -13,8 +13,6 @@ Make sure you're using a genuine one for boards that do not have a 3.3V panda po
## Openocd ## Openocd
Install openocd. For Ubuntu 24.04, the one in the package manager works fine: `sudo apt install openocd`. Install openocd. For Ubuntu 24.04, the one in the package manager works fine: `sudo apt install openocd`.
To run, use `./debug_f4.sh (TODO)` or `./debug_h7.sh` depending on the panda.
## GDB ## GDB
You need `gdb-multiarch`. You need `gdb-multiarch`.
-11
View File
@@ -1,11 +0,0 @@
#!/usr/bin/env sh
set -e
DFU_UTIL="dfu-util"
scons -u -j$(nproc)
PYTHONPATH=.. python3 -c "from python import Panda; Panda().reset(enter_bootstub=True); Panda().reset(enter_bootloader=True)" || true
sleep 1
$DFU_UTIL -d 0483:df11 -a 0 -s 0x08004000 -D obj/panda.bin.signed
$DFU_UTIL -d 0483:df11 -a 0 -s 0x08000000:leave -D obj/bootstub.panda.bin
-11
View File
@@ -1,11 +0,0 @@
#!/usr/bin/env sh
set -e
DFU_UTIL="dfu-util"
scons -u -j$(nproc)
PYTHONPATH=.. python3 -c "from python import Panda; Panda().reset(enter_bootstub=True); Panda().reset(enter_bootloader=True)" || true
sleep 1
$DFU_UTIL -d 0483:df11 -a 0 -s 0x08004000 -D obj/panda.bin.signed
$DFU_UTIL -d 0483:df11 -a 0 -s 0x08000000:leave -D obj/bootstub.panda.bin
-11
View File
@@ -1,11 +0,0 @@
#!/usr/bin/env sh
set -e
DFU_UTIL="dfu-util"
scons -u -j$(nproc)
PYTHONPATH=.. python3 -c "from python import Panda; Panda().reset(enter_bootstub=True); Panda().reset(enter_bootloader=True)" || true
sleep 1
$DFU_UTIL -d 0483:df11 -a 0 -s 0x08020000 -D obj/panda_h7.bin.signed
$DFU_UTIL -d 0483:df11 -a 0 -s 0x08000000:leave -D obj/bootstub.panda_h7.bin
+1 -1
View File
@@ -1,4 +1,4 @@
#include "bootkick_declarations.h" #include "board/drivers/drivers.h"
bool bootkick_reset_triggered = false; bool bootkick_reset_triggered = false;
@@ -1,5 +0,0 @@
#pragma once
extern bool bootkick_reset_triggered;
void bootkick_tick(bool ignition, bool recent_heartbeat);
-222
View File
@@ -1,222 +0,0 @@
#include "bxcan_declarations.h"
// IRQs: CAN1_TX, CAN1_RX0, CAN1_SCE
// CAN2_TX, CAN2_RX0, CAN2_SCE
// CAN3_TX, CAN3_RX0, CAN3_SCE
CAN_TypeDef *cans[CAN_ARRAY_SIZE] = {CAN1, CAN2, CAN3};
uint8_t can_irq_number[CAN_IRQS_ARRAY_SIZE][CAN_IRQS_ARRAY_SIZE] = {
{ CAN1_TX_IRQn, CAN1_RX0_IRQn, CAN1_SCE_IRQn },
{ CAN2_TX_IRQn, CAN2_RX0_IRQn, CAN2_SCE_IRQn },
{ CAN3_TX_IRQn, CAN3_RX0_IRQn, CAN3_SCE_IRQn },
};
bool can_set_speed(uint8_t can_number) {
bool ret = true;
CAN_TypeDef *CANx = CANIF_FROM_CAN_NUM(can_number);
uint8_t bus_number = BUS_NUM_FROM_CAN_NUM(can_number);
ret &= llcan_set_speed(
CANx,
bus_config[bus_number].can_speed,
can_loopback,
(unsigned int)(can_silent) & (1U << can_number)
);
return ret;
}
void can_clear_send(CAN_TypeDef *CANx, uint8_t can_number) {
can_health[can_number].can_core_reset_cnt += 1U;
llcan_clear_send(CANx);
}
void update_can_health_pkt(uint8_t can_number, uint32_t ir_reg) {
CAN_TypeDef *CANx = CANIF_FROM_CAN_NUM(can_number);
uint32_t esr_reg = CANx->ESR;
can_health[can_number].bus_off = ((esr_reg & CAN_ESR_BOFF) >> CAN_ESR_BOFF_Pos);
can_health[can_number].bus_off_cnt += can_health[can_number].bus_off;
can_health[can_number].error_warning = ((esr_reg & CAN_ESR_EWGF) >> CAN_ESR_EWGF_Pos);
can_health[can_number].error_passive = ((esr_reg & CAN_ESR_EPVF) >> CAN_ESR_EPVF_Pos);
can_health[can_number].last_error = ((esr_reg & CAN_ESR_LEC) >> CAN_ESR_LEC_Pos);
if ((can_health[can_number].last_error != 0U) && (can_health[can_number].last_error != 7U)) {
can_health[can_number].last_stored_error = can_health[can_number].last_error;
}
can_health[can_number].receive_error_cnt = ((esr_reg & CAN_ESR_REC) >> CAN_ESR_REC_Pos);
can_health[can_number].transmit_error_cnt = ((esr_reg & CAN_ESR_TEC) >> CAN_ESR_TEC_Pos);
can_health[can_number].irq0_call_rate = interrupts[can_irq_number[can_number][0]].call_rate;
can_health[can_number].irq1_call_rate = interrupts[can_irq_number[can_number][1]].call_rate;
can_health[can_number].irq2_call_rate = interrupts[can_irq_number[can_number][2]].call_rate;
if (ir_reg != 0U) {
can_health[can_number].total_error_cnt += 1U;
// RX message lost due to FIFO overrun
if ((CANx->RF0R & (CAN_RF0R_FOVR0)) != 0U) {
can_health[can_number].total_rx_lost_cnt += 1U;
CANx->RF0R &= ~(CAN_RF0R_FOVR0);
}
can_clear_send(CANx, can_number);
}
}
// ***************************** CAN *****************************
// CANx_SCE IRQ Handler
static void can_sce(uint8_t can_number) {
update_can_health_pkt(can_number, 1U);
}
// CANx_TX IRQ Handler
void process_can(uint8_t can_number) {
if (can_number != 0xffU) {
ENTER_CRITICAL();
CAN_TypeDef *CANx = CANIF_FROM_CAN_NUM(can_number);
uint8_t bus_number = BUS_NUM_FROM_CAN_NUM(can_number);
// check for empty mailbox
CANPacket_t to_send;
if ((CANx->TSR & (CAN_TSR_TERR0 | CAN_TSR_ALST0)) != 0U) { // last TX failed due to error arbitration lost
can_health[can_number].total_tx_lost_cnt += 1U;
CANx->TSR |= (CAN_TSR_TERR0 | CAN_TSR_ALST0);
}
if ((CANx->TSR & CAN_TSR_TME0) == CAN_TSR_TME0) {
// add successfully transmitted message to my fifo
if ((CANx->TSR & CAN_TSR_RQCP0) == CAN_TSR_RQCP0) {
if ((CANx->TSR & CAN_TSR_TXOK0) == CAN_TSR_TXOK0) {
CANPacket_t to_push;
to_push.fd = 0U;
to_push.returned = 1U;
to_push.rejected = 0U;
to_push.extended = (CANx->sTxMailBox[0].TIR >> 2) & 0x1U;
to_push.addr = (to_push.extended != 0U) ? (CANx->sTxMailBox[0].TIR >> 3) : (CANx->sTxMailBox[0].TIR >> 21);
to_push.data_len_code = CANx->sTxMailBox[0].TDTR & 0xFU;
to_push.bus = bus_number;
WORD_TO_BYTE_ARRAY(&to_push.data[0], CANx->sTxMailBox[0].TDLR);
WORD_TO_BYTE_ARRAY(&to_push.data[4], CANx->sTxMailBox[0].TDHR);
can_set_checksum(&to_push);
rx_buffer_overflow += can_push(&can_rx_q, &to_push) ? 0U : 1U;
}
// clear interrupt
// careful, this can also be cleared by requesting a transmission
CANx->TSR |= CAN_TSR_RQCP0;
}
if (can_pop(can_queues[bus_number], &to_send)) {
if (can_check_checksum(&to_send)) {
can_health[can_number].total_tx_cnt += 1U;
// only send if we have received a packet
CANx->sTxMailBox[0].TIR = ((to_send.extended != 0U) ? (to_send.addr << 3) : (to_send.addr << 21)) | (to_send.extended << 2);
CANx->sTxMailBox[0].TDTR = to_send.data_len_code;
BYTE_ARRAY_TO_WORD(CANx->sTxMailBox[0].TDLR, &to_send.data[0]);
BYTE_ARRAY_TO_WORD(CANx->sTxMailBox[0].TDHR, &to_send.data[4]);
// Send request TXRQ
CANx->sTxMailBox[0].TIR |= 0x1U;
} else {
can_health[can_number].total_tx_checksum_error_cnt += 1U;
}
refresh_can_tx_slots_available();
}
}
EXIT_CRITICAL();
}
}
// CANx_RX0 IRQ Handler
// blink blue when we are receiving CAN messages
void can_rx(uint8_t can_number) {
CAN_TypeDef *CANx = CANIF_FROM_CAN_NUM(can_number);
uint8_t bus_number = BUS_NUM_FROM_CAN_NUM(can_number);
while ((CANx->RF0R & CAN_RF0R_FMP0) != 0U) {
can_health[can_number].total_rx_cnt += 1U;
// can is live
pending_can_live = 1;
// add to my fifo
CANPacket_t to_push;
to_push.fd = 0U;
to_push.returned = 0U;
to_push.rejected = 0U;
to_push.extended = (CANx->sFIFOMailBox[0].RIR >> 2) & 0x1U;
to_push.addr = (to_push.extended != 0U) ? (CANx->sFIFOMailBox[0].RIR >> 3) : (CANx->sFIFOMailBox[0].RIR >> 21);
to_push.data_len_code = CANx->sFIFOMailBox[0].RDTR & 0xFU;
to_push.bus = bus_number;
WORD_TO_BYTE_ARRAY(&to_push.data[0], CANx->sFIFOMailBox[0].RDLR);
WORD_TO_BYTE_ARRAY(&to_push.data[4], CANx->sFIFOMailBox[0].RDHR);
can_set_checksum(&to_push);
// forwarding (panda only)
int bus_fwd_num = safety_fwd_hook(bus_number, to_push.addr);
if (bus_fwd_num != -1) {
CANPacket_t to_send;
to_send.fd = 0U;
to_send.returned = 0U;
to_send.rejected = 0U;
to_send.extended = to_push.extended; // TXRQ
to_send.addr = to_push.addr;
to_send.bus = to_push.bus;
to_send.data_len_code = to_push.data_len_code;
(void)memcpy(to_send.data, to_push.data, dlc_to_len[to_push.data_len_code]);
can_set_checksum(&to_send);
can_send(&to_send, bus_fwd_num, true);
can_health[can_number].total_fwd_cnt += 1U;
}
safety_rx_invalid += safety_rx_hook(&to_push) ? 0U : 1U;
ignition_can_hook(&to_push);
led_set(LED_BLUE, true);
rx_buffer_overflow += can_push(&can_rx_q, &to_push) ? 0U : 1U;
// next
CANx->RF0R |= CAN_RF0R_RFOM0;
}
}
static void CAN1_TX_IRQ_Handler(void) { process_can(0); }
static void CAN1_RX0_IRQ_Handler(void) { can_rx(0); }
static void CAN1_SCE_IRQ_Handler(void) { can_sce(0); }
static void CAN2_TX_IRQ_Handler(void) { process_can(1); }
static void CAN2_RX0_IRQ_Handler(void) { can_rx(1); }
static void CAN2_SCE_IRQ_Handler(void) { can_sce(1); }
static void CAN3_TX_IRQ_Handler(void) { process_can(2); }
static void CAN3_RX0_IRQ_Handler(void) { can_rx(2); }
static void CAN3_SCE_IRQ_Handler(void) { can_sce(2); }
bool can_init(uint8_t can_number) {
bool ret = false;
REGISTER_INTERRUPT(CAN1_TX_IRQn, CAN1_TX_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_1)
REGISTER_INTERRUPT(CAN1_RX0_IRQn, CAN1_RX0_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_1)
REGISTER_INTERRUPT(CAN1_SCE_IRQn, CAN1_SCE_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_1)
REGISTER_INTERRUPT(CAN2_TX_IRQn, CAN2_TX_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_2)
REGISTER_INTERRUPT(CAN2_RX0_IRQn, CAN2_RX0_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_2)
REGISTER_INTERRUPT(CAN2_SCE_IRQn, CAN2_SCE_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_2)
REGISTER_INTERRUPT(CAN3_TX_IRQn, CAN3_TX_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_3)
REGISTER_INTERRUPT(CAN3_RX0_IRQn, CAN3_RX0_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_3)
REGISTER_INTERRUPT(CAN3_SCE_IRQn, CAN3_SCE_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_3)
if (can_number != 0xffU) {
CAN_TypeDef *CANx = CANIF_FROM_CAN_NUM(can_number);
ret &= can_set_speed(can_number);
ret &= llcan_init(CANx);
// in case there are queued up messages
process_can(can_number);
}
return ret;
}
-22
View File
@@ -1,22 +0,0 @@
#pragma once
// IRQs: CAN1_TX, CAN1_RX0, CAN1_SCE
// CAN2_TX, CAN2_RX0, CAN2_SCE
// CAN3_TX, CAN3_RX0, CAN3_SCE
#define CAN_ARRAY_SIZE 3
#define CAN_IRQS_ARRAY_SIZE 3
extern CAN_TypeDef *cans[CAN_ARRAY_SIZE];
extern uint8_t can_irq_number[CAN_IRQS_ARRAY_SIZE][CAN_IRQS_ARRAY_SIZE];
bool can_set_speed(uint8_t can_number);
void can_clear_send(CAN_TypeDef *CANx, uint8_t can_number);
void update_can_health_pkt(uint8_t can_number, uint32_t ir_reg);
// ***************************** CAN *****************************
// CANx_TX IRQ Handler
void process_can(uint8_t can_number);
// CANx_RX0 IRQ Handler
// blink blue when we are receiving CAN messages
void can_rx(uint8_t can_number);
bool can_init(uint8_t can_number);
+10 -9
View File
@@ -1,4 +1,4 @@
#include "can_common_declarations.h" #include "board/drivers/drivers.h"
uint32_t safety_tx_blocked = 0; uint32_t safety_tx_blocked = 0;
uint32_t safety_rx_invalid = 0; uint32_t safety_rx_invalid = 0;
@@ -11,7 +11,6 @@ can_health_t can_health[PANDA_CAN_CNT] = {{0}, {0}, {0}};
bool ignition_can = false; bool ignition_can = false;
uint32_t ignition_can_cnt = 0U; uint32_t ignition_can_cnt = 0U;
int pending_can_live = 0;
bool can_silent = true; bool can_silent = true;
bool can_loopback = false; bool can_loopback = false;
@@ -29,7 +28,7 @@ bool can_loopback = false;
__attribute__((section(".axisram"))) can_buffer(rx_q, CAN_RX_BUFFER_SIZE) __attribute__((section(".axisram"))) can_buffer(rx_q, CAN_RX_BUFFER_SIZE)
__attribute__((section(".itcmram"))) can_buffer(tx1_q, CAN_TX_BUFFER_SIZE) __attribute__((section(".itcmram"))) can_buffer(tx1_q, CAN_TX_BUFFER_SIZE)
__attribute__((section(".itcmram"))) can_buffer(tx2_q, CAN_TX_BUFFER_SIZE) __attribute__((section(".itcmram"))) can_buffer(tx2_q, CAN_TX_BUFFER_SIZE)
#else #else // kept for PC
can_buffer(rx_q, CAN_RX_BUFFER_SIZE) can_buffer(rx_q, CAN_RX_BUFFER_SIZE)
can_buffer(tx1_q, CAN_TX_BUFFER_SIZE) can_buffer(tx1_q, CAN_TX_BUFFER_SIZE)
can_buffer(tx2_q, CAN_TX_BUFFER_SIZE) can_buffer(tx2_q, CAN_TX_BUFFER_SIZE)
@@ -133,15 +132,11 @@ bus_config_t bus_config[PANDA_CAN_CNT] = {
{ .bus_lookup = 0U, .can_num_lookup = 0U, .forwarding_bus = -1, .can_speed = 5000U, .can_data_speed = 20000U, .canfd_auto = false, .canfd_enabled = false, .brs_enabled = false, .canfd_non_iso = false }, { .bus_lookup = 0U, .can_num_lookup = 0U, .forwarding_bus = -1, .can_speed = 5000U, .can_data_speed = 20000U, .canfd_auto = false, .canfd_enabled = false, .brs_enabled = false, .canfd_non_iso = false },
{ .bus_lookup = 1U, .can_num_lookup = 1U, .forwarding_bus = -1, .can_speed = 5000U, .can_data_speed = 20000U, .canfd_auto = false, .canfd_enabled = false, .brs_enabled = false, .canfd_non_iso = false }, { .bus_lookup = 1U, .can_num_lookup = 1U, .forwarding_bus = -1, .can_speed = 5000U, .can_data_speed = 20000U, .canfd_auto = false, .canfd_enabled = false, .brs_enabled = false, .canfd_non_iso = false },
{ .bus_lookup = 2U, .can_num_lookup = 2U, .forwarding_bus = -1, .can_speed = 5000U, .can_data_speed = 20000U, .canfd_auto = false, .canfd_enabled = false, .brs_enabled = false, .canfd_non_iso = false }, { .bus_lookup = 2U, .can_num_lookup = 2U, .forwarding_bus = -1, .can_speed = 5000U, .can_data_speed = 20000U, .canfd_auto = false, .canfd_enabled = false, .brs_enabled = false, .canfd_non_iso = false },
// { .bus_lookup = 0xFFU, .can_num_lookup = 0xFFU, .forwarding_bus = -1, .can_speed = 333U, .can_data_speed = 333U, .canfd_auto = false, .canfd_enabled = false, .brs_enabled = false, .canfd_non_iso = false },
}; };
void can_init_all(void) { void can_init_all(void) {
for (uint8_t i=0U; i < PANDA_CAN_CNT; i++) { for (uint8_t i=0U; i < PANDA_CAN_CNT; i++) {
if (!current_board->has_canfd) { bus_config[i].canfd_enabled = false;
bus_config[i].can_data_speed = 0U;
bus_config[i].canfd_enabled = false;
}
can_clear(can_queues[i]); can_clear(can_queues[i]);
(void)can_init(i); (void)can_init(i);
} }
@@ -205,8 +200,14 @@ void ignition_can_hook(CANPacket_t *msg) {
ignition_can = (msg->data[0] >> 5) == 0x6U; ignition_can = (msg->data[0] >> 5) == 0x6U;
ignition_can_cnt = 0U; ignition_can_cnt = 0U;
} }
} }
// TODO: this is too loose, Teslas have 0x222
// body v2 exception
// if (((msg->bus == 0U) || (msg->bus == 2U)) && (msg->addr == 0x222U)) {
// ignition_can = true;
// ignition_can_cnt = 0U;
// }
} }
bool can_tx_check_min_slots_free(uint32_t min) { bool can_tx_check_min_slots_free(uint32_t min) {
@@ -1,81 +0,0 @@
#pragma once
typedef struct {
volatile uint32_t w_ptr;
volatile uint32_t r_ptr;
uint32_t fifo_size;
CANPacket_t *elems;
} can_ring;
typedef struct {
uint8_t bus_lookup;
uint8_t can_num_lookup;
int8_t forwarding_bus;
uint32_t can_speed;
uint32_t can_data_speed;
bool canfd_auto;
bool canfd_enabled;
bool brs_enabled;
bool canfd_non_iso;
} bus_config_t;
extern uint32_t safety_tx_blocked;
extern uint32_t safety_rx_invalid;
extern uint32_t tx_buffer_overflow;
extern uint32_t rx_buffer_overflow;
extern can_health_t can_health[PANDA_CAN_CNT];
// Ignition detected from CAN meessages
extern bool ignition_can;
extern uint32_t ignition_can_cnt;
extern bool can_silent;
extern int pending_can_live;
// ******************* functions prototypes *********************
bool can_init(uint8_t can_number);
void process_can(uint8_t can_number);
// ********************* instantiate queues *********************
extern can_ring *can_queues[PANDA_CAN_CNT];
// helpers
#define WORD_TO_BYTE_ARRAY(dst8, src32) 0[dst8] = ((src32) & 0xFFU); 1[dst8] = (((src32) >> 8U) & 0xFFU); 2[dst8] = (((src32) >> 16U) & 0xFFU); 3[dst8] = (((src32) >> 24U) & 0xFFU)
#define BYTE_ARRAY_TO_WORD(dst32, src8) ((dst32) = 0[src8] | (1[src8] << 8U) | (2[src8] << 16U) | (3[src8] << 24U))
// ********************* interrupt safe queue *********************
bool can_pop(can_ring *q, CANPacket_t *elem);
bool can_push(can_ring *q, const CANPacket_t *elem);
uint32_t can_slots_empty(const can_ring *q);
// assign CAN numbering
// bus num: CAN Bus numbers in panda, sent to/from USB
// Min: 0; Max: 127; Bit 7 marks message as receipt (bus 129 is receipt for but 1)
// cans: Look up MCU can interface from bus number
// can number: numeric lookup for MCU CAN interfaces (0 = CAN1, 1 = CAN2, etc);
// bus_lookup: Translates from 'can number' to 'bus number'.
// can_num_lookup: Translates from 'bus number' to 'can number'.
// forwarding bus: If >= 0, forward all messages from this bus to the specified bus.
// Helpers
// Panda: Bus 0=CAN1 Bus 1=CAN2 Bus 2=CAN3
extern bus_config_t bus_config[PANDA_CAN_CNT];
#define CANIF_FROM_CAN_NUM(num) (cans[num])
#define BUS_NUM_FROM_CAN_NUM(num) (bus_config[num].bus_lookup)
#define CAN_NUM_FROM_BUS_NUM(num) (bus_config[num].can_num_lookup)
void can_init_all(void);
void can_set_orientation(bool flipped);
#ifdef PANDA_JUNGLE
void can_set_forwarding(uint8_t from, uint8_t to);
#endif
void ignition_can_hook(CANPacket_t *to_push);
bool can_tx_check_min_slots_free(uint32_t min);
uint8_t calculate_checksum(const uint8_t *dat, uint32_t len);
void can_set_checksum(CANPacket_t *packet);
bool can_check_checksum(CANPacket_t *packet);
void can_send(CANPacket_t *to_push, uint8_t bus_number, bool skip_tx_hook);
bool is_speed_valid(uint32_t speed, const uint32_t *all_speeds, uint8_t len);
+32 -10
View File
@@ -1,12 +1,16 @@
#include "clock_source_declarations.h" #include "board/drivers/drivers.h"
#define CLOCK_SOURCE_PERIOD_MS 50U
#define CLOCK_SOURCE_PULSE_LEN_MS 2U
void clock_source_set_timer_params(uint16_t param1, uint16_t param2) { void clock_source_set_timer_params(uint16_t param1, uint16_t param2) {
// Pulse length of each channel // Pulse length of each channel
register_set(&(TIM1->CCR1), (((param1 & 0xFF00U) >> 8U)*10U), 0xFFFFU); register_set(&(TIM1->CCR1), (((param1 & 0xFF00U) >> 8U)*10U), 0xFFFFU);
register_set(&(TIM1->CCR2), ((param1 & 0x00FFU)*10U), 0xFFFFU); register_set(&(TIM1->CCR2), ((param1 & 0x00FFU)*10U), 0xFFFFU);
register_set(&(TIM1->CCR3), (((param2 & 0xFF00U) >> 8U)*10U), 0xFFFFU); register_set(&(TIM8->CCR3), (((param2 & 0xFF00U) >> 8U)*10U), 0xFFFFU);
// Timer period // Timer period
register_set(&(TIM1->ARR), (((param2 & 0x00FFU)*10U) - 1U), 0xFFFFU); register_set(&(TIM1->ARR), (((param2 & 0x00FFU)*10U) - 1U), 0xFFFFU);
register_set(&(TIM1->CCR4), ((TIM1->ARR + 1U) / 2U), 0xFFFFU);
} }
void clock_source_init(bool enable_channel1) { void clock_source_init(bool enable_channel1) {
@@ -14,12 +18,12 @@ void clock_source_init(bool enable_channel1) {
register_set(&(TIM1->PSC), ((APB2_TIMER_FREQ*100U)-1U), 0xFFFFU); // Tick on 0.1 ms register_set(&(TIM1->PSC), ((APB2_TIMER_FREQ*100U)-1U), 0xFFFFU); // Tick on 0.1 ms
register_set(&(TIM1->ARR), ((CLOCK_SOURCE_PERIOD_MS*10U) - 1U), 0xFFFFU); // Period register_set(&(TIM1->ARR), ((CLOCK_SOURCE_PERIOD_MS*10U) - 1U), 0xFFFFU); // Period
register_set(&(TIM1->CCMR1), 0U, 0xFFFFU); // No output on compare register_set(&(TIM1->CCMR1), 0U, 0xFFFFU); // No output on compare
register_set(&(TIM1->CCER), TIM_CCER_CC1E, 0xFFFFU); // Enable compare 1 register_set(&(TIM1->CCER), TIM_CCER_CC1E | TIM_CCER_CC2NE, 0xFFFFU); // Enable compares
register_set(&(TIM1->CCR1), (CLOCK_SOURCE_PULSE_LEN_MS*10U), 0xFFFFU); // Compare 1 value register_set(&(TIM1->CCR1), (CLOCK_SOURCE_PULSE_LEN_MS*10U), 0xFFFFU); // Compare 1 value
register_set(&(TIM1->CCR2), (CLOCK_SOURCE_PULSE_LEN_MS*10U), 0xFFFFU); // Compare 1 value register_set(&(TIM1->CCR2), (CLOCK_SOURCE_PULSE_LEN_MS*10U), 0xFFFFU); // Compare 2 value
register_set(&(TIM1->CCR3), (CLOCK_SOURCE_PULSE_LEN_MS*10U), 0xFFFFU); // Compare 1 value register_set(&(TIM1->CCR4), (CLOCK_SOURCE_PERIOD_MS*5U), 0xFFFFU); // For slave timer
register_set_bits(&(TIM1->DIER), TIM_DIER_UIE | TIM_DIER_CC1IE); // Enable interrupts register_set_bits(&(TIM1->DIER), TIM_DIER_UIE | TIM_DIER_CC1IE); // Enable interrupts
register_set(&(TIM1->CR1), TIM_CR1_CEN, 0x3FU); // Enable timer
// No interrupts // No interrupts
NVIC_DisableIRQ(TIM1_UP_TIM10_IRQn); NVIC_DisableIRQ(TIM1_UP_TIM10_IRQn);
@@ -30,15 +34,33 @@ void clock_source_init(bool enable_channel1) {
set_gpio_alternate(GPIOA, 8, GPIO_AF1_TIM1); set_gpio_alternate(GPIOA, 8, GPIO_AF1_TIM1);
} }
set_gpio_alternate(GPIOB, 14, GPIO_AF1_TIM1); set_gpio_alternate(GPIOB, 14, GPIO_AF1_TIM1);
set_gpio_alternate(GPIOB, 15, GPIO_AF1_TIM1);
// Set PWM mode // Set PWM mode
register_set(&(TIM1->CCMR1), (0b110UL << TIM_CCMR1_OC1M_Pos) | (0b110UL << TIM_CCMR1_OC2M_Pos), 0xFFFFU); register_set(&(TIM1->CCMR1), (0b110UL << TIM_CCMR1_OC1M_Pos) | (0b110UL << TIM_CCMR1_OC2M_Pos), 0xFFFFU);
register_set(&(TIM1->CCMR2), (0b110UL << TIM_CCMR2_OC3M_Pos), 0xFFFFU); register_set(&(TIM1->CCMR2), (0b110UL << TIM_CCMR2_OC3M_Pos) | (0b111UL << TIM_CCMR2_OC4M_Pos), 0xFFFFU);
// Enable output // Enable output
register_set(&(TIM1->BDTR), TIM_BDTR_MOE, 0xFFFFU); register_set(&(TIM1->BDTR), TIM_BDTR_MOE, 0xFFFFU);
// Enable complementary compares // Sync with slave
register_set_bits(&(TIM1->CCER), TIM_CCER_CC2NE | TIM_CCER_CC3NE); register_set(&(TIM1->SMCR), TIM_SMCR_MSM , 0xFFFFU);
register_set(&(TIM1->CR2), (0b0111U << TIM_CR2_MMS_Pos), 0xFFFFU);
register_set(&(TIM8->SMCR), (0b0100U << TIM_SMCR_SMS_Pos) | (0b000U << TIM_SMCR_TS_Pos), 0xFFFFU);
// Setup slave timer (TIM8)
register_set(&(TIM8->PSC), TIM1->PSC, 0xFFFFU);
register_set(&(TIM8->ARR), TIM1->ARR, 0xFFFFU);
register_set(&(TIM8->CCMR2), (0b110UL << TIM_CCMR2_OC3M_Pos), 0xFFFFU);
register_set(&(TIM8->CCR3), (CLOCK_SOURCE_PULSE_LEN_MS * 10U), 0xFFFFU);
register_set(&(TIM8->CCER), TIM_CCER_CC3NE, 0xFFFFU);
// MOE for TIM8 as well
register_set(&(TIM8->BDTR), TIM_BDTR_MOE, 0xFFFFU);
// Set GPIO
set_gpio_alternate(GPIOB, 15, GPIO_AF3_TIM8);
// Enable timers
register_set(&(TIM1->CR1), TIM_CR1_CEN, 0x3FU);
register_set(&(TIM8->CR1), TIM_CR1_CEN, 0x3FU);
} }
@@ -1,7 +0,0 @@
#pragma once
#define CLOCK_SOURCE_PERIOD_MS 50U
#define CLOCK_SOURCE_PULSE_LEN_MS 2U
void clock_source_set_timer_params(uint16_t param1, uint16_t param2);
void clock_source_init(bool enable_channel1);
+287
View File
@@ -0,0 +1,287 @@
#pragma once
#include "board/can.h"
#include "board/health.h"
#include "board/crc.h"
#ifdef STM32H7
#include "board/stm32h7/lladc_declarations.h"
#endif
// ******************** bootkick ********************
extern bool bootkick_reset_triggered;
void bootkick_tick(bool ignition, bool recent_heartbeat);
// ******************** can_common ********************
typedef struct {
volatile uint32_t w_ptr;
volatile uint32_t r_ptr;
uint32_t fifo_size;
CANPacket_t *elems;
} can_ring;
typedef struct {
uint8_t bus_lookup;
uint8_t can_num_lookup;
int8_t forwarding_bus;
uint32_t can_speed;
uint32_t can_data_speed;
bool canfd_auto;
bool canfd_enabled;
bool brs_enabled;
bool canfd_non_iso;
} bus_config_t;
extern uint32_t safety_tx_blocked;
extern uint32_t safety_rx_invalid;
extern uint32_t tx_buffer_overflow;
extern uint32_t rx_buffer_overflow;
extern can_health_t can_health[PANDA_CAN_CNT];
// Ignition detected from CAN meessages
extern bool ignition_can;
extern uint32_t ignition_can_cnt;
extern bool can_silent;
extern bool can_loopback;
// ******************* functions prototypes *********************
bool can_init(uint8_t can_number);
void process_can(uint8_t can_number);
// ********************* instantiate queues *********************
extern can_ring *can_queues[PANDA_CAN_CNT];
// helpers
#define WORD_TO_BYTE_ARRAY(dst8, src32) 0[dst8] = ((src32) & 0xFFU); 1[dst8] = (((src32) >> 8U) & 0xFFU); 2[dst8] = (((src32) >> 16U) & 0xFFU); 3[dst8] = (((src32) >> 24U) & 0xFFU)
#define BYTE_ARRAY_TO_WORD(dst32, src8) ((dst32) = 0[src8] | (1[src8] << 8U) | (2[src8] << 16U) | (3[src8] << 24U))
// ********************* interrupt safe queue *********************
bool can_pop(can_ring *q, CANPacket_t *elem);
bool can_push(can_ring *q, const CANPacket_t *elem);
uint32_t can_slots_empty(const can_ring *q);
extern bus_config_t bus_config[PANDA_CAN_CNT];
#define CANIF_FROM_CAN_NUM(num) (cans[num])
#define BUS_NUM_FROM_CAN_NUM(num) (bus_config[num].bus_lookup)
#define CAN_NUM_FROM_BUS_NUM(num) (bus_config[num].can_num_lookup)
void can_init_all(void);
void can_set_orientation(bool flipped);
#ifdef PANDA_JUNGLE
void can_set_forwarding(uint8_t from, uint8_t to);
#endif
void ignition_can_hook(CANPacket_t *to_push);
bool can_tx_check_min_slots_free(uint32_t min);
uint8_t calculate_checksum(const uint8_t *dat, uint32_t len);
void can_set_checksum(CANPacket_t *packet);
bool can_check_checksum(CANPacket_t *packet);
void can_send(CANPacket_t *to_push, uint8_t bus_number, bool skip_tx_hook);
bool is_speed_valid(uint32_t speed, const uint32_t *all_speeds, uint8_t len);
// ******************** clock_source ********************
void clock_source_set_timer_params(uint16_t param1, uint16_t param2);
void clock_source_init(bool enable_channel1);
// ******************** fan ********************
struct fan_state_t {
uint16_t tach_counter;
uint16_t rpm;
uint8_t power;
float error_integral;
uint8_t cooldown_counter;
};
extern struct fan_state_t fan_state;
void fan_set_power(uint8_t percentage);
void llfan_init(void);
void fan_init(void);
// Call this at FAN_TICK_FREQ
void fan_tick(void);
// ******************** fdcan ********************
#ifdef STM32H7
typedef struct {
volatile uint32_t header[2];
volatile uint32_t data_word[CANPACKET_DATA_SIZE_MAX/4U];
} canfd_fifo;
extern FDCAN_GlobalTypeDef *cans[PANDA_CAN_CNT];
#define CAN_ACK_ERROR 3U
void can_clear_send(FDCAN_GlobalTypeDef *FDCANx, uint8_t can_number);
void update_can_health_pkt(uint8_t can_number, uint32_t ir_reg);
void process_can(uint8_t can_number);
void can_rx(uint8_t can_number);
bool can_init(uint8_t can_number);
// ******************** harness ********************
#define HARNESS_STATUS_NC 0U
#define HARNESS_STATUS_NORMAL 1U
#define HARNESS_STATUS_FLIPPED 2U
struct harness_t {
uint8_t status;
uint16_t sbu1_voltage_mV;
uint16_t sbu2_voltage_mV;
bool relay_driven;
bool sbu_adc_lock;
};
extern struct harness_t harness;
struct harness_configuration {
GPIO_TypeDef * const GPIO_SBU1;
GPIO_TypeDef * const GPIO_SBU2;
GPIO_TypeDef * const GPIO_relay_SBU1;
GPIO_TypeDef * const GPIO_relay_SBU2;
const uint8_t pin_SBU1;
const uint8_t pin_SBU2;
const uint8_t pin_relay_SBU1;
const uint8_t pin_relay_SBU2;
const adc_signal_t adc_signal_SBU1;
const adc_signal_t adc_signal_SBU2;
};
// The ignition relay is only used for testing purposes
void set_intercept_relay(bool intercept, bool ignition_relay);
bool harness_check_ignition(void);
void harness_tick(void);
void harness_init(void);
// ******************** interrupts ********************
typedef struct interrupt {
IRQn_Type irq_type;
void (*handler)(void);
uint32_t call_counter;
uint32_t call_rate;
uint32_t max_call_rate; // Call rate is defined as the amount of calls each second
uint32_t call_rate_fault;
} interrupt;
void interrupt_timer_init(void);
uint32_t microsecond_timer_get(void);
void unused_interrupt_handler(void);
extern interrupt interrupts[NUM_INTERRUPTS];
#define REGISTER_INTERRUPT(irq_num, func_ptr, call_rate_max, rate_fault) \
interrupts[irq_num].irq_type = (irq_num); \
interrupts[irq_num].handler = (func_ptr); \
interrupts[irq_num].call_counter = 0U; \
interrupts[irq_num].call_rate = 0U; \
interrupts[irq_num].max_call_rate = (call_rate_max); \
interrupts[irq_num].call_rate_fault = (rate_fault);
extern float interrupt_load;
void handle_interrupt(IRQn_Type irq_type);
// Every second
void interrupt_timer_handler(void);
void init_interrupts(bool check_rate_limit);
#endif // STM32H7
// ******************** registers ********************
// 10 bit hash with 23 as a prime
#define REGISTER_MAP_SIZE 0x3FFU
#define HASHING_PRIME 23U
// Do not put bits in the check mask that get changed by the hardware
void register_set(volatile uint32_t *addr, uint32_t val, uint32_t mask);
// Set individual bits. Also add them to the check_mask.
// Do not use this to change bits that get reset by the hardware
void register_set_bits(volatile uint32_t *addr, uint32_t val);
// Clear individual bits. Also add them to the check_mask.
// Do not use this to clear bits that get set by the hardware
void register_clear_bits(volatile uint32_t *addr, uint32_t val);
// To be called periodically
void check_registers(void);
void init_registers(void);
// ******************** simple_watchdog ********************
typedef struct simple_watchdog_state_t {
uint32_t fault;
uint32_t last_ts;
uint32_t threshold;
} simple_watchdog_state_t;
void simple_watchdog_kick(void);
void simple_watchdog_init(uint32_t fault, uint32_t threshold);
// ******************** spi ********************
// got max rate from hitting a non-existent endpoint
// in a tight loop, plus some buffer
#define SPI_IRQ_RATE 16000U
#define SPI_BUF_SIZE 4096U
extern uint8_t spi_buf_rx[SPI_BUF_SIZE];
extern uint8_t spi_buf_tx[SPI_BUF_SIZE];
extern uint16_t spi_error_count;
void can_tx_comms_resume_spi(void);
void spi_init(void);
void spi_rx_done(void);
void spi_tx_done(bool reset);
// ******************** uart ********************
#ifdef STM32H7
// ***************************** Definitions *****************************
#define FIFO_SIZE_INT 0x400U
typedef struct uart_ring {
volatile uint16_t w_ptr_tx;
volatile uint16_t r_ptr_tx;
uint8_t *elems_tx;
uint32_t tx_fifo_size;
volatile uint16_t w_ptr_rx;
volatile uint16_t r_ptr_rx;
uint8_t *elems_rx;
uint32_t rx_fifo_size;
USART_TypeDef *uart;
void (*callback)(struct uart_ring*);
bool overwrite;
} uart_ring;
// ***************************** Function prototypes *****************************
void debug_ring_callback(uart_ring *ring);
void uart_tx_ring(uart_ring *q);
uart_ring *get_ring_by_number(int a);
// ************************* Low-level buffer functions *************************
bool get_char(uart_ring *q, char *elem);
bool injectc(uart_ring *q, char elem);
bool put_char(uart_ring *q, char elem);
void clear_uart_buff(uart_ring *q);
// ************************ High-level debug functions **********************
void putch(const char a);
void print(const char *a);
void puthx(uint32_t i, uint8_t len);
void puth(unsigned int i);
#if defined(DEBUG_SPI) || defined(BOOTSTUB) || defined(DEBUG)
static void puth4(unsigned int i);
#endif
#if defined(DEBUG_SPI) || defined(DEBUG_USB) || defined(DEBUG_COMMS)
static void hexdump(const void *a, int l);
#endif
#endif // STM32H7
// ******************** usb ********************
void usb_init(void);
void refresh_can_tx_slots_available(void);
void can_tx_comms_resume_usb(void);
+64 -33
View File
@@ -1,8 +1,37 @@
#include "stm32h7/lli2c.h" #include "board/stm32h7/lli2c.h"
#define CODEC_I2C_ADDR 0x10 #define CODEC_I2C_ADDR 0x10
void fake_siren_init(void); void siren_tim7_init(void) {
// Init trigger timer (around 2.5kHz)
register_set(&TIM7->PSC, 0U, 0xFFFFU);
register_set(&TIM7->ARR, 133U, 0xFFFFU);
register_set(&TIM7->CR2, (0b10U << TIM_CR2_MMS_Pos), TIM_CR2_MMS_Msk);
register_set(&TIM7->CR1, TIM_CR1_ARPE | TIM_CR1_URS, 0x088EU);
TIM7->SR = 0U;
TIM7->CR1 |= TIM_CR1_CEN;
}
void siren_dac_init(void) {
DAC1->DHR8R1 = (1U << 7);
DAC1->DHR8R2 = (1U << 7);
register_set(&DAC1->MCR, 0U, 0xFFFFFFFFU);
register_set(&DAC1->CR, DAC_CR_TEN1 | (6U << DAC_CR_TSEL1_Pos) | DAC_CR_DMAEN1, 0xFFFFFFFFU);
register_set_bits(&DAC1->CR, DAC_CR_EN1 | DAC_CR_EN2);
}
void siren_dma_init(void) {
// 1Vpp sine wave with 1V offset
static const uint8_t fake_siren_lut[360] = { 134U, 135U, 137U, 138U, 139U, 140U, 141U, 143U, 144U, 145U, 146U, 148U, 149U, 150U, 151U, 152U, 154U, 155U, 156U, 157U, 158U, 159U, 160U, 162U, 163U, 164U, 165U, 166U, 167U, 168U, 169U, 170U, 171U, 172U, 174U, 175U, 176U, 177U, 177U, 178U, 179U, 180U, 181U, 182U, 183U, 184U, 185U, 186U, 186U, 187U, 188U, 189U, 190U, 190U, 191U, 192U, 193U, 193U, 194U, 195U, 195U, 196U, 196U, 197U, 197U, 198U, 199U, 199U, 199U, 200U, 200U, 201U, 201U, 202U, 202U, 202U, 203U, 203U, 203U, 203U, 204U, 204U, 204U, 204U, 204U, 204U, 204U, 205U, 205U, 205U, 205U, 205U, 205U, 205U, 204U, 204U, 204U, 204U, 204U, 204U, 204U, 203U, 203U, 203U, 203U, 202U, 202U, 202U, 201U, 201U, 200U, 200U, 199U, 199U, 199U, 198U, 197U, 197U, 196U, 196U, 195U, 195U, 194U, 193U, 193U, 192U, 191U, 190U, 190U, 189U, 188U, 187U, 186U, 186U, 185U, 184U, 183U, 182U, 181U, 180U, 179U, 178U, 177U, 177U, 176U, 175U, 174U, 172U, 171U, 170U, 169U, 168U, 167U, 166U, 165U, 164U, 163U, 162U, 160U, 159U, 158U, 157U, 156U, 155U, 154U, 152U, 151U, 150U, 149U, 148U, 146U, 145U, 144U, 143U, 141U, 140U, 139U, 138U, 137U, 135U, 134U, 133U, 132U, 130U, 129U, 128U, 127U, 125U, 124U, 123U, 122U, 121U, 119U, 118U, 117U, 116U, 115U, 113U, 112U, 111U, 110U, 109U, 108U, 106U, 105U, 104U, 103U, 102U, 101U, 100U, 99U, 98U, 97U, 96U, 95U, 94U, 93U, 92U, 91U, 90U, 89U, 88U, 87U, 86U, 85U, 84U, 83U, 82U, 82U, 81U, 80U, 79U, 78U, 78U, 77U, 76U, 76U, 75U, 74U, 74U, 73U, 72U, 72U, 71U, 71U, 70U, 70U, 69U, 69U, 68U, 68U, 67U, 67U, 67U, 66U, 66U, 66U, 65U, 65U, 65U, 65U, 64U, 64U, 64U, 64U, 64U, 64U, 64U, 64U, 64U, 63U, 64U, 64U, 64U, 64U, 64U, 64U, 64U, 64U, 64U, 65U, 65U, 65U, 65U, 66U, 66U, 66U, 67U, 67U, 67U, 68U, 68U, 69U, 69U, 70U, 70U, 71U, 71U, 72U, 72U, 73U, 74U, 74U, 75U, 76U, 76U, 77U, 78U, 78U, 79U, 80U, 81U, 82U, 82U, 83U, 84U, 85U, 86U, 87U, 88U, 89U, 90U, 91U, 92U, 93U, 94U, 95U, 96U, 97U, 98U, 99U, 100U, 101U, 102U, 103U, 104U, 105U, 106U, 108U, 109U, 110U, 111U, 112U, 113U, 115U, 116U, 117U, 118U, 119U, 121U, 122U, 123U, 124U, 125U, 127U, 128U, 129U, 130U, 132U, 133U };
// Setup DMAMUX (DAC_CH1_DMA as input)
register_set(&DMAMUX1_Channel1->CCR, 67U, DMAMUX_CxCR_DMAREQ_ID_Msk);
register_set(&DMA1_Stream1->PAR, (uint32_t)&(DAC1->DHR8R1), 0xFFFFFFFFU);
// Setup DMA
register_set(&DMA1_Stream1->M0AR, (uint32_t)fake_siren_lut, 0xFFFFFFFFU);
register_set(&DMA1_Stream1->FCR, 0U, 0x00000083U);
DMA1_Stream1->NDTR = sizeof(fake_siren_lut);
DMA1_Stream1->CR = (0b11UL << DMA_SxCR_PL_Pos) | DMA_SxCR_MINC | DMA_SxCR_CIRC | (1U << DMA_SxCR_DIR_Pos);
}
void fake_siren_codec_enable(bool enabled) { void fake_siren_codec_enable(bool enabled) {
if (enabled) { if (enabled) {
@@ -28,13 +57,21 @@ void fake_siren_codec_enable(bool enabled) {
} }
} }
static void fake_i2c_siren_init(void) {
siren_dac_init();
siren_dma_init();
siren_tim7_init();
// Enable the I2C to the codec
i2c_init(I2C5);
fake_siren_codec_enable(false);
}
void fake_siren_set(bool enabled) { void fake_i2c_siren_set(bool enabled) {
static bool initialized = false; static bool initialized = false;
static bool fake_siren_enabled = false; static bool fake_siren_enabled = false;
if (!initialized) { if (!initialized) {
fake_siren_init(); fake_i2c_siren_init();
initialized = true; initialized = true;
} }
@@ -50,35 +87,29 @@ void fake_siren_set(bool enabled) {
fake_siren_enabled = enabled; fake_siren_enabled = enabled;
} }
void fake_siren_init(void) { void fake_siren_set(bool enabled) {
// 1Vpp sine wave with 1V offset static bool initialized = false;
static const uint8_t fake_siren_lut[360] = { 134U, 135U, 137U, 138U, 139U, 140U, 141U, 143U, 144U, 145U, 146U, 148U, 149U, 150U, 151U, 152U, 154U, 155U, 156U, 157U, 158U, 159U, 160U, 162U, 163U, 164U, 165U, 166U, 167U, 168U, 169U, 170U, 171U, 172U, 174U, 175U, 176U, 177U, 177U, 178U, 179U, 180U, 181U, 182U, 183U, 184U, 185U, 186U, 186U, 187U, 188U, 189U, 190U, 190U, 191U, 192U, 193U, 193U, 194U, 195U, 195U, 196U, 196U, 197U, 197U, 198U, 199U, 199U, 199U, 200U, 200U, 201U, 201U, 202U, 202U, 202U, 203U, 203U, 203U, 203U, 204U, 204U, 204U, 204U, 204U, 204U, 204U, 205U, 205U, 205U, 205U, 205U, 205U, 205U, 204U, 204U, 204U, 204U, 204U, 204U, 204U, 203U, 203U, 203U, 203U, 202U, 202U, 202U, 201U, 201U, 200U, 200U, 199U, 199U, 199U, 198U, 197U, 197U, 196U, 196U, 195U, 195U, 194U, 193U, 193U, 192U, 191U, 190U, 190U, 189U, 188U, 187U, 186U, 186U, 185U, 184U, 183U, 182U, 181U, 180U, 179U, 178U, 177U, 177U, 176U, 175U, 174U, 172U, 171U, 170U, 169U, 168U, 167U, 166U, 165U, 164U, 163U, 162U, 160U, 159U, 158U, 157U, 156U, 155U, 154U, 152U, 151U, 150U, 149U, 148U, 146U, 145U, 144U, 143U, 141U, 140U, 139U, 138U, 137U, 135U, 134U, 133U, 132U, 130U, 129U, 128U, 127U, 125U, 124U, 123U, 122U, 121U, 119U, 118U, 117U, 116U, 115U, 113U, 112U, 111U, 110U, 109U, 108U, 106U, 105U, 104U, 103U, 102U, 101U, 100U, 99U, 98U, 97U, 96U, 95U, 94U, 93U, 92U, 91U, 90U, 89U, 88U, 87U, 86U, 85U, 84U, 83U, 82U, 82U, 81U, 80U, 79U, 78U, 78U, 77U, 76U, 76U, 75U, 74U, 74U, 73U, 72U, 72U, 71U, 71U, 70U, 70U, 69U, 69U, 68U, 68U, 67U, 67U, 67U, 66U, 66U, 66U, 65U, 65U, 65U, 65U, 64U, 64U, 64U, 64U, 64U, 64U, 64U, 64U, 64U, 63U, 64U, 64U, 64U, 64U, 64U, 64U, 64U, 64U, 64U, 65U, 65U, 65U, 65U, 66U, 66U, 66U, 67U, 67U, 67U, 68U, 68U, 69U, 69U, 70U, 70U, 71U, 71U, 72U, 72U, 73U, 74U, 74U, 75U, 76U, 76U, 77U, 78U, 78U, 79U, 80U, 81U, 82U, 82U, 83U, 84U, 85U, 86U, 87U, 88U, 89U, 90U, 91U, 92U, 93U, 94U, 95U, 96U, 97U, 98U, 99U, 100U, 101U, 102U, 103U, 104U, 105U, 106U, 108U, 109U, 110U, 111U, 112U, 113U, 115U, 116U, 117U, 118U, 119U, 121U, 122U, 123U, 124U, 125U, 127U, 128U, 129U, 130U, 132U, 133U }; static bool fake_siren_enabled = false;
// Init DAC if (!initialized) {
register_set(&DAC1->MCR, 0U, 0xFFFFFFFFU); siren_tim7_init();
register_set(&DAC1->CR, DAC_CR_TEN1 | (6U << DAC_CR_TSEL1_Pos) | DAC_CR_DMAEN1, 0xFFFFFFFFU); initialized = true;
register_set_bits(&DAC1->CR, DAC_CR_EN1); }
// Setup DMAMUX (DAC_CH1_DMA as input) if (enabled != fake_siren_enabled) {
register_set(&DMAMUX1_Channel1->CCR, 67U, DMAMUX_CxCR_DMAREQ_ID_Msk); if (enabled) {
sound_stop_dac();
// Setup DMA siren_dac_init();
register_set(&DMA1_Stream1->M0AR, (uint32_t) fake_siren_lut, 0xFFFFFFFFU); siren_dma_init();
register_set(&DMA1_Stream1->PAR, (uint32_t) &(DAC1->DHR8R1), 0xFFFFFFFFU); current_board->set_amp_enabled(true);
DMA1_Stream1->NDTR = sizeof(fake_siren_lut); register_set_bits(&DMA1_Stream1->CR, DMA_SxCR_EN);
register_set(&DMA1_Stream1->FCR, 0U, 0x00000083U); } else {
DMA1_Stream1->CR = (0b11UL << DMA_SxCR_PL_Pos); current_board->set_amp_enabled(false);
DMA1_Stream1->CR |= DMA_SxCR_MINC | DMA_SxCR_CIRC | (1U << DMA_SxCR_DIR_Pos); // Stop modified 8-bit DAC and start normal 12-bit DAC
sound_stop_dac();
// Init trigger timer (around 2.5kHz) sound_init_dac();
register_set(&TIM7->PSC, 0U, 0xFFFFU); register_set_bits(&BDMA_Channel0->CCR, BDMA_CCR_EN);
register_set(&TIM7->ARR, 133U, 0xFFFFU); }
register_set(&TIM7->CR2, (0b10U << TIM_CR2_MMS_Pos), TIM_CR2_MMS_Msk); fake_siren_enabled = enabled;
register_set(&TIM7->CR1, TIM_CR1_ARPE | TIM_CR1_URS, 0x088EU); }
TIM7->SR = 0U;
TIM7->CR1 |= TIM_CR1_CEN;
// Enable the I2C to the codec
i2c_init(I2C5);
fake_siren_codec_enable(false);
} }
+10 -49
View File
@@ -1,68 +1,39 @@
#include "fan_declarations.h" #include "board/drivers/drivers.h"
struct fan_state_t fan_state; struct fan_state_t fan_state;
static const uint8_t FAN_TICK_FREQ = 8U; static const uint8_t FAN_TICK_FREQ = 8U;
static const uint8_t FAN_STALL_THRESHOLD_MIN = 3U;
void fan_set_power(uint8_t percentage) { void fan_set_power(uint8_t percentage) {
fan_state.target_rpm = ((current_board->fan_max_rpm * CLAMP(percentage, 0U, 100U)) / 100U); if (percentage > 0U) {
fan_state.power = CLAMP(percentage, 20U, 100U);
} else {
fan_state.power = 0U;
}
} }
void llfan_init(void);
void fan_init(void) { void fan_init(void) {
fan_state.stall_threshold = FAN_STALL_THRESHOLD_MIN;
fan_state.cooldown_counter = current_board->fan_enable_cooldown_time * FAN_TICK_FREQ; fan_state.cooldown_counter = current_board->fan_enable_cooldown_time * FAN_TICK_FREQ;
llfan_init(); llfan_init();
} }
// Call this at FAN_TICK_FREQ // Call this at FAN_TICK_FREQ
void fan_tick(void) { void fan_tick(void) {
const float FAN_I = 6.5f; if (current_board->has_fan) {
const uint8_t FAN_STALL_THRESHOLD_MAX = 8U;
if (current_board->fan_max_rpm > 0U) {
// Measure fan RPM // Measure fan RPM
uint16_t fan_rpm_fast = fan_state.tach_counter * (60U * FAN_TICK_FREQ / 4U); // 4 interrupts per rotation uint16_t fan_rpm_fast = fan_state.tach_counter * (60U * FAN_TICK_FREQ / 4U); // 4 interrupts per rotation
fan_state.tach_counter = 0U; fan_state.tach_counter = 0U;
fan_state.rpm = (fan_rpm_fast + (3U * fan_state.rpm)) / 4U; fan_state.rpm = (fan_rpm_fast + (3U * fan_state.rpm)) / 4U;
// Stall detection
bool fan_stalled = false;
if (current_board->fan_stall_recovery) {
if (fan_state.target_rpm > 0U) {
if (fan_rpm_fast == 0U) {
fan_state.stall_counter = MIN(fan_state.stall_counter + 1U, 254U);
} else {
fan_state.stall_counter = 0U;
}
if (fan_state.stall_counter > (fan_state.stall_threshold*FAN_TICK_FREQ)) {
fan_stalled = true;
fan_state.stall_counter = 0U;
fan_state.stall_threshold = CLAMP(fan_state.stall_threshold + 2U, FAN_STALL_THRESHOLD_MIN, FAN_STALL_THRESHOLD_MAX);
fan_state.total_stall_count += 1U;
// datasheet gives this range as the minimum startup duty
fan_state.error_integral = CLAMP(fan_state.error_integral, 20.0f, 45.0f);
}
} else {
fan_state.stall_counter = 0U;
fan_state.stall_threshold = FAN_STALL_THRESHOLD_MIN;
}
}
#ifdef DEBUG_FAN #ifdef DEBUG_FAN
puth(fan_state.target_rpm); puth(fan_state.target_rpm);
print(" "); puth(fan_rpm_fast); print(" "); puth(fan_rpm_fast);
print(" "); puth(fan_state.power); print(" "); puth(fan_state.power);
print(" "); puth(fan_state.stall_counter);
print("\n"); print("\n");
#endif #endif
// Cooldown counter // Cooldown counter to prevent noise on tachometer line.
if (fan_state.target_rpm > 0U) { if (fan_state.power > 0U) {
fan_state.cooldown_counter = current_board->fan_enable_cooldown_time * FAN_TICK_FREQ; fan_state.cooldown_counter = current_board->fan_enable_cooldown_time * FAN_TICK_FREQ;
} else { } else {
if (fan_state.cooldown_counter > 0U) { if (fan_state.cooldown_counter > 0U) {
@@ -70,18 +41,8 @@ void fan_tick(void) {
} }
} }
// Update controller
if (fan_state.target_rpm == 0U) {
fan_state.error_integral = 0.0f;
} else {
float error = (fan_state.target_rpm - fan_rpm_fast) / ((float) current_board->fan_max_rpm);
fan_state.error_integral += FAN_I * error;
}
fan_state.error_integral = CLAMP(fan_state.error_integral, 0U, current_board->fan_max_pwm);
fan_state.power = fan_state.error_integral;
// Set PWM and enable line // Set PWM and enable line
pwm_set(TIM3, 3, fan_state.power); pwm_set(TIM3, 3, fan_state.power);
current_board->set_fan_enabled(!fan_stalled && ((fan_state.target_rpm > 0U) || (fan_state.cooldown_counter > 0U))); current_board->set_fan_enabled((fan_state.power > 0U) || (fan_state.cooldown_counter > 0U));
} }
} }
-20
View File
@@ -1,20 +0,0 @@
#pragma once
struct fan_state_t {
uint16_t tach_counter;
uint16_t rpm;
uint16_t target_rpm;
uint8_t power;
float error_integral;
uint8_t stall_counter;
uint8_t stall_threshold;
uint8_t total_stall_count;
uint8_t cooldown_counter;
};
extern struct fan_state_t fan_state;
void fan_set_power(uint8_t percentage);
void llfan_init(void);
void fan_init(void);
// Call this at FAN_TICK_FREQ
void fan_tick(void);
+10 -11
View File
@@ -1,6 +1,6 @@
#include "fdcan_declarations.h" #include "board/drivers/drivers.h"
FDCAN_GlobalTypeDef *cans[CANS_ARRAY_SIZE] = {FDCAN1, FDCAN2, FDCAN3}; FDCAN_GlobalTypeDef *cans[PANDA_CAN_CNT] = {FDCAN1, FDCAN2, FDCAN3};
static bool can_set_speed(uint8_t can_number) { static bool can_set_speed(uint8_t can_number) {
bool ret = true; bool ret = true;
@@ -13,7 +13,7 @@ static bool can_set_speed(uint8_t can_number) {
bus_config[bus_number].can_data_speed, bus_config[bus_number].can_data_speed,
bus_config[bus_number].canfd_non_iso, bus_config[bus_number].canfd_non_iso,
can_loopback, can_loopback,
(unsigned int)(can_silent) & (1U << can_number) can_silent
); );
return ret; return ret;
} }
@@ -32,7 +32,7 @@ void can_clear_send(FDCAN_GlobalTypeDef *FDCANx, uint8_t can_number) {
} }
void update_can_health_pkt(uint8_t can_number, uint32_t ir_reg) { void update_can_health_pkt(uint8_t can_number, uint32_t ir_reg) {
uint8_t can_irq_number[3][2] = { uint8_t can_irq_number[PANDA_CAN_CNT][2] = {
{ FDCAN1_IT0_IRQn, FDCAN1_IT1_IRQn }, { FDCAN1_IT0_IRQn, FDCAN1_IT1_IRQn },
{ FDCAN2_IT0_IRQn, FDCAN2_IT1_IRQn }, { FDCAN2_IT0_IRQn, FDCAN2_IT1_IRQn },
{ FDCAN3_IT0_IRQn, FDCAN3_IT1_IRQn }, { FDCAN3_IT0_IRQn, FDCAN3_IT1_IRQn },
@@ -63,7 +63,6 @@ void update_can_health_pkt(uint8_t can_number, uint32_t ir_reg) {
can_health[can_number].irq0_call_rate = interrupts[can_irq_number[can_number][0]].call_rate; can_health[can_number].irq0_call_rate = interrupts[can_irq_number[can_number][0]].call_rate;
can_health[can_number].irq1_call_rate = interrupts[can_irq_number[can_number][1]].call_rate; can_health[can_number].irq1_call_rate = interrupts[can_irq_number[can_number][1]].call_rate;
if (ir_reg != 0U) { if (ir_reg != 0U) {
// Clear error interrupts // Clear error interrupts
FDCANx->IR |= (FDCAN_IR_PED | FDCAN_IR_PEA | FDCAN_IR_EP | FDCAN_IR_BO | FDCAN_IR_RF0L); FDCANx->IR |= (FDCAN_IR_PED | FDCAN_IR_PEA | FDCAN_IR_EP | FDCAN_IR_BO | FDCAN_IR_RF0L);
@@ -158,17 +157,13 @@ void can_rx(uint8_t can_number) {
// Clear all new messages from Rx FIFO 0 // Clear all new messages from Rx FIFO 0
FDCANx->IR |= FDCAN_IR_RF0N; FDCANx->IR |= FDCAN_IR_RF0N;
while((FDCANx->RXF0S & FDCAN_RXF0S_F0FL) != 0U) { while ((FDCANx->RXF0S & FDCAN_RXF0S_F0FL) != 0U) {
can_health[can_number].total_rx_cnt += 1U; can_health[can_number].total_rx_cnt += 1U;
// can is live
pending_can_live = 1;
// get the index of the next RX FIFO element (0 to FDCAN_RX_FIFO_0_EL_CNT - 1) // get the index of the next RX FIFO element (0 to FDCAN_RX_FIFO_0_EL_CNT - 1)
uint32_t rx_fifo_idx = (uint8_t)((FDCANx->RXF0S >> FDCAN_RXF0S_F0GI_Pos) & 0x3FU); uint32_t rx_fifo_idx = (uint8_t)((FDCANx->RXF0S >> FDCAN_RXF0S_F0GI_Pos) & 0x3FU);
// Recommended to offset get index by at least +1 if RX FIFO is in overwrite mode and full (datasheet) // Recommended to offset get index by at least +1 if RX FIFO is in overwrite mode and full (datasheet)
if((FDCANx->RXF0S & FDCAN_RXF0S_F0F) == FDCAN_RXF0S_F0F) { if ((FDCANx->RXF0S & FDCAN_RXF0S_F0F) == FDCAN_RXF0S_F0F) {
rx_fifo_idx = ((rx_fifo_idx + 1U) >= FDCAN_RX_FIFO_0_EL_CNT) ? 0U : (rx_fifo_idx + 1U); rx_fifo_idx = ((rx_fifo_idx + 1U) >= FDCAN_RX_FIFO_0_EL_CNT) ? 0U : (rx_fifo_idx + 1U);
can_health[can_number].total_rx_lost_cnt += 1U; // At least one message was lost can_health[can_number].total_rx_lost_cnt += 1U; // At least one message was lost
} }
@@ -220,6 +215,10 @@ void can_rx(uint8_t can_number) {
can_health[can_number].total_fwd_cnt += 1U; can_health[can_number].total_fwd_cnt += 1U;
} }
#ifdef PANDA_BODY
body_can_rx(&to_push);
#endif
safety_rx_invalid += safety_rx_hook(&to_push) ? 0U : 1U; safety_rx_invalid += safety_rx_hook(&to_push) ? 0U : 1U;
ignition_can_hook(&to_push); ignition_can_hook(&to_push);
-28
View File
@@ -1,28 +0,0 @@
#pragma once
// IRQs: FDCAN1_IT0, FDCAN1_IT1
// FDCAN2_IT0, FDCAN2_IT1
// FDCAN3_IT0, FDCAN3_IT1
#define CANFD
typedef struct {
volatile uint32_t header[2];
volatile uint32_t data_word[CANPACKET_DATA_SIZE_MAX/4U];
} canfd_fifo;
#define CANS_ARRAY_SIZE 3
extern FDCAN_GlobalTypeDef *cans[CANS_ARRAY_SIZE];
#define CAN_ACK_ERROR 3U
void can_clear_send(FDCAN_GlobalTypeDef *FDCANx, uint8_t can_number);
void update_can_health_pkt(uint8_t can_number, uint32_t ir_reg);
// ***************************** CAN *****************************
// FDFDCANx_IT1 IRQ Handler (TX)
void process_can(uint8_t can_number);
// FDFDCANx_IT0 IRQ Handler (RX and errors)
// blink blue when we are receiving CAN messages
void can_rx(uint8_t can_number);
bool can_init(uint8_t can_number);
+23 -25
View File
@@ -1,34 +1,32 @@
#include "harness_declarations.h" #include "board/drivers/drivers.h"
struct harness_t harness; struct harness_t harness;
// The ignition relay is only used for testing purposes // The ignition relay is only used for testing purposes
void set_intercept_relay(bool intercept, bool ignition_relay) { void set_intercept_relay(bool intercept, bool ignition_relay) {
if (current_board->harness_config->has_harness) { bool drive_relay = intercept;
bool drive_relay = intercept; if (harness.status == HARNESS_STATUS_NC) {
if (harness.status == HARNESS_STATUS_NC) { // no harness, no relay to drive
// no harness, no relay to drive drive_relay = false;
drive_relay = false; }
}
if (drive_relay || ignition_relay) { if (drive_relay || ignition_relay) {
harness.relay_driven = true; harness.relay_driven = true;
} }
// wait until we're not reading the analog voltages anymore // wait until we're not reading the analog voltages anymore
while (harness.sbu_adc_lock) {} while (harness.sbu_adc_lock) {}
if (harness.status == HARNESS_STATUS_NORMAL) { if (harness.status == HARNESS_STATUS_NORMAL) {
set_gpio_output(current_board->harness_config->GPIO_relay_SBU1, current_board->harness_config->pin_relay_SBU1, !ignition_relay); set_gpio_output(current_board->harness_config->GPIO_relay_SBU1, current_board->harness_config->pin_relay_SBU1, !ignition_relay);
set_gpio_output(current_board->harness_config->GPIO_relay_SBU2, current_board->harness_config->pin_relay_SBU2, !drive_relay); set_gpio_output(current_board->harness_config->GPIO_relay_SBU2, current_board->harness_config->pin_relay_SBU2, !drive_relay);
} else { } else {
set_gpio_output(current_board->harness_config->GPIO_relay_SBU1, current_board->harness_config->pin_relay_SBU1, !drive_relay); set_gpio_output(current_board->harness_config->GPIO_relay_SBU1, current_board->harness_config->pin_relay_SBU1, !drive_relay);
set_gpio_output(current_board->harness_config->GPIO_relay_SBU2, current_board->harness_config->pin_relay_SBU2, !ignition_relay); set_gpio_output(current_board->harness_config->GPIO_relay_SBU2, current_board->harness_config->pin_relay_SBU2, !ignition_relay);
} }
if (!(drive_relay || ignition_relay)) { if (!(drive_relay || ignition_relay)) {
harness.relay_driven = false; harness.relay_driven = false;
}
} }
} }
@@ -56,13 +54,13 @@ static uint8_t harness_detect_orientation(void) {
#ifndef BOOTSTUB #ifndef BOOTSTUB
// We can't detect orientation if the relay is being driven // We can't detect orientation if the relay is being driven
if (!harness.relay_driven && current_board->harness_config->has_harness) { if (!harness.relay_driven) {
harness.sbu_adc_lock = true; harness.sbu_adc_lock = true;
set_gpio_mode(current_board->harness_config->GPIO_SBU1, current_board->harness_config->pin_SBU1, MODE_ANALOG); set_gpio_mode(current_board->harness_config->GPIO_SBU1, current_board->harness_config->pin_SBU1, MODE_ANALOG);
set_gpio_mode(current_board->harness_config->GPIO_SBU2, current_board->harness_config->pin_SBU2, MODE_ANALOG); set_gpio_mode(current_board->harness_config->GPIO_SBU2, current_board->harness_config->pin_SBU2, MODE_ANALOG);
harness.sbu1_voltage_mV = adc_get_mV(current_board->harness_config->adc_channel_SBU1); harness.sbu1_voltage_mV = adc_get_mV(&current_board->harness_config->adc_signal_SBU1);
harness.sbu2_voltage_mV = adc_get_mV(current_board->harness_config->adc_channel_SBU2); harness.sbu2_voltage_mV = adc_get_mV(&current_board->harness_config->adc_signal_SBU2);
uint16_t detection_threshold = current_board->avdd_mV / 2U; uint16_t detection_threshold = current_board->avdd_mV / 2U;
// Detect connection and orientation // Detect connection and orientation
@@ -1,34 +0,0 @@
#pragma once
#define HARNESS_STATUS_NC 0U
#define HARNESS_STATUS_NORMAL 1U
#define HARNESS_STATUS_FLIPPED 2U
struct harness_t {
uint8_t status;
uint16_t sbu1_voltage_mV;
uint16_t sbu2_voltage_mV;
bool relay_driven;
bool sbu_adc_lock;
};
extern struct harness_t harness;
struct harness_configuration {
const bool has_harness;
GPIO_TypeDef * const GPIO_SBU1;
GPIO_TypeDef * const GPIO_SBU2;
GPIO_TypeDef * const GPIO_relay_SBU1;
GPIO_TypeDef * const GPIO_relay_SBU2;
const uint8_t pin_SBU1;
const uint8_t pin_SBU2;
const uint8_t pin_relay_SBU1;
const uint8_t pin_relay_SBU2;
const uint8_t adc_channel_SBU1;
const uint8_t adc_channel_SBU2;
};
// The ignition relay is only used for testing purposes
void set_intercept_relay(bool intercept, bool ignition_relay);
bool harness_check_ignition(void);
void harness_tick(void);
void harness_init(void);
+1 -1
View File
@@ -1,4 +1,4 @@
#include "interrupts_declarations.h" #include "board/drivers/drivers.h"
void unused_interrupt_handler(void) { void unused_interrupt_handler(void) {
// Something is wrong if this handler is called! // Something is wrong if this handler is called!
@@ -1,31 +0,0 @@
#pragma once
typedef struct interrupt {
IRQn_Type irq_type;
void (*handler)(void);
uint32_t call_counter;
uint32_t call_rate;
uint32_t max_call_rate; // Call rate is defined as the amount of calls each second
uint32_t call_rate_fault;
} interrupt;
void interrupt_timer_init(void);
uint32_t microsecond_timer_get(void);
void unused_interrupt_handler(void);
extern interrupt interrupts[NUM_INTERRUPTS];
#define REGISTER_INTERRUPT(irq_num, func_ptr, call_rate_max, rate_fault) \
interrupts[irq_num].irq_type = (irq_num); \
interrupts[irq_num].handler = (func_ptr); \
interrupts[irq_num].call_counter = 0U; \
interrupts[irq_num].call_rate = 0U; \
interrupts[irq_num].max_call_rate = (call_rate_max); \
interrupts[irq_num].call_rate_fault = (rate_fault);
extern float interrupt_load;
void handle_interrupt(IRQn_Type irq_type);
// Every second
void interrupt_timer_handler(void);
void init_interrupts(bool check_rate_limit);
+1 -1
View File
@@ -3,7 +3,7 @@
#define LED_GREEN 1U #define LED_GREEN 1U
#define LED_BLUE 2U #define LED_BLUE 2U
#define LED_PWM_POWER 5U #define LED_PWM_POWER 2U
void led_set(uint8_t color, bool enabled) { void led_set(uint8_t color, bool enabled) {
if (color < 3U) { if (color < 3U) {
+45 -45
View File
@@ -1,56 +1,56 @@
#define PWM_COUNTER_OVERFLOW 2000U // To get ~50kHz #define PWM_COUNTER_OVERFLOW 4800U // To get ~25kHz
// TODO: Implement for 32-bit timers // TODO: Implement for 32-bit timers
void pwm_init(TIM_TypeDef *TIM, uint8_t channel){ void pwm_init(TIM_TypeDef *TIM, uint8_t channel){
// Enable timer and auto-reload // Enable timer and auto-reload
register_set(&(TIM->CR1), TIM_CR1_CEN | TIM_CR1_ARPE, 0x3FU); register_set(&(TIM->CR1), TIM_CR1_CEN | TIM_CR1_ARPE, 0x3FU);
// Set channel as PWM mode 1 and enable output // Set channel as PWM mode 1 and enable output
switch(channel){ switch(channel){
case 1U: case 1U:
register_set_bits(&(TIM->CCMR1), (TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1PE)); register_set_bits(&(TIM->CCMR1), (TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1PE));
register_set_bits(&(TIM->CCER), TIM_CCER_CC1E); register_set_bits(&(TIM->CCER), TIM_CCER_CC1E);
break; break;
case 2U: case 2U:
register_set_bits(&(TIM->CCMR1), (TIM_CCMR1_OC2M_2 | TIM_CCMR1_OC2M_1 | TIM_CCMR1_OC2PE)); register_set_bits(&(TIM->CCMR1), (TIM_CCMR1_OC2M_2 | TIM_CCMR1_OC2M_1 | TIM_CCMR1_OC2PE));
register_set_bits(&(TIM->CCER), TIM_CCER_CC2E); register_set_bits(&(TIM->CCER), TIM_CCER_CC2E);
break; break;
case 3U: case 3U:
register_set_bits(&(TIM->CCMR2), (TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3PE)); register_set_bits(&(TIM->CCMR2), (TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3PE));
register_set_bits(&(TIM->CCER), TIM_CCER_CC3E); register_set_bits(&(TIM->CCER), TIM_CCER_CC3E);
break; break;
case 4U: case 4U:
register_set_bits(&(TIM->CCMR2), (TIM_CCMR2_OC4M_2 | TIM_CCMR2_OC4M_1 | TIM_CCMR2_OC4PE)); register_set_bits(&(TIM->CCMR2), (TIM_CCMR2_OC4M_2 | TIM_CCMR2_OC4M_1 | TIM_CCMR2_OC4PE));
register_set_bits(&(TIM->CCER), TIM_CCER_CC4E); register_set_bits(&(TIM->CCER), TIM_CCER_CC4E);
break; break;
default: default:
break; break;
} }
// Set max counter value // Set max counter value
register_set(&(TIM->ARR), PWM_COUNTER_OVERFLOW, 0xFFFFU); register_set(&(TIM->ARR), PWM_COUNTER_OVERFLOW, 0xFFFFU);
// Update registers and clear counter // Update registers and clear counter
TIM->EGR |= TIM_EGR_UG; TIM->EGR |= TIM_EGR_UG;
} }
void pwm_set(TIM_TypeDef *TIM, uint8_t channel, uint8_t percentage){ void pwm_set(TIM_TypeDef *TIM, uint8_t channel, uint8_t percentage){
uint16_t comp_value = (((uint16_t) percentage * PWM_COUNTER_OVERFLOW) / 100U); uint16_t comp_value = (((uint16_t) percentage * PWM_COUNTER_OVERFLOW) / 100U);
switch(channel){ switch(channel){
case 1U: case 1U:
register_set(&(TIM->CCR1), comp_value, 0xFFFFU); register_set(&(TIM->CCR1), comp_value, 0xFFFFU);
break; break;
case 2U: case 2U:
register_set(&(TIM->CCR2), comp_value, 0xFFFFU); register_set(&(TIM->CCR2), comp_value, 0xFFFFU);
break; break;
case 3U: case 3U:
register_set(&(TIM->CCR3), comp_value, 0xFFFFU); register_set(&(TIM->CCR3), comp_value, 0xFFFFU);
break; break;
case 4U: case 4U:
register_set(&(TIM->CCR4), comp_value, 0xFFFFU); register_set(&(TIM->CCR4), comp_value, 0xFFFFU);
break; break;
default: default:
break; break;
} }
} }
+17 -5
View File
@@ -1,4 +1,13 @@
#include "registers_declarations.h" #include "board/drivers/drivers.h"
typedef struct reg {
volatile uint32_t *address;
uint32_t value;
uint32_t check_mask;
bool logged_fault;
} reg;
#define CHECK_COLLISION(hash, addr) (((uint32_t) register_map[hash].address != 0U) && (register_map[hash].address != (addr)))
static reg register_map[REGISTER_MAP_SIZE]; static reg register_map[REGISTER_MAP_SIZE];
@@ -49,10 +58,13 @@ void check_registers(void){
if((uint32_t) register_map[i].address != 0U){ if((uint32_t) register_map[i].address != 0U){
ENTER_CRITICAL() ENTER_CRITICAL()
if((*(register_map[i].address) & register_map[i].check_mask) != (register_map[i].value & register_map[i].check_mask)){ if((*(register_map[i].address) & register_map[i].check_mask) != (register_map[i].value & register_map[i].check_mask)){
if(!register_map[i].logged_fault){ #ifdef DEBUG_FAULTS
print("Register 0x"); puth((uint32_t) register_map[i].address); print(" divergent! Map: 0x"); puth(register_map[i].value); print(" Reg: 0x"); puth(*(register_map[i].address)); print("\n"); print("Register at address 0x"); puth((uint32_t) register_map[i].address); print(" is divergent!");
register_map[i].logged_fault = true; print(" Map: 0x"); puth(register_map[i].value);
} print(" Register: 0x"); puth(*(register_map[i].address));
print(" Mask: 0x"); puth(register_map[i].check_mask);
print("\n");
#endif
fault_occurred(FAULT_REGISTER_DIVERGENT); fault_occurred(FAULT_REGISTER_DIVERGENT);
} }
EXIT_CRITICAL() EXIT_CRITICAL()
@@ -1,25 +0,0 @@
#pragma once
typedef struct reg {
volatile uint32_t *address;
uint32_t value;
uint32_t check_mask;
bool logged_fault;
} reg;
// 10 bit hash with 23 as a prime
#define REGISTER_MAP_SIZE 0x3FFU
#define HASHING_PRIME 23U
#define CHECK_COLLISION(hash, addr) (((uint32_t) register_map[hash].address != 0U) && (register_map[hash].address != (addr)))
// Do not put bits in the check mask that get changed by the hardware
void register_set(volatile uint32_t *addr, uint32_t val, uint32_t mask);
// Set individual bits. Also add them to the check_mask.
// Do not use this to change bits that get reset by the hardware
void register_set_bits(volatile uint32_t *addr, uint32_t val);
// Clear individual bits. Also add them to the check_mask.
// Do not use this to clear bits that get set by the hardware
void register_clear_bits(volatile uint32_t *addr, uint32_t val);
// To be called periodically
void check_registers(void);
void init_registers(void);
+1 -1
View File
@@ -1,4 +1,4 @@
#include "simple_watchdog_declarations.h" #include "board/drivers/drivers.h"
static simple_watchdog_state_t wd_state; static simple_watchdog_state_t wd_state;
@@ -1,10 +0,0 @@
#pragma once
typedef struct simple_watchdog_state_t {
uint32_t fault;
uint32_t last_ts;
uint32_t threshold;
} simple_watchdog_state_t;
void simple_watchdog_kick(void);
void simple_watchdog_init(uint32_t fault, uint32_t threshold);
+28 -13
View File
@@ -1,24 +1,41 @@
#pragma once #pragma once
#include "spi_declarations.h" #include "board/drivers/drivers.h"
#include "crc.h"
#ifdef STM32H7
#define SPI_BUF_SIZE 2048U
// H7 DMA2 located in D2 domain, so we need to use SRAM1/SRAM2 // H7 DMA2 located in D2 domain, so we need to use SRAM1/SRAM2
#ifdef STM32H7
__attribute__((section(".sram12"))) uint8_t spi_buf_rx[SPI_BUF_SIZE]; __attribute__((section(".sram12"))) uint8_t spi_buf_rx[SPI_BUF_SIZE];
__attribute__((section(".sram12"))) uint8_t spi_buf_tx[SPI_BUF_SIZE]; __attribute__((section(".sram12"))) uint8_t spi_buf_tx[SPI_BUF_SIZE];
#else #else
#define SPI_BUF_SIZE 1024U
uint8_t spi_buf_rx[SPI_BUF_SIZE]; uint8_t spi_buf_rx[SPI_BUF_SIZE];
uint8_t spi_buf_tx[SPI_BUF_SIZE]; uint8_t spi_buf_tx[SPI_BUF_SIZE];
#endif #endif
#define SPI_CHECKSUM_START 0xABU
#define SPI_SYNC_BYTE 0x5AU
#define SPI_HACK 0x79U
#define SPI_DACK 0x85U
#define SPI_NACK 0x1FU
// SPI states
enum {
SPI_STATE_HEADER,
SPI_STATE_HEADER_ACK,
SPI_STATE_HEADER_NACK,
SPI_STATE_DATA_RX,
SPI_STATE_DATA_RX_ACK,
SPI_STATE_DATA_TX
};
uint16_t spi_error_count = 0; uint16_t spi_error_count = 0;
uint16_t spi_checksum_error_count = 0; #define SPI_HEADER_SIZE 7U
// low level SPI prototypes
void llspi_init(void);
void llspi_mosi_dma(uint8_t *addr, int len);
void llspi_miso_dma(uint8_t *addr, int len);
#if defined(ENABLE_SPI) || defined(BOOTSTUB)
static uint8_t spi_state = SPI_STATE_HEADER; static uint8_t spi_state = SPI_STATE_HEADER;
static uint16_t spi_data_len_mosi; static uint16_t spi_data_len_mosi;
static bool spi_can_tx_ready = false; static bool spi_can_tx_ready = false;
@@ -155,9 +172,12 @@ void spi_rx_done(void) {
print("SPI: did expect data for can_write\n"); print("SPI: did expect data for can_write\n");
} }
} else if (spi_endpoint == 0xABU) { } else if (spi_endpoint == 0xABU) {
// test endpoint, send max response length // test endpoint: mimics panda -> device transfer
response_len = spi_data_len_miso; response_len = spi_data_len_miso;
response_ack = true; response_ack = true;
} else if (spi_endpoint == 0xACU) {
// test endpoint: mimics device -> panda transfer (with NACK)
response_ack = false;
} else { } else {
print("SPI: unexpected endpoint"); puth(spi_endpoint); print("\n"); print("SPI: unexpected endpoint"); puth(spi_endpoint); print("\n");
} }
@@ -236,8 +256,3 @@ void spi_tx_done(bool reset) {
void can_tx_comms_resume_spi(void) { void can_tx_comms_resume_spi(void) {
spi_can_tx_ready = true; spi_can_tx_ready = true;
} }
#else
void can_tx_comms_resume_spi(void) {
return;
}
#endif
-52
View File
@@ -1,52 +0,0 @@
#pragma once
#include "crc.h"
#define SPI_TIMEOUT_US 10000U
// got max rate from hitting a non-existent endpoint
// in a tight loop, plus some buffer
#define SPI_IRQ_RATE 16000U
#ifdef STM32H7
#define SPI_BUF_SIZE 2048U
// H7 DMA2 located in D2 domain, so we need to use SRAM1/SRAM2
__attribute__((section(".sram12"))) extern uint8_t spi_buf_rx[SPI_BUF_SIZE];
__attribute__((section(".sram12"))) extern uint8_t spi_buf_tx[SPI_BUF_SIZE];
#else
#define SPI_BUF_SIZE 1024U
extern uint8_t spi_buf_rx[SPI_BUF_SIZE];
extern uint8_t spi_buf_tx[SPI_BUF_SIZE];
#endif
#define SPI_CHECKSUM_START 0xABU
#define SPI_SYNC_BYTE 0x5AU
#define SPI_HACK 0x79U
#define SPI_DACK 0x85U
#define SPI_NACK 0x1FU
// SPI states
enum {
SPI_STATE_HEADER,
SPI_STATE_HEADER_ACK,
SPI_STATE_HEADER_NACK,
SPI_STATE_DATA_RX,
SPI_STATE_DATA_RX_ACK,
SPI_STATE_DATA_TX
};
extern uint16_t spi_error_count;
#define SPI_HEADER_SIZE 7U
// low level SPI prototypes
void llspi_init(void);
void llspi_mosi_dma(uint8_t *addr, int len);
void llspi_miso_dma(uint8_t *addr, int len);
void can_tx_comms_resume_spi(void);
#if defined(ENABLE_SPI) || defined(BOOTSTUB)
void spi_init(void);
void spi_rx_done(void);
void spi_tx_done(bool reset);
#endif
+6 -22
View File
@@ -1,6 +1,4 @@
#include "uart_declarations.h" #include "board/drivers/drivers.h"
// IRQs: USART2, USART3, UART5
// ***************************** Definitions ***************************** // ***************************** Definitions *****************************
@@ -28,12 +26,7 @@
UART_BUFFER(debug, FIFO_SIZE_INT, FIFO_SIZE_INT, USART2, debug_ring_callback, true) UART_BUFFER(debug, FIFO_SIZE_INT, FIFO_SIZE_INT, USART2, debug_ring_callback, true)
// SOM debug = UART7 // SOM debug = UART7
#ifdef STM32H7 UART_BUFFER(som_debug, FIFO_SIZE_INT, FIFO_SIZE_INT, UART7, NULL, true)
UART_BUFFER(som_debug, FIFO_SIZE_INT, FIFO_SIZE_INT, UART7, NULL, true)
#else
// UART7 is not available on F4
UART_BUFFER(som_debug, 1U, 1U, NULL, NULL, true)
#endif
uart_ring *get_ring_by_number(int a) { uart_ring *get_ring_by_number(int a) {
uart_ring *ring = NULL; uart_ring *ring = NULL;
@@ -112,15 +105,6 @@ bool put_char(uart_ring *q, char elem) {
return ret; return ret;
} }
void clear_uart_buff(uart_ring *q) {
ENTER_CRITICAL();
q->w_ptr_tx = 0;
q->r_ptr_tx = 0;
q->w_ptr_rx = 0;
q->r_ptr_rx = 0;
EXIT_CRITICAL();
}
// ************************ High-level debug functions ********************** // ************************ High-level debug functions **********************
void putch(const char a) { void putch(const char a) {
// misra-c2012-17.7: serial debug function, ok to ignore output // misra-c2012-17.7: serial debug function, ok to ignore output
@@ -145,14 +129,14 @@ void puth(unsigned int i) {
puthx(i, 8U); puthx(i, 8U);
} }
#if defined(ENABLE_SPI) || defined(BOOTSTUB) || defined(DEBUG) #if defined(DEBUG_SPI) || defined(BOOTSTUB) || defined(DEBUG)
void puth4(unsigned int i) { static void puth4(unsigned int i) {
puthx(i, 4U); puthx(i, 4U);
} }
#endif #endif
#if defined(ENABLE_SPI) || defined(BOOTSTUB) || defined(DEBUG_USB) || defined(DEBUG_COMMS) #if defined(DEBUG_SPI) || defined(BOOTSTUB) || defined(DEBUG_USB) || defined(DEBUG_COMMS)
void hexdump(const void *a, int l) { static void hexdump(const void *a, int l) {
if (a != NULL) { if (a != NULL) {
for (int i=0; i < l; i++) { for (int i=0; i < l; i++) {
if ((i != 0) && ((i & 0xf) == 0)) print("\n"); if ((i != 0) && ((i & 0xf) == 0)) print("\n");
-39
View File
@@ -1,39 +0,0 @@
#pragma once
// IRQs: USART2, USART3, UART5
// ***************************** Definitions *****************************
#define FIFO_SIZE_INT 0x400U
typedef struct uart_ring {
volatile uint16_t w_ptr_tx;
volatile uint16_t r_ptr_tx;
uint8_t *elems_tx;
uint32_t tx_fifo_size;
volatile uint16_t w_ptr_rx;
volatile uint16_t r_ptr_rx;
uint8_t *elems_rx;
uint32_t rx_fifo_size;
USART_TypeDef *uart;
void (*callback)(struct uart_ring*);
bool overwrite;
} uart_ring;
// ***************************** Function prototypes *****************************
void debug_ring_callback(uart_ring *ring);
void uart_tx_ring(uart_ring *q);
uart_ring *get_ring_by_number(int a);
// ************************* Low-level buffer functions *************************
bool get_char(uart_ring *q, char *elem);
bool injectc(uart_ring *q, char elem);
bool put_char(uart_ring *q, char elem);
void clear_uart_buff(uart_ring *q);
// ************************ High-level debug functions **********************
void putch(const char a);
void print(const char *a);
void puthx(uint32_t i, uint8_t len);
void puth(unsigned int i);
#if defined(ENABLE_SPI) || defined(BOOTSTUB) || defined(DEBUG)
void puth4(unsigned int i);
#endif
void hexdump(const void *a, int l);
+86 -6
View File
@@ -1,4 +1,87 @@
#include "usb_declarations.h" #include "board/drivers/drivers.h"
// IRQs: OTG_FS
typedef union {
uint16_t w;
struct BW {
uint8_t msb;
uint8_t lsb;
}
bw;
} uint16_t_uint8_t;
typedef union _USB_Setup {
uint32_t d8[2];
struct _SetupPkt_Struc
{
uint8_t bmRequestType;
uint8_t bRequest;
uint16_t_uint8_t wValue;
uint16_t_uint8_t wIndex;
uint16_t_uint8_t wLength;
} b;
} USB_Setup_TypeDef;
// **** supporting defines ****
#define USB_REQ_GET_STATUS 0x00
#define USB_REQ_SET_ADDRESS 0x05
#define USB_REQ_GET_DESCRIPTOR 0x06
#define USB_REQ_SET_CONFIGURATION 0x09
#define USB_REQ_SET_INTERFACE 0x0B
#define USB_DESC_TYPE_DEVICE 0x01
#define USB_DESC_TYPE_CONFIGURATION 0x02
#define USB_DESC_TYPE_STRING 0x03
#define USB_DESC_TYPE_INTERFACE 0x04
#define USB_DESC_TYPE_ENDPOINT 0x05
#define USB_DESC_TYPE_DEVICE_QUALIFIER 0x06
#define USB_DESC_TYPE_BINARY_OBJECT_STORE 0x0f
// offsets for configuration strings
#define STRING_OFFSET_LANGID 0x00
#define STRING_OFFSET_IMANUFACTURER 0x01
#define STRING_OFFSET_IPRODUCT 0x02
#define STRING_OFFSET_ISERIAL 0x03
#define STRING_OFFSET_ICONFIGURATION 0x04
// WinUSB requests
#define WINUSB_REQ_GET_COMPATID_DESCRIPTOR 0x04
#define WINUSB_REQ_GET_EXT_PROPS_OS 0x05
#define WINUSB_REQ_GET_DESCRIPTOR 0x07
#define STS_DATA_UPDT 2
#define STS_SETUP_UPDT 6
// for the repeating interfaces
#define DSCR_INTERFACE_LEN 9
#define DSCR_ENDPOINT_LEN 7
#define DSCR_CONFIG_LEN 9
#define DSCR_DEVICE_LEN 18
// endpoint types
#define ENDPOINT_TYPE_BULK 2
#define ENDPOINT_TYPE_INT 3
// These are arbitrary values used in bRequest
#define MS_VENDOR_CODE 0x20
#define WEBUSB_VENDOR_CODE 0x30
// BOS constants
#define BINARY_OBJECT_STORE_DESCRIPTOR_LENGTH 0x05
#define BINARY_OBJECT_STORE_DESCRIPTOR 0x0F
#define WINUSB_PLATFORM_DESCRIPTOR_LENGTH 0x9E
// Convert machine byte order to USB byte order
#define TOUSBORDER(num)\
((num) & 0xFFU), (((uint16_t)(num) >> 8) & 0xFFU)
// take in string length and return the first 2 bytes of a string descriptor
#define STRING_DESCRIPTOR_HEADER(size)\
(((((size) * 2) + 2) & 0xFF) | 0x0300)
#define ENDPOINT_RCV 0x80
#define ENDPOINT_SND 0x00
static uint8_t response[USBPACKET_MAX_SIZE]; static uint8_t response[USBPACKET_MAX_SIZE];
@@ -502,11 +585,8 @@ static void usb_setup(void) {
control_req.length = setup.b.wLength.w; control_req.length = setup.b.wLength.w;
resp_len = comms_control_handler(&control_req, response); resp_len = comms_control_handler(&control_req, response);
// response pending if -1 was returned USB_WritePacket(response, MIN(resp_len, setup.b.wLength.w), 0);
if (resp_len != -1) { USBx_OUTEP(0U)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
USB_WritePacket(response, MIN(resp_len, setup.b.wLength.w), 0);
USBx_OUTEP(0U)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK;
}
} }
} }
-111
View File
@@ -1,111 +0,0 @@
#pragma once
// IRQs: OTG_FS
typedef union {
uint16_t w;
struct BW {
uint8_t msb;
uint8_t lsb;
}
bw;
} uint16_t_uint8_t;
typedef union _USB_Setup {
uint32_t d8[2];
struct _SetupPkt_Struc
{
uint8_t bmRequestType;
uint8_t bRequest;
uint16_t_uint8_t wValue;
uint16_t_uint8_t wIndex;
uint16_t_uint8_t wLength;
} b;
} USB_Setup_TypeDef;
void usb_init(void);
void refresh_can_tx_slots_available(void);
// **** supporting defines ****
#define USB_REQ_GET_STATUS 0x00
#define USB_REQ_CLEAR_FEATURE 0x01
#define USB_REQ_SET_FEATURE 0x03
#define USB_REQ_SET_ADDRESS 0x05
#define USB_REQ_GET_DESCRIPTOR 0x06
#define USB_REQ_SET_DESCRIPTOR 0x07
#define USB_REQ_GET_CONFIGURATION 0x08
#define USB_REQ_SET_CONFIGURATION 0x09
#define USB_REQ_GET_INTERFACE 0x0A
#define USB_REQ_SET_INTERFACE 0x0B
#define USB_REQ_SYNCH_FRAME 0x0C
#define USB_DESC_TYPE_DEVICE 0x01
#define USB_DESC_TYPE_CONFIGURATION 0x02
#define USB_DESC_TYPE_STRING 0x03
#define USB_DESC_TYPE_INTERFACE 0x04
#define USB_DESC_TYPE_ENDPOINT 0x05
#define USB_DESC_TYPE_DEVICE_QUALIFIER 0x06
#define USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION 0x07
#define USB_DESC_TYPE_BINARY_OBJECT_STORE 0x0f
// offsets for configuration strings
#define STRING_OFFSET_LANGID 0x00
#define STRING_OFFSET_IMANUFACTURER 0x01
#define STRING_OFFSET_IPRODUCT 0x02
#define STRING_OFFSET_ISERIAL 0x03
#define STRING_OFFSET_ICONFIGURATION 0x04
#define STRING_OFFSET_IINTERFACE 0x05
// WebUSB requests
#define WEBUSB_REQ_GET_URL 0x02
// WebUSB types
#define WEBUSB_DESC_TYPE_URL 0x03
#define WEBUSB_URL_SCHEME_HTTPS 0x01
#define WEBUSB_URL_SCHEME_HTTP 0x00
// WinUSB requests
#define WINUSB_REQ_GET_COMPATID_DESCRIPTOR 0x04
#define WINUSB_REQ_GET_EXT_PROPS_OS 0x05
#define WINUSB_REQ_GET_DESCRIPTOR 0x07
#define STS_GOUT_NAK 1
#define STS_DATA_UPDT 2
#define STS_XFER_COMP 3
#define STS_SETUP_COMP 4
#define STS_SETUP_UPDT 6
// for the repeating interfaces
#define DSCR_INTERFACE_LEN 9
#define DSCR_ENDPOINT_LEN 7
#define DSCR_CONFIG_LEN 9
#define DSCR_DEVICE_LEN 18
// endpoint types
#define ENDPOINT_TYPE_CONTROL 0
#define ENDPOINT_TYPE_ISO 1
#define ENDPOINT_TYPE_BULK 2
#define ENDPOINT_TYPE_INT 3
// These are arbitrary values used in bRequest
#define MS_VENDOR_CODE 0x20
#define WEBUSB_VENDOR_CODE 0x30
// BOS constants
#define BINARY_OBJECT_STORE_DESCRIPTOR_LENGTH 0x05
#define BINARY_OBJECT_STORE_DESCRIPTOR 0x0F
#define WINUSB_PLATFORM_DESCRIPTOR_LENGTH 0x9E
// Convert machine byte order to USB byte order
#define TOUSBORDER(num)\
((num) & 0xFFU), (((uint16_t)(num) >> 8) & 0xFFU)
// take in string length and return the first 2 bytes of a string descriptor
#define STRING_DESCRIPTOR_HEADER(size)\
(((((size) * 2) + 2) & 0xFF) | 0x0300)
#define ENDPOINT_RCV 0x80
#define ENDPOINT_SND 0x00
// ***************************** USB port *****************************
void can_tx_comms_resume_usb(void);
-2
View File
@@ -57,9 +57,7 @@ void early_initialization(void) {
if (enter_bootloader_mode == ENTER_BOOTLOADER_MAGIC) { if (enter_bootloader_mode == ENTER_BOOTLOADER_MAGIC) {
led_init(); led_init();
#ifdef PANDA
current_board->init_bootloader(); current_board->init_bootloader();
#endif
led_set(LED_GREEN, 1); led_set(LED_GREEN, 1);
jump_to_bootloader(); jump_to_bootloader();
} }
-2
View File
@@ -5,9 +5,7 @@
#include "utils.h" #include "utils.h"
#define CANFD
#define ALLOW_DEBUG #define ALLOW_DEBUG
#define PANDA
#define ENTER_CRITICAL() 0 #define ENTER_CRITICAL() 0
#define EXIT_CRITICAL() 0 #define EXIT_CRITICAL() 0
-25
View File
@@ -1,25 +0,0 @@
#include "faults_declarations.h"
uint8_t fault_status = FAULT_STATUS_NONE;
uint32_t faults = 0U;
void fault_occurred(uint32_t fault) {
if ((faults & fault) == 0U) {
if ((PERMANENT_FAULTS & fault) != 0U) {
print("Permanent fault occurred: 0x"); puth(fault); print("\n");
fault_status = FAULT_STATUS_PERMANENT;
} else {
print("Temporary fault occurred: 0x"); puth(fault); print("\n");
fault_status = FAULT_STATUS_TEMPORARY;
}
}
faults |= fault;
}
void fault_recovered(uint32_t fault) {
if ((PERMANENT_FAULTS & fault) == 0U) {
faults &= ~fault;
} else {
print("Cannot recover from a permanent fault!\n");
}
}
-44
View File
@@ -1,44 +0,0 @@
#pragma once
#define FAULT_STATUS_NONE 0U
#define FAULT_STATUS_TEMPORARY 1U
#define FAULT_STATUS_PERMANENT 2U
// Fault types, matches cereal.log.PandaState.FaultType
#define FAULT_RELAY_MALFUNCTION (1UL << 0)
#define FAULT_UNUSED_INTERRUPT_HANDLED (1UL << 1)
#define FAULT_INTERRUPT_RATE_CAN_1 (1UL << 2)
#define FAULT_INTERRUPT_RATE_CAN_2 (1UL << 3)
#define FAULT_INTERRUPT_RATE_CAN_3 (1UL << 4)
#define FAULT_INTERRUPT_RATE_TACH (1UL << 5)
#define FAULT_INTERRUPT_RATE_GMLAN (1UL << 6) // deprecated
#define FAULT_INTERRUPT_RATE_INTERRUPTS (1UL << 7)
#define FAULT_INTERRUPT_RATE_SPI_DMA (1UL << 8)
#define FAULT_INTERRUPT_RATE_SPI_CS (1UL << 9)
#define FAULT_INTERRUPT_RATE_UART_1 (1UL << 10)
#define FAULT_INTERRUPT_RATE_UART_2 (1UL << 11)
#define FAULT_INTERRUPT_RATE_UART_3 (1UL << 12)
#define FAULT_INTERRUPT_RATE_UART_5 (1UL << 13)
#define FAULT_INTERRUPT_RATE_UART_DMA (1UL << 14)
#define FAULT_INTERRUPT_RATE_USB (1UL << 15)
#define FAULT_INTERRUPT_RATE_TIM1 (1UL << 16)
#define FAULT_INTERRUPT_RATE_TIM3 (1UL << 17)
#define FAULT_REGISTER_DIVERGENT (1UL << 18)
#define FAULT_INTERRUPT_RATE_KLINE_INIT (1UL << 19)
#define FAULT_INTERRUPT_RATE_CLOCK_SOURCE (1UL << 20)
#define FAULT_INTERRUPT_RATE_TICK (1UL << 21)
#define FAULT_INTERRUPT_RATE_EXTI (1UL << 22)
#define FAULT_INTERRUPT_RATE_SPI (1UL << 23)
#define FAULT_INTERRUPT_RATE_UART_7 (1UL << 24)
#define FAULT_SIREN_MALFUNCTION (1UL << 25)
#define FAULT_HEARTBEAT_LOOP_WATCHDOG (1UL << 26)
#define FAULT_INTERRUPT_RATE_SOUND_DMA (1UL << 27)
// Permanent faults
#define PERMANENT_FAULTS 0U
extern uint8_t fault_status;
extern uint32_t faults;
void fault_occurred(uint32_t fault);
void fault_recovered(uint32_t fault);
+1 -1
View File
@@ -3,7 +3,7 @@ import os
import subprocess import subprocess
import argparse import argparse
from panda_tici import Panda from panda import Panda
board_path = os.path.dirname(os.path.realpath(__file__)) board_path = os.path.dirname(os.path.realpath(__file__))
+3 -12
View File
@@ -1,16 +1,10 @@
// from the linker script // from the linker script
#ifdef STM32H7 #define APP_START_ADDRESS 0x8020000U
#define APP_START_ADDRESS 0x8020000U
#elif defined(STM32F4)
#define APP_START_ADDRESS 0x8004000U
#endif
// flasher state variables // flasher state variables
uint32_t *prog_ptr = NULL; uint32_t *prog_ptr = NULL;
bool unlocked = false; bool unlocked = false;
void spi_init(void);
int comms_control_handler(ControlPacket_t *req, uint8_t *resp) { int comms_control_handler(ControlPacket_t *req, uint8_t *resp) {
int resp_len = 0; int resp_len = 0;
@@ -87,7 +81,7 @@ int comms_control_handler(ControlPacket_t *req, uint8_t *resp) {
case 0xd6: case 0xd6:
COMPILE_TIME_ASSERT(sizeof(gitversion) <= USBPACKET_MAX_SIZE); COMPILE_TIME_ASSERT(sizeof(gitversion) <= USBPACKET_MAX_SIZE);
memcpy(resp, gitversion, sizeof(gitversion)); memcpy(resp, gitversion, sizeof(gitversion));
resp_len = sizeof(gitversion); resp_len = sizeof(gitversion) - 1U;
break; break;
// **** 0xd8: reset ST // **** 0xd8: reset ST
case 0xd8: case 0xd8:
@@ -134,15 +128,12 @@ void soft_flasher_start(void) {
gpio_usb_init(); gpio_usb_init();
led_init(); led_init();
// enable USB // enable comms
usb_init(); usb_init();
#ifdef ENABLE_SPI
if (current_board->has_spi) { if (current_board->has_spi) {
gpio_spi_init(); gpio_spi_init();
spi_init(); spi_init();
} }
#endif
// green LED on for flashing // green LED on for flashing
led_set(LED_GREEN, 1); led_set(LED_GREEN, 1);
-3
View File
@@ -1,3 +0,0 @@
#!/usr/bin/env bash
gdb-multiarch --eval-command="target extended-remote localhost:3333"
+4 -3
View File
@@ -1,6 +1,5 @@
// When changing these structs, python/__init__.py needs to be kept up to date! #pragma once
#define HEALTH_PACKET_VERSION 17
struct __attribute__((packed)) health_t { struct __attribute__((packed)) health_t {
uint32_t uptime_pkt; uint32_t uptime_pkt;
uint32_t voltage_pkt; uint32_t voltage_pkt;
@@ -27,9 +26,11 @@ struct __attribute__((packed)) health_t {
uint16_t sbu1_voltage_mV; uint16_t sbu1_voltage_mV;
uint16_t sbu2_voltage_mV; uint16_t sbu2_voltage_mV;
uint8_t som_reset_triggered; uint8_t som_reset_triggered;
uint16_t sound_output_level_pkt;
uint8_t controls_allowed_lateral_pkt;
uint8_t controls_allowed_longitudinal_pkt;
}; };
#define CAN_HEALTH_PACKET_VERSION 5
typedef struct __attribute__((packed)) { typedef struct __attribute__((packed)) {
uint8_t bus_off; uint8_t bus_off;
uint32_t bus_off_cnt; uint32_t bus_off_cnt;
-18
View File
@@ -1,18 +0,0 @@
import os
import copy
Import('build_project', 'base_project_f4', 'base_project_h7')
build_projects = {
"panda_jungle": base_project_f4,
"panda_jungle_h7": base_project_h7,
}
for project_name, project in build_projects.items():
flags = [
"-DPANDA_JUNGLE",
]
if os.getenv("FINAL_PROVISIONING"):
flags += ["-DFINAL_PROVISIONING"]
build_project(project_name, project, flags)
+12 -29
View File
@@ -3,11 +3,11 @@ import os
import struct import struct
from functools import wraps from functools import wraps
from panda_tici import Panda, PandaDFU from panda import Panda, PandaDFU
from panda_tici.python.constants import McuType from panda.python.constants import McuType, compute_version_hash
BASEDIR = os.path.dirname(os.path.realpath(__file__)) BASEDIR = os.path.dirname(os.path.realpath(__file__))
FW_PATH = os.path.join(BASEDIR, "obj/") FW_PATH = os.path.join(BASEDIR, "../obj/")
def ensure_jungle_health_packet_version(fn): def ensure_jungle_health_packet_version(fn):
@@ -23,7 +23,7 @@ def ensure_jungle_health_packet_version(fn):
class PandaJungleDFU(PandaDFU): class PandaJungleDFU(PandaDFU):
def recover(self): def recover(self):
fn = os.path.join(FW_PATH, self.get_mcu_type().config.bootstub_fn.replace("panda", "panda_jungle")) fn = os.path.join(FW_PATH, self._mcu_type.config.bootstub_fn.replace("panda", "panda_jungle"))
with open(fn, "rb") as f: with open(fn, "rb") as f:
code = f.read() code = f.read()
self.program_bootstub(code) self.program_bootstub(code)
@@ -34,13 +34,12 @@ class PandaJungle(Panda):
USB_PIDS = (0xddef, 0xddcf) USB_PIDS = (0xddef, 0xddcf)
HW_TYPE_UNKNOWN = b'\x00' HW_TYPE_UNKNOWN = b'\x00'
HW_TYPE_V1 = b'\x01'
HW_TYPE_V2 = b'\x02' HW_TYPE_V2 = b'\x02'
F4_DEVICES = [HW_TYPE_V1, ]
H7_DEVICES = [HW_TYPE_V2, ] H7_DEVICES = [HW_TYPE_V2, ]
SUPPORTED_DEVICES = H7_DEVICES
HEALTH_PACKET_VERSION = 1 HEALTH_PACKET_VERSION = compute_version_hash(os.path.join(BASEDIR, "jungle_health.h"))
HEALTH_STRUCT = struct.Struct("<IffffffHHHHHHHHHHHH") HEALTH_STRUCT = struct.Struct("<IffffffHHHHHHHHHHHH")
HARNESS_ORIENTATION_NONE = 0 HARNESS_ORIENTATION_NONE = 0
@@ -53,7 +52,7 @@ class PandaJungle(Panda):
def flash(self, fn=None, code=None, reconnect=True): def flash(self, fn=None, code=None, reconnect=True):
if not fn: if not fn:
fn = os.path.join(FW_PATH, self.get_mcu_type().config.app_fn.replace("panda", "panda_jungle")) fn = os.path.join(FW_PATH, McuType.H7.config.app_fn.replace("panda", "panda_jungle"))
super().flash(fn=fn, code=code, reconnect=reconnect) super().flash(fn=fn, code=code, reconnect=reconnect)
def recover(self, timeout: int | None = 60, reset: bool = True) -> bool: def recover(self, timeout: int | None = 60, reset: bool = True) -> bool:
@@ -74,23 +73,9 @@ class PandaJungle(Panda):
self.flash() self.flash()
return True return True
def get_mcu_type(self) -> McuType:
hw_type = self.get_type()
if hw_type in PandaJungle.F4_DEVICES:
return McuType.F4
elif hw_type in PandaJungle.H7_DEVICES:
return McuType.H7
else:
# have to assume F4, see comment in Panda.connect
# initially Jungle V1 has HW type: bytearray(b'')
if hw_type == b'' or self._assume_f4_mcu:
return McuType.F4
raise ValueError(f"unknown HW type: {hw_type}")
def up_to_date(self, fn=None) -> bool: def up_to_date(self, fn=None) -> bool:
if fn is None: if fn is None:
fn = os.path.join(FW_PATH, self.get_mcu_type().config.app_fn.replace("panda", "panda_jungle")) fn = os.path.join(FW_PATH, McuType.H7.config.app_fn.replace("panda", "panda_jungle"))
return super().up_to_date(fn=fn) return super().up_to_date(fn=fn)
# ******************* health ******************* # ******************* health *******************
@@ -123,13 +108,11 @@ class PandaJungle(Panda):
# ******************* control ******************* # ******************* control *******************
# Returns tuple with health packet version and CAN packet/USB packet version
def get_packets_versions(self): def get_packets_versions(self):
dat = self._handle.controlRead(PandaJungle.REQUEST_IN, 0xdd, 0, 0, 3) dat = self._handle.controlRead(PandaJungle.REQUEST_IN, 0xdd, 0, 0, 8)
if dat and len(dat) == 3: if dat and len(dat) == 8:
a = struct.unpack("BBB", dat) return struct.unpack("<II", dat)
return (a[0], a[1], a[2]) return (0, 0)
return (-1, -1, -1)
# ******************* jungle stuff ******************* # ******************* jungle stuff *******************
+2 -18
View File
@@ -2,6 +2,7 @@
typedef void (*board_init)(void); typedef void (*board_init)(void);
typedef void (*board_board_tick)(void); typedef void (*board_board_tick)(void);
typedef bool (*board_get_button)(void); typedef bool (*board_get_button)(void);
typedef void (*board_init_bootloader)(void);
typedef void (*board_set_panda_power)(bool enabled); typedef void (*board_set_panda_power)(bool enabled);
typedef void (*board_set_panda_individual_power)(uint8_t port_num, bool enabled); typedef void (*board_set_panda_individual_power)(uint8_t port_num, bool enabled);
typedef void (*board_set_ignition)(bool enabled); typedef void (*board_set_ignition)(bool enabled);
@@ -17,12 +18,11 @@ struct board {
GPIO_TypeDef * const led_GPIO[3]; GPIO_TypeDef * const led_GPIO[3];
const uint8_t led_pin[3]; const uint8_t led_pin[3];
const uint8_t led_pwm_channels[3]; // leave at 0 to disable PWM const uint8_t led_pwm_channels[3]; // leave at 0 to disable PWM
const bool has_canfd;
const bool has_sbu_sense;
const uint16_t avdd_mV; const uint16_t avdd_mV;
board_init init; board_init init;
board_board_tick board_tick; board_board_tick board_tick;
board_get_button get_button; board_get_button get_button;
board_init_bootloader init_bootloader;
board_set_panda_power set_panda_power; board_set_panda_power set_panda_power;
board_set_panda_individual_power set_panda_individual_power; board_set_panda_individual_power set_panda_individual_power;
board_set_ignition set_ignition; board_set_ignition set_ignition;
@@ -40,7 +40,6 @@ struct board {
// ******************* Definitions ******************** // ******************* Definitions ********************
#define HW_TYPE_UNKNOWN 0U #define HW_TYPE_UNKNOWN 0U
#define HW_TYPE_V1 1U
#define HW_TYPE_V2 2U #define HW_TYPE_V2 2U
// CAN modes // CAN modes
@@ -59,18 +58,3 @@ struct board {
uint8_t harness_orientation = HARNESS_ORIENTATION_NONE; uint8_t harness_orientation = HARNESS_ORIENTATION_NONE;
uint8_t can_mode = CAN_MODE_NORMAL; uint8_t can_mode = CAN_MODE_NORMAL;
uint8_t ignition = 0U; uint8_t ignition = 0U;
void unused_set_individual_ignition(uint8_t bitmask) {
UNUSED(bitmask);
}
void unused_board_enable_header_pin(uint8_t pin_num, bool enabled) {
UNUSED(pin_num);
UNUSED(enabled);
}
void unused_set_panda_individual_power(uint8_t port_num, bool enabled) {
UNUSED(port_num);
UNUSED(enabled);
}
-158
View File
@@ -1,158 +0,0 @@
// ///////////////////////// //
// Jungle board v1 (STM32F4) //
// ///////////////////////// //
void board_v1_enable_can_transceiver(uint8_t transceiver, bool enabled) {
switch (transceiver) {
case 1U:
set_gpio_output(GPIOC, 1, !enabled);
break;
case 2U:
set_gpio_output(GPIOC, 13, !enabled);
break;
case 3U:
set_gpio_output(GPIOA, 0, !enabled);
break;
case 4U:
set_gpio_output(GPIOB, 10, !enabled);
break;
default:
print("Invalid CAN transceiver ("); puth(transceiver); print("): enabling failed\n");
break;
}
}
void board_v1_set_can_mode(uint8_t mode) {
board_v1_enable_can_transceiver(2U, false);
board_v1_enable_can_transceiver(4U, false);
switch (mode) {
case CAN_MODE_NORMAL:
print("Setting normal CAN mode\n");
// B12,B13: disable OBD mode
set_gpio_mode(GPIOB, 12, MODE_INPUT);
set_gpio_mode(GPIOB, 13, MODE_INPUT);
// B5,B6: normal CAN2 mode
set_gpio_alternate(GPIOB, 5, GPIO_AF9_CAN2);
set_gpio_alternate(GPIOB, 6, GPIO_AF9_CAN2);
can_mode = CAN_MODE_NORMAL;
board_v1_enable_can_transceiver(2U, true);
break;
case CAN_MODE_OBD_CAN2:
print("Setting OBD CAN mode\n");
// B5,B6: disable normal CAN2 mode
set_gpio_mode(GPIOB, 5, MODE_INPUT);
set_gpio_mode(GPIOB, 6, MODE_INPUT);
// B12,B13: OBD mode
set_gpio_alternate(GPIOB, 12, GPIO_AF9_CAN2);
set_gpio_alternate(GPIOB, 13, GPIO_AF9_CAN2);
can_mode = CAN_MODE_OBD_CAN2;
board_v1_enable_can_transceiver(4U, true);
break;
default:
print("Tried to set unsupported CAN mode: "); puth(mode); print("\n");
break;
}
}
void board_v1_set_harness_orientation(uint8_t orientation) {
switch (orientation) {
case HARNESS_ORIENTATION_NONE:
set_gpio_output(GPIOA, 2, false);
set_gpio_output(GPIOA, 3, false);
set_gpio_output(GPIOA, 4, false);
set_gpio_output(GPIOA, 5, false);
harness_orientation = orientation;
break;
case HARNESS_ORIENTATION_1:
set_gpio_output(GPIOA, 2, false);
set_gpio_output(GPIOA, 3, (ignition != 0U));
set_gpio_output(GPIOA, 4, true);
set_gpio_output(GPIOA, 5, false);
harness_orientation = orientation;
break;
case HARNESS_ORIENTATION_2:
set_gpio_output(GPIOA, 2, (ignition != 0U));
set_gpio_output(GPIOA, 3, false);
set_gpio_output(GPIOA, 4, false);
set_gpio_output(GPIOA, 5, true);
harness_orientation = orientation;
break;
default:
print("Tried to set an unsupported harness orientation: "); puth(orientation); print("\n");
break;
}
}
bool panda_power = false;
void board_v1_set_panda_power(bool enable) {
panda_power = enable;
set_gpio_output(GPIOB, 14, enable);
}
bool board_v1_get_button(void) {
return get_gpio_input(GPIOC, 8);
}
void board_v1_set_ignition(bool enabled) {
ignition = enabled ? 0xFFU : 0U;
board_v1_set_harness_orientation(harness_orientation);
}
float board_v1_get_channel_power(uint8_t channel) {
UNUSED(channel);
return 0.0f;
}
uint16_t board_v1_get_sbu_mV(uint8_t channel, uint8_t sbu) {
UNUSED(channel); UNUSED(sbu);
return 0U;
}
void board_v1_init(void) {
common_init_gpio();
// A8,A15: normal CAN3 mode
set_gpio_alternate(GPIOA, 8, GPIO_AF11_CAN3);
set_gpio_alternate(GPIOA, 15, GPIO_AF11_CAN3);
board_v1_set_can_mode(CAN_MODE_NORMAL);
// Enable CAN transceivers
for(uint8_t i = 1; i <= 4; i++) {
board_v1_enable_can_transceiver(i, true);
}
// Set normal CAN mode
board_v1_set_can_mode(CAN_MODE_NORMAL);
// Set to no harness orientation
board_v1_set_harness_orientation(HARNESS_ORIENTATION_NONE);
// Enable panda power by default
board_v1_set_panda_power(true);
}
void board_v1_tick(void) {}
board board_v1 = {
.has_canfd = false,
.has_sbu_sense = false,
.avdd_mV = 3300U,
.init = &board_v1_init,
.led_GPIO = {GPIOC, GPIOC, GPIOC},
.led_pin = {9, 7, 6},
.board_tick = &board_v1_tick,
.get_button = &board_v1_get_button,
.set_panda_power = &board_v1_set_panda_power,
.set_panda_individual_power = &unused_set_panda_individual_power,
.set_ignition = &board_v1_set_ignition,
.set_individual_ignition = &unused_set_individual_ignition,
.set_harness_orientation = &board_v1_set_harness_orientation,
.set_can_mode = &board_v1_set_can_mode,
.enable_can_transceiver = &board_v1_enable_can_transceiver,
.enable_header_pin = &unused_board_enable_header_pin,
.get_channel_power = &board_v1_get_channel_power,
.get_sbu_mV = &board_v1_get_sbu_mV,
};
+20 -20
View File
@@ -2,6 +2,8 @@
// Jungle board v2 (STM32H7) // // Jungle board v2 (STM32H7) //
// ///////////////////////// // // ///////////////////////// //
#define ADC_CHANNEL(a, c) {.adc = (a), .channel = (c), .sample_time = SAMPLETIME_810_CYCLES, .oversampling = OVERSAMPLING_1}
gpio_t power_pins[] = { gpio_t power_pins[] = {
{.bank = GPIOA, .pin = 0}, {.bank = GPIOA, .pin = 0},
{.bank = GPIOA, .pin = 1}, {.bank = GPIOA, .pin = 1},
@@ -47,22 +49,22 @@ gpio_t sbu2_relay_pins[] = {
{.bank = GPIOE, .pin = 12}, {.bank = GPIOE, .pin = 12},
}; };
adc_channel_t sbu1_channels[] = { const adc_signal_t sbu1_channels[] = {
{.adc = ADC3, .channel = 12}, ADC_CHANNEL(ADC3, 12),
{.adc = ADC3, .channel = 2}, ADC_CHANNEL(ADC3, 2),
{.adc = ADC3, .channel = 4}, ADC_CHANNEL(ADC3, 4),
{.adc = ADC3, .channel = 6}, ADC_CHANNEL(ADC3, 6),
{.adc = ADC3, .channel = 8}, ADC_CHANNEL(ADC3, 8),
{.adc = ADC3, .channel = 10}, ADC_CHANNEL(ADC3, 10),
}; };
adc_channel_t sbu2_channels[] = { const adc_signal_t sbu2_channels[] = {
{.adc = ADC1, .channel = 13}, ADC_CHANNEL(ADC1, 13),
{.adc = ADC3, .channel = 3}, ADC_CHANNEL(ADC3, 3),
{.adc = ADC3, .channel = 5}, ADC_CHANNEL(ADC3, 5),
{.adc = ADC3, .channel = 7}, ADC_CHANNEL(ADC3, 7),
{.adc = ADC3, .channel = 9}, ADC_CHANNEL(ADC3, 9),
{.adc = ADC3, .channel = 11}, ADC_CHANNEL(ADC3, 11),
}; };
void board_v2_set_harness_orientation(uint8_t orientation) { void board_v2_set_harness_orientation(uint8_t orientation) {
@@ -204,8 +206,7 @@ void board_v2_set_individual_ignition(uint8_t bitmask) {
float board_v2_get_channel_power(uint8_t channel) { float board_v2_get_channel_power(uint8_t channel) {
float ret = 0.0f; float ret = 0.0f;
if ((channel >= 1U) && (channel <= 6U)) { if ((channel >= 1U) && (channel <= 6U)) {
uint16_t readout = adc_get_mV(ADC1, channel - 1U); // these are mapped nicely in hardware uint16_t readout = adc_get_mV(&(const adc_signal_t) ADC_CHANNEL(ADC1, channel - 1U)); // these are mapped nicely in hardware
ret = (((float) readout / 33e6) - 0.8e-6) / 52e-6 * 12.0f; ret = (((float) readout / 33e6) - 0.8e-6) / 52e-6 * 12.0f;
} else { } else {
print("Invalid channel ("); puth(channel); print(")\n"); print("Invalid channel ("); puth(channel); print(")\n");
@@ -218,10 +219,10 @@ uint16_t board_v2_get_sbu_mV(uint8_t channel, uint8_t sbu) {
if ((channel >= 1U) && (channel <= 6U)) { if ((channel >= 1U) && (channel <= 6U)) {
switch(sbu){ switch(sbu){
case SBU1: case SBU1:
ret = adc_get_mV(sbu1_channels[channel - 1U].adc, sbu1_channels[channel - 1U].channel); ret = adc_get_mV(&sbu1_channels[channel - 1U]);
break; break;
case SBU2: case SBU2:
ret = adc_get_mV(sbu2_channels[channel - 1U].adc, sbu2_channels[channel - 1U].channel); ret = adc_get_mV(&sbu2_channels[channel - 1U]);
break; break;
default: default:
print("Invalid SBU ("); puth(sbu); print(")\n"); print("Invalid SBU ("); puth(sbu); print(")\n");
@@ -287,10 +288,9 @@ void board_v2_init(void) {
void board_v2_tick(void) {} void board_v2_tick(void) {}
board board_v2 = { board board_v2 = {
.has_canfd = true,
.has_sbu_sense = true,
.avdd_mV = 3300U, .avdd_mV = 3300U,
.init = &board_v2_init, .init = &board_v2_init,
.init_bootloader = &board_v2_tick,
.led_GPIO = {GPIOE, GPIOE, GPIOE}, .led_GPIO = {GPIOE, GPIOE, GPIOE},
.led_pin = {4, 3, 2}, .led_pin = {4, 3, 2},
.board_tick = &board_v2_tick, .board_tick = &board_v2_tick,
+2 -2
View File
@@ -3,7 +3,7 @@ import os
import subprocess import subprocess
import argparse import argparse
from panda_tici import PandaJungle from panda import PandaJungle
board_path = os.path.dirname(os.path.realpath(__file__)) board_path = os.path.dirname(os.path.realpath(__file__))
@@ -12,7 +12,7 @@ if __name__ == "__main__":
parser.add_argument("--all", action="store_true", help="Recover all panda jungle devices") parser.add_argument("--all", action="store_true", help="Recover all panda jungle devices")
args = parser.parse_args() args = parser.parse_args()
subprocess.check_call(f"scons -C {board_path}/.. -u -j$(nproc) {board_path}", shell=True) subprocess.check_call(f"scons -C {board_path}/.. -u -j$(nproc) .", shell=True)
if args.all: if args.all:
serials = PandaJungle.list() serials = PandaJungle.list()
-3
View File
@@ -1,6 +1,3 @@
// When changing these structs, python/__init__.py needs to be kept up to date!
#define JUNGLE_HEALTH_PACKET_VERSION 1
struct __attribute__((packed)) jungle_health_t { struct __attribute__((packed)) jungle_health_t {
uint32_t uptime_pkt; uint32_t uptime_pkt;
float ch1_power; float ch1_power;

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