aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/stm32f0/Kconfig2
-rw-r--r--src/stm32f0/Makefile2
-rw-r--r--src/stm32f0/gpio.c20
-rw-r--r--src/stm32f0/gpio.h55
-rw-r--r--src/stm32f0/i2c.c88
-rw-r--r--src/stm32f0/spi.c106
-rw-r--r--src/stm32f0/stm32f0xx_hal_conf.h2
7 files changed, 274 insertions, 1 deletions
diff --git a/src/stm32f0/Kconfig b/src/stm32f0/Kconfig
index faab5b94..5b285615 100644
--- a/src/stm32f0/Kconfig
+++ b/src/stm32f0/Kconfig
@@ -7,6 +7,8 @@ config STM32F0_SELECT
default y
select HAVE_GPIO
select HAVE_GPIO_ADC
+ select HAVE_GPIO_I2C
+ select HAVE_GPIO_SPI
select HAVE_GPIO_BITBANGING
config BOARD_DIRECTORY
diff --git a/src/stm32f0/Makefile b/src/stm32f0/Makefile
index 7044b5c4..e48b49d5 100644
--- a/src/stm32f0/Makefile
+++ b/src/stm32f0/Makefile
@@ -26,6 +26,8 @@ src-$(CONFIG_DEBUG_OUT) += stm32f0/log.c
src-$(CONFIG_SERIAL) += stm32f0/serial.c
src-y += generic/serial_irq.c
src-$(CONFIG_HAVE_GPIO_ADC) += stm32f0/adc.c
+src-$(CONFIG_HAVE_GPIO_I2C) += stm32f0/i2c.c
+src-$(CONFIG_HAVE_GPIO_SPI) += stm32f0/spi.c
src-y += $(addprefix ../, $(wildcard lib/hal-stm32f0/source/stm32f0xx_*.c))
src-y += generic/crc16_ccitt.c generic/armcm_irq.c
src-y += ../lib/cmsis-stm32f0/source/system_stm32f0xx.c
diff --git a/src/stm32f0/gpio.c b/src/stm32f0/gpio.c
index 74e2fb9e..859cd8d0 100644
--- a/src/stm32f0/gpio.c
+++ b/src/stm32f0/gpio.c
@@ -51,6 +51,7 @@ uint8_t const avail_pins[] = {
static uint8_t
gpio_check_pin(uint8_t pin)
{
+ gpio_check_busy(pin);
int i;
for(i=0; i<ARRAY_SIZE(avail_pins); i++) {
if (avail_pins[i] == pin)
@@ -139,3 +140,22 @@ void gpio_init(void)
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOF_CLK_ENABLE();
}
+
+void gpio_check_busy(uint8_t pin)
+{
+ // Increase to uint32_t and assert <32 on bigger chips
+ static uint16_t pinmap;
+ assert_param(sizeof(avail_pins)<16);
+
+ for (int i = 0; i<sizeof(avail_pins); i++) {
+ if(avail_pins[i]==pin) {
+ if(pinmap&(1<<i)) {
+ break;
+ } else {
+ pinmap |= 1<<i;
+ return;
+ }
+ }
+ }
+ shutdown("GPIO check failed");
+}
diff --git a/src/stm32f0/gpio.h b/src/stm32f0/gpio.h
new file mode 100644
index 00000000..7127a496
--- /dev/null
+++ b/src/stm32f0/gpio.h
@@ -0,0 +1,55 @@
+#ifndef __GENERIC_GPIO_H
+#define __GENERIC_GPIO_H
+
+#include <stdint.h> // uint8_t
+
+struct gpio_out {
+ uint8_t pin;
+};
+struct gpio_out gpio_out_setup(uint8_t pin, uint8_t val);
+void gpio_out_reset(struct gpio_out g, uint8_t val);
+void gpio_out_toggle_noirq(struct gpio_out g);
+void gpio_out_toggle(struct gpio_out g);
+void gpio_out_write(struct gpio_out g, uint8_t val);
+
+struct gpio_in {
+ uint8_t pin;
+};
+struct gpio_in gpio_in_setup(uint8_t pin, int8_t pull_up);
+void gpio_in_reset(struct gpio_in g, int8_t pull_up);
+uint8_t gpio_in_read(struct gpio_in g);
+
+struct gpio_pwm {
+ uint8_t pin;
+};
+struct gpio_pwm gpio_pwm_setup(uint8_t pin, uint32_t cycle_time, uint8_t val);
+void gpio_pwm_write(struct gpio_pwm g, uint8_t val);
+
+struct gpio_adc {
+ uint8_t pin;
+};
+struct gpio_adc gpio_adc_setup(uint8_t pin);
+uint32_t gpio_adc_sample(struct gpio_adc g);
+uint16_t gpio_adc_read(struct gpio_adc g);
+void gpio_adc_cancel_sample(struct gpio_adc g);
+
+struct spi_config {
+ uint32_t cfg;
+};
+struct spi_config spi_setup(uint32_t bus, uint8_t mode, uint32_t rate);
+void spi_prepare(struct spi_config config);
+void spi_transfer(struct spi_config config, uint8_t receive_data
+ , uint8_t len, uint8_t *data);
+
+struct i2c_config {
+ uint8_t addr;
+};
+
+struct i2c_config i2c_setup(uint32_t bus, uint32_t rate, uint8_t addr);
+void i2c_write(struct i2c_config config, uint8_t write_len, uint8_t *write);
+void i2c_read(struct i2c_config config, uint8_t reg_len, uint8_t *reg
+ , uint8_t read_len, uint8_t *read);
+
+void gpio_check_busy(uint8_t pin);
+
+#endif // gpio.h
diff --git a/src/stm32f0/i2c.c b/src/stm32f0/i2c.c
new file mode 100644
index 00000000..6a600e1f
--- /dev/null
+++ b/src/stm32f0/i2c.c
@@ -0,0 +1,88 @@
+/*
+ * i2c support on STM32F0
+ *
+ * Copyright (C) 2019 Eug Krashtan <eug.krashtan@gmail.com>
+ * This file may be distributed under the terms of the GNU GPLv3 license.
+ *
+ */
+
+#include "stm32f0xx_hal.h"
+#include "command.h" // shutdown
+#include "board/gpio.h" // i2c_setup
+#include "sched.h" // sched_shutdown
+#include "command.h" // shutdown
+
+I2C_HandleTypeDef hi2c1;
+
+struct i2c_config i2c_setup(uint32_t bus, uint32_t rate, uint8_t addr)
+{
+ GPIO_InitTypeDef GPIO_InitStruct = {0};
+ /**I2C1 GPIO Configuration
+ PF0-OSC_IN ------> I2C1_SDA
+ PF1-OSC_OUT ------> I2C1_SCL
+ */
+ gpio_check_busy(0x30); //PF0
+ gpio_check_busy(0x31); //PF1
+
+ GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
+ GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
+ GPIO_InitStruct.Pull = GPIO_PULLUP;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
+ GPIO_InitStruct.Alternate = GPIO_AF1_I2C1;
+ HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
+
+ hi2c1.Instance = I2C1;
+ hi2c1.Init.Timing = 0x2000090E;
+ hi2c1.Init.OwnAddress1 = addr;
+ hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
+ hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
+ hi2c1.Init.OwnAddress2 = 0;
+ hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
+ hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
+ hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
+ HAL_I2C_Init(&hi2c1);
+ /** Configure Analogue filter
+ */
+ HAL_I2CEx_ConfigAnalogFilter(&hi2c1, I2C_ANALOGFILTER_ENABLE);
+ /** Configure Digital filter
+ */
+ HAL_I2CEx_ConfigDigitalFilter(&hi2c1, 0);
+ return (struct i2c_config){ .addr = addr };
+}
+
+void i2c_write(struct i2c_config config, uint8_t write_len, uint8_t *write)
+{
+ while(HAL_I2C_Master_Transmit(&hi2c1, config.addr, write,
+ (uint16_t)write_len, (uint32_t)1000)!= HAL_OK) {
+ if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF) {
+ shutdown("Buffer error");
+ }
+ }
+}
+
+void i2c_read(struct i2c_config config, uint8_t reg_len, uint8_t *reg
+ , uint8_t read_len, uint8_t *read)
+{
+ i2c_write(config, reg_len, reg);
+ while(HAL_I2C_Master_Receive(&hi2c1, config.addr, read,
+ (uint16_t)read_len, (uint32_t)1000)!= HAL_OK) {
+ if (HAL_I2C_GetError(&hi2c1) != HAL_I2C_ERROR_AF) {
+ shutdown("Buffer error");
+ }
+ }
+}
+
+/**
+* @brief I2C MSP Initialization
+* @param hi2c: I2C handle pointer
+* @retval None
+*/
+void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c)
+{
+ if(hi2c->Instance==I2C1)
+ {
+ /* Peripheral clock enable */
+ __HAL_RCC_GPIOF_CLK_ENABLE();
+ __HAL_RCC_I2C1_CLK_ENABLE();
+ }
+}
diff --git a/src/stm32f0/spi.c b/src/stm32f0/spi.c
new file mode 100644
index 00000000..683645e4
--- /dev/null
+++ b/src/stm32f0/spi.c
@@ -0,0 +1,106 @@
+/*
+ * SPI support on STM32F0 - without HAL for space saving
+ *
+ * Copyright (C) 2019 Eug Krashtan <eug.krashtan@gmail.com>
+ * This file may be distributed under the terms of the GNU GPLv3 license.
+ *
+ */
+
+#include <string.h> // memcpy
+#include "stm32f0xx_hal.h"
+#include "command.h" // shutdown
+#include "board/gpio.h" // spi_setup
+#include "sched.h" // sched_shutdown
+#include "log.h"
+
+//static SPI_HandleTypeDef hspi1;
+
+void spi_hw_setup(uint32_t rate)
+{
+ GPIO_InitTypeDef GPIO_InitStruct = {0};
+
+ /* SPI1 init - no HAL */
+ __HAL_RCC_SPI1_CLK_ENABLE();
+ __HAL_RCC_GPIOA_CLK_ENABLE();
+
+ /**SPI1 GPIO Configuration
+ PA5 ------> SPI1_SCK
+ PA6 ------> SPI1_MISO
+ PA7 ------> SPI1_MOSI
+ */
+ gpio_check_busy(0x05); //PA5
+ gpio_check_busy(0x06); //PA6
+ gpio_check_busy(0x07); //PA7
+ GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
+ GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
+ GPIO_InitStruct.Alternate = GPIO_AF0_SPI1;
+ HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+
+ if (rate > 800000) {
+ SPI1->CR1 = SPI_BAUDRATEPRESCALER_64;
+ } else {
+ SPI1->CR1 = SPI_BAUDRATEPRESCALER_256;
+ }
+
+ SPI1->CR1 |= SPI_MODE_MASTER | SPI_DIRECTION_2LINES | SPI_CR1_SSM |
+ SPI_POLARITY_LOW | SPI_PHASE_1EDGE |
+ SPI_FIRSTBIT_MSB | SPI_CRCCALCULATION_DISABLE;
+
+ SPI1->CR2 = SPI_NSS_PULSE_DISABLE | SPI_DATASIZE_8BIT |
+ SPI_RXFIFO_THRESHOLD_QF;
+
+ SPI1->CR1 |= SPI_CR1_SPE; // Enable
+
+ //hspi1.Instance = SPI1;
+ //hspi1.Init.Mode = SPI_MODE_MASTER;
+ //hspi1.Init.Direction = SPI_DIRECTION_2LINES;
+ //hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
+ //hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
+ //hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
+ //hspi1.Init.NSS = SPI_NSS_SOFT;
+ //hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
+ //hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
+ //hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
+ //hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
+ //hspi1.Init.CRCPolynomial = 7;
+ //hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
+ //hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
+ //HAL_SPI_Init(&hspi1);
+}
+
+struct spi_config
+spi_setup(uint32_t bus, uint8_t mode, uint32_t rate)
+{
+ if (bus > 0 || !rate)
+ shutdown("Invalid spi_setup parameters");
+
+ spi_hw_setup(rate);
+ return (struct spi_config){ .cfg = SPI1->CR1 };
+}
+
+void
+spi_prepare(struct spi_config config)
+{
+ SPI1->CR1 = config.cfg;
+}
+
+void
+spi_transfer(struct spi_config config, uint8_t receive_data,
+ uint8_t len, uint8_t *data)
+{
+ uint8_t rxptr = 0;
+ while (rxptr<len) {
+ while(!(SPI1->SR & SPI_SR_TXE));
+ __DMB();
+ *((uint8_t*)&(SPI1->DR)) = data[rxptr]; // Hack with pointers
+ // to write/read only 8 bits from 16-bit DR (see errata)
+ while(!(SPI1->SR & SPI_SR_RXNE));
+ __DMB();
+ if(receive_data) {
+ data[rxptr] = *((uint8_t*)&(SPI1->DR));
+ }
+ rxptr ++;
+ }
+}
diff --git a/src/stm32f0/stm32f0xx_hal_conf.h b/src/stm32f0/stm32f0xx_hal_conf.h
index fdc58be4..5457b8a1 100644
--- a/src/stm32f0/stm32f0xx_hal_conf.h
+++ b/src/stm32f0/stm32f0xx_hal_conf.h
@@ -63,7 +63,7 @@
/*#define HAL_LPTIM_MODULE_ENABLED */
/*#define HAL_RNG_MODULE_ENABLED */
/*#define HAL_RTC_MODULE_ENABLED */
-/*#define HAL_SPI_MODULE_ENABLED */
+#define HAL_SPI_MODULE_ENABLED
#define HAL_TIM_MODULE_ENABLED
#define HAL_UART_MODULE_ENABLED
/*#define HAL_USART_MODULE_ENABLED */