EmbeddedRelated.com
Forums
Memfault Beyond the Launch

$0.03 microcontroller

Started by Clifford Heath October 9, 2018
On Monday, October 15, 2018 at 10:26:51 AM UTC-4, Paul Rubin wrote:
> gnuarm.deletethisbit@gmail.com writes: > > http://www.youboy.com/s504250937.html > > Three for a penny! But wait, there's MORE!!! It also has more memory > > and an ADC. > > That's 0.35 Chinese Yuan (not Japanese Yen, which uses a similar-looking > currency symbol) so about 0.05 USD.
Ok, thanks. So much for using Google to translate currency. You just saved my fledgling import, export, arbitrage business! Rick C.
On Mon, 15 Oct 2018 10:44:07 +0200, Philipp Klaus Krause <pkk@spth.de>
wrote:

>Am 12.10.2018 um 20:30 schrieb upsidedown@downunder.com: >> >> With such small ROM/RAM sizes, who needs reentrant functions ? > >Everyone. With an efficent stack-pointer-relative addresing mode, you >put all local varibles on the stack and only need as much RAM as the >local variables along the longest path in the call tree.
If you do not have efficient stack pointer relative addressing modes, why would you put local variables on stack ?
>If your local variables are all static, the local variables of two >functions that never get called at the same time still both takespace in >RAM at the same time.
Just create global variables Tmp1, Tmp2, Tmp3 ... and use these as function local variables. As long as two functions do not call each other directly or indirectly, you can safely use these global variables as function local variables. To make your program even prettier, use function specific aliases for Tmp1, Tnp2 etc.. by using #define statements in C or multiple labels in assembly language storage allocation.
> >Compilers can sometimes overly local variables on non-reentrant >functions as an optimization, but that will only work for some cases; >often it would require link-timeoptimization, which is not that common >in compilers for small &#4294967295;Cs.
Why do you need a linker for such small processor.? Since you are going to use a cross-copiler on a PC with mega/gigabytes of memory, you just compile/assemble everything into binary at once.
>Example: main() calls f() and g(); both f() and g() call h(). All four >functions are in different translation units, f() and g() both use a lot >of local variables, while main() and h() use little. Without link-time >optimization, the compiler will use about as much RAM as f() and g() >together, when the local variables are static. When they are put on the >stack, it will only need as much RAM as either f() or g().
See above, no need for linker or stack variables. The question is, do you even need full scale parameter passing ? Function h() could use some predefined memory locations and both f() and g() can put the parameter into those memory locations before calling h(). Only those parameters that are different when calling from f() or g() needs to be passed, h() can get the parameters that are the same in both cases do not need to be passed, h() knows the parameter already at startup. Of course such tricks becomes impractical with larger system, but with 1 KW / 64 B, this should definitely be doable.
Am 15.10.2018 um 10:44 schrieb Philipp Klaus Krause:
> Am 12.10.2018 um 20:30 schrieb upsidedown@downunder.com: >> >> With such small ROM/RAM sizes, who needs reentrant functions ? > > Everyone.
Absolutely not. Reentrant functions are a massive nuisance on fully embedded systems, if only because they routinely make it impossible to determine the actual stack size usage.
> With an efficent stack-pointer-relative addresing mode, you > put all local varibles on the stack and only need as much RAM as the > local variables along the longest path in the call tree.
And without such an addressing mode, you don't, because you'll suffer badly in every conceivable aspect.
> If your local variables are all static, the local variables of two > functions that never get called at the same time still both takespace in > RAM at the same time.
So don't mark them 'static', unless they actually have to be.
> Compilers can sometimes overly local variables on non-reentrant > functions as an optimization, but that will only work for some cases; > often it would require link-timeoptimization, which is not that common > in compilers for small &micro;Cs.
On the contrary: it's precisely the compilers for such stack-starved architectures (e.g. the 8051) that have been coupling behind-the-scenes static allocation of automatic variables with whole-program overlay analysis since effectively forever. They really had to, because the alternative would be painful to the point of being unusable.
Am 15.10.2018 um 16:29 schrieb Paul Rubin:
> Philipp Klaus Krause <pkk@spth.de> writes: >> Compilers can sometimes overly local variables on non-reentrant >> functions as an optimization, but that will only work for some cases; >> often it would require link-timeoptimization, which is not that common >> in compilers for small &micro;Cs. > > Normally you'd use whole-program optimization, I thought. I don't know > if SDCC supports that, but GCC does, as do the more serious commercial > embedded compilers. >
Does GCC support any of these very simple &micro;C architectures? I thought anyhting supported by GCC tends to have rather powerful insturction sets and plenty of registers aynway, so functions could be made reentrant by default without any problems resulting. While some link-time optimizations are commonly requested features for SDCC, currently none are supported. In SDCC, even inter-procedural optimizations within the same translation unit are not as powerful as they should be. Well, there always is a lot of work to do on SDCC, and there are only a few volunteers with time to work on it. So SDCC developers priorize (usually by personal preferences). Still, when looking at the big picture, SDCC is doing quite well compared to other compilers for the same architectures (see e.g. http://www.colecovision.eu/stm8/compilers.shtml - comparison from early 2018, around the time of the SDCC 3.7.0 release - current SDCC is 3.8.0). Philipp
Am 15.10.2018 um 20:34 schrieb upsidedown@downunder.com:
> On Mon, 15 Oct 2018 10:44:07 +0200, Philipp Klaus Krause <pkk@spth.de> > wrote: > >> Am 12.10.2018 um 20:30 schrieb upsidedown@downunder.com: >>> >>> With such small ROM/RAM sizes, who needs reentrant functions ? >> >> Everyone. With an efficent stack-pointer-relative addresing mode, you >> put all local varibles on the stack and only need as much RAM as the >> local variables along the longest path in the call tree. > > If you do not have efficient stack pointer relative addressing modes, > why would you put local variables on stack ?
1) The question was "With such small ROM/RAM sizes, who needs reentrant functions ?". And it was a reply to a post were the lack of a effiednt sp-relative addressing mode was cited as a disadvatage of the Padauk. So my reasoning was, that one would want local variables on the stack, even for small RAM / ROM, so the lack of sp-relative addressing is a disadvatage - as one has to either put local variables elsewhere or handle stackk accesses in an inefficent way. 2) There will still be some use cases for reentrant functions. And since the Padauk has a relatively large ROM - at least compared to the RAM (the ROM/RAM ratio seems far higher than on typical STM8 or MCS-51 devices), when speed doesn't matter, maybe it might still be worth putting variables on the stack. A compiler should provide an option for that (as, e.g. SDCC does for architectures without efficnet stack access, such as MCS-51 or HC08).
> >> If your local variables are all static, the local variables of two >> functions that never get called at the same time still both takespace in >> RAM at the same time. > > Just create global variables Tmp1, Tmp2, Tmp3 ... and use these as > function local variables. As long as two functions do not call each > other directly or indirectly, you can safely use these global > variables as function local variables.
I'd rather write idiomatic C anmd leave such optimizations to the compiler. Philipp
Am 15.10.2018 um 21:22 schrieb Hans-Bernhard Br&ouml;ker:
> Am 15.10.2018 um 10:44 schrieb Philipp Klaus Krause: >> Am 12.10.2018 um 20:30 schrieb upsidedown@downunder.com: >>> >>> With such small ROM/RAM sizes, who needs reentrant functions ? >> >> Everyone. > > Absolutely not. Reentrant functions are a massive nuisance on fully > embedded systems, if only because they routinely make it impossible to > determine the actual stack size usage.
What is the problem? Either you use recursion - in which case the functions need to be reentrant, there is no alternative, or you don't. In the latter case you'd need to do whole-program analysis to efficiently overlay the variables - a very similar analysis could tell you the the total stack usage.
> >> With an efficent stack-pointer-relative addresing mode, you >> put all local varibles on the stack and only need as much RAM as the >> local variables along the longest path in the call tree. > > And without such an addressing mode, you don't, because you'll suffer > badly in every conceivable aspect.
Yes. So compilers like SDCC when targeting MCS-51 or HC08 don't use the stack by default (--stack-auto puts local variables on the stack per-file, __reentrant does so per function).
> >> Compilers can sometimes overly local variables on non-reentrant >> functions as an optimization, but that will only work for some cases; >> often it would require link-timeoptimization, which is not that common >> in compilers for small &micro;Cs. > > On the contrary: it's precisely the compilers for such stack-starved > architectures (e.g. the 8051) that have been coupling behind-the-scenes > static allocation of automatic variables with whole-program overlay > analysis since effectively forever. They really had to, because the > alternative would be painful to the point of being unusable. >
Well, SDCC when targeting MCS-51 or HC08 would be the combination that I know a bit about (though personally, I mostly use SDCC to target Z80 or STM8, which can both use the stack efficiently). SDCC doesn't really have link-time optimization yet, compilation units are handled independently. Regarding different compilation units, it can still overlay the variables of leaf functions - i.e. non-reentrant differnet that do not call non-reentrant functions, but not much more. Philipp
On 16/10/18 09:19, Philipp Klaus Krause wrote:
> Am 15.10.2018 um 16:29 schrieb Paul Rubin: >> Philipp Klaus Krause <pkk@spth.de> writes: >>> Compilers can sometimes overly local variables on non-reentrant >>> functions as an optimization, but that will only work for some cases; >>> often it would require link-timeoptimization, which is not that common >>> in compilers for small &micro;Cs. >> >> Normally you'd use whole-program optimization, I thought. I don't know >> if SDCC supports that, but GCC does, as do the more serious commercial >> embedded compilers. >> > > Does GCC support any of these very simple &micro;C architectures?
No.
> I thought > anyhting supported by GCC tends to have rather powerful insturction sets > and plenty of registers aynway, so functions could be made reentrant by > default without any problems resulting.
Most gcc targets are quite powerful, with plenty of registers - and re-entrancy is not a problem. Some are a bit weaker, like the 8-bit AVR, and get inefficient with complicated stack usage. But it does not support the 8-bit CISC accumulator-based devices that SDCC targets.
> > While some link-time optimizations are commonly requested features for > SDCC, currently none are supported. In SDCC, even inter-procedural > optimizations within the same translation unit are not as powerful as > they should be. > Well, there always is a lot of work to do on SDCC, and there are only a > few volunteers with time to work on it. So SDCC developers priorize > (usually by personal preferences). > > Still, when looking at the big picture, SDCC is doing quite well > compared to other compilers for the same architectures (see e.g. > http://www.colecovision.eu/stm8/compilers.shtml - comparison from early > 2018, around the time of the SDCC 3.7.0 release - current SDCC is 3.8.0). > > Philipp >
Am 16.10.2018 um 10:00 schrieb Philipp Klaus Krause:
> Am 15.10.2018 um 21:22 schrieb Hans-Bernhard Br&ouml;ker: >> Am 15.10.2018 um 10:44 schrieb Philipp Klaus Krause: >>> Am 12.10.2018 um 20:30 schrieb upsidedown@downunder.com: >>>> >>>> With such small ROM/RAM sizes, who needs reentrant functions ? >>> >>> Everyone. >> >> Absolutely not. Reentrant functions are a massive nuisance on fully >> embedded systems, if only because they routinely make it impossible to >> determine the actual stack size usage. > > What is the problem?
The major part of it is that I mixed up Reentrance with Recursion there ... sorry for that. OTOH, one does tend to influence the other. Without recursion, one would only really need reentrance to be able to call the same function from separate threads of execution. On controllers this small, that would only happen if you're calling the same function from inside an interrupt handler and the main loop. And frankly: you really don't want to do that. If an ISR on this kind of hardware becomes big enough you feel the need to split it into sub-functions, that almost certainly means you've picked entirely the wrong tool for the job. In other words: for this kind of system (very small, with rotten stack-based addressing), not only doesn't everyone need re-entrant functions, it's more like nobody does.
>> On the contrary: it's precisely the compilers for such stack-starved >> architectures (e.g. the 8051) that have been coupling behind-the-scenes >> static allocation of automatic variables with whole-program overlay >> analysis since effectively forever. They really had to, because the >> alternative would be painful to the point of being unusable. >> > > Well, SDCC when targeting MCS-51 or HC08 would be the combination that I > know a bit about
I don't think anyone has ever seriously claimed SDCC to be anywhere near the pinnacle of compiler design for the 8051. ;-P Frankly, just looking at statements in this thread has me thinking that the usual suspects among commercial offerings from 20 years ago might still run circles around it today.
> SDCC doesn't really have link-time optimization yet, compilation > units are handled independently.
Well, given the gigantic scale differences between the target hardware and the build host, just turning the whole thing into a single compilation unit (by force, if necessary) should really be a no-brainer.
On Tuesday, October 16, 2018 at 4:52:44 PM UTC-4, Hans-Bernhard Br&ouml;ker wrote:
> Am 16.10.2018 um 10:00 schrieb Philipp Klaus Krause: > > Am 15.10.2018 um 21:22 schrieb Hans-Bernhard Br&ouml;ker: > >> Am 15.10.2018 um 10:44 schrieb Philipp Klaus Krause: > >>> Am 12.10.2018 um 20:30 schrieb upsidedown@downunder.com: > >>>> > >>>> With such small ROM/RAM sizes, who needs reentrant functions ? > >>> > >>> Everyone. > >> > >> Absolutely not. Reentrant functions are a massive nuisance on fully > >> embedded systems, if only because they routinely make it impossible to > >> determine the actual stack size usage. > > > > What is the problem? > > The major part of it is that I mixed up Reentrance with Recursion there > ... sorry for that. > > OTOH, one does tend to influence the other. Without recursion, one > would only really need reentrance to be able to call the same function > from separate threads of execution. On controllers this small, that > would only happen if you're calling the same function from inside an > interrupt handler and the main loop.
I don't believe this is correct. Reentrance is a problem any time a routine is entered again before it is exited from a prior call. This can happen without multiple threads when a routine is called from a routine that was ultimately called from within the routine. I suppose you might consider this to be recursion, but my point is this can happen without the intent of using recursion. Rick C.
Am 16.10.2018 um 23:01 schrieb gnuarm.deletethisbit@gmail.com:
> On Tuesday, October 16, 2018 at 4:52:44 PM UTC-4, Hans-Bernhard > Br&ouml;ker wrote:
>> OTOH, one does tend to influence the other. Without recursion, >> one would only really need reentrance to be able to call the same >> function from separate threads of execution. On controllers this >> small, that would only happen if you're calling the same function >> from inside an interrupt handler and the main loop.
> I don't believe this is correct. Reentrance is a problem any time a > routine is entered again before it is exited from a prior call. This > can happen without multiple threads when a routine is called from a > routine that was ultimately called from within the routine. I > suppose you might consider this to be recursion,
Oh, there's no doubt about it: that's recursion all right. Some might prefer to qualify it as indirect recursion, a.k.a. a loop in the call graph, but it's still recursion.
> but my point is this > can happen without the intent of using recursion.
I'll asume we agree on this: unintended recursion is clear a bug in the code, every time. That could arguably be classified an actual benefit of using a such a stack-starved CPU architecture: any competent C compiler for it will have to perform call tree analysis anyway, so it finds that particular bug "en passant". More typical C toolchains relying on stack-centric calling conventions might not bother with such analysis, and thus won't see the bug. Until you use the accompanying stack size calculation tool, that is, which will barf.

Memfault Beyond the Launch