本帖最后由 andeyqi 于 2024-1-8 18:39 编辑
简介:
RT-thread 系统的移植适配主要是bsp 部分的输配,cpu 相关的光放的代码已经支持了大量的CPU 体系架构的代码,驱动本分的代码一般由厂家sdk 提供,我们只要把sdk 的代码适配到系统里就可以完成最小系统的适配支持,以下链接(https://club.rt-thread.org/ask/article/869d12cbe0bb712b.html)是部分的mcu 的移植说明我们参照下流程及官方的文档(https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/README),参考上面的资料开始我们的主题适配Rt-thread 系统至LPC860-max 开发板,以下是RT-thread 的启动流程,方便我们移植理解系统启动流程。
1.创建 lpc860-max bsp 目录
更新RT-thread 代码库bsp 目录下没有lpc865 的板卡,我们创建个lpcxpresso860_max 目录并把官方的sdk 软件包放到该目录下待用,参照其他bsp目录结构创建drivers/applications/board 文件夹分别用于防止适配rt-thread 驱动框架的驱动,应用程序及板级初始化程序。
图1.1
2.添加kconfig 文件
RT-thread 是个高度可裁剪的系统,配置工具使用的是kconfig 工具,在bsp 目录下执行menuconfig 命令图,通过形界面的方式进行配置,我们参照其他bsp ,本地参照的是gd32 的kconfig 将对应的文件拷贝至新建的lpcxpresso860_max bsp 目录下,kconfig 内容如下:
- mainmenu "RT-Thread Configuration"
- config BSP_DIR
- string
- option env="BSP_ROOT"
- default "."
- config RTT_DIR
- string
- option env="RTT_ROOT"
- default "../.."
- config PKGS_DIR
- string
- option env="PKGS_ROOT"
- default "packages"
- source "$RTT_DIR/Kconfig"
- source "$PKGS_DIR/Kconfig"
- source "board/Kconfig"
复制代码
以上配置文件配置了BSP_ROOT/PKGS_ROOT/RTT_ROOT 路径,并引用了 "$RTT_DIR/Kconfig"/"$PKGS_DIR/Kconfig"/"board/Kconfig" 文件,其中"board/Kconfig" 文件配置片上资源配置,shell 使用串口资源是通过此配置文件来配置,我们参照gd32 的配置添加如下配置文件。
- menu "Hardware Drivers Config"
- config SOC_SERIES_LPC86X
- bool
- default y
- config SOC_LPC860MAX
- bool
- select SOC_SERIES_LPC86X
- select RT_USING_COMPONENTS_INIT
- select RT_USING_USER_MAIN
- default y
- menu "Onboard Peripheral Drivers"
- endmenu
- menu "On-chip Peripheral Drivers"
- config BSP_USING_GPIO
- bool "Enable GPIO"
- select RT_USING_PIN
- default y
- menuconfig BSP_USING_UART
- bool "Enable UART"
- default y
- select RT_USING_SERIAL
- if BSP_USING_UART
- config BSP_USING_UART0
- bool "Enable UART0"
- default n
- config BSP_UART0_RX_USING_DMA
- bool "Enable UART0 RX DMA"
- depends on BSP_USING_UART0
- select RT_SERIAL_USING_DMA
- default n
- config BSP_USING_UART1
- bool "Enable UART1"
- default y
- config BSP_UART1_RX_USING_DMA
- bool "Enable UART1 RX DMA"
- depends on BSP_USING_UART1
- select RT_SERIAL_USING_DMA
- default n
- endif
- endmenu
- menu "Board extended module Drivers"
- endmenu
- endmenu
复制代码 上述配置通过的结构和menuconfig 下 Hardware Drivers Config 菜单下下配置,配置截图如下。
2.scons 配置
RT-thread 的工程配置及文件管理是通过scons 脚本控制的,我们只需要配置需要编译的文件就可以通过scans 命令自动生成IAR/MDK/GCC 的配置工程, 我们本次试验使用的是IAR 的工程,其他工程的实现也是类似。
2.1 IAR 工程模板文件创建
在对应的BSP 目录下添加 template.ewp 工程模板文件,更新模板文件的Debug/Release 配置下的CPU 型号及链接脚本路径后并保存即可,本地配置的如下。
图2.1.1
图2.1.2
2.2 工程配置 2.2.1 bsp 根目录下scons 配置
参照其他BSP 目录下的结构添加如下三个文件至bsp 根目录下:
SConstruct:
- import os
- import sys
- import rtconfig
- if os.getenv('RTT_ROOT'):
- RTT_ROOT = os.getenv('RTT_ROOT')
- else:
- RTT_ROOT = os.path.normpath(os.getcwd() + '/../..')
- sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')]
- try:
- from building import *
- except:
- print('Cannot found RT-Thread root directory, please check RTT_ROOT')
- print(RTT_ROOT)
- exit(-1)
- TARGET = 'rtthread.' + rtconfig.TARGET_EXT
- DefaultEnvironment(tools=[])
- env = Environment(tools = ['mingw'],
- AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS,
- CC = rtconfig.CC, CCFLAGS = rtconfig.CFLAGS,
- AR = rtconfig.AR, ARFLAGS = '-rc',
- CXX = rtconfig.CXX, CXXFLAGS = rtconfig.CXXFLAGS,
- LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS)
- env.PrependENVPath('PATH', rtconfig.EXEC_PATH)
- if rtconfig.PLATFORM in ['iccarm']:
- env.Replace(CCCOM = ['$CC $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -o $TARGET $SOURCES'])
- env.Replace(ARFLAGS = [''])
- env.Replace(LINKCOM = env["LINKCOM"] + ' --map rtthread.map')
- Export('RTT_ROOT')
- Export('rtconfig')
- SDK_ROOT = os.path.abspath('.')
- if os.path.exists(SDK_ROOT + '/SDK_2_13_0_LPCXpresso860MAX'):
- libraries_path_prefix = SDK_ROOT + '/SDK_2_13_0_LPCXpresso860MAX'
- else:
- libraries_path_prefix = os.path.dirname(SDK_ROOT) + '/SDK_2_13_0_LPCXpresso860MAX'
- SDK_LIB = libraries_path_prefix
- Export('SDK_LIB')
- # prepare building environment
- objs = PrepareBuilding(env, RTT_ROOT, has_libcpu=False)
- # make a building
- DoBuilding(TARGET, objs)
复制代码 SConscript:
- # for module compiling
- import os
- Import('RTT_ROOT')
- from building import *
- cwd = GetCurrentDir()
- objs = []
- list = os.listdir(cwd)
- for d in list:
- path = os.path.join(cwd, d)
- if os.path.isfile(os.path.join(path, 'SConscript')):
- objs = objs + SConscript(os.path.join(d, 'SConscript'))
- Return('objs')
复制代码 rtconfig.py
- import os
- # toolchains options
- ARCH='arm'
- CPU='cortex-m0'
- CROSS_TOOL='keil'
- # bsp lib config
- BSP_LIBRARY_TYPE = None
- if os.getenv('RTT_CC'):
- CROSS_TOOL = os.getenv('RTT_CC')
- if os.getenv('RTT_ROOT'):
- RTT_ROOT = os.getenv('RTT_ROOT')
- # cross_tool provides the cross compiler
- # EXEC_PATH is the compiler execute path, for example, CodeSourcery, Keil MDK, IAR
- if CROSS_TOOL == 'gcc':
- PLATFORM = 'gcc'
- EXEC_PATH = r'C:\Users\XXYYZZ'
- elif CROSS_TOOL == 'keil':
- PLATFORM = 'armcc'
- EXEC_PATH = r'C:/Keil_v5'
- elif CROSS_TOOL == 'iar':
- PLATFORM = 'iccarm'
- EXEC_PATH = r'C:/Program Files (x86)/IAR Systems/Embedded Workbench 8.3'
- if os.getenv('RTT_EXEC_PATH'):
- EXEC_PATH = os.getenv('RTT_EXEC_PATH')
- BUILD = 'debug'
- if PLATFORM == 'gcc':
- # toolchains
- PREFIX = 'arm-none-eabi-'
- CC = PREFIX + 'gcc'
- AS = PREFIX + 'gcc'
- AR = PREFIX + 'ar'
- CXX = PREFIX + 'g++'
- LINK = PREFIX + 'gcc'
- TARGET_EXT = 'elf'
- SIZE = PREFIX + 'size'
- OBJDUMP = PREFIX + 'objdump'
- OBJCPY = PREFIX + 'objcopy'
- DEVICE = ' -mcpu=cortex-m0 -mthumb -ffunction-sections -fdata-sections'
- CFLAGS = DEVICE
- AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp'
- LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=rtthread-lpc824.map,-cref,-u,Reset_Handler -T lpc824_rom.ld'
- CPATH = ''
- LPATH = ''
- if BUILD == 'debug':
- CFLAGS += ' -O0 -gdwarf-2'
- AFLAGS += ' -gdwarf-2'
- else:
- CFLAGS += ' -O2'
- CXXFLAGS = CFLAGS
- POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.bin\n' + SIZE + ' $TARGET \n'
- elif PLATFORM == 'armcc':
- # toolchains
- CC = 'armcc'
- CXX = 'armcc'
- AS = 'armasm'
- AR = 'armar'
- LINK = 'armlink'
- TARGET_EXT = 'axf'
- DEVICE = ' --cpu Cortex-M0+'
- CFLAGS = DEVICE + ' --apcs=interwork'
- AFLAGS = DEVICE
- LFLAGS = DEVICE + ' --info sizes --info totals --info unused --info veneers --list rtthread-lpc824.map --scatter lpc824_rom.sct'
- CFLAGS += ' -D__MICROLIB '
- AFLAGS += ' --pd "__MICROLIB SETA 1" '
- LFLAGS += ' --library_type=microlib '
- EXEC_PATH += '/ARM/ARMCC/bin/'
- if BUILD == 'debug':
- CFLAGS += ' -g -O0'
- AFLAGS += ' -g'
- else:
- CFLAGS += ' -O2'
- CXXFLAGS = CFLAGS
- CFLAGS += ' -std=c99'
- POST_ACTION = 'fromelf --bin $TARGET --output rtthread.bin \nfromelf -z $TARGET'
- elif PLATFORM == 'iccarm':
- # toolchains
- CC = 'iccarm'
- CXX = 'iccarm'
- AS = 'iasmarm'
- AR = 'iarchive'
- LINK = 'ilinkarm'
- TARGET_EXT = 'out'
- DEVICE = '-Dewarm'
- #DEVICE = ' -D USE_STDPERIPH_DRIVER' + ' -D GD32F407xK'
- CFLAGS = DEVICE
- CFLAGS += ' --diag_suppress Pa050'
- CFLAGS += ' --no_cse'
- CFLAGS += ' --no_unroll'
- CFLAGS += ' --no_inline'
- CFLAGS += ' --no_code_motion'
- CFLAGS += ' --no_tbaa'
- CFLAGS += ' --no_clustering'
- CFLAGS += ' --no_scheduling'
- CFLAGS += ' --endian=little'
- CFLAGS += ' --cpu=Cortex-M0'
- CFLAGS += ' -e'
- CFLAGS += ' --fpu=None'
- CFLAGS += ' --dlib_config "' + EXEC_PATH + '/arm/INC/c/DLib_Config_Normal.h"'
- CFLAGS += ' -Ol'
- CFLAGS += ' --use_c++_inline'
- AFLAGS = DEVICE
- AFLAGS += ' -s+'
- AFLAGS += ' -w+'
- AFLAGS += ' -r'
- AFLAGS += ' --cpu Cortex-M0'
- AFLAGS += ' --fpu None'
- LFLAGS = ' --config "Libraries/iar/LPC845_flash.icf"'
- LFLAGS += ' --redirect _Printf=_PrintfTiny'
- LFLAGS += ' --redirect _Scanf=_ScanfSmall'
- LFLAGS += ' --entry __iar_program_start'
- CXXFLAGS = CFLAGS
-
- EXEC_PATH = EXEC_PATH + '/arm/bin/'
- POST_ACTION = 'ielftool --bin $TARGET rtthread.bin'
- def dist_handle(BSP_ROOT, dist_dir):
- import sys
- cwd_path = os.getcwd()
- sys.path.append(os.path.join(os.path.dirname(BSP_ROOT), 'tools'))
- from sdk_dist import dist_do_building
- dist_do_building(BSP_ROOT, dist_dir)
复制代码
2.2.2 SDK 目录下scons 配置按照上面的方法将SDK 的驱动文件加入scons 配置脚本。
- import rtconfig
- from building import *
- # get current directory
- cwd = GetCurrentDir()
- # The set of source files associated with this SConscript file.
- src = ['devices/LPC865/drivers/fsl_acomp.c']
- src += ['devices/LPC865/drivers/fsl_adc.c']
- src += ['devices/LPC865/drivers/fsl_clock.c']
- src += ['devices/LPC865/drivers/fsl_common.c']
- src += ['devices/LPC865/drivers/fsl_common_arm.c']
- src += ['devices/LPC865/drivers/fsl_crc.c']
- src += ['devices/LPC865/drivers/fsl_ftm.c']
- src += ['devices/LPC865/drivers/fsl_dma.c']
- src += ['devices/LPC865/drivers/fsl_gpio.c']
- src += ['devices/LPC865/drivers/fsl_i2c.c']
- src += ['devices/LPC865/drivers/fsl_i2c_dma.c']
- src += ['devices/LPC865/drivers/fsl_i3c.c']
- src += ['devices/LPC865/drivers/fsl_i3c_dma.c']
- src += ['devices/LPC865/drivers/fsl_iap.c']
- src += ['devices/LPC865/drivers/fsl_inputmux.c']
- src += ['devices/LPC865/drivers/fsl_mrt.c']
- src += ['devices/LPC865/drivers/fsl_pint.c']
- src += ['devices/LPC865/drivers/fsl_power.c']
- src += ['devices/LPC865/drivers/fsl_reset.c']
- src += ['devices/LPC865/drivers/fsl_spi.c']
- src += ['devices/LPC865/drivers/fsl_swm.c']
- src += ['devices/LPC865/drivers/fsl_syscon.c']
- src += ['devices/LPC865/drivers/fsl_usart.c']
- src += ['devices/LPC865/drivers/fsl_wkt.c']
- src += ['devices/LPC865/drivers/fsl_wwdt.c']
- src += ['devices/LPC865/drivers/fsl_syscon.c']
- src += ['devices/LPC865/drivers/fsl_usart.c']
- src += ['devices/LPC865/drivers/fsl_wkt.c']
- src += ['devices/LPC865/drivers/fsl_wwdt.c']
- src += ['devices/LPC865/system_LPC865.c']
- path = [
- cwd + '/CMSIS/Core/Include',
- cwd + '/devices/LPC865',
- cwd + '/devices/LPC865/drivers',]
- CPPDEFINES = ['CPU_LPC865M201JBD64']
- group = DefineGroup('Libraries', src, depend = [''], CPPPATH = path, CPPDEFINES = CPPDEFINES)
- Return('group')
复制代码 2.2.3 board 根目录下scons 配置
board 目录下我们通过MCUXpresso IDE 生成的时钟及pin 相关代码复制到board 目录下,加入工程编译,在board 目录下添加SConscript文件内容如下:
- import os
- import rtconfig
- from building import *
- Import('SDK_LIB')
- cwd = GetCurrentDir()
- # add general drivers
- src = Split('''
- board.c
- clock_config.c
- pin_mux.c
- ''')
- path = [cwd]
- startup_path_prefix = SDK_LIB
- if rtconfig.PLATFORM in ['gcc']:
- src += [startup_path_prefix + '/devices/LPC865/gcc/startup_LPC865.s']
- elif rtconfig.PLATFORM in ['armcc', 'armclang']:
- src += [startup_path_prefix + '/devices/LPC865/arm/startup_LPC865.s']
- elif rtconfig.PLATFORM in ['iccarm']:
- src += [startup_path_prefix + '/devices/LPC865/iar/startup_LPC865.s']
- group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path)
- Return('group')
复制代码
2.2.4 drivers录下scons 配置
drivers 目录下的文件是适配rt-thread 驱动框架的程序,本次的最小系统的实验会包含uart和gpio的驱动结构,gpio 的驱动适配可以参照该贴(https://www.nxpic.org.cn/module/forum/thread-630593-1-1.html)对gpio进行封装,串口的驱动可以参照RT-thread 串行驱动程序框架进行适配,适配的方法在此不进一步展开了,对应的代码如下,参照如上的方法添加入scons 管理。
drv_gpio.c 代码如下:
- #include <rtdevice.h>
- #include <rthw.h>
- #include <rtconfig.h>
- #ifdef RT_USING_PIN
- #include "fsl_device_registers.h"
- #include "fsl_iocon.h"
- #include "fsl_gpio.h"
- #define SCON_INDEX(offset) ((offset)/0x04u)
- #define PIN_NUM(port, no) (((((port) & 0x1u) << 5) | ((no) & 0x1Fu)))
- #define LPC8XX_PIN(index, port, pin,iocon) {index, port, pin, iocon}
- struct pin_index
- {
- int8_t index;
- uint8_t port;
- uint8_t pin;
- uint8_t iocon;
- };
- static const struct pin_index pins[] =
- {
- LPC8XX_PIN(0,0,0,SCON_INDEX(0x044u)), /* PIO0_0 */
- LPC8XX_PIN(1,0,1,SCON_INDEX(0x02cu)),
- LPC8XX_PIN(2,0,2,SCON_INDEX(0x018u)),
- LPC8XX_PIN(3,0,3,SCON_INDEX(0x014u)),
- LPC8XX_PIN(4,0,4,SCON_INDEX(0x010u)),
- LPC8XX_PIN(5,0,5,SCON_INDEX(0x00cu)),
- LPC8XX_PIN(6,0,6,SCON_INDEX(0x040u)),
- LPC8XX_PIN(7,0,7,SCON_INDEX(0x03cu)),
- LPC8XX_PIN(8,0,8,SCON_INDEX(0x038u)),
- LPC8XX_PIN(9,0,9,SCON_INDEX(0x034u)),
- LPC8XX_PIN(10,0,10,SCON_INDEX(0x020u)),
- LPC8XX_PIN(11,0,11,SCON_INDEX(0x01cu)),
- LPC8XX_PIN(12,0,12,SCON_INDEX(0x008u)),
- LPC8XX_PIN(13,0,13,SCON_INDEX(0x004u)),
- LPC8XX_PIN(14,0,14,SCON_INDEX(0x048u)),
- LPC8XX_PIN(15,0,15,SCON_INDEX(0x028u)),
- LPC8XX_PIN(16,0,16,SCON_INDEX(0x024u)),
- LPC8XX_PIN(17,0,17,SCON_INDEX(0x000u)),
- LPC8XX_PIN(18,0,18,SCON_INDEX(0x078u)),
- LPC8XX_PIN(19,0,19,SCON_INDEX(0x074u)),
- LPC8XX_PIN(20,0,20,SCON_INDEX(0x070u)),
- LPC8XX_PIN(21,0,21,SCON_INDEX(0x06cu)),
- LPC8XX_PIN(22,0,22,SCON_INDEX(0x068u)),
- LPC8XX_PIN(23,0,23,SCON_INDEX(0x064u)),
- LPC8XX_PIN(24,0,24,SCON_INDEX(0x060u)),
- LPC8XX_PIN(25,0,25,SCON_INDEX(0x05cu)),
- LPC8XX_PIN(26,0,26,SCON_INDEX(0x058u)),
- LPC8XX_PIN(27,0,27,SCON_INDEX(0x054u)),
- LPC8XX_PIN(28,0,28,SCON_INDEX(0x050u)),
- LPC8XX_PIN(29,0,29,SCON_INDEX(0x0c8u)),
- LPC8XX_PIN(30,0,30,SCON_INDEX(0x0ccu)),
- LPC8XX_PIN(31,0,31,SCON_INDEX(0x08cu)),
- LPC8XX_PIN(32,1,0,SCON_INDEX(0x090u)),
- LPC8XX_PIN(33,1,1,SCON_INDEX(0x094u)),
- LPC8XX_PIN(34,1,2,SCON_INDEX(0x098u)),
- LPC8XX_PIN(35,1,3,SCON_INDEX(0x0a4u)),
- LPC8XX_PIN(36,1,4,SCON_INDEX(0x0a8u)),
- LPC8XX_PIN(37,1,5,SCON_INDEX(0x0acu)),
- LPC8XX_PIN(38,1,6,SCON_INDEX(0x0b8u)),
- LPC8XX_PIN(39,1,7,SCON_INDEX(0x0c4u)),
- LPC8XX_PIN(40,1,8,SCON_INDEX(0x07cu)),
- LPC8XX_PIN(41,1,9,SCON_INDEX(0x080u)),
- LPC8XX_PIN(42,1,10,SCON_INDEX(0x0dcu)),
- LPC8XX_PIN(43,1,11,SCON_INDEX(0x0d8u)),
- LPC8XX_PIN(44,1,12,SCON_INDEX(0x084u)),
- LPC8XX_PIN(45,1,13,SCON_INDEX(0x088u)),
- LPC8XX_PIN(46,1,14,SCON_INDEX(0x09cu)),
- LPC8XX_PIN(47,1,15,SCON_INDEX(0x0a0u)),
- LPC8XX_PIN(48,1,16,SCON_INDEX(0x0b0u)),
- LPC8XX_PIN(49,1,17,SCON_INDEX(0x0b4u)),
- LPC8XX_PIN(50,1,18,SCON_INDEX(0x0bcu)),
- LPC8XX_PIN(51,1,19,SCON_INDEX(0x0c0u)),
- LPC8XX_PIN(52,1,20,SCON_INDEX(0x0d0u)),
- LPC8XX_PIN(53,1,21,SCON_INDEX(0x0d4u))
- };
- #define ITEM_NUM(items) sizeof(items) / sizeof(items[0])
- /**
- * @brief pin get
- * @param name P0.1
- * @retval pin number
- */
- static rt_base_t lpc8xx_pin_get(const char * name)
- {
- int pin = 0;
- int hw_port_num, hw_pin_num = 0;
- int i, name_len;
- name_len = strlen(name);
- if ((name_len < 4) || (name_len >= 6))
- {
- return -1;
- }
-
- if ((name[0] != 'P') || (name[2] != '.'))
- {
- return -1;
- }
-
- if ((name[1] >= '0') && (name[1] <= '1'))
- {
- hw_port_num = (int)(name[1] - '0');
- }
- else
- {
- return -1;
- }
-
- for (i = 3; i < name_len; i++)
- {
- hw_pin_num *= 10;
- hw_pin_num += name[i] - '0';
- }
- pin = PIN_NUM(hw_port_num, hw_pin_num);
- return pin;
- }
- /**
- * @brief get pin
- * @param pin
- * @retval None
- */
- const struct pin_index *get_pin(uint8_t pin)
- {
- const struct pin_index *index;
- if (pin < ITEM_NUM(pins))
- {
- index = &pins[pin];
- if (index->index == -1)
- index = NULL;
- }
- else
- {
- index = NULL;
- }
- return index;
- }
- /**
- * @brief set pin mode
- * @param pin, mode
- * @retval None
- */
- static void lpc8xx_pin_mode(rt_device_t dev, rt_base_t pin, rt_uint8_t mode)
- {
- const struct pin_index *index = NULL;
- index = get_pin(pin);
- if (index == NULL)
- {
- return;
- }
- switch(mode)
- {
- case PIN_MODE_OUTPUT:
- IOCON_PinMuxSet(IOCON,index->iocon,IOCON_MODE_PULLUP);
- GPIO_PinInit(GPIO, index->port, index->pin, &(gpio_pin_config_t){kGPIO_DigitalOutput, (0)});
- break;
- case PIN_MODE_OUTPUT_OD:
- IOCON_PinMuxSet(IOCON,index->iocon,IOCON_OPENDRAIN_EN);
- GPIO_PinInit(GPIO, index->port, index->pin, &(gpio_pin_config_t){kGPIO_DigitalOutput, (0)});
- break;
- case PIN_MODE_INPUT:
- GPIO_PinInit(GPIO, index->port, index->pin, &(gpio_pin_config_t){kGPIO_DigitalInput, (0)});
- break;
- case PIN_MODE_INPUT_PULLUP:
- IOCON_PinMuxSet(IOCON,index->iocon,IOCON_MODE_PULLUP);
- /* input setting: pull up. */
- GPIO_PinInit(GPIO, index->port, index->pin, &(gpio_pin_config_t){kGPIO_DigitalInput, (0)});
- break;
- case PIN_MODE_INPUT_PULLDOWN:
- IOCON_PinMuxSet(IOCON,index->iocon,IOCON_MODE_PULLDOWN);
- /* input setting: pull down. */
- GPIO_PinInit(GPIO, index->port, index->pin, &(gpio_pin_config_t){kGPIO_DigitalInput, (0)});
- break;
- default:
- break;
- }
- }
- /**
- * @brief pin write
- * @param pin, valuie
- * @retval None
- */
- static void lpc8xx_pin_write(rt_device_t dev, rt_base_t pin, rt_uint8_t value)
- {
- const struct pin_index *index = NULL;
- index = get_pin(pin);
- if (index == NULL)
- {
- return;
- }
- GPIO_PinWrite(GPIO,index->port,index->pin,(uint8_t)value);
- }
- /**
- * @brief pin read
- * @param dev, pin
- * @retval None
- */
- static rt_int8_t lpc8xx_pin_read(rt_device_t dev, rt_base_t pin)
- {
- int value = PIN_LOW;
- const struct pin_index *index = NULL;
- index = get_pin(pin);
- if (index == NULL)
- {
- return value;
- }
- value = GPIO_PinRead(GPIO,index->port,index->pin);
- return value;
- }
- const static struct rt_pin_ops lpc8xx_pin_ops =
- {
- .pin_mode = lpc8xx_pin_mode,
- .pin_write = lpc8xx_pin_write,
- .pin_read = lpc8xx_pin_read,
- .pin_get = lpc8xx_pin_get,
- .pin_attach_irq = RT_NULL,
- .pin_detach_irq= RT_NULL,
- .pin_irq_enable = RT_NULL,
- };
- int rt_hw_pin_init(void)
- {
- int result;
- result = rt_device_pin_register("pin", &lpc8xx_pin_ops, RT_NULL);
- return result;
- }
- INIT_BOARD_EXPORT(rt_hw_pin_init);
- #endif
复制代码
drv_uart.c 代码如下:
- /*
- * Copyright (c) 2006-2022, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2021-08-20 BruceOu first implementation
- */
- #include "drv_usart.h"
- #ifdef RT_USING_SERIAL
- #if !defined(BSP_USING_UART0)
- #error "Please define at least one UARTx"
- #endif
- #include <rtdevice.h>
- static void LPC845_UART_IRQHandler(struct rt_serial_device *serial);
- #if defined(BSP_USING_UART0)
- struct rt_serial_device serial0;
- void USART0_IRQHandler(void)
- {
- /* enter interrupt */
- rt_interrupt_enter();
- LPC845_UART_IRQHandler(&serial0);
- /* leave interrupt */
- rt_interrupt_leave();
- }
- #endif /* BSP_USING_UART0 */
- static const struct lpc845_uart uart_obj[] = {
- #ifdef BSP_USING_UART0
- {
- USART0, // uart peripheral index
- USART0_IRQn, // uart iqrn
- &serial0,
- "uart0",
- },
- #endif
- };
- /**
- * @brief UART MSP Initialization
- * This function configures the hardware resources used in this example:
- * - Peripheral's clock enable
- * - Peripheral's GPIO Configuration
- * - NVIC configuration for UART interrupt request enable
- * @param huart: UART handle pointer
- * @retval None
- */
- void lpc845_uart_gpio_init(struct lpc845_uart *uart)
- {
-
- /* init uart recive ring buffer */
- NVIC_SetPriority(uart->irqn, 0);
- NVIC_EnableIRQ(uart->irqn);
- }
- /**
- * @brief uart configure
- * @param serial, cfg
- * @retval None
- */
- static rt_err_t lpc845_uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
- {
- struct lpc845_uart *uart;
- status_t status;
- usart_config_t usartConfig;
- RT_ASSERT(serial != RT_NULL);
- RT_ASSERT(cfg != RT_NULL);
- uart = (struct lpc845_uart *)serial->parent.user_data;
- /* config usart struct */
- USART_GetDefaultConfig(&usartConfig);
- usartConfig.baudRate_Bps = cfg->baud_rate;
- usartConfig.bitCountPerChar = kUSART_8BitsPerChar;
- usartConfig.parityMode = kUSART_ParityDisabled;
- usartConfig.stopBitCount = kUSART_OneStopBit;
- usartConfig.enableRx = true;
- usartConfig.enableTx = true;
- /* init usart */
- status = USART_Init(USART0, &usartConfig, BOARD_DEBUG_USART_CLK_FREQ);
- if (kStatus_Success != status)
- {
- return status;
- }
- lpc845_uart_gpio_init(uart);
- /* enable usart rx interrupts */
- USART_EnableInterrupts(USART0, kUSART_RxReadyInterruptEnable | kUSART_RxNoiseInterruptEnable);
- NVIC_EnableIRQ(USART0_IRQn);
- return RT_EOK;
- }
- /**
- * @brief uart control
- * @param serial, arg
- * @retval None
- */
- static rt_err_t lpc845_uart_control(struct rt_serial_device *serial, int cmd, void *arg)
- {
- struct lpc845_uart *uart;
- RT_ASSERT(serial != RT_NULL);
- uart = (struct lpc845_uart *)serial->parent.user_data;
- switch (cmd)
- {
- case RT_DEVICE_CTRL_CLR_INT:
- /* disable rx irq */
- NVIC_DisableIRQ(uart->irqn);
- /* disable interrupt */
- USART_DisableInterrupts(uart->uart_periph, kUSART_RxReadyInterruptEnable | kUSART_RxNoiseInterruptEnable);
- break;
- case RT_DEVICE_CTRL_SET_INT:
- /* enable rx irq */
- NVIC_EnableIRQ(uart->irqn);
- /* enable interrupt */
- USART_EnableInterrupts(uart->uart_periph, kUSART_RxReadyInterruptEnable | kUSART_RxNoiseInterruptEnable);
- break;
- }
- return RT_EOK;
- }
- /**
- * @brief uart put char
- * @param serial, ch
- * @retval None
- */
- static int lpc845_uart_putc(struct rt_serial_device *serial, char ch)
- {
- struct lpc845_uart *uart;
- RT_ASSERT(serial != RT_NULL);
- uart = (struct lpc845_uart *)serial->parent.user_data;
- USART_WriteBlocking(uart->uart_periph,(uint8_t *)&ch,1);
- return RT_EOK;
- }
- /**
- * @brief uart get char
- * @param serial
- * @retval None
- */
- static int lpc845_uart_getc(struct rt_serial_device *serial)
- {
- int ch = -1;
- RT_ASSERT(serial != RT_NULL);
- if(USART_GetStatusFlags(USART0)&kUSART_RxReady)
- {
- ch = (int)USART0->RXDAT;
- }
-
- return ch;
- }
- /**
- * Uart common interrupt process. This need add to uart ISR.
- *
- * @param serial serial device
- */
- static void LPC845_UART_IRQHandler(struct rt_serial_device *serial)
- {
- struct lpc845_uart *uart = (struct lpc845_uart *) serial->parent.user_data;
- RT_ASSERT(uart != RT_NULL);
-
- if(USART_GetStatusFlags(USART0)&kUSART_RxReady)
- {
- rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
- }
- }
- static const struct rt_uart_ops lpc845_uart_ops =
- {
- .configure = lpc845_uart_configure,
- .control = lpc845_uart_control,
- .putc = lpc845_uart_putc,
- .getc = lpc845_uart_getc,
- RT_NULL,
- };
- /**
- * @brief uart init
- * @param None
- * @retval None
- */
- int rt_hw_usart_init(void)
- {
- struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
- int i;
- int result;
- for (i = 0; i < sizeof(uart_obj) / sizeof(uart_obj[0]); i++)
- {
- uart_obj[i].serial->ops = &lpc845_uart_ops;
- uart_obj[i].serial->config = config;
- /* register UART1 device */
- result = rt_hw_serial_register(uart_obj[i].serial,
- uart_obj[i].device_name,
- RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
- (void *)&uart_obj[i]);
- RT_ASSERT(result == RT_EOK);
- }
- return result;
- }
- INIT_BOARD_EXPORT(rt_hw_usart_init);
- #endif
复制代码
2.2.5 applications目录下scons 配置
此目录下编写main 函数代码通过上述的gpio 驱动结构周期的点亮板子的led,测试代码如下。
- /*
- * Copyright (c) 2006-2022, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2021-08-20 BruceOu first implementation
- */
- #include <stdio.h>
- #include <rtthread.h>
- #include <rtdevice.h>
- #include <board.h>
- #include <drivers/pin.h>
- int main(void)
- {
- int count = 1;
- rt_base_t pin = rt_pin_get("P1.12");
- rt_pin_mode(pin,PIN_MODE_OUTPUT);
- while (count++)
- {
- rt_pin_write(pin,1);
- rt_thread_mdelay(500);
- rt_pin_write(pin,0);
- rt_thread_mdelay(500);
- }
- return RT_EOK;
- }
复制代码
3 生成IAR 工程验证
以上配置完成后既可以通过scons --target=iar 生成IAR 工程,执行后会在bsp 目录下生成对应的IAR 工程。
图 3.1
打开工程后对应的RT-thread kernel,SDK,及驱动程程序已经按照我们配置的方式加入工程了,生成的工程如下。
图 3.2
生成的工程编译通过后将程序下载到板卡内运行,发现板子的LED 按照预期的方式闪烁,串口也可以正常响应输入命令,至此RT-thread 最小系统已经跑起来了。
系统运行起来后,输入free 命令查看系统堆空间的使用情况发现,只剩余248字节了,这已经是减小main task 和shell task的任务栈空间后的尺寸,8KB的内存剩余空间已经不是很充足,移植RT-thread 主要目的还是学习对应的丰富的组件及驱动框架,后续会使用手里的S32K146的板子板子相对memory资源充足,外设也比较丰富,来适配rt-threa系统继续深入学习。
|