22#ifdef USE_SHD_FIRMWARE_DATA
38constexpr uint8_t STM32_ACK = 0x79;
39constexpr uint8_t STM32_NACK = 0x1F;
40constexpr uint8_t STM32_BUSY = 0x76;
42constexpr uint8_t STM32_CMD_INIT = 0x7F;
43constexpr uint8_t STM32_CMD_GET = 0x00;
44constexpr uint8_t STM32_CMD_GVR = 0x01;
45constexpr uint8_t STM32_CMD_GID = 0x02;
46constexpr uint8_t STM32_CMD_RM = 0x11;
47constexpr uint8_t STM32_CMD_GO = 0x21;
48constexpr uint8_t STM32_CMD_WM = 0x31;
49constexpr uint8_t STM32_CMD_WM_NS = 0x32;
50constexpr uint8_t STM32_CMD_ER = 0x43;
51constexpr uint8_t STM32_CMD_EE = 0x44;
52constexpr uint8_t STM32_CMD_EE_NS = 0x45;
53constexpr uint8_t STM32_CMD_WP = 0x63;
54constexpr uint8_t STM32_CMD_WP_NS = 0x64;
55constexpr uint8_t STM32_CMD_UW = 0x73;
56constexpr uint8_t STM32_CMD_UW_NS = 0x74;
57constexpr uint8_t STM32_CMD_RP = 0x82;
58constexpr uint8_t STM32_CMD_RP_NS = 0x83;
59constexpr uint8_t STM32_CMD_UR = 0x92;
60constexpr uint8_t STM32_CMD_UR_NS = 0x93;
61constexpr uint8_t STM32_CMD_CRC = 0xA1;
62constexpr uint8_t STM32_CMD_ERR = 0xFF;
64constexpr uint32_t STM32_RESYNC_TIMEOUT = 35 * 1000;
65constexpr uint32_t STM32_MASSERASE_TIMEOUT = 35 * 1000;
66constexpr uint32_t STM32_PAGEERASE_TIMEOUT = 5 * 1000;
67constexpr uint32_t STM32_BLKWRITE_TIMEOUT = 1 * 1000;
68constexpr uint32_t STM32_WUNPROT_TIMEOUT = 1 * 1000;
69constexpr uint32_t STM32_WPROT_TIMEOUT = 1 * 1000;
70constexpr uint32_t STM32_RPROT_TIMEOUT = 1 * 1000;
71constexpr uint32_t DEFAULT_TIMEOUT = 5 * 1000;
73constexpr uint8_t STM32_CMD_GET_LENGTH = 17;
79constexpr uint8_t STM_RESET_CODE[] = {
84 0x0c, 0xed, 0x00, 0xe0,
85 0x04, 0x00, 0xfa, 0x05
88constexpr uint32_t STM_RESET_CODE_SIZE =
sizeof(STM_RESET_CODE);
101constexpr uint8_t STM_OBL_LAUNCH_CODE[] = {
106 0x10, 0x20, 0x02, 0x40,
107 0x00, 0x20, 0x00, 0x00
110constexpr uint32_t STM_OBL_LAUNCH_CODE_SIZE =
sizeof(STM_OBL_LAUNCH_CODE);
121 if (addr < stm->dev->fl_start || addr > stm->dev->fl_end)
125 addr -= stm->dev->fl_start;
126 const auto *psize = stm->dev->fl_ps;
128 while (addr >= psize[0]) {
135 return addr ? page + 1 : page;
139 auto *stream = stm->stream;
146 timeout = DEFAULT_TIMEOUT;
151 if (!stream->available()) {
152 if (
millis() - start_time < timeout)
154 ESP_LOGD(TAG,
"Failed to read ACK timeout=%i", timeout);
155 return STM32_ERR_UNKNOWN;
158 stream->read_byte(&rxbyte);
160 if (rxbyte == STM32_ACK)
162 if (rxbyte == STM32_NACK)
163 return STM32_ERR_NACK;
164 if (rxbyte != STM32_BUSY) {
165 ESP_LOGD(TAG,
"Got byte 0x%02x instead of ACK", rxbyte);
166 return STM32_ERR_UNKNOWN;
174 auto *
const stream = stm->stream;
176 static constexpr auto BUFFER_SIZE = 2;
177 const uint8_t buf[] = {
179 static_cast<uint8_t
>(cmd ^ 0xFF),
181 static_assert(
sizeof(buf) == BUFFER_SIZE,
"Buf expected to be 2 bytes");
183 stream->write_array(buf, BUFFER_SIZE);
186 stm32_err_t s_err = stm32_get_ack_timeout(stm, timeout);
187 if (s_err == STM32_ERR_OK)
189 if (s_err == STM32_ERR_NACK) {
190 ESP_LOGD(TAG,
"Got NACK from device on command 0x%02x", cmd);
192 ESP_LOGD(TAG,
"Unexpected reply from device on command 0x%02x", cmd);
194 return STM32_ERR_UNKNOWN;
198 return stm32_send_command_timeout(stm, cmd, 0);
203 auto *
const stream = stm->stream;
207 static constexpr auto BUFFER_SIZE = 2;
208 const uint8_t buf[] = {
210 static_cast<uint8_t
>(STM32_CMD_ERR ^ 0xFF),
212 static_assert(
sizeof(buf) == BUFFER_SIZE,
"Buf expected to be 2 bytes");
215 while (t1 - t0 < STM32_RESYNC_TIMEOUT) {
216 stream->write_array(buf, BUFFER_SIZE);
218 if (!stream->read_array(&
ack, 1)) {
222 if (
ack == STM32_NACK)
226 return STM32_ERR_UNKNOWN;
242 auto *
const stream = stm->stream;
244 if (stm32_send_command(stm, cmd) != STM32_ERR_OK)
245 return STM32_ERR_UNKNOWN;
248 if (!stream->read_array(data, 1))
249 return STM32_ERR_UNKNOWN;
251 if (!stream->read_array(data + 1,
len + 1))
252 return STM32_ERR_UNKNOWN;
256 const auto ret = stream->read_array(data,
len + 2);
257 if (
ret &&
len == data[0])
261 if (stm32_resync(stm) != STM32_ERR_OK)
262 return STM32_ERR_UNKNOWN;
263 if (stm32_send_command(stm, cmd) != STM32_ERR_OK)
264 return STM32_ERR_UNKNOWN;
265 if (!stream->read_array(data, 1))
266 return STM32_ERR_UNKNOWN;
269 ESP_LOGD(TAG,
"Re sync (len = %d)", data[0]);
270 if (stm32_resync(stm) != STM32_ERR_OK)
271 return STM32_ERR_UNKNOWN;
274 if (stm32_send_command(stm, cmd) != STM32_ERR_OK)
275 return STM32_ERR_UNKNOWN;
277 if (!stream->read_array(data,
len + 2))
278 return STM32_ERR_UNKNOWN;
290 auto *
const stream = stm->stream;
292 stream->write_array(&STM32_CMD_INIT, 1);
296 bool ret = stream->read_array(&
byte, 1);
297 if (
ret &&
byte == STM32_ACK)
299 if (
ret &&
byte == STM32_NACK) {
301 ESP_LOGD(TAG,
"Warning: the interface was not closed properly.");
305 ESP_LOGD(TAG,
"Failed to init device.");
306 return STM32_ERR_UNKNOWN;
313 stream->write_array(&STM32_CMD_INIT, 1);
316 ret = stream->read_array(&
byte, 1);
317 if (
ret &&
byte == STM32_NACK)
319 ESP_LOGD(TAG,
"Failed to init device.");
320 return STM32_ERR_UNKNOWN;
324 auto *
const stream = stm->stream;
326 if (stm32_send_command(stm, stm->cmd->er) != STM32_ERR_OK) {
327 ESP_LOGD(TAG,
"Can't initiate chip mass erase!");
328 return STM32_ERR_UNKNOWN;
332 if (stm->cmd->er == STM32_CMD_ER) {
333 const auto s_err = stm32_send_command_timeout(stm, 0xFF, STM32_MASSERASE_TIMEOUT);
334 if (s_err != STM32_ERR_OK) {
335 return STM32_ERR_UNKNOWN;
341 static constexpr auto BUFFER_SIZE = 3;
342 const uint8_t buf[] = {
347 static_assert(
sizeof(buf) == BUFFER_SIZE,
"Expected the buffer to be 3 bytes");
348 stream->write_array(buf, 3);
351 const auto s_err = stm32_get_ack_timeout(stm, STM32_MASSERASE_TIMEOUT);
352 if (s_err != STM32_ERR_OK) {
353 ESP_LOGD(TAG,
"Mass erase failed. Try specifying the number of pages to be erased.");
354 return STM32_ERR_UNKNOWN;
359template<
typename T> std::unique_ptr<T[], void (*)(T *memory)> malloc_array_raii(
size_t size) {
361 static const auto DELETOR = [](T *memory) {
364 return std::unique_ptr<T[],
decltype(DELETOR)>{
static_cast<T *
>(malloc(
size)),
369 auto *
const stream = stm->stream;
376 if (stm32_send_command(stm, stm->cmd->er) != STM32_ERR_OK) {
377 ESP_LOGD(TAG,
"Can't initiate chip mass erase!");
378 return STM32_ERR_UNKNOWN;
382 if (stm->cmd->er == STM32_CMD_ER) {
384 auto buf = malloc_array_raii<uint8_t>(1 + pages + 1);
387 return STM32_ERR_UNKNOWN;
389 buf[i++] = pages - 1;
391 for (
auto pg_num = spage; pg_num < (pages + spage); pg_num++) {
396 stream->write_array(&buf[0], i);
399 const auto s_err = stm32_get_ack_timeout(stm, pages * STM32_PAGEERASE_TIMEOUT);
400 if (s_err != STM32_ERR_OK) {
401 return STM32_ERR_UNKNOWN;
409 auto buf = malloc_array_raii<uint8_t>(2 + 2 * pages + 1);
412 return STM32_ERR_UNKNOWN;
415 uint8_t pg_byte = (pages - 1) >> 8;
418 pg_byte = (pages - 1) & 0xFF;
422 for (
auto pg_num = spage; pg_num < spage + pages; pg_num++) {
423 pg_byte = pg_num >> 8;
426 pg_byte = pg_num & 0xFF;
431 stream->write_array(&buf[0], i);
434 const auto s_err = stm32_get_ack_timeout(stm, pages * STM32_PAGEERASE_TIMEOUT);
435 if (s_err != STM32_ERR_OK) {
436 ESP_LOGD(TAG,
"Page-by-page erase failed. Check the maximum pages your device supports.");
437 return STM32_ERR_UNKNOWN;
451 return STM32_ERR_UNKNOWN;
457 static constexpr int N = 1;
460 return *
reinterpret_cast<const char *
>(&N) == 1;
465 return ((v & 0xFF000000) >> 24) | ((v & 0x00FF0000) >> 8) | ((v & 0x0000FF00) << 8) | ((v & 0x000000FF) << 24);
478 static const auto CLOSE = [](
stm32_t *stm32) {
486 return std::unique_ptr<
stm32_t,
decltype(CLOSE)>{
ptr, CLOSE};
492#define newer(prev, a) (((prev) == STM32_CMD_ERR) ? (a) : (((prev) > (a)) ? (prev) : (a)))
497 auto stm = make_stm32_with_deletor(
static_cast<stm32_t *
>(calloc(
sizeof(
stm32_t), 1)));
500 return make_stm32_with_deletor(
nullptr);
502 stm->stream = stream;
507 return make_stm32_with_deletor(
nullptr);
509 memset(stm->cmd, STM32_CMD_ERR,
sizeof(
stm32_cmd_t));
512 if (stm32_send_init_seq(stm) != STM32_ERR_OK)
513 return make_stm32_with_deletor(
nullptr);
517 if (stm32_send_command(stm, STM32_CMD_GVR) != STM32_ERR_OK) {
518 return make_stm32_with_deletor(
nullptr);
525 return make_stm32_with_deletor(
nullptr);
527 stm->version = buf[0];
530 if (stm32_get_ack(stm) != STM32_ERR_OK) {
531 return make_stm32_with_deletor(
nullptr);
536 const auto len = ([&]() {
538 if (stm->cmd_get_reply) {
539 for (
auto i = 0; stm->cmd_get_reply[i].length; ++i) {
540 if (stm->version == stm->cmd_get_reply[i].version) {
541 return stm->cmd_get_reply[i].length;
546 return STM32_CMD_GET_LENGTH;
549 if (stm32_guess_len_cmd(stm, STM32_CMD_GET, buf,
len) != STM32_ERR_OK)
550 return make_stm32_with_deletor(
nullptr);
553 const auto stop = buf[0] + 1;
554 stm->bl_version = buf[1];
556 for (
auto i = 1; i < stop; ++i) {
557 const auto val = buf[i + 1];
575 case STM32_CMD_WM_NS:
576 stm->cmd->wm = newer(stm->cmd->wm,
val);
580 case STM32_CMD_EE_NS:
581 stm->cmd->er = newer(stm->cmd->er,
val);
584 case STM32_CMD_WP_NS:
585 stm->cmd->wp = newer(stm->cmd->wp,
val);
588 case STM32_CMD_UW_NS:
589 stm->cmd->uw = newer(stm->cmd->uw,
val);
592 case STM32_CMD_RP_NS:
593 stm->cmd->rp = newer(stm->cmd->rp,
val);
596 case STM32_CMD_UR_NS:
597 stm->cmd->ur = newer(stm->cmd->ur,
val);
600 stm->cmd->crc = newer(stm->cmd->crc,
val);
603 if (new_cmds++ == 0) {
604 ESP_LOGD(TAG,
"GET returns unknown commands (0x%2x",
val);
606 ESP_LOGD(TAG,
", 0x%2x",
val);
613 if (stm32_get_ack(stm) != STM32_ERR_OK) {
614 return make_stm32_with_deletor(
nullptr);
617 if (stm->cmd->get == STM32_CMD_ERR || stm->cmd->gvr == STM32_CMD_ERR || stm->cmd->gid == STM32_CMD_ERR) {
618 ESP_LOGD(TAG,
"Error: bootloader did not returned correct information from GET command");
619 return make_stm32_with_deletor(
nullptr);
623 if (stm32_guess_len_cmd(stm, stm->cmd->gid, buf, 1) != STM32_ERR_OK) {
624 return make_stm32_with_deletor(
nullptr);
626 const auto returned = buf[0] + 1;
628 ESP_LOGD(TAG,
"Only %d bytes sent in the PID, unknown/unsupported device", returned);
629 return make_stm32_with_deletor(
nullptr);
631 stm->pid = (buf[1] << 8) | buf[2];
633 ESP_LOGD(TAG,
"This bootloader returns %d extra bytes in PID:", returned);
634 for (
auto i = 2; i <= returned; i++) {
635 ESP_LOGD(TAG,
" %02x", buf[i]);
638 if (stm32_get_ack(stm) != STM32_ERR_OK) {
639 return make_stm32_with_deletor(
nullptr);
643 while (stm->dev->id != 0x00 && stm->dev->id != stm->pid)
647 ESP_LOGD(TAG,
"Unknown/unsupported device (Device ID: 0x%03x)", stm->pid);
648 return make_stm32_with_deletor(
nullptr);
655 const unsigned int len) {
656 auto *
const stream = stm->stream;
662 ESP_LOGD(TAG,
"Error: READ length limit at 256 bytes");
663 return STM32_ERR_UNKNOWN;
666 if (stm->cmd->rm == STM32_CMD_ERR) {
667 ESP_LOGD(TAG,
"Error: READ command not implemented in bootloader.");
668 return STM32_ERR_NO_CMD;
671 if (stm32_send_command(stm, stm->cmd->rm) != STM32_ERR_OK)
672 return STM32_ERR_UNKNOWN;
674 static constexpr auto BUFFER_SIZE = 5;
675 uint8_t buf[BUFFER_SIZE];
676 populate_buffer_with_address(buf,
address);
678 stream->write_array(buf, BUFFER_SIZE);
681 if (stm32_get_ack(stm) != STM32_ERR_OK)
682 return STM32_ERR_UNKNOWN;
684 if (stm32_send_command(stm,
len - 1) != STM32_ERR_OK)
685 return STM32_ERR_UNKNOWN;
687 if (!stream->read_array(data,
len))
688 return STM32_ERR_UNKNOWN;
694 const unsigned int len) {
695 auto *
const stream = stm->stream;
701 ESP_LOGD(TAG,
"Error: READ length limit at 256 bytes");
702 return STM32_ERR_UNKNOWN;
707 ESP_LOGD(TAG,
"Error: WRITE address must be 4 byte aligned");
708 return STM32_ERR_UNKNOWN;
711 if (stm->cmd->wm == STM32_CMD_ERR) {
712 ESP_LOGD(TAG,
"Error: WRITE command not implemented in bootloader.");
713 return STM32_ERR_NO_CMD;
717 if (stm32_send_command(stm, stm->cmd->wm) != STM32_ERR_OK)
718 return STM32_ERR_UNKNOWN;
720 static constexpr auto BUFFER_SIZE = 5;
721 uint8_t buf1[BUFFER_SIZE];
722 populate_buffer_with_address(buf1,
address);
724 stream->write_array(buf1, BUFFER_SIZE);
726 if (stm32_get_ack(stm) != STM32_ERR_OK)
727 return STM32_ERR_UNKNOWN;
729 const unsigned int aligned_len = (
len + 3) & ~3;
730 uint8_t buf[256 + 2];
732 buf[0] = aligned_len - 1;
733 memcpy(&buf[1], data,
len);
735 memset(&buf[1 +
len], 0xFF, aligned_len -
len);
736 buf[aligned_len + 1] =
xor_bytes(buf, aligned_len + 1);
737 stream->write_array(buf, aligned_len + 2);
740 const auto s_err = stm32_get_ack_timeout(stm, STM32_BLKWRITE_TIMEOUT);
741 if (s_err != STM32_ERR_OK) {
742 return STM32_ERR_UNKNOWN;
748 if (stm->cmd->uw == STM32_CMD_ERR) {
749 ESP_LOGD(TAG,
"Error: WRITE UNPROTECT command not implemented in bootloader.");
750 return STM32_ERR_NO_CMD;
753 if (stm32_send_command(stm, stm->cmd->uw) != STM32_ERR_OK)
754 return STM32_ERR_UNKNOWN;
756 return stm32_check_ack_timeout(stm32_get_ack_timeout(stm, STM32_WUNPROT_TIMEOUT),
757 []() { ESP_LOGD(TAG,
"Error: Failed to WRITE UNPROTECT"); });
761 if (stm->cmd->wp == STM32_CMD_ERR) {
762 ESP_LOGD(TAG,
"Error: WRITE PROTECT command not implemented in bootloader.");
763 return STM32_ERR_NO_CMD;
766 if (stm32_send_command(stm, stm->cmd->wp) != STM32_ERR_OK)
767 return STM32_ERR_UNKNOWN;
769 return stm32_check_ack_timeout(stm32_get_ack_timeout(stm, STM32_WPROT_TIMEOUT),
770 []() { ESP_LOGD(TAG,
"Error: Failed to WRITE PROTECT"); });
774 if (stm->cmd->ur == STM32_CMD_ERR) {
775 ESP_LOGD(TAG,
"Error: READOUT UNPROTECT command not implemented in bootloader.");
776 return STM32_ERR_NO_CMD;
779 if (stm32_send_command(stm, stm->cmd->ur) != STM32_ERR_OK)
780 return STM32_ERR_UNKNOWN;
782 return stm32_check_ack_timeout(stm32_get_ack_timeout(stm, STM32_MASSERASE_TIMEOUT),
783 []() { ESP_LOGD(TAG,
"Error: Failed to READOUT UNPROTECT"); });
787 if (stm->cmd->rp == STM32_CMD_ERR) {
788 ESP_LOGD(TAG,
"Error: READOUT PROTECT command not implemented in bootloader.");
789 return STM32_ERR_NO_CMD;
792 if (stm32_send_command(stm, stm->cmd->rp) != STM32_ERR_OK)
793 return STM32_ERR_UNKNOWN;
795 return stm32_check_ack_timeout(stm32_get_ack_timeout(stm, STM32_RPROT_TIMEOUT),
796 []() { ESP_LOGD(TAG,
"Error: Failed to READOUT PROTECT"); });
803 if (stm->cmd->er == STM32_CMD_ERR) {
804 ESP_LOGD(TAG,
"Error: ERASE command not implemented in bootloader.");
805 return STM32_ERR_NO_CMD;
819 if (!(stm->dev->flags & F_NO_ME))
820 return stm32_mass_erase(stm);
822 pages = flash_addr_to_page_ceil(stm, stm->dev->fl_end);
829 static constexpr uint32_t MAX_PAGE_SIZE = 512;
831 const auto n = std::min(pages, MAX_PAGE_SIZE);
832 const auto s_err = stm32_pages_erase(stm, spage, n);
833 if (s_err != STM32_ERR_OK)
843 static constexpr uint32_t BUFFER_SIZE = 256;
845 const auto stack_le = le_u32(0x20002000);
846 const auto code_address_le = le_u32(target_address + 8 + 1);
850 if (target_address & 0x3) {
851 ESP_LOGD(TAG,
"Error: code address must be 4 byte aligned");
852 return STM32_ERR_UNKNOWN;
856 static const auto DELETOR = [](uint8_t *memory) {
861 std::unique_ptr<uint8_t,
decltype(DELETOR)> mem{
static_cast<uint8_t *
>(malloc(
length)),
865 return STM32_ERR_UNKNOWN;
867 memcpy(mem.get(), &stack_le,
sizeof(stack_le));
868 memcpy(mem.get() + 4, &code_address_le,
sizeof(code_address_le));
869 memcpy(mem.get() + 8, code, code_size);
871 auto *
pos = mem.get();
874 const auto w = std::min(
length, BUFFER_SIZE);
876 return STM32_ERR_UNKNOWN;
884 return stm32_go(stm, target_address);
888 auto *
const stream = stm->stream;
890 if (stm->cmd->go == STM32_CMD_ERR) {
891 ESP_LOGD(TAG,
"Error: GO command not implemented in bootloader.");
892 return STM32_ERR_NO_CMD;
895 if (stm32_send_command(stm, stm->cmd->go) != STM32_ERR_OK)
896 return STM32_ERR_UNKNOWN;
898 static constexpr auto BUFFER_SIZE = 5;
899 uint8_t buf[BUFFER_SIZE];
900 populate_buffer_with_address(buf,
address);
902 stream->write_array(buf, BUFFER_SIZE);
905 if (stm32_get_ack(stm) != STM32_ERR_OK)
906 return STM32_ERR_UNKNOWN;
911 const auto target_address = stm->dev->ram_start;
913 if (stm->dev->flags & F_OBLL) {
915 return stm32_run_raw_code(stm, target_address, STM_OBL_LAUNCH_CODE, STM_OBL_LAUNCH_CODE_SIZE);
917 return stm32_run_raw_code(stm, target_address, STM_RESET_CODE, STM_RESET_CODE_SIZE);
923 static constexpr auto BUFFER_SIZE = 5;
924 auto *
const stream = stm->stream;
927 ESP_LOGD(TAG,
"Start and end addresses must be 4 byte aligned");
928 return STM32_ERR_UNKNOWN;
931 if (stm->cmd->crc == STM32_CMD_ERR) {
932 ESP_LOGD(TAG,
"Error: CRC command not implemented in bootloader.");
933 return STM32_ERR_NO_CMD;
936 if (stm32_send_command(stm, stm->cmd->crc) != STM32_ERR_OK)
937 return STM32_ERR_UNKNOWN;
940 static constexpr auto BUFFER_SIZE = 5;
941 uint8_t buf[BUFFER_SIZE];
942 populate_buffer_with_address(buf,
address);
944 stream->write_array(buf, BUFFER_SIZE);
948 if (stm32_get_ack(stm) != STM32_ERR_OK)
949 return STM32_ERR_UNKNOWN;
952 static constexpr auto BUFFER_SIZE = 5;
953 uint8_t buf[BUFFER_SIZE];
954 populate_buffer_with_address(buf,
address);
956 stream->write_array(buf, BUFFER_SIZE);
960 if (stm32_get_ack(stm) != STM32_ERR_OK)
961 return STM32_ERR_UNKNOWN;
963 if (stm32_get_ack(stm) != STM32_ERR_OK)
964 return STM32_ERR_UNKNOWN;
967 uint8_t buf[BUFFER_SIZE];
968 if (!stream->read_array(buf, BUFFER_SIZE))
969 return STM32_ERR_UNKNOWN;
971 if (buf[4] != (buf[0] ^ buf[1] ^ buf[2] ^ buf[3]))
972 return STM32_ERR_UNKNOWN;
974 *crc = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
989 static constexpr uint32_t CRCPOLY_BE = 0x04c11db7;
990 static constexpr uint32_t CRC_MSBMASK = 0x80000000;
993 ESP_LOGD(TAG,
"Buffer length must be multiple of 4 bytes");
1000 data |= *buf++ << 16;
1001 data |= *buf++ << 24;
1006 for (
size_t i = 0; i < 32; ++i) {
1007 if (crc & CRC_MSBMASK) {
1008 crc = (crc << 1) ^ CRCPOLY_BE;
1018 static constexpr uint32_t CRC_INIT_VALUE = 0xFFFFFFFF;
1019 static constexpr uint32_t BUFFER_SIZE = 256;
1021 uint8_t buf[BUFFER_SIZE];
1024 ESP_LOGD(TAG,
"Start and end addresses must be 4 byte aligned");
1025 return STM32_ERR_UNKNOWN;
1028 if (stm->cmd->crc != STM32_CMD_ERR)
1032 const auto total_len =
length;
1033 uint32_t current_crc = CRC_INIT_VALUE;
1035 const auto len = std::min(BUFFER_SIZE,
length);
1037 ESP_LOGD(TAG,
"Failed to read memory at address 0x%08x, target write-protected?",
address);
1038 return STM32_ERR_UNKNOWN;
1044 ESP_LOGD(TAG,
"\rCRC address 0x%08x (%.2f%%) ",
address, (100.0f / (
float) total_len) * (
float) (
address - start));
1046 ESP_LOGD(TAG,
"Done.");
1048 return STM32_ERR_OK;
bool read_array(uint8_t *data, size_t len)
ESPHOME_LOG_TAG(TAG, "hw_timer_esp_idf")
static void int int int w
static void int int int int const uint8_t * ptr
std::span< const uint8_t > data
stm32_err_t stm32_wunprot_memory(const stm32_unique_ptr &stm)
stm32_err_t stm32_reset_device(const stm32_unique_ptr &stm)
stm32_unique_ptr stm32_init(uart::UARTDevice *stream, const uint8_t flags, const char init)
constexpr auto STREAM_OPT_CMD_INIT
constexpr auto STREAM_OPT_RETRY
struct Stm32 { uart::UARTDevice *stream; uint8_t flags; struct VarlenCmd *cmd_get_reply; uint8_t bl_version; uint8_t version; uint8_t option1, option2; uint16_t pid; stm32_cmd_t *cmd; const stm32_dev_t *dev;} stm32_t
stm32_err_t stm32_readprot_memory(const stm32_unique_ptr &stm)
stm32_err_t stm32_crc_wrapper(const stm32_unique_ptr &stm, uint32_t address, uint32_t length, uint32_t *crc)
struct Stm32Cmd { uint8_t get; uint8_t gvr; uint8_t gid; uint8_t rm; uint8_t go; uint8_t wm; uint8_t er; uint8_t wp; uint8_t uw; uint8_t rp; uint8_t ur; uint8_t crc;} stm32_cmd_t
stm32_err_t stm32_write_memory(const stm32_unique_ptr &stm, uint32_t address, const uint8_t *data, const unsigned int len)
constexpr auto STM32_MASS_ERASE
constexpr auto STM32_MAX_PAGES
stm32_err_t stm32_runprot_memory(const stm32_unique_ptr &stm)
stm32_err_t stm32_go(const stm32_unique_ptr &stm, const uint32_t address)
stm32_err_t stm32_crc_memory(const stm32_unique_ptr &stm, const uint32_t address, const uint32_t length, uint32_t *const crc)
stm32_err_t stm32_read_memory(const stm32_unique_ptr &stm, const uint32_t address, uint8_t *data, const unsigned int len)
uint32_t stm32_sw_crc(uint32_t crc, uint8_t *buf, unsigned int len)
constexpr auto STREAM_OPT_BYTE
constexpr auto STREAM_OPT_GVR_ETX
stm32_err_t stm32_erase_memory(const stm32_unique_ptr &stm, uint32_t spage, uint32_t pages)
std::unique_ptr< stm32_t, void(*)(stm32_t *)> stm32_unique_ptr
enum Stm32Err { STM32_ERR_OK=0, STM32_ERR_UNKNOWN, STM32_ERR_NACK, STM32_ERR_NO_CMD, } stm32_err_t
stm32_err_t stm32_wprot_memory(const stm32_unique_ptr &stm)
constexpr uint8_t xor_bytes(const uint8_t *data, size_t len, uint8_t init=0)
XOR the bytes of data with size len, starting from init.
uint32_t IRAM_ATTR HOT millis()