32F417 / 32F437 auto detect of extra 64k RAM - Page 1
Forum section: electronics / general

author: peter-h
author_rank: Super Contributor
timestamp: June 28, 2023, 04:05:56 pm
content: I have all this working, and tweaked things like _sbrk()Code:// This is used by malloc().// The original Newlib version of this, on which the ST code was based// https://github.com/zephyrproject-rtos/zephyr/blob/main/lib/libc/newlib/libc-hooks.c// allowed the heap to go all the way up to the current SP value, which is stupid.// This one sets the limit at the base (lowest memory address) of the stack area.// Also see init_heap() in main.c.caddr_t _sbrk(int incr){// These two are defined in the linkfile but _top is varied according to g_dev_idextern char end asm("_end");// end of BSSextern char top asm("_top");// base of the general stackextern uint32_t g_dev_id;int extra_ram = 0;if (g_dev_id == 437){extra_ram += (64 * 1024);}static char *heap_end;// this gets initialised to NULL by C conventionchar *prev_heap_end;// this gets initialised on 1st call here// This sets heap_end to end of BSS, on the first call to _sbrkif (heap_end == NULL)heap_end = &end;prev_heap_end = heap_end;// top = top of RAM minus size of stackif ( (heap_end + incr) > (&top + extra_ram) ){errno = ENOMEM;// not apparently used by anythingprev_heap_end = (char*) -1;}else{heap_end += incr;}//debug_thread_printf("malloc sbrk, incr=%d, ret=%08x",(int)incr, (int) prev_heap_end);return (caddr_t) prev_heap_end;}whereCode:// Get device ID and set up global ID valueif ( HAL_GetDEVID() == 0x413 )g_dev_id=417;if ( HAL_GetDEVID() == 0x419 )g_dev_id=437;but there is a problem: I cannot do e.g.uint8_t fred[63*1024];i.e. a static global variable cannot access the extra 64 because the linkfile still contains the 32F417 memory mappingCode:MEMORY{FLASH_BOOT (rx) : ORIGIN = 0x08000000, LENGTH = 32KFLASH_APP (rx) : ORIGIN = 0x08008000, LENGTH = 1024K-32KRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128KRAM_L (xrw) : ORIGIN = 0x2001f000, LENGTH = 4KCCMRAM (rw) : ORIGIN = 0x10000000, LENGTH = 64K}i.e. I would need to also change LENGTH = 128K to LENGTH = 192K. The error comes from the linker.The obvious hack is to have LENGTH =192Kin the linkfileanywaybut then the Build Analyser will be misleading if the CPU is a 417. No way around this, I guessI just wonder how others have done it.I really do not want to have two Cube IDE projects or different builds. And changing the CPU type in Cube (one needs to do it in more than one place, and that is just the ones I know about!) is a can of worms which would need a massive amount of regression testing.It is of course obvious that the Cube Build Analyser won't know the CPU typeThe 32F437 is believed by experts to be an exact superset of the 32F417, with just one exception: the Vbat measurement using ADC1 (/4 or /2 resistor divider) and FWIW I have verified this over years of development work (I have both CPUs in various boards).

author: DavidAlfa
author_rank: Super Contributor
timestamp: June 28, 2023, 05:11:25 pm
content: Why don't simply make a 417/407 firmware?You'll have to program them anyways!

author: SiliconWizard
author_rank: Super Contributor
timestamp: June 28, 2023, 07:09:36 pm
content: I would personally write a linker script which defines the base common RAM area (and associate all 'common' data sections to it), and define a separate RAM area for the extra 64KB, and define a dedicated section for it.Then whatever data in C that you define that must be in this extra 64KB will have to be declared using a section attribute.I suppose you may have wanted something more "transparent", but I don't really see how you can do this safely.

author: thm_w
author_rank: Super Contributor
timestamp: June 28, 2023, 10:28:15 pm
content: Quote from: DavidAlfa on June 28, 2023, 05:11:25 pmYeah, although I assume this can be done under the same project, eg have a "407 release" and a "417 release", with build flags selecting which linker script to use.

author: nctnico
author_rank: Super Contributor
timestamp: June 28, 2023, 10:32:52 pm
content: I'd put the heap into the extra memory and allow to allocate more memory if there is more ram. Put all static allocations that are fixed regardless of memory size in the memory size that is common. If there needs to be a 'static' array with a size that changes according to the amount of memory, then it should be allocated from the heap at the start and never released.

author: peter-h
author_rank: Super Contributor
timestamp: June 29, 2023, 05:51:19 am
content: QuoteNo need to change Cube to program a 417 or 437It's a good Q why this works but it does. It does show the CPU type during the firmware load via SWD.QuoteWhere would the build flags be set? Cube IDE has a fantastic amount of config options, which I totally want to avoid changing. Thereisa way to formally set the CPU type also, and I've documented this in the project design doc, but it seems to be necessary in several places.QuoteThat's clever, especially as the main driver of needing more RAM is TLS which gets a 48k block (within which it runs its private heap). But I actually have a working product with TLS and with the 417; it just has only about 10k free RAM.My current code looks like this. I fill in a global variable with 417 or 437 (decimal) based on the CPU ID (0x413 or 0x419) and if it is a 437 I move certain operations (in this case filling the stack area with "S" - there are actually very few such operations) higher up by 64k. The syntax for picking up symbol values from the linkfile into C is bizzare but it is what is widely usedCode:// Get CPU type into B_g_dev_idif ( B_HAL_GetDEVID() == 0x413 )B_g_dev_id=417;if ( B_HAL_GetDEVID() == 0x419 )B_g_dev_id=437;// Fill stack with "S". This used to be in the startup .s code.// We do it here because it is easier to grab the CPU ID in C code (above)// We are filling the stack area but the stack is used to call B_memset :)// So we just reduce the filled length by 64 bytes. Only about 20 is needed.// The syntax needed to pick up the symbols is weird; also used in _sbrk().extern char _top;char* stack_base;// base of stack (from linkfile)stack_base = &_top;extern char _Stack_Size;// size of stack (from linkfile)char* stack_size;stack_size = &_Stack_Size;if (B_g_dev_id==437){stack_base += (64*1024);// 32F437 has stack 64k higher up}B_memset((char*)stack_base,'S',(int)stack_size-64);What would be helpful would be a prominent build-time warning if the yellow value belowfalls below 64k. I have no idea how to do that. It would say something like "WARNING: RAM usage needs a 32F437".It needs to come from the linkfile, and is all this lotCode:/* Initialized data sections for rest of the unit. These go into RAM, load LMA copy after code *//* This stuff is copied from FLASH to RAM by C code in the main stub */.all_nonboot_data :{. = ALIGN(4);_s_nonboot_data = .;/* create a global symbol at data start */*(.data .data*)/* .data sections */. = ALIGN(4);_e_nonboot_data = .;/* define a global symbol at data end */} >RAM AT >FLASH_APP/* used by the main stub C code to initialize data */_si_nonboot_data = LOADADDR(.all_nonboot_data);/* Uninitialized data section for rest of unit *//* This stuff is zeroed by C code in the main stub */. = ALIGN(4);.all_nonboot_bss :{_s_nonboot_bss = .;/* define a global symbol at bss start */*(.bss .bss* .COMMON .common .common*). = ALIGN(4);_e_nonboot_bss = .;/* define a global symbol at bss end */} >RAM

author: thm_w
author_rank: Super Contributor
timestamp: June 29, 2023, 09:39:14 pm
content: Quote from: peter-h on June 29, 2023, 05:51:19 amI don't use cube but it should be a standard feature in any IDE to have multiple build configurations.Seems shown on page 61 here:https://www.st.com/resource/en/user_manual/um2609-stm32cubeide-user-guide-stmicroelectronics.pdf-T "STM32F401RETX_FLASH.ld"

author: peter-h
author_rank: Super Contributor
timestamp: June 29, 2023, 10:03:51 pm
content: I have a strange problem.It is OK to have the 1st vector in the VTOR vector table pointing to an initial stack value of ram base + 128k (0x20020000), but having SP itself pointing to ram base + 192k (0x20030000), at the point when interrupts are initially set up and enabled?Code:Vectors2:.word _estack // 0x20020000.word main.word NMI_Handler.word HardFault_Handler.word MemManage_HandleretcIOW, does the 32F4 interrupt system read that first vector table value for some purpose?I know FreeRTOS bloody well does read it, hence the "adds" instruction thereCode:static void prvPortStartFirstTask( void ){/* Start the first task. This also clears the bit that indicates the FPU isin use in case the FPU was used before the scheduler was started - whichwould otherwise result in the unnecessary leaving of space in the SVC stackfor lazy saving of FPU registers. */extern uint32_t g_dev_id;if (g_dev_id==437){__asm volatile(" ldr r0, =0xE000ED08\n" /* Use the NVIC offset register to locate the stack. */" ldr r0, \n"" ldr r0, \n"" adds r0, #65536\n" // adjust for stack being 64k higher up" msr msp, r0\n" /* Set the msp back to the start of the stack. */" mov r0, #0\n" /* Clear the bit that indicates the FPU is in use, see comment above. */" msr control, r0\n"" cpsie i\n" /* Globally enable interrupts. */" cpsie f\n"" dsb\n"" isb\n"" svc 0\n" /* System call to start first task. */" nop\n");The code is bombing in quite a drastic wayMy vector table is in FLASH because that is safer, but if this was some huge problem it could be in RAM and then I can have the right value actually in the table.

author: nctnico
author_rank: Super Contributor
timestamp: June 29, 2023, 10:08:21 pm
content: Quote from: thm_w on June 29, 2023, 09:39:14 pmCubeIDE aka Eclipse supports multiple build configurations just fine. It is the stuff that ST has bolted on that loses track if you are going to target different microcontrollers. But then again, for any serious work you'll want to avoid relying on what ST has bolted onto Eclipse.

author: Siwastaja
author_rank: Super Contributor
timestamp: June 30, 2023, 05:40:32 am
content: Quote from: peter-h on June 29, 2023, 10:03:51 pmAFAIK, no. The first two entries are read out just for SP and PC initialization after actual chip reset signal (power up reset or software reset through NVIC_SystemReset())

author: peter-h
author_rank: Super Contributor
timestamp: June 30, 2023, 08:26:21 am
content: QuoteSure, but I really want a single firmware to support boards with a 417 or a 437. There are huge production, support, maintenance, etc advantages.

author: Siwastaja
author_rank: Super Contributor
timestamp: June 30, 2023, 08:40:39 am
content: Stupid question: what kind of application benefits from more RAM? Unlike desktop computing where you might benefit from being able to open more Firefox tabs with more RAM, or make Photoshop faster by reducing disk swapping, usually microcontroller projects have fixed functional constraints, i.e., you need to do X, Y and Z. If the smaller RAM is enough to do that, why would you need to do anything different on the larger part? Just leave excess address space unused. Like, you don'tneedto initialize stack pointer with theendof RAM.And, if you end up adding feature Å only on larger RAM parts, easiest way to do that is to add another section after the stack and put large static buffers etc. used by feature Å there. No need to do anything compile-time - use the larger RAM in linker script and let the compiler place that section on address space that is illegal on the smaller part. As the feature is turned off, those variables are never accessed and everything's fine.

author: hans
author_rank: Super Contributor
timestamp: June 30, 2023, 09:27:32 am
content: Quote from: peter-h on June 29, 2023, 05:51:19 amThat should not be a warning but an error.The worst thing is to detect a fault, but not tell it's severity to a programmer. Memory stack issues can lead to strange cases. I once had to debug a bootloader + application issue with a colleague. We spent the best part of 1-2 weeks on tracing it down. When the application stack(s) grew too much, the application would crash. Turns out we had some mess going on with stack pointers in our bootloader.I agree with Siwastaja. Stacks can be put at any arbitrary location, as FreeRTOS will do, but by default the stack of main() is at the "end of RAM" (that it knows about). I read that you're using a heap, which is commonly not best practice on embedded because of fragmentation issues if its constantly used for reallocations. More memory would alleviate some memory pressure of the heap, but if that is necessary due to instable software, then that is bad design.Ideally on embedded you allocate all buffers statically. If you know the processor at compiletime, perhaps you could resize some buffers to handle bigger bursts if that is a necessary wish. But other than that I don't really see the point.

author: peter-h
author_rank: Super Contributor
timestamp: June 30, 2023, 11:57:06 am
content: QuoteHard to explain without describing the product but to a large extent I am right now doing work which will be a helluva lot easier to do now than if somebody wants it in a year's time when I've forgotten half the stuff.I can tell you I have enough RAM on the 417 (about 55k spare) unless somebody invokes TLS which mallocs a 48k block... There is a possible graphic LCD applicatio; biggest LCD with SPI is not that big but big enough, and graphics libs like RAM.But right now I have broken this box comprehensively. I suspect the linkfile syntax does not allow /* comments */ in some placesI am seeing the CPU vanishing into hyperspace, but the binary seems ok byte for byte. Completely weird.QuoteAbsolutely!QuoteI am using the 64k CCM for FreeRTOS stacks, so that bit is isolated. But FR still picks up the _estack word from the vector table, for reasons too convoluted for my pay grade. But I handle that bit too, now, adding 64k to the value retrieved.The heap is only for TLS (see above) and it is organised so it can never fragment (the block is freed when the TLS session ends, etc. This has been tested over a couple of years. I hate heap stuff too but sometimes it is right for optional features, and in e.g. 55k it is impossible to fragment with a 48k malloc. One could statically alloc that 48k, sure, but you waste 48k if TLS is not used.I see a lot of value in production in a single firmware edition, covering multiple product variants. For example I have ARINC429 as an expensive factory option, and the chip is auto detected at startup, and an RTOS task for it is started.

author: peter-h
author_rank: Super Contributor
timestamp: June 30, 2023, 07:19:37 pm
content: QuoteDoes msp come into any of this? FreeRTOS uses it, but the preceeding code doesn't appear to set it.

author: tellurium
author_rank: Frequent Contributor
timestamp: July 02, 2023, 10:43:52 pm
content: FreeRTOS provides several different malloc implementations.One of them is heap5.c, which can use several non-adjacent memory blocks.https://www.freertos.org/a00111.html#heap_5

author: peter-h
author_rank: Super Contributor
timestamp: July 03, 2023, 06:52:42 am
content: Currently I am using heap_4 and this has been working perfectly - like all of FreeRTOS actually.For the moment I've had to give up on the auto detect of the extra 64k. I've put in in a #define so I can move on with the project.There is a mystery problem, which is intermittent and hard to track down. It crashes the target, and bizzarely Cube IDE needs to be restarted also!It looks like one can't just load SP to _estack (the symbol of the last RAM location + 1 i.e. 0x20020000 for a 32F417; this load also happens at the very startup which is the asm startupxxx.s code) and then add 64k to it if the 437 is detectedCode:// Get CPU type and store ituin32_t B_g_dev_id=0;if ( B_HAL_GetDEVID() == 0x413 )B_g_dev_id=417;if ( B_HAL_GetDEVID() == 0x419 )B_g_dev_id=437;// Load SP to top of *real* RAM per CPU typeasm volatile ("ldr sp, = _estack \n");#ifdef EXTRA_64Kif (B_g_dev_id==437){asm volatile ("ldr sp, = _estack+65536 \n");}#endif// Fill stack with "S". This used to be in the startup .s code.// We do it here because it is easier to grab the CPU ID in C code (above)//ldrr2, = 0x2001e000 /* = _estack - _Stack_Size *///bLoopFillStack//FillStack://movs r3, 0x53535353/* fill with 'S' *///str r3, //adds r2, r2, #4//LoopFillStack://ldrr3, = _estack /* = 0x20020000 *///cmpr2, r3//bccFillStack// We are filling the stack area but the stack is used to call B_memset :)// So we just reduce the filled length a bit. Only a few are needed.// The syntax needed to pick up the symbols is weird; also used in _sbrk().extern char _top;char* stack_base;// base of stack (from linkfile)stack_base = &_top;extern char _Stack_Size;// size of stack (from linkfile)char* stack_size;stack_size = &_Stack_Size;#ifdef EXTRA_64Kif (B_g_dev_id==437){stack_base += 65536;// 32F437 has stack 64k higher up}#endifB_memset((char*)stack_base,'S',(int)stack_size-256);void B_main_real(void);B_main_real();for(;;);It could be the stack fill but I can't see why. I suspect there is something else I am not setting up i.e. adding 64k to the end of the stack is not the whole story. I already do the +64k fixup to _sbrk so the heap should work correctly too, and same for the heap init at startup (a bug in the newlib heap; requires the whole heap to be allocated and freed before it can be used).All modded code has been stepped through, too.The trouble starts before the RTOS starts, but after timer tick interrupt is enabled, which may be another clue.In the RTOS code there is thiswhich is the only reference to the entry SP value that I can find. The RTOS has its internal stacks in the 64k CCM, which is a separate area not used by anything else.I wonder if perhaps there is some CPU sync stuff - the sort of thing which needs __DSB etc.In fact looking at it again now I am confused whether the reference to 0xE000ED08 is actually reading the vector table and only that; the comment about the NVIC offset doesn't make sense.

author: abyrvalg
author_rank: Frequent Contributor
timestamp: July 03, 2023, 08:19:22 am
content: You have several local vars in that function changing the SP. Depending on compiler’s allocation decisions (assign everything to registers or to stack) some of them could suddenly “teleport away” after the asm line writing to SP, resulting in a totally unpredictable behavior (i.e. the fill part using trash values found in the new stack memory for base/size).Either do the SP modification earlier in the asm startup or split this code into two separate functions and call them from a function without local vars.Edit: E000ED08 is VTOR register and that code looks correct (read the table ptr from VTOR, read the first word via table ptr).

author: peter-h
author_rank: Super Contributor
timestamp: July 03, 2023, 11:34:52 am
content: I thought asm is absolutely immune from optimisation. I guess you are saying the compiler might say to itself that sp has already been loaded so no need to load it again.It amazes me that any C actually worksIsn't a register "volatile"?How about thisEDIT: I did that but it stilll bombs, so I will continue to dig around.Does msp do anything, in the context of 32F4 interrupt system?

author: tellurium
author_rank: Frequent Contributor
timestamp: July 03, 2023, 01:58:47 pm
content: Quote from: peter-h on July 03, 2023, 06:52:42 amUse whatever you use, I am pointing out that heap_5 exists, cause noone mentioned it before, and it is relevant to your question.By the way. What was that _sbrk snippet above, if you're using heap_4? _sbrk is for newlib's malloc. Do you intermix newlib's malloc and freertos's malloc ?

author: peter-h
author_rank: Super Contributor
timestamp: July 03, 2023, 02:21:35 pm
content: QuoteIn what way? From the FR doc:heap_4 - coalescences adjacent free blocks to avoid fragmentation. Includes absolute address placement option. heap_5 - as per heap_4, with the ability to span the heap across multiple non-adjacent memory areas.AFAICT I don't need this. For the 32F417 and 32F437 my memory architecture isidentical. The only difference is that the top end items are 64k higher up: the general stack (which is used only in main.c startup and then for interrupts) and therefore the available heap is 64k bigger. The heap base is the end of BSS as usual, and that does not move. I am not splitting the heap, etc.QuoteNo. The "general heap" in my product is indeed the Newlib heap. It works; I merely had to make it thread safe by mutexing malloc() and free().The code contained mutex calls but a) they were dummies b) no source was supplied; only a lib and c) the lib was non-weak so had to be weakened using objcopy (various past threads). The FR heap is used only by FR, internally, and is all in the 64k CCM. Like the LWIP heap is used only by LWIP, internally. And for good measure MbedTLS runs its own heap, inside a 48k block allocated on the general heapYes, it all works. AFAICT FR builds the tasks on its heap and never frees them. LWIP does god knows what internally. MbedTLS likewise._sbrk also works; I've been tracing the code to make sure.I don't think this issue is heap related. I suspect it is caused by my messing with the SP and not fixing up something else.

author: abyrvalg
author_rank: Frequent Contributor
timestamp: July 03, 2023, 05:45:10 pm
content: Quote from: peter-h on July 03, 2023, 11:34:52 amNo, I mean something like this:Code:PUSH {R4, LR}SUB SP, #8 ; make space for local varsLDR R0, =_topSTR R0,  ; initialize start_of_stack var at SP+0MOV R0, #0x100STR R0, [SP, #4] ; initialize stack_size var at SP+4…LDR SP, =_estack+0x10000 ; your asm lineLDR R0,  ; fetch start_of_stackMOV R1, #0x53 ; ‘S’LDR R2, [SP, #4] ; fetch stack_sizeBL memsetmemset would trash an area starting at random location and of random size because both LDRs from [SP+offset] are fetching some random values from locations off by +0x10000 (because SP has changed between STR and LDR). Kaboom!

author: peter-h
author_rank: Super Contributor
timestamp: July 03, 2023, 06:24:42 pm
content: I just don't understand this.I know that doing e.g.void fred(){asm volatile ("ldr sp, = _estack \n");......}is no good because when fred() is entered, there is code there which sets up the stack frame (of a size appropriate to the local variables found within the function). But now I have moved SP so that stack frame is gone.So if I want to transfer control (all these functions are never-return ones) to joe() and I want joe() to run on a different stack, I need to set up SPbeforecalling joe().Code:// === At this point, interrupts and DMA must still be disabled ====// Execute loader. Reboots afterwards.extern char _loader_ram_start;extern char _loader_ram_end;extern char _loader_flash_start;// Copy loader code and its init data to RAM.B_memcpy(&_loader_ram_start, &_loader_flash_start, &_loader_ram_end - &_loader_ram_start);// Set SP to top of CCM. This is not where the the general stack is but it doesn't matter because// the loader always reboots at the end. This assignment can't be done inside loader because it trashes// the stack frame and any local variables which are allocated *at* the call.asm volatile ("ldr sp, = 0x10010000 \n");// See comments in loader.c for why the long call.extern void loader_entry() __attribute__((long_call));loader_entry();// never get here (loader always reboots)for (;;);}I've changed things around a bit but still can't see the problem. The parms to memset have been verified by stepping through the code.The circumstances where it fails are obscure but if I #undefine the 437 extra 64k tests it all runs. This is the code in previous discussion. b_main is entered from startupxxx.s init code, with SP loaded to top of 417 RAM:Code:// This is the original main() called from the startup_stm32f407xx.s code// We don't do much here to enable the B_memset to fill the stack area. The real b_main// sets up a big stack frame because it contains so 512 buffer(s) on the stack.// See also https://www.eevblog.com/forum/microcontrollers/32f4-arm32-huge-stack-frame-0x250-bytes-why/void B_main(void){// Get CPU type and store itif ( B_HAL_GetDEVID() == 0x413 )B_g_dev_id=417;if ( B_HAL_GetDEVID() == 0x419 )B_g_dev_id=437;// Load SP to top of *real* RAM per CPU type// This throws away previous stack but it doesn't matter#ifdef EXTRA_64Kif (B_g_dev_id==437){asm volatile ("ldr sp, = _estack+65536 \n");}else{asm volatile ("ldr sp, = _estack \n");}#elseasm volatile ("ldr sp, = _estack \n");#endif// Fill stack with "S". This used to be in the startup .s code.// We do it here because it is easier to grab the CPU ID in C code (above)// We are filling the stack area but the stack is used to call B_memset :)// So we just reduce the filled length a bit. Only a few are needed.// The syntax needed to pick up the symbols is weird; also used in _sbrk().extern char _top;char* stack_base;// base of stack (from linkfile)stack_base = &_top;extern char _Stack_Size;// size of stack (from linkfile)char* stack_size;stack_size = &_Stack_Size;#ifdef EXTRA_64Kif (B_g_dev_id==437){stack_base += 65536;// 32F437 has stack 64k higher up}#endifB_memset((char*)stack_base,'S',(int)stack_size-256);void B_main_real(void);B_main_real();// We should never get herefor (;;);}I already use__attribute__((optimize("O0")))on the above function, to prevent any funny compiler business.

author: peter-h
author_rank: Super Contributor
timestamp: July 04, 2023, 12:51:08 pm
content: There is something simple to watch out for:A function allocates a stack frame for all local variables which the compiler found inside it. This happens immediately after it is entered.If that function manipulates SP, any local variables cannot be used anymore because the stack frame has gone. They have to be statics.But you can load the SP and call a function. That function will obviously use the new stack.

author: Nominal Animal
author_rank: Super Contributor
timestamp: July 04, 2023, 01:15:15 pm
content: It is impossible to fix this cleanly at run time, because we are talking about the address space available here.Does your end user end up including the correctstm32f417xx.h/stm32f437xx.hheader?I assume they have to, because how would they access the peripherals correctly otherwise?The two header files define macrosFLASH_BASE(0x08000000),FLASH_END(0x080FFFFF and 0x081FFFFF); and only the '437 definesSRAM3_BASE(0x20020000) andSRAM3_BB_BASE(0x22400000).So, what I would do, is tell the users to add a specific include, after all other includes in their main source file. That file would contain for exampleCode:#ifndef thatfile_H#define thatfile_H#ifdef __cplusplusextern "C" {#endif /* __cplusplus */#define DEFINE_LINKER_SYMBOL(_name) \__attribute__ ((externally_visible, used, unavailable, section (".omit"))) \void _name(void) { }#if (FLASH_END - FLASH_BASE) == 0x001FFFFFDEFINE_LINKER_SYMBOL(__device_flash_2048k);#elseDEFINE_LINKER_SYMBOL(__device_flash_1024k);#endifDEFINE_LINKER_SYMBOL(__device_ccmram_64k);#ifdef SRAM3_BASEDEFINE_LINKER_SYMBOL(__device_ram_192k);#elseDEFINE_LINKER_SYMBOL(__device_ram_128k);#endif#ifdef __cplusplus}#endif /* __cplusplus */#endif /* thatfile_H */and start your linker script withCode:PROVIDE(FLASH_SIZE = DEFINED(__device_flash_2048k) ? 2048K : DEFINED(__device_flash_1024k) ? 1024K : 0);ASSERT(FLASH_SIZE > 0, "thatfile_H not included: unknown Flash memory size!");PROVIDE(CCMRAM_SIZE = DEFINED(__device_ccmram_64k) ? 64K : 0);ASSERT(CCMRAM_SIZE > 0, "thatfile_H not included: unknown closely-coupled data memory size!");PROVIDE(RAM_SIZE = DEFINED(__device_ram_192k) ? 192K : DEFINED(__device_ram_128k) ? 128K : 0);ASSERT(RAM_SIZE > 0, "thatfile_H not included: unknown RAM size!");MEMORY {FLASH_BOOT (rx) : ORIGIN = 0x08000000, LENGTH = 32KFLASH_APP (rx) : ORIGIN = ORIGIN(FLASH_BOOT) + 32K, LENGTH = FLASH_SIZE - 32KCCMRAM (rwx) : ORIGIN = 0x10000000, LENGTH = CCMRAM_SIZERAM (rwx) : ORIGIN = 0x20000000, LENGTH = RAM_SIZE - 4KRAM_L (rwx) : ORIGIN = ORIGIN(RAM) + RAM_SIZE - 4K, LENGTH = 4K}SECTIONS {/DISCARD/ { *(.omit) }}The.omitsection is discarded, so that the flag linker symbols won't use up any room in the actual binary.Alternatively, you can create header files32f417.hand32f437.h, which not only include the properstm32f4?7xx.h, but also define the symbols used by the linker script to determine the address space ranges as above.Then, the developer-user includes just that one file (which will also include any other necessary common includes et cetera), and off they go.

author: abyrvalg
author_rank: Frequent Contributor
timestamp: July 04, 2023, 02:02:34 pm
content: Why do you need to move the stack at all? Just place it like this:ram_start:.data.bss.stack.heapand grow the heap into the additional 64K

author: peter-h
author_rank: Super Contributor
timestamp: July 04, 2023, 02:26:34 pm
content: QuoteNo need to. The 437 is a superset of the 417 in every way except one: the Vbat measurement using ADC1, where the resistor divider is 1/4 versus 1/2.So the only difference, if the extra 64k RAM of the 437 is desired, is moving the stack up 64k. And this is not just moving SP; in the interests of good coding one also has to fill that region with 'S' or some such.I have now got a lot further. But I have a funny one, a real mystery, but something which must be very simple. The central issue is whether the Cube disassembly listing is a disassemblyof the binary(with symbol names inserted where addresses match) or whether it is done with a copy/paste of bits of theassembler listing produced by the compiler. I suspect the latter.The code disassembled at the yellow address bears no resemblance to memcpy().On the face of it, there is something wrong with the values sent to memcpy and/or memset, but I can't debug them properly because I don't know the register conventions for parameter passing, and stepping into the functions is not possible because a) I don't have the C source and b) the code displayed is duff. Replacing those two functions with my own ones solves this problem and everything works!QuoteYou are totally right - if the extra 64k was used only for heap.But using the extra 64k RAM conventionallyshouldwork. I really cannot see why not. Something totally weird is going on. Could be just Cube doing silly buggers... but if I disable the checks for the extra 64k, it runs OK.It also runs fine if the memcpy and memset at the start of the "overlay" are local functions and not the Newlib ones. And this is not some simple product which might work by luck; the amount of functionality is huge. As a 24/7 test I am running a TLS session every 60 seconds, and a constant traffic on serial over TCP, plus a GPS to ARINC429 converter, etc.Code:// Entry point for code called by the boot block - has to be located at the base of FLASH+32k// This is done in linkfile// Has to be "int" otherwise compiler complains :)// Because it is reached via an asm jmp, various measures to prevent it getting optimised away, which don't work. What does work// is vector2 (which is in assembler and thus immune to optimisation) having a dword pointing to main().__attribute__((optimize("O0")))__attribute__((used)) // does not do anythingint main(){// Initialise DATAextern char _s_nonboot_data;extern char _e_nonboot_data;extern char _si_nonboot_data;S_memcpy(&_s_nonboot_data, &_si_nonboot_data, &_e_nonboot_data - &_s_nonboot_data);// Zero BSS and COMMONextern char _s_nonboot_bss;extern char _e_nonboot_bss;S_memset(&_s_nonboot_bss, 0, &_e_nonboot_bss - &_s_nonboot_bss);// Go to main programmain_real();// We should never get herefor (;;);}// Local versions of functions used above. They should not be necessary but they avoid the use// of the Newlib stdlib ones for which we have no sources.__attribute__((optimize("O0")))// prevent replacement with memcpy()void S_memcpy (void *dest, const void *src, size_t len){char *d = dest;const char *s = src;while (len--)*d++ = *s++;}__attribute__((optimize("O0")))// prevent replacement with memset()void S_memset(void *s, char c, size_t len){char * p=s;while(len--){*p++ = c;}}// Vectab2.s ends up linked here, at base of FLASH + 32k + 512

author: Nominal Animal
author_rank: Super Contributor
timestamp: July 04, 2023, 04:16:32 pm
content: Quote from: peter-h on July 04, 2023, 02:26:34 pmBut the user's won't be able to exploit the additional features of the '437, like the 2D DMA engine, I2C FLTR register for controlling I2C analog and digital noise filter, Serial Audio Interface (SAI), RCC PLLSAICFGR or DCKCFGR for additional clocks (including PLLSAI oscillator), 1024k of additional Flash, SPI4, SPI5, SPI6, UART7, UART8, GPIOJ, GPIOK, AES_GCM and AES_CCM hash modes, additional HASH digest registers (8 instead of 5, so 256 bits instead of 160 bits), additional 8 Flash ACR wait latency options, voltage regulator over- and under-drive options (PWR_CSR_ODRDY, PWR_CSR_URDY), some SYSCFG_MEMRMP and SYSCFG_PMC flags (see AN4073), and increased maximum frequency from 168MHz to 180MHz?Seems.. wasteful to me, especially because everything the user would need to do is to include the proper header file, depending on their MCU model, that can then include the corresponding stm32f?7xx.h and export the functions defined in the always-accessible boot Flash.As discussed before, this would be much easier if split into parts, so that when the master boot loader is built, it also produces a skeleton project with correct linker script for the next level code, including user-accessible symbols for the exported functions and variables in the master boot loader. These are simple assignments of formsymbolname=runtimeaddress;. If used within an output section definition, then the address is relative to the start of that output section; if used outside the SECTIONS command, the address is absolute.For example, if your master boot loader code exports a function namedreboot(), which is executed at address 0x08000120 (offset 0x120 from the beginning of the FLASH region), then the header file you provide needs to declare it,extern void reboot(void) __attribute__((noreturn));and in the linker script, for the user C code to execute it, you havereboot = 0x8000120;outside any command blocks. This does mean that each user project would need the particular headers and linker script for the currently installed master boot loader.You can also do a jump table at a fixed address in Flash, each being exactly 4 bytes long and resolving to an unconditional branch instruction,b.wlabel.Each entry in the jump table then corresponds to a jump to a specific function exported by the master boot loader, for example the first one could be the abovementionedreboot(). This costs one unconditional branch instruction, or four bytes, per function exported from the master boot loader to user programs, but this way their location in the Flash isn't fixed.Then, the user can compile their code for any master boot loader version, because the actual function entry points are always the same in the jump table; the jump table itself may vary, as it is part of the master boot loader.If you need some read-only configuration values (including the bootloader version), I recommend you put a structure at a fixed address in Flash, that contains the values, and export the structure symbol in the linker script. Pad the structure with some zeroes, so that later versions of the master boot loader can export new values, and the user code detect if their master boot loader is too old to export that value.

author: peter-h
author_rank: Super Contributor
timestamp: July 04, 2023, 04:50:08 pm
content: QuoteThose are all good points, but a finished product is likely constrained by GPIO pin allocations, so most extra features cannot be used anyway.

author: Siwastaja
author_rank: Super Contributor
timestamp: July 04, 2023, 05:50:16 pm
content: Quote from: peter-h on July 04, 2023, 04:50:08 pmI'm asking again, if the point of ONE FIRMWARE is for manufacturability with two BOM options, why would you need to take advantage of the "extra RAM", when you don't take advantage of any other extra feature (like peripherals) either?On the other hand, if you plan doing different projects on different CPUs, then obviously it won't be one firmwareanyway, so none of this crap is needed.Or are you solving a nonexistent problem and trying to find a way which causes most trouble and maximizes the number of forum posts?

author: peter-h
author_rank: Super Contributor
timestamp: July 04, 2023, 07:27:20 pm
content: QuoteThat's just the way it is. The extra RAM is all that is needed, and indeed most of the extra features cannot be used due to no GPIO left. The 180MHz could be used. What would be really handy would be hardware RSATakes 3 seconds right now.QuoteAll of the above.Just wondered... are you Russian, by any chance?

author: nctnico
author_rank: Super Contributor
timestamp: July 04, 2023, 07:30:51 pm
content: Quote from: Nominal Animal on July 04, 2023, 04:16:32 pmMy default solution is to also include a version number in such a configuration struct so software can't (at least) use the wrong layout. Best case software can try to convert between configuration versions but I never implemented that so far.

author: peter-h
author_rank: Super Contributor
timestamp: July 04, 2023, 07:45:53 pm
content: QuoteOr thishttps://stackoverflow.com/questions/19252128/how-to-use-the-include-command-in-ld-linker-scriptI think I've fixed it all. Several things, mostly silly. But a good learning experience.but with 32F437, above is the same but:Thank you all (those who helped) for all your huge help

author: Siwastaja
author_rank: Super Contributor
timestamp: July 05, 2023, 05:33:20 am
content: Quote from: peter-h on July 04, 2023, 07:27:20 pm... nope?

author: SiliconWizard
author_rank: Super Contributor
timestamp: July 05, 2023, 06:12:21 am
content: as well?

author: peter-h
author_rank: Super Contributor
timestamp: July 05, 2023, 08:38:06 am
content: Rudeness.

author: Siwastaja
author_rank: Super Contributor
timestamp: July 05, 2023, 09:23:17 am
content: You get somewhat more "rude" replies when you ask for extensive help with details while actively refusing to discuss the question what you areactuallydoing - i.e., playing thex-y questiongame. The reason is simple: such behavior itself appearsrude. But I don't mean this is wrong; maybe your project is a commercial one with obvious limitations what you can discuss and what you can't. But then the discussion will not be as fruitful as it would with full disclosure available, you need to live with it.Ignoring advice by others due to your stubborness also appears rude to others. You can't choose different rules for yourself and then expect others need to play extra nice with you. While I applaud your "I want to do it this way, help me with this, I don't want any help with the big picture" attitude as interesting and thought-provoking, you need to accept you are going to get honest replies (along the lines: "geez, what a stupid problem to waste time with") without sugar-coating, too.As almost every message of yours start with blaming everything else except yourself (tools no one else has any problems with are now total crap, documentation is always crap even though others find absolutely no issue with GNU LD documentation), expect to be shown that there is blame to your actions, too. If you don't want that, stop the blame shifting game, you are the one who always starts it.I have been reading your posts with interest for an extended time now and it is still quite unclear to me whether you complicate your already-solved problems on purpose because you enjoy doing things in esoteric ways, or if that is truly something you don't want, but still "somehow" things always end up that way, which you find very frustrating (no wonder), and then you get even more frustrated when others point to you that there are easier ways out of the whole minefield, as you fail to see those ways.If the latter, what you would need is help with the big picture and priorization of things, and picking your fights better. After all, the problems you are solving are very common and solved gazillion of times, with no need to sort functions in linker scripts or compile code with -O0. For example, regarding bootloaders, you have got very good tips how to design asimplearchitecture, but it seems you ignore the advice.

author: peter-h
author_rank: Super Contributor
timestamp: July 05, 2023, 10:49:13 am
content: I've been on tech forums since about 1990. There is a tradeoff between forming a specific question and making a huge long post. The former should get intelligent reponses while latter is likely to be ignored.The project is intended to sell eventually (although I also plan to use it for various hobby projects) and that constrains how much I can post, but I take care to post the relevant detail.On this topic, auto RAM detect, there are great reasons for not building multiple projects, not building the boot block separately, etc, but I would have to post the whole RM which nobody would read. But let me give a little example: a while ago somebody set up a Cube kit with multiple projects, and I found some files were cross-linked across projects. Wasted god knows how much time and was discovered only by accident. Could have been a disaster. A bit like the (true) story about a company with 20 devs writing code for a year, backed up to some unix box every day, plus a tape drive, then somebody upgrades the HD, reformats it, and finds that the tape backup was dud the whole time. Luckily they had printouts so they collected all the secretaries and got 50% of them to type it all in, other 50% to proof read it. I am more careful than most, because it is all my business, and any shit lands on my lap. I have no help and use the internet to find answers, while hopefully contributing stuff which others may find helpful in years to come.ThisQuoteis purely gratuitous rudeness, which has no place in my "world". If you don't get that, nothing I can do about it. As a current tech forum mod/admin (343k total posts in 10 years) I am pretty familiar with that sort of thing, but actually I would just delete such a post because it is a borderline personal attack and thus contra the rules on that forum.

author: Siwastaja
author_rank: Super Contributor
timestamp: July 05, 2023, 11:50:40 am
content: Quote from: peter-h on July 05, 2023, 10:49:13 amI'm not asking you to provide more details or make longer posts. I'm suggesting you should discuss more about the big picture, and less about weird corner cases in esoteric use pattern of tools, although Iappreciatewhat you do because such esoteric details areinterestingand I learn every time from your threads, but it is sad if you do not enjoy it or have a job to finish. Also, you should sometimes try what others suggest, instead of trying to find "just that one fix to this one line" which seemingly "solves" the problem you think you have.QuoteOK, you are free to have that opinion but I don't agree. You are still allowing being rude and playing social games, and you only draw the line by honesty, such that more honest = worse. If I had formed the same sentence to be even more rude, but in a more subtle, hidden way, you'd have been OK with it. Fact is, you are rude all the time. This is why you receive rude replies. I'm just being directly rude, and the question I posed is honest one, and you should really pay attention to it. After all, if you are trying to make a product, trying to solve nonexistent problem after another is a total disaster time-wise and the project will never finish. I'm truly trying to be helpful here, as I have sometimes the same tendency to veer off to development time sinks. It truly seems to me you are just going in defensive coping pattern because I asked the right question. Do some introspection.BTW, name-calling a Finn "a Russian" is quite some personal attack and definitely rude, and I think you know it (I don't believe you did it by accident). I don't mind name-calling if that eases your pain, but that's still hypocritical.

author: nctnico
author_rank: Super Contributor
timestamp: July 05, 2023, 12:38:04 pm
content: Quote from: Siwastaja on July 05, 2023, 09:23:17 amYou have to define simple. AFAIK peter-h wants to have the entire project (bootloader + firmware) as a single project so it is easy to keep both together and thus makes it easier to distribute to people who want to work on the project. All while avoiding having to resort to command line tools / scripts. Sometimes making a truly simple solution is extremely hard to do.

author: peter-h
author_rank: Super Contributor
timestamp: July 05, 2023, 01:50:21 pm
content: QuoteIt is those where I get stuck. The rest I can just do...QuoteI don't get that... social games???QuoteI think you have a problem. Sorry but I can't help.I know why most forums allow this: it drives advert clicks way up.QuoteExactly.I have just one Cube project and when this is built (with ctrl-b to build it only, or F11 to build + send to STLINK debugger) it runs a post build batch file which also generates a second version of the project for 3rd parties to use (without the boot block and various confidential parts). Same Cube config in every way but you just import this second project. That batch file is actually complicated (50 lines? - took me a whole day) but once done it is done for ever. It just works.I actually run this 2nd dev kit in a VM, to ensure there is no cross contamination. That VM forms a totally standalone environment which will run tomorrow, or in 10 years' time. Taking suitable care to handle the windoze license inside it, it can be distributed, too. This is a major plus for a corporate environment; most companies lose sources (or can't build them anymore) and lose basically everything within a few years.Like most things to do with today's chips (2000 page RMs etc) Cube itself is way too complicated to expect anybody to learn how to use it from scratch. The project config alone would be horrific.There is a lot of other stuff e.g. security, inherent in remote firmware deployment.And the various issues I've posted about have had very little to do with building it all together.

author: Siwastaja
author_rank: Super Contributor
timestamp: July 05, 2023, 03:17:04 pm
content: Quote from: peter-h on July 05, 2023, 01:50:21 pmExactly - you don't get that - social games would pass your acceptance filter. You are not against being rude, you are against people saying the inconvenient truth out loud. Your bootloader saga has lasted for, what, more than a year with numerous threads and dozens of detailed posts. What is the reason you don't give a chance to any idea that was suggested to you by people like ataradov and others, like maintaining the bootloader as a separate "project". You can compile them together using makefiles or scripting language of your choice - the whole concept of "projects" is arbitrary, and only pushed to you because of CubeIDE, which was your choice to use.Also, what is the reason you bang your head against the wall with CubeIDE - there are now 38 pages on your "buggy crap" thread - when you could simply automate the whole shebang using a simple <100-line makefile, so that anyone could just start working with the project (typemake), without installing virtual machines running cubes and reading some documentation about what buttons to click?This is what I'm after. If the reason is that you trulywantto work this way, and letting the project grind to a halt for a year, two, maybe three is acceptable compromise - then this is totally fine. But I have this feeling you are not satisfied with the outcome and are projecting your anger against those who have guts to say this out loud. But go on, you can keep ignoring everyone who tries to truly help you. You can even put me in your ignore list, and you can continue name-calling me, which is what you have been doing all the time (sarcastic "genius" name calling, and annoyingly indirect "I'm being called an idiot by you" gaslighting, despite my numerous attempts to rectify this by clarifying I don't think you're an idiot. This is also a form of social game on your part, you know. But I'm sure you won't recognize it, or think as something which isagainst the rules.)

author: peter-h
author_rank: Super Contributor
timestamp: July 05, 2023, 04:12:22 pm
content: QuoteHmmm, debugging? OK, one can buy a Segger and use their 1970s user interface. I had a play with that. OK in 1980s...I do know the difference, having come from Wordstar 4, then Brief (remember Underware, Inc?), Polymake, etc. I still sell a user programmable comms product which uses this stuff. For good measure the compiler needs DOS 6.2so winXP command box, or a VMWARE equivalent. Must have sold 100+ of these kits at £450 each. Zero now.But the acceptance of these 20th century tools today is roughly -273.16C.Also the acceptance of a dev kit selling for £450 is roughly -273.16C.

author: Siwastaja
author_rank: Super Contributor
timestamp: July 05, 2023, 05:11:41 pm
content: You can let users import the project in any IDE they like to debug with, without having to run all production or your official process through that IDE. This forces your project "project file free" and avoids mystical cross-dependencies or weird bugs. This brings the best out of both worlds. Fact is, for automation like code builds, command line tools are still relevant in 2023 because they can be easily automated. You can also integrate tests this way, while Cube does not provide any kind of test facilities whatsoever. (Unit and integration tests are way more important than single-stepping code in debugger and examining memory bits, but it seems many microcontroller folks are mentally stuck in 1980's, just with fancier graphical UIs. We should learn useful bits from application programming field, where tests and traceability are everything, andno oneasks for a debugger.)

author: peter-h
author_rank: Super Contributor
timestamp: July 05, 2023, 05:39:39 pm
content: Cube is free, and the project is just a tree, so they can import into any IDE which can import stuff.Then spend days working out the compiler and linker options and libraries...Good luck with that. Guess who will be supporting customers on it?

author: Siwastaja
author_rank: Super Contributor
timestamp: July 05, 2023, 05:47:09 pm
content: Quote from: peter-h on July 05, 2023, 05:39:39 pmNo no no, the idea is to put all that in a single, simple makefile. Once it's done, no one has to figure out anything; just git pull; make. If debugging or other specialties are needed, import to any IDE. But don't make the project depend on it, because such tooling needs are like farts, those by others stink more, so don't force people to one IDE.And if you think you need some super special compiler and linker options, step back and try to imagine why other people do not need them. My projects have been with 99% the same options for over a decade.

author: nctnico
author_rank: Super Contributor
timestamp: July 05, 2023, 06:21:58 pm
content: Quote from: Siwastaja on July 05, 2023, 05:47:09 pmThe problem is that at that point you'll have lost 100% of the people that just want to make a quick change to a project. I see that with all my customers that want to have a go with the source code themselves. You are definitely not doing people like that a favour with command line tools for which they can't look up 'howto' guides quickly or that need installing a whole bunch of other tools. It is much easier to say 'Install CubeIDE version X.Y', import the project and go from there. The whole reason CubeMX (and similar IDEs exist) is to get going quickly without much fuss either as the developer side and the customer side. Besides that, creating a good, universal makefile is an art in itself. Even up to the point where tools where created around it (autoconf) or alternatives (cmake for example).

author: Nominal Animal
author_rank: Super Contributor
timestamp: July 05, 2023, 06:46:40 pm
content: Quote from: nctnico on July 05, 2023, 06:21:58 pmThat's a bit unfair, becauseautoconfwas created to adjust Makefiles for different Unix systems without user intervention; not because of any intrinsic Makefile properties. Stuff like whether certain features and functions were provided by the system or not; nothing to do with the Makefile syntax per se. Autoconf wasn't and isn't a particularly good or useful way to adjust settings in Makefiles. Other tools, like the Linux kernel configuration tools, don't actually edit the Makefiles directly, and instead work on flat text files that define macros/constants that define the configuration, and are included and used by the actual unmodified Makefiles.While I much prefer Makefiles myself (and can craft robust ones), and do not like to use any specific IDE, I can see why an IDE would make a big difference when the intent is to provide aproductfor clients to develop further.After all, at the point when Arduino came about, we already had full free open source development tools for AVR (avr-gcc, avr-binutils, avr-libc), while most vendors still charged for the development tools quite a lot. The Arduino folks just wrapped it all within an IDE based on Java (with a weird preprocessor), but that made the field explode among hobbyists.

author: wek
author_rank: Frequent Contributor
timestamp: July 05, 2023, 08:45:36 pm
content: Quote from: Siwastaja on July 05, 2023, 05:47:09 pmGetting make to make on anybody's PC (and that's mostly flavours of Windows, however you don't like the idea) is surprisingly hard. We've had a thread about it recentlyhttps://www.eevblog.com/forum/microcontrollers/lets-discuss-telluriums-tutorial/msg4437313/#msg4437313I don't dig git either, and have arguments, but we are hijacking this thread already.JW

author: peter-h
author_rank: Super Contributor
timestamp: July 06, 2023, 06:40:14 am
content: Yeah - not supporting Windoze, requiring the use of git, editing makefiles, will practically kill the market except to hard-core anoraks who are probably not going to buy anything like this anyway because they built their own during the previous nightSupport is a huge angle and I strive to minimise this by design and clear docs. Auto detect of the RAM is a part of this.I still don't have a good solution for the linkfile LENGTH=128K or 192K. I will live with this for now; it is easy to document.

author: AVI-crak
author_rank: Regular Contributor
timestamp: July 06, 2023, 07:29:40 am
content: I don't understand the meaning of the conversation.Any project with a physical layer is strictly tied to a specific chip. And in some cases there is a link to the chip version of a particular model - as it has a different number of errors, and very different behavior.The year the chip was made is important!!!The project simply won't work on another chip.In the case of using the IDE from ST - you must specify the version of the IDE!!!If you failed to debug the project in two months, then it is useless to work further. Old projects with an iron level are also dying. In the case of the ST company, the one who runs the fastest wins.In order for the project not to lose its relevance over the years, you need to get rid of the iron level, from changing software, from rigid binding to a specific chip.Oh yes, write in pure C - it is eternal.

author: peter-h
author_rank: Super Contributor
timestamp: July 06, 2023, 05:20:44 pm
content: QuoteHow?

author: nctnico
author_rank: Super Contributor
timestamp: July 06, 2023, 05:34:47 pm
content: Quote from: peter-h on July 06, 2023, 05:20:44 pmI guess AVI-crak is referring to different versions of the same chip that may or may not have fixes for silicon bugs. But since you can read the chip revision from the chip, you can determine which silicon bugs you need to work around and which are fixed. But it does take extra software.

author: Nominal Animal
author_rank: Super Contributor
timestamp: July 06, 2023, 06:26:25 pm
content: Quote from: nctnico on July 06, 2023, 05:34:47 pmYes. If the chip can be identifiedbeforecompile time, and its bugs described via preprocessor macros, then one can save RAM/Flash use by only including the required workarounds.This is nothing new, because standard C libraries on Linux and BSDs have had to do exactly this for decades. It is why one configuration parameter is kernel version; features available in all later versions are assumed to be available, to limit the set. Granted, instead of checking the kernel version, the standard C libraries use a fallback-and-flag mechanism, because unsupported syscalls return a special "Not implemented" error code. (That is, if sayopenatsyscall ever returns not implemented, the C library will fall back to internal path mangling and usingopensyscall from that point onwards.)At the source code level, modularization helps a lot here. You need to write the low-level hardware-access layer to abstract out the hardware differences. I do not like using HAL for these, because their abstractions are generic; but the abstractions actually needed depend on what the software needs. That is, the abstractions should be designed based on what the software needs, and not based on what the various hardware provides: the opposite way vendors like ST design their HALs.Design-wise, it is a lot of work, because you have to simultaneously consider both top-down (ie. what the final software needs, to perform its functions) and bottom-up (ie. what the differences are or may be between the hardware versions this software will run on). Also takes quite a bit of experience to know what matters in practice, and so on.Note that I am not claiming that doing it this way makes any business sense; I am only describing what is technically possible and done in other similar circumstances.

author: peter-h
author_rank: Super Contributor
timestamp: July 06, 2023, 06:28:09 pm
content: I would be amazed if any of my code relies on some CPU bugs having been fixed.How long has a 32F417 been out? I bought my main stock in 2019, before covid came and made them unobtainable.Edit: year 2010 approx.

author: Nominal Animal
author_rank: Super Contributor
timestamp: July 06, 2023, 06:30:02 pm
content: Have you checkedthe errataST provides?

author: peter-h
author_rank: Super Contributor
timestamp: July 06, 2023, 06:38:33 pm
content: Yes, at various times.Practically the whole lot describes never-fixed stuff e.g.The yellow is never-fixed (for good reasons, obviously) and only the few shown had been fixed, like the CPU ID (fixed for good reasons, obviously!).I would conclude that if my software, mostly either written by me or a colleague since about 2019, or based on ex ST Cube MX "HAL" code from c. 2019 (not much left of it now), works correctly, that should be OK.Most of the stuff in the errata is not even used in my code (but some would be "interesting" if it was, like the I2S stuff) but I spotted thisand I am buggered if I know where this code is. I see FIFO related stuff in a number of places. But the entire USB code is run as an ISR so it would be a question of priorities. But maybe not since the corruption happens only if writing to the other USB regs, ints from other things should not affect it. Anyway, it does work.If ST started fixing that long list, it would break a lot of software.

author: nctnico
author_rank: Super Contributor
timestamp: July 06, 2023, 07:31:26 pm
content: Quote from: Nominal Animal on July 06, 2023, 06:26:25 pmNo, these workarounds are typically enabled / disabled at runtime to make the software more compatible with all possible hardware out there. This doesn't increase size of the software significantly because the workarounds are only a few lines of code.

author: peter-h
author_rank: Super Contributor
timestamp: July 06, 2023, 07:43:10 pm
content: From the 5 pages of unfixed errata, and only a few items which were fixed, and all of those few were fixed after version 1, there is a clear policy by ST to not fix any of the stuff which is there today.I also think, practically, that with a chip which came out in say 2010, if say UART 3 was dud, somebody would have noticed and reported it.The ST website confirms the 32F417 with a 10 year min production life commencing 2013.https://www.st.com/content/st_com/en/about/quality-and-reliability/product-longevity.html#10-year-longevity

author: Nominal Animal
author_rank: Super Contributor
timestamp: July 06, 2023, 09:07:43 pm
content: Quote from: nctnico on July 06, 2023, 07:31:26 pmThat is what is most commonly done, yes (except workarounds like the stack pointer being loaded from incorrect address if an interrupt happens during the data phase usingLDR SP, , #imm, with workaround being to load the value to a temporary register and from there to stack pointer, tend to be always enabled, since they are harmless on hardware that does not have the bug).But, if the exact variant is known at compile time, they can be implemented directly, without any runtime checks or patching. This kind of code adapting to hardware is not new, and can be also done at compile time, not only runtime, was my point.Quote from: peter-h on July 06, 2023, 07:43:10 pmBased on the errata, it definitely looks that way.The OTG_FS and OTG_HS bugs mean there may be some USB HID devices that won't work with STM32F417 as the host. (The only low-speed USB devices I've ever seen are someoldcustom HID devices, like those used in old mini numpads and old bar code readers.)The OTG_FS_DCFG bug means when read, the DAD and PFIVL bits (4-12) may be incorrect. The workaround is to use a 32-bit RAM variable for it, initializing it to0x0220'0000(it's bootup initialization value), and do the operations on the RAM variable and just copy the value tousbx->DCFG. I don't see such a workaround in STM32CubeF4/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usb.c at Github, though.I didn't look at the other errata.

author: SiliconWizard
author_rank: Super Contributor
timestamp: July 06, 2023, 09:16:08 pm
content: Quote from: peter-h on July 06, 2023, 07:43:10 pmSo you're close to EOL now?I would definitely consider switching to something newer.As to unfixed silicon bugs, that's annoying but rather common. Silicon bugs are expensive to fix and fixes lead to revisions of the same IC with different behavior, which the customer would have to deal with at run time one way or another, which can be worse than having a workaround for a known bug and sticking to it without ever fixing the bug.

author: peter-h
author_rank: Super Contributor
timestamp: July 06, 2023, 09:42:42 pm
content: The 10 year guaranteestartson Jan 2023.And they have been renewing the 10 year period every year for the last few years.Based on what I've seen over the last 30-40 years I reckon ST will run these chips for a total of 25-30 years, same as Hitachi have been doing. So maybe another 15 years.Another positive factor is that the chinese have picked the 407 (417 without hardware crypto) as one of the main chips to rip off (legally or not). They might know somethingI can use the 407 with just one #define change in one .h file, and it works with no practical performance loss (the aes256 code in MbedTLS runs at almost 1MB/sec). The 407 is a hugely popular chip.Re the USB thing, my product is a USBclientonly. The OTG mode was not implemented, not least because a) it was not needed b) it leads to unrealistic customer expectations as regards supported clients and c) available power for clients would be very limited.