Mcu programming 101 writeup - Page 1
Forum section: electronics / general

author: wek
author_rank: Frequent Contributor
timestamp: May 29, 2022, 10:50:53 am
content: [shameless self-promotion]http://efton.sk/STM32/mcu_programming_101.htmlComments welcome.[/shameless self-promotion]JW

author: pcprogrammer
author_rank: Super Contributor
timestamp: May 29, 2022, 11:04:08 am
content: Good to see someone promote bare metal programming instead of using the manufacturers pile of garbage like STM HAL (Hardware Abstraction Layers) code. I, for sure am no fan of thoseIt might be me, but most of my attempts to make a simple program with their IDE and generated code failed to workMy comment: Since it is aimed towards the novice you might refrain from abbreviations like RMW and use read-modify-write instead.

author: Electro707
author_rank: Contributor
timestamp: May 30, 2022, 10:33:10 pm
content: Nice article! Great for a beginner so they are aware that just calling `digitalWrite()` isn't all there is to it (also that specific function is way too bloated, but that's a conversation for a different day).QuoteFrom my experience generally HALs tend to be meh. I personally prefer things like ST's LL (Low Level) code as a nice middle-ground, which is nice when needing to switch the micro to a different one of the same family. At least with ST's generator there is an option to switch the initialization from HAL to LL which I do everytime.

author: brucehoult
author_rank: Super Contributor
timestamp: May 31, 2022, 05:00:05 am
content: Good start. It ended just as I was getting into it :-)

author: wek
author_rank: Frequent Contributor
timestamp: May 31, 2022, 10:29:35 pm
content: Thanks.Tried to make it as sparse as possible. Got carried away towards the end.May extend/follow up in the future, but I am not sure how. The topic is too wide and I don't feel confident enough to write authoritatively about the details.Not to mention time.JW

author: tepalia02
author_rank: Regular Contributor
timestamp: July 01, 2022, 08:00:51 am
content: Thanks for sharing.

author: wek
author_rank: Frequent Contributor
timestamp: March 18, 2024, 01:56:25 am
content: Part2, on minimalistic toolchain.Didn't feel that good as the first one, but a friend requested a few words of help and again, I got carried away...Comments, please.JW

author: brucehoult
author_rank: Super Contributor
timestamp: March 18, 2024, 08:56:48 am
content: "Burning" doesn't sound so bad, especially for EPROM or OTP. "Flashing" is pretty common, and accurate on most modern MCUs.There are a number of endearing English grammar mistakes, mostly dropped articles, which I won't enumerate.

author: tellurium
author_rank: Frequent Contributor
timestamp: March 18, 2024, 04:01:33 pm
content: Very nice write upAn idea just came to my mindTo have such tutorial with embedded editor, just likehttps://go.dev/tour/welcome/1A dev board can be flashed via webusb. And logs can be observed via webusb. Like herehttps://mongoose.ws/demo/?board=Nucleo-H743ZI&project=mqttThen a tutorial immediately becomes more powerful learning tool, cause readers can experiment on the fly.

author: wek
author_rank: Frequent Contributor
timestamp: March 19, 2024, 09:02:27 am
content: Thanks for the comments.@brucehoult, "flashing" sounds good, will rephrase. Shall I do that also in the main text? "Device programming" sounds old, doesn't it.Sorry for the errors in grammar. I don't think I can improve in that too much.@tellurium, I see your point, and I beg to disagree. IMO the main thrill in mcu programming is the physical aspect ("see the LED blinking"). Remote debugging also adds "magic", which I propose to minimize at this stage. Don't get me wrong; I understand that there are merits in remote debugging.JW

author: tellurium
author_rank: Frequent Contributor
timestamp: March 19, 2024, 02:15:27 pm
content: Quote from: wek on March 19, 2024, 09:02:27 amI sometimes use chatgpt -https://chat.openai.com/to turn my bad English into something more readable.Quote from: wek on March 19, 2024, 09:02:27 amCan you elaborate on that please? What do you mean by "remote debugging"? I did not get the point. I did not get the point about the "physical aspect". All I suggested is to have your code snippets be flashable to a real physical board without any external tools, just using a browser.

author: wek
author_rank: Frequent Contributor
timestamp: March 19, 2024, 03:06:25 pm
content: > chatGPTI perhaps prefer my English be bad and mine :-)> What do you mean by "remote debugging"?Sorry, I did not pay enough attention to your post/links and misunderstood the intention.> have your code snippets be flashable to a real physical board without any external tools, just using a browserDunno. Have strong proponents of "browser-based computing" in my circles, I'm not that sure about these. Let's just say that without experience I don't really should form opinions.Things move and one learns every day... :-)Thanks,JW

author: peter-h
author_rank: Super Contributor
timestamp: March 20, 2024, 03:48:49 pm
content: I think the article #2 is very good. I wish I knew this when I was at that stage ~ 3 years ago. Just some random comments:startup_stm32f407xx.s- it is odd why this is in asm, when all of it (except loading SP) can be done in C, and indeed I have done so for my RAM-based loader code e.g.Code:extern char _loader_ram_start;extern char _loader_ram_end;extern char _loader_flash_start;// Copy loader code and its init data to RAM.memcpy(&_loader_ram_start, &_loader_flash_start, &_loader_ram_end - &_loader_ram_start);// Set SP to top of CCM. This is not where the general stack is normally 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.// NOTE local variables cannot be used after the SP load.asm volatile ("ldr sp, = 0x10010000 \n");Also as others pointed out years ago, the asm code is very obviously sub-optimal and written by kids.__libc_init_array- you confirm it is C++ only but when I was working on this I found it extremely hard to get a confirmation, so I left it inin linkfileCode:.preinit_array :{PROVIDE_HIDDEN (__preinit_array_start = .);KEEP (*(.preinit_array*))PROVIDE_HIDDEN (__preinit_array_end = .);} >FLASH_APP.init_array :{PROVIDE_HIDDEN (__init_array_start = .);KEEP (*(SORT(.init_array.*)))KEEP (*(.init_array*))PROVIDE_HIDDEN (__init_array_end = .);} >FLASH_APP.fini_array :{PROVIDE_HIDDEN (__fini_array_start = .);KEEP (*(.fini_array*))KEEP (*(SORT(.fini_array.*)))PROVIDE_HIDDEN (__fini_array_end = .);} >FLASH_APPand then I call __libc_init_array(void) which is not supplied in source form and lives in libc. I wasted a huge amount of time on this. But I am not 100% sure - see e.g. thishttps://stackoverflow.com/questions/49708591/use-of-libc-init-array-call-stm32removing call to SystemInit()- that call is partly duplicated later on in ST's codeBut only partly. Took me a while to unravel it all.STLINK-V3- I may be wrong but I think you need V3 to get the "high speed debugging UART" - the SWV ITM data consoleCode:/** Copied here from core_cm4.h.\brief ITM Send Character\details Transmits a character via the ITM channel 0, and\li Just returns when no debugger is connected that has booked the output.\li Is blocking when a debugger is connected, but the previous character sent has not been transmitted.\param  ch Character to transmit.*/static void ITM_SendChar_2 (uint32_t ch){if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */{while (ITM->PORT.u32 == 0UL){__NOP();}ITM->PORT.u8 = (uint8_t)ch;}return;}The rest is very good but since I have always used CUBE IDE (horrible to set up but somebody else did it for me) I can't usefully comment on it. A "make" is desirable only for bigger projects; today's PCs are so fast that a batch file based compile-all is fine. In the 1980s, a "make" was desirable again but because PCs were about 100x slower.Your English is outstanding!

author: wek
author_rank: Frequent Contributor
timestamp: March 25, 2024, 08:41:56 am
content: > startup_stm32f407xx.s - it is odd why this is in asmChicken/egg. Startup code is to prepare everything needed to run C, so how could startup be in C if it haven't had things prepared?OTOH, if that C is simple enough and doesn't use globals/statics, it should be fine. I personally don't like it because of the "fundamental" reason above.Also, what I don't quite get is the urge to set SP. I see that regularly. But, it's set by hardware from the first word in the vector table, after all. Is this some cargo-cult thing or is there any material reason for it? I couldn't find any hints. After all, cargo-cult followers don't know it's a cargo-cult, do they, so they can't report.> __libc_init_array - you confirm it is C++ onlyFollowing discussion here (also in your "CubeIDE is crap" thread) andelsewhere, I don't; the upcoming version of the 101.5 text is rephrased.My text is aimed at minimal. Your application is everything but (use of RTOS, printf()...). The more "magic" which comes with the tools you use, the less you will be able to kick out the "why would I need this" stuff.> STLINK-V3 - I may be wrong but I think you need V3 to get the "high speed debugging UART" - the SWV ITM data consoleSWO "UART Rx" is available in STLink/V2, too.> today's PCs are so fast that a batch file based compile-all is fineThere are merits of using make beyond speed, too, but generally, this is a valid point.> some libc functions are not reentrant (not in this thread, you've mentioned it elsewhere, but I think it's relevant to the "minimal" and "have control" overarching topic)It may come as a nasty surprise, but by the C standard, *none* of the standard library functions are to be considered reentrant. In other words, thou shalt not use e.g. abs() both in main and interrupts.(Also, the standard claims *all* symbols defined in the library chapter (C99 chapter 7) to be reserved, yes, writing your own abs() may result in nasty surprises and it did in the past - and I know you say the library functions as they are supplied with Cube can't be simply overriden - this is likely to be dependent on several minute details of how exactly things are compiled/linked, not just having library functions weak, and matter for further extensive painful discussion, not here and not now).Programs written so are not strictly conformant thus not portable. OTOH, who cares about strict standard conformance and portability? Isn't functionality the ultimate goal? Is there any relevant mcu *application* where code portability is of any concern whatsoever?Now for many library functions (e.g. <math.h>) it would be rather strange if they would be non-reentrant. I can imagine system-level library functions (i.e. those which are not covered by the "freestanding" clause of C99) to be non-reentrant - the printf()/scanf() family may be prime example, although <time.h> may be the prime counter-example, too.Here's newlib's documentation promising that only a portion of it is non-reentrant, and that they can be made reentrant too.JW

author: brucehoult
author_rank: Super Contributor
timestamp: March 25, 2024, 09:21:09 am
content: Quote from: wek on March 25, 2024, 08:41:56 amOn a VERY limited set of hardware: Cortex-M. It's not the case on RISC-V or 6502 or z80 or .. probably most others. Is it true on Cortex-A? I don't know but I think probably not.Cortex-M is particularly dumbed-down hand-holding hardware. Being able to put pointers to standard C API functions as interrupt vector is most unusual, for example. That costs both hardware (gates) and execution time for interrupt functions that don't actually need that many registers. But it makes training of new bare-metal programmers a little easier.

author: peter-h
author_rank: Super Contributor
timestamp: March 25, 2024, 10:20:56 am
content: QuoteAre you referring to the way ISRs can just be written in C, with no special code needed, and implemented via the magic numbers on the stack telling the CPU that it has just exited an ISR so no "RETI" is needed?I think that's quite elegant, although it does make interrupts a bit slower.QuoteYes; a fair point. I have done 40 years of asm so not complainingBut the startup.s stuff is entirely memset, memcpy, and I would hope those functions don't need any kind of setup.Code:.section .text.Reset_Handler.weak Reset_Handler.type Reset_Handler, %functionReset_Handler:/* SP for all of boot block/* If we have the extra 64k (32F437) then SP is adjusted later */ldr sp, =_estack/* Copy the boot block initialised data from FLASH to SRAM */movs r1, #0b LoopCopyDataInitCopyDataInit:ldr r3, =_si_boot_dataldr r3, [r3, r1]str r3, [r0, r1]adds r1, r1, #4LoopCopyDataInit:ldr r0, =_s_boot_dataldr r3, =_e_boot_dataadds r2, r0, r1cmp r2, r3bcc CopyDataInit/* Zero fill the boot block bss segment. */ldr r2, =_s_boot_bssb LoopFillZerobssFillZerobss:movs r3, #0str r3, , #4LoopFillZerobss:ldr r3, = _e_boot_bsscmp r2, r3bcc FillZerobss/* Initialise CCM RAM - fills the whole CCM */ldrr2, = 0x10000000 /* was _sccmram */bLoopFillZeroCcmFillZeroCcm:movs r3, 0xaaaaaaaa/* this fill intentionally differs from the a5a5a5a5 fill used by FreeRTOS for its stacks */str r3, adds r2, r2, #4LoopFillZeroCcm:ldrr3, = 0x10010000 /* was _eccmram */cmpr2, r3bccFillZeroCcm/* Initialise the 8k stack at the top of the 128k RAM. This is 32F417 only *//* For the 32F437, extra 64k, the fill is done later */ldrr2, = 0x2001e000 /* = _estack - _Stack_Size */bLoopFillStackFillStack:movs r3, 0x73737373/* fill with 's' */str r3, adds r2, r2, #4LoopFillStack:ldrr3, = _estack /* = 0x20020000 */cmpr2, r3bccFillStack/* Call the application's entry point - in this case the "main()" in the boot loader */bl mainbx lr.size Reset_Handler, .-Reset_HandlerQuoteGenerally I agree but it is good to be able to test "algorithms" on a PC, in M$ VC++ (or maybe some old C compiler, but stepping through the code is valuable). This can go quite a long way e.g. I have a win32 executable version of MbedTLS which can be used to access https websites and report why something isn't working, which is likely to be an absolute bastard to do in the embedded system.Good point about the SP getting preloaded, although Cube IDE still doesldr sp, =_estack

author: wek
author_rank: Frequent Contributor
timestamp: March 25, 2024, 12:33:44 pm
content: Quote from: brucehoult on March 25, 2024, 09:21:09 amYes; but isn't the startup code in question specific to that very VERY limited hardware?Quote from: brucehoultQuote from: peter-hYes that's what @brucehoult refers to; but theres more to it: multi-level nesting/prioritizing including the late arrival optimization, some lengthy instructions are interruptible/replayable in order to reduce latency, FP registers lazy stacking, tail chaining, maybe more.In all other "usual" processors, you are supposed to take care of all of these "manually", and/or just suffer whatever consequences there are. I like that level of hand-holding and gladly pay for the few millicent's worth of gates spent on that.Quote from: brucehoultI don't think so; most practical ISRs do need those 4 registers and more. I don't remember seeing a real-world ISR disasm without prologue pushing more registers. Of course, you can come up with an artificial counterexample whenever you want (*).And if you want to talk about wasted gates, what about the constants/tables (and associated address decoders) which nobody ever uses (among other things, because they often don't even conform to ARM's own specification)? So, no, I'd say, those gates in the interrupt logic were quite well spent.QuoteI doubt it. Given proper documentation, bare metal programmers usually have no problem understanding what RETI is and why.JW(*) actually, I've written one, but that was a rather idiotic attempt to salvage existing badly designed hardware, the "you surely can work around it in code, yeah?" kind

author: tellurium
author_rank: Frequent Contributor
timestamp: March 26, 2024, 12:11:46 am
content: Quote from: wek on March 25, 2024, 08:41:56 amIt is a common misconception that a startup code is required to run C.It is perfectly possible to have an ARM code with zero assembly.In fact I don't really understand why all these vendors keep writing their startup code in assembly, IMO it is just stupid.The startup code can be easily written in C.For example, look at Alex Taradov'shttps://github.com/ataradov/mcu-starter-projectsThis is ST project, with startup code in pure C, no assembly stuff:https://github.com/ataradov/mcu-starter-projects/tree/master/stm32g071The reset handler does everything required in C: initialises data, BSS , VTOR and calls main():https://github.com/ataradov/mcu-starter-projects/blob/243aa5aceaa7362263806fb52eca7bef28d2f597/stm32g071/startup_stm32g0.c#L144-L159

author: brucehoult
author_rank: Super Contributor
timestamp: March 26, 2024, 01:22:24 am
content: Quote from: tellurium on March 26, 2024, 12:11:46 amIt is on almost all CPUs.QuoteOnly because Arm went out of their way to enable this on the very simple Cortex-M cores by putting the vector table initially at a fixed address of 0, and included the initial stack pointer (which is not, in fact, the address of a handler) as the first entry, with special handling in the hardware to preload it intoSP.You can change the vector table address later, but only by using asm.QuoteIn the same project of Alex's, the startup code for FE310 uses inline asm to initspandgp, then falls though intoreset_handler(), which itself uses inline asm (in thewrite_csrmacro) to init themtvecpointer to the trap handler.Similarly, if there is an FPU (the FE310 doesn't have one) or vector unit then asm is required to turn those on. Also if you have a chip with User mode then you need asm to switch to running User mode code, and asm to init the PMP (Physical Memory Protection) unit so that the user mode code doesn't trap as soon as it tries to fetch an instruction (not to mention data reads and writes) which it by default has no privilege to do.This is perfectly normal and not a weakness. The only way to init all these things in C would be if CSRs were memory-mapped and that would be a pretty bad design for many reasons.

author: Circlotron
author_rank: Super Contributor
timestamp: March 26, 2024, 01:39:13 am
content: Quote from: pcprogrammer on May 29, 2022, 11:04:08 amBare metal??? Assembly or nothing!

author: SiliconWizard
author_rank: Super Contributor
timestamp: March 26, 2024, 03:18:52 am
content: And even so, you still need assembly to at least set up the stack (on ARM Cortex) and possibly other things like setting some CSRs (RISC-V) depending on target, so if you use C with inline assembly and you think you're a big boy not using any assembly, good for you. That's just delusion.In most cases for MCUs, the startup code, beside doing the above, will zero out the bss section and initialize data, you'll use memcpy() and memset() for this instead of a couple lines of assembly. If you think there's a lot to gain with that, again good for you. Whatever floats one's boat.

author: peter-h
author_rank: Super Contributor
timestamp: March 26, 2024, 07:12:24 am
content: Another thing is that constructs such asCode:src = &_etext;dst = &_data;while (dst < &_edata)*dst++ = *src++;are liable to be detected by the compiler and replaced with memcpy() memset() etc. This is an absolute bastard if your project involves a "boot block" architecture (needed for e.g. non-brickable firmware updates) because the boot block is highly unlikely to have access to stdlib, so this needs additional expertise either in the linking department which is a bastard area - the linkfile syntax - which almost nobody understands (note also the compiler won't be aware of the subsequent inability of the linker to find the relevant functions) or in using things like -O0 (no optimisation) attribute for that code. The GCC compiler option -fno-tree-loop-distribute-patterns to suppress loop structure detection is not reliable (acc. to my project notes from 2021). I wasted days on this stuff and with 40 years of asm from Z80 onwards I am not exactly unfamiliar with how that worksIt's OK if you document all this in the source but all I see is e.g.Code:* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE* POSSIBILITY OF SUCH DAMAGE.Remember that we are discussing code provided by STM (etc) for people who are often starting with some dev kit. These people are going to get totally stumped by issues like above. Anyone not believing this, visit the ST forumAnd, probably, unless you are using -O0, the loop identification exposes the project to a compiler version dependence. Already, just now, Cube 1.15.0 (GCC v12) breaks a load of stuff, one of which is some "executable" complaint from the linker. Yet more work...The great thing about asm is that it never gets touched.

author: wek
author_rank: Frequent Contributor
timestamp: March 26, 2024, 08:14:37 am
content: Control (as in microcontroller) is the name of my game.This very thread, and especially the __libc_init_array() discussion, is the proof, that when using C you are exposed to whatever other strong minded people put in there.And that "it's normal to have startup in C, everybody does that"? Well, there's a bunch of things "everybody does". I try to understand what others do, how they do that and why(*), because there may be genuine reasons; but just too often there are little to none, and I try not just follow the masses blindly. It's their leg, their shot. I am responsible for mine.> Bare metal??? Assembly or nothing!:-D , but world is somehow not black and white.JW(*)> In fact I don't really understand why all these vendors keep writing their startup code in assembly, IMO it is just stupid.Can you please explain, why do you think it's stupid? Whatever I wrote above, I am genuinely interested in what's the reasoning behind this, except "it's possible".

author: tellurium
author_rank: Frequent Contributor
timestamp: March 26, 2024, 08:49:01 am
content: Quote from: wek on March 26, 2024, 08:14:37 amPlease note that the "stupid" remark was given to the VENDOR's startup code that they ship with their IDEs and CMSIS packages.I understand that some assembly would be required. But definitely not the whole startup file should be in assembly. Just few snippets, like setting specific registers, and that's all. Initialising data, BSS, vector table - can be perfectly done in C, and it will be much more readable and understood code.So the argument here is clarity. If it can be written in C, in a much more clear way than in assembly, then why shouldn't it? Is there a reason? What's the reason?I am a bit surprised to be asked giving reasons for "C vs assembly" argument, to be honest.

author: peter-h
author_rank: Super Contributor
timestamp: March 26, 2024, 09:00:25 am
content: The reason, as posted above, is obscure side effects, unpredictable compiler optimisation, etc.Another thing, usually but not always immaterial, is that you can't just "write code" in C. You can only write a Cfunction, so a stack frame will get set up, as shown e.g. herehttps://www.eevblog.com/forum/microcontrollers/is-st-cube-ide-a-piece-of-buggy-crap/msg5412443/#msg5412443So you aren't getting simple direct code at startup.

author: wek
author_rank: Frequent Contributor
timestamp: March 26, 2024, 10:36:29 am
content: Quote from: tellurium on March 26, 2024, 08:49:01 amOK, I see. Thanks.Quote from: telluriumSurprise is mutual; I did not expect to list the counterarguments here.JWPS. I don't mind to receive what others might see as (lightly) offensive, as long as it's delivered in a friendly manner within a relevant argument, which is what's here. I'm in fact glad when my errors are pointed out in such apt manner. I believe this is a more accepted behaviour in Eastern Europe than in the West.

author: peter-h
author_rank: Super Contributor
timestamp: March 26, 2024, 11:31:34 am
content: QuoteDo you mean being polite is more desirable, or the opposite?There is a bunch of us ex Soviet Bloc guys in this threadIME, the level of politeness depends strongly onwherein the Soviet Bloc one is from.In W Europe, the level of politeness depends strongly on the country, as any forum admin will tell you

author: jnk0le
author_rank: Regular Contributor
timestamp: March 27, 2024, 01:45:11 am
content: Quote from: tellurium on March 26, 2024, 08:49:01 amBe aware that there seems to be a competiton on who will write the worst startup code in assembly so the C one doesn't look too bad.ABI overhead may make the prologue and libc calls more expensive than doing it inline (not counting memcpy itself).With the assumptions about the section layouts you can get to something like those:https://github.com/jnk0le/simple-crt/blob/master/cm0/combotablecrt_stm32f030x6.Shttps://github.com/jnk0le/simple-crt/blob/master/ch32v003/combotablecrt_ch32v003x4.S(no, compilers cannot optimize around linker symbols like this)

author: peter-h
author_rank: Super Contributor
timestamp: March 27, 2024, 07:34:57 am
content: What does "branch to cmp first and escape from scattered space" mean??

author: wek
author_rank: Frequent Contributor
timestamp: March 27, 2024, 01:31:22 pm
content: > What does "branch to cmp first and escape from scattered space" mean??@jnk0le's code uses space in the vector table which is not used and usually just filled with zeroes (that's "scattered space").The whole comment is probably a copy/paste artefact and probably leftover from a different Cortex-Mx startup where there was not enough "scattered" space, and the "cmp" (which probably refers to check for end of loop) was outside of it.JWPS.> Do you mean being polite is more desirable, or the opposite?Politeness is not a goal in discussion, but a tool. If "this is stupid" from context meant "I believe this is not optimal and it could be done better, ask me and I'll explain", then to me this level of not being polite is okay, delivering the message faster and with a degree of personal engagement. Context is extremely important here, and, as you've said, the "general context" is (also) geographically dependent; and if in doubt, it's just better to keep to be polite.

author: peter-h
author_rank: Super Contributor
timestamp: March 27, 2024, 04:49:06 pm
content: OK but putting executable code into holes in the vector table must rank alongside self-modifying code, like modifying the offset inld a, (ix+23)I suppose it safeguards your employmentI agree re politeness but too many people don't follow that rule. The non-following of it also tends to correlate with the rate of posting

author: jnk0le
author_rank: Regular Contributor
timestamp: March 28, 2024, 12:26:01 am
content: The offending part is about efficiently skipping the first loop iteration (in case section is empty) while escaping the 8 byte areaSo far I have found no way to get around those skips (like discarding a section if other section is empty) for more "normal" startups.Quote from: peter-h on March 26, 2024, 11:31:34 amThat depends also on the native language affecting those discussions. Russian is known to be the opposite of the native british in terms of that "politeness".Quote from: peter-h on March 27, 2024, 04:49:06 pmThere is more generic one as well:https://github.com/jnk0le/simple-crt/blob/master/cm0/crt_cm0.S

author: peter-h
author_rank: Super Contributor
timestamp: March 28, 2024, 07:46:45 am
content: QuoteAn understatement of the year.

author: wek
author_rank: Frequent Contributor
timestamp: March 31, 2024, 11:38:10 pm
content: Updated101 and halfwith "flashing" and removing C++ reference in description of __libc_init_array(), which now also links to205.Writing this one was very frustrating.JW

author: peter-h
author_rank: Super Contributor
timestamp: April 01, 2024, 07:45:15 am
content: Good writeup.Yes what a mess this __libc_init_array() stuff is. In my project, stepping shows that a loop there is executed 3 times, but I didn't spend time working out the addresses of the functions called. Basically, some functions in the libc.a library use static variables which need initialisation: stuff like malloc, printf, etc.I replaced printf anyway with a version which is multi-threaded and does not need mutexes; details posted in previous threads.

author: bostonman
author_rank: Super Contributor
timestamp: April 02, 2024, 05:29:01 pm
content: I just began reading this thread and the original link to the write up.Being a person who has a general/basic understanding of programming, the difficulty I find is that most tutorials lead you down a rabbit hole and/or branch off in different directions rather than define the necessities upfront.Often times I find tutorials to just use terminology as if the reader already knows their meaning and/or the purpose of environments (or whatever they are called) needed to be installed in order to run code.A basic tutorial for me would be defining the minimum pieces needed and their meaning/usage along with the end goal result(s).An example is a C program where we want Hello World!. Tutorials I'd like to see would be to list the minimum items needed to perform this, what they do, why they are needed, and, the end result (in this case display Hello World).Recently I've been contemplating whether I want to try going down the path of learning some basic microcontroller code because I'm seeing more designs use these, but also wanted to tinker with PICs for a while too (and recent confusion was whether I want PICs of PICaxes).So personally I'd enjoy seeing a general flow necessary to program a micro, something very basic without deviating too much. Maybe the items needed to write code, program the chip, etc... which instructions are available so the user knows what the chip is capable of (an example is how do I go from Hello World in a C program to utilizing this knowledge in a micro?), etc...

author: peter-h
author_rank: Super Contributor
timestamp: April 02, 2024, 08:19:17 pm
content: There is a LOT to know to output Hello World on an embedded system!Firstly, what do you want to output it on? A serial port, to feed into say Teraterm, via a RS232 to USB adaptor? That would be the easiest by far.

author: bostonman
author_rank: Super Contributor
timestamp: April 03, 2024, 01:55:57 am
content: QuoteIt was more of a statement meaning C is taught or someone has a desire to learn. The books all have you learn Hello World (as with other languages too), math functions, etc... but I've never seen a basic/simple explanation how to go from that to implementing that knowledge into a micro.

author: brucehoult
author_rank: Super Contributor
timestamp: April 03, 2024, 03:55:29 am
content: Quote from: bostonman on April 03, 2024, 01:55:57 am"Hello World" is only basic if someone hands you a working "printf", which itself consists of thousands of individual instructions.Ok, "puts" is a bit simpler, but people usually assume they will be able to output integers as well, if not floating point (that part that really IS thousands of instructions).

author: wek
author_rank: Frequent Contributor
timestamp: April 03, 2024, 06:44:06 am
content: Quote from: brucehoult on April 03, 2024, 03:55:29 amOn PC (and alike), the bulk of that complexity from the user program is taken over by the OS, which by itself is a HUGE program.There's no OS on mcus, that's why blinky is the Hello World! of mcu world.I though that 101 is clear in this regard, and also it was aimed at answering exactly the questions@bostonmanthrew up above. Apparently, I failed miserably. Sorry.JW

author: wek
author_rank: Frequent Contributor
timestamp: April 03, 2024, 06:55:37 am
content: Quote from: bostonman on April 02, 2024, 05:29:01 pmThis, for example is a seemingly innocuous question, which has several extensive answers, depending on who is asking and why.My dad recently asked me, how can he make some text he writes, bold. Context is, in any random editor (mainly web-based) he happens to be using. Another context is, he was not very familiar with the concept of Ctrl/Alt/Shift-based keybord shortcuts (btw. Ctrl-B may not be as universal as it may appear at the first glance).(He had an even better one: how could he have a single keyboard layout for all the central-european languages he's using...)JW

author: peter-h
author_rank: Super Contributor
timestamp: April 03, 2024, 07:01:12 am
content: I think one could do this but it would be a detailed "recipe", which in the simplest case would use a batch file (no IDE) to compile, link, and load to an STLINK debugger, and using a specific ST dev board. But it would be a dead-end.Or one could do a detailed "recipe" using Cube IDE, a frozen version (in my case 1.14.1) to do the same thing. I am actually doing this right now so others can continue with my project. This is better because for all its faults Cube IDE is a very capable tool and effectively conceals the huge complexity of any actually usable setup. Just doing an LED blinking example will get the user to rapidly get an LED to blink but then he hits a brick wall when he wants to implement some printf to output text (via SWV (which needs Cube IDE running), a UART, or whatever). Cube is ST copyright so ultimately it will not be possible to do this "quite legally" because older versions disappear from the ST website after a few months, but I am sure ST could not care less if somebody knocks up a website hosting say 1.14.1 Cube IDE installer (1GB). This way would enable someone to get going with a more complex functionality and for hardware they can do what almost everybody does: start with an ST dev board and use the schematics as the basis for the custom product. The other problem with this - far more useful - approach is that you cannot generate the code anywhere near wholly using MX, due to the number of bugs which need fixing to make stuff like USB VCP actually work properly. And nobody involved in a commercial product will want to give away the fixed source code. Look at the mess with the ETH - LWIP integration, with "piranha" on the ST forum posting snippets which I am sure work (within some specific code, which never gets posted) but which few people can use. Most people doing embedded for real and who have fixed code are doing it commercially.The ST Cube MX + dev board approach gets people going quickly with blinking an LED, and then the ST forum fills up with 10000 people asking desperate questions about how to do the next thing... and nobody is helping them, because nobody can help somebody, at that level of competence.

author: bostonman
author_rank: Super Contributor
timestamp: April 03, 2024, 04:50:33 pm
content: QuoteI wasn't trying to imply your work wasn't clear or not appreciated. If anything, I had more appreciation someone took the time to create such a document and hope you didn't take anything the wrong way.My problem is clearly that I haven't devoted extensive time to programming. Many others have dove deep into programming starting from scratch and for many years, whereas I have familiarity with many languages, but feel overwhelmed by the various tools to create a program. Usually when I get interested in programming, I find myself spending more time trying to figure out and/or learn the basic tools to start than I do actually understanding the foundation.What I've noticed is: someone can ask one programming question such as a good compiler, or IDE, or whatever, and get ten different answers from ten different people. This isn't a bad thing, but when the information is coming at a person like a wave, it can become overwhelming; this was the main reason for my feedback.With say C, I know the initial steps, a goal (print Hello World), and then know it needs to be compiled. While this is the general steps for many programming areas, I know enough about C to keep it simple with say Notepad++, GCC compiler, and run the .exe.My point above wasn't your write up, it was more about how complex programming is and how many easily get confused.

author: peter-h
author_rank: Super Contributor
timestamp: April 03, 2024, 07:01:51 pm
content: QuoteAnd there is the problemIn our world there is no .exe. In the PC command line (DOS, win16, win32) world you could literally type (here is Borland C++ which I used for years for this sort of hacking)bcc hello.cand then run hello.exe withhelloand you get "hello world" on the console. That kit is set up to literally do that.Same in the unix world where you use "cc", and the executable is not a .exe and has no filetype (the executable status is in the file attributes). That is all designed to just work like that.In embedded it is a lot more complicated, but also a typical embedded system has a ton of I/O which needs to be sorted out somehow. And everybody is doing something different.

author: bostonman
author_rank: Super Contributor
timestamp: April 07, 2024, 02:56:38 pm
content: QuoteWish I got into more in depth programming when I was younger to have a better foundation now. Maybe it's me, but find the stuff comes at me like a tidal wave when I begin getting bombarded with all the terms.