Skip to content

Commit

Permalink
s gpio: added some more doc + simplifications
Browse files Browse the repository at this point in the history
  • Loading branch information
haukepetersen committed Feb 19, 2016
1 parent 4cf040b commit 7aff094
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 27 deletions.
1 change: 1 addition & 0 deletions cpu/kinetis_common/include/periph_cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ enum {
PORT_E = 4, /**< port E */
PORT_F = 5, /**< port F */
PORT_G = 6, /**< port G */
GPIO_PORTS_NUMOF /**< overall number of available ports */
};

/**
Expand Down
83 changes: 56 additions & 27 deletions cpu/kinetis_common/periph/gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,54 +29,69 @@
#include "cpu.h"
#include "periph/gpio.h"

#define PORT_SHIFT (12)
/**
* @brief Shifting a gpio_t value by this number of bit we can extract the
* port number from the GPIO base address
*/
#define GPIO_SHIFT (6)

/**
* @brief Mask used to extract the PORT base address from the gpio_t value
*/
#define PORT_ADDR_MASK (0x00007000)

/**
* @brief Mask used to extract the GPIO base address from the gpio_t value
*/
#define GPIO_ADDR_MASK (0x000001c0)

/**
* @brief Cleaned up PORT base address
*/
#define PORT_ADDR_BASE (PORTA_BASE & ~(PORT_ADDR_MASK))

/**
* @brief Cleaned up GPIO base address
*/
#define GPIO_ADDR_BASE (GPIOA_BASE & ~(GPIO_ADDR_MASK))

#define GPIO_PORTS_NUMOF (7)
/**
* @brief Kinetis CPUs have 32 pins per port
*/
#define PINS_PER_PORT (32)

/**
* @brief Calculate the needed memory (in byte) needed to save 4 bits per MCU
* pin
*/
#define ISR_MAP_SIZE (GPIO_PORTS_NUMOF * PINS_PER_PORT * 4 / 8)

/**
* @brief We allow for 7 (4-bit - 1) concurrent external interrupts to be set
* @brief Define the number of simultaneously configurable interrupt channels
*
* We have configured 4-bits per pin, so we can go up to 16 simultaneous active
* extern interrupt sources.
*/
#define CTX_NUMOF (7U)
#define CTX_NUMOF (8U)

/**
* @brief Interrupt context data
*/
typedef struct {
gpio_cb_t cb;
void *arg;
uint32_t state;
} isr_ctx_t;

/**
* @brief Allocation of memory for 7 independent interrupt slots
* @brief Allocation of memory for each independent interrupt slot
*/
static isr_ctx_t isr_ctx[CTX_NUMOF] = {{0}};

/**
* @brief Allocation of 4 bit per pin to map a pin to an interrupt context
* @brief Allocation of 4 bit per pin to map a pin to an interrupt context
*/
static uint32_t isr_map[] = {
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
#if GPIO_PORTS_NUMOF > 4
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
#endif
#if GPIO_PORTS_NUMOF > 5
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
#endif
#if GPIO_PORTS_NUMOF > 6
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
#endif
#if GPIO_PORTS_NUMOF > 7
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff
#endif
};
static uint32_t isr_map[ISR_MAP_SIZE];


static inline PORT_Type *port(gpio_t pin)
Expand Down Expand Up @@ -105,7 +120,7 @@ static inline void clk_en(gpio_t pin)
}

/**
* @brief Get context for a specific pin
* @brief Get context for a specific pin
*/
static inline int get_ctx(int port, int pin)
{
Expand All @@ -126,20 +141,34 @@ static int get_free_ctx(void)
}

/**
* @brief Write an entry to the context map array
* @brief Write an entry to the context map array
*/
static void write_map(int port, int pin, int ctx)
{
isr_map[(port * 4) + (pin >> 3)] &= ~(0xf << ((pin & 0x7) * 4));
isr_map[(port * 4) + (pin >> 3)] |= (ctx << ((pin & 0x7) * 4));
}

/**
* @brief Clear the context for the given pin
*/
static void ctx_clear(int port, int pin)
{
int ctx = get_ctx(port, pin);
write_map(port, pin, ctx);
}

int gpio_init(gpio_t pin, gpio_dir_t dir, gpio_pp_t pullup)
{
/* enable port clock */
clk_en(pin);
/* configure the port, set to analog mode while doing this to be safe */
/* configure the port, disable interrupt and set to analog mode while doing
* this to be safe, also clear the pin's ISR context */
uint32_t isr_state = port(pin)->PCR[pin_num(pin)];
port(pin)->PCR[pin_num(pin)] = GPIO_AF_ANALOG;
if (isr_state & PORT_PCR_IRQC_MASK) {
ctx_clear(port_num(pin), pin_num(pin));
}
/* set pin direction */
gpio(pin)->PDDR &= ~(1 << pin_num(pin));
gpio(pin)->PDDR |= (dir << pin_num(pin));
Expand Down

0 comments on commit 7aff094

Please sign in to comment.