8

What is the RPi GPIO Pin output current?

I assume it's more than 10mA since it can drive LEDs without any problem but what is the spec?

0

4 Answers 4

6

After reset it's 8mA. You can program it up to 16mA though

4
  • i got used to PIC where the rated current are fixed/rated, didn't expect it to be programmable. Do you have any idea how to program it to 16mA? or what's the default value? Jul 18, 2012 at 2:29
  • 1
    @JeeShenLee, the default is 8mA Jul 18, 2012 at 2:34
  • 4
    Any chance of some example code? Jul 18, 2012 at 6:30
  • The link is no longer working. Sep 16, 2015 at 23:11
2

To program the PADS registers to alter the output current, the following shows the pertinent code:

#define BCM2708_PERI_BASE        0x20000000
#define GPIO_BASE                (BCM2708_PERI_BASE + 0x200000) /* GPIO   */
#define PADS_BASE                (BCM2708_PERI_BASE + 0x100000) /* PADS   */

#define PADS0   *(pads+11)
#define PADS1   *(pads+12)
#define PADS2   *(pads+13)

// I/O access - Reqires maping.
volatile unsigned *pads;

Then from your code, after mmap'ing the pads (see here) pointer you should be able to set the pads registers like so,

PADS0 = (0xFFFFFFF8 & PADS0) | 7; // Sets GPIO 0-27 to 16mA
PADS1 = (0xFFFFFFF8 & PADS1) | 4; // Sets GPIO 28-45 to 10mA
PADS2 = (0xFFFFFFF8 & PADS2);     // Sets GPIO 46-53 to 2mA
7
  • Have you tested this? I reckon this is a seg fault? Jul 19, 2012 at 8:43
  • I realised I can't test it, until this afternoon, but will update with complete working example.
    – Dog Ears
    Jul 19, 2012 at 8:49
  • why would this seg fault?
    – Dog Ears
    Jul 19, 2012 at 8:50
  • Because 0x20100000 isn't in your virtual memory. Jul 19, 2012 at 8:52
  • I can understand what you mean about mapping etc; it would be nice to see that updated at some point so that the code works as downloaded. Jul 19, 2012 at 8:58
1

If you can bear some of my old C code, here is an example of performing the mapping in C

#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <limits.h>
#include <unistd.h>
#include <time.h>
#include <signal.h>
#include <termios.h>
#include <ctype.h>

#define FALSE                    (0)
#define TRUE                     (!FALSE)
#define NULL_FD                  ((int)0)
#define MAP_NAME_LEN             (20)
#define NO_MASK                  (UINT_MAX)

#define BCM2708_PERI_BASE        0x20000000
#define GPIO_BASE                (BCM2708_PERI_BASE + 0x200000) /* GPIO   */
#define PADS_BASE                (BCM2708_PERI_BASE + 0x100000) /* PADS   */

#define PADS0                    (11 * 4)
#define PADS1                    (12 * 4)
#define PADS2                    (13 * 4)

#define PADS_CURRENT_MASK        (0x00000007)

typedef struct raw_memory {
    void *accessor;             // Base location for memory access
    unsigned int offset;        // Offset into base for the starting point
    unsigned int length;
    char name[MAP_NAME_LEN + 1];
} raw_memory;

int memFile = NULL_FD;
raw_memory rawMemPads= {MAP_FAILED, 0, 0, "PADS"};


void RegWrite(raw_memory *base, unsigned int address, unsigned int mask, unsigned int value);
unsigned int RegRead(raw_memory *base, unsigned int address);
BOOL MapMemory(raw_memory *base, int device, unsigned int startAddress, size_t size);
void UnmapMemory(raw_memory *base);

void RegWrite(raw_memory *base, unsigned int address, unsigned int mask, unsigned int value) {
    if (base->accessor == MAP_FAILED) {
        printf("RegWrite failed due to an unmapped base (%s)!\n", base->name);
    } else if (address >= base->length) {
        printf("RegWrite failed due to address out of bounds (%s, 0x%08X)!\n", base->name, address);
    } else {
        if (mask != NO_MASK) {
            unsigned int read = RegRead(base, address);
            value &= mask;
            value |= (~mask) & read;
        }
        *((unsigned int *)(base->accessor + base->offset + address)) = value;
    }
}

BOOL MapMemory(raw_memory *base, int device, unsigned int startAddress, size_t size) {
    // Unmap first if already allocated
    if (base->accessor != MAP_FAILED) {
        UnmapMemory(base);
    }
    // Align start address to the page size (we can only map page aligned blocks)
    base->offset = (unsigned int)(startAddress / getpagesize()) * getpagesize();
    // Compute the necessary size to cover the alignment
    base->length = (unsigned int)size;
    size += (size_t)(startAddress - base->offset);
    // Map the memory from the device to a local address
    base->accessor = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, device, base->offset);
    if (base->accessor == MAP_FAILED) {
        return FALSE;
    } else {
        // Calculate the offset needed by read / write functions to get startAddress as 0
        base->offset = startAddress - base->offset;
        return TRUE;
    }
}

void UnmapMemory(raw_memory *base) {
    if (base->accessor != MAP_FAILED) {
        munmap(base->accessor, base->offset + base->length);
        base->accessor = MAP_FAILED;
    } else {
    }
}

int main(void) {
    // Enable raw memory access
    if (memFile == NULL_FD) memFile = open("/dev/mem", O_RDWR | O_SYNC); 
    if (memFile == NULL_FD) {
        printf("Failed to open /dev/mem (are we root?) !\n");
        return 1;
    }

    // Map GPIO memory
    if (!MapMemory(&rawMemPads, memFile, PADS_BASE, 1024)) {
        printf("Failed to map GPIO device memory !\n");
        return 2;
    }

    // Actual work here
    RegWrite(&rawMem, PADS0, PADS_CURRENT_MASK, 7); // Sets GPIO 0-27 to 16mA
    RegWrite(&rawMem, PADS1, PADS_CURRENT_MASK, 4); // Sets GPIO 28-45 to 10mA
    RegWrite(&rawMem, PADS2, PADS_CURRENT_MASK, 0); // Sets GPIO 46-53 to 2mA

    // Any other code here
    //

    // Unmap the GPIO memory
    if (rawMemPads.accessor != MAP_FAILED) {
        UnmapMemory(&rawMemPads);
    }

    // Disable raw memory access
    if (memFile != NULL_FD) {
        close(memFile);
        memFile = NULL_FD;
    }

    return 0;
}

Excuse the length, it is a long bit of setup so that the main bit of code for doing masked writes is short, also it allows for out-of-alignment pages, which is not really an issue here (I had this problem previously with a different embedded register map). Note that you will need to run the binary as root or the mapping will fail as permission denied to /dev/mem

1
  • Does not compile, rawMem is not declared in main(). Also "BOOL" is not a valid datatype but is fixed with including <stdbool.h> and changing it to lowercase "bool".
    – timonsku
    Jun 15, 2016 at 12:42
0

I know this thread is ancient (but not closed!) however it was really helpful to me so I am contributing what might be a useful update.

Using pigpio you can set the GPIO pin current via "PAD strength" for a group (PAD) of pins. Using the interactive pigs tool. To set PAD0 (GPIOs 0-27) to 16mA (see pigs "pads" cmd:

pigs pads 0 16

You can also use the native C, pigpiod pipe interface, C pigpiod or Python gpiod (pgpiod is a daemon that serves up a socket interface to pigpio). Before you use pigs or any of the other pigpio d socket-based bindings, make sure you do

sudo pigpiod

I tested it and it on RPi 4B (32 bit Raspbian) and I was able to drive a 13 mA load.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.