wang liu

imx-m4fwloader issue on the imx8m mini board(New)

Discussion created by wang liu on May 18, 2019
Latest reply on May 21, 2019 by Wigros Sun

Hi,

I want to port imx-m4fwloader to support imx8m mini board, but I have some issues.

The imx-m4fwloader is downloaded from GitHub - NXPmicro/imx-m4fwloader: Tool for loading firmware to M4 core on i.MX6SX and 7D ,and I modify it to adapt imx8m mini board.

The modified code m4fwloader.c is below:

 

 

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <fcntl.h>
#include <ctype.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <stdint.h>


#define LogVerbose(...) \
   do { \
      if (verbose) \
         printf(__VA_ARGS__); \
     } while (0)
#define LogError(...) printf(__VA_ARGS__)


#define MAP_SIZE 4096UL
#define MAP_MASK (MAP_SIZE - 1)
#define MAP_OCRAM_SIZE 64 * 1024
#define MAP_OCRAM_MASK (MAP_OCRAM_SIZE - 1)
#define MAX_FILE_SIZE MAP_OCRAM_SIZE


static int fd;
static int verbose = 1;

void regshow(uint32_t addr, char* name)
{
      off_t target;
      void *map_base, *virt_addr;

      target = (off_t)addr;
      map_base = mmap(0, MAP_SIZE, PROT_READ, MAP_SHARED, fd, target & ~MAP_MASK);
      virt_addr = (unsigned char*)(map_base + (target & MAP_MASK));
      LogVerbose("%s (0x%08X): 0x%08X\r\n", name, addr, *((uint32_t*)virt_addr));
      munmap(map_base, MAP_SIZE);
}

 

void stop_cpu(void)
{
uint32_t reg = 0x3039000C;
uint32_t read_result;
void *map_base, *virt_addr;

regshow(reg, "STOP - before");
map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, reg & ~MAP_MASK);
virt_addr = (unsigned char*)(map_base + (reg & MAP_MASK));
read_result = *((uint32_t*)virt_addr);
*((uint32_t*)virt_addr) = (read_result & (~(1 << 3)));
munmap(virt_addr, MAP_SIZE);
regshow(reg, "STOP - after");
}


void start_cpu(void)
{
uint32_t reg = 0x3039000C;
uint32_t read_result;
void *map_base, *virt_addr;

regshow(reg, "STOP - before");
map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, reg & ~MAP_MASK);
virt_addr = (unsigned char*)(map_base + (reg & MAP_MASK));
read_result = *((uint32_t*)virt_addr);
*((uint32_t*)virt_addr) = (read_result | (1 << 3)|(1<<0));

read_result = *((uint32_t*)virt_addr);
*((uint32_t*)virt_addr) = (read_result & (~(1 << 0)));

munmap(virt_addr, MAP_SIZE);
regshow(reg, "STOP - after");
}

 

void set_stack_pc(uint32_t stack, uint32_t pc)
{
off_t target = (off_t)0x007E0000;//M4 boot ROM: OCRAM_S(0x00180000) or TCML(0x007E0000)
void *map_base, *virt_addr;

map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, target & ~MAP_MASK);

virt_addr = (unsigned char*)(map_base + (target & MAP_MASK));
*((uint32_t*)virt_addr) = stack;

virt_addr = (unsigned char*)(map_base + ((target + 0x4) & MAP_MASK));
*((uint32_t*)virt_addr) = pc;

munmap(map_base, MAP_SIZE);
}

 

uint32_t align(uint32_t n, uint32_t align)
{
      return (n + (align - 1)) & (~(align - 1));
}

 

void load_m4_fw(char* filepath, uint32_t loadaddr)
{
uint32_t size, size_8;
FILE* fdf;
char* filebuffer;
void *map_base, *virt_addr;
uint32_t stack, pc;

fdf = fopen(filepath, "rb");
fseek(fdf, 0, SEEK_END);
size = ftell(fdf);
fseek(fdf, 0, SEEK_SET);
if (size > MAX_FILE_SIZE) {
LogError("File size too big, can't load: %d > %d \n",size, MAX_FILE_SIZE);
return;
}

 

printf("size = %d\n",size);
size_8 = align(size, 8);
printf("size_8 = %d\n",size_8);

filebuffer = (char*)malloc(size_8+1);
if (size != fread(filebuffer, sizeof(char), size, fdf)) {
free(filebuffer);
return;
}
fclose(fdf);

stack = (filebuffer[0] | (filebuffer[1] << 8) | (filebuffer[2] << 16) | (filebuffer[3] << 24));
pc = (filebuffer[4] | (filebuffer[5] << 8) | (filebuffer[6] << 16) | (filebuffer[7] << 24));

if (loadaddr == 0x0) {
loadaddr = pc & 0xFFFF0000; /* Align */
}

LogVerbose("FILENAME = %s; loadaddr = 0x%08x\n",filepath, loadaddr);

map_base = mmap(0, MAP_OCRAM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, loadaddr & ~MAP_OCRAM_MASK);
virt_addr = (unsigned char*)(map_base + (loadaddr & MAP_OCRAM_MASK));
memcpy(virt_addr, filebuffer, size_8);
munmap(map_base, MAP_OCRAM_SIZE);

LogVerbose("Will set PC and STACK...");
set_stack_pc(stack, pc);

LogVerbose("...Done\n");
free(filebuffer);
}

 

int main(int argc, char** argv)
{
int n;
uint32_t loadaddr;
char* p;
char* filepath = argv[1];

if (argc < 2) {
LogError("Usage:\n"
"%s [filename.bin] [0xLOADADDR] # loads new firmware\n"
"or: %s stop # holds the auxiliary core in reset\n"
"or: %s start # releases the auxiliary core from reset\n"
"or: %s kick [n] # triggers interrupt on RPMsg virtqueue n\n",
argv[0], argv[0], argv[0], argv[0], argv[0]);
return 0;
}

fd = open("/dev/mem", O_RDWR | O_SYNC);
if (fd < 0) {
LogError("Could not open /dev/mem, are you root?\n");
return 0;
}

if (!strcmp(argv[1], "stop")) {
stop_cpu();
return 0;
}
else if (!strcmp(argv[1], "start")) {
start_cpu();
return 0;
}

if (access(filepath, F_OK) == -1) {
LogError("File %s not found.\n", argv[1]);
return 0;
}

loadaddr = strtoul(argv[2], &p, 16);
LogVerbose("LoadAddr is: %X\n", loadaddr);

LogVerbose("Will stop CPU now...\n");
stop_cpu();

LogVerbose("Will load M4 firmware...\n");
load_m4_fw(filepath, loadaddr);

LogVerbose("Will start CPU now...\n");
start_cpu();

LogVerbose("Done!\n");
close(fd);

return 0;
}

 

Then I compile and execute it in the shell:

root@imx8mmevk:~#
root@imx8mmevk:~#
root@imx8mmevk:~# ls
cmsis_ecspi_int_loopback_transfer.bin hello_world.bin
root@imx8mmevk:~#
root@imx8mmevk:~# m4fwloader /home/root/cmsis_ecspi_int_loopback_transfer.bin 0x7e0000 --verbose
LoadAddr is: 7E0000
Will stop CPU now...
STOP - before (0x3039000C): 0x000000AB
STOP - after (0x3039000C): 0x000000A3
Will load M4 firmware...
size = 21948
size_8 = 21952

 

It hangs on and the shell is died. No debug message outputs.

There is no way to bring up the board except reboot.

Can you help me fix this?

Outcomes