Api hw gpio pwm (#199)

* initial gpio layer

* move temlplate.c to template.c.example in preparing to applications.mk rework

* separate arduino layer

* separate flipper_hal.x

* prepare to switch applications on v2 core gpio api

* swithch applications to v2 gpio api

* gpio api for local target

* better gpio_disable handling

* remove pwm functions from local target

* inline gpio funcs

* common function to init all api's

* fix local example blink

* move delay us to hal api folder

* move pwm_set/pwm_stop to hal api folder

* update applications to use hal pwm api

* remove gpio mode case warning

* add speaker demo to build

Co-authored-by: DrZlo13 <who.just.the.doctor@gmail.com>
This commit is contained in:
coreglitch
2020-10-26 13:16:54 +06:00
committed by GitHub
parent c8cc3c7dc8
commit f5b342abbe
41 changed files with 464 additions and 341 deletions

View File

@@ -1,98 +0,0 @@
/*
Flipper devices inc.
GPIO and HAL implementations
*/
#pragma once
#include <stdbool.h>
#include "main.h"
typedef enum { GpioModeInput, GpioModeOutput, GpioModeOpenDrain } GpioMode;
typedef struct {
GPIO_TypeDef* port;
uint32_t pin;
} GpioPin;
void app_gpio_init(GpioPin gpio, GpioMode mode);
static inline void app_gpio_write(GpioPin gpio, bool state) {
if(gpio.pin != 0) {
if(state) {
gpio.port->BSRR = (uint32_t)gpio.pin;
} else {
gpio.port->BRR = (uint32_t)gpio.pin;
}
}
}
static inline bool app_gpio_read(GpioPin gpio) {
if(gpio.pin != 0) {
return (gpio.port->IDR & gpio.pin) != 0x00u;
}
return false;
}
void delay_us_init_DWT(void);
void delay_us(float time);
void pwm_set(float value, float freq, TIM_HandleTypeDef* tim, uint32_t channel);
void pwm_stop(TIM_HandleTypeDef* tim, uint32_t channel);
extern TIM_HandleTypeDef htim8;
static inline void app_tim_ic_init(bool both) {
HAL_TIM_OC_Stop(&htim8, TIM_CHANNEL_2);
TIM_IC_InitTypeDef sConfigIC = {0};
sConfigIC.ICPolarity = both ? TIM_INPUTCHANNELPOLARITY_BOTHEDGE :
TIM_INPUTCHANNELPOLARITY_FALLING;
sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
sConfigIC.ICFilter = 0;
HAL_TIM_IC_ConfigChannel(&htim8, &sConfigIC, TIM_CHANNEL_2);
HAL_TIM_IC_Start_IT(&htim8, TIM_CHANNEL_2);
}
static inline void app_tim_pulse(uint32_t width) {
htim8.State = HAL_TIM_STATE_BUSY;
__HAL_TIM_DISABLE(&htim8);
__HAL_TIM_SET_COUNTER(&htim8, 0);
TIM_OC_InitTypeDef sConfigOC;
sConfigOC.OCMode = TIM_OCMODE_INACTIVE;
sConfigOC.Pulse = (uint16_t)(width);
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
// HAL_TIM_OC_ConfigChannel(&htim8, &sConfigOC, TIM_CHANNEL_2);
htim8.Lock = HAL_LOCKED;
/* Configure the TIM Channel 2 in Output Compare */
TIM_OC2_SetConfig(htim8.Instance, &sConfigOC);
htim8.Lock = HAL_UNLOCKED;
// TIM_CCxChannelCmd(htim8.Instance, TIM_CHANNEL_2, TIM_CCx_ENABLE);
/* Reset the CCxE Bit */
htim8.Instance->CCER &= ~(TIM_CCER_CC1E << (TIM_CHANNEL_2 & 0x1FU));
/* Set or reset the CCxE Bit */
htim8.Instance->CCER |= (uint32_t)(TIM_CCx_ENABLE << (TIM_CHANNEL_2 & 0x1FU));
__HAL_TIM_MOE_ENABLE(&htim8);
__HAL_TIM_ENABLE(&htim8);
htim8.State = HAL_TIM_STATE_READY;
}
static inline void app_tim_stop() {
HAL_TIM_OC_Stop(&htim8, TIM_CHANNEL_2);
HAL_TIM_IC_Stop(&htim8, TIM_CHANNEL_2);
}

View File

@@ -2,7 +2,7 @@
#define __INPUT_PRIV_H
#include "main.h"
#include "flipper_hal.h"
#include "flipper_v2.h"
#define DEBOUNCE_TICKS 10

View File

@@ -1,69 +0,0 @@
/*
Flipper devices inc.
GPIO and HAL implementations
*/
#include "main.h"
#include "flipper_hal.h"
void app_gpio_init(GpioPin gpio, GpioMode mode) {
if(gpio.pin != 0) {
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.Pin = gpio.pin;
GPIO_InitStruct.Pull = GPIO_NOPULL;
switch(mode) {
case GpioModeInput:
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
break;
case GpioModeOutput:
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
break;
case GpioModeOpenDrain:
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
break;
}
HAL_GPIO_Init(gpio.port, &GPIO_InitStruct);
}
}
void delay_us_init_DWT(void) {
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
DWT->CYCCNT = 0U;
}
void delay_us(float time) {
uint32_t start = DWT->CYCCNT;
uint32_t time_ticks = time * (SystemCoreClock / 1000000);
while((DWT->CYCCNT - start) < time_ticks) {
};
}
void pwm_set(float value, float freq, TIM_HandleTypeDef* tim, uint32_t channel) {
tim->Init.CounterMode = TIM_COUNTERMODE_UP;
tim->Init.Period = (uint32_t)((SystemCoreClock / (tim->Init.Prescaler + 1)) / freq);
tim->Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
tim->Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
HAL_TIM_PWM_Init(tim);
TIM_OC_InitTypeDef sConfigOC;
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = (uint16_t)(tim->Init.Period * value);
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
HAL_TIM_PWM_ConfigChannel(tim, &sConfigOC, channel);
HAL_TIM_PWM_Start(tim, channel);
}
void pwm_stop(TIM_HandleTypeDef* tim, uint32_t channel) {
HAL_TIM_PWM_Stop(tim, channel);
}

View File

@@ -31,7 +31,7 @@
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "fatfs/fatfs.h"
#include "flipper_hal.h"
#include "api-hal.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/

View File

@@ -0,0 +1,14 @@
#include "api-hal-delay.h"
void delay_us_init_DWT(void) {
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
DWT->CYCCNT = 0U;
}
void delay_us(float time) {
uint32_t start = DWT->CYCCNT;
uint32_t time_ticks = time * (SystemCoreClock / 1000000);
while((DWT->CYCCNT - start) < time_ticks) {
};
}

View File

@@ -0,0 +1,5 @@
#pragma once
#include "main.h"
void delay_us(float time);
void delay_us_init_DWT(void);

View File

@@ -0,0 +1,14 @@
#include "api-hal-gpio.h"
// init GPIO
void hal_gpio_init(GpioPin* gpio, GpioMode mode, GpioPull pull, GpioSpeed speed) {
// TODO: Alternate Functions
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = gpio->pin;
GPIO_InitStruct.Mode = mode;
GPIO_InitStruct.Pull = pull;
GPIO_InitStruct.Speed = speed;
HAL_GPIO_Init(gpio->port, &GPIO_InitStruct);
}

View File

@@ -0,0 +1,61 @@
#pragma once
#include "main.h"
#include "stdbool.h"
// this defined in xx_hal_gpio.c, so...
#define GPIO_NUMBER (16U)
typedef enum {
GpioModeInput = GPIO_MODE_INPUT,
GpioModeOutputPushPull = GPIO_MODE_OUTPUT_PP,
GpioModeOutputOpenDrain = GPIO_MODE_OUTPUT_OD,
GpioModeAltFunctionPushPull = GPIO_MODE_AF_PP,
GpioModeAltFunctionOpenDrain = GPIO_MODE_AF_OD,
GpioModeAnalog = GPIO_MODE_ANALOG,
GpioModeInterruptRise = GPIO_MODE_IT_RISING,
GpioModeInterruptFall = GPIO_MODE_IT_FALLING,
GpioModeInterruptRiseFall = GPIO_MODE_IT_RISING_FALLING,
GpioModeEventRise = GPIO_MODE_EVT_RISING,
GpioModeEventFall = GPIO_MODE_EVT_FALLING,
GpioModeEventRiseFall = GPIO_MODE_EVT_RISING_FALLING,
} GpioMode;
typedef enum {
GpioSpeedLow = GPIO_SPEED_FREQ_LOW,
GpioSpeedMedium = GPIO_SPEED_FREQ_MEDIUM,
GpioSpeedHigh = GPIO_SPEED_FREQ_HIGH,
GpioSpeedVeryHigh = GPIO_SPEED_FREQ_VERY_HIGH,
} GpioSpeed;
typedef enum {
GpioPullNo = GPIO_NOPULL,
GpioPullUp = GPIO_PULLUP,
GpioPullDown = GPIO_PULLDOWN,
} GpioPull;
typedef struct {
GPIO_TypeDef* port;
uint16_t pin;
} GpioPin;
// init GPIO
void hal_gpio_init(GpioPin* gpio, GpioMode mode, GpioPull pull, GpioSpeed speed);
// write value to GPIO, false = LOW, true = HIGH
static inline void hal_gpio_write(GpioPin* gpio, bool state) {
// writing to BSSR is an atomic operation
if(state == true) {
gpio->port->BSRR = gpio->pin;
} else {
gpio->port->BSRR = (uint32_t)gpio->pin << GPIO_NUMBER;
}
}
// read value from GPIO, false = LOW, true = HIGH
static inline bool hal_gpio_read(GpioPin* gpio) {
if((gpio->port->IDR & gpio->pin) != 0x00U) {
return true;
} else {
return false;
}
}

View File

@@ -0,0 +1,22 @@
#include "api-hal-pwm.h"
void hal_pwm_set(float value, float freq, TIM_HandleTypeDef* tim, uint32_t channel) {
tim->Init.CounterMode = TIM_COUNTERMODE_UP;
tim->Init.Period = (uint32_t)((SystemCoreClock / (tim->Init.Prescaler + 1)) / freq);
tim->Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
tim->Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
HAL_TIM_PWM_Init(tim);
TIM_OC_InitTypeDef sConfigOC;
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = (uint16_t)(tim->Init.Period * value);
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
HAL_TIM_PWM_ConfigChannel(tim, &sConfigOC, channel);
HAL_TIM_PWM_Start(tim, channel);
}
void hal_pwm_stop(TIM_HandleTypeDef* tim, uint32_t channel) {
HAL_TIM_PWM_Stop(tim, channel);
}

View File

@@ -0,0 +1,6 @@
#pragma once
#include "main.h"
#include "stdbool.h"
void hal_pwm_set(float value, float freq, TIM_HandleTypeDef* tim, uint32_t channel);
void hal_pwm_stop(TIM_HandleTypeDef* tim, uint32_t channel);

View File

@@ -0,0 +1,5 @@
#pragma once
#include "api-hal-gpio.h"
#include "api-hal-delay.h"
#include "api-hal-pwm.h"

View File

@@ -64,7 +64,8 @@ C_SOURCES += \
$(CUBE_DIR)/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ioreq.c \
$(CUBE_DIR)/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c \
$(wildcard $(TARGET_DIR)/Src/*.c) \
$(wildcard $(TARGET_DIR)/Src/fatfs/*.c)
$(wildcard $(TARGET_DIR)/Src/fatfs/*.c) \
$(wildcard $(TARGET_DIR)/api-hal/*.c)
ASM_SOURCES += $(TARGET_DIR)/startup_stm32l476xx.s
@@ -93,5 +94,6 @@ CFLAGS += \
-I$(CUBE_DIR)/Drivers/CMSIS/Device/ST/STM32L4xx/Include \
-I$(CUBE_DIR)/Drivers/CMSIS/Include \
-I$(CUBE_DIR)/Drivers/CMSIS/Include \
-I$(TARGET_DIR)/Src/fatfs
-I$(TARGET_DIR)/Src/fatfs \
-I$(TARGET_DIR)/api-hal

View File

@@ -10,56 +10,6 @@ GPIO and HAL implementations
#include <stdbool.h>
#include "main.h"
typedef enum { GpioModeInput, GpioModeOutput, GpioModeOpenDrain } GpioMode;
typedef struct {
const char* port;
uint32_t pin;
GpioMode mode;
} GpioPin;
void app_gpio_init(GpioPin gpio, GpioMode mode);
static inline void app_gpio_write(GpioPin gpio, bool state) {
if(gpio.pin != 0) {
if(state) {
printf("[GPIO] %s%d on\n", gpio.port, gpio.pin);
} else {
printf("[GPIO] %s%d off\n", gpio.port, gpio.pin);
}
} else {
printf("[GPIO] no pin\n");
}
}
static inline bool app_gpio_read(GpioPin gpio) {
// TODO emulate pin state?
return false;
}
typedef enum { GPIO_PIN_SET = 1, GPIO_PIN_RESET = 0 } HAL_GPIO_PIN_STATE;
void HAL_GPIO_WritePin(const char* port, uint32_t pin, HAL_GPIO_PIN_STATE state);
void delay_us(uint32_t time);
void pwm_set(float value, float freq, TIM_HandleTypeDef* tim, uint32_t channel);
extern TIM_HandleTypeDef htim8;
static inline void app_tim_ic_init(bool both) {
printf("[TIM] init\n");
}
static inline void app_tim_pulse(uint32_t width) {
printf("[TIM] pulse %d\n", width);
}
static inline void app_tim_stop() {
printf("[TIM] stop\n");
}
#define GPIOA "PA"
#define GPIOB "PB"
#define GPIOC "PC"

View File

@@ -8,41 +8,6 @@ GPIO and HAL implementations
#include "flipper_hal.h"
#include <stdio.h>
void app_gpio_init(GpioPin gpio, GpioMode mode) {
if(gpio.pin != 0) {
switch(mode) {
case GpioModeInput:
printf("[GPIO] %s%d input\n", gpio.port, gpio.pin);
break;
case GpioModeOutput:
printf("[GPIO] %s%d push pull\n", gpio.port, gpio.pin);
break;
case GpioModeOpenDrain:
printf("[GPIO] %s%d open drain\n", gpio.port, gpio.pin);
break;
}
gpio.mode = mode;
} else {
printf("[GPIO] no pin\n");
}
}
void delay_us(uint32_t time) {
// How to deal with it
printf("[DELAY] %d us\n", time);
}
void pwm_set(float value, float freq, TIM_HandleTypeDef* tim, uint32_t channel) {
printf("[TIM] set pwm %d:%d %f Hz, %f%%\n", *tim, channel, freq, value * 100.);
}
void HAL_GPIO_WritePin(const char* port, uint32_t pin, HAL_GPIO_PIN_STATE state) {
printf("[GPIO] set pin %s:%d = %d\n", port, pin, state);
}
HAL_StatusTypeDef
HAL_SPI_Transmit(SPI_HandleTypeDef* hspi, uint8_t* pData, uint16_t size, uint32_t Timeout) {
printf("[SPI] write %d to %s: ", size, *hspi);

View File

@@ -0,0 +1,7 @@
#include "api-hal-delay.h"
#include <stdio.h>
void delay_us(uint32_t time) {
// How to deal with it
printf("[DELAY] %d us\n", time);
}

View File

@@ -0,0 +1,4 @@
#pragma once
#include "main.h"
void delay_us(uint32_t time);

View File

@@ -0,0 +1,47 @@
#include "api-hal-gpio.h"
#include <stdio.h>
// init GPIO
void hal_gpio_init(GpioPin* gpio, GpioMode mode, GpioPull pull, GpioSpeed speed){
// TODO more mode
if(gpio->pin != 0) {
switch(mode) {
case GpioModeInput:
printf("[GPIO] %s%d input\n", gpio->port, gpio->pin);
break;
case GpioModeOutputPushPull:
printf("[GPIO] %s%d push pull\n", gpio->port, gpio->pin);
break;
case GpioModeOutputOpenDrain:
printf("[GPIO] %s%d open drain\n", gpio->port, gpio->pin);
break;
default:
printf("[GPIO] %s%d mode %d unsupported\n", gpio->port, gpio->pin, mode);
break;
}
} else {
printf("[GPIO] no pin\n");
}
}
// write value to GPIO, false = LOW, true = HIGH
void hal_gpio_write(GpioPin* gpio, bool state){
if(gpio->pin != 0) {
if(state) {
printf("[GPIO] %s%d on\n", gpio->port, gpio->pin);
} else {
printf("[GPIO] %s%d off\n", gpio->port, gpio->pin);
}
} else {
printf("[GPIO] no pin\n");
}
}
// read value from GPIO, false = LOW, true = HIGH
bool hal_gpio_read(GpioPin* gpio){
// TODO emulate pin state?
return false;
}

View File

@@ -0,0 +1,49 @@
#pragma once
#include "main.h"
#include "stdbool.h"
// hw-api
typedef char GPIO_TypeDef;
typedef enum {
GpioModeInput,
GpioModeOutputPushPull,
GpioModeOutputOpenDrain,
GpioModeAltFunctionPushPull,
GpioModeAltFunctionOpenDrain,
GpioModeAnalog,
GpioModeInterruptRise,
GpioModeInterruptFall,
GpioModeInterruptRiseFall,
GpioModeEventRise,
GpioModeEventFall,
GpioModeEventRiseFall,
} GpioMode;
typedef enum {
GpioSpeedLow,
GpioSpeedMedium,
GpioSpeedHigh,
GpioSpeedVeryHigh,
} GpioSpeed;
typedef enum {
GpioPullNo,
GpioPullUp,
GpioPullDown,
} GpioPull;
typedef struct {
GPIO_TypeDef* port;
uint16_t pin;
} GpioPin;
// init GPIO
void hal_gpio_init(GpioPin* gpio, GpioMode mode, GpioPull pull, GpioSpeed speed);
// write value to GPIO, false = LOW, true = HIGH
void hal_gpio_write(GpioPin* gpio, bool state);
// read value from GPIO, false = LOW, true = HIGH
bool hal_gpio_read(GpioPin* gpio);

View File

@@ -0,0 +1,5 @@
#pragma once
#include "api-hal-gpio.h"
#include "api-hal-delay.h"
#include "flipper_hal.h"

View File

@@ -18,5 +18,8 @@ C_SOURCES += $(TARGET_DIR)/fatfs/syscall.c
# memory manager
C_SOURCES += $(TARGET_DIR)/Src/heap_4.c
CFLAGS += -I$(TARGET_DIR)/api-hal
C_SOURCES += $(wildcard $(TARGET_DIR)/api-hal/*.c)
run: all
$(OBJ_DIR)/$(PROJECT).elf