[fpc-devel] ENC28J60 Ethernet Controller AVR/ARM Driver

Michael Ring mail at michael-ring.org
Sun Jun 2 16:38:18 CEST 2019


My 10 Cents on 'Embedded friendlyness':

Objects and simple functions/procedures do not differ much in 
flash/memory usage as long as you do not use constructors/destructors.

Calling your first constuctor adds arround 750 bytes of extra code (on 
avr platform). As those avr devices can have very low amount of flash 
i'd stay away from constuctors if possible.I'd also try to avoid virtual 
methods as the compiler will have to create a vmt and this will cost you 
precious RAM.

Enhanced Records are also a good choice because you can save some bytes 
as the compiler can reuse the "self" parameter to address other fields 
in the record. This saves space on arm/mipsel targets where Devices like 
spi/uart/i2c are modeled as records and you usually address more than 
one register in a typical call to initialize or use the device.
Last time I checked Enhanced Records also do not have constructors/vmt's 
(OK, not true for delphi...) so also no easy chance to waste that extra 
Flash/Ram on constuctors and vmt's.....

Besides those memory saving arguments here are some more ideas:

When using Objects or advanced records you can simplify code that can 
use more than one communications protocol, e.g. those cheap 
OLED-Displays often are able to be driven via either SPI and I2C. When 
you create a thin layer on SPI/I2C then it is quite easy to support both 
protocols with low overhead and quite clean code for this kind of devices.

 From the "syntax candy" side of things I would definitely prefer 
Objects/Advanced Records over raw functions/procedures as you will get 
nice syntax help for all methods/properties as soon as you type the name 
of your instance in Lazarus.

So what about classes?

In a perfect world where everybody uses high performance 32bit 
microcontrollers (CortexM4/M7 chips from Microchip(Atmel)/ST/NXP) I 
would only use Classes and be happy forever, but unfortunately it seems 
that those 'big' chips, although beeing quite cheap (arround $10 to $40 
for a very decent development board) do not catch that much attention, 
wonder why...

And on all the small chips (LPC8xx/LPC11xx, AVR...,SAMD10/11) are 
absolutely not suited for classes as usage of classes will usually come 
with a high memory footprint , you will use all language features 
available and this requires you to often include additional units like 
sysutils which alone comes with a huge memory overhead and code 
generated for classes often includes hidden helpers that cost you extra 
CPU-Cycles and even more Flash..... Also Classes ar instanciated on 
Heap, so you also need to include HeapMgr, not the biggest price to pay 
but anoher few k of flash are gone....

If you want to dig deeper i'd recommend to compile your code with the 
'-a' parameter, this parameter tells fpc to not delete the generated 
assembler files and simply by looking at those you get a good feel on 
what code is efficient and what code wastes cycles/flash like hell.

So, to sum up, for me advanced records are currently the most efficient 
way to program microcontrollers, mainly because of my focus on smaller 
executables for the widest range of controllers, but depending on your 
requirements your mileage may vary.....

Michael


Here's a lpi file to get you started in your investigations, you may 
need to change a few paths as they are unix specific....

<?xml version="1.0" encoding="UTF-8"?>
<CONFIG>
   <ProjectOptions>
     <General>
       <UseAppBundle Value="False"/>
     </General>
     <BuildModes Count="1">
       <Item1 Name="default" Default="True"/>
     </BuildModes>
     <Units Count="1">
       <Unit0>
         <Filename Value="test.lpr"/>
         <IsPartOfProject Value="True"/>
         <IsVisibleTab Value="True"/>
         <Loaded Value="True"/>
       </Unit0>
     </Units>
   </ProjectOptions>
   <CompilerOptions>
     <Target>
       <Filename Value="test"/>
     </Target>
     <SearchPaths>
       <UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/>
     </SearchPaths>
     <CodeGeneration>
       <TargetCPU Value="avr"/>
       <TargetOS Value="embedded"/>
     </CodeGeneration>
     <Linking>
       <Debugging>
         <GenerateDebugInfo Value="True"/>
         <DebugInfoType Value="dsDwarf2"/>
         <UseLineInfoUnit Value="False"/>
       </Debugging>
     </Linking>
     <Other>
       <CustomOptions Value="-Cpavr5
-XP/usr/local/bin/avr-
-WpATMEGA328P
-dATMEGA328P
-MObjFpc
-a
       "/>
     </Other>
   </CompilerOptions>
</CONFIG>

Am 01.06.19 um 15:37 schrieb Dimitrios Chr. Ioannidis via fpc-devel:
>
> Hi,
>
>   I started to write a driver ( 
> https://github.com/dioannidis/fp_ethernet_enc28j60.git ) for this chip 
> ( ENC28J60 Ethernet Controller ) first for the AVR platform, ( heavily 
> inspired from the UIPEthernet library ( 
> https://github.com/UIPEthernet/UIPEthernet.git )) and I want to ask 
> the community, of course, is there anyone that already done it ?
>
>   My goal is to made the free pascal users able to use a very low cost 
> solution Arduino Nano / UNO  development board with a ENC28J60 module 
> for a little IoT ( and not only ) fun, learning e.t.c. ...
>
>   I managed to configure the chip and the driver receives packets ( 
> broadcast packets configured to allow only ARP ).
>
>   Now, because I'm not embedded developer I'm thinking that I would 
> need help / advices to take some decisions so here I am.
>
>   First and more important, in the new FPC version, will the AVR 
> platform review / resolve the following issues :
>
>     "AVR - incorrect stack error checking" 
> (https://bugs.freepascal.org/view.php?id=35332)
>     "AVR - Assembler routines for 8, 16 & 32 bit unsigned div (code 
> contribution)" ( https://bugs.freepascal.org/view.php?id=32103 )
>     "AVR - invalid address used when evaluating a variable in gdb" ( 
> https://bugs.freepascal.org/view.php?id=33914 )
>     "AVR - Incorrect SPI clock rate bit constant names in some 
> microcontroller units" ( https://bugs.freepascal.org/view.php?id=32339 )
>     and add support for theavrxmega3 subarch, atmega 3208, 3209, 4808, 
> 4809 ( from Christo Crause's repository 
> https://github.com/ccrause/freepascal.git ) ?
>
>   Except from Laksen's ethernet stack ( 
> https://github.com/Laksen/fp-ethernet.git ) is there other, more 
> lightweight, ethernet stack library written in Object Pascal ?
>
>   As I'm not a compiler guy, isthe "volatile" intrinsic supported in 
> AVR platform ( I didn't find it in intrinsics unit ) ?
>
>   In FPC embedded world/platforms, is the Object approach more SRAM 
> hungry ( my tests are inconclusive ) from the procedure / function 
> approach ?
>
>   What's more embedded "friendly" ?
>
> this :
>
> interface
>
> type
>   TUART = Object
>   private
>     FBaudRate: DWord;
>     function Divider: Integer;
>   public
>     procedure Init(const ABaudRate: DWord = 57600);
>     procedure SendChar(c: char);
>     function ReadChar: char;
>     procedure SendString(s: ShortString);
>     procedure SendStringLn(s: ShortString = '');
>   end;
>
> or this :
>
> interface
>
>   var
>     FBaudRate: DWord;
>     function Divider: Integer;
>     procedure Init(const ABaudRate: DWord = 57600);
>     procedure SendChar(c: char);
>     function ReadChar: char;
>     procedure SendString(s: ShortString);
>
>     procedure SendStringLn(s: ShortString = '');
>
>
> And of course anyone who wants to help is welcome .
>
> regards,
>
> -- 
>
> Dimitrios Chr. Ioannidis
>
>
> _______________________________________________
> fpc-devel maillist  -fpc-devel at lists.freepascal.org
> http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freepascal.org/pipermail/fpc-devel/attachments/20190602/03918fa3/attachment.html>


More information about the fpc-devel mailing list