Skip to content

saul/gpio: Low footprint handling of active-low signals + state initialization#7586

Merged
miri64 merged 5 commits intoRIOT-OS:masterfrom
cladmi:pr/saul/gpio
Oct 10, 2017
Merged

saul/gpio: Low footprint handling of active-low signals + state initialization#7586
miri64 merged 5 commits intoRIOT-OS:masterfrom
cladmi:pr/saul/gpio

Conversation

@cladmi
Copy link
Copy Markdown
Contributor

@cladmi cladmi commented Sep 8, 2017

This is a low footprint implementation for SAUL active-low and state init.

The basic idea, is to pass saul_gpio_params_t structure to read/write instead of only pin (which already saves code), and add a single flags entry in it.
This removes the need to duplicate drivers and only adds one enum entry.

I changed the samr21-xpro to invert led and button.

My footprint tests where done with examples/saul the samr21-xpro

Steps samr21-xpro iotlab-m3
Original 17364 21352
Change dev 17340 21332
Inverted support 17360 21352
Init support 17384 21380

All steps are done in different commit so I could only put some part of it.

Size testing procedure

export RIOT_VERSION='' # prevents the version to change size
make BOARD=samr21-xpro | grep 'examples/saul' | cut -f 4
make BOARD=iotlab-m3 | grep 'examples/saul' | cut -f 4

I did not put initial state setting in the output only mode for readability, but I could (it is harmless by default). Or put a DEVELHELP message when using it for an input.

This could replace #7151, #7148

@cladmi
Copy link
Copy Markdown
Contributor Author

cladmi commented Sep 8, 2017

Setting dev in saul_reg_t to a pointer to const should not be a problem because both saul_read_t and saul_write_t don't modify dev: const void *dev, and so subfunctions should not modify it too.

With dev being set to a pointer to const, saul_adcs pointer array can also be removed to save space.

@smlng smlng requested a review from haukepetersen September 11, 2017 08:55
@smlng smlng added the Type: enhancement The issue suggests enhanceable parts / The PR enhances parts of the codebase / documentation label Sep 11, 2017
@smlng smlng requested review from aabadie and smlng September 11, 2017 08:55
.pin = LED0_PIN,
.mode = GPIO_OUT
.mode = GPIO_OUT,
.flags = 0,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(here and below) when using designated initializers, empty fields don't have to be specified. So IMO the .flags = 0 should go.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That what I was thinking too, but when talking with @haukepetersen he thought they may be required for some architecture.
I will remove them all.

.name = "LED",
.pin = LED0_PIN,
.mode = GPIO_OUT
.mode = GPIO_OUT,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this mode field mean that when using saul, a GPIO pin config (in/out, pullups) ist hard-coded at compile time?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think so, then at runtime in auto_init_gpio.c the mode field is used to select in or out saul driver and is given to gpio_init.

smlng
smlng previously requested changes Sep 18, 2017
gpio_t pin = *((const gpio_t *)dev);
res->val[0] = (gpio_read(pin)) ? 1 : 0;
const saul_gpio_params_t *p = (const saul_gpio_params_t *)dev;
int inverted = (p->flags | SAUL_GPIO_INVERTED);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be int inverted = (p->flags & SAUL_GPIO_INVERTED);, or not?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do this mistake all the time.

gpio_t pin = *((const gpio_t *)dev);
gpio_write(pin, state->val[0]);
const saul_gpio_params_t *p = (const saul_gpio_params_t *)dev;
int inverted = (p->flags | SAUL_GPIO_INVERTED);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dito, as above should be &?

const saul_gpio_params_t *p = (const saul_gpio_params_t *)dev;
int inverted = (p->flags | SAUL_GPIO_INVERTED);

res->val[0] = (gpio_read(p->pin)) ? !inverted : inverted;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you could use XOR here and below, i.e.,

res->val[0] = gpio_read(p->pin) ^ inverted;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am doing an XOR, but not a bitwise xor.

I just checked and no it cannot be replaced, gpio_read is only expected to return a positive value on HIGH. https://github.com/RIOT-OS/RIOT/blob/2017.07/drivers/include/periph/gpio.h#L189

When looking at actual implementation, the first I found in alpha order is https://github.com/RIOT-OS/RIOT/blob/2017.07/cpu/atmega_common/periph/gpio.c#L209 which in fact does not return 1.

The previous code was also doing this (gpio_read(pin) ? 1 : 0)
The thing I have here, is that I expect SAUL_GPIO_INVERTED to be equal to 1. Maybe it would require a static assert for this.

@smlng
Copy link
Copy Markdown
Member

smlng commented Sep 18, 2017

@haukepetersen I thought there already was some similar attempt (by you) in the past to tackle this invert stuff, so could be a duplicate here?

@aabadie aabadie added the CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR label Oct 1, 2017
@aabadie
Copy link
Copy Markdown
Contributor

aabadie commented Oct 1, 2017

so could be a duplicate here?

As stated in the initial comment "This could replace #7151, #7148 ", so I don't think it's a duplicate but rather a better proposal. The #7151 version increases the firmware size by 100 bytes, here it's only 20 with other improvements included: gpio being cleared at auto_init.

I vote for this one.

aabadie
aabadie previously requested changes Oct 1, 2017
Copy link
Copy Markdown
Contributor

@aabadie aabadie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few minor comments. Otherwise the changes here do what they are supposed to correctly (tested on samr21-xpro and nucleo-l432).

#ifdef MODULE_SAUL_GPIO
typedef enum {
SAUL_GPIO_INVERTED = 1 << 0, /**< pin is used as inverted */
SAUL_GPIO_CLEAR = 1 << 1, /**< set pin inactive after initialization */
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe rename to SAUL_GPIO_INIT_CLEAR to be more explicit. Same with SAUL_GPIO_INIT_SET below

.pin = LED0_PIN,
.mode = GPIO_OUT
.mode = GPIO_OUT,
.flags = SAUL_GPIO_INVERTED,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIUC the logic, you should add SAUL_GPIO_CLEAR (or SAUL_GPIO_INIT_CLEAR) to ensure the pin initialized cleared ? Otherwise it's set after initialization (default GPIO behavior on this board).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think changing the initial value belongs to a different commit. So I prefer not include it in this PR.

@cladmi
Copy link
Copy Markdown
Contributor Author

cladmi commented Oct 2, 2017

I can split this PR in three if some points need to be discussed specifically. Because there really are 3 parts to it:

  • changing to const void *dev in saul_reg_t and using it to reduce code size
  • Adding inverted mode support and using it for samr21
  • Adding state initialization support

I will wait for @haukepetersen before changing.

Copy link
Copy Markdown
Contributor

@haukepetersen haukepetersen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two minor comments, else this looks good to me.

const char *name; /**< name of the device connected to this pin */
gpio_t pin; /**< GPIO pin to initialize and expose */
gpio_mode_t mode; /**< pin mode to use */
const char *name; /**< name of the device connected to this pin */
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here and below: please align comment to 4 spaces

typedef enum {
SAUL_GPIO_INVERTED = 1 << 0, /**< pin is used as inverted */
SAUL_GPIO_INIT_CLEAR = 1 << 1, /**< set pin inactive after initialization */
SAUL_GPIO_INIT_SET = 1 << 2, /**< set pin active after initialization */
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here and in other places of this PR: I would tend to remove the comma after the last element

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Forget about it. As we don't use C89 there is no reason, so keep it as is.

Copy link
Copy Markdown
Contributor

@haukepetersen haukepetersen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK, please squash

@haukepetersen haukepetersen added the CI: needs squashing Commits in this PR need to be squashed; If set, CI systems will mark this PR as unmergable label Oct 5, 2017
@cladmi
Copy link
Copy Markdown
Contributor Author

cladmi commented Oct 5, 2017

Rebased and squashed

@vincent-d vincent-d added CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR and removed CI: needs squashing Commits in this PR need to be squashed; If set, CI systems will mark this PR as unmergable CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR labels Oct 6, 2017
@miri64 miri64 dismissed stale reviews from aabadie, smlng, and kaspar030 October 10, 2017 16:48

Was addressed

@miri64 miri64 merged commit 72edaa3 into RIOT-OS:master Oct 10, 2017
@cladmi cladmi deleted the pr/saul/gpio branch October 24, 2017 15:12
@cladmi cladmi added this to the Release 2017.10 milestone Nov 7, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Type: enhancement The issue suggests enhanceable parts / The PR enhances parts of the codebase / documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants