Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ if (${LA9310_BOOT_MODE} STREQUAL "pcie")
# "drivers/misc/bbdev_ipc.c"
"drivers/pcie/la9310_pcie.c"
"utils/task_stats.c"
"fwloader.c"
)
elseif(${LA9310_BOOT_MODE} STREQUAL "i2c")
target_compile_definitions(la9310 PUBLIC "-DTURN_ON_STANDALONE_MODE")
Expand Down
105 changes: 105 additions & 0 deletions src/fwloader.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#include "FreeRTOS.h"
#include <semphr.h>
#include "core_cm4.h"

#include "immap.h"
#include "log.h"
#include "immap.h"
#include "fwloader.h"
#include <string.h>
#include "la9310_host_if.h"
#include "la9310_info.h"

extern struct la9310_info g_la9310_info;

void prepare_fwloader()
{
volatile struct header *boot_header;
struct la9310_hif * pxHif = g_la9310_info.pHif;
volatile struct la9310_sw_cmd_desc * pxCmdDesc = &( pxHif->sw_cmd_desc );
extern uintptr_t __FWL_DEST_ADDR__;
extern uintptr_t __FWL_LOAD_ADDR__;
extern uintptr_t __FWL_LOAD_END__;

// Shut down FreeRTOS
log_info("Shutdown FreeRTOS\n");
disable_irq();

// We still have memset, so let's clear the scratch buffer
log_info("Clear Header from Scratchbuffer... ");
boot_header = (struct header *) g_la9310_info.dtcm_addr;
memset((void *) boot_header, 0, sizeof(struct header));
boot_header->preamble = 0xc001c0de;
log_info("Done!\n");

// Copy bootloader code to its destination
uint8_t *src = (uint8_t *) &__FWL_LOAD_ADDR__;
uint8_t *dst = (uint8_t *) &__FWL_DEST_ADDR__;
uint32_t size = ((void *) &__FWL_LOAD_END__) - ((void *) &__FWL_LOAD_ADDR__);
log_info("Copy %d bytes firmware from %p to %p loading code to end of RAM... ", size, src, dst);
memcpy(dst, src, size);
log_info("Done!\n");

// Tell the host we are ready for firmware reloading
pxCmdDesc->status = LA9310_SW_CMD_STATUS_DONE;
dmb();

log_info("Ready for reloading the firmware...\n\r");

// Wait for a firmware image
while (boot_header->preamble != PREAMBLE)
dmb();

log_info("Received new firmware image!\n\r");
}



void fwloader(void) __attribute__((section(".fwloader")));
void fwloader()
{
volatile struct header *boot_header;
__attribute__((__noreturn__)) void (*jump_bl_entry)(void) = NULL;
unsigned int pc_value;

__asm__ volatile (
"mov %0, pc" // Der Befehl speichert den Wert des PC in der Variablen pc_value
: "=r" (pc_value) // Output Operand
);

log_info("I am in the upper RAM part now: 0x%08x\n", pc_value);

// We still have memset, so let's clear the scratch buffer
boot_header = (struct header *) g_la9310_info.dtcm_addr;

// The image is there, let's load it
dmb();
uint32_t src_offset = boot_header->bl_src_offset;
uint32_t dst_addr = boot_header->bl_dest;
uint32_t size = boot_header->bl_size;

log_info("boot_header->bl_src_offset: 0x%08x\n", src_offset);
log_info("boot_header->bl_dest: 0x%08x\n", dst_addr);
log_info("boot_header->bl_size: 0x%08x\n", size);
log_info("boot_header->bl_entry: 0x%08x\n", boot_header->bl_entry);

// As we most likely will overwrite memcpy we have to do it manually
uint32_t *dst = (uint32_t *) dst_addr;
uint32_t *src = (uint32_t *) (src_offset + g_la9310_info.pcie_obound);

log_info("Copy from 0x%p to 0x%p\n", src, dst);

for (uint32_t copied = 0; copied < size; copied += 4)
{
*dst++ = *src++;
}

boot_header->preamble = 0xaffed00f;

jump_bl_entry = (void *)(boot_header->bl_entry | M4_THUMB_BIT);

jump_bl_entry();

// Control should never reach here
while (1);
}
26 changes: 26 additions & 0 deletions src/fwloader.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#ifndef FWLOADER_H_
#define FWLOADER_H_

#include <stdint.h>

#define M4_THUMB_BIT 0x1 /* M4 Thumb bit */

/* Boot header structure */
struct header {
#define PREAMBLE 0xaa55aa55
uint32_t preamble;
uint32_t plugin_size;
uint32_t plugin_offset;
uint32_t bl_size;
uint32_t bl_src_offset;
uint32_t bl_dest;
uint32_t bl_entry;
#define PCIE_EDMA_DIS_MASK 0x00000001
#define RESET_HS_DIS_MASK 0x00010000
uint32_t flags;
};

void prepare_fwloader();
void fwloader();

#endif
15 changes: 15 additions & 0 deletions src/limesdr_micro/limesdr_commands.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "lms7002m/spi.h"

#include "eeprom.h"
#include "fwloader.h"

static uint16_t xo_dac_value = 0;

Expand Down Expand Up @@ -475,6 +476,20 @@ static void vSwCmdTask( void * pvParameters )
status = LA9310_SW_CMD_STATUS_DONE;
break;
}
case 5: { // Enter firmware reloading mode
prepare_fwloader();
fwloader();
break;
}
case 6: { // Signalize firmware is alive
uint32_t pattern = pxCmdDesc->data[0];
pxCmdDesc->status = LA9310_SW_CMD_STATUS_IN_PROGRESS;
pxCmdDesc->data[0] = ~pattern;
status = LA9310_SW_CMD_STATUS_DONE;
log_info("Alive Pattern - changed 0x%08x to 0x%08x\n", pattern, ~pattern);

break;
}
default:
log_err( "sw cmd not implemented: %d\r\n", pxCmdDesc->cmd );
status = LA9310_SW_CMD_STATUS_ERROR;
Expand Down
12 changes: 11 additions & 1 deletion src/platform/ARM_CM4/la9310_host_pcie_mode.ld
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ HEAP_SIZE = 0x200;

MEMORY
{
m_tcml (RWX) : ORIGIN = 0x1F800000, LENGTH = 0x0001B000
m_tcml (RWX) : ORIGIN = 0x1F800000, LENGTH = 0x0001A000
m_tcml_bl (RWX) : ORIGIN = 0x1F81A000, LENGTH = 0x00001000
m_dtcm (RW) : ORIGIN = 0x20000000, LENGTH = 0x0000F000
br_data (R) : ORIGIN = 0x2000F000, LENGTH = 0x00001000
}
Expand Down Expand Up @@ -176,6 +177,15 @@ SECTIONS
__END_BSS = .;
} > m_tcml

.fwloader :
{
__FWL_DEST_ADDR__ = .;
KEEP(*.o(.text.*fwloader*))
} > m_tcml_bl AT > m_tcml

__FWL_LOAD_ADDR__ = LOADADDR(.fwloader );
__FWL_LOAD_END__ = __FWL_LOAD_ADDR__ + SIZEOF(.fwloader );

.heap :
{
. = ALIGN(8);
Expand Down