From e24dc405767e39ef8386f8cfdebbc61c5df8a99c Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Thu, 5 Dec 2024 12:08:50 +0100 Subject: [PATCH] lvgl: Add support for FSMC as 16 bit interface STM32 FSMC peripheral (for accessing external memories) is used to write to LCD with 8080 II 16 bit interface. It allows for maximum performance when LCD is connected to dedicated pins. Signed-off-by: Jerzy Kasenberg --- .../lcd_itf/itf_8080_stm32_fsmc/pkg.yml | 28 +++++ .../src/itf_8080_stm32_fsmc.c | 113 ++++++++++++++++++ hw/drivers/display/lcd_itf/pkg.yml | 2 + hw/drivers/display/lcd_itf/syscfg.yml | 1 + hw/mcu/stm/stm32f4xx/include/mcu/mcu.h | 24 ++++ 5 files changed, 168 insertions(+) create mode 100644 hw/drivers/display/lcd_itf/itf_8080_stm32_fsmc/pkg.yml create mode 100644 hw/drivers/display/lcd_itf/itf_8080_stm32_fsmc/src/itf_8080_stm32_fsmc.c diff --git a/hw/drivers/display/lcd_itf/itf_8080_stm32_fsmc/pkg.yml b/hw/drivers/display/lcd_itf/itf_8080_stm32_fsmc/pkg.yml new file mode 100644 index 0000000000..0b4b6d10b1 --- /dev/null +++ b/hw/drivers/display/lcd_itf/itf_8080_stm32_fsmc/pkg.yml @@ -0,0 +1,28 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +pkg.name: hw/drivers/display/lcd_itf/itf_8080_stm32_fsmc +pkg.description: LCD Standard 8080 parallel interface handled by fsmc +pkg.keywords: + - display + +pkg.apis: + - lcd_interface + +pkg.deps: diff --git a/hw/drivers/display/lcd_itf/itf_8080_stm32_fsmc/src/itf_8080_stm32_fsmc.c b/hw/drivers/display/lcd_itf/itf_8080_stm32_fsmc/src/itf_8080_stm32_fsmc.c new file mode 100644 index 0000000000..af70bced72 --- /dev/null +++ b/hw/drivers/display/lcd_itf/itf_8080_stm32_fsmc/src/itf_8080_stm32_fsmc.c @@ -0,0 +1,113 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include +#include + +#include +#include + +#define PIN(b, pin) ((b >> pin) & 1) + +static inline void lcd_itf_8080_write_word(uint16_t w) +{ + *(uint16_t *)(0x60000000) = w; +} + +#define LCD_ITF_8080_WRITE_BYTE(n) lcd_itf_8080_write_word(n) +#define LCD_ITF_8080_WRITE_WORD(n) lcd_itf_8080_write_word(n) + +void +lcd_itf_write_bytes(const uint8_t *bytes, size_t size) +{ + for (size_t i = 0; i < size; ++i) { + LCD_ITF_8080_WRITE_BYTE(*bytes++); + } +} + +void +lcd_itf_write_color_data(uint16_t x1, uint16_t x2, uint16_t y1, uint16_t y2, void *pixels) +{ + const uint16_t *data = (const uint16_t *)pixels; + size_t size = (x2 - x1 + 1) * (y2 - y1 + 1) * 2; + + LCD_DC_PIN_DATA(); + LCD_CS_PIN_ACTIVE(); + if (LV_COLOR_16_SWAP == 0) { + for (size_t i = 0; i < size; i += 2, data++) { + LCD_ITF_8080_WRITE_WORD(*data); + } + } else { + lcd_itf_write_bytes((const uint8_t *)pixels, size); + } + LCD_CS_PIN_INACTIVE(); +} + +void +lcd_ift_write_cmd(const uint8_t *cmd, int cmd_length) +{ + LCD_DC_PIN_COMMAND(); + LCD_CS_PIN_ACTIVE(); + LCD_ITF_8080_WRITE_BYTE(*cmd); + if (cmd_length > 1) { + LCD_DC_PIN_DATA(); + lcd_itf_write_bytes(cmd + 1, cmd_length - 1); + } + LCD_CS_PIN_INACTIVE(); +} + + +void +lcd_itf_init(void) +{ + hal_gpio_init_out(MYNEWT_VAL(LCD_DC_PIN), 0); + if (MYNEWT_VAL(LCD_CS_PIN) >= 0) { + hal_gpio_init_out(MYNEWT_VAL(LCD_CS_PIN), 1); + } + if (MYNEWT_VAL(LCD_RESET_PIN) >= 0) { + hal_gpio_init_out(MYNEWT_VAL(LCD_RESET_PIN), 1); + } +// hal_gpio_init_af(STM32_FSMC_NE1, GPIO_AF12_FSMC, HAL_GPIO_PULL_NONE, 0); + hal_gpio_init_af(STM32_FSMC_NWE, GPIO_AF12_FSMC, HAL_GPIO_PULL_NONE, 0); + hal_gpio_init_af(STM32_FSMC_NOE, GPIO_AF12_FSMC, HAL_GPIO_PULL_NONE, 0); + hal_gpio_init_af(STM32_FSMC_D0, GPIO_AF12_FSMC, HAL_GPIO_PULL_NONE, 0); + hal_gpio_init_af(STM32_FSMC_D1, GPIO_AF12_FSMC, HAL_GPIO_PULL_NONE, 0); + hal_gpio_init_af(STM32_FSMC_D2, GPIO_AF12_FSMC, HAL_GPIO_PULL_NONE, 0); + hal_gpio_init_af(STM32_FSMC_D3, GPIO_AF12_FSMC, HAL_GPIO_PULL_NONE, 0); + hal_gpio_init_af(STM32_FSMC_D4, GPIO_AF12_FSMC, HAL_GPIO_PULL_NONE, 0); + hal_gpio_init_af(STM32_FSMC_D5, GPIO_AF12_FSMC, HAL_GPIO_PULL_NONE, 0); + hal_gpio_init_af(STM32_FSMC_D6, GPIO_AF12_FSMC, HAL_GPIO_PULL_NONE, 0); + hal_gpio_init_af(STM32_FSMC_D7, GPIO_AF12_FSMC, HAL_GPIO_PULL_NONE, 0); + hal_gpio_init_af(STM32_FSMC_D8, GPIO_AF12_FSMC, HAL_GPIO_PULL_NONE, 0); + hal_gpio_init_af(STM32_FSMC_D9, GPIO_AF12_FSMC, HAL_GPIO_PULL_NONE, 0); + hal_gpio_init_af(STM32_FSMC_D10, GPIO_AF12_FSMC, HAL_GPIO_PULL_NONE, 0); + hal_gpio_init_af(STM32_FSMC_D11, GPIO_AF12_FSMC, HAL_GPIO_PULL_NONE, 0); + hal_gpio_init_af(STM32_FSMC_D12, GPIO_AF12_FSMC, HAL_GPIO_PULL_NONE, 0); + hal_gpio_init_af(STM32_FSMC_D13, GPIO_AF12_FSMC, HAL_GPIO_PULL_NONE, 0); + hal_gpio_init_af(STM32_FSMC_D14, GPIO_AF12_FSMC, HAL_GPIO_PULL_NONE, 0); + hal_gpio_init_af(STM32_FSMC_D15, GPIO_AF12_FSMC, HAL_GPIO_PULL_NONE, 0); + + __HAL_RCC_GPIOD_CLK_ENABLE(); + __HAL_RCC_GPIOE_CLK_ENABLE(); + __HAL_RCC_FSMC_CLK_ENABLE(); + FSMC_Bank1->BTCR[0] = FSMC_BCR1_WREN_Msk | (1 << FSMC_BCR1_MWID_Pos) | (0 << FSMC_BCR1_MTYP_Pos) | FSMC_BCR1_MBKEN_Msk; + FSMC_Bank1->BTCR[1] = 0x00100200; +} diff --git a/hw/drivers/display/lcd_itf/pkg.yml b/hw/drivers/display/lcd_itf/pkg.yml index 006dd9b2b8..40643d0e72 100644 --- a/hw/drivers/display/lcd_itf/pkg.yml +++ b/hw/drivers/display/lcd_itf/pkg.yml @@ -32,4 +32,6 @@ pkg.deps.'LCD_ITF == "8080_II_8_bit"': - "@apache-mynewt-core/hw/drivers/display/lcd_itf/itf_8080" pkg.deps.'LCD_ITF == "8080_II_16_bit"': - "@apache-mynewt-core/hw/drivers/display/lcd_itf/itf_8080" +pkg.deps.'LCD_ITF == "8080_II_16_bit_stm32_fsmc"': + - "@apache-mynewt-core/hw/drivers/display/lcd_itf/itf_8080_stm32_fsmc" diff --git a/hw/drivers/display/lcd_itf/syscfg.yml b/hw/drivers/display/lcd_itf/syscfg.yml index 4fed89ea4f..1da3ac62f9 100644 --- a/hw/drivers/display/lcd_itf/syscfg.yml +++ b/hw/drivers/display/lcd_itf/syscfg.yml @@ -25,6 +25,7 @@ syscfg.defs: - spi - 8080_II_8_bit - 8080_II_16_bit + - 8080_II_16_bit_stm32_fsmc value: spi LCD_CS_PIN: description: LCD chip select pin for SPI. diff --git a/hw/mcu/stm/stm32f4xx/include/mcu/mcu.h b/hw/mcu/stm/stm32f4xx/include/mcu/mcu.h index 3a71c635cf..a3fa819edd 100644 --- a/hw/mcu/stm/stm32f4xx/include/mcu/mcu.h +++ b/hw/mcu/stm/stm32f4xx/include/mcu/mcu.h @@ -47,6 +47,30 @@ extern "C" { #define STM32_SYSTEM_MEMORY 0x1FF00000 #endif +/* FSMC pins are dedicated */ +#define STM32_FSMC_NE1 MCU_GPIO_PORTD(7) +#define STM32_FSMC_NE2 MCU_GPIO_PORTG(9) +#define STM32_FSMC_NE3 MCU_GPIO_PORTG(10) +#define STM32_FSMC_NE4 MCU_GPIO_PORTG(12) +#define STM32_FSMC_NOE MCU_GPIO_PORTD(4) +#define STM32_FSMC_NWE MCU_GPIO_PORTD(5) +#define STM32_FSMC_D0 MCU_GPIO_PORTD(14) +#define STM32_FSMC_D1 MCU_GPIO_PORTD(15) +#define STM32_FSMC_D2 MCU_GPIO_PORTD(0) +#define STM32_FSMC_D3 MCU_GPIO_PORTD(1) +#define STM32_FSMC_D4 MCU_GPIO_PORTE(7) +#define STM32_FSMC_D5 MCU_GPIO_PORTE(8) +#define STM32_FSMC_D6 MCU_GPIO_PORTE(9) +#define STM32_FSMC_D7 MCU_GPIO_PORTE(10) +#define STM32_FSMC_D8 MCU_GPIO_PORTE(11) +#define STM32_FSMC_D9 MCU_GPIO_PORTE(12) +#define STM32_FSMC_D10 MCU_GPIO_PORTE(13) +#define STM32_FSMC_D11 MCU_GPIO_PORTE(14) +#define STM32_FSMC_D12 MCU_GPIO_PORTE(15) +#define STM32_FSMC_D13 MCU_GPIO_PORTD(8) +#define STM32_FSMC_D14 MCU_GPIO_PORTD(9) +#define STM32_FSMC_D15 MCU_GPIO_PORTD(10) + #ifdef __cplusplus } #endif