AVRUtils - I/O Abstraction

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

Hey,

 

I just posted my very first project on the project page ( http://community.atmel.com/projects/avrutils-io-abstraction ).

 

Suggestions, Feedback and comments are very welcomed :)

 

Greetings

Last Edited: Sun. Jul 10, 2016 - 11:34 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Why does that say "Compiler/Assembler: AVR32 GNU Toolchain" then go on to talk about mega2560/mega8/etc? Is if for AVR8 or AVR32 ?

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

Oh snap!

 

I'm sorry, I misunderstood the meaning — AVR8 of course!

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

I'd also recommend registering and putting it on the far more professional hosting site at spaces.atmel.com which will even give you an VN or Git repository for it.

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

I am a big fan of anyone who strives to write portable code, but I stopped reading the project introduction after the first sentence about solving the AVR's "hardware abstraction debacle".

 

Lots of us have been abstracting AVR8 hardware, with little or no fuss – for many years. Where is the debacle and what do you mean?

- John

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

The example.s would be more useful if it had been compiled with -g !

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

clawson wrote:
I'd also recommend registering and putting it on the far more professional hosting site at spaces.atmel.com which will even give you an VN or Git repository for it.

 

Thank you for your suggestion. I am considering uploading it there as well!

 

jfiresto wrote:

I am a big fan of anyone who strives to write portable code, but I stopped reading the project introduction after the first sentence about solving the AVR's "hardware abstraction debacle".

 

Lots of us have been abstracting AVR8 hardware, with little or no fuss – for many years. Where is the debacle and what do you mean?

 

I have used AVR 8 bit microcontrollers for almost three years now and I didn't find a solution myself OR on the internet which is clean and does not violate any standards.

For example the `attribute((packed))` "hack" is not guaranteed to work.

I further got convinced that this still is an issue because of the existence of this project

At this point I must note that I didn't read all of the project's discussion so it is possible that I missed something there.

 

jfiresto wrote:

Lots of us have been abstracting AVR8 hardware, with little or no fuss – for many years.

Great! Can you share your clean solution then?

 

clawson wrote:
The example.s would be more useful if it had been compiled with -g !

 

Thank you so much! Updated the repo :)

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

dthreel wrote:
For example the `attribute((packed))` "hack" is not guaranteed to work.

In what sense does it not work? Do you mean if you take the code to something other than GCC? AFAIK __attribute__((packed)) has always worked for me when I've been using GCC whether it's AVR, ARM, x86/AMD64 or whatever. In fact it's kind of superfluous for AVR8 as it has a natural 8 bit alignment anyway.

 

Personally I use the very simple sbit.h from Peter Dannegger which is centred around:

//                      Access bits like variables:
struct bits {
  uint8_t b0:1, b1:1, b2:1, b3:1, b4:1, b5:1, b6:1, b7:1;
} __attribute__((__packed__));
#define SBIT_(port,pin) ((*(volatile struct bits*)&port).b##pin)
#define SBIT(x,y)       SBIT_(x,y)

#ifdef PORTA

#define	PORT_A0		SBIT( PORTA, 0 )
#define	PORT_A1		SBIT( PORTA, 1 )
etc.

You then just say (for example):

#define RED_LED PORT_D3

RED_LED = 1;
etc.

 

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

clawson wrote:

dthreel wrote:
For example the `attribute((packed))` "hack" is not guaranteed to work.

In what sense does it not work? Do you mean if you take the code to something other than GCC? AFAIK __attribute__((packed)) has always worked for me when I've been using GCC whether it's AVR, ARM, x86/AMD64 or whatever. In fact it's kind of superfluous for AVR8 as it has a natural 8 bit alignment anyway.

 

I can't recall the source but I've read that attribute((packed)) has issues with byte order (endianness).

Maybe you are right and it works for all AVRs.

But on a personal note I don't really feel safe with the type punning.

 

 

Nevertheless I think my library still has some use to it, for example the bus method which I really like. 

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

I had a chance to look at your examples, but could not think of how to take advantage of the library. I have had projects where I have needed to gather digital inputs from several ports and then pack them into one or more status bytes or words. I have had others where I have needed to switch digital outputs scattered across multiple ports. Finally, I have had projects where I have had digital inputs and outputs jump i/o ports and pins, upon moving code from one microcontroller model to another.

 

In the first case, I could write a function-like C-macro or a C-function, possible static inline, that gathered the bits and generated packed byte(s) or word(s). If the hardware design was not fixed, a few tweaks of the PCB layout would often allow the bits to be gathered and packed in parallel – and much more compactly and quickly.

 

In the second case, I could often write a quick macro or function that would simply set an individual output bit, directly, wherever it may be. Rarely, was there any significant cost, in terms of the programming or to the design, of setting individual bits one after another. When there was, I could do as I did in the first case.

 

In both cases, I could define symbols, macros and functions that isolated the hardware particulars and details from the rest of the code. With the consequence, that in the third case, I would simply edit the ports and bits of the above macros and functions, and in a very short time, return to working on other things.

 

Now, there are people, here, who have done many more designs than I have, and many who have designed things I could not even dream of. They or you or both, may have problems where a i/o bit-abstraction library makes bit management and control much more pleasant. I am just not one of them and not yet sensing it. It is a pity for me, because you seem really enthusiastic about i/o bits!

 

- John

Last Edited: Sun. Jul 10, 2016 - 10:10 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

jfiresto wrote:

I had a chance to look at your examples, but could not think of how to take advantage of the library. I have had projects where I have needed to gather digital inputs from several ports and then pack them into one or more status bytes or words. I have had others where I have needed to switch digital outputs scattered across multiple ports. Finally, I have had projects where I have had digital inputs and outputs jump i/o ports and pins, upon moving code from one microcontroller model to another.

 

In the first case, I could write a function-like C-macro or a C-function, possible static inline, that gathered the bits and generated packed byte(s) or word(s). If the hardware design was not fixed, a few tweaks of the PCB layout would often allow the bits to be gathered and packed in parallel – and much more compactly and quickly.

 

In the second case, I could often write a quick macro or function that would simply set an individual output bit, directly, wherever it may be. Rarely, was there any significant cost, in terms of the programming or to the design, of setting individual bits one after another. When there was, I could do as I did in the first case.

 

In both cases, I could define symbols, macros and functions that isolated the hardware particulars and details from the rest of the code. With the consequence, that in the third case, I would simply edit the ports and bits of the above macros and functions, and in a very short time, return to working on other things.

 

Now, there are people, here, who have done many more designs than I have, and many who have designed things I could not even dream of. They or you or both, may have problems where a i/o bit-abstraction library makes bit management and control much more pleasant. I am just not one of them and not yet sensing it. It is a pity for me, because you seem really enthusiastic about i/o bits!

 

 

First off thank you for revisiting this thread and for having a look at my examples!

I know the technique with the wrapper functions and actually did apply it myself.

One problem I see with this approach is, that it is a pain when you need to make some changes very rapidly.

I know bit masking is trivial but when you've got no way to display information then you have to basically rely on the fact that your function is behaving in the right way. (or do messy test-setup)

If I can't test / rely on my function then this leaves me insecure.

Before you ask, we didn't have a debugger in our environment so this was not an option at the time.

 

I tried to solve this problem with a reliable library in which it is easy to apply changes to:

Take for example this manually written code:

inline uint8_t readBus(void) {
	uint8_t port1 = PINA;
	uint8_t port2 = PINB;
	uint8_t retval;

	retval  = (port1 & 0xF0) >> 4;
	retval |= (port2 & 0x0F) << 4;

	return retval;
}

This, indeed, is nothing spectacular and pretty trivial;

yet it becomes terrible annoying and stressful for me when I need to apply changes on the I/O part of the program:

if I hypothetically moved one bit from PORTA to PORTC then I'd needed to write a mostly new function.

This sucks! Especially for fast prototyping & testing out new ideas.

 

Now compare it to:

// each data bit defined
// in a clean and isolated manner
#define DB0 ..
#define DB1 ..
#define DB2 ..
#define DB3 ..
#define DB4 ..
#define DB5 ..
#define DB6 ..
#define DB7 ..
// btw I'm working on optimizing the whole
// bus thing when all bits are on the same port
// etc.

// defined bus
#define MY_BUS io__bus(8, DB0, DB1, DB2, DB3, DB4, DB5, DB6, DB7)

// bus will be treated like a normal 8 bit variable:
io__write(MY_BUS, 0xF0); // sets DB4 to DB7 high
io__write(DB0, 1); // just sets DB0 high

I need to swap DB2 and DB3? No problem! I could just change the definition of DB2 and DB3 OR I could swap the names in the `io__bus` call & done!

I think you can see that you are definitely able to safe yourself a lot of time and hassle :)

 

But after all I just absolved my apprenticeship so I don't really have any "real world" engineering experience (I wish I've had =D).

I'm pretty experienced in software programming though (I code for almost 8 years now).

 

 

 

Last Edited: Sun. Jul 10, 2016 - 08:26 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

dthreel wrote:
... I need to swap DB2 and DB3? No problem! I could just change the definition of DB2 and DB3 OR I could swap the names in the `io__bus` call & done! I think you can see that you are definitely able to safe yourself a lot of time and hassle.
Well, that is the issue. I do not think it would not save me much time or hassle. I could use the library when writing a small part of a project's Hardware Abstraction / Portability layer. Let us be generous and suppose 20%. In turn, the work on the HAL would only be a small part of an entire project, let us say, being generous, also 20%. A very optimistic estimate is that a bit abstraction library might reduce my work by 4%.

 

Four percent is still something, but I think the library in its present state, would be a bit of a distraction, and might even slow down the overall development of a product or system. In writing the firmware, I want to abstract the details of a system's hardware as directly and quickly as possible: so that I can concentrate on the system's function and use. I do not want to think about how LED D1 maps to bit 3 of port B, and that it is active low. I want the code to simply light the status LED or toggle it, so that I can think about how the system might signal normal operation and different faults. As far as I can see, I would need to add a second abstraction layer to the bit abstraction layer to achieve that. It is perhaps not a great exaggeration to say that the present bit abstraction library would get me "stuck" thinking about bits.

 

Now if you could have the library make active low inputs and outputs appear active high, then it could at least abstract that detail, and help eliminate some of the second abstraction layer. AFAIK, you can not do that with the trick Peter Dannegger used, of mapping bit fields to port bits.

 

Perhaps I wish for something impossible: a bit abstraction library that frees me from thinking about bits!

 

- John

Last Edited: Mon. Jul 11, 2016 - 06:28 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I did something similar a while ago. In a simple header file. Without all the functionality you have implemented though.

See attachment (if you are interested). I have just added the comment on top of the file. (Don't need them myself, I use this file for all my avr projects;-)

 

Regards

Ruudje

Attachment(s):