2024-09-08 04:19 PM
Hi I am using Stm32L0 series board to create a custom external loader. I am using cubeIDE (version: 1.16.0)
I am using winboard W25Q64 chip. I wrote a driver using online driver and interfaced it with my board using standard SPI2. I can read /write data on this external flash without any issue.
I tried to create the external loader, initially I was getting "Error Parsing Fail" issue but then I added some padding bytes to my struct which resolved the problem. Now I can create the external loader and I can use it to read data from address 0x0 using cubeProgrammer. I can read roughly 8192 bytes from starting address 0x0.
However I cant write data into the memory using external loader. One thing to note that cubeProgrammer is not showing my memory size and my memory type is also appearing as unknown:
This is my structure and its initialisation.
#define SECTOR_NUM 10 // Max Number of Sector types
struct DeviceSectors {
unsigned long SectorNum; // Number of Sectors
unsigned long SectorSize; // Sector Size in Bytes
};
struct StorageInfo {
char DeviceName[50]; // Device Name and Description (reduced to fit)
unsigned short DeviceType; // Device Type: ONCHIP, EXT8BIT, EXT16BIT, ...
unsigned long DeviceStartAddress; // Default Device Start Address
unsigned long DeviceSize; // Total Size of Device
unsigned long PageSize; // Programming Page Size
unsigned char EraseValue; // Content of Erased Memory
unsigned char reserved[3]; // Reserved for alignment
struct DeviceSectors sectors[SECTOR_NUM]; // Sectors
unsigned long padding[13]; // Padding
};
Please have a look on my Dev_Inf.c file:
#include "Dev_Inf.h"
#include "main.h"
#if defined (__ICCARM__)
__root const struct StorageInfo StorageInfo = {
#else
const struct StorageInfo const StorageInfo =
{
#endif
"W25Q64_STM32L073_SPI2", // Device Name
7,
0x90000000,
0x00800000,
0x0100,
0xFF,
{0},
2048, 0x1000,
0x0000, 0x0000,
{0}
};
I have tried different boards and also different version of cubeProgrammer (2.17.0 as well as 2.14.0) but this problem is not going away. For some reason cubeProgammer is not able to retrieve the correct information about my page size, my memory type, memory size and also start address.
I am new to external loader world. Any help will be appreciated. Please also see my attached linker filer for your reference:
ENTRY(Init)
/* Generate 2 segment for Loader code and device info */
PHDRS {Loader PT_LOAD ; SgInfo PT_LOAD ; }
/* Highest address of the user mode stack */
_estack = ORIGIN(RAM_LOADER) + LENGTH(RAM_LOADER); /* end of RAM */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x200; /* required amount of heap */
_Min_Stack_Size = 0x400; /* required amount of stack */
/* Specify the memory areas */
MEMORY
{
RAM_LOADER (xrw) : ORIGIN = 0x20000004, LENGTH = 20K
}
/* Define output sections */
SECTIONS
{
/* The startup code goes first into FLASH */
.isr_vector :
{
. = . + 0x1FC;
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} >RAM_LOADER :Loader
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >RAM_LOADER
.ARM : {
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} >RAM_LOADER :Loader
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array*))
PROVIDE_HIDDEN (__preinit_array_end = .);
} >RAM_LOADER :Loader
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array*))
PROVIDE_HIDDEN (__init_array_end = .);
} >RAM_LOADER :Loader
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT(.fini_array.*)))
KEEP (*(.fini_array*))
PROVIDE_HIDDEN (__fini_array_end = .);
} >RAM_LOADER :Loader
/* used by the startup to initialize data */
_sidata = LOADADDR(.data);
/* Initialized data sections goes into RAM, load LMA copy after code */
.data :
{
. = ALIGN(4);
_sdata = .; /* create a global symbol at data start */
*(.data) /* .data sections */
*(.data*) /* .data* sections */
. = ALIGN(4);
_edata = .; /* define a global symbol at data end */
} >RAM_LOADER :Loader
/* Uninitialized data section */
. = ALIGN(4);
.bss :
{
/* This is used by the startup in order to initialize the .bss secion */
_sbss = .; /* define a global symbol at bss start */
__bss_start__ = _sbss;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .; /* define a global symbol at bss end */
__bss_end__ = _ebss;
} >RAM_LOADER :Loader
/* The program code and other data goes into FLASH */
.text :
{
. = ALIGN(4);
*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
*(.glue_7) /* glue arm to thumb code */
*(.glue_7t) /* glue thumb to arm code */
*(.eh_frame)
KEEP (*Loader_Src.o ( .text* ))
KEEP (*(.init))
KEEP (*(.fini))
. = ALIGN(4);
_etext = .; /* define a global symbols at end of code */
} >RAM_LOADER :Loader
.Dev_info :
{
KEEP(*Dev_Inf.o ( .rodata* ))
} :SgInfo
/* Constant data goes into FLASH */
.rodata :
{
. = ALIGN(4);
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
. = ALIGN(4);
} >RAM_LOADER :Loader
/* User_heap_stack section, used to check that there is enough RAM left */
._user_heap_stack :
{
. = ALIGN(4);
PROVIDE ( end = . );
PROVIDE ( _end = . );
. = . + _Min_Heap_Size;
. = . + _Min_Stack_Size;
. = ALIGN(4);
} >RAM_LOADER :Loader
/* Remove information from the compiler libraries */
/DISCARD/ :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}
.ARM.attributes 0 : { *(.ARM.attributes) }
}
Please let me know if you guys need any further info.
Thanks in advance,
Zain