Memory model for Microcontrollers - Page 1
Forum section: electronics / general

author: Kittu20
author_rank: Regular Contributor
timestamp: April 30, 2024, 05:58:01 pm
content: Hi there,I came across this linkhttps://www.geeksforgeeks.org/memory-layout-of-c-program/amp/explaining the C memory layout and how variables are stored in memory sections. The example used here involves a PC.I'm curious to know if this memory model is also applicable to microcontrollers like 8051, PIC, AVR, and ARM. Have you used this c memory model for these microcontrollers?

author: mariush
author_rank: Super Contributor
timestamp: April 30, 2024, 06:02:54 pm
content: Aren't you the same person that asked this here ?https://www.avrfreaks.net/s/topic/a5C3l000000BqGsEAK/t391526

author: tggzzz
author_rank: Super Contributor
timestamp: April 30, 2024, 06:07:50 pm
content: Have a look at the OP's record, w.r.t. the number of topics started and the number of times they responded in their thread, the question's depth and the use of search engines.Form your own opinion.

author: Kittu20
author_rank: Regular Contributor
timestamp: April 30, 2024, 06:28:00 pm
content: Quote from: mariush on April 30, 2024, 06:02:54 pmYes, that was me. However, my question wasn't fully resolved or clarified, so I was hoping to gain more insight or a different perspective this time

author: Kittu20
author_rank: Regular Contributor
timestamp: April 30, 2024, 06:34:21 pm
content: Quote from: tggzzz on April 30, 2024, 06:07:50 pmI understand that this topic might be easier for you to grasp, but I'm finding it quite challenging. That's why I've approached my question a bit differently this time, hoping to gain more clarity.

author: pcprogrammer
author_rank: Super Contributor
timestamp: April 30, 2024, 06:51:09 pm
content: Think about this, "how much random access memory is there available on my microcontroller" and then think about wasting it with lists that keep track of the usage of this memory.When you only have 2K of RAM you don't waste it with the usage of malloc, you just declare variables or buffers for your tasks and forget about heaps as much as you can.

author: PlainName
author_rank: Super Contributor
timestamp: April 30, 2024, 09:30:24 pm
content: QuoteDynamically allocating storage can allow you to store more things than you have space for had you used static allocation. You just can't store them all at the same time, but that may be perfectly OK in the application. For a small micro you would probably have a combination, with dynamic memory being allocated from a block of statically allocated memory.Er... and malloc isn't the be-all and end-all of dynamic memory. Indeed, if you think that's how it has to be done then you could well be missing some really useful techniques.

author: tellurium
author_rank: Frequent Contributor
timestamp: April 30, 2024, 11:42:14 pm
content: NOTE: This message has been deleted by the forum moderator Simon for being against the forum rules and/or at the discretion of the moderator as being in the best interests of the forum community and the nature of the thread.If you believe this to be in error, please contact the moderator involved.An optional additional explanation is:

author: Kittu20
author_rank: Regular Contributor
timestamp: April 30, 2024, 11:55:18 pm
content: I think that the C memory layout sections like .text, .data, .bss, .heap, .stack depend on the type of microcontroller and compiler. We cannot view these memory sections for 8051 and PIC microcontrollers because they do not support them, whereas we can view these sections using STM32CubeMX and STM family

author: Kittu20
author_rank: Regular Contributor
timestamp: May 01, 2024, 12:01:45 am
content: Quote from: tellurium on April 30, 2024, 11:42:14 pmI apologize if I'm struggling to grasp the concept. I am trying my best I genuinely want to learn and appreciate any guidance or explanations provided. Please feel free to share your insights or suggestions on how I can improve my understanding. Thank you for your patience

author: langwadt
author_rank: Super Contributor
timestamp: May 01, 2024, 12:22:41 am
content: Quote from: Kittu20 on May 01, 2024, 12:01:45 amyes it is similar, that's how C works, though for an MCU with flash it is more like this.https://shatteredsilicon.co.uk/wp-content/uploads/sites/7/2021/01/Embedded-Memory-1.png

author: radiolistener
author_rank: Super Contributor
timestamp: May 01, 2024, 01:04:12 am
content: Quote from: Kittu20 on April 30, 2024, 05:58:01 pmDifferent MCU has different memory layout. They may have different architecture, for example some of them may have separate address space for program and for data and other have the same address space for both.

author: Nominal Animal
author_rank: Super Contributor
timestamp: May 01, 2024, 02:47:57 am
content: Kittu20, are you familiar with the termaddress space? Simply put, it means that a given address, say address 24, can refer to completely different things, if there is more than one address space.Let's do a deep dive into the subject. (For those annoyed at my wall of text posts, I apologize; in my defense, I do believe the below information is useful or perhaps even necessary for learners interested in embedded/microcontroller development.)On x86 and x86-64 (= AMD64), there are two address spaces: memory and I/O. I/O addresses use different machine instructions (INandOUT) compared to normal memory accesses. 32- and 64-bit x86 and x86-64 also supportvirtual memory, where a privileged kernel can control what addresses unprivileged code can access, and map different physical memory addresses to the address space the unprivileged code can see. Because of security reasons, current fully-featured 32-bit and 64-bit operating systems useaddress space layout randomization, where the actual address ranges used by some code are varied at run time. The binaries they run containrelocation records, so the run-time linker can "fix" the code and data to refer to the correct randomized addresses.Aforementioned x86 and x86-64 are based on thevon Neumann architecture, where code and data uses the same address spaces. Older AVRs for example useHarvard architecture, where code and data use separate address spaces (and even separate machine instructions, LPM/ELPM/SPM for program memory, LD/ST et al for data memory).Clang supports multiple address spaces for both C and C++, but GCC currently only for C. This is why the Arduino environment is so "messy": it uses its own preprocessor, butg++(GNU GCC C++ compiler) for compiling, which only supports von Neumann architectures; but to work for Harvard architectures, the Arduino developers had to cut some corners. For example, strings in RAM and strings in Flash use different functions (_Psuffix in function name). (In my opinion, because of this, C is more powerful language for older AVRs than C++ is, unless you limit yourself to Clang. When the compiler can understand pointer and variable address spaces, you can use much less RAM and Flash, and leave the compiler to optimize the low-level accesses as best it can. I like that.)ARM Cortex-Mmicrocontrollers use a single address space for everything. Different types of memory and even peripheral devices are accessible at different addresses. It is amemory-mappedarchitecture; one subtype of von Neumann architectures.Most embedded development toolchains nowadays useELFformat object files. Every code and data object (or "thing" in general) in ELF object files always belong to a specificsection. By default,.textsection corresponds to code,.datato initialized variables,.bssto uninitialized variables, and so on; but this is just a convention, not a requirement. When compilers generate code or allocate global variables, they do not assign them a fixed address, but an address relative to the relevant section. The compilers even allow you to specify the section name yourself, if you want. If you want to refer to a fixed address in your C or C++ code, you normally do so via a pointer: you declare a pointer to the code or data at that fixed address, and set the pointer value to that address.When the different ELF object files are linked to form an executable or an embedded system firmware image, it is thelinker–– often executed automagically by the compiler –– that decides the addresses at which different sections will occupy. The way it does this is controlled by alinker script. Fortunately, at least GNU/GCC/binutils (ld and gold) and Clang (LLVM LLD) linker scripts use the exact same format, documentedhere.In practice, this means that if you declare structure variables describing a memory-mapped peripheral, you can assign it a specific section, sayhw_name, and in the linker script, assign it the correct start address. If you have device variants where the addresses vary but the structures stay identical, you can just create a different linker script for each variant.As an example, consider Teensy 3.x, programmed in the Arduino environment, using the Teensyduino add-on. Thecore support files are here, including the linker scripts formkl26z64(Teensy LC),mk20dx128(Teensy 3.0 and 3.1),mk20dx256(Teensy 3.2),mk64fx512(Teensy 3.5), andmk66fx1m0(Teensy 3.6). There are some#if defined(__MKxxxx__) .. #endifsnippets in the C/C++ code accounting for differences in e.g. peripherals, but the same codebase supports all these different Cortex-M0 (LC), Cortex-M4 (3.0, 3.1, 3.2), and Cortex-M4F (3.5, 3.6) microcontrollers.(sdcc AKA Small Device C Compiler, used for e.g. Intel MCS51 (8051 et al), HC08, Z80, MOS 6502, Padauk pdk14 and pdk15, et cetera, doesn't really use ELF format object files; its linkers take command-line arguments specifying the details that provide roughly similar but very limited functionality compared to "bigger compilers'" linker scripts.)In summary, this means that there is no fixed order or mapping for the different sections, at all. Sometimes the processor/microcontroller, bootloader, and/or the board requires specific addresses for specific things, like peripherals at specific address range, RAM at another, Flash at yet another, maybe PSRAM in yet another, and so on, but the rest –– especially RAM use for initialized and uninitialized data, heap, and stack –– is up to the linker script (or equivalent configuration when using e.g.sdccthat has no explicit linker script).Footnote:GCC and Clang compiler options--ffunction-sections --fdata-sections -Wl,--gc-sectionsutilize ELF section and relocation information to drop completely unneeded code and data from the final linked object. It does this by using a separate code/data/bss sub-section for every function, variable, and object. Because ELF relocation records are section-specific, simply checking whether there are any relocation records targeting a section, the linker can tell whether the function/variable/object is used or not.I use ELF section supportextensively, both in embedded development, and when writing POSIX/GNU C for Linux/MacOS/BSDs. The most useful case is declaring structures in separate source files, and have the linker collect them into a single contiguous array. If you use Linux, you might want to examine myRPN calculator example: in this one, you can create new mathematical operators and declare them in a new C source file, compile it, and link it to the final binary, and the operator will be automagically available.The one downside to this is that the order of the elements in the final array is unspecified: you cannot rely on the array elements being in any specific order.I've written a few tools to deal with this –– I'd love to have e.g. an external Python script to be able to sort or reorder the entries, without changing their contents (Python because GDB also supports helper "commands" written in Python); or to add a perfect hash table for the entries (say, for command lookup) –– but I'm still investigating how to make that robust enough for my paranoid tastes.

author: pcprogrammer
author_rank: Super Contributor
timestamp: May 01, 2024, 06:29:38 am
content: Quote from: PlainName on April 30, 2024, 09:30:24 pmIt very much depends on your application of course, but for the things I do I yet have to run into an application that needs to share the available memory between different tasks. In fact I try to stay clear of standard libraries as much as possible and do everything with basic C.When the need arises to use some of the same memory for different tasks I won't be using malloc either.

author: langwadt
author_rank: Super Contributor
timestamp: May 01, 2024, 07:56:45 am
content: Quote from: pcprogrammer on May 01, 2024, 06:29:38 amthen how do you manage to run any C at all without a stack?

author: pcprogrammer
author_rank: Super Contributor
timestamp: May 01, 2024, 08:05:15 am
content: Quote from: langwadt on May 01, 2024, 07:56:45 amStack is part of basic C, so that is used and taken into account.Same as when programming in assembler, there is a reserved amount of memory for the stack.

author: SiliconWizard
author_rank: Super Contributor
timestamp: May 01, 2024, 08:05:33 am
content: Quote from: langwadt on May 01, 2024, 07:56:45 amObviously the concept of "sharing memory" and even "dynamic allocation" is a bit elastic for many. Yes, many do not even realize that the basic stack, that you can't really do without in C that I know of (or that would be a bastardized variant of C), is both "shared memory" (unless you have separate stacks for separate tasks, but that would require some "manual" handling) and "dynamic allocation".

author: pcprogrammer
author_rank: Super Contributor
timestamp: May 01, 2024, 08:19:41 am
content: Quote from: SiliconWizard on May 01, 2024, 08:05:33 amStack is basically part of the processor and you need it to be able to return from subroutines. There are processors that have multiple hardware stacks for user, system and or interrupt tasks. Then there are also software stacks that can be used of course. It all depends on programming languages, compilers and interpreters.Declaring a lot of local variables in a function might be cause for stack overflow when the compiler uses the hardware stack for these, depending on how much stack space you reserve, so it is always good practice to think about where what data goes. That is why I have always liked old fashioned assembler, the total inside in how memory is used, as long as you write all the code yourself of course. A "modern" instruction set like for ARM is less fun because of the complexity of it. So many possibilities.

author: Nominal Animal
author_rank: Super Contributor
timestamp: May 01, 2024, 10:29:52 am
content: Many linker scripts I've seen use a single consecutive RAM area for heap and stack, with heap growing upwards and stack downwards. This way, the application code gets the best use of the leftover RAM, regardless of whether it uses deep stack (recursion) ormalloc()-style dynamic allocation. The risk, of course, is that the two collide.One of my favourite AVR microcontrollers is theATmega32U4, because of its native USB 2.0 (High Speed, 12 Mbit/s, and Low Speed, 1 Mbit/s) interface and instruction set well suited for C compilers. It has only 2.5k of SRAM, 32k of Flash, and 1k of EEPROM, and 832 bytes dedicated for USB endpoint, so it is definitely limited by today's standards; but pretty darn nice for keyboards and other USB Human Interface Devices and USB-to-Serial/SPI/I2C stuff, when using freestanding C (i.e., without standard C library) on bare metal. Fortunately, it has 32 general-purpose 8-bit registers (six of which are used as three 16-bit pointer registers), so most local variables in functions stay in registers, not using any RAM.As it is Harvard architecture, Flash (program) and RAM (data) use separate address spaces. It also has a somewhat separate I/O address space, and a yet another address space for EEPROM.Using initialized global variables (datasection) costs both RAM and Flash, because their values need to be copied from Flash or EEPROM to RAM during bootup. However, it is cheap to clear the RAM. GCC and Clang support putting zero-initialized variables intobsssection (-fzero-initialized-in-bssoption, enabled by default). Thus, programmers targeting small microcontrollers benefit from designing their global variables to be initialized to all zeros. On ATmega32u4, there is "lots" of Flash compared to RAM, so this is not really an issue, but is still useful to know for bare-metal programmers.With 2.5k of RAM, you don't usually use heap at all viamalloc()-style functions. Sometimes, a stack-like heap can be useful, with either "push" and "pop" style functions, or with allocation moving the heap boundary and release/free reverting the heap to a previous state (so that any intervening allocations are also released/freed). This way there is no bookkeeping needed to track allocations, and the overhead is minimal. This also behaves nicely when the stack grows downwards. There also isn't any "heap" section per se, because such a "heap" occupies the same contiguous otherwise unused RAM as the stack is in, and basically relies on the stack not growing large enough to overlap with the "heap".If we consider the original question for ATmega32u4, text will be in Flash (program memory) in its own address space, and stack + heap + data in its own address space. Stack and heap often occupy the same address range (often at the upper end of the RAM address range), with stack growing downwards and any heap allocations upwards. Depending on the developer, there may not even be an initialized data section, only a zero-initialized "bss"-type section –– and that can be surprising, with global variables initialized in ones C code having unexpected random or zero values on the microcontroller ––; but supporting both (non-zero)-initialized and uninitialized/zero-initialized data costs only the additional Flash space for the bootloader function and Flash/EEPROM space to hold the initial values.The take-away is that a developer using GCC/Clang toolchain for ATmega32u4 AVR microcontroller has quite fine-grained control of the memory layout (at the bootloader and linker level), and can tune the details to best suit their needs.

author: brucehoult
author_rank: Super Contributor
timestamp: May 01, 2024, 10:31:15 am
content: Quote from: pcprogrammer on May 01, 2024, 06:29:38 amI don't know what you're doing but it is EXTREMELY common for applications, including deeply embedded ones, to operate in two phases 1) initialization, 2) a loop processing events. It is very common for initialization to need to use a good amount of memory temporarily, which can then be freed before running the main loop, which can use that memory for other things. Some of that might be on the stack, but not all.Even when it can be on the stack, you need to structure your code carefully into functions so that init memory actually IS freed e.g. don't do init in the main program, but call a function for it.

author: pcprogrammer
author_rank: Super Contributor
timestamp: May 01, 2024, 11:17:27 am
content: Quote from: brucehoult on May 01, 2024, 10:31:15 amI guess I should have added "for embedded coding", but since this thread is about microcontrollers it is basically implied.The things I do with microcontrollers are mostly, small MCU based, simple control devices, like the FT remote control I wrote about, and the initialization done for this kind of things is trivial and mainly configuring of peripheral registers, so no or not a lot of additional memory needed. For the more demanding stuff I might use the standard libraries and even dynamic memory allocation, but only if there is plenty of memory available.On a big computer it is a different story. There is an OS to work with and memory management that makes things a whole other ballgame.

author: tellurium
author_rank: Frequent Contributor
timestamp: May 01, 2024, 11:18:29 am
content: Quote from: Kittu20 on May 01, 2024, 12:01:45 amYou do not struggle with anything, cause you're a bot.A person that wants to learn, shows a totally different pattern. Asks specific questions, follows up on explanations.The topics that you start are way too broad. So different all the time. Questions are never specific. And you never seem to learn anything, years after you asked.It's a shame to see people reply. Well, maybe there is a merit to it, as other engineers may learn reading those threads.

author: brucehoult
author_rank: Super Contributor
timestamp: May 01, 2024, 11:23:41 am
content: Quote from: pcprogrammer on May 01, 2024, 11:17:27 amMy reply was about embedded programming.QuoteIf any additional memory is required at all then reclaiming and reusing that memory can allow you to run on a smaller and cheaper chip. For example one with 512 bytes of RAM instead of 2k. Or maybe even one with 32 bytes of RAM/registers.

author: pcprogrammer
author_rank: Super Contributor
timestamp: May 01, 2024, 11:40:24 am
content: Quote from: brucehoult on May 01, 2024, 11:23:41 amIf needed sure, but these days devices with a nice amount of memory are cheap, and especially when you are a hobbyist it is not of much importance.I have never worked in a market where there was a need for a lot of cost saving, which might be called a luxury, and when the more sophisticated MCU's came around I was solely active in system management and web based software development. Only after I early retired I got back in the game of microcontrollers to discover this whole new world of very nice and fast gadgets to play with.Wonderful times coding in C where I used to do everything in 6502, Z80 or 8051 assembler. The portability of C for a lot of functionality is lovely. Fat change with assembler without a lot of work when changing the underlying processor.

author: mikeselectricstuff
author_rank: Super Contributor
timestamp: May 01, 2024, 11:59:28 am
content: Quote from: brucehoult on May 01, 2024, 10:31:15 amReally ? What sort of initialisation would need a significant amount of RAM temporarily ?

author: Kittu20
author_rank: Regular Contributor
timestamp: May 01, 2024, 12:59:56 pm
content: Quote from: tellurium on May 01, 2024, 11:18:29 amVery discouraging comment.Learning can be a gradual process, and everyone has their own pace and approach. I am trying my best if you have suggestions for improvement, I'm open to hearing them.

author: PlainName
author_rank: Super Contributor
timestamp: May 01, 2024, 02:07:15 pm
content: Since quite a few users thing you're a bot, perhaps you could post something to show that you're not. A screencap from your PC of this thread, perhaps, or stamped photo of something you're working on.

author: Kittu20
author_rank: Regular Contributor
timestamp: May 01, 2024, 02:43:40 pm
content: I have a many screencap photo to share. I am attaching few of them

author: tellurium
author_rank: Frequent Contributor
timestamp: May 01, 2024, 03:55:41 pm
content: Arduino "screen capture" is fromhttps://forum.arduino.cc/t/arduino-based-traffic-light-system/1144573st-link and terminal "captures" are also not a captures, but images from internet.I guess it is fine when people talk to bot. I just don't like being deceived that I talk to a person.

author: Kittu20
author_rank: Regular Contributor
timestamp: May 01, 2024, 04:14:02 pm
content: Don't you think we are moving from the main issues of the thread? By the way, I shared the photos that were on my mobile, and I have many other pictures as well

author: MK14
author_rank: Super Contributor
timestamp: May 01, 2024, 04:24:33 pm
content: Quote from: Kittu20 on May 01, 2024, 04:14:02 pmEDIT:I didn't realize the picture was perhaps put in, in jest, or for similar reasons. As later posts in the thread, would seem to indicate.At least one of the pictures, seems to trace through to an AI bot centre, or similar.Here:https://www.neosofttech.com/services/artificial-intelligence-machine-learning/

author: Kittu20
author_rank: Regular Contributor
timestamp: May 01, 2024, 04:34:43 pm
content: Oh come on, after reading the rest of the comments, I couldn't resist. So , I got up and now I'm clicking and sending pictures of whatever electronic items I have.It's ridiculous, man! It feels like I'm being accused and standing in court

author: PlainName
author_rank: Super Contributor
timestamp: May 01, 2024, 04:43:01 pm
content: QuoteWell, you were!But nicely played

author: pcprogrammer
author_rank: Super Contributor
timestamp: May 01, 2024, 07:54:18 pm
content: Quote from: Kittu20 on May 01, 2024, 04:34:43 pmI'm missing today's newspaper on the background to really prove it is your electronics stuff on the floor.And what tellurium did not seem to notice is that it is your post on the arduino forum. So for an alleged bot you do come around.

author: jnk0le
author_rank: Regular Contributor
timestamp: May 01, 2024, 09:07:02 pm
content: Lооkѕ lіkе ѕоmеоnе іѕ trоllіng wіth АІ ѕраmbоt ѕіmіlаr tо GРТ-4сhаn but thіѕ tіmе сараblе оf роѕtіng іmаgеѕ аnd lеѕѕ blаtаnt.mѕg5090590 іѕ раrtісulаrlу ѕuѕ - thіѕ іѕ nоt еvеn а сорураѕtе frоm аttасhеd dаtаѕhееt, еvеnlеѕѕ а роѕt рrоduсеd bу "lеаrnіng nеwbіе", but ехасtlу whаt сhаtgрt wоuld hаlluсіnаtе.Quote from: Kittu20 on May 01, 2024, 04:34:43 pmТhеу аѕkеd уоu tо роѕt а ѕсrееnѕhоt оf thіѕ thrеаd, nоt а rаndоm іmаgеѕ. Іf уоu аrе unаblе thеn Could you tell us why apples are bigger than dogs? This should help us solve your issue with memory model.

author: tellurium
author_rank: Frequent Contributor
timestamp: May 01, 2024, 09:09:58 pm
content: I am not convinced at all.People that REALLY want answers to their questions, behave differently. They ask, they double-check, they engage.That thing, Kittu, does not do that.Even on that Arduino post - not a single follow up. Even when asked a concrete question, a very vague, non-concrete answer was given.As it was pointed out, he asked the same question years ago inhttps://www.avrfreaks.net/s/topic/a5C3l000000BqGsEAK/t391526And what? Not a single follow up on that thread.Do I believe in the "It was different, I want to learn more" nonsense? I don't.Anyhow, I don't want to waste any more time on this. If you guys want to entertain the bot, your choice.

author: MK14
author_rank: Super Contributor
timestamp: May 01, 2024, 09:31:33 pm
content: (As already mentioned) In the following thread:https://www.eevblog.com/forum/microcontrollers/larger-and-more-complex-embedded-systems/msg5072800/#msg5072800Kittu20, seems to admit to using AI (ChatGPT etc), to formulate the questions, which perhaps explains why they appear to be a bot, even if they aren't.Quote from: Kittu20 on September 22, 2023, 02:25:28 amSo, it perhaps is no surprise, why so many people seem to think they are a bot.

author: MK14
author_rank: Super Contributor
timestamp: May 02, 2024, 10:55:52 am
content: I suspect, using ChatGPT to formulate your posts. Distorts, changes and hides, potentially important details about the REAL question, being asked.Hindering, people who want to help you.Sometimes, a person asking questions, really needs help in different areas. But, this 'ChatGPT' way for posting questions, in a thread, removes such important information.Also, it seems to make your questions, look like they come from a BOT, which means some people will then ignore the question and possibly you as a user, as a result.

author: tellurium
author_rank: Frequent Contributor
timestamp: May 02, 2024, 12:55:36 pm
content: Sure. An embedded engineer (from India!) does not know English.

author: MK14
author_rank: Super Contributor
timestamp: May 02, 2024, 12:59:43 pm
content: Quote from: tellurium on May 02, 2024, 12:55:36 pmI agree, there seems to be something 'funny' going on. But I'm not sure, exactly what.Vague guesses, would be they don't want others, to know who they are, as they are putting questions arising from their job, e.g. Automotive related.They could be trolling.Maybe it is some kind of 'bot' operation, with some (possibly) human, intervention, from time to time.Their posts, just don't seem 'right'.

author: Kittu20
author_rank: Regular Contributor
timestamp: May 02, 2024, 01:34:24 pm
content: Quote from: tellurium on May 02, 2024, 12:55:36 pmI think you are a bot that is trolling me here in a bad way. I've previously requested that you stick to the thread topic, but you repeating same things and I never said I don't know English; I simply mentioned that I'm not good in it. If you can't help someone, you shouldn't discourage them either. Everyone has their self-respect. You may be intelligent, but I am not, which is why I ask questions that I believe should be asked, but there's nothing beyond self-respect

author: Kittu20
author_rank: Regular Contributor
timestamp: May 02, 2024, 01:47:42 pm
content: Now I come back to the original question. I think memory layout is relevant for target devices like PC and ARM but not for 8051 and PIC microcontrollers. I need to look to MAP file.The map file shows a summary of all memory usage, including the locations of variables and functions.

author: pcprogrammer
author_rank: Super Contributor
timestamp: May 02, 2024, 02:06:10 pm
content: Quote from: Kittu20 on May 02, 2024, 01:47:42 pmDepends on whom are working on the project. If it is just you, then you should know about the variables and buffers being used in the code. When using third party libraries it becomes a different story. Depends on availability of source code or not.Furthermore it boils down to the tools that are available. With .elf files you can extract a lot of information with the different tools. I myself hardly use these kind of tools, because most of what I do is based on my own code, and for that I know what the variables are, and I don't care where they are in the actual memory, not until something does not work as expected and you need to debug.

author: peter-h
author_rank: Super Contributor
timestamp: May 02, 2024, 09:58:19 pm
content: QuoteThis is a difficult topic because there are huge numbers ofreal peoplewho are making postings purely to kick off discussions. The questions may come from ChatGPT or some such but the real person is present to deal with whatever fallout takes place.I run a tech forum (not electronics) and even though I am intimately familiar with the subject there, I sometimes struggle with this when somebody manages to start a thread which then continues into some good responses. Most people recognise when this is happening and don't bother to respond, but it varies.Whythey do it is a mystery. It is believed to be to generate text for ChatGPT etc (ChatGPT is no "AI" - it is just a very good piece of code which does statistical analysis on vast amounts of text, and it needs lots of relevanthuman-producedtext to work) but as far as anyone knows they are not getting money for this. I guess not having a life is as good an explanation as any. On my site we had a guy who literally spent 16hrs/day on his Ipad, generating thousands of posts per month. He ran multiple personas too... including a female which was a clever tactic because women get tons of engagement (a variation of the ancient "damsel in distress" method, which always works) in any male dominated community.If I was a mod I would delete any question posts which are just seeking to generate generic essays, but it is hard to do this when a) there are good responses by the time the mod sees it and b) the forum runsadvertswhich obviously need to generate clicks. Adverts are the big problem but that's another story...

author: MK14
author_rank: Super Contributor
timestamp: May 02, 2024, 10:17:08 pm
content: Quote from: peter-h on May 02, 2024, 09:58:19 pmThanks!That is an excellent response.Not being able to see the (hopefully) real people, who started a thread. Combined with also not knowing how much time and effort the original poster made, beforehand to answer the question(s) themselves, makes it rather tricky to know how to react.There are so many (freely in most countries), resources available, through search engines, Wikis and a huge range of books, some free, some library or purchase only. So the obvious question of why they didn't use those resources, instead, also comes to mind.Modern forums (just how you described), can provide a very quick and easy (lazy), way for someone with unsound motivations, e.g. trolling, they are bored, or they just like making threads (it gives them 'kicks'), for whatever reason(s). Can seem rather unfair, as a troll can create a partly silly, time wasting question, in a matter of minutes (or less, even).Causing others to waste time (in some but NOT all cases), responding to those threads or posts.It must be stressful, being a moderator, and having to decide, when to take no action, give a vacation (temporary ban, or other such things), or ban them, for a while or permanently.(As regards this thread) I suppose, it might not be out of malice, or related to ChatGPT/bots, but just be, that they perhaps need to consider improving the quality of their thread starting (opening) question(s).Otherwise, we could write a book load (quite literally), of replies, and still completely NOT answer the real intended question(s).

author: PlainName
author_rank: Super Contributor
timestamp: May 02, 2024, 10:34:38 pm
content: QuoteIf the questionable post generates good responses, isn't that what a forum is supposed to be about? Does it really matter what started it if there is proper engagement between posters, and people learn something they otherwise might not?It had crossed my mind that maybe Dave was behind this, seeking to distract from SMPU employment, water power and similar recurring subjects

author: MK14
author_rank: Super Contributor
timestamp: May 02, 2024, 10:48:22 pm
content: Quote from: PlainName on May 02, 2024, 10:34:38 pmI still don't like the idea, of possibly poorly written questions and/or bots and/or trolling. Creating the thread, in the first place.But you are right. It can in some cases, lead to rather interesting and education threads, as a result.

author: PlainName
author_rank: Super Contributor
timestamp: May 03, 2024, 09:39:47 am
content: Yes, my first thought is that it is wrong, but perhaps that's the emotional impact of feeling conned. There is a difference between someone giving you $5 because they won $100 and want to share their good fortune, and giving you $5 because their mates dared them go near that homeless **** and then laugh about it afterwards. In both cases you get $5 but you'd perhaps appreciate it more in the first case.

author: MK14
author_rank: Super Contributor
timestamp: May 03, 2024, 10:23:15 am
content: Quote from: PlainName on May 03, 2024, 09:39:47 amUnfortunately, as I see it. There is a technical danger, from an engineering knowledge point of view (in my opinion). With allowing, trolling and/or made up questions and/or too general, unspecific, created questions etc.Which is, that with 'real' questions, created from current real life issues. Such as, why does my circuit oscillate?Because, then, we can spend our engineering resources, solving the actual, real life problems and issues, that actually really occur.But completely made up questions. Can create situations, which don't really exist, and neither do the problems, posed by such questions.E.g. Why have I caught a virus infection, from my upstairs neighbor, from him using a secret, micro-wave, fiddly-sticks, memory mapped, ray gun at me, and how does he know where I'm located, at any given time?Plz hlp!But the thing is, it is (almost certainly) just the imagination of the OP's, possibly mentally ill state of mind (or trolling and/or technical misunderstandings), rather than a real, proper technical question. Probably mentioning, a number of things, which are not technically feasible or possible.

author: tellurium
author_rank: Frequent Contributor
timestamp: May 03, 2024, 02:58:58 pm
content: For those who'll read this thread - IMO the explanation by Nominal Animal is the most complete, I am talking abouthttps://www.eevblog.com/forum/microcontrollers/memory-model-for-microcontrollers/msg5478241/#msg5478241However I think it is a bit advanced. I'll take the liberty to put Nominal Animal's explanation in simple terms.Assume we take STM32 ARM microcontrollers as hardware, and GCC as a toolchain.The microcontroller's memory has many regions, and simply speaking, there are:a) flash region: contains firmware code. You can read bytes from that region as if it is a simple RAM , but writing to that region is a complex procedure.b) RAM region: you can read and write anything therec) peripheral controllers: memory-mapped IO. reading and writing to that memory produce special effects depending on a controller. For example, writing to a specific place inside a GPIO controller may turn GPIO pin (e.g. LED) on or off.|-------[ FLASH ]--------[ RAM ]----------------------[ GPIOA ]-----[ other periperals controllers....]------|So, that's what hardware defines. There is no .text, no .heap, nothing like that. Just those memory regions, and if you manage to create a firmware code - a .bin file, and write it to flash, that's all what matters. An MCU starts executing that code from the FLASH region, and the code can access RAM and peripherals, that's it.Now, you can use different programming languages / compilers to produce a firmware binary. If you use C, then your program is, simply speaking, a set of functions and variables. For example, this:Code:static int led_state; // A variable. Goes to the RAM region.void toggle_led(void) { // A function. Goes to the FLASH regionGPIOA->BSRR |= ..... led_state ... // A piece of code that accesses a variable from RAM region, and a controller in GPIOA region}int main(void) {....toggle_led();}The task of the toolchain is to produce a firmware binary. Inside the binary, as it stated above, there are no notions of .text/.heap/.data. Only machine codes, and data pieces at specific addresses.So how the toolchain produces that binary? There are several steps:a) GCC compiler compiles your code into the object files. Object files have ELF format. That format specifies so-called sections. Code (functions) go into the .text section. Data (variables) go into the .data section. Node that other languages can also produce ELF, so this is not really C specific.b) Produced object files linked together by a linker to produce an output firmware.elf file. A linker uses a "linker script" file that has instructions like this: "put .text section to the memory region that starts at 0x8000000, and .data section at memory region that starts at 0x20000000". Of course, 0x8000000 is FLASH region, and 0x20000000 is RAM region. That's the place where ELF sections are mapped to the hardware memory regions.c) An "objdcopy" tool extracts .text and .data sections from firmware.elf and concatenates them into firmware.bin. So essentially firmware.bin file is a collection of all functions, followed by all variables.That's it!Now, if you look closer, then you see that GCC would need to create two functions from the above examples: main() and toggle_led(). So in the FLASH memory, there will be a main() code, followed by the toggle_led() code (or vice versa). Likewise, for variables, there is a int variable "led_state" that needs to go into the RAM section. If there are more variables defined by the program, they will be placed in the RAM region one after another.That's what they call a compile-time allocation. When a linker is done with arranging functions and variables to appropriate places, it generates the .map file if the appropriate build flag is given.When all variables are placed in RAM, there is a free RAM space left. That will be heap. And at the very end of RAM region there is stack. So if we magnify RAM region, we'll see something like this:---[led_state|var2|var3|...|end| HEAP---> <-- STACK]-------|<--------------------------------- RAM --------------------------------->|Usually linker scripts mark the end of all variables with a special symbol "end", so that the malloc function may know where heap starts. Also from the linker script file, it knows where RAM ends, and what's the maximum configured stack size. That's how malloc knows its boundaries.This is my understanding of the memory model works, and its interaction with ELF sections. Note that this description is simplified, I've omitted a bunch of stuff like vectors, startup code and .data relocation, BSS, etc etc.

author: eutectique
author_rank: Frequent Contributor
timestamp: May 03, 2024, 04:32:07 pm
content: Quote from: tellurium on May 03, 2024, 02:58:58 pmA couple of hints (for posterity):I prefer to place heap and stack the other way round:---[ <-- stack] [led_state|var2|var3|...|end| heap---> ]-------Thus, stack will never grow to smash the variables on heap (producing mysterious bugs). Instead, it will stumble off the cliff and right into the safety net of a meaningful DataAbort handler.Also, my stack and heap are two distinct regions in the linker script, withorgandlencalculated relative to each other, so that--print-memory-usagelinker flag gives a nice and clear picture.

author: jnk0le
author_rank: Regular Contributor
timestamp: May 03, 2024, 04:43:32 pm
content: Quote from: peter-h on May 02, 2024, 09:58:19 pmThere is a lot of money involved in this kind of trolling if you consider potential use for psyops.Either by delivering it directly or just to farm a credible accounts to be used later by "professionals" (instead of e.g. a blatant "green accounts" that suddenly have a lot to say about the rus-ua war).And psyops term is not exclusive to the military grade ones, but even a trivial purposes like whistle marketing, or purely political.If there is demand, there are companies selling appropriate services.And if we are talking about commercial use, look at his 3rd photo:neosoft- looks like company name, there are multiple similarly named companies but this one (already mentioned) explicitly mentions "AI" in whole portfolio:https://in.linkedin.com/company/neosofthttps://www.neosofttech.com/services/artificial-intelligence-machine-learning/neosoft-ThinkPad-X270- default ubuntu hostname formatting:https://superuser.com/questions/734998/where-does-ubuntu-get-the-default-hostname-W10DG- most likely inventarization number, typical in corporations- offending company is also located in India- reverse image search yields this thread only (unlike the "traffic light" or ebay/aliexpress one:https://irq5.io/2017/07/25/making-usbasp-chinese-clones-usable/used herehttps://www.avrfreaks.net/s/topic/a5CV40000000ajRMAQ/t394567)- what is even the purpose of photografing this, are we yet to see another GPT-question related to berkeley output from `size` program?- he seems to be using win11 normallyhttps://www.edaboard.com/threads/uart-communication-for-sending-integer-values.408205/,https://www.avrfreaks.net/s/topic/a5CV40000000ajRMAQ/t394567Also, the kittu* accounts started activity few months after the Yannic video about GPT-4chan.If true, we are probably seeing that someone is testing something here. (like reactions, time to compromise or this is a decoy and there is higher quality bot posting from stolen accounts etc.)

author: tellurium
author_rank: Frequent Contributor
timestamp: May 03, 2024, 05:17:22 pm
content: Quote from: jnk0le on May 03, 2024, 04:43:32 pmSounds very much like so.And the testing goes pretty well, to the point that forum admins delete messages of real users in order to defend the bot.

author: tellurium
author_rank: Frequent Contributor
timestamp: May 03, 2024, 05:23:00 pm
content: Quote from: eutectique on May 03, 2024, 04:32:07 pmThat is a nice strategy indeed!One may argue that the strategy when heap and stack grow towards each other is good cause gives the best RAM utilitzation, when one does not know in advance which one is going to grow more. But for an embedded application, a firmware engineer might have a pretty good idea about the limits, so the extra price to pay for safety is well worth paying.

author: Kittu20
author_rank: Regular Contributor
timestamp: May 03, 2024, 05:46:15 pm
content: You can think whatever you want, I won't say anything about it. I have already given my explanation. Regarding the links you shared earlier, the question I asked in the first thread, you can see the output in the terminal that i was getting after running code on my PIC micro . And in the other link, I bought the programmer, but after many attempts, I am unable to use it. Not only me many other members also complain that programmer wasn't good faced problem. I wasted my money buying the wrong programmer because I didn't have prior experience with it.

author: Kittu20
author_rank: Regular Contributor
timestamp: May 03, 2024, 05:52:20 pm
content: Quote from: tellurium on May 03, 2024, 05:17:22 pmI claim that you are a bot because you are posting the same message repeatedly. If you are not a bot, prove that you are not a bot

author: peter-h
author_rank: Super Contributor
timestamp: May 03, 2024, 05:53:09 pm
content: QuoteA firmware engineer won't use a heapWell, except to do a one-off malloc for some product option, never to be freed.Or malloc+free of a block so big that fragmentation is impossible.

author: Kittu20
author_rank: Regular Contributor
timestamp: May 03, 2024, 06:04:51 pm
content: Since this thread has now become off-topic, I would like to ask a question. I'm noticing that some users are trolling and discouraging me, which is making me very upset. Should I leave this forum or should I ignore such people?

author: tellurium
author_rank: Frequent Contributor
timestamp: May 03, 2024, 06:10:14 pm
content: Quote from: peter-h on May 03, 2024, 05:53:09 pmIf one needs networking / TCP/IP, then using heap is reasonable. Peter, you're the one who complained about mbedTLS being RAM hungry?

author: peter-h
author_rank: Super Contributor
timestamp: May 03, 2024, 07:13:30 pm
content: Yes, but I throw away the whole 60k block when the connection is closed, which makes it fairly safe. Fragmentationwithinthe MbedTLS private heap is still possible but almost nobody understands MbedTLS anyway, and it seems to be pretty reliable doing what I am doing with it

author: jnk0le
author_rank: Regular Contributor
timestamp: May 03, 2024, 07:29:25 pm
content: Quote from: Kittu20 on May 03, 2024, 05:46:15 pmThose should be showing as USB HID device and work only with PROGISP software (which has expected quality, don't even bother with it).No drivers needed if you have installed something by zadig - uninstall it. (only USBASP requires it)Otherwise unit is defective (HW or just FW) or there is something wrong with USB LS implementation on host machine.The best way to handle those is to immediately reprogram them into usbasp. This of course requires another working programmer and correct firmwarehttps://www.sciencetronics.com/greenphotons/?p=938&cpage=2provides firmware for atmega8(L) ones. (tested on my MX-USBISP-V3.01)https://github.com/aleh/usbisp/tree/master/bin/firmware- should have proper binaries for atmega88 ones (V4 and higher??)EDIT: The users that have problems with them are mostly the ones expecting it to work as usbasp.

author: peter-h
author_rank: Super Contributor
timestamp: May 04, 2024, 09:56:37 pm
content: On why people generate text for ChatGPT etc:

author: PlainName
author_rank: Super Contributor
timestamp: May 04, 2024, 10:17:55 pm
content: So they essentially want gobs of stuff to train their LLM to be the fount of all knowledge? On the one had that would be cool (if it didn't end up behind a significant paywall) - kind of like the next Google search, which was kind of like the next encyclopedia. But on the other hand it may just be masses of complete rubbish so not actually any help in making knowledge more accessible.Copyright is a double-edged sword. Creators need an incentive to both create and share, but big corps like Disney overdo it with several lifetime's lock-in and payback. IMO, copyright should be limited to the same as patents: 20 years tops. But that's going off on a tangent...

author: tellurium
author_rank: Frequent Contributor
timestamp: May 04, 2024, 10:24:38 pm
content: Yeah, AI trains on expert content. For now, it is still easy to recognise it by a behavioral pattern.E.g. a human pattern is to ask a question, then iterate and follow up.Example: take a look at the "porting C++ to C" thread -https://www.eevblog.com/forum/microcontrollers/help-porting-2-functions-from-c-to-c/Or, "starting with stm32" thread -https://www.eevblog.com/forum/microcontrollers/starting-with-stm32-(nucleo-l412kb)/Note how much OPs iterate over the answers, trying to figure out the solution.AI's pattern is different - it just asks the question and NEVER does any meaningful follow up. Even when many answers were given, and tons of hints. Look at this thread - not a single meaningful follow up on a on-topic answers (many of them!). Despite all the claims about "genuine interest" and so on.But I guess AI progresses, and soon we'll see more human-like behavior, including follow-up questions, etc.

author: MK14
author_rank: Super Contributor
timestamp: May 04, 2024, 10:45:20 pm
content: I've investigated the OP, to a fair extent.They do seem to be a BOT.Fortunately, the 'owners' of the BOT, are partly open to where it comes from.My early indications, are that considerably earlier versions, of that 'bot', were much more clearly labeled. So, that they could be traced to, what I would prefer to call the Google AI department.But, they instead seem to call it the Google Deep Learning (entity/department).I can't be 100% sure, and don't want to waste lots of time researching it.Supplying link(s) to what I found out, is not really possible in this case. Because it involves one or more other peoples, personal information, in real life.Also, the OP makes no sense, being a real person. Because they seem to have several posting styles. Varying between, poor quality English, better quality and even good quality English and coherent responses/questions.If you want to see the actual information for yourself. Go on a mission and find some of the OLDEST posts (anywhere), that this system of bots has made. The questions remain all too similar. Then look at the user and see if you can identify Google Deep Learning (obvious hints/information), from what you find.N.B. They do seem to also use completely different user IDs, but the question(s) remain all too familiar.Disclaimer:If I'm wrong here, and you (the OP) are a real person and posting genuine stuff. Then you need to consider seeking medical help, as there seem to be thousands or more, of these questions, repeated in numerous forums and similar places. Over a very long period of time, e.g. 2007 and perhaps longer.Also, it seems to take bits of some replies on some forums, then turn those into question(s) it puts onto completely different forums.So the original question might be about the 'C' language. Then someone mentions MATLAB. Then the question changes into a MATLAB version.I.e. Like here:https://www.eevblog.com/forum/microcontrollers/matlab-and-c-language-in-automotive-software-development/msg5425259/#msg5425259

author: MK14
author_rank: Super Contributor
timestamp: May 04, 2024, 11:26:50 pm
content: Let me give you another example.The following, fairly recent thread, (different forum), seems to show how the possible 'BOT', changed their original question, into the one that this thread, seems to be about.I.e. Possible so called 'machine learning'.Also, as mentioned by someone else in this thread, notice how the 'bot' refused and ignored the comment in my link, to use GOOGLE search.https://www.electro-tech-online.com/threads/better-use-of-function-pointers.165802/#post-1447881

author: IanB
author_rank: Super Contributor
timestamp: May 04, 2024, 11:54:01 pm
content: Quote from: tellurium on May 03, 2024, 02:58:58 pmThis was a really nice description, thanks.I have a follow up question:Suppose I have some constant data, like a lookup table, for example. Since this is static, it can go into flash memory (where the code lives) and not RAM (where the variables live). However, the lookup table in the source file is data, not code. How would one go about telling the compiler to put this lookup table in its own section in flash, and not in the RAM? Would the compiler do this automatically if you declare the lookup table as static/const/readonly? Would the compiler possibly generate some initialization code that copies the data from flash to RAM on startup for ease of access? Do embedded tools typically give you control over this, and to visualize the binary layout that will be produced by the compiler/linker?

author: tellurium
author_rank: Frequent Contributor
timestamp: May 05, 2024, 01:11:17 am
content: As far as I understand, constant data goes to the .rodata section, not .data.And usually linker scripts put .rodata on flash, right after code (.text) - exactly the way you suggested.Example: ST's linker script for one of the H7 :https://github.com/STMicroelectronics/cmsis_device_h7/blob/88f29645ec7e063bae3d5e58699fc541a81efac6/Source/Templates/gcc/linker/stm32h747xx_flash_CM7.ld#L79-L86The .data relocation to RAM is part of the MCU startup code. A compiler does not generate any relocation code.Here's a snippet from the same H7 startup file:https://github.com/STMicroelectronics/cmsis_device_h7/blob/88f29645ec7e063bae3d5e58699fc541a81efac6/Source/Templates/gcc/startup_stm32h747xx.s#L66-L86Both linker script, and .data relocation, are explained in my guide (https://github.com/cpq/bare-metal-programming-guide), but in a more "scattered" manner.A linker script and startup file are usually part of the device SDK. Of course anyone can modify them, but there is rarely a need to do so.If one wants to learn how things work, one could create a really minimal working linker script, and a small C-only (no assembly) startup file.Here's an example from the bare metal guide for STM32F429:https://github.com/cpq/bare-metal-programming-guide/blob/main/steps/step-4-printf/link.ld- a small linker scripthttps://github.com/cpq/bare-metal-programming-guide/blob/main/steps/step-4-printf/startup.c- a small C-only startup filehttps://github.com/cpq/bare-metal-programming-guide/tree/main/steps/step-4-printf- a complete projectI would recommend Alex'shttps://github.com/ataradov/mcu-starter-projectsas a very nice example of minimal & functional approach to bare metal firmware implementation.

author: Kittu20
author_rank: Regular Contributor
timestamp: May 05, 2024, 03:31:43 am
content: Quote from: tellurium on April 30, 2024, 11:42:14 pmThank you very much, @Simon, for deleting the post and making the right decision. If possible, please remove any unnecessary off-topic posts in the thread, close the thread, as I do not wish to continue it

author: peter-h
author_rank: Super Contributor
timestamp: May 05, 2024, 06:13:09 am
content: QuoteExcept most don't do the "follow up" bit because- they can't be bothered- they are working in some company which prohibits posting- they abandoned the project- they are working on a product and don't want to give away too muchBTW you can find out a lot about someone by googling on their forum nicknameI regularly do this on the one I run, where the poster was quite smart but probably malicious.Also there are sites which can identify ChatGPT output with a high probability.QuoteThis varies, even by version of the same CPU compiler. From my project notes:With ARM GCC, statics are categorised thus:int fred; goes into BSS (used to go into COMMON in GCC versions before v10)int fred=0; goes into BSS (which by definition is zeroed by startup code)int fred=1; goes into DATA (statics initialised to nonzero, copied to RAM at start)I don't think anything goes into .rodata in current arm32 GCC although the original ST-supplied linkfile contains loads of code referencing it.Another reason for freezing the compiler version on a given project, but that's another debate... I have frozen Cube IDE on 1.14.1, due to issues with the GCC tools which Cube 1.15.0 introduces. Cube itself is also broken at 1.15 - can't drive the debugger!

author: tellurium
author_rank: Frequent Contributor
timestamp: May 05, 2024, 08:34:35 am
content: Quote from: peter-h on May 05, 2024, 06:13:09 amNo it does not vary. "int fred" does not go to .rodata simply because it is, well, not constant. You can change it.Try to declare `const char *message = "blah";` and see.

author: Nominal Animal
author_rank: Super Contributor
timestamp: May 05, 2024, 09:57:54 am
content: Quote from: tellurium on May 03, 2024, 02:58:58 pmI didn't know what depth/complexity would be most useful, so did it what I thought would be most useful.Having someone else do the same at a different depth/complexity is extremely useful; thanks!Quote from: IanB on May 04, 2024, 11:54:01 pmGenerally, using__attribute__((section ("sectionname")))consttypevarname[] = {values...,};With older AVRs with separate Flash and RAM address spaces and separate machine instructions to access them, we have__flashqualifier that causes the (C only for GCC, C or C++ for Clang>=13) to put it in the.progmem.datasection, so to use a different section, you use an alias:__attribute__((section ("sectionname")))static consttypeinternal_varname[] = {values...,};extern __attribute__((alias ("internal_varname")))__flash consttypevarname[sizeof internal_varname/ sizeof internal_varname ];Because of the__flashqualifier, accesses tovarnamewill use the LPM instruction.For compatibility, it is best to usesectionnames that begin with.progmem..Other compilation units (source files compiled to different object files) accessing the array should use prototypeextern __flash consttypevarname[size-if-known];wheresize-if-knownis the number of elements, or omitted if unknown.(The reason this alias trick works correctly is that the__flashattribute tells the compiler to generate the correct code (LPM et cetera, instead of LDS et cetera); but symbol references use only the name (without any section references). Thus, similar tricks will work in all compilers having such qualifiers, using ELF object files and symbol aliasing.)The source code generated will be similar to.section bar,"aw",@progbits.type array, @object.size array,size-in-bytesinternal_varname:array contents.globalvarname.setvarname,internal_varnamegenerating the expected machine code and object files;internal_varnamewill be a local symbol, and not accessible from other compilation units.Another option is to use only the__flashqualifier, and compile the lookup table to a separate object file, then change the section name using e.g.avr-objcopy --rename-section .progmem.data .progmem.namelookuptable.o.Even older versions of GCC (I have 5.3.0, for example) generate acceptable code for AVRs, but for Clang, you'll want version 16 or later.In general, the__attribute__((section (sectionname)))used with a function or data object (variable or constant) picks up the "type" of the section from what it is used with for the assembler, so technically setting a section affects both the function or data object it is used with, and the section declaration itself. GCC and Clang linker scripts, however, use only the section name, so using common prefixes with '.' separators makes writing linker scripts easier. Standard linker scripts, for example, tend to consider all sections starting with.text.as just another.textsection, so with suitable standard prefix section names, one won't need to modify the linker scripts at all. (The__flashor equivalent qualifier is needed to tell the compiler which instructions can be used to access the variable or data object. The AVRioattribute works in a similar way, but for register and I/O bit manipulation.)Quote from: IanB on May 04, 2024, 11:54:01 pmFor certain targets (having a single Flash + RAM address space) using certain compiler options (-fdata-sectionsto put each data variable or object into a separate segment) and linker scripts, yes.For example, ARM Cortex-M targets using standard linker scripts and-fdata-sectionsGCC or Clang compiler option would do this.Quote from: IanB on May 04, 2024, 11:54:01 pmNo, that is done by the boot loader or initialization code, which is also responsible for setting up stack; and on more complex microcontrollers, sets up clock sources, trains DRAM, and so on.Quote from: IanB on May 04, 2024, 11:54:01 pmYes. There are two separate cases: one where the boot loader is separate, possibly in a reserved Flash section, and does all the initialization; and the other where there is no bootloader per se (and the system cannot update its own firmware, it is done using external tools).In the first case, the boot loader code base is separate. It gives some promises –– minimally in the form of the linker script specifying the memory ranges available to the application part, and the address of the symbol that is executed whenever the boot loader has done ––, which should be documented somewhere, especially if it also provides additional functions in Flash one can utilize, but the linker script does describe the minimum details and the layout.In the second case, the initialization code is linked with the application part, so the final link map (you can obtain from linker tools) will describe the full firmware image. In this case too the linker script will describe the binary layout. (It varies whether the locations of memory-mapped peripherals are defined in the linker script, accessed via fixed-address pointers in the source code, or via fixed-address C/C++ extension attributes in the source code. The last one is common in older Harvard architectures with multiple address spaces, for example when bit access instructions are limited to a small I/O address range. So, the linker script may not describe how all peripherals are accessed, even if in the same address space; for those, you need to examine the source code.)

author: PlainName
author_rank: Super Contributor
timestamp: May 05, 2024, 10:39:25 am
content: Quote from: IanB on May 04, 2024, 11:54:01 pmStrictly, the compiler plays not part other than to label things. The linker is the bit that places everything in the appropriate parts of the memory map. Nowadays it's unusual to think about the linker because the compiler or IDE will run it automatically, and the IDE vendor provides suitable default directives. If you check some embedded project source there will no doubt be a .ld file, which tells the linker what to place in which sections and where they locate in absolute memory.QuoteNot really, but... The compiler just compiles code. There will be a startup file which does the system initialisation, from initial boot to setting up memory (if necessary), copying initialised data, etc., then chainging to main().QuoteMore so than desktop or phone apps, but the IDE may not make it easy. Can't offhand think of one that makes it easy to visualize what the result will look like - see the attached linker files for PIC32 and STM32 projects, for example. A user either won't mess with these, ever, or will play around at the start of the project and then be done with it.Attached are STM32 and PIC32 linker files, and typical STM32 startup code. I added the .txt extension for the forum to accept them. If you browse any embedded project you have you should find something similar.edit: nominal beat me to it, more coherently. But the attachments may still be useful to scare you off dealing with 'em

author: mikeselectricstuff
author_rank: Super Contributor
timestamp: May 05, 2024, 10:47:50 am
content: QuoteAny decent compile/link ecosystem should by default put const data in flash unless explicitly told to do otherwise - as mentioned there are sometimes reasons to do otherwise, like harvard architectures that may have a speed penalty, or where flash and RAM have different access speeds, but these should be something that has to be explicitly requested.

author: nctnico
author_rank: Super Contributor
timestamp: May 05, 2024, 11:05:05 am
content: Quote from: mikeselectricstuff on May 05, 2024, 10:47:50 amI agree. Using sections is a complicated way versus simply using const if the goal is to have data in flash.Often there are a whole bunch of sections in the linker descriptor file which doesn't make making changes easy. And the linker descriptor file will vary per target / microcontroller type so using sections doesn't make code very portable either (besides needing to document the non-standard sections). So in general I'd advise against using sections unless there really is no alternative way.

author: Nominal Animal
author_rank: Super Contributor
timestamp: May 05, 2024, 11:17:31 am
content: Quote from: mikeselectricstuff on May 05, 2024, 10:47:50 amFor architectures with a single address space for Flash and RAM,yes.In the above snippet,__attribute__((section ("sectionname")))is only needed to put the variablein its own sectionin Flash.That is,consttypevarname[] = {values...,};suffices to put the variable in the normal Flash data section (whose name varies a bit depending on architecture).This works with standard/default linker scripts for ARM Cortex-M targets using both GCC and Clang, for example.Similarly, on older AVRs,__flash consttypevarname[] = {values...,};suffices to put the variable in the normal Flash data section in (.progmem.data), and have instructions accessing it use theLPMinstruction.With GCC, this works only in C; with Clang, in both C and C++. This is because GNU g++ does not support address spaces for C++, and is also the reason why the Arduino environment is so wonky. Also note that the external definition, for use in other compilation units, is "extern __flash consttypevarname[size-if-known];", i.e. the__flashqualifier is required; otherwise the other compilation units would use data memory instructions for access.To repeat why "its own section" is so useful with GCC/binutils/Clang toolchains, is that if you use a properly aligned and sized structures, you can do__attribute__((section ("sectionname"), used))static conststruct-typevarname_is_irrelevant= {definition};in different compilation units, different source files, and the linker will provide you all of them (in a semi-random order) in a single array at runtime, viaextern conststruct-type__start_sectionname[];extern conststruct-type__stop_sectionname[];#define ELEMENTS ((size_t)(__stop_sectionname- __start_sectionname))#define ELEMENT(index) (__start_sectionname)For older AVRs, I recommend using the alias trick; you do also need to useextern __flash const ...above.Also, knowing the section name lets you do all sorts ofobjdumpandobjcopyshenanigans. Even relocation records are based on sections; that is, relocation records are typically offsets to a section, not offsets to a symbol value. It is easy, almost trivial, to manipulate complete ELF sections as part of your build; manipulating individual symbols within sections containing other symbols is fraught with hidden dangers. I don't manipulate individual symbols (other thanaddingthem) outside the C compiler and linker script. I often do manipulate (the contents of) entire sections outside the C compiler and linker script, knowing that it also affects any symbols defined within it. (Which I often discard, by making them local viastatic const.)

author: peter-h
author_rank: Super Contributor
timestamp: May 05, 2024, 01:00:24 pm
content: Yes indeed const does generate rodata. Or RODATA

author: IanB
author_rank: Super Contributor
timestamp: May 05, 2024, 04:22:15 pm
content: Quote from: PlainName on May 05, 2024, 10:39:25 amYes, this is exactly what I'm asking. When you compile C code for a desktop OS, the reference to startup code and startup entry point is automatically inserted by the compiler. You can use compiler options to make your own main() function the entry point, and avoid the initialization code being included, which can result in a much smaller executable. It follows that when you have an embedded target, the compiler could also insert some code that does some housekeeping on startup before reaching main(). I guess the only question would be if the startup/initialization code is standard, or if it is ever adjusted according to the contents of your program?(If you are using C++, the compiler can automatically generate and include lots of code in your program that you didn't write.)

author: Nominal Animal
author_rank: Super Contributor
timestamp: May 05, 2024, 05:39:02 pm
content: Quote from: IanB on May 05, 2024, 04:22:15 pmIf you usefreestandingC, via-ffreestandingcompiler option, then no such code is included.Otherwise, the C runtime support (crt) is linked in; it is provided by one or more files named*crt*.oby the standard C library you use.(This is separate from the actual standard C library itself, which can be dynamically or statically linked; and from compiler support library/objects likelibgccwhen using GCC on many architectures.)The exact set linked in may depend on the compiler and the compiler options; especially whether generating position independent executables (PIE) or not, sometimes depending whether debug information is included or not.Thus, it really depends on the standard C library you use, and compiler options; but not the contents of your program.

author: nctnico
author_rank: Super Contributor
timestamp: May 05, 2024, 06:06:17 pm
content: Quote from: IanB on May 05, 2024, 04:22:15 pmThat depends on the target. When starting a regular C program, the very minimal requirement is to set the stack pointer and jump the main(). A Cortex-Mx microcontroller can do this in hardware so you won't need any startup code at all. When main is called, you'll need to clear the memory for the variables (call memset) and copy the initialised variables from flash to RAM (memcpy). The addresses (symbols) where the variables are located and the initialised data needs to go from / to are defined in the linker descriptor file.On other CPUs some assembly code is needed to set things up before calling main.

author: langwadt
author_rank: Super Contributor
timestamp: May 05, 2024, 06:41:45 pm
content: Quote from: nctnico on May 05, 2024, 06:06:17 pmI think even for a cortex-m the memory initialization and such is normally done before calling main, but it can be written in Crandom example from the interweb,https://github.com/westrup/stm32/blob/master/startup.c

author: nctnico
author_rank: Super Contributor
timestamp: May 05, 2024, 06:51:18 pm
content: Probably ST wanted to hide the init as part of the HAL or avoid confusion and have everything initialised before calling main. In my own code these two lines do all the required initialisation:Code:memset(_data, 0, _stack_end - __bss_start__-32);//clear memory including stackif (_edata!=_data) memcpy(_data, _datastart , _edata-_data);//copy initialised variables if presentI make it a point to clear the stack as well. In some rare cases old data on the stack can trigger very rare bugs in combination with (for example) an array / pointer going out of bounds even across resets. Clearing the stack results in consistent behaviour of the fault.

author: peter-h
author_rank: Super Contributor
timestamp: May 05, 2024, 07:00:02 pm
content: Better still fill the stack with "s" or some such, and then dumping it afterwards will show the usage up to that point.But yes it should deffo be filled with something consistent. I fill my general stack with "s", the RTOS area with something else, then the RTOS fills its task stacks with "S" (IIRC) etc.

author: langwadt
author_rank: Super Contributor
timestamp: May 05, 2024, 07:13:11 pm
content: Quote from: nctnico on May 05, 2024, 06:51:18 pmclearing the stack (or setting it to some magic number) can give you an hint on how much is being used by examining the stack areaIf you use the ST IDE the startup is an assembly file added to the project, it also calls a systeminit function to setup clock/fpu/memory before calling mainhttps://github.com/STMicroelectronics/STM32CubeF4/blob/master/Projects/STM32F401RE-Nucleo/Templates/STM32CubeIDE/Example/Startup/startup_stm32f401ceux.s

author: nctnico
author_rank: Super Contributor
timestamp: May 05, 2024, 07:23:51 pm
content: Quote from: langwadt on May 05, 2024, 07:13:11 pmI do that differently. I sample the stack pointer inside a timer interrupt and update the 'lowest stack address' variable when it is below the previous value. This gives a very quick idea of worst case stack usage without going through a lot memory. I do admit I 'stole' this idea from someone else though. Clearing memory to zero is a very safe thing to do as 0 or NULL is often regarded as the end of something or invalid. Setting the stack memory area to a different value, could cause more problems than is solves. Also, used stack space is likely to be unequal to zero.

author: PlainName
author_rank: Super Contributor
timestamp: May 05, 2024, 07:28:14 pm
content: The stack could move between samples, so it will give you a good idea but risks missing peaks.

author: tellurium
author_rank: Frequent Contributor
timestamp: May 05, 2024, 08:57:33 pm
content: Quote from: IanB on May 05, 2024, 04:22:15 pmWhen you compile the code for desktop, you produce an ELF file. An ELF file has a "entry point" symbol. You can check the entry point by using objdump:Code:$ objdump -f ~/tmp/wizard/firmware.elf...start address: 0x30007a39For the ARM firmware file, the entry point is basically ignored, because firmware binary is produced and flashed as I described earlier. The entry point is used by debuggers - by fetching an entry point from a firmware.elf, a debugger knows where to set a default breakpoint. An entry point is specified by a linker script. It is usually set to a reset handlier, e.g.:https://github.com/STMicroelectronics/cmsis_device_h7/blob/88f29645ec7e063bae3d5e58699fc541a81efac6/Source/Templates/gcc/linker/stm32h747xx_flash_CM7.ld#L35On a desktop system, the situation is different. As far as I understand, there is a standard, called ABI (application binary interface). It says that on UNIX systems, an entry point of a binary should be a symbol called "_start". When a unix kernel starts a process, it loads the first page of an executable file into memory, and loops over a list of so called "image activators". Those are functions that recognise file format and try to start an executable. There are image activators for ELF files, for shell scripts, etc etc.So ELF image activator looks for and ELF signature at the beginning of the file, and if it finds it, it scans the ELF header for the _start symbol. Then it does a bunch of other things, and it jumps to _start. A function _start is part of a C runtime - it is located in a file crt*.o, which gets linked to your binary at the build stage, as Nominal Animal pointed out. This part of C runtime implements an ABI - that's why it is separate from a C library itself. A function _start loads dynamic libraries, prepares argv, argc, environ, and then calls main().So when you say "reference to startup code and startup entry point is automatically inserted by the compiler." - yeah, pretty much. By the linker. The startup code is that _start function.

author: IanB
author_rank: Super Contributor
timestamp: May 05, 2024, 09:28:32 pm
content: Quote from: tellurium on May 05, 2024, 08:57:33 pmI follow everything you are saying, thank you, especially the reference to the linker. But I think that in very simple compilations the distinction between the compiler and the linker is a bit blurred. The compiler invokes the linker and tells it what to do to make an executable, and it is the C compiler that tells the linker to include the C runtime with your code. You can tell the compiler not to include the C runtime, as illustrated in the video below, and that leaves you with a bare executable where you have no C runtime support.What I was curious about is when you target an embedded platform, you might also have initialization code automatically added to your binary via the platform SDK, and that this code would do whatever is necessary on the platform you are targeting to set things up before entering your code. Other people have explained about this in the posts above (thank you). It also appears that if you know what you are doing, you can do some minimal initialization yourself, manually, and not ask the SDK to look after it for you.Whatever the case, I understand that "it depends" and "read the documentation for your platform" are important memos, and these would not escape me if I were doing this for real.

author: tellurium
author_rank: Frequent Contributor
timestamp: May 05, 2024, 09:42:37 pm
content: As it was described above, there is no hidden, or default, startup/init code added to the embedded firmware executable. A linker script defines an entry point symbol, and it is set so in the produced ELF header. However if you're creating a binary firmware from your .elf file, via "objdump -O binary firmware.elf firmware.bin" , then you don't even need to specify an entry point. It is NOT required to make a valid firmware binary. There is NOTHING hidden or secret, and you can't optimise an embedded code by those tricks described in the "desktop" videos. Because ELF format is NOT used by the firmware binary, and the startup code is explicit - taken from vendor's SDK or hand-written.

author: IanB
author_rank: Super Contributor
timestamp: May 05, 2024, 09:58:00 pm
content: Quote from: tellurium on May 05, 2024, 09:42:37 pmYes, I've got it. Please don't think I am arguing with youIt's not about hidden or secret, it's about automatic. As you wrote above, startup code may be "taken from the vendor's SDK". I don't think you mean I need to copy/paste the start up code from the SDK and include it in my project, I think you mean that the SDK will automatically include the necessary startup code for me when I create my project? I expect I can use the appropriate SDK from the vendor, say "create new empty project", build that project, and it will automatically include whatever startup code is needed for the platform? (I am assuming here that I would be using an IDE, rather than using bare bones command line tools.)Beyond this point, I think there is nothing more for me to ask unless/until I actually get a development kit for a suitable microcontroller, install the SDK, and start writing code for it.

author: nctnico
author_rank: Super Contributor
timestamp: May 05, 2024, 10:11:44 pm
content: It is never really automatic. There are two options to get the startup code linked into the binary automatically:1) The SDK (like ST's cube) automatically adds a file with the startup code.2) The SDK + C libraries automatically selects the right C startup library to be linked into the projectIf you study the source files and list of libraries which are part of the project, you should be able to see what is what.However, the SDK has to be tailored for the specific microcontroller. If you use vanilla VS Code or Eclipse CDT and a GCC / CLANG install, you'll need to do everything yourself (I'm not going into whether this is good or bad; I leave that to the readers to decide for themselves).What doesn't help is that a lot of this is hidden under the hood. For example: GCC (as a collection of tools) has relative paths to the includes, linker descriptor files and libraries hard coded inside the executables so even without specifying paths for where to find specific inludes and libraries, it can find them. This makes GCC easy to use but it also hides some very important information which makes it look like a lot of things happen automagically.

author: jnk0le
author_rank: Regular Contributor
timestamp: May 05, 2024, 11:47:31 pm
content: Quote from: MK14 on May 04, 2024, 10:45:20 pmQuote from: MK14 on May 04, 2024, 10:45:20 pmOf course missed the most obvious explanation: collect unique "individual expertise" data to train their AI models.That would explain weird questions on topics that can often be just googled up.Also, there was another instance on r/riscv repeatedly asking the same 'questions' while gaslighting (deleting) previous ones.@brucehoult has been dealing with it IIRC

author: SiliconWizard
author_rank: Super Contributor
timestamp: May 06, 2024, 12:36:02 am
content: I don't think the person itself is a bot - no bot can talk like this exactly. It sounds too "human" in some of the phrasing. But there's a high probability this is a real person working at testing & training AI.

author: Kittu20
author_rank: Regular Contributor
timestamp: May 06, 2024, 02:36:51 am
content: Does my question not make sense? I see that many experts also have doubts, which they are clarifying in this thread by asking other members. Then, as an intern, why can't I have doubts?

author: pcprogrammer
author_rank: Super Contributor
timestamp: May 06, 2024, 05:47:35 am
content: Quote from: IanB on May 05, 2024, 09:58:00 pmCreating the project for par example a STM32F103C8 in the CubeIDE includes the process of generating the startup file, either by just copying the .s file or filling it in from a template. When you use another IDE it might not be the case and you have to add it yourself or write the needed code in C, or just copy a project from someone else and use that as a base.The compiler(s) is(are) then instructed by the make process to compile the individual files that are in your project. I wrote compiler(s) because there can be different ones for the different file types, like C, C++ or assembler. For the latter it is not really a compiler but an assembler.What a compiler does is translate the C, C++ code to assembler, and then assemble it into machine code. The latter being the binary data that is processed by the processor.

author: pcprogrammer
author_rank: Super Contributor
timestamp: May 06, 2024, 05:48:33 am
content: Quote from: nctnico on May 05, 2024, 10:11:44 pmWhich is even worse on the Arduino platform.

author: MK14
author_rank: Super Contributor
timestamp: May 06, 2024, 07:28:07 am
content: Quote from: SiliconWizard on May 06, 2024, 12:36:02 amYes, to the last bit of your post. Although, I think some of those 'human' elements, might themselves, be part of its AI, as well.One example is here:https://forums.freertos.org/t/practical-rtos-project-ideas-for-real-world-applications/17981Where the responding poster, hasn't noticed that it might be an AI/deep-learning thing, but makes comments about its rather strange and weird 'learning' behavior.Quote

author: MK14
author_rank: Super Contributor
timestamp: May 06, 2024, 07:47:33 am
content: Quote from: Kittu20 on May 06, 2024, 02:36:51 amIs it ok, if I ask you a question, as an intern.As an intern, you must be a human adult. A human adult, must know what a (paper) envelope or sleeve is?Similarly, an intern, must know what a credit card is, what it looks like and what the different parts of it, basically are.So, when we go to the following thread:https://forum.allaboutcircuits.com/threads/biometric-system.192026/#post-1801070How come, you don't seem to know about those basic facts. Quotes of the relevant bits, follow:QuoteAn adult (intern), would reasonably be expected to know what a (paper?) sleeve looks like, and is.QuoteFollowed by a picture of a credit card, in that thread.Surely as a (human) adult intern, you know what a credit card is?

author: peter-h
author_rank: Super Contributor
timestamp: May 06, 2024, 08:16:15 am
content: BeautifulAndsoobvious that this is purely a response generation exercise.

author: PlainName
author_rank: Super Contributor
timestamp: May 06, 2024, 08:37:40 am
content: QuoteHaving followed that link, and the subsequent link, I don't find the questions indicate what you believe to be the case. The thing about the box vs sleeve is that it's not obvious what it is or should be called - I wouldn't call it a sleeve (it's cardboard, not paper). And the 'card below' is credit-cardsizedbut isn't a credit card (since it has a fingerprint reader embedded, apparently).

author: MK14
author_rank: Super Contributor
timestamp: May 06, 2024, 08:47:39 am
content: Quote from: PlainName on May 06, 2024, 08:37:40 amHere is the picture:I argue/suggest, that a real human (Adult) Intern, would readily and immediately know what the sleeve is in the picture.Link in question:https://www.biometricupdate.com/201805/mastercards-remote-enrollment-solution-for-biometric-payment-cards-developed-with-idexBut, I do agree, that the biometric (sensor) bit, is NOT obvious, to everyone.

author: MK14
author_rank: Super Contributor
timestamp: May 06, 2024, 09:09:03 am
content: Quote from: PlainName on May 06, 2024, 08:37:40 amAs regards your criticisms of the 'credit card', I agree with you. Because, biometric sensors, on credit cards, is not that obvious.But, the way that Kittu20, talks and asks about credit cards, complete with a picture of one. Makes it sound like, they (Kittu20), don't really know or understand about credit cards.As would be expected, from some kind of AI/machine-learning/deep-learning entity, which has never touched or seen a credit card, in real life. Hence the confusion and strange/weird questions, from Kittu20.Excluding somewhat obvious exceptions, such as they live in an underground cult, in the middle of know-where, and never meet or interact with real people.

author: MK14
author_rank: Super Contributor
timestamp: May 06, 2024, 09:25:47 am
content: Quote from: Kittu20 on May 06, 2024, 02:36:51 amDo you now know what a 'short short' is?https://forum.allaboutcircuits.com/threads/rules-of-c-language-are-very-confusing.189740/Quote

author: Nominal Animal
author_rank: Super Contributor
timestamp: May 06, 2024, 09:32:34 am
content: Quote from: IanB on May 05, 2024, 09:28:32 pmNote that the linker script can alwaysinclude specific object files(that do not need to be mentioned in compiler or linker command line options).Thus, the linker script is the first place you should look at, to find out what kind of initialization or support code a build toolchain will include, and what kind of memory layout will be generated (unless ASLR and dynamic linking is used).The C runtime (some*crt*.ofiles) is just so common that compiler default linker scripts have them baked in for fully-hosted environments (i.e., code running under a fully-featured operating system, with the standard C library available).This is also the reason why I believe all embedded programmers should learn to read (and to a lesser degree, write) GCC/Binutils/Clanglinker scripts. I did it by reading the linker script documentation while examining existing linker scripts. If you have ever used Awk or its variants, you'll find the basic idea of operation familiar; otherwise, think of linker scripts as recipes, or rules, the linker needs to follow. If you don't have any linker scripts at hand, look at the various Arduino support cores, they have plenty of them.(It would also be very useful to understand the difference between 'fully-hosted' and 'freestanding' C and C++. Freestanding C is pretty well defined in the standards, while for C++ it is 'implementation defined'; but mainly it deals with the difference in what features are available. Some header files like<stddef.h>,<stdint.h>,<stdarg.h>,<stdbool.h>,<stdalign.h>,<stdnoreturn.h>,<limits.h>,<iso646.h>, and<float.h>are provided by the compiler, so they and all they expose are always available (if at all; some of those depend on the C version used). The (rest of) standard C library is only available in hosted environments. For linking, it also means C runtime support (*crt*.o) isnotincluded in builds based on freestanding C.)Quote from: MK14 on May 06, 2024, 08:47:39 amI'm an adult but not an intern who has had that brand credit card for a couple of decades, but didn't know what the heck the purpose of that sleeve is: I've never seen those before. (I'm also rather skeptical about biometrics here: if robbed, I'd rather prefer to keep my fingertips, than have the robbers take those too. Obligatory XKCD:538.)It seems to me that if Kittu20 is a real human being only using LLM to help them with their English output (as opposed to training one and/or acting as an intermediary to one), it would be a good idea to stop: the way LLMs are used now –– some claim already about half of web traffic is bots (although only a small fraction use LLMs) –– means that broken English is better accepted in technical discussions than LLM/bot use is. (Even just a week ago I thought it'd be okay to use LLMs for helping with foreign language output; now I do not think so anymore.)

author: peter-h
author_rank: Super Contributor
timestamp: May 06, 2024, 09:47:12 am
content: QuoteThis is a great observation. After some of the posts here I went to look in Cube, as a little exercise, to see where the order of the program modules is set up, and could not find it. Of course it is in the linkfile... You start with specific modules e.g. vectors.o, then startup.o and then you collect up all the other stuff with *.oIt doesn't actually matter so long as vectors.o is the first one.There is a vast amount of obscure config in Cube for the libraries to be used. Loads of ways to get burnt by changing it accidentally.

author: Nominal Animal
author_rank: Super Contributor
timestamp: May 06, 2024, 10:38:10 am
content: I believe that trying to write a single linker script to cater for multiple use cases will result in an ugly, unmaintainable result.The best linker scripts I've seen target a specific variant and use case of a board.Adding support for a new MCU or board is then easy, as one starts from the most similar existing one, saves it under a new name related to the MCU and/or board, and does the required modifications.Early development with multiple targets is more work, because you have to carefully copy the changes across all targets' linker scripts and keep them "in sync" with respect to changes; but, when they finally stabilize, it gets much easier and is worth it.If you use a separate linker scripts for production and development, you can use the exact same code base, even exact same object files without recompilation: just discard any debugging-related information. You do need to use dedicated sections for the debugging stuff; I use preprocessor macros with descriptive names for the section definitions. You can use the ELF tools (objdump/readelf) to examine relocation records, to see if any outside the debugging-related sections refer to debugging information, to ensure nothing ever tries to access the removed data or functions. (Because that is a "If there are any, it is a failure" type check, it is quite simple and robust. Also, the exact same mechanism is used internally with-ffunction-sections -fdata-sections -Wl,--gc-sectionsoptions to prune out unused data and functions, so this is a commonly trusted mechanism already; not a "hack".)Consider, for example, writing a simple variable-accessing interface for use during testing. You use the structure-in-a-dedicated-section to describe each variable (type, pointer to, name, and possibly valid range), and a simple parser to query and set them at run time via some serial interface. You separate its initialization and operation to separate functions in a debugging section, and create aweaknon-debug initialization function stub that just returns. The normal initialization code only calls that initialization function; the debug one if it is linked in, the do-nothing stub if the debug one is omitted. (This is howweakELF symbols work; they're extensively used in library code to allow application code to override library functions just by writing a non-weak function with the same signature.)The benefit is that at run time, depending on which sections are included and which dropped, only the initialization function call target changes, and there are no other non-debug code changes in the firmware between instrumented and production builds. Much better than compiling instrumented and production builds separately, if machine-code level examination is needed/useful. Ordinary devices and hobbyists don't care, though – except for oddball paranoid uncle bumbleϝucks like myself.

author: eutectique
author_rank: Frequent Contributor
timestamp: May 06, 2024, 11:05:39 am
content: Quote

author: PlainName
author_rank: Super Contributor
timestamp: May 06, 2024, 12:46:33 pm
content: Quote from: MK14 on May 06, 2024, 08:47:39 amWhat's with the 'human (Adult) Intern' stuff? Too many variable thereI'm an adult (though not an intern) and English is my native language, but if you asked me what that thing is without benefit of this thread, I wouldn't have called it a sleeve. Actually, I'm not sure what I would have called it, but 'sleeve' is not the first thing to pop into my head.I think part of the reason for that is because it doesn't go the full length of the card. I would be thinking of some term related to 'slot'.Anyway, the gist is that I agree that there is something peculiar - it strikes me that some of the questions wouldn't be asked by someone clearly as versed in the arts as previous questions suggested. A little like a teacher running a test (which would tie in with generating LLM fodder). But the examples you gave there are not, IMO, definitive. I've seen far more likely ones from actual humans on here, and those have been English-speaking humans at that!I'm intrigued that no-one has wondered what 'intern' means in all this. A student at college? Someone working for free for the experience? Graduate on his first job?

author: MK14
author_rank: Super Contributor
timestamp: May 06, 2024, 02:57:55 pm
content: Quote from: PlainName on May 06, 2024, 12:46:33 pmTrue, there is quite a lot of scope for intern, to mean a wide range of things.I also agree that your posts and other(s), suggesting that it is NOT so obvious, to know what some of the things I posted in the thread, actually are (at least to EVERYONE), is a valid point/contradiction to my (AI/Deep-learning) narrative.I have managed to find the following, which seems to be the same user. But, their thread and posts, seem to be much more like a real human.https://www.avrfreaks.net/s/topic/a5C3l000000UkUVEA0/t191795?page=1Because, they seem to show detailed, and clear photographs of hand drawn circuit(s) and real physical electronics in use, by an upcoming hobbyist.I suppose, anyone round the world, who is reading technical books, or even internet technical articles. When they have the slightest misunderstanding (e.g. why are PNP as opposed to, NPN transistors, used in circuits, sometimes).Could create hundreds of forum accounts, in different websites, and over a period of time. Put those questions, in them.Eventually amassing a huge number of threads/questions, all over the place.

author: IanB
author_rank: Super Contributor
timestamp: May 06, 2024, 03:19:13 pm
content: Quote from: PlainName on May 06, 2024, 12:46:33 pmIt's a card reader, surely?If you go shopping with your chip-enabled credit or debit card, you push it into the card slot, and it goes about half way in. This is normal.Many people (especially in the UK) may have a card reader device from their bank for online banking. This also has a slot that accepts about half the length of the card (this is all that is needed to read the chip).When I look at the photo above, it seems obvious that it is a credit card. Without reading the article, what comes to mind is a "chip and fingerprint" security device on a card, as an alternative to the usual "chip and pin" security. Naturally, the fingerprint reader part needs to be exposed so you can put your finger on it, while the chip needs to be inside the machine, so it can read the data off it.

author: MK14
author_rank: Super Contributor
timestamp: May 06, 2024, 03:22:47 pm
content: Quote from: eutectique on May 06, 2024, 11:05:39 amThanks, that's funny (and interesting, in its own way, how distinguished people, react, to such questions).I've watched it twice, and others now, or closely related, including the first part, of that video series.

author: PlainName
author_rank: Super Contributor
timestamp: May 06, 2024, 03:30:38 pm
content: Quote from: IanB on May 06, 2024, 03:19:13 pmIt's not a card reader I've ever seen before: too thin, and no display or keypad. So whilst it likelyisa card reader, I wouldn't have described it as one on first sight. For all I know it might've been a cardholderthat sticks on something and you use it to park your card.

author: Kittu20
author_rank: Regular Contributor
timestamp: May 06, 2024, 03:46:19 pm
content: To those who think I'm a bot, thank you I am bot who draws circuit diagrams by hand, purchases electronic components, connects them on a breadboard, solder components onto PCBs, tests circuits using a multimeter, writes and compiles code, and views results in a terminal. I know that if I ask any questions on this forum, I may continue to be trolled. Therefore, perhaps I should refrain from participating in this forum

author: MK14
author_rank: Super Contributor
timestamp: May 06, 2024, 03:52:57 pm
content: Quote from: Kittu20 on May 06, 2024, 03:46:19 pmTrolling, would surely mean, that the people involved were doing it on purpose.But, if it was being done, because of mistakes and/or misunderstandings, that would be different.

author: nctnico
author_rank: Super Contributor
timestamp: May 06, 2024, 04:41:02 pm
content: Quote from: Kittu20 on May 06, 2024, 03:46:19 pmI'd like to recommend you to buy this book:https://www.oreilly.com/library/view/making-embedded-systems/9781098151539/It is not super expensive and well worth the money. I can highly recommend it to anyone wanting to venture into working with microcontrollers.This book answers a lot (if not all) of the questions you have in a much more structured way compared to gathering bits & pieces from a forum.

author: MK14
author_rank: Super Contributor
timestamp: May 06, 2024, 05:34:15 pm
content: Quote from: Kittu20 on May 06, 2024, 03:46:19 pmI'm SORRY, if I've caused any offense or annoyance.Unfortunately, this forum seems to get lots of 'attacks' from bots and similar, these days.I'd suggest, anyone using ChatGPT, as part or all of their post. Should carefully and clearly label the content as such. Otherwise, it can make the poster look like a bot.Second excuse:I keep on seeing, the following forum warning message, currently (which reminds me of spammers, old style bots and ChatGPT related bots etc):Quote

author: peter-h
author_rank: Super Contributor
timestamp: May 06, 2024, 06:52:29 pm
content: I am afraid that all forum mods are struggling with ChatGPT - whether it is humans making generic-question posts to generate potential text for "AI" (as this guy seems to be doing) or people using ChatGPT to generate text for posting (possibly because they can't speak any English and ChatGPT is a bit better than google translate).Fortunately, for now, ChatGPT produces fairly obvious output. Bland, sickly-sweet, devoid of any personal "colour". But this will change.Dealing with this is a part of my job and FWIW I start with looking at the original poster signup parameters. I won't list them all openly but start with comparing the declared country (no country selected -> ban) with the IP country. If the two are say the USA and India, then ban. Look at activity (yes admins can see it all) and humans with an actual interest will have been doing the right sort of searches before the signup. Etc. The problem is doing this on a big forum, say 100 signups a day... a lot can be automated (like the IP comparison, but that needs to be done carefully).

author: jnk0le
author_rank: Regular Contributor
timestamp: May 06, 2024, 07:32:47 pm
content: Quote from: MK14 on May 06, 2024, 02:57:55 pmIn that thread this dongle does enumerate as USBHID, later under "libusb-win32 devices", after which PROGISP was tried and failed.At this stage uninstalling the libusb driver should make the PROGISP detect the probe. (may need a reconnection)About a year later:https://www.avrfreaks.net/s/topic/a5CV40000000ajRMAQ/t394567It suddenly doesn't appear in dev manager at all.Assuming this is the same probe, considering the "wasted money" comments. He could be trying to reprogram it to usbasp (as indicated by linked website), but with the wrong firmware.Then the "translation" process has cut out the most important part of why it doesn't show up in dev manager.

author: westfw
author_rank: Super Contributor
timestamp: May 07, 2024, 05:34:02 am
content: QuoteOn the negative side, there is more discussion here on the nature and motivation of the poster than there is on either answering or clarifying the question (on both the OP's side AND the other forum members.)If either side would just SHUT UP about whether this is some sort of ChatGPT experiment, perhaps there would be enough useful content here for ... OTHER people to learn something (maybe here, maybe through "AIs" - what do you care if your answers get filtered through algorithms before it gets sent to the next person who asks a question? I doubt whether many of you are using your EEVBlog forum posts in the "publications" section of your resume...So, with that in mind...The "memory model" of having text, data, bss, stack, and heap is a C language thing. The exact implementation varies.As a "C language thing", the memory model is very much applicable to microconrollers.Yes, it's used on PIC, AVR, and ARM, and probably 8051.Yes, I've used it on both AVR and ARM (and also embedded x86, 68k, PPC, and MIPS.)The referenced web page does NOT really "involve a (modern) PC" when it comes to the details of the locations and growth direction of the various memory areas. With the 64bit address space now commonly available, a PC program probably picks some ridiculously large part of the address space for each piece, and then uses the OS and MMU/Pager to attach pieces of that address space to real memory as needed. eg Code at 0x1000000000000, Data at 0x2000000000000000, Heap at 0x73adf00000000000, Stack at 0x88deadbee0000000. (Note the weird addresses for Heap and Stack. It's a modern feature to randomize those addresses for security reasons. And the program doesn't need Stack or Heap addresses till runtime.) Also, it leaves out the now-common "read only data" section, which is important on PC-like systems for security purposes, and on microcontrollers so that constant data can be placed in flash.Exact implementations vary. For example, some compilers use a separate data stack and return stack (I think this is probably required for PIC and 8051, but there are AVR compilers that do it as well.)Hardware varies. On many microcontrollers, flash and RAM are not contiguous, or even in the same address space. And I've even used systems where the stack grows upward. A non-readable return stack is pretty common (that's why "two stacks" on a PIC.)Optimizations vary. I believe that implementing the data stack on a PIC is sufficiently expensive that it is a compiler option to allocate function-local data (which would normally be on a stack) globally, which is pretty easy as long as you haven't done any recursion.Implementation and management details of the Heap are especially variable. Systems I've used have kept careful track of free/malloc calls - which task did them, from which PC, a queue of the last N mallocs and frees, etc (I think it's a law: "in any large system, the complexity of malloc/free will increase until you also need to implement some sort of "lighter weight memory allocator."")The usual suspects have posted a bunch of useful information (THANK YOU nctnico, nominalAnimal, brucehoult!) about how a lot of the memory layout is actually under developer control. (but I'd claim that the "model" remains the same.)If Kittu20 needs additional explanation or details, they need to be more explicit about telling us exactly what parts they don't understand, or what additional information they need, or how they are confused. (that this hasn't been forthcoming is ... one of the problems in this thread.)Meanwhile, there are signs that OTHER people (including myself) are learning stuff from the technical-content posts in this thread, which is a good thing.

author: westfw
author_rank: Super Contributor
timestamp: May 07, 2024, 06:12:41 am
content: QuoteHmm. I should clarify that AFAIK, this model originated in C (on the PDP11), or perhaps one of the C predecessors (Algol? BCPL? The Fortran compilers I used didn't have a stack.) However, it's a pretty useful and workable memory model that is now used for many other languages as well.

author: Nominal Animal
author_rank: Super Contributor
timestamp: May 07, 2024, 07:04:02 am
content: Quote from: westfw on May 07, 2024, 05:34:02 amYes. It can beextendedby additional sections if using ELF-based toolchains, and its layout is controllable by the linker script or linker options, but the underlying idea/model –– and purpose –– remains the same.Thinking about the ways you can maximally utilize your Flash and RAM is the same thing as thinking about how to best use the "model".(I personally am a big proponent of using those additional sections, to both provide useful build-time and run-time features, but also making the source code more maintainable in the long term. I use them on all sorts of architectures, from small AVR firmware code, to fully featured x86-64 Linux applications.)Arduino environment is not the best example of how to utilize the "model", especially on older AVRs. The design of the "model" in Arduino environment is a compromise: it was heavily limited by the choice of the GNU g++ compiler, which cannot handle the separate address spaces and machine instructions used to access Flash and RAM, for technical reasons. The GNU gcc compiler can, but it would have limited the Arduino sketches to freestanding C, instead of freestanding C++ which they chose to use. (Clang can, in both C and C++, but for AVRs you'll want version 16 or later, which was released in late 2023; so it wasn't a possible choice for Arduino, until very very recently.)Fortunately, for ARM Cortex-M cores and many others, those with a single address space for Flash and RAM, the "model" does not have such low-level restrictions. Even later AVRs have such aunified address space, because it makes development for them in C and C++ so much easier.Quote from: westfw on May 07, 2024, 06:12:41 amIf we ignore small differences like whether there is a stack, one stack for return addresses and data, a return address stack only, or separate stacks for return addresses and function local variables, I do believe the base model originates in the very first true operating systems that allowed executing programs and returning back to initial system state afterwards; i.e. not simply grabbing the hardware, but "playing nice" with others.I mean, surely there were (similar) implementations before that, too, but at that point in time, such a "model" becamemandatoryfor tracking the resources a program would use, and to provide interfaces for such programs to request and release data memory from the operating system. (I do believe that for predecessors to ANSI C, the first such interfaces usedbrk() or sbrk()instead ofmalloc()/free().)Simply put, dividing the memory address space needed intocode,uninitialized data,initialized data, and optionallystack, is the minimum requirement for such tracking and management. It also turns out that even when developing embedded firmware or kernels, such divisions (and more detailed subdivisions and additions) are useful and effective for a number of purposes, so it juststuck.In a very real sense, it is the minimum common denominator among machine code memory use organization.Quote from: IanB on May 07, 2024, 06:37:18 amABI, or application binary interface, is a different thing, to the "model" discussed here. ABI describes how data is passed between different programs, or between an "application" and a "kernel" or "library".C basically requires a calling convention where one or morevariablescan be passed to the callee (called code) by value (i.e., changes done in the callee are not visible to the caller), and the callee returns a single variable.The argument is that some ABIs are designed to optimize this and this only, with other details like which registers the callee is required to keep unchanged, and which registers it can modify ("clobber" is the term used!) based on C; and this yields suboptimal results.I agree. C is not the do-all, be-all of programming languages, and although it is currently the easiest for other programming languages to use forbinding–– interfacing to code written in other programming languages ––, it should not be used as the only design criteria or guide.Fortunately, compilers can support more than one ABI at the same time, even on the same hardware architecture. For example, the embedded ARM Cortex-M ABI ––arm-none-eabiorarm-none-eabihfin ELFy terms –– is different to the ABI used in Linux (arm-linux-eabiorarm-linux-eabihf). (Thehfat end indicates hardware floating point support.)32-bit Intel/AMD x86 and 64-bit x86-64 hasseveraldifferent ABIs, originating from different operating systems.If you are familiar with Windows code, then that's exactly what e.g.fastcall,cdecletc. do on a per-function basis, although they only modify thecalling conventionpart of the ABI.Linux happens to use the SysV ABI on both x86 and x86-64. You can find its description for examplehere. The x86-64 System V ABI has one peculiarity I've found is very nice, even in C,because it was not designed solely for C in mind: it supports returning two different (integer or pointer) variables in registers (as well as passing up to six (integer or pointer) variables in registers). It means that I can do e.g.Code:typedef struct {int64_t value;int64_t status;} i64_value_status;i64_value_status my_function(int64_t a, int64_t b, void *cptr, long d, void *eptr, uint64_t f);and all parameters and the result value and status will be passed in registers, without going through the "slow" stack.Thus, once again, the ABI thing is not really a technical question, but a human one:how does one agree upon a good ABI? Using C as your only yardstick is not a good way. But, humans being humans, when your only tool is a hammer, all problems look like nails; and many humans do tend to stick to a single tool.

author: Tation
author_rank: Regular Contributor
timestamp: May 07, 2024, 08:24:55 am
content: Quote from: Nominal Animal on May 07, 2024, 07:04:02 amARM's AAPCS also states a parameter and return value passing mechanism that uses registers and, if not enough space on registers, then uses the stack or a memory buffer. The mechanism uses registers R0 thru R3 allowing the passing of up to 4 parameters or a vector up to 128 bits.The AAPCS even states that:Quote

author: Nominal Animal
author_rank: Super Contributor
timestamp: May 07, 2024, 10:01:04 am
content: Those wondering, ARM AAPCS = Procedure Call Standard for the Arm Architecture, maintained currently at Github atARM-software/abi-aa/.Anticipating the followup question (of how much embedded developers can affect the ABI used): While we can choose from different ABIs, to implement a new one, one needs to add the ABI support to a suitable compiler. No C or C++ compiler I know of lets an end user define the ABI, although GCC and Clang do let you reserve (a callee-saved) register using-ffixed-registercompiler option or as aglobal register variable.(On e.g. AVRs, which have 32 8-bit registers, reserving one or two registers (R2 to R17 are callee-saved) allows one to write simple super-lightweight interrupt routines in assembly that use no stack other than their return address, since they can use the reserved register(s) directly. Say, for example, toggling only a fixed I/O pin will only take about a dozen cycles or so, most of it (~10 cycles) being the typical interrupt overhead on AVR. For details on the ABI GCC and Clang use on AVR, seeavr-gccwiki.)

author: westfw
author_rank: Super Contributor
timestamp: May 08, 2024, 08:31:40 am
content: QuoteI didn't notice whether it has already been mentioned that between the Gnu linker and "objcopy", there are extensive tools for manipulating sections. (well, I guess the linker via linker scripts has been well-discussed, but there are other ways as well.) Objcopy lets you do things like "take this text file and turn it into a linkable data element in the named section"...For microcontrollers, you need to be a bit careful when converting the .elf file to uploadable formats that all of the relevant sections that you've defined actually make it to the chip.QuoteMy understanding is that C++ standards folk refused to allow the "named address spaces" that were added to C (in gcc versions somewhat newer than originally used in Arduino) and would have permitted transparent access to flash. Not true?The newer AVRs have a portion of their flash always mapped into the same 64K address spaces as RAM. This works fine ("const" data goes into flash) on chips with 48k of flash or less; I don't know about the bigger chips (only 32k at a time is mappable.)

author: Nominal Animal
author_rank: Super Contributor
timestamp: May 08, 2024, 11:52:23 am
content: Quote from: westfw on May 08, 2024, 08:31:40 amYes, viaobjcopy -I binary --add-sectionsectionname=data.bintarget.oConversely,objcopy -O binary -jsectionnamesource.odata.binextracts the contents of a section to a binary file.The limitation is that this excludes relocation information. For example, if the data contains addresses of functions or variables, those are lost. Fortunately,objdump -trsource.oprovides enough information to recover those on most architectures. (To generate C source that recreates the replacement data as an ELF object file. For example, to sort all entries.)Moreover, theELF object file formatitself is straightforward to parse. There are only four variants: 32-bit little-endian, 32-bit big-endian, 64-bit little-endian, and 64-bit big-endian. I've found it easy to read from e.g. Python (using thestruct module), but if one is careful, I've found parsingobjdumpoutput quite acceptable, too. (One just has to ensure that unexpected input is complained about, and not try to parse "almost correct" inputs.)One useful thing is to also usereadelf, because the two (objdumpandreadelf) are tools intended for roughly the same purpose, but use completely separate source code bases.Quote from: westfw on May 08, 2024, 08:31:40 amThe C++ standards folks rejected named address spaces, yes; but like Clang/LLVM, GNU g++ could have implemented them asan extension to C++.I tried to locate the original discussion a decade to two ago, when named address spaces were initially added to GCC, but could only findbug 69549which isn't the first time it came up. The argument was that the g++ developers could not find/decide a workable way the named address space qualifiers would have worked with templates and overloads. AIUI, Clang/LLVM treats address spaces as a first-level qualifier, i.e. different address-space qualified types are different types, and differ also from the base type. This seems to work just fine (after initial teething issues!), but the GNU g++ developers do not seem to agree.Funnily enough, this does affect even x86-64/AMD64, because of FS and GS segment register support; essentially, it has support for three separate address spaces. The FS segment is commonly used for thread-local storage –– each thread in a process seeing a different chunk of memory there. (The main tirck is that at offset 0 in that segment is the address at which the segment starts in the normal address space, so that when you apply e.g. address-of operator to a thread-local variable, the compiler doesn't just generate the FS segment address, it takes the TLS segment base address and adds the offset to the variable, generating the address in the global address space. Darn nifty if you ask me!) There areshenanigansthat could be done with the GS segment register in C++, if GNU g++ would just support named address spaces like Clang/LLVM does.Quote from: westfw on May 08, 2024, 08:31:40 amYes; in general, this is called anunified address spacein documentation.

author: MK14
author_rank: Super Contributor
timestamp: May 08, 2024, 11:53:59 am
content: While we are on this subject area, one question comes to mind.On 'proper', larger CPUs/computers, i.e. NOT most small/medium Microcontrollers. They usually have memory management units, virtual memory and operating systems. So, that each significant process/program and hence on individual cores/threads. It can appear and be treated as if it had an entire computer to itself, potentially starting at address $0000.., and with little or no worries about conflicting/sharing with anything else.With some exceptions, of course.But on (especially lower end) Microcontrollers, they typically don't have memory management units, virtual memory and somewhat often, don't run operating systems (with many exceptions).Yet, even at the low end of Microcontrollers these days, e.g. Raspberry PI PICO (pair of small M0(+) arm cores). They can have two or more, separate cores.So, how does the compiler(s), linkers etc. Cope with such possible conflicts, and uncertainty, over what the other core(s) / threads are using or not?Or in other words, you could have two completely separate Main()'s (one running on one core, the other running on the second), but which MUST mostly always use completely different locations in memory (except where they are intentionally sharing memory).My guess would be that the resources get split up (using link symbols etc), into smaller sections. With one core using its own set of linker symbols. But that must get very complicated, if one core runs a C program and the other, runs a completely different language (if that is even allowed).Fortunately, most/many programs on the PI PICO, are just fine with using only a single core. So, I've been fine, up to now.

author: westfw
author_rank: Super Contributor
timestamp: May 08, 2024, 07:41:13 pm
content: QuoteUsually you compile and one set of sources into a single binary, so that that stage of development doesn't know that there are going to be more than one CPU. Stack and Heap can be assigned to each cpu (or task) at runtime, but data, text, and rodata can be freely and randomly interleaved.

author: MK14
author_rank: Super Contributor
timestamp: May 08, 2024, 08:42:21 pm
content: Quote from: westfw on May 08, 2024, 07:41:13 pmThanks, that makes a lot of sense.I didn't release that such a simple and elegant solution, existed for that problem. I was expecting something longer and more complicated.Also, there might have to be rules/limits, so that only the first thread/core can access the hardware registers (as in I/O). To avoid possible race hazards, locking conditions and things. Otherwise mechanisms such as mutexes might resolve such issues.

author: Nominal Animal
author_rank: Super Contributor
timestamp: May 08, 2024, 09:40:28 pm
content: The simplest locking primitives when you have more than one core in a microcontroller are usuallyspinlocks. They are named that, because a core waiting for the spinlock to become free will just spin in a tight loop.RP2040, for example, provides 32 hardware spinlocks. On other architectures, either an atomic compare-exchange or load-linked, store-conditional is used (in a loop), with each core or task having their own identifying value they try to set the spinlock to. They spin in the loop trying, until they succeed.The main difficulty in implementation is the interactions with caches (cache coherency, atomic accesses), requiring careful construction for each architecture: a naïve implementation will look like it should work, but because of cache coherency or memory atomicity details, more than one core may believe they own the spinlock at the same time! Also, if the cores have separate caches, the cacheline containing the spinlock may end up being ping-ponged between RAM and the two contending cores, making the spinning partamazinglyslow. Which is why operating systems typically provide "better" locking primitives, which let other stuff run while tasks wait to grab a lock, and only use spinlocks for very short durations, like copying some variable or object only.

author: MK14
author_rank: Super Contributor
timestamp: May 08, 2024, 10:26:21 pm
content: Quote from: Nominal Animal on May 08, 2024, 09:40:28 pmThat's clever, that the RP2040 (PICO), for example, provides 32 hardware spinlocks. Using the SIO unit, to create them. Since the SIO connects to both cores, and (presumably) internally has 32 bits worth of state, for doing it.As you detailed, caches can be problematic. They can also introduce significant uncertainty, on how the real-time software (especially timing wise), will behave.32 spinlocks, should be enough, for quite a few independent sections of software, to do their own things.I suppose, a mechanism, more like a callback (but to help with multiple cores), whereby, it can carry on doing other stuff, until the locked thing(s) it wanted, are ready.Given the extensive, long and sometimes prohibitively expensive software development costs. It might be better, to get a single core CPU with much greater speed (clock frequency and/or IPC) for that single core, rather than handle all the complexities of coping with multiple cores.On the other hand, it can be fun, educational and save money on the parts cost, if something was going into large scale mass production. Then the dual core RP2040, can make sense. Hence making it worth the extra time invested in such work.

author: Nominal Animal
author_rank: Super Contributor
timestamp: May 09, 2024, 12:58:38 pm
content: Quote from: MK14 on May 08, 2024, 10:26:21 pmI disagree, but my opinion is colored by my own experience, and having specialized in parallel and distributed computing (in HPC, simulations and such).When you can separate the logical tasks for each core, the end result can be much simpler than the same functionality running on a single core.The key difference is understanding and using the various mechanisms one can use for communications (and passing data) between the cores, and how to separate the "jobs" effectively.In other words, you do need to learn/knowmoreprogramming techniques, but it is worth it in the end. Message passing, message queues and mailboxes, are extremely common, and very often used in systems programming especially in low-level graphics interfaces. Inter-core interrupts (where code in one core causes an interrupt in a designated other core or all other cores) are also useful, but more for synchronization than data/message passing. RPis use a mailbox interface for communicating between the VC and the ARM core, for example. If you care to learn by a combination of learning the background idea/theory and then experiment, I assure you can get the hang of it quick.It does require some experience to design the separation between logical workloads in a parallel/multi-core system effectively, though.If we look at historical precedents, the first parallelization primitives in programming languages revolved around parallelizing loops and such, which really isn't that useful in real life; we just had to learn the better ways, eventually.

author: MK14
author_rank: Super Contributor
timestamp: May 09, 2024, 01:50:21 pm
content: Quote from: Nominal Animal on May 09, 2024, 12:58:38 pmI don't think there are any right or wrong answers as such. It is like many engineering things, whereby there are millions of different ways of skinning a cat.A period of time, after I posted, what you quoted. I partly changed my mind, because some real-time tasks, would actually benefit from the separation (partly like how you describe), but I was thinking more on the lines of. One of the CPUs could have any intensive interrupt handling sections, with the corresponding timing jitter, and increases in maximum latency.But the other core, could have few or no interrupts, and hence be able to have rather deterministic timings and progress through what it is supposed to do.I see your point, which is a very good one. Which (if I understood it correctly), is saying that splitting real life software tasks/jobs (presumably in some but not all cases), between different CPUs (or threads), can be a useful way of breaking/partitioning down a task, into efficiently sized 'chunks' for software developers, to handle.Because single core performance (barring possible future developments/inventions, e.g. Quantum computers, although that would be more like a huge number of tiny cores, acting in parallel), is unlikely to speed up that much, because of laws of physics limitations, such as the speed of light and limits as to how small, low capacitance and fast, real life producible integrated circuits, can develop into.Also, that tends to use disproportionately much more power, than lower frequency solutions.Whereas, having an ever increasing number of cores, in the same processor package, for CPUs or graphics cards. Tends to be cost, size and power efficient. So could well be the way forward.But there could be barriers, such as Amdahl law.https://en.wikipedia.org/wiki/Amdahl%27s_law

author: JPortici
author_rank: Super Contributor
timestamp: May 09, 2024, 05:35:44 pm
content: Quote from: MK14 on May 08, 2024, 11:53:59 ammy extremely limited experience with dual core MCUs is that they are completely separated system: they share the GPIO and some mailbox system to communicate with each other, but then each core is in fact a separate MCU: separate memory, separate peripherals. So each core effectively runs its own firmware and treats the other core(s) as independent entities, and use the mailboxes to communicate.Then if you use an RTOS with multicore support you can select which task goes to which core, either at compile time or at runtime.. freeRTOS for example support some kind of multicore multiprocessing

author: MK14
author_rank: Super Contributor
timestamp: May 09, 2024, 05:56:02 pm
content: Quote from: JPortici on May 09, 2024, 05:35:44 pmThat sounds like a good idea. The extra resources of multiple-cores, combined with the extra features of an OS, such as the aforementioned freeRTOS, sounds interesting for some projects. It would mean a project running on a very low cost RP2040 Raspberry PI pico, could have some of the functionality of its bigger brothers, such as the Raspberry PI 5.But without their bulky size, relatively heavy power consumption and difficulties, that might arise, because a full blown Linux, Windows or similar OS, is too much for most microcontroller projects.

author: Nominal Animal
author_rank: Super Contributor
timestamp: May 09, 2024, 06:00:43 pm
content: I swear I posted a reply, but it vanished into thin air!Quote from: MK14 on May 09, 2024, 01:50:21 pmFully agreed; that's why I described mine as an opinion I currently have due to my own personal experiences.Quote from: MK14 on May 09, 2024, 01:50:21 pmYes, exactly.Splitting code into separatetaskscan make each of them much more manageable even on a single-core device; although then you do need atask scheduler, and think about priorities and pre-emption. On a multi-core device with one main task per core, you don't even need a task scheduler.As mentioned, FreeRTOS provides one such task scheduler and locking primitives and message mailbox primitives for you.In my own case, the overall approach has lead to me considering using more than one MCU in many of my designs, so that the main MCU doesn't need to be so powerful (so a cheaper and more energy-efficient MCU suffices). For example, the ultra-cheap Padauk pdk14/pdk15 ones (programmed usingsddcandFree PDK) for additional PWM, or PDM generation in a tight loop.In the same vein, I like to use microcontrollers with native USB, high-speed (480 Mbit/s) if possible, full-speed at minimum (12 Mbit/s), for I/O with single board computers running Linux. It is easy for the microcontrollers to handle the timing requirements et cetera, and just transfer the not-so-timing-critical commands and bulk data via USB. These don't need to be expensive either, as the WCH CH55x are cheap (CH552G about 0.50€ in singles!) and easily programmed usingsddcandch55xduino.My favourite, of course, isTeensy 4.0, which using default Teensyduino USB Serial implementation can easily sustain 200+ Mbit/s (25 Mbytes/s) to a Linux host, with no other requirements on the Teensy side than writing in chunks of at least few bytes, instead of individual bytes to the USB stream.I haven't even checked how fast I can transfer to Teensy using Linux USB Bulk transfers, because at 25 Mbytes/sec, you can update a 320×200 pixel 16-bit display at over 160fps; the bottleneck is the Teensy-to-Display, not the USB Serial or tty layer.Quote from: MK14 on May 09, 2024, 01:50:21 pmThe main practical cause for Amdahl's law in HPC simulations is the simulator design: they do computation and communication in separate steps instead of in parallel.Let me rant a bit, and show you a real-world example of this.Consider a 2D simulation limited to a rectangular area. You split it in roughly equal sections, with each core (ornodein HPC terms) handling one. The border regions between neighbors need to be synchronized between nodes, so most simulators just do some computation, then transfer the changes in the border region to their neighbors, in turns. Because the width of the border region is fixed –– it is at least the maximum interaction distance within the simulation –– it forms the fixed, non-parallelizable term in Amdahl's law, limiting the benefit of adding more cores to work on the same problem.My solution is to subdivide the region each core handles. For example, if the region in split in one dimension, then we need four subregions per core with roughly equal amounts of work:╔═╤═╤═╤═╦═╤═╤═╤═╦═╤═╤═╤═╗║1│2│3│4║1│2│3│4║1│2│3│4║(three regions/cores)╚═╧═╧═╧═╩═╧═╧═╧═╩═╧═╧═╧═╝All cores work on region 3.All cores work on region 4, for double the amount.All cores work on region 3. Each core also sends the relevant changes from region 4 to their neighbor on the right, and receives the same information from their neighbor on the left.All cores work on region 2.All cores work on region 1, for double the amount.All cores work on region 2. Each core also sends the relevant changes from region 1 to their neighbor on the left, and receives the same from their neighbor on the right.After each such cycle, evendetailed balanceis maintained (all reversible events have the exact same probability in either direction; for example a particle wandering from subregion 1 to subregion 4, and vice versa – but depending on the subregion origin, you need to start the examination from a different substep!). It's easy to verify numerically, but I've never bothered to find out how to write the proof in a form acceptable to mathy papers.This pushes the Amdahl's law limit much higher: to where the transfer of data takes longer than the computation in the sub-step. Up to that point, this scales linearly –– quite perfectly so in practice! –– as the number of cores increases.When the simulated region is split to multiple cores in two or three dimensions, you need a minimum of 4×4=16 to 4×4×4=64 cells, with a 2×2 or 2×2×2 computing region traveling it in a (near) Hilbert curve, with similarly two cells between the working areas of neighboring cores.Unfortunately, scientists creating these simulators do not seem to be able to handle this kind of spatial complexity in their programming, so their response is typically "That's way too complicated! I'll just request more CPU time from the cluster and use the samecrappy codeeveryone else uses".Yes, I am bitter! When I was young, I didn't believescientistscould be this short-sighted. And I cannot really read papers on materials physics using Monte Carlo methods anymore, because the discontinuities at simulation boundaries in their plots makes my eyes bleed.Ahem.Back to the topic at hand.In many cases the Amdahl limit is a consequence ofdata transfers, either their latency, or limited bandwidth. Heck, even on x86-64/AMD64 processors the RAM ↔ cache bandwidth and cache miss latencies (and in multithreaded processes, cacheline ping-pong between cores) is typically the limiting factor, and not the computational capabilities of a core.

author: Nominal Animal
author_rank: Super Contributor
timestamp: May 09, 2024, 07:13:43 pm
content: Quote from: JPortici on May 09, 2024, 05:35:44 pmThis is also common when the cores are of different types. For example, in Raspberry Pi's, the ARM core and the VC core use mailboxes to communicate with each other.It is also very common with all sorts of graphics controllers on ARM, x86, and x86-64.I like the approach. The main gotcha is fully, carefully and completely documenting the interface between them, and either sticking to it, or keeping the documentation ahead of the implementation. Letting the documentation lapse is an utterly fatal failure in the long term. I'm serious, no hyperbole.The documentation serves a dual purpose: it describes for those who do not know yet or have forgotten some of the details; but also forces those who do know organize their thoughts and describe their knowledge of it. Multi-core bugs typically arise from misunderstanding how the system is supposed to work, the difference between what the programmer intended and what they wrote in code, or from the complex interactions between separate pieces of code (typical example being locking order and locking schemes in general). I really cannot stress the importance of correct, full documentation of the interfaces/boundaries enough.

author: MK14
author_rank: Super Contributor
timestamp: May 09, 2024, 07:17:03 pm
content: Quote from: Nominal Animal on May 09, 2024, 06:00:43 pmNext time, use a spinlock! (Joke)Quote from: Nominal Animal on May 09, 2024, 06:00:43 pmThat's a tricky one. Technically speaking, especially from a software point of view, but also from the real life power consumption figures and component costs (BOMs), you are right.But, in practice, I can imagine (if it was for a large department in a business), the upper managers and most senior technical staff, saying no!Because, if you have a single, large MCU, doing everything, that will be seen as just having one piece of software/firmware inside of it. So there is only one (albeit very large and complicated), piece of software to write, test and get working.But, if instead, you have 10 relatively small MCUs, doing the same task. Although, technically speaking, I accept that it could use a lot less power, cost a lot less, allow much more efficient partitioning of the software development process, potentially making it cheaper, quicker and more reliable, to create.The upper management may raise the following concerns:Instead of there being one single MCU, that needs to work, there would be ten, so it could (in rough theory), be ten times more likely to break, and hence be less reliable.There (could) would be ten sets of software firmware, to download, install, test, develop and maintain. Hence ten smaller software teams, but with people sometimes leaving, vacations and sickness etc. At any given time, one or more of those teams could be non-working, because the sole key player of that team, is unavailable at the moment.If MCU hardware malfunction was suspected, as a cause of the current issues. One MCU would be a lot quicker and easier to replace, than ten smaller ones, usually. But not always.Instead of having one big set of manuals for the sole big MCU, there could be 4 or 5, different sets of manuals, for each different MCU type. Which would be a lot of work for a new team member to absorb, especially at the beginning.If there is a need for debugging. As well as uncertainty over it being an issue with the software or hardware, it would also be an issue, which of the n (e.g. ten) MCUs, was causing the issues.In practice, communications systems, are a risk of being problematic, such as a source of very complicated, and perhaps exceedingly rare and/or difficult to reproduce issues and bugs.Because a big single MCU, doesn't necessarily need to communicate with anything else (depending on the project requirements).But, for example ten MCU system, often (but not always, they could be almost 100% independent for some projects), may need very extensive communications. Which could have very hard to realize, bugs or issues, with the communications protocols.Also, easily debugging such systems, and being able to check (trace) all those communications, could be extremely difficult, expensive and time consuming.E.g. What if every hundredth (1 in 100) time, the system is switched on, it fails to 'boot up' and start, reliably. It would be a real pain, switching it on and off, hundreds of times. It might take 30 seconds for it to fully boot-up, into its menus or whatever it does. So very time consuming, if there are problems.Then the issue would be, which combination of those ten MCUs, is causing the issue(s)?If you want to manually flick through the software, to see if you can see any potential weaknesses. There could be, ten sets of such software listings, which is harder and takes longer (probably).But overall, I accept that perhaps experimentation and real life experiences, of using those two alternatives techniques. Would help, find out which is best (if any method is), rather than using human intuition, and gut-feelings, which are not always right.

author: JPortici
author_rank: Super Contributor
timestamp: May 09, 2024, 07:20:12 pm
content: Quote from: MK14 on May 09, 2024, 05:56:02 pmi guess it depends from the task at hand... and if the cores are symmetric (identical) or not.For example, it's very rare for me to need a variable number of threads at runtime, so i know in advance how many resources i need, hence i design the tasks (or the firmware) to reside in the appropriate coreIn case you wonder it's common for MCUs to be asymmetrical (for example, M4+M0/cortex A + cortex M/dsPIC33CH in which either/and core/peripherals are different) unlesss you go for something like cortex R which is symmetrical, but in that case you usually want to run the cores in lockstep mode

author: Nominal Animal
author_rank: Super Contributor
timestamp: May 09, 2024, 07:29:28 pm
content: Quote from: MK14 on May 09, 2024, 07:17:03 pmDefinitely yes. Which makes me want toI often remind people that my own opinions are geared towards making better stuff and making things better, to learn to make better things; and not getting employed with a good salary or making a profitable business. To me, there are too many of the latter already, and not nearly enough of the former, because in the current electronics and software markets, the two are usually/typically mutually exclusive. Feel free to disagree, too: the situation, needs, and balance varies from person to person. Mine are just one approach among many.

author: nctnico
author_rank: Super Contributor
timestamp: May 09, 2024, 07:43:54 pm
content: Quote from: MK14 on May 09, 2024, 07:17:03 pmThe problem with this approach is that partitioning into seperate processes is very hard to get right. Processes typically need to communicate at many different levels which hugely complicates timing relationships. In practise seperating into different processes often leads to more problems than it solves so it needs to be considered very carefully. My personal rule of thumb is to only split processes when their functionality really, truly needs to happen in parallel. This also requires making a good structural design of how data is being processes and states are going to be handled. Just starting coding is going to end in a mess. Especially when having teams doing their own thing without coordination and specifications.

author: MK14
author_rank: Super Contributor
timestamp: May 09, 2024, 08:00:21 pm
content: Quote from: nctnico on May 09, 2024, 07:43:54 pmYou have raised some very good points!, thanks.That makes perfect sense.I'd also like to add, that in my understanding. Many projects, end up changing, during the project development phase.Perhaps because the customers, keep on changing their minds and/or keep on fiddling with the specifications (warning: Those issues, get multiplied by a large factor, if any government department, is involved!).But also, while the thing (project) is being developed. The original ideas can need extensive reworking, to work reliably and well. So, there can be lots of changes.So, having one big MCU, means that it can contain, many of these changes.But as you appeared to state. Splitting up the functionality, between different units (MCUs), could lead to issues, further down the line.E.g. The Big/Main MCU has 512k of ram and the smallest additional MCUs, have only 96 bytes each.So, if things change and all the code is in a sole, big MCU. Project changes, meaning the smaller tasks need an additional 256 bytes (because of buffers to support, bigger and wider, command queues or whatever). It is no problem, needing a few extra sets of 256 bytes, when a total 512k of ram is available.But if the smallest MCUs, were specified as having only 96 bytes ram in total for all its code. That would be a major headache.

author: MK14
author_rank: Super Contributor
timestamp: May 09, 2024, 08:10:44 pm
content: Quote from: JPortici on May 09, 2024, 07:20:12 pmNow you mention it, I had only partially noticed that many MCUs are asymmetric.I presume that the MCU manufacturer's know what they are doing. So, either their own research and experience or customer (especially very big ones) requests and requirements (or even practicalities of the manufacturing process, such as to keep overall power consumption to within reasonable limits), is why they have done that.Thanks for pointing it out.Maybe there is a tendency for one of the processors, to handle the real-time I/O, and related interrupts and timings. So, it doesn't need more complicated instructions, such as floating point, nor needing maximum performance. As a lot of its time, might be 'wasted', in polling loops, waiting for interrupts to occur and other house-keeping tasks.But the other processor, runs (perhaps) the algorithms and other heavy stuff. So, needs the best performance, floating-point and other extra bits and pieces.I also wonder if it is to reduce the licensing fees for the Arm CPU cores?As an M0(+) is free or relatively free for some (I think), but the M4 etc, floating-point versions, probably do get charged licence fees.

author: nctnico
author_rank: Super Contributor
timestamp: May 09, 2024, 08:17:38 pm
content: The problem not only exists when using multiple CPUs (or even seperate microcontrollers), but also when using pre-emptive (time slicing) multitasking. For a project I'm involved in there is an ongoing project to rewrite the entire project from scratch due to a bad design of seperate processes, sharing of information and timing problems. The original design simply is unfixable.When using multiple physical CPUs / microcontrollers you have the additional problem that you don't know the state and communication between the physical units will fail. This means you'll need to implement methods to recover / deal with communication and node problems.

author: SiliconWizard
author_rank: Super Contributor
timestamp: May 09, 2024, 08:33:55 pm
content: Quote from: Nominal Animal on May 09, 2024, 12:58:38 pmYes. I agree with that. But this "key" difference is unfortunately not well known, even less so mastered, by most. That's unfortunate.I find the RP2040 a very nice starting point for learning how to design embedded multi-core systems. It has hardware spinlocks, a very simple mailbox between the 2 cores, and banked SRAM which allows the 2 cores to access RAM concurrently for data that is placed in different banks. That gives a lot to play with, while stilll being simple enough to grasp in just a few hours.

author: Nominal Animal
author_rank: Super Contributor
timestamp: May 09, 2024, 09:30:10 pm
content: Quote from: nctnico on May 09, 2024, 07:43:54 pmQuote from: SiliconWizard on May 09, 2024, 08:33:55 pmBoth true.This does require experience and understanding of the possible approaches, and their relative merits and downsides, definitely. Yet, the knowledge is not that complicated or massive; thevolumeof experience and understanding is not that big.I do a lot of POSIX+GNU C development on Linux, and extremely often usePOSIX threads. (The default stack size is immense, so it is a good practice to set a smaller/configurable stack size for your worker threads; it's just four or five lines of C more.)x86, x86-64, and Armv8.1-A also have atomic operations (not just ll-sc/cmpxchg, but atomic add/and/or/xor) exposed via compiler-providedatomic built-ins, which allow very interestinglocklessthread-safe structures.Isuspect, but am not certain, that writing useful tools and experiment with abstract data structures and methods of splitting overall workload to separate tasks/threads/processes in an effective and maintainable way, in the Linux/BSD/MacOS POSIX+GNU C environment, is an useful way to learn parallel (and distributed if you add e.g. MPI, sayOpenMPI) programming techniques useful for embedded programming. Things like Unix domain stream sockets are pretty near perfect analogues for error-free full-duplex serial communications, and POSIX signal delivery behaves very similarly to interrupts (with selective masking/blocking of signals on a per-thread basis).In comparison, I do not believe using e.g. OpenMP extensions to C are useful at all.I do test all my ideas in fully-hosted environment in C in Linux first, before writing it for a microcontroller. Because I understand the difference betweenfreestandingandhostedC environments, I understand which C library features I need to avoid to keep the implementation portable to limited embedded environments, and what Linux/POSIX features "map" nicely to embedded features. In many cases, I simulate (to a varying degree – sometimes just the user interface, sometimes entirely) what I'd like the microcontroller to achieve, before even picking which microcontroller dev board I'll use!Mostly, my projects interface to a SBC, though, and I haven't made any truly complex microcontroller projects yet.I definitely believe the underlying problem –– the difficulty in learning how to split the workload efficiently, which synchronization and communication primitives to use –– is an issue of lack of well-known good examples, documentation, and other learning materials; and not that the concepts involved are themselves hard per se. It is verydifferent, which means that the more experience you have in single-threaded C, the harder it can be to un-learn the details that work differently in a parallel or distributed environment, before one can truly learn and understand the new different stuff.

author: tellurium
author_rank: Frequent Contributor
timestamp: May 09, 2024, 10:27:14 pm
content: So why don't you write a guide, guys, and share the knowledge you have.Take rp2040 as an example, and create a simple lockless queue that two tasks on two cores can use to exchange data.

author: Nominal Animal
author_rank: Super Contributor
timestamp: May 09, 2024, 11:19:59 pm
content: Quote from: tellurium on May 09, 2024, 10:27:14 pmRP2040 is a Cortex-M0+ (ARMv6-m) core, which does not have any kind of atomic support; lockless data structures cannot be implemented for it. That's why they added the hardware spinlock support: software atomics are impossible on Cortex-M0+.Cortex-M3/M4/M7 (ARMv7-m) supportsload-link, store-conditionalaka LL/SC for atomics, via LDREX (load-exclusive) and STREX (store-exclusive); see e.g.ARM Cortex-M3 documentation here.Basically, LDREX loads (8, 16, or 32-bit) data from an address, and you have a few cycles to do something with it. The following STREX to the same address succeeds only if the other core(s) did not access the same address (and the "do something with it" did not include executing a CLREX instruction); it has both a store destination address in a register, as well as a destination success register.With LDREX/STREX (or any other LL/SC implementation), "lockless" structures are inherently spinlocks. For example, let's say you have a counter, and you want each caller to obtain a separate value, monotonically increasing without gaps:Code:unsigned int v = 0;unsigned int next(void) {return __atomic_fetch_add(&v, 1, __ATOMIC_SEQ_CST);}On x86 and x86-64, the function simplifies to loading 1 in some register and then doing a singlelock xaddinstruction. Thelockprefix means the processor will handle the synchronization across cores, and it will be atomic. It can take some cycles longer than a normalxadd, but it will not spin.On ARMv8-a, it simplifies to loading the address and 1 to some registers, and then doing a singleldaddal(same asstaddal) instruction, which is equivalent to thelock xaddon x86/x86-64.On Cortex-M3/M4/M7, it compiles to a loop aroundldrex,adds,strex, withdmb(data memory barrier) surrounding the loop. These normally end up never iterating more than once, and I do not believe it is possible for multiple cores to keep perfectly lockstep for more than a few iterations (even if you try to), because of caches and the underlying bus hardware. While it looks and acts atomic at the C level, I don't really consider this "lockless".On Cortex-M0/M0+, you need to implement your own__atomic_fetch_add(), as the compiler just generates a call to it. The instruction set just doesn't have a way to implement it automatically. The implementation on RP2040 would use a dedicated spinlock (typically the same one forall"atomic accesses") for the duration of the load-modify-store cycle. It, too, normally spins/blocks only for the duration of one load-modify-store cycle, but isn't "lockless" by any interpretation.

author: SiliconWizard
author_rank: Super Contributor
timestamp: May 09, 2024, 11:26:38 pm
content: Note that the Pico SDK does include such queues already implemented for you, using spinlocks. You can have a look at the source code. They've done a decent job.Links:https://github.com/raspberrypi/pico-sdk/tree/master/src/common/pico_synchttps://github.com/raspberrypi/pico-sdk/tree/master/src/common/pico_util

author: Nominal Animal
author_rank: Super Contributor
timestamp: May 09, 2024, 11:33:12 pm
content: Quote from: tellurium on May 09, 2024, 10:27:14 pmMy own learning path was so different to those learning programming today that I don't know what the effective approach to learning this stuff is. I don't even have any good books to recommend!I have thought about it, though; a lot, actually. The problem is I need a set ofvictimslearners to experiment on first, to see exactly which approaches and descriptions of the concepts involved actuallyworkon todays programmers.Besides, I'mstill broken, with any kind of responsibility or making promises causing me to fail, for now. I can answer questions and help, and do my own stuff if I don't show it to others or in public, but that's about it.

author: nctnico
author_rank: Super Contributor
timestamp: May 10, 2024, 10:26:29 am
content: Quote from: Nominal Animal on May 09, 2024, 11:33:12 pmSame here. A good start would be to create a mental model people can use to 'visualise' how processes interact when they run in parallel (either on multiple CPUs and/or by time-slicing). Thinking back to my EE study, this topic wasn't explored very deeply during software engineering related classes. Maybe the problem is that educators have the idea that processes run isolated without any interaction between processes.

author: JPortici
author_rank: Super Contributor
timestamp: May 10, 2024, 11:54:12 am
content: Quote from: MK14 on May 09, 2024, 08:10:44 pmExactly.For example: dsPIC33CH, the slave core has less memory and overall less communication peripherals, but it runs from RAM (needs to be loaded from the master) so it's both faster and has less cycle penalties from branches. Its peripheral set contains multiple ADCs, DACs, comparators and many, many PWMs. The slave core is aimed at digital power / motor control loops.The master core has a ton of memory, and almost all the communication peripherals (many UARTs, I2C, SPI, SENT, CAN, ...) the master core is thought to be the arbiter and communicate with the rest of the system.Similarly speaking, the M4/M0 hybrids: the M0 usually having peripherals better suited for IO management (buttons, lights, bit banging...) and the M4 core is both more powerful and it runs the algorythms.Those CortexA/CortexM (such as STM32MP) use the cortex A for the user interface/embedded linux/communication, obviously, and the cortex M to run real time tasks

author: MK14
author_rank: Super Contributor
timestamp: May 11, 2024, 01:20:26 pm
content: Quote from: JPortici on May 10, 2024, 11:54:12 amThanks for a very insightful response. After chewing over it for a while, I want to comment that..I suspect, that perhaps it originates, because a long time ago, when things were less integrated than now, many such embedded systems, had a big and powerful DSP on them (if required), and a somewhat powerful microcontroller as well (not always needed, as sometimes the DSP could handle the lot).So for argument sake, let's say the item was a middle of the road, Hi-Fi unit, from the 1990s/2000s. The DSP, would act as a powerful sound processing system. E.g. To improve the sound effects, create special, adjustable room type (simulated) stereo effects, show a frequency bar graph and other things.Whereas a normal MCU, could handle the HI-FIs, buttons, LEDs, displays, and the control logic/driving for any radios, tape decks, record players, and CD drives, etc.I think DSPs use to be extremely expensive, so the more of the work, that could be off-loaded to a normal MCU, which were relatively cheap, even quite some time ago. The cheaper the product could be, to be produced.These days, they tend to include extra DSP instructions (or similar), on some modern MCU processors.N.B. Before anyone tries to jump in and correct me. I'm uncertain of how exactly they use to split the work between DSPs and MCUs, and also how often MCUs were included in past DSP products.Also the DSPs, could have had considerably better quality peripherals, compared to MCUs, a long while ago, in the past. Such as very high speed A to D converters, with decent (for that time), resolution.

author: Kittu20
author_rank: Regular Contributor
timestamp: May 11, 2024, 02:47:53 pm
content: Thank you for the discussions and responses on my post. I want to address any concerns some of you may have about my authenticity. I assure you that I am a real person, not a bot, genuinely interested in learning from this community. I have a background in electronics engineering, I am interested growing career in the field of embedded systems. I am actively on a learning journey in the field of embedded systems. To enhance my practical understanding, I have purchased microcontrollers, sensors, and other devices to conduct experiments. I am improving my coding skills by writing code on my Windows laptop.You may have noticed that I ask questions about C programming, microcontrollers, and embedded projects. I strongly believe that having a solid foundation in C programming is essential for success in embedded systems.I've noticed some criticism regarding my approach to asking questions, particularly about not being specific enough. I want to clarify that I don't see there's a strict order or specific rulebook dictating how questions should be asked. I ask questions based on what's on my mind and what I'm genuinely curious about. I seek clarity on topics that I find challenging or unclear. There are no guidelines here specifying what questions should or shouldn't be asked—I simply ask what I need help with. My goal here is to learn and improve my knowledge. If you can guide me in the right direction, I can improve my questions and interactions.The reason I posted about C memory layout is because I found this concept challenging to grasp fully. I was interested in understanding how the concept of memory layout in C programming is practically used,My specific question was about how experienced individuals in embedded systems utilize memory layout, especially those who have worked with microcontrollers like 8051,PIC and ARM. I wanted to know if anyone here has used it practically, question was simply for sharing knowledge.I had a general understanding of memory layout and its subsections, mention reference link in thr first. I was initially confused because each microcontroller has its own unique memory structure, although in general memory layouts are generally divided into four specific sections I realized that memory layout is a general concept and not related to c language rather, it depends entirely on the hardware being used.To those who believe I am a bot, I have never seen a bot that participates in these hands-on activities such as writing C programs, Sharing screenshots of program output. Making hardware connections on breadboards and sharing picture on forum, Reading datasheets, Drawing block diagrams and circuit diagrams on paper, Sharing screenshots and pictures of real work on forums.I actively share my own C programs, connect components on breadboard, write programs for microcontrollers, and share output screenshots—all done by my own hands.These activities reflect my genuine interest and commitment to learning and exploring electronics and programming.If there are still any doubts in your minds, I would be happy to address them and clarify any concerns. I want to ensure that there is no room for misunderstanding, as I value genuine help and constructive discussions within this community.I truly value the insights and expertise shared here, and I'm eager to absorb as much knowledge as I can to enhance my skills.

author: MK14
author_rank: Super Contributor
timestamp: May 11, 2024, 03:34:49 pm
content: Quote from: Kittu20 on May 11, 2024, 02:47:53 pmSpeaking in general. On a desktop PC, 40k of RAM, is 40k of RAM, regardless of which part of main memory, it is. I.e. If the computer has 8GB of main memory, it is all pretty much the same. With some excepts, such as if parts of it are allocated to any built in graphics units (iGPUs).But on a (hypothetical, but vaguely typical), MCU (microcontroller), the RAM, may have specific hardware features, pertaining to specific segments of it.E.g. (but still hypothetical, so I don't need to delve into lots of datasheets, to give real life examples).Only an 8k section, is connected to the low power (battery backed up) section, possibly also supporting a real-time clock feature. So, that 8k, needs to have any/all of the variables and stuff, which need to retain their contents, even if there is a power-down (assuming the battery backup capabilities are used).A different 16k section, maybe the only parts of RAM, which are shared between the main processor, and the much lower clock frequency (max), very low power consumption processor (sometimes seen on some RiscV CPUs), in the same chip.A particular 2k section may be semi-reserved for USB and/or CAN and/or other specialized hardware features.The DMA and/or cache and/or other features, may similarly be limited to only part(s) of the RAM address space.Hence the need to get the address map(s) right. But there can be many other reasons for needing to adjust the maps, some of which have already been mentioned in this thread.

author: pcprogrammer
author_rank: Super Contributor
timestamp: May 11, 2024, 04:01:08 pm
content: Quote from: MK14 on May 11, 2024, 03:34:49 pmThere are also microcontrollers that have different types of RAM in it. For instance the Allwinner F1C100s has a small section of SRAM to be used by, at minimum, the boot loader and a large section of DRAM for which the controller has to be initialized first to be able to use it. That is why a boot loader needs to go into the small SRAM and do the needed initialization before the main program can be loaded into the DRAM. It is not capable of running code directly from FLASH memory and it does not have any of that build in.Another thing with RAM can be how it is coupled to the processor. In ARM based controllers it is possible to have TCM (Tightly Coupled Memory) with a faster access from the core than the SRAM. The TCM part can be divided into instruction and data memory.

author: Nominal Animal
author_rank: Super Contributor
timestamp: May 11, 2024, 07:57:23 pm
content: Even on ATmega32U4 (8-bit "old-style" AVR), the native USB peripheral has 832 bytes of dual-ported RAM, but to the AVR core, it's more like a configurable set of FIFOs dedicated for USB.(It is quite a lot, considering it has only 2560 bytes of SRAM, but it is how it can sustain about 1 Mbytes/sec over USB, about 8 Mbit/s of payload data.)The most RAM variants I know of on a microcontroller is definitely onTeensy 4.1: normal built-in RAM (OCRAM), tightly-coupled data memory (DTCM), tightly-coupled instruction memory (ITCM), and external RAM (I use an additional 8 or 16 Mbytes of PSRAM). Plus there is 32k of instruction cache and 32k of data cache, which is transparent to the code (except for cache eviction and prefetch instructions so one can get the maximum use out of them). All with only one core.Fortunately, it has a single 32-bit address space, and even PSRAM is accessed without any shenanigans in the very same address space. Aside from timing differences and architectural details when doingshenanigans(DMA and FlexIO support functions), one doesn't really need to worry about it. (There are even two GPIO peripherals to choose from for each I/O pin, depending on which interconnect bus you want to use.)(One reason I like Teensy 4.1 so much is that for USD $42, you can get a Cortex-M7 with hardware FP (32- and 64-bit) running at 600 MHz with 19 MiB (512k + 512k + 8M + 8M = 19,922,944 bytes) of RAM, 8 MiB of Flash, "lockable" with run-time code encryption/decryption support, 100Base-T Ethernet, two high-speed (480 Mbit/s) native USB interfaces (with support for one Host and one Client port currently), almost 50 usable I/O pins with lots of peripherals, and pretty goodTeensyduinosupport library for development in the Arduino environment with sources atGitHub; plus aforumwhere the developer participates actively. Very nice for hobbyists like me. The one proprietary part is the programming/bootloaderchip.)I'm pretty sure the RAM model for tile processors (like XMOS xCore) has even more parts, because there each core has some local RAM, and one or more RAM regions of variously shared RAM.On architectures with virtual memory support, we can go an order of magnitude more complicated. Over a decade ago, Icreated an exampleof how to use memory-mapped files in Linux for manipulating a terabyte (1,099,511,627,776 bytes) -sized object in memory, as long as you have sufficient disk storage, speed limited only by the storage-RAM bandwidth. Not to mention things like mapping the same RAM pages twice consecutively, so that you can treat a cyclic buffer (whose size is a multiple of page size) as always having linear data (assuming the cache coherency allows this safely; they often do not).There definitely is a limit as to how deep one should dive into the details, before actually needing the info and applying it in practice.I personally only bother to remember the key ideas, and how the different features can be useful; and just look up the details whenever I need them (for example to write this post).(That is also why I prefer written text over face-to-face for technical discussions. Face-to-face, I'm always repeating "oh wait, I recall I had read something pertinent about that... now, what was it again.. lemme quickly look it up and review before we continue". Unless we're doing research or experimenting on a new-to-all thing, so that everyone is interested in those other references, in which case it's fun and pretty effective, too. Definitely does not impress the administrative types, though!)

author: xvr
author_rank: Frequent Contributor
timestamp: May 11, 2024, 08:15:18 pm
content: C language standard specified for some generic Virtual Machine. This VM would be mapped to real physical architecture of target processor in some processor specific way. VM used in standard to get rid of multiplicity of real CPU architecture - there is impossible define C implementation foreachparticular processor.C compiler consumed C source code and generates machine code for particular processor. To do so it would use multiple memory segments for run C VM on real hardware. These segments are  hidden from developer, and handled by C runtime. There are segments for heap, stack, exception tables (for C++), initialization/finalization code (C++) etc.There is another story for segments which comes from CPU architecture itself. These segments were listed in previous messages. There are RTC memory (including battery backed RAM), interrupt tables, dedicated buffers, such as USB endpoints, Ethernet MAC buffers, CAN mail slots, etc.These segments directly available to developer, and compiler itself do not managed them at all.Some architecture has extension to C memory model, such as multiple data spaces (8051 for example has 3 data spaces: near, far, external), code overlay spaces etc. For all of them C compiler provides some dedicated support not only in memory layout, but in code generation and sometimes in extension of C language and runtime support.Sometime C compiler can even providedifferentmapping of C VM to physical architecture. For this purpose C compiler introduced 'models' which selected by special command line switches. Such models can change size of pointers (32/64 bit - was used on Itanium), sizes of int/long, default data segments, using special types of pointers (PIC compiler introduced 'universal' pointer that can point to code or data segments, despite the fact that access to that segments required different code sequences)

author: MK14
author_rank: Super Contributor
timestamp: May 12, 2024, 04:08:26 pm
content: Quote from: Kittu20 on May 11, 2024, 02:47:53 pmWhat I'd suggest, as one of your activities, that could help you achieve your goals. Is undertaking such project(s). It can show any current weaknesses, in your skills and strategies, which should improve your experience levels and interest in the subject.I don't know what you would like or not like. But it makes more sense to find projects that interest you.It could be almost anything. A C program running on a microcontroller, which flashes LEDs, in ever more complicated and interesting flash patterns.A 6 digit seven segment LED display, 4 function calculator, with keypad. Written in C or assembly language (if assembly language, perhaps go for integer only, unless the MCU supports built in hardware floating point).An internet radio, with your own custom human interface screen and keypad, to choose what they want to listen to. Which can automatically switch off, after a certain number of minutes if desired.