Skip to content
Snippets Groups Projects
Commit e819fc9a authored by cpq's avatar cpq
Browse files

Enhance GPIO interface

parent 4b450599
No related branches found
No related tags found
No related merge requests found
#include <sdk.h> #include <sdk.h>
static int led_pin = 2; static int led_pin = LED1; // To override: make CFLAGS_EXTRA=-DLED1=5
int main(void) { int main(void) {
wdt_disable(); wdt_disable();
......
SOURCES = main.c
include ../../make/project.mk
#include <sdk.h>
static int led = 2, pin = 4;
int main(void) {
wdt_disable();
gpio_output(led);
gpio_input(pin);
for (;;) {
sdk_log("in: %d\n", gpio_read(pin));
gpio_toggle(led);
spin(2999999);
}
return 0;
}
#define GPIO_FUNC_OUT_SEL REG(0X3ff44530) #define GPIO_FUNC_OUT_SEL_CFG_REG REG(0X3ff44530) // Pins 0-39
#define GPIO_OUT_REG REG(0X3ff44004) #define GPIO_FUNC_IN_SEL_CFG_REG REG(0X3ff44130) // Pins 0-39
#define GPIO_ENABLE_REG REG(0X3ff44020) #define GPIO_OUT_REG REG(0X3ff44004) // Pins 0-31
#define GPIO_IN_REG REG(0x3FF4403C) // Pins 0-31
#define GPIO_ENABLE_REG REG(0X3ff44020) // Pins 0-31
#define GPIO_OUT1_REG REG(0X3ff44010) // Pins 32-39
#define GPIO_IN1_REG REG(0X3ff44040) // Pins 32-39
#define GPIO_ENABLE1_REG REG(0X3ff4402c) // Pins 32-39
static inline void gpio_output_enable(int pin, int enable) {
volatile unsigned long *r = GPIO_ENABLE_REG;
if (pin > 31) pin -= 31, r = GPIO_ENABLE1_REG;
r[0] &= ~BIT(pin);
r[0] |= (enable ? 1U : 0U) << pin;
}
static inline void gpio_output(int pin) { static inline void gpio_output(int pin) {
GPIO_FUNC_OUT_SEL[pin] = 256; // Configure GPIO as a simple output GPIO_FUNC_OUT_SEL_CFG_REG[pin] = 256; // Simple output, TRM 4.3.3
GPIO_ENABLE_REG[0] |= BIT(pin); // Enable pin. See TRM 4.3.3 gpio_output_enable(pin, 1);
}
static inline void gpio_write(int pin, int value) {
volatile unsigned long *r = GPIO_OUT_REG;
if (pin > 31) pin -= 31, r = GPIO_OUT1_REG;
r[0] &= ~BIT(pin); // Clear first
r[0] |= (value ? 1U : 0U) << pin; // Then set
} }
static inline void gpio_toggle(int pin) { static inline void gpio_toggle(int pin) {
GPIO_OUT_REG[0] ^= BIT(pin); volatile unsigned long *r = GPIO_OUT_REG;
if (pin > 31) pin -= 31, r = GPIO_OUT1_REG;
r[0] ^= BIT(pin);
}
static inline void gpio_input(int pin) {
// Index lookup table for IO_MUX_GPIOx_REG, TRM 4.12
unsigned char map[40] = {17, 34, 16, 33, 18, 27, 24, 25, 26, 21, // 0-9
22, 23, 13, 14, 12, 15, 19, 20, 28, 29, // 10-19
30, 31, 32, 35, 36, 9, 10, 11, 0, 0, // 20-29
0, 0, 7, 8, 5, 6, 1, 2, 3, 4}; // 30-39
volatile unsigned long *mux = REG(0X3ff49000);
if (pin < 0 || pin > (int) sizeof(map) || map[pin] == 0) return;
gpio_output_enable(pin, 0); // Disable output
mux[pin] |= BIT(9); // Enable input
}
static inline int gpio_read(int pin) {
volatile unsigned long *r = GPIO_IN_REG;
if (pin > 31) pin -= 31, r = GPIO_IN1_REG;
return r[0] & BIT(pin) ? 1 : 0;
} }
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#pragma once #pragma once
#include <assert.h> #include <assert.h>
#include <errno.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
...@@ -11,7 +12,12 @@ ...@@ -11,7 +12,12 @@
#define BIT(x) (1UL << (x)) #define BIT(x) (1UL << (x))
#define REG(x) ((volatile unsigned long *) (x)) #define REG(x) ((volatile unsigned long *) (x))
#ifndef LED1
#define LED1 2 // Default LED pin
#endif
#include "gpio.h" #include "gpio.h"
#include "spi.h"
#include "wdt.h" #include "wdt.h"
static inline void spin(volatile unsigned long count) { static inline void spin(volatile unsigned long count) {
......
struct spi {
int miso, mosi, clk, freq;
};
int spi_init(struct spi *spi);
int spi_txn(struct spi *spi);
...@@ -6,6 +6,16 @@ PORT ?= /dev/ttyUSB0 ...@@ -6,6 +6,16 @@ PORT ?= /dev/ttyUSB0
ESPTOOL ?= esptool.py ESPTOOL ?= esptool.py
TOOLCHAIN ?= xtensa-esp32-elf TOOLCHAIN ?= xtensa-esp32-elf
# -g3 pulls enums and defines into the debug info for GDB
# -ffunction-sections -fdata-sections, -Wl,--gc-sections remove unused code
# strict WARNFLAGS protect from stupid mistakes
INCLUDES ?= -I. -I$(ROOT_PATH)/include
WARNFLAGS ?= -W -Wall -Wextra -Werror -Wundef -Wshadow -Wdouble-promotion -fno-common -Wconversion
OPTFLAGS ?= -Os -g3 -ffunction-sections -fdata-sections
CFLAGS ?= $(WARNFLAGS) $(OPTFLAGS) $(MCUFLAGS) $(INCLUDES) $(CFLAGS_EXTRA)
LINKFLAGS ?= $(MCUFLAGS) -T$(ROOT_PATH)/ld/$(ARCH).ld --gc-sections
ifeq "$(ARCH)" "c3" ifeq "$(ARCH)" "c3"
MCUFLAGS += -march=rv32imc -mabi=ilp32 MCUFLAGS += -march=rv32imc -mabi=ilp32
WARNFLAGS += -Wformat-truncation WARNFLAGS += -Wformat-truncation
...@@ -13,16 +23,6 @@ else ...@@ -13,16 +23,6 @@ else
CFLAGS += -mlongcalls -mtext-section-literals CFLAGS += -mlongcalls -mtext-section-literals
endif endif
# -g3 pulls enums and defines into the debug info for GDB
# -ffunction-sections -fdata-sections, -Wl,--gc-sections remove unused code
# strict WARNFLAGS protect from stupid mistakes
INCLUDES += -I. -I$(ROOT_PATH)/include
WARNFLAGS += -W -Wall -Wextra -Werror -Wundef -Wshadow -Wdouble-promotion -fno-common -Wconversion
OPTFLAGS += -Os -g3 -ffunction-sections -fdata-sections
CFLAGS += $(WARNFLAGS) $(OPTFLAGS) $(MCUFLAGS) $(INCLUDES)
LINKFLAGS += $(MCUFLAGS) -T$(ROOT_PATH)/ld/$(ARCH).ld --gc-sections
SOURCES += $(wildcard $(ROOT_PATH)/src/*.c) SOURCES += $(wildcard $(ROOT_PATH)/src/*.c)
OBJECTS = $(SOURCES:%.c=$(OBJ_PATH)/%.o) $(OBJ_PATH)/boot.o OBJECTS = $(SOURCES:%.c=$(OBJ_PATH)/%.o) $(OBJ_PATH)/boot.o
......
...@@ -34,8 +34,8 @@ void *sbrk(int diff) { ...@@ -34,8 +34,8 @@ void *sbrk(int diff) {
} }
void __assert_func(const char *a, int b, const char *c, const char *d) { void __assert_func(const char *a, int b, const char *c, const char *d) {
gpio_output(2); gpio_output(LED1);
for (;;) spin(199999), gpio_toggle(2); for (;;) spin(199999), gpio_toggle(LED1);
(void) a; (void) a;
(void) b; (void) b;
(void) c; (void) c;
......
// Copyright (c) 2021 Cesanta
// All rights reserved
#include <sdk.h>
int spi_init(struct spi *spi) {
(void) spi;
return 0;
}
int spi_txn(struct spi *spi) {
(void) spi;
return 0;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment