Skip to content

Commit b63e23d

Browse files
committed
Add files
0 parents  commit b63e23d

14 files changed

+1857
-0
lines changed

CMakeLists.txt

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
cmake_minimum_required(VERSION 3.14)
2+
project(PICo24_Flasher)
3+
4+
set(CMAKE_CXX_STANDARD 17)
5+
6+
set(CPM_DOWNLOAD_VERSION 0.27.5)
7+
set(CPM_DOWNLOAD_LOCATION "${CMAKE_BINARY_DIR}/cmake/CPM_${CPM_DOWNLOAD_VERSION}.cmake")
8+
9+
if(NOT (EXISTS ${CPM_DOWNLOAD_LOCATION}))
10+
message(STATUS "Downloading CPM.cmake")
11+
file(DOWNLOAD https://github.com/TheLartians/CPM.cmake/releases/download/v${CPM_DOWNLOAD_VERSION}/CPM.cmake ${CPM_DOWNLOAD_LOCATION})
12+
endif()
13+
14+
include(${CPM_DOWNLOAD_LOCATION})
15+
16+
CPMAddPackage(
17+
NAME cxxopts
18+
GITHUB_REPOSITORY jarro2783/cxxopts
19+
VERSION 3.0.0
20+
GIT_TAG 97a4d5511ffefc81a97abd3d67b37f66e57655ee
21+
GIT_SHALLOW ON
22+
)
23+
24+
CPMAddPackage(
25+
NAME IODash
26+
GITHUB_REPOSITORY YukiWorkshop/IODash
27+
VERSION 0.1.7
28+
GIT_SHALLOW ON
29+
)
30+
31+
CPMAddPackage(
32+
NAME iHexPP
33+
GITHUB_REPOSITORY SudoMaker/iHexPP
34+
VERSION 0.0.2
35+
GIT_SHALLOW ON
36+
)
37+
38+
add_executable(picoboot PICoBoot_Utility.cpp PICoBoot_Utility.hpp ScanDevice.cpp SerialOps.cpp Protocol.cpp Cmd_Flash.cpp Cmd_Info.cpp Cmd_Reboot.cpp Cmd_Devices.cpp Cmd_Env.cpp Cmd_Erase.cpp)
39+
target_link_libraries(picoboot stdc++fs cxxopts IODash iHexPP)

Cmd_Devices.cpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
This file is part of PICoBoot Utility.
3+
4+
Copyright (C) 2021 ReimuNotMoe <[email protected]>
5+
6+
This program is free software: you can redistribute it and/or modify
7+
it under the terms of the GNU Affero General Public License as
8+
published by the Free Software Foundation, either version 3 of the
9+
License, or (at your option) any later version.
10+
11+
This program is distributed in the hope that it will be useful,
12+
but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
GNU Affero General Public License for more details.
15+
16+
You should have received a copy of the GNU Affero General Public License
17+
along with this program. If not, see <https://www.gnu.org/licenses/>.
18+
*/
19+
20+
#include "PICoBoot_Utility.hpp"
21+
22+
int Command_Devices(const std::vector<std::string>& args) {
23+
24+
auto paths = ScanDevice_GetValidDevices();
25+
26+
printf("%20.20s %20.20s\n", "path", "bl version");
27+
28+
for (auto &it : paths) {
29+
Serial tty;
30+
tty.open(it);
31+
32+
#ifdef __CYGWIN__
33+
try {
34+
#endif
35+
tty.make_raw();
36+
tty.speed() = 2000000;
37+
#ifdef __CYGWIN__
38+
} catch (...) {
39+
40+
}
41+
#endif
42+
43+
auto info_bl_ver = serial_chat(tty, FlasherCommand_GetBootloaderVersion, nullptr);
44+
*info_bl_ver.end() = 0;
45+
46+
printf("%20.20s %20.20s\n", it.c_str(), info_bl_ver.data());
47+
}
48+
49+
return 0;
50+
}

Cmd_Env.cpp

Lines changed: 290 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,290 @@
1+
/*
2+
This file is part of PICoBoot Utility.
3+
4+
Copyright (C) 2021 ReimuNotMoe <[email protected]>
5+
6+
This program is free software: you can redistribute it and/or modify
7+
it under the terms of the GNU Affero General Public License as
8+
published by the Free Software Foundation, either version 3 of the
9+
License, or (at your option) any later version.
10+
11+
This program is distributed in the hope that it will be useful,
12+
but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
GNU Affero General Public License for more details.
15+
16+
You should have received a copy of the GNU Affero General Public License
17+
along with this program. If not, see <https://www.gnu.org/licenses/>.
18+
*/
19+
20+
#include "PICoBoot_Utility.hpp"
21+
22+
std::vector<std::string> env_list = {
23+
"watchdog_config",
24+
"watchdog_max_fails",
25+
"allow_read",
26+
"allow_write",
27+
"app_name",
28+
"app_version",
29+
30+
"reboot_count",
31+
"watchdog_failed_count",
32+
"boot_reason",
33+
"reboot_target",
34+
};
35+
36+
enum {
37+
EnvType_u8, EnvType_s8,
38+
EnvType_u16, EnvType_s16,
39+
EnvType_u32, EnvType_s32,
40+
EnvType_u64, EnvType_s64,
41+
42+
EnvType_str, EnvType_bin,
43+
};
44+
std::unordered_map<std::string, std::tuple<uint8_t, uint8_t, uint8_t, uint8_t>> env_table = {
45+
// Category, Type, Offset, Size
46+
{"watchdog_config", {0, EnvType_u8, 1, 1}},
47+
{"watchdog_max_fails", {0, EnvType_u8, 2, 1}},
48+
{"allow_read", {0, EnvType_u32, 4, 4}},
49+
{"allow_write", {0, EnvType_u32, 8, 4}},
50+
{"app_name", {0, EnvType_str, 12, 16}},
51+
{"app_version", {0, EnvType_str, 28, 8}},
52+
53+
{"reboot_count", {1, EnvType_u32, 0, 4}},
54+
{"watchdog_failed_count", {1, EnvType_u32, 4, 4}},
55+
{"boot_reason", {1, EnvType_u8, 8, 1}},
56+
{"reboot_target", {1, EnvType_u8, 9, 1}},
57+
};
58+
59+
static void print_val(uint8_t type, uint8_t *target, uint8_t len) {
60+
switch (type) {
61+
case EnvType_u8: {
62+
uint8_t val = *((uint8_t *) target);
63+
printf("%" PRIu8 " (0x%02x)\n", val, val);
64+
}
65+
break;
66+
case EnvType_s8: {
67+
int8_t val = *((int8_t *) target);
68+
printf("%" PRId8 " (0x%02x)\n", val, val);
69+
}
70+
break;
71+
case EnvType_u16: {
72+
uint16_t val = *((uint16_t *) target);
73+
printf("%" PRIu16 " (0x%04x)\n", val, val);
74+
}
75+
break;
76+
case EnvType_s16: {
77+
int16_t val = *((int16_t *) target);
78+
printf("%" PRId16 " (0x%04x)\n", val, val);
79+
}
80+
break;
81+
case EnvType_u32: {
82+
uint32_t val = *((uint32_t *) target);
83+
printf("%" PRIu32 " (0x%08x)\n", val, val);
84+
}
85+
break;
86+
case EnvType_s32: {
87+
int32_t val = *((int32_t *) target);
88+
printf("%" PRId32 " (0x%08x)\n", val, val);
89+
}
90+
break;
91+
case EnvType_u64: {
92+
uint64_t val = *((uint64_t *) target);
93+
printf("%" PRIu64 " (0x%016lx)\n", val, val);
94+
}
95+
break;
96+
case EnvType_s64: {
97+
int64_t val = *((int64_t *) target);
98+
printf("%" PRId64 " (0x%016lx)\n", val, val);
99+
}
100+
break;
101+
case EnvType_str: {
102+
printf("%.*s (len = %u)\n", len, target, len);
103+
}
104+
break;
105+
case EnvType_bin: {
106+
for (size_t i = 0; i < len; i++) {
107+
printf("%02x ", target[i]);
108+
}
109+
printf("(len = %u)\n", len);
110+
}
111+
break;
112+
113+
}
114+
}
115+
116+
int write_env(Serial &tty, uint8_t cat, uint8_t type, uint8_t offset, uint8_t len, const std::string& user_input) {
117+
uint8_t buf[len];
118+
bool hex = (user_input.find("0x") == 0);
119+
int base = hex ? 16 : 10;
120+
121+
switch (type) {
122+
case EnvType_u8:
123+
*((uint8_t *) buf) = strtoul(user_input.c_str(), nullptr, base);
124+
break;
125+
case EnvType_s8:
126+
*((int8_t *) buf) = strtol(user_input.c_str(), nullptr, base);
127+
break;
128+
case EnvType_u16:
129+
*((uint16_t *) buf) = strtoul(user_input.c_str(), nullptr, base);
130+
break;
131+
case EnvType_s16:
132+
*((int16_t *) buf) = strtol(user_input.c_str(), nullptr, base);
133+
break;
134+
case EnvType_u32:
135+
*((uint32_t *) buf) = strtoul(user_input.c_str(), nullptr, base);
136+
break;
137+
case EnvType_s32:
138+
*((int32_t *) buf) = strtol(user_input.c_str(), nullptr, base);
139+
break;
140+
case EnvType_u64:
141+
*((uint64_t *) buf) = strtoul(user_input.c_str(), nullptr, base);
142+
break;
143+
case EnvType_s64:
144+
*((int64_t *) buf) = strtol(user_input.c_str(), nullptr, base);
145+
break;
146+
case EnvType_str:
147+
strncpy(reinterpret_cast<char *>(buf), user_input.c_str(), len);
148+
break;
149+
case EnvType_bin:
150+
puts("Unsupported at this moment.");
151+
abort();
152+
break;
153+
}
154+
155+
156+
for (size_t i=0; i<len; i++) {
157+
uint8_t pkt[4] = {cat, static_cast<uint8_t>(offset+i), buf[i], 0};
158+
pkt[3] = crc8(pkt, 3);
159+
160+
auto rcv = serial_chat(tty, FlasherCommand_EnvironmentWrite, pkt);
161+
uint8_t rc = *((uint8_t *)rcv.data());
162+
163+
if (rc != FlasherResult_OK) {
164+
printf("error: failed to write environment variable: %s\n", FlasherResult_strerror(rc));
165+
return 2;
166+
}
167+
}
168+
169+
return 0;
170+
}
171+
172+
int Command_Env(const std::vector<std::string>& args) {
173+
if (args.size() < 2) {
174+
puts("usage: env <show|get KEY|set KEY VALUE|save [static|runtime]>>");
175+
return 2;
176+
}
177+
178+
if (global_device_path.empty()) {
179+
auto paths = ScanDevice_GetValidDevices();
180+
if (paths.size() > 1) {
181+
puts("More than one devices connected. Please specify one using the `-d' option.");
182+
return 1;
183+
} else {
184+
global_device_path = paths[0];
185+
}
186+
}
187+
188+
Serial tty;
189+
tty.open(global_device_path);
190+
191+
#ifdef __CYGWIN__
192+
try {
193+
#endif
194+
tty.make_raw();
195+
tty.speed() = 2000000;
196+
#ifdef __CYGWIN__
197+
} catch (...) {
198+
199+
}
200+
#endif
201+
202+
if (args[1] == "show") {
203+
uint8_t cat = 0;
204+
auto env_block0 = serial_chat(tty, FlasherCommand_EnvironmentRead, &cat);
205+
cat = 1;
206+
auto env_block1 = serial_chat(tty, FlasherCommand_EnvironmentRead, &cat);
207+
208+
for (auto &it : env_list) {
209+
auto &envdef = env_table[it];
210+
uint8_t *target;
211+
212+
const char *category;
213+
214+
if (std::get<0>(envdef) == 0) {
215+
target = env_block0.data();
216+
category = "static";
217+
} else {
218+
target = env_block1.data();
219+
category = "runtime";
220+
}
221+
222+
printf("%s.%s: ", category, it.c_str());
223+
224+
print_val(std::get<1>(envdef), target + std::get<2>(envdef), std::get<3>(envdef));
225+
}
226+
} else if (args[1] == "save") {
227+
uint8_t arg = 0x3;
228+
229+
if (args.size() > 2) {
230+
if (args[2] == "static") {
231+
arg = 0x1;
232+
} else if (args[2] == "runtime") {
233+
arg = 0x2;
234+
}
235+
}
236+
237+
auto rcv = serial_chat(tty, FlasherCommand_EnvironmentSave, &arg);
238+
uint8_t rc = *((uint8_t *)rcv.data());
239+
240+
if (rc != FlasherResult_OK) {
241+
printf("error: failed to save environment: %s\n", FlasherResult_strerror(rc));
242+
}
243+
return 2;
244+
} else if (args[1] == "get") {
245+
if (args.size() != 3) {
246+
puts("error: please specify a name");
247+
return 2;
248+
}
249+
250+
auto it = env_table.find(args[2]);
251+
252+
if (it != env_table.end()) {
253+
auto &envdef = it->second;
254+
uint8_t *target;
255+
256+
uint8_t cat = 0;
257+
auto env_block0 = serial_chat(tty, FlasherCommand_EnvironmentRead, &cat);
258+
cat = 1;
259+
auto env_block1 = serial_chat(tty, FlasherCommand_EnvironmentRead, &cat);
260+
261+
if (std::get<0>(envdef) == 0) {
262+
target = env_block0.data();
263+
} else {
264+
target = env_block1.data();
265+
}
266+
267+
print_val(std::get<1>(envdef), target + std::get<2>(envdef), std::get<3>(envdef));
268+
} else {
269+
puts("error: not a valid environment name (please don't write prefixes like `static.' or `runtime.' here)");
270+
return 2;
271+
}
272+
} else if (args[1] == "set") {
273+
if (args.size() != 4) {
274+
puts("error: please specify key and value");
275+
return 2;
276+
}
277+
278+
auto it = env_table.find(args[2]);
279+
280+
if (it != env_table.end()) {
281+
auto &envdef = it->second;
282+
return write_env(tty, std::get<0>(envdef), std::get<1>(envdef), std::get<2>(envdef), std::get<3>(envdef), args[3]);
283+
} else {
284+
puts("error: not a valid environment name (please don't write prefixes like `static.' or `runtime.' here)");
285+
return 2;
286+
}
287+
}
288+
289+
return 0;
290+
}

0 commit comments

Comments
 (0)