stm32f0: SPI and i2c interfaces added
Signed-off-by: Eugene Krashtan <eug.krashtan@gmail.com>
This commit is contained in:
parent
b79db3e3d6
commit
45f0ea29a6
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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 ++;
|
||||
}
|
||||
}
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue