From 5c093aaf76600ca853035c07db095b48b34f40ba Mon Sep 17 00:00:00 2001 From: Alfred Klomp Date: Sun, 13 Mar 2016 12:59:58 +0100 Subject: [PATCH 1/8] gpio: generate bank and mask values with a macro Easier to read. --- Demo/Drivers/gpio.c | 64 +++++++++++++++++++++++++-------------------- 1 file changed, 36 insertions(+), 28 deletions(-) diff --git a/Demo/Drivers/gpio.c b/Demo/Drivers/gpio.c index 485de89..e16c335 100644 --- a/Demo/Drivers/gpio.c +++ b/Demo/Drivers/gpio.c @@ -5,6 +5,9 @@ #include "gpio.h" +#define BANK(pin) ((pin) >> 5) +#define MASK(pin) (1UL << ((pin) & 0x1F)) + typedef struct { unsigned long GPFSEL[6]; ///< Function selection registers. unsigned long Reserved_1; @@ -52,44 +55,49 @@ void SetGpioDirection(unsigned int pinNum, enum GPIO_DIR dir) { SetGpioFunction(pinNum,dir); } -void SetGpio(unsigned int pinNum, unsigned int pinVal) { - unsigned long offset=pinNum/32; - unsigned long mask=(1<<(pinNum%32)); +void SetGpio(unsigned int pinNum, unsigned int pinVal) +{ + unsigned long bank = BANK(pinNum); + unsigned long mask = MASK(pinNum); if(pinVal) { - pRegs->GPSET[offset]|=mask; + pRegs->GPSET[bank] |= mask; } else { - pRegs->GPCLR[offset]|=mask; + pRegs->GPCLR[bank] |= mask; } } -int ReadGpio(unsigned int pinNum) { - return ((pRegs->GPLEV[pinNum/32])>>(pinNum%32))&1; +int ReadGpio(unsigned int pinNum) +{ + unsigned long bank = BANK(pinNum); + unsigned long mask = MASK(pinNum); + + return ((pRegs->GPLEV[bank]) >> mask) & 1; } void EnableGpioDetect(unsigned int pinNum, enum DETECT_TYPE type) { - unsigned long mask=(1<GPREN[offset]|=mask; + pRegs->GPREN[bank] |= mask; break; case DETECT_FALLING: - pRegs->GPFEN[offset]|=mask; + pRegs->GPFEN[bank] |= mask; break; case DETECT_HIGH: - pRegs->GPHEN[offset]|=mask; + pRegs->GPHEN[bank] |= mask; break; case DETECT_LOW: - pRegs->GPLEN[offset]|=mask; + pRegs->GPLEN[bank] |= mask; break; case DETECT_RISING_ASYNC: - pRegs->GPAREN[offset]|=mask; + pRegs->GPAREN[bank] |= mask; break; case DETECT_FALLING_ASYNC: - pRegs->GPAFEN[offset]|=mask; + pRegs->GPAFEN[bank] |= mask; break; case DETECT_NONE: break; @@ -98,27 +106,27 @@ void EnableGpioDetect(unsigned int pinNum, enum DETECT_TYPE type) void DisableGpioDetect(unsigned int pinNum, enum DETECT_TYPE type) { - unsigned long mask=~(1<<(pinNum%32)); - unsigned long offset=pinNum/32; - + unsigned long bank = BANK(pinNum); + unsigned long mask = MASK(pinNum); + switch(type) { case DETECT_RISING: - pRegs->GPREN[offset]&=mask; + pRegs->GPREN[bank] &= ~mask; break; case DETECT_FALLING: - pRegs->GPFEN[offset]&=mask; + pRegs->GPFEN[bank] &= ~mask; break; case DETECT_HIGH: - pRegs->GPHEN[offset]&=mask; + pRegs->GPHEN[bank] &= ~mask; break; case DETECT_LOW: - pRegs->GPLEN[offset]&=mask; + pRegs->GPLEN[bank] &= ~mask; break; case DETECT_RISING_ASYNC: - pRegs->GPAREN[offset]&=mask; + pRegs->GPAREN[bank] &= ~mask; break; case DETECT_FALLING_ASYNC: - pRegs->GPAFEN[offset]&=mask; + pRegs->GPAFEN[bank] &= ~mask; break; case DETECT_NONE: break; @@ -127,8 +135,8 @@ void DisableGpioDetect(unsigned int pinNum, enum DETECT_TYPE type) void ClearGpioInterrupt(unsigned int pinNum) { - unsigned long mask=(1<<(pinNum%32)); - unsigned long offset=pinNum/32; + unsigned long bank = BANK(pinNum); + unsigned long mask = MASK(pinNum); - pRegs->GPEDS[offset]=mask; + pRegs->GPEDS[bank] = mask; } From a8413eb7e66f48886fff16181445a86dd27f64a0 Mon Sep 17 00:00:00 2001 From: Alfred Klomp Date: Wed, 9 Mar 2016 22:17:26 +0100 Subject: [PATCH 2/8] gpio: namespace functions as gpioSomething() for uniformity Also mark constant parameters as `const' in function declarations. --- Demo/Drivers/gpio.c | 60 ++++++++++++++++++++++++--------------------- Demo/Drivers/gpio.h | 29 +++++++++++----------- Demo/main.c | 6 ++--- 3 files changed, 50 insertions(+), 45 deletions(-) diff --git a/Demo/Drivers/gpio.c b/Demo/Drivers/gpio.c index e16c335..e87f7ae 100644 --- a/Demo/Drivers/gpio.c +++ b/Demo/Drivers/gpio.c @@ -38,47 +38,49 @@ typedef struct { volatile BCM2835_GPIO_REGS * const pRegs = (BCM2835_GPIO_REGS *) (0x20200000); - -void SetGpioFunction(unsigned int pinNum, unsigned int funcNum) { - - int offset = pinNum / 10; +void +gpioFunctionSet (const unsigned int pin, const unsigned int func) +{ + int offset = pin / 10; unsigned long val = pRegs->GPFSEL[offset]; // Read in the original register value. - int item = pinNum % 10; + int item = pin % 10; val &= ~(0x7 << (item * 3)); - val |= ((funcNum & 0x7) << (item * 3)); + val |= ((func & 0x7) << (item * 3)); pRegs->GPFSEL[offset] = val; } -void SetGpioDirection(unsigned int pinNum, enum GPIO_DIR dir) { - SetGpioFunction(pinNum,dir); +void +gpioDirectionSet (const unsigned int pin, const enum GPIO_DIR dir) +{ + gpioFunctionSet(pin, dir); } -void SetGpio(unsigned int pinNum, unsigned int pinVal) +void +gpioWrite (const unsigned int pin, const unsigned int val) { - unsigned long bank = BANK(pinNum); - unsigned long mask = MASK(pinNum); + unsigned long bank = BANK(pin); + unsigned long mask = MASK(pin); - if(pinVal) { - pRegs->GPSET[bank] |= mask; - } else { - pRegs->GPCLR[bank] |= mask; - } + val ? (pRegs->GPSET[bank] |= mask) + : (pRegs->GPCLR[bank] |= mask); } -int ReadGpio(unsigned int pinNum) +unsigned int +gpioRead (const unsigned int pin) { - unsigned long bank = BANK(pinNum); - unsigned long mask = MASK(pinNum); + unsigned long bank = BANK(pin); + unsigned long mask = MASK(pin); return ((pRegs->GPLEV[bank]) >> mask) & 1; } -void EnableGpioDetect(unsigned int pinNum, enum DETECT_TYPE type) +void +gpioDetectEnable (const unsigned int pin, const enum DETECT_TYPE type) { - unsigned long bank = BANK(pinNum); - unsigned long mask = MASK(pinNum); + unsigned long bank = BANK(pin); + unsigned long mask = MASK(pin); switch(type) { case DETECT_RISING: @@ -104,10 +106,11 @@ void EnableGpioDetect(unsigned int pinNum, enum DETECT_TYPE type) } } -void DisableGpioDetect(unsigned int pinNum, enum DETECT_TYPE type) +void +gpioDetectDisable (const unsigned int pin, const enum DETECT_TYPE type) { - unsigned long bank = BANK(pinNum); - unsigned long mask = MASK(pinNum); + unsigned long bank = BANK(pin); + unsigned long mask = MASK(pin); switch(type) { case DETECT_RISING: @@ -133,10 +136,11 @@ void DisableGpioDetect(unsigned int pinNum, enum DETECT_TYPE type) } } -void ClearGpioInterrupt(unsigned int pinNum) +void +gpioInterruptClear (const unsigned int pin) { - unsigned long bank = BANK(pinNum); - unsigned long mask = MASK(pinNum); + unsigned long bank = BANK(pin); + unsigned long mask = MASK(pin); pRegs->GPEDS[bank] = mask; } diff --git a/Demo/Drivers/gpio.h b/Demo/Drivers/gpio.h index fa45970..767b2d2 100644 --- a/Demo/Drivers/gpio.h +++ b/Demo/Drivers/gpio.h @@ -26,23 +26,24 @@ enum GPIO_DIR { GPIO_OUT }; -/* GPIO pin setup */ -void SetGpioFunction (unsigned int pinNum, unsigned int funcNum); -/* A simple wrapper around SetGpioFunction */ -void SetGpioDirection (unsigned int pinNum, enum GPIO_DIR dir); +// GPIO pin setup: +void gpioFunctionSet (const unsigned int pin, const unsigned int func); -/* Set GPIO output level */ -void SetGpio (unsigned int pinNum, unsigned int pinVal); +// A simple wrapper around SetGpioFunction: +void gpioDirectionSet (const unsigned int pin, const enum GPIO_DIR dir); -/* Read GPIO pin level */ -int ReadGpio (unsigned int pinNum); +// Set GPIO output level: +void gpioWrite (const unsigned int pin, const unsigned int val); -/* GPIO pull up/down resistor control function (NOT YET IMPLEMENTED) */ -int PudGpio (unsigned int pinNum, enum PULL_STATE state); +// Read GPIO pin level: +unsigned int gpioRead (const unsigned int pin); -/* Interrupt related functions */ -void EnableGpioDetect (unsigned int pinNum, enum DETECT_TYPE type); -void DisableGpioDetect (unsigned int pinNum, enum DETECT_TYPE type); -void ClearGpioInterrupt (unsigned int pinNum); +// GPIO pull up/down resistor control function (NOT YET IMPLEMENTED): +int gpioPud (const unsigned int pin, const enum PULL_STATE state); + +// Interrupt related functions: +void gpioDetectEnable (const unsigned int pin, const enum DETECT_TYPE type); +void gpioDetectDisable (const unsigned int pin, const enum DETECT_TYPE type); +void gpioInterruptClear (const unsigned int pin); #endif diff --git a/Demo/main.c b/Demo/main.c index 183a259..d3b1356 100644 --- a/Demo/main.c +++ b/Demo/main.c @@ -9,7 +9,7 @@ void task1(void *pParam) { int i = 0; while(1) { i++; - SetGpio(16, 1); + gpioWrite(16, 1); vTaskDelay(200); } } @@ -20,7 +20,7 @@ void task2(void *pParam) { while(1) { i++; vTaskDelay(100); - SetGpio(16, 0); + gpioWrite(16, 0); vTaskDelay(100); } } @@ -34,7 +34,7 @@ void task2(void *pParam) { **/ void main (void) { - SetGpioFunction(16, 1); // RDY led + gpioFunctionSet(16, 1); // RDY led xTaskCreate(task1, "LED_0", 128, NULL, 0, NULL); xTaskCreate(task2, "LED_1", 128, NULL, 0, NULL); From 32b6d8b4398793ed6040b5e1a08a0d37ba0b2497 Mon Sep 17 00:00:00 2001 From: Alfred Klomp Date: Mon, 7 Mar 2016 00:04:34 +0100 Subject: [PATCH 3/8] gpio: use CamelCase for enum types, namespace properly Use the 'Gpio' prefix for public GPIO enumerates. --- Demo/Drivers/gpio.c | 40 ++++++++++++++++++++------------------- Demo/Drivers/gpio.h | 46 ++++++++++++++++++++++----------------------- 2 files changed, 44 insertions(+), 42 deletions(-) diff --git a/Demo/Drivers/gpio.c b/Demo/Drivers/gpio.c index e87f7ae..c9fb55b 100644 --- a/Demo/Drivers/gpio.c +++ b/Demo/Drivers/gpio.c @@ -52,7 +52,7 @@ gpioFunctionSet (const unsigned int pin, const unsigned int func) } void -gpioDirectionSet (const unsigned int pin, const enum GPIO_DIR dir) +gpioDirectionSet (const unsigned int pin, const enum GpioDir dir) { gpioFunctionSet(pin, dir); } @@ -77,61 +77,63 @@ gpioRead (const unsigned int pin) } void -gpioDetectEnable (const unsigned int pin, const enum DETECT_TYPE type) +gpioDetectEnable (const unsigned int pin, const enum GpioDetect type) { unsigned long bank = BANK(pin); unsigned long mask = MASK(pin); - switch(type) { - case DETECT_RISING: + switch (type) + { + case GPIO_DETECT_RISING: pRegs->GPREN[bank] |= mask; break; - case DETECT_FALLING: + case GPIO_DETECT_FALLING: pRegs->GPFEN[bank] |= mask; break; - case DETECT_HIGH: + case GPIO_DETECT_HIGH: pRegs->GPHEN[bank] |= mask; break; - case DETECT_LOW: + case GPIO_DETECT_LOW: pRegs->GPLEN[bank] |= mask; break; - case DETECT_RISING_ASYNC: + case GPIO_DETECT_RISING_ASYNC: pRegs->GPAREN[bank] |= mask; break; - case DETECT_FALLING_ASYNC: + case GPIO_DETECT_FALLING_ASYNC: pRegs->GPAFEN[bank] |= mask; break; - case DETECT_NONE: + case GPIO_DETECT_NONE: break; } } void -gpioDetectDisable (const unsigned int pin, const enum DETECT_TYPE type) +gpioDetectDisable (const unsigned int pin, const enum GpioDetect type) { unsigned long bank = BANK(pin); unsigned long mask = MASK(pin); - switch(type) { - case DETECT_RISING: + switch (type) + { + case GPIO_DETECT_RISING: pRegs->GPREN[bank] &= ~mask; break; - case DETECT_FALLING: + case GPIO_DETECT_FALLING: pRegs->GPFEN[bank] &= ~mask; break; - case DETECT_HIGH: + case GPIO_DETECT_HIGH: pRegs->GPHEN[bank] &= ~mask; break; - case DETECT_LOW: + case GPIO_DETECT_LOW: pRegs->GPLEN[bank] &= ~mask; break; - case DETECT_RISING_ASYNC: + case GPIO_DETECT_RISING_ASYNC: pRegs->GPAREN[bank] &= ~mask; break; - case DETECT_FALLING_ASYNC: + case GPIO_DETECT_FALLING_ASYNC: pRegs->GPAFEN[bank] &= ~mask; break; - case DETECT_NONE: + case GPIO_DETECT_NONE: break; } } diff --git a/Demo/Drivers/gpio.h b/Demo/Drivers/gpio.h index 767b2d2..2459c5a 100644 --- a/Demo/Drivers/gpio.h +++ b/Demo/Drivers/gpio.h @@ -1,36 +1,36 @@ #ifndef _GPIO_H_ #define _GPIO_H_ -/* GPIO event detect types */ -enum DETECT_TYPE { - DETECT_NONE, - DETECT_RISING, - DETECT_FALLING, - DETECT_HIGH, - DETECT_LOW, - DETECT_RISING_ASYNC, - DETECT_FALLING_ASYNC +// GPIO event detect types +enum GpioDetect { + GPIO_DETECT_NONE, + GPIO_DETECT_RISING, + GPIO_DETECT_FALLING, + GPIO_DETECT_HIGH, + GPIO_DETECT_LOW, + GPIO_DETECT_RISING_ASYNC, + GPIO_DETECT_FALLING_ASYNC, }; -/* GPIO pull up or down states */ -enum PULL_STATE { - PULL_DISABLE, - PULL_UP, - PULL_DOWN, - PULL_RESERVED +// GPIO pull up or down states +enum GpioPull { + GPIO_PULL_DISABLE, + GPIO_PULL_UP, + GPIO_PULL_DOWN, + GPIO_PULL_RESERVED, }; -/* Pin data direction */ -enum GPIO_DIR { - GPIO_IN, - GPIO_OUT +// Pin data direction +enum GpioDir { + GPIO_DIR_IN, + GPIO_DIR_OUT, }; // GPIO pin setup: void gpioFunctionSet (const unsigned int pin, const unsigned int func); // A simple wrapper around SetGpioFunction: -void gpioDirectionSet (const unsigned int pin, const enum GPIO_DIR dir); +void gpioDirectionSet (const unsigned int pin, const enum GpioDir dir); // Set GPIO output level: void gpioWrite (const unsigned int pin, const unsigned int val); @@ -39,11 +39,11 @@ void gpioWrite (const unsigned int pin, const unsigned int val); unsigned int gpioRead (const unsigned int pin); // GPIO pull up/down resistor control function (NOT YET IMPLEMENTED): -int gpioPud (const unsigned int pin, const enum PULL_STATE state); +int gpioPud (const unsigned int pin, const enum GpioPull state); // Interrupt related functions: -void gpioDetectEnable (const unsigned int pin, const enum DETECT_TYPE type); -void gpioDetectDisable (const unsigned int pin, const enum DETECT_TYPE type); +void gpioDetectEnable (const unsigned int pin, const enum GpioDetect type); +void gpioDetectDisable (const unsigned int pin, const enum GpioDetect type); void gpioInterruptClear (const unsigned int pin); #endif From 5fff7a246f9e0d748b1c1660a7c72d63b0df033f Mon Sep 17 00:00:00 2001 From: Alfred Klomp Date: Mon, 7 Mar 2016 00:54:35 +0100 Subject: [PATCH 4/8] gpio: detection: use data table --- Demo/Drivers/gpio.c | 113 +++++++++++++++----------------------------- Demo/Drivers/gpio.h | 1 - 2 files changed, 39 insertions(+), 75 deletions(-) diff --git a/Demo/Drivers/gpio.c b/Demo/Drivers/gpio.c index c9fb55b..a0ef7b5 100644 --- a/Demo/Drivers/gpio.c +++ b/Demo/Drivers/gpio.c @@ -8,35 +8,35 @@ #define BANK(pin) ((pin) >> 5) #define MASK(pin) (1UL << ((pin) & 0x1F)) +// Base memory location for GPIO registers: +#define GPIO_REG_BASE 0x20200000 + +// Define a GPIO register: +#define GPIO_REG(offs) ((volatile unsigned long *) (GPIO_REG_BASE + offs)) + +// Pin event detection: +#define GPREN GPIO_REG (0x004C) +#define GPFEN GPIO_REG (0x0058) +#define GPHEN GPIO_REG (0x0064) +#define GPLEN GPIO_REG (0x0070) +#define GPAREN GPIO_REG (0x007C) +#define GPAFEN GPIO_REG (0x0088) + typedef struct { - unsigned long GPFSEL[6]; ///< Function selection registers. - unsigned long Reserved_1; - unsigned long GPSET[2]; - unsigned long Reserved_2; - unsigned long GPCLR[2]; - unsigned long Reserved_3; - unsigned long GPLEV[2]; - unsigned long Reserved_4; - unsigned long GPEDS[2]; - unsigned long Reserved_5; - unsigned long GPREN[2]; - unsigned long Reserved_6; - unsigned long GPFEN[2]; - unsigned long Reserved_7; - unsigned long GPHEN[2]; - unsigned long Reserved_8; - unsigned long GPLEN[2]; - unsigned long Reserved_9; - unsigned long GPAREN[2]; - unsigned long Reserved_A; - unsigned long GPAFEN[2]; - unsigned long Reserved_B; - unsigned long GPPUD[1]; - unsigned long GPPUDCLK[2]; - //Ignoring the reserved and test bytes -} BCM2835_GPIO_REGS; - -volatile BCM2835_GPIO_REGS * const pRegs = (BCM2835_GPIO_REGS *) (0x20200000); + unsigned long GPFSEL[6]; ///< Function selection registers. + unsigned long Reserved_1; + unsigned long GPSET[2]; + unsigned long Reserved_2; + unsigned long GPCLR[2]; + unsigned long Reserved_3; + unsigned long GPLEV[2]; + unsigned long Reserved_4; + unsigned long GPEDS[2]; + unsigned long Reserved_5; +} __attribute__((packed)) +BCM2835_GPIO_REGS; + +volatile BCM2835_GPIO_REGS * const pRegs = (BCM2835_GPIO_REGS *) (GPIO_REG_BASE); void gpioFunctionSet (const unsigned int pin, const unsigned int func) @@ -76,35 +76,22 @@ gpioRead (const unsigned int pin) return ((pRegs->GPLEV[bank]) >> mask) & 1; } +static volatile unsigned long *detect_map[] = { + [GPIO_DETECT_RISING] = GPREN, + [GPIO_DETECT_FALLING] = GPFEN, + [GPIO_DETECT_HIGH] = GPHEN, + [GPIO_DETECT_LOW] = GPLEN, + [GPIO_DETECT_RISING_ASYNC] = GPAREN, + [GPIO_DETECT_FALLING_ASYNC] = GPAFEN, +}; + void gpioDetectEnable (const unsigned int pin, const enum GpioDetect type) { unsigned long bank = BANK(pin); unsigned long mask = MASK(pin); - switch (type) - { - case GPIO_DETECT_RISING: - pRegs->GPREN[bank] |= mask; - break; - case GPIO_DETECT_FALLING: - pRegs->GPFEN[bank] |= mask; - break; - case GPIO_DETECT_HIGH: - pRegs->GPHEN[bank] |= mask; - break; - case GPIO_DETECT_LOW: - pRegs->GPLEN[bank] |= mask; - break; - case GPIO_DETECT_RISING_ASYNC: - pRegs->GPAREN[bank] |= mask; - break; - case GPIO_DETECT_FALLING_ASYNC: - pRegs->GPAFEN[bank] |= mask; - break; - case GPIO_DETECT_NONE: - break; - } + detect_map[type][bank] |= mask; } void @@ -113,29 +100,7 @@ gpioDetectDisable (const unsigned int pin, const enum GpioDetect type) unsigned long bank = BANK(pin); unsigned long mask = MASK(pin); - switch (type) - { - case GPIO_DETECT_RISING: - pRegs->GPREN[bank] &= ~mask; - break; - case GPIO_DETECT_FALLING: - pRegs->GPFEN[bank] &= ~mask; - break; - case GPIO_DETECT_HIGH: - pRegs->GPHEN[bank] &= ~mask; - break; - case GPIO_DETECT_LOW: - pRegs->GPLEN[bank] &= ~mask; - break; - case GPIO_DETECT_RISING_ASYNC: - pRegs->GPAREN[bank] &= ~mask; - break; - case GPIO_DETECT_FALLING_ASYNC: - pRegs->GPAFEN[bank] &= ~mask; - break; - case GPIO_DETECT_NONE: - break; - } + detect_map[type][bank] &= ~mask; } void diff --git a/Demo/Drivers/gpio.h b/Demo/Drivers/gpio.h index 2459c5a..34b2957 100644 --- a/Demo/Drivers/gpio.h +++ b/Demo/Drivers/gpio.h @@ -3,7 +3,6 @@ // GPIO event detect types enum GpioDetect { - GPIO_DETECT_NONE, GPIO_DETECT_RISING, GPIO_DETECT_FALLING, GPIO_DETECT_HIGH, From f062a9916ce90ef6ce3c05200ca0246350e453bd Mon Sep 17 00:00:00 2001 From: Alfred Klomp Date: Mon, 7 Mar 2016 01:24:05 +0100 Subject: [PATCH 5/8] gpio: access registers through #define'd constructs --- Demo/Drivers/gpio.c | 42 ++++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/Demo/Drivers/gpio.c b/Demo/Drivers/gpio.c index a0ef7b5..a627d93 100644 --- a/Demo/Drivers/gpio.c +++ b/Demo/Drivers/gpio.c @@ -14,6 +14,19 @@ // Define a GPIO register: #define GPIO_REG(offs) ((volatile unsigned long *) (GPIO_REG_BASE + offs)) +// Function selection: +#define GPFSEL GPIO_REG (0x0000) + +// Set and clear pins: +#define GPSET GPIO_REG (0x001C) +#define GPCLR GPIO_REG (0x0028) + +// Pin level readout: +#define GPLEV GPIO_REG (0x0034) + +// Pin event detection status: +#define GPEDS GPIO_REG (0x0040) + // Pin event detection: #define GPREN GPIO_REG (0x004C) #define GPFEN GPIO_REG (0x0058) @@ -22,33 +35,18 @@ #define GPAREN GPIO_REG (0x007C) #define GPAFEN GPIO_REG (0x0088) -typedef struct { - unsigned long GPFSEL[6]; ///< Function selection registers. - unsigned long Reserved_1; - unsigned long GPSET[2]; - unsigned long Reserved_2; - unsigned long GPCLR[2]; - unsigned long Reserved_3; - unsigned long GPLEV[2]; - unsigned long Reserved_4; - unsigned long GPEDS[2]; - unsigned long Reserved_5; -} __attribute__((packed)) -BCM2835_GPIO_REGS; - -volatile BCM2835_GPIO_REGS * const pRegs = (BCM2835_GPIO_REGS *) (GPIO_REG_BASE); - void gpioFunctionSet (const unsigned int pin, const unsigned int func) { int offset = pin / 10; - unsigned long val = pRegs->GPFSEL[offset]; // Read in the original register value. + // Read in the original register value: + unsigned long val = GPFSEL[offset]; int item = pin % 10; val &= ~(0x7 << (item * 3)); val |= ((func & 0x7) << (item * 3)); - pRegs->GPFSEL[offset] = val; + GPFSEL[offset] = val; } void @@ -63,8 +61,8 @@ gpioWrite (const unsigned int pin, const unsigned int val) unsigned long bank = BANK(pin); unsigned long mask = MASK(pin); - val ? (pRegs->GPSET[bank] |= mask) - : (pRegs->GPCLR[bank] |= mask); + val ? (GPSET[bank] |= mask) + : (GPCLR[bank] |= mask); } unsigned int @@ -73,7 +71,7 @@ gpioRead (const unsigned int pin) unsigned long bank = BANK(pin); unsigned long mask = MASK(pin); - return ((pRegs->GPLEV[bank]) >> mask) & 1; + return (GPLEV[bank] & mask) ? 1 : 0; } static volatile unsigned long *detect_map[] = { @@ -109,5 +107,5 @@ gpioInterruptClear (const unsigned int pin) unsigned long bank = BANK(pin); unsigned long mask = MASK(pin); - pRegs->GPEDS[bank] = mask; + GPEDS[bank] = mask; } From f1600786769f8b32a866d2cd21a0f4c234562c84 Mon Sep 17 00:00:00 2001 From: Alfred Klomp Date: Tue, 8 Mar 2016 23:57:36 +0100 Subject: [PATCH 6/8] gpio: define all pin functions, add getter function --- Demo/Drivers/gpio.c | 31 ++++++++++++++++++++----------- Demo/Drivers/gpio.h | 22 ++++++++++++++-------- Demo/main.c | 2 +- 3 files changed, 35 insertions(+), 20 deletions(-) diff --git a/Demo/Drivers/gpio.c b/Demo/Drivers/gpio.c index a627d93..85aca99 100644 --- a/Demo/Drivers/gpio.c +++ b/Demo/Drivers/gpio.c @@ -36,23 +36,32 @@ #define GPAFEN GPIO_REG (0x0088) void -gpioFunctionSet (const unsigned int pin, const unsigned int func) +gpioFunctionSet (const unsigned int pin, const enum GpioFunc func) { - int offset = pin / 10; + unsigned long bank = pin / 10; + unsigned long item = pin % 10; + unsigned long mask = 7UL << (item * 3); - // Read in the original register value: - unsigned long val = GPFSEL[offset]; + // Get current register value: + unsigned long reg = GPFSEL[bank]; - int item = pin % 10; - val &= ~(0x7 << (item * 3)); - val |= ((func & 0x7) << (item * 3)); - GPFSEL[offset] = val; + // Mask out the bits for this pin: + reg &= ~mask; + + // Insert new bits for this pin: + reg |= (unsigned long)func << (item * 3); + + // Store back: + GPFSEL[bank] = reg; } -void -gpioDirectionSet (const unsigned int pin, const enum GpioDir dir) +enum GpioFunc +gpioFunctionGet (const unsigned int pin) { - gpioFunctionSet(pin, dir); + unsigned long bank = pin / 10; + unsigned long item = pin % 10; + + return (GPFSEL[bank] >> (item * 3)) & 7; } void diff --git a/Demo/Drivers/gpio.h b/Demo/Drivers/gpio.h index 34b2957..dc62fe2 100644 --- a/Demo/Drivers/gpio.h +++ b/Demo/Drivers/gpio.h @@ -19,17 +19,23 @@ enum GpioPull { GPIO_PULL_RESERVED, }; -// Pin data direction -enum GpioDir { - GPIO_DIR_IN, - GPIO_DIR_OUT, +// Pin functions +enum GpioFunc { + GPIO_FUNC_INPUT = 0, // Pin is input + GPIO_FUNC_OUTPUT = 1, // Pin is output + GPIO_FUNC_ALT_0 = 4, // Alternative function 0 + GPIO_FUNC_ALT_1 = 5, // Alternative function 1 + GPIO_FUNC_ALT_2 = 6, // Alternative function 2 + GPIO_FUNC_ALT_3 = 7, // Alternative function 3 + GPIO_FUNC_ALT_4 = 3, // Alternative function 4 + GPIO_FUNC_ALT_5 = 2, // Alternative function 5 }; -// GPIO pin setup: -void gpioFunctionSet (const unsigned int pin, const unsigned int func); +// Set GPIO pin function: +void gpioFunctionSet (const unsigned int pin, const enum GpioFunc func); -// A simple wrapper around SetGpioFunction: -void gpioDirectionSet (const unsigned int pin, const enum GpioDir dir); +// Get GPIO pin function: +enum GpioFunc gpioFunctionGet (const unsigned int pin); // Set GPIO output level: void gpioWrite (const unsigned int pin, const unsigned int val); diff --git a/Demo/main.c b/Demo/main.c index d3b1356..a13c8b2 100644 --- a/Demo/main.c +++ b/Demo/main.c @@ -34,7 +34,7 @@ void task2(void *pParam) { **/ void main (void) { - gpioFunctionSet(16, 1); // RDY led + gpioFunctionSet(16, GPIO_FUNC_OUTPUT); // RDY led xTaskCreate(task1, "LED_0", 128, NULL, 0, NULL); xTaskCreate(task2, "LED_1", 128, NULL, 0, NULL); From e713318cb27bf117b34d055782746e73ef98567e Mon Sep 17 00:00:00 2001 From: Alfred Klomp Date: Wed, 9 Mar 2016 22:15:21 +0100 Subject: [PATCH 7/8] gpio: rewrite event detection function Return 0 if no event was detected, or 1 if one was. Reset the event bit to restart the detection. --- Demo/Drivers/gpio.c | 14 +++++++++++--- Demo/Drivers/gpio.h | 8 ++++---- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/Demo/Drivers/gpio.c b/Demo/Drivers/gpio.c index 85aca99..cbca4d0 100644 --- a/Demo/Drivers/gpio.c +++ b/Demo/Drivers/gpio.c @@ -110,11 +110,19 @@ gpioDetectDisable (const unsigned int pin, const enum GpioDetect type) detect_map[type][bank] &= ~mask; } -void -gpioInterruptClear (const unsigned int pin) +unsigned int +gpioDetected (const unsigned int pin) { unsigned long bank = BANK(pin); unsigned long mask = MASK(pin); - GPEDS[bank] = mask; + // No event if bit not set: + if (!(GPEDS[bank] & mask)) + return 0; + + // Clear event by setting bit to 1: + GPEDS[bank] |= mask; + + // Confirm event: + return 1; } diff --git a/Demo/Drivers/gpio.h b/Demo/Drivers/gpio.h index dc62fe2..b906d29 100644 --- a/Demo/Drivers/gpio.h +++ b/Demo/Drivers/gpio.h @@ -46,9 +46,9 @@ unsigned int gpioRead (const unsigned int pin); // GPIO pull up/down resistor control function (NOT YET IMPLEMENTED): int gpioPud (const unsigned int pin, const enum GpioPull state); -// Interrupt related functions: -void gpioDetectEnable (const unsigned int pin, const enum GpioDetect type); -void gpioDetectDisable (const unsigned int pin, const enum GpioDetect type); -void gpioInterruptClear (const unsigned int pin); +// Event detection functions: +void gpioDetectEnable (const unsigned int pin, const enum GpioDetect type); +void gpioDetectDisable (const unsigned int pin, const enum GpioDetect type); +unsigned int gpioDetected (const unsigned int pin); #endif From 6d282cdc1141fbfcbeb5bef3bf0debea453defdc Mon Sep 17 00:00:00 2001 From: Alfred Klomp Date: Sun, 13 Mar 2016 20:09:23 +0100 Subject: [PATCH 8/8] gpio: implement gpioPull() for pull-up/down/none --- Demo/Drivers/gpio.c | 46 +++++++++++++++++++++++++++++++++++++++++++++ Demo/Drivers/gpio.h | 12 ++++++------ 2 files changed, 52 insertions(+), 6 deletions(-) diff --git a/Demo/Drivers/gpio.c b/Demo/Drivers/gpio.c index cbca4d0..15cec85 100644 --- a/Demo/Drivers/gpio.c +++ b/Demo/Drivers/gpio.c @@ -35,6 +35,10 @@ #define GPAREN GPIO_REG (0x007C) #define GPAFEN GPIO_REG (0x0088) +// Pull up/down/none: +#define GPPUD GPIO_REG (0x0094) +#define GPPUDCLK GPIO_REG (0x0098) + void gpioFunctionSet (const unsigned int pin, const enum GpioFunc func) { @@ -126,3 +130,45 @@ gpioDetected (const unsigned int pin) // Confirm event: return 1; } + +static inline void +wait (unsigned long cycles) +{ + // Each loop iteration takes three instructions: + cycles /= 3; + + // Busy-wait by decrementing the cycle counter until it reaches zero: + asm volatile ( + "1: sub %0, %0, #1 \n\t" + " cmp %0, #0 \n\t" + " bne 1b \n\t" + : + : "r" (cycles) + : "cc" + ); +} + +void +gpioPull (const unsigned int pin, const enum GpioPull type) +{ + unsigned long bank = BANK(pin); + unsigned long mask = MASK(pin); + + // Setup direction register: + *GPPUD = type; + + // Wait 150 cycles to set up the control signal: + wait(150); + + // Activate clock signal for this pin: + GPPUDCLK[bank] |= mask; + + // Wait 150 cycles to hold the control signal: + wait(150); + + // Remove control signal: + *GPPUD = 0; + + // Remove clock signal: + GPPUDCLK[bank] = 0; +} diff --git a/Demo/Drivers/gpio.h b/Demo/Drivers/gpio.h index b906d29..c10c44e 100644 --- a/Demo/Drivers/gpio.h +++ b/Demo/Drivers/gpio.h @@ -13,10 +13,10 @@ enum GpioDetect { // GPIO pull up or down states enum GpioPull { - GPIO_PULL_DISABLE, - GPIO_PULL_UP, - GPIO_PULL_DOWN, - GPIO_PULL_RESERVED, + GPIO_PULL_DISABLE = 0, + GPIO_PULL_DOWN = 1, + GPIO_PULL_UP = 2, + GPIO_PULL_RESERVED = 3, }; // Pin functions @@ -43,8 +43,8 @@ void gpioWrite (const unsigned int pin, const unsigned int val); // Read GPIO pin level: unsigned int gpioRead (const unsigned int pin); -// GPIO pull up/down resistor control function (NOT YET IMPLEMENTED): -int gpioPud (const unsigned int pin, const enum GpioPull state); +// GPIO pull-up/down/none: +void gpioPull (const unsigned int pin, const enum GpioPull type); // Event detection functions: void gpioDetectEnable (const unsigned int pin, const enum GpioDetect type);