Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2019-06

ENC28J60 Ethernet Controller AVR/ARM Driver

12 messages · 5 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Dimitrios Chr. Ioannidis

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

Reply by email

Michael Ring
to Dimitrios Chr. Ioannidis

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>

Dimitrios Chr. Ioannidis wrote 92 lines
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 http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel

Reply by email

Jeppe Johansen
to Dimitrios Chr. Ioannidis:   I started to write a driver ( https://github.com/dioannidis/fp_ethernet_enc28j60.git )…
Dimitrios Chr. Ioannidis wrote 25 lines
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)

It should work now. Looking into whether it will make sense to just use up all the space of non-data as suggested in the related issue.

"AVR - Assembler routines for 8, 16 & 32 bit unsigned div (code contribution)" ( https://bugs.freepascal.org/view.php?id=32103 )

Fixed as well.

"AVR - invalid address used when evaluating a variable in gdb" ( https://bugs.freepascal.org/view.php?id=33914 )

Looking into this.

Show quoted text 10 lines
"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 ?

Not sure, but I doubt it. But how much more lightweight do you need it to be? ;)

  As I'm not a compiler guy, isthe "volatile" intrinsic supported in AVR platform ( I didn't find it in intrinsics unit ) ?

It's supported, but it does not do least not now, and I don't think that will change. All global variable or pointer accesses are considered volatile to my knowledge.

But volatile in FPC does not guarantee any atomic access. So this would need to be by you. If what you need is just atomic access, then simple functions like these generate optimal code:

procedure AtomicWnrite(var value: word; new_value: word); inline;
var
   b: Byte;
begin
   b:=avr_save;
   value:=new_value;
   avr_restore(b);
end;
function AtomicRead(var value: word): word; inline;
var
   b: Byte;
begin
   b:=avr_save;
   AtomicRead:=value;
   avr_restore(b);
end;
Show quoted text 7 lines
  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" ?

If used sensibly they should be more or less equal in size, but you will see some extra overhead with objects. Mostly due to needing passing the pointer to the object as an argument. But you also gain some level of abstraction. So it's a tradeoff.

Show quoted text 45 lines
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-pascal maillist - http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Reply by email

Dimitrios Chr. Ioannidis
to Jeppe Johansen

Hi Jeppe,

Wow, what can I say.
In a weekend you fix / resolve issues that they were stalled for a long time. Really appreciated.

Jeppe Johansen wrote
On 6/1/19 3:37 PM, Dimitrios Chr. Ioannidis via fpc-pascal wrote:

< snip >

Show quoted text 6 lines
>   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 [3]) It should work now. Looking into whether it will make sense to just use up all the space of non-data as suggested in the related issue.

Nice ! Now I can continue to work feeling safer avoiding unnoticed stack heap collision.

>     "AVR - Assembler routines for 8, 16 & 32 bit unsigned div > (code contribution)" ( https://bugs.freepascal.org/view.php?id=32103 > [4] ) Fixed as well.

Kudos to Christo Crause and thank you very much Jeppe that took the time to review it.

< snip >

>     and add support for the avrxmega3 subarch, atmega 3208, > 3209, 4808, 4809 ( from Christo Crause's repository > https://github.com/ccrause/freepascal.git [7] ) ?

Any news, plans for those mcu's ( I don't want to push my luck ... )?

Show quoted text 5 lines
>   Except from Laksen's ethernet stack ( > https://github.com/Laksen/fp-ethernet.git [8] ) is there other, more > lightweight, ethernet stack library written in Object Pascal ? Not sure, but I doubt it. But how much more lightweight do you need it to be? ;)

:-0 ! Ohh !

Just realized that the Laksen and Jeppe is the same person …

It's embarrassing ! :$ !

Show quoted text 36 lines
>   As I'm not a compiler guy, is the "volatile" intrinsic supported > in AVR platform ( I didn't find it in intrinsics unit ) ? It's supported, but it does not do least not now, and I don't think that will change. All global variable or pointer accesses are considered volatile to my knowledge. But volatile in FPC does not guarantee any atomic access. So this would need to be by you. If what you need is just atomic access, then simple functions like these generate optimal code: procedure AtomicWnrite(var value: word; new_value: word); inline; var   b: Byte; begin   b:=avr_save;   value:=new_value;   avr_restore(b); end; function AtomicRead(var value: word): word; inline; var   b: Byte; begin   b:=avr_save;   AtomicRead:=value;   avr_restore(b); end; >   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" ? If used sensibly they should be more or less equal in size, but you will see some extra overhead with objects. Mostly due to needing passing the pointer to the object as an argument. But you also gain some level of abstraction. So it's a tradeoff.

Some valuable hints there.

Thank you Jeppe for your time and work.

regards,

Dimitrios Chr. Ioannidis

Reply by email

Christo Crause
to Dimitrios Chr. Ioannidis: Wow, what can I say. In a weekend you fix / resolve issues that they were stalled for a…

On Mon, Jun 3, 2019 at 11:16 AM Dimitrios Chr. Ioannidis via fpc-devel <

Show quoted text 8 lines
wrote: >> and add support for the avrxmega3 subarch, atmega 3208, >> 3209, 4808, 4809 ( from Christo Crause's repository >> https://github.com/ccrause/freepascal.git [7] ) ? Any news, plans for those mcu's ( I don't want to push my luck ... )?

AFAIK the code hasn't been tested on an actual mcu from this family, so it is probably not yet ready for inclusion in a stable version.

Reply by email

Dimitrios Chr. Ioannidis
to Christo Crause

Hi Christo,

Στις 3/6/2019 9:47 μ.μ., ο Christo Crause έγραψε:

Show quoted text 13 lines
On Mon, Jun 3, 2019 at 11:16 AM Dimitrios Chr. Ioannidis via fpc-devel < > wrote: >>     and add support for the avrxmega3 subarch, atmega 3208, >> 3209, 4808, 4809 ( from Christo Crause's repository >> https://github.com/ccrause/freepascal.git [7] ) ? Any news, plans for those mcu's ( I don't want to push my luck ... )? AFAIK the code hasn't been tested on an actual mcu from this family, so it is probably not yet ready for inclusion in a stable version.

I build a simple blinky for a atmega4809 and it worked. I thought that I informed you regarding this but it seems that I forgot.

If you want I can run some tests. You can send me tests that you think that are appropriate for those mcu's.

I've soldered a atmega4809 on a breakout pcb and of course I can solder the others atmega3208/9 and the athemega4808 for testing .

PS: I'm curious if there is, a test suite for testing the compiler in such hardware or how can someone create such a test ...

regards,

Dimitrios Chr. Ioannidis

Reply by email

Christo Crause
to Dimitrios Chr. Ioannidis

On Mon, Jun 3, 2019 at 9:21 PM Dimitrios Chr. Ioannidis via fpc-devel <

Show quoted text 11 lines
wrote: I build a simple blinky for a atmega4809 and it worked. I thought that I informed you regarding this but it seems that I forgot. If you want I can run some tests. You can send me tests that you think that are appropriate for those mcu's. I've soldered a atmega4809 on a breakout pcb and of course I can solder the others atmega3208/9 and the athemega4808 for testing .

Good news. I'll have t think what is different enough between the old style mega/tiny and the new xmega style controllers to warrant specific testing...

PS: I'm curious if there is, a test suite for testing the compiler in such hardware or how can someone create such a test ...

The test suite seems quite flexible, it is may be possible to build in a hardware interface (such as a serial port) to test controller responses. Another alterive could be to run code through a simulator such as simavr or fp-simavr.

Reply by email

Florian Klämpfl
to Christo Crause
Christo Crause wrote 20 lines
On Mon, Jun 3, 2019 at 9:21 PM Dimitrios Chr. Ioannidis via fpc-devel < > wrote: I build a simple blinky for a atmega4809 and it worked. I thought that I informed you regarding this but it seems that I forgot. If you want I can run some tests. You can send me tests that you think that are appropriate for those mcu's. I've soldered a atmega4809 on a breakout pcb and of course I can solder the others atmega3208/9 and the athemega4808 for testing . Good news.  I'll have t think what is different enough between the old style mega/tiny and the new xmega style controllers to warrant specific testing...   PS: I'm curious if there is, a test suite for testing the compiler in such hardware or how can someone create such a test ... The test suite seems quite flexible, it is may be possible to build in a hardware interface (such as a serial port) to test controller responses.  Another alterive could be to run code through a simulator such as simavr or fp-simavr.

This is already possible. See my test script how to do it: https://svn.freepascal.org/svn/fpcbuild/scripts/florian/win/tavr.bat

Reply by email

Dimitrios Chr. Ioannidis
to Jeppe Johansen: It should work now. Looking into whether it will make sense to just use up all the space…

Hi Jeppe,

Στις 2/6/2019 5:46 μ.μ., ο Jeppe Johansen έγραψε:

On 6/1/19 3:37 PM, Dimitrios Chr. Ioannidis via fpc-pascal wrote:

< snip >

Show quoted text 28 lines
>   As I'm not a compiler guy, isthe "volatile" intrinsic supported in > AVR platform ( I didn't find it in intrinsics unit ) ? > It's supported, but it does not do least not now, and I don't think that will change. All global variable or pointer accesses are considered volatile to my knowledge. But volatile in FPC does not guarantee any atomic access. So this would need to be by you. If what you need is just atomic access, then simple functions like these generate optimal code: procedure AtomicWnrite(var value: word; new_value: word); inline; var   b: Byte; begin   b:=avr_save;   value:=new_value;   avr_restore(b); end; function AtomicRead(var value: word): word; inline; var   b: Byte; begin   b:=avr_save;   AtomicRead:=value;   avr_restore(b); end;

Can I use those inside an interrupt handler ? What about nested interrupts ?

regards,

Dimitrios Chr. Ioannidis

Reply by email

Christo Crause
to Dimitrios Chr. Ioannidis

On Wed, Jun 5, 2019 at 8:21 AM Dimitrios Chr. Ioannidis via fpc-devel <

Show quoted text 26 lines
wrote: Στις 2/6/2019 5:46 μ.μ., ο Jeppe Johansen έγραψε: > On 6/1/19 3:37 PM, Dimitrios Chr. Ioannidis via fpc-pascal wrote: > procedure AtomicWnrite(var value: word; new_value: word); inline; > var > b: Byte; > begin > b:=avr_save; > value:=new_value; > avr_restore(b); > end; > > function AtomicRead(var value: word): word; inline; > var > b: Byte; > begin > b:=avr_save; > AtomicRead:=value; > avr_restore(b); > end; Can I use those inside an interrupt handler ? What about nested interrupts ?

In my opinion not required for a normal ISR, since the global interrupt flag is disabled anyway. Obviously if you enable the global interrupt flag inside an ISR tor nesting interrupts then you would need the above functions for atomic access to variables.

For new architectures such as tinyAVR1 or megaAVR0 series the interrupt systems are a bit more involved (not sure how one would ensure atomic access if a normal ISR is interrupted by a non-maskable interrupt).

Reply by email

Jeppe Johansen
to Dimitrios Chr. Ioannidis: Στις 2/6/2019 5:46 μ.μ., ο Jeppe Johansen έγραψε: < snip > Can I use those…
Dimitrios Chr. Ioannidis wrote 41 lines
Hi Jeppe, Στις 2/6/2019 5:46 μ.μ., ο Jeppe Johansen έγραψε: > On 6/1/19 3:37 PM, Dimitrios Chr. Ioannidis via fpc-pascal wrote: < snip > >>   As I'm not a compiler guy, isthe "volatile" intrinsic supported in >> AVR platform ( I didn't find it in intrinsics unit ) ? >> > It's supported, but it does not do least not now, > and I don't think that will change. All global variable or pointer > accesses are considered volatile to my knowledge. > > But volatile in FPC does not guarantee any atomic access. So this > would need to be by you. If what you need is just atomic access, then > simple functions like these generate optimal code: > > procedure AtomicWnrite(var value: word; new_value: word); inline; > var >   b: Byte; > begin >   b:=avr_save; >   value:=new_value; >   avr_restore(b); > end; > > function AtomicRead(var value: word): word; inline; > var >   b: Byte; > begin >   b:=avr_save; >   AtomicRead:=value; >   avr_restore(b); > end; Can I use those inside an interrupt handler ? What about nested interrupts ? regards,

Yes, avr_save returns the initial state of SREG, and then disables interrupts.

Reply by email