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/+/8486

-- gerrit

commit d1003cea6ed37402fc777320904fe23f26565895
Author: tigransukiasyan <tigran.sukias...@taurotech.com>
Date:   Thu Sep 12 05:43:50 2024 -0700

    target: add new command for nrf91
    
    add command nrf91_update_mfw to update nRF91 modem firmware
    the usage of the command is as follows:
      nrf91_update_mfw <loader_file> <segment_files> ...
    the target needs to be reset-halted before this command
    
    Change-Id: I6814682250736cfbcea94eac35bc197561b8721e
    Signed-off-by: tigransukiasyan <tigran.sukias...@taurotech.com>

diff --git a/src/target/target.c b/src/target/target.c
index 9d1d2f5507..db424952dd 100644
--- a/src/target/target.c
+++ b/src/target/target.c
@@ -49,6 +49,8 @@
 #include "smp.h"
 #include "semihosting_common.h"
 
+#include "src/target/image.h"
+
 /* default halt wait timeout (ms) */
 #define DEFAULT_HALT_TIMEOUT 5000
 
@@ -4661,6 +4663,181 @@ 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?
  */
@@ -5609,6 +5786,13 @@ 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,
@@ -6744,6 +6928,13 @@ 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,

-- 

Reply via email to