light pascal lazarus / 77-Embedded ---------------------------------------------------------------------- devport · 2019-12-23 10:48 Hello, I was wondering if it is possible to use FPC (not object-oriented) without ballast in the form of system.pas etc.? The clean program weighs over 4kB from the very beginning, which with a memory size of 32kB is a large percentage of use. I tried to replace the system.pas files with my versions, but the compiler constantly calls some structures that it uses. the goal is to achieve output file ~ 1kB maybe less. in ARM ---------------------------------------------------------------------- marcov · 2019-12-23 12:06 I assume the avr embedded targets are fairly tight ? ---------------------------------------------------------------------- MarkMLl · 2019-12-23 12:34 I was thinking that referring to them as a template might be a good starting point. MarkMLl ---------------------------------------------------------------------- marcov · 2019-12-23 12:40 For the desperate there is also https://www.muppetlabs.com/~breadbox/software/tiny/teensy.html but there they also bypass binutils and resort to assembler directly. ---------------------------------------------------------------------- six1 · 2019-12-23 12:50 ...but marcov, his statement at the end is: Here, at last, we have honestly gone as far as we can go. There is no getting around the fact that the 45th byte in the file, which specifies the number of entries in the program header table, needs to be non-zero, needs to be present, and needs to be in the 45th position from the start of the ELF header. We are forced to conclude that there is nothing more that can be done. ...can't belive it will be 45... it must be 42  none insiders must read this: https://en.wikipedia.org/wiki/Phrases_from_The_Hitchhiker%27s_Guide_to _the_Galaxy#Answer_to_the_Ultimate_Question_of_Life,_the_Universe,_and _Everything_(42) ---------------------------------------------------------------------- MarkMLl · 2019-12-23 14:07 QuoteThe King then read from his book: "Rule forty-two. _All persons more than a mile high to leave the court_." Non-insiders should give precedence to "Alice in Wonderland" which has been around rather longer :-) MarkMLl ---------------------------------------------------------------------- devport · 2019-12-23 14:10 OK, I came to some conclusions without having to get rid of system.pas files etc. The use of STR in the program increases the size by an average of 4kB !!! (at least that's how I observe) Using the string variable in function passing increases the result code by ~ 800B once. I must use VAR (reference) reduce the amount of generated code. In general, I come to the conclusion that most of the optimizations should be kept on my side, not the compiler. So the compiler does as I command it. ---------------------------------------------------------------------- marcov · 2019-12-23 16:50 Note that such growth tapers off quickly once all language string helper have been used. Any way, it is hard to suggest anything since you don't explain what exactly you need it for. ---------------------------------------------------------------------- devport · 2019-12-23 18:07 I have written a similar program in C for uC Cortex-M0. And my point is that in Pascal I haven't even achieved half of the functionality, and I'm already exceeding 5kB Flash more than the one written in C. It worries me very much I am slowly beginning to come to the conclusion that Pascal is not suitable for writing in microcontrollers. I have big problems writing in this language ... I do the same thing as in C, and yet I encounter Hard Fault more often than I did in C. For example: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i function Int_To_Str(buf : PChar; x : smallint):word;var  buff : array[0..5] of char;  p : PChar;  size : longint; value : smallint;begin  Result := 0;  p := @buff;  value := x;  size := longint(buf);   if(value < 0) then begin    buf^ := '-';    Inc(buf);    value := -value;  end;   if(value = 0) then begin    buf^ := '0';    Inc(buf);    exit;  end;   while(value > 0) do begin    p^ := char(value mod 10 + Ord('0'));    value := value div 10;    inc(p);  end;   while p <> @buff do begin  dec(p);    buf^ := p^;    inc(buf);  end;   size := longint(buf)- size;  Result := word(size);end; If Call where Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i var st : string;begin Int_To_Str(@st, 20);  end. i get Hard Fault in line " buf^ := p^ " Any attempt to write to 'buf ^' results in an error. In C compiller this function it works. STR I don't want to use because it weighs a lot :/ and requires heapmgr.pas (more kB) ---------------------------------------------------------------------- MiR · 2019-12-23 18:23 I think you are on the right track now, if you really want to bring down code size you have to check your every move and it's costs. Strings are very expensive both as ansistrings (possible for e.g. arm, mips targets), there you will in most cases need to add heapmgr (Hint! Hint!) to make them properly work and the code for handling them is quite complex (--> big) and also as shortstrings (avr) where they consume 256 bytes of precious ram on your stack for every function call that uses strings. Take a look at a function that concats two strings and returns the result, and while doing that say goodbye to 768 bytes of precious stack.... Also, for example using classes also increases code size, they need heapmgr and precious RAM is also used by VMT's when virtual methods are used. The list goes on, when you want to keep codesize down you need to always check the generated assembler code and prepare for surprises   The question I always ask myself is WHY people today choose severely cpu and memory limited chips for freepascal... I can understand it from the educational aspect, you learn a lot when trying to squeeze complex code into 32kb of Flash, but how many of the people using such a small system actually want to go through this learning curve? There are quite capable and cheap boards out there in the sub-10$ range that offer 64-128kb of flash (look for STM32F103C8T6 or maple mini) and come with a stlinkv2 compatible debugger, there are even more capable boards with STM32F4 Chips (search for STM32F411CEU6) with 128kb RAM and 512kb Flash or ATSAMD21 Boards like Arduino-Zero or clones. Thoses Chipsets eat through most of the limitations that come with todays freepascal, they have enough flash for some not so optimized code and they have enough CPU power to easily execute the complex string methods in freepascal. Please do not misunderstand me, I like the smell of freshly generated assembler output of fpc, but I ask myself does everybody want to start that hard? One could argue that AVR chips and older Arm Chips are easier to understand because of less complexity, but is this really true? Me, I do not think so, you can also start simple with newer arm or mips chips, but there's a lot more (like DMA, advanced timers) that comes in handy once you have mastered the basics and start with the more challenging stuff. But until that point you have already had a lot of fun with blinking LED's, OLED-Displays or whatever without hitting the out of RAM/Flash- Memory wall even once. Michael ---------------------------------------------------------------------- marcov · 2019-12-23 18:31 Quote from: devport on December 23, 2019, 07:07:26 pmI have written a similar program in C for uC Cortex-M0. And my point is that in Pascal I haven't even achieved half of the functionality, and I'm already exceeding 5kB Flash more than the one written in C. With such constraints you indeed need to lay off the automated types. (though I would avoid textual I/O in microcontrollers in general) QuoteIt worries me very much I am slowly beginning to come to the conclusion that Pascal is not suitable for writing in microcontrollers. Pascal and C are nearly equivalent in theoretical performance. The difference is more in the amount and quality of compilers and what their optimization targets are. Free Pascal's Object Pascal is like C++. It is high level language, but the lowlevel (in C++ case: C) still lives there. Just like that, rock bottom Pascal is like C without macros. (iow #define only for constants). You will need to learn to adjust the level QuoteI have big problems writing in this language ... I do the same thing as in C, and yet I encounter Hard Fault more often than I did in C. It could be a compiler bug, but 9 to 10 this is some mistake you made. If you are less proficient in embedded Pascal that can happen. Stay critical and try to isolate the problem. It could be as little as translating char  buff[5] into array[0..5] of char; {1 char more!} ---------------------------------------------------------------------- valdir.marcos · 2019-12-23 18:45 Quote from: marcov on December 23, 2019, 07:31:59 pmQuote from: devport on December 23, 2019, 07:07:26 pmI have written a similar program in C for uC Cortex-M0. And my point is that in Pascal I haven't even achieved half of the functionality, and I'm already exceeding 5kB Flash more than the one written in C.With such constraints you indeed need to lay off the automated types. (though I would avoid textual I/O in microcontrollers in general)QuoteIt worries me very much I am slowly beginning to come to the conclusion that Pascal is not suitable for writing in microcontrollers.Pascal and C are nearly equivalent in theoretical performance. The difference is more in the amount and quality of compilers and what their optimization targets are. Free Pascal's Object Pascal is like C++. It is high level language, but the lowlevel (in C++ case: C) still lives there. Just like that, rock bottom Pascal is like C without macros. (iow #define only for constants). You will need to learn to adjust the levelQuoteI have big problems writing in this language ... I do the same thing as in C, and yet I encounter Hard Fault more often than I did in C.It could be a compiler bug, but 9 to 10 this is some mistake you made. If you are less proficient in embedded Pascal that can happen. Stay critical and try to isolate the problem. It could be as little as translating char  buff[5] into array[0..5] of char; {1 char more!}Could PicPas example help this discussion? PicPas, Pascal compiler for Microchip PIC https://forum.lazarus.freepascal.org/index.php/topic,36595.0.html https://github.com/t-edson/PicPas ---------------------------------------------------------------------- devport · 2019-12-23 18:46 However, I will not give up without a fight yet. : P I will learn the behavior of the Pascal compiler and correct my code first. ---------------------------------------------------------------------- devport · 2019-12-23 18:53 PicPas, For me, this is a good approach to programming microcontrollers. I thought about it myself in the context of ARM Cortex ---------------------------------------------------------------------- MarkMLl · 2019-12-23 19:32 To be honest, I don't think it's fair comparing Pascal against C on account of the implicit complexity (support for finally blocks etc.) that Pascal carries around even if strings etc. aren't used. It's only marginally fair to compare Pascal against C++ (with managed strings support) on account of the flexibility that C/C++ have to recompile stuff rather than making do with precompiled "one size fits all" units. MarkMLl ---------------------------------------------------------------------- lucamar · 2019-12-23 19:33 Quote from: devport on December 23, 2019, 07:07:26 pmi get Hard Fault in line " buf^ := p^ " Any attempt to write to 'buf ^' results in an error. The notation something^ applies only to a pointer: it's meant to dereference it. Your buf variable, though, is an array: you should access/set it by using an index into the array, as in: buf[x] := p^ In C it's different because an "array" is almost exactly the same as a pointer. ---------------------------------------------------------------------- valdir.marcos · 2019-12-23 19:37 Quote from: marcov on December 23, 2019, 07:31:59 pmQuote from: devport on December 23, 2019, 07:07:26 pmI have written a similar program in C for uC Cortex-M0. And my point is that in Pascal I haven't even achieved half of the functionality, and I'm already exceeding 5kB Flash more than the one written in C.With such constraints you indeed need to lay off the automated types. (though I would avoid textual I/O in microcontrollers in general)QuoteIt worries me very much I am slowly beginning to come to the conclusion that Pascal is not suitable for writing in microcontrollers.Pascal and C are nearly equivalent in theoretical performance. The difference is more in the amount and quality of compilers and what their optimization targets are. Free Pascal's Object Pascal is like C++. It is high level language, but the lowlevel (in C++ case: C) still lives there. Just like that, rock bottom Pascal is like C without macros. (iow #define only for constants). You will need to learn to adjust the levelQuoteI have big problems writing in this language ... I do the same thing as in C, and yet I encounter Hard Fault more often than I did in C.It could be a compiler bug, but 9 to 10 this is some mistake you made. If you are less proficient in embedded Pascal that can happen. Stay critical and try to isolate the problem. It could be as little as translating char  buff[5] into array[0..5] of char; {1 char more!}Older and simpler Pascal implementations prior to Free Pascal would be more appropriate to beat C results in this case? ---------------------------------------------------------------------- MarkMLl · 2019-12-23 20:32 Quote from: valdir.marcos on December 23, 2019, 08:37:22 pmOlder and simpler Pascal implementations prior to Free Pascal would be more appropriate to beat C results in this case? No, because Pascal has always- from day one- had up-level addressing and better handling of strings than C has. I think it would be interesting, though, if there were some way of /completely/ disabling "Delphi-style" strings, and running FPC (with a subset of units/packages) with only "classical" Pascal strings (size predeclared, length in element , absolute limit of 256 8-bit characters) and possibly with no compiler support for finalisation blocks and exceptions. /If/ that could be done, then it would be possible to compare against say TP5 and against various Modula-2 compilers which as I understand it had well-regarded optimisation (because the user was giving the compiler a bit more information about what he was trying to do). MarkMLl ---------------------------------------------------------------------- marcov · 2019-12-23 21:36 Quote from: valdir.marcos on December 23, 2019, 08:37:22 pmOlder and simpler Pascal implementations prior to Free Pascal would be more appropriate to beat C results in this case? First, there is no universal "C". Some C compilers optimize for size (e.g. Keile), some not. And no. My remark was primarily about using the optimal subsets, and only secondarily about compiler selection. If you use the wrong subset (e.g. TP4 has a string[] and goes back to 1989 or so), then you still will be bulky. ---------------------------------------------------------------------- FPK · 2019-12-23 23:21 *sigh* again the myth of the large binaries. An empty program for avr25 results in -Wpattiny28 tavr.pp -O4 Free Pascal Compiler version 3.3.1 [2019/12/24] for avr Copyright (c) 1993-2019 by Florian Klaempfl and others Target OS: Embedded Compiling tavr.pp Assembling program Linking tavr 2 lines compiled, 0.0 sec, 38 bytes code, 0 bytes data The 38 bytes come from the interrupt handlers. ---------------------------------------------------------------------- MarkMLl · 2019-12-24 08:35 Quote from: FPK on December 24, 2019, 12:21:31 am*sigh* again the myth of the large binaries. An empty program for avr25 results in ... Linking tavr 2 lines compiled, 0.0 sec, 38 bytes code, 0 bytes data The 38 bytes come from the interrupt handlers. No myth at all: his complaint was about ARM. Somebody else made the point that perhaps comparing with AVR would be worthwhile. MarkMLl ---------------------------------------------------------------------- Thaddy · 2019-12-24 08:46 Quote from: MarkMLl on December 24, 2019, 09:35:14 amNo myth at all: his complaint was about ARM. Somebody else made the point that perhaps comparing with AVR would be worthwhile. MarkMLl ARM embedded has similar sizes. But don't expect a Raspberry Pi with a full Debian as embedded. It will have the same overhead that comes with a full OS. That's a trap less experienced programmers always fall into, ---------------------------------------------------------------------- MarkMLl · 2019-12-24 09:10 @Thaddy: Good point. MarkMLl ---------------------------------------------------------------------- PascalDragon · 2019-12-24 09:36 Quote from: MarkMLl on December 23, 2019, 09:32:43 pmI think it would be interesting, though, if there were some way of /completely/ disabling "Delphi-style" strings, and running FPC (with a subset of units/packages) with only "classical" Pascal strings (size predeclared, length in element , absolute limit of 256 8-bit characters) and possibly with no compiler support for finalisation blocks and exceptions. /If/ that could be done, then it would be possible to compare against say TP5 and against various Modula-2 compilers which as I understand it had well-regarded optimisation (because the user was giving the compiler a bit more information about what he was trying to do).You don't need some way to disable Delphi- style strings, because if you don't use them, then the compiler and linker won't include the corresponding functionality (this is especially true for the embedded target). Same for implicit exception frames: if you don't use managed types then the implicit frames won't be generated. Also for the embedded target one can explicitely decide which features should be enabled when compiling the RTL (take a look at $fpcdir/rtl/embedded/system.cfg), thus avoiding that it's used by accident. Quote from: lucamar on December 23, 2019, 08:33:39 pmQuote from: devport on December 23, 2019, 07:07:26 pmi get Hard Fault in line " buf^ := p^ " Any attempt to write to 'buf ^' results in an error. The notation something^ applies only to a pointer: it's meant to dereference it. Your buf variable, though, is an array: you should access/set it by using an index into the array, as in: buf[x] := p^ In C it's different because an "array" is almost exactly the same as a pointer. Take a look at the code again. buf is an input argument of type PChar and p is a pointer to the local array buff. Quote from: FPK on December 24, 2019, 12:21:31 am*sigh* again the myth of the large binaries. An empty program for avr25 results in -Wpattiny28 tavr.pp -O4 Free Pascal Compiler version 3.3.1 [2019/12/24] for avr Copyright (c) 1993-2019 by Florian Klaempfl and others Target OS: Embedded Compiling tavr.pp Assembling program Linking tavr 2 lines compiled, 0.0 sec, 38 bytes code, 0 bytes data The 38 bytes come from the interrupt handlers. The point you mentioned is empty program. But once users start to use more features that size obviously increases. So they need to monitor what they use so that they don't break any size constraints. ---------------------------------------------------------------------- lucamar · 2019-12-24 10:41 Quote from: PascalDragon on December 24, 2019, 10:36:06 amQuote from: lucamar on December 23, 2019, 08:33:39 pmQuote from: devport on December 23, 2019, 07:07:26 pmi get Hard Fault in line " buf^ := p^ " Any attempt to write to 'buf ^' results in an error. The notation something^ applies only to a pointer: it's meant to dereference it. Your buf variable, though, is an array: you should access/set it by using an index into the array, as in: buf[x] := p^ In C it's different because an "array" is almost exactly the same as a pointer. Take a look at the code again. buf is an input argument of type PChar and p is a pointer to the local array buff. Oops! You're right, of course. I mistook buff and buf ---------------------------------------------------------------------- julkas · 2019-12-24 10:47 Quote from: FPK on December 24, 2019, 12:21:31 am*sigh* again the myth of the large binaries. An empty program for avr25 results in -Wpattiny28 tavr.pp -O4 Free Pascal Compiler version 3.3.1 [2019/12/24] for avr Copyright (c) 1993-2019 by Florian Klaempfl and others Target OS: Embedded Compiling tavr.pp Assembling program Linking tavr 2 lines compiled, 0.0 sec, 38 bytes code, 0 bytes data The 38 bytes come from the interrupt handlers. I think without real life project (working code) we can't make objective discussion. ---------------------------------------------------------------------- Hartmut · 2019-12-24 11:13 Quote from: PascalDragon on December 24, 2019, 10:36:06 amAlso for the embedded target one can explicitely decide which features should be enabled when compiling the RTL (take a look at $fpcdir/rtl/embedded/system.cfg), thus avoiding that it's used by accident. In FPC 3.0.4 I did not find a system.cfg in this folder, but a rtl.cfg. Do you mean this? ---------------------------------------------------------------------- julkas · 2019-12-24 11:27 Quote from: Hartmut on December 24, 2019, 12:13:25 pmQuote from: PascalDragon on December 24, 2019, 10:36:06 amAlso for the embedded target one can explicitely decide which features should be enabled when compiling the RTL (take a look at $fpcdir/rtl/embedded/system.cfg), thus avoiding that it's used by accident. In FPC 3.0.4 I did not find a system.cfg in this folder, but a rtl.cfg. Do you mean this? Check trunk ---------------------------------------------------------------------- devport · 2019-12-24 11:51 OKEY Gentlemen, and perhaps Lady's, I have already partly understood the operation of the FPC compiler and this action is beginning to suit me. I wouldn't want to create an unnecessary storm here. From now on, I check 2x how the code I write affects the size of the output. It was my inexperience with this compiler that gave rise to this topic. I apologize in advance. ---------------------------------------------------------------------- MarkMLl · 2019-12-24 11:59 Quote from: devport on December 24, 2019, 12:51:43 pmIt was my inexperience with this compiler that gave rise to this topic. I apologize in advance. Don't. Unless it really is an FAQ, raising an issue which results in core developers updating the rest of us on the state of the art is always valuable. MarkMLl ---------------------------------------------------------------------- PascalDragon · 2019-12-24 13:09 Quote from: Hartmut on December 24, 2019, 12:13:25 pmQuote from: PascalDragon on December 24, 2019, 10:36:06 amAlso for the embedded target one can explicitely decide which features should be enabled when compiling the RTL (take a look at $fpcdir/rtl/embedded/system.cfg), thus avoiding that it's used by accident. In FPC 3.0.4 I did not find a system.cfg in this folder, but a rtl.cfg. Do you mean this? In 3.0.4 it's indeed the rtl.cfg. For trunk that was changed to system.cfg which is used to compile the System unit and rtl.cfg which is used for the remainder of the RTL (currently only used for i8086 to ensure that smartlinking is enabled) as the enabled features are now stored in the System unit. ---------------------------------------------------------------------- FPK · 2019-12-24 22:33 Quote from: PascalDragon on December 24, 2019, 10:36:06 amQuote from: FPK on December 24, 2019, 12:21:31 am*sigh* again the myth of the large binaries. An empty program for avr25 results in -Wpattiny28 tavr.pp -O4 Free Pascal Compiler version 3.3.1 [2019/12/24] for avr Copyright (c) 1993-2019 by Florian Klaempfl and others Target OS: Embedded Compiling tavr.pp Assembling program Linking tavr 2 lines compiled, 0.0 sec, 38 bytes code, 0 bytes data The 38 bytes come from the interrupt handlers. The point you mentioned is empty program. Of course, I did so, because this is the example people typically use trying to make their point. ---------------------------------------------------------------------- julkas · 2019-12-25 09:37 Quote from: devport on December 24, 2019, 12:51:43 pmOKEY From now on, I check 2x how the code I write affects the size of the output. My first working FPC AVR target port (without strings, advanced records, heap, ...) http://elm-chan.org/fsw/ff/00index_p.html  - hex image size is ~ 9k vs C ~ 2 - 4k. ---------------------------------------------------------------------- FPK · 2019-12-25 15:32 Quote from: julkas on December 25, 2019, 10:37:46 amQuote from: devport on December 24, 2019, 12:51:43 pmOKEY From now on, I check 2x how the code I write affects the size of the output. My first working FPC AVR target port (without strings, advanced records, heap, ...) http://elm-chan.org/fsw/ff/00index_p.html  - hex image size is ~ 9k vs C ~ 2 - 4k. Not unlikely for a first try. Pascal is not C and some innocent looking code might pull in unwanted parts of the RTL. I hope you checked the map file for such problems? ---------------------------------------------------------------------- Laksen · 2019-12-25 16:31 Did you use trunk? The newest doesn't pull in exception handling for divisions/modulus by constants for example ---------------------------------------------------------------------- devport · 2019-12-25 16:48 I'm using build from December 22, 2019 ---------------------------------------------------------------------- julkas · 2019-12-25 18:25 Quote from: Laksen on December 25, 2019, 05:31:51 pmDid you use trunk? The newest doesn't pull in exception handling for divisions/modulus by constants for example Code: Text  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i $  ppcrossavr.exe -iFree Pascal Compiler version 3.3.1 Compiler date    : 2019/09/22Compiler CPU target: avr Any reason for update? ---------------------------------------------------------------------- Thaddy · 2019-12-26 07:54 2019/09/22 is not exactly new is it? Trunk is a moving target and if you want to use it, plz compile on a daily basis, not three monthly. ---------------------------------------------------------------------- julkas · 2020-01-01 13:32 Quote from: Thaddy on December 26, 2019, 08:54:55 am2019/09/22 is not exactly new is it? Trunk is a moving target and if you want to use it, plz compile on a daily basis, not three monthly. After update - Code: Text  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i $  ppcrossavr.exe -iFree Pascal Compiler version 3.3.1 Compiler date    : 2020/01/01Compiler CPU target: avr Code: Text  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i 2120 lines compiled, 0.4 sec, 9694 bytes code, 539 bytes data  Any hint, advice? Happy New Year to great Pascal community ! BTW - Careful with whitespaces on Windows ! ---------------------------------------------------------------------- FPK · 2020-01-01 14:35 Quote from: FPK on December 25, 2019, 04:32:06 pmPascal is not C and some innocent looking code might pull in unwanted parts of the RTL. I hope you checked the map file for such problems? ---------------------------------------------------------------------- Laksen · 2020-01-01 15:04 Show the code that generates that much ---------------------------------------------------------------------- julkas · 2020-01-01 15:10 Quote from: Laksen on January 01, 2020, 04:04:44 pmShow the code that generates that much https://github.com/JulStrat/pff/tree/devop/examples/arduino ---------------------------------------------------------------------- d.ioannidis · 2020-01-09 21:41 Quote from: julkas on December 25, 2019, 07:25:02 pmQuote from: Laksen on December 25, 2019, 05:31:51 pmDid you use trunk? The newest doesn't pull in exception handling for divisions/modulus by constants for example < snip > Any reason for update? Well for this example, a TX-only software ( bit-bang'ed ) UART for attiny85 I had ( if I remember correctly, don't have a 3.0.4 ppcrossavr handy ) approx. ~20% size reduction : Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i // bit bang'ing Software-UART TX example//// Adapted / Ported from//// a tiny software UART TX for the AVR ATtiny// https://marcelmg.github.io/software_uart/ program fp_attiny85_test; {$MODE OBJFPC}{$MACRO ON}{$INLINE ON}{$LONGSTRINGS OFF}{$WRITEABLECONST OFF} // Timer interrupt service routine name.{$DEFINE TIMER_INT := 'TIMER0_COMPA_ISR'} // Change these to use another pin.{$DEFINE TX_PORT    := PORTB }{$DEFINE TX_PIN     := 0   }{$DEFINE TX_DDR     := DDRB  }{$DEFINE TX_DDR_PIN := 0     } uses  intrinsics; // Read directly from flash and not from SRAM.// HAS_LPMX also means that movw is available.{$if defined(CPUAVR_HAS_LPMX)}const  HelloWorldStr: string[14] = 'Hello World ! '; section '.progmem';  FPCStr: string[22] = 'Free Pascal Rocks !!! '; section '.progmem';   function read_progmem_byte(constref v: byte): byte; assembler; nostackframe;  asm    MOVW    ZL, r24    LPM     r24, Z  end;   function read_progmem_str(constref s: shortstring): ShortString;  var    len, i: byte;  begin    len := read_progmem_byte(byte(s[0]));    setlength(Result, len);    for i := 1 to len do      Result[i] := char(read_progmem_byte(byte(s[i])));  end;{$ENDIF}   procedure AtomicWrite(var Value: word; new_value: word);  var    b: byte;  begin    b := avr_save;    Value := new_value;    avr_restore(b);  end;   function AtomicRead(var Value: word): word;  var    b: byte;  begin    b := avr_save;    Result := Value;    avr_restore(b);  end; var  // Used as a TX shift register.  tx_shift_reg: word;   function UART_tx(constref ACharacter: char): boolean;  var    local_tx_shift_reg: word;  begin    Result := True;    local_tx_shift_reg := AtomicRead(tx_shift_reg);     // Check if sending the previous character is not yet finished.    // Transmission is finished when tx_shift_reg = 0.    if local_tx_shift_reg <> 0 then      Result := False    else    begin       // Fill the TX shift register with the character to be sent and      // the start & stop bits (start bit (1<<0) is already 0).      local_tx_shift_reg := (word(ACharacter) shl 1) or (1 shl 9);      AtomicWrite(tx_shift_reg, local_tx_shift_reg);       // Start Timer0 with a prescaler of 8.    TCCR0B := (1 shl CS0 + 1);    end;  end;   procedure UART_tx_str(constref AString: ShortString);  var    iLen, x: byte;  begin    iLen := Length(AString);    x := 1;    while (iLen >= x) do    // Send the next character after the      // the previous character transmission is finished.      if UART_tx(AString[x]) then        Inc(x);  end;   procedure UART_init;  begin    // Set TX pin as output.    TX_DDR := TX_DDR or (1 shl TX_DDR_PIN);    TX_PORT := TX_PORT or (1 shl TX_PIN);     // Set Timer0 to CTC mode.    TCCR0A := (1 shl WGM0 + 1);     // Enable output compare 0 A interrupt.    TIMSK := TIMSK or (1 shl OCF0A);     // Set compare value to 103 to achieve a 9600 baud rate (i.e. 104µs),    // together with the 8MHz/8=1MHz Timer0 clock.    {NOTE: since the internal 8MHz oscillator is not very accurate, this value can be tuned      to achieve the desired baud rate, so if it doesn't work with the nominal value (103), try      increasing or decreasing the value by 1 or 2 }    OCR0A := 103;  end;   procedure TIMER0_COMPA_ISR; public Name TIMER_INT; Interrupt;  begin    // Output LSB of the TX shift register at the TX pin.    if (tx_shift_reg and 1) = 1 then      TX_PORT := TX_PORT or (1 shl TX_PIN)    else      TX_PORT := TX_PORT and not (1 shl TX_PIN);     // Shift the TX shift register one bit to the right.    tx_shift_reg := (tx_shift_reg shr 1);     // If the stop bit has been sent, the shift register will be 0    // and the transmission is completed, so we can stop & reset Timer0.    if tx_shift_reg = 0 then    begin      TCCR0B := 0;      TCNT0 := 0;    end;  end;   // Generated by delay loop calculator  // at http://www.bretmulvey.com/avrdelay.html   // Delay 4 000 000 cycles  // 500ms at 8.0 MHz  procedure _delay_loop; assembler; nostackframe;  label    L1;  asm    LDI     r18, 21    LDI     r19, 75    LDI     r20, 191  L1:    DEC     r20    BRNE    L1    DEC     r19    BRNE    L1    DEC     r18    BRNE    L1    NOP  end; begin  UART_init;   // Enable Global Interrupts.  avr_sei;   repeat// Read directly from flash and not from SRAM.// HAS_LPMX also means that movw is available.{$if defined(CPUAVR_HAS_LPMX)}    UART_tx_str(read_progmem_str(HelloWorldStr));    UART_tx_str(read_progmem_str(FPCStr));{$elseif}    UART_tx_str('Hello World ! ');    UART_tx_str('Free Pascal Rocks !!! ');{$endif}    _delay_loop;  until False;end.   Project build options Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i -Tembedded- Pavr-MObjFPC-Scghi-CX-Os4-gt-Xs-XX-l-vewnhibq-Fi..\lib\avr-embedded- Fu..\source-Fu.-FU..\lib\avr-embedded- FE..\bin-o..\bin\fp_attiny85_test-a-al-Xe-Xm-Sm- CpAVR25-WpATTINY85-XPavr--FDG:\Programming\dimitris\tools\avr8-gnu- toolchain\bin-dF_CPU:=8000000  and avrsize reports : Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i Compile Project, Mode: Release, OS: embedded, CPU: avr, Target: G:\Programming \dimitris\Projects\fp_attiny85_test\bin\fp_attiny85_test: Success, Hints: 1fp_attiny85_test.lpr(131,13) Hint: Local proc "TIMER0_COMPA_ISR" is not usedProject: Executing command after: SuccessAVR Memory Usage----------------Device: attiny85 Program:     626 bytes (7.6% Full)(.text + .data + .bootloader) Data:          2 bytes (0.4% Full)(.data + .bss + .noinit) FPC Compiler builded with OPT="-O1 -CX -XX" : Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i FPC executable:Compiler=G:\Programming\dimitris\tools\fpc- trunk\bin\x86_64-win64\fpc.exeOptions=CompilerDate=5/1/2020 20:00:02RealCompiler=G:\Programming\dimitris\tools\fpc- trunk\bin\x86_64-win64\ppcrossavr.exeRealCompilerDate=8/1/2020 20:18:2 4RealTargetOS=embeddedRealTargetCPU=avrRealCompilerInPath=G:\Programmi ng\dimitris\tools\fpc-trunk\bin\x86_64- win64\ppcrossavr.exeVersion=3.3.1CfgFilename=G:\Programming\dimitris\t ools\fpc-trunk\bin\x86_64-win64\fpc.cfg ---------------------------------------------------------------------- julkas · 2020-01-13 14:10 Quote from: FPK on December 24, 2019, 12:21:31 am*sigh* again the myth of the large binaries. An empty program for avr25 results in -Wpattiny28 tavr.pp -O4 Free Pascal Compiler version 3.3.1 [2019/12/24] for avr Copyright (c) 1993-2019 by Florian Klaempfl and others Target OS: Embedded Compiling tavr.pp Assembling program Linking tavr 2 lines compiled, 0.0 sec, 38 bytes code, 0 bytes data The 38 bytes come from the interrupt handlers. Try following - Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program tt; var  x: DWORD;  begin  x := x div 17;end. Result - I think it's not acceptableCode: Text  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i $ ppcrossavr.exe -Tembedded -Cpavr5 -vi -aln -Wpatmega328p -XPavr- -O3 -Xm tt.pasTarget OS: EmbeddedCompiling tt.pasAssembling ttLinking tt7 lines compiled, 0.1 sec, 1814 bytes code, 50 bytes data ---------------------------------------------------------------------- FPK · 2020-01-13 20:08 Whether it is acceptable or not does not matter. div handling with all it's infrastructure needed in object pascal is that big. FPC generates an ldi, three moves and a call for the div. Of course, one could cheat and implement some special tailored div. procedure for such useless benchmarks so the exception handling infrastructure is left out but this makes no difference in real world programs. ---------------------------------------------------------------------- d.ioannidis · 2020-01-13 20:46 Hi,   AFAIU, even Atmel in AVR200: Multiply and Divide Routines for unsigned  8-bit  division ( optimized for size) report "Code Size (Words) 14" for their algorithm ....   Also someone more experienced than me, said "...scaling calculations so that divisions are done with powers of 2 are popular on 8 bitters because shifts are much simpler than division." .   You'll notice it if you change the value 17 with 32, 64 etc ... Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i Free Pascal Compiler version 3.3.1 [2020/01/12] for avrCopyright (c) 1993-2019 by Florian Klaempfl and othersTarget OS: EmbeddedCompiling tt.lprtt.lpr(11,8) Warning: Variable "x" does not seem to be initializedAssembling ttLinking tt12 lines compiled, 0.2 sec, 218 bytes code, 0 bytes data1 warning(s) issued   regards, ---------------------------------------------------------------------- ccrause · 2020-01-14 12:23 Quote from: FPK on January 13, 2020, 09:08:13 pmWhether it is acceptable or not does not matter. div handling with all it's infrastructure needed in object pascal is that big. FPC generates an ldi, three moves and a call for the div. 8< ... I agree that the safety of using Pascal should not be sacrificed, but I would like to suggest that more compact error handling could be implemented for AVR, see e.g. the suggestion in issue 35754.  Basically, remove exception raising code, since exception handling support is not enabled anyway. ---------------------------------------------------------------------- julkas · 2020-01-14 13:30 Quote from: ccrause on January 14, 2020, 01:23:34 pmQuote from: FPK on January 13, 2020, 09:08:13 pmWhether it is acceptable or not does not matter. div handling with all it's infrastructure needed in object pascal is that big. FPC generates an ldi, three moves and a call for the div. 8< ... I agree that the safety of using Pascal should not be sacrificed, but I would like to suggest that more compact error handling could be implemented for AVR, see e.g. the suggestion in issue 35754.  Basically, remove exception raising code, since exception handling support is not enabled anyway. rtl/embedded/system.cfg - Code: Text  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i # does not require extra memory, neither code nor data# in programs not using e. g. writeln based I/O which is the common case for AVR#ifdef CPUAVR-SfOBJECTS-SfEXCEPTIONS-SfCLASSES-SfRTTI# AVR6 has normally more memory, so enable more functions#ifdef CPUAVR6-SfANSISTRINGS-SfWIDESTRINGS-SfDYNARRAYS-SfTHREADING- SfVARIANTS-SfOBJECTS-SfCOMMANDARGS-SfRANDOM-SfRESOURCES#endif#endifSo exception handling enabled or disabled? ---------------------------------------------------------------------- ccrause · 2020-01-14 15:12 Quote from: julkas on January 14, 2020, 02:30:16 pmQuote from: ccrause on January 14, 2020, 01:23:34 pmQuote from: FPK on January 13, 2020, 09:08:13 pmWhether it is acceptable or not does not matter. div handling with all it's infrastructure needed in object pascal is that big. FPC generates an ldi, three moves and a call for the div. 8< ... I agree that the safety of using Pascal should not be sacrificed, but I would like to suggest that more compact error handling could be implemented for AVR, see e.g. the suggestion in issue 35754.  Basically, remove exception raising code, since exception handling support is not enabled anyway. rtl/embedded/system.cfg - Code: Text  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i # does not require extra memory, neither code nor data# in programs not using e. g. writeln based I/O which is the common case for AVR#ifdef CPUAVR-SfOBJECTS-SfEXCEPTIONS-SfCLASSES-SfRTTI# AVR6 has normally more memory, so enable more functions#ifdef CPUAVR6-SfANSISTRINGS-SfWIDESTRINGS-SfDYNARRAYS-SfTHREADING- SfVARIANTS-SfOBJECTS-SfCOMMANDARGS-SfRANDOM-SfRESOURCES#endif#endifSo exception handling enabled or disabled? Let me rephrase: According to the Wiki: To enable the RTL to raise exceptions instead of generating runtime errors, use the SysUtils unit in your program. SysUtils unit is not included in the list of units for AVR in Makefile => there is no point currently to check if an exception should be raised for AVR in the RTL error handling code. Of course the easiest solution right now to reduce the size of the RTL error handling portion of the code is to comment out -SfEXCEPTIONS in system.cfg and rebuild RTL. ---------------------------------------------------------------------- Laksen · 2020-01-14 16:33 Ahh, yeah div still pulls in the exception handling. I actually thought that had been changed, as in have generic *_checkoverflow versions that do division by zero checking. When dividing by a positive non-zero constant there can never be overflows, and this is usually what is used on AVR (divide/mod by 10 for int<>string conversion) ---------------------------------------------------------------------- julkas · 2020-01-14 16:53 Ok. I will rebuild cross compiler and report results. Thanks. ---------------------------------------------------------------------- julkas · 2020-01-18 13:10 After disabling -SfEXCEPTIONS -SfCLASSES in rtl/embedded/system.cfg code size reduced by 1K - Code: Text  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i 2057 lines compiled, 0.5 sec, 7174 bytes code, 388 bytes data ---------------------------------------------------------------------- julkas · 2020-01-19 11:16 Strange output. I have disabled  CLASSES, EXCEPTIONS -  Code: Text  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i $ ppcrossavr.exe -iFree Pascal Compiler version 3.3.1 Compiler date      : 2020/01/18Compiler CPU target: avr Supported targets (targets marked with '{*}' are under development):  embedded: Embedded Supported CPU instruction sets:  AVR1,AVR2,AVR25,AVR3,AVR31,AVR35,AVR4,AVR5,AVR51,AVR6 Supported FPU instruction sets:  NONE,SOFT,LIBGCC Supported inline assembler modes:  STANDARD  GAS Recognized compiler and RTL features:  HEAP,INITFINAL,RT TI,CLASSES,EXCEPTIONS,EXITCODE,ANSISTRINGS,WIDESTRINGS  TEXTIO,CONSOLEIO,FILEIO,RANDOM,VARIANTS,OBJECTS,DYNARRAYS,THREADING  C OMMANDARGS,PROCESSES,STACKCHECK,DYNLIBS,SOFTFPU,OBJECTIVEC1,RESOURCES  UNICODESTRINGS ---------------------------------------------------------------------- ccrause · 2020-01-19 14:07 Quote from: julkas on January 19, 2020, 12:16:17 pmStrange output. I have disabled  CLASSES, EXCEPTIONS -  Code: Text  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i Recognized compiler and RTL features:  HEAP,INITFINAL,RTTI,CLASSES,EXCEPTIONS,EXI TCODE,ANSISTRINGS,WIDESTRINGS  TEXTIO,CONSOLEIO,FILEIO,RANDOM,VARIANTS,OBJECTS,DYNARRAYS,THREADING  C OMMANDARGS,PROCESSES,STACKCHECK,DYNLIBS,SOFTFPU,OBJECTIVEC1,RESOURCES  UNICODESTRINGS That is the list of features the compiler knows of.  It does not mean that the system unit was compiled with those features enabled. ---------------------------------------------------------------------- julkas · 2020-01-19 14:16 Quote from: ccrause on January 19, 2020, 03:07:31 pmQuote from: julkas on January 19, 2020, 12:16:17 pmStrange output. I have disabled  CLASSES, EXCEPTIONS -  Code: Text  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i Recognized compiler and RTL features:  HEAP,INITFINAL,RTTI,CLASSES,EXCEPTIONS,EXI TCODE,ANSISTRINGS,WIDESTRINGS  TEXTIO,CONSOLEIO,FILEIO,RANDOM,VARIANTS,OBJECTS,DYNARRAYS,THREADING  C OMMANDARGS,PROCESSES,STACKCHECK,DYNLIBS,SOFTFPU,OBJECTIVEC1,RESOURCES  UNICODESTRINGS That is the list of features the compiler knows of.  It does not mean that the system unit was compiled with those features enabled. OK. How read / output enabled compiler features ? Simple question. I need only enabled compiler features. ppcrossavr.exe -ir current output - Code: Text  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i HEAPINITFIN ALRTTICLASSESEXCEPTIONSEXITCODEANSISTRINGSWIDESTRINGSTEXTIOCONSOLEIOFI LEIORANDOMVARIANTSOBJECTSDYNARRAYSTHREADINGCOMMANDARGSPROCESSESSTACKCH ECKDYNLIBSSOFTFPUOBJECTIVEC1RESOURCESUNICODESTRINGS ---------------------------------------------------------------------- ccrause · 2020-01-19 15:15 Whether a feature is available or not is not known by the compiler, since the feature support is included (or not) depending on the features enabled when the RTL was compiled.  The RTL supported features are available as compile time macros.  To see this add command line option -va when compiling a unit or program.  The compiler will then list the available features for the current subarch RTL.  Below I have copied the feature macros displayed after the compiler loaded the system unit when compiling one of my AVR projects: Code: Text  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i Debug: [0.051] (SYSTEM)   (10056) Finished loading unit SYSTEMDebug: [0.051] Searching file adctest.pp... foundDebug: [0.051] Searching file adctest.pp... foundDebug: [0.051] /home/christo/fpc/fpc- avr/src/examples/adc4809/adctest.pp(3,5)  (3101) Macro defined: FPC_HAS_FEATURE_HEAPDebug: [0.051] /home/christo/fpc/fpc- avr/src/examples/adc4809/adctest.pp(3,5)  (3101) Macro defined: FPC_HAS_FEATURE_RTTIDebug: [0.051] /home/christo/fpc/fpc- avr/src/examples/adc4809/adctest.pp(3,5)  (3101) Macro defined: FPC_HAS_FEATURE_TEXTIODebug: [0.051] /home/christo/fpc/fpc- avr/src/examples/adc4809/adctest.pp(3,5)  (3101) Macro defined: FPC_HAS_FEATURE_FILEIODebug: [0.051] /home/christo/fpc/fpc- avr/src/examples/adc4809/adctest.pp(3,5)  (3101) Macro defined: FPC_HAS_FEATURE_OBJECTSDebug: [0.051] (ADCTEST)  (10057) Registering new unit OBJPAS This way you can test whether a feature is supported before trying to use it in code: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i type  {$if defined(FPC_HAS_FEATURE_CLASSES)}  TTest = class    procedure foo;  end;  {$elseif defined(FPC_HAS_FEATURE_OBJECTS)}  TTest = object    procedure foo;  end;  {$else}    {$fatal 'Either CLASSES or OBJECTS must be supported for this to compile'}  {$endif} ---------------------------------------------------------------------- julkas · 2020-01-19 16:47 Thanks. -va option is very useful.