查看: 285|回复: 0

[原创] 【LPC860-max板卡试用】rt-thread 最小系统适配

[复制链接]
  • TA的每日心情
    奋斗
    14 小时前
  • 签到天数: 595 天

    [LV.9]以坛为家II

    51

    主题

    2225

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    7072
    最后登录
    2024-4-28
    发表于 2024-1-1 22:51:53 | 显示全部楼层 |阅读模式
    本帖最后由 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 的启动流程,方便我们移植理解系统启动流程。
    启动流程.png



    1.创建 lpc860-max bsp 目录

          更新RT-thread 代码库bsp 目录下没有lpc865 的板卡,我们创建个lpcxpresso860_max 目录并把官方的sdk 软件包放到该目录下待用,参照其他bsp目录结构创建drivers/applications/board 文件夹分别用于防止适配rt-thread 驱动框架的驱动,应用程序及板级初始化程序。

    1_bsp.png

    图1.1

    2.添加kconfig 文件

        RT-thread 是个高度可裁剪的系统,配置工具使用的是kconfig 工具,在bsp 目录下执行menuconfig 命令图,通过形界面的方式进行配置,我们参照其他bsp ,本地参照的是gd32 的kconfig 将对应的文件拷贝至新建的lpcxpresso860_max bsp 目录下,kconfig 内容如下:
    1. mainmenu "RT-Thread Configuration"

    2. config BSP_DIR
    3.     string
    4.     option env="BSP_ROOT"
    5.     default "."

    6. config RTT_DIR
    7.     string
    8.     option env="RTT_ROOT"
    9.     default "../.."

    10. config PKGS_DIR
    11.     string
    12.     option env="PKGS_ROOT"
    13.     default "packages"

    14. source "$RTT_DIR/Kconfig"
    15. source "$PKGS_DIR/Kconfig"
    16. source "board/Kconfig"
    复制代码

    以上配置文件配置了BSP_ROOT/PKGS_ROOT/RTT_ROOT 路径,并引用了 "$RTT_DIR/Kconfig"/"$PKGS_DIR/Kconfig"/"board/Kconfig"  文件,其中"board/Kconfig" 文件配置片上资源配置,shell 使用串口资源是通过此配置文件来配置,我们参照gd32 的配置添加如下配置文件。
    1. menu "Hardware Drivers Config"

    2. config SOC_SERIES_LPC86X
    3.     bool
    4.     default y

    5. config SOC_LPC860MAX
    6.     bool
    7.     select SOC_SERIES_LPC86X
    8.     select RT_USING_COMPONENTS_INIT
    9.     select RT_USING_USER_MAIN
    10.     default y

    11. menu "Onboard Peripheral Drivers"

    12. endmenu

    13. menu "On-chip Peripheral Drivers"

    14.     config BSP_USING_GPIO
    15.         bool "Enable GPIO"
    16.         select RT_USING_PIN
    17.         default y

    18.     menuconfig BSP_USING_UART
    19.         bool "Enable UART"
    20.         default y
    21.         select RT_USING_SERIAL
    22.         if BSP_USING_UART
    23.             config BSP_USING_UART0
    24.                 bool "Enable UART0"
    25.                 default n

    26.             config BSP_UART0_RX_USING_DMA
    27.                 bool "Enable UART0 RX DMA"
    28.                 depends on BSP_USING_UART0
    29.                 select RT_SERIAL_USING_DMA
    30.                 default n

    31.             config BSP_USING_UART1
    32.                 bool "Enable UART1"
    33.                 default y

    34.             config BSP_UART1_RX_USING_DMA
    35.                 bool "Enable UART1 RX DMA"
    36.                 depends on BSP_USING_UART1
    37.                 select RT_SERIAL_USING_DMA
    38.                 default n
    39.         endif
    40. endmenu

    41. menu "Board extended module Drivers"

    42. endmenu

    43. endmenu
    复制代码
    上述配置通过的结构和menuconfig  下 Hardware Drivers Config 菜单下下配置,配置截图如下。


    board.jpg
    2.scons 配置
          RT-thread 的工程配置及文件管理是通过scons 脚本控制的,我们只需要配置需要编译的文件就可以通过scans 命令自动生成IAR/MDK/GCC 的配置工程, 我们本次试验使用的是IAR 的工程,其他工程的实现也是类似。


    2.1 IAR 工程模板文件创建


            在对应的BSP 目录下添加 template.ewp 工程模板文件,更新模板文件的Debug/Release 配置下的CPU 型号及链接脚本路径后并保存即可,本地配置的如下。
    2..11.jpg

    图2.1.1

    2.1.2.jpg

    图2.1.2



    2.2 工程配置
    2.2.1 bsp 根目录下scons 配置

    参照其他BSP 目录下的结构添加如下三个文件至bsp 根目录下:
    SConstruct:
    1. import os
    2. import sys
    3. import rtconfig

    4. if os.getenv('RTT_ROOT'):
    5.     RTT_ROOT = os.getenv('RTT_ROOT')
    6. else:
    7.     RTT_ROOT = os.path.normpath(os.getcwd() + '/../..')

    8. sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')]
    9. try:
    10.     from building import *
    11. except:
    12.     print('Cannot found RT-Thread root directory, please check RTT_ROOT')
    13.     print(RTT_ROOT)
    14.     exit(-1)

    15. TARGET = 'rtthread.' + rtconfig.TARGET_EXT

    16. DefaultEnvironment(tools=[])
    17. env = Environment(tools = ['mingw'],
    18.     AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS,
    19.     CC = rtconfig.CC, CCFLAGS = rtconfig.CFLAGS,
    20.     AR = rtconfig.AR, ARFLAGS = '-rc',
    21.     CXX = rtconfig.CXX, CXXFLAGS = rtconfig.CXXFLAGS,
    22.     LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS)
    23. env.PrependENVPath('PATH', rtconfig.EXEC_PATH)

    24. if rtconfig.PLATFORM in ['iccarm']:
    25.     env.Replace(CCCOM = ['$CC $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -o $TARGET $SOURCES'])
    26.     env.Replace(ARFLAGS = [''])
    27.     env.Replace(LINKCOM = env["LINKCOM"] + ' --map rtthread.map')

    28. Export('RTT_ROOT')
    29. Export('rtconfig')

    30. SDK_ROOT = os.path.abspath('.')

    31. if os.path.exists(SDK_ROOT + '/SDK_2_13_0_LPCXpresso860MAX'):
    32.     libraries_path_prefix = SDK_ROOT + '/SDK_2_13_0_LPCXpresso860MAX'
    33. else:
    34.     libraries_path_prefix = os.path.dirname(SDK_ROOT) + '/SDK_2_13_0_LPCXpresso860MAX'

    35. SDK_LIB = libraries_path_prefix
    36. Export('SDK_LIB')

    37. # prepare building environment
    38. objs = PrepareBuilding(env, RTT_ROOT, has_libcpu=False)

    39. # make a building
    40. DoBuilding(TARGET, objs)
    复制代码
    SConscript:
    1. # for module compiling
    2. import os
    3. Import('RTT_ROOT')
    4. from building import *

    5. cwd = GetCurrentDir()
    6. objs = []
    7. list = os.listdir(cwd)

    8. for d in list:
    9.     path = os.path.join(cwd, d)
    10.     if os.path.isfile(os.path.join(path, 'SConscript')):
    11.         objs = objs + SConscript(os.path.join(d, 'SConscript'))

    12. Return('objs')
    复制代码
    rtconfig.py
    1. import os

    2. # toolchains options
    3. ARCH='arm'
    4. CPU='cortex-m0'
    5. CROSS_TOOL='keil'

    6. # bsp lib config
    7. BSP_LIBRARY_TYPE = None

    8. if os.getenv('RTT_CC'):
    9.     CROSS_TOOL = os.getenv('RTT_CC')
    10. if os.getenv('RTT_ROOT'):
    11.     RTT_ROOT = os.getenv('RTT_ROOT')

    12. # cross_tool provides the cross compiler
    13. # EXEC_PATH is the compiler execute path, for example, CodeSourcery, Keil MDK, IAR
    14. if  CROSS_TOOL == 'gcc':
    15.     PLATFORM    = 'gcc'
    16.     EXEC_PATH   = r'C:\Users\XXYYZZ'
    17. elif CROSS_TOOL == 'keil':
    18.     PLATFORM    = 'armcc'
    19.     EXEC_PATH   = r'C:/Keil_v5'
    20. elif CROSS_TOOL == 'iar':
    21.     PLATFORM = 'iccarm'
    22.     EXEC_PATH   = r'C:/Program Files (x86)/IAR Systems/Embedded Workbench 8.3'

    23. if os.getenv('RTT_EXEC_PATH'):
    24.     EXEC_PATH = os.getenv('RTT_EXEC_PATH')

    25. BUILD = 'debug'

    26. if PLATFORM == 'gcc':
    27.     # toolchains
    28.     PREFIX = 'arm-none-eabi-'
    29.     CC = PREFIX + 'gcc'
    30.     AS = PREFIX + 'gcc'
    31.     AR = PREFIX + 'ar'
    32.     CXX = PREFIX + 'g++'
    33.     LINK = PREFIX + 'gcc'
    34.     TARGET_EXT = 'elf'
    35.     SIZE = PREFIX + 'size'
    36.     OBJDUMP = PREFIX + 'objdump'
    37.     OBJCPY = PREFIX + 'objcopy'

    38.     DEVICE = ' -mcpu=cortex-m0 -mthumb -ffunction-sections -fdata-sections'
    39.     CFLAGS = DEVICE
    40.     AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp'
    41.     LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=rtthread-lpc824.map,-cref,-u,Reset_Handler -T lpc824_rom.ld'

    42.     CPATH = ''
    43.     LPATH = ''

    44.     if BUILD == 'debug':
    45.         CFLAGS += ' -O0 -gdwarf-2'
    46.         AFLAGS += ' -gdwarf-2'
    47.     else:
    48.         CFLAGS += ' -O2'

    49.     CXXFLAGS = CFLAGS

    50.     POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.bin\n' + SIZE + ' $TARGET \n'

    51. elif PLATFORM == 'armcc':
    52.     # toolchains
    53.     CC = 'armcc'
    54.     CXX = 'armcc'
    55.     AS = 'armasm'
    56.     AR = 'armar'
    57.     LINK = 'armlink'
    58.     TARGET_EXT = 'axf'

    59.     DEVICE = ' --cpu Cortex-M0+'
    60.     CFLAGS = DEVICE + ' --apcs=interwork'
    61.     AFLAGS = DEVICE
    62.     LFLAGS = DEVICE + ' --info sizes --info totals --info unused --info veneers --list rtthread-lpc824.map --scatter lpc824_rom.sct'

    63.     CFLAGS += ' -D__MICROLIB '
    64.     AFLAGS += ' --pd "__MICROLIB SETA 1" '
    65.     LFLAGS += ' --library_type=microlib '
    66.     EXEC_PATH += '/ARM/ARMCC/bin/'

    67.     if BUILD == 'debug':
    68.         CFLAGS += ' -g -O0'
    69.         AFLAGS += ' -g'
    70.     else:
    71.         CFLAGS += ' -O2'

    72.     CXXFLAGS = CFLAGS
    73.     CFLAGS += ' -std=c99'

    74.     POST_ACTION = 'fromelf --bin $TARGET --output rtthread.bin \nfromelf -z $TARGET'

    75. elif PLATFORM == 'iccarm':
    76.     # toolchains
    77.     CC = 'iccarm'
    78.     CXX = 'iccarm'
    79.     AS = 'iasmarm'
    80.     AR = 'iarchive'
    81.     LINK = 'ilinkarm'
    82.     TARGET_EXT = 'out'

    83.     DEVICE = '-Dewarm'
    84.     #DEVICE = ' -D USE_STDPERIPH_DRIVER' + ' -D GD32F407xK'

    85.     CFLAGS = DEVICE
    86.     CFLAGS += ' --diag_suppress Pa050'
    87.     CFLAGS += ' --no_cse'
    88.     CFLAGS += ' --no_unroll'
    89.     CFLAGS += ' --no_inline'
    90.     CFLAGS += ' --no_code_motion'
    91.     CFLAGS += ' --no_tbaa'
    92.     CFLAGS += ' --no_clustering'
    93.     CFLAGS += ' --no_scheduling'
    94.     CFLAGS += ' --endian=little'
    95.     CFLAGS += ' --cpu=Cortex-M0'
    96.     CFLAGS += ' -e'
    97.     CFLAGS += ' --fpu=None'
    98.     CFLAGS += ' --dlib_config "' + EXEC_PATH + '/arm/INC/c/DLib_Config_Normal.h"'
    99.     CFLAGS += ' -Ol'
    100.     CFLAGS += ' --use_c++_inline'

    101.     AFLAGS = DEVICE
    102.     AFLAGS += ' -s+'
    103.     AFLAGS += ' -w+'
    104.     AFLAGS += ' -r'
    105.     AFLAGS += ' --cpu Cortex-M0'
    106.     AFLAGS += ' --fpu None'

    107.     LFLAGS = ' --config "Libraries/iar/LPC845_flash.icf"'
    108.     LFLAGS += ' --redirect _Printf=_PrintfTiny'
    109.     LFLAGS += ' --redirect _Scanf=_ScanfSmall'
    110.     LFLAGS += ' --entry __iar_program_start'

    111.     CXXFLAGS = CFLAGS
    112.    
    113.     EXEC_PATH = EXEC_PATH + '/arm/bin/'
    114.     POST_ACTION = 'ielftool --bin $TARGET rtthread.bin'

    115. def dist_handle(BSP_ROOT, dist_dir):
    116.     import sys
    117.     cwd_path = os.getcwd()
    118.     sys.path.append(os.path.join(os.path.dirname(BSP_ROOT), 'tools'))
    119.     from sdk_dist import dist_do_building
    120.     dist_do_building(BSP_ROOT, dist_dir)
    复制代码

    2.2.2 SDK 目录下scons 配置按照上面的方法将SDK 的驱动文件加入scons 配置脚本。
    1. import rtconfig
    2. from building import *

    3. # get current directory
    4. cwd = GetCurrentDir()

    5. # The set of source files associated with this SConscript file.

    6. src = ['devices/LPC865/drivers/fsl_acomp.c']
    7. src += ['devices/LPC865/drivers/fsl_adc.c']
    8. src += ['devices/LPC865/drivers/fsl_clock.c']
    9. src += ['devices/LPC865/drivers/fsl_common.c']
    10. src += ['devices/LPC865/drivers/fsl_common_arm.c']
    11. src += ['devices/LPC865/drivers/fsl_crc.c']
    12. src += ['devices/LPC865/drivers/fsl_ftm.c']
    13. src += ['devices/LPC865/drivers/fsl_dma.c']
    14. src += ['devices/LPC865/drivers/fsl_gpio.c']
    15. src += ['devices/LPC865/drivers/fsl_i2c.c']
    16. src += ['devices/LPC865/drivers/fsl_i2c_dma.c']
    17. src += ['devices/LPC865/drivers/fsl_i3c.c']
    18. src += ['devices/LPC865/drivers/fsl_i3c_dma.c']
    19. src += ['devices/LPC865/drivers/fsl_iap.c']
    20. src += ['devices/LPC865/drivers/fsl_inputmux.c']
    21. src += ['devices/LPC865/drivers/fsl_mrt.c']
    22. src += ['devices/LPC865/drivers/fsl_pint.c']
    23. src += ['devices/LPC865/drivers/fsl_power.c']
    24. src += ['devices/LPC865/drivers/fsl_reset.c']
    25. src += ['devices/LPC865/drivers/fsl_spi.c']
    26. src += ['devices/LPC865/drivers/fsl_swm.c']
    27. src += ['devices/LPC865/drivers/fsl_syscon.c']
    28. src += ['devices/LPC865/drivers/fsl_usart.c']
    29. src += ['devices/LPC865/drivers/fsl_wkt.c']
    30. src += ['devices/LPC865/drivers/fsl_wwdt.c']
    31. src += ['devices/LPC865/drivers/fsl_syscon.c']
    32. src += ['devices/LPC865/drivers/fsl_usart.c']
    33. src += ['devices/LPC865/drivers/fsl_wkt.c']
    34. src += ['devices/LPC865/drivers/fsl_wwdt.c']
    35. src += ['devices/LPC865/system_LPC865.c']

    36. path = [
    37.     cwd + '/CMSIS/Core/Include',
    38.     cwd + '/devices/LPC865',
    39.     cwd + '/devices/LPC865/drivers',]

    40. CPPDEFINES = ['CPU_LPC865M201JBD64']

    41. group = DefineGroup('Libraries', src, depend = [''], CPPPATH = path, CPPDEFINES = CPPDEFINES)

    42. Return('group')
    复制代码
    2.2.3 board 根目录下scons 配置
            board  目录下我们通过MCUXpresso IDE 生成的时钟及pin 相关代码复制到board 目录下,加入工程编译,在board 目录下添加SConscript文件内容如下:
    1. import os
    2. import rtconfig
    3. from building import *

    4. Import('SDK_LIB')

    5. cwd = GetCurrentDir()

    6. # add general drivers
    7. src = Split('''
    8. board.c
    9. clock_config.c
    10. pin_mux.c
    11. ''')

    12. path =  [cwd]

    13. startup_path_prefix = SDK_LIB

    14. if rtconfig.PLATFORM in ['gcc']:
    15.     src += [startup_path_prefix + '/devices/LPC865/gcc/startup_LPC865.s']
    16. elif rtconfig.PLATFORM in ['armcc', 'armclang']:
    17.     src += [startup_path_prefix + '/devices/LPC865/arm/startup_LPC865.s']
    18. elif rtconfig.PLATFORM in ['iccarm']:
    19.     src += [startup_path_prefix + '/devices/LPC865/iar/startup_LPC865.s']

    20. group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path)

    21. 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 代码如下:
    1. #include <rtdevice.h>
    2. #include <rthw.h>
    3. #include <rtconfig.h>

    4. #ifdef RT_USING_PIN

    5. #include "fsl_device_registers.h"
    6. #include "fsl_iocon.h"
    7. #include "fsl_gpio.h"

    8. #define SCON_INDEX(offset) ((offset)/0x04u)

    9. #define PIN_NUM(port, no) (((((port) & 0x1u) << 5) | ((no) & 0x1Fu)))


    10. #define LPC8XX_PIN(index, port, pin,iocon) {index, port, pin, iocon}

    11. struct pin_index
    12. {
    13.     int8_t index;
    14.     uint8_t port;
    15.     uint8_t pin;
    16.     uint8_t iocon;
    17. };

    18. static const struct pin_index pins[] =
    19. {
    20.     LPC8XX_PIN(0,0,0,SCON_INDEX(0x044u)), /* PIO0_0 */
    21.     LPC8XX_PIN(1,0,1,SCON_INDEX(0x02cu)),
    22.     LPC8XX_PIN(2,0,2,SCON_INDEX(0x018u)),
    23.     LPC8XX_PIN(3,0,3,SCON_INDEX(0x014u)),
    24.     LPC8XX_PIN(4,0,4,SCON_INDEX(0x010u)),
    25.     LPC8XX_PIN(5,0,5,SCON_INDEX(0x00cu)),
    26.     LPC8XX_PIN(6,0,6,SCON_INDEX(0x040u)),
    27.     LPC8XX_PIN(7,0,7,SCON_INDEX(0x03cu)),
    28.     LPC8XX_PIN(8,0,8,SCON_INDEX(0x038u)),
    29.     LPC8XX_PIN(9,0,9,SCON_INDEX(0x034u)),
    30.     LPC8XX_PIN(10,0,10,SCON_INDEX(0x020u)),
    31.     LPC8XX_PIN(11,0,11,SCON_INDEX(0x01cu)),
    32.     LPC8XX_PIN(12,0,12,SCON_INDEX(0x008u)),
    33.     LPC8XX_PIN(13,0,13,SCON_INDEX(0x004u)),
    34.     LPC8XX_PIN(14,0,14,SCON_INDEX(0x048u)),
    35.     LPC8XX_PIN(15,0,15,SCON_INDEX(0x028u)),
    36.     LPC8XX_PIN(16,0,16,SCON_INDEX(0x024u)),
    37.     LPC8XX_PIN(17,0,17,SCON_INDEX(0x000u)),
    38.     LPC8XX_PIN(18,0,18,SCON_INDEX(0x078u)),
    39.     LPC8XX_PIN(19,0,19,SCON_INDEX(0x074u)),
    40.     LPC8XX_PIN(20,0,20,SCON_INDEX(0x070u)),
    41.     LPC8XX_PIN(21,0,21,SCON_INDEX(0x06cu)),
    42.     LPC8XX_PIN(22,0,22,SCON_INDEX(0x068u)),
    43.     LPC8XX_PIN(23,0,23,SCON_INDEX(0x064u)),
    44.     LPC8XX_PIN(24,0,24,SCON_INDEX(0x060u)),
    45.     LPC8XX_PIN(25,0,25,SCON_INDEX(0x05cu)),
    46.     LPC8XX_PIN(26,0,26,SCON_INDEX(0x058u)),
    47.     LPC8XX_PIN(27,0,27,SCON_INDEX(0x054u)),
    48.     LPC8XX_PIN(28,0,28,SCON_INDEX(0x050u)),
    49.     LPC8XX_PIN(29,0,29,SCON_INDEX(0x0c8u)),
    50.     LPC8XX_PIN(30,0,30,SCON_INDEX(0x0ccu)),
    51.     LPC8XX_PIN(31,0,31,SCON_INDEX(0x08cu)),
    52.     LPC8XX_PIN(32,1,0,SCON_INDEX(0x090u)),
    53.     LPC8XX_PIN(33,1,1,SCON_INDEX(0x094u)),
    54.     LPC8XX_PIN(34,1,2,SCON_INDEX(0x098u)),
    55.     LPC8XX_PIN(35,1,3,SCON_INDEX(0x0a4u)),
    56.     LPC8XX_PIN(36,1,4,SCON_INDEX(0x0a8u)),
    57.     LPC8XX_PIN(37,1,5,SCON_INDEX(0x0acu)),
    58.     LPC8XX_PIN(38,1,6,SCON_INDEX(0x0b8u)),
    59.     LPC8XX_PIN(39,1,7,SCON_INDEX(0x0c4u)),
    60.     LPC8XX_PIN(40,1,8,SCON_INDEX(0x07cu)),
    61.     LPC8XX_PIN(41,1,9,SCON_INDEX(0x080u)),
    62.     LPC8XX_PIN(42,1,10,SCON_INDEX(0x0dcu)),
    63.     LPC8XX_PIN(43,1,11,SCON_INDEX(0x0d8u)),
    64.     LPC8XX_PIN(44,1,12,SCON_INDEX(0x084u)),
    65.     LPC8XX_PIN(45,1,13,SCON_INDEX(0x088u)),
    66.     LPC8XX_PIN(46,1,14,SCON_INDEX(0x09cu)),
    67.     LPC8XX_PIN(47,1,15,SCON_INDEX(0x0a0u)),
    68.     LPC8XX_PIN(48,1,16,SCON_INDEX(0x0b0u)),
    69.     LPC8XX_PIN(49,1,17,SCON_INDEX(0x0b4u)),
    70.     LPC8XX_PIN(50,1,18,SCON_INDEX(0x0bcu)),
    71.     LPC8XX_PIN(51,1,19,SCON_INDEX(0x0c0u)),
    72.     LPC8XX_PIN(52,1,20,SCON_INDEX(0x0d0u)),
    73.     LPC8XX_PIN(53,1,21,SCON_INDEX(0x0d4u))
    74. };

    75. #define ITEM_NUM(items) sizeof(items) / sizeof(items[0])


    76. /**
    77.   * @brief  pin get
    78.   * @param  name P0.1
    79.   * @retval pin number
    80.   */
    81. static rt_base_t lpc8xx_pin_get(const char * name)
    82. {
    83.     int pin = 0;
    84.     int hw_port_num, hw_pin_num = 0;
    85.     int i, name_len;

    86.     name_len = strlen(name);

    87.     if ((name_len < 4) || (name_len >= 6))
    88.     {
    89.         return -1;
    90.     }
    91.    
    92.     if ((name[0] != 'P') || (name[2] != '.'))
    93.     {
    94.         return -1;
    95.     }
    96.    
    97.     if ((name[1] >= '0') && (name[1] <= '1'))
    98.     {
    99.         hw_port_num = (int)(name[1] - '0');
    100.     }
    101.     else
    102.     {
    103.         return -1;
    104.     }
    105.    
    106.     for (i = 3; i < name_len; i++)
    107.     {
    108.         hw_pin_num *= 10;
    109.         hw_pin_num += name[i] - '0';
    110.     }

    111.     pin = PIN_NUM(hw_port_num, hw_pin_num);

    112.     return pin;

    113. }



    114. /**
    115.   * @brief  get pin
    116.   * @param  pin
    117.   * @retval None
    118.   */
    119. const struct pin_index *get_pin(uint8_t pin)
    120. {
    121.     const struct pin_index *index;

    122.     if (pin < ITEM_NUM(pins))
    123.     {
    124.         index = &pins[pin];
    125.         if (index->index == -1)
    126.         index = NULL;
    127.     }
    128.     else
    129.     {
    130.         index = NULL;
    131.     }

    132.     return index;
    133. }


    134. /**
    135.   * @brief  set pin mode
    136.   * @param  pin, mode
    137.   * @retval None
    138.   */
    139. static void lpc8xx_pin_mode(rt_device_t dev, rt_base_t pin, rt_uint8_t mode)
    140. {
    141.     const struct pin_index *index = NULL;

    142.     index = get_pin(pin);
    143.     if (index == NULL)
    144.     {
    145.         return;
    146.     }

    147.     switch(mode)
    148.     {
    149.     case PIN_MODE_OUTPUT:
    150.         IOCON_PinMuxSet(IOCON,index->iocon,IOCON_MODE_PULLUP);
    151.         GPIO_PinInit(GPIO, index->port, index->pin, &(gpio_pin_config_t){kGPIO_DigitalOutput, (0)});
    152.         break;
    153.     case PIN_MODE_OUTPUT_OD:
    154.         IOCON_PinMuxSet(IOCON,index->iocon,IOCON_OPENDRAIN_EN);
    155.         GPIO_PinInit(GPIO, index->port, index->pin, &(gpio_pin_config_t){kGPIO_DigitalOutput, (0)});
    156.         break;
    157.     case PIN_MODE_INPUT:
    158.         GPIO_PinInit(GPIO, index->port, index->pin, &(gpio_pin_config_t){kGPIO_DigitalInput, (0)});
    159.         break;
    160.     case PIN_MODE_INPUT_PULLUP:
    161.         IOCON_PinMuxSet(IOCON,index->iocon,IOCON_MODE_PULLUP);
    162.         /* input setting: pull up. */
    163.         GPIO_PinInit(GPIO, index->port, index->pin, &(gpio_pin_config_t){kGPIO_DigitalInput, (0)});
    164.         break;
    165.     case PIN_MODE_INPUT_PULLDOWN:
    166.         IOCON_PinMuxSet(IOCON,index->iocon,IOCON_MODE_PULLDOWN);
    167.         /* input setting: pull down. */
    168.         GPIO_PinInit(GPIO, index->port, index->pin, &(gpio_pin_config_t){kGPIO_DigitalInput, (0)});
    169.         break;
    170.     default:
    171.         break;
    172.     }
    173. }


    174. /**
    175.   * @brief  pin write
    176.   * @param   pin, valuie
    177.   * @retval None
    178.   */
    179. static void lpc8xx_pin_write(rt_device_t dev, rt_base_t pin, rt_uint8_t value)
    180. {
    181.     const struct pin_index *index = NULL;

    182.     index = get_pin(pin);
    183.     if (index == NULL)
    184.     {
    185.         return;
    186.     }

    187.     GPIO_PinWrite(GPIO,index->port,index->pin,(uint8_t)value);
    188. }



    189. /**
    190.   * @brief  pin read
    191.   * @param  dev, pin
    192.   * @retval None
    193.   */
    194. static rt_int8_t lpc8xx_pin_read(rt_device_t dev, rt_base_t pin)
    195. {
    196.     int value = PIN_LOW;
    197.     const struct pin_index *index = NULL;

    198.     index = get_pin(pin);
    199.     if (index == NULL)
    200.     {
    201.         return value;
    202.     }

    203.     value = GPIO_PinRead(GPIO,index->port,index->pin);
    204.     return value;
    205. }


    206. const static struct rt_pin_ops lpc8xx_pin_ops =
    207. {
    208.     .pin_mode = lpc8xx_pin_mode,
    209.     .pin_write = lpc8xx_pin_write,
    210.     .pin_read = lpc8xx_pin_read,
    211.     .pin_get = lpc8xx_pin_get,
    212.     .pin_attach_irq = RT_NULL,
    213.     .pin_detach_irq= RT_NULL,
    214.     .pin_irq_enable = RT_NULL,
    215. };


    216. int rt_hw_pin_init(void)
    217. {
    218.     int result;

    219.     result = rt_device_pin_register("pin", &lpc8xx_pin_ops, RT_NULL);

    220.     return result;
    221. }

    222. INIT_BOARD_EXPORT(rt_hw_pin_init);

    223. #endif
    复制代码


    drv_uart.c 代码如下:
    1. /*
    2. * Copyright (c) 2006-2022, RT-Thread Development Team
    3. *
    4. * SPDX-License-Identifier: Apache-2.0
    5. *
    6. * Change Logs:
    7. * Date           Author       Notes
    8. * 2021-08-20     BruceOu      first implementation
    9. */

    10. #include "drv_usart.h"

    11. #ifdef RT_USING_SERIAL

    12. #if !defined(BSP_USING_UART0)
    13. #error "Please define at least one UARTx"
    14. #endif

    15. #include <rtdevice.h>

    16. static void LPC845_UART_IRQHandler(struct rt_serial_device *serial);

    17. #if defined(BSP_USING_UART0)
    18. struct rt_serial_device serial0;

    19. void USART0_IRQHandler(void)
    20. {
    21.     /* enter interrupt */
    22.     rt_interrupt_enter();

    23.     LPC845_UART_IRQHandler(&serial0);

    24.     /* leave interrupt */
    25.     rt_interrupt_leave();
    26. }

    27. #endif /* BSP_USING_UART0 */


    28. static const struct lpc845_uart uart_obj[] = {
    29.     #ifdef BSP_USING_UART0
    30.     {
    31.         USART0,                                 // uart peripheral index
    32.         USART0_IRQn,                            // uart iqrn
    33.         &serial0,
    34.         "uart0",
    35.     },
    36.     #endif
    37. };


    38. /**
    39. * @brief UART MSP Initialization
    40. *        This function configures the hardware resources used in this example:
    41. *           - Peripheral's clock enable
    42. *           - Peripheral's GPIO Configuration
    43. *           - NVIC configuration for UART interrupt request enable
    44. * @param huart: UART handle pointer
    45. * @retval None
    46. */
    47. void lpc845_uart_gpio_init(struct lpc845_uart *uart)
    48. {
    49.         
    50.     /* init uart recive ring buffer */
    51.     NVIC_SetPriority(uart->irqn, 0);
    52.     NVIC_EnableIRQ(uart->irqn);
    53. }

    54. /**
    55.   * @brief  uart configure
    56.   * @param  serial, cfg
    57.   * @retval None
    58.   */
    59. static rt_err_t lpc845_uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
    60. {
    61.     struct lpc845_uart *uart;
    62.     status_t status;
    63.     usart_config_t usartConfig;

    64.     RT_ASSERT(serial != RT_NULL);
    65.     RT_ASSERT(cfg != RT_NULL);

    66.     uart = (struct lpc845_uart *)serial->parent.user_data;

    67.     /* config usart struct */
    68.     USART_GetDefaultConfig(&usartConfig);
    69.     usartConfig.baudRate_Bps =  cfg->baud_rate;
    70.     usartConfig.bitCountPerChar = kUSART_8BitsPerChar;
    71.     usartConfig.parityMode = kUSART_ParityDisabled;
    72.     usartConfig.stopBitCount = kUSART_OneStopBit;
    73.     usartConfig.enableRx = true;
    74.     usartConfig.enableTx = true;

    75.     /* init usart */
    76.     status = USART_Init(USART0, &usartConfig, BOARD_DEBUG_USART_CLK_FREQ);

    77.     if (kStatus_Success != status)
    78.     {
    79.         return status;
    80.     }

    81.         lpc845_uart_gpio_init(uart);

    82.     /* enable usart rx interrupts */
    83.     USART_EnableInterrupts(USART0, kUSART_RxReadyInterruptEnable | kUSART_RxNoiseInterruptEnable);
    84.     NVIC_EnableIRQ(USART0_IRQn);

    85.     return RT_EOK;
    86. }

    87. /**
    88.   * @brief  uart control
    89.   * @param  serial, arg
    90.   * @retval None
    91.   */
    92. static rt_err_t lpc845_uart_control(struct rt_serial_device *serial, int cmd, void *arg)
    93. {
    94.     struct lpc845_uart *uart;

    95.     RT_ASSERT(serial != RT_NULL);
    96.     uart = (struct lpc845_uart *)serial->parent.user_data;

    97.     switch (cmd)
    98.     {
    99.     case RT_DEVICE_CTRL_CLR_INT:
    100.         /* disable rx irq */
    101.         NVIC_DisableIRQ(uart->irqn);
    102.         /* disable interrupt */
    103.         USART_DisableInterrupts(uart->uart_periph, kUSART_RxReadyInterruptEnable | kUSART_RxNoiseInterruptEnable);

    104.         break;
    105.     case RT_DEVICE_CTRL_SET_INT:
    106.         /* enable rx irq */
    107.         NVIC_EnableIRQ(uart->irqn);
    108.         /* enable interrupt */
    109.         USART_EnableInterrupts(uart->uart_periph, kUSART_RxReadyInterruptEnable | kUSART_RxNoiseInterruptEnable);
    110.         break;
    111.     }

    112.     return RT_EOK;
    113. }

    114. /**
    115.   * @brief  uart put char
    116.   * @param  serial, ch
    117.   * @retval None
    118.   */
    119. static int lpc845_uart_putc(struct rt_serial_device *serial, char ch)
    120. {
    121.     struct lpc845_uart *uart;

    122.     RT_ASSERT(serial != RT_NULL);
    123.     uart = (struct lpc845_uart *)serial->parent.user_data;

    124.     USART_WriteBlocking(uart->uart_periph,(uint8_t *)&ch,1);

    125.     return RT_EOK;
    126. }

    127. /**
    128.   * @brief  uart get char
    129.   * @param  serial
    130.   * @retval None
    131.   */
    132. static int lpc845_uart_getc(struct rt_serial_device *serial)
    133. {
    134.     int ch = -1;

    135.     RT_ASSERT(serial != RT_NULL);

    136.     if(USART_GetStatusFlags(USART0)&kUSART_RxReady)
    137.     {
    138.          ch = (int)USART0->RXDAT;
    139.     }
    140.      
    141.     return ch;
    142. }

    143. /**
    144. * Uart common interrupt process. This need add to uart ISR.
    145. *
    146. * @param serial serial device
    147. */

    148. static void LPC845_UART_IRQHandler(struct rt_serial_device *serial)
    149. {
    150.     struct lpc845_uart *uart = (struct lpc845_uart *) serial->parent.user_data;

    151.     RT_ASSERT(uart != RT_NULL);


    152.    
    153.     if(USART_GetStatusFlags(USART0)&kUSART_RxReady)
    154.     {
    155.         rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
    156.     }
    157. }

    158. static const struct rt_uart_ops lpc845_uart_ops =
    159. {
    160.     .configure = lpc845_uart_configure,
    161.     .control = lpc845_uart_control,
    162.     .putc = lpc845_uart_putc,
    163.     .getc = lpc845_uart_getc,
    164.     RT_NULL,
    165. };

    166. /**
    167.   * @brief  uart init
    168.   * @param  None
    169.   * @retval None
    170.   */
    171. int rt_hw_usart_init(void)
    172. {
    173.     struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
    174.     int i;

    175.     int result;

    176.     for (i = 0; i < sizeof(uart_obj) / sizeof(uart_obj[0]); i++)
    177.     {
    178.         uart_obj[i].serial->ops    = &lpc845_uart_ops;
    179.         uart_obj[i].serial->config = config;

    180.         /* register UART1 device */
    181.         result = rt_hw_serial_register(uart_obj[i].serial,
    182.                               uart_obj[i].device_name,
    183.                               RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
    184.                               (void *)&uart_obj[i]);
    185.         RT_ASSERT(result == RT_EOK);
    186.     }

    187.     return result;
    188. }

    189. INIT_BOARD_EXPORT(rt_hw_usart_init);

    190. #endif
    复制代码

    2.2.5 applications录下scons 配置

            此目录下编写main 函数代码通过上述的gpio 驱动结构周期的点亮板子的led,测试代码如下。

    1. /*
    2. * Copyright (c) 2006-2022, RT-Thread Development Team
    3. *
    4. * SPDX-License-Identifier: Apache-2.0
    5. *
    6. * Change Logs:
    7. * Date           Author       Notes
    8. * 2021-08-20     BruceOu      first implementation
    9. */

    10. #include <stdio.h>
    11. #include <rtthread.h>
    12. #include <rtdevice.h>
    13. #include <board.h>
    14. #include <drivers/pin.h>


    15. int main(void)
    16. {
    17.     int count = 1;
    18.     rt_base_t pin = rt_pin_get("P1.12");
    19.     rt_pin_mode(pin,PIN_MODE_OUTPUT);

    20.     while (count++)
    21.     {
    22.         rt_pin_write(pin,1);
    23.         rt_thread_mdelay(500);
    24.         rt_pin_write(pin,0);
    25.         rt_thread_mdelay(500);
    26.     }

    27.     return RT_EOK;
    28. }
    复制代码

    3 生成IAR 工程验证

    以上配置完成后既可以通过scons --target=iar 生成IAR 工程,执行后会在bsp 目录下生成对应的IAR 工程。

    3.1.jpg

    图 3.1

    打开工程后对应的RT-thread kernel,SDK,及驱动程程序已经按照我们配置的方式加入工程了,生成的工程如下。

    3.2.jpg

    图 3.2

    生成的工程编译通过后将程序下载到板卡内运行,发现板子的LED 按照预期的方式闪烁,串口也可以正常响应输入命令,至此RT-thread 最小系统已经跑起来了。

    dfd22ed0c975dc3ea8e4a41a5769f2aa[00-00-00--00-00-06].gif


    系统运行起来后,输入free 命令查看系统堆空间的使用情况发现,只剩余248字节了,这已经是减小main task 和shell  task的任务栈空间后的尺寸,8KB的内存剩余空间已经不是很充足,移植RT-thread 主要目的还是学习对应的丰富的组件及驱动框架,后续会使用手里的S32K146的板子板子相对memory资源充足,外设也比较丰富,来适配rt-threa系统继续深入学习。





    ****资料整理****

    RT-Thread编程手册.pdf (5.15 MB, 下载次数: 0)






    该会员没有填写今日想说内容.
    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2024-4-28 23:51 , Processed in 0.111068 second(s), 20 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

    快速回复 返回顶部 返回列表