This is an automated email from Gerrit. "Tigran Sukiasyan <tigran.sukias...@taurotech.com>" just uploaded a new patch set to Gerrit, which you can find at https://review.openocd.org/c/openocd/+/8510
-- gerrit commit c9bd09936818f26a82d2fac40329dfb52e76b70e Author: tigransukiasyan <tigran.sukias...@taurotech.com> Date: Thu Sep 26 02:26:02 2024 -0700 src/flash/nor: move nrf91_update_mfw command to src/flash/nor move the command handler and registration to src/flash/nor/nrf5.c use enumaerations for nrf91 flash section base addresses Change-Id: Ib4d8ff96839fb329c553b86737ecc60dcba169c7 Signed-off-by: tigransukiasyan <tigran.sukias...@taurotech.com> diff --git a/src/flash/nor/nrf5.c b/src/flash/nor/nrf5.c index 5cb552aa94..f342df63f9 100644 --- a/src/flash/nor/nrf5.c +++ b/src/flash/nor/nrf5.c @@ -18,6 +18,7 @@ #include <helper/types.h> #include <helper/time_support.h> #include <helper/bits.h> +#include "src/target/image.h" /* The refresh code is constant across the current spectrum of nRF5 devices */ #define WATCHDOG_REFRESH_VALUE 0x6e524635 @@ -1480,6 +1481,181 @@ error: return res; } +enum nrf91_bases { + NRF91_NVMC_S_BASE = 0x50039000, + NRF91_SPU_BASE = 0x50003000, + NRF91_IPC_NS_BASE = 0x4002A000, + NRF91_SRAM_BASE = 0x20000000, + NRF91_POWER_S_BASE = 0x50005000, +}; + +void nrf91_setup_device_for_dfu(struct target *target) +{ + target_write_u32(target, NRF91_NVMC_S_BASE + 0x504, 0x01); + target_write_u32(target, NRF53APP_91_UICR_BASE + 0x1C, 0x0E); + target_write_u32(target, NRF53APP_91_UICR_BASE + 0x20, 0x20); + target_write_u32(target, NRF91_NVMC_S_BASE + 0x504, 0x00); + + // configure IPC to be in non-secure mode + target_write_u32(target, NRF91_SPU_BASE + 0x8A8, 0x00000002); + + // configure IPC HW for DFU + target_write_u32(target, NRF91_IPC_NS_BASE + 0x514, 0x00000002); + target_write_u32(target, NRF91_IPC_NS_BASE + 0x51C, 0x00000008); + target_write_u32(target, NRF91_IPC_NS_BASE + 0x610, 0x21000000); + target_write_u32(target, NRF91_IPC_NS_BASE + 0x614, 0x00000000); + target_write_u32(target, NRF91_IPC_NS_BASE + 0x590, 0x00000001); + target_write_u32(target, NRF91_IPC_NS_BASE + 0x598, 0x00000004); + target_write_u32(target, NRF91_IPC_NS_BASE + 0x5A0, 0x00000010); + + // configure RAM as non-secure + for (int i = 0; i < 32; ++i) + target_write_u32(target, NRF91_SPU_BASE + 0x700 + i * 4, 0x00000007); + + // allocate memory in RAM + target_write_u32(target, NRF91_SRAM_BASE + 0x0, 0x80010000); + target_write_u32(target, NRF91_SRAM_BASE + 0x4, 0x2100000C); + target_write_u32(target, NRF91_SRAM_BASE + 0x8, 0x0003FC00); + + // reset the modem + target_write_u32(target, NRF91_POWER_S_BASE + 0x610, 0); + target_write_u32(target, NRF91_POWER_S_BASE + 0x614, 1); + target_write_u32(target, NRF91_POWER_S_BASE + 0x610, 1); + target_write_u32(target, NRF91_POWER_S_BASE + 0x614, 0); + target_write_u32(target, NRF91_POWER_S_BASE + 0x610, 0); + + // wait until the modem is reset + sleep(2); + + // clear event registers before using + target_write_u32(target, NRF91_IPC_NS_BASE + 0x100, 0); + target_write_u32(target, NRF91_IPC_NS_BASE + 0x108, 0); + target_write_u32(target, NRF91_IPC_NS_BASE + 0x110, 0); +} + +void nrf91_wait_and_ack_events(struct target *target) +{ + bool fault = false; + uint32_t value = 0; + target_addr_t fault_event = NRF91_IPC_NS_BASE + 0100; + target_addr_t command_event = NRF91_IPC_NS_BASE + 0x108; + target_addr_t data_event = NRF91_IPC_NS_BASE + 0x110; + while (true) { + target_read_u32(target, fault_event, &value); + if (value != 0) { + fault = true; + break; + } + target_read_u32(target, command_event, &value); + if (value != 0) + break; + target_read_u32(target, data_event, &value); + if (value != 0) + break; + } + target_write_u32(target, fault_event, 0); + target_write_u32(target, command_event, 0); + target_write_u32(target, data_event, 0); + + uint32_t response = 0; + target_read_u32(target, NRF91_SRAM_BASE + 0xC, &response); + if ((response & 0xff000000) == 0xa5000000) + LOG_DEBUG("ack"); + if ((response & 0xff000000) == 0x5a000000) + LOG_ERROR("nack\n"); + if (fault) + LOG_ERROR("fault\n"); +} + +int nrf91_write_section_to_ram(struct target *target, struct image *image, size_t section_number, bool is_loader) +{ + int retval = ERROR_OK; + uint32_t count = image->sections[section_number].size; + target_addr_t address = image->sections[section_number].base_address; + target_addr_t chunk_write_address = NRF91_SRAM_BASE + 0x18; + const size_t buffersize = 0x10000; + uint8_t *buffer_addr = image->sections[section_number].private; + + while (count > 0) { + const unsigned int max_chunk_len = buffersize; + const size_t chunk_len = MIN(count, max_chunk_len); + count -= chunk_len; + + if (is_loader) + target_write_memory(target, address, 1, chunk_len, buffer_addr); + else + target_write_memory(target, chunk_write_address, 1, chunk_len, buffer_addr); + + if (retval != ERROR_OK) { + LOG_ERROR("write_memory: write at " TARGET_ADDR_FMT " with width=%u and count=%zu failed", + address, 8, chunk_len); + retval = ERROR_FAIL; + break; + } + if (!is_loader) { + target_write_u32(target, NRF91_SRAM_BASE + 0x10, address); + target_write_u32(target, NRF91_SRAM_BASE + 0x14, chunk_len); + target_write_u32(target, NRF91_SRAM_BASE + 0x0C, 0x3); + target_write_u32(target, NRF91_IPC_NS_BASE + 0x004, 1); + nrf91_wait_and_ack_events(target); + } + + address += chunk_len; + buffer_addr += chunk_len; + } + return retval; +} + +COMMAND_HANDLER(nrf91_handle_update_modem_firmware) +{ + /* + * argv[1] = dfu loader file (.ihex) + * argv[2:] = segment files (.hex) + */ + + int e = 0; + + if (CMD_ARGC < 3) + return ERROR_COMMAND_SYNTAX_ERROR; + + struct target *target = get_current_target(CMD_CTX); + nrf91_setup_device_for_dfu(target); + + /* Arg1: dfu loader file. */ + const char *dfu_loader_path = CMD_ARGV[0]; + LOG_INFO("DFU loader: %s", dfu_loader_path); + struct image image; + image.base_address_set = false; + image.base_address = 0x0; + image.start_address_set = false; + + // Program the loader to the RAM + e = image_open(&image, dfu_loader_path, NULL); + for (size_t i = 0; i < image.num_sections; ++i) + nrf91_write_section_to_ram(target, &image, i, true); + + target_write_u32(target, NRF91_IPC_NS_BASE + 0x004, 1); + nrf91_wait_and_ack_events(target); + image_close(&image); + + /* The rest of the args: segment files. */ + int first_segment_arg_index = 1; + for (unsigned int i = first_segment_arg_index; i < CMD_ARGC; ++i) { + image.base_address_set = false; + image.base_address = 0x0; + image.start_address_set = false; + const char *segment_path = CMD_ARGV[i]; + + // Write and commit all the sections of each segment file + e = image_open(&image, segment_path, NULL); + for (size_t j = 0; j < image.num_sections; ++j) { + LOG_INFO("Writing section %d of segment %d", (unsigned int)(j + 1), (unsigned int)(i - 1)); + nrf91_write_section_to_ram(target, &image, j, false); + } + image_close(&image); + } + return e; +} static const struct command_registration nrf5_exec_command_handlers[] = { { @@ -1489,6 +1665,13 @@ static const struct command_registration nrf5_exec_command_handlers[] = { .help = "Erase all flash contents of the chip.", .usage = "", }, + { + .name = "nrf91_update_mfw", + .mode = COMMAND_EXEC, + .handler = nrf91_handle_update_modem_firmware, + .help = "Updates the modem firmware", + .usage = "nrf91_update_mfw loader_file segments..." + }, COMMAND_REGISTRATION_DONE }; diff --git a/src/target/target.c b/src/target/target.c index db424952dd..9d1d2f5507 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -49,8 +49,6 @@ #include "smp.h" #include "semihosting_common.h" -#include "src/target/image.h" - /* default halt wait timeout (ms) */ #define DEFAULT_HALT_TIMEOUT 5000 @@ -4663,181 +4661,6 @@ static int target_jim_write_memory(Jim_Interp *interp, int argc, return e; } -void setup_device_for_dfu(struct target *target) -{ - target_write_u32(target, 0x50039504, 0x01); - target_write_u32(target, 0x00FF801C, 0x0E); - target_write_u32(target, 0x00FF8020, 0x20); - target_write_u32(target, 0x50039504, 0x00); - - // configure IPC to be in non-secure mode - target_write_u32(target, 0x500038A8, 0x00000002); - - // configure IPC HW for DFU - target_write_u32(target, 0x4002A514, 0x00000002); - target_write_u32(target, 0x4002A51C, 0x00000008); - target_write_u32(target, 0x4002A610, 0x21000000); - target_write_u32(target, 0x4002A614, 0x00000000); - target_write_u32(target, 0x4002A590, 0x00000001); - target_write_u32(target, 0x4002A598, 0x00000004); - target_write_u32(target, 0x4002A5A0, 0x00000010); - - // configure RAM as non-secure - for (int i = 0; i < 32; ++i) - target_write_u32(target, 0x50003700 + i * 4, 0x00000007); - - // allocate memory in RAM - target_write_u32(target, 0x20000000, 0x80010000); - target_write_u32(target, 0x20000004, 0x2100000C); - target_write_u32(target, 0x20000008, 0x0003FC00); - - // reset the modem - target_write_u32(target, 0x50005610, 0); - target_write_u32(target, 0x50005614, 1); - target_write_u32(target, 0x50005610, 1); - target_write_u32(target, 0x50005614, 0); - target_write_u32(target, 0x50005610, 0); - - // wait until the modem is reset - sleep(2); - - // clear event registers before using - target_write_u32(target, 0x4002a100, 0); - target_write_u32(target, 0x4002a108, 0); - target_write_u32(target, 0x4002a110, 0); -} - -void wait_and_ack_events(struct target *target) -{ - bool fault = false; - uint32_t value = 0; - target_addr_t fault_event = 0x4002A100; - target_addr_t command_event = 0x4002A108; - target_addr_t data_event = 0x4002A110; - while (true) { - target_read_u32(target, fault_event, &value); - if (value != 0) { - fault = true; - break; - } - target_read_u32(target, command_event, &value); - if (value != 0) - break; - target_read_u32(target, data_event, &value); - if (value != 0) - break; - } - target_write_u32(target, fault_event, 0); - target_write_u32(target, command_event, 0); - target_write_u32(target, data_event, 0); - - uint32_t response = 0; - target_read_u32(target, 0x2000000C, &response); - if ((response & 0xff000000) == 0xa5000000) - LOG_DEBUG("ack"); - if ((response & 0xff000000) == 0x5a000000) - LOG_ERROR("nack\n"); - if (fault) - LOG_ERROR("fault\n"); -} - -int write_section_to_ram(Jim_Interp *interp, struct target *target, struct image *image, - size_t section_number, bool is_loader) -{ - int retval = ERROR_OK; - uint32_t count = image->sections[section_number].size; - target_addr_t address = image->sections[section_number].base_address; - target_addr_t chunk_write_address = 0x20000018; - const size_t buffersize = 0x10000; - uint8_t *buffer_addr = image->sections[section_number].private; - - while (count > 0) { - const unsigned int max_chunk_len = buffersize; - const size_t chunk_len = MIN(count, max_chunk_len); - count -= chunk_len; - - if (is_loader) - target_write_memory(target, address, 1, chunk_len, buffer_addr); - else - target_write_memory(target, chunk_write_address, 1, chunk_len, buffer_addr); - - if (retval != ERROR_OK) { - LOG_ERROR("write_memory: write at " TARGET_ADDR_FMT " with width=%u and count=%zu failed", - address, 8, chunk_len); - Jim_SetResultString(interp, "write_memory: failed to write memory", -1); - retval = JIM_ERR; - break; - } - if (!is_loader) { - target_write_u32(target, 0x20000010, address); - target_write_u32(target, 0x20000014, chunk_len); - target_write_u32(target, 0x2000000C, 0x3); - target_write_u32(target, 0x4002a004, 1); - wait_and_ack_events(target); - } - - address += chunk_len; - buffer_addr += chunk_len; - } - return retval; -} - -static int target_jim_nrf91_update_modem_firmware(Jim_Interp *interp, int argc, - Jim_Obj * const *argv) -{ - /* - * argv[1] = dfu loader file (.ihex) - * argv[2:] = segment files (.hex) - */ - - int e = 0; - - if (argc < 3) { - Jim_WrongNumArgs(interp, 1, argv, "dfu_loader segments..."); - return JIM_ERR; - } - - struct command_context *cmd_ctx = current_command_context(interp); - assert(cmd_ctx); - struct target *target = get_current_target(cmd_ctx); - setup_device_for_dfu(target); - - /* Arg1: dfu loader file. */ - const char *dfu_loader_path = Jim_String(argv[1]); - LOG_INFO("DFU loader: %s", dfu_loader_path); - struct image image; - image.base_address_set = false; - image.base_address = 0x0; - image.start_address_set = false; - - // Program the loader to the RAM - e = image_open(&image, dfu_loader_path, NULL); - for (size_t i = 0; i < image.num_sections; ++i) - write_section_to_ram(interp, target, &image, i, true); - - target_write_u32(target, 0x4002a004, 1); - wait_and_ack_events(target); - image_close(&image); - - /* The rest of the args: segment files. */ - int first_segment_arg_index = 2; - for (int i = first_segment_arg_index; i < argc; ++i) { - image.base_address_set = false; - image.base_address = 0x0; - image.start_address_set = false; - const char *segment_path = Jim_String(argv[i]); - - // Write and commit all the sections of each segment file - e = image_open(&image, segment_path, NULL); - for (size_t j = 0; j < image.num_sections; ++j) { - LOG_INFO("Writing section %d of segment %d", (unsigned int)(j + 1), (unsigned int)(i - 1)); - write_section_to_ram(interp, target, &image, j, false); - } - image_close(&image); - } - return e; -} - /* FIX? should we propagate errors here rather than printing them * and continuing? */ @@ -5786,13 +5609,6 @@ static const struct command_registration target_instance_command_handlers[] = { .help = "Write Tcl list of 8/16/32/64 bit numbers to target memory", .usage = "address width data ['phys']", }, - { - .name = "nrf91_update_mfw", - .mode = COMMAND_EXEC, - .jim_handler = target_jim_nrf91_update_modem_firmware, - .help = "Updates the modem firmware", - .usage = "nrf91_update_mfw loader_file segments..." - }, { .name = "eventlist", .handler = handle_target_event_list, @@ -6928,13 +6744,6 @@ static const struct command_registration target_exec_command_handlers[] = { .help = "Write Tcl list of 8/16/32/64 bit numbers to target memory", .usage = "address width data ['phys']", }, - { - .name = "nrf91_update_mfw", - .mode = COMMAND_EXEC, - .jim_handler = target_jim_nrf91_update_modem_firmware, - .help = "Updates the modem firmware", - .usage = "nrf91_update_mfw loader_file segments..." - }, { .name = "debug_reason", .mode = COMMAND_EXEC, --