diff --git a/BUILD.gn b/BUILD.gn new file mode 100644 index 0000000..8edf483 --- /dev/null +++ b/BUILD.gn @@ -0,0 +1,24 @@ +# Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. +# Licensed 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. + +if (ohos_kernel_type == "liteos_m") { + import("//kernel/liteos_m/liteos.gni") + + module_name = get_path_info(rebase_path("."), "name") + module_group(module_name) { + modules = [] + if (defined(LOSCFG_BOARD_GD32F450)) { + modules += [ "khdvk_450a" ] + } + } +} diff --git a/Kconfig.liteos_m.boards b/Kconfig.liteos_m.boards new file mode 100644 index 0000000..5cec54b --- /dev/null +++ b/Kconfig.liteos_m.boards @@ -0,0 +1,16 @@ +# Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. +# Licensed 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. + +if SOC_GD32F450 +orsource "khdvk_450a/Kconfig.liteos_m.board" +endif diff --git a/Kconfig.liteos_m.defconfig.boards b/Kconfig.liteos_m.defconfig.boards new file mode 100644 index 0000000..35e0437 --- /dev/null +++ b/Kconfig.liteos_m.defconfig.boards @@ -0,0 +1,14 @@ +# Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. +# Licensed 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. + +orsource "*/Kconfig.liteos_m.defconfig.board" diff --git a/Kconfig.liteos_m.shields b/Kconfig.liteos_m.shields new file mode 100644 index 0000000..0b2e49b --- /dev/null +++ b/Kconfig.liteos_m.shields @@ -0,0 +1,14 @@ +# Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. +# Licensed 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. + +orsource "shields/Kconfig.liteos_m.shields" diff --git a/NOTICE b/NOTICE new file mode 100755 index 0000000..94c76d0 --- /dev/null +++ b/NOTICE @@ -0,0 +1,56 @@ +OPEN SOURCE SOFTWARE NOTICE + +Please note we provide an open source software notice for the third party open source software along with this software and/or this software component (in the following just “this SOFTWARE”). The open source software licenses are granted by the respective right holders. + +Warranty Disclaimer +THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS. + +Copyright Notice and License Texts +---------------------------------------------------------------------- +Software: mklfs V1.0 + +Copyright notice: +Copyright (C) 2015 - 2020, IBEROXARXA SERVICIOS INTEGRALES, S.L. +Copyright (C) 2015 - 2020, Jaume Olivé Petrus (jolive@whitecatboard.org) + +Copyright (C) 2015 - 2020, IBEROXARXA SERVICIOS INTEGRALES, S.L. +Copyright (C) 2015 - 2020, Jaume Olivé Petrus (jolive@whitecatboard.org) + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of the nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + * The WHITECAT logotype cannot be changed, you can remove it, but you + cannot change it in any way. The WHITECAT logotype is: + + /\ /\ + / \_____/ \ + /_____________\ + W H I T E C A T + + * Redistributions in binary form must retain all copyright notices printed + to any local or remote output device. This include any reference to + Lua RTOS, whitecatboard.org, Lua, and other copyright notices that may + appear in the future. + +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 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. + +Lua RTOS, a tool for make a LFS file system image diff --git a/OAT.xml b/OAT.xml index 51b484c..77ebe31 100644 --- a/OAT.xml +++ b/OAT.xml @@ -32,6 +32,14 @@ + + + + + + + + @@ -45,6 +53,7 @@ + @@ -77,7 +86,7 @@ - + diff --git a/README_zh.md b/README_zh.md index c39f4de..711421e 100644 --- a/README_zh.md +++ b/README_zh.md @@ -2,18 +2,28 @@ ## 简介 +深开鸿致力于实现更大范围的以软件定义硬件,引领智慧基建、智慧康养、智慧能源、智慧交通、智慧制造、智慧政务、智慧金融、智慧教育等多个行业变革,赋能、赋智、赋值千行百业的数智化转型。目前基于openharmony操作系统适配了多款开发板,本仓用于托管相关智能硬件。 + ### 开发板简介 **深开鸿【金星】系列智慧屏khdvk_3566b开发板** 基于OpenHarmony内嵌KaihongOS的智慧屏开发板,采用ROCKCHIP RK3566 Cortex-A55 四核处理器,提供多路通用显示屏接口,接口类型丰富,支持外设拓展,满足多种人机交互场景的需求,适用于平板电脑,学习机,人脸别相关,主要产品有匝机通道,刷脸支付,工业机器人,医疗检测设备,车牌识别,广告机、数字标牌、智能自助终端、智能零售终端等相关产品。 +**深开鸿khdvk_450a开发板** + +khdvk_450a开发板使用GD32F450ZKT6作为主控制器,使用Mini USB接口或者DC-005连接器提供5V电源,提供包括扩展引脚在内的SWD、Reset、Boot、User button key、LED、CAN、I2C、I2S、USART、RTC、LCD、SPI、ADC、DAC、EXMC、CTC、SDIO、ENET、USBFS、USBHS等外设资源。 + +开发板支持OpenHarmony 轻量系统,并支持display、以太网通讯等能力,可广泛应用于人工智能、工业控制、电机变频、图形显示、传感器网络、无人机、机器人、物联网等创新领域。 + ## 目录 ``` device/board/kaihong ├── figures # 插图 -└── khdvk_3566b # khdvk_3566b开发板 +├── khdvk_3566b # khdvk_3566b开发板 +├── khdvk_450a # KHDVK-450A开发板 +├── xxx # 其他开发板持续开发中 ``` ## 使用说明 @@ -22,7 +32,12 @@ khdvk_3566b参考: - [khdvk_3566b](khdvk_3566b/README_zh.md) +khdvk_450a参考: + +- [khdvk_450a](khdvk_450a/README_zh.md) + ## 相关仓 - [vendor/kaihong](https://gitee.com/openharmony-sig/vendor_kaihong) -- [device/soc/rockchip](https://gitee.com/openharmony-sig/device_soc_rockchip) \ No newline at end of file +- [device/soc/rockchip](https://gitee.com/openharmony-sig/device_soc_rockchip) +- [device_soc_gigadevice](https://gitee.com/openharmony-sig/device_soc_gigadevice) \ No newline at end of file diff --git a/khdvk_450a/BUILD.gn b/khdvk_450a/BUILD.gn new file mode 100644 index 0000000..72e2515 --- /dev/null +++ b/khdvk_450a/BUILD.gn @@ -0,0 +1,30 @@ +# Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. +# Licensed 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. + +if (ohos_kernel_type == "liteos_m") { + import("//kernel/liteos_m/liteos.gni") + + module_name = get_path_info(rebase_path("."), "name") + module_group(module_name) { + modules = [ "liteos_m" ] + + deps = [ ":pre_pack" ] + } + + build_ext_component("pre_pack") { + exec_path = rebase_path(".", root_build_dir) + out_path = rebase_path(root_out_dir) + curr_path = rebase_path(".") + command = "sh pack_tools/pre_pack.sh ${out_path} ${curr_path}/pack_tools" + } +} diff --git a/khdvk_450a/Kconfig.liteos_m.board b/khdvk_450a/Kconfig.liteos_m.board new file mode 100644 index 0000000..b4dd8b0 --- /dev/null +++ b/khdvk_450a/Kconfig.liteos_m.board @@ -0,0 +1,16 @@ +# Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. +# Licensed 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. + +menuconfig BOARD_GD32F450 + bool "select board gd32f450" + depends on SOC_GD32F450 \ No newline at end of file diff --git a/khdvk_450a/Kconfig.liteos_m.defconfig.board b/khdvk_450a/Kconfig.liteos_m.defconfig.board new file mode 100644 index 0000000..c124771 --- /dev/null +++ b/khdvk_450a/Kconfig.liteos_m.defconfig.board @@ -0,0 +1,21 @@ +# Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. +# Licensed 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. + +if BOARD_GD32F450 +config FLASH_SIZE + int + default 8 + help + support flash size +endif #BOARD_GD32F450 + diff --git a/khdvk_450a/README_zh.md b/khdvk_450a/README_zh.md new file mode 100755 index 0000000..dafc014 --- /dev/null +++ b/khdvk_450a/README_zh.md @@ -0,0 +1,95 @@ +# KHDVK-450A开发板 + +## 介绍 + +KHDVK-450A开发板使用GD32F450ZKT6作为主控制器,使用Mini USB接口或者DC-005连接器提供5V电源,提供包括扩展引脚在内的SWD、Reset、Boot、User button key、LED、CAN、I2C、I2S、USART、RTC、LCD、SPI、ADC、DAC、EXMC、CTC、SDIO、ENET、USBFS、USBHS等外设资源。 + +开发板支持OpenHarmony 轻量系统,并支持display、以太网通讯等能力,可广泛应用于人工智能、工业控制、电机变频、图形显示、传感器网络、无人机、机器人、物联网等创新领域。 + + + +**图1** KHDVK-450A开发板正面外观图 + +![img](./docs/figures/开发板接口展示图.png) + + + +**图2** KHDVK-450A开发板背面外观图 + +![img](./docs/figures/开发板背面图.jpg) + + + +## 规格 + +KHDVK-450A开发板MCU处理器规格及通用规格清单如表1所示: + +**表1** KHDVK-450A开发板MCU处理器规格及通用规格清单 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
芯片兆易创新GD32F450ZKT6芯片
架构ARM
主频200 MHz
工作电压5V
内存&存储内置512 KB至3072 KB闪存;内置256KB至512KB SRAM;EXMC接口支持外部SDRAM与SRAM;
通用规格支持OpenHarmony轻量系统
支持SDIO、以太网MAC
8个UART(9Mbit/s);6个SPI (30Mbit/s); 3个I2C (400Kbit/s);
高达3个12位,2.6M SPS ADC(高达24通道)
丰富的扩展接口,支持多种视频输入输出接口(详见底板规格说明)
+ +KHDVK-450A开发板底板规格说明如表2所示: + +**表2** KHDVK-450A开发板底板规格说明 + +| 接口名称 | 接口说明 | +| --------------------- | ---------------------- | +| 显示接口 | LCD (320*480) | +| 以太网 | 1个10/100M以太网控制器 | +| LED | 3个 | +| WDG | 1路 | +| USART+UART | 4+4路 | +| I2C | 3路 | +| SPI | 6路 | +| CAN 2.0B | 2路 | +| USB 2.0 | FS_OTG+HS_OTG | +| I2S | 2路 | +| SDIO | 1路 | +| EXMC/SDRAM | 1/1路 | +| 12bit ADC Units (CHs) | 3(24)路 | +| 12bit DAC Units | 2路 | + +## 关键特性 + +KHDVK-450A开发板支持OpenHarmony 轻量系统,并支持display、以太网通讯等能力,可广泛应用于人工智能、工业控制、电机变频、图形显示、传感器网络、无人机、机器人、物联网等创新领域。 + +## 固件烧录 + +KHDVK-450A固件烧录实践请参考[KHDVK-450A固件烧录实践](https://gitee.com/openharmony-sig/vendor_kaihong/blob/master/khdvk_450a/README_zh.md) diff --git a/khdvk_450a/adapter/hals/iot_hardware/wifiiot_lite/BUILD.gn b/khdvk_450a/adapter/hals/iot_hardware/wifiiot_lite/BUILD.gn new file mode 100755 index 0000000..a5a7252 --- /dev/null +++ b/khdvk_450a/adapter/hals/iot_hardware/wifiiot_lite/BUILD.gn @@ -0,0 +1,27 @@ +# Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. +# Licensed 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. + +static_library("hal_iothardware") { + sources = [ + "hal_iot_flash.c", + "hal_iot_gpio.c", + "hal_iot_i2c.c", + "hal_iot_pwm.c", + "hal_iot_uart.c", + "hal_iot_watchdog.c", + "hal_lowpower.c", + "hal_reset.c", + ] + include_dirs = + [ "//device/soc/gigadevice/gd32f4xx/sdk/drivers/gd32f4xx_driver/include" ] +} diff --git a/khdvk_450a/adapter/hals/iot_hardware/wifiiot_lite/hal_iot_flash.c b/khdvk_450a/adapter/hals/iot_hardware/wifiiot_lite/hal_iot_flash.c new file mode 100644 index 0000000..85697d3 --- /dev/null +++ b/khdvk_450a/adapter/hals/iot_hardware/wifiiot_lite/hal_iot_flash.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 "iot_errno.h" +#include "iot_flash.h" +#include "fmc_operation.h" + +#define ADDR_FMC_SECTOR_0 ((uint32_t)0x08000000) /*!< base address of sector 0, 16 kbytes */ +#define ADDR_FMC_SECTOR_1 ((uint32_t)0x08004000) /*!< base address of sector 1, 16 kbytes */ +#define ADDR_FMC_SECTOR_2 ((uint32_t)0x08008000) /*!< base address of sector 2, 16 kbytes */ +#define ADDR_FMC_SECTOR_3 ((uint32_t)0x0800C000) /*!< base address of sector 3, 16 kbytes */ +#define ADDR_FMC_SECTOR_4 ((uint32_t)0x08010000) /*!< base address of sector 4, 64 kbytes */ +#define ADDR_FMC_SECTOR_5 ((uint32_t)0x08020000) /*!< base address of sector 5, 64 kbytes */ +#define ADDR_FMC_SECTOR_6 ((uint32_t)0x08040000) /*!< base address of sector 6, 64 kbytes */ +#define ADDR_FMC_SECTOR_7 ((uint32_t)0x08060000) /*!< base address of sector 7, 64 kbytes */ +#define ADDR_FMC_SECTOR_8 ((uint32_t)0x08080000) /*!< base address of sector 8, 64 kbytes */ +#define ADDR_FMC_SECTOR_9 ((uint32_t)0x080A0000) /*!< base address of sector 9, 64 kbytes */ +#define ADDR_FMC_SECTOR_10 ((uint32_t)0x080C0000) /*!< base address of sector 10, 64 kbytes */ +#define ADDR_FMC_SECTOR_11 ((uint32_t)0x080E0000) /*!< base address of sector 11, 64 kbytes */ + +static uint32_t g_startAddr = 0; + +static int32_t IoTFmcWrite8Bit(uint32_t addr, uint16_t length, int8_t *data_8) +{ + uint32_t address = addr; + fmc_state_enum fmcState; + fmc_unlock(); + fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_OPERR | FMC_FLAG_WPERR | FMC_FLAG_PGMERR | FMC_FLAG_PGSERR); + for (uint32_t i = 0; i < length; i++) { + fmcState = fmc_byte_program(address, data_8[i]); + if (FMC_READY == fmcState) { + address++; + } else if (FMC_BUSY == fmcState) { + while (1) { } + } else { + return IOT_FAILURE; + } + } + fmc_lock(); + return IOT_SUCCESS; +} + +unsigned int IoTFlashRead(unsigned int flashOffset, unsigned int size, unsigned char *ramData) +{ + if (!size || !ramData || !g_startAddr) { + return IOT_FAILURE; + } + unsigned int addr = g_startAddr + flashOffset; + fmc_read_8bit_data(addr, size, ramData); + return IOT_SUCCESS; +} + +unsigned int IoTFlashWrite(unsigned int flashOffset, unsigned int size, const unsigned char *ramData, + unsigned char doErase) +{ + if (!size || !ramData || !g_startAddr) { + return IOT_FAILURE; + } + unsigned int addr = g_startAddr + flashOffset; + if (doErase) { + fmc_erase_sector_by_address(addr); + } + if (IoTFmcWrite8Bit(addr, size, ramData)) { + return IOT_FAILURE; + } + return IOT_SUCCESS; +} + +unsigned int IoTFlashErase(unsigned int flashOffset, unsigned int size) +{ + unsigned int addr = g_startAddr + flashOffset; + fmc_erase_sector_by_address(addr); + return IOT_SUCCESS; +} + +unsigned int IoTFlashInit(void) +{ + g_startAddr = ADDR_FMC_SECTOR_1; + return IOT_SUCCESS; +} + +unsigned int IoTFlashDeinit(void) +{ + g_startAddr = 0; + return IOT_SUCCESS; +} diff --git a/khdvk_450a/adapter/hals/iot_hardware/wifiiot_lite/hal_iot_gpio.c b/khdvk_450a/adapter/hals/iot_hardware/wifiiot_lite/hal_iot_gpio.c new file mode 100644 index 0000000..443955d --- /dev/null +++ b/khdvk_450a/adapter/hals/iot_hardware/wifiiot_lite/hal_iot_gpio.c @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 "iot_errno.h" +#include "iot_gpio.h" +#include "stdbool.h" +#include "gd32f4xx_rcu.h" + +#define GPIO_PERIPH(x) (((x)&0xF0) >> 4) +#define GPIO_PIN(x) ((x)&0x0F) +#define RCU_PERIPH(x) (((x)&0xF0) >> 4) +#define PRE_PRIORITY (2U) +#define SUB_PRIORITY (0U) +#define INPUT_MODE_BYTE (2U) + +static unsigned int port_id = 0; +static unsigned int pin_id = 0; +static unsigned int rcu_port_id = 0; +static unsigned int exti5_9_pin_id = 0; +static unsigned int exti10_15_pin_id = 0; + +const unsigned int gpio_port_arr[9] = { + GPIOA, GPIOB, GPIOC, GPIOD, GPIOE, GPIOF, GPIOG, GPIOH, GPIOI, +}; + +const unsigned int rcu_port_arr[9] = { + RCU_GPIOA, RCU_GPIOB, RCU_GPIOC, RCU_GPIOD, RCU_GPIOE, RCU_GPIOF, RCU_GPIOG, RCU_GPIOH, RCU_GPIOI, +}; + +const unsigned int exti_port_arr[9] = { + EXTI_SOURCE_GPIOA, EXTI_SOURCE_GPIOB, EXTI_SOURCE_GPIOC, EXTI_SOURCE_GPIOD, EXTI_SOURCE_GPIOE, + EXTI_SOURCE_GPIOF, EXTI_SOURCE_GPIOG, EXTI_SOURCE_GPIOH, EXTI_SOURCE_GPIOI, +}; + +const unsigned int exti_pin_arr[16] = { + EXTI_SOURCE_PIN0, EXTI_SOURCE_PIN1, EXTI_SOURCE_PIN2, EXTI_SOURCE_PIN3, EXTI_SOURCE_PIN4, EXTI_SOURCE_PIN5, + EXTI_SOURCE_PIN6, EXTI_SOURCE_PIN7, EXTI_SOURCE_PIN8, EXTI_SOURCE_PIN9, EXTI_SOURCE_PIN10, EXTI_SOURCE_PIN11, + EXTI_SOURCE_PIN12, EXTI_SOURCE_PIN13, EXTI_SOURCE_PIN14, EXTI_SOURCE_PIN15, +}; + +unsigned int IoTGpioInit(unsigned int id) +{ + rcu_port_id = RCU_PERIPH(id); + rcu_periph_clock_enable(rcu_port_arr[rcu_port_id]); + return IOT_SUCCESS; +} + +unsigned int IoTGpioSetDir(unsigned int id, IotGpioDir dir) +{ + port_id = GPIO_PERIPH(id); + pin_id = GPIO_PIN(id); + if (IOT_GPIO_DIR_IN == dir) { + gpio_mode_set(gpio_port_arr[port_id], GPIO_MODE_INPUT, GPIO_PUPD_NONE, BIT(pin_id)); + } else if (IOT_GPIO_DIR_OUT == dir) { + gpio_mode_set(gpio_port_arr[port_id], GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, BIT(pin_id)); + gpio_output_options_set(gpio_port_arr[port_id], GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, BIT(pin_id)); + } + return IOT_SUCCESS; +} + +unsigned int IoTGpioGetDir(unsigned int id, IotGpioDir *dir) +{ + port_id = GPIO_PERIPH(id); + pin_id = GPIO_PIN(id); + unsigned int reg_ctl_val = GPIO_CTL(gpio_port_arr[port_id]); + *dir = (uint8_t)((reg_ctl_val >> (INPUT_MODE_BYTE * pin_id)) & 0xff); + return IOT_SUCCESS; +} + +unsigned int IoTGpioSetOutputVal(unsigned int id, IotGpioValue val) +{ + port_id = GPIO_PERIPH(id); + pin_id = GPIO_PIN(id); + if (IOT_GPIO_VALUE0 == val) { + gpio_bit_reset(gpio_port_arr[port_id], BIT(pin_id)); + } else if (IOT_GPIO_VALUE1 == val) { + gpio_bit_set(gpio_port_arr[port_id], BIT(pin_id)); + } + return IOT_SUCCESS; +} + +unsigned int IoTGpioGetOutputVal(unsigned int id, IotGpioValue *val) +{ + port_id = GPIO_PERIPH(id); + pin_id = GPIO_PIN(id); + *val = gpio_output_bit_get(gpio_port_arr[port_id], pin_id); + return IOT_SUCCESS; +} + +unsigned int IoTGpioGetInputVal(unsigned int id, IotGpioValue *val) +{ + port_id = GPIO_PERIPH(id); + pin_id = GPIO_PIN(id); + *val = gpio_input_bit_get(gpio_port_arr[port_id], pin_id); + return IOT_SUCCESS; +} + +unsigned int IoTGpioRegisterIsrFunc(unsigned int id, IotGpioIntType intType, IotGpioIntPolarity intPolarity, + GpioIsrCallbackFunc func, char *arg) +{ + if (intType != IOT_INT_TYPE_LEVEL && intType != IOT_INT_TYPE_LEVEL) { + return IOT_FAILURE; + } + if (intPolarity != IOT_GPIO_EDGE_FALL_LEVEL_LOW && intPolarity != IOT_GPIO_EDGE_RISE_LEVEL_HIGH) { + return IOT_FAILURE; + } + port_id = GPIO_PERIPH(id); + pin_id = GPIO_PIN(id); + rcu_port_id = RCU_PERIPH(id); + + rcu_periph_clock_enable(rcu_port_arr[rcu_port_id]); + rcu_periph_clock_enable(RCU_SYSCFG); + + gpio_mode_set(gpio_port_arr[port_id], GPIO_MODE_INPUT, GPIO_PUPD_NONE, BIT(pin_id)); + /* enable and set EXTI interrupt to the lowest priority */ + nvic_irq_enable(EXTI0_IRQn, PRE_PRIORITY, SUB_PRIORITY); + syscfg_exti_line_config(exti_port_arr[port_id], exti_pin_arr[pin_id]); + + if (IOT_GPIO_EDGE_FALL_LEVEL_LOW == intPolarity) { + exti_init(BIT(pin_id), EXTI_INTERRUPT, EXTI_TRIG_FALLING); + } else { + exti_init(BIT(pin_id), EXTI_INTERRUPT, EXTI_TRIG_RISING); + } + exti_interrupt_flag_clear(BIT(pin_id)); + return IOT_SUCCESS; +} + +unsigned int IoTGpioUnregisterIsrFunc(unsigned int id) +{ + port_id = GPIO_PERIPH(id); + gpio_deinit(gpio_port_arr[port_id]); + return IOT_SUCCESS; +} + +unsigned int IoTGpioSetIsrMask(unsigned int id, unsigned char mask) +{ + pin_id = GPIO_PIN(id); + exti_interrupt_flag_clear(BIT(pin_id)); + return IOT_SUCCESS; +} + +unsigned int IoTGpioSetIsrMode(unsigned int id, IotGpioIntType intType, IotGpioIntPolarity intPolarity) +{ + if (intType != IOT_INT_TYPE_LEVEL && intType != IOT_INT_TYPE_LEVEL) { + return IOT_FAILURE; + } + if (intPolarity != IOT_GPIO_EDGE_FALL_LEVEL_LOW && intPolarity != IOT_GPIO_EDGE_RISE_LEVEL_HIGH) { + return IOT_FAILURE; + } + port_id = GPIO_PERIPH(id); + pin_id = GPIO_PIN(id); + rcu_port_id = RCU_PERIPH(id); + rcu_periph_clock_enable(rcu_port_arr[rcu_port_id]); + rcu_periph_clock_enable(RCU_SYSCFG); + gpio_mode_set(gpio_port_arr[port_id], GPIO_MODE_INPUT, GPIO_PUPD_NONE, BIT(pin_id)); + /* enable and set EXTI interrupt to the lowest priority */ + nvic_irq_enable(EXTI0_IRQn, PRE_PRIORITY, SUB_PRIORITY); + syscfg_exti_line_config(exti_port_arr[port_id], exti_pin_arr[pin_id]); + if (IOT_GPIO_EDGE_FALL_LEVEL_LOW == intPolarity) { + exti_init(BIT(pin_id), EXTI_INTERRUPT, EXTI_TRIG_FALLING); + } else { + exti_init(BIT(pin_id), EXTI_INTERRUPT, EXTI_TRIG_RISING); + } + exti_interrupt_flag_clear(BIT(pin_id)); + return IOT_SUCCESS; +} + +unsigned int IoTGpioDeinit(unsigned int id) +{ + port_id = GPIO_PERIPH(id); + pin_id = GPIO_PIN(id); + rcu_port_id = RCU_PERIPH(id); + if (IOT_SUCCESS == IoTGpioUnregisterIsrFunc(id)) { + rcu_periph_clock_disable(rcu_port_arr[rcu_port_id]); + } + gpio_mode_set(gpio_port_arr[port_id], GPIO_MODE_INPUT, GPIO_PUPD_NONE, BIT(pin_id)); + return IOT_SUCCESS; +} \ No newline at end of file diff --git a/khdvk_450a/adapter/hals/iot_hardware/wifiiot_lite/hal_iot_i2c.c b/khdvk_450a/adapter/hals/iot_hardware/wifiiot_lite/hal_iot_i2c.c new file mode 100644 index 0000000..0fdb0e3 --- /dev/null +++ b/khdvk_450a/adapter/hals/iot_hardware/wifiiot_lite/hal_iot_i2c.c @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 "iot_errno.h" +#include "iot_i2c.h" +#include "los_sem.h" +#include "gd32f4xx.h" +#include "gd32f4xx_i2c.h" + +#define MAX_I2C_ID_NUM (2) // 最大I2C ID数 +#define I2C_OWN_ADDRESS7 (0x72) +#define I2C0_BUS_ID 0 +#define I2C1_BUS_ID 1 +#define I2C2_BUS_ID 2 +#define MESSAGE_LAST_SECOND 2 +#define MESSAGE_LAST_THIRD 3 +static uint32_t get_i2c_chn(unsigned int id) +{ + switch (id) { + case I2C0_BUS_ID: + return I2C0; + case I2C1_BUS_ID: + return I2C1; + case I2C2_BUS_ID: + return I2C2; + default: + break; + } +} + +static uint32_t get_i2c_rcu_chn(unsigned int id) +{ + switch (id) { + case I2C0_BUS_ID: + return RCU_I2C0; + case I2C1_BUS_ID: + return RCU_I2C1; + case I2C2_BUS_ID: + return RCU_I2C2; + default: + break; + } +} + +unsigned int IoTI2cWrite(unsigned int id, unsigned short deviceAddr, const unsigned char *data, unsigned int dataLen) +{ + if (id > MAX_I2C_ID_NUM) { + return IOT_FAILURE; + } + uint32_t chn = get_i2c_chn(id); + while (i2c_flag_get(chn, I2C_FLAG_I2CBSY)) { }; // 等待总线空闲 + i2c_start_on_bus(chn); // 发送start信号 + while (!i2c_flag_get(chn, I2C_FLAG_SBSEND)) { }; + i2c_master_addressing(chn, deviceAddr, I2C_TRANSMITTER); // 设置从机地址操作 + while (!i2c_flag_get(chn, I2C_FLAG_ADDSEND)) { }; // 等待从机地址发送标志 + i2c_flag_clear(chn, I2C_FLAG_ADDSEND); // 清除从机地址发送标志 + while (!i2c_flag_get(chn, I2C_FLAG_TBE)) { }; + for (uint8_t i = 0; i < dataLen; i++) { + i2c_data_transmit(chn, data[i]); + while (!i2c_flag_get(chn, I2C_FLAG_BTC)) { }; // 等待数据寄存器空 + } + i2c_stop_on_bus(chn); // 发送stop信号 + while (I2C_CTL0(chn) & I2C_CTL0_STOP) { }; + return IOT_SUCCESS; +} + +unsigned int IoTI2cRead(unsigned int id, unsigned short deviceAddr, unsigned char *dataIn, unsigned int len) +{ + unsigned char *data = dataIn; + unsigned int dataLen = len; + if (id > MAX_I2C_ID_NUM) { + return IOT_FAILURE; + } + uint32_t chn = get_i2c_chn(id); + while (i2c_flag_get(chn, I2C_FLAG_I2CBSY)) { }; // 等待总线空闲 + if (dataLen == MESSAGE_LAST_SECOND) { + i2c_ackpos_config(chn, I2C_ACKPOS_NEXT); + } // 接收数据长度等于2时,首先将POAP置1 + i2c_start_on_bus(chn); // 发送start信号 + while (!i2c_flag_get(chn, I2C_FLAG_SBSEND)) { }; // 等待SBSEND标志 + i2c_master_addressing(chn, deviceAddr, I2C_RECEIVER); // 设置从机地址操作 + if (dataLen < MESSAGE_LAST_THIRD) { + i2c_ack_config(chn, I2C_ACK_DISABLE); + } // 接收数据长度小于3时,需先清除ACK + while (!i2c_flag_get(chn, I2C_FLAG_ADDSEND)) { }; // 等待从机地址发送标志 + i2c_flag_clear(chn, I2C_FLAG_ADDSEND); // 清除从机地址发送标志 + while (dataLen) { + if (dataLen == MESSAGE_LAST_THIRD) { + while (!i2c_flag_get(chn, I2C_FLAG_BTC)) { }; // 等待倒数第二个数据被接收到寄存器 + i2c_ack_config(chn, I2C_ACK_DISABLE); // 清除ACK + } + if (dataLen == MESSAGE_LAST_SECOND) { + while (!i2c_flag_get(chn, I2C_FLAG_BTC)) { }; + i2c_stop_on_bus(chn); // 发送stop信号 + } + if (i2c_flag_get(chn, I2C_FLAG_RBNE)) { // 等待RBNE位被设置 + *data = i2c_data_receive(chn); // 从I2C总线读取数据 + data++; + dataLen--; + } + } + while (I2C_CTL0(chn) & I2C_CTL0_STOP) { }; + i2c_ack_config(chn, I2C_ACK_ENABLE); + return IOT_SUCCESS; +} + +unsigned int IoTI2cInit(unsigned int id, unsigned int baudrate) +{ + if (id > MAX_I2C_ID_NUM) { + return IOT_FAILURE; + } + uint32_t chn = get_i2c_chn(id); + rcu_periph_clock_enable(get_i2c_rcu_chn(id)); + i2c_clock_config(chn, baudrate, I2C_DTCY_2); + i2c_mode_addr_config(chn, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, I2C_OWN_ADDRESS7); + i2c_enable(chn); + i2c_ack_config(chn, I2C_ACK_ENABLE); + return IOT_SUCCESS; +} + +unsigned int IoTI2cDeinit(unsigned int id) +{ + if (id > MAX_I2C_ID_NUM) { + return IOT_FAILURE; + } + uint32_t chn = get_i2c_chn(id); + i2c_deinit(chn); + i2c_disable(chn); + return IOT_SUCCESS; +} + +unsigned int IoTI2cSetBaudrate(unsigned int id, unsigned int baudrate) +{ + if (id > MAX_I2C_ID_NUM) { + return IOT_FAILURE; + } + i2c_clock_config(get_i2c_chn(id), baudrate, I2C_DTCY_2); + return IOT_SUCCESS; +} diff --git a/khdvk_450a/adapter/hals/iot_hardware/wifiiot_lite/hal_iot_pwm.c b/khdvk_450a/adapter/hals/iot_hardware/wifiiot_lite/hal_iot_pwm.c new file mode 100644 index 0000000..de33cad --- /dev/null +++ b/khdvk_450a/adapter/hals/iot_hardware/wifiiot_lite/hal_iot_pwm.c @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 "iot_errno.h" +#include "iot_pwm.h" +#include "gd32f4xx.h" + +// GPIOx[0:4] TIMEx[5:7] PINx[8:15] + +// GPIOx = (PX & 0xF000) >> 12 +// TIMEx = (PX & 0x0F00) >> 8 +// AFmode = (PX & 0x2F00) >> 4 +// PIN = (PX & 0x200F) >> 0 + +#define GPIO(x) ((((x)&0xF000) >> 12)) +#define TIME(x) ((((x)&0x0F00) >> 8)) +#define TIME_CH(x) ((((x)&0x00F0) >> 4)) +#define PINx(x) ((((x)&0x000F) >> 0)) + +#define BIT(x) ((uint32_t)((uint32_t)0x01U << (x))) +#define BITS(start, end) ((0xFFFFFFFFUL << (start)) & (0xFFFFFFFFUL >> (31U - (uint32_t)(end)))) +#define TIMER_NUM (14) +#define TIMER_CHN_NUM (4) +#define GPIO_NUM (9) +#define ZERO_PULSE (0) +#define SYS_CLK (200000000) +#define CLK_PRESCALER (200 - 1) +#define PWM_CLK (SYS_CLK / ((CLK_PRESCALER) + 1)) +#define PERCENTAGE 100 + +#define INVALID_TIME5 5 +#define INVALID_TIME6 6 +#define INVALID_GPIO_GROUP 6 +#define INVALID_GPIO_GROUPS_START 8 +const unsigned int time_arr[TIMER_NUM] = { + TIMER0, TIMER1, TIMER2, TIMER3, TIMER4, TIMER5, TIMER6, TIMER7, TIMER8, TIMER9, TIMER10, TIMER11, TIMER12, TIMER13, +}; +const unsigned int rcu_time_arr[TIMER_NUM] = { + RCU_TIMER0, RCU_TIMER1, RCU_TIMER2, RCU_TIMER3, RCU_TIMER4, RCU_TIMER5, RCU_TIMER6, + RCU_TIMER7, RCU_TIMER8, RCU_TIMER9, RCU_TIMER10, RCU_TIMER11, RCU_TIMER12, RCU_TIMER13, +}; +const unsigned int gpio_arr[GPIO_NUM] = { + GPIOA, GPIOB, GPIOC, GPIOD, GPIOE, GPIOF, GPIOG, GPIOH, GPIOI, +}; +const unsigned int rcu_gpio_arr[GPIO_NUM] = { + RCU_GPIOA, RCU_GPIOB, RCU_GPIOC, RCU_GPIOD, RCU_GPIOE, RCU_GPIOF, RCU_GPIOG, RCU_GPIOH, RCU_GPIOI, +}; +const unsigned int af_mode_arr[TIMER_NUM] = { + GPIO_AF_1, /* 0 */ + GPIO_AF_1, /* 1 */ + GPIO_AF_2, /* 2 */ + GPIO_AF_2, /* 3 */ + GPIO_AF_2, /* 4 */ + 0, /* 5 */ + 0, /* 6 */ + GPIO_AF_3, /* 7 */ + GPIO_AF_3, /* 8 */ + GPIO_AF_3, /* 9 */ + GPIO_AF_3, /* 10 */ + RCU_TIMER9, /* 11 */ + RCU_TIMER9, /* 12 */ + RCU_TIMER9, /* 13 */ +}; +const unsigned int time_ch_arr[TIMER_CHN_NUM] = { + TIMER_CH_0, /* 0 */ + TIMER_CH_1, /* 1 */ + TIMER_CH_2, /* 2 */ + TIMER_CH_3, /* 3 */ +}; + +unsigned int GpioConfigInit(unsigned int data) +{ + unsigned char gpiox = GPIO(data); + unsigned char pin = PINx(data); + unsigned char time = TIME(data); + if (time == INVALID_TIME5 || time == INVALID_TIME6 || gpiox == INVALID_GPIO_GROUP || + gpiox > INVALID_GPIO_GROUPS_START) { + return IOT_FAILURE; + } else { + rcu_periph_clock_enable(rcu_gpio_arr[gpiox]); // RCU_GPIOB + gpio_mode_set(gpio_arr[gpiox], GPIO_MODE_AF, GPIO_PUPD_NONE, BIT(pin)); // GPIOB GPIO_PIN_3 + gpio_output_options_set(gpio_arr[gpiox], GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, BIT(pin)); // GPIOB GPIO_PIN_3 + gpio_af_set(gpio_arr[gpiox], af_mode_arr[time], BIT(pin)); // GPIOB GPIO_AF_1 GPIO_PIN_3 + rcu_periph_clock_enable(rcu_time_arr[time]); // 选择开启的RCC RCU_TIMER1 + rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4); // 固定 + } + return IOT_SUCCESS; +} + +unsigned int GpioConfigDeinit(unsigned int data) +{ + unsigned char gpiox = GPIO(data); + unsigned char pin = PINx(data); + unsigned char time = TIME(data); + if (time == INVALID_TIME5 || time == INVALID_TIME6 || gpiox == INVALID_GPIO_GROUP || + gpiox > INVALID_GPIO_GROUPS_START) { + return IOT_FAILURE; + } else { + gpio_bit_reset(gpio_arr[gpiox], BIT(pin)); + rcu_periph_clock_disable(rcu_gpio_arr[gpiox]); + rcu_periph_clock_disable(rcu_time_arr[time]); + } + return IOT_SUCCESS; +} + +unsigned int IoTPwmInit(unsigned int port) +{ + int ret = GpioConfigInit(port); + if (!ret) { + return IOT_FAILURE; + } + return IOT_SUCCESS; +} + +unsigned int IoTPwmDeinit(unsigned int port) +{ + int ret = GpioConfigDeinit(port); + if (!ret) { + return IOT_FAILURE; + } + return IOT_SUCCESS; +} + +unsigned int IoTPwmStart(unsigned int port, unsigned short duty, unsigned int freq) +{ + unsigned char gpiox = GPIO(port); + unsigned char pin = PINx(port); + unsigned char ch = TIME_CH(port); + unsigned char time = TIME(port); + timer_parameter_struct timer_initpara; + timer_oc_parameter_struct timer_ocintpara; + + if (time == INVALID_TIME5 || time == INVALID_TIME6 || gpiox == INVALID_GPIO_GROUP || + gpiox > INVALID_GPIO_GROUPS_START || freq == 0) { + return IOT_FAILURE; + } + + unsigned int period = PWM_CLK / freq; + unsigned int val = (PWM_CLK / period) * duty / PERCENTAGE; + + /* TIMER1 configuration */ + timer_initpara.prescaler = CLK_PRESCALER; // 分频 SystemCoreClock / 199+1 = 1MHz 1000000hz = 1Mhz + timer_initpara.alignedmode = TIMER_COUNTER_EDGE; // 触发方式设置根据边沿决定 + timer_initpara.counterdirection = TIMER_COUNTER_UP; // 设置为上升沿触发 + timer_initpara.period = period; + timer_initpara.clockdivision = TIMER_CKDIV_DIV1; // clock division value is 1,fDTS=fTIMER_CK + timer_initpara.repetitioncounter = 0; + timer_init(time_arr[time], &timer_initpara); + + timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_HIGH; // 通道输出极性 + timer_ocintpara.outputstate = TIMER_CCX_ENABLE; // 通道输出状态 + timer_ocintpara.ocnpolarity = TIMER_OCN_POLARITY_HIGH; // 通道处于空闲时的输出 + timer_ocintpara.outputnstate = TIMER_CCXN_DISABLE; // 互补通道输出极性 + timer_ocintpara.ocidlestate = TIMER_OC_IDLE_STATE_LOW; // 互补通道输出状态 + timer_ocintpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW; // 互补通道处于空闲时的输出 + timer_channel_output_config(time_arr[time], time_ch_arr[ch], &timer_ocintpara); + + timer_channel_output_pulse_value_config(time_arr[time], time_ch_arr[ch], val); + timer_channel_output_mode_config(time_arr[time], time_ch_arr[ch], TIMER_OC_MODE_PWM0); + timer_channel_output_shadow_config(time_arr[time], time_ch_arr[ch], TIMER_OC_SHADOW_DISABLE); + timer_auto_reload_shadow_enable(time_arr[time]); + timer_enable(time_arr[time]); + + return IOT_SUCCESS; +} + +unsigned int IoTPwmStop(unsigned int port) +{ + unsigned char ch = TIME_CH(port); + unsigned char time = TIME(port); + timer_channel_output_pulse_value_config(time_arr[time], time_ch_arr[ch], ZERO_PULSE); + timer_disable(time_arr[time]); +} \ No newline at end of file diff --git a/khdvk_450a/adapter/hals/iot_hardware/wifiiot_lite/hal_iot_uart.c b/khdvk_450a/adapter/hals/iot_hardware/wifiiot_lite/hal_iot_uart.c new file mode 100644 index 0000000..2076f85 --- /dev/null +++ b/khdvk_450a/adapter/hals/iot_hardware/wifiiot_lite/hal_iot_uart.c @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 "iot_errno.h" +#include "iot_uart.h" +#include "los_sem.h" +#define DEFAULT_BAUDRATE (115200U) +typedef struct { + unsigned int uartID; /* data */ + rcu_periph_enum gpioTxClock; + rcu_periph_enum gpioRxClock; + rcu_periph_enum uartClock; + unsigned int af; + unsigned int txGpio; + unsigned int txPin; + unsigned int rxGpio; + unsigned int rxPin; +} UartSt; + +UartSt gdUart[] = { + {USART0, RCU_GPIOA, RCU_GPIOA, RCU_USART0, GPIO_AF_7, GPIOA, GPIO_PIN_9, GPIOA, GPIO_PIN_10}, + {USART1, RCU_GPIOD, RCU_GPIOD, RCU_USART1, GPIO_AF_7, GPIOD, GPIO_PIN_5, GPIOD, GPIO_PIN_6}, + {USART2, RCU_GPIOB, RCU_GPIOB, RCU_USART2, GPIO_AF_7, GPIOB, GPIO_PIN_10, GPIOB, GPIO_PIN_11}, + {UART3, RCU_GPIOC, RCU_GPIOC, RCU_UART3, GPIO_AF_8, GPIOC, GPIO_PIN_10, GPIOC, GPIO_PIN_11}, + {UART4, RCU_GPIOC, RCU_GPIOD, RCU_UART4, GPIO_AF_8, GPIOC, GPIO_PIN_12, GPIOD, GPIO_PIN_2}, + {USART5, RCU_GPIOC, RCU_GPIOC, RCU_USART5, GPIO_AF_8, GPIOC, GPIO_PIN_6, GPIOC, GPIO_PIN_7}, +}; + +unsigned int IoTUartInit(unsigned int id, const IotUartAttribute *param) +{ + if (id >= sizeof(gdUart) / sizeof(*gdUart)) { + return IOT_FAILURE; + } + + // 使能 GPIO 时钟源 + rcu_periph_clock_enable(gdUart[id].gpioTxClock); + if (gdUart[id].gpioTxClock != gdUart[id].gpioRxClock) { + rcu_periph_clock_enable(gdUart[id].gpioRxClock); + } + // 使能 USART0 时钟源 + rcu_periph_clock_enable(gdUart[id].uartClock); + + /* 复用引脚为 USARTx_Tx */ + gpio_af_set(gdUart[id].txGpio, gdUart[id].af, gdUart[id].txPin); + + /* 复用引脚为 USARTx_Rx */ + gpio_af_set(gdUart[id].rxGpio, gdUart[id].af, gdUart[id].rxPin); + + /* 设置引脚为上拉复用 */ + gpio_mode_set(gdUart[id].txGpio, GPIO_MODE_AF, GPIO_PUPD_PULLUP, gdUart[id].txPin); + gpio_output_options_set(gdUart[id].txGpio, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, gdUart[id].txPin); + + /* 设置引脚为上拉复用 */ + gpio_mode_set(gdUart[id].rxGpio, GPIO_MODE_AF, GPIO_PUPD_PULLUP, gdUart[id].rxPin); + gpio_output_options_set(gdUart[id].rxGpio, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, gdUart[id].rxPin); + + /* USART 配置 */ + usart_deinit(gdUart[id].uartID); + if (param != NULL) { + usart_baudrate_set(gdUart[id].uartID, param->baudRate); + } else { + usart_baudrate_set(gdUart[id].uartID, DEFAULT_BAUDRATE); + } + usart_receive_config(gdUart[id].uartID, USART_RECEIVE_ENABLE); + usart_transmit_config(gdUart[id].uartID, USART_TRANSMIT_ENABLE); + usart_flag_clear(gdUart[id].uartID, USART_FLAG_TC | USART_FLAG_TBE); + usart_enable(gdUart[id].uartID); + return IOT_SUCCESS; +} + +int IoTUartRead(unsigned int id, unsigned char *data, unsigned int dataLen) +{ + if (id >= sizeof(gdUart) / sizeof(*gdUart)) { + return IOT_FAILURE; + } + + for (int i = 0; i < sizeof(dataLen); i++) { + while (usart_flag_get(gdUart[id].uartID, USART_FLAG_RBNE) == RESET) { }; + data[i] = usart_data_receive(gdUart[id].uartID); + } + return IOT_SUCCESS; +} + +int IoTUartWrite(unsigned int id, const unsigned char *data, unsigned int dataLen) +{ + if (id >= sizeof(gdUart) / sizeof(*gdUart)) { + return IOT_FAILURE; + } + for (int i = 0; i < sizeof(dataLen); i++) { + usart_data_transmit(gdUart[id].uartID, (uint8_t)data[i]); + while (RESET == usart_flag_get(gdUart[id].uartID, USART_FLAG_TBE)) { }; + } + return IOT_SUCCESS; +} + +unsigned int IoTUartDeinit(unsigned int id) +{ + if (id >= sizeof(gdUart) / sizeof(*gdUart)) { + return IOT_FAILURE; + } + usart_deinit(gdUart[id].uartID); + return IOT_SUCCESS; +} + +unsigned int IoTUartSetFlowCtrl(unsigned int id, IotFlowCtrl flowCtrl) +{ + if (id >= sizeof(gdUart) / sizeof(*gdUart)) { + return IOT_FAILURE; + } + uint32_t rtsConfig; + uint32_t ctsConfig; + switch (flowCtrl) { + case IOT_FLOW_CTRL_NONE: + rtsConfig = USART_RTS_DISABLE; + ctsConfig = USART_CTS_DISABLE; + break; + case IOT_FLOW_CTRL_RTS_CTS: + rtsConfig = USART_RTS_ENABLE; + ctsConfig = USART_CTS_ENABLE; + break; + case IOT_FLOW_CTRL_RTS_ONLY: + rtsConfig = USART_RTS_ENABLE; + ctsConfig = USART_CTS_DISABLE; + break; + case IOT_FLOW_CTRL_CTS_ONLY: + rtsConfig = USART_RTS_DISABLE; + ctsConfig = USART_CTS_ENABLE; + break; + default: + return IOT_FAILURE; + } + usart_hardware_flow_rts_config(gdUart[id].uartID, rtsConfig); + usart_hardware_flow_cts_config(gdUart[id].uartID, ctsConfig); + return IOT_SUCCESS; +} diff --git a/khdvk_450a/adapter/hals/iot_hardware/wifiiot_lite/hal_iot_watchdog.c b/khdvk_450a/adapter/hals/iot_hardware/wifiiot_lite/hal_iot_watchdog.c new file mode 100755 index 0000000..01b2283 --- /dev/null +++ b/khdvk_450a/adapter/hals/iot_hardware/wifiiot_lite/hal_iot_watchdog.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 "iot_watchdog.h" +#include "gd32f4xx_fwdgt.h" + +void IoTWatchDogEnable(void) +{ + fwdgt_enable(); + return; +} + +void IoTWatchDogKick(void) +{ + fwdgt_counter_reload(); + return; +} + +void IoTWatchDogDisable(void) +{ + // sdk not support + return; +} diff --git a/khdvk_450a/adapter/hals/iot_hardware/wifiiot_lite/hal_lowpower.c b/khdvk_450a/adapter/hals/iot_hardware/wifiiot_lite/hal_lowpower.c new file mode 100644 index 0000000..2929931 --- /dev/null +++ b/khdvk_450a/adapter/hals/iot_hardware/wifiiot_lite/hal_lowpower.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 "lowpower.h" +#include "iot_errno.h" +#include "gd32f4xx_pmu.h" +#include "core_cm4.h" + +unsigned int LpcInit(void) +{ + rcu_periph_clock_enable(RCU_PMU); + return IOT_SUCCESS; +} + +unsigned int LpcSetType(LpcType type) +{ + switch (type) { + case NO_SLEEP: + pmu_to_standbymode(); + break; + case LIGHT_SLEEP: + pmu_to_sleepmode(WFI_CMD); + break; + case DEEP_SLEEP: + pmu_to_deepsleepmode(PMU_LDO_LOWPOWER, PMU_LOWDRIVER_DISABLE, WFI_CMD); + break; + default: + return IOT_FAILURE; + } + return IOT_SUCCESS; +} \ No newline at end of file diff --git a/khdvk_450a/adapter/hals/iot_hardware/wifiiot_lite/hal_reset.c b/khdvk_450a/adapter/hals/iot_hardware/wifiiot_lite/hal_reset.c new file mode 100755 index 0000000..65b1141 --- /dev/null +++ b/khdvk_450a/adapter/hals/iot_hardware/wifiiot_lite/hal_reset.c @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 "reset.h" +#include "gd32f4xx.h" +void RebootDevice(unsigned int cause) +{ + NVIC_SystemReset(); + return; +} diff --git a/khdvk_450a/adapter/hals/update/BUILD.gn b/khdvk_450a/adapter/hals/update/BUILD.gn new file mode 100755 index 0000000..1405735 --- /dev/null +++ b/khdvk_450a/adapter/hals/update/BUILD.gn @@ -0,0 +1,22 @@ +# Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. +# Licensed 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. + +import("//build/lite/config/component/lite_component.gni") + +static_library("hal_update_static") { + sources = [ "hal_hota_board.c" ] + include_dirs = [ + "//base/update/sys_installer_lite/hals", + "//base/update/sys_installer_lite/interfaces/kits", + ] +} diff --git a/khdvk_450a/adapter/hals/update/hal_hota_board.c b/khdvk_450a/adapter/hals/update/hal_hota_board.c new file mode 100755 index 0000000..2d78de7 --- /dev/null +++ b/khdvk_450a/adapter/hals/update/hal_hota_board.c @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 "hal_hota_board.h" +#include "stdio.h" +static BOOL HOTA_STATUS = 0; +int HotaHalInit(void) +{ + if (HOTA_STATUS == 1) { + return OHOS_FAILURE; + } else { + HOTA_STATUS = 1; + return OHOS_SUCCESS; + } +} + +int HotaHalGetUpdateIndex(unsigned int *index) +{ + return OHOS_SUCCESS; +} + +int HotaHalDeInit(void) +{ + if (HOTA_STATUS == 0) { + return OHOS_FAILURE; + } else { + HOTA_STATUS = 0; + return OHOS_SUCCESS; + } +} + +int HotaHalRead(int partition, unsigned int offset, unsigned int bufLen, + unsigned char *buffer) +{ + return -1; +} + +int HotaHalWrite(int partition, unsigned char *buffer, unsigned int offset, + unsigned int bufLen) +{ + return OHOS_SUCCESS; +} + +int HotaHalRestart(void) +{ + return OHOS_SUCCESS; +} + +int HotaHalSetBootSettings(void) +{ + return OHOS_SUCCESS; +} + +int HotaHalRollback(void) +{ + return OHOS_SUCCESS; +} + +const ComponentTableInfo *HotaHalGetPartitionInfo() +{ + return 0; +} + +unsigned char *HotaHalGetPubKey(unsigned int *length) +{ + return 0; +} + + +int HotaHalGetUpdateAbility(void) +{ + return ABILITY_PKG_SEARCH | ABILITY_PKG_DLOAD; +} + +int HotaHalGetOtaPkgPath(char *path, int len) +{ + return OHOS_SUCCESS; +} + +int HotaHalIsDeviceCanReboot(void) +{ + return 1; +} + +int HotaHalGetMetaData(UpdateMetaData *metaData) +{ + return OHOS_SUCCESS; +} + +int HotaHalSetMetaData(UpdateMetaData *metaData) +{ + return OHOS_SUCCESS; +} + +int HotaHalRebootAndCleanUserData(void) +{ + return OHOS_SUCCESS; +} + +int HotaHalRebootAndCleanCache(void) +{ + return OHOS_SUCCESS; +} + +int HotaHalIsDevelopMode(void) +{ + return OHOS_SUCCESS; +} + +int HotaHalCheckVersionValid(const char *currentVersion, const char *pkgVersion, unsigned int pkgVersionLength) +{ + return (strncmp(currentVersion, pkgVersion, pkgVersionLength) == 0) ? 1 : 0; +} diff --git a/khdvk_450a/adapter/hals/utils/file/BUILD.gn b/khdvk_450a/adapter/hals/utils/file/BUILD.gn new file mode 100755 index 0000000..4c43eff --- /dev/null +++ b/khdvk_450a/adapter/hals/utils/file/BUILD.gn @@ -0,0 +1,29 @@ +# Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. +# Licensed 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. + +import("//build/lite/config/component/lite_component.gni") + +static_library("hal_file_static") { + sources = [ "hal_file.c" ] + include_dirs = [ + "//commonlibrary/utils_lite/hals/file", + "//third_party/littlefs", + "//third_party/littlefs/bd", + "//drivers/hdf_core/framework/include/platform", + "//drivers/hdf_core/framework/include/utils", + "//drivers/hdf_core/adapter/khdf/liteos_m/osal/include", + "//drivers/hdf_core/framework/include/osal", + "//drivers/hdf_core/framework/include/core", + "//drivers/hdf_core/framework/core/common/include/host", + ] +} diff --git a/khdvk_450a/adapter/hals/utils/file/hal_file.c b/khdvk_450a/adapter/hals/utils/file/hal_file.c new file mode 100644 index 0000000..550c9a4 --- /dev/null +++ b/khdvk_450a/adapter/hals/utils/file/hal_file.c @@ -0,0 +1,471 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 +#include +#include +#include +#include +#include +#include +#include "los_fs.h" +#include "errno.h" +#include "lfs.h" +#include "los_task.h" +#include "fmc_operation.h" +#include "exmc_sdram.h" +#include "utils_file.h" + +#define GD32F450ZIT6_FLASH_BANK1_SECTOR17_ADDR 0x08200000 +#ifndef GD32F450ZIT6_FLASH_SECTOR_SIZE +#define GD32F450ZIT6_FLASH_SECTOR_SIZE (4 * 1024) +#endif + +#define SLOT_AVAILABLE (-1) +#define HAL_ERROR (-1) + +#define RD_WR_FIELD_MASK 0x000f +#define CREAT_EXCL_FIELD_MASK 0x00f0 +#define TRUNC_FILED_MASK 0x0f00 + +#define ADDITIONAL_LEN 2 +#define MAX_PATH_LEN 40 +#define MAX_OPEN_FILE_NUM 32 +#define FLASH_ROOT_PATH "/data" +#define DIR_SEPARATOR "/" +#define RAM_ROOT_PATH "/ram" + +#define FLASH_READ_SIZE 1 // 128 /* 最小读取字节数,所有的读取操作字节数必须是它的倍数(影响内存消耗) */ +#define FLASH_PROG_SIZE 1 // 128 /* 最小写入字节数,所有的写入操作字节数必须是它的倍数(影响内存消耗) */ +#define FLASH_BLOCK_SIZE \ + GD32F450ZIT6_FLASH_SECTOR_SIZE /* 擦除块字节数,不会影响内存消耗,每个文件至少占用一个块,必须是READ_SIZE/PROG_SIZE的倍数 \ + */ +#define FLASH_CACHE_SIZE \ + 128 /* 块缓存的大小,缓存越大磁盘访问越小,性能越高,必须是READ_SIZE/PROG_SIZE的倍数,且是BLOCK_SIZE的因数 */ +#define FLASH_LOOKAHEAD_SIZE 16 /* 块分配预测深度,分配块时每次步进多少个块,必须为8的整数倍,对于内存消耗影响不大 */ +#define FLASH_BLOCK_CYCLES \ + 500 /* 逐出元数据日志并将元数据移动到另一个块之前的擦除周期数,值越大性能越好,但磨损越不均匀,-1将禁用块级磨损均衡 \ + */ +#define FLASH_BLOCK_COUNT (1024 * 1024 / FLASH_BLOCK_SIZE) + +#define DEVICE_SDRAM_NAME EXMC_SDRAM_DEVICE0 +#define SDRAM_OFFSET_ADDRESS 0x01000000 +#define SDRAM_BLOCK_ADDRESS 0xC0000000 +#define SDRAM_READ_SIZE 1 //128 /* 最小读取字节数,所有的读取操作字节数必须是它的倍数(影响内存消耗) */ +#define SDRAM_PROG_SIZE 1 //128 /* 最小写入字节数,所有的写入操作字节数必须是它的倍数(影响内存消耗) */ +#define SDRAM_BLOCK_COUNT 2048 +#define SDRAM_BLOCK_SIZE 256 /* 擦除块字节数,不会影响内存消耗,每个文件至少占用一个块,必须是READ_SIZE/PROG_SIZE的倍数 */ +#define SDRAM_CACHE_SIZE 128 /* 块缓存的大小,缓存越大磁盘访问越小,性能越高,必须是READ_SIZE/PROG_SIZE的倍数,且是BLOCK_SIZE的因数 */ +#define SDRAM_LOOKAHEAD_SIZE 64 /* 块分配预测深度,分配块时每次步进多少个块,必须为8的整数倍,对于内存消耗影响不大 */ +#define SDRAM_BLOCK_CYCLES 500 /* 逐出元数据日志并将元数据移动到另一个块之前的擦除周期数,值越大性能越好,但磨损越不均匀,-1将禁用块级磨损均衡 */ + +#define MAX_PATH_LEN 40 + +int littlefs_block_read(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, void *buffer, lfs_size_t size); +int littlefs_block_write(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, const void *buffer, + lfs_size_t size); +int littlefs_block_erase(const struct lfs_config *c, lfs_block_t block); +int littlefs_block_sync(const struct lfs_config *c); + +struct fs_cfg { + char *mount_point; + struct lfs_config lfs_cfg; +}; +static struct fs_cfg fs[LOSCFG_LFS_MAX_MOUNT_SIZE] = {0}; + +static struct PartitionCfg part_cfg[LOSCFG_LFS_MAX_MOUNT_SIZE] ={ + { + .readFunc = NULL, + .writeFunc = NULL, + .eraseFunc = NULL, + .readSize = FLASH_READ_SIZE, // 读闪存 以字节为单位读取的块的最小大小。所有读操作都是该值的倍数。 + .writeSize = FLASH_PROG_SIZE, // 写闪存 以字节为单位的块程序的最小大小。所有程序操作都是该值的倍数。 + .blockSize = GD32F450ZIT6_FLASH_SECTOR_SIZE, // 块大小 可擦块的大小(以字节为单位),必须是读取大小和程序大小的倍数。 + .blockCount = FLASH_BLOCK_COUNT, // 块个数 设备上可擦的块数。 + .cacheSize = FLASH_CACHE_SIZE, // 系统缓存必须是读写缓存的倍数 块大小的因数 + .lookaheadSize = FLASH_LOOKAHEAD_SIZE, // 类似目录缓存 必须是8的倍数 + .blockCycles = FLASH_BLOCK_CYCLES, // 每500次磨损来一次均衡 + .partNo = 1, // 用来判断底层操作函数的标志num + }, + { + .readFunc = NULL, + .writeFunc = NULL, + .eraseFunc = NULL, + .readSize = SDRAM_READ_SIZE, // 读闪存 以字节为单位读取的块的最小大小。所有读操作都是该值的倍数。 + .writeSize = SDRAM_PROG_SIZE, // 写闪存 以字节为单位的块程序的最小大小。所有程序操作都是该值的倍数。 + .blockSize = SDRAM_BLOCK_SIZE, // 块大小 可擦块的大小(以字节为单位),必须是读取大小和程序大小的倍数。 + .blockCount = SDRAM_BLOCK_COUNT, // 块个数 设备上可擦的块数。 + .cacheSize = SDRAM_CACHE_SIZE, // 系统缓存必须是读写缓存的倍数 块大小的因数 + .lookaheadSize = SDRAM_LOOKAHEAD_SIZE, // 类似目录缓存 必须是8的倍数 + .blockCycles = SDRAM_BLOCK_CYCLES, // 每500次磨损来一次均衡 + .partNo = 2, // 用来判断底层操作函数的标志num + } +}; + +int lfs_init(void) +{ + DIR *dir = NULL; + fs[0].mount_point = FLASH_ROOT_PATH; + fs[1].mount_point = RAM_ROOT_PATH; + for (int i = 0; i < sizeof(fs) / sizeof(fs[0]); i++) { + if (fs[i].mount_point == NULL) { + continue; + } + + int ret = mount(NULL, fs[i].mount_point, "littlefs", 0, &part_cfg[i]); + printf("%s: mount fs on '%s' %s\n", __func__, fs[i].mount_point, (ret == 0) ? "succeed" : "failed"); + if ((dir = opendir(fs[i].mount_point)) == NULL) { + printf("first time create file %s\n", fs[i].mount_point); + ret = mkdir(fs[i].mount_point, S_IRUSR | S_IWUSR); + if (ret != LOS_OK) { + printf("Mkdir failed %d[%d]\n", ret, errno); + return ret; + } else { + printf("mkdir success %d\n", ret); + } + } else { + printf("open dir success!\n"); + closedir(dir); + } + } + return LFS_ERR_OK; +} + +int littlefs_block_read(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, void *buffer, lfs_size_t size) +{ + uint32_t intlock; + intlock = LOS_IntLock(); + uint32_t addr; + int partNum = (int) c->context; + switch (partNum) { + case 1: + addr = + ((uint32_t)((uint32_t)block * GD32F450ZIT6_FLASH_SECTOR_SIZE) + GD32F450ZIT6_FLASH_BANK1_SECTOR17_ADDR + off); + fmc_read_8bit_data(addr, size, buffer); + break; + case 2: + addr = + ((uint32_t)((uint32_t)block * SDRAM_BLOCK_SIZE) + SDRAM_OFFSET_ADDRESS + off + SDRAM_BLOCK_ADDRESS); + int ret = memcpy_s(buffer, size, (void*)addr, size); + if (ret != 0) { + printf("The read sdram address 0x%x is failed ret = %d",addr,ret); + LOS_IntRestore(intlock); + return LOS_NOK; + } + break; + default: + printf("partNum(%d) is out of range \n", partNum); + LOS_IntRestore(intlock); + return LOS_NOK; + } + LOS_IntRestore(intlock); + return LFS_ERR_OK; +} + +int littlefs_block_write(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, const void *buffer, + lfs_size_t size) +{ + uint32_t intlock; + intlock = LOS_IntLock(); + uint32_t addr; + int partNum = (int) c->context; + switch (partNum) { + case 1: + addr = + ((uint32_t)((uint32_t)block * GD32F450ZIT6_FLASH_SECTOR_SIZE) + GD32F450ZIT6_FLASH_BANK1_SECTOR17_ADDR + off); + fmc_write_8bit_data(addr, size, buffer); + break; + case 2: + addr = + ((uint32_t)((uint32_t)block * SDRAM_BLOCK_SIZE) + SDRAM_OFFSET_ADDRESS + off + SDRAM_BLOCK_ADDRESS); + int ret = memcpy_s((void*)addr, size, buffer, size); + if (ret != 0) { + printf("The write sdram address 0x%x is failed ret = %d",addr,ret); + LOS_IntRestore(intlock); + return LOS_NOK; + } + break; + default: + printf("partNum(%d) is out of range \n", partNum); + LOS_IntRestore(intlock); + return LOS_NOK; + } + LOS_IntRestore(intlock); + return LFS_ERR_OK; +} + +int littlefs_block_erase(const struct lfs_config *c, lfs_block_t block) +{ + uint32_t intlock; + intlock = LOS_IntLock(); + uint32_t addr; + int partNum = (int) c->context; + switch (partNum) { + case 1: + addr = + (uint32_t)(GD32F450ZIT6_FLASH_BANK1_SECTOR17_ADDR + (block * GD32F450ZIT6_FLASH_SECTOR_SIZE)); + fmc_erase_sector_by_address(addr); + break; + case 2: + addr = + ((uint32_t)((uint32_t)block * SDRAM_BLOCK_SIZE) + SDRAM_OFFSET_ADDRESS + SDRAM_BLOCK_ADDRESS); + int ret = memset_s((void *)addr,SDRAM_BLOCK_SIZE , 0xff, SDRAM_BLOCK_SIZE); + if (ret != 0) { + printf("The earse sdram address 0x%x is failed ret = %d",addr,ret); + LOS_IntRestore(intlock); + return LOS_NOK; + } + break; + default: + printf("partNum(%d) is out of range \n", partNum); + LOS_IntRestore(intlock); + return LOS_NOK; + } + LOS_IntRestore(intlock); + return LFS_ERR_OK; +} + +int littlefs_block_sync(const struct lfs_config *c) +{ + return LFS_ERR_OK; +} + +static int g_FileHandlerArray[MAX_OPEN_FILE_NUM] = { + SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, + SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, + SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, + SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, + SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE, SLOT_AVAILABLE +}; + +static int GetAvailableFileHandlerIndex(void) +{ + int i = MAX_OPEN_FILE_NUM; + + for (; i > 0; i--) { + if (g_FileHandlerArray[i - 1] == SLOT_AVAILABLE) { + break; + } + } + + return i; +} +static int ConvertFlags(int oflag) +{ + int ret = 0; + int buffer = 0; + + buffer = (oflag & RD_WR_FIELD_MASK); + if (buffer == O_RDONLY_FS) { + ret = O_RDONLY; + } else if (buffer == O_WRONLY_FS) { + ret = O_WRONLY; + } else if (buffer == O_RDWR_FS) { + ret = O_RDWR; + } + + buffer = (oflag & CREAT_EXCL_FIELD_MASK); + if ((buffer & O_CREAT_FS) != 0) { + ret |= O_CREAT; + } + + if ((buffer & O_EXCL_FS) != 0) { + ret |= O_EXCL; + } + + buffer = (oflag & TRUNC_FILED_MASK); + if ((buffer & O_TRUNC_FS) != 0) { + ret |= O_TRUNC; + } + + if ((buffer & O_APPEND_FS) != 0) { + ret |= O_APPEND; + } + + return ret; +} + +static char *GetActualFilePath(const char *path) +{ + int len; + char *file_path = NULL; + + len = strnlen(path, MAX_PATH_LEN); + if (len >= MAX_PATH_LEN) { + printf("path is too long!\r\n"); + return NULL; + } + + len += (strlen(RAM_ROOT_PATH) + ADDITIONAL_LEN); + file_path = (char *)malloc(len); + if (file_path == NULL) { + printf("malloc failed!\r\n"); + return NULL; + } + + strcpy_s(file_path, len, RAM_ROOT_PATH); + strcat_s(file_path, len, DIR_SEPARATOR); + strcat_s(file_path, len, path); + + return file_path; +} + +int HalFileOpen(const char *path, int oflag, int mode) +{ + int index; + int fd; + char *file_path; + + index = GetAvailableFileHandlerIndex(); + if (index == 0) { + printf("error: can not find index available!\n"); + return HAL_ERROR; + } + + file_path = GetActualFilePath(path); + if (file_path == NULL) { + return HAL_ERROR; + } + + fd = open(file_path, ConvertFlags(oflag)); + if (fd < 0) { + printf("error:failed to open file : errno = %d\n", errno); + free(file_path); + return HAL_ERROR; + } + + g_FileHandlerArray[index - 1] = fd; + free(file_path); + + return index; +} + +int HalFileClose(int fd) +{ + int ret; + + /* make sure fd is within the allowed range, which is 1 to MAX_OPEN_FILE_NUM */ + if ((fd > MAX_OPEN_FILE_NUM) || (fd <= 0)) { + printf("error: close: fd(%d) is out of range!\n", fd); + return HAL_ERROR; + } + + ret = close(g_FileHandlerArray[fd - 1]); + if (ret != 0) { + printf("error: failed to close ret = %d!\n", ret); + return HAL_ERROR; + } + LOS_MDelay(0x0A); + + g_FileHandlerArray[fd - 1] = SLOT_AVAILABLE; + + return ret; +} + +int HalFileRead(int fd, char *buf, unsigned int len) +{ + /* make sure fd is within the allowed range, which is 1 to MAX_OPEN_FILE_NUM */ + if ((fd > MAX_OPEN_FILE_NUM) || (fd <= 0)) { + printf("error: read: fd(%d) is out of range!\n", fd); + return HAL_ERROR; + } + + return read(g_FileHandlerArray[fd - 1], buf, len); +} + +int HalFileWrite(int fd, const char *buf, unsigned int len) +{ + /* make sure fd is within the allowed range, which is 1 to MAX_OPEN_FILE_NUM */ + if ((fd > MAX_OPEN_FILE_NUM) || (fd <= 0)) { + printf("error: write: fd(%d) is out of range!\n", fd); + return HAL_ERROR; + } + + return write(g_FileHandlerArray[fd - 1], buf, len); +} + +int HalFileDelete(const char *path) +{ + char *file_path; + int ret; + + file_path = GetActualFilePath(path); + if (file_path == NULL) { + printf("error: delete: file_path == NULL\n"); + return HAL_ERROR; + } + + ret = unlink(file_path); + free(file_path); + LOS_MDelay(0x0A); + return ret; +} + +int HalFileStat(const char *path, unsigned int *fileSize) +{ + char *file_path; + struct stat f_info; + int ret; + + file_path = GetActualFilePath(path); + if (file_path == NULL) { + printf("error: stat: file_path == NULL\n"); + return HAL_ERROR; + } + + ret = stat(file_path, &f_info); + *fileSize = f_info.st_size; + free(file_path); + + return ret; +} + +int HalFileSeek(int fd, int offset, unsigned int whence) +{ + int ret = 0; + struct stat f_info; + + /* make sure fd is within the allowed range, which is 1 to MAX_OPEN_FILE_NUM */ + if ((fd > MAX_OPEN_FILE_NUM) || (fd <= 0)) { + printf("error: seek: fd(%d) is out of range!\n", fd); + return HAL_ERROR; + } + + ret = fstat(g_FileHandlerArray[fd - 1], &f_info); + if (ret != 0) { + printf("error: fail to fstat!\n"); + return HAL_ERROR; + } + + if (whence == SEEK_SET_FS) { + if (offset > f_info.st_size) { + printf("error: seek offset is more than st_size %d vs %d!\n", offset, f_info.st_size); + ret = HAL_ERROR; + } + } + + ret = lseek(g_FileHandlerArray[fd - 1], offset, whence); + if ((ret > f_info.st_size) || (ret < 0)) { + printf("error: lseek ret:f_info.st_size %d vs %d\n", ret, f_info.st_size); + return HAL_ERROR; + } + + return ret; +} \ No newline at end of file diff --git a/khdvk_450a/docs/figures/开发板接口展示图.png b/khdvk_450a/docs/figures/开发板接口展示图.png new file mode 100644 index 0000000..e619c64 Binary files /dev/null and b/khdvk_450a/docs/figures/开发板接口展示图.png differ diff --git a/khdvk_450a/docs/figures/开发板正面图.png b/khdvk_450a/docs/figures/开发板正面图.png new file mode 100644 index 0000000..8880cab Binary files /dev/null and b/khdvk_450a/docs/figures/开发板正面图.png differ diff --git a/khdvk_450a/docs/figures/开发板背面图.jpg b/khdvk_450a/docs/figures/开发板背面图.jpg new file mode 100644 index 0000000..5554560 Binary files /dev/null and b/khdvk_450a/docs/figures/开发板背面图.jpg differ diff --git a/khdvk_450a/liteos_m/BUILD.gn b/khdvk_450a/liteos_m/BUILD.gn new file mode 100755 index 0000000..802301d --- /dev/null +++ b/khdvk_450a/liteos_m/BUILD.gn @@ -0,0 +1,33 @@ +# Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. +# Licensed 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. + +import("//kernel/liteos_m/liteos.gni") + +module_name = get_path_info(rebase_path("."), "name") +module_group(module_name) { + modules = [ + "hdf_config", + "bsp", + "drivers", + "ethernet", + "key_input", + ] + + if (defined(LOSCFG_DRIVERS_HDF_USER_LCD)) { + modules += [ + "ui", + "display", + "logo", + ] + } +} diff --git a/khdvk_450a/liteos_m/bsp/BUILD.gn b/khdvk_450a/liteos_m/bsp/BUILD.gn new file mode 100644 index 0000000..3787e45 --- /dev/null +++ b/khdvk_450a/liteos_m/bsp/BUILD.gn @@ -0,0 +1,115 @@ +# Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. +# Licensed 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. + +import("//kernel/liteos_m/liteos.gni") + +config("public") { + lib_dirs = [ "$root_out_dir/libs" ] + + ldflags = [ "-Wl,-T" + rebase_path("startup/gd32f4xx_flash.ld") ] + + include_dirs = [ + "startup", + "sdram", + "../key_input", + "../ui", + "//commonlibrary/utils_lite/include/", + "//drivers/hdf_core/framework/include/osal", + "//drivers/hdf_core/framework/include/utils", + "//drivers/hdf_core/adapter/khdf/liteos_m/osal/include", + "//drivers/hdf_core/framework/include/platform", + "//base/hiviewdfx/hilog_lite/interfaces/native/innerkits", + "//device/board/kaihong/khdvk_450a/liteos_m/logo/logo_src/", + ] + ldflags += [ + "-Wl,--whole-archive", + "-lbootstrap", + "-lbroadcast", + "-lparam_client_lite", + ] + + if (build_xts) { + ldflags += [ + "-lhctest", + + # 公共基础库 + "-lmodule_ActsUtilsFileTest", + # "-lmodule_ActsKvStoreTest", + + "-lmodule_ActsWifiIotTest", + + # DFX + "-lmodule_ActsDfxFuncTest", + "-lmodule_ActsHieventLiteTest", + + # 启动恢复 + "-lmodule_ActsBootstrapTest", + "-lmodule_ActsParameterTest", + + # 分布式任务调度 + "-lmodule_ActsSamgrTest", + + # 安全 + "-lmodule_ActsHuksHalFunctionTest", + "-lhuks_test_common", + + # 升级 + "-lmodule_ActsUpdaterFuncTest", + + # LwIP + "-lmodule_ActsLwipTest", + ] + defines = [ + "CONFIG_I2C_SUPPORT", + "CONFIG_PWM_SUPPORT", + ] + } + + ldflags += force_lib_flag + ldflags += [ "-Wl,--no-whole-archive" ] + + libs = [ + "c", + "m", + "stdc++", + "nosys", + ] +} +module_name = "bsp" +kernel_module(module_name) { + sources = [ + "platform/hm_sys.c", + "platform/printf.c", + "sdram/exmc_sdram.c", + "startup/gd32f4xx_it.c", + "startup/gd32f4xx_systick.c", + "startup/main.c", + "startup/startup_gd32f4xx.s", + "usart/usart.c", + ] + + if (defined(LOSCFG_RECV_USART_SPECIFIC_DATA_THEN_RESET)) { + sources += [ "bootloader_reset/bootloader_reset.c" ] + } + + if (defined(LOSCFG_DRIVERS_USER_KEY_INPUT)) { + sources += [ "key_input/key_input_gd32f450.c" ] + } + + include_dirs = [ "usart" ] + + deps = [ + "$ohos_board_adapter_dir/hals/iot_hardware/wifiiot_lite:hal_iothardware", + "//base/startup/syspara_lite/frameworks/parameter/src:sysparam", + ] +} diff --git a/khdvk_450a/liteos_m/bsp/bootloader_reset/bootloader_reset.c b/khdvk_450a/liteos_m/bsp/bootloader_reset/bootloader_reset.c new file mode 100755 index 0000000..d26b0a3 --- /dev/null +++ b/khdvk_450a/liteos_m/bsp/bootloader_reset/bootloader_reset.c @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 "uart_if.h" +#include "cmsis_os2.h" +#include "ohos_init.h" +#include "los_task.h" + +#define UART_BUFFER_LEN_RX 64 +#define UART_RX_IDLE0 0 +#define UART_RX_IDLE1 1 +#define UART_RX_IDLE2 2 +#define UART_RX_IDLE3 3 +#define UART_RX_IDLE4 4 +#define UART_RX_IDLE5 5 +#define UART_RX_IDLE6 6 +#define UART_RX_IDLE7 7 +#define OFFSET 8 +#define DELAY_TIME 10 +#define TASK_PRIORITY 6 + +typedef struct { + uint32_t rxLen; + uint8_t rxStat; + uint8_t rsv[3]; + uint8_t *rxPtr; + uint8_t rxBuffer[UART_BUFFER_LEN_RX]; +} UART_INFO; +static UART_INFO uart0; +static uint32_t restLen; +uint8_t usart_get_crc(void) +{ + uint32_t i; + uint8_t crc = 0; + + for (i = 0; i < uart0.rxLen; i++) { + crc += uart0.rxBuffer[i]; + } + + return ~crc; +} +void uart_buff_init(void) +{ + uart0.rxLen = 0; + uart0.rxPtr = uart0.rxBuffer; + uart0.rxStat = 0; + memset_s(&uart0.rxBuffer, UART_BUFFER_LEN_RX, 0, UART_BUFFER_LEN_RX); +} + +static int32_t Uart0Add(char uChar) +{ + uart0.rxStat++; + *uart0.rxPtr = uChar; + uart0.rxPtr++; + uart0.rxLen++; + return uart0.rxStat; +} + +static void HandleByOrder(char uChar) +{ + switch (uart0.rxStat) { + case UART_RX_IDLE0: + if (uChar == 0x5) { + uart0.rxLen = 0; + uart0.rxPtr = uart0.rxBuffer; + Uart0Add(uChar); + } + break; + case UART_RX_IDLE1: + uart0.rxStat = (uChar == 0x5) ? Uart0Add(uChar) : 0; + break; + case UART_RX_IDLE2: + case UART_RX_IDLE3: + uart0.rxStat = (uChar == 0xa) ? Uart0Add(uChar) : 0; + break; + case UART_RX_IDLE4: + uart0.rxStat = (uChar == 0) ? Uart0Add(uChar) : 0; + break; + case UART_RX_IDLE5: + Uart0Add(uChar); + restLen = uChar; + break; + case UART_RX_IDLE6: + Uart0Add(uChar); + restLen = (restLen << OFFSET) | uChar; + if (restLen == OFFSET) { + restLen = 1; + } else { + uart0.rxStat = 0; + } + break; + case UART_RX_IDLE7: + if (uart0.rxLen >= UART_BUFFER_LEN_RX) { + uart0.rxStat = 0; + break; + } + Uart0Add(uChar); + uart0.rxStat--; + restLen--; + if (restLen != 0) { + break; + } + if (usart_get_crc() == 0) { + NVIC_SystemReset(); + } else { + uart0.rxStat = 0; + } + default: + break; + } +} +void StartResetBootloader(void) +{ + uint32_t port = 0; + int32_t ret; + uint32_t baudRate; + uint8_t uChar; + DevHandle handle = NULL; + handle = UartOpen(port); + if (handle == NULL) { + printf("UartOpen %u: failed!\n", port); + return NULL; + } + ret = UartSetTransMode(handle, UART_MODE_RD_BLOCK); + if (ret != 0) { + return; + } + uart_buff_init(); + int t = 1; + while (t > 0) { + ret = UartRead(handle, &uChar, 1); + if (ret < 0) { + printf("UartRead: failed, ret %d\n", ret); + UartClose(handle); + return; + } + HandleByOrder(uChar); + } +} + +static void ResetBootloader(void) +{ + uint32_t uwRet; + uint32_t taskID; + TSK_INIT_PARAM_S stTask = {0}; + + stTask.pfnTaskEntry = (TSK_ENTRY_FUNC)StartResetBootloader; + stTask.uwStackSize = 0x1000; + stTask.pcName = "StartResetBootloader"; + stTask.usTaskPrio = TASK_PRIORITY; + uwRet = LOS_TaskCreate(&taskID, &stTask); + if (uwRet != LOS_OK) { + printf("ResetBootloader Task create failed\r\n"); + } +} + +SYS_RUN(ResetBootloader); diff --git a/khdvk_450a/liteos_m/bsp/platform/hm_sys.c b/khdvk_450a/liteos_m/bsp/platform/hm_sys.c new file mode 100644 index 0000000..c4de282 --- /dev/null +++ b/khdvk_450a/liteos_m/bsp/platform/hm_sys.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 "gd32f4xx.h" + +/** + * @brief Initiates a system reset request to reset the MCU. + * @retval None + */ +void HAL_NVIC_SystemReset(void) +{ + /* System Reset */ + NVIC_SystemReset(); +} diff --git a/khdvk_450a/liteos_m/bsp/platform/printf.c b/khdvk_450a/liteos_m/bsp/platform/printf.c new file mode 100644 index 0000000..11c752d --- /dev/null +++ b/khdvk_450a/liteos_m/bsp/platform/printf.c @@ -0,0 +1,826 @@ +/* + *Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. +*/ +/////////////////////////////////////////////////////////////////////////////// +// \author (c) Marco Paland (info@paland.com) +// 2014-2019, PALANDesign Hannover, Germany +// +// \license The MIT License (MIT) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +// \brief Tiny printf, sprintf and (v)snprintf implementation, optimized for speed on +// embedded systems with a very limited resources. These routines are thread +// safe and reentrant! +// Use this instead of the bloated standard/newlib printf cause these use +// malloc for printf (and may not be thread safe). +// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include "usart.h" + +// define this globally (e.g. gcc -DPRINTF_INCLUDE_CONFIG_H ...) to include the +// printf_config.h header file +// default: undefined +#ifdef PRINTF_INCLUDE_CONFIG_H +#include "printf_config.h" +#endif + +// 'ntoa' conversion buffer size, this must be big enough to hold one converted +// numeric number including padded zeros (dynamically created on stack) +// default: 32 byte +#ifndef PRINTF_NTOA_BUFFER_SIZE +#define PRINTF_NTOA_BUFFER_SIZE 32U +#endif + +// 'ftoa' conversion buffer size, this must be big enough to hold one converted +// float number including padded zeros (dynamically created on stack) +// default: 32 byte +#ifndef PRINTF_FTOA_BUFFER_SIZE +#define PRINTF_FTOA_BUFFER_SIZE 32U +#endif + +// support for the floating point type (%f) +// default: activated +#ifndef PRINTF_DISABLE_SUPPORT_FLOAT +#define PRINTF_SUPPORT_FLOAT +#endif + +// define the default floating point precision +// default: 6 digits +#ifndef PRINTF_DEFAULT_FLOAT_PRECISION +#define PRINTF_DEFAULT_FLOAT_PRECISION 6U +#endif + +// define the largest float suitable to print with %f +// default: 1e9 +#ifndef PRINTF_MAX_FLOAT +#define PRINTF_MAX_FLOAT 1e9 +#endif + +// support for the long long types (%llu or %p) +// default: activated +#ifndef PRINTF_DISABLE_SUPPORT_LONG_LONG +#define PRINTF_SUPPORT_LONG_LONG +#endif + +// support for the ptrdiff_t type (%t) +// ptrdiff_t is normally defined in as long or long long type +// default: activated +#ifndef PRINTF_DISABLE_SUPPORT_PTRDIFF_T +#define PRINTF_SUPPORT_PTRDIFF_T +#endif + +// internal flag definitions +#define FLAGS_ZEROPAD (1U << 0U) +#define FLAGS_LEFT (1U << 1U) +#define FLAGS_PLUS (1U << 2U) +#define FLAGS_SPACE (1U << 3U) +#define FLAGS_HASH (1U << 4U) +#define FLAGS_UPPERCASE (1U << 5U) +#define FLAGS_CHAR (1U << 6U) +#define FLAGS_SHORT (1U << 7U) +#define FLAGS_LONG (1U << 8U) +#define FLAGS_LONG_LONG (1U << 9U) +#define FLAGS_PRECISION (1U << 10U) +#define FLAGS_ADAPT_EXP (1U << 11U) + +// import float.h for DBL_MAX +#if defined(PRINTF_SUPPORT_FLOAT) +#include +#endif + +// output function type +typedef void (*out_fct_type)(char character, void *buffer, int idx, int maxlen); + +// wrapper (used as buffer) for output function type +typedef struct { + void (*fct)(char character, void *arg); + void *arg; +} out_fct_wrap_type; + +// internal buffer output +static inline void Gd32OutBuffer(char character, void *buffer, int idx, int maxlen) +{ + if (idx < maxlen) { + ((char *)buffer)[idx] = character; + } +} + +// internal null output +static inline void Gd32OutNull(char character, void *buffer, int idx, int maxlen) +{ + (void)character; + (void)buffer; + (void)idx; + (void)maxlen; +} + +static inline void Gd32OutChar(char character, void *buffer, int idx, int maxlen) +{ + (void)buffer; + (void)idx; + (void)maxlen; + if (character) { + Gd32IoPutChar(character); + } +} + +// internal output function wrapper +static inline void Gd32OutFct(char character, void *buffer, int idx, int maxlen) +{ + (void)idx; + (void)maxlen; + if (character) { + // buffer is the output fct pointer + ((out_fct_wrap_type *)buffer)->fct(character, ((out_fct_wrap_type *)buffer)->arg); + } +} + +// internal secure strlen +// \return The length of the string (excluding the terminating 0) limited by 'maxsize' +static inline unsigned int Gd32Strnlen(const char *str, int maxsizein) +{ + int maxsize = maxsizein; + const char *s; + for (s = str; *s && maxsize--; ++s) { } + return (unsigned int)(s - str); +} + +// internal test if char is a digit (0-9) +// \return true if char is a digit +static inline bool _is_digit(char ch) +{ + return (ch >= '0') && (ch <= '9'); +} + +// internal ASCII string to unsigned int conversion +#define INTERVAL_ATOI 10U +static unsigned int _atoi(const char **str) +{ + unsigned int i = 0U; + while (_is_digit(**str)) { + i = i * INTERVAL_ATOI + (unsigned int)(*((*str)++) - '0'); + } + return i; +} + +// output the specified string in reverse, taking care of any zero-padding +static int Gd32OutRev(out_fct_type out, char *buffer, int idxin, int maxlen, const char *buf, int length, + unsigned int width, unsigned int flags) +{ + const int start_idx = idxin; + int idx = idxin; + int len = length; + // pad spaces up to given width + if (!(flags & FLAGS_LEFT) && !(flags & FLAGS_ZEROPAD)) { + for (int i = len; i < width; i++) { + out(' ', buffer, idx++, maxlen); + } + } + + // reverse string + while (len) { + out(buf[--len], buffer, idx++, maxlen); + } + + // append pad spaces up to given width + if (flags & FLAGS_LEFT) { + while (idx - start_idx < width) { + out(' ', buffer, idx++, maxlen); + } + } + + return idx; +} +#define HEXADECIMAL 16U +#define OCTONARY 8U +#define BINARY 2U + +// internal itoa format +static int Gd32NtoaFormat(out_fct_type out, char *buffer, int idx, int maxlen, char *buf, int length, bool negative, + unsigned int base, unsigned int prec, unsigned int widthin, unsigned int flags) +{ + int len = length; + int width = widthin; + // pad leading zeros + if (!(flags & FLAGS_LEFT)) { + if (width && (flags & FLAGS_ZEROPAD) && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) { + width--; + } + while ((len < prec) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = '0'; + } + while ((flags & FLAGS_ZEROPAD) && (len < width) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = '0'; + } + } + + // handle hash + if (flags & FLAGS_HASH) { + if (!(flags & FLAGS_PRECISION) && len && ((len == prec) || (len == width))) { + len--; + if (len && (base == HEXADECIMAL)) { + len--; + } + } + if ((base == HEXADECIMAL) && !(flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = 'x'; + } else if ((base == HEXADECIMAL) && (flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = 'X'; + } else if ((base == BINARY) && (len < PRINTF_NTOA_BUFFER_SIZE)) { + buf[len++] = 'b'; + } + if (len < PRINTF_NTOA_BUFFER_SIZE) { + buf[len++] = '0'; + } + } + + if (len < PRINTF_NTOA_BUFFER_SIZE) { + if (negative) { + buf[len++] = '-'; + } else if (flags & FLAGS_PLUS) { + buf[len++] = '+'; // ignore the space if the '+' exists + } else if (flags & FLAGS_SPACE) { + buf[len++] = ' '; + } + } + + return Gd32OutRev(out, buffer, idx, maxlen, buf, len, width, flags); +} + +// internal itoa for 'long' type +static int Gd32NtoaLong(out_fct_type out, char *buffer, int idx, int maxlen, unsigned long valuein, bool negative, + unsigned long base, unsigned int prec, unsigned int width, unsigned int flagsin) +{ + char buf[PRINTF_NTOA_BUFFER_SIZE]; + int len = 0U; + unsigned int flags = flagsin; + unsigned long value = valuein; + // no hash for 0 values + if (!value) { + flags &= ~FLAGS_HASH; + } + + // write if precision != 0 and value is != 0 + if (!(flags & FLAGS_PRECISION) || value) { + do { + if (base == 0) { + return 0; + } + const char digit = (char)(value % base); + buf[len++] = digit < 0x0A ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 0x0A; + value /= base; + } while (value && (len < PRINTF_NTOA_BUFFER_SIZE)); + } + + return Gd32NtoaFormat(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags); +} +#define MAX_DIGITS 9 + +// internal itoa for 'long long' type +#if defined(PRINTF_SUPPORT_LONG_LONG) +static int Gd32NtoaLongLong(out_fct_type out, char *buffer, int idx, int maxlen, unsigned long long valuein, + bool negative, unsigned long long base, unsigned int prec, unsigned int width, + unsigned int flagsin) +{ + char buf[PRINTF_NTOA_BUFFER_SIZE]; + int len = 0U; + unsigned int flags = flagsin; + unsigned long long value = valuein; + // no hash for 0 values + if (!value) { + flags &= ~FLAGS_HASH; + } + + // write if precision != 0 and value is != 0 + if (!(flags & FLAGS_PRECISION) || value) { + do { + if (base == 0) { + return 0; + } + const char digit = (char)(value % base); + buf[len++] = digit < (MAX_DIGITS + 1) ? '0' + digit + : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - (MAX_DIGITS + 1); + value /= base; + } while (value && (len < PRINTF_NTOA_BUFFER_SIZE)); + } + + return Gd32NtoaFormat(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags); +} +#endif // PRINTF_SUPPORT_LONG_LONG + +#if defined(PRINTF_SUPPORT_FLOAT) + +#define LIMIT_PRECISION 9U +// internal ftoa for fixed decimal floating point +static int Gd32Ftoa(out_fct_type out, char *buffer, int idx, int maxlen, double valuein, unsigned int precin, + unsigned int widthin, unsigned int flags) +{ + char buf[PRINTF_FTOA_BUFFER_SIZE]; + int len = 0U; + double diff = 0.0; + double value = valuein; + unsigned int prec = precin; + unsigned int width = widthin; + // powers of 10 + static const double pow10[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000}; + + // test for special values + if (value != value) { + return Gd32OutRev(out, buffer, idx, maxlen, "nan", sizeof("nan"), width, flags); + } + if (value < -DBL_MAX) { + return Gd32OutRev(out, buffer, idx, maxlen, "fni-", sizeof("fni-"), width, flags); + } + if (value > DBL_MAX) { + return Gd32OutRev(out, buffer, idx, maxlen, (flags & FLAGS_PLUS) ? "fni+" : "fni", + (flags & FLAGS_PLUS) ? sizeof("fni+") : sizeof("fni"), width, flags); + } + + // test for very large values + // standard printf behavior is to print EVERY whole number digit + // -- which could be 100s of characters overflowing your buffers == bad + if ((value > PRINTF_MAX_FLOAT) || (value < -PRINTF_MAX_FLOAT)) { + return 0U; + } + + // test for negative + bool negative = false; + if (value < 0) { + negative = true; + value = 0 - value; + } + + // set default precision, if not set explicitly + if (!(flags & FLAGS_PRECISION)) { + prec = PRINTF_DEFAULT_FLOAT_PRECISION; + } + // limit precision to 9, cause a prec >= 10 can lead to overflow errors + while ((len < PRINTF_FTOA_BUFFER_SIZE) && (prec > LIMIT_PRECISION)) { + buf[len++] = '0'; + prec--; + } + + int whole = (int)value; + double tmp = (value - whole) * pow10[prec]; + unsigned long frac = (unsigned long)tmp; + diff = tmp - frac; +#define MIN_PRECISION 0.5 + if (diff > MIN_PRECISION) { + ++frac; + // handle rollover, e.g. case 0.99 with prec 1 is 1.0 + if (frac >= pow10[prec]) { + frac = 0; + ++whole; + } + } else if (diff < MIN_PRECISION) { + } else if ((frac == 0U) || (frac & 1U)) { + // if halfway, round up if odd OR if last digit is 0 + ++frac; + } + + if (prec == 0U) { + diff = value - (double)whole; + if ((!(diff < MIN_PRECISION) || (diff > MIN_PRECISION)) && (whole & 1)) { + // exactly 0.5 and ODD, then round up + // 1.5 -> 2, but 2.5 -> 2 + ++whole; + } + } else { + unsigned int count = prec; + // now do fractional part, as an unsigned number + while (len < PRINTF_FTOA_BUFFER_SIZE) { + --count; + buf[len++] = (char)(0x30 + (frac % 0x0A)); + if (!(frac /= 0x0A)) { + break; + } + } + // add extra 0s + while ((len < PRINTF_FTOA_BUFFER_SIZE) && (count-- > 0U)) { + buf[len++] = '0'; + } + if (len < PRINTF_FTOA_BUFFER_SIZE) { + // add decimal + buf[len++] = '.'; + } + } + + // do whole part, number is reversed + while (len < PRINTF_FTOA_BUFFER_SIZE) { + buf[len++] = (char)(0x30 + (whole % 0x0A)); + if (!(whole /= 0x0A)) { + break; + } + } + + // pad leading zeros + if (!(flags & FLAGS_LEFT) && (flags & FLAGS_ZEROPAD)) { + if (width && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) { + width--; + } + while ((len < width) && (len < PRINTF_FTOA_BUFFER_SIZE)) { + buf[len++] = '0'; + } + } + + if (len < PRINTF_FTOA_BUFFER_SIZE) { + if (negative) { + buf[len++] = '-'; + } else if (flags & FLAGS_PLUS) { + buf[len++] = '+'; // ignore the space if the '+' exists + } else if (flags & FLAGS_SPACE) { + buf[len++] = ' '; + } + } + + return Gd32OutRev(out, buffer, idx, maxlen, buf, len, width, flags); +} + +#endif // PRINTF_SUPPORT_FLOAT + +// internal vsnprintf +static int Gd32Vsnintf(out_fct_type outin, char *buffer, const int maxlen, const char *formatin, va_list va) +{ + unsigned int flags, width, precision, n; + int idx = 0U; + const char *format = formatin; + out_fct_type out = outin; + if (!buffer) { + // use null output function + out = Gd32OutNull; + } + + while (*format) { + // format specifier? %[flags][width][.precision][length] + if (*format != '%') { + // no + out(*format, buffer, idx++, maxlen); + format++; + continue; + } else { + // yes, evaluate it + format++; + } + + // evaluate flags + flags = 0U; + do { + switch (*format) { + case '0': + flags |= FLAGS_ZEROPAD; + format++; + n = 1U; + break; + case '-': + flags |= FLAGS_LEFT; + format++; + n = 1U; + break; + case '+': + flags |= FLAGS_PLUS; + format++; + n = 1U; + break; + case ' ': + flags |= FLAGS_SPACE; + format++; + n = 1U; + break; + case '#': + flags |= FLAGS_HASH; + format++; + n = 1U; + break; + default: + n = 0U; + break; + } + } while (n); + + // evaluate width field + width = 0U; + if (_is_digit(*format)) { + width = _atoi(&format); + } else if (*format == '*') { + const int w = va_arg(va, int); + if (w < 0) { + flags |= FLAGS_LEFT; // reverse padding + width = (unsigned int)-w; + } else { + width = (unsigned int)w; + } + format++; + } + + // evaluate precision field + precision = 0U; + if (*format == '.') { + flags |= FLAGS_PRECISION; + format++; + if (_is_digit(*format)) { + precision = _atoi(&format); + } else if (*format == '*') { + const int prec = (int)va_arg(va, int); + precision = prec > 0 ? (unsigned int)prec : 0U; + format++; + } + } + + // evaluate length field + switch (*format) { + case 'l': + flags |= FLAGS_LONG; + format++; + if (*format == 'l') { + flags |= FLAGS_LONG_LONG; + format++; + } + break; + case 'h': + flags |= FLAGS_SHORT; + format++; + if (*format == 'h') { + flags |= FLAGS_CHAR; + format++; + } + break; +#if defined(PRINTF_SUPPORT_PTRDIFF_T) + case 't': + flags |= (sizeof(ptrdiff_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); + format++; + break; +#endif + case 'j': + flags |= (sizeof(intmax_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); + format++; + break; + case 'z': + flags |= (sizeof(int) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); + format++; + break; + default: + break; + } + + // evaluate specifier + switch (*format) { + case 'd': + case 'i': + case 'u': + case 'x': + case 'X': + case 'o': + case 'b': { + // set the base + unsigned int base; + if (*format == 'x' || *format == 'X') { + base = 16U; + } else if (*format == 'o') { + base = 8U; + } else if (*format == 'b') { + base = 2U; + } else { + base = 10U; + flags &= ~FLAGS_HASH; // no hash for dec format + } + // uppercase + if (*format == 'X') { + flags |= FLAGS_UPPERCASE; + } + + // no plus or space flag for u, x, X, o, b + if ((*format != 'i') && (*format != 'd')) { + flags &= ~(FLAGS_PLUS | FLAGS_SPACE); + } + + // ignore '0' flag when precision is given + if (flags & FLAGS_PRECISION) { + flags &= ~FLAGS_ZEROPAD; + } + + // convert the integer + if ((*format == 'i') || (*format == 'd')) { + // signed + if (flags & FLAGS_LONG_LONG) { +#if defined(PRINTF_SUPPORT_LONG_LONG) + const long long value = va_arg(va, long long); + idx = Gd32NtoaLongLong(out, buffer, idx, maxlen, + (unsigned long long)(value > 0 ? value : 0 - value), value < 0, base, + precision, width, flags); +#endif + } else if (flags & FLAGS_LONG) { + const long value = va_arg(va, long); + idx = Gd32NtoaLong(out, buffer, idx, maxlen, (unsigned long)(value > 0 ? value : 0 - value), + value < 0, base, precision, width, flags); + } else { + const int value = (flags & FLAGS_CHAR) ? (char)va_arg(va, int) + : (flags & FLAGS_SHORT) ? (short int)va_arg(va, int) + : va_arg(va, int); + idx = Gd32NtoaLong(out, buffer, idx, maxlen, (unsigned int)(value > 0 ? value : 0 - value), + value < 0, base, precision, width, flags); + } + } else { + // unsigned + if (flags & FLAGS_LONG_LONG) { +#if defined(PRINTF_SUPPORT_LONG_LONG) + idx = Gd32NtoaLongLong(out, buffer, idx, maxlen, va_arg(va, unsigned long long), false, base, + precision, width, flags); +#endif + } else if (flags & FLAGS_LONG) { + idx = Gd32NtoaLong(out, buffer, idx, maxlen, va_arg(va, unsigned long), false, base, precision, + width, flags); + } else { + const unsigned int value = (flags & FLAGS_CHAR) ? (unsigned char)va_arg(va, unsigned int) + : (flags & FLAGS_SHORT) + ? (unsigned short int)va_arg(va, unsigned int) + : va_arg(va, unsigned int); + idx = Gd32NtoaLong(out, buffer, idx, maxlen, value, false, base, precision, width, flags); + } + } + format++; + break; + } +#if defined(PRINTF_SUPPORT_FLOAT) + case 'f': + case 'F': + if (*format == 'F') { + flags |= FLAGS_UPPERCASE; + } + idx = Gd32Ftoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags); + format++; + break; +#endif // PRINTF_SUPPORT_FLOAT + case 'c': { + unsigned int l = 1U; + // pre padding + if (!(flags & FLAGS_LEFT)) { + while (l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + // char output + out((char)va_arg(va, int), buffer, idx++, maxlen); + // post padding + if (flags & FLAGS_LEFT) { + while (l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + format++; + break; + } + + case 's': { + const char *p = va_arg(va, char *); + if (!p) { + p = '(null)'; + } + unsigned int l = Gd32Strnlen(p, precision ? precision : (int)-1); + // pre padding + if (flags & FLAGS_PRECISION) { + l = (l < precision ? l : precision); + } + if (!(flags & FLAGS_LEFT)) { + while (l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + // string output + while ((*p != 0) && (!(flags & FLAGS_PRECISION) || precision--)) { + out(*(p++), buffer, idx++, maxlen); + } + // post padding + if (flags & FLAGS_LEFT) { + while (l++ < width) { + out(' ', buffer, idx++, maxlen); + } + } + format++; + break; + } + + case 'p': { + width = sizeof(void *) * 2U; + flags |= FLAGS_ZEROPAD | FLAGS_UPPERCASE; +#if defined(PRINTF_SUPPORT_LONG_LONG) + const bool is_ll = sizeof(uintptr_t) == sizeof(long long); + if (is_ll) { + idx = Gd32NtoaLongLong(out, buffer, idx, maxlen, (uintptr_t)va_arg(va, void *), false, 16U, + precision, width, flags); + } else { +#endif + idx = Gd32NtoaLong(out, buffer, idx, maxlen, (unsigned long)((uintptr_t)va_arg(va, void *)), false, + 16U, precision, width, flags); +#if defined(PRINTF_SUPPORT_LONG_LONG) + } +#endif + format++; + break; + } + + case '%': + out('%', buffer, idx++, maxlen); + format++; + break; + + default: + out(*format, buffer, idx++, maxlen); + format++; + break; + } + } + + // termination + out((char)0, buffer, idx < maxlen ? idx : maxlen - 1U, maxlen); + + // return written chars without terminating \0 + return (int)idx; +} + +#include "cmsis_os2.h" +static osMutexId_t g_MuxUart = NULL; +int InitUartMutex(void) +{ + g_MuxUart = osMutexNew(NULL); + if (g_MuxUart != NULL) { + printf("\ncreat g_MuxUart=%d ok\n", g_MuxUart); + } + + return 0; +} +int __wrap_printf(const char *format, ...) +{ + va_list va; + if (g_MuxUart != NULL) { + osMutexAcquire(g_MuxUart, osWaitForever); + } + va_start(va, format); + char buffer[1]; + const int ret = Gd32Vsnintf(Gd32OutChar, buffer, (int)-1, format, va); + va_end(va); + if (g_MuxUart != NULL) { + osMutexRelease(g_MuxUart); + } + return ret; +} + +int __wrap_sprintf(char *buffer, const char *format, ...) +{ + va_list va; + va_start(va, format); + const int ret = Gd32Vsnintf(Gd32OutBuffer, buffer, 0x7fffffff, format, va); + va_end(va); + return ret; +} + +int __wrap_snprintf(char *buffer, int count, const char *format, ...) +{ + va_list va; + va_start(va, format); + const int ret = Gd32Vsnintf(Gd32OutBuffer, buffer, count, format, va); + va_end(va); + return ret; +} + +int __wrap_vprintf(const char *format, va_list va) +{ + char buffer[1]; + return Gd32Vsnintf(Gd32OutChar, buffer, 0x7fffffff, format, va); +} + +int __wrap_vsnprintf(char *buffer, int count, const char *format, va_list va) +{ + return Gd32Vsnintf(Gd32OutBuffer, buffer, count, format, va); +} + +int fctprintf(void (*out)(char character, void *arg), void *arg, const char *format, ...) +{ + va_list va; + va_start(va, format); + const out_fct_wrap_type out_fct_wrap = {out, arg}; + const int ret = Gd32Vsnintf(Gd32OutFct, (char *)(uintptr_t)&out_fct_wrap, (int)-1, format, va); + va_end(va); + return ret; +} diff --git a/khdvk_450a/liteos_m/bsp/sdram/exmc_sdram.c b/khdvk_450a/liteos_m/bsp/sdram/exmc_sdram.c new file mode 100644 index 0000000..e79578e --- /dev/null +++ b/khdvk_450a/liteos_m/bsp/sdram/exmc_sdram.c @@ -0,0 +1,435 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 "gd32f4xx.h" +#include "gd32f4xx_systick.h" +#include "exmc_sdram.h" + +/* define mode register content */ +/* burst length */ +#define SDRAM_MODEREG_BURST_LENGTH_1 ((uint16_t)0x0000) +#define SDRAM_MODEREG_BURST_LENGTH_2 ((uint16_t)0x0001) +#define SDRAM_MODEREG_BURST_LENGTH_4 ((uint16_t)0x0002) +#define SDRAM_MODEREG_BURST_LENGTH_8 ((uint16_t)0x0003) + +/* burst type */ +#define SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL ((uint16_t)0x0000) +#define SDRAM_MODEREG_BURST_TYPE_INTERLEAVED ((uint16_t)0x0008) + +/* CAS latency */ +#define SDRAM_MODEREG_CAS_LATENCY_2 ((uint16_t)0x0020) +#define SDRAM_MODEREG_CAS_LATENCY_3 ((uint16_t)0x0030) + +/* write mode */ +#define SDRAM_MODEREG_WRITEBURST_MODE_PROGRAMMED ((uint16_t)0x0000) +#define SDRAM_MODEREG_WRITEBURST_MODE_SINGLE ((uint16_t)0x0200) + +#define SDRAM_MODEREG_OPERATING_MODE_STANDARD ((uint16_t)0x0000) + +#define SDRAM_TIMEOUT ((uint32_t)0x0000FFFF) +#define ADDR_STEP ((uint16_t)2) +void clean_bss(void) +{ + volatile unsigned int *start = (volatile unsigned int *)&__bss_start__; + volatile unsigned int *end = (volatile unsigned int *)&__bss_end__; + + printf("bss start is %p %p\n", __bss_start__, &__bss_start__); + printf("bss end is %p %p\n", __bss_end__, &__bss_end__); + while (start <= end) { + *start++ = 0; + } +} + +/*! + \brief initialize sdram peripheral + \param[in] sdram_device: specify the SDRAM device + \param[out] none + \retval none +*/ +void sdram_rcu_periph_clock_enable(void) +{ + /* enable EXMC clock */ + rcu_periph_clock_enable(RCU_EXMC); + rcu_periph_clock_enable(RCU_GPIOB); + rcu_periph_clock_enable(RCU_GPIOC); + rcu_periph_clock_enable(RCU_GPIOD); + rcu_periph_clock_enable(RCU_GPIOE); + rcu_periph_clock_enable(RCU_GPIOF); + rcu_periph_clock_enable(RCU_GPIOG); + rcu_periph_clock_enable(RCU_GPIOH); +} +void sdram_gpio_init(void) +{ + /* common GPIO configuration */ + /* SDNWE(PC0),SDNE0(PC2),SDCKE0(PC3) pin configuration */ + gpio_af_set(GPIOC, GPIO_AF_12, GPIO_PIN_0 | GPIO_PIN_2 | GPIO_PIN_3); + gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_0 | GPIO_PIN_2 | GPIO_PIN_3); + gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_0 | GPIO_PIN_2 | GPIO_PIN_3); + + /* D2(PD0),D3(PD1),D13(PD8),D14(PD9),D15(PD10),D0(PD14),D1(PD15) pin configuration */ + gpio_af_set(GPIOD, GPIO_AF_12, + GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_14 | GPIO_PIN_15); + gpio_mode_set(GPIOD, GPIO_MODE_AF, GPIO_PUPD_PULLUP, + GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_14 | GPIO_PIN_15); + gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, + GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_14 | + GPIO_PIN_15); + + /* NBL0(PE0),NBL1(PE1),D4(PE7),D5(PE8),D6(PE9),D7(PE10),D8(PE11), + D9(PE12),D10(PE13),D11(PE14),D12(PE15) pin configuration */ + gpio_af_set(GPIOE, GPIO_AF_12, + GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | + GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15); + gpio_mode_set(GPIOE, GPIO_MODE_AF, GPIO_PUPD_PULLUP, + GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | + GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15); + gpio_output_options_set(GPIOE, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, + GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | + GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15); + + /* A0(PF0),A1(PF1),A2(PF2),A3(PF3),A4(PF4),A5(PF5),NRAS(PF11), + A6(PF12),A7(PF13),A8(PF14),A9(PF15) pin configuration */ + gpio_af_set(GPIOF, GPIO_AF_12, + GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_11 | + GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15); + gpio_mode_set(GPIOF, GPIO_MODE_AF, GPIO_PUPD_PULLUP, + GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_11 | + GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15); + gpio_output_options_set(GPIOF, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, + GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_11 | + GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15); + + /* A10(PG0),A11(PG1),A12(PG2),A14(PG4),A15(PG5),SDCLK(PG8),NCAS(PG15) pin configuration */ + gpio_af_set(GPIOG, GPIO_AF_12, + GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_8 | GPIO_PIN_15); + gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_PULLUP, + GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_8 | GPIO_PIN_15); + gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, + GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_8 | GPIO_PIN_15); +} + +void sdram_timing_init_struct_configure(exmc_sdram_timing_parameter_struct *sdram_timing_init_struct) +{ + /* LMRD: 2 clock cycles */ + int16_t delay_t1 = 2; + sdram_timing_init_struct->load_mode_register_delay = delay_t1; + /* XSRD: min = 75ns */ + int16_t delay_t2 = 8; + sdram_timing_init_struct->exit_selfrefresh_delay = delay_t2; + /* RASD: min=44ns , max=120k (ns) */ + int16_t delay_t3 = 5; + sdram_timing_init_struct->row_address_select_delay = delay_t3; + /* ARFD: min=66ns */ + int16_t delay_t4 = 7; + sdram_timing_init_struct->auto_refresh_delay = delay_t4; + /* WRD: min=1 Clock cycles +7.5ns */ + int16_t delay_t5 = 2; + sdram_timing_init_struct->write_recovery_delay = delay_t5; + /* RPD: min=20ns */ + int16_t delay_t6 = 3; + sdram_timing_init_struct->row_precharge_delay = delay_t6; + /* RCD: min=20ns */ + int16_t delay_t7 = 3; + sdram_timing_init_struct->row_to_column_delay = delay_t7; +} +void sdram_init_struct_config(uint32_t sdram_device, exmc_sdram_parameter_struct *sdram_init_struct, + exmc_sdram_timing_parameter_struct *sdram_timing_init_struct) +{ + sdram_init_struct->sdram_device = sdram_device; + sdram_init_struct->column_address_width = EXMC_SDRAM_COW_ADDRESS_9; + sdram_init_struct->row_address_width = EXMC_SDRAM_ROW_ADDRESS_13; + sdram_init_struct->data_width = EXMC_SDRAM_DATABUS_WIDTH_16B; + sdram_init_struct->internal_bank_number = EXMC_SDRAM_4_INTER_BANK; + sdram_init_struct->cas_latency = EXMC_CAS_LATENCY_3_SDCLK; + sdram_init_struct->write_protection = DISABLE; + sdram_init_struct->sdclock_config = EXMC_SDCLK_PERIODS_2_HCLK; + sdram_init_struct->burst_read_switch = ENABLE; + sdram_init_struct->pipeline_read_delay = EXMC_PIPELINE_DELAY_1_HCLK; + sdram_init_struct->timing = sdram_timing_init_struct; +} +void sdram_command_init_struct_config(int step, uint32_t bank_select, uint32_t command_content, + exmc_sdram_command_parameter_struct *sdram_command_init_struct) +{ + switch (step) { + case 0x3: + sdram_command_init_struct->command = EXMC_SDRAM_CLOCK_ENABLE; + sdram_command_init_struct->bank_select = bank_select; + sdram_command_init_struct->auto_refresh_number = EXMC_SDRAM_AUTO_REFLESH_1_SDCLK; + sdram_command_init_struct->mode_register_content = 0; + break; + case 0x5: + sdram_command_init_struct->command = EXMC_SDRAM_PRECHARGE_ALL; + sdram_command_init_struct->bank_select = bank_select; + sdram_command_init_struct->auto_refresh_number = EXMC_SDRAM_AUTO_REFLESH_1_SDCLK; + sdram_command_init_struct->mode_register_content = 0; + break; + case 0x6: + sdram_command_init_struct->command = EXMC_SDRAM_AUTO_REFRESH; + sdram_command_init_struct->bank_select = bank_select; + sdram_command_init_struct->auto_refresh_number = EXMC_SDRAM_AUTO_REFLESH_8_SDCLK; + sdram_command_init_struct->mode_register_content = 0; + break; + case 0x7: + sdram_command_init_struct->command = EXMC_SDRAM_LOAD_MODE_REGISTER; + sdram_command_init_struct->bank_select = bank_select; + sdram_command_init_struct->auto_refresh_number = EXMC_SDRAM_AUTO_REFLESH_1_SDCLK; + sdram_command_init_struct->mode_register_content = command_content; + break; + default : + break; + } +} +ErrStatus time_out_check(uint32_t sdram_device) +{ + uint32_t timeout = SDRAM_TIMEOUT; + while ((exmc_flag_get(sdram_device, EXMC_SDRAM_FLAG_NREADY) != RESET) && (timeout > 0)) { + timeout--; + } + if (timeout == 0) { + printf("in %s %s:%d timeout\n", __FILE__, __FUNCTION__, __LINE__); + return ERROR; + } + return SUCCESS; +} +ErrStatus exmc_synchronous_dynamic_ram_init(uint32_t sdram_device) +{ + exmc_sdram_parameter_struct sdram_init_struct; + exmc_sdram_timing_parameter_struct sdram_timing_init_struct; + exmc_sdram_command_parameter_struct sdram_command_init_struct; + uint32_t command_content = 0, bank_select; + + sdram_rcu_periph_clock_enable(); + + sdram_gpio_init(); + /* specify which SDRAM to read and write */ + if (EXMC_SDRAM_DEVICE0 == sdram_device) { + bank_select = EXMC_SDRAM_DEVICE0_SELECT; + } else { + bank_select = EXMC_SDRAM_DEVICE1_SELECT; + } + + /* EXMC SDRAM device initialization sequence --------------------------------*/ + /* Step 1 : configure SDRAM timing registers --------------------------------*/ + sdram_timing_init_struct_configure(&sdram_timing_init_struct); + + /* step 2 : configure SDRAM control registers ---------------------------------*/ + sdram_init_struct_config(sdram_device, &sdram_init_struct, &sdram_timing_init_struct); + /* EXMC SDRAM bank initialization */ + exmc_sdram_init(&sdram_init_struct); + + /* step 3 : configure CKE high command---------------------------------------*/ + sdram_command_init_struct_config(0x3, bank_select, command_content, &sdram_command_init_struct); + /* wait until the SDRAM controller is ready */ + if (time_out_check(sdram_device) != SUCCESS) { + return ERROR; + } + /* send the command */ + exmc_sdram_command_config(&sdram_command_init_struct); + + /* step 4 : insert 10ms delay----------------------------------------------*/ + int16_t delay_t8 = 10; + Gd32f4xxDelay1ms(delay_t8); + + /* step 5 : configure precharge all command----------------------------------*/ + sdram_command_init_struct_config(0x5, bank_select, command_content, &sdram_command_init_struct); + /* wait until the SDRAM controller is ready */ + if (time_out_check(sdram_device) != SUCCESS) { + return ERROR; + } + /* send the command */ + exmc_sdram_command_config(&sdram_command_init_struct); + + /* step 6 : configure Auto-Refresh command-----------------------------------*/ + sdram_command_init_struct_config(0x6, bank_select, command_content, &sdram_command_init_struct); + /* wait until the SDRAM controller is ready */ + if (time_out_check(sdram_device) != SUCCESS) { + return ERROR; + } + /* send the command */ + exmc_sdram_command_config(&sdram_command_init_struct); + + /* step 7 : configure load mode register command-----------------------------*/ + /* program mode register */ + command_content = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_1 | SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL | + SDRAM_MODEREG_CAS_LATENCY_3 | SDRAM_MODEREG_OPERATING_MODE_STANDARD | + SDRAM_MODEREG_WRITEBURST_MODE_SINGLE; + + sdram_command_init_struct_config(0x7, bank_select, command_content, &sdram_command_init_struct); + + /* wait until the SDRAM controller is ready */ + if (time_out_check(sdram_device) != SUCCESS) { + return ERROR; + } + /* send the command */ + exmc_sdram_command_config(&sdram_command_init_struct); + + /* step 8 : set the auto-refresh rate counter--------------------------------*/ + /* 64ms, 8192-cycle refresh, 64ms/8192=7.81us */ + /* SDCLK_Freq = SYS_Freq/2 */ + /* (7.81 us * SDCLK_Freq) - 20 */ + int16_t auto_refresh_iterval = 761; + exmc_sdram_refresh_count_set(auto_refresh_iterval); + + /* wait until the SDRAM controller is ready */ + if (time_out_check(sdram_device) != SUCCESS) { + return ERROR; + } + int16_t delay_t9 = 500; + Gd32f4xxDelay1ms(delay_t9); + + printf("*********************clean_bss\n"); + clean_bss(); + return SUCCESS; +} + +/*! + \brief fill the buffer with specified value + \param[in] pbuffer: pointer on the buffer to fill + \param[in] buffer_lengh: size of the buffer to fill + \param[in] offset: the initial value to fill in the buffer + \param[out] none + \retval none +*/ +void fill_buffer(uint8_t *pbuffer, uint16_t buffer_lengh, uint16_t offset) +{ + uint16_t index = 0; + + /* fill the buffer with specified values */ + for (index = 0; index < buffer_lengh; index++) { + pbuffer[index] = 0x10 + index + offset; + } +} + +/*! + \brief write a byte buffer(data is 8 bits) to the EXMC SDRAM memory + \param[in] sdram_device: specify which a SDRAM memory block is written + \param[in] pbuffer: pointer to buffer + \param[in] writeaddr: SDRAM memory internal address from which the data will be written + \param[in] numbytetowrite: number of bytes to write + \param[out] none + \retval none +*/ +void sdram_writebuffer_8(uint32_t sdram_device, uint8_t *pbuffer, uint32_t writeaddr, uint32_t numbytetowrite) +{ + uint32_t temp_addr; + + /* Select the base address according to EXMC_Bank */ + if (sdram_device == EXMC_SDRAM_DEVICE0) { + temp_addr = SDRAM_DEVICE0_ADDR; + } else { + temp_addr = SDRAM_DEVICE1_ADDR; + } + + /* While there is data to write */ + for (; numbytetowrite != 0; numbytetowrite--) { + /* Transfer data to the memory */ + *(uint8_t *)(temp_addr + writeaddr) = *pbuffer++; + + /* Increment the address */ + writeaddr += 1; + } +} + +/*! + \brief read a block of 8-bit data from the EXMC SDRAM memory + \param[in] sdram_device: specify which a SDRAM memory block is written + \param[in] pbuffer: pointer to buffer + \param[in] readaddr: SDRAM memory internal address to read from + \param[in] numbytetoread: number of bytes to read + \param[out] none + \retval none +*/ +void sdram_readbuffer_8(uint32_t sdram_device, uint8_t *pbuffer, uint32_t readaddr, uint32_t numbytetoread) +{ + uint32_t temp_addr; + + /* select the base address according to EXMC_Bank */ + if (sdram_device == EXMC_SDRAM_DEVICE0) { + temp_addr = SDRAM_DEVICE0_ADDR; + } else { + temp_addr = SDRAM_DEVICE1_ADDR; + } + + /* while there is data to read */ + for (; numbytetoread != 0; numbytetoread--) { + /* read a byte from the memory */ + *pbuffer++ = *(uint8_t *)(temp_addr + readaddr); + + /* increment the address */ + readaddr += 1; + } +} + +/*! + \brief write a half-word buffer(data is 16 bits) to the EXMC SDRAM memory + \param[in] sdram_device: specify which a SDRAM memory block is written + \param[in] pbuffer: pointer to buffer + \param[in] writeaddr: SDRAM memory internal address from which the data will be written + \param[in] numbytetowrite: number of half-word to write + \param[out] none + \retval none +*/ +void sdram_writebuffer_16(uint32_t sdram_device, uint16_t *pbuffer, uint32_t writeaddr, uint32_t numtowrite) +{ + uint32_t temp_addr; + __IO uint32_t write_addr_prt = writeaddr; + + /* Select the base address according to EXMC_Bank */ + if (sdram_device == EXMC_SDRAM_DEVICE0) { + temp_addr = SDRAM_DEVICE0_ADDR; + } else { + temp_addr = SDRAM_DEVICE1_ADDR; + } + + /* While there is data to write */ + for (; numtowrite != 0; numtowrite--) { + /* Transfer data to the memory */ + *(uint16_t *)(temp_addr + write_addr_prt) = *pbuffer++; + + /* Increment the address */ + write_addr_prt += ADDR_STEP; + } +} + +/*! + \brief read a block of 16-bit data from the EXMC SDRAM memory + \param[in] sdram_device: specify which a SDRAM memory block is written + \param[in] pbuffer: pointer to buffer + \param[in] readaddr: SDRAM memory internal address to read from + \param[in] numtowrite: number of half-word to read + \param[out] none + \retval none +*/ +void sdram_readbuffer_16(uint32_t sdram_device, uint16_t *pbuffer, uint32_t readaddr, uint32_t numtowrite) +{ + uint32_t temp_addr; + __IO uint32_t write_addr_prt = readaddr; + + /* select the base address according to EXMC_Bank */ + if (sdram_device == EXMC_SDRAM_DEVICE0) { + temp_addr = SDRAM_DEVICE0_ADDR; + } else { + temp_addr = SDRAM_DEVICE1_ADDR; + } + + /* while there is data to read */ + for (; numtowrite != 0; numtowrite--) { + /* read a byte from the memory */ + *pbuffer++ = *(uint16_t *)(temp_addr + write_addr_prt); + + /* increment the address */ + write_addr_prt += ADDR_STEP; + } +} diff --git a/khdvk_450a/liteos_m/bsp/sdram/exmc_sdram.h b/khdvk_450a/liteos_m/bsp/sdram/exmc_sdram.h new file mode 100644 index 0000000..2a227a3 --- /dev/null +++ b/khdvk_450a/liteos_m/bsp/sdram/exmc_sdram.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 EXMC_SDRAM_H +#define EXMC_SDRAM_H + +#include "gd32f4xx.h" + +#define SDRAM_DEVICE0_ADDR ((uint32_t)0xC0000000) +#define SDRAM_DEVICE1_ADDR ((uint32_t)0xD0000000) + +extern int __bss_start__; +extern int __bss_end__; + +/* initialize sdram peripheral */ +ErrStatus exmc_synchronous_dynamic_ram_init(uint32_t sdram_device); +/* fill the buffer with specified value */ +void fill_buffer(uint8_t *pbuffer, uint16_t buffer_lengh, uint16_t offset); +/* write a byte buffer(data is 8 bits) to the EXMC SDRAM memory */ +void sdram_writebuffer_8(uint32_t sdram_device, uint8_t *pbuffer, uint32_t writeaddr, uint32_t numbytetowrite); +/* read a block of 8-bit data from the EXMC SDRAM memory */ +void sdram_readbuffer_8(uint32_t sdram_device, uint8_t *pbuffer, uint32_t readaddr, uint32_t numbytetoread); +/* write a half-word buffer(data is 16 bits) to the EXMC SDRAM memory */ +void sdram_writebuffer_16(uint32_t sdram_device, uint16_t *pbuffer, uint32_t writeaddr, uint32_t numtowrite); +/* read a block of 16-bit data from the EXMC SDRAM memory */ +void sdram_readbuffer_16(uint32_t sdram_device, uint16_t *pbuffer, uint32_t readaddr, uint32_t numtowrite); + +#endif /* EXMC_SDRAM_H */ diff --git a/khdvk_450a/liteos_m/bsp/startup/gd32f4xx_flash.ld b/khdvk_450a/liteos_m/bsp/startup/gd32f4xx_flash.ld new file mode 100644 index 0000000..4cee38e --- /dev/null +++ b/khdvk_450a/liteos_m/bsp/startup/gd32f4xx_flash.ld @@ -0,0 +1,265 @@ +/* +***************************************************************************** +** +** File : gd32f4xx_flash.ld +** +** Abstract : Linker script for GD32F4xxZK Device with +** 3027KByte FLASH, 192KByte RAM +** +** Set heap size, stack size and stack location according +** to application requirements. +** +** Set memory bank area and size if external memory is used. +** +** Target : GDicroelectronics GD32 +** +** Environment : Atollic TrueSTUDIO(R) +** +** Distribution: The file is distributed �as is,?without any warranty +** of any kind. +** +** (c)Copyright Atollic AB. +** You may use this file as-is or modify it according to the needs of your +** project. Distribution of this file (unmodified or modified) is not +** permitted. Atollic AB permit registered Atollic TrueSTUDIO(R) users the +** rights to distribute the assembled, compiled & linked contents of this +** file as part of an application binary file, provided that it is built +** using the Atollic TrueSTUDIO(R) toolchain. +** +***************************************************************************** +*/ + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Highest address of the user mode stack */ +_estack = 0x20030000; /* end of 256K RAM */ + +/* Generate a link error if heap and stack don't fit into RAM */ +_Min_Heap_Size = 0x200; /* required amount of heap */ +_Min_Stack_Size = 0x400; /* required amount of stack */ + +/* Specify the memory areas */ +/* FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 3072K */ +/* FLASH (rx) : ORIGIN = 0x8010000, LENGTH = 3008K 7680K*/ +MEMORY +{ +FLASH (rx) : ORIGIN = 0x8010000, LENGTH = 3008K +RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 192K +CCMRAM (rw) : ORIGIN = 0x10000000, LENGTH = 64K +SDRAM (rw) : ORIGIN = 0xC0800000, LENGTH = 7168K +} + +/* Define output sections */ +SECTIONS +{ + /* The startup code goes first into FLASH */ + .isr_vector : + { + . = ALIGN(4); + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + } >FLASH + + /* The program code and other data goes into FLASH */ + .text : + { + . = ALIGN(4); + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + + *(.glue_7) /* glue arm to thumb code */ + *(.glue_7t) /* glue thumb to arm code */ + *(.eh_frame) + . = ALIGN(4); + __zinitcall_bsp_start = .; + KEEP (*(.zinitcall.bsp0.init)) + KEEP (*(.zinitcall.bsp1.init)) + KEEP (*(.zinitcall.bsp2.init)) + KEEP (*(.zinitcall.bsp3.init)) + KEEP (*(.zinitcall.bsp4.init)) + __zinitcall_bsp_end = .; + __zinitcall_device_start = .; + KEEP (*(.zinitcall.device0.init)) + KEEP (*(.zinitcall.device1.init)) + KEEP (*(.zinitcall.device2.init)) + KEEP (*(.zinitcall.device3.init)) + KEEP (*(.zinitcall.device4.init)) + __zinitcall_device_end = .; + __zinitcall_core_start = .; + KEEP (*(.zinitcall.core0.init)) + KEEP (*(.zinitcall.core1.init)) + KEEP (*(.zinitcall.core2.init)) + KEEP (*(.zinitcall.core3.init)) + KEEP (*(.zinitcall.core4.init)) + __zinitcall_core_end = .; + __zinitcall_sys_service_start = .; + KEEP (*(.zinitcall.sys.service0.init)) + KEEP (*(.zinitcall.sys.service1.init)) + KEEP (*(.zinitcall.sys.service2.init)) + KEEP (*(.zinitcall.sys.service3.init)) + KEEP (*(.zinitcall.sys.service4.init)) + __zinitcall_sys_service_end = .; + __zinitcall_sys_feature_start = .; + KEEP (*(.zinitcall.sys.feature0.init)) + KEEP (*(.zinitcall.sys.feature1.init)) + KEEP (*(.zinitcall.sys.feature2.init)) + KEEP (*(.zinitcall.sys.feature3.init)) + KEEP (*(.zinitcall.sys.feature4.init)) + __zinitcall_sys_feature_end = .; + __zinitcall_run_start = .; + KEEP (*(.zinitcall.run0.init)) + KEEP (*(.zinitcall.run1.init)) + KEEP (*(.zinitcall.run2.init)) + KEEP (*(.zinitcall.run3.init)) + KEEP (*(.zinitcall.run4.init)) + __zinitcall_run_end = .; + __zinitcall_app_service_start = .; + KEEP (*(.zinitcall.app.service0.init)) + KEEP (*(.zinitcall.app.service1.init)) + KEEP (*(.zinitcall.app.service2.init)) + KEEP (*(.zinitcall.app.service3.init)) + KEEP (*(.zinitcall.app.service4.init)) + __zinitcall_app_service_end = .; + __zinitcall_app_feature_start = .; + KEEP (*(.zinitcall.app.feature0.init)) + KEEP (*(.zinitcall.app.feature1.init)) + KEEP (*(.zinitcall.app.feature2.init)) + KEEP (*(.zinitcall.app.feature3.init)) + KEEP (*(.zinitcall.app.feature4.init)) + __zinitcall_app_feature_end = .; + __zinitcall_test_start = .; + KEEP (*(.zinitcall.test0.init)) + KEEP (*(.zinitcall.test1.init)) + KEEP (*(.zinitcall.test2.init)) + KEEP (*(.zinitcall.test3.init)) + KEEP (*(.zinitcall.test4.init)) + __zinitcall_test_end = .; + __zinitcall_exit_start = .; + KEEP (*(.zinitcall.exit0.init)) + KEEP (*(.zinitcall.exit1.init)) + KEEP (*(.zinitcall.exit2.init)) + KEEP (*(.zinitcall.exit3.init)) + KEEP (*(.zinitcall.exit4.init)) + __zinitcall_exit_end = .; + _hdf_drivers_start = .; + KEEP(*(.hdf.driver)) + _hdf_drivers_end = .; + . = ALIGN(4); + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; /* define a global symbols at end of code */ + } >FLASH + + /* Constant data goes into FLASH */ + .rodata : + { + . = ALIGN(4); + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + . = ALIGN(4); + } >FLASH + + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH + .ARM : { + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + } >FLASH + + .ARM.attributes : { *(.ARM.attributes) } > FLASH + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >FLASH + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + } >FLASH + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(.fini_array*)) + KEEP (*(SORT(.fini_array.*))) + PROVIDE_HIDDEN (__fini_array_end = .); + } >FLASH + + /* used by the startup to initialize data */ + _sidata = .; + + /* Initialized data sections goes into RAM, load LMA copy after code */ + .data : AT ( _sidata ) + { + . = ALIGN(4); + _sdata = .; /* create a global symbol at data start */ + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + + . = ALIGN(4); + _edata = .; /* define a global symbol at data end */ + } >RAM + + _siccmram = LOADADDR(.ccmram); + + /* CCM-RAM section + * + * IMPORTANT NOTE! + * If initialized variables will be placed in this section, + * the startup code needs to be modified to copy the init-values. + */ + .ccmram : + { + . = ALIGN(4); + _sccmram = .; /* create a global symbol at ccmram start */ + *(.ccmram) + *(.ccmram*) + + . = ALIGN(4); + _eccmram = .; /* create a global symbol at ccmram end */ + } >CCMRAM AT> FLASH + /* Uninitialized data section */ + . = ALIGN(4); + .bss : + { + /* This is used by the startup in order to initialize the .bss secion */ + _sbss = .; /* define a global symbol at bss start */ + __bss_start__ = _sbss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _ebss = .; /* define a global symbol at bss end */ + __bss_end__ = _ebss; + } >SDRAM + + PROVIDE ( end = _ebss ); + PROVIDE ( _end = _ebss ); + + /* User_heap_stack section, used to check that there is enough RAM left */ + ._user_heap_stack : + { + . = ALIGN(4); + . = . + _Min_Heap_Size; + . = . + _Min_Stack_Size; + . = ALIGN(4); + } >RAM + + + + /* Remove information from the standard libraries */ + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } +} diff --git a/khdvk_450a/liteos_m/bsp/startup/gd32f4xx_it.c b/khdvk_450a/liteos_m/bsp/startup/gd32f4xx_it.c new file mode 100755 index 0000000..25f65b2 --- /dev/null +++ b/khdvk_450a/liteos_m/bsp/startup/gd32f4xx_it.c @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 "gd32f4xx_it.h" +#include "gd32f4xx_systick.h" + +/*! + \brief this function handles SysTick exception + \param[in] none + \param[out] none + \retval none +*/ +void GD32F450_SysTick_Handler(void) +{ + Gd32f4xxDelayDecrement(); +} diff --git a/khdvk_450a/liteos_m/bsp/startup/gd32f4xx_it.h b/khdvk_450a/liteos_m/bsp/startup/gd32f4xx_it.h new file mode 100755 index 0000000..37958b2 --- /dev/null +++ b/khdvk_450a/liteos_m/bsp/startup/gd32f4xx_it.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 GD32F4XX_IT_H +#define GD32F4XX_IT_H + +#include "gd32f4xx.h" + +/* function declarations */ +/* this function handles NMI exception */ +void NMI_Handler(void); +/* this function handles HardFault exception */ +void HardFault_Handler(void); +/* this function handles MemManage exception */ +void MemManage_Handler(void); +/* this function handles BusFault exception */ +void BusFault_Handler(void); +/* this function handles UsageFault exception */ +void UsageFault_Handler(void); +/* this function handles SVC exception */ +void SVC_Handler(void); +/* this function handles DebugMon exception */ +void DebugMon_Handler(void); +/* this function handles PendSV exception */ +void PendSV_Handler(void); +/* this function handles SysTick exception */ +void GD32F450_SysTick_Handler(void); + +#endif /* GD32F4XX_IT_H */ diff --git a/khdvk_450a/liteos_m/bsp/startup/gd32f4xx_systick.c b/khdvk_450a/liteos_m/bsp/startup/gd32f4xx_systick.c new file mode 100644 index 0000000..30db86e --- /dev/null +++ b/khdvk_450a/liteos_m/bsp/startup/gd32f4xx_systick.c @@ -0,0 +1,83 @@ +/*! + \file systick.c + \brief the systick configuration file + + \version 2016-08-15, V1.0.0, demo for GD32F4xx + \version 2018-12-12, V2.0.0, demo for GD32F4xx +*/ + +/* + Copyright (c) 2018 GigaDevice Semiconductor Inc. + + 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. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + 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 HOLDER 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. +*/ + +#include "gd32f4xx.h" +#include "gd32f4xx_systick.h" + +#define TICK_FOR_1000_HZ 1000U +volatile static uint32_t delay = 1; + +/*! + \brief configure systick + \param[in] none + \param[out] none + \retval none +*/ +void Gd32f4xxSystickConfig(void) +{ + /* setup systick timer for 1000Hz interrupts */ + if (SysTick_Config(SystemCoreClock / TICK_FOR_1000_HZ)) { + /* capture error */ + while (1) { } + } + /* configure the systick handler priority */ + NVIC_SetPriority(SysTick_IRQn, 0x00U); +} + +/*! + \brief delay a time in milliseconds + \param[in] count: count in milliseconds + \param[out] none + \retval none +*/ +void Gd32f4xxDelay1ms(uint32_t count) +{ + delay = count; + + while (delay != 0U) { } +} + +/*! + \brief delay decrement + \param[in] none + \param[out] none + \retval none +*/ +void Gd32f4xxDelayDecrement(void) +{ + if (delay != 0U) { + delay--; + } +} diff --git a/khdvk_450a/liteos_m/bsp/startup/gd32f4xx_systick.h b/khdvk_450a/liteos_m/bsp/startup/gd32f4xx_systick.h new file mode 100755 index 0000000..2860f65 --- /dev/null +++ b/khdvk_450a/liteos_m/bsp/startup/gd32f4xx_systick.h @@ -0,0 +1,40 @@ +/* + Copyright (c) 2018 GigaDevice Semiconductor Inc. + + 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. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + 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 HOLDER 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. +*/ + +#ifndef SYS_TICK_H +#define SYS_TICK_H + +#include + +/* configure systick */ +void Gd32f4xxSystickConfig(void); +/* delay a time in milliseconds */ +void Gd32f4xxDelay1ms(uint32_t count); +/* delay decrement */ +void Gd32f4xxDelayDecrement(void); + +#endif /* SYS_TICK_H */ diff --git a/khdvk_450a/liteos_m/bsp/startup/main.c b/khdvk_450a/liteos_m/bsp/startup/main.c new file mode 100644 index 0000000..8bb6008 --- /dev/null +++ b/khdvk_450a/liteos_m/bsp/startup/main.c @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 "ohos_init.h" +#include "cmsis_os2.h" +#include "logo_interface.h" +#include "gd32f4xx.h" +#include "gd32f4xx_systick.h" +#include "exmc_sdram.h" +#include "hilog/log.h" + +#define APP_ADDR_OFF ((uint32_t)0x10000) // 应用程序起始地址偏移 +#define LOG_DOMAIN 0x00201 +#define LOG_TAG "main" +#define TIME_PEROID 5000 +#define DELAY_TIME 1000 +#define STACK_SIZE 0x1000 +#define PRIORITY 32 +#define BUFFER_START_LEN 2 + +static void SysInit(void) +{ + OHOS_SystemInit(); +} + +static void DeadWhile(void) +{ + while (1) { + osDelay(DELAY_TIME); + HILOG_ERROR(0, "enter in DeadWhile"); + } +} + +static void MainBoot(void) +{ + /* + CMSIS Highest priority 34 + CMSIS Norbal priority 24 + CMSIS Lowest priority 3 + CMSIS_PRI = 34 - LOS_PRI + */ + osThreadId_t threadId = NULL; + osThreadAttr_t attr = {0}; + attr.name = "MainBoot"; + attr.stack_size = STACK_SIZE; + attr.priority = PRIORITY; + threadId = osThreadNew(SysInit, NULL, &attr); + if (threadId == NULL) { + HILOG_ERROR(0, "MainBoot task create failed!!!"); + } + + osThreadDetach(threadId); +} + +int HiLogWriteInternal(const char *buffer, size_t bufLen) +{ + if (!buffer) { + return -1; + } + + // because it's called as HiLogWriteInternal(buf, strlen(buf) + 1) + if (bufLen < BUFFER_START_LEN) { + return 0; + } + + if (buffer[bufLen - BUFFER_START_LEN] != '\n') { + *((char *)buffer + bufLen - 1) = '\n'; + } else { + bufLen--; + } + + printf("%s", buffer); + + return 0; +} + +static void InitBoardBefore(void) +{ + nvic_vector_table_set(NVIC_VECTTAB_FLASH, APP_ADDR_OFF); // 中断向量重映射 + gpio_mode_set(GPIOD, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN_4); // reset led2 +} + +static void InitBoard(void) +{ + ErrStatus init_state; + + USART0_UART_Init(); + Gd32f4xxSystickConfig(); + + init_state = exmc_synchronous_dynamic_ram_init(EXMC_SDRAM_DEVICE0); + if (ERROR == init_state) { + HILOG_ERROR(0, "SDRAM initialize fail!"); + while (1) { } + } + + HILOG_INFO(0, "SDRAM initialized success!\n"); +} + +static void Gif_Init(void) +{ + int reval = 0; + while (!reval) { + reval = GifLoad("/data/cartoon_logo.gif"); + HILOG_INFO(0, "GifLoad try again ...\n\n"); + } + HILOG_INFO(0, "GifLoad ok ...\n\n"); +} + +/** + * @brief The application entry point. + * @retval int + */ +int main(void) +{ + osStatus_t status = osError; + + InitBoardBefore(); + InitBoard(); + HILOG_INFO(0, "build time is %s:%s\n\n", __DATE__, __TIME__); + + status = osKernelInitialize(); + if (status != osOK) { + HILOG_ERROR(0, "osKernelInitialize fail!"); + while (1) { } + } + HILOG_INFO(0, "Open Harmony 3.1 Release start ...\n\n"); + + lfs_init(); +#ifdef LOSCFG_DRIVERS_HDF_USER_LCD + Gif_Init(); +#endif + DeviceManagerStart(); + enet_adapter_init(NULL); + + InitUartMutex(); + MainBoot(); + + status = osKernelStart(); + if (status != osOK) { + HILOG_ERROR(0, "osKernelStart fail!"); + } + while (1) { } +} \ No newline at end of file diff --git a/khdvk_450a/liteos_m/bsp/startup/startup_gd32f4xx.s b/khdvk_450a/liteos_m/bsp/startup/startup_gd32f4xx.s new file mode 100644 index 0000000..644f105 --- /dev/null +++ b/khdvk_450a/liteos_m/bsp/startup/startup_gd32f4xx.s @@ -0,0 +1,486 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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. + */ + + .syntax unified + .cpu cortex-m4 + .fpu softvfp + .thumb + +.global g_pfnVectors +.global Default_Handler + +/* start address of the static initialization data */ +.word _sidata +/* start address of the data section */ +.word _sdata +/* end address of the data section */ +.word _edata +/* start address of the bss section */ +.word _sbss +/* end address of the bss section */ +.word _ebss + + + .section .text.Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function + +Reset_Handler: +/* copy the data segment into ram */ + movs r1, #0 + b DataInit + +CopyData: + ldr r3, =_sidata + ldr r3, [r3, r1] + str r3, [r0, r1] + adds r1, r1, #4 + +DataInit: + ldr r0, =_sdata + ldr r3, =_edata + adds r2, r0, r1 + cmp r2, r3 + bcc CopyData +/* configure the clock */ + bl SystemInit +/* start execution of the program */ + bl main + bx lr +.size Reset_Handler, .-Reset_Handler + + + + .section .text.Default_Handler,"ax",%progbits +Default_Handler: +Infinite_Loop: + b Infinite_Loop + .size Default_Handler, .-Default_Handler + + + .section .isr_vector,"a",%progbits + .type g_pfnVectors, %object + .size g_pfnVectors, .-g_pfnVectors + + +g_pfnVectors: + .word _estack + .word Reset_Handler /* Vector Number 1,Reset Handler */ + .word NMI_Handler /* Vector Number 2,NMI Handler */ + .word HardFault_Handler /* Vector Number 3,Hard Fault Handler */ + .word MemManage_Handler /* Vector Number 4,MPU Fault Handler */ + .word BusFault_Handler /* Vector Number 5,Bus Fault Handler */ + .word UsageFault_Handler /* Vector Number 6,Usage Fault Handler */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word 0 /* Reserved */ + .word SVC_Handler /* Vector Number 11,SVCall Handler */ + .word DebugMon_Handler /* Vector Number 12,Debug Monitor Handler */ + .word 0 /* Reserved */ + .word PendSV_Handler /* Vector Number 14,PendSV Handler */ + .word GD32F450_SysTick_Handler /* Vector Number 15,SysTick Handler */ + + /* External Interrupts */ + .word WWDGT_IRQHandler /* Vector Number 16,Window Watchdog Timer */ + .word LVD_IRQHandler /* Vector Number 17,LVD through EXTI Line detect */ + .word TAMPER_STAMP_IRQHandler /* Vector Number 18,Tamper and TimeStamp through EXTI Line detect */ + .word RTC_WKUP_IRQHandler /* Vector Number 19,RTC Wakeup through EXTI Line */ + .word FMC_IRQHandler /* Vector Number 20,FMC */ + .word RCU_CTC_IRQHandler /* Vector Number 21,RCU and CTC */ + .word EXTI0_IRQHandler /* Vector Number 22,EXTI Line 0 */ + .word EXTI1_IRQHandler /* Vector Number 23,EXTI Line 1 */ + .word EXTI2_IRQHandler /* Vector Number 24,EXTI Line 2 */ + .word EXTI3_IRQHandler /* Vector Number 25,EXTI Line 3 */ + .word EXTI4_IRQHandler /* Vector Number 26,EXTI Line 4 */ + .word DMA0_Channel0_IRQHandler /* Vector Number 27,DMA0 Channel 0 */ + .word DMA0_Channel1_IRQHandler /* Vector Number 28,DMA0 Channel 1 */ + .word DMA0_Channel2_IRQHandler /* Vector Number 29,DMA0 Channel 2 */ + .word DMA0_Channel3_IRQHandler /* Vector Number 30,DMA0 Channel 3 */ + .word DMA0_Channel4_IRQHandler /* Vector Number 31,DMA0 Channel 4 */ + .word DMA0_Channel5_IRQHandler /* Vector Number 32,DMA0 Channel 5 */ + .word DMA0_Channel6_IRQHandler /* Vector Number 33,DMA0 Channel 6 */ + .word ADC_IRQHandler /* Vector Number 34,ADC */ + .word CAN0_TX_IRQHandler /* Vector Number 35,CAN0 TX */ + .word CAN0_RX0_IRQHandler /* Vector Number 36,CAN0 RX0 */ + .word CAN0_RX1_IRQHandler /* Vector Number 37,CAN0 RX1 */ + .word CAN0_EWMC_IRQHandler /* Vector Number 38,CAN0 EWMC */ + .word EXTI5_9_IRQHandler /* Vector Number 39,EXTI5 to EXTI9*/ + .word TIMER0_BRK_TIMER8_IRQHandler /* Vector Number 40,TIMER0 Break and TIMER8 */ + .word TIMER0_UP_TIMER9_IRQHandler /* Vector Number 41,TIMER0 Update and TIMER9 */ + .word TIMER0_TRG_CMT_TIMER10_IRQHandler /* Vector Number 42,TIMER0 Trigger and Commutation and TIMER10 */ + .word TIMER0_CC_IRQHandler /* Vector Number 43,TIMER0 Capture Compare */ + .word TIMER1_IRQHandler /* Vector Number 44,TIMER1 */ + .word TIMER2_IRQHandler /* Vector Number 45,TIMER2 */ + .word TIMER3_IRQHandler /* Vector Number 46,TIMER3 */ + .word I2C0_EV_IRQHandler /* Vector Number 47,I2C0 Event */ + .word I2C0_ER_IRQHandler /* Vector Number 48,I2C0 Error */ + .word I2C1_EV_IRQHandler /* Vector Number 49,I2C1 Event */ + .word I2C1_ER_IRQHandler /* Vector Number 50,I2C1 Error */ + .word SPI0_IRQHandler /* Vector Number 51,SPI0 */ + .word SPI1_IRQHandler /* Vector Number 52,SPI1 */ + .word USART0_IRQHandler /* Vector Number 53,USART0 */ + .word USART1_IRQHandler /* Vector Number 54,USART1 */ + .word USART2_IRQHandler /* Vector Number 55,USART2 */ + .word EXTI10_15_IRQHandler /* Vector Number 56,EXTI10 to EXTI15 */ + .word RTC_Alarm_IRQHandler /* Vector Number 57,RTC Alarm */ + .word USBFS_WKUP_IRQHandler /* Vector Number 58,USBFS Wakeup */ + .word TIMER7_BRK_TIMER11_IRQHandler /* Vector Number 59,TIMER7 Break and TIMER11 */ + .word TIMER7_UP_TIMER12_IRQHandler /* Vector Number 60,TIMER7 Update and TIMER12 */ + .word TIMER7_TRG_CMT_TIMER13_IRQHandler /* Vector Number 61,TIMER7 Trigger and Commutation and TIMER13 */ + .word TIMER7_CC_IRQHandler /* Vector Number 62,TIMER7 Capture Compare */ + .word DMA0_Channel7_IRQHandler /* Vector Number 63,DMA0 Channel7 */ + .word EXMC_IRQHandler /* Vector Number 64,EXMC */ + .word SDIO_IRQHandler /* Vector Number 65,SDIO */ + .word TIMER4_IRQHandler /* Vector Number 66,TIMER4 */ + .word SPI2_IRQHandler /* Vector Number 67,SPI2 */ + .word UART3_IRQHandler /* Vector Number 68,UART3 */ + .word UART4_IRQHandler /* Vector Number 69,UART4 */ + .word TIMER5_DAC_IRQHandler /* Vector Number 70,TIMER5 and DAC0 DAC1 Underrun error */ + .word TIMER6_IRQHandler /* Vector Number 71,TIMER6 */ + .word DMA1_Channel0_IRQHandler /* Vector Number 72,DMA1 Channel0 */ + .word DMA1_Channel1_IRQHandler /* Vector Number 73,DMA1 Channel1 */ + .word DMA1_Channel2_IRQHandler /* Vector Number 74,DMA1 Channel2 */ + .word DMA1_Channel3_IRQHandler /* Vector Number 75,DMA1 Channel3 */ + .word DMA1_Channel4_IRQHandler /* Vector Number76:DMA1 Channel4 */ + .word ENET_IRQHandler /* Vector Number 77:Ethernet*/ + .word ENET_WKUP_IRQHandler /* Vector Number 78:Ethernet Wakeup through EXTI Line*/ + .word CAN1_TX_IRQHandler /* Vector Number 79:CAN1 TX*/ + .word CAN1_RX0_IRQHandler /* Vector Number 80:CAN1 RX0*/ + .word CAN1_RX1_IRQHandler /* Vector Number 81:CAN1 RX1*/ + .word CAN1_EWMC_IRQHandler /* Vector Number 82:CAN1 EWMC*/ + .word USBFS_IRQHandler /* Vector Number 83:USBFS*/ + .word DMA1_Channel5_IRQHandler /* Vector Number 84:DMA1 Channel5*/ + .word DMA1_Channel6_IRQHandler /* Vector Number 85:DMA1 Channel6*/ + .word DMA1_Channel7_IRQHandler /* Vector Number 86:DMA1 Channel7*/ + .word USART5_IRQHandler /* Vector Number 87:USART5*/ + .word I2C2_EV_IRQHandler /* Vector Number 88:I2C2 Event*/ + .word I2C2_ER_IRQHandler /* Vector Number 89:I2C2 Error*/ + .word USBHS_EP1_Out_IRQHandler /* Vector Number 90:USBHS Endpoint 1 Out */ + .word USBHS_EP1_In_IRQHandler /* Vector Number 91:USBHS Endpoint 1 in*/ + .word USBHS_WKUP_IRQHandler /* Vector Number 92:USBHS Wakeup through EXTI Line*/ + .word USBHS_IRQHandler /* Vector Number 93:USBHS*/ + .word DCI_IRQHandler /* Vector Number 94:DCI*/ + .word 0 /* Reserved*/ + .word TRNG_IRQHandler /* Vector Number 96:TRNG*/ + .word FPU_IRQHandler /* Vector Number 97:FPU*/ + .word UART6_IRQHandler /* Vector Number 98:UART6*/ + .word UART7_IRQHandler /* Vector Number 99:UART7*/ + .word SPI3_IRQHandler /* Vector Number 100:SPI3*/ + .word SPI4_IRQHandler /* Vector Number 101:SPI4*/ + .word SPI5_IRQHandler /* Vector Number 102:SPI5*/ + .word 0 /* Reserved*/ + .word TLI_IRQHandler /* Vector Number 104:TLI*/ + .word TLI_ER_IRQHandler /* Vector Number 105:TLI Error*/ + .word IPA_IRQHandler /* Vector Number 106:IPA*/ + + + + .weak NMI_Handler + .thumb_set NMI_Handler,Default_Handler + + .weak HardFault_Handler + .thumb_set HardFault_Handler,Default_Handler + + .weak MemManage_Handler + .thumb_set MemManage_Handler,Default_Handler + + .weak BusFault_Handler + .thumb_set BusFault_Handler,Default_Handler + + .weak UsageFault_Handler + .thumb_set UsageFault_Handler,Default_Handler + + .weak SVC_Handler + .thumb_set SVC_Handler,Default_Handler + + .weak DebugMon_Handler + .thumb_set DebugMon_Handler,Default_Handler + + .weak PendSV_Handler + .thumb_set PendSV_Handler,Default_Handler + + .weak GD32F450_SysTick_Handler + .thumb_set GD32F450_SysTick_Handler,Default_Handler + + .weak WWDGT_IRQHandler + .thumb_set WWDGT_IRQHandler,Default_Handler + + .weak LVD_IRQHandler + .thumb_set LVD_IRQHandler,Default_Handler + + .weak TAMPER_STAMP_IRQHandler + .thumb_set TAMPER_STAMP_IRQHandler,Default_Handler + + .weak RTC_WKUP_IRQHandler + .thumb_set RTC_WKUP_IRQHandler,Default_Handler + + .weak FMC_IRQHandler + .thumb_set FMC_IRQHandler,Default_Handler + + .weak RCU_CTC_IRQHandler + .thumb_set RCU_CTC_IRQHandler,Default_Handler + + .weak EXTI0_IRQHandler + .thumb_set EXTI0_IRQHandler,Default_Handler + + .weak EXTI1_IRQHandler + .thumb_set EXTI1_IRQHandler,Default_Handler + + .weak EXTI2_IRQHandler + .thumb_set EXTI2_IRQHandler,Default_Handler + + .weak EXTI3_IRQHandler + .thumb_set EXTI3_IRQHandler,Default_Handler + + .weak EXTI4_IRQHandler + .thumb_set EXTI4_IRQHandler,Default_Handler + + .weak DMA0_Channel0_IRQHandler + .thumb_set DMA0_Channel0_IRQHandler,Default_Handler + + .weak DMA0_Channel1_IRQHandler + .thumb_set DMA0_Channel1_IRQHandler,Default_Handler + + .weak DMA0_Channel2_IRQHandler + .thumb_set DMA0_Channel2_IRQHandler,Default_Handler + + .weak DMA0_Channel3_IRQHandler + .thumb_set DMA0_Channel3_IRQHandler,Default_Handler + + .weak DMA0_Channel4_IRQHandler + .thumb_set DMA0_Channel4_IRQHandler,Default_Handler + + .weak DMA0_Channel5_IRQHandler + .thumb_set DMA0_Channel5_IRQHandler,Default_Handler + + .weak DMA0_Channel6_IRQHandler + .thumb_set DMA0_Channel6_IRQHandler,Default_Handler + + .weak ADC_IRQHandler + .thumb_set ADC_IRQHandler,Default_Handler + + .weak CAN0_TX_IRQHandler + .thumb_set CAN0_TX_IRQHandler,Default_Handler + + .weak CAN0_RX0_IRQHandler + .thumb_set CAN0_RX0_IRQHandler,Default_Handler + + .weak CAN0_RX1_IRQHandler + .thumb_set CAN0_RX1_IRQHandler,Default_Handler + + .weak CAN0_EWMC_IRQHandler + .thumb_set CAN0_EWMC_IRQHandler,Default_Handler + + .weak EXTI5_9_IRQHandler + .thumb_set EXTI5_9_IRQHandler,Default_Handler + + .weak TIMER0_BRK_TIMER8_IRQHandler + .thumb_set TIMER0_BRK_TIMER8_IRQHandler,Default_Handler + + .weak TIMER0_UP_TIMER9_IRQHandler + .thumb_set TIMER0_UP_TIMER9_IRQHandler,Default_Handler + + .weak TIMER0_TRG_CMT_TIMER10_IRQHandler + .thumb_set TIMER0_TRG_CMT_TIMER10_IRQHandler,Default_Handler + + .weak TIMER0_CC_IRQHandler + .thumb_set TIMER0_CC_IRQHandler,Default_Handler + + .weak TIMER1_IRQHandler + .thumb_set TIMER1_IRQHandler,Default_Handler + + .weak TIMER2_IRQHandler + .thumb_set TIMER2_IRQHandler,Default_Handler + + .weak TIMER3_IRQHandler + .thumb_set TIMER3_IRQHandler,Default_Handler + + .weak I2C0_EV_IRQHandler + .thumb_set I2C0_EV_IRQHandler,Default_Handler + + .weak I2C0_ER_IRQHandler + .thumb_set I2C0_ER_IRQHandler,Default_Handler + + .weak I2C1_EV_IRQHandler + .thumb_set I2C1_EV_IRQHandler,Default_Handler + + .weak I2C1_ER_IRQHandler + .thumb_set I2C1_ER_IRQHandler,Default_Handler + + .weak SPI0_IRQHandler + .thumb_set SPI0_IRQHandler,Default_Handler + + .weak SPI1_IRQHandler + .thumb_set SPI1_IRQHandler,Default_Handler + + .weak USART0_IRQHandler + .thumb_set USART1_IRQHandler,Default_Handler + + .weak USART1_IRQHandler + .thumb_set USART2_IRQHandler,Default_Handler + + .weak USART2_IRQHandler + .thumb_set USART3_IRQHandler,Default_Handler + + .weak EXTI10_15_IRQHandler + .thumb_set EXTI10_15_IRQHandler,Default_Handler + + .weak RTC_Alarm_IRQHandler + .thumb_set RTC_Alarm_IRQHandler,Default_Handler + + .weak USBFS_WKUP_IRQHandler + .thumb_set USBFS_WKUP_IRQHandler,Default_Handler + + .weak TIMER7_BRK_TIMER11_IRQHandler + .thumb_set TIMER7_BRK_TIMER11_IRQHandler,Default_Handler + + .weak TIMER7_UP_TIMER12_IRQHandler + .thumb_set TIMER7_UP_TIMER12_IRQHandler,Default_Handler + + .weak TIMER7_TRG_CMT_TIMER13_IRQHandler + .thumb_set TIMER7_TRG_CMT_TIMER13_IRQHandler,Default_Handler + + .weak TIMER7_CC_IRQHandler + .thumb_set TIMER7_CC_IRQHandler,Default_Handler + + .weak DMA0_Channel7_IRQHandler + .thumb_set DMA0_Channel7_IRQHandler,Default_Handler + + .weak EXMC_IRQHandler + .thumb_set EXMC_IRQHandler,Default_Handler + + .weak SDIO_IRQHandler + .thumb_set SDIO_IRQHandler,Default_Handler + + .weak TIMER4_IRQHandler + .thumb_set TIMER4_IRQHandler,Default_Handler + + .weak SPI2_IRQHandler + .thumb_set SPI2_IRQHandler,Default_Handler + + .weak UART3_IRQHandler + .thumb_set UART3_IRQHandler,Default_Handler + + .weak UART4_IRQHandler + .thumb_set UART4_IRQHandler,Default_Handler + + .weak TIMER5_DAC_IRQHandler + .thumb_set TIMER5_DAC_IRQHandler,Default_Handler + + .weak TIMER6_IRQHandler + .thumb_set TIMER6_IRQHandler,Default_Handler + + .weak DMA1_Channel0_IRQHandler + .thumb_set DMA1_Channel0_IRQHandler,Default_Handler + + .weak DMA1_Channel1_IRQHandler + .thumb_set DMA1_Channel1_IRQHandler,Default_Handler + + .weak DMA1_Channel2_IRQHandler + .thumb_set DMA1_Channel2_IRQHandler,Default_Handler + + .weak DMA1_Channel3_IRQHandler + .thumb_set DMA1_Channel3_IRQHandler,Default_Handler + + .weak DMA1_Channel4_IRQHandler + .thumb_set DMA1_Channel4_IRQHandler,Default_Handler + + .weak ENET_IRQHandler + .thumb_set ENET_IRQHandler,Default_Handler + + .weak ENET_WKUP_IRQHandler + .thumb_set ENET_WKUP_IRQHandler,Default_Handler + + .weak CAN1_TX_IRQHandler + .thumb_set CAN1_TX_IRQHandler,Default_Handler + + .weak CAN1_RX0_IRQHandler + .thumb_set CAN1_RX0_IRQHandler,Default_Handler + + .weak CAN1_RX1_IRQHandler + .thumb_set CAN1_RX1_IRQHandler,Default_Handler + + .weak CAN1_EWMC_IRQHandler + .thumb_set CAN1_EWMC_IRQHandler,Default_Handler + + .weak USBFS_IRQHandler + .thumb_set USBFS_IRQHandler,Default_Handler + + .weak DMA1_Channel5_IRQHandler + .thumb_set DMA1_Channel5_IRQHandler,Default_Handler + + .weak DMA1_Channel6_IRQHandler + .thumb_set DMA1_Channel6_IRQHandler,Default_Handler + + .weak DMA1_Channel7_IRQHandler + .thumb_set DMA1_Channel7_IRQHandler,Default_Handler + + .weak USART5_IRQHandler + .thumb_set USART5_IRQHandler,Default_Handler + + .weak I2C2_EV_IRQHandler + .thumb_set I2C2_EV_IRQHandler,Default_Handler + + .weak I2C2_ER_IRQHandler + .thumb_set I2C2_ER_IRQHandler,Default_Handler + + .weak USBHS_EP1_Out_IRQHandler + .thumb_set USBHS_EP1_Out_IRQHandler,Default_Handler + + .weak USBHS_EP1_In_IRQHandler + .thumb_set USBHS_EP1_In_IRQHandler,Default_Handler + + .weak USBHS_WKUP_IRQHandler + .thumb_set USBHS_WKUP_IRQHandler,Default_Handler + + .weak USBHS_IRQHandler + .thumb_set USBHS_IRQHandler,Default_Handler + + .weak DCI_IRQHandler + .thumb_set DCI_IRQHandler,Default_Handler + + .weak TRNG_IRQHandler + .thumb_set TRNG_IRQHandler,Default_Handler + + .weak FPU_IRQHandler + .thumb_set FPU_IRQHandler,Default_Handler + + .weak UART6_IRQHandler + .thumb_set UART6_IRQHandler,Default_Handler + + .weak UART7_IRQHandler + .thumb_set UART7_IRQHandler,Default_Handler + + .weak SPI3_IRQHandler + .thumb_set SPI3_IRQHandler,Default_Handler + + .weak SPI4_IRQHandler + .thumb_set SPI4_IRQHandler,Default_Handler + + .weak SPI5_IRQHandler + .thumb_set SPI5_IRQHandler,Default_Handler + + .weak TLI_IRQHandler + .thumb_set TLI_IRQHandler,Default_Handler + + .weak TLI_ER_IRQHandler + .thumb_set TLI_ER_IRQHandler ,Default_Handler + + .weak IPA_IRQHandler + .thumb_set IPA_IRQHandler,Default_Handler + + +/******************* (C) COPYRIGHT 2018 GIGADEVICE *****END OF FILE****/ diff --git a/khdvk_450a/liteos_m/bsp/startup/target_config.h b/khdvk_450a/liteos_m/bsp/startup/target_config.h new file mode 100644 index 0000000..21ed648 --- /dev/null +++ b/khdvk_450a/liteos_m/bsp/startup/target_config.h @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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. + */ + +/**@defgroup los_config System configuration items + * @ingroup kernel + */ + +#ifndef _TARGET_CONFIG_H +#define _TARGET_CONFIG_H + +#include +#include "gd32f4xx.h" + + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +/*============================================================================= + System clock module configuration +=============================================================================*/ +#define OS_SYS_CLOCK SystemCoreClock +#define LOSCFG_BASE_CORE_TICK_PER_SECOND (1000UL) +#define LOSCFG_BASE_CORE_TICK_HW_TIME 0 +#define LOSCFG_BASE_CORE_TICK_WTIMER 0 +#define LOSCFG_BASE_CORE_TICK_RESPONSE_MAX SysTick_LOAD_RELOAD_Msk + +/*============================================================================= + Hardware interrupt module configuration +=============================================================================*/ +#define LOSCFG_PLATFORM_HWI 1 +#define LOSCFG_USE_SYSTEM_DEFINED_INTERRUPT 1 +#define LOSCFG_PLATFORM_HWI_LIMIT 90 +#define LOSCFG_PLATFORM_HWI_WITH_ARG 1 +/*============================================================================= + Task module configuration +=============================================================================*/ +#define LOSCFG_BASE_CORE_TSK_LIMIT 24 +#define LOSCFG_BASE_CORE_TSK_IDLE_STACK_SIZE (0x1000U) +#define LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE (0x1600U) +#define LOSCFG_BASE_CORE_TSK_MIN_STACK_SIZE (0x130U) +#define LOSCFG_BASE_CORE_TIMESLICE 1 +#define LOSCFG_BASE_CORE_TIMESLICE_TIMEOUT 10 +/*============================================================================= + Semaphore module configuration +=============================================================================*/ +#define LOSCFG_BASE_IPC_SEM 1 +#define LOSCFG_BASE_IPC_SEM_LIMIT 48 +/*============================================================================= + Mutex module configuration +=============================================================================*/ +#define LOSCFG_BASE_IPC_MUX 1 +#define LOSCFG_BASE_IPC_MUX_LIMIT 200 +/*============================================================================= + Queue module configuration +=============================================================================*/ +#define LOSCFG_BASE_IPC_QUEUE 1 +#define LOSCFG_BASE_IPC_QUEUE_LIMIT 24 +/*============================================================================= + Software timer module configuration +=============================================================================*/ +#define LOSCFG_BASE_CORE_SWTMR 1 +#define LOSCFG_BASE_CORE_SWTMR_ALIGN 0 +#define LOSCFG_BASE_CORE_SWTMR_LIMIT 48 +/*============================================================================= + Memory module configuration +=============================================================================*/ +#define LOSCFG_MEM_MUL_POOL 1 +#define OS_SYS_MEM_NUM 20 +#define LOSCFG_KERNEL_PRINTF 1 + +#define LOSCFG_BASE_CORE_SCHED_SLEEP 1 + +#define LOSCFG_SYS_EXTERNAL_HEAP 1 +#define LOSCFG_SYS_HEAP_ADDR (void *)0xC0000000 +#define LOSCFG_SYS_HEAP_SIZE 0x800000UL // 8M bytes + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif /* _TARGET_CONFIG_H */ diff --git a/khdvk_450a/liteos_m/bsp/usart/usart.c b/khdvk_450a/liteos_m/bsp/usart/usart.c new file mode 100644 index 0000000..d0d2b7d --- /dev/null +++ b/khdvk_450a/liteos_m/bsp/usart/usart.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 "gd32f4xx.h" + +/* USART0 init function */ +void USART0_UART_Init(void) +{ + // 使能 GPIO 时钟源 + rcu_periph_clock_enable(RCU_GPIOA); + + // 使能 USART0 时钟源 + rcu_periph_clock_enable(RCU_USART0); + + /* 复用引脚为 USARTx_Tx */ + gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_9); + + /* 复用引脚为 USARTx_Rx */ + gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_10); + + /* 设置引脚为上拉复用 */ + gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_9); + gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9); + + /* 设置引脚为上拉复用 */ + gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_10); + gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_10); + + /* USART 配置 */ + usart_deinit(USART0); + usart_baudrate_set(USART0, 115200U); + usart_receive_config(USART0, USART_RECEIVE_ENABLE); + usart_transmit_config(USART0, USART_TRANSMIT_ENABLE); + usart_enable(USART0); +} + +static int Gd32IoPutCharRaw(int ch) +{ + usart_data_transmit(USART0, (uint8_t)ch); + while (RESET == usart_flag_get(USART0, USART_FLAG_TBE)) { } + + return ch; +} + +int Gd32IoPutChar(int ch) +{ + if (ch == '\n') { + Gd32IoPutCharRaw('\r'); + } + + return Gd32IoPutCharRaw(ch); +} \ No newline at end of file diff --git a/khdvk_450a/liteos_m/bsp/usart/usart.h b/khdvk_450a/liteos_m/bsp/usart/usart.h new file mode 100644 index 0000000..ea774d5 --- /dev/null +++ b/khdvk_450a/liteos_m/bsp/usart/usart.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 USART_H_ +#define USART_H_ + +extern int Gd32IoPutChar(int ch); + +#endif \ No newline at end of file diff --git a/khdvk_450a/liteos_m/config.gni b/khdvk_450a/liteos_m/config.gni new file mode 100644 index 0000000..7e77635 --- /dev/null +++ b/khdvk_450a/liteos_m/config.gni @@ -0,0 +1,126 @@ +# Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. +# Licensed 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. + +# Kernel type, e.g. "linux", "liteos_a", "liteos_m". +kernel_type = "liteos_m" + +# Kernel version. +kernel_version = "3.0.0" + +# Board CPU type, e.g. "cortex-a7", "riscv32". +board_cpu = "cortex-m4" + +# Board arch, e.g. "armv7-a", "rv32imac". +board_arch = "" + +# Toolchain name used for system compiling. +# E.g. gcc-arm-none-eabi, arm-linux-harmonyeabi-gcc, ohos-clang, riscv32-unknown-elf. +# Note: The default toolchain is "ohos-clang". It's not mandatory if you use the default toolchain. +board_toolchain = "arm-none-eabi-gcc" + +use_board_toolchain = true + +# The toolchain path installed, it's not mandatory if you have added toolchain path to your ~/.bashrc. +board_toolchain_path = "" + +# Compiler prefix. +board_toolchain_prefix = "arm-none-eabi-" + +# Compiler type, "gcc" or "clang". +board_toolchain_type = "gcc" + +# Board related common compile flags. +board_cflags = [ + "-mcpu=cortex-m4", + "-mfpu=fpv4-sp-d16", + "-mfloat-abi=hard", + "-mthumb", + "-Og", + "-Wall", + "-fno-stack-protector", + "-DGD32F450", + "-D__FPU_PRESENT", + "-D__LITEOS_M__", + "-DLOSCFG_BASE_CORE_HILOG=1", +] + +# add force link library in board_cflags +# config.json parse +if (product_path != "") { + product_conf = read_file("${product_path}/config.json", "json") + param_list = product_conf.param_list + force_link_lib_list = param_list.force_link_lib_list + + force_lib_flag = [ + "-Llibs", + "-Wl,--whole-archive", + ] + + foreach(item, force_link_lib_list) { + if (item.enable == "true") { + foreach(lib, item.force_link_libs) { + temp = "-l" + temp += lib + force_lib_flag += [ temp ] + } + } + } + + force_lib_flag += [ "-Wl,--no-whole-archive" ] +} + +board_asmflags = [ + "-Og", + "-Wall", + "-fdata-sections", + "-ffunction-sections", +] + +board_cxx_flags = board_cflags + +board_cxx_flags += [ + "-fno-rtti", + "-std=c++11", +] + +board_ld_flags = [ + "-lstdc++", + "-lsupc++", + "--specs=nano.specs", + "-Wl,--wrap=_malloc_r", + "-Wl,--wrap=_realloc_r", + "-Wl,--wrap=_reallocf_r", + "-Wl,--wrap=_free_r", + "-Wl,--wrap=_memalign_r", + "-Wl,--wrap=_malloc_usable_size_r", + "-Wl,--wrap=printf", + "-Wl,--wrap=sprintf", + "-Wl,--wrap=snprintf", + "-Wl,--wrap=vsnprintf", + "-Wl,--wrap=vprintf", +] + +# Board related headfiles search path. +board_include_dirs = [ + "//utils/native/lite/include", + "//base/iothardware/peripheral/interfaces/inner_api", +] + +# Board adapter dir for OHOS components. +board_adapter_dir = "//device/board/kaihong/khdvk_450a/adapter" + +# Sysroot path. +board_configed_sysroot = "" + +# Board storage type, it used for file system generation. +storage_type = "" diff --git a/khdvk_450a/liteos_m/display/BUILD.gn b/khdvk_450a/liteos_m/display/BUILD.gn new file mode 100644 index 0000000..6c0e773 --- /dev/null +++ b/khdvk_450a/liteos_m/display/BUILD.gn @@ -0,0 +1,34 @@ +# Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. +# Licensed 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. + +import("//drivers/hdf_core/adapter/khdf/liteos_m/hdf.gni") + +hdf_driver("display") { + sources = [ + "disp_hal_hdf.c", + "display_gfx.c", + "display_gralloc.c", + "display_layer.c", + "lcd_abs_if.c", + "lcd_gd32f4xx.c", + "lcd_hardware_init.c", + "tli_ipa_config.c", + ] + include_dirs = [ + ".", + "//drivers/peripheral/display/interfaces/include", + "//drivers/peripheral/display/hal", + "//drivers/peripheral/base", + "//drivers/hdf_core/framework/support/platform/include/gpio/", + ] +} \ No newline at end of file diff --git a/khdvk_450a/liteos_m/display/disp_hal_hdf.c b/khdvk_450a/liteos_m/display/disp_hal_hdf.c new file mode 100644 index 0000000..861b867 --- /dev/null +++ b/khdvk_450a/liteos_m/display/disp_hal_hdf.c @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 "lcd_abs_if.h" +#include "hdf_log.h" +#include "hdf_base.h" + +#define LCD_MAX_SUPPORT 1 + +static int32_t lcdInit[LCD_MAX_SUPPORT] = {0}; +static int8_t *sDispFrameBuffer = NULL; + +int32_t DispInit(uint32_t devId) +{ + struct PanelData *panelData = GetPanel(devId); + HDF_LOGI("enter in %s\n", __FUNCTION__); + + if (devId >= LCD_MAX_SUPPORT) { + HDF_LOGE("DispInit->devId = %d fail to <= LCD_MAX_SUPPORT! ", devId); + return HDF_ERR_INVALID_PARAM; + } + + if (lcdInit[devId] == 1) { + HDF_LOGI("DispInit: lcdInit[%d] == 1", devId); + return HDF_SUCCESS; + } + + if (panelData == NULL) { + HDF_LOGE("%s: GetPanelData failed", __func__); + return HDF_ERR_INVALID_PARAM; + } + + if (panelData->init) { + /* panel driver init */ + if (panelData->init(panelData) != HDF_SUCCESS) { + HDF_LOGE("%s: panelData->init failed", __func__); + return HDF_FAILURE; + } + } + + lcdInit[devId] = 1; + + return HDF_SUCCESS; +} + +int32_t DispGetInfo(uint32_t devId, struct DispInfo *info) +{ + if (info == NULL) { + HDF_LOGE("DispGetInfo: info == NULL !"); + return HDF_FAILURE; + } + struct PanelData *panelData = GetPanel(devId); + if (panelData == NULL) { + HDF_LOGE("%s: GetPanelData failed", __func__); + return HDF_FAILURE; + } + struct PanelInfo *panelInfo = panelData->info; + if (panelInfo == NULL) { + HDF_LOGE("%s: GetPanelInfo failed", __func__); + return HDF_FAILURE; + } + info->width = panelInfo->width; + info->height = panelInfo->height; + info->intfSync = OUTPUT_USER; + info->intfType = (uint32_t)panelInfo->intfType; + info->frameRate = panelInfo->frameRate; + + return HDF_SUCCESS; +} + +int32_t DispOn(uint32_t devId, uint32_t fbSize) +{ + struct PanelData *panelData = GetPanel(devId); + if (panelData == NULL) { + HDF_LOGE("%s: GetPanelData failed", __func__); + return HDF_FAILURE; + } + if (panelData->on) { + /* panel driver on */ + if (panelData->on(panelData) != HDF_SUCCESS) { + HDF_LOGE("%s: panelData->on failed", __func__); + return HDF_FAILURE; + } + } + return HDF_SUCCESS; +} + +void DispUmap(uint32_t size) +{ + if (sDispFrameBuffer != NULL) { + OsalMemFree(sDispFrameBuffer); + sDispFrameBuffer = NULL; + } +} + +void *DispMmap(uint32_t size) +{ + if (sDispFrameBuffer) { + return sDispFrameBuffer; + } else { + sDispFrameBuffer = OsalMemCalloc(size); + return sDispFrameBuffer; + } + + return NULL; +} + +int32_t DispOff(uint32_t devId) +{ + struct PanelData *panelData = GetPanel(devId); + if (panelData == NULL) { + HDF_LOGE("%s: GetPanelData failed", __func__); + return HDF_FAILURE; + } + if (panelData->off) { + /* panel driver off */ + if (panelData->off(panelData) != HDF_SUCCESS) { + HDF_LOGE("%s: panelData->off failed", __func__); + return HDF_FAILURE; + } + } + + if (sDispFrameBuffer) { + free(sDispFrameBuffer); + sDispFrameBuffer = NULL; + } + + return HDF_SUCCESS; +} + +int32_t DispSetBacklight(uint32_t devId, uint32_t level) +{ + struct PanelData *panelData = GetPanel(devId); + if (panelData == NULL) { + HDF_LOGE("%s: GetPanelData failed", __func__); + return HDF_FAILURE; + } + if (panelData->setBacklight) { + /* panel driver set backlight */ + if (panelData->setBacklight(panelData, level) != HDF_SUCCESS) { + HDF_LOGE("%s: panelData->setBacklight failed", __func__); + return HDF_FAILURE; + } + } + + return HDF_SUCCESS; +} + +void DispFlush(uint32_t devId, LayerBuffer *buffer) +{ + struct PanelData *panelData = GetPanel(devId); + if (panelData == NULL) { + HDF_LOGE("%s: GetPanelData failed", __func__); + return HDF_FAILURE; + } + + if (panelData->dispFlush) { + if (panelData->dispFlush(buffer->width, buffer->height, (uint16_t *)(buffer->data.virAddr)) != HDF_SUCCESS) { + HDF_LOGE("%s: panelData->dispFlush failed", __func__); + return HDF_FAILURE; + } + } + + return HDF_SUCCESS; +} diff --git a/khdvk_450a/liteos_m/display/display_gfx.c b/khdvk_450a/liteos_m/display/display_gfx.c new file mode 100644 index 0000000..2fe79d4 --- /dev/null +++ b/khdvk_450a/liteos_m/display/display_gfx.c @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 "display_type.h" +#include "display_gfx.h" + +int32_t GfxInitialize(GfxFuncs **funcs) +{ + if (funcs == NULL) { + return DISPLAY_NULL_PTR; + } + *funcs = NULL; + return DISPLAY_SUCCESS; +} + +int32_t GfxUninitialize(GfxFuncs *funcs) +{ + return DISPLAY_SUCCESS; +} \ No newline at end of file diff --git a/khdvk_450a/liteos_m/display/display_gralloc.c b/khdvk_450a/liteos_m/display/display_gralloc.c new file mode 100644 index 0000000..7c524a7 --- /dev/null +++ b/khdvk_450a/liteos_m/display/display_gralloc.c @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 "display_gralloc.h" +#include "display_type.h" + +int32_t GrallocInitialize(GrallocFuncs **funcs) +{ + if (funcs == NULL) { + return DISPLAY_NULL_PTR; + } + *funcs = NULL; + return DISPLAY_SUCCESS; +} + +int32_t GrallocUninitialize(GrallocFuncs *funcs) +{ + return DISPLAY_SUCCESS; +} \ No newline at end of file diff --git a/khdvk_450a/liteos_m/display/display_layer.c b/khdvk_450a/liteos_m/display/display_layer.c new file mode 100644 index 0000000..75715e1 --- /dev/null +++ b/khdvk_450a/liteos_m/display/display_layer.c @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 "hdf_log.h" +#include "disp_hal.h" +#include "display_type.h" +#include "display_layer.h" + +#define DEV_ID 0 +#define LAYER_ID 0 +#define DISP_WIDTH 320 +#define DISP_HEIGHT 480 +#define BITS_PER_PIXEL 16 // 32 +#define BITS_TO_BYTE 8 + +struct LayerPrivate { + uint32_t width; + uint32_t height; + int32_t pitch; + PixelFormat pixFmt; + void *fbAddr; + uint32_t fbSize; +}; + +static struct LayerPrivate *GetLayerInstance(void) +{ + static struct LayerPrivate layerPriv = { + .width = DISP_WIDTH, + .height = DISP_HEIGHT, + .pixFmt = PIXEL_FMT_BGR_565, + }; + + return &layerPriv; +} + +static int32_t InitDisplay(uint32_t devId) +{ + if (devId != DEV_ID) { + HDF_LOGE("devId invalid"); + return DISPLAY_FAILURE; + } + if (DispInit(devId) != DISPLAY_SUCCESS) { + HDF_LOGE("DispInit failed"); + return DISPLAY_FAILURE; + } + + return DISPLAY_SUCCESS; +} + +static int32_t DeinitDisplay(uint32_t devId) +{ + if (devId != DEV_ID) { + HDF_LOGE("devId invalid"); + return DISPLAY_FAILURE; + } + DispOff(devId); + + return DISPLAY_SUCCESS; +} + +static int32_t OpenLayer(uint32_t devId, const LayerInfo *layerInfo, uint32_t *layerId) +{ + if (layerInfo == NULL || layerId == NULL) { + HDF_LOGE("pointer is null"); + return DISPLAY_NULL_PTR; + } + if (devId != DEV_ID) { + HDF_LOGE("devId invalid"); + return DISPLAY_FAILURE; + } + struct LayerPrivate *priv = GetLayerInstance(); + priv->width = layerInfo->width; + priv->height = layerInfo->height; + priv->pixFmt = layerInfo->pixFormat; + priv->pitch = layerInfo->width * layerInfo->bpp / BITS_TO_BYTE; + priv->fbSize = ((priv->pitch * priv->height) + 0xfff) & (~0xfff); + + if (DispOn(devId, priv->fbSize) != DISPLAY_SUCCESS) { + HDF_LOGE("DispOn failed"); + return DISPLAY_FAILURE; + } + *layerId = LAYER_ID; + return DISPLAY_SUCCESS; +} + +static int32_t CloseLayer(uint32_t devId, uint32_t layerId) +{ + if (devId != DEV_ID) { + HDF_LOGE("devId invalid"); + return DISPLAY_FAILURE; + } + + if (layerId != LAYER_ID) { + HDF_LOGE("layerId invalid"); + return DISPLAY_FAILURE; + } + + return DISPLAY_SUCCESS; +} + +static int32_t GetDisplayInfo(uint32_t devId, DisplayInfo *dispInfo) +{ + if (dispInfo == NULL) { + HDF_LOGE("dispInfo is null"); + return DISPLAY_NULL_PTR; + } + if (devId != DEV_ID) { + HDF_LOGE("devId invalid"); + return DISPLAY_FAILURE; + } + struct DispInfo info = {0}; + + if (DispGetInfo(devId, &info) != DISPLAY_SUCCESS) { + HDF_LOGE("DispGetInfo failed"); + return DISPLAY_FAILURE; + } + + dispInfo->width = info.width; + dispInfo->height = info.height; + dispInfo->rotAngle = ROTATE_NONE; + return DISPLAY_SUCCESS; +} + +static int32_t Flush(uint32_t devId, uint32_t layerId, LayerBuffer *buffer) +{ + if (devId != DEV_ID) { + HDF_LOGE("devId invalid"); + return DISPLAY_FAILURE; + } + if (layerId != LAYER_ID) { + HDF_LOGE("layerId invalid"); + return DISPLAY_FAILURE; + } + if (buffer == NULL) { + HDF_LOGE("buffer is null"); + return DISPLAY_FAILURE; + } + + DispFlush(devId, buffer); + + return DISPLAY_SUCCESS; +} + +static int32_t GetLayerBuffer(uint32_t devId, uint32_t layerId, LayerBuffer *buffer) +{ + if (buffer == NULL) { + HDF_LOGE("buffer is null"); + return DISPLAY_NULL_PTR; + } + if (devId != DEV_ID) { + HDF_LOGE("devId invalid"); + return DISPLAY_FAILURE; + } + if (layerId != LAYER_ID) { + HDF_LOGE("layerId invalid"); + return DISPLAY_FAILURE; + } + struct LayerPrivate *priv = GetLayerInstance(); + buffer->fenceId = 0; + buffer->width = priv->width; + buffer->height = priv->height; + buffer->pixFormat = priv->pixFmt; + buffer->pitch = priv->pitch; + priv->fbAddr = (void *)DispMmap(priv->fbSize); + if (priv->fbAddr == NULL) { + HDF_LOGE("mmap fb address failed, size 0x%x", priv->fbSize); + priv->pitch = 0; + priv->fbSize = 0; + return DISPLAY_FAILURE; + } + buffer->data.phyAddr = (uint32_t)priv->fbAddr; + buffer->data.virAddr = priv->fbAddr; + if (buffer->data.virAddr == NULL) { + HDF_LOGE("virAddr null"); + return DISPLAY_FAILURE; + } + return DISPLAY_SUCCESS; +} + +int32_t LayerInitialize(LayerFuncs **funcs) +{ + if (funcs == NULL) { + HDF_LOGE("funcs is null"); + return DISPLAY_NULL_PTR; + } + + LayerFuncs *lFuncs = (LayerFuncs *)malloc(sizeof(LayerFuncs)); + if (lFuncs == NULL) { + HDF_LOGE("lFuncs is null"); + return DISPLAY_NULL_PTR; + } + + (void)memset_s(lFuncs, sizeof(LayerFuncs), 0, sizeof(LayerFuncs)); + lFuncs->InitDisplay = InitDisplay; + lFuncs->DeinitDisplay = DeinitDisplay; + lFuncs->GetDisplayInfo = GetDisplayInfo; + lFuncs->CreateLayer = OpenLayer; + lFuncs->CloseLayer = CloseLayer; + lFuncs->Flush = Flush; + lFuncs->GetLayerBuffer = GetLayerBuffer; + *funcs = lFuncs; + + return DISPLAY_SUCCESS; +} + +int32_t LayerUninitialize(LayerFuncs *funcs) +{ + if (funcs == NULL) { + HDF_LOGE("funcs is null"); + return DISPLAY_NULL_PTR; + } + free(funcs); + + return DISPLAY_SUCCESS; +} diff --git a/khdvk_450a/liteos_m/display/lcd_abs_if.c b/khdvk_450a/liteos_m/display/lcd_abs_if.c new file mode 100644 index 0000000..54ca997 --- /dev/null +++ b/khdvk_450a/liteos_m/display/lcd_abs_if.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 "lcd_abs_if.h" +#include "hdf_log.h" + +#define TRANSFORM_KILO 1000 +#define TRANSFORM_MILL 1000000 + +static struct PanelManager g_panelManager = {0}; + +#define LCD_HDF_SUCCESS (0) /* < The operation is successful. */ +#define LCD_HDF_FAILURE (-1) /* < Failed to invoke the OS underlying function. */ +#define LCD_HDF_ERR_INVALID_PARAM (-3) /* < Invalid parameter. */ + +int32_t RegisterPanel(struct PanelData *data) +{ + HDF_LOGI("enter in %s\n", __FUNCTION__); + + int32_t panelNum; + if (data == NULL) { + HDF_LOGE("%s: panel data is null", __func__); + return LCD_HDF_ERR_INVALID_PARAM; + } + panelNum = g_panelManager.panelNum; + if (panelNum >= PANEL_MAX) { + HDF_LOGE("%s registered panel up PANEL_MAX", __func__); + return LCD_HDF_FAILURE; + } + g_panelManager.panel[panelNum] = data; + g_panelManager.panelNum++; + + return LCD_HDF_SUCCESS; +} + +struct PanelManager *GetPanelManager(void) +{ + if (g_panelManager.panelNum == 0) { + return NULL; + } else { + return &g_panelManager; + } +} + +struct PanelData *GetPanel(int32_t index) +{ + struct PanelManager *panelManager = NULL; + + panelManager = GetPanelManager(); + if (panelManager == NULL) { + HDF_LOGE("%s panelManager is null", __func__); + return NULL; + } + if (index >= g_panelManager.panelNum) { + HDF_LOGE("%s index is greater than g_panelManager.panelNum", __func__); + return NULL; + } + + return panelManager->panel[index]; +} \ No newline at end of file diff --git a/khdvk_450a/liteos_m/display/lcd_abs_if.h b/khdvk_450a/liteos_m/display/lcd_abs_if.h new file mode 100644 index 0000000..c6313c2 --- /dev/null +++ b/khdvk_450a/liteos_m/display/lcd_abs_if.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 LCD_ABS_IF_H +#define LCD_ABS_IF_H + +#include "disp_hal.h" + +/* support max panel number */ +#define PANEL_MAX 1 +#define LCD_PANEL_DEV_ID 0 + +struct BlkDesc { + uint32_t type; + uint32_t minLevel; + uint32_t maxLevel; + uint32_t defLevel; +}; + +struct PanelInfo { + uint32_t width; + uint32_t height; + uint32_t hbp; + uint32_t hfp; + uint32_t hsw; + uint32_t vbp; + uint32_t vfp; + uint32_t vsw; + uint32_t frameRate; + uint32_t dev_id; + uint32_t intfType; + enum IntfSync intfSync; + struct BlkDesc blk; +}; + +struct PanelStatus { + uint32_t currLevel; +}; + +struct PanelData { + struct HdfDeviceObject *object; + int32_t (*init)(struct PanelData *panel); + int32_t (*on)(struct PanelData *panel); + int32_t (*off)(struct PanelData *panel); + int32_t (*setBacklight)(struct PanelData *panel, uint32_t level); + int32_t (*dispFlush)(uint16_t disWidth, uint16_t disHeight, uint16_t *dataBuffer); + struct PanelInfo *info; + struct PanelStatus status; +}; + +struct PanelManager { + struct PanelData *panel[PANEL_MAX]; + uint32_t panelNum; +}; + +int32_t RegisterPanel(struct PanelData *data); +struct PanelManager *GetPanelManager(void); +struct PanelData *GetPanel(int32_t index); + +#endif /* LCD_ABS_IF_H */ diff --git a/khdvk_450a/liteos_m/display/lcd_gd32f4xx.c b/khdvk_450a/liteos_m/display/lcd_gd32f4xx.c new file mode 100644 index 0000000..9ef1137 --- /dev/null +++ b/khdvk_450a/liteos_m/display/lcd_gd32f4xx.c @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 "hdf_log.h" +#include "hdf_device_desc.h" +#include "device_resource_if.h" +#include "osal_time.h" +#include "lcd_abs_if.h" +#include "tli_ipa_config.h" +#include "lcd_hardware_init.h" + +#define HDF_LOG_TAG gd_lcd + +#define WIDTH (320) +#define HEIGHT (480) +#define PICTURE_DEFAULT_POSITION_X 0 +#define PICTURE_DEFAULT_POSITION_Y 0 +#define PICTURE_WIDTH 162 +#define PICTURE_HEIGHT 320 +#define DELAY_500_MS 500 +#define DELAY_50_MS 50 +#define DISWIDTH 137 +#define DISHEIGHT 160 +#define DISHEIGHT_STANDARD 310 +#define DISHEIGHT_STEP 10 +static int32_t PanelReadId(uint32_t *p_dev_id); +struct PanelDevice { + struct PanelData panelData; + struct PanelInfo panelInfo; +}; + +static struct PanelDevice priv = { + .panelInfo = + { + .width = WIDTH, + .height = HEIGHT, + .frameRate = 60, + .intfSync = OUTPUT_USER, + }, +}; +#define US_TO_MS_CONV (1000) + +static void LcdMDelay(uint32_t timeOut) +{ + OsalTimespec startTick = {0, 0}; + OsalTimespec endTick = {0, 0}; + OsalTimespec diffTick = {0, 0}; + + OsalGetTime(&startTick); + do { + OsalMSleep(1); + + /* time out break */ + OsalGetTime(&endTick); + OsalDiffTime(&startTick, &endTick, &diffTick); + if ((uint32_t)(diffTick.sec * US_TO_MS_CONV + diffTick.usec / US_TO_MS_CONV) >= timeOut) { + break; + } + } while (true); +} +#define RGB565_DATA_BUFF_SIZE 307200 // 320*480*2=307200 137*320*2=87680 +static uint8_t *g_blended_address_buffer = NULL; + +static int32_t PanelInit(struct PanelData *panel) +{ + HDF_LOGI("enter in %s\n", __FUNCTION__); + static const unsigned char gImageLogo[32] = {0}; + if (panel == NULL) { + HDF_LOGE("in %s: panel == NULL", __FUNCTION__); + return HDF_ERR_INVALID_PARAM; + } + if (g_blended_address_buffer == NULL) { + g_blended_address_buffer = (uint8_t *)OsalMemCalloc(RGB565_DATA_BUFF_SIZE); + if (g_blended_address_buffer == NULL) { + HDF_LOGE("in %s:%s %d: mallc g_blended_address_buffer failed\n", __FILE__, __FUNCTION__, __LINE__); + return; + } + + memset_s(&g_blended_address_buffer[0], RGB565_DATA_BUFF_SIZE, 0, RGB565_DATA_BUFF_SIZE); + } + + LcdMDelay(DELAY_500_MS); + + InitLcdGpio(); + + InitLcdRegister(); // init lcd register + + ConfigTli(); + SetLcdBackgroundLayer(); + SetLcdFrontLayer(0, PICTURE_DEFAULT_POSITION_X, PICTURE_DEFAULT_POSITION_Y, 1, 1, + (uint32_t)gImageLogo); // set layer0 + tli_layer_enable(LAYER0); + tli_layer_enable(LAYER1); + tli_reload_config(TLI_FRAME_BLANK_RELOAD_EN); + tli_enable(); + + SetLcdFrontLayer(1, PICTURE_DEFAULT_POSITION_X, PICTURE_DEFAULT_POSITION_Y, WIDTH, HEIGHT, + (uint32_t)&g_blended_address_buffer[0]); // set layer1 + + tli_reload_config(TLI_REQUEST_RELOAD_EN); + + return HDF_SUCCESS; +} + +static int32_t PanelReadId(uint32_t *p_dev_id) +{ + return HDF_SUCCESS; +} + +static int32_t PanelOn(struct PanelData *panel) +{ + return HDF_SUCCESS; +} + +static int32_t PanelOff(struct PanelData *panel) +{ + return HDF_SUCCESS; +} + +static int32_t PanelSetBacklight(struct PanelData *panel, uint32_t level) +{ + return HDF_SUCCESS; +} + +static int32_t PanelFlush(uint16_t disWidth, uint16_t disHeight, uint16_t *dataBuffer) +{ + if ((disWidth <= 0) || (disHeight <= 0) || (dataBuffer == NULL)) { + HDF_LOGE("input para is wrong: disWidth(%d) disHeight(%d) dataBuffer(%p)", disWidth, disHeight, dataBuffer); + return HDF_ERR_INVALID_PARAM; + } + + SetLcdFrontLayer(1, PICTURE_DEFAULT_POSITION_X, PICTURE_DEFAULT_POSITION_X, disWidth, disHeight, + (uint32_t)&g_blended_address_buffer[0]); + tli_reload_config(TLI_REQUEST_RELOAD_EN); // make layer_settings in work + +#ifdef USE_IPA + ipaConfig(disWidth, disHeight, (uint32_t)dataBuffer, (uint32_t)&g_blended_address_buffer[0]); + ipa_transfer_enable(); + while (RESET == ipa_interrupt_flag_get(IPA_INT_FLAG_FTF)) { } +#else + uint16_t area_multip = 2; + memcpy_s(&g_blended_address_buffer[0], (disWidth * disHeight * area_multip), dataBuffer, + (disWidth * disHeight * area_multip)); +#endif + + return HDF_SUCCESS; +} + +static int32_t PanelDriverInit(struct HdfDeviceObject *object) +{ + HDF_LOGI("enter in %s\n", __FUNCTION__); + + if (object == NULL) { + return HDF_ERR_INVALID_PARAM; + } + + priv.panelData.info = &priv.panelInfo; + priv.panelData.init = PanelInit; + priv.panelData.on = PanelOn; + priv.panelData.off = PanelOff; + priv.panelData.setBacklight = PanelSetBacklight; + priv.panelData.dispFlush = PanelFlush; + priv.panelData.object = object; + if (RegisterPanel(&priv.panelData) != HDF_SUCCESS) { + HDF_LOGE("%s: RegisterPanel failed", __func__); + return HDF_FAILURE; + } + + return HDF_SUCCESS; +} + +static int32_t PanelDriverBind(struct HdfDeviceObject *device) +{ + (void)device; + return HDF_SUCCESS; +} + +static void PanelDriverRelease(struct HdfDeviceObject *device) +{ + (void)device; +} + +static struct HdfDriverEntry g_lcdDriverEntry = { + .moduleVersion = 1, + .moduleName = "GD_LCD_MODULE_HDF", + .Bind = PanelDriverBind, + .Init = PanelDriverInit, + .Release = PanelDriverRelease, +}; + +HDF_INIT(g_lcdDriverEntry); \ No newline at end of file diff --git a/khdvk_450a/liteos_m/display/lcd_hardware_init.c b/khdvk_450a/liteos_m/display/lcd_hardware_init.c new file mode 100644 index 0000000..a84e88a --- /dev/null +++ b/khdvk_450a/liteos_m/display/lcd_hardware_init.c @@ -0,0 +1,362 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 "lcd_hardware_init.h" + +#define LCD_SPI_CS(a) \ + do { \ + if (a) { \ + gpio_bit_set(LCD_CS_GPIO_PORT, LCD_CS_PIN); \ + } else { \ + gpio_bit_reset(LCD_CS_GPIO_PORT, LCD_CS_PIN); \ + } \ + } while (0) +#define SPI_DCLK(a) \ + do { \ + if (a) { \ + gpio_bit_set(LCD_SPI_SCK_GPIO_PORT, LCD_SPI_SCK_PIN); \ + } else { \ + gpio_bit_reset(LCD_SPI_SCK_GPIO_PORT, LCD_SPI_SCK_PIN); \ + } \ + } while (0) +#define SPI_SDA(a) \ + do { \ + if (a) { \ + gpio_bit_set(LCD_SPI_MOSI_GPIO_PORT, LCD_SPI_MOSI_PIN); \ + } else { \ + gpio_bit_reset(LCD_SPI_MOSI_GPIO_PORT, LCD_SPI_MOSI_PIN); \ + } \ + } while (0) + +#define DELAY_120_MS 120 +#define DELAY_20_MS 20 +#define WRITE_OFFSET 8 +static void delay(uint32_t count); + +/*! + \brief enable the LCD + \param[in] none + \param[out] none + \retval none +*/ +void lcdEnable(void) +{ + gpio_bit_set(LCD_CS_GPIO_PORT, LCD_CS_PIN); +} + +/*! + \brief disable the LCD + \param[in] none + \param[out] none + \retval none +*/ +void lcdDisable(void) +{ + gpio_bit_reset(LCD_CS_GPIO_PORT, LCD_CS_PIN); +} + +/*! + \brief configure the LCD control line + \param[in] none + \param[out] none + \retval none +*/ +void lcdCtrlGpioConfig(void) +{ + /* enable GPIOs clock */ + rcu_periph_clock_enable(LCD_CS_GPIO_CLK); + rcu_periph_clock_enable(LCD_RS_GPIO_CLK); + + /* configure LCD_CS_GPIO_PORT(PD11) and LCD_RS_GPIO_PORT(PE3) */ + gpio_mode_set(LCD_CS_GPIO_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LCD_CS_PIN); + gpio_output_options_set(LCD_CS_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LCD_CS_PIN); + + gpio_mode_set(LCD_RS_GPIO_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LCD_RS_PIN); + gpio_output_options_set(LCD_RS_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LCD_RS_PIN); + + /* set the chip select pin */ + lcdCtrlLineSet(LCD_CS_GPIO_PORT, LCD_CS_PIN); +} + +/*! + \brief set the LCD control line + \param[in] gpiox: control line GPIO + \arg LCD_CS_GPIO_PORT: LCD chip select GPIO + \arg LCD_RS_GPIO_PORT: LCD register/RAM selection GPIO + \param[in] gpiopin: control line pin + \arg LCD_CS_PIN: LCD chip select pin + \arg LCD_RS_PIN: LCD register/RAM selection pin + \param[out] none + \retval none +*/ +void lcdCtrlLineSet(uint32_t gpiox, uint16_t gpiopin) +{ + gpio_bit_set(gpiox, gpiopin); +} + +/*! + \brief reset the LCD control line + \param[in] gpiox: control line GPIO + \arg LCD_CS_GPIO_PORT: LCD chip select GPIO + \arg LCD_RS_GPIO_PORT: LCD register/RAM selection GPIO + \param[in] gpiopin: control line pin + \arg LCD_CS_PIN: LCD chip select pin + \arg LCD_RS_PIN: LCD register/RAM selection pin + \param[out] none + \retval none +*/ +void lcdCtrlLineReset(uint32_t gpiox, uint16_t gpiopin) +{ + gpio_bit_reset(gpiox, gpiopin); +} + +/*! + \brief configure the LCD SPI and it's GPIOs + \param[in] none + \param[out] none + \retval none +*/ +void InitLcdSpiGpio(void) +{ + /* GPIO clock enable */ + rcu_periph_clock_enable(LCD_SPI_SCK_GPIO_CLK); + rcu_periph_clock_enable(LCD_SPI_MOSI_GPIO_CLK); + + /* configure the LCD SPI pins */ + gpio_mode_set(LCD_SPI_SCK_GPIO_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LCD_SPI_SCK_PIN); + gpio_output_options_set(LCD_SPI_SCK_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LCD_SPI_SCK_PIN); + gpio_mode_set(LCD_SPI_MOSI_GPIO_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LCD_SPI_MOSI_PIN); + gpio_output_options_set(LCD_SPI_MOSI_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LCD_SPI_MOSI_PIN); +} + +/*! + \brief write command to select LCD register + \param[in] lcd_register: the address of the selected register + \param[out] none + \retval none +*/ +void lcdCommandWrite(uint8_t lcd_register) +{ + /* reset LCD_RS to send command */ + lcdCtrlLineReset(LCD_RS_GPIO_PORT, LCD_RS_PIN); + + /* reset LCD control line and send command */ + lcdDisable(); + while (RESET == spi_i2s_flag_get(LCD_SPI, SPI_FLAG_TBE)) { } + spi_i2s_data_transmit(LCD_SPI, lcd_register); + + /* wait until a data is sent */ + while (RESET != spi_i2s_flag_get(LCD_SPI, SPI_FLAG_TRANS)) { } + + lcdEnable(); +} + +/*! + \brief write data to select LCD register + \param[in] value: the value that will be written to the selected register + \param[out] none + \retval none +*/ +void lcdDateWrite(uint8_t value) +{ + /* set LCD_RS to send data */ + lcdCtrlLineSet(LCD_RS_GPIO_PORT, LCD_RS_PIN); + + /* reset LCD control line and send data */ + lcdDisable(); + while (RESET == spi_i2s_flag_get(LCD_SPI, SPI_FLAG_TBE)) { } + + spi_i2s_data_transmit(LCD_SPI, value); + + /* wait until a data is sent */ + while (RESET != spi_i2s_flag_get(LCD_SPI, SPI_FLAG_TRANS)) { } + + lcdEnable(); +} + +/*! + \brief GPIO emulated SPI byte write + \param[in] byte: data to be sent + \param[out] none + \retval none +*/ +void spiIOByteWrite(unsigned char byteIn) +{ + unsigned char n; + unsigned char byte = byteIn; + for (n = 0; n < WRITE_OFFSET; n++) { + if (byte & 0x80) { + SPI_SDA(1); + } else { + SPI_SDA(0); + } + byte <<= 1; + + SPI_DCLK(0); + SPI_DCLK(1); + } +} + +/*! + \brief GPIO emulated SPI write command + \param[in] cmd: command to be sent + \param[out] none + \retval none +*/ +void spiIOCommandWrite(uint8_t cmd) +{ + LCD_SPI_CS(0); + SPI_SDA(0); + SPI_DCLK(0); + SPI_DCLK(1); + spiIOByteWrite(cmd); + + LCD_SPI_CS(1); +} + +/*! + \brief GPIO emulated SPI write data + \param[in] tem_data: data to be sent + \param[out] none + \retval none +*/ +void spiIODateWrite(uint8_t tem_data) +{ + LCD_SPI_CS(0); + SPI_SDA(1); + SPI_DCLK(0); + SPI_DCLK(1); + spiIOByteWrite(tem_data); + LCD_SPI_CS(1); +} + +void InitLcdRegisterBefore(void) +{ + delay(DELAY_120_MS); + + LCD_SPI_CS(1); + delay(DELAY_20_MS); + LCD_SPI_CS(0); + + spiIOCommandWrite(0xE0); // P-Gamma + spiIODateWrite(0x00); + spiIODateWrite(0x10); + spiIODateWrite(0x14); + spiIODateWrite(0x03); + spiIODateWrite(0x0E); + spiIODateWrite(0x04); + spiIODateWrite(0x36); + spiIODateWrite(0x56); + spiIODateWrite(0x4B); + spiIODateWrite(0x04); + spiIODateWrite(0x0C); + spiIODateWrite(0x0A); + spiIODateWrite(0x30); + spiIODateWrite(0x34); + spiIODateWrite(0x0F); + + spiIOCommandWrite(0XE1); // N-Gamma + spiIODateWrite(0x00); + spiIODateWrite(0x0E); + spiIODateWrite(0x13); + spiIODateWrite(0x03); + spiIODateWrite(0x10); + spiIODateWrite(0x06); + spiIODateWrite(0x3E); + spiIODateWrite(0x34); + spiIODateWrite(0x55); + spiIODateWrite(0x05); + spiIODateWrite(0x0F); + spiIODateWrite(0x0E); + spiIODateWrite(0x3A); + spiIODateWrite(0x3E); + spiIODateWrite(0x0F); +} +void InitLcdRegister(void) +{ + InitLcdRegisterBefore(); + spiIOCommandWrite(0XC0); // Power Control 1 + spiIODateWrite(0x0F); // Vreg1out + spiIODateWrite(0x0C); // Verg2out + + spiIOCommandWrite(0xC1); // Power Control 2 + spiIODateWrite(0x41); // VGH,VGL + + spiIOCommandWrite(0xC5); // Power Control 3 + spiIODateWrite(0x00); + spiIODateWrite(0x21); // Vcom + spiIODateWrite(0x80); + + spiIOCommandWrite(0x2a); + spiIODateWrite(0 >> WRITE_OFFSET); + spiIODateWrite(0); + spiIODateWrite(LCD_PIXEL_WIDTH >> WRITE_OFFSET); + spiIODateWrite((uint8_t)LCD_PIXEL_WIDTH); + + spiIOCommandWrite(0x2b); + spiIODateWrite(0 >> WRITE_OFFSET); + spiIODateWrite(0); + spiIODateWrite(LCD_PIXEL_HEIGHT >> WRITE_OFFSET); + spiIODateWrite((uint8_t)LCD_PIXEL_HEIGHT); + + spiIOCommandWrite(0x36); // Memory Access + spiIODateWrite(0x48); + + spiIOCommandWrite(0x3A); // Interface Pixel Format + spiIODateWrite(0x66); // 18bit + // spiIODateWrite(0x55); // 16bit + + spiIOCommandWrite(0XB0); // Interface Mode Control + spiIODateWrite(0x00); + + spiIOCommandWrite(0xB1); // Frame rate + spiIODateWrite(0xA0); // 60Hz + + spiIOCommandWrite(0xB4); // Display Inversion Control + spiIODateWrite(0x02); // 2-dot + + spiIOCommandWrite(0XB6); // RGB/MCU Interface Control + spiIODateWrite(0x22); // MCU + spiIODateWrite(0x02); // Source,Gate scan dieection + + spiIOCommandWrite(0XE9); // Set Image Function + spiIODateWrite(0x00); // disable 24 bit data input + + spiIOCommandWrite(0xF7); // Adjust Control + spiIODateWrite(0xA9); + spiIODateWrite(0x51); + spiIODateWrite(0x2C); + spiIODateWrite(0x82); // D7 stream, loose + + spiIOCommandWrite(0x21); // Normal Black + + spiIOCommandWrite(0x11); // Sleep out + delay(DELAY_120_MS); + spiIOCommandWrite(0x29); // Display on + + delay(DELAY_120_MS); +} + +/*! + \brief insert a delay time + \param[in] count: delay time + \param[out] none + \retval none +*/ +static void delay(__IO uint32_t count) +{ + __IO uint32_t index = 0; + for (index = count; index != 0; index--) { } +} diff --git a/khdvk_450a/liteos_m/display/lcd_hardware_init.h b/khdvk_450a/liteos_m/display/lcd_hardware_init.h new file mode 100644 index 0000000..8543def --- /dev/null +++ b/khdvk_450a/liteos_m/display/lcd_hardware_init.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 LCD_HARDWARE_INIT_H_ +#define LCD_HARDWARE_INIT_H_ + +#include "gd32f4xx.h" + +#define LCD_CS_PIN GPIO_PIN_11 +#define LCD_CS_GPIO_PORT GPIOD +#define LCD_CS_GPIO_CLK RCU_GPIOD + +#define LCD_RS_PIN GPIO_PIN_3 +#define LCD_RS_GPIO_PORT GPIOE +#define LCD_RS_GPIO_CLK RCU_GPIOE + +#define LCD_SPI_SCK_PIN GPIO_PIN_13 +#define LCD_SPI_SCK_GPIO_PORT GPIOG +#define LCD_SPI_SCK_GPIO_CLK RCU_GPIOG + +#define LCD_SPI_MOSI_PIN GPIO_PIN_14 +#define LCD_SPI_MOSI_GPIO_PORT GPIOG +#define LCD_SPI_MOSI_GPIO_CLK RCU_GPIOG + +#define LCD_SPI SPI5 +#define LCD_SPI_CLK RCU_SPI5 + +#define LCD_PIXEL_WIDTH ((uint16_t)320) +#define LCD_PIXEL_HEIGHT ((uint16_t)480) + +/* choose only one of them based on the version of LCD */ +// #define USE_LCD_VERSION_1_1 /* LCD V1.1 or earlier */ +// #define USE_LCD_VERSION_1_2 /* LCD V1.2 */ +// #define USE_LCD_VERSION_1_3 /* LCD V1.3 (TK035F3296) */ +#define USE_LCD_VERSION_1_4 /* LCD V1.4 (3LINE SPI + RGB) */ + +/* enable the LCD */ +void lcdEnable(void); +/* disable the LCD */ +void lcdDisable(void); +/* configure the LCD control line */ +void lcdCtrlGpioConfig(void); +/* set the LCD control line */ +void lcdCtrlLineSet(uint32_t gpiox, uint16_t gpiopin); +/* reset the LCD control line */ +void lcdCtrlLineReset(uint32_t gpiox, uint16_t gpiopin); +/* configure the LCD SPI and it's GPIOs */ +void InitLcdSpiGpio(void); +/* write command to select LCD register */ +void lcdCommandWrite(uint8_t lcd_register); +/* write data to select LCD register */ +void lcdDateWrite(uint8_t value); +/* configure the LCD based on the power on sequence 3(for V1.4 LCD, inanbo) */ +void InitLcdRegister(void); + +#endif /* _LCD_CONFIG_H_ */ diff --git a/khdvk_450a/liteos_m/display/tli_ipa_config.c b/khdvk_450a/liteos_m/display/tli_ipa_config.c new file mode 100644 index 0000000..730d52b --- /dev/null +++ b/khdvk_450a/liteos_m/display/tli_ipa_config.c @@ -0,0 +1,302 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 "hdf_log.h" +#include "los_task.h" +#include "gd32f4xx.h" +#include "lcd_hardware_init.h" +#include "tli_ipa_config.h" + +#define HORIZONTAL_SYNCHRONOUS_PULSE 10 +#define HORIZONTAL_BACK_PORCH 20 +#define ACTIVE_WIDTH 320 +#define HORIZONTAL_FRONT_PORCH 40 + +#define VERTICAL_SYNCHRONOUS_PULSE 2 +#define VERTICAL_BACK_PORCH 2 +#define ACTIVE_HEIGHT 480 +#define VERTICAL_FRONT_PORCH 4 +#define PLLSAI_N 108 +#define PLLSAI_P 2 +#define PLLSAI_R 3 +#define WIDTH_DOUBLE 2 +#define WIDTH_OFFSET 3 +/*! + \brief LCD configuration + \param[in] none + \param[out] none + \retval none +*/ +void InitLcdGpio(void) +{ + /* configure the LCD control line */ + lcdCtrlGpioConfig(); + lcdDisable(); + lcdEnable(); + + /* configure the GPIO of TLI */ + InitTliGpio(); + + /* configure the LCD_SPI */ + InitLcdSpiGpio(); +} + +void SetLcdBackgroundLayer(void) +{ + tli_parameter_struct tli_init_struct; + + /* initialize the parameters of structure */ + tli_struct_para_init(&tli_init_struct); + + /* TLI initialization */ + tli_init_struct.signalpolarity_hs = TLI_HSYN_ACTLIVE_LOW; + tli_init_struct.signalpolarity_vs = TLI_VSYN_ACTLIVE_LOW; + tli_init_struct.signalpolarity_de = TLI_DE_ACTLIVE_LOW; + tli_init_struct.signalpolarity_pixelck = TLI_PIXEL_CLOCK_INVERTEDTLI; + + tli_init_struct.synpsz_hpsz = HORIZONTAL_SYNCHRONOUS_PULSE - 1; + tli_init_struct.synpsz_vpsz = VERTICAL_SYNCHRONOUS_PULSE - 1; + tli_init_struct.backpsz_hbpsz = HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH - 1; + tli_init_struct.backpsz_vbpsz = VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH - 1; + tli_init_struct.activesz_hasz = HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH + ACTIVE_WIDTH - 1; + tli_init_struct.activesz_vasz = VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH + ACTIVE_HEIGHT - 1; + tli_init_struct.totalsz_htsz = + HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH + ACTIVE_WIDTH + HORIZONTAL_FRONT_PORCH - 1; + tli_init_struct.totalsz_vtsz = + VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH + ACTIVE_HEIGHT + VERTICAL_FRONT_PORCH - 1; + + /* LCD background color configure */ + tli_init_struct.backcolor_red = 0xFF; + tli_init_struct.backcolor_green = 0xFF; + tli_init_struct.backcolor_blue = 0xFF; + tli_init(&tli_init_struct); +} + +int32_t SetLcdFrontLayer(uint32_t layerId, uint32_t left, uint32_t top, uint32_t pictureWidth, uint32_t pictureHeight, + uint32_t pictureBuffer) +{ + uint32_t layerX; + tli_layer_parameter_struct tli_layer_init_struct; + /* initialize the parameters of structure */ + tli_layer_struct_para_init(&tli_layer_init_struct); + + if (layerId > 1) { + HDF_LOGE("layerId(%d) is more than 1\n", layerId); + return -1; + } + + if ((left + pictureWidth) > ACTIVE_WIDTH) { + HDF_LOGE("total width is out of range [0, %d]\n", ACTIVE_WIDTH); + return -1; + } + + if ((top + pictureHeight) > ACTIVE_HEIGHT) { + HDF_LOGE("total height is out of range [0, %d]\n", ACTIVE_HEIGHT); + return -1; + } + + if (layerId == 0) { + layerX = LAYER0; + } else { + layerX = LAYER1; + } + + tli_layer_init_struct.layer_window_leftpos = (0 + left + HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH); + tli_layer_init_struct.layer_window_rightpos = + (pictureWidth + left + HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH - 1); + tli_layer_init_struct.layer_window_toppos = (0 + top + VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH); + tli_layer_init_struct.layer_window_bottompos = + (pictureHeight + top + VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH - 1); + + tli_layer_init_struct.layer_ppf = LAYER_PPF_RGB565; + tli_layer_init_struct.layer_sa = 0xFF; + tli_layer_init_struct.layer_acf1 = LAYER_ACF1_PASA; + tli_layer_init_struct.layer_acf2 = LAYER_ACF2_PASA; + tli_layer_init_struct.layer_default_alpha = 0; + tli_layer_init_struct.layer_default_blue = 0; + tli_layer_init_struct.layer_default_green = 0; + tli_layer_init_struct.layer_default_red = 0; + tli_layer_init_struct.layer_frame_bufaddr = pictureBuffer; + tli_layer_init_struct.layer_frame_line_length = ((pictureWidth * WIDTH_DOUBLE) + WIDTH_OFFSET); + tli_layer_init_struct.layer_frame_buf_stride_offset = (pictureWidth * WIDTH_DOUBLE); + tli_layer_init_struct.layer_frame_total_line_number = pictureHeight; + tli_layer_init(layerX, &tli_layer_init_struct); + + return 0; +} + +/*! + \brief configure TLI peripheral + \param[in] none + \param[out] none + \retval none +*/ +void ConfigTli(void) +{ + tli_parameter_struct tli_init_struct; + tli_layer_parameter_struct tli_layer_init_struct; + + /* initialize the parameters of structure */ + tli_struct_para_init(&tli_init_struct); + tli_layer_struct_para_init(&tli_layer_init_struct); + + rcu_periph_clock_enable(RCU_TLI); + + /* configure the PLLSAI clock to generate lcd clock */ + if (ERROR == rcu_pllsai_config(PLLSAI_N, PLLSAI_P, PLLSAI_R)) { + while (1) { } + } + rcu_tli_clock_div_config(RCU_PLLSAIR_DIV4); + rcu_osci_on(RCU_PLLSAI_CK); + if (ERROR == rcu_osci_stab_wait(RCU_PLLSAI_CK)) { + while (1) { } + } +} + +/*! + \brief IPA initialize and configuration + \param[in] none + \param[out] none + \retval none +*/ +int32_t ipaConfig(uint32_t width, uint32_t height, uint32_t srcAddr, uint32_t desAddr) +{ + ipa_destination_parameter_struct ipa_destination_init_struct; + ipa_foreground_parameter_struct ipa_fg_init_struct; + + /* 如果目标层像素格式是ARGB8888,这些位必须是32位对齐,如果目标层像素格式是 + RGB565, ARGB1555或ARGB4444,这些位必须是16位对齐,如果违背以上对齐规 + 则,当传输使能的时候,将检测到一个配置错误。 */ + ipa_foreground_struct_para_init(&ipa_fg_init_struct); + ipa_destination_struct_para_init(&ipa_destination_init_struct); + + rcu_periph_clock_enable(RCU_IPA); + + ipa_deinit(); + /* IPA pixel format convert mode configure */ + ipa_pixel_format_convert_mode_set(IPA_FGTODE); + /* destination pixel format configure */ + ipa_destination_init_struct.destination_pf = IPA_DPF_RGB565; + /* destination memory base address configure */ + ipa_destination_init_struct.destination_memaddr = desAddr; + /* destination pre-defined alpha value RGB configure */ + ipa_destination_init_struct.destination_pregreen = 0; + ipa_destination_init_struct.destination_preblue = 0; + ipa_destination_init_struct.destination_prered = 0; + ipa_destination_init_struct.destination_prealpha = 0; + /* destination line offset configure */ + ipa_destination_init_struct.destination_lineoff = 0; + /* height of the image to be processed configure */ + ipa_destination_init_struct.image_height = height; + /* width of the image to be processed configure */ + ipa_destination_init_struct.image_width = width; + /* IPA destination initialization */ + ipa_destination_init(&ipa_destination_init_struct); + + /* IPA foreground configure */ + ipa_fg_init_struct.foreground_memaddr = srcAddr; + ipa_fg_init_struct.foreground_pf = FOREGROUND_PPF_RGB565; + ipa_fg_init_struct.foreground_alpha_algorithm = IPA_FG_ALPHA_MODE_0; + ipa_fg_init_struct.foreground_prealpha = 0; + ipa_fg_init_struct.foreground_lineoff = 0; + ipa_fg_init_struct.foreground_preblue = 0; + ipa_fg_init_struct.foreground_pregreen = 0; + ipa_fg_init_struct.foreground_prered = 0; + /* foreground initialization */ + ipa_foreground_init(&ipa_fg_init_struct); +} + +/*! + \brief configure TLI peripheral and display blend image + \param[in] none + \param[out] none + \retval none +*/ +int32_t tliBlendConfig(uint32_t left, uint32_t top, uint32_t pictureWidth, uint32_t pictureHeight, + uint32_t pictureBuffer) +{ + SetLcdFrontLayer(1, left, top, pictureWidth, pictureHeight, pictureBuffer); + + return 0; +} +/*! + \brief configure TLI GPIO + \param[in] none + \param[out] none + \retval none +*/ +void InitTliGpio(void) +{ + /* enable the periphral clock */ + rcu_periph_clock_enable(RCU_GPIOA); + rcu_periph_clock_enable(RCU_GPIOB); + rcu_periph_clock_enable(RCU_GPIOC); + rcu_periph_clock_enable(RCU_GPIOD); + rcu_periph_clock_enable(RCU_GPIOF); + rcu_periph_clock_enable(RCU_GPIOG); + + /* configure HSYNC(PC6), VSYNC(PA4), PCLK(PG7), DE(PF10) */ + /* configure LCD_R7(PG6), LCD_R6(PA8), LCD_R5(PA12), LCD_R4(PA11), LCD_R3(PB0), + LCD_G7(PD3), LCD_G6(PC7), LCD_G5(PB11), LCD_G4(PB10), LCD_G3(PG10), LCD_G2(PA6), + LCD_B7(PB9), LCD_B6(PB8), LCD_B5(PA3), LCD_B4(PG12), LCD_B3(PG11) */ + gpio_af_set(GPIOA, GPIO_AF_14, GPIO_PIN_3); + gpio_af_set(GPIOA, GPIO_AF_14, GPIO_PIN_4); + gpio_af_set(GPIOA, GPIO_AF_14, GPIO_PIN_6); + gpio_af_set(GPIOA, GPIO_AF_14, GPIO_PIN_8); + gpio_af_set(GPIOA, GPIO_AF_14, GPIO_PIN_11); + gpio_af_set(GPIOA, GPIO_AF_14, GPIO_PIN_12); + + gpio_af_set(GPIOB, GPIO_AF_9, GPIO_PIN_0); + gpio_af_set(GPIOB, GPIO_AF_14, GPIO_PIN_8); + gpio_af_set(GPIOB, GPIO_AF_14, GPIO_PIN_9); + gpio_af_set(GPIOB, GPIO_AF_14, GPIO_PIN_10); + gpio_af_set(GPIOB, GPIO_AF_14, GPIO_PIN_11); + + gpio_af_set(GPIOC, GPIO_AF_14, GPIO_PIN_6); + gpio_af_set(GPIOC, GPIO_AF_14, GPIO_PIN_7); + + gpio_af_set(GPIOD, GPIO_AF_14, GPIO_PIN_3); + + gpio_af_set(GPIOF, GPIO_AF_14, GPIO_PIN_10); + + gpio_af_set(GPIOG, GPIO_AF_14, GPIO_PIN_6); + gpio_af_set(GPIOG, GPIO_AF_14, GPIO_PIN_7); + gpio_af_set(GPIOG, GPIO_AF_9, GPIO_PIN_10); + gpio_af_set(GPIOG, GPIO_AF_14, GPIO_PIN_11); + gpio_af_set(GPIOG, GPIO_AF_9, GPIO_PIN_12); + + gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, + GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_6 | GPIO_PIN_8 | GPIO_PIN_11 | GPIO_PIN_12); + gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, + GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_6 | GPIO_PIN_8 | GPIO_PIN_11 | GPIO_PIN_12); + + gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, + GPIO_PIN_0 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11); + gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, + GPIO_PIN_0 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11); + + gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_6 | GPIO_PIN_7); + gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_6 | GPIO_PIN_7); + + gpio_mode_set(GPIOD, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_3); + gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_3); + + gpio_mode_set(GPIOF, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_10); + gpio_output_options_set(GPIOF, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_10); + + gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, + GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12); + gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, + GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12); +} diff --git a/khdvk_450a/liteos_m/display/tli_ipa_config.h b/khdvk_450a/liteos_m/display/tli_ipa_config.h new file mode 100644 index 0000000..c16896a --- /dev/null +++ b/khdvk_450a/liteos_m/display/tli_ipa_config.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 TLI_IPA_CONFIG_H_ +#define TLI_IPA_CONFIG_H_ + +extern void InitLcdGpio(void); +extern int32_t ipaConfig(uint32_t width, uint32_t height, uint32_t srcAddr, uint32_t desAddr); +extern int32_t tliBlendConfig(uint32_t left, uint32_t top, uint32_t pictureWidth, uint32_t pictureHeight, + uint32_t pictureBuffer); +extern void InitTliGpio(void); +extern void SetLcdBackgroundLayer(void); +extern int32_t SetLcdFrontLayer(uint32_t layerId, uint32_t left, uint32_t top, uint32_t pictureWidth, + uint32_t pictureHeight, uint32_t pictureBuffer); +#endif \ No newline at end of file diff --git a/khdvk_450a/liteos_m/drivers/BUILD.gn b/khdvk_450a/liteos_m/drivers/BUILD.gn new file mode 100644 index 0000000..8bc1cd0 --- /dev/null +++ b/khdvk_450a/liteos_m/drivers/BUILD.gn @@ -0,0 +1,29 @@ +# Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. +# Licensed 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. + +import("//build/lite/config/component/lite_component.gni") +import("//build/lite/config/subsystem/lite_subsystem.gni") +import("//kernel/liteos_m/liteos.gni") + +module_name = get_path_info(rebase_path("."), "name") +module_group(module_name) { + modules = [ + "adc", + "i2c", + "gpio", + "uart", + "pwm", + "spi", + "dac", + ] +} diff --git a/khdvk_450a/liteos_m/drivers/Kconfig b/khdvk_450a/liteos_m/drivers/Kconfig new file mode 100644 index 0000000..4140b6b --- /dev/null +++ b/khdvk_450a/liteos_m/drivers/Kconfig @@ -0,0 +1,130 @@ +if DRIVERS_HDF +menu "User Driver" + +config DRIVERS_HDF_USER_LCD + bool "Enable Lcd Driver" + default n + depends on DRIVERS + help + Answer Y to enable lcd driver. + +config DRIVERS_HDF_USER_I2C + bool "Enable hdf I2C driver" + default n + depends on DRIVERS_HDF_PLATFORM_I2C + help + Answer Y to enable hdf I2C driver. + +config DRIVERS_HDF_USER_I2C_TEST + bool "Enable hdf I2C driver test" + default n + depends on DRIVERS_HDF_USER_I2C + help + Answer Y to enable hdf I2C driver test. + +config DRIVERS_HDF_USER_PWM + bool "Enable hdf PWM driver" + default n + depends on DRIVERS_HDF_PLATFORM_PWM + help + Answer Y to enable hdf PWM driver. + +config DRIVERS_HDF_USER_PWM_TEST + bool "Enable hdf PWM driver test" + default n + depends on DRIVERS_HDF_USER_PWM + help + Answer Y to enable hdf PWM driver test. + +config DRIVERS_HDF_USER_UART + bool "Enable hdf UART driver" + default y + depends on DRIVERS_HDF_PLATFORM_UART + help + Answer Y to enable hdf UART driver. + +config RECV_USART_SPECIFIC_DATA_THEN_RESET + bool "Enable RECEIVE USART specific data THEN RESET" + default n + depends on DRIVERS_HDF_USER_UART + help + Answer Y to enable RECV_USART_SPECIFIC_DATA_then_RESET + +config DRIVERS_HDF_USER_UART_TEST + bool "Enable hdf UART driver test" + default n + depends on DRIVERS_HDF_USER_UART + help + Answer Y to enable hdf UART driver test. + +config DRIVERS_HDF_USER_GPIO + bool "Enable hdf GPIO driver" + default n + depends on DRIVERS_HDF_PLATFORM_GPIO + help + Answer Y to enable hdf GPIO driver. + +config DRIVERS_HDF_USER_GPIO_TEST + bool "Enable hdf GPIO driver TEST" + default n + depends on DRIVERS_HDF_USER_GPIO + help + Answer Y to enable hdf GPIO driver TEST + +config DRIVERS_HDF_USER_SPI + bool "Enable hdf SPI driver" + default n + depends on DRIVERS_HDF_PLATFORM_SPI + help + Answer Y to enable hdf SPI driver. + +config DRIVERS_HDF_USER_SPI_TEST + bool "Enable hdf SPI driver test" + default n + depends on DRIVERS_HDF_USER_SPI + help + Answer Y to enable hdf SPI driver test. + +config DRIVERS_HDF_USER_DAC + bool "Enable hdf DAC driver" + default n + help + Answer Y to enable hdf DAC driver. + +config DRIVERS_HDF_USER_DAC_TEST + bool "Enable hdf DAC driver TEST" + default n + depends on DRIVERS_HDF_USER_DAC + help + Answer Y to enable hdf DAC driver TEST + +config DRIVERS_HDF_USER_ADC + bool "Enable hdf ADC driver" + default n + depends on DRIVERS_HDF_PLATFORM_ADC + help + Answer Y to enable hdf I2C driver. + +config DRIVERS_HDF_USER_ADC_TEST + bool "Enable hdf ADC driver test" + default n + depends on DRIVERS_HDF_USER_ADC + help + Answer Y to enable hdf ADC driver test. + +config DRIVERS_USER_KEY_INPUT + bool "Enable KEY INPUT driver" + default n + depends on DRIVERS_HDF_USER_GPIO + help + Answer Y to enable KEY INPUT driver. + +config DRIVERS_USER_KEY_INPUT_TEST + bool "Enable KEY INPUT driver TEST" + default n + depends on DRIVERS_USER_KEY_INPUT + help + Answer Y to enable KEY INPUT driver TEST +endmenu + +endif \ No newline at end of file diff --git a/khdvk_450a/liteos_m/drivers/adc/BUILD.gn b/khdvk_450a/liteos_m/drivers/adc/BUILD.gn new file mode 100644 index 0000000..f866034 --- /dev/null +++ b/khdvk_450a/liteos_m/drivers/adc/BUILD.gn @@ -0,0 +1,35 @@ +# Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. +# Licensed 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. + +import("//drivers/hdf_core/adapter/khdf/liteos_m/hdf.gni") + +module_switch = defined(LOSCFG_DRIVERS_HDF_USER_ADC) +module_name = get_path_info(rebase_path("."), "name") +hdf_driver(module_name) { + sources = [ "adc_gd32f4xx.c" ] + include_dirs = [ + ".", + "../../sdk/drivers/gd32f4xx_driver/include", + "//kernel/liteos_m/kernel/include", + ] + if (defined(LOSCFG_DRIVERS_HDF_CONFIG_MACRO)) { + HDF_HCS_BUILD_PATH = rebase_path( + "//device/board/$device_company/$device_name/liteos_m/hdf_config") + cmd = "if [ -f ${HDF_HCS_BUILD_PATH}/BUILD.gn ]; then echo true; else echo false; fi" + HAVE_HCS_BUILD_PATH = + exec_script("//build/lite/run_shell_cmd.py", [ cmd ], "value") + if (HAVE_HCS_BUILD_PATH) { + deps = [ "${HDF_HCS_BUILD_PATH}" ] + } + } +} diff --git a/khdvk_450a/liteos_m/drivers/adc/adc_gd32f4xx.c b/khdvk_450a/liteos_m/drivers/adc/adc_gd32f4xx.c new file mode 100644 index 0000000..0b40382 --- /dev/null +++ b/khdvk_450a/liteos_m/drivers/adc/adc_gd32f4xx.c @@ -0,0 +1,426 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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. + */ + +#ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO +#include "hcs_macro.h" +#include "hdf_config_macro.h" +#else +#include "device_resource_if.h" +#endif + +#include "hdf_device_desc.h" +#include "hdf_log.h" +#include "adc_core.h" +#include "osal_mem.h" +#include "osal_time.h" +#include "gd32f4xx_adc.h" + +#define HDF_LOG_TAG GD_ADC_MODULE_HDF + +#define CHANNEL_GROUP 0U +#define CHANNEL_LENGTH 1U +#define TIME_OUT 5000 +#define BEGIN_TIMES 0 +#define GPIO_REG_BASE 0x40020000 +#define GPIO_BIT_PER_GROUP 16 +#define GPIO_REG_STEP 0x400 +#define DELAY_TIME_MS 1 +#define ADC_REG_STEP 0x100 + +struct AdcDeviceCntlr { + struct AdcDevice device; + uint32_t regBasePhy; + uint32_t deviceNum; + uint8_t channelNums; + uint8_t validChannels[16]; + uint32_t outputPinNums[16]; + uint8_t currentChannel; + uint32_t currentPinNum; +}; +#define US_TO_MS_CONV (1000) + +static void AdcMDelay(uint32_t timeOut) +{ + OsalTimespec startTick = {0, 0}; + OsalTimespec endTick = {0, 0}; + OsalTimespec diffTick = {0, 0}; + + OsalGetTime(&startTick); + do { + OsalMSleep(1); + + /* time out break */ + OsalGetTime(&endTick); + OsalDiffTime(&startTick, &endTick, &diffTick); + if ((uint32_t)(diffTick.sec * US_TO_MS_CONV + diffTick.usec / US_TO_MS_CONV) >= timeOut) { + break; + } + } while (true); +} +static uint32_t g_times = BEGIN_TIMES; + +static inline uint32_t ToGpioPeriph(uint32_t local) +{ + uint32_t gpioPeriph = 0; + + gpioPeriph = GPIO_REG_BASE + (local / GPIO_BIT_PER_GROUP) * GPIO_REG_STEP; + + return gpioPeriph; +} + +static inline uint32_t ToGpioPin(uint32_t local) +{ + uint32_t pinNum = 0; + + pinNum = local % GPIO_BIT_PER_GROUP; + + return (BIT(pinNum)); +} + +static inline uint32_t Adc(uint32_t devNum) +{ + return ADC0 + devNum * ADC_REG_STEP; +} + +static inline uint32_t RcuAdc(uint32_t devNum) +{ + return RCU_ADC0 + devNum; +} + +static uint16_t AdcGetData(struct AdcDeviceCntlr *adc) +{ + if (adc == NULL) { + HDF_LOGE("%s %d: invalid param adc!", __func__, __LINE__); + return 0; + } + /* enable GPIOX clock */ + rcu_periph_clock_enable(ToGpioPeriph(adc->currentPinNum)); + /* config the GPIO as analog mode */ + gpio_mode_set(ToGpioPeriph(adc->currentPinNum), GPIO_MODE_ANALOG, GPIO_PUPD_NONE, ToGpioPin(adc->currentPinNum)); + /* ADC regular channel config */ + adc_regular_channel_config(adc->regBasePhy, CHANNEL_GROUP, adc->currentChannel, ADC_SAMPLETIME_480); + /* ADC software trigger enable */ + adc_software_trigger_enable(adc->regBasePhy, ADC_REGULAR_CHANNEL); + g_times = BEGIN_TIMES; + /* wait the end of conversion flag */ + while (!adc_flag_get(adc->regBasePhy, ADC_FLAG_EOC) && g_times < TIME_OUT) { + g_times++; + }; + /* clear the end of conversion flag */ + adc_flag_clear(adc->regBasePhy, ADC_FLAG_EOC); + /* return regular channel sample value */ + return adc_regular_data_read(adc->regBasePhy); +} + +static int32_t AdcDevRead(struct AdcDevice *device, uint8_t channel, uint32_t *val) +{ + int ret = HDF_FAILURE; + struct AdcDeviceCntlr *adc = NULL; + + if (device == NULL) { + HDF_LOGE("%s %d: device is null!", __func__, __LINE__); + return HDF_ERR_INVALID_PARAM; + } + + adc = (struct AdcDeviceCntlr *)device; + for (int i = 0; i < adc->channelNums; i++) { + if (channel == adc->validChannels[i]) { + adc->currentChannel = adc->validChannels[i]; + adc->currentPinNum = adc->outputPinNums[i]; + ret = HDF_SUCCESS; + break; + } + } + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s %d: invalid channel number:%d", __func__, __LINE__, channel); + return HDF_ERR_INVALID_PARAM; + } + + *val = (uint32_t)AdcGetData(adc); + if (g_times == TIME_OUT) { + HDF_LOGE("%s %d:data read out of time!", __func__, __LINE__); + return HDF_ERR_TIMEOUT; + } + + return HDF_SUCCESS; +} + +static int32_t AdcDevStop(struct AdcDevice *device) +{ + if (device == NULL) { + HDF_LOGE("%s %d: device is null!", __func__, __LINE__); + return HDF_ERR_INVALID_PARAM; + } + /* reset ADC */ + adc_deinit(); + + return HDF_SUCCESS; +} + +static int32_t AdcDevStart(struct AdcDevice *device) +{ + if (device == NULL) { + HDF_LOGE("%s %d: device is null!", __func__, __LINE__); + return HDF_ERR_INVALID_PARAM; + } + struct AdcDeviceCntlr *adc = NULL; + adc = (struct AdcDeviceCntlr *)device; + /* enable ADC clock */ + rcu_periph_clock_enable(RcuAdc(adc->deviceNum)); + /* config ADC clock */ + adc_clock_config(ADC_ADCCK_PCLK2_DIV8); + /* reset ADC */ + adc_deinit(); + /* ADC mode config */ + adc_sync_mode_config(ADC_SYNC_MODE_INDEPENDENT); + /* ADC contineous function disable */ + adc_special_function_config(adc->regBasePhy, ADC_CONTINUOUS_MODE, DISABLE); + /* ADC scan mode disable */ + adc_special_function_config(adc->regBasePhy, ADC_SCAN_MODE, DISABLE); + /* ADC data alignment config */ + adc_data_alignment_config(adc->regBasePhy, ADC_DATAALIGN_RIGHT); + /* ADC channel length config */ + adc_channel_length_config(adc->regBasePhy, ADC_REGULAR_CHANNEL, CHANNEL_LENGTH); + /* ADC trigger config */ + adc_external_trigger_source_config(adc->regBasePhy, ADC_REGULAR_CHANNEL, ADC_EXTTRIG_REGULAR_T0_CH0); + adc_external_trigger_config(adc->regBasePhy, ADC_REGULAR_CHANNEL, EXTERNAL_TRIGGER_DISABLE); + /* enable ADC interface */ + adc_enable(adc->regBasePhy); + AdcMDelay(DELAY_TIME_MS); + /* ADC calibration and reset calibration */ + adc_calibration_enable(adc->regBasePhy); + return HDF_SUCCESS; +} + +static const struct AdcMethod g_method = { + .read = AdcDevRead, + .stop = AdcDevStop, + .start = AdcDevStart, +}; + +#ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO +#define ADC_FIND_CONFIG(node, name, adc) \ + do { \ + if (strcmp(HCS_PROP(node, match_attr), name) == 0) { \ + uint32_t deviceNum = HCS_PROP(node, deviceNum); \ + uint8_t channelNums = HCS_PROP(node, channelNums); \ + uint8_t validChannels[] = HCS_ARRAYS(HCS_NODE(node, validChannels)); \ + uint32_t outputPinNums[] = HCS_ARRAYS(HCS_NODE(node, outputPinNums)); \ + adc->deviceNum = deviceNum; \ + adc->channelNums = channelNums; \ + for (int i = 0; i < channelNums; i++) { \ + adc->validChannels[i] = validChannels[i]; \ + adc->outputPinNums[i] = outputPinNums[i]; \ + } \ + result = HDF_SUCCESS; \ + } \ + } while (0) +#define PLATFORM_CONFIG HCS_NODE(HCS_ROOT, platform) +#define PLATFORM_ADC_CONFIG HCS_NODE(HCS_NODE(HCS_ROOT, platform), adc_config) +static int32_t AdcReadDrs(struct AdcDeviceCntlr *adc, const char *deviceMatchAttr) +{ + int32_t result = HDF_FAILURE; + if (adc == NULL || deviceMatchAttr == NULL) { + HDF_LOGE("%s %d: device or deviceMatchAttr is NULL", __func__, __LINE__); + return HDF_ERR_INVALID_PARAM; + } + +#if HCS_NODE_HAS_PROP(PLATFORM_CONFIG, adc_config) + HCS_FOREACH_CHILD_VARGS(PLATFORM_ADC_CONFIG, ADC_FIND_CONFIG, deviceMatchAttr, adc); +#endif + if (result != HDF_SUCCESS) { + HDF_LOGE("resourceNode %s is NULL\r\n", deviceMatchAttr); + } + return result; +} +#else +static int32_t AdcReadDrs(struct AdcDeviceCntlr *adc, struct DeviceResourceNode *node) +{ + int32_t ret = HDF_SUCCESS; + struct DeviceResourceIface *drsOps = NULL; + if (adc == NULL || node == NULL) { + HDF_LOGE("%s %d: AdcDeviceCntlr or DeviceResourceNode is null!", __func__, __LINE__); + return HDF_ERR_INVALID_PARAM; + } + + drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); + if (drsOps == NULL || drsOps->GetUint32 == NULL) { + HDF_LOGE("%s %d: invalid drs ops fail!", __func__, __LINE__); + return HDF_FAILURE; + } + + ret = drsOps->GetUint32(node, "deviceNum", &adc->deviceNum, 0); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s %d: read deviceNum fail!", __func__, __LINE__); + return ret; + } + + ret = drsOps->GetUint8(node, "channelNums", &adc->channelNums, 0); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s %d: read channelNums fail!", __func__, __LINE__); + return ret; + } + + ret = drsOps->GetUint8Array(node, "validChannels", adc->validChannels, adc->channelNums, 0); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s %d: read validChannels fail!", __func__, __LINE__); + return ret; + } + + ret = drsOps->GetUint32Array(node, "outputPinNums", &adc->outputPinNums, adc->channelNums, 0); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s %d: read outputPinNums fail!", __func__, __LINE__); + return ret; + } + adc->currentChannel = 0; + adc->currentPinNum = 0; + return HDF_SUCCESS; +} +#endif + +static int32_t AdcParseInit(struct HdfDeviceObject *device) +{ + int32_t ret = HDF_SUCCESS; + struct AdcDeviceCntlr *adc = NULL; + adc = (struct AdcDeviceCntlr *)OsalMemCalloc(sizeof(*adc)); + do { + if (adc == NULL) { + HDF_LOGE("%s %d: malloc AdcDeviceCntlr failed!", __func__, __LINE__); + ret = HDF_ERR_MALLOC_FAIL; + break; + } + HDF_LOGI("%s: Enter", __func__); + +#ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO + if (device == NULL || device->deviceMatchAttr == NULL) { + HDF_LOGE("%s %d: device or device->deviceMatchAttr is null !", __func__, __LINE__); + ret = HDF_ERR_INVALID_OBJECT; + break; + } + ret = AdcReadDrs(adc, device->deviceMatchAttr); +#else + if (device == NULL || device->property == NULL) { + HDF_LOGE("%s %d: device or device->property is null !", __func__, __LINE__); + ret = HDF_ERR_INVALID_OBJECT; + break; + } + ret = AdcReadDrs(adc, device->property); +#endif + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s %d: adc read failed!", __func__, __LINE__); + break; + } + adc->regBasePhy = Adc(adc->deviceNum); + adc->device.priv = (void *)adc; + adc->device.devNum = adc->deviceNum; + adc->device.ops = &g_method; + ret = AdcDeviceAdd(&adc->device); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s %d: adc device add failed!", __func__, __LINE__); + break; + } + HDF_LOGI("%s: adc%d init success", __func__, adc->deviceNum); + return HDF_SUCCESS; + } while (0); + + if (adc != NULL) { + AdcDeviceRemove(&adc->device); + OsalMemFree(adc); + OsalMemFree(adc->validChannels); + OsalMemFree(adc->outputPinNums); + } + return ret; +} + +static int32_t AdcInit(struct HdfDeviceObject *device) +{ + int32_t ret; + if (device == NULL) { + HDF_LOGE("%s %d: device node is null!", __func__, __LINE__); + return HDF_ERR_INVALID_PARAM; + } + + ret = AdcParseInit(device); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s %d: adc parse init failed!", __func__, __LINE__); + } + return ret; +} + +#ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO +static void AdcRemoveByObject(const struct HdfDeviceObject *device) +{ + struct AdcDevice *adcDev = NULL; + struct AdcDeviceCntlr *adc = NULL; + + if (device == NULL) { + HDF_LOGE("%s %d: device is NULL", __func__, __LINE__); + return; + } + + adcDev = device->priv; + if (adcDev == NULL) { + HDF_LOGE("%s %d: device priv is NULL\r\n", __func__, __LINE__); + return; + } + + AdcDevicePut(adcDev); + AdcDeviceRemove(adcDev); + adc = (struct AdcDeviceCntlr *)adcDev; + OsalMemFree(adcDev); +} +#else +static void AdcRemoveByNode(const struct DeviceResourceNode *node) +{ + int32_t ret; + int32_t deviceNum; + struct AdcDevice *device = NULL; + struct AdcDeviceCntlr *adc = NULL; + struct DeviceResourceIface *drsOps = NULL; + + drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); + + ret = drsOps->GetUint32(node, "deviceNum", (uint32_t *)&deviceNum, 0); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s %d: get resouce failed!", __func__, __LINE__); + return ret; + } + device = AdcDeviceGet(deviceNum); + if (device != NULL && device->priv == node) { + AdcDevicePut(device); + AdcDeviceRemove(device); + adc = (struct AdcDeviceCntlr *)device; + OsalMemFree(adc); + } +} +#endif + +static void AdcRelease(struct HdfDeviceObject *device) +{ +#ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO + AdcRemoveByObject(device); +#else + AdcRemoveByNode(device->property); +#endif +} + +static struct HdfDriverEntry g_AdcDriverEntry = { + .moduleVersion = 1, + .Init = AdcInit, + .Release = AdcRelease, + .moduleName = "GD_ADC_MODULE_HDF", +}; + +HDF_INIT(g_AdcDriverEntry); \ No newline at end of file diff --git a/khdvk_450a/liteos_m/drivers/dac/BUILD.gn b/khdvk_450a/liteos_m/drivers/dac/BUILD.gn new file mode 100644 index 0000000..466eb21 --- /dev/null +++ b/khdvk_450a/liteos_m/drivers/dac/BUILD.gn @@ -0,0 +1,46 @@ +# Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. +# Licensed 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. +import("//drivers/hdf_core/adapter/khdf/liteos_m/hdf.gni") + +module_switch = defined(LOSCFG_DRIVERS_HDF_USER_DAC) +module_name = get_path_info(rebase_path("."), "name") +hdf_driver(module_name) { + sources = [ "dac_gd32f4xx.c" ] + + if (defined(LOSCFG_DRIVERS_HDF_USER_DAC)) { + sources += [ + "$HDF_FRAMEWORKS_PATH/support/platform/src/dac/dac_core.c", + "$HDF_FRAMEWORKS_PATH/support/platform/src/dac/dac_if.c", + ] + } + + include_dirs = [ + ".", + "//drivers/hdf_core/framework/support/platform/include/dac/", + ] + + if (defined(LOSCFG_DRIVERS_HDF_USER_DAC)) { + include_dirs += [ "$HDF_FRAMEWORKS_PATH/support/platform/include/dac" ] + } + + if (defined(LOSCFG_DRIVERS_HDF_CONFIG_MACRO)) { + HDF_HCS_BUILD_PATH = rebase_path( + "//device/board/$device_company/$device_name/liteos_m/hdf_config") + cmd = "if [ -f ${HDF_HCS_BUILD_PATH}/BUILD.gn ]; then echo true; else echo false; fi" + HAVE_HCS_BUILD_PATH = + exec_script("//build/lite/run_shell_cmd.py", [ cmd ], "value") + if (HAVE_HCS_BUILD_PATH) { + deps = [ "${HDF_HCS_BUILD_PATH}" ] + } + } +} diff --git a/khdvk_450a/liteos_m/drivers/dac/dac_gd32f4xx.c b/khdvk_450a/liteos_m/drivers/dac/dac_gd32f4xx.c new file mode 100644 index 0000000..f807c5b --- /dev/null +++ b/khdvk_450a/liteos_m/drivers/dac/dac_gd32f4xx.c @@ -0,0 +1,423 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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. + */ +#ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO +#include "hcs_macro.h" +#include "hdf_config_macro.h" +#else +#include "device_resource_if.h" +#endif +#include "hdf_device_desc.h" +#include "hdf_log.h" +#include "dac_core.h" +#include "gd32f4xx_dac.h" + +#define ALIGN_NUM 3 +#define MAX_CHANNEL_NUM 2 +#define MAX_VAL 4096 +#define GPIO_PIN_TOTAL 140 +#define GPIO_REG_BASE 0x40020000 +#define GPIO_REG_STEP 0x00000400 +#define GPIO_BIT_PER_GROUP 16 + +struct DacCntrl { + struct DacDevice device; + uint32_t deviceNum; + uint32_t validChannel; + uint32_t outputPinNum; + uint32_t alignment; +}; + +static uint32_t g_alignedList[ALIGN_NUM] = { + DAC_ALIGN_12B_R, + DAC_ALIGN_12B_L, + DAC_ALIGN_8B_R, +}; + +typedef enum { + PORT_NUM_0 = 0, + PORT_NUM_1, + PORT_NUM_2, +} Port; + +static inline struct DacCntrl *ToDacDev(struct DacDevice *device) +{ + return (struct DacCntrl *)device; +} + +static inline uint32_t ToGpioPeriph(uint16_t local) +{ + uint32_t gpioPeriph = 0; + + gpioPeriph = GPIO_REG_BASE + (local / GPIO_BIT_PER_GROUP) * GPIO_REG_STEP; + + return gpioPeriph; +} + +static inline uint32_t ToGpioPin(uint16_t local) +{ + uint32_t pinNum = 0; + + pinNum = local % GPIO_BIT_PER_GROUP; + + return (BIT(pinNum)); +} + +static inline rcu_periph_enum ToGpioRcuPeriphNum(uint16_t local) +{ + rcu_periph_enum rcuPeriph; + + rcuPeriph = (rcu_periph_enum)(RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, local / GPIO_BIT_PER_GROUP)); + + return rcuPeriph; +} + +static int32_t DacDevWrite(struct DacDevice *device, uint32_t channel, uint32_t val) +{ + struct DacCntrl *dacCntrl = NULL; +#ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO + if (device == NULL) +#else + if (device == NULL || device->priv == NULL) +#endif + { + HDF_LOGE("%s: device or priv is NULL", __func__); + return HDF_ERR_INVALID_OBJECT; + } + + dacCntrl = ToDacDev(device); + if (dacCntrl == NULL) { + HDF_LOGE("%s: dacCntrl is NULL", __func__); + return HDF_ERR_INVALID_OBJECT; + } + + if ((dacCntrl->validChannel != 0) || (channel != dacCntrl->validChannel)) { + HDF_LOGE("%s: channel is invalid!", __func__); + return HDF_ERR_INVALID_PARAM; + } + + if (val > MAX_VAL) { + HDF_LOGE("%s, val = (%d) is invalid!", __func__, val); + return HDF_ERR_INVALID_PARAM; + } + + dac_data_set(channel, g_alignedList[dacCntrl->alignment], (uint16_t)val); + + return HDF_SUCCESS; +} + +static int32_t DacDevStop(struct DacDevice *device) +{ + struct DacCntrl *dacCntrl = NULL; + + if (device == NULL || device->priv == NULL) { + HDF_LOGE("%s: device or priv is NULL", __func__); + return HDF_ERR_INVALID_OBJECT; + } + + dacCntrl = ToDacDev(device); + dac_disable(dacCntrl->deviceNum); + + return HDF_SUCCESS; +} + +static int32_t DacDevStart(struct DacDevice *device) +{ + struct DacCntrl *dacCntrl = NULL; +#ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO + if (device == NULL) +#else + if (device == NULL || device->priv == NULL) +#endif + { + HDF_LOGE("%s: device or priv is NULL", __func__); + return HDF_ERR_INVALID_OBJECT; + } + + dacCntrl = ToDacDev(device); + + dac_deinit(); + dac_trigger_disable(dacCntrl->deviceNum); + dac_wave_mode_config(dacCntrl->deviceNum, DAC_WAVE_DISABLE); + dac_enable(dacCntrl->deviceNum); + + return HDF_SUCCESS; +} + +static const struct DacMethod g_DacDeviceMethod = { + .write = DacDevWrite, + .stop = DacDevStop, + .start = DacDevStart, +}; + +static void DacDevConfig(uint32_t port, uint32_t outputPinNum) +{ + rcu_periph_clock_enable(RCU_DAC); + + rcu_periph_clock_enable(ToGpioRcuPeriphNum(outputPinNum)); + gpio_mode_set(ToGpioPeriph(outputPinNum), GPIO_MODE_ANALOG, GPIO_PUPD_NONE, ToGpioPin(outputPinNum)); +} + +#ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO +#define DAC_FIND_CONFIG(node, name) \ + do { \ + HDF_LOGI("%s: Enter", __func__); \ + resource = (struct DacCntrl *)OsalMemCalloc(sizeof(*resource)); \ + if (resource == NULL) { \ + HDF_LOGE("%s: Malloc resource fail!", __func__); \ + result = HDF_ERR_MALLOC_FAIL; \ + } \ + if (HCS_PROP(node, exists) == 1) { \ + resource->deviceNum = HCS_PROP(node, deviceNum); \ + resource->validChannel = HCS_PROP(node, validChannel); \ + resource->outputPinNum = HCS_PROP(node, outputPinNum); \ + resource->alignment = HCS_PROP(node, alignment); \ + result = HDF_SUCCESS; \ + } \ + if (result != HDF_SUCCESS) { \ + HDF_LOGE("%s: Read drs fail! ret:%d", __func__, result); \ + OsalMemFree(resource); \ + resource = NULL; \ + } \ + if (result == HDF_SUCCESS) { \ + DacDevConfig(resource->deviceNum, resource->outputPinNum); \ + resource->device.priv = NULL; \ + resource->device.devNum = resource->deviceNum; \ + resource->device.chanNum = resource->validChannel; \ + resource->device.ops = &g_DacDeviceMethod; \ + result = DacDeviceAdd(&resource->device); \ + } \ + if (result != HDF_SUCCESS) { \ + HDF_LOGE("%s: add Dac controller failed! ret = %d", __func__, result); \ + if (resource != NULL) { \ + OsalMemFree(resource); \ + resource = NULL; \ + } \ + } \ + HDF_LOGI("%s: DAC%d init success", __func__, resource->deviceNum); \ + } while (0) +#define PLATFORM_CONFIG HCS_NODE(HCS_ROOT, platform) +#define PLATFORM_DAC_CONFIG HCS_NODE(HCS_NODE(HCS_ROOT, platform), dac_config) +static int32_t DacDevReadDrs(void) +{ + int32_t result = HDF_FAILURE; + struct DacCntrl *resource = NULL; +#if HCS_NODE_HAS_PROP(PLATFORM_CONFIG, dac_config) + HCS_FOREACH_CHILD_VARGS(PLATFORM_DAC_CONFIG, DAC_FIND_CONFIG, 1); +#endif + if (result != HDF_SUCCESS) { + HDF_LOGE("resourceNode is NULL\r\n"); + } + return result; +} +#else +static int32_t DacDevReadDrs(struct DacCntrl *resource, const struct DeviceResourceNode *node) +{ + int32_t ret; + struct DeviceResourceIface *drsOps = NULL; + + drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); + if (drsOps == NULL || drsOps->GetUint32 == NULL) { + HDF_LOGE("%s: invalid drs ops fail!", __func__); + return HDF_FAILURE; + } + + ret = drsOps->GetUint32(node, "deviceNum", &resource->deviceNum, 0); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: read deviceNum fail!", __func__); + return ret; + } + + ret = drsOps->GetUint32(node, "validChannel", &resource->validChannel, 0); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: read validChannel fail!", __func__); + return ret; + } + + ret = drsOps->GetUint32(node, "outputPinNum", &resource->outputPinNum, 0); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: read validChannel fail!", __func__); + return ret; + } + + ret = drsOps->GetUint32(node, "alignment", &resource->alignment, 0); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: read alignment fail!", __func__); + return ret; + } + + return HDF_SUCCESS; +} +#endif + +#ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO +static int32_t DacDevParseAndInit(struct HdfDeviceObject *device, const char *deviceMatchAttr) +{ + (void)device; + int32_t ret; + if (device == NULL) { + HDF_LOGE("%s: param is NULL\r\n", __func__); + return HDF_ERR_INVALID_PARAM; + } + + ret = DacDevReadDrs(); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: dac device init fail! ret:%d", __func__, ret); + return ret; + } + + return HDF_SUCCESS; +} +#else +static int32_t DacDevParseAndInit(struct HdfDeviceObject *device, const struct DeviceResourceNode *node) +{ + (void)device; + int32_t ret; + struct DacCntrl *dacCntrl = NULL; + + if (device == NULL || device->property == NULL || node == NULL) { + HDF_LOGE("%s: param is NULL\r\n", __func__); + return HDF_ERR_INVALID_PARAM; + } + HDF_LOGI("%s: Enter", __func__); + dacCntrl = (struct DacCntrl *)OsalMemCalloc(sizeof(*dacCntrl)); + if (dacCntrl == NULL) { + HDF_LOGE("%s: Malloc dacCntrl fail!", __func__); + return HDF_ERR_MALLOC_FAIL; + } + + ret = DacDevReadDrs(dacCntrl, node); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: Read drs fail! ret:%d", __func__, ret); + OsalMemFree(dacCntrl); + dacCntrl = NULL; + return ret; + } + + DacDevConfig(dacCntrl->validChannel, dacCntrl->outputPinNum); + + dacCntrl->device.priv = (void *)node; + dacCntrl->device.devNum = dacCntrl->deviceNum; + dacCntrl->device.chanNum = dacCntrl->validChannel; + dacCntrl->device.ops = &g_DacDeviceMethod; + + ret = DacDeviceAdd(&dacCntrl->device); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: add Dac controller failed! ret = %d", __func__, ret); + if (dacCntrl != NULL) { + OsalMemFree(dacCntrl); + dacCntrl = NULL; + } + return ret; + } + HDF_LOGI("%s: DAC%d init success", __func__, dacCntrl->deviceNum); + return HDF_SUCCESS; +} +#endif + +static int32_t DacDevInit(struct HdfDeviceObject *device) +{ + int32_t ret; + const struct DeviceResourceNode *childNode = NULL; +#ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO + if (device == NULL) +#else + if (device == NULL || device->property == NULL) +#endif + { + HDF_LOGE("%s: device or property is NULL", __func__); + return HDF_ERR_INVALID_OBJECT; + } + + ret = HDF_SUCCESS; + +#ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO + ret = DacDevParseAndInit(device, device->deviceMatchAttr); + if (ret != HDF_SUCCESS) { + return ret; + } +#else + DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) + { + ret = DacDevParseAndInit(device, childNode); + if (ret != HDF_SUCCESS) { + break; + } + } +#endif + return ret; +} + +#ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO + +#else +static void DacDevRemoveByNode(const struct DeviceResourceNode *node) +{ + int32_t ret; + int16_t devNum; + + struct DacDevice *device = NULL; + struct DacCntrl *dacCntrl = NULL; + struct DeviceResourceIface *drsOps = NULL; + + drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); + if (drsOps == NULL || drsOps->GetUint32 == NULL) { + HDF_LOGE("%s: invalid drs ops fail!", __func__); + return; + } + + ret = drsOps->GetUint16(node, "devNum", (uint16_t *)&devNum, 0); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: read devNum fail!", __func__); + return; + } + + device = DacDeviceGet(devNum); + if (device != NULL && device->priv == node) { + DacDevicePut(device); + DacDeviceRemove(device); + dacCntrl = (struct DacCntrl *)device; + OsalMemFree(dacCntrl); + } + + return; +} +#endif + +static void DacDevRelease(struct HdfDeviceObject *device) +{ +#ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO + +#else + const struct DeviceResourceNode *childNode = NULL; + if (device == NULL || device->property == NULL) { + HDF_LOGE("%s: device or property is NULL", __func__); + return; + } + + DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) + { + DacDevRemoveByNode(childNode); + } +#endif +} + +static struct HdfDriverEntry g_dacDriverEntry = { + .moduleVersion = 1, + .Init = DacDevInit, + .Release = DacDevRelease, + .moduleName = "GD_DAC_MODULE_HDF", +}; + +HDF_INIT(g_dacDriverEntry); \ No newline at end of file diff --git a/khdvk_450a/liteos_m/drivers/gpio/BUILD.gn b/khdvk_450a/liteos_m/drivers/gpio/BUILD.gn new file mode 100644 index 0000000..b043625 --- /dev/null +++ b/khdvk_450a/liteos_m/drivers/gpio/BUILD.gn @@ -0,0 +1,35 @@ +# Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. +# Licensed 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. +import("//drivers/hdf_core/adapter/khdf/liteos_m/hdf.gni") + +module_switch = defined(LOSCFG_DRIVERS_HDF_USER_GPIO) +module_name = get_path_info(rebase_path("."), "name") +hdf_driver(module_name) { + sources = [ "gpio_gd32f450.c" ] + + include_dirs = [ + ".", + "//drivers/hdf_core/framework/support/platform/include/gpio/", + ] + + if (defined(LOSCFG_DRIVERS_HDF_CONFIG_MACRO)) { + HDF_HCS_BUILD_PATH = rebase_path( + "//device/board/$device_company/$device_name/liteos_m/hdf_config") + cmd = "if [ -f ${HDF_HCS_BUILD_PATH}/BUILD.gn ]; then echo true; else echo false; fi" + HAVE_HCS_BUILD_PATH = + exec_script("//build/lite/run_shell_cmd.py", [ cmd ], "value") + if (HAVE_HCS_BUILD_PATH) { + deps = [ "${HDF_HCS_BUILD_PATH}" ] + } + } +} diff --git a/khdvk_450a/liteos_m/drivers/gpio/gpio_gd32f450.c b/khdvk_450a/liteos_m/drivers/gpio/gpio_gd32f450.c new file mode 100644 index 0000000..4a3cb43 --- /dev/null +++ b/khdvk_450a/liteos_m/drivers/gpio/gpio_gd32f450.c @@ -0,0 +1,814 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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. + */ + +#ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO +#include "hcs_macro.h" +#include "hdf_config_macro.h" +#else +#include "device_resource_if.h" +#endif +#include "hdf_log.h" +#include "los_interrupt.h" +#include "gpio_core.h" +#include "gd32f4xx.h" + +#define HDF_LOG_TAG gpio_gd32f450 + +#define GPIO_PIN_TOTAL 140 +#define GPIO_REG_BASE 0x40020000 +#define GPIO_REG_STEP 0x00000400 +#define GPIO_BIT_PER_GROUP 16 + +#define DEFAULT_PRE_PRIORITY 2U +#define DEFAULT_SUB_PRIORITY 0U +#define EXIT_PIN_SOURCE_MAX GPIO_BIT_PER_GROUP +#define GPIO_MODE_DATA_LENGTH 2 +#define EXTI5_9_IRQ_START_NUM 5 +#define EXTI5_9_IRQ_END_NUM 9 +#define EXTI10_15_IRQ_START_NUM 10 +#define EXTI10_15_IRQ_END_NUM 15 +#define EXTI5_9_IRQ_PARAM_NUM 5 +#define EXTI10_15_IRQ_PARAM_NUM 6 + +typedef enum { + PIN_EXTI0 = 0, + PIN_EXTI1 = 1, + PIN_EXTI2 = 2, + PIN_EXTI3 = 3, + PIN_EXTI4 = 4, + PIN_EXTI5 = 5, + PIN_EXTI6 = 6, + PIN_EXTI7 = 7, + PIN_EXTI8 = 8, + PIN_EXTI9 = 9, + PIN_EXTI10 = 10, + PIN_EXTI11 = 11, + PIN_EXTI12 = 12, + PIN_EXTI13 = 13, + PIN_EXTI14 = 14, + PIN_EXTI15 = 15, +} EXTI0_NUM; + +typedef enum { + PIN_NUM0 = 0, + PIN_NUM1 = 1, + PIN_NUM2 = 2, + PIN_NUM3 = 3, + PIN_NUM4 = 4, + PIN_NUM5 = 5, + PIN_NUM6 = 6, + PIN_NUM7 = 7, + PIN_NUM8 = 8, + PIN_NUM9 = 9, + PIN_NUM10 = 10, + PIN_NUM11 = 11, + PIN_NUM12 = 12, + PIN_NUM13 = 13, + PIN_NUM14 = 14, + PIN_NUM15 = 15, +} PIN_NUM; +/* GPIO 分组 */ +// PA0 ~ PA15, 0-15 +// PB0 ~ PB15, 16-31 +// PC0 ~ PC15, 32-47 +// PD0 ~ PD15, 48-63 +// PE0 ~ PE15, 64-79 +// PF0 ~ PF15, 80-95 +// PG0 ~ PG15, 96-111 +// PH0 ~ PH15, 112-117 +// PI0 ~ PI11. 118-139 + +/* 一个中断线仅支持一个端口触发 */ +// EXTILineNumber Source +// 0 PA0/PB0/PC0/PD0/PE0/PF0/PG0/PH0/PI0 +// 1 PA1/PB1/PC1/PD1/PE1/PF1/PG1/PH1/PI1 +// 2 PA2/PB2/PC2/PD2/PE2/PF2/PG2/PH2/PI2 +// 3 PA3/PB3/PC3/PD3/PE3/PF3/PG3/PH3/PI3 +// 4 PA4/PB4/PC4/PD4/PE4/PF4/PG4/PH4/PI4 +// 5 PA5/PB5/PC5/PD5/PE5/PF5/PG5/PH5/PI5 +// 6 PA6/PB6/PC6/PD6/PE6/PF6/PG6/PH6/PI6 +// 7 PA7/PB7/PC7/PD7/PE7/PF7/PG7/PH7/PI7 +// 8 PA8/PB8/PC8/PD8/PE8/PF8/PG8/PH8/PI8 +// 9 PA9/PB9/PC9/PD9/PE9/PF9/PG9/PH9/PI9 +// 10 PA10/PB10/PC10/PD10/PE10/PF10/PG10/PH10/PI10 +// 11 PA11/PB11/PC11/PD11/PE11/PF11/PG11/PH11/PI11 +// 12 PA12/PB12/PC12/PD12/PE12/PF12/PG12/PH12 +// 13 PA13/PB13/PC13/PD13/PE13/PF13/PG13/PH13 +// 14 PA14/PB14/PC14/PD14/PE14/PF14/PG14/PH14 +// 15 PA15/PB15/PC15/PD15/PE15/PF15/PG15/PH15 + +struct GpioDevCntlr { + struct GpioCntlr cntlr; + + uint32_t irqSave; + OsalSpinlock lock; + + uint32_t start; + uint32_t count; +}; + +struct DevIrqInfo { + uint8_t isRegistered; + struct GpioCntlr *cntlr; + uint16_t sourceLocal; +}; +static struct DevIrqInfo g_DevIrqInfo[EXIT_PIN_SOURCE_MAX] = {0}; + +struct IrqFuncParam { + uint8_t startExti; + uint8_t endExti; + uint8_t irqRcu; +}; +static struct IrqFuncParam g_Exti[7]; + +static inline struct GpioDevCntlr *ToGpioDevCntlr(struct GpioCntlr *cntlr) +{ + if (cntlr == NULL) { + HDF_LOGE("%s, cntlr is NULL", __func__); + return NULL; + } + return (struct GpioDevCntlr *)cntlr; +} + +static inline uint32_t ToGpioPeriph(struct GpioCntlr *cntlr, uint16_t local) +{ + uint32_t gpioPeriph = 0; + + gpioPeriph = GPIO_REG_BASE + (local / GPIO_BIT_PER_GROUP) * GPIO_REG_STEP; + + return gpioPeriph; +} + +static inline uint32_t ToGpioPin(struct GpioCntlr *cntlr, uint16_t local) +{ + uint32_t pinNum = 0; + + pinNum = local % GPIO_BIT_PER_GROUP; + + return (BIT(pinNum)); +} + +static inline uint8_t ToGpioExitSourceIndex(struct GpioCntlr *cntlr, uint16_t local) +{ + return (local % GPIO_BIT_PER_GROUP); +} + +static inline exti_line_enum ToGpioExtiLineNum(struct GpioCntlr *cntlr, uint16_t local) +{ + uint32_t pinNum = 0; + + pinNum = local % GPIO_BIT_PER_GROUP; + + return (BIT(pinNum)); +} + +static inline rcu_periph_enum ToGpioRcuPeriphNum(struct GpioCntlr *cntlr, uint16_t local) +{ + rcu_periph_enum rcuPeriph; + + rcuPeriph = (rcu_periph_enum)(RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, local / GPIO_BIT_PER_GROUP)); + + return rcuPeriph; +} + +static uint8_t ToGpioRcuIndex(uint16_t local) +{ + uint16_t pinNum = 0; + uint8_t index = 0; + pinNum = local % GPIO_BIT_PER_GROUP; + if (pinNum < EXTI5_9_IRQ_START_NUM) { + index = pinNum; + } else if (pinNum < EXTI10_15_IRQ_START_NUM) { + index = EXTI5_9_IRQ_PARAM_NUM; + } else { + index = EXTI10_15_IRQ_PARAM_NUM; + } + return index; +} +static void InitExti(void) +{ + static uint8_t single = 0; + if (single == 0) { + for (int i = 0; i < EXTI5_9_IRQ_PARAM_NUM; i++) { + g_Exti[i].startExti = i; + g_Exti[i].endExti = i; + g_Exti[i].irqRcu = EXTI0_IRQn + i; + } + g_Exti[EXTI5_9_IRQ_PARAM_NUM].startExti = EXTI5_9_IRQ_START_NUM; + g_Exti[EXTI5_9_IRQ_PARAM_NUM].endExti = EXTI5_9_IRQ_END_NUM; + g_Exti[EXTI5_9_IRQ_PARAM_NUM].irqRcu = EXTI5_9_IRQn; + g_Exti[EXTI10_15_IRQ_PARAM_NUM].startExti = EXTI10_15_IRQ_START_NUM; + g_Exti[EXTI10_15_IRQ_PARAM_NUM].endExti = EXTI10_15_IRQ_END_NUM; + g_Exti[EXTI10_15_IRQ_PARAM_NUM].irqRcu = EXTI10_15_IRQn; + single = 1; + } +} + +static inline uint8_t ToGpioIrqNum(struct GpioCntlr *cntlr, uint16_t local) +{ + uint8_t index; + index = ToGpioRcuIndex(local); + return g_Exti[index].irqRcu; +} + +static inline uint8_t ToGpioExtiSourcePort(struct GpioCntlr *cntlr, uint16_t local) +{ + uint8_t groupNum = 0; + + groupNum = local / GPIO_BIT_PER_GROUP; + + return ((uint8_t)groupNum); +} + +static inline uint8_t ToGpioExtiSourcePin(struct GpioCntlr *cntlr, uint16_t local) +{ + uint8_t pinNum = 0; + + pinNum = local % GPIO_BIT_PER_GROUP; + + return ((uint8_t)pinNum); +} + +static int32_t GpioDevSetDir(struct GpioCntlr *cntlr, uint16_t local, uint16_t dir) +{ + uint32_t gpioPeriph; + uint32_t mode; + uint32_t pull; + uint32_t pin; + struct GpioDevCntlr *p = NULL; + + if (cntlr == NULL) { + HDF_LOGE("%s, cntlr is NULL", __func__); + return HDF_ERR_INVALID_PARAM; + } + + if (local >= GPIO_PIN_TOTAL) { + HDF_LOGE("%s, local(%d) is out of range", __func__, local); + return HDF_ERR_INVALID_PARAM; + } + + if ((dir != GPIO_DIR_IN) && (dir != GPIO_DIR_OUT)) { + HDF_LOGE("%s, dir(%d) is not right", __func__, dir); + return HDF_ERR_INVALID_PARAM; + } + + p = ToGpioDevCntlr(cntlr); + gpioPeriph = ToGpioPeriph(cntlr, local); + if (dir == GPIO_DIR_IN) { + mode = GPIO_MODE_INPUT; + } else { + mode = GPIO_MODE_OUTPUT; + } + pull = GPIO_PUPD_NONE; + pin = ToGpioPin(cntlr, local); + + if (OsalSpinLockIrqSave(&p->lock, &p->irqSave) != HDF_SUCCESS) { + HDF_LOGE("in %s:%s %d: get spinLock failed", __FILE__, __FUNCTION__, __LINE__); + return HDF_ERR_DEVICE_BUSY; + } + + gpio_mode_set(gpioPeriph, mode, pull, pin); + + (void)OsalSpinUnlockIrqRestore(&p->lock, &p->irqSave); + + return HDF_SUCCESS; +} + +static int32_t GpioDevGetDir(struct GpioCntlr *cntlr, uint16_t local, uint16_t *dir) +{ + uint32_t gpioPeriph; + uint32_t ctl; + uint32_t pin; + uint32_t readDir; + + if (cntlr == NULL) { + HDF_LOGE("%s, cntlr is NULL", __func__); + return HDF_ERR_INVALID_PARAM; + } + + if (local >= GPIO_PIN_TOTAL) { + HDF_LOGE("%s, local(%d) is out of range", __func__, local); + return HDF_ERR_INVALID_PARAM; + } + + if (dir == NULL) { + HDF_LOGE("%s, dir is NULL", __func__); + return HDF_ERR_INVALID_PARAM; + } + + gpioPeriph = ToGpioPeriph(cntlr, local); + pin = ToGpioPin(cntlr, local); + ctl = GPIO_CTL(gpioPeriph); + readDir = (ctl >> (GPIO_MODE_DATA_LENGTH * pin)) & 0x03; + + if (readDir == GPIO_MODE_OUTPUT) { + *dir = GPIO_DIR_OUT; + } else if (readDir == GPIO_MODE_INPUT) { + *dir = GPIO_DIR_IN; + } else { // default direction + HDF_LOGE("invalid gpio mode input/output!"); + return HDF_ERR_INVALID_PARAM; + } + + return HDF_SUCCESS; +} + +static int32_t GpioDevWrite(struct GpioCntlr *cntlr, uint16_t local, uint16_t val) +{ + uint32_t gpioPeriph; + uint32_t pin; + bit_status bitValue; + struct GpioDevCntlr *p = NULL; + + if (cntlr == NULL) { + HDF_LOGE("%s, cntlr is NULL", __func__); + return HDF_ERR_INVALID_PARAM; + } + + if (local >= GPIO_PIN_TOTAL) { + HDF_LOGE("%s, local(%d) is out of range", __func__, local); + return HDF_ERR_INVALID_PARAM; + } + p = ToGpioDevCntlr(cntlr); + gpioPeriph = ToGpioPeriph(cntlr, local); + pin = ToGpioPin(cntlr, local); + if (val == 1) { + bitValue = SET; + } else { + bitValue = RESET; + } + + if (OsalSpinLockIrqSave(&p->lock, &p->irqSave) != HDF_SUCCESS) { + HDF_LOGE("in %s:%s %d: get spinLock failed", __FILE__, __FUNCTION__, __LINE__); + return HDF_ERR_DEVICE_BUSY; + } + + gpio_bit_write(gpioPeriph, pin, bitValue); + + (void)OsalSpinUnlockIrqRestore(&p->lock, &p->irqSave); + + return HDF_SUCCESS; +} + +static int32_t GpioDevRead(struct GpioCntlr *cntlr, uint16_t local, uint16_t *val) +{ + uint32_t gpioPeriph; + uint32_t pin; + bit_status bitValue; + + if (cntlr == NULL) { + HDF_LOGE("%s, cntlr is NULL", __func__); + return HDF_ERR_INVALID_PARAM; + } + + if (local >= GPIO_PIN_TOTAL) { + HDF_LOGE("%s, local(%d) is out of range", __func__, local); + return HDF_ERR_INVALID_PARAM; + } + + gpioPeriph = ToGpioPeriph(cntlr, local); + pin = ToGpioPin(cntlr, local); + + bitValue = gpio_input_bit_get(gpioPeriph, pin); + if (bitValue == SET) { + *val = GPIO_VAL_HIGH; + } else { + *val = GPIO_VAL_LOW; + } + + return HDF_SUCCESS; +} + +static void GpioDevClearIrqUnsafe(struct GpioCntlr *cntlr, uint16_t local) +{ + exti_line_enum lineX; + lineX = ToGpioExtiLineNum(cntlr, local); + + exti_interrupt_flag_clear(lineX); +} + +static void GpioDevSetIrqEnableUnsafe(struct GpioCntlr *cntlr, uint16_t local, int flag) +{ + exti_line_enum lineX; + + lineX = ToGpioExtiLineNum(cntlr, local); + + if (flag == 0) { + exti_interrupt_disable(lineX); + } else { + exti_interrupt_enable(lineX); + } +} + +static int32_t GpioDevEnableIrq(struct GpioCntlr *cntlr, uint16_t local) +{ + struct GpioDevCntlr *p = NULL; + + static int isFirstEnterFlag = 1; + if (isFirstEnterFlag == 1) { + rcu_periph_clock_enable(RCU_SYSCFG); + isFirstEnterFlag = 0; + } + + if (cntlr == NULL) { + HDF_LOGE("%s, cntlr is NULL", __func__); + return HDF_ERR_INVALID_PARAM; + } + + if (local >= GPIO_PIN_TOTAL) { + HDF_LOGE("%s, local(%d) is out of range", __func__, local); + return HDF_ERR_INVALID_PARAM; + } + + p = ToGpioDevCntlr(cntlr); + if (OsalSpinLockIrqSave(&p->lock, &p->irqSave) != HDF_SUCCESS) { + HDF_LOGE("in %s:%s %d: get spinLock failed", __FILE__, __FUNCTION__, __LINE__); + return HDF_ERR_DEVICE_BUSY; + } + + GpioDevSetIrqEnableUnsafe(cntlr, local, 1); + + nvic_irq_enable(ToGpioIrqNum(cntlr, local), DEFAULT_PRE_PRIORITY, DEFAULT_SUB_PRIORITY); + syscfg_exti_line_config(ToGpioExtiSourcePort(cntlr, local), ToGpioExtiSourcePin(cntlr, local)); + + (void)OsalSpinUnlockIrqRestore(&p->lock, &p->irqSave); + return HDF_SUCCESS; +} + +static int32_t GpioDevDisableIrq(struct GpioCntlr *cntlr, uint16_t local) +{ + struct GpioDevCntlr *p = NULL; + + if (cntlr == NULL) { + HDF_LOGE("%s, cntlr is NULL", __func__); + return HDF_ERR_INVALID_PARAM; + } + + if (local >= GPIO_PIN_TOTAL) { + HDF_LOGE("%s, local(%d) is out of range", __func__, local); + return HDF_ERR_INVALID_PARAM; + } + + p = ToGpioDevCntlr(cntlr); + if (OsalSpinLockIrqSave(&p->lock, &p->irqSave) != HDF_SUCCESS) { + HDF_LOGE("in %s:%s %d: get spinLock failed", __FILE__, __FUNCTION__, __LINE__); + return HDF_ERR_DEVICE_BUSY; + } + + GpioDevSetIrqEnableUnsafe(cntlr, local, 0); + + (void)OsalSpinUnlockIrqRestore(&p->lock, &p->irqSave); + return HDF_SUCCESS; +} + +/* 中断处理方式仅支持沿触发 */ +static int32_t GpioDevSetIrqTypeUnsafe(struct GpioCntlr *cntlr, uint16_t local, uint16_t mode) +{ + exti_line_enum lineNum; + exti_trig_type_enum trigType; + + lineNum = ToGpioExtiLineNum(cntlr, local); + + switch (mode) { + case OSAL_IRQF_TRIGGER_RISING: + trigType = EXTI_TRIG_RISING; + break; + case OSAL_IRQF_TRIGGER_FALLING: + trigType = EXTI_TRIG_FALLING; + break; + case OSAL_IRQF_TRIGGER_HIGH: + case OSAL_IRQF_TRIGGER_LOW: + case OSAL_IRQF_TRIGGER_NONE: + default: + HDF_LOGE("%s:irq mode(%x) not support", __func__, mode); + return HDF_ERR_INVALID_PARAM; + } + + exti_init(lineNum, EXTI_INTERRUPT, trigType); + exti_interrupt_flag_clear(lineNum); + + return HDF_SUCCESS; +} + +static void DevExitIrqHandler(struct IrqFuncParam *para) +{ + HDF_LOGI("===================== INTERRUPT:%s %d id addr=%0x para add=%0x", __FUNCTION__, __LINE__, para); + struct DevIrqInfo *p_info; + for (uint8_t i = para->startExti; i <= para->endExti; i++) { + exti_line_enum linex = BIT(i); + if (RESET != exti_interrupt_flag_get(linex)) { + exti_interrupt_flag_clear(linex); + p_info = &g_DevIrqInfo[i]; + if (p_info->isRegistered == 1) { + GpioCntlrIrqCallback(p_info->cntlr, p_info->sourceLocal); + } + } + } +} + +static UINT32 DevHwiCreate(struct GpioCntlr *cntlr, uint16_t local) +{ + HwiIrqParam irqParam; + uint8_t index; + + index = ToGpioRcuIndex(local); + irqParam.pDevId = &g_Exti[index]; + return LOS_HwiCreate(ToGpioIrqNum(cntlr, local), 0, 0, (HWI_PROC_FUNC)DevExitIrqHandler, &irqParam); +} + +static UINT32 DevHwiDelete(struct GpioCntlr *cntlr, uint16_t local) +{ + uint8_t i; + uint8_t index; + + index = ToGpioRcuIndex(local); + for (i = g_Exti[index].startExti; i <= g_Exti[index].endExti; i++) { + if (g_DevIrqInfo[index].isRegistered == 1) { + break; + } + } + + if (i > g_Exti[index].endExti) { + return LOS_HwiDelete(ToGpioIrqNum(cntlr, local), NULL); + } + + return HDF_SUCCESS; +} + +static int32_t GpioDevSetIrq(struct GpioCntlr *cntlr, uint16_t local, uint16_t mode) +{ + struct GpioDevCntlr *p = NULL; + uint8_t index; + + if (cntlr == NULL) { + HDF_LOGE("%s, cntlr is NULL", __func__); + return HDF_ERR_INVALID_PARAM; + } + + if (local >= GPIO_PIN_TOTAL) { + HDF_LOGE("%s, local(%d) is out of range", __func__, local); + return HDF_ERR_INVALID_PARAM; + } + + p = ToGpioDevCntlr(cntlr); + if (OsalSpinLockIrqSave(&p->lock, &p->irqSave) != HDF_SUCCESS) { + HDF_LOGE("in %s:%s %d: get spinLock failed", __FILE__, __FUNCTION__, __LINE__); + return HDF_ERR_DEVICE_BUSY; + } + + InitExti(); + gpio_mode_set(ToGpioPeriph(cntlr, local), GPIO_MODE_INPUT, GPIO_PUPD_NONE, ToGpioPin(cntlr, local)); + GpioDevSetIrqTypeUnsafe(cntlr, local, mode); + GpioDevSetIrqEnableUnsafe(cntlr, local, 0); // disable irq when set + GpioDevClearIrqUnsafe(cntlr, local); + + index = ToGpioExitSourceIndex(cntlr, local); + if (g_DevIrqInfo[index].isRegistered == 1) { + HDF_LOGE("%s: exitSourceIndex [%d] has already been registered! You need to unset it", index); + (void)OsalSpinUnlockIrqRestore(&p->lock, &p->irqSave); + return HDF_FAILURE; + } + + g_DevIrqInfo[index].isRegistered = 1; + g_DevIrqInfo[index].cntlr = cntlr; + g_DevIrqInfo[index].sourceLocal = local; + + (void)DevHwiCreate(cntlr, local); + + (void)OsalSpinUnlockIrqRestore(&p->lock, &p->irqSave); + + return HDF_SUCCESS; +} + +static int32_t GpioDevUnsetIrq(struct GpioCntlr *cntlr, uint16_t local) +{ + struct GpioDevCntlr *p = NULL; + uint8_t index; + if (cntlr == NULL) { + HDF_LOGE("%s, cntlr is NULL", __func__); + return HDF_ERR_INVALID_PARAM; + } + + if (local >= GPIO_PIN_TOTAL) { + HDF_LOGE("%s, local(%d) is out of range", __func__, local); + return HDF_ERR_INVALID_PARAM; + } + + p = ToGpioDevCntlr(cntlr); + if (OsalSpinLockIrqSave(&p->lock, &p->irqSave) != HDF_SUCCESS) { + HDF_LOGE("in %s:%s %d: get spinLock failed", __FILE__, __FUNCTION__, __LINE__); + return HDF_ERR_DEVICE_BUSY; + } + + index = ToGpioExitSourceIndex(cntlr, local); + g_DevIrqInfo[index].isRegistered = 0; + + GpioDevSetIrqEnableUnsafe(cntlr, local, 0); + GpioDevClearIrqUnsafe(cntlr, local); + (void)DevHwiDelete(cntlr, local); + + (void)OsalSpinUnlockIrqRestore(&p->lock, &p->irqSave); + + return HDF_SUCCESS; +} + +static struct GpioMethod g_Method = { + .request = NULL, + .release = NULL, + .write = GpioDevWrite, + .read = GpioDevRead, + .setDir = GpioDevSetDir, + .getDir = GpioDevGetDir, + .toIrq = NULL, + .setIrq = GpioDevSetIrq, + .unsetIrq = GpioDevUnsetIrq, + .enableIrq = GpioDevEnableIrq, + .disableIrq = GpioDevDisableIrq, +}; + +#ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO +#define GPIO_FIND_CONFIG(node, name, resource) \ + do { \ + if (strcmp(HCS_PROP(node, match_attr), name) == 0) { \ + uint32_t start = HCS_PROP(node, start); \ + uint32_t count = HCS_PROP(node, count); \ + resource->start = start; \ + resource->count = count; \ + result = HDF_SUCCESS; \ + } \ + } while (0) +#define PLATFORM_CONFIG HCS_NODE(HCS_ROOT, platform) +#define PLATFORM_GPIO_CONFIG HCS_NODE(HCS_NODE(HCS_ROOT, platform), gpio_config) +static int32_t DevGetGpioDeviceResource(struct GpioDevCntlr *resource, const char *deviceMatchAttr) +{ + int32_t result = HDF_FAILURE; + if (resource == NULL || deviceMatchAttr == NULL) { + HDF_LOGE("%s: resource or deviceMatchAttr is NULL", __func__); + return HDF_ERR_INVALID_PARAM; + } + +#if HCS_NODE_HAS_PROP(PLATFORM_CONFIG, gpio_config) + HCS_FOREACH_CHILD_VARGS(PLATFORM_GPIO_CONFIG, GPIO_FIND_CONFIG, deviceMatchAttr, resource); +#endif + if (result != HDF_SUCCESS) { + HDF_LOGE("resourceNode %s is NULL\r\n", deviceMatchAttr); + } + + return result; +} +#else +static int32_t DevGetGpioDeviceResource(struct GpioDevCntlr *p, const struct DeviceResourceNode *node) +{ + int32_t ret = 0; + + if (node == NULL) { + HDF_LOGE("%s, device resource node is NULL", __func__); + return HDF_ERR_INVALID_PARAM; + } + + struct DeviceResourceIface *drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); + if (drsOps == NULL || drsOps->GetUint16 == NULL || drsOps->GetUint32 == NULL) { + HDF_LOGE("%s: invalid drs ops fail!", __func__); + return HDF_FAILURE; + } + + ret = drsOps->GetUint32(node, "start", &p->start, 0); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: read regBase fail!", __func__); + return ret; + } + + ret = drsOps->GetUint32(node, "count", &p->count, 0); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: read regStep fail!", __func__); + return ret; + } + + if ((p->start < 0) || (p->start >= GPIO_PIN_TOTAL)) { + HDF_LOGE("%s: start(%d) is out of range", __func__, p->start); + return HDF_ERR_INVALID_PARAM; + } + + if ((p->count <= 0) || ((p->start + p->count - 1) >= GPIO_PIN_TOTAL)) { + HDF_LOGE("%s start(%d): count(%d) is out of range", __func__, p->start, p->count); + return HDF_ERR_INVALID_PARAM; + } + + return HDF_SUCCESS; +} +#endif + +static int32_t GpioDevBind(struct HdfDeviceObject *device) +{ + HDF_LOGI("%s: Enter %d", __FILE__, __FUNCTION__, __LINE__); + (void)device; + return HDF_SUCCESS; +} +static void GpioRcuInit(struct GpioDevCntlr *p) +{ + rcu_periph_enum rcuPeriph = RCU_GPIOA; + if (p == NULL) { + HDF_LOGE("%s: GpioDevCntlr null!", __func__); + return; + } + rcu_periph_clock_enable(RCU_SYSCFG); + for (int32_t i = 0; i < p->count; i++) { + rcuPeriph = ToGpioRcuPeriphNum(&p->cntlr, (p->start + i)); + rcu_periph_clock_enable(rcuPeriph); + } +} +static int32_t GpioDevInit(struct HdfDeviceObject *device) +{ + int32_t ret; + struct GpioDevCntlr *p = NULL; + + HDF_LOGI("%s: Enter", __FUNCTION__); + +#ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO + if (device == NULL) +#else + if (device == NULL || device->property == NULL) +#endif + { + HDF_LOGE("%s: device or property null!", __func__); + return HDF_ERR_INVALID_OBJECT; + } + + p = (struct GpioDevCntlr *)OsalMemCalloc(sizeof(struct GpioDevCntlr)); + if (p == NULL) { + HDF_LOGE("%s: malloc memory failed", __func__); + return HDF_ERR_MALLOC_FAIL; + } + memset_s(p, sizeof(struct GpioDevCntlr), 0, sizeof(struct GpioDevCntlr)); + + if (OsalSpinInit(&p->lock) != HDF_SUCCESS) { + HDF_LOGE("%s: OsalSpinInit failed!", __func__); + OsalSpinDestroy(&p->lock); + return HDF_FAILURE; + } +#ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO + ret = DevGetGpioDeviceResource(p, device->deviceMatchAttr); +#else + ret = DevGetGpioDeviceResource(p, device->property); +#endif + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: read drs fail:%x", __func__, ret); + return ret; + } + + p->cntlr.start = p->start; + p->cntlr.count = p->count; +#ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO + p->cntlr.priv = NULL; +#else + p->cntlr.priv = (void *)device->property; +#endif + p->cntlr.ops = &g_Method; + + GpioRcuInit(p); + + ret = GpioCntlrAdd(&p->cntlr); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: err add controller: %x", __func__, ret); + return ret; + } + + device->priv = p; + HDF_LOGI("%s: gpio init success", __func__); + return HDF_SUCCESS; +} + +static void GpioDevRelease(struct HdfDeviceObject *device) +{ + struct GpioDevCntlr *p = NULL; + + if (device->priv != NULL) { + p = (struct GpioDevCntlr *)device->priv; + OsalMemFree(p); + + device->priv = NULL; + } + + return; +} + +struct HdfDriverEntry g_gpioDriverEntry = { + .moduleVersion = 1, + .Bind = GpioDevBind, + .Init = GpioDevInit, + .Release = GpioDevRelease, + .moduleName = "GD_GPIO_MODULE_HDF", +}; +HDF_INIT(g_gpioDriverEntry); diff --git a/khdvk_450a/liteos_m/drivers/i2c/BUILD.gn b/khdvk_450a/liteos_m/drivers/i2c/BUILD.gn new file mode 100755 index 0000000..3717012 --- /dev/null +++ b/khdvk_450a/liteos_m/drivers/i2c/BUILD.gn @@ -0,0 +1,32 @@ +# Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. +# Licensed 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. + +import("//drivers/hdf_core/adapter/khdf/liteos_m/hdf.gni") + +module_switch = defined(LOSCFG_DRIVERS_HDF_USER_I2C) +module_name = get_path_info(rebase_path("."), "name") +hdf_driver(module_name) { + sources = [ "i2c_gd32f4xx.c" ] + include_dirs = [ "../../sdk/drivers/gd32f4xx_driver/include" ] + + if (defined(LOSCFG_DRIVERS_HDF_CONFIG_MACRO)) { + HDF_HCS_BUILD_PATH = rebase_path( + "//device/board/$device_company/$device_name/liteos_m/hdf_config") + cmd = "if [ -f ${HDF_HCS_BUILD_PATH}/BUILD.gn ]; then echo true; else echo false; fi" + HAVE_HCS_BUILD_PATH = + exec_script("//build/lite/run_shell_cmd.py", [ cmd ], "value") + if (HAVE_HCS_BUILD_PATH) { + deps = [ "${HDF_HCS_BUILD_PATH}" ] + } + } +} diff --git a/khdvk_450a/liteos_m/drivers/i2c/i2c_gd32f4xx.c b/khdvk_450a/liteos_m/drivers/i2c/i2c_gd32f4xx.c new file mode 100644 index 0000000..4cfa6ce --- /dev/null +++ b/khdvk_450a/liteos_m/drivers/i2c/i2c_gd32f4xx.c @@ -0,0 +1,523 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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. + */ + +#ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO +#include "hcs_macro.h" +#include "hdf_config_macro.h" +#else +#include "device_resource_if.h" +#endif +#include "hdf_device_desc.h" +#include "hdf_log.h" +#include "i2c_core.h" +#include "i2c_if.h" +#include "osal_mem.h" +#include "osal_mutex.h" +#include "osal_time.h" + +#include "gd32f4xx.h" +#include "gd32f4xx_i2c.h" + +#define HDF_LOG_TAG i2c_gd32f4xx + +#define DELAY_MS 1 +#define TIMEOUT_MS 0xfff + +#define GPIO_PIN_TOTAL 140 +#define GPIO_REG_STEP 0x00000400 +#define GPIO_REG_BASE 0x40020000 +#define GPIO_REG_STEP 0x00000400 +#define GPIO_BIT_PER_GROUP 16 + +#define I2C_BUS_0 0 +#define I2C_BUS_1 1 +#define I2C_BUS_2 2 +#define I2C_FLAG_WRITE 0 +#define MESSAGE_LAST_SECOND 2 +#define MESSAGE_LAST_THIRD 3 +#define US_TO_MS_CONV (1000) + +static void I2cMDelay(uint32_t timeOut) +{ + OsalTimespec startTick = {0, 0}; + OsalTimespec endTick = {0, 0}; + OsalTimespec diffTick = {0, 0}; + + OsalGetTime(&startTick); + do { + OsalMSleep(1); + /* time out break */ + OsalGetTime(&endTick); + OsalDiffTime(&startTick, &endTick, &diffTick); + if ((uint32_t)(diffTick.sec * US_TO_MS_CONV + diffTick.usec / US_TO_MS_CONV) >= timeOut) { + break; + } + } while (true); +} + +static inline int32_t I2cTimeOutCheck(void) +{ + static int16_t iTmp = 0; + I2cMDelay(DELAY_MS); + iTmp++; + if (iTmp > TIMEOUT_MS) { + iTmp = 0; + return HDF_ERR_TIMEOUT; + } + return HDF_SUCCESS; +} + +struct I2cDevResource { + uint16_t bus; + uint16_t scl; + uint16_t sda; + uint32_t speed; + uint32_t regBasePhy; + uint32_t rcuGpio; + uint32_t rcuI2c; + struct OsalMutex mutex; +}; + +static inline uint32_t ToGpioPeriph(uint16_t local) +{ + uint32_t gpioPeriph = 0; + + gpioPeriph = GPIO_REG_BASE + (local / GPIO_BIT_PER_GROUP) * GPIO_REG_STEP; + + return gpioPeriph; +} + +static inline uint32_t ToGpioPin(uint16_t local) +{ + uint32_t pinNum = 0; + + pinNum = local % GPIO_BIT_PER_GROUP; + + return (BIT(pinNum)); +} + +static inline uint32_t ToGpioRcu(uint16_t local) +{ + uint32_t Periph = 0; + + Periph = local / GPIO_BIT_PER_GROUP; + + return (RCU_GPIOA + Periph); +} + +#ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO +#define I2C_FIND_CONFIG(node, name, resource) \ + do { \ + if (strcmp(HCS_PROP(node, match_attr), name) == 0) { \ + resource->bus = HCS_PROP(node, bus); \ + resource->speed = HCS_PROP(node, speed); \ + resource->scl = HCS_PROP(node, scl); \ + resource->sda = HCS_PROP(node, sda); \ + result = HDF_SUCCESS; \ + } \ + } while (0) +#define PLATFORM_CONFIG HCS_NODE(HCS_ROOT, platform) +#define PLATFORM_I2C_CONFIG HCS_NODE(HCS_NODE(HCS_ROOT, platform), i2c_config) +static int32_t GetI2cDeviceResource(struct I2cDevResource *i2cResource, const char *deviceMatchAttr) +{ + int32_t result = HDF_FAILURE; + struct I2cDevResource *resource = NULL; + if (i2cResource == NULL || deviceMatchAttr == NULL) { + HDF_LOGE("device or deviceMatchAttr is NULL\r\n"); + return HDF_ERR_INVALID_PARAM; + } + resource = i2cResource; +#if HCS_NODE_HAS_PROP(PLATFORM_CONFIG, i2c_config) + HCS_FOREACH_CHILD_VARGS(PLATFORM_I2C_CONFIG, I2C_FIND_CONFIG, deviceMatchAttr, resource); +#endif + if (result != HDF_SUCCESS) { + HDF_LOGE("resourceNode %s is NULL\r\n", deviceMatchAttr); + } + + return result; +} +#else +static int32_t GetI2cDeviceResource(struct I2cDevResource *i2cResource, const struct DeviceResourceNode *resourceNode) +{ + if (i2cResource == NULL || resourceNode == NULL) { + HDF_LOGE("[%s]: param is NULL\r\n", __func__); + return HDF_ERR_INVALID_PARAM; + } + + struct DeviceResourceIface *ops = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); + if (ops == NULL || ops->GetUint32 == NULL || ops->GetUint16 == NULL || ops->GetUint16Array == NULL) { + HDF_LOGE("DeviceResourceIface is invalid\r\n"); + return HDF_ERR_INVALID_OBJECT; + } + + if (ops->GetUint32(resourceNode, "speed", &i2cResource->speed, 0) != HDF_SUCCESS) { + HDF_LOGE("%s: read i2c speed fail!", __func__); + return HDF_FAILURE; + } + + if (ops->GetUint16(resourceNode, "bus", &i2cResource->bus, 0) != HDF_SUCCESS) { + HDF_LOGE("%s: read i2c bus fail!", __func__); + return HDF_FAILURE; + } + + if (ops->GetUint16(resourceNode, "scl", &i2cResource->scl, 0) != HDF_SUCCESS) { + HDF_LOGE("%s: read i2c scl fail!", __func__); + return HDF_FAILURE; + } + + if (ops->GetUint16(resourceNode, "sda", &i2cResource->sda, 0) != HDF_SUCCESS) { + HDF_LOGE("%s: read i2c sda fail!", __func__); + return HDF_FAILURE; + } + + return HDF_SUCCESS; +} +#endif + +static uint32_t I2cParaCheck(struct I2cDevResource *i2cResource) +{ + if (i2cResource->bus != I2C_BUS_0 && i2cResource->bus != I2C_BUS_1 && i2cResource->bus != I2C_BUS_2) { + HDF_LOGE("%s: I2c(%d) bus is invalid!", __func__, i2cResource->bus); + return HDF_ERR_INVALID_PARAM; + } + + if (i2cResource->scl > GPIO_PIN_TOTAL || i2cResource->sda > GPIO_PIN_TOTAL) { + HDF_LOGE("%s: I2c(%d) gpio port is invalid!", __func__, i2cResource->bus); + return HDF_ERR_INVALID_PARAM; + } + + return HDF_SUCCESS; +} + +static void I2cConfigCompletion(struct I2cDevResource *i2cResource) +{ + switch (i2cResource->bus) { + case I2C_BUS_0: + i2cResource->regBasePhy = I2C0; + i2cResource->rcuGpio = ToGpioRcu(i2cResource->scl); + i2cResource->rcuI2c = RCU_I2C0; + break; + case I2C_BUS_1: + i2cResource->regBasePhy = I2C1; + i2cResource->rcuGpio = ToGpioRcu(i2cResource->scl); + i2cResource->rcuI2c = RCU_I2C1; + break; + case I2C_BUS_2: + i2cResource->regBasePhy = I2C2; + i2cResource->rcuGpio = ToGpioRcu(i2cResource->scl); + i2cResource->rcuI2c = RCU_I2C2; + break; + default: + break; + } + + return; +} + +static int32_t AttachI2cDevice(struct I2cCntlr *host, const struct HdfDeviceObject *device) +{ + int32_t ret = HDF_FAILURE; + +#ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO + if (device == NULL || host == NULL) { +#else + if (device == NULL || device->property == NULL || host == NULL) { +#endif + HDF_LOGE("[%s]: param is NULL\r\n", __func__); + return HDF_ERR_INVALID_PARAM; + } + + struct I2cDevResource *i2cResource = (struct I2cDevResource *)OsalMemCalloc(sizeof(struct I2cDevResource)); + if (i2cResource == NULL) { + HDF_LOGE("[%s]: OsalMemCalloc I2cDevResource fail\r\n", __func__); + return HDF_ERR_MALLOC_FAIL; + } + +#ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO + ret = GetI2cDeviceResource(i2cResource, device->deviceMatchAttr); +#else + ret = GetI2cDeviceResource(i2cResource, device->property); +#endif + if (ret != HDF_SUCCESS || I2cParaCheck(i2cResource) != HDF_SUCCESS) { + OsalMemFree(i2cResource); + return HDF_FAILURE; + } + I2cConfigCompletion(i2cResource); + + host->busId = i2cResource->bus; + host->priv = i2cResource; + + return HDF_SUCCESS; +} + +static void I2cGpioConfig(struct I2cDevResource *i2cResource) +{ + /* enable GPIOB clock */ + rcu_periph_clock_enable(i2cResource->rcuGpio); + /* enable I2C0 clock */ + rcu_periph_clock_enable(i2cResource->rcuI2c); + + /* connect PB6 to I2C0_SCL */ + gpio_af_set(ToGpioPeriph(i2cResource->scl), GPIO_AF_4, ToGpioPin(i2cResource->scl)); + /* connect PB7 to I2C0_SDA */ + gpio_af_set(ToGpioPeriph(i2cResource->sda), GPIO_AF_4, ToGpioPin(i2cResource->sda)); + + gpio_mode_set(ToGpioPeriph(i2cResource->scl), GPIO_MODE_AF, GPIO_PUPD_PULLUP, ToGpioPin(i2cResource->scl)); + gpio_output_options_set(ToGpioPeriph(i2cResource->scl), GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, + ToGpioPin(i2cResource->scl)); + gpio_mode_set(ToGpioPeriph(i2cResource->sda), GPIO_MODE_AF, GPIO_PUPD_PULLUP, ToGpioPin(i2cResource->sda)); + gpio_output_options_set(ToGpioPeriph(i2cResource->sda), GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, + ToGpioPin(i2cResource->sda)); +} + +static void I2cConfig(struct I2cDevResource *i2cResource) +{ + /* configure I2C clock */ + i2c_clock_config(i2cResource->regBasePhy, i2cResource->speed, I2C_DTCY_2); + /* enable I2C0 */ + i2c_enable(i2cResource->regBasePhy); + /* enable acknowledge */ + i2c_ack_config(i2cResource->regBasePhy, I2C_ACK_ENABLE); +} + +static uint32_t Gd32f4xxI2cWrite(struct I2cDevResource *device, struct I2cMsg *msg) +{ + uint16_t bufIdx = 0; + uint8_t val; + /* 等待总线空闲 */ + while (i2c_flag_get(device->regBasePhy, I2C_FLAG_I2CBSY) && !I2cTimeOutCheck()) { } + if (!(msg->flags & I2C_FLAG_NO_START)) { + /* 发送start信号 */ + i2c_start_on_bus(device->regBasePhy); + while (!i2c_flag_get(device->regBasePhy, I2C_FLAG_SBSEND) && !I2cTimeOutCheck()) { } + } + /* 设置从机地址操作 */ + i2c_master_addressing(device->regBasePhy, msg->addr, I2C_TRANSMITTER); + /* 等待从机地址发送标志 */ + while (!i2c_flag_get(device->regBasePhy, I2C_FLAG_ADDSEND) && !I2cTimeOutCheck()) { } + /* 清除从机地址发送标志 */ + i2c_flag_clear(device->regBasePhy, I2C_FLAG_ADDSEND); + while (!i2c_flag_get(device->regBasePhy, I2C_FLAG_TBE) && !I2cTimeOutCheck()) { } + while (bufIdx < msg->len) { + val = msg->buf[bufIdx]; + i2c_data_transmit(device->regBasePhy, val); + bufIdx++; + /* 等待数据寄存器空 */ + while (!i2c_flag_get(device->regBasePhy, I2C_FLAG_BTC) && !I2cTimeOutCheck()) { } + } + + if (msg->flags & I2C_FLAG_STOP) { + /* 发送stop信号 */ + i2c_stop_on_bus(device->regBasePhy); + while ((I2C_CTL0(device->regBasePhy) & I2C_CTL0_STOP) && !I2cTimeOutCheck()) { } + } + + return HDF_SUCCESS; +} + +static int Gd32f4xxI2cRead(struct I2cDevResource *device, struct I2cMsg *msg) +{ + uint16_t bufIdx = 0; + uint8_t val; + /* 等待总线空闲 */ + while (i2c_flag_get(device->regBasePhy, I2C_FLAG_I2CBSY) && !I2cTimeOutCheck()) { } + if (msg->len == MESSAGE_LAST_SECOND) { + /* 接收数据长度等于2时,首先将POAP置1 */ + i2c_ackpos_config(device->regBasePhy, I2C_ACKPOS_NEXT); + } + + if (!(msg->flags & I2C_FLAG_NO_START)) { + i2c_start_on_bus(device->regBasePhy); + /* 等待SBSEND标志 */ + while (!i2c_flag_get(device->regBasePhy, I2C_FLAG_SBSEND) && !I2cTimeOutCheck()) { } + } + + i2c_master_addressing(device->regBasePhy, msg->addr, I2C_RECEIVER); + if (msg->len < MESSAGE_LAST_THIRD) { + /* 接收数据长度小于3时,需先清除ACK */ + i2c_ack_config(device->regBasePhy, I2C_ACK_DISABLE); + } + /* 等待从机地址发送标志 */ + while (!i2c_flag_get(device->regBasePhy, I2C_FLAG_ADDSEND) && !I2cTimeOutCheck()) { } + /* 清除从机地址发送标志 */ + i2c_flag_clear(device->regBasePhy, I2C_FLAG_ADDSEND); + while (bufIdx < msg->len) { + /* 等待倒数第二个数据被接收到寄存器 */ + if (msg->len - bufIdx == MESSAGE_LAST_THIRD) { + while (!i2c_flag_get(device->regBasePhy, I2C_FLAG_BTC) && !I2cTimeOutCheck()) { } + /* 清除ACK */ + i2c_ack_config(device->regBasePhy, I2C_ACK_DISABLE); + } + if (msg->len - bufIdx == MESSAGE_LAST_SECOND) { + while (!i2c_flag_get(device->regBasePhy, I2C_FLAG_BTC) && !I2cTimeOutCheck()) { } + if (msg->flags & I2C_FLAG_STOP) { + i2c_stop_on_bus(device->regBasePhy); + } + } + /* 等待RBNE位被设置 */ + if (i2c_flag_get(device->regBasePhy, I2C_FLAG_RBNE)) { + /* 从I2C总线读取数据 */ + val = i2c_data_receive(device->regBasePhy); + msg->buf[bufIdx] = val; + bufIdx++; + } + } + + if (msg->flags & I2C_FLAG_STOP) { + while ((I2C_CTL0(device->regBasePhy) & I2C_CTL0_STOP) && !I2cTimeOutCheck()) { } + } + + i2c_ack_config(device->regBasePhy, I2C_ACK_ENABLE); + return HDF_SUCCESS; +} + +static int32_t I2cDataTransfer(struct I2cCntlr *cntlr, struct I2cMsg *msgs, int16_t count) +{ + int32_t i = 0; + int32_t ret; + + if (cntlr == NULL || msgs == NULL || cntlr->priv == NULL) { + HDF_LOGE("[%s]: I2cDataTransfer param is NULL!\r\n", __func__); + return HDF_ERR_INVALID_PARAM; + } + if (count <= 0) { + HDF_LOGE("[%s]: I2c msg count err\r\n", __func__); + return HDF_ERR_INVALID_PARAM; + } + + struct I2cDevResource *device = (struct I2cDevResource *)cntlr->priv; + if (device == NULL) { + HDF_LOGE("%s: I2c device is NULL\r\n", __func__); + return HDF_DEV_ERR_NO_DEVICE; + } + + struct I2cMsg *msg = NULL; + if (HDF_SUCCESS != OsalMutexLock(&device->mutex)) { + HDF_LOGE("[%s]: OsalMutexLock fail\r\n", __func__); + return HDF_ERR_TIMEOUT; + } + + for (i = 0; i < count; i++) { + msg = &msgs[i]; + if (msg->flags & (I2C_FLAG_ADDR_10BIT | I2C_FLAG_READ_NO_ACK | I2C_FLAG_IGNORE_NO_ACK | I2C_FLAG_NO_START)) { + HDF_LOGE("%s: flag %d is not support", __func__, msg->flags); + } else if (msg->flags == (I2C_FLAG_READ | I2C_FLAG_STOP)) { + ret = Gd32f4xxI2cRead(device, msg); + } else if (msg->flags == I2C_FLAG_STOP) { + ret = Gd32f4xxI2cWrite(device, msg); + } + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: I2c transfer fail!,flag :%d", __func__, msg->flags); + break; + } + } + OsalMutexUnlock(&device->mutex); + + return i; +} + +static const struct I2cMethod g_I2cMethod = { + .transfer = I2cDataTransfer, +}; + +static int32_t I2cDriverBind(struct HdfDeviceObject *device) +{ + if (device == NULL) { + HDF_LOGE("[%s]: I2c device is NULL\r\n", __func__); + return HDF_FAILURE; + } + return HDF_SUCCESS; +} + +static void I2cDriverRelease(struct HdfDeviceObject *device) +{ + struct I2cCntlr *i2cCntrl = NULL; + struct I2cDevResource *i2cDevice = NULL; + + HDF_LOGI("%s: enter", __func__); + + if (device == NULL) { + HDF_LOGE("%s: device is NULL", __func__); + return; + } + + i2cCntrl = device->priv; + if (i2cCntrl == NULL || i2cCntrl->priv == NULL) { + HDF_LOGE("%s: i2cCntrl is NULL\r\n", __func__); + return; + } + i2cCntrl->ops = NULL; + + i2cDevice = (struct I2cDevResource *)i2cCntrl->priv; + + if (i2cDevice != NULL) { + OsalMutexDestroy(&i2cDevice->mutex); + OsalMemFree(i2cDevice); + } + OsalMemFree(i2cCntrl); + + return; +} + +static int32_t I2cDriverInit(struct HdfDeviceObject *device) +{ + int32_t ret = HDF_FAILURE; + struct I2cCntlr *host = NULL; + + if (device == NULL) { + HDF_LOGE("%s: device or property is NULL", __func__); + return HDF_ERR_INVALID_OBJECT; + } + HDF_LOGI("%s: Enter", __func__); + + host = (struct I2cCntlr *)OsalMemCalloc(sizeof(struct I2cCntlr)); + if (host == NULL) { + HDF_LOGE("[%s]: malloc host is NULL\r\n", __func__); + return HDF_ERR_MALLOC_FAIL; + } + + host->ops = &g_I2cMethod; + device->priv = (void *)host; + + ret = AttachI2cDevice(host, device); + if (ret != HDF_SUCCESS) { + HDF_LOGE("[%s]: AttachI2cDevice error, ret = %d\r\n", __func__, ret); + I2cDriverRelease(device); + return HDF_DEV_ERR_ATTACHDEV_FAIL; + } + + /* configure GPIO */ + I2cGpioConfig((struct I2cDevResource *)host->priv); + + /* configure I2C */ + I2cConfig((struct I2cDevResource *)host->priv); + + ret = I2cCntlrAdd(host); + if (ret != HDF_SUCCESS) { + I2cDriverRelease(device); + return HDF_FAILURE; + } + HDF_LOGI("%s: i2c%d init success", __func__, host->busId); + return HDF_SUCCESS; +} + +struct HdfDriverEntry g_i2cDriverEntry = { + .moduleVersion = 1, + .Bind = I2cDriverBind, + .Init = I2cDriverInit, + .Release = I2cDriverRelease, + .moduleName = "GD_I2C_MODULE_HDF", +}; +HDF_INIT(g_i2cDriverEntry); diff --git a/khdvk_450a/liteos_m/drivers/pwm/BUILD.gn b/khdvk_450a/liteos_m/drivers/pwm/BUILD.gn new file mode 100755 index 0000000..1468c38 --- /dev/null +++ b/khdvk_450a/liteos_m/drivers/pwm/BUILD.gn @@ -0,0 +1,32 @@ +# Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. +# Licensed 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. + +import("//drivers/hdf_core/adapter/khdf/liteos_m/hdf.gni") + +module_switch = defined(LOSCFG_DRIVERS_HDF_USER_PWM) +module_name = get_path_info(rebase_path("."), "name") +hdf_driver(module_name) { + sources = [ "pwm_gd32f4xx.c" ] + include_dirs = [ "../../sdk/drivers/gd32f4xx_driver/include" ] + + if (defined(LOSCFG_DRIVERS_HDF_CONFIG_MACRO)) { + HDF_HCS_BUILD_PATH = rebase_path( + "//device/board/$device_company/$device_name/liteos_m/hdf_config") + cmd = "if [ -f ${HDF_HCS_BUILD_PATH}/BUILD.gn ]; then echo true; else echo false; fi" + HAVE_HCS_BUILD_PATH = + exec_script("//build/lite/run_shell_cmd.py", [ cmd ], "value") + if (HAVE_HCS_BUILD_PATH) { + deps = [ "${HDF_HCS_BUILD_PATH}" ] + } + } +} diff --git a/khdvk_450a/liteos_m/drivers/pwm/pwm_gd32f4xx.c b/khdvk_450a/liteos_m/drivers/pwm/pwm_gd32f4xx.c new file mode 100644 index 0000000..1fa08cd --- /dev/null +++ b/khdvk_450a/liteos_m/drivers/pwm/pwm_gd32f4xx.c @@ -0,0 +1,438 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 +#ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO +#include "hcs_macro.h" +#include "hdf_config_macro.h" +#else +#include "device_resource_if.h" +#endif +#include "hdf_device_desc.h" +#include "pwm_core.h" +#include "hdf_log.h" +#include "osal_mem.h" + +#include "gd32f4xx_timer.h" +#include "gd32f4xx_gpio.h" + +#define HDF_LOG_TAG pwm_gd32f4xx + +#define SYS_CORE_CLK 120000000 // 120MHz +#define PER_SEC_NSEC 1000000000 + +#define GPIO_PORT_MAX 8 +#define GPIO_PIN_MAX 15 +#define GPIO_PORT_IDX 0 +#define GPIO_PIN_IDX 1 +#define GPIO_ARRY_SIZE 2 +#define GPIO_REG_STEP 0x00000400 +#define PRESCALER_MAX 65535 +#define PWM_TIMER_0 0 +#define PWM_TIMER_1 1 +#define PWM_TIMER_2 2 +#define PWM_TIMER_3 3 +#define PWM_TIMER_4 4 +#define PWM_TIMER_7 7 +#define PWM_TIMER_8 8 +#define PWM_TIMER_11 11 + +#define PWM_TIMER_ROW_SIZE 8 +#define PWM_TIMER_COL_SIZE 3 +#define PWM_TIMER_KEY 0 +#define PWM_TIMER_VALUE_TIMER 1 +#define PWM_TIMER_VALUE_RCU 2 + +static uint32_t g_gdTimerMap[PWM_TIMER_ROW_SIZE][PWM_TIMER_COL_SIZE] = { + PWM_TIMER_0, TIMER0, RCU_TIMER0, PWM_TIMER_1, TIMER1, RCU_TIMER1, PWM_TIMER_2, TIMER2, + RCU_TIMER2, PWM_TIMER_3, TIMER3, RCU_TIMER3, PWM_TIMER_4, TIMER4, RCU_TIMER4, PWM_TIMER_7, + TIMER7, RCU_TIMER7, PWM_TIMER_8, TIMER8, RCU_TIMER8, PWM_TIMER_11, TIMER11, RCU_TIMER11, +}; + +typedef struct { + uint16_t timerId; + uint16_t pwmCh; + uint32_t pwmTm; + uint16_t pwmId; + uint32_t rcuTimer; + uint16_t chGpio[GPIO_ARRY_SIZE]; +} PwmResource; + +#ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO +#define PWM_FIND_CONFIG(node, name, resource) \ + do { \ + if (strcmp(HCS_PROP(node, match_attr), name) == 0) { \ + uint16_t channel = HCS_PROP(node, pwm_ch); \ + uint16_t id = HCS_PROP(node, pwm_id); \ + uint16_t timerId = HCS_PROP(node, timer_id); \ + uint16_t chGpio[] = HCS_ARRAYS(HCS_NODE(node, ch_gpio)); \ + resource->pwmCh = channel; \ + resource->pwmId = id; \ + resource->timerId = timerId; \ + for (uint16_t i = 0; i < GPIO_ARRY_SIZE; i++) { \ + resource->chGpio[i] = chGpio[i]; \ + } \ + result = HDF_SUCCESS; \ + } \ + } while (0) +#define PLATFORM_CONFIG HCS_NODE(HCS_ROOT, platform) +#define PLATFORM_PWM_CONFIG HCS_NODE(HCS_NODE(HCS_ROOT, platform), pwm_config) +static int32_t GetPwmDeviceResource(PwmResource *resource, const char *deviceMatchAttr) +{ + int32_t result = HDF_FAILURE; + if (resource == NULL || deviceMatchAttr == NULL) { + HDF_LOGE("%s: resource or deviceMatchAttr is NULL", __func__); + return HDF_ERR_INVALID_PARAM; + } + +#if HCS_NODE_HAS_PROP(PLATFORM_CONFIG, pwm_config) + HCS_FOREACH_CHILD_VARGS(PLATFORM_PWM_CONFIG, PWM_FIND_CONFIG, deviceMatchAttr, resource); +#endif + if (result != HDF_SUCCESS) { + HDF_LOGE("resourceNode %s is NULL\r\n", deviceMatchAttr); + } + + return result; +} +#else +static int32_t GetPwmDeviceResource(PwmResource *resource, const struct DeviceResourceNode *resourceNode) +{ + struct DeviceResourceIface *dri = NULL; + + if (resource == NULL || resourceNode == NULL) { + HDF_LOGE("resource or device is NULL\r\n"); + return HDF_ERR_INVALID_PARAM; + } + + dri = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); + if (dri == NULL || dri->GetUint16 == NULL || dri->GetUint32 == NULL || dri->GetUint16Array == NULL) { + HDF_LOGE("DeviceResourceIface is invalid\r\n"); + return HDF_ERR_INVALID_PARAM; + } + + if (dri->GetUint16(resourceNode, "pwm_ch", &resource->pwmCh, 0) != HDF_SUCCESS) { + HDF_LOGE("read pwm_ch fail\r\n"); + return HDF_FAILURE; + } + + if (dri->GetUint16(resourceNode, "pwm_id", &resource->pwmId, 0) != HDF_SUCCESS) { + HDF_LOGE("read pwm_id fail\r\n"); + return HDF_FAILURE; + } + + if (dri->GetUint16(resourceNode, "timer_id", &resource->timerId, 0) != HDF_SUCCESS) { + HDF_LOGE("read timer_id fail\r\n"); + return HDF_FAILURE; + } + + if (dri->GetUint16Array(resourceNode, "ch_gpio", &resource->chGpio, GPIO_ARRY_SIZE, 0) != HDF_SUCCESS) { + HDF_LOGE("read ch_gpio fail!"); + return HDF_FAILURE; + } + + return HDF_SUCCESS; +} +#endif + +static int32_t PwmTimerCheck(PwmResource *dev) +{ + int16_t i = 0; + + if (dev->chGpio[GPIO_PORT_IDX] > GPIO_PORT_MAX || dev->chGpio[GPIO_PIN_IDX] > GPIO_PIN_MAX) { + HDF_LOGE("%s: pwm(%d) gpio ch is invalid!", __func__, dev->pwmId); + return HDF_ERR_INVALID_PARAM; + } + + for (; i < PWM_TIMER_ROW_SIZE; i++) { + if (dev->timerId == g_gdTimerMap[i][PWM_TIMER_KEY]) { + return HDF_SUCCESS; + } + } + HDF_LOGE("%s: pwm(%d) timer is invalid!", __func__, dev->pwmId); + + return HDF_FAILURE; +} + +static void PwmConfigCompletion(PwmResource *dev) +{ + int16_t i = 0; + + for (; i < PWM_TIMER_ROW_SIZE; i++) { + if (dev->timerId == g_gdTimerMap[i][PWM_TIMER_KEY]) { + dev->pwmTm = g_gdTimerMap[i][PWM_TIMER_VALUE_TIMER]; + dev->rcuTimer = g_gdTimerMap[i][PWM_TIMER_VALUE_RCU]; + } + } + + return; +} + +static int32_t AttachPwmDevice(struct PwmDev *host, const struct HdfDeviceObject *device) +{ + int32_t ret; + PwmResource *pwmDevice = NULL; +#ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO + if (device == NULL || host == NULL) { +#else + if (device == NULL || device->property == NULL || host == NULL) { +#endif + HDF_LOGE("%s: param is NULL\r\n", __func__); + return HDF_ERR_INVALID_PARAM; + } + pwmDevice = (PwmResource *)OsalMemCalloc(sizeof(PwmResource)); + if (pwmDevice == NULL) { + HDF_LOGE("%s: OsalMemAlloc pwmDevice error\r\n", __func__); + return HDF_ERR_MALLOC_FAIL; + } +#ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO + ret = GetPwmDeviceResource(pwmDevice, device->deviceMatchAttr); +#else + ret = GetPwmDeviceResource(pwmDevice, device->property); +#endif + if (ret != HDF_SUCCESS || PwmTimerCheck(pwmDevice) != HDF_SUCCESS) { + (void)OsalMemFree(pwmDevice); + return HDF_FAILURE; + } + + PwmConfigCompletion(pwmDevice); + host->priv = pwmDevice; + host->num = pwmDevice->pwmId; + + return HDF_SUCCESS; +} + +static void ChannelGpioConfig(PwmResource *dev) +{ + rcu_periph_clock_enable(RCU_GPIOB); + + /* Configure PB10(TIMER1_CH2) as alternate function */ + gpio_mode_set(dev->chGpio[GPIO_PORT_IDX] * GPIO_REG_STEP + GPIO_BASE, GPIO_MODE_AF, GPIO_PUPD_NONE, + BIT(dev->chGpio[GPIO_PIN_IDX])); + gpio_output_options_set(dev->chGpio[GPIO_PORT_IDX] * GPIO_REG_STEP + GPIO_BASE, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, + BIT(dev->chGpio[GPIO_PIN_IDX])); + + gpio_af_set(dev->chGpio[GPIO_PORT_IDX] * GPIO_REG_STEP + GPIO_BASE, GPIO_AF_1, BIT(dev->chGpio[GPIO_PIN_IDX])); +} + +static int32_t PwmTimerConfig(PwmResource *resource, struct PwmConfig *config) +{ + /* TIMER1 configuration: generate PWM signals with different duty cycles: + TIMER1CLK = SystemCoreClock / 120 = 1MHz */ + timer_oc_parameter_struct timer_ocintpara; + timer_parameter_struct timer_initpara; + + rcu_periph_clock_enable(resource->rcuTimer); + rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4); + timer_struct_para_init(&timer_initpara); + timer_deinit(resource->pwmTm); + + /* TIMER1 configuration */ + timer_initpara.prescaler = config->period / PER_SEC_NSEC * SYS_CORE_CLK - 1; + if (timer_initpara.prescaler < 0 || timer_initpara.prescaler > PRESCALER_MAX) { + HDF_LOGE("%s: prescaler must be 0~65535! ", __func__); + return HDF_ERR_INVALID_PARAM; + } + timer_initpara.alignedmode = TIMER_COUNTER_EDGE; + timer_initpara.counterdirection = TIMER_COUNTER_UP; + timer_initpara.period = config->period; + timer_initpara.clockdivision = TIMER_CKDIV_DIV1; + timer_initpara.repetitioncounter = 0; + timer_init(resource->pwmTm, &timer_initpara); + + /* CH2 configuration in PWM mode 0 */ + timer_channel_output_struct_para_init(&timer_ocintpara); + if (config->polarity == PWM_NORMAL_POLARITY) { + timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_HIGH; + timer_ocintpara.ocnpolarity = TIMER_OCN_POLARITY_HIGH; + } else { + timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_LOW; + timer_ocintpara.ocnpolarity = TIMER_OCN_POLARITY_LOW; + } + timer_ocintpara.outputstate = TIMER_CCX_ENABLE; + timer_ocintpara.outputnstate = TIMER_CCXN_DISABLE; + timer_ocintpara.ocidlestate = TIMER_OC_IDLE_STATE_LOW; + timer_ocintpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW; + + timer_channel_output_config(resource->pwmTm, resource->pwmCh, &timer_ocintpara); + + /* CH2 configuration duty cycle */ + timer_channel_output_pulse_value_config(resource->pwmTm, resource->pwmCh, config->duty); + timer_channel_output_mode_config(resource->pwmTm, resource->pwmCh, TIMER_OC_MODE_PWM0); + timer_channel_output_shadow_config(resource->pwmTm, resource->pwmCh, TIMER_OC_SHADOW_DISABLE); + + /* auto-reload preload enable */ + timer_auto_reload_shadow_enable(resource->pwmTm); + /* TIMER1 enable */ + timer_enable(resource->pwmTm); + + return HDF_SUCCESS; +} + +void PwmTimerStop(PwmResource *dev) +{ + timer_channel_output_pulse_value_config(dev->pwmTm, dev->pwmCh, 0); + timer_disable(dev->pwmTm); +} + +static int32_t PwmDevSetConfig(struct PwmDev *pwm, struct PwmConfig *config) +{ + PwmResource *prvPwm = NULL; + + if (pwm == NULL || config == NULL || (config->period > PER_SEC_NSEC)) { + HDF_LOGE("%s\r\n", __FUNCTION__); + return HDF_ERR_INVALID_PARAM; + } + + prvPwm = (PwmResource *)PwmGetPriv(pwm); + if (prvPwm == NULL) { + return HDF_DEV_ERR_NO_DEVICE; + } + + if (config->status == PWM_ENABLE_STATUS) { + if (PwmTimerConfig(prvPwm, config) != HDF_SUCCESS) { + HDF_LOGE("set timer config failed!\r\n"); + return HDF_FAILURE; + } + } else { + PwmTimerStop(prvPwm); + } + + return HDF_SUCCESS; +} + +static int32_t PwmDevOpen(struct PwmDev *pwm) +{ + if (pwm == NULL) { + HDF_LOGE("%s\r\n", __FUNCTION__); + return HDF_ERR_INVALID_PARAM; + } + + return HDF_SUCCESS; +} + +static int32_t PwmDevClose(struct PwmDev *pwm) +{ + PwmResource *prvPwm = NULL; + + if (pwm == NULL) { + HDF_LOGE("%s\r\n", __FUNCTION__); + return HDF_ERR_INVALID_PARAM; + } + prvPwm = (PwmResource *)PwmGetPriv(pwm); + if (prvPwm == NULL) { + HDF_LOGE("%s\r\n", __FUNCTION__); + return HDF_DEV_ERR_NO_DEVICE; + } + + PwmTimerStop(prvPwm); + + return HDF_SUCCESS; +} + +struct PwmMethod g_pwmmethod = { + .setConfig = PwmDevSetConfig, + .open = PwmDevOpen, + .close = PwmDevClose, +}; + +static int32_t PwmDriverBind(struct HdfDeviceObject *device) +{ + struct PwmDev *devService = NULL; + if (device == NULL) { + HDF_LOGE("hdfDevice object is null!\r\n"); + return HDF_ERR_INVALID_OBJECT; + } + + devService = (struct PwmDev *)OsalMemCalloc(sizeof(struct PwmDev)); + if (devService == NULL) { + HDF_LOGE("malloc pwmDev failed\n"); + return HDF_ERR_MALLOC_FAIL; + } + device->service = &devService->service; + devService->device = device; + + return HDF_SUCCESS; +} + +static int32_t PwmDriverInit(struct HdfDeviceObject *device) +{ + int32_t ret; + struct PwmDev *host = NULL; + + if (device == NULL) { + HDF_LOGE("%s: device is NULL\r\n", __func__); + return HDF_ERR_INVALID_OBJECT; + } + HDF_LOGI("%s: Enter", __func__); + + host = (struct PwmDev *)device->service; + if (host == NULL) { + HDF_LOGE("%s: host is NULL\r\n", __func__); + return HDF_ERR_MALLOC_FAIL; + } + + ret = AttachPwmDevice(host, device); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s:attach error\r\n", __func__); + return HDF_DEV_ERR_ATTACHDEV_FAIL; + } + + ChannelGpioConfig((PwmResource *)host->priv); + + host->method = &g_pwmmethod; + ret = PwmDeviceAdd(device, host); + if (ret != HDF_SUCCESS) { + PwmDeviceRemove(device, host); + OsalMemFree(host->device); + OsalMemFree(host); + return HDF_DEV_ERR_NO_DEVICE; + } + HDF_LOGI("%s: PWM%d init success", __func__, host->num); + return HDF_SUCCESS; +} + +static void PwmDriverRelease(struct HdfDeviceObject *device) +{ + struct PwmDev *host = NULL; + + if (device == NULL || device->service == NULL) { + HDF_LOGE("device is null\r\n"); + return; + } + + host = (struct PwmDev *)device->service; + if (host != NULL && host->device != NULL) { + host->method = NULL; + OsalMemFree(host->device); + OsalMemFree(host); + host->device = NULL; + host = NULL; + } + + device->service = NULL; + host = NULL; + + return; +} + +struct HdfDriverEntry g_pwmDriverEntry = { + .moduleVersion = 1, + .moduleName = "GD_PWM_MODULE_HDF", + .Bind = PwmDriverBind, + .Init = PwmDriverInit, + .Release = PwmDriverRelease, +}; +HDF_INIT(g_pwmDriverEntry); \ No newline at end of file diff --git a/khdvk_450a/liteos_m/drivers/spi/BUILD.gn b/khdvk_450a/liteos_m/drivers/spi/BUILD.gn new file mode 100644 index 0000000..8a00f61 --- /dev/null +++ b/khdvk_450a/liteos_m/drivers/spi/BUILD.gn @@ -0,0 +1,35 @@ +# Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. +# Licensed 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. + +import("//drivers/hdf_core/adapter/khdf/liteos_m/hdf.gni") + +module_switch = defined(LOSCFG_DRIVERS_HDF_USER_SPI) +module_name = get_path_info(rebase_path("."), "name") +hdf_driver(module_name) { + sources = [ "spi_gd32f4xx.c" ] + include_dirs = [ "../../sdk/drivers/gd32f4xx_driver/include" ] + if (defined(LOSCFG_SHIELD_V200ZR_EVB_T1) && + defined(LOSCFG_DRIVERS_HDF_CONFIG_MACRO)) { + deps = [ "//device/board/fnlink/shields" ] + } + if (defined(LOSCFG_DRIVERS_HDF_CONFIG_MACRO)) { + HDF_HCS_BUILD_PATH = rebase_path( + "//device/board/$device_company/$device_name/liteos_m/hdf_config") + cmd = "if [ -f ${HDF_HCS_BUILD_PATH}/BUILD.gn ]; then echo true; else echo false; fi" + HAVE_HCS_BUILD_PATH = + exec_script("//build/lite/run_shell_cmd.py", [ cmd ], "value") + if (HAVE_HCS_BUILD_PATH) { + deps = [ "${HDF_HCS_BUILD_PATH}" ] + } + } +} diff --git a/khdvk_450a/liteos_m/drivers/spi/spi_gd32f4xx.c b/khdvk_450a/liteos_m/drivers/spi/spi_gd32f4xx.c new file mode 100644 index 0000000..da8fe19 --- /dev/null +++ b/khdvk_450a/liteos_m/drivers/spi/spi_gd32f4xx.c @@ -0,0 +1,667 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 "hdf_device_desc.h" +#include "hdf_log.h" +#include "spi_core.h" +#include "gd32f4xx_spi.h" +#include "spi_if.h" +#ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO +#include "hcs_macro.h" +#include "hdf_config_macro.h" +#else +#include "device_resource_if.h" +#endif + +#define BITWORD_EIGHT 8 +#define BITWORD_SIXTEEN 16 +#define PER_MS_IN_SEC 1000 +#define SPI_CLK 100000000 +#define WAIT_TIME_MAX 10000 +#define SPICFG_MODE 0x0000 +#define SPI_SOFT 0 + +#define GPIO_REG_BASE 0x40020000 +#define GPIO_REG_STEP 0x00000400 +#define GPIO_BIT_PER_GROUP 16 + +typedef enum { + BAUD_RATE_DIV2 = 2, + BAUD_RATE_DIV4 = 4, + BAUD_RATE_DIV8 = 8, + BAUD_RATE_DIV16 = 16, + BAUD_RATE_DIV32 = 32, + BAUD_RATE_DIV64 = 64, + BAUD_RATE_DIV128 = 128, + BAUD_RATE_DIV256 = 256, +} SPI_BAUD_RATE; + +typedef enum { + SPI_PORT1 = 0, + SPI_PORT2, + SPI_PORT3, + SPI_PORT4, + SPI_PORT5, + SPI_PORT6, + SPI_PORT_MAX, +} SPI_GROUPS; + +typedef struct { + uint32_t speed; + uint8_t num; + uint8_t csPin; + uint8_t dataSize; + uint8_t misoPin; + uint8_t mosiPin; + uint8_t clkPin; + uint8_t csSoft; + uint8_t transMode; + uint8_t mode; + uint8_t afPin; + uint8_t enableQuad; +} SpiResource; + +typedef struct { + uint32_t spiId; + SpiResource resource; +} SpiDevice; + +static uint32_t g_spiGroupMaps[SPI_PORT_MAX] = { + SPI0, SPI1, SPI2, SPI3, SPI4, SPI5, +}; + +static uint32_t g_rcuSpiGroupMaps[SPI_PORT_MAX] = { + RCU_SPI0, RCU_SPI1, RCU_SPI2, RCU_SPI3, RCU_SPI4, RCU_SPI5, +}; + +static inline uint32_t ToGpioPeriph(uint16_t local) +{ + uint32_t gpioPeriph = 0; + + gpioPeriph = GPIO_REG_BASE + (local / GPIO_BIT_PER_GROUP) * GPIO_REG_STEP; + + return gpioPeriph; +} + +static inline uint32_t ToGpioPin(uint16_t local) +{ + uint32_t pinNum = 0; + + pinNum = local % GPIO_BIT_PER_GROUP; + + return (BIT(pinNum)); +} + +static inline rcu_periph_enum ToGpioRcuPeriphNum(uint16_t local) +{ + rcu_periph_enum rcuPeriph; + + rcuPeriph = (rcu_periph_enum)(RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, local / GPIO_BIT_PER_GROUP)); + + return rcuPeriph; +} + +static void EnableSpiClock(uint32_t spiNum) +{ + switch (spiNum) { + case SPI_PORT1: + spi_enable(SPI0); + case SPI_PORT2: + spi_enable(SPI1); + case SPI_PORT3: + spi_enable(SPI2); + case SPI_PORT4: + spi_enable(SPI3); + case SPI_PORT5: + spi_enable(SPI4); + case SPI_PORT6: + spi_enable(SPI5); + default: + break; + } +} + +static void InitSpiRcu(const SpiResource *resource) +{ + rcu_periph_clock_enable(ToGpioRcuPeriphNum(resource->csPin)); + rcu_periph_clock_enable(g_rcuSpiGroupMaps[resource->csPin % GPIO_BIT_PER_GROUP]); +} + +static void InitSpiGpio(const SpiResource *resource) +{ + gpio_af_set(ToGpioPeriph(resource->misoPin), AF(resource->afPin), ToGpioPin(resource->misoPin)); + gpio_af_set(ToGpioPeriph(resource->mosiPin), AF(resource->afPin), ToGpioPin(resource->mosiPin)); + gpio_af_set(ToGpioPeriph(resource->clkPin), AF(resource->afPin), ToGpioPin(resource->clkPin)); + + if (resource->enableQuad == TRUE) { + gpio_af_set(GPIOG, AF(resource->afPin), GPIO_PIN_10); + gpio_af_set(GPIOG, AF(resource->afPin), GPIO_PIN_11); + } + + gpio_mode_set(ToGpioPeriph(resource->misoPin), GPIO_MODE_AF, GPIO_PUPD_NONE, ToGpioPin(resource->misoPin)); + gpio_mode_set(ToGpioPeriph(resource->mosiPin), GPIO_MODE_AF, GPIO_PUPD_NONE, ToGpioPin(resource->mosiPin)); + gpio_mode_set(ToGpioPeriph(resource->clkPin), GPIO_MODE_AF, GPIO_PUPD_NONE, ToGpioPin(resource->clkPin)); + if (resource->enableQuad == TRUE) { + gpio_output_options_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_10); + gpio_output_options_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_11); + } + + gpio_output_options_set(ToGpioPeriph(resource->misoPin), GPIO_OTYPE_PP, GPIO_OSPEED_25MHZ, + ToGpioPin(resource->misoPin)); + gpio_output_options_set(ToGpioPeriph(resource->mosiPin), GPIO_OTYPE_PP, GPIO_OSPEED_25MHZ, + ToGpioPin(resource->mosiPin)); + gpio_output_options_set(ToGpioPeriph(resource->clkPin), GPIO_OTYPE_PP, GPIO_OSPEED_25MHZ, + ToGpioPin(resource->clkPin)); + if (resource->enableQuad == TRUE) { + gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_25MHZ, GPIO_PIN_10); + gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_25MHZ, GPIO_PIN_11); + } + + gpio_mode_set(ToGpioPeriph(resource->csPin), GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, ToGpioPin(resource->csPin)); + gpio_output_options_set(ToGpioPeriph(resource->csPin), GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, + ToGpioPin(resource->csPin)); +} + +static int32_t SpiSendRecv(const SpiDevice *spiDevice, uint8_t *txData, uint8_t *rxData, uint16_t len) +{ + uint32_t spiId; + uint32_t time = 0; + SpiResource *resource = NULL; + if (spiDevice == NULL || len == 0) { + HDF_LOGE("spi input para err"); + return HDF_ERR_INVALID_PARAM; + } + spiId = spiDevice->spiId; + resource = &spiDevice->resource; + + if ((resource->transMode == SPI_INTERRUPT_TRANSFER) || (resource->transMode == SPI_DMA_TRANSFER)) { + HDF_LOGE("%s: transfer mode is not support!", __func__); + return HDF_ERR_INVALID_PARAM; + } else if (resource->transMode != SPI_POLLING_TRANSFER) { + HDF_LOGE("%s: error transfer mode!", __func__); + } + + while (len--) { + if (txData != NULL) { + time = 0; + while ((RESET == spi_i2s_flag_get(g_spiGroupMaps[spiId], SPI_FLAG_TBE)) && (time <= WAIT_TIME_MAX)) { + time++; + } + if (time > WAIT_TIME_MAX) { + return HDF_FAILURE; + } + spi_i2s_data_transmit(g_spiGroupMaps[spiId], *txData); + txData++; + } + + if (rxData != NULL) { + time = 0; + while ((RESET == spi_i2s_flag_get(g_spiGroupMaps[spiId], SPI_FLAG_RBNE)) && (time <= WAIT_TIME_MAX)) { + time++; + } + if (time > WAIT_TIME_MAX) { + return HDF_FAILURE; + } + *rxData = spi_i2s_data_receive(g_spiGroupMaps[spiId]); + rxData++; + } + } + + return HDF_SUCCESS; +} +static void SpiClkInit(spi_parameter_struct *spi, const SpiResource *resource) +{ + if (SPI_CLK / resource->speed <= BAUD_RATE_DIV2) { + spi->prescale = SPI_PSC_2; + } else if (SPI_CLK / resource->speed <= BAUD_RATE_DIV4) { + spi->prescale = SPI_PSC_4; + } else if (SPI_CLK / resource->speed <= BAUD_RATE_DIV8) { + spi->prescale = SPI_PSC_8; + } else if (SPI_CLK / resource->speed <= BAUD_RATE_DIV16) { + spi->prescale = SPI_PSC_16; + } else if (SPI_CLK / resource->speed <= BAUD_RATE_DIV32) { + spi->prescale = SPI_PSC_32; + } else if (SPI_CLK / resource->speed <= BAUD_RATE_DIV64) { + spi->prescale = SPI_PSC_64; + } else if (SPI_CLK / resource->speed <= BAUD_RATE_DIV128) { + spi->prescale = SPI_PSC_128; + } else if (SPI_CLK / resource->speed > BAUD_RATE_DIV128) { + spi->prescale = SPI_PSC_256; + } +} +static void SpiStructInit(spi_parameter_struct *spi, const SpiResource *resource) +{ + uint32_t temp = 0; + spi->device_mode = SPI_MASTER; + spi->trans_mode = SPI_TRANSMODE_FULLDUPLEX; + if (resource->dataSize == BITWORD_EIGHT) { + spi->frame_size = SPI_FRAMESIZE_8BIT; + } else { + spi->frame_size = SPI_FRAMESIZE_16BIT; + } + temp = (resource->mode & (SPI_CLK_PHASE | SPI_CLK_POLARITY)); + switch (temp) { + case (SPI_CLK_PHASE | SPI_CLK_POLARITY): + spi->clock_polarity_phase = SPI_CK_PL_HIGH_PH_2EDGE; + break; + case SPI_CLK_PHASE: + spi->clock_polarity_phase = SPI_CK_PL_LOW_PH_2EDGE; + break; + case SPI_CLK_POLARITY: + spi->clock_polarity_phase = SPI_CK_PL_HIGH_PH_1EDGE; + break; + default: + spi->clock_polarity_phase = SPI_CK_PL_LOW_PH_1EDGE; + break; + } + if (resource->mode & SPI_MODE_LSBFE) { + spi->endian = SPI_ENDIAN_LSB; + } else { + spi->endian = SPI_ENDIAN_MSB; + } + if (resource->csSoft == SPI_SOFT) { + spi->nss = SPI_NSS_SOFT; + } else { + spi->nss = SPI_NSS_HARD; + } + SpiClkInit(spi, resource); + return; +} + +static int32_t InitSpiDevice(const SpiDevice *spiDevice) +{ + SpiResource *resource = NULL; + spi_parameter_struct spiInitStruct = {0}; + uint32_t spix; + + if (spiDevice == NULL) { + HDF_LOGE("%s: invalid parameter", __func__); + return HDF_ERR_INVALID_PARAM; + } + + resource = &spiDevice->resource; + spix = g_spiGroupMaps[resource->num]; + + SpiStructInit(&spiInitStruct, resource); + spi_init(spix, &spiInitStruct); + + if (resource->enableQuad == TRUE) { + /* quad wire SPI_IO2 and SPI_IO3 pin output enable */ + spi_quad_io23_output_enable(spix); + } + + spi_enable(spix); + + return HDF_SUCCESS; +} + +#ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO +#define SPI_FIND_CONFIG(node, name, resource, spiDevice) \ + do { \ + if (strcmp(HCS_PROP(node, match_attr), name) == 0) { \ + resource->speed = HCS_PROP(node, speed); \ + resource->num = HCS_PROP(node, num); \ + resource->csPin = HCS_PROP(node, csPin); \ + resource->dataSize = HCS_PROP(node, dataSize); \ + resource->clkPin = HCS_PROP(node, clkPin); \ + resource->mosiPin = HCS_PROP(node, mosiPin); \ + resource->misoPin = HCS_PROP(node, misoPin); \ + resource->afPin = HCS_PROP(node, afPin); \ + resource->enableQuad = HCS_PROP(node, enableQuad); \ + resource->csSoft = HCS_PROP(node, csSoft); \ + resource->transMode = HCS_PROP(node, transMode); \ + resource->mode = HCS_PROP(node, mode); \ + spiDevice->spiId = resource->num; \ + result = HDF_SUCCESS; \ + } \ + } while (0) + +#define PLATFORM_CONFIG HCS_NODE(HCS_ROOT, platform) +#define PLATFORM_SPI_CONFIG HCS_NODE(HCS_NODE(HCS_ROOT, platform), spi_config) +static int32_t GetSpiDeviceResource(SpiDevice *spiDevice, const char *deviceMatchAttr) +{ + int32_t result = HDF_FAILURE; + SpiResource *resource = NULL; + if (spiDevice == NULL || deviceMatchAttr == NULL) { + HDF_LOGE("device or deviceMatchAttr is NULL"); + return HDF_ERR_INVALID_PARAM; + } + resource = &spiDevice->resource; +#if HCS_NODE_HAS_PROP(PLATFORM_CONFIG, spi_config) + HCS_FOREACH_CHILD_VARGS(PLATFORM_SPI_CONFIG, SPI_FIND_CONFIG, deviceMatchAttr, resource, spiDevice); +#endif + if (result != HDF_SUCCESS) { + HDF_LOGE("resourceNode %s is NULL", deviceMatchAttr); + } + return result; +} +#else +static int32_t GetSpiDeviceResource(SpiDevice *spiDevice, const struct DeviceResourceNode *resourceNode) +{ + struct DeviceResourceIface *dri = NULL; + SpiResource *resource = NULL; + + if (spiDevice == NULL || resourceNode == NULL) { + HDF_LOGE("%s: PARAM is NULL", __func__); + return HDF_ERR_INVALID_PARAM; + } + + resource = &spiDevice->resource; + if (resource == NULL) { + HDF_LOGE("%s: resource is NULL", __func__); + return HDF_ERR_INVALID_OBJECT; + } + + dri = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); + if (dri == NULL || dri->GetUint16 == NULL || dri->GetUint8 == NULL || dri->GetUint32 == NULL) { + HDF_LOGE("DeviceResourceIface is invalid"); + return HDF_ERR_INVALID_PARAM; + } + + if (dri->GetUint8(resourceNode, "num", &resource->num, 0) != HDF_SUCCESS) { + HDF_LOGE("get config num failed"); + return HDF_FAILURE; + } + if (dri->GetUint8(resourceNode, "csPin", &resource->csPin, 0) != HDF_SUCCESS) { + HDF_LOGE("get config csPin failed"); + return HDF_FAILURE; + } + if (dri->GetUint32(resourceNode, "speed", &resource->speed, 0) != HDF_SUCCESS) { + HDF_LOGE("get config speed failed"); + return HDF_FAILURE; + } + if (dri->GetUint32(resourceNode, "dataSize", &resource->dataSize, 0) != HDF_SUCCESS) { + HDF_LOGE("get config dataSize failed"); + return HDF_FAILURE; + } + if (dri->GetUint32(resourceNode, "clkPin", &resource->clkPin, 0) != HDF_SUCCESS) { + HDF_LOGE("get config spiClkPin failed"); + return HDF_FAILURE; + } + if (dri->GetUint32(resourceNode, "mosiPin", &resource->mosiPin, 0) != HDF_SUCCESS) { + HDF_LOGE("get config spiMosiPin failed"); + return HDF_FAILURE; + } + if (dri->GetUint32(resourceNode, "misoPin", &resource->misoPin, 0) != HDF_SUCCESS) { + HDF_LOGE("get config spiMisoPin failed"); + return HDF_FAILURE; + } + if (dri->GetUint32(resourceNode, "csSoft", &resource->csSoft, 0) != HDF_SUCCESS) { + HDF_LOGE("get config spiCsSoft failed"); + return HDF_FAILURE; + } + if (dri->GetUint32(resourceNode, "transMode", &resource->transMode, 0) != HDF_SUCCESS) { + HDF_LOGE("get config transMode failed"); + return HDF_FAILURE; + } + if (dri->GetUint32(resourceNode, "mode", &resource->mode, 0) != HDF_SUCCESS) { + HDF_LOGE("get config mode failed"); + return HDF_FAILURE; + } + if (dri->GetUint32(resourceNode, "afPin", &resource->afPin, 0) != HDF_SUCCESS) { + HDF_LOGE("get config afPin failed"); + return HDF_FAILURE; + } + if (dri->GetUint32(resourceNode, "enableQuad", &resource->enableQuad, 0) != HDF_SUCCESS) { + HDF_LOGE("get config enableQuad failed"); + return HDF_FAILURE; + } + + spiDevice->spiId = resource->num; + + return HDF_SUCCESS; +} +#endif + +static int32_t AttachSpiDevice(struct SpiCntlr *spiCntlr, const struct HdfDeviceObject *device) +{ + int32_t ret; + SpiDevice *spiDevice = NULL; + +#ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO + if (spiCntlr == NULL || device == NULL) { +#else + if (spiCntlr == NULL || device == NULL || device->property == NULL) { +#endif + HDF_LOGE("%s: param is NULL", __func__); + return HDF_ERR_INVALID_PARAM; + } + + spiDevice = (struct SpiDevice *)OsalMemAlloc(sizeof(*spiDevice)); + if (spiDevice == NULL) { + HDF_LOGE("%s: OsalMemAlloc spiDevice error", __func__); + return HDF_ERR_MALLOC_FAIL; + } + +#ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO + ret = GetSpiDeviceResource(spiDevice, device->deviceMatchAttr); +#else + ret = GetSpiDeviceResource(spiDevice, device->property); +#endif + if (ret != HDF_SUCCESS) { + (void)OsalMemFree(spiDevice); + return HDF_FAILURE; + } + + spiCntlr->priv = spiDevice; + spiCntlr->busNum = spiDevice->spiId; + + InitSpiRcu(&spiDevice->resource); + InitSpiGpio(&spiDevice->resource); + InitSpiDevice(spiDevice); + + return HDF_SUCCESS; +} + +static int32_t SpiDevOpen(struct SpiCntlr *spiCntlr) +{ + HDF_LOGI("Enter %s", __func__); + if (spiCntlr == NULL) { + HDF_LOGE("spiCntlr is NULL"); + return HDF_ERR_INVALID_PARAM; + } + SpiDevice *spiDevice = NULL; + spiDevice = (SpiDevice *)spiCntlr->priv; + uint32_t spix = g_spiGroupMaps[spiDevice->resource.num]; + spi_enable(spix); + + return HDF_SUCCESS; +} + +static int32_t SpiDevClose(struct SpiCntlr *spiCntlr) +{ + HDF_LOGI("Enter %s", __func__); + if (spiCntlr == NULL) { + HDF_LOGE("spiCntlr is NULL"); + return HDF_ERR_INVALID_PARAM; + } + SpiDevice *spiDevice = NULL; + spiDevice = (SpiDevice *)spiCntlr->priv; + uint32_t spix = g_spiGroupMaps[spiDevice->resource.num]; + spi_disable(spix); + + return HDF_SUCCESS; +} + +static int32_t SpiDevGetCfg(struct SpiCntlr *spiCntlr, struct SpiCfg *spiCfg) +{ + SpiDevice *spiDevice = NULL; + if (spiCntlr == NULL || spiCfg == NULL || spiCntlr->priv == NULL) { + HDF_LOGE("%s: spiCntlr is NULL", __func__); + return HDF_ERR_INVALID_PARAM; + } + spiDevice = (SpiDevice *)spiCntlr->priv; + if (spiDevice == NULL) { + return HDF_DEV_ERR_NO_DEVICE; + } + + spiCfg->maxSpeedHz = spiDevice->resource.speed; + spiCfg->mode = spiDevice->resource.mode; + spiCfg->transferMode = spiDevice->resource.transMode; + spiCfg->bitsPerWord = spiDevice->resource.dataSize; + + return HDF_SUCCESS; +} + +static int32_t SpiDevSetCfg(struct SpiCntlr *spiCntlr, struct SpiCfg *spiCfg) +{ + SpiDevice *spiDevice = NULL; + if (spiCntlr == NULL || spiCfg == NULL || spiCntlr->priv == NULL) { + HDF_LOGE("%s: spiCntlr is NULL", __func__); + return HDF_ERR_INVALID_PARAM; + } + spiDevice = (SpiDevice *)spiCntlr->priv; + if (spiDevice == NULL) { + HDF_LOGE("%s: spiDevice is NULL", __func__); + return HDF_DEV_ERR_NO_DEVICE; + } + + if ((spiDevice->resource.speed == spiCfg->maxSpeedHz) && (spiDevice->resource.dataSize == spiCfg->bitsPerWord) && + (spiDevice->resource.transMode == spiCfg->transferMode) && (spiDevice->resource.mode == spiCfg->mode)) { + return HDF_SUCCESS; + } + + spiDevice->resource.speed = spiCfg->maxSpeedHz; + spiDevice->resource.dataSize = spiCfg->bitsPerWord; + spiDevice->resource.transMode = spiCfg->transferMode; + spiDevice->resource.mode = spiCfg->mode; + + return InitSpiDevice(spiDevice); +} + +static int32_t SpiDevTransfer(struct SpiCntlr *spiCntlr, struct SpiMsg *spiMsg, uint32_t count) +{ + SpiDevice *spiDevice = NULL; + uint32_t ticks = 0; + int32_t ret = 0; + uint8_t singleCsChange = 0; + struct SpiMsg *msg = NULL; + msg = (struct SpiMsg *)OsalMemAlloc(sizeof(*msg)); + if (spiCntlr == NULL || spiCntlr->priv == NULL) { + HDF_LOGE("%s: spiCntlr is NULL", __func__); + return HDF_ERR_INVALID_PARAM; + } + spiDevice = (SpiDevice *)spiCntlr->priv; + InitSpiDevice(spiDevice); + + for (size_t i = 0; i < count; i++) { + msg = &spiMsg[i]; + gpio_bit_reset(ToGpioPeriph((spiDevice->resource).csPin), ToGpioPin((spiDevice->resource).csPin)); + + ret = SpiSendRecv(spiDevice, msg->wbuf, msg->rbuf, msg->len); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: SpiSendRecv failed: ret is %x", __func__, ret); + } + + if (msg->keepCs == 0 || singleCsChange) { + gpio_bit_reset(ToGpioPeriph((spiDevice->resource).csPin), ToGpioPin((spiDevice->resource).csPin)); + } + if (msg->delayUs > 0) { + ticks = (msg->delayUs / PER_MS_IN_SEC); + osDelay(ticks); + } + } + + HDF_LOGD("%s success\n", __func__); + return HDF_SUCCESS; +} + +struct SpiCntlrMethod g_method = { + .Transfer = SpiDevTransfer, + .SetCfg = SpiDevSetCfg, + .GetCfg = SpiDevGetCfg, + .Open = SpiDevOpen, + .Close = SpiDevClose, +}; + +static int32_t SpiDriverBind(struct HdfDeviceObject *device) +{ + struct SpiCntrl *spiCntlr = NULL; + + HDF_LOGI("%s: Enter ", __func__); + + if (device == NULL) { + HDF_LOGE("device object is null!"); + return HDF_ERR_INVALID_PARAM; + } + + spiCntlr = SpiCntlrCreate(device); + if (spiCntlr == NULL) { + HDF_LOGE("SpiCntrlCreate object failed!"); + return HDF_FAILURE; + } + HDF_LOGI("%s spi bind success\n", __func__); + + return HDF_SUCCESS; +} + +static int32_t SpiDriverInit(struct HdfDeviceObject *device) +{ + int32_t ret; + struct SpiCntlr *spiCntlr = NULL; + + if (device == NULL) { + HDF_LOGE("device object is null!"); + return HDF_ERR_INVALID_PARAM; + } + HDF_LOGI("%s: Enter", __func__); + + spiCntlr = SpiCntlrFromDevice(device); + if (spiCntlr == NULL) { + HDF_LOGE("%s: spiCntlr is NULL", __func__); + return HDF_DEV_ERR_NO_DEVICE; + } + + ret = AttachSpiDevice(spiCntlr, device); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: attach error", __func__); + return HDF_DEV_ERR_ATTACHDEV_FAIL; + } + + spiCntlr->method = &g_method; + HDF_LOGI("%s spi%d init success\n", __func__, spiCntlr->busNum); + + return HDF_SUCCESS; +} + +static void SpiDriverRelease(struct HdfDeviceObject *device) +{ + struct SpiCntlr *spiCntlr = NULL; + SpiDevice *spiDevice = NULL; + if (device == NULL) { + HDF_LOGE("%s: device is NULL", __func__); + return; + } + + spiCntlr = SpiCntlrFromDevice(device); + if (spiCntlr == NULL || spiCntlr->priv == NULL) { + HDF_LOGE("%s: spiCntlr is NULL", __func__); + return; + } + + spiDevice = (SpiDevice *)spiCntlr->priv; + OsalMemFree(spiDevice); + + HDF_LOGD("%s success", __func__); +} + +struct HdfDriverEntry g_hdfSpiDevice = { + .moduleVersion = 1, + .moduleName = "GD_SPI_MODULE_HDF", + .Bind = SpiDriverBind, + .Init = SpiDriverInit, + .Release = SpiDriverRelease, +}; +HDF_INIT(g_hdfSpiDevice); \ No newline at end of file diff --git a/khdvk_450a/liteos_m/drivers/uart/BUILD.gn b/khdvk_450a/liteos_m/drivers/uart/BUILD.gn new file mode 100644 index 0000000..adfd511 --- /dev/null +++ b/khdvk_450a/liteos_m/drivers/uart/BUILD.gn @@ -0,0 +1,35 @@ +# Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. +# Licensed 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. + +import("//drivers/hdf_core/adapter/khdf/liteos_m/hdf.gni") + +module_switch = defined(LOSCFG_DRIVERS_HDF_USER_UART) +module_name = get_path_info(rebase_path("."), "name") +hdf_driver(module_name) { + sources = [ "uart_gd32f4xx.c" ] + include_dirs = [ + ".", + "//device/soc/gigadevice/gd32f4xx/sdk/drivers/gd32f4xx_driver/include/", + ] + + if (defined(LOSCFG_DRIVERS_HDF_CONFIG_MACRO)) { + HDF_HCS_BUILD_PATH = rebase_path( + "//device/board/$device_company/$device_name/liteos_m/hdf_config") + cmd = "if [ -f ${HDF_HCS_BUILD_PATH}/BUILD.gn ]; then echo true; else echo false; fi" + HAVE_HCS_BUILD_PATH = + exec_script("//build/lite/run_shell_cmd.py", [ cmd ], "value") + if (HAVE_HCS_BUILD_PATH) { + deps = [ "${HDF_HCS_BUILD_PATH}" ] + } + } +} diff --git a/khdvk_450a/liteos_m/drivers/uart/uart_gd32f4xx.c b/khdvk_450a/liteos_m/drivers/uart/uart_gd32f4xx.c new file mode 100755 index 0000000..c82cb45 --- /dev/null +++ b/khdvk_450a/liteos_m/drivers/uart/uart_gd32f4xx.c @@ -0,0 +1,763 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 "hdf_device_desc.h" + +#ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO +#include "hcs_macro.h" +#include "hdf_config_macro.h" +#else +#include "device_resource_if.h" +#endif +#include "hdf_log.h" +#include "osal.h" +#include "los_mux.h" +#include "los_queue.h" + +#include "uart_if.h" +#include "uart_core.h" +#include "gd32f4xx_usart.h" + +#define HDF_LOG_TAG uart_gd32f4xx +#define UART_HWI_PRIO (0U) +#define UART_HWI_MODE (1U) +#define CLOCK_APB (2) +#define UART_BUS_NUMS (8) +#define GPIO_REG_BASE 0x40020000 +#define GPIO_REG_STEP 0x00000400 +#define GPIO_BIT_PER_GROUP 16 + +struct UartCtrl { + uint32_t num; + uint32_t regBase; + uint32_t irqNum; + OSAL_DECLARE_SPINLOCK(lock); + uint32_t baudRate; + enum UartTransMode mode; + uint32_t openCount; + uint32_t af; + uint32_t txPin; + uint32_t rxPin; + uint32_t fifoSize; + void *priv; +}; + +static int32_t g_regBase; +static UINT32 g_queue; + +static inline uint32_t ToGpioPin(uint16_t local) +{ + uint32_t pinNum = 0; + + pinNum = local % GPIO_BIT_PER_GROUP; + + return (BIT(pinNum)); +} + +static inline uint32_t ToGpioPeriph(uint16_t local) +{ + uint32_t gpioPeriph = 0; + + gpioPeriph = GPIO_REG_BASE + (local / GPIO_BIT_PER_GROUP) * GPIO_REG_STEP; + + return gpioPeriph; +} + +static rcu_periph_enum GpioRcuEnumFind(uint32_t gpioGroup) +{ + uint32_t gpioClockOffset; + gpioClockOffset = gpioGroup / GPIO_BIT_PER_GROUP; + return RCU_REGIDX_BIT(AHB1EN_REG_OFFSET, gpioClockOffset); +} + +static rcu_periph_enum UartRcuEnumFind(struct UartCtrl *uart) +{ + rcu_periph_enum usartRcus[UART_BUS_NUMS] = { + RCU_USART0, RCU_USART1, RCU_USART2, RCU_UART3, RCU_UART4, RCU_USART5, RCU_UART6, RCU_UART7, + }; + return usartRcus[uart->num]; +} + +static uint32_t UartRegBaseFind(struct UartCtrl *uart) +{ + uint32_t usarts[UART_BUS_NUMS] = { + USART0, USART1, USART2, UART3, UART4, USART5, UART6, UART7, + }; + return usarts[uart->num]; +} + +// enable uart, and enable tx/rx mode +static int32_t UartEnable(struct UartCtrl *uart, int enable) +{ + if (enable) { + int32_t gpioGroup; + int32_t gpioTxPin; + int32_t gpioRxPin; + gpioGroup = ToGpioPeriph(uart->txPin); + gpioTxPin = ToGpioPin(uart->txPin); + gpioRxPin = ToGpioPin(uart->rxPin); + rcu_periph_clock_enable(GpioRcuEnumFind(uart->txPin)); + rcu_periph_clock_enable(UartRcuEnumFind(uart)); + + gpio_af_set(gpioGroup, AF(uart->af), gpioTxPin); + gpio_af_set(gpioGroup, AF(uart->af), gpioRxPin); + + gpio_mode_set(gpioGroup, GPIO_MODE_AF, GPIO_PUPD_PULLUP, gpioTxPin); + gpio_output_options_set(gpioGroup, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, gpioTxPin); + + gpio_mode_set(gpioGroup, GPIO_MODE_AF, GPIO_PUPD_PULLUP, gpioRxPin); + gpio_output_options_set(gpioGroup, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, gpioRxPin); + + usart_deinit(uart->regBase); + + usart_baudrate_set(uart->regBase, uart->baudRate); + usart_word_length_set(uart->regBase, USART_WL_8BIT); + usart_stop_bit_set(uart->regBase, USART_STB_1BIT); + usart_parity_config(uart->regBase, USART_PM_NONE); + + usart_hardware_flow_rts_config(uart->regBase, USART_RTS_DISABLE); + usart_hardware_flow_cts_config(uart->regBase, USART_CTS_DISABLE); + + usart_receive_config(uart->regBase, USART_RECEIVE_ENABLE); + usart_transmit_config(uart->regBase, USART_TRANSMIT_ENABLE); + + usart_flag_clear(uart->regBase, USART_FLAG_TC | USART_FLAG_TBE); + + usart_enable(uart->regBase); + + nvic_irq_enable(uart->irqNum, 2U, 0U); + + usart_interrupt_enable(uart->regBase, USART_INT_RBNE); + } else { + usart_deinit(uart->regBase); + + usart_receive_config(uart->regBase, USART_RECEIVE_DISABLE); + usart_transmit_config(uart->regBase, USART_TRANSMIT_DISABLE); + + usart_flag_clear(uart->regBase, USART_FLAG_TC | USART_FLAG_TBE); + + usart_interrupt_disable(uart->regBase, USART_INT_RBNE); + + nvic_irq_disable(uart->irqNum); + + usart_disable(uart->regBase); + } + return 0; +} + +static int32_t UartDataBits(struct UartCtrl *uart, uint32_t bits) +{ + switch (bits) { + case UART_ATTR_DATABIT_8: + usart_word_length_set(uart->regBase, USART_WL_8BIT); + break; + default: + HDF_LOGE("%s: not support parameter.\r\n", __func__); + return HDF_ERR_INVALID_PARAM; + } + + return 0; +} + +static int32_t UartStopBits(struct UartCtrl *uart, uint32_t bits) +{ + switch (bits) { + case UART_ATTR_STOPBIT_1: + usart_stop_bit_set(uart->regBase, USART_STB_1BIT); + break; + case UART_ATTR_STOPBIT_1P5: + usart_stop_bit_set(uart->regBase, USART_STB_1_5BIT); + break; + case UART_ATTR_STOPBIT_2: + usart_stop_bit_set(uart->regBase, USART_STB_2BIT); + break; + default: + HDF_LOGE("%s: not support parameter.\r\n", __func__); + return HDF_ERR_INVALID_PARAM; + } + + return 0; +} + +static int32_t UartParity(struct UartCtrl *uart, uint32_t parity) +{ + switch (parity) { + case UART_ATTR_PARITY_NONE: + usart_parity_config(uart->regBase, USART_PM_NONE); + break; + case UART_ATTR_PARITY_ODD: + usart_parity_config(uart->regBase, USART_PM_ODD); + break; + case UART_ATTR_PARITY_EVEN: + usart_parity_config(uart->regBase, USART_PM_EVEN); + break; + default: + HDF_LOGE("%s: not support parameter.\r\n", __func__); + return HDF_ERR_INVALID_PARAM; + } + + return 0; +} + +static int32_t UartRts(struct UartCtrl *uart, uint32_t rts) +{ + switch (rts) { + case UART_ATTR_RTS_DIS: + usart_hardware_flow_rts_config(uart->regBase, USART_RTS_DISABLE); + break; + case UART_ATTR_RTS_EN: + usart_hardware_flow_rts_config(uart->regBase, USART_RTS_ENABLE); + break; + default: + HDF_LOGE("%s: not support parameter.\r\n", __func__); + return HDF_ERR_INVALID_PARAM; + } + + return 0; +} + +static int32_t UartCts(struct UartCtrl *uart, uint32_t cts) +{ + switch (cts) { + case UART_ATTR_CTS_DIS: + usart_hardware_flow_cts_config(uart->regBase, USART_CTS_DISABLE); + break; + case UART_ATTR_CTS_EN: + usart_hardware_flow_cts_config(uart->regBase, USART_CTS_ENABLE); + break; + default: + HDF_LOGE("%s: not support parameter.\r\n", __func__); + return HDF_ERR_INVALID_PARAM; + } + + return 0; +} + +static int32_t UartBaudrate(struct UartCtrl *uart, uint32_t baudRate) +{ + usart_baudrate_set(uart->regBase, baudRate); + return 0; +} + +static int32_t UartConfig(struct UartCtrl *uart) +{ + int32_t ret; + struct UartAttribute *attr = (struct UartAttribute *)uart->priv; + + ret = UartDataBits(uart, attr->dataBits); + ret |= UartStopBits(uart, attr->stopBits); + ret |= UartParity(uart, attr->parity); + ret |= UartRts(uart, attr->rts); + ret |= UartCts(uart, attr->cts); + + return ret; +} + +static int32_t UartDevOpen(struct UartHost *host) +{ + int32_t ret = HDF_SUCCESS; + + struct UartCtrl *uart = (struct UartCtrl *)host->priv; + + OsalSpinLock(&(uart->lock)); + + struct UartAttribute *attr = (struct UartAttribute *)uart->priv; + + attr->dataBits = UART_ATTR_DATABIT_8; + attr->parity = UART_ATTR_PARITY_NONE; + attr->stopBits = UART_ATTR_STOPBIT_1; + attr->rts = UART_ATTR_RTS_DIS; + attr->cts = UART_ATTR_CTS_DIS; + + UartConfig(uart); + UartEnable(uart, true); + ret = LOS_QueueCreate("queue", uart->fifoSize, &g_queue, 0, 1); + if (ret != LOS_OK) { + HDF_LOGE("create queue failure, error: %x\n", ret); + } + uart->openCount++; + + OsalSpinUnlock(&(uart->lock)); + return ret; +} + +static int32_t UartDevClose(struct UartHost *host) +{ + struct UartCtrl *uart = (struct UartCtrl *)host->priv; + + if (--uart->openCount > 0) { + return HDF_FAILURE; + } + + OsalSpinLock(&(uart->lock)); + + UartEnable(uart, false); + + OsalSpinUnlock(&(uart->lock)); + + return HDF_SUCCESS; +} + +static int32_t UartDevRead(struct UartHost *host, uint8_t *data, uint32_t size) +{ + if (host == NULL || host->priv == NULL) { + HDF_LOGE("%s: invalid parameter.\r\n", __func__); + return HDF_ERR_INVALID_PARAM; + } + + int32_t ret = 0; + int32_t recvSize = 0; + int32_t readLen = 1; + int32_t timeOut = 0; + + struct UartCtrl *uart = (struct UartCtrl *)host->priv; + + OsalSpinLock(&(uart->lock)); + + if (uart->mode == UART_MODE_RD_BLOCK) { + timeOut = LOS_WAIT_FOREVER; + } else if (uart->mode == UART_MODE_RD_NONBLOCK) { + timeOut = 0; + } else { + HDF_LOGE("mode not support"); + } + while (recvSize < size) { + ret = LOS_QueueReadCopy(g_queue, data + recvSize, &readLen, timeOut); + if (ret == LOS_ERRNO_QUEUE_ISEMPTY) { + break; + } + recvSize++; + } + + OsalSpinUnlock(&(uart->lock)); + return recvSize; +} + +static int32_t UartDevWrite(struct UartHost *host, uint8_t *data, uint32_t size) +{ + int32_t ret = HDF_SUCCESS; + if (host == NULL || host->priv == NULL || data == NULL) { + HDF_LOGE("%s: invalid parameter.\r\n", __func__); + return HDF_ERR_INVALID_PARAM; + } + struct UartCtrl *uart = (struct UartCtrl *)host->priv; + + OsalSpinLock(&(uart->lock)); + + for (int i = 0; i < size; i++) { + if (data[i] == '\n') { + usart_data_transmit(uart->regBase, '\r'); + while (RESET == usart_flag_get(uart->regBase, USART_FLAG_TBE)) { }; + usart_data_transmit(uart->regBase, '\n'); + } else { + usart_data_transmit(uart->regBase, data[i]); + } + while (RESET == usart_flag_get(uart->regBase, USART_FLAG_TBE)) { }; + } + + OsalSpinUnlock(&(uart->lock)); + + return ret; +} + +static int32_t UartDevGetBaud(struct UartHost *host, uint32_t *baudRate) +{ + int32_t ret = HDF_SUCCESS; + if (host == NULL || host->priv == NULL || baudRate == NULL) { + HDF_LOGE("%s: invalid parameter", __func__); + return HDF_ERR_INVALID_PARAM; + } + struct UartCtrl *uart = (struct UartCtrl *)host->priv; + + OsalSpinLock(&(uart->lock)); + + *baudRate = uart->baudRate; + + OsalSpinUnlock(&(uart->lock)); + return ret; +} + +static int32_t UartDevSetBaud(struct UartHost *host, uint32_t baudRate) +{ + int32_t ret = HDF_SUCCESS; + if (host == NULL || host->priv == NULL || baudRate == 0) { + HDF_LOGE("%s: invalid parameter", __func__); + return HDF_ERR_INVALID_PARAM; + } + struct UartCtrl *uart = (struct UartCtrl *)host->priv; + + OsalSpinLock(&(uart->lock)); + + if (uart->baudRate != baudRate) { + UartBaudrate(uart, baudRate); + uart->baudRate = baudRate; + } + + OsalSpinUnlock(&(uart->lock)); + return ret; +} + +static int32_t UartDevGetAttribute(struct UartHost *host, struct UartAttribute *attribute) +{ + int32_t ret = HDF_SUCCESS; + struct UartCtrl *uart = NULL; + struct UartAttribute *attr = NULL; + if (host == NULL || host->priv == NULL || attribute == NULL) { + HDF_LOGE("%s: invalid parameter", __func__); + return HDF_ERR_INVALID_PARAM; + } + uart = (struct UartCtrl *)host->priv; + attr = (struct UartAttribute *)uart->priv; + + OsalSpinLock(&(uart->lock)); + + memcpy_s(attribute, sizeof(struct UartAttribute), attr, sizeof(struct UartAttribute)); + + OsalSpinUnlock(&(uart->lock)); + + return ret; +} + +static int32_t UartDevSetAttribute(struct UartHost *host, struct UartAttribute *attribute) +{ + HDF_LOGE("func: %s, UartSetAttribute ok\r\n", __func__); + int32_t ret = HDF_SUCCESS; + struct UartCtrl *uart = NULL; + struct UartAttribute *attr = NULL; + if (host == NULL || host->priv == NULL || attribute == NULL) { + HDF_LOGE("%s: invalid parameter", __func__); + return HDF_ERR_INVALID_PARAM; + } + uart = (struct UartCtrl *)host->priv; + attr = (struct UartAttribute *)uart->priv; + + OsalSpinLock(&(uart->lock)); + + // 保存新配置 + memcpy_s(attr, sizeof(struct UartAttribute), attribute, sizeof(struct UartAttribute)); + + // 根据新配置,更新寄存器 + ret = UartConfig(uart); + + OsalSpinUnlock(&(uart->lock)); + return ret; +} + +static int32_t UartDevSetTransMode(struct UartHost *host, enum UartTransMode mode) +{ + int32_t ret = HDF_SUCCESS; + struct UartCtrl *uart = (struct UartCtrl *)host->priv; + + OsalSpinLock(&(uart->lock)); + + switch (mode) { + case UART_MODE_RD_BLOCK: + uart->mode = UART_MODE_RD_BLOCK; + break; + case UART_MODE_RD_NONBLOCK: + uart->mode = UART_MODE_RD_NONBLOCK; + break; + default: + HDF_LOGE("%s: unsupport mode %#x.\r\n", __func__, mode); + break; + } + + OsalSpinUnlock(&(uart->lock)); + + return ret; +} + +struct UartHostMethod g_uartOps = {.Init = UartDevOpen, + .Deinit = UartDevClose, + .Read = UartDevRead, + .Write = UartDevWrite, + .GetBaud = UartDevGetBaud, + .SetBaud = UartDevSetBaud, + .GetAttribute = UartDevGetAttribute, + .SetAttribute = UartDevSetAttribute, + .SetTransMode = UartDevSetTransMode, + .pollEvent = NULL}; + +#ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO +#define UART_FIND_CONFIG(node, name, uart) \ + do { \ + if (strcmp(HCS_PROP(node, match_attr), name) == 0) { \ + uint32_t devNum = HCS_PROP(node, num); \ + uint16_t baudRate = HCS_PROP(node, baudrate); \ + uint16_t mode = HCS_PROP(node, mode); \ + uint32_t interrupt = HCS_PROP(node, interrupt); \ + uint32_t fifoSize = HCS_PROP(node, fifo_size); \ + uint32_t af = HCS_PROP(node, af); \ + uint32_t txPin = HCS_PROP(node, tx_pin); \ + uint32_t rxPin = HCS_PROP(node, rx_pin); \ + uart->num = devNum; \ + uart->baudRate = baudRate; \ + uart->mode = mode; \ + uart->irqNum = interrupt; \ + uart->fifoSize = fifoSize; \ + uart->af = af; \ + uart->txPin = txPin; \ + uart->rxPin = rxPin; \ + result = HDF_SUCCESS; \ + } \ + } while (0) +#define PLATFORM_CONFIG HCS_NODE(HCS_ROOT, platform) +#define PLATFORM_UART_CONFIG HCS_NODE(HCS_NODE(HCS_ROOT, platform), controller_0x40011000) +static int32_t ReadUartHcsSource(struct UartCtrl *uart, const char *deviceMatchAttr) +{ + int32_t result = HDF_FAILURE; + if (uart == NULL || deviceMatchAttr == NULL) { + HDF_LOGE("%s: uart resource or deviceMatchAttr is NULL", __func__); + return HDF_ERR_INVALID_PARAM; + } + +#if HCS_NODE_HAS_PROP(PLATFORM_CONFIG, controller_0x40011000) + HCS_FOREACH_CHILD_VARGS(PLATFORM_UART_CONFIG, UART_FIND_CONFIG, deviceMatchAttr, uart); +#endif + if (result != HDF_SUCCESS) { + HDF_LOGE("resourceNode %s is NULL\r\n", deviceMatchAttr); + } + + return result; +} +#else +static int32_t ReadUartHcsSource(struct UartCtrl *uart, const struct DeviceResourceNode *node) +{ + int32_t ret; + struct DeviceResourceIface *drsOps = NULL; + + drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); + if (drsOps == NULL || drsOps->GetUint32 == NULL) { + HDF_LOGE("%s: invalid drs ops!\r\n", __func__); + return HDF_FAILURE; + } + + ret = drsOps->GetUint32(node, "num", &uart->num, 0); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: read num fail!\r\n", __func__); + return ret; + } + + ret = drsOps->GetUint32(node, "mode", &uart->mode, 0); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: read mode fail!\r\n", __func__); + return ret; + } + + ret = drsOps->GetUint32(node, "baudrate", &uart->baudRate, 0); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: read baud_rate fail!\r\n", __func__); + return ret; + } + + ret = drsOps->GetUint32(node, "interrupt", &uart->irqNum, 0); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: read interrupt fail!\r\n", __func__); + return ret; + } + + ret = drsOps->GetUint32(node, "fifo_size", &uart->fifoSize, 0); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: read fifoSize fail!\r\n", __func__); + return ret; + } + + ret = drsOps->GetUint32(node, "af", &uart->af, 0); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: read af fail!\r\n", __func__); + return ret; + } + + ret = drsOps->GetUint32(node, "tx_pin", &uart->txPin, 0); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: read tx_pin fail!\r\n", __func__); + return ret; + } + + ret = drsOps->GetUint32(node, "rx_pin", &uart->rxPin, 0); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: read rx_pin fail!\r\n", __func__); + return ret; + } + + return HDF_SUCCESS; +} +#endif + +static int32_t UartDevBind(struct HdfDeviceObject *device) +{ + int32_t ret; + struct UartHost *host = NULL; + struct UartCtrl *uart = NULL; + struct UartAttribute *attr = NULL; + HDF_LOGI("%s: Enter", __func__); + +#ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO + if (device == NULL) { +#else + if (device == NULL || device->property == NULL) { +#endif + HDF_LOGE("%s: device or property is null!.\r\n", __func__); + return HDF_ERR_INVALID_OBJECT; + } + + host = UartHostCreate(device); + if (host == NULL) { + HDF_LOGE("%s: UartHostCreate fail!.\r\n", __func__); + return HDF_ERR_MALLOC_FAIL; + } + + // 申请内存空间 + uart = (struct UartCtrl *)OsalMemCalloc(sizeof(struct UartCtrl)); + if (uart == NULL) { + HDF_LOGE("%s: malloc uart fail!.\r\n", __func__); + return HDF_ERR_MALLOC_FAIL; + } + + // attr + attr = (struct UartAttribute *)OsalMemCalloc(sizeof(struct UartAttribute)); + if (uart == NULL) { + HDF_LOGE("%s: malloc attr fail!.\r\n", __func__); + OsalMemFree(uart); + return HDF_ERR_MALLOC_FAIL; + } + uart->priv = (void *)attr; +#ifdef LOSCFG_DRIVERS_HDF_CONFIG_MACRO + ret = ReadUartHcsSource(uart, device->deviceMatchAttr); +#else + ret = ReadUartHcsSource(uart, device->property); +#endif + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: read drs fail:%d.\r\n", __func__, ret); + OsalMemFree(attr); + OsalMemFree(uart); + return ret; + } + + uart->regBase = UartRegBaseFind(uart); + host->method = &g_uartOps; + host->priv = uart; + host->num = uart->num; + HDF_LOGI("%s: Bind sucess", __func__); + return HDF_SUCCESS; +} + +static void UsartIrq(void) +{ + char ch; + char recvCh = 0; + UINT32 recvSize = 1; + uint32_t ret; + + while (RESET != usart_interrupt_flag_get(g_regBase, USART_INT_FLAG_RBNE)) { + ch = usart_data_receive(g_regBase); + ret = LOS_QueueWriteCopy(g_queue, &ch, 1, 0); + if (ret == LOS_ERRNO_QUEUE_ISFULL) { + LOS_QueueReadCopy(g_queue, &recvCh, &recvSize, 0); + LOS_QueueWriteCopy(g_queue, &ch, 1, 0); + } + } +} + +static int32_t UartDevInit(struct HdfDeviceObject *device) +{ + int32_t ret = HDF_SUCCESS; + struct UartHost *host = NULL; + struct UartCtrl *uart = NULL; + + HDF_LOGI("%s: Enter", __func__); + + if (device == NULL) { + HDF_LOGE("%s: device is null.\r\n", __func__); + return HDF_FAILURE; + } + + host = UartHostFromDevice(device); + if (host == NULL) { + HDF_LOGE("%s: host is null.\r\n", __func__); + return HDF_FAILURE; + } + + uart = (struct UartCtrl *)host->priv; + if (uart == NULL) { + HDF_LOGE("%s: uart is null.\r\n", __func__); + return HDF_FAILURE; + } + + g_regBase = uart->regBase; + + LOS_HwiCreate(uart->irqNum, UART_HWI_PRIO, UART_HWI_MODE, (HWI_PROC_FUNC)UsartIrq, NULL); + + ret = OsalSpinInit(&(uart->lock)); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: OsalSpinInit fail.\r\n", __func__); + return HDF_FAILURE; + } + + OsalSpinLock(&(uart->lock)); + + UartEnable(uart, true); + + OsalSpinUnlock(&(uart->lock)); + HDF_LOGI("%s: init uart%d sucess", __func__, uart->num); + return ret; +} + +static void UartDevRelease(struct HdfDeviceObject *device) +{ + struct UartHost *host = NULL; + struct UartCtrl *uart = NULL; + HDF_LOGD("%s::enter, deviceObject=%p", __func__, device); + if (device == NULL) { + HDF_LOGE("%s: device is null.\r\n", __func__); + return; + } + + host = UartHostFromDevice(device); + if (host == NULL) { + HDF_LOGE("%s: host is null.\r\n", __func__); + return; + } + + uart = (struct UartCtrl *)host->priv; + if (uart == NULL) { + HDF_LOGE("%s: uart is null.\r\n", __func__); + return; + } + + OsalSpinLock(&(uart->lock)); + + LOS_HwiDelete(uart->irqNum, NULL); + + UartEnable(uart, false); + + OsalSpinUnlock(&(uart->lock)); + + OsalSpinDestroy(&(uart->lock)); + + OsalMemFree(uart->priv); + OsalMemFree(uart); + + UartHostDestroy(host); +} + +struct HdfDriverEntry g_hdf_driver_uart_entry = { + .moduleVersion = 1, + .Bind = UartDevBind, + .Init = UartDevInit, + .Release = UartDevRelease, + .moduleName = "GD_UART_MODULE_HDF", +}; +HDF_INIT(g_hdf_driver_uart_entry); diff --git a/khdvk_450a/liteos_m/drivers/wdg/BUILD.gn b/khdvk_450a/liteos_m/drivers/wdg/BUILD.gn new file mode 100644 index 0000000..eedcc81 --- /dev/null +++ b/khdvk_450a/liteos_m/drivers/wdg/BUILD.gn @@ -0,0 +1,36 @@ +# Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. +# Licensed 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. + +import("//drivers/hdf_core/adapter/khdf/liteos_m/hdf.gni") + +module_switch = defined(0) +module_name = get_path_info(rebase_path("."), "name") +hdf_driver(module_name) { + sources = [ + "watchdog.c", #模块要编译的源码文件 + ] + include_dirs = [ + ".", #依赖的头文件目录 + ] + + if (defined(LOSCFG_DRIVERS_HDF_CONFIG_MACRO)) { + HDF_HCS_BUILD_PATH = rebase_path( + "//device/board/$device_company/$device_name/liteos_m/hdf_config") + cmd = "if [ -f ${HDF_HCS_BUILD_PATH}/BUILD.gn ]; then echo true; else echo false; fi" + HAVE_HCS_BUILD_PATH = + exec_script("//build/lite/run_shell_cmd.py", [ cmd ], "value") + if (HAVE_HCS_BUILD_PATH) { + deps = [ "${HDF_HCS_BUILD_PATH}" ] + } + } +} diff --git a/khdvk_450a/liteos_m/drivers/wdg/watchdog.c b/khdvk_450a/liteos_m/drivers/wdg/watchdog.c new file mode 100644 index 0000000..4010aab --- /dev/null +++ b/khdvk_450a/liteos_m/drivers/wdg/watchdog.c @@ -0,0 +1,432 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 "watchdog.h" + +/** + * fls - find last (most-significant) bit set + * @x: the word to search + * + * This is defined the same way as ffs. + * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32. + */ +#define START_FLS 32 +#define OFFSET16 16 +#define OFFSET8 8 +#define OFFSET4 4 +#define OFFSET2 2 +#define OFFSET1 1 +#define BORDER_MULTIPLE 1000 +#define TWO_TO_TENTH 1024 +static int generic_fls(int t) +{ + int r = START_FLS; + int x = t; + if (!x) { + return 0; + } + if (!(x & 0xffff0000u)) { + x <<= OFFSET16; + r -= OFFSET16; + } + if (!(x & 0xff000000u)) { + x <<= OFFSET8; + r -= OFFSET8; + } + if (!(x & 0xf0000000u)) { + x <<= OFFSET4; + r -= OFFSET4; + } + if (!(x & 0xc0000000u)) { + x <<= OFFSET2; + r -= OFFSET2; + } + if (!(x & 0x80000000u)) { + x <<= OFFSET1; + r -= OFFSET1; + } + return r; +} + +static inline int ilog2(unsigned int x) +{ + return generic_fls(x) - 1; +} + +unsigned long roundup_pow_of_two(unsigned long n) +{ + return 1UL << generic_fls(n - 1); +} + +static inline uint32_t reg_read(void volatile *base, uint32_t reg) +{ + return OSAL_READL((uintptr_t)base + reg); +} + +static inline void reg_write(void volatile *base, uint32_t reg, uint32_t val) +{ + OSAL_WRITEL(val, (uintptr_t)base + reg); +} + +// get clock source real rate +static inline int32_t GD450wdgGetClockRate(struct GD450wdg *iwdg) +{ + int ret = HDF_SUCCESS; + + /* + if "clock_source" is set, use the real rate of clock source + otherwise, use the default clock rate + */ + if (iwdg->clock_source != NULL) { + // get clock source real rate. + // ... + ret = HDF_SUCCESS; + } + + return ret; +} + +static inline uint32_t GD450wdgGetSr(struct GD450wdg *iwdg) +{ + return reg_read(iwdg->base, IWDG_SR); +} + +int32_t GD450wdgStart(struct WatchdogCntlr *wdt) +{ + struct GD450wdg *iwdg = NULL; + uint32_t tout, presc, iwdg_pr, iwdg_rlr, iwdg_sr; + uint32_t i = 10; + + if (wdt == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + iwdg = (struct GD450wdg *)wdt->priv; + + // 计算装载值 + tout = iwdg->seconds; // 超时秒数 + + // 计算边界 + if (tout > (iwdg->max_hw_heartbeat_ms * BORDER_MULTIPLE)) { + tout = iwdg->max_hw_heartbeat_ms * BORDER_MULTIPLE; + } + if (tout < iwdg->min_timeout) { + tout = iwdg->min_timeout; + } + + presc = DIV_ROUND_UP(tout * iwdg->rate, RLR_MAX + 1); + + /* The prescaler is align on power of 2 and start at 2 ^ PR_SHIFT. */ + presc = roundup_pow_of_two(presc); + iwdg_pr = (presc <= (1 << PR_SHIFT)) ? 0 : ilog2(presc) - PR_SHIFT; + if (presc == 0) { + return HDF_FAILURE; + } + iwdg_rlr = ((tout * iwdg->rate) / presc) - 1; + + /* enable write access */ + reg_write(iwdg->base, IWDG_KR, KR_KEY_EWA); + + /* set prescaler & reload registers */ + reg_write(iwdg->base, IWDG_PR, iwdg_pr); + reg_write(iwdg->base, IWDG_RLR, iwdg_rlr); + reg_write(iwdg->base, IWDG_KR, KR_KEY_ENABLE); + + // 等待状态寄存器 SR_PVU | SR_RVU 复位 + while ((iwdg_sr = GD450wdgGetSr(iwdg)) & (SR_PVU | SR_RVU)) { + if (!(--i)) { + HDF_LOGE("Fail to set prescaler, reload regs."); + return HDF_FAILURE; + } + } + + /* reload watchdog */ + reg_write(iwdg->base, IWDG_KR, KR_KEY_RELOAD); + + /* iwdg start */ + iwdg->start = true; + + return HDF_SUCCESS; +} + +int32_t GD450wdgSetTimeout(struct WatchdogCntlr *wdt, uint32_t seconds) +{ + struct GD450wdg *iwdg = NULL; + + if (wdt == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + + iwdg = (struct GD450wdg *)wdt->priv; + iwdg->seconds = seconds; + + // 如果iwdg已经是启动状态, 需要重新装载超时值并继续喂狗操作 + if (iwdg->start) { + return GD450wdgStart(wdt); + } + + return HDF_SUCCESS; +} + +int32_t GD450wdgGetTimeout(struct WatchdogCntlr *wdt, uint32_t *seconds) +{ + struct GD450wdg *iwdg = NULL; + if (wdt == NULL || seconds == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + iwdg = (struct GD450wdg *)wdt->priv; + + *seconds = iwdg->seconds; + + return HDF_SUCCESS; +} + +static int32_t GD450wdgFeed(struct WatchdogCntlr *wdt) +{ + struct GD450wdg *iwdg = NULL; + + if (wdt == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + iwdg = (struct GD450wdg *)wdt->priv; + + /* reload watchdog */ + reg_write(iwdg->base, IWDG_KR, KR_KEY_RELOAD); + + return HDF_SUCCESS; +} + +static int32_t GD450wdgGetStatus(struct WatchdogCntlr *wdt, int32_t *status) +{ + (void)status; + int32_t ret = WATCHDOG_STOP; + struct GD450wdg *iwdg = NULL; + + if (wdt == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + iwdg = (struct GD450wdg *)wdt->priv; + + if (iwdg->start) { + ret = WATCHDOG_START; + } + return ret; +} + +/* WatchdogOpen 的时候被调用 */ +static int32_t GD450wdgGetPriv(struct WatchdogCntlr *wdt) +{ + int32_t ret; + struct GD450wdg *iwdg = NULL; + + if (wdt == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + iwdg = (struct GD450wdg *)wdt->priv; + + // 获取当前时钟源频率 + ret = GD450wdgGetClockRate(iwdg); + if (ret != HDF_SUCCESS) { + HDF_LOGE("GD450wdgGetClockRate fail, ret : %#x.", ret); + return HDF_FAILURE; + } + + // 计算最大最小的超时时间 + iwdg->min_timeout = DIV_ROUND_UP((RLR_MIN + 1) * PR_MIN, iwdg->rate); + iwdg->max_hw_heartbeat_ms = ((RLR_MAX + 1) * TWO_TO_TENTH * BORDER_MULTIPLE) / iwdg->rate; + + return ret; +} + +/* WatchdogClose 的时候被调用 */ +static void GD450wdgReleasePriv(struct WatchdogCntlr *wdt) +{ + (void)wdt; +} + +static struct WatchdogMethod g_gd450_iwdg_ops = {.feed = GD450wdgFeed, + .getPriv = GD450wdgGetPriv, + .getStatus = GD450wdgGetStatus, + .getTimeout = GD450wdgGetTimeout, + .releasePriv = GD450wdgReleasePriv, + .setTimeout = GD450wdgSetTimeout, + .start = GD450wdgStart, + + // stm32mp1的iwdg不支持软件停止 + .stop = NULL}; + +static int32_t GD450wdgReadDrs(struct GD450wdg *iwdg, const struct DeviceResourceNode *node) +{ + int32_t ret; + struct DeviceResourceIface *drsOps = NULL; + + drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); + if (drsOps == NULL || drsOps->GetUint32 == NULL) { + HDF_LOGE("%s: invalid drs ops!", __func__); + return HDF_FAILURE; + } + + // num + ret = drsOps->GetUint32(node, "num", &iwdg->num, 0); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: read num fail!", __func__); + return ret; + } + + // reg_base + ret = drsOps->GetUint32(node, "reg_base", &iwdg->phy_base, 0); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: read regBase fail!", __func__); + return ret; + } + + // reg_step + ret = drsOps->GetUint32(node, "reg_step", &iwdg->reg_step, 0); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: read regStep fail!", __func__); + return ret; + } + + // default timeout + ret = drsOps->GetUint32(node, "timeout_sec", &iwdg->seconds, DEFAULT_TIMEOUT); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: read timeout fail!", __func__); + return ret; + } + + // default source rate + ret = drsOps->GetUint32(node, "clock_rate", &iwdg->rate, DEFAULT_CLOCK_RATE); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: read clock_rate fail!", __func__); + return ret; + } + + // start + iwdg->start = drsOps->GetBool(node, "start"); + + return HDF_SUCCESS; +} + +static int32_t GD450wdgBind(struct HdfDeviceObject *device) +{ + int32_t ret; + struct GD450wdg *iwdg = NULL; + + if (device == NULL || device->property == NULL) { + HDF_LOGE("%s: device or property is null!", __func__); + return HDF_ERR_INVALID_OBJECT; + } + + // 申请内存空间 + iwdg = (struct GD450wdg *)OsalMemCalloc(sizeof(struct GD450wdg)); + if (iwdg == NULL) { + HDF_LOGE("%s: malloc iwdg fail!", __func__); + return HDF_ERR_MALLOC_FAIL; + } + + // 解析配置 + ret = GD450wdgReadDrs(iwdg, device->property); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: read drs fail:%d", __func__, ret); + OsalMemFree(iwdg); + return ret; + } + + // 寄存器映射 + iwdg->base = OsalIoRemap(iwdg->phy_base, iwdg->reg_step); + if (iwdg->base == NULL) { + HDF_LOGE("%s: ioremap regbase fail!", __func__); + OsalMemFree(iwdg); + return HDF_ERR_IO; + } + + // 填充操作符 + iwdg->wdt.priv = (void *)iwdg; + iwdg->wdt.ops = &g_gd450_iwdg_ops; + iwdg->wdt.device = device; + iwdg->wdt.wdtId = iwdg->num; + + // add device + ret = WatchdogCntlrAdd(&iwdg->wdt); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: err add watchdog:%d.", __func__, ret); + OsalIoUnmap((void *)iwdg->base); + OsalMemFree(iwdg); + return ret; + } + + return HDF_SUCCESS; +} + +static int32_t GD450wdgInit(struct HdfDeviceObject *device) +{ + int32_t ret; + struct WatchdogCntlr *wdt = NULL; + struct GD450wdg *iwdg = NULL; + + // get WatchdogCntlr + wdt = WatchdogCntlrFromDevice(device); + if (wdt == NULL) { + return HDF_FAILURE; + } + iwdg = (struct GD450wdg *)wdt->priv; + + // get priv data(get clock source) + ret = GD450wdgGetPriv(wdt); + if (ret != HDF_SUCCESS) { + HDF_LOGE("GD450wdgGetPriv fail."); + return HDF_FAILURE; + } + + // set default timeout + ret = GD450wdgSetTimeout(wdt, iwdg->seconds); + if (ret != HDF_SUCCESS) { + HDF_LOGE("GD450wdgSetTimeout fail."); + return HDF_FAILURE; + } + + return HDF_SUCCESS; +} + +static void GD450wdgRelease(struct HdfDeviceObject *device) +{ + struct WatchdogCntlr *wdt = NULL; + struct GD450wdg *iwdg = NULL; + + if (device == NULL) { + return; + } + + wdt = WatchdogCntlrFromDevice(device); + if (wdt == NULL) { + return; + } + WatchdogCntlrRemove(wdt); + + iwdg = (struct GD450wdg *)wdt->priv; + if (iwdg->base != NULL) { + OsalIoUnmap((void *)iwdg->base); + iwdg->base = NULL; + } + OsalMemFree(iwdg); +} + +struct HdfDriverEntry g_hdf_driver_iwdg_entry = { + .moduleVersion = 1, + .Bind = GD450wdgBind, + .Init = GD450wdgInit, + .Release = GD450wdgRelease, + .moduleName = "gd450_iwdg", +}; +HDF_INIT(g_hdf_driver_iwdg_entry); diff --git a/khdvk_450a/liteos_m/drivers/wdg/watchdog.h b/khdvk_450a/liteos_m/drivers/wdg/watchdog.h new file mode 100644 index 0000000..80361bf --- /dev/null +++ b/khdvk_450a/liteos_m/drivers/wdg/watchdog.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 WATCHDOG_H +#define WATCHDOG_H +#include "device_resource_if.h" +#include "hdf_device_desc.h" +#include "hdf_log.h" +#include "gpio_core.h" +#include "gd32f4xx_gpio.h" +#include "watchdog_if.h" +#include "watchdog_core.h" + +#define HDF_LOG_TAG GD450wdg + +#define BITS_PER_LONG 32 + +#define GENMASK(h, l) (((~0UL) << (l)) & (~0UL >> (BITS_PER_LONG - 1 - (h)))) + +/* IWDG registers */ +#define IWDG_KR 0x00 /* Key register */ +#define IWDG_PR 0x04 /* Prescaler Register */ +#define IWDG_RLR 0x08 /* ReLoad Register */ +#define IWDG_SR 0x0C /* Status Register */ +#define IWDG_WINR 0x10 /* Windows Register */ + +/* IWDG_KR register bit mask */ +#define KR_KEY_RELOAD 0xAAAA /* reload counter enable */ +#define KR_KEY_ENABLE 0xCCCC /* peripheral enable */ +#define KR_KEY_EWA 0x5555 /* write access enable */ +#define KR_KEY_DWA 0x0000 /* write access disable */ + +/* IWDG_PR register */ +#define PR_SHIFT 2 +#define PR_MIN BIT(PR_SHIFT) + +/* IWDG_RLR register values */ +#define RLR_MIN 0x2 /* min value recommended */ +#define RLR_MAX GENMASK(11, 0) /* max value of reload register */ + +/* IWDG_SR register bit mask */ +#define SR_PVU BIT(0) /* Watchdog prescaler value update */ +#define SR_RVU BIT(1) /* Watchdog counter reload value update */ + +/* set timeout to 100000 us */ +#define TIMEOUT_US 100000 +#define SLEEP_US 1000 + +#define DEFAULT_TIMEOUT (32) +#define DEFAULT_TASK_STACK_SIZE (0x800) +#define DEFAULT_CLOCK_RATE (32000) + +#define DIV_ROUND_UP(n, d) (((n) + (d)-1) / (d)) + +struct GD450wdg { + struct WatchdogCntlr wdt; // 控制器 + uint32_t num; // 当前独立看门狗编号 + void volatile *base; // 虚拟地址 + uint32_t phy_base; // 物理地址 + uint32_t reg_step; // 映射大小 + uint32_t seconds; // 当前设置的超时值(s) + bool start; // 当前iwdg是否已经启动 + uint32_t rate; // 时钟源频率 + char *clock_source; // 时钟源名称 + uint32_t min_timeout; // 最小超时时间 + uint32_t max_hw_heartbeat_ms; // 最大超时时间 +}; + +#endif \ No newline at end of file diff --git a/khdvk_450a/liteos_m/ethernet/BUILD.gn b/khdvk_450a/liteos_m/ethernet/BUILD.gn new file mode 100644 index 0000000..1a14b4b --- /dev/null +++ b/khdvk_450a/liteos_m/ethernet/BUILD.gn @@ -0,0 +1,31 @@ +# Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. +# Licensed 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. + +import("//kernel/liteos_m/liteos.gni") +import("$LITEOSTHIRDPARTY/lwip/lwip.gni") +import("$LITEOSTOPDIR/components/net/lwip-2.1/lwip_porting.gni") + +module_switch = defined(LOSCFG_NET_LWIP) +module_name = "lwip" +kernel_module(module_name) { + sources = LWIP_PORTING_FILES + LWIPNOAPPSFILES - [ "$LWIPDIR/api/sockets.c" ] + sources += [ + "src/ethernetif.c", + "src/gd32f4xx_enet_eval.c", + "src/lwip_adapter.c", + ] +} + +config("public") { + include_dirs = [ "include" ] + LWIP_PORTING_INCLUDE_DIRS + LWIP_INCLUDE_DIRS +} diff --git a/khdvk_450a/liteos_m/ethernet/include/ethernetif.h b/khdvk_450a/liteos_m/ethernet/include/ethernetif.h new file mode 100644 index 0000000..e17319c --- /dev/null +++ b/khdvk_450a/liteos_m/ethernet/include/ethernetif.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 ETHERNET_H_ +#define ETHERNET_H_ +#include +#include "gd32f4xx_enet.h" +#include "cmsis_os2.h" + +/* ENET RxDMA/TxDMA descriptor */ +extern enet_descriptors_struct rxdesc_tab[ENET_RXBUF_NUM], txdesc_tab[ENET_TXBUF_NUM]; + +/* ENET receive buffer */ +extern uint8_t rx_buff[ENET_RXBUF_NUM][ENET_RXBUF_SIZE]; + +/* ENET transmit buffer */ +extern uint8_t tx_buff[ENET_TXBUF_NUM][ENET_TXBUF_SIZE]; + +/* global transmit and receive descriptors pointers */ +extern enet_descriptors_struct *dma_current_txdesc; +extern enet_descriptors_struct *dma_current_rxdesc; +extern void ENET_IRQHandler_CB(void); +#endif \ No newline at end of file diff --git a/khdvk_450a/liteos_m/ethernet/include/gd32f4xx_enet_eval.h b/khdvk_450a/liteos_m/ethernet/include/gd32f4xx_enet_eval.h new file mode 100644 index 0000000..688d81e --- /dev/null +++ b/khdvk_450a/liteos_m/ethernet/include/gd32f4xx_enet_eval.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 GD32F4XX_ENET_EVAL_H +#define GD32F4XX_ENET_EVAL_H + +void lwip_stack_init(void); + +#endif \ No newline at end of file diff --git a/khdvk_450a/liteos_m/ethernet/include/lwip_adapter.h b/khdvk_450a/liteos_m/ethernet/include/lwip_adapter.h new file mode 100644 index 0000000..d0e2abd --- /dev/null +++ b/khdvk_450a/liteos_m/ethernet/include/lwip_adapter.h @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 LWIP_ADAPTER_H +#define LWIP_ADAPTER_H + +#include "gd32f4xx.h" +#include "stdint.h" + +void lwip_stack_init(void); +#define DHCP_TIMEOUT_S 30 +#define ETH_THREAD_PRIORITY 5 +#define ENET_TASK_STACK_SIZE 1024 +#define ENET_TASK_PRIORITY 30 +#define DHCP_TASK_STACK_SIZE 1024 +#define DHCP_TASK_PRIORITY 29 + +#define USE_ENET_INTERRUPT +#define MAC_ADDR0 2 +#define MAC_ADDR1 0xA +#define MAC_ADDR2 0xF +#define MAC_ADDR3 0xE +#define MAC_ADDR4 0xD +#define MAC_ADDR5 6 + +/* static IP address: IP_ADDR0.IP_ADDR1.IP_ADDR2.IP_ADDR3 */ +#define IP_ADDR0 192 +#define IP_ADDR1 168 +#define IP_ADDR2 100 +#define IP_ADDR3 2 + +/* remote IP address: IP_S_ADDR0.IP_S_ADDR1.IP_S_ADDR2.IP_S_ADDR3 */ +#define IP_S_ADDR0 192 +#define IP_S_ADDR1 168 +#define IP_S_ADDR2 100 +#define IP_S_ADDR3 3 + +/* net mask */ +#define NETMASK_ADDR0 255 +#define NETMASK_ADDR1 255 +#define NETMASK_ADDR2 255 +#define NETMASK_ADDR3 0 + +/* gateway address */ +#define GW_ADDR0 192 +#define GW_ADDR1 168 +#define GW_ADDR2 100 +#define GW_ADDR3 1 + +#define RMII_MODE // user have to provide the 50 MHz clock by soldering a 50 MHz oscillator + +/* clock the PHY from external 25MHz crystal (only for MII mode) */ +#ifdef MII_MODE +#define PHY_CLOCK_MCO +#endif + +typedef union { + UINT32 u32_addr; + UINT8 u8_addr[4]; +} IPUnion; + +typedef struct { + unsigned char useStaticIp; + IPUnion ipaddr; + IPUnion netmask; + IPUnion gw; + unsigned char useStaticMac; + unsigned char macAddr[6]; +} EthLinkInfo; + +typedef enum { + STATE_UPDATE_LINK_DOWN = 0, + STATE_UPDATE_LINK_UP = 1, +} EthLinkState; + +typedef void (*net_state_callBack)(EthLinkState state); + +#define PHY_STATUS_CALLBACK(func, val) \ + { \ + do { \ + if ((func) != NULL) { \ + (func)(val); \ + } \ + } while (0); \ + } + +extern void enet_gpio_config(void); + +#endif // end of #ifndef LWIP_ADAPTER_H \ No newline at end of file diff --git a/khdvk_450a/liteos_m/ethernet/include/lwipopts.h b/khdvk_450a/liteos_m/ethernet/include/lwipopts.h new file mode 100644 index 0000000..4dbb292 --- /dev/null +++ b/khdvk_450a/liteos_m/ethernet/include/lwipopts.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 GD_PORT_LWIPOPTS_H +#define GD_PORT_LWIPOPTS_H + +#include_next "lwip/lwipopts.h" + +#undef ETH_PAD_SIZE +#define ETH_PAD_SIZE 0 + +#define LWIP_SOCKET_SELECT_FUNC 1 + +// #ifdef LWIP_IPV6 +// #undef LWIP_IPV6 +// #endif +// #define LWIP_IPV6 1 + + +#endif /* GD_PORT_LWIPOPTS_H */ diff --git a/khdvk_450a/liteos_m/ethernet/src/ethernetif.c b/khdvk_450a/liteos_m/ethernet/src/ethernetif.c new file mode 100644 index 0000000..61d697c --- /dev/null +++ b/khdvk_450a/liteos_m/ethernet/src/ethernetif.c @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 "lwip/opt.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "lwip/timeouts.h" +#include "netif/etharp.h" +#include "lwip/err.h" +#include "lwip_adapter.h" +#include "gd32f4xx_enet.h" +#include "cmsis_os2.h" +#include "los_interrupt.h" +#include "ethernetif.h" + +#define ETHERNETIF_INPUT_TASK_STACK_SIZE (1024) +#define ETHERNETIF_INPUT_TASK_PRIO (5) +#define LOWLEVEL_OUTPUT_WAITING_TIME (250) +/* The time to block waiting for input */ +#define LOWLEVEL_INPUT_WAITING_TIME ((uint32_t)100) +#define ENET_MTU (1500) + +/* define those to better describe your network interface */ +#define IFNAME0 'G' +#define IFNAME1 'D' + +/* preserve another ENET RxDMA/TxDMA ptp descriptor for normal mode */ +enet_descriptors_struct ptp_txstructure[ENET_TXBUF_NUM]; +enet_descriptors_struct ptp_rxstructure[ENET_RXBUF_NUM]; + +void ethernetif_input(void *pvParameters); + +static struct netif *low_netif = NULL; +osSemaphoreId_t g_rx_semaphore = NULL; + +static void low_level_init(struct netif *netif) +{ + uint32_t i; + + /* set netif MAC hardware address length */ + netif->hwaddr_len = ETHARP_HWADDR_LEN; + + /* set netif MAC hardware address */ + int index = 0; + netif->hwaddr[index++] = MAC_ADDR0; + netif->hwaddr[index++] = MAC_ADDR1; + netif->hwaddr[index++] = MAC_ADDR2; + netif->hwaddr[index++] = MAC_ADDR3; + netif->hwaddr[index++] = MAC_ADDR4; + netif->hwaddr[index++] = MAC_ADDR5; + + /* set netif maximum transfer unit */ + netif->mtu = ENET_MTU; + + /* accept broadcast address and ARP traffic */ + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; + + low_netif = netif; + + /* create binary semaphore used for informing ethernetif of frame reception */ + if (g_rx_semaphore == NULL) { + g_rx_semaphore = osSemaphoreNew(1, 1, g_rx_semaphore); + osSemaphoreAcquire(g_rx_semaphore, 0); + } + + /* initialize MAC address in ethernet MAC */ + enet_mac_address_set(ENET_MAC_ADDRESS0, netif->hwaddr); + + /* initialize descriptors list: chain/ring mode */ +#ifdef SELECT_DESCRIPTORS_ENHANCED_MODE + enet_ptp_enhanced_descriptors_chain_init(ENET_DMA_TX); + enet_ptp_enhanced_descriptors_chain_init(ENET_DMA_RX); +#else + enet_descriptors_chain_init(ENET_DMA_TX); + enet_descriptors_chain_init(ENET_DMA_RX); +#endif + + for (i = 0; i < ENET_RXBUF_NUM; i++) { + enet_rx_desc_immediate_receive_complete_interrupt(&rxdesc_tab[i]); + } + +#ifdef CHECKSUM_BY_HARDWARE + /* enable the TCP, UDP and ICMP checksum insertion for the Tx frames */ + for (i = 0; i < ENET_TXBUF_NUM; i++) { + enet_transmit_checksum_config(&txdesc_tab[i], ENET_CHECKSUM_TCPUDPICMP_FULL); + } +#endif + + /* create the task that handles the ETH_MAC */ + osThreadAttr_t attr = {.name = "ETHERNETIF_INPUT", + .attr_bits = 0U, + .cb_mem = NULL, + .stack_mem = NULL, + .stack_size = ETHERNETIF_INPUT_TASK_STACK_SIZE, + .priority = ETHERNETIF_INPUT_TASK_PRIO}; + osThreadNew((osThreadFunc_t)ethernetif_input, (void *)netif, &attr); + + /* enable MAC and DMA transmission and reception */ + enet_enable(); +} + +static err_t low_level_output(struct netif *netif, struct pbuf *p) +{ + static osSemaphoreId_t s_tx_semaphore = NULL; + struct pbuf *q; + uint8_t *buffer; + uint16_t framelength = 0; + ErrStatus reval = ERROR; + + SYS_ARCH_DECL_PROTECT(sr); + + if (s_tx_semaphore == NULL) { + s_tx_semaphore = osSemaphoreNew(1, 1, NULL); + } + + if (osOK == osSemaphoreAcquire(s_tx_semaphore, LOWLEVEL_OUTPUT_WAITING_TIME)) { + sr = LOS_IntLock(); + while ((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_DAV)) { } + buffer = (uint8_t *)(enet_desc_information_get(dma_current_txdesc, TXDESC_BUFFER_1_ADDR)); + + for (q = p; q != NULL; q = q->next) { + memcpy_s((uint8_t *)&buffer[framelength], q->len, q->payload, q->len); + framelength = framelength + q->len; + } + + /* transmit descriptors to give to DMA */ +#ifdef SELECT_DESCRIPTORS_ENHANCED_MODE + reval = ENET_NOCOPY_PTPFRAME_TRANSMIT_ENHANCED_MODE(framelength, NULL); +#else + reval = ENET_NOCOPY_FRAME_TRANSMIT(framelength); +#endif + + LOS_IntRestore(sr); + + osSemaphoreRelease(s_tx_semaphore); + } + + if (SUCCESS == reval) { + return ERR_OK; + } else { + while (1) { } + } +} + +static struct pbuf *low_level_input(struct netif *netif) +{ + struct pbuf *p = NULL, *q; + uint32_t l = 0; + u16_t len; + uint8_t *buffer; + + /* obtain the size of the packet and put it into the "len" variable. */ + len = enet_desc_information_get(dma_current_rxdesc, RXDESC_FRAME_LENGTH); + buffer = (uint8_t *)(enet_desc_information_get(dma_current_rxdesc, RXDESC_BUFFER_1_ADDR)); + + if (len > 0) { + p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); + } + if (p != NULL) { + for (q = p; q != NULL; q = q->next) { + memcpy_s((uint8_t *)q->payload, q->len, (u8_t *)&buffer[l], q->len); + l = l + q->len; + } + } +#ifdef SELECT_DESCRIPTORS_ENHANCED_MODE + ENET_NOCOPY_PTPFRAME_RECEIVE_ENHANCED_MODE(NULL); +#else + ENET_NOCOPY_FRAME_RECEIVE(); +#endif + + return p; +} + +void ethernetif_input(void *pvParameters) +{ + struct pbuf *p; + SYS_ARCH_DECL_PROTECT(sr); + + for (;;) { + if (osOK != osSemaphoreAcquire(g_rx_semaphore, LOWLEVEL_INPUT_WAITING_TIME)) { + continue; + } + while (1) { + sr = LOS_IntLock(); + p = low_level_input(low_netif); + LOS_IntRestore(sr); + + if (p == NULL) { + break; + } + if (ERR_OK != low_netif->input(p, low_netif)) { + pbuf_free(p); + break; + } + } + } +} + +err_t ethernetif_init(struct netif *netif) +{ + LWIP_ASSERT("netif != NULL", (netif != NULL)); + + netif->name[0] = IFNAME0; + netif->name[1] = IFNAME1; + + netif->output = etharp_output; + netif->linkoutput = low_level_output; + + /* initialize the hardware */ + low_level_init(netif); + + return ERR_OK; +} + +void ENET_IRQHandler_CB(void) +{ + /* frame received */ + if (SET == enet_interrupt_flag_get(ENET_DMA_INT_FLAG_RS)) { + /* give the semaphore to wakeup LwIP task */ + osSemaphoreRelease(g_rx_semaphore); + } + enet_interrupt_flag_clear(ENET_DMA_INT_FLAG_RS_CLR); + enet_interrupt_flag_clear(ENET_DMA_INT_FLAG_NI_CLR); +} \ No newline at end of file diff --git a/khdvk_450a/liteos_m/ethernet/src/gd32f4xx_enet_eval.c b/khdvk_450a/liteos_m/ethernet/src/gd32f4xx_enet_eval.c new file mode 100644 index 0000000..f4429c1 --- /dev/null +++ b/khdvk_450a/liteos_m/ethernet/src/gd32f4xx_enet_eval.c @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 "los_config.h" +#include "gd32f4xx_enet.h" +#include "lwip_adapter.h" +#include "cmsis_os2.h" + +static __IO UINT32 enet_init_status = 0; + +void enet_gpio_config(void) +{ + rcu_periph_clock_enable(RCU_GPIOA); + rcu_periph_clock_enable(RCU_GPIOB); + rcu_periph_clock_enable(RCU_GPIOC); + rcu_periph_clock_enable(RCU_GPIOD); + rcu_periph_clock_enable(RCU_GPIOG); + rcu_periph_clock_enable(RCU_GPIOH); + rcu_periph_clock_enable(RCU_GPIOI); + + gpio_af_set(GPIOA, GPIO_AF_0, GPIO_PIN_8); + gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_8); + gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_8); + + /* enable SYSCFG clock */ + rcu_periph_clock_enable(RCU_SYSCFG); + +#ifdef RMII_MODE + syscfg_enet_phy_interface_config(SYSCFG_ENET_PHY_RMII); + + /* PA1: ETH_RMII_REF_CLK */ + gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_1); + gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_1); + + /* PA2: ETH_MDIO */ + gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_2); + gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_2); + + /* PA7: ETH_RMII_CRS_DV */ + gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_7); + gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_7); + + gpio_af_set(GPIOA, GPIO_AF_11, GPIO_PIN_1); + gpio_af_set(GPIOA, GPIO_AF_11, GPIO_PIN_2); + gpio_af_set(GPIOA, GPIO_AF_11, GPIO_PIN_7); + + /* PB11: ETH_RMII_TX_EN */ + gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_11); + gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_11); + + /* PB12: ETH_RMII_TXD0 */ + gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_12); + gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_12); + + /* PB13: ETH_RMII_TXD1 */ + gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_13); + gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_13); + + gpio_af_set(GPIOB, GPIO_AF_11, GPIO_PIN_11); + gpio_af_set(GPIOB, GPIO_AF_11, GPIO_PIN_12); + gpio_af_set(GPIOB, GPIO_AF_11, GPIO_PIN_13); + + /* PC1: ETH_MDC */ + gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_1); + gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_1); + + /* PC4: ETH_RMII_RXD0 */ + gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_4); + gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_4); + + /* PC5: ETH_RMII_RXD1 */ + gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_5); + gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_5); + + gpio_af_set(GPIOC, GPIO_AF_11, GPIO_PIN_1); + gpio_af_set(GPIOC, GPIO_AF_11, GPIO_PIN_4); + gpio_af_set(GPIOC, GPIO_AF_11, GPIO_PIN_5); +#endif +} diff --git a/khdvk_450a/liteos_m/ethernet/src/lwip_adapter.c b/khdvk_450a/liteos_m/ethernet/src/lwip_adapter.c new file mode 100644 index 0000000..fd23bef --- /dev/null +++ b/khdvk_450a/liteos_m/ethernet/src/lwip_adapter.c @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 "stdint.h" +#include "los_config.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/tcp.h" +#include "lwip/udp.h" +#include "netif/etharp.h" +#include "lwip/dhcp.h" +#include "lwip/tcpip.h" +#include "lwip/priv/tcp_priv.h" +#include "lwip/timeouts.h" +#include "lwip/netif.h" +#include "lwip/ip4_addr.h" +#include "lwip/sockets.h" +#include "gd32f4xx.h" +#include "gd32f4xx_enet_eval.h" +#include "gd32f4xx_enet.h" +#include "cmsis_os2.h" +#include "los_interrupt.h" +#include "ethernetif.h" +#include "lwip_adapter.h" + +err_t ethernetif_init(struct netif *netif); +#define MAX_DHCP_TRIES 4 +#define DELAY250_MS 250 +#define DELAY1000_MS 1000 +#define IRQ_PRIORITY 2 +#define CREATE_IRQ_MODE 5 +static EthLinkInfo gEthLinkInfo = {.useStaticIp = 1, .useStaticMac = 1}; + +typedef enum { DHCP_START = 0, DHCP_WAIT_ADDRESS, DHCP_ADDRESS_ASSIGNED, DHCP_TIMEOUT } dhcp_state_enum; + +#ifdef USE_DHCP +dhcp_state_enum dhcp_state = DHCP_START; +#endif + +struct netif g_mynetif; +unsigned int tcp_timer = 0; +unsigned int arp_timer = 0; +ip_addr_t ip_address = {0}; + +void lwip_dhcp_process_handle(void); + +void lwip_stack_init(void) +{ + ip_addr_t ipaddr; + ip_addr_t netmask; + ip_addr_t gw; + + tcpip_init(NULL, NULL); + +#ifdef TIMEOUT_CHECK_USE_LWIP + sys_timeouts_init(); +#endif + +#ifdef USE_DHCP + ipaddr.addr = 0; + netmask.addr = 0; + gw.addr = 0; +#else + IP_ADDR4(&ipaddr, IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3); + IP_ADDR4(&netmask, NETMASK_ADDR0, NETMASK_ADDR1, NETMASK_ADDR2, NETMASK_ADDR3); + IP_ADDR4(&gw, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3); + +#endif /* USE_DHCP */ + + netif_add(&g_mynetif, &ipaddr, &netmask, &gw, NULL, ðernetif_init, &tcpip_input); + /* registers the default network interface */ + netif_set_default(&g_mynetif); + + /* when the netif is fully configured this function must be called */ + netif_set_up(&g_mynetif); +} + +#ifdef USE_DHCP +void dhcp_task(void *pvParameters) +{ + ip_addr_t ipaddr; + ip_addr_t netmask; + ip_addr_t gw; + struct dhcp *dhcp_client; + + for (;;) { + switch (dhcp_state) { + case DHCP_START: + dhcp_start(&g_mynetif); + /* IP address should be set to 0 every time we want to assign a new DHCP address */ + dhcp_state = DHCP_WAIT_ADDRESS; + printf("dhcp start\n"); + break; + + case DHCP_WAIT_ADDRESS: + /* read the new IP address */ + ip_address.addr = g_mynetif.ip_addr.addr; + printf("dhcp wait addr\n"); + if (ip_address.addr != 0) { + dhcp_state = DHCP_ADDRESS_ASSIGNED; + printf("\r\nDHCP -- eval board ip address: %d.%d.%d.%d \r\n", ip4_addr1_16(&ip_address), + ip4_addr2_16(&ip_address), ip4_addr3_16(&ip_address), ip4_addr4_16(&ip_address)); + } else { + /* DHCP timeout */ + dhcp_client = netif_dhcp_data(&g_mynetif); + if (dhcp_client->tries > MAX_DHCP_TRIES) { + dhcp_state = DHCP_TIMEOUT; + /* stop DHCP */ + dhcp_stop(&g_mynetif); + printf("dhcp set static addr\n"); + /* static address used */ + IP4_ADDR(&ipaddr, IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3); + IP4_ADDR(&netmask, NETMASK_ADDR0, NETMASK_ADDR1, NETMASK_ADDR2, NETMASK_ADDR3); + IP4_ADDR(&gw, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3); + netif_set_addr(&g_mynetif, &ipaddr, &netmask, &gw); + } + } + break; + + default: + break; + } + osDelay(DELAY250_MS); + } +} +#endif + +#ifdef USE_ENET_INTERRUPT +static void nvic_configuration(void) +{ + nvic_irq_enable(ENET_IRQn, IRQ_PRIORITY, 0); +} +#endif + +static __IO UINT32 enet_init_status = 0; + +void enet_taskEntery(void *param) +{ + ErrStatus reval_state = ERROR; + +#ifdef USE_ENET_INTERRUPT + nvic_configuration(); +#endif /* USE_ENET_INTERRUPT */ + + /* configure the GPIO ports for ethernet pins */ + enet_gpio_config(); + + /* enable ethernet clock */ + rcu_periph_clock_enable(RCU_ENET); + rcu_periph_clock_enable(RCU_ENETTX); + rcu_periph_clock_enable(RCU_ENETRX); + + /* reset ethernet on AHB bus */ + enet_deinit(); + reval_state = enet_software_reset(); + while (ERROR == reval_state) { + printf("enet reset \n"); + osDelay(DELAY1000_MS); + } + +#ifdef USE_ENET_INTERRUPT + enet_interrupt_enable(ENET_DMA_INT_NIE); + enet_interrupt_enable(ENET_DMA_INT_RIE); +#endif /* USE_ENET_INTERRUPT */ + + lwip_stack_init(); + LOS_HwiCreate(ENET_IRQn, 0, CREATE_IRQ_MODE, (HWI_PROC_FUNC)ENET_IRQHandler_CB, 0); + + net_state_callBack callback = (net_state_callBack)param; + uint16_t phy_value; + uint16_t status = 0; + while (1) { + enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BSR, &phy_value); + if (status == (phy_value & PHY_LINKED_STATUS)) { + osDelay(DELAY1000_MS); + continue; + } + status = phy_value & PHY_LINKED_STATUS; + if (status != RESET) { /* link status changes from down to up */ + if (enet_init_status == 0) { /* init phy once */ +#ifdef CHECKSUM_BY_HARDWARE + enet_init_status = + enet_init(ENET_AUTO_NEGOTIATION, ENET_AUTOCHECKSUM_DROP_FAILFRAMES, ENET_BROADCAST_FRAMES_PASS); +#else + enet_init_status = + enet_init(ENET_AUTO_NEGOTIATION, ENET_NO_AUTOCHECKSUM, ENET_BROADCAST_FRAMES_PASS); +#endif + } + PHY_STATUS_CALLBACK(callback, STATE_UPDATE_LINK_DOWN); + } else { + /* link status changes from up to down */ + PHY_STATUS_CALLBACK(callback, STATE_UPDATE_LINK_UP); + } + osDelay(DELAY1000_MS); + } +} + +void enet_adapter_init(net_state_callBack callBack) +{ + osThreadAttr_t attr = {.name = "net_init", + .attr_bits = 0U, + .cb_mem = NULL, + .stack_mem = NULL, + .stack_size = ENET_TASK_STACK_SIZE, + .priority = ENET_TASK_PRIORITY}; + if (osThreadNew((osThreadFunc_t)enet_taskEntery, (void *)callBack, &attr) == NULL) { + printf("Create net task failed! \n"); + } + +#ifdef USE_DHCP + /* start DHCP client */ + osThreadAttr_t attr1 = { + .name = "DHCP", .attr_bits = 0U, .cb_mem = NULL, .stack_mem = NULL, .stack_size = 1024, .priority = 29}; + if (osThreadNew((osThreadFunc_t)dhcp_task, NULL, &attr1) == NULL) { + printf("Create DHCP task failed! \n"); + } +#endif +} diff --git a/khdvk_450a/liteos_m/hdf_config/BUILD.gn b/khdvk_450a/liteos_m/hdf_config/BUILD.gn new file mode 100644 index 0000000..0bb0cbc --- /dev/null +++ b/khdvk_450a/liteos_m/hdf_config/BUILD.gn @@ -0,0 +1,27 @@ +# Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. +# Licensed 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. + +if (ohos_kernel_type == "liteos_m") { + import("//drivers/hdf_core/adapter/khdf/liteos_m/hdf.gni") + + macro_switch = defined(LOSCFG_DRIVERS_HDF_CONFIG_MACRO) + module_name = get_path_info(rebase_path("."), "name") + config("public") { + include_dirs = [ "$target_gen_dir" ] + } + hdf_driver(module_name) { + hcs_sources = [ "hdf.hcs" ] + special_visibility = + [ "//device/board/kaihong/khdvk_450a/liteos_m/drivers/*" ] + } +} diff --git a/khdvk_450a/liteos_m/hdf_config/adc/adc_config.hcs b/khdvk_450a/liteos_m/hdf_config/adc/adc_config.hcs new file mode 100644 index 0000000..e21118b --- /dev/null +++ b/khdvk_450a/liteos_m/hdf_config/adc/adc_config.hcs @@ -0,0 +1,13 @@ +root { + platform { + adc_config{ + adc_0 { + deviceNum = 2; // 设备号 + channelNums = 1; // 有效通道数量 + validChannels = [4]; // 有效通道号,[4,7]代表4通道和7通道 + outputPinNums = [86]; // 有效通道对应gpio号 + match_attr = "GD_ADC_MODULE_HDF_CONFIG_0"; + } + } + } +} \ No newline at end of file diff --git a/khdvk_450a/liteos_m/hdf_config/dac/dac_config.hcs b/khdvk_450a/liteos_m/hdf_config/dac/dac_config.hcs new file mode 100644 index 0000000..b0bb2e5 --- /dev/null +++ b/khdvk_450a/liteos_m/hdf_config/dac/dac_config.hcs @@ -0,0 +1,18 @@ +root { + platform { + dac_config { + match_attr = "GD_DAC_MODULE_HDF_CONFIG"; + template dac_device { + deviceNum = 0; + validChannel = 0x1; + rate = 20000; + } + device_0 :: dac_device { + deviceNum = 0; + validChannel = 0x0; + outputPinNum = 4; + alignment = 0; + } + } + } +} diff --git a/khdvk_450a/liteos_m/hdf_config/device_info/device_info.hcs b/khdvk_450a/liteos_m/hdf_config/device_info/device_info.hcs new file mode 100755 index 0000000..abfdb52 --- /dev/null +++ b/khdvk_450a/liteos_m/hdf_config/device_info/device_info.hcs @@ -0,0 +1,122 @@ +root { + device_info { + match_attr = "hdf_manager"; + template host { + hostName = ""; + priority = 100; + template device { + template deviceNode { + policy = 0; + priority = 100; + preload = 0; + permission = 0664; + moduleName = ""; + serviceName = ""; + deviceMatchAttr = ""; + } + } + } + platform :: host { + hostName = "platform_host"; + priority = 50; + device_i2c :: device { + i2c_manager :: deviceNode { + policy = 2; + priority = 50; + moduleName = "HDF_PLATFORM_I2C_MANAGER"; + serviceName = "HDF_PLATFORM_I2C_MANAGER"; + } + i2c0 :: deviceNode { + policy = 0; + priority = 100; + moduleName = "GD_I2C_MODULE_HDF"; + serviceName = ""; + deviceMatchAttr = "i2c0_config"; + } + } + device_pwm1 :: device { + pwm1 :: deviceNode { // pwm config + policy = 1; + priority = 100; + moduleName = "GD_PWM_MODULE_HDF"; + serviceName = "HDF_PLATFORM_PWM_1"; + deviceMatchAttr = "pwm1_config"; + } + } + device_spi :: device { + device0 :: deviceNode { + policy = 2; + priority = 100; + preload = 1; + permission = 0664; + moduleName = "GD_SPI_MODULE_HDF"; + serviceName = "HDF_PLATFORM_SPI_5"; + deviceMatchAttr = "spi0_config"; + } + } + device_gpio :: device { + device0 :: deviceNode { + policy = 0; + priority = 10; + permission = 0644; + moduleName = "GD_GPIO_MODULE_HDF"; + deviceMatchAttr = "GD_GPIO_MODULE_HDF_CONFIG"; + } + } + device_lcd :: device { + lcd0 :: deviceNode { + policy = 0; + priority = 10; + permission = 0644; + moduleName = "GD_LCD_MODULE_HDF"; + deviceMatchAttr = "GD_LCD_MODULE_HDF_CONFIG"; + } + } + device_uart0 :: device { + uart0 :: deviceNode { + policy = 1; + priority = 40; + preload = 1; + permission = 0664; + moduleName = "GD_UART_MODULE_HDF"; + serviceName = "HDF_PLATFORM_UART_0"; + deviceMatchAttr = "uart0_config"; + } + } + device_adc :: device { + adc_manager :: deviceNode { + policy = 0; + priority = 50; + permission = 0644; + moduleName = "HDF_PLATFORM_ADC_MANAGER"; + serviceName = "HDF_PLATFORM_ADC_MANAGER"; + } + device0 :: deviceNode { + policy = 0; + priority = 150; + permission = 0644; + moduleName = "GD_ADC_MODULE_HDF"; + serviceName = ""; + deviceMatchAttr = "GD_ADC_MODULE_HDF_CONFIG_0"; + } + } + device_dac :: device { + device0 :: deviceNode { + policy = 0; + priority = 52; + permission = 0644; + serviceName = "HDF_PLATFORM_DAC_MANAGER"; + moduleName = "HDF_PLATFORM_DAC_MANAGER"; + } + dac_virtual :: deviceNode { + policy = 0; + priority = 56; + permission = 0644; + moduleName = "GD_DAC_MODULE_HDF"; + serviceName = "VIRTUAL_DAC_DRIVER"; + deviceMatchAttr = "GD_DAC_MODULE_HDF_CONFIG"; + } + } + } + } +} diff --git a/khdvk_450a/liteos_m/hdf_config/gpio/gpio_config.hcs b/khdvk_450a/liteos_m/hdf_config/gpio/gpio_config.hcs new file mode 100644 index 0000000..d6ef126 --- /dev/null +++ b/khdvk_450a/liteos_m/hdf_config/gpio/gpio_config.hcs @@ -0,0 +1,11 @@ +root { + platform { + gpio_config { + gpio_config1 { + match_attr = "GD_GPIO_MODULE_HDF_CONFIG"; + start = 0; + count = 140; + } + } + } +} \ No newline at end of file diff --git a/khdvk_450a/liteos_m/hdf_config/hdf.hcs b/khdvk_450a/liteos_m/hdf_config/hdf.hcs new file mode 100644 index 0000000..c0879aa --- /dev/null +++ b/khdvk_450a/liteos_m/hdf_config/hdf.hcs @@ -0,0 +1,13 @@ +#include "device_info/device_info.hcs" +#include "i2c/i2c_config.hcs" +#include "spi/spi_config.hcs" +#include "dac/dac_config.hcs" +#include "uart/uart_config.hcs" +#include "gpio/gpio_config.hcs" +#include "lcd/lcd_config.hcs" +#include "pwm/pwm_config.hcs" +#include "adc/adc_config.hcs" + +root { + module = "gd,gd32f450"; +} \ No newline at end of file diff --git a/khdvk_450a/liteos_m/hdf_config/i2c/i2c_config.hcs b/khdvk_450a/liteos_m/hdf_config/i2c/i2c_config.hcs new file mode 100644 index 0000000..d2186d7 --- /dev/null +++ b/khdvk_450a/liteos_m/hdf_config/i2c/i2c_config.hcs @@ -0,0 +1,17 @@ +root { + platform { + i2c_config { + i2c0 { + match_attr = "i2c0_config"; + //support: 0 1 2 + bus = 0; + //baud: 100,400,3500 K + speed = 100000; + // SCL/SDA - I2C0 = PB6/PB7 + // GPIO PORT: 0~140 + scl = 22; + sda = 23; + } + } + } +} \ No newline at end of file diff --git a/khdvk_450a/liteos_m/hdf_config/lcd/lcd_config.hcs b/khdvk_450a/liteos_m/hdf_config/lcd/lcd_config.hcs new file mode 100644 index 0000000..455b5b6 --- /dev/null +++ b/khdvk_450a/liteos_m/hdf_config/lcd/lcd_config.hcs @@ -0,0 +1,10 @@ +root { + platform { + lcd_config { + lcd_config1 { + match_attr = "GD_LCD_MODULE_HDF_CONFIG"; + lcd_version = "V1.4"; + } + } + } +} \ No newline at end of file diff --git a/khdvk_450a/liteos_m/hdf_config/pwm/pwm_config.hcs b/khdvk_450a/liteos_m/hdf_config/pwm/pwm_config.hcs new file mode 100644 index 0000000..a4161c1 --- /dev/null +++ b/khdvk_450a/liteos_m/hdf_config/pwm/pwm_config.hcs @@ -0,0 +1,15 @@ +root { + platform { + pwm_config { + pwm1_config { + match_attr = "pwm1_config"; // default use pwm1 + pwm_ch = 0x0002; // timer chanel: ch0 ch1 ch2 ch3 + pwm_id = 0x0001; + // channel 2's gpio: PB10 + // GPIO PORT: A~I=0~8 + ch_gpio = [1, 10]; + timer_id = 1; // timer 1 + } + } + } +} \ No newline at end of file diff --git a/khdvk_450a/liteos_m/hdf_config/spi/spi_config.hcs b/khdvk_450a/liteos_m/hdf_config/spi/spi_config.hcs new file mode 100644 index 0000000..5cb4902 --- /dev/null +++ b/khdvk_450a/liteos_m/hdf_config/spi/spi_config.hcs @@ -0,0 +1,21 @@ +root { + platform { + spi_config { + spi_config1 { + match_attr = "spi0_config"; + num = 5; + speed = 815200; + dataSize = 8; + transMode = 0; + mode = 12; + csSoft = 0; + clkPin = 109; + mosiPin = 110; + misoPin = 108; + csPin = 105; + afPin = 5; + enableQuad = 1; + } + } + } +} \ No newline at end of file diff --git a/khdvk_450a/liteos_m/hdf_config/uart/uart_config.hcs b/khdvk_450a/liteos_m/hdf_config/uart/uart_config.hcs new file mode 100644 index 0000000..f8cfe64 --- /dev/null +++ b/khdvk_450a/liteos_m/hdf_config/uart/uart_config.hcs @@ -0,0 +1,17 @@ +root { + platform { + controller_0x40011000 { + uart0_config { + match_attr = "uart0_config"; + num = 0; + baudrate = 115200; + mode = 0; + interrupt = 37; + fifo_size = 256; + af = 7; + tx_pin = 9; + rx_pin = 10; + } + } + } +} \ No newline at end of file diff --git a/khdvk_450a/liteos_m/key_input/BUILD.gn b/khdvk_450a/liteos_m/key_input/BUILD.gn new file mode 100644 index 0000000..adf45a5 --- /dev/null +++ b/khdvk_450a/liteos_m/key_input/BUILD.gn @@ -0,0 +1,23 @@ +# Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. +# Licensed 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. + +import("//kernel/liteos_m/liteos.gni") + +module_name = "bsp" +kernel_module(module_name) { + sources = [] + if (defined(LOSCFG_DRIVERS_USER_KEY_INPUT)) { + sources += [ "key_input_gd32f450.c" ] + } + include_dirs = [ "." ] +} diff --git a/khdvk_450a/liteos_m/key_input/key_input_gd32f450.c b/khdvk_450a/liteos_m/key_input/key_input_gd32f450.c new file mode 100644 index 0000000..8f4be84 --- /dev/null +++ b/khdvk_450a/liteos_m/key_input/key_input_gd32f450.c @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 "cmsis_os2.h" +#include "los_compiler.h" +#include "osal_mem.h" +#include "gpio_if.h" +#include "key_input_gd32f450.h" + +#define WAKEUP_KEY_GPIO_NUM 0 // PA0 +#define TAMPER_KEY_GPIO_NUM 45 // PC13 +#define USER_KEY_GPIO_NUM 30 // PB14 +#define DELAY_10_MS 10 +#define DELAY_20_MS 20 +#define KEY_INDEX_0 0 +#define KEY_INDEX_1 1 +#define KEY_INDEX_2 2 +#define STACK_SIZE 0x1000 +#define INPUT_TASK_PRIORITY 29 + +static AllKeyCond *g_allKeyCond; +static UINT32 g_allKeyGpioNum[MAX_KEY_NUM]; + +static void Gd32f450GetKeyInputDeviceResource(void) +{ + g_allKeyGpioNum[KEY_INDEX_0] = WAKEUP_KEY_GPIO_NUM; + + g_allKeyGpioNum[KEY_INDEX_1] = TAMPER_KEY_GPIO_NUM; + + g_allKeyGpioNum[KEY_INDEX_2] = USER_KEY_GPIO_NUM; +} + +static void GpioPinScan(int32_t key) +{ + uint16_t ret = 0; + int isPressed = 0; + GpioRead(g_allKeyGpioNum[key], &ret); + if (ret == 0) { + osDelay(DELAY_10_MS); + GpioRead(g_allKeyGpioNum[key], &ret); + } + if (ret) { + isPressed = 0; + } else { + isPressed = 1; + } + g_allKeyCond->isPressed[key] = isPressed; +} + +static void KeyInputScanCallback(void) +{ + while (1) { + for (int32_t i = 0; i < MAX_KEY_NUM; i++) { + GpioPinScan(i); + } + osDelay(DELAY_20_MS); + } +} + +static void Gd32f450KeyInputTaskCreate(void) +{ + osThreadId_t threadId = NULL; + osThreadAttr_t attr = {0}; + memset_s(&attr, sizeof(osThreadAttr_t), 0, sizeof(osThreadAttr_t)); + attr.name = "KeyInputScanCallback"; + attr.stack_size = STACK_SIZE; + attr.priority = (INPUT_TASK_PRIORITY); + threadId = osThreadNew(KeyInputScanCallback, NULL, &attr); + if (threadId == NULL) { + printf("KeyInputScanCallback task create failed.\n"); + return -1; + } +} + +int32_t Gd32f450KeyInputInit() +{ + if (g_allKeyCond != NULL) { + printf("%s: Malloc g_allKeyCond fail!\r\n", __func__); + return HDF_FAILURE; + } + int ret = 0; + printf("enter in %s:%s %d\r\n", __FILE__, __FUNCTION__, __LINE__); + g_allKeyCond = (AllKeyCond *)OsalMemCalloc(sizeof(*g_allKeyCond)); + if (g_allKeyCond == NULL) { + printf("%s: Malloc g_allKeyCond fail!\r\n", __func__); + return HDF_ERR_MALLOC_FAIL; + } + memset_s(g_allKeyCond, sizeof(*g_allKeyCond), 0, sizeof(*g_allKeyCond)); + Gd32f450GetKeyInputDeviceResource(); + + for (int32_t i = 0; i < MAX_KEY_NUM; i++) { + ret = GpioSetDir(g_allKeyGpioNum[i], GPIO_DIR_IN); + if (ret != 0) { + printf("GpioSetDir: failed, ret %d\n", ret); + OsalMemFree(g_allKeyCond); + g_allKeyCond = NULL; + return HDF_FAILURE; + } + } + + g_allKeyCond->keyType[KEY_INDEX_0] = KEY_WAKEUP; + g_allKeyCond->keyType[KEY_INDEX_1] = KEY_TAMPER; + g_allKeyCond->keyType[KEY_INDEX_2] = KEY_USER; + + Gd32f450KeyInputTaskCreate(); + + return HDF_SUCCESS; +} + +int32_t Gd32f450KeyInputRelease() +{ + printf("enter in %s:%s %d\r\n", __FILE__, __FUNCTION__, __LINE__); + OsalMemFree(g_allKeyCond); + g_allKeyCond = NULL; + return HDF_SUCCESS; +} + +AllKeyCond *Gd32f450ALLKeyInputRead(void) +{ + return g_allKeyCond; +} + +int Gd32f450SingleKeyInputRead(KEY_TYPE keyId) +{ + return g_allKeyCond->isPressed[keyId]; +} diff --git a/khdvk_450a/liteos_m/key_input/key_input_gd32f450.h b/khdvk_450a/liteos_m/key_input/key_input_gd32f450.h new file mode 100644 index 0000000..5bbccbd --- /dev/null +++ b/khdvk_450a/liteos_m/key_input/key_input_gd32f450.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 GD32F4XX_KEY_INPUT_H_ +#define GD32F4XX_KEY_INPUT_H_ +#ifdef __cplusplus +extern "C" { +#endif + +#define MAX_KEY_NUM (KEY_LIMIT + 1) +typedef enum { + KEY_WAKEUP = 0, + KEY_TAMPER, + KEY_USER, + KEY_LIMIT = KEY_USER, +} KEY_TYPE; + +typedef struct { + KEY_TYPE keyType[MAX_KEY_NUM]; + int isPressed[MAX_KEY_NUM]; +} AllKeyCond; + +extern int32_t Gd32f450KeyInputInit(void); +extern int32_t Gd32f450KeyInputRelease(void); +extern AllKeyCond *Gd32f450ALLKeyInputRead(void); +extern int Gd32f450SingleKeyInputRead(KEY_TYPE keyId); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/khdvk_450a/liteos_m/logo/BUILD.gn b/khdvk_450a/liteos_m/logo/BUILD.gn new file mode 100755 index 0000000..e381cf4 --- /dev/null +++ b/khdvk_450a/liteos_m/logo/BUILD.gn @@ -0,0 +1,23 @@ +# Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. +# Licensed 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. + +import("//drivers/hdf_core/adapter/khdf/liteos_m/hdf.gni") + +hdf_driver("logo") { + sources = [ "logo_src/logo_src.c" ] + include_dirs = [ + "logo_src/", + "//third_party/cmsis/CMSIS/RTOS2/Include", + "//third_party/giflib/", + ] +} diff --git a/khdvk_450a/liteos_m/logo/logo_src/logo_interface.h b/khdvk_450a/liteos_m/logo/logo_src/logo_interface.h new file mode 100644 index 0000000..db64f34 --- /dev/null +++ b/khdvk_450a/liteos_m/logo/logo_src/logo_interface.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 LOGO_INTERFACE_H +#define LOGO_INTERFACE_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern int GifLoad(const char *src); +extern int GetGifImgCnt(void); +extern uint8_t *GetGifData(uint8_t imageIndex); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/khdvk_450a/liteos_m/logo/logo_src/logo_src.c b/khdvk_450a/liteos_m/logo/logo_src/logo_src.c new file mode 100644 index 0000000..cdd4673 --- /dev/null +++ b/khdvk_450a/liteos_m/logo/logo_src/logo_src.c @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 "gif_lib.h" +#define ARGB_SKIP_INDEX (4) +#define OPA_OPAQUE (255) + +static uint8_t *gifImageData = NULL; +static uint8_t imageIndex = 0; +static uint32_t gifDataSize = 0; +static GifFileType *gifFileType = NULL; + +static void DealGifImageData(GifFileType *gifFileType, GifImageDesc *gifImageDesc, + + SavedImage *savedImage, GraphicsControlBlock gcb, ColorMapObject *colorMap) +{ + uint8_t colorIndex = 0; + GifColorType *gifColorType = NULL; + uint32_t index = 0; + bool transparentColor = true; + int32_t loc = 0; + for (int32_t x = 0; x < gifFileType->SHeight; x++) { + for (int32_t y = 0; y < gifFileType->SWidth; y++) { + transparentColor = true; + if ((x >= gifImageDesc->Top) && (x < gifImageDesc->Top + gifImageDesc->Height) && + (y >= gifImageDesc->Left) && (y < gifImageDesc->Left + gifImageDesc->Width)) { + loc = (x - gifImageDesc->Top) * gifImageDesc->Width + (y - gifImageDesc->Left); + colorIndex = savedImage->RasterBits[loc]; + + if ((gcb.DisposalMode != DISPOSE_DO_NOT) || (gcb.TransparentColor == NO_TRANSPARENT_COLOR) || + (colorIndex != gcb.TransparentColor)) { + transparentColor = false; + } + } + if (transparentColor) { + index += ARGB_SKIP_INDEX; + } else { + gifColorType = &colorMap->Colors[colorIndex]; + gifImageData[index++] = gifColorType->Blue; + gifImageData[index++] = gifColorType->Green; + gifImageData[index++] = gifColorType->Red; + gifImageData[index++] = OPA_OPAQUE; + } + } + } +} + +static void SetGifFrame(GifFileType *gifFileType, int32_t imageIndex) +{ + SavedImage *savedImage = &(gifFileType->SavedImages[imageIndex]); + + GifImageDesc *gifImageDesc = &(savedImage->ImageDesc); + + GraphicsControlBlock gcb; + DGifSavedExtensionToGCB(gifFileType, imageIndex, &gcb); + + ColorMapObject *colorMap = NULL; + if (gifImageDesc->ColorMap != NULL) { + colorMap = gifImageDesc->ColorMap; + } else { + colorMap = gifFileType->SColorMap; + } + + DealGifImageData(gifFileType, gifImageDesc, savedImage, gcb, colorMap); +} + +int GetGifImgCnt(void) +{ + return gifFileType->ImageCount; +} + +uint8_t *GetGifData(uint8_t imageIndex) +{ + SetGifFrame(gifFileType, imageIndex); + return gifImageData; +} + +int GifLoad(const char *src) +{ + int error = D_GIF_SUCCEEDED; + gifFileType = DGifOpenFileName(src, &error); + if (gifFileType == NULL) { + return GIF_ERROR; + } + if (error != D_GIF_SUCCEEDED) { + return GIF_ERROR; + } + if (GIF_ERROR == DGifSlurp(gifFileType)) { + return GIF_ERROR; + } + gifDataSize = gifFileType->SWidth * gifFileType->SHeight * ARGB_SKIP_INDEX; + + gifImageData = (uint8_t *)malloc(gifDataSize); + if (gifImageData == NULL) { + DGifCloseFile(gifFileType, NULL); + } + return GIF_OK; +} \ No newline at end of file diff --git a/khdvk_450a/liteos_m/ui/BUILD.gn b/khdvk_450a/liteos_m/ui/BUILD.gn new file mode 100644 index 0000000..f1d9645 --- /dev/null +++ b/khdvk_450a/liteos_m/ui/BUILD.gn @@ -0,0 +1,50 @@ +# Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. +# Licensed 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. + +declare_args() { + kh_ace_enable = false +} + +import("//drivers/hdf_core/adapter/khdf/liteos_m/hdf.gni") + +config("public") { + include_dirs = [ "." ] +} + +hdf_driver("ui_adapter") { + sources = [ + "display_device.cpp", + "fbdev.cpp", + "ui_main.cpp", + ] + + if (defined(LOSCFG_DRIVERS_USER_KEY_INPUT)) { + sources += [ "key_input.cpp" ] + } + + public_configs = [ ":public" ] + public_deps = [ "//foundation/graphic/ui:ui" ] + if (kh_ace_enable) { + defines = [ "ENABLE_ACE" ] + public_deps += [ "//foundation/arkui/ace_engine_lite/frameworks:ace_lite" ] + } + + include_dirs = [ + "//drivers/peripheral/display/interfaces/include", + "//drivers/peripheral/base", + "//foundation/graphic/ui/frameworks", + "//third_party/freetype/include", + "//device/board/kaihong/khdvk_450a/liteos_m/key_input", + "//device/board/kaihong/khdvk_450a/liteos_m/ui", + ] +} diff --git a/khdvk_450a/liteos_m/ui/display_device.cpp b/khdvk_450a/liteos_m/ui/display_device.cpp new file mode 100644 index 0000000..2973621 --- /dev/null +++ b/khdvk_450a/liteos_m/ui/display_device.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 "display_device.h" +#include "components/root_view.h" +#include "draw/draw_utils.h" +#include "fbdev.h" + +namespace OHOS { + DisplayDevice *DisplayDevice::GetInstance() + { + static DisplayDevice instance; + if (!instance.isRegister_) { + FbdevInit(); + instance.isRegister_ = true; + instance.SetScreenShape(CIRCLE); + } + return &instance; + } + + BufferInfo *DisplayDevice::GetFBBufferInfo() + { + static BufferInfo bufferInfo; + LiteSurfaceData *surfaceData = GetDevSurfaceData(); + bufferInfo.rect = {0, 0, HORIZONTAL_RESOLUTION - 1, VERTICAL_RESOLUTION - 1}; + bufferInfo.mode = RGB565; + bufferInfo.color = 0x44; + bufferInfo.phyAddr = surfaceData->phyAddr; + bufferInfo.virAddr = surfaceData->virAddr; + // 3: Shift right 3 bits + bufferInfo.stride = HORIZONTAL_RESOLUTION * (DrawUtils::GetPxSizeByColorMode(bufferInfo.mode) >> 3); + bufferInfo.width = HORIZONTAL_RESOLUTION; + bufferInfo.height = VERTICAL_RESOLUTION; + this->fbAddr = surfaceData->phyAddr; + return &bufferInfo; + } + + void DisplayDevice::UpdateFBBuffer() + { + BufferInfo *bufferInfo = DisplayDevice::GetInstance()->GetFBBufferInfo(); + if (this->fbAddr != bufferInfo->phyAddr) { + this->fbAddr = bufferInfo->phyAddr; + RootView::GetInstance()->UpdateBufferInfo(bufferInfo); + // Get the newest fbAddr, ensure that the buffer is available before TaskHandler() + } + } + + void DisplayDevice::Flush(const Rect &flushRect) + { + FbdevFlush(); + } +} // namespace OHOS diff --git a/khdvk_450a/liteos_m/ui/display_device.h b/khdvk_450a/liteos_m/ui/display_device.h new file mode 100644 index 0000000..7eb40d8 --- /dev/null +++ b/khdvk_450a/liteos_m/ui/display_device.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 DISPLAY_DEVICE_H +#define DISPLAY_DEVICE_H + +#include "engines/gfx/soft_engine.h" + +namespace OHOS { + class DisplayDevice : public SoftEngine { + public: + DisplayDevice() + { + } + virtual ~DisplayDevice() + { + } + static DisplayDevice *GetInstance(); + + void Flush(const Rect &flushRect); + BufferInfo *GetFBBufferInfo() override; + void UpdateFBBuffer(); + + private: + bool isRegister_ = false; + void *fbAddr = nullptr; + }; +} // namespace OHOS + +#endif // DISPLAY_DEVICE_H diff --git a/khdvk_450a/liteos_m/ui/fbdev.cpp b/khdvk_450a/liteos_m/ui/fbdev.cpp new file mode 100644 index 0000000..632dd46 --- /dev/null +++ b/khdvk_450a/liteos_m/ui/fbdev.cpp @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 "fbdev.h" +#include "display_layer.h" +#include "display_type.h" +#include "gfx_utils/color.h" +#include "gfx_utils/graphic_log.h" +#include "graphic_config.h" +namespace OHOS { + struct DisplayDesc { + LayerFuncs *layerFuncs; + uint32_t devId; + uint32_t layerId; + LayerBuffer buffer; + LayerRotateType rotateType; + }; + + static LayerInfo g_layerInfo = {}; + static DisplayDesc g_display = {}; + constexpr const uint8_t DISPALY_DEV_ID = 0; + +#ifdef LAYER_PF_ARGB1555 + constexpr const uint8_t LAYER_BPP = 16; + constexpr const PixelFormat HDI_LAYER_PIXEL_FORMAT = PIXEL_FMT_RGBA_5551; + constexpr const ImagePixelFormat LAYER_PIXEL_FORMAT = IMAGE_PIXEL_FORMAT_ARGB1555; +#elif defined LAYER_PF_ARGB565 + constexpr const uint8_t LAYER_BPP = 16; + constexpr const PixelFormat HDI_LAYER_PIXEL_FORMAT = PIXEL_FMT_RGB_565; + constexpr const ImagePixelFormat LAYER_PIXEL_FORMAT = IMAGE_PIXEL_FORMAT_RGB565; +#elif defined LAYER_PF_ARGB8888 + constexpr const uint8_t LAYER_BPP = 32; + // constexpr const PixelFormat HDI_LAYER_PIXEL_FORMAT = PIXEL_FMT_RGBA_8888; + constexpr const PixelFormat HDI_LAYER_PIXEL_FORMAT = PIXEL_FMT_RGB_565; + constexpr const ImagePixelFormat LAYER_PIXEL_FORMAT = IMAGE_PIXEL_FORMAT_RGB565; +// constexpr const ImagePixelFormat LAYER_PIXEL_FORMAT = IMAGE_PIXEL_FORMAT_ARGB8888; +#endif + constexpr const uint8_t BITS_PER_BYTE = 8; + static LiteSurfaceData g_devSurfaceData = {}; + + LayerRotateType GetLayerRotateType() + { + return g_display.rotateType; + } + + static void AllocDisplayBuffer(void) + { + if (g_display.layerFuncs->GetLayerBuffer != nullptr) { + int32_t ret = g_display.layerFuncs->GetLayerBuffer(g_display.devId, g_display.layerId, &g_display.buffer); + if (ret != DISPLAY_SUCCESS) { + GRAPHIC_LOGE("getLayerBuffer fail"); + return; + } + } + } + + LiteSurfaceData *GetDevSurfaceData() + { + AllocDisplayBuffer(); + g_devSurfaceData.phyAddr = reinterpret_cast(g_display.buffer.data.phyAddr); + g_devSurfaceData.virAddr = static_cast(g_display.buffer.data.virAddr); + g_devSurfaceData.pixelFormat = LAYER_PIXEL_FORMAT; + g_devSurfaceData.width = g_layerInfo.width; + g_devSurfaceData.height = g_layerInfo.height; + g_devSurfaceData.stride = g_display.buffer.pitch; + g_devSurfaceData.bytePerPixel = g_layerInfo.bpp / BITS_PER_BYTE; + return &g_devSurfaceData; + } + + static void DisplayInit(void) + { + int32_t ret = LayerInitialize(&g_display.layerFuncs); + if (ret != DISPLAY_SUCCESS || g_display.layerFuncs == nullptr) { + GRAPHIC_LOGE("layer initialize failed"); + return; + } + if (g_display.layerFuncs->InitDisplay != nullptr) { + ret = g_display.layerFuncs->InitDisplay(DISPALY_DEV_ID); + if (ret != DISPLAY_SUCCESS) { + GRAPHIC_LOGE("InitDisplay fail"); + return; + } + } + } + + static void OpenLayer(void) + { + if (g_display.layerFuncs->GetDisplayInfo == nullptr) { + return; + } + g_display.devId = DISPALY_DEV_ID; + DisplayInfo displayInfo = {}; + int32_t ret = g_display.layerFuncs->GetDisplayInfo(g_display.devId, &displayInfo); + if (ret != DISPLAY_SUCCESS) { + GRAPHIC_LOGE("GetDisplayInfo fail"); + return; + } + g_display.rotateType = static_cast(displayInfo.rotAngle); + g_layerInfo.width = displayInfo.width; + g_layerInfo.height = displayInfo.height; + g_layerInfo.bpp = LAYER_BPP; + g_layerInfo.pixFormat = HDI_LAYER_PIXEL_FORMAT; + g_layerInfo.type = LAYER_TYPE_GRAPHIC; + if (g_display.layerFuncs->CreateLayer != nullptr) { + ret = g_display.layerFuncs->CreateLayer(g_display.devId, &g_layerInfo, &g_display.layerId); + if (ret != DISPLAY_SUCCESS) { + GRAPHIC_LOGE("CreateLayer fail"); + return; + } + } + } + + void FbdevFlush() + { + if (g_display.layerFuncs->Flush != nullptr) { + int32_t ret = g_display.layerFuncs->Flush(g_display.devId, g_display.layerId, &g_display.buffer); + if (ret != DISPLAY_SUCCESS) { + GRAPHIC_LOGE("flush fail"); + return; + } + } + } + + void FbdevInit() + { + DisplayInit(); + OpenLayer(); + GetDevSurfaceData(); + } + + void FbdevClose() + { + if (g_display.layerFuncs->CloseLayer == nullptr) { + return; + } + if (g_display.layerFuncs->DeinitDisplay == nullptr) { + return; + } + int32_t ret = g_display.layerFuncs->CloseLayer(g_display.devId, g_display.layerId); + if (ret != DISPLAY_SUCCESS) { + GRAPHIC_LOGE("CloseLayer fail"); + return; + } + ret = g_display.layerFuncs->DeinitDisplay(g_display.devId); + if (ret != DISPLAY_SUCCESS) { + GRAPHIC_LOGE("DeinitDisplay fail"); + return; + } + ret = LayerUninitialize(g_display.layerFuncs); + if (ret != DISPLAY_SUCCESS) { + GRAPHIC_LOGE("LayerUninitialize fail"); + } + } +} // namespace OHOS diff --git a/khdvk_450a/liteos_m/ui/fbdev.h b/khdvk_450a/liteos_m/ui/fbdev.h new file mode 100644 index 0000000..26bbcc8 --- /dev/null +++ b/khdvk_450a/liteos_m/ui/fbdev.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 GRAPHIC_LITE_FBDEV_H +#define GRAPHIC_LITE_FBDEV_H + +#include "gfx_utils/pixel_format_utils.h" + +namespace OHOS { + enum LayerRotateType { + LAYER_ROTATE_NONE = 0, /**< No rotation */ + LAYER_ROTATE_90, /**< Rotation by 90 degrees */ + LAYER_ROTATE_180, /**< Rotation by 180 degrees */ + LAYER_ROTATE_270, /**< Rotation by 270 degrees */ + LAYER_ROTATE_BUTT /**< Invalid operation */ + }; + + struct LiteSurfaceData { + ImagePixelFormat pixelFormat; + uint16_t width; + uint16_t height; + uint8_t *virAddr; + uint8_t *phyAddr; + uint32_t stride; + uint8_t bytePerPixel; + }; + + /** + * @brief Get dev surface data. + */ + LiteSurfaceData *GetDevSurfaceData(); + + /** + * @brief Get layer rotate type. + */ + LayerRotateType GetLayerRotateType(); + + /** + * @brief Initialize fbdev. + */ + void FbdevInit(void); + + /** + * @brief Close fbdev. + */ + void FbdevClose(); + + /** + * @brief flush + */ + void FbdevFlush(); +} // namespace OHOS +#endif // GRAPHIC_LITE_HI_FBDEV_H diff --git a/khdvk_450a/liteos_m/ui/key_input.cpp b/khdvk_450a/liteos_m/ui/key_input.cpp new file mode 100644 index 0000000..5c6c460 --- /dev/null +++ b/khdvk_450a/liteos_m/ui/key_input.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 "events/key_event.h" +#include "gfx_utils/graphic_log.h" +#include "key_input_gd32f450.h" +#include "key_input.h" + +namespace OHOS { + namespace { + static uint16_t g_lastKeyId = 0; + } // namespace + + KeyInput::KeyInput() + { + Gd32f450KeyInputInit(); + } + + KeyInput *KeyInput::GetInstance() + { + static KeyInput keyInput; + return &keyInput; + } + + bool KeyInput::Read(DeviceData &data) + { + data.keyId = g_lastKeyId; + data.state = (uint16_t)Gd32f450SingleKeyInputRead((KEY_TYPE)g_lastKeyId); + + if (g_lastKeyId < MAX_KEY_NUM - 1) { + g_lastKeyId++; + return true; + } else { + g_lastKeyId = 0; + return false; + } + + return false; + } +} // namespace OHOS diff --git a/khdvk_450a/liteos_m/ui/key_input.h b/khdvk_450a/liteos_m/ui/key_input.h new file mode 100644 index 0000000..8ee2546 --- /dev/null +++ b/khdvk_450a/liteos_m/ui/key_input.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 GRAPHIC_LITE_KEY_INPUT_H +#define GRAPHIC_LITE_KEY_INPUT_H + +#include "dock/key_input_device.h" + +namespace OHOS { + class KeyInput : public KeyInputDevice { + public: + KeyInput(); + virtual ~KeyInput() + { + } + static KeyInput *GetInstance(); + bool Read(DeviceData &data) override; + + private: + }; +} // namespace OHOS +#endif // GRAPHIC_LITE_KEY_INPUT_H \ No newline at end of file diff --git a/khdvk_450a/liteos_m/ui/ui_main.cpp b/khdvk_450a/liteos_m/ui/ui_main.cpp new file mode 100644 index 0000000..31a6be7 --- /dev/null +++ b/khdvk_450a/liteos_m/ui/ui_main.cpp @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 "ui_main.h" +#include "cmsis_os.h" +#include "pthread.h" +#include "core/render_manager.h" +#include "common/graphic_startup.h" +#include "common/image_decode_ability.h" +#include "common/input_device_manager.h" +#include "common/task_manager.h" +#include "display_device.h" +#include "engines/gfx/gfx_engine_manager.h" +#include "font/ui_font.h" +#include "font/ui_font_header.h" +#include "font/ui_font_vector.h" +#include "gfx_utils/graphic_log.h" +#include "graphic_config.h" +#include "hal_tick.h" +#include "key_input.h" +#define ENABLE_FPS +#ifdef ENABLE_ACE +#include "product_adapter.h" +#endif + +static const int32_t FONT_MEM_LEN = 40 * 1024; +static uint8_t g_fontMemBaseAddr[FONT_MEM_LEN]; +#if ENABLE_ICU +static uint8_t g_icuMemBaseAddr[SHAPING_WORD_DICT_LENGTH]; +#endif + +using namespace OHOS; + +static void InitFontEngine() +{ +#if ENABLE_VECTOR_FONT + GraphicStartUp::InitFontEngine(reinterpret_cast(g_fontMemBaseAddr), FONT_MEM_LEN, VECTOR_FONT_DIR, + DEFAULT_VECTOR_FONT_FILENAME); +#endif + +#if ENABLE_ICU + GraphicStartUp::InitLineBreakEngine(reinterpret_cast(g_icuMemBaseAddr), SHAPING_WORD_DICT_LENGTH, + VECTOR_FONT_DIR, DEFAULT_LINE_BREAK_RULE_FILENAME); +#endif +} + +static void InitImageDecodeAbility() +{ + uint32_t imageType = IMG_SUPPORT_BITMAP | OHOS::IMG_SUPPORT_JPEG | OHOS::IMG_SUPPORT_PNG; + ImageDecodeAbility::GetInstance().SetImageDecodeAbility(imageType); +} + +static void InitHal() +{ + DisplayDevice *display = DisplayDevice::GetInstance(); + BaseGfxEngine::InitGfxEngine(display); +#ifdef LOSCFG_DRIVERS_USER_KEY_INPUT + KeyInput *key = KeyInput::GetInstance(); + InputDeviceManager::GetInstance()->Add(key); +#endif +} + +void InitUiKit(void) +{ + GraphicStartUp::Init(); + // init display/input device + InitHal(); + // init font engine + InitFontEngine(); + // init suppot image format + InitImageDecodeAbility(); +} + +__attribute__((weak)) void RunApp(void) +{ + GRAPHIC_LOGI("RunApp default"); +} + +#ifdef ENABLE_ACE +static void RenderTEHandler() +{ +} +#endif + +static void UiMainTask(void *arg) +{ + (void)arg; + // init ui kit (hal/fontengine/imagedecode/...) + InitUiKit(); + + // run user app + RunApp(); + +#ifdef ENABLE_ACE + const ACELite::TEHandlingHooks hooks = {RenderTEHandler, NULL}; + ACELite::ProductAdapter::RegTEHandlers(hooks); +#endif +#ifdef ENABLE_FPS + uint32_t cnt = 0; + uint32_t start = HALTick::GetInstance().GetTime(); +#endif + while (1) { +#ifdef ENABLE_ACE + // Here render all js app in the same task. + ACELite::ProductAdapter::DispatchTEMessage(); +#endif + + DisplayDevice::GetInstance()->UpdateFBBuffer(); + uint32_t temp = HALTick::GetInstance().GetTime(); + TaskManager::GetInstance()->TaskHandler(); + uint32_t time = HALTick::GetInstance().GetElapseTime(temp); + if (time < DEFAULT_TASK_PERIOD) { + osDelay(DEFAULT_TASK_PERIOD - time); + } +#ifdef ENABLE_FPS + cnt++; + time = HALTick::GetInstance().GetElapseTime(start); + int16_t timeout = 1000; + if (time >= timeout) { + GRAPHIC_LOGD("uitest time=%u, cnt=%u", time, cnt); + if (time == 0) { + return; + } + GRAPHIC_LOGD("uitest %u fps", timeout * cnt / time); + start = HALTick::GetInstance().GetTime(); + cnt = 0; + } +#endif + } +} +static const int32_t UI_THREAD_STACK_SIZE = 1024 * 32; + +void UiMain(void) +{ + osThreadAttr_t attr; + + attr.name = "display-demo"; + attr.attr_bits = 0U; + attr.cb_mem = NULL; + attr.cb_size = 0U; + attr.stack_mem = NULL; + attr.stack_size = UI_THREAD_STACK_SIZE; + attr.priority = osPriorityNormal; + + if (osThreadNew((osThreadFunc_t)UiMainTask, NULL, &attr) == NULL) { + GRAPHIC_LOGE("Failed to create UiMainTask"); + } +} diff --git a/khdvk_450a/liteos_m/ui/ui_main.h b/khdvk_450a/liteos_m/ui/ui_main.h new file mode 100644 index 0000000..82a70fb --- /dev/null +++ b/khdvk_450a/liteos_m/ui/ui_main.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed 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 __UI_MAIN_H__ +#define __UI_MAIN_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +void InitUiKit(void); +void UiMain(void); + +#ifdef __cplusplus +} +#endif + +#endif // __UI_MAIN_H__ diff --git a/khdvk_450a/pack_tools/LICENSE b/khdvk_450a/pack_tools/LICENSE new file mode 100755 index 0000000..4a45986 --- /dev/null +++ b/khdvk_450a/pack_tools/LICENSE @@ -0,0 +1,177 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/khdvk_450a/pack_tools/combination.py b/khdvk_450a/pack_tools/combination.py new file mode 100644 index 0000000..fdcb0f7 --- /dev/null +++ b/khdvk_450a/pack_tools/combination.py @@ -0,0 +1,69 @@ +# Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. +# Licensed 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. + +import os +import argparse + +# src: src_file_path +# dst: dst_file_path +# memory_size: malloced memory size, unit: byte +def append_file_data(src, dst, memory_size): + src_file_size = os.stat(src).st_size + + if(memory_size < 0): + raise Exception("memory_size < 0") + + if(memory_size < src_file_size): + raise Exception("memory_size is too small to hold src_file_data") + + src_fd = open(src, 'rb') + dst_fd = open(dst, 'ab') + + # append src_file_data to dst file + buf = src_fd.read(1024) + while buf: + dst_fd.write(buf) + buf = src_fd.read(1024) + + # fill free space with 0xff + buf = bytes([0xff]) + for i in range(memory_size - src_file_size): + dst_fd.write(buf) + + src_fd.close() + dst_fd.close() + +def cmd_parse(): + parser=argparse.ArgumentParser() + parser.add_argument('--bootloader_path',help='bootloader_path', required=True) + parser.add_argument('--kernel_path',help='kernel_path', required=True) + parser.add_argument('--file_path',help='file_path') + parser.add_argument('--image_path',help='image_path', required=True) + parser.add_argument('--bootloader_zone_size', help='bootloader_zone_size,Unit: KB',type=int,default=64) + parser.add_argument('--kernel_zone_size', help='kernel_zone_size,Unit: KB',type=int,default=1984) + parser.add_argument('--file_zone_size', help='file_zone_size,Unit: KB',type=int,default=1024) + #parser.print_help() + args = parser.parse_args() + return args + +args = cmd_parse() + +# ensure image_file existing and set image_file empty +image_fd = open(args.image_path, 'wb') +image_fd.close() + +#add file to image +append_file_data(args.bootloader_path, args.image_path, args.bootloader_zone_size * 1024) +append_file_data(args.kernel_path, args.image_path, args.kernel_zone_size * 1024) +if(args.file_path): + append_file_data(args.file_path, args.image_path, args.file_zone_size * 1024) diff --git a/khdvk_450a/pack_tools/gd32_uart_bootloader.bin b/khdvk_450a/pack_tools/gd32_uart_bootloader.bin new file mode 100644 index 0000000..e87d374 Binary files /dev/null and b/khdvk_450a/pack_tools/gd32_uart_bootloader.bin differ diff --git a/khdvk_450a/pack_tools/mk_lfs.sh b/khdvk_450a/pack_tools/mk_lfs.sh new file mode 100755 index 0000000..3069985 --- /dev/null +++ b/khdvk_450a/pack_tools/mk_lfs.sh @@ -0,0 +1,32 @@ +#!/bin/bash +# Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. +# Licensed 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 -e + +SCRIPT_PATH=$(dirname $0) +SRC_PATH="$1" +NO_APP_DATA_FLAG="$2" +OUT_DIR=${SRC_PATH}/.. +echo "=========>>gd32f4xx file system make:src path=$SRC_PATH,SCRIPT_PATH=${SCRIPT_PATH},OUT_DIR=${OUT_DIR}" >&2 + + +if [[ $NO_APP_DATA_FLAG == "no_app_data" ]]; then + python3 ${SCRIPT_PATH}/combination.py --bootloader_path ${SCRIPT_PATH}/gd32_uart_bootloader.bin --kernel_path ${OUT_DIR}/OHOS_Image.bin --image_path ${OUT_DIR}/gd32f4xx.bin +else + #cd ${SRC_PATH}/.. + # ${SCRIPT_PATH}/mklfs -c $SRC_PATH -b 4096 -r 128 -p 128 -s 1048576 -n 1 -l 32 -e 128 -k 500 -i ${OUT_DIR}/lfs.img + ${OUT_DIR}/mklfs -c $SRC_PATH -b 4096 -r 1 -p 1 -s 1048576 -n 1 -l 16 -e 128 -k 500 -i ${OUT_DIR}/lfs.img + #cd - + python3 ${SCRIPT_PATH}/combination.py --bootloader_path ${SCRIPT_PATH}/gd32_uart_bootloader.bin --kernel_path ${OUT_DIR}/OHOS_Image.bin --file_path ${OUT_DIR}/lfs.img --image_path ${OUT_DIR}/gd32f4xx.bin +fi + diff --git a/khdvk_450a/pack_tools/pre_pack.sh b/khdvk_450a/pack_tools/pre_pack.sh new file mode 100755 index 0000000..526078f --- /dev/null +++ b/khdvk_450a/pack_tools/pre_pack.sh @@ -0,0 +1,41 @@ +# Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. +# Licensed 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. + +#!/bin/bash +set -e + +OUT_DIR="$1" +DEST_PATH="$2" +PACKTOOL_PATH=${OUT_DIR}/kh_packtool +echo "=========>>kh pre build:DEST_PATH=${DEST_PATH},PACKTOOL_PATH=${PACKTOOL_PATH}" >&2 + +if [ ! -f ${DEST_PATH}/gd32_uart_bootloader.bin ]; then + echo "=========>>kh pre build:${DEST_PATH}/gd32_uart_bootloader.bin does not exist." >&2 + if [ -d ${PACKTOOL_PATH} ]; then + rm -rf ${PACKTOOL_PATH} + fi + mkdir -p ${PACKTOOL_PATH} + cd ${PACKTOOL_PATH} + git clone https://gitee.com/download_tools/khdvk_450a.git + cp -af khdvk_450a/bootloader/gd32_uart_bootloader.bin ${DEST_PATH} + cd - +fi + +if [ ! -f ${OUT_DIR}/mklfs ]; then + echo "=========>>kh pre build:${OUT_DIR}/mklfs does not exist." >&2 + cd ${DEST_PATH}/../../third_party/ + # gcc -std=gnu99 -Os -Wall -Ilfs -I. -D__NO_INLINE__ -I../../../../third_party/littlefs -o mklfs mklfs.c ../../../../third_party/littlefs/lfs.c ../../../../third_party/littlefs/lfs_util.c + # mv ${DEST_PATH}/../../third_party/mklfs ${OUT_DIR} + ../../../../prebuilts/build-tools/linux-x86/bin/gn gen out && ../../../../prebuilts/build-tools/linux-x86/bin/ninja -C out && mv out/mklfs ${OUT_DIR} && rm -rf out + cd - +fi \ No newline at end of file diff --git a/third_party/.gn b/third_party/.gn new file mode 100755 index 0000000..dcf3d5e --- /dev/null +++ b/third_party/.gn @@ -0,0 +1,13 @@ +# Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development Co., Ltd. +# Licensed 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. +buildconfig="//gnconfig/BUILDCONFIG.gn" \ No newline at end of file diff --git a/third_party/BUILD.gn b/third_party/BUILD.gn new file mode 100755 index 0000000..bd90add --- /dev/null +++ b/third_party/BUILD.gn @@ -0,0 +1,32 @@ +# Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. +# Licensed 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. +executable("mklfs") { + sources = [ + "mklfs.c", + "../../../../third_party/littlefs/lfs.c", + "../../../../third_party/littlefs/lfs_util.c" + ] + + include_dirs = [ + ".", + "lfs", + "../../../../third_party/littlefs" + ] + + cflags = [ + "-std=gnu99", + "-Os", + "-Wall", + "-D__NO_INLINE__" + ] +} \ No newline at end of file diff --git a/third_party/LICENSE b/third_party/LICENSE new file mode 100755 index 0000000..bda5a2b --- /dev/null +++ b/third_party/LICENSE @@ -0,0 +1,42 @@ +/* + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of the nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * * The WHITECAT logotype cannot be changed, you can remove it, but you + * cannot change it in any way. The WHITECAT logotype is: + * + * /\ /\ + * / \_____/ \ + * /_____________\ + * W H I T E C A T + * + * * Redistributions in binary form must retain all copyright notices printed + * to any local or remote output device. This include any reference to + * Lua RTOS, whitecatboard.org, Lua, and other copyright notices that may + * appear in the future. + * + * 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 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. + * + * Lua RTOS, a tool for make a LFS file system image + * + */ \ No newline at end of file diff --git a/third_party/README.OpenSource b/third_party/README.OpenSource new file mode 100755 index 0000000..4feef29 --- /dev/null +++ b/third_party/README.OpenSource @@ -0,0 +1,11 @@ +[ + { + "Name" : "mklfs", + "License" : "BSD 3-Clause License", + "License File" : "LICENSE", + "Version Number" : "V1.0", + "Owner" : "wangzhongjin@kaihong.com", + "Upstream URL" : "https://github.com/whitecatboard/Lua-RTOS-ESP32/tree/master/components/mklfs/src", + "Description" : "File image maker for the little fail-safe filesystem" + } +] \ No newline at end of file diff --git a/third_party/gnconfig/BUILDCONFIG.gn b/third_party/gnconfig/BUILDCONFIG.gn new file mode 100755 index 0000000..ac3e49f --- /dev/null +++ b/third_party/gnconfig/BUILDCONFIG.gn @@ -0,0 +1,13 @@ +# Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development Co., Ltd. +# Licensed 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_default_toolchain("//gnconfig/toolchain:user_define_gcc") \ No newline at end of file diff --git a/third_party/gnconfig/toolchain/BUILD.gn b/third_party/gnconfig/toolchain/BUILD.gn new file mode 100755 index 0000000..749b611 --- /dev/null +++ b/third_party/gnconfig/toolchain/BUILD.gn @@ -0,0 +1,98 @@ +# Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development Co., Ltd. +# Licensed 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. +toolchain("user_define_gcc") { + tool("cc") { + depfile = "{{output}}.d" + command = "gcc -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_c}} -c {{source}} -o {{output}}" + depsformat = "gcc" + description = "CC {{output}}" + outputs = [ + "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o", + ] + } + + tool("cxx") { + depfile = "{{output}}.d" + command = "g++ -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}} -c {{source}} -o {{output}}" + depsformat = "gcc" + description = "CXX {{output}}" + outputs = [ + "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o", + ] + } + + tool("alink") { + rspfile = "{{output}}.rsp" + command = "rm -f {{output}} && ar rcs {{output}} @$rspfile" + description = "AR {{target_output_name}}{{output_extension}}" + rspfile_content = "{{inputs}}" + outputs = [ + "{{target_out_dir}}/{{target_output_name}}{{output_extension}}", + ] + default_output_extension = ".a" + output_prefix = "lib" + } + + tool("solink") { + soname = "{{target_output_name}}{{output_extension}}" # e.g. "libfoo.so". + sofile = "{{output_dir}}/$soname" + rspfile = soname + ".rsp" + + command = "g++ -shared {{ldflags}} -o $sofile -Wl,-soname=$soname @$rspfile" + rspfile_content = "-Wl,--whole-archive {{inputs}} {{solibs}} -Wl,--no-whole-archive {{libs}}" + + description = "SOLINK $soname" + + # Use this for {{output_extension}} expansions unless a target manually + # overrides it (in which case {{output_extension}} will be what the target + # specifies). + default_output_extension = ".so" + + # Use this for {{output_dir}} expansions unless a target manually overrides + # it (in which case {{output_dir}} will be what the target specifies). + default_output_dir = "{{root_out_dir}}" + + outputs = [ + sofile, + ] + link_output = sofile + depend_output = sofile + output_prefix = "lib" + } + + tool("link") { + outfile = "{{target_output_name}}{{output_extension}}" + rspfile = "$outfile.rsp" + command = "g++ {{ldflags}} -o $outfile @$rspfile {{solibs}} {{libs}}" + description = "LINK $outfile" + default_output_dir = "{{root_out_dir}}" + rspfile_content = "{{inputs}}" + outputs = [ + outfile, + ] + } + + tool("stamp") { + command = "touch {{output}}" + description = "STAMP {{output}}" + } + + tool("copy") { + command = "cp -af {{source}} {{output}}" + description = "COPY {{source}} {{output}}" + } + + toolchain_args = { + use_linux_gcc_toolchain = "user" + } +} diff --git a/third_party/mklfs.c b/third_party/mklfs.c new file mode 100755 index 0000000..3193e47 --- /dev/null +++ b/third_party/mklfs.c @@ -0,0 +1,361 @@ +/* + * Copyright (C) 2015 - 2020, IBEROXARXA SERVICIOS INTEGRALES, S.L. + * Copyright (C) 2015 - 2020, Jaume Olivé Petrus (jolive@whitecatboard.org) + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of the nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * * The WHITECAT logotype cannot be changed, you can remove it, but you + * cannot change it in any way. The WHITECAT logotype is: + * + * /\ /\ + * / \_____/ \ + * /_____________\ + * W H I T E C A T + * + * * Redistributions in binary form must retain all copyright notices printed + * to any local or remote output device. This include any reference to + * Lua RTOS, whitecatboard.org, Lua, and other copyright notices that may + * appear in the future. + * + * 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 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. + * + * Lua RTOS, a tool for make a LFS file system image + * + */ + +#include "lfs.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct lfs_config cfg; +static lfs_t lfs; +static uint8_t *data; + +static int lfs_read(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, void *buffer, lfs_size_t size) +{ + memcpy(buffer, data + (block * c->block_size) + off, size); + return 0; +} + +static int lfs_prog(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, const void *buffer, lfs_size_t size) +{ + memcpy(data + (block * c->block_size) + off, buffer, size); + return 0; +} + +static int lfs_erase(const struct lfs_config *c, lfs_block_t block) +{ + memset(data + (block * c->block_size), 0, c->block_size); + return 0; +} + +static int lfs_sync(const struct lfs_config *c) +{ + return 0; +} + +static void create_dir(char *src) +{ + char *path; + + path = strchr(src, '/'); + if (path) { + + int ret; + fprintf(stdout, "%s\r\n", path); + + if ((ret = lfs_mkdir(&lfs, path)) < 0) { + fprintf(stderr, "can't create directory %s: error=%d\r\n", path, ret); + exit(1); + } + } +} + +static void create_file(char *src) +{ + char *path; + + path = strchr(src, '/'); + if (path) { + fprintf(stdout, "%s\r\n", path); + + // Open source file + FILE *srcf = fopen(src, "rb"); + if (!srcf) { + fprintf(stderr, "can't open source file %s: errno=%d (%s)\r\n", src, errno, strerror(errno)); + exit(1); + } + + // Open destination file + lfs_file_t dstf; + int ret; + if ((ret = lfs_file_open(&lfs, &dstf, path, LFS_O_WRONLY | LFS_O_CREAT)) < 0) { + fprintf(stderr, "can't open destination file %s: error=%d\r\n", path, ret); + exit(1); + } + + char c = fgetc(srcf); + while (!feof(srcf)) { + ret = lfs_file_write(&lfs, &dstf, &c, 1); + if (ret < 0) { + fprintf(stderr, "can't write to destination file %s: error=%d\r\n", path, ret); + exit(1); + } + c = fgetc(srcf); + } + + // Close destination file + ret = lfs_file_close(&lfs, &dstf); + if (ret < 0) { + fprintf(stderr, "can't close destination file %s: error=%d\r\n", path, ret); + exit(1); + } + + // Close source file + fclose(srcf); + } +} +static void skip_direct(char *curr_path, struct dirent *ent, char *src); + +static void compact(char *src) +{ + DIR *dir; + + dir = opendir(src); + if (dir) { + struct dirent *ent; + char curr_path[PATH_MAX]; + while ((ent = readdir(dir))) { + // Skip . and .. directories + skip_direct(curr_path, ent, src); + } + + closedir(dir); + } +} +static void skip_direct(char *curr_path, struct dirent *ent, char *src) +{ + if ((strcmp(ent->d_name, ".") != 0) && (strcmp(ent->d_name, "..") != 0)) { + // Update the current path + strcpy(curr_path, src); + strcat(curr_path, "/"); + strcat(curr_path, ent->d_name); + + if (ent->d_type == DT_DIR) { + create_dir(curr_path); + compact(curr_path); + } else if (ent->d_type == DT_REG) { + create_file(curr_path); + } + } +} +void usage(void) +{ + fprintf(stdout, + "usage: mklfs -c -b -r -p -s -n " + " -l -e -k -i \r\n"); +} + +static int is_number(const char *s) +{ + const char *c = s; + + while (*c) { + if ((*c < '0') || (*c > '9')) { + return 0; + } + c++; + } + + return 1; +} + +static int is_hex(const char *s) +{ + const char *c = s; + + if (*c++ != '0') { + return 0; + } + + if (*c++ != 'x') { + return 0; + } + + while (*c) { + if (((*c < '0') || (*c > '9')) && ((*c < 'A') || (*c > 'F')) && ((*c < 'a') || (*c > 'f'))) { + return 0; + } + c++; + } + + return 1; +} + +static int to_int(const char *s) +{ + if (is_number(s)) { + return atoi(s); + } else if (is_hex(s)) { + return (int)strtol(s, NULL, 0x10); + } + + return -1; +} + +int main(int argc, char **argv) +{ + char *src = NULL; // Source directory + char *dst = NULL; // Destination image + int c; // Current option + int block_size = 0; // Block size + int read_size = 0; // Read size + int prog_size = 0; // Prog size + int fs_size = 0; // File system size + int err; + int part_no = 0; // context + int blk_cycles = 0; // block_cycles + int la_size = 0; // lookahead_size + int ca_size = 0; // cache_size + + while ((c = getopt(argc, argv, "c:i:b:p:r:s:n:l:e:k:")) != -1) { + switch (c) { + case 'c': + src = optarg; + break; + + case 'i': + dst = optarg; + break; + + case 'b': + block_size = to_int(optarg); + break; + + case 'p': + prog_size = to_int(optarg); + break; + + case 'r': + read_size = to_int(optarg); + break; + + case 's': + fs_size = to_int(optarg); + break; + + case 'n': + part_no = to_int(optarg); + break; + + case 'l': + la_size = to_int(optarg); + break; + + case 'e': + ca_size = to_int(optarg); + break; + + case 'k': + blk_cycles = to_int(optarg); + break; + default: + break; + } + } + + if ((src == NULL) || (dst == NULL) || (block_size <= 0) || (prog_size <= 0) || (read_size <= 0) || (fs_size <= 0)) { + usage(); + exit(1); + } + + // Mount the file system + cfg.read = lfs_read; + cfg.prog = lfs_prog; + cfg.erase = lfs_erase; + cfg.sync = lfs_sync; + + cfg.block_size = block_size; + cfg.read_size = read_size; + cfg.prog_size = prog_size; + cfg.block_count = fs_size / cfg.block_size; + cfg.lookahead_size = la_size; + cfg.context = (void *)part_no; + cfg.block_cycles = blk_cycles; + cfg.cache_size = ca_size; + + data = calloc(1, fs_size); + if (!data) { + fprintf(stderr, "no memory for mount\r\n"); + return -1; + } + + err = lfs_format(&lfs, &cfg); + if (err < 0) { + fprintf(stderr, "format error: error=%d\r\n", err); + return -1; + } + + err = lfs_mount(&lfs, &cfg); + if (err < 0) { + fprintf(stderr, "mount error: error=%d\r\n", err); + return -1; + } + + char * last_dir = strrchr(src, '/'); + if (last_dir) { + last_dir++; + compact(last_dir); + } else { + compact(src); + } + + FILE *img = fopen(dst, "wb+"); + + if (!img) { + fprintf(stderr, "can't create image file: errno=%d (%s)\r\n", errno, strerror(errno)); + return -1; + } + + int ret; + ret = fwrite(data, 1, fs_size, img); + if(ret < 0) { + fprintf(stderr, "fwrite(data, 1, fs_size, img): errno=%d (%s)\r\n", errno, strerror(errno)); + } + + ret = fclose(img); + if(ret < 0) { + fprintf(stderr, "fclose(img): errno=%d (%s)\r\n", errno, strerror(errno)); + return -1; + } + + return 0; +}