6

I just acquired the latest Pi-3. In the Pi B+ and Pi 2 it was possible to access both the red and green LED through /sys/class/leds/led0 and /sys/class/leds/led1.

After setting up the Pi 3, I have seen that I have lost /sys/class/leds/led1, which is the green LED. I am suspecting that one of the GPIOs controlling the LED may have been taken by the wifi/bt module. Would there be a way to recover the functionality?

Milliways
  • 59,890
  • 31
  • 101
  • 209
John Smith
  • 1,251
  • 3
  • 17
  • 27

4 Answers4

6

The latest Raspbian (using kernel 4.9) seems to have restored access to /sys/class/leds/led1 which can be used to control the PWR LED on the Pi3.

NOTE this changed to /sys/class/leds/PWR in kernel 6.1 (but is a symlink to /sys/devices/platform/leds/leds/PWR/ which is easier to access).

NOTE while the LED is now controllable, the circuitry would not allow it to be turned on if the voltage is too low.

The activity of the LEDs is now controlled by Device Tree. See /boot/overlays/README

There is a limited ability to control the LEDs

act_led_trigger         Choose which activity the LED tracks.
                        Use "heartbeat" for a nice load indicator.
                        (default "mmc")

act_led_activelow Set to "on" to invert the sense of the LED (default "off") N.B. For Pi3 see pi3-act-led overlay.

act_led_gpio Set which GPIO to use for the activity LED (in case you want to connect it to an external device) (default "16" on a non-Plus board, "47" on a Plus or Pi 2) N.B. For Pi3 see pi3-act-led overlay.

pwr_led_trigger pwr_led_activelow pwr_led_gpio As for act_led_*, but using the PWR LED. Not available on Model A/B boards.

You could use heartbeat to indicate a running Pi.

DISCLAIMER This is from the official documentation. Now the (partial) circuitry of the Pi3 is published (although it is frustratingly vague and incomplete) the PWR LED appears to be directly driven by the APX803 chip.

The following may be more use if you want an indication of state, although it requires additional circuitry.

Name:   gpio-poweroff
Info:   Drives a GPIO high or low on reboot
Load:   dtoverlay=gpio-poweroff,<param>=<val>
Params: gpiopin                 GPIO for signalling (default 26)
    active_low              Set if the power control device requires a
                            high-&gt;low transition to trigger a power-down.
                            Note that this will require the support of a
                            custom dt-blob.bin to prevent a power-down
                            during the boot process, and that a reboot
                            will also cause the pin to go low.

Incidentally it is better to use sudo poweroff rather than halt as this causes the green led to flash 10 times at 1 second intervals on poweroff.

Milliways
  • 59,890
  • 31
  • 101
  • 209
4

The activity and power LEDs on the Pi3 are now connected to a GPIO port expander hanging off I2C bus 0 (the bus you must not use on the Pi3).

There is a mailbox interface to the LEDs. An (untested by me) example of using the mailbox interface for the activity LED is given at

https://github.com/vanvught/rpidmx512/blob/master/lib-bcm2835/src/bcm2837_gpio_virt.c

I presume if it works for the activity LED it will also work for the power LED.

/**
 * @file bcm2837_gpio_virt.c
 *
 */
/* This code is inspired by:
 *
 * https://github.com/raspberrypi/linux/blob/02ce9572cc77c65f49086bbc4281233bd3fa48b7/drivers/gpio/gpio-bcm-virt.c
 *
 */
/* Copyright (C) 2016 by Arjan van Vught mailto:info@raspberrypi-dmx.nl
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:

 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.

 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
#if defined (RPI3)
#include <stdint.h>
#include <stdbool.h>

#include "arm/synchronize.h"
#include "bcm2835.h"
#include "bcm2835_mailbox.h"

#define RPI_FIRMWARE_FRAMEBUFFER_GET_GPIOVIRTBUF 0x00040010;
#define NUM_GPIO 2

static volatile uint32_t gpiovirtbuf;
static uint32_t enables_disables[NUM_GPIO];

struct vc_msg_tag_uint32_t {
    uint32_t tag_id;            ///< the message id
    uint32_t buffer_size;       ///< size of the buffer
    uint32_t data_size;         ///< amount of data being sent or received
    uint32_t value;             ///<

};

struct vc_msg_uint32_t {
    uint32_t msg_size;                  ///< simply, sizeof(struct vc_msg)
    uint32_t request_code;              ///< holds various information like the success and number of bytes returned (refer to mailboxes wiki)
    struct vc_msg_tag_uint32_t tag;     ///< the tag structure above to make
    uint32_t end_tag;                   ///< an end identifier, should be set to NULL
};

static uint32_t get_uint32_t(void) {
    struct vc_msg_uint32_t *vc_msg = (struct vc_msg_uint32_t *)MEM_COHERENT_REGION;

    vc_msg->msg_size = sizeof(struct vc_msg_uint32_t);
    vc_msg->request_code = 0;
    vc_msg->tag.tag_id = RPI_FIRMWARE_FRAMEBUFFER_GET_GPIOVIRTBUF;
    vc_msg->tag.buffer_size = 4;
    vc_msg->tag.data_size = 0;
    vc_msg->tag.value = 0;
    vc_msg->end_tag = 0;

    bcm2835_mailbox_flush();
    bcm2835_mailbox_write(BCM2835_MAILBOX_PROP_CHANNEL, GPU_MEM_BASE + (uint32_t)vc_msg);
    (void)bcm2835_mailbox_read(BCM2835_MAILBOX_PROP_CHANNEL);

    dmb();

    if (vc_msg->request_code != BCM2835_MAILBOX_SUCCESS) {
        return 0;
    }

    return vc_msg->tag.value;
}

uint32_t bcm2837_gpio_virt_get_address(void) {
    return gpiovirtbuf;
}

void bcm2837_gpio_virt_init(void) {
    int i;

    for (i = 0 ; i < NUM_GPIO ; i++) {
        enables_disables[i] = 0;
    }

    gpiovirtbuf = get_uint32_t();
    gpiovirtbuf &= 0x3FFFFFFF;
}

void bcm2837_gpio_virt_led_set(int val) {
    uint16_t enables, disables;
    int16_t diff;
    bool lit;

    if (gpiovirtbuf == 0) {
        return;
    }

    enables = enables_disables[0] >> 16;
    disables = enables_disables[0] >> 0;

    diff = (int16_t) (enables - disables);
    lit = diff > 0;

    if ((val && lit) || (!val && !lit)) {
        return;
    }

    if (val) {
        enables++;
    } else {
        disables++;
    }

    enables_disables[0] = (enables << 16) | (disables << 0);

    dmb();
    *(volatile uint32_t *)gpiovirtbuf = enables_disables[0];
}
#endif
joan
  • 71,024
  • 5
  • 73
  • 106
2

I haven't figured out how to get the Red LED working but I have figured out (kinda) how to get the Green LED under control.

This is from user pelwell in the post here.

130 is the activity LED, so /opt/vc/bin/vcmailbox 0x00038041 8 8 130 1 will turn it on and /opt/vc/bin/vcmailbox 0x00038041 8 8 130 0 will turn it off. Be aware that any SD card activity will override the value you set, so if you really want programmatic control of that LED you should change the LED trigger:

sudo sh -c "echo none > /sys/class/leds/led0/trigger"        # Static LED off
sudo sh -c "echo default-on > /sys/class/leds/led0/trigger"   # Static LED on
sudo sh -c "echo mmc0 > /sys/class/leds/led0/trigger"        # The normal behaviour

The way I'm using it is basically hacking this into a C program. After running one of the commands to get the Green LED into a static state, I use these commands in my C code which seem to work for the moment. Be sure to #include <stdlib.h>

//Turn Green LED ON
system("/opt/vc/bin/vcmailbox 0x00038041 8 8 130 1");

//Turn Green LED OFF
system("/opt/vc/bin/vcmailbox 0x00038041 8 8 130 0");

Although I am aware that this command is using the Video Core Mailbox to talk to the GPU (VCOS) and thus ask it to twiddle the bit controlling the Green LED, I am very UNaware how this is being accomplished or how this 'vcmailbox' function runs. I have not been able to find solid documentation on it besides a few code examples in how to use the mailbox system. Writing an entire mailbox interface seems a little crazy for what I'm trying to do (custom LED blinking in order to indicate a few simple statuses-kinda like beep codes on a motherboard) and if anyone knows a more simple/succinct/elegant way to control the onboard LEDs Please! Reduce my ignorance!

kawthuldrok
  • 121
  • 2
-1

Switch power (red) led off on my Pi 3:

sudo sh -c "echo none > /sys/class/leds/led1/trigger"

You can put this in /etc/rc.local for a reboot before the exit 0 line:

sudo sh -c "echo none > /sys/class/leds/led1/trigger" &

goobering
  • 10,730
  • 4
  • 39
  • 64