This is an automated email from the ASF dual-hosted git repository. xiaoxiang781216 pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 7091ee3f5beccea0d64665b0c295a220efa30267 Author: Alan Carvalho de Assis <[email protected]> AuthorDate: Mon Oct 12 15:27:38 2026 -0300 boards/stm32f1: Add Digital Dream NVMPG pendant board. Add support for the Digital Dream NVMPG CNC pendant (nvmpg-stm32f1), used with the NVUM/NVEM/EC300/EC500 motion controllers. It is based on an STM32F103RCT6 with an ILI9225 176x220 TFT on a 16-bit GPIO bus, 10 keys and a USART1 link to the controller. The board provides: - An lcd_dev_s driver for the ILI9225 on the bit-banged 8080 16-bit bus (the upstream ILI9225 driver only supports SPI), registered as /dev/lcd0 in landscape mode (220x176). - The keys exported as /dev/gpio0..9. - The "dro" configuration, running the industry/cnc/nvmpg-dro application as replacement firmware for the pendant. Signed-off-by: Alan Carvalho de Assis <[email protected]> Co-Authored-By: Claude Opus 5.5 <[email protected]> --- boards/Kconfig | 12 + boards/arm/stm32f1/nvmpg-stm32f1/CMakeLists.txt | 23 + boards/arm/stm32f1/nvmpg-stm32f1/Kconfig | 17 + .../stm32f1/nvmpg-stm32f1/configs/dro/defconfig | 35 ++ boards/arm/stm32f1/nvmpg-stm32f1/include/board.h | 131 +++++ boards/arm/stm32f1/nvmpg-stm32f1/scripts/Make.defs | 37 ++ boards/arm/stm32f1/nvmpg-stm32f1/scripts/ld.script | 127 +++++ .../arm/stm32f1/nvmpg-stm32f1/src/CMakeLists.txt | 35 ++ boards/arm/stm32f1/nvmpg-stm32f1/src/Make.defs | 37 ++ .../arm/stm32f1/nvmpg-stm32f1/src/nvmpg-stm32f1.h | 105 ++++ boards/arm/stm32f1/nvmpg-stm32f1/src/stm32_boot.c | 75 +++ .../arm/stm32f1/nvmpg-stm32f1/src/stm32_bringup.c | 86 ++++ boards/arm/stm32f1/nvmpg-stm32f1/src/stm32_gpio.c | 123 +++++ .../arm/stm32f1/nvmpg-stm32f1/src/stm32_ili9225.c | 553 +++++++++++++++++++++ 14 files changed, 1396 insertions(+) diff --git a/boards/Kconfig b/boards/Kconfig index 045d03e09ee..fbcc1c550e1 100644 --- a/boards/Kconfig +++ b/boards/Kconfig @@ -1967,6 +1967,14 @@ config ARCH_BOARD_NUCLEO_F103RB ---help--- STMicro Nucleo F103RB board based on the STMicro STM32F103RBT6 MCU. +config ARCH_BOARD_NVMPG_STM32F1 + bool "Digital Dream NVMPG CNC pendant (STM32F103RC)" + depends on ARCH_CHIP_STM32F103RC + ---help--- + Digital Dream NVMPG pendant for NVUM/NVEM/EC300/EC500 CNC motion + controllers: STM32F103RCT6, ILI9225 176x220 TFT on a 16-bit GPIO + bus, 10 keys and a USART1 link to the controller. + config ARCH_BOARD_NUCLEO_F207ZG bool "STM32F207 Nucleo F207ZG" depends on ARCH_CHIP_STM32F207ZG @@ -4211,6 +4219,7 @@ config ARCH_BOARD default "nucleo-f072rb" if ARCH_BOARD_NUCLEO_F072RB default "nucleo-f091rc" if ARCH_BOARD_NUCLEO_F091RC default "nucleo-f103rb" if ARCH_BOARD_NUCLEO_F103RB + default "nvmpg-stm32f1" if ARCH_BOARD_NVMPG_STM32F1 default "nucleo-f207zg" if ARCH_BOARD_NUCLEO_F207ZG default "nucleo-f302r8" if ARCH_BOARD_NUCLEO_F302R8 default "nucleo-f303re" if ARCH_BOARD_NUCLEO_F303RE @@ -5180,6 +5189,9 @@ endif if ARCH_BOARD_NUCLEO_F103RB source "boards/arm/stm32f1/nucleo-f103rb/Kconfig" endif +if ARCH_BOARD_NVMPG_STM32F1 +source "boards/arm/stm32f1/nvmpg-stm32f1/Kconfig" +endif if ARCH_BOARD_NUCLEO_F207ZG source "boards/arm/stm32f2/nucleo-f207zg/Kconfig" endif diff --git a/boards/arm/stm32f1/nvmpg-stm32f1/CMakeLists.txt b/boards/arm/stm32f1/nvmpg-stm32f1/CMakeLists.txt new file mode 100644 index 00000000000..b2674c97fe4 --- /dev/null +++ b/boards/arm/stm32f1/nvmpg-stm32f1/CMakeLists.txt @@ -0,0 +1,23 @@ +# ############################################################################## +# boards/arm/stm32f1/nvmpg-stm32f1/CMakeLists.txt +# +# SPDX-License-Identifier: Apache-2.0 +# +# 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. +# +# ############################################################################## + +add_subdirectory(src) diff --git a/boards/arm/stm32f1/nvmpg-stm32f1/Kconfig b/boards/arm/stm32f1/nvmpg-stm32f1/Kconfig new file mode 100644 index 00000000000..1a8751f85ad --- /dev/null +++ b/boards/arm/stm32f1/nvmpg-stm32f1/Kconfig @@ -0,0 +1,17 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +if ARCH_BOARD_NVMPG_STM32F1 + +config NVMPG_STM32F1_HSE_8MHZ + bool "Clock from an 8MHz HSE crystal (72MHz)" + default n + ---help--- + The original NVMPG firmware clocks the PLL from HSI/2, so the + crystal fitted on the board is not known. By default NuttX does + the same (HSI/2 x 16 = 64MHz). Select this if the board has an + 8MHz crystal to run at 72MHz from the HSE instead. + +endif # ARCH_BOARD_NVMPG_STM32F1 diff --git a/boards/arm/stm32f1/nvmpg-stm32f1/configs/dro/defconfig b/boards/arm/stm32f1/nvmpg-stm32f1/configs/dro/defconfig new file mode 100644 index 00000000000..3679dc66d44 --- /dev/null +++ b/boards/arm/stm32f1/nvmpg-stm32f1/configs/dro/defconfig @@ -0,0 +1,35 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_DISABLE_PTHREAD is not set +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD="nvmpg-stm32f1" +CONFIG_ARCH_BOARD_NVMPG_STM32F1=y +CONFIG_ARCH_CHIP="stm32f1" +CONFIG_ARCH_CHIP_STM32=y +CONFIG_ARCH_CHIP_STM32F103RC=y +CONFIG_ARCH_CHIP_STM32F1=y +CONFIG_BOARD_LOOPSPERMSEC=5483 +CONFIG_DEFAULT_SMALL=y +CONFIG_DEV_GPIO=y +CONFIG_INDUSTRY_CNC_NVMPG_DRO=y +CONFIG_INIT_ENTRYPOINT="nvmpg_dro_main" +CONFIG_INTELHEX_BINARY=y +CONFIG_LCD=y +CONFIG_LCD_DEV=y +CONFIG_LCD_NOGETRUN=y +CONFIG_RAM_SIZE=49152 +CONFIG_RAM_START=0x20000000 +CONFIG_RAW_BINARY=y +CONFIG_SERIAL_TERMIOS=y +CONFIG_START_DAY=12 +CONFIG_START_MONTH=10 +CONFIG_START_YEAR=2026 +CONFIG_STM32_JTAG_SW_ENABLE=y +CONFIG_STM32_PWR=y +CONFIG_STM32_USART1=y +CONFIG_TASK_NAME_SIZE=0 diff --git a/boards/arm/stm32f1/nvmpg-stm32f1/include/board.h b/boards/arm/stm32f1/nvmpg-stm32f1/include/board.h new file mode 100644 index 00000000000..2a0565d2832 --- /dev/null +++ b/boards/arm/stm32f1/nvmpg-stm32f1/include/board.h @@ -0,0 +1,131 @@ +/**************************************************************************** + * boards/arm/stm32f1/nvmpg-stm32f1/include/board.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + * + ****************************************************************************/ + +#ifndef __BOARDS_ARM_STM32F1_NVMPG_STM32F1_INCLUDE_BOARD_H +#define __BOARDS_ARM_STM32F1_NVMPG_STM32F1_INCLUDE_BOARD_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#ifndef __ASSEMBLY__ +# include <stdint.h> +# include <stdbool.h> +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Clocking *****************************************************************/ + +/* The original NVMPG firmware runs the PLL from HSI/2 even though it starts + * the HSE, so the crystal value is not known for sure. By default we do the + * same thing (HSI/2 x 16 = 64MHz), which works whatever crystal is fitted. + * Select CONFIG_NVMPG_STM32F1_HSE_8MHZ if the board has an 8MHz crystal to + * run at 72MHz. + */ + +#define STM32_HSI_FREQUENCY 8000000ul +#define STM32_LSI_FREQUENCY 40000 /* Between 30kHz and 60kHz */ +#define STM32_LSE_FREQUENCY 32768 + +#ifdef CONFIG_NVMPG_STM32F1_HSE_8MHZ +# define STM32_BOARD_XTAL 8000000ul +# define STM32_HSE_FREQUENCY STM32_BOARD_XTAL + +/* PLL source is HSE/1, PLL multiplier is 9: 8MHz x 9 = 72MHz */ + +# define STM32_CFGR_PLLSRC RCC_CFGR_PLLSRC +# define STM32_CFGR_PLLXTPRE 0 +# define STM32_CFGR_PLLMUL RCC_CFGR_PLLMUL_CLKx9 +# define STM32_PLL_FREQUENCY (9*STM32_BOARD_XTAL) +#else +# define STM32_HSE_FREQUENCY 0 + +/* PLL source is HSI/2, PLL multiplier is 16: 4MHz x 16 = 64MHz */ + +# define STM32_CFGR_PLLSRC 0 +# define STM32_CFGR_PLLXTPRE 0 +# define STM32_CFGR_PLLMUL RCC_CFGR_PLLMUL_CLKx16 +# define STM32_PLL_FREQUENCY (16*STM32_HSI_FREQUENCY/2) +#endif + +/* Use the PLL and set the SYSCLK source to be the PLL */ + +#define STM32_SYSCLK_SW RCC_CFGR_SW_PLL +#define STM32_SYSCLK_SWS RCC_CFGR_SWS_PLL +#define STM32_SYSCLK_FREQUENCY STM32_PLL_FREQUENCY + +/* AHB clock (HCLK) is SYSCLK */ + +#define STM32_RCC_CFGR_HPRE RCC_CFGR_HPRE_SYSCLK +#define STM32_HCLK_FREQUENCY STM32_SYSCLK_FREQUENCY + +/* APB2 clock (PCLK2) is HCLK */ + +#define STM32_RCC_CFGR_PPRE2 RCC_CFGR_PPRE2_HCLK +#define STM32_PCLK2_FREQUENCY STM32_HCLK_FREQUENCY +#define STM32_APB2_CLKIN (STM32_PCLK2_FREQUENCY) + +/* APB1 clock (PCLK1) is HCLK/2 */ + +#define STM32_RCC_CFGR_PPRE1 RCC_CFGR_PPRE1_HCLKd2 +#define STM32_PCLK1_FREQUENCY (STM32_HCLK_FREQUENCY/2) + +/* Timers */ + +#define STM32_TIM1_CLKIN (STM32_PCLK2_FREQUENCY) +#define STM32_TIM8_CLKIN (STM32_PCLK2_FREQUENCY) +#define STM32_TIM2_CLKIN (2*STM32_PCLK1_FREQUENCY) +#define STM32_TIM3_CLKIN (2*STM32_PCLK1_FREQUENCY) +#define STM32_TIM4_CLKIN (2*STM32_PCLK1_FREQUENCY) +#define STM32_TIM5_CLKIN (2*STM32_PCLK1_FREQUENCY) +#define STM32_TIM6_CLKIN (2*STM32_PCLK1_FREQUENCY) +#define STM32_TIM7_CLKIN (2*STM32_PCLK1_FREQUENCY) + +/* LCD **********************************************************************/ + +/* ILI9225 176x220 TFT used in landscape: 220 columns x 176 rows */ + +#define NVMPG_LCD_XRES 220 +#define NVMPG_LCD_YRES 176 + +/* Keys *********************************************************************/ + +/* Ten push buttons, active low. The original firmware sends key index + 2 + * to the controller when a key is pressed, and (index + 2) | 0x80 when it is + * released. They are exported as /dev/gpio0 .. /dev/gpio9. + */ + +#define NVMPG_NKEYS 10 + +/* Alternate function pin selections ****************************************/ + +/* USART1: link to the NVUM/NVEM controller (PA9 = TX, PA10 = RX) */ + +#define GPIO_USART1_TX GPIO_ADJUST_MODE(GPIO_USART1_TX_0, GPIO_MODE_50MHz) +#define GPIO_USART1_RX GPIO_USART1_RX_0 + +#endif /* __BOARDS_ARM_STM32F1_NVMPG_STM32F1_INCLUDE_BOARD_H */ diff --git a/boards/arm/stm32f1/nvmpg-stm32f1/scripts/Make.defs b/boards/arm/stm32f1/nvmpg-stm32f1/scripts/Make.defs new file mode 100644 index 00000000000..297dfb9c8d9 --- /dev/null +++ b/boards/arm/stm32f1/nvmpg-stm32f1/scripts/Make.defs @@ -0,0 +1,37 @@ +############################################################################ +# boards/arm/stm32f1/nvmpg-stm32f1/scripts/Make.defs +# +# SPDX-License-Identifier: Apache-2.0 +# +# 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 $(TOPDIR)/.config +include $(TOPDIR)/tools/Config.mk +include $(TOPDIR)/arch/arm/src/armv7-m/Toolchain.defs + +LDSCRIPT = ld.script +ARCHSCRIPT += $(BOARD_DIR)$(DELIM)scripts$(DELIM)$(LDSCRIPT) + +CFLAGS := $(ARCHCFLAGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS) +CXXFLAGS := $(ARCHCXXFLAGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHXXINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS) +CPPFLAGS := $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS) +AFLAGS := $(CFLAGS) -D__ASSEMBLY__ + +NXFLATLDFLAGS1 = -r -d -warn-common +NXFLATLDFLAGS2 = $(NXFLATLDFLAGS1) -T$(TOPDIR)/binfmt/libnxflat/gnu-nxflat-pcrel.ld -no-check-sections +LDNXFLATFLAGS = -e main -s 2048 diff --git a/boards/arm/stm32f1/nvmpg-stm32f1/scripts/ld.script b/boards/arm/stm32f1/nvmpg-stm32f1/scripts/ld.script new file mode 100644 index 00000000000..2da7a68ed10 --- /dev/null +++ b/boards/arm/stm32f1/nvmpg-stm32f1/scripts/ld.script @@ -0,0 +1,127 @@ +/**************************************************************************** + * boards/arm/stm32f1/nvmpg-stm32f1/scripts/ld.script + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + * + ****************************************************************************/ + +/* The STM32F103RCT6 has 256Kb of FLASH beginning at address 0x0800:0000 and + * 48Kb of SRAM. + * + * When booting from FLASH, FLASH memory is aliased to address 0x0000:0000 + * where the code expects to begin execution by jumping to the entry point in + * the 0x0800:0000 address range. + */ + +MEMORY +{ + flash (rx) : ORIGIN = 0x08000000, LENGTH = 256K + sram (rwx) : ORIGIN = 0x20000000, LENGTH = 48K +} + +OUTPUT_ARCH(arm) +EXTERN(_vectors) +ENTRY(_stext) +SECTIONS +{ + .text : { + _stext = ABSOLUTE(.); + *(.vectors) + *(.text .text.*) + *(.fixup) + *(.gnu.warning) + *(.rodata .rodata.*) + *(.gnu.linkonce.t.*) + *(.glue_7) + *(.glue_7t) + *(.got) + *(.gcc_except_table) + *(.gnu.linkonce.r.*) + _etext = ABSOLUTE(.); + } > flash + + .init_section : ALIGN(4) { + _sinit = ABSOLUTE(.); + KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP(*(.init_array EXCLUDE_FILE(*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o) .ctors)) + _einit = ABSOLUTE(.); + } > flash + + .ARM.extab : ALIGN(4) { + *(.ARM.extab*) + } > flash + + .ARM.exidx : ALIGN(4) { + __exidx_start = ABSOLUTE(.); + *(.ARM.exidx*) + __exidx_end = ABSOLUTE(.); + } > flash + + .tdata : { + _stdata = ABSOLUTE(.); + *(.tdata .tdata.* .gnu.linkonce.td.*); + _etdata = ABSOLUTE(.); + } > flash + + .tbss : { + _stbss = ABSOLUTE(.); + *(.tbss .tbss.* .gnu.linkonce.tb.* .tcommon); + _etbss = ABSOLUTE(.); + } > flash + + _eronly = ABSOLUTE(.); + + /* The RAM vector table (if present) should lie at the beginning of SRAM */ + + .ram_vectors : { + *(.ram_vectors) + } > sram + + .data : ALIGN(4) { + _sdata = ABSOLUTE(.); + *(.data .data.*) + *(.gnu.linkonce.d.*) + CONSTRUCTORS + . = ALIGN(4); + _edata = ABSOLUTE(.); + } > sram AT > flash + + .bss : ALIGN(4) { + _sbss = ABSOLUTE(.); + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + _ebss = ABSOLUTE(.); + } > sram + + /* Stabs debugging sections. */ + + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_info 0 : { *(.debug_info) } + .debug_line 0 : { *(.debug_line) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_aranges 0 : { *(.debug_aranges) } +} diff --git a/boards/arm/stm32f1/nvmpg-stm32f1/src/CMakeLists.txt b/boards/arm/stm32f1/nvmpg-stm32f1/src/CMakeLists.txt new file mode 100644 index 00000000000..d8190dfe88e --- /dev/null +++ b/boards/arm/stm32f1/nvmpg-stm32f1/src/CMakeLists.txt @@ -0,0 +1,35 @@ +# ############################################################################## +# boards/arm/stm32f1/nvmpg-stm32f1/src/CMakeLists.txt +# +# SPDX-License-Identifier: Apache-2.0 +# +# 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. +# +# ############################################################################## + +set(SRCS stm32_boot.c stm32_bringup.c) + +if(CONFIG_DEV_GPIO) + list(APPEND SRCS stm32_gpio.c) +endif() + +if(CONFIG_LCD) + list(APPEND SRCS stm32_ili9225.c) +endif() + +target_sources(board PRIVATE ${SRCS}) + +set_property(GLOBAL PROPERTY LD_SCRIPT "${NUTTX_BOARD_DIR}/scripts/ld.script") diff --git a/boards/arm/stm32f1/nvmpg-stm32f1/src/Make.defs b/boards/arm/stm32f1/nvmpg-stm32f1/src/Make.defs new file mode 100644 index 00000000000..3bbd98f4d8c --- /dev/null +++ b/boards/arm/stm32f1/nvmpg-stm32f1/src/Make.defs @@ -0,0 +1,37 @@ +############################################################################ +# boards/arm/stm32f1/nvmpg-stm32f1/src/Make.defs +# +# SPDX-License-Identifier: Apache-2.0 +# +# 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 $(TOPDIR)/Make.defs + +CSRCS = stm32_boot.c stm32_bringup.c + +ifeq ($(CONFIG_DEV_GPIO),y) +CSRCS += stm32_gpio.c +endif + +ifeq ($(CONFIG_LCD),y) +CSRCS += stm32_ili9225.c +endif + +DEPPATH += --dep-path board +VPATH += :board +CFLAGS += ${INCDIR_PREFIX}$(TOPDIR)$(DELIM)arch$(DELIM)$(CONFIG_ARCH)$(DELIM)src$(DELIM)board$(DELIM)board diff --git a/boards/arm/stm32f1/nvmpg-stm32f1/src/nvmpg-stm32f1.h b/boards/arm/stm32f1/nvmpg-stm32f1/src/nvmpg-stm32f1.h new file mode 100644 index 00000000000..97ef05da013 --- /dev/null +++ b/boards/arm/stm32f1/nvmpg-stm32f1/src/nvmpg-stm32f1.h @@ -0,0 +1,105 @@ +/**************************************************************************** + * boards/arm/stm32f1/nvmpg-stm32f1/src/nvmpg-stm32f1.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + * + ****************************************************************************/ + +#ifndef __BOARDS_ARM_STM32F1_NVMPG_STM32F1_SRC_NVMPG_STM32F1_H +#define __BOARDS_ARM_STM32F1_NVMPG_STM32F1_SRC_NVMPG_STM32F1_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <arch/board/board.h> + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* LCD: ILI9225 on a bit-banged 8080 16-bit bus ***************************** + * + * D0..D15 PB0..PB15 (needs JTAG disabled to free PB3/PB4; SWD is kept) + * /WR PC10 + * RS PC11 (0 = index register, 1 = data) + * /CS PC12 + * /RD PA15 + * /RESET not connected to the MCU + */ + +#define GPIO_LCD_DATA (GPIO_OUTPUT|GPIO_CNF_OUTPP|GPIO_MODE_50MHz|\ + GPIO_OUTPUT_SET|GPIO_PORTB) +#define GPIO_LCD_WR (GPIO_OUTPUT|GPIO_CNF_OUTPP|GPIO_MODE_50MHz|\ + GPIO_OUTPUT_SET|GPIO_PORTC|GPIO_PIN10) +#define GPIO_LCD_RS (GPIO_OUTPUT|GPIO_CNF_OUTPP|GPIO_MODE_50MHz|\ + GPIO_OUTPUT_SET|GPIO_PORTC|GPIO_PIN11) +#define GPIO_LCD_CS (GPIO_OUTPUT|GPIO_CNF_OUTPP|GPIO_MODE_50MHz|\ + GPIO_OUTPUT_SET|GPIO_PORTC|GPIO_PIN12) +#define GPIO_LCD_RD (GPIO_OUTPUT|GPIO_CNF_OUTPP|GPIO_MODE_50MHz|\ + GPIO_OUTPUT_SET|GPIO_PORTA|GPIO_PIN15) + +/* Keys: active low, external pull-ups (floating inputs). The order below + * matches the key index used by the original firmware (code = index + 2). + */ + +#define GPIO_KEY(port, pin) (GPIO_INPUT|GPIO_CNF_INFLOAT|GPIO_MODE_INPUT|\ + (port)|(pin)) + +#define GPIO_KEY0 GPIO_KEY(GPIO_PORTA, GPIO_PIN2) /* Axis Up 0x02 */ +#define GPIO_KEY1 GPIO_KEY(GPIO_PORTA, GPIO_PIN1) /* Axis Down 0x03 */ +#define GPIO_KEY2 GPIO_KEY(GPIO_PORTA, GPIO_PIN0) /* Spindle 0x04 */ +#define GPIO_KEY3 GPIO_KEY(GPIO_PORTC, GPIO_PIN3) /* Step x1.. 0x05 */ +#define GPIO_KEY4 GPIO_KEY(GPIO_PORTC, GPIO_PIN2) /* Home 0x06 */ +#define GPIO_KEY5 GPIO_KEY(GPIO_PORTC, GPIO_PIN1) /* GOTOZ 0x07 */ +#define GPIO_KEY6 GPIO_KEY(GPIO_PORTC, GPIO_PIN0) /* Zero 0x08 */ +#define GPIO_KEY7 GPIO_KEY(GPIO_PORTC, GPIO_PIN15) /* 1/2 0x09 */ +#define GPIO_KEY8 GPIO_KEY(GPIO_PORTC, GPIO_PIN14) /* Side right 0x0a */ +#define GPIO_KEY9 GPIO_KEY(GPIO_PORTA, GPIO_PIN3) /* Side left 0x0b */ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_bringup + * + * Description: + * Perform architecture-specific initialization. Called from + * board_late_initialize() (CONFIG_BOARD_LATE_INITIALIZE=y) or from + * board_app_initialize(). + * + ****************************************************************************/ + +int stm32_bringup(void); + +/**************************************************************************** + * Name: stm32_gpio_initialize + * + * Description: + * Register the keys as /dev/gpio0 .. /dev/gpio9. + * + ****************************************************************************/ + +#ifdef CONFIG_DEV_GPIO +int stm32_gpio_initialize(void); +#endif + +#endif /* __BOARDS_ARM_STM32F1_NVMPG_STM32F1_SRC_NVMPG_STM32F1_H */ diff --git a/boards/arm/stm32f1/nvmpg-stm32f1/src/stm32_boot.c b/boards/arm/stm32f1/nvmpg-stm32f1/src/stm32_boot.c new file mode 100644 index 00000000000..09280744cd3 --- /dev/null +++ b/boards/arm/stm32f1/nvmpg-stm32f1/src/stm32_boot.c @@ -0,0 +1,75 @@ +/**************************************************************************** + * boards/arm/stm32f1/nvmpg-stm32f1/src/stm32_boot.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <nuttx/board.h> +#include <arch/board/board.h> + +#include "arm_internal.h" +#include "stm32_dbgmcu.h" +#include "nvmpg-stm32f1.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_boardinitialize + * + * Description: + * All STM32 architectures must provide the following entry point. This + * entry point is called early in the initialization -- after all memory + * has been configured and mapped but before any devices have been + * initialized. + * + ****************************************************************************/ + +void stm32_boardinitialize(void) +{ + /* Keep the debug clocks running while the idle loop sleeps in WFI, so + * that SWD can attach to the running firmware. The pendant is always + * externally powered, so the extra current does not matter. + */ + + modifyreg32(STM32_DBGMCU_CR, 0, DBGMCU_CR_SLEEP); +} + +/**************************************************************************** + * Name: board_late_initialize + * + * Description: + * Called immediately after up_initialize() and just before the initial + * application is started (CONFIG_BOARD_LATE_INITIALIZE=y). + * + ****************************************************************************/ + +#ifdef CONFIG_BOARD_LATE_INITIALIZE +void board_late_initialize(void) +{ + stm32_bringup(); +} +#endif diff --git a/boards/arm/stm32f1/nvmpg-stm32f1/src/stm32_bringup.c b/boards/arm/stm32f1/nvmpg-stm32f1/src/stm32_bringup.c new file mode 100644 index 00000000000..a196f72a651 --- /dev/null +++ b/boards/arm/stm32f1/nvmpg-stm32f1/src/stm32_bringup.c @@ -0,0 +1,86 @@ +/**************************************************************************** + * boards/arm/stm32f1/nvmpg-stm32f1/src/stm32_bringup.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <sys/types.h> +#include <syslog.h> + +#include <nuttx/board.h> + +#ifdef CONFIG_LCD_DEV +# include <nuttx/lcd/lcd_dev.h> +#endif + +#include "nvmpg-stm32f1.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_bringup + * + * Description: + * Perform architecture-specific initialization + * + ****************************************************************************/ + +int stm32_bringup(void) +{ + int ret = OK; + +#ifdef CONFIG_DEV_GPIO + /* Keys as /dev/gpio0 .. /dev/gpio9 */ + + ret = stm32_gpio_initialize(); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: stm32_gpio_initialize() failed: %d\n", ret); + } +#endif + +#ifdef CONFIG_LCD + ret = board_lcd_initialize(); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: board_lcd_initialize() failed: %d\n", ret); + } + +# ifdef CONFIG_LCD_DEV + /* LCD character driver as /dev/lcd0 */ + + ret = lcddev_register(0); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: lcddev_register() failed: %d\n", ret); + } +# endif +#endif + + UNUSED(ret); + return OK; +} diff --git a/boards/arm/stm32f1/nvmpg-stm32f1/src/stm32_gpio.c b/boards/arm/stm32f1/nvmpg-stm32f1/src/stm32_gpio.c new file mode 100644 index 00000000000..64982444108 --- /dev/null +++ b/boards/arm/stm32f1/nvmpg-stm32f1/src/stm32_gpio.c @@ -0,0 +1,123 @@ +/**************************************************************************** + * boards/arm/stm32f1/nvmpg-stm32f1/src/stm32_gpio.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + * + ****************************************************************************/ + +/* The ten pendant keys exported as /dev/gpio0 .. /dev/gpio9 (inputs, true + * means released). PA0..PA3 and PC0..PC3 share EXTI lines, so the keys + * cannot all be IRQ buttons and the application polls them instead. + */ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <stdbool.h> +#include <assert.h> + +#include <nuttx/ioexpander/gpio.h> + +#include <arch/board/board.h> + +#include "chip.h" +#include "stm32.h" +#include "nvmpg-stm32f1.h" + +#if defined(CONFIG_DEV_GPIO) && !defined(CONFIG_GPIO_LOWER_HALF) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct stm32gpio_dev_s +{ + struct gpio_dev_s gpio; + uint8_t id; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int gpin_read(FAR struct gpio_dev_s *dev, FAR bool *value); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct gpio_operations_s gpin_ops = +{ + .go_read = gpin_read, + .go_write = NULL, + .go_attach = NULL, + .go_enable = NULL, +}; + +static const uint32_t g_keys[NVMPG_NKEYS] = +{ + GPIO_KEY0, GPIO_KEY1, GPIO_KEY2, GPIO_KEY3, GPIO_KEY4, + GPIO_KEY5, GPIO_KEY6, GPIO_KEY7, GPIO_KEY8, GPIO_KEY9, +}; + +static struct stm32gpio_dev_s g_gpin[NVMPG_NKEYS]; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static int gpin_read(FAR struct gpio_dev_s *dev, FAR bool *value) +{ + FAR struct stm32gpio_dev_s *stm32gpio = (FAR struct stm32gpio_dev_s *)dev; + + DEBUGASSERT(stm32gpio != NULL && value != NULL); + DEBUGASSERT(stm32gpio->id < NVMPG_NKEYS); + + *value = stm32_gpioread(g_keys[stm32gpio->id]); + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_gpio_initialize + ****************************************************************************/ + +int stm32_gpio_initialize(void) +{ + int i; + + for (i = 0; i < NVMPG_NKEYS; i++) + { + stm32_configgpio(g_keys[i]); + + g_gpin[i].gpio.gp_pintype = GPIO_INPUT_PIN; + g_gpin[i].gpio.gp_ops = &gpin_ops; + g_gpin[i].id = i; + gpio_pin_register(&g_gpin[i].gpio, i); + } + + return OK; +} + +#endif /* CONFIG_DEV_GPIO && !CONFIG_GPIO_LOWER_HALF */ diff --git a/boards/arm/stm32f1/nvmpg-stm32f1/src/stm32_ili9225.c b/boards/arm/stm32f1/nvmpg-stm32f1/src/stm32_ili9225.c new file mode 100644 index 00000000000..2bef0750862 --- /dev/null +++ b/boards/arm/stm32f1/nvmpg-stm32f1/src/stm32_ili9225.c @@ -0,0 +1,553 @@ +/**************************************************************************** + * boards/arm/stm32f1/nvmpg-stm32f1/src/stm32_ili9225.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + * + ****************************************************************************/ + +/* ILI9225 176x220 TFT on a GPIO bit-banged 8080 16-bit bus. + * + * The upstream drivers/lcd/ili9225.c only supports SPI, so this board + * provides its own lcd_dev_s. The panel is used in landscape (220x176): + * + * GRAM vertical address (0..219) = screen column (x) + * GRAM horizontal address (0..175) = 175 - screen row (y) + * + * which is the same orientation as the original NVMPG firmware. Entry mode + * AM=1 makes the address counter move along the vertical (x) direction + * first, so a screen raster line is one contiguous GRAM write. + */ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <stdint.h> +#include <stdbool.h> +#include <errno.h> +#include <assert.h> +#include <debug.h> + +#include <nuttx/arch.h> +#include <nuttx/board.h> +#include <nuttx/irq.h> +#include <sys/param.h> +#include <nuttx/lcd/lcd.h> +#include <nuttx/video/fb.h> + +#include <arch/board/board.h> + +#include "arm_internal.h" +#include "stm32.h" +#include "nvmpg-stm32f1.h" + +#ifdef CONFIG_LCD + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define LCD_XRES NVMPG_LCD_XRES +#define LCD_YRES NVMPG_LCD_YRES +#define LCD_BPP 16 + +/* Control pin masks (GPIOA/GPIOC BSRR/BRR) */ + +#define LCD_WR_BIT (1 << 10) /* PC10 */ +#define LCD_RS_BIT (1 << 11) /* PC11 */ +#define LCD_CS_BIT (1 << 12) /* PC12 */ +#define LCD_RD_BIT (1 << 15) /* PA15 */ + +/* ILI9225 registers used here */ + +#define ILI9225_DRIVER_OUTPUT 0x01 +#define ILI9225_LCD_AC_DRIVING 0x02 +#define ILI9225_ENTRY_MODE 0x03 +#define ILI9225_DISP_CTRL1 0x07 +#define ILI9225_BLANK_PERIOD 0x08 +#define ILI9225_FRAME_CYCLE 0x0b +#define ILI9225_INTERFACE_CTRL 0x0c +#define ILI9225_OSC_CTRL 0x0f +#define ILI9225_POWER_CTRL1 0x10 +#define ILI9225_POWER_CTRL2 0x11 +#define ILI9225_POWER_CTRL3 0x12 +#define ILI9225_POWER_CTRL4 0x13 +#define ILI9225_POWER_CTRL5 0x14 +#define ILI9225_VCI_RECYCLING 0x15 +#define ILI9225_RAM_ADDR_H 0x20 +#define ILI9225_RAM_ADDR_V 0x21 +#define ILI9225_GRAM_DATA 0x22 +#define ILI9225_HWIN_END 0x36 +#define ILI9225_HWIN_START 0x37 +#define ILI9225_VWIN_END 0x38 +#define ILI9225_VWIN_START 0x39 + +/* Entry mode: BGR=1, I/D=10 (V increment, H decrement), AM=1 */ + +#define ILI9225_ENTRY_LANDSCAPE 0x1028 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct nvmpg_lcd_s +{ + struct lcd_dev_s dev; /* Publicly visible device structure */ + uint8_t power; /* Current power setting */ + bool initialized; + uint16_t runbuffer[LCD_XRES]; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int lcd_putrun(FAR struct lcd_dev_s *dev, fb_coord_t row, + fb_coord_t col, FAR const uint8_t *buffer, + size_t npixels); +static int lcd_putarea(FAR struct lcd_dev_s *dev, fb_coord_t row_start, + fb_coord_t row_end, fb_coord_t col_start, + fb_coord_t col_end, FAR const uint8_t *buffer, + fb_coord_t stride); +static int lcd_getvideoinfo(FAR struct lcd_dev_s *dev, + FAR struct fb_videoinfo_s *vinfo); +static int lcd_getplaneinfo(FAR struct lcd_dev_s *dev, unsigned int planeno, + FAR struct lcd_planeinfo_s *pinfo); +static int lcd_getpower(FAR struct lcd_dev_s *dev); +static int lcd_setpower(FAR struct lcd_dev_s *dev, int power); +static int lcd_getcontrast(FAR struct lcd_dev_s *dev); +static int lcd_setcontrast(FAR struct lcd_dev_s *dev, + unsigned int contrast); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct nvmpg_lcd_s g_lcd = +{ + .dev = + { + .getvideoinfo = lcd_getvideoinfo, + .getplaneinfo = lcd_getplaneinfo, + .getpower = lcd_getpower, + .setpower = lcd_setpower, + .getcontrast = lcd_getcontrast, + .setcontrast = lcd_setcontrast, + }, +}; + +/* Power-on sequence taken from the original NVMPG firmware */ + +static const uint16_t g_init_power[][2] = +{ + { ILI9225_POWER_CTRL2, 0x001a }, + { ILI9225_POWER_CTRL3, 0x3121 }, + { ILI9225_POWER_CTRL4, 0x006c }, + { ILI9225_POWER_CTRL5, 0x4249 }, + { ILI9225_POWER_CTRL1, 0x0800 }, +}; + +static const uint16_t g_init_ramp[] = +{ + 0x011a, 0x031a, 0x071a, 0x0f1a, 0x0f3a +}; + +static const uint16_t g_init_regs[][2] = +{ + { ILI9225_DRIVER_OUTPUT, 0x011c }, + { ILI9225_LCD_AC_DRIVING, 0x0100 }, + { ILI9225_ENTRY_MODE, ILI9225_ENTRY_LANDSCAPE }, + { ILI9225_DISP_CTRL1, 0x0000 }, + { ILI9225_BLANK_PERIOD, 0x0808 }, + { ILI9225_FRAME_CYCLE, 0x1100 }, + { ILI9225_INTERFACE_CTRL, 0x0000 }, + { ILI9225_OSC_CTRL, 0x1401 }, + { ILI9225_VCI_RECYCLING, 0x0000 }, + { ILI9225_RAM_ADDR_H, 0x0000 }, + { ILI9225_RAM_ADDR_V, 0x0000 }, + { 0x50, 0x0001 }, /* Gamma 0x50..0x59 */ + { 0x51, 0x020b }, + { 0x52, 0x0805 }, + { 0x53, 0x0404 }, + { 0x54, 0x0c0c }, + { 0x55, 0x000c }, + { 0x56, 0x0101 }, + { 0x57, 0x0400 }, + { 0x58, 0x1108 }, + { 0x59, 0x050c }, + { ILI9225_HWIN_END, LCD_YRES - 1 }, /* Full window */ + { ILI9225_HWIN_START, 0x0000 }, + { ILI9225_VWIN_END, LCD_XRES - 1 }, + { ILI9225_VWIN_START, 0x0000 }, + { ILI9225_OSC_CTRL, 0x0b01 }, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/* Bus primitives. These are written against the registers directly: going + * through stm32_gpiowrite() for every edge would make a full screen redraw + * several times slower. + */ + +static inline void lcd_wrbus(uint16_t value) +{ + putreg32(value, STM32_GPIOB_ODR); + putreg32(LCD_WR_BIT, STM32_GPIOC_BRR); + putreg32(LCD_WR_BIT, STM32_GPIOC_BSRR); +} + +static inline void lcd_select(void) +{ + putreg32(LCD_CS_BIT, STM32_GPIOC_BRR); +} + +static inline void lcd_deselect(void) +{ + putreg32(LCD_CS_BIT, STM32_GPIOC_BSRR); +} + +static inline void lcd_index(uint16_t index) +{ + putreg32(LCD_RS_BIT, STM32_GPIOC_BRR); + lcd_wrbus(index); + putreg32(LCD_RS_BIT, STM32_GPIOC_BSRR); +} + +static void lcd_writereg(uint16_t reg, uint16_t value) +{ + lcd_select(); + lcd_index(reg); + lcd_wrbus(value); + lcd_deselect(); +} + +/* Reads only the ID register, so the slow path through stm32_configgpio() + * to turn PB0..15 around is fine here. + */ + +static uint16_t lcd_readreg(uint16_t reg) +{ + uint16_t value; + int i; + + lcd_select(); + lcd_index(reg); + + for (i = 0; i < 16; i++) + { + stm32_configgpio(GPIO_INPUT | GPIO_CNF_INFLOAT | GPIO_MODE_INPUT | + GPIO_PORTB | (i << GPIO_PIN_SHIFT)); + } + + putreg32(LCD_RD_BIT, STM32_GPIOA_BRR); + up_udelay(5); + value = (uint16_t)getreg32(STM32_GPIOB_IDR); + putreg32(LCD_RD_BIT, STM32_GPIOA_BSRR); + + for (i = 0; i < 16; i++) + { + stm32_configgpio(GPIO_LCD_DATA | (i << GPIO_PIN_SHIFT)); + } + + lcd_deselect(); + return value; +} + +/* Select the screen rectangle [x0..x1] x [y0..y1] and leave the controller + * ready to receive pixels in raster order (left to right, top to bottom). + */ + +static void lcd_setarea(fb_coord_t x0, fb_coord_t y0, + fb_coord_t x1, fb_coord_t y1) +{ + lcd_writereg(ILI9225_HWIN_END, LCD_YRES - 1 - y0); + lcd_writereg(ILI9225_HWIN_START, LCD_YRES - 1 - y1); + lcd_writereg(ILI9225_VWIN_END, x1); + lcd_writereg(ILI9225_VWIN_START, x0); + lcd_writereg(ILI9225_RAM_ADDR_H, LCD_YRES - 1 - y0); + lcd_writereg(ILI9225_RAM_ADDR_V, x0); +} + +static void lcd_fill(uint16_t color) +{ + int i; + + lcd_setarea(0, 0, LCD_XRES - 1, LCD_YRES - 1); + lcd_select(); + lcd_index(ILI9225_GRAM_DATA); + putreg32(color, STM32_GPIOB_ODR); + + for (i = 0; i < LCD_XRES * LCD_YRES; i++) + { + putreg32(LCD_WR_BIT, STM32_GPIOC_BRR); + putreg32(LCD_WR_BIT, STM32_GPIOC_BSRR); + } + + lcd_deselect(); +} + +/**************************************************************************** + * Name: lcd_putrun + ****************************************************************************/ + +static int lcd_putrun(FAR struct lcd_dev_s *dev, fb_coord_t row, + fb_coord_t col, FAR const uint8_t *buffer, + size_t npixels) +{ + FAR const uint16_t *src = (FAR const uint16_t *)buffer; + + DEBUGASSERT(buffer != NULL && ((uintptr_t)buffer & 1) == 0); + DEBUGASSERT(row < LCD_YRES && col + npixels <= LCD_XRES); + + lcd_setarea(col, row, col + npixels - 1, row); + lcd_select(); + lcd_index(ILI9225_GRAM_DATA); + + while (npixels-- > 0) + { + lcd_wrbus(*src++); + } + + lcd_deselect(); + return OK; +} + +/**************************************************************************** + * Name: lcd_putarea + ****************************************************************************/ + +static int lcd_putarea(FAR struct lcd_dev_s *dev, fb_coord_t row_start, + fb_coord_t row_end, fb_coord_t col_start, + fb_coord_t col_end, FAR const uint8_t *buffer, + fb_coord_t stride) +{ + size_t width = col_end - col_start + 1; + fb_coord_t row; + size_t i; + + DEBUGASSERT(buffer != NULL && ((uintptr_t)buffer & 1) == 0); + DEBUGASSERT(row_end < LCD_YRES && col_end < LCD_XRES); + + if (stride == 0) + { + stride = width * sizeof(uint16_t); + } + + lcd_setarea(col_start, row_start, col_end, row_end); + lcd_select(); + lcd_index(ILI9225_GRAM_DATA); + + for (row = row_start; row <= row_end; row++) + { + FAR const uint16_t *src = (FAR const uint16_t *)buffer; + + for (i = 0; i < width; i++) + { + lcd_wrbus(src[i]); + } + + buffer += stride; + } + + lcd_deselect(); + return OK; +} + +/**************************************************************************** + * Name: lcd_getvideoinfo + ****************************************************************************/ + +static int lcd_getvideoinfo(FAR struct lcd_dev_s *dev, + FAR struct fb_videoinfo_s *vinfo) +{ + DEBUGASSERT(vinfo != NULL); + + vinfo->fmt = FB_FMT_RGB16_565; + vinfo->xres = LCD_XRES; + vinfo->yres = LCD_YRES; + vinfo->nplanes = 1; + return OK; +} + +/**************************************************************************** + * Name: lcd_getplaneinfo + ****************************************************************************/ + +static int lcd_getplaneinfo(FAR struct lcd_dev_s *dev, unsigned int planeno, + FAR struct lcd_planeinfo_s *pinfo) +{ + FAR struct nvmpg_lcd_s *priv = (FAR struct nvmpg_lcd_s *)dev; + + DEBUGASSERT(pinfo != NULL && planeno == 0); + + pinfo->putrun = lcd_putrun; + pinfo->putarea = lcd_putarea; + pinfo->buffer = (FAR uint8_t *)priv->runbuffer; + pinfo->bpp = LCD_BPP; + pinfo->dev = dev; + return OK; +} + +/**************************************************************************** + * Name: lcd_getpower / lcd_setpower + ****************************************************************************/ + +static int lcd_getpower(FAR struct lcd_dev_s *dev) +{ + FAR struct nvmpg_lcd_s *priv = (FAR struct nvmpg_lcd_s *)dev; + + return priv->power; +} + +static int lcd_setpower(FAR struct lcd_dev_s *dev, int power) +{ + FAR struct nvmpg_lcd_s *priv = (FAR struct nvmpg_lcd_s *)dev; + + if (power > 0) + { + lcd_writereg(ILI9225_DISP_CTRL1, 0x0016); + up_mdelay(2); + lcd_writereg(ILI9225_DISP_CTRL1, 0x0017); + priv->power = 1; + } + else + { + lcd_writereg(ILI9225_DISP_CTRL1, 0x0000); + priv->power = 0; + } + + return OK; +} + +/**************************************************************************** + * Name: lcd_getcontrast / lcd_setcontrast + ****************************************************************************/ + +static int lcd_getcontrast(FAR struct lcd_dev_s *dev) +{ + return -ENOSYS; +} + +static int lcd_setcontrast(FAR struct lcd_dev_s *dev, unsigned int contrast) +{ + return -ENOSYS; +} + +/**************************************************************************** + * Name: lcd_hwinit + ****************************************************************************/ + +static void lcd_hwinit(void) +{ + uint16_t id; + int i; + + /* PB3/PB4 are only usable as GPIO with JTAG-DP disabled + * (CONFIG_STM32_JTAG_SW_ENABLE keeps SWD available for debugging). + */ + + for (i = 0; i < 16; i++) + { + stm32_configgpio(GPIO_LCD_DATA | (i << GPIO_PIN_SHIFT)); + } + + stm32_configgpio(GPIO_LCD_WR); + stm32_configgpio(GPIO_LCD_RS); + stm32_configgpio(GPIO_LCD_CS); + stm32_configgpio(GPIO_LCD_RD); + + up_mdelay(50); + lcd_writereg(0x00, 0x0001); /* Start oscillator */ + up_mdelay(50); + + id = lcd_readreg(0x00); + lcdinfo("LCD ID: %04x\n", id); + UNUSED(id); + + for (i = 0; i < nitems(g_init_power); i++) + { + lcd_writereg(g_init_power[i][0], g_init_power[i][1]); + } + + up_mdelay(10); + + for (i = 0; i < nitems(g_init_ramp); i++) + { + lcd_writereg(ILI9225_POWER_CTRL2, g_init_ramp[i]); + up_mdelay(i < 3 ? 10 : 20); + } + + up_mdelay(30); + + for (i = 0; i < nitems(g_init_regs); i++) + { + lcd_writereg(g_init_regs[i][0], g_init_regs[i][1]); + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_lcd_initialize + ****************************************************************************/ + +int board_lcd_initialize(void) +{ + FAR struct nvmpg_lcd_s *priv = &g_lcd; + + if (!priv->initialized) + { + lcd_hwinit(); + lcd_fill(0x0000); + lcd_setpower(&priv->dev, CONFIG_LCD_MAXPOWER); + priv->initialized = true; + } + + return OK; +} + +/**************************************************************************** + * Name: board_lcd_getdev + ****************************************************************************/ + +FAR struct lcd_dev_s *board_lcd_getdev(int lcddev) +{ + if (lcddev != 0) + { + return NULL; + } + + return &g_lcd.dev; +} + +/**************************************************************************** + * Name: board_lcd_uninitialize + ****************************************************************************/ + +void board_lcd_uninitialize(void) +{ + lcd_setpower(&g_lcd.dev, 0); +} + +#endif /* CONFIG_LCD */
