diff options
Diffstat (limited to 'bsps/arm/stm32h7/start/stm32h7-hal.c')
-rw-r--r-- | bsps/arm/stm32h7/start/stm32h7-hal.c | 276 |
1 files changed, 276 insertions, 0 deletions
diff --git a/bsps/arm/stm32h7/start/stm32h7-hal.c b/bsps/arm/stm32h7/start/stm32h7-hal.c new file mode 100644 index 0000000000..3dcc3098f4 --- /dev/null +++ b/bsps/arm/stm32h7/start/stm32h7-hal.c @@ -0,0 +1,276 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/* + * Copyright (C) 2020 embedded brains GmbH (http://www.embedded-brains.de) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stm32h7/hal.h> + +#include <rtems.h> + +stm32h7_module_index stm32h7_get_module_index(const void *regs) +{ + switch ((uintptr_t) regs) { + case GPIOA_BASE: + return STM32H7_MODULE_GPIOA; + case GPIOB_BASE: + return STM32H7_MODULE_GPIOB; + case GPIOC_BASE: + return STM32H7_MODULE_GPIOC; + case GPIOD_BASE: + return STM32H7_MODULE_GPIOD; + case GPIOE_BASE: + return STM32H7_MODULE_GPIOE; + case GPIOF_BASE: + return STM32H7_MODULE_GPIOF; + case GPIOG_BASE: + return STM32H7_MODULE_GPIOG; + case GPIOH_BASE: + return STM32H7_MODULE_GPIOH; + case GPIOI_BASE: + return STM32H7_MODULE_GPIOI; + case GPIOJ_BASE: + return STM32H7_MODULE_GPIOJ; + case GPIOK_BASE: + return STM32H7_MODULE_GPIOK; + case USART1_BASE: + return STM32H7_MODULE_USART1; + case USART2_BASE: + return STM32H7_MODULE_USART2; + case USART3_BASE: + return STM32H7_MODULE_USART3; + case UART4_BASE: + return STM32H7_MODULE_UART4; + case UART5_BASE: + return STM32H7_MODULE_UART5; + case USART6_BASE: + return STM32H7_MODULE_USART6; + case UART7_BASE: + return STM32H7_MODULE_UART7; + case UART8_BASE: + return STM32H7_MODULE_UART8; +#ifdef UART9_BASE + case UART9_BASE: + return STM32H7_MODULE_UART9; +#endif +#ifdef USART10_BASE + case USART10_BASE: + return STM32H7_MODULE_USART10; +#endif + case RNG_BASE: + return STM32H7_MODULE_RNG; + } + + return STM32H7_MODULE_INVALID; +} + +typedef struct { + __IO uint32_t *enr; + uint32_t enable_bit; +} stm32h7_clk_info; + +static const stm32h7_clk_info stm32h7_clk[] = { + [STM32H7_MODULE_INVALID] = { NULL, 0 }, + [STM32H7_MODULE_GPIOA] = { &RCC->AHB4ENR, RCC_AHB4ENR_GPIOAEN }, + [STM32H7_MODULE_GPIOB] = { &RCC->AHB4ENR, RCC_AHB4ENR_GPIOBEN }, + [STM32H7_MODULE_GPIOC] = { &RCC->AHB4ENR, RCC_AHB4ENR_GPIOCEN }, + [STM32H7_MODULE_GPIOD] = { &RCC->AHB4ENR, RCC_AHB4ENR_GPIODEN }, + [STM32H7_MODULE_GPIOE] = { &RCC->AHB4ENR, RCC_AHB4ENR_GPIOEEN }, + [STM32H7_MODULE_GPIOF] = { &RCC->AHB4ENR, RCC_AHB4ENR_GPIOFEN }, + [STM32H7_MODULE_GPIOG] = { &RCC->AHB4ENR, RCC_AHB4ENR_GPIOGEN }, + [STM32H7_MODULE_GPIOH] = { &RCC->AHB4ENR, RCC_AHB4ENR_GPIOHEN }, + [STM32H7_MODULE_GPIOI] = { &RCC->AHB4ENR, RCC_AHB4ENR_GPIOIEN }, + [STM32H7_MODULE_GPIOJ] = { &RCC->AHB4ENR, RCC_AHB4ENR_GPIOJEN }, + [STM32H7_MODULE_GPIOK] = { &RCC->AHB4ENR, RCC_AHB4ENR_GPIOKEN }, + [STM32H7_MODULE_USART1] = { &RCC->APB2ENR, RCC_APB2ENR_USART1EN }, + [STM32H7_MODULE_USART2] = { &RCC->APB1LENR, RCC_APB1LENR_USART2EN }, + [STM32H7_MODULE_USART3] = { &RCC->APB1LENR, RCC_APB1LENR_USART3EN }, + [STM32H7_MODULE_UART4] = { &RCC->APB1LENR, RCC_APB1LENR_UART4EN }, + [STM32H7_MODULE_UART5] = { &RCC->APB1LENR, RCC_APB1LENR_UART5EN }, + [STM32H7_MODULE_USART6] = { &RCC->APB2ENR, RCC_APB2ENR_USART6EN }, + [STM32H7_MODULE_UART7] = { &RCC->APB1LENR, RCC_APB1LENR_UART7EN }, + [STM32H7_MODULE_UART8] = { &RCC->APB1LENR, RCC_APB1LENR_UART8EN }, +#ifdef UART9_BASE + [STM32H7_MODULE_UART9] = { &RCC->APB2ENR, RCC_APB2ENR_UART9EN }, +#else + [STM32H7_MODULE_UART9] = { NULL, 0 }, +#endif +#ifdef USART10_BASE + [STM32H7_MODULE_USART10] = { &RCC->APB2ENR, RCC_APB2ENR_USART10EN }, +#else + [STM32H7_MODULE_USART10] = { NULL, 0 }, +#endif + [STM32H7_MODULE_RNG] = { &RCC->AHB2ENR, RCC_AHB2ENR_RNGEN }, + [STM32H7_MODULE_ETH1MAC] = { &RCC->AHB1ENR, RCC_AHB1ENR_ETH1MACEN }, + [STM32H7_MODULE_ETH1TX] = { &RCC->AHB1ENR, RCC_AHB1ENR_ETH1TXEN }, + [STM32H7_MODULE_ETH1RX] = { &RCC->AHB1ENR, RCC_AHB1ENR_ETH1RXEN }, + [STM32H7_MODULE_USB1_OTG] = { &RCC->AHB1ENR, RCC_AHB1ENR_USB1OTGHSEN }, + [STM32H7_MODULE_USB1_OTG_ULPI] = { &RCC->AHB1ENR, RCC_AHB1ENR_USB1OTGHSULPIEN }, + [STM32H7_MODULE_USB2_OTG] = { &RCC->AHB1ENR, RCC_AHB1ENR_USB2OTGHSEN }, + [STM32H7_MODULE_USB2_OTG_ULPI] = { &RCC->AHB1ENR, RCC_AHB1ENR_USB2OTGHSULPIEN } +}; + +void stm32h7_clk_enable(stm32h7_module_index index) +{ + __IO uint32_t *enr; + uint32_t enable_bit; + rtems_interrupt_level level; + + enr = stm32h7_clk[index].enr; + enable_bit = stm32h7_clk[index].enable_bit; + + rtems_interrupt_disable(level); + SET_BIT(*enr, enable_bit); + /* Delay after an RCC peripheral clock enabling */ + *enr; + rtems_interrupt_enable(level); +} + +void stm32h7_clk_disable(stm32h7_module_index index) +{ + __IO uint32_t *enr; + uint32_t enable_bit; + rtems_interrupt_level level; + + enr = stm32h7_clk[index].enr; + enable_bit = stm32h7_clk[index].enable_bit; + + rtems_interrupt_disable(level); + CLEAR_BIT(*enr, enable_bit); + rtems_interrupt_enable(level); +} + +static const stm32h7_clk_info stm32h7_clk_low_power[] = { + [STM32H7_MODULE_INVALID] = { NULL, 0 }, + [STM32H7_MODULE_GPIOA] = { &RCC->AHB4LPENR, RCC_AHB4LPENR_GPIOALPEN }, + [STM32H7_MODULE_GPIOB] = { &RCC->AHB4LPENR, RCC_AHB4LPENR_GPIOBLPEN }, + [STM32H7_MODULE_GPIOC] = { &RCC->AHB4LPENR, RCC_AHB4LPENR_GPIOCLPEN }, + [STM32H7_MODULE_GPIOD] = { &RCC->AHB4LPENR, RCC_AHB4LPENR_GPIODLPEN }, + [STM32H7_MODULE_GPIOE] = { &RCC->AHB4LPENR, RCC_AHB4LPENR_GPIOELPEN }, + [STM32H7_MODULE_GPIOF] = { &RCC->AHB4LPENR, RCC_AHB4LPENR_GPIOFLPEN }, + [STM32H7_MODULE_GPIOG] = { &RCC->AHB4LPENR, RCC_AHB4LPENR_GPIOGLPEN }, + [STM32H7_MODULE_GPIOH] = { &RCC->AHB4LPENR, RCC_AHB4LPENR_GPIOHLPEN }, + [STM32H7_MODULE_GPIOI] = { &RCC->AHB4LPENR, RCC_AHB4LPENR_GPIOILPEN }, + [STM32H7_MODULE_GPIOJ] = { &RCC->AHB4LPENR, RCC_AHB4LPENR_GPIOJLPEN }, + [STM32H7_MODULE_GPIOK] = { &RCC->AHB4LPENR, RCC_AHB4LPENR_GPIOKLPEN }, + [STM32H7_MODULE_USART1] = { &RCC->APB2LPENR, RCC_APB2LPENR_USART1LPEN }, + [STM32H7_MODULE_USART2] = { &RCC->APB1LLPENR, RCC_APB1LLPENR_USART2LPEN }, + [STM32H7_MODULE_USART3] = { &RCC->APB1LLPENR, RCC_APB1LLPENR_USART3LPEN }, + [STM32H7_MODULE_UART4] = { &RCC->APB1LLPENR, RCC_APB1LLPENR_UART4LPEN }, + [STM32H7_MODULE_UART5] = { &RCC->APB1LLPENR, RCC_APB1LLPENR_UART5LPEN }, + [STM32H7_MODULE_USART6] = { &RCC->APB2LPENR, RCC_APB2LPENR_USART6LPEN }, + [STM32H7_MODULE_UART7] = { &RCC->APB1LLPENR, RCC_APB1LLPENR_UART7LPEN }, + [STM32H7_MODULE_UART8] = { &RCC->APB1LLPENR, RCC_APB1LLPENR_UART8LPEN }, +#ifdef UART9_BASE + [STM32H7_MODULE_UART9] = { &RCC->APB2LPENR, RCC_APB2LPENR_UART9LPEN }, +#else + [STM32H7_MODULE_UART9] = { NULL, 0 }, +#endif +#ifdef USART10_BASE + [STM32H7_MODULE_USART10] = { &RCC->APB2LPENR, RCC_APB2LPENR_USART10LPEN }, +#else + [STM32H7_MODULE_USART10] = { NULL, 0 }, +#endif + [STM32H7_MODULE_RNG] = { &RCC->AHB2LPENR, RCC_AHB2LPENR_RNGLPEN }, + [STM32H7_MODULE_ETH1MAC] = { &RCC->AHB1LPENR, RCC_AHB1LPENR_ETH1MACLPEN }, + [STM32H7_MODULE_ETH1TX] = { &RCC->AHB1LPENR, RCC_AHB1LPENR_ETH1TXLPEN }, + [STM32H7_MODULE_ETH1RX] = { &RCC->AHB1LPENR, RCC_AHB1LPENR_ETH1RXLPEN }, + [STM32H7_MODULE_USB1_OTG] = { &RCC->AHB1LPENR, RCC_AHB1LPENR_USB1OTGHSLPEN }, + [STM32H7_MODULE_USB1_OTG_ULPI] = { &RCC->AHB1LPENR, RCC_AHB1LPENR_USB1OTGHSULPILPEN }, + [STM32H7_MODULE_USB2_OTG] = { &RCC->AHB1LPENR, RCC_AHB1LPENR_USB2OTGHSLPEN }, + [STM32H7_MODULE_USB2_OTG_ULPI] = { &RCC->AHB1LPENR, RCC_AHB1LPENR_USB2OTGHSULPILPEN } +}; + +void stm32h7_clk_low_power_enable(stm32h7_module_index index) +{ + __IO uint32_t *enr; + uint32_t enable_bit; + rtems_interrupt_level level; + + enr = stm32h7_clk_low_power[index].enr; + enable_bit = stm32h7_clk_low_power[index].enable_bit; + + rtems_interrupt_disable(level); + SET_BIT(*enr, enable_bit); + /* Delay after an RCC peripheral clock enabling */ + *enr; + rtems_interrupt_enable(level); +} + +void stm32h7_clk_low_power_disable(stm32h7_module_index index) +{ + __IO uint32_t *enr; + uint32_t enable_bit; + rtems_interrupt_level level; + + enr = stm32h7_clk_low_power[index].enr; + enable_bit = stm32h7_clk_low_power[index].enable_bit; + + rtems_interrupt_disable(level); + CLEAR_BIT(*enr, enable_bit); + rtems_interrupt_enable(level); +} + +void stm32h7_gpio_init(const stm32h7_gpio_config *config) +{ + stm32h7_module_index index; + + index = stm32h7_get_module_index(config->regs); + stm32h7_clk_enable(index); + HAL_GPIO_Init(config->regs, &config->config); +} + +void stm32h7_uart_polled_write(rtems_termios_device_context *base, char c) +{ + stm32h7_uart_context *ctx; + USART_TypeDef *regs; + + ctx = stm32h7_uart_get_context(base); + regs = ctx->uart.Instance; + + while ((regs->ISR & USART_ISR_TXE_TXFNF) == 0) { + /* Wait */ + } + + regs->TDR = (uint8_t) c; +} + +int stm32h7_uart_polled_read(rtems_termios_device_context *base) +{ + stm32h7_uart_context *ctx; + USART_TypeDef *regs; + + ctx = stm32h7_uart_get_context(base); + regs = ctx->uart.Instance; + + if ((regs->ISR & USART_ISR_RXNE_RXFNE) == 0) { + return -1; + } + + return (uint8_t) regs->RDR; +} |