CREATING MY FIRST LIBRARY

Go To Last Post
10 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hello everyone,

 

I'm trying to make my first ever library but the problem I facing is how can I pass data i.e. PORTx, DDRx, PINx etc registers to my function in library.

While writing function I used to define them in beginning like:

#define ABC PORTA

But know i'm wondering how can I pass this ABC to a function in my library.

#help 

This topic has a solution.
Last Edited: Wed. Jan 25, 2017 - 02:40 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The concept of abstracting the port access comes up frequently. I'd suggest a search will answer your questions in greater detail than you had considered.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I hope you won't mind if I ask for specific links of tutorial on it or stuff that is related to library formation.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You need to use/pass a pointer 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ports have addresses, no? So, when you do 

 

#define ABC PORTA

All you are doing is replacing ABC with PORTA and you are replacing PORTA with the address of PortA. As a result, any time you use ABC, that ultimately gets replaced by the address of PortA. I do that sort of thing all the time:  

 

#define LedPort PORTC
#define SwitchPort PORTC

It makes no difference that you have multiple names that resolve to PORTC.

 

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

Last Edited: Thu. Dec 15, 2016 - 08:44 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

But my question still remains unanswered that is if I have a library in which I need to pass information about on which port my peripheral is connected then how can I do that.

Should I pass the address of PORT and if I do that and pass it to a function of that library then it would consider it a value rather than address. Then how can I write to it. Right?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Look up how pointers are handled in C.

But to answer your question:

foo(&PORTA); //passes the address of PORTA to function foo

foo(PORTA); //passes the value of PORTA to function foo

 

"Some people die at 25 and aren't buried until 75." -Benjamin Franklin

 

What is life's greatest illusion?"  "Innocence, my brother." -Skyrim

 

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

I've written a lot about this but, sadly, the search engine here is not very good and it's tricky to find previous responses. However the bottom line is that static libs play NO part in AVR development for EXACTLY the reason you just discovered! Say you have a library for driving an LCD and you want the user to be able to say which PORT pins the LCD is attached to then either you need to do something horrendous like:

enum {
    LCD_PORTA,
    LCD_PORTB,
    LCD_PORTC,
    LCD_PORTD
} lcdPort;

void lcd_init(lcdPort portID) {
    switch (portID) {
        case LCD_PORTA:
            DDRA = 0xFF;
            break;
        case LCD_PORTB:
            DDRB = 0xFF;
            break;
        case LCD_PORTC:
            DDRC = 0xFF;
            break;
        case LCD_PORTD:
            DDRD = 0xFF;
            break;
    }
}

or you have to have the user pass you the addresses of PORTx, DDRx, PINx like:

void lcd_init(volatile uint8_t * lcd_DDR, volatile uint8_t * lcd_PORT, volatile uint8_t * lcd_PIN) {
    *lcd_DDR = 0xFF;
    etc.
}

If, however you give the user a .h and a .c file you can offer:

// lcd.h
#define LCD_DDR DDRB
#define LCD_PORT PORTB
etc.
// lcd.c
void lcd_init() {
    LCD_DDR = 0xFF;
}

Now the user just modifies the given lcd.h, adds the lcd.c to their project and builds it all along with the rest of their code.

 

The other issue with the liblcd.a solution is that their are 17 different AVR architectures so as a minimum, if you were to offer a prebuilt binary i nthe form of a .a file you would need to supply 17 different variants just as you see here:

avr8-gnu-toolchain-linux_x86_64/avr/lib$ find . -name "lib[c|m].a"
./avr3/libc.a
./avr3/libm.a
./avr4/libc.a
./avr4/libm.a
./avr5/libc.a
./avr5/libm.a
./avrtiny/libc.a
./avrtiny/libm.a
./avrxmega6/libc.a
./avrxmega6/libm.a
./avr31/libc.a
./avr31/libm.a
./avr25/tiny-stack/libc.a
./avr25/tiny-stack/libm.a
./avr25/libc.a
./avr25/libm.a
./avr35/libc.a
./avr35/libm.a
./avr51/libc.a
./avr51/libm.a
./tiny-stack/libc.a
./tiny-stack/libm.a
./avrxmega5/libc.a
./avrxmega5/libm.a
./avrxmega4/libc.a
./avrxmega4/libm.a
./libc.a
./avrxmega2/libc.a
./avrxmega2/libm.a
./libm.a
./avrxmega7/libc.a
./avrxmega7/libm.a
./avr6/libc.a
./avr6/libm.a

That is the library for the avr-gcc C compiler - you can see that it has multiple copies of libm.a and libc.a for this very reason.

 

So forget about static libs - they have no place for AVR (whatever the confusing project dialog in AS7 might suggest!) and just supply your user with .h/.c (or .cpp) and let them configure and build the code for their intended target.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Using Google I found some of my prior posts about this:

 

https://www.avrfreaks.net/forum/s...

https://www.avrfreaks.net/forum/i...

https://www.avrfreaks.net/comment...

https://www.avrfreaks.net/forum/u...

 

point (5) in the last one is a very strong one! The raison d'etre for libXXX.a in the old days was to only include code that was required. So a typical libXXX.a consisted of a load of single function function.o files and when you linked and used function 1 , 3 and 9 then it just pulled in functio1.o, function3.o and function9.o but now -ffunction-sections and -gc-sections makes such division pointless so it removed a lot of the reason to use static libs anyway.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Amazing. Thanks a lot for such a detailed reply.