RT-Thread学习

article/2025/8/25 21:53:56

一、入门

RT-Thread官网  官网文档   Rt-thread学习文档 
RT-Thread官方bilibili视频号   GD32官网
教你动手移植RT-Thread到国产MCU    如何移植RT-Thread到GD32单片机上(非studio版)
东方青讲RT-Thread  RT-Thread内核入门指南
RT-Thread Studio 教程
rtthread移植
野火rt-thread教程
RT-Thread-学习分析(详细版)huawei
RT-Thread-学习分析(详细版)csdn

二、启动流程

RT-THREAD 自动初始化详解
RT-Thread启动流程详解(硬件初始化篇)
RT-Thread的各种硬件、线程初始化过程
STM32 RT-Thread 系统分析(1)- 启动文件
RT-Thread学习笔记 --(1)RT-Thread开发环境搭建
RT-Thread学习笔记 --(2)RT-Thread启动过程分析
RT-Thread学习笔记 --(3)RT-Thread自动初始化机制分析
RT-Thread学习笔记 --(4)RT-Thread多线程学习总结
RT-Thread学习笔记 --(5)RT-Thread线程间同步学习总结
RT-Thread学习笔记 --(6)RT-Thread线程间通信学习总结
RT-Thread学习笔记 --(7)RT-Thread中断管理学习总结
RT-Thread学习笔记 --(8)RT-Thread时钟管理学习总结
RT-Thread学习笔记 --(9)RT-Thread内存管理学习总结
RT-Thread INIT_BOARD_EXPORT无效或进入不了导出的函数
进入这个界面,下面蓝色部分请添加:–keep .o(.rti_fn.)

RT-Thread的自动初始化依赖宏开关:RT_USING_COMPONENTS_INIT,分为6个等级,可以查看rtdef.h文件
使用INIT_APP_EXPORT(led_init)宏,初始化函数就会被自动初始化,不用在其他地方显式调用 led_init() 。


/* board init routines will be called in board_init() function */
#define INIT_BOARD_EXPORT(fn)           INIT_EXPORT(fn, "1")/* pre/device/component/env/app init routines will be called in init_thread */
/* components pre-initialization (pure software initilization) */
#define INIT_PREV_EXPORT(fn)            INIT_EXPORT(fn, "2")
/* device initialization */
#define INIT_DEVICE_EXPORT(fn)          INIT_EXPORT(fn, "3")
/* components initialization (dfs, lwip, ...) */
#define INIT_COMPONENT_EXPORT(fn)       INIT_EXPORT(fn, "4")
/* environment initialization (mount disk, ...) */
#define INIT_ENV_EXPORT(fn)             INIT_EXPORT(fn, "5")
/* appliation initialization (rtgui application etc ...) */
#define INIT_APP_EXPORT(fn)             INIT_EXPORT(fn, "6")
INIT_BOARD_EXPORT(key_gpio_init); /* 先执行 01 */
INIT_BOARD_EXPORT(drv_pm_hw_init); /* 02 */
INIT_BOARD_EXPORT(rt_hw_rtc_init); /* 03 */ 

在这里插入图片描述
在这里插入图片描述

  • rtthread_startup() 函数是 RT-Thread 规定的统一启动入口。启动调度器之前,系统所创建的线程在执行 rt_thread_startup() 后并不会立马运行,它们会处于就绪状态等待系统调度。MDK 的扩展功能 S u b Sub Sub$ 和 S u p e r Super Super$。
  • startup_stm32f103xe.s 开始-> components.c
    根据宏跳转到对应函数,如MDK: int S u b Sub Sub$main(void) ->int rtthread_startup(void)
    rtthread_startup:关闭中断 ->板级初始化 -> 打印版本信息-> 定时器初始化->调度器初始化 -> 信号初始化->创建初始化线程(main线程) -> 定时器线程初始化 -> 空闲线程初始化->启动调度器。

三、串口相关

RT thread 设备驱动组件之USART设备
Rtthread之串口初始化流程分析

rtthread串口接收不定长数据

四、finsh相关

剖析RT-Thread中console与finsh组件实现(1)
剖析RT-Thread中console与finsh组件实现(2)
剖析RT-Thread中console与finsh组件实现(3)

五、线程

5.1 线程使用

动态方法:rt_thread_create();rt_thread_delete();
静态方法:rt_thread_init();rt_thread_detach();真正开始运行多任务 rt_thread_startup(tid)

线程追寻函数原型:

静态:
rt_err_t rt_thread_init(struct rt_thread *thread,const char       *name,void (*entry)(void *parameter),void             *parameter,void             *stack_start,rt_uint32_t       stack_size,rt_uint8_t        priority,rt_uint32_t       tick);
动态:
rt_thread_t rt_thread_create(const char *name,void (*entry)(void *parameter),void       *parameter,rt_uint32_t stack_size,rt_uint8_t  priority,rt_uint32_t tick);

系统自带的线程创建实例:

void rt_application_init(void)
{rt_thread_t tid;
#ifdef RT_USING_HEAPtid = rt_thread_create("main", main_thread_entry, RT_NULL,RT_MAIN_THREAD_STACK_SIZE, RT_MAIN_THREAD_PRIORITY, 20);RT_ASSERT(tid != RT_NULL);
#elsert_err_t result;tid = &main_thread;result = rt_thread_init(tid, "main", main_thread_entry, RT_NULL,main_stack, sizeof(main_stack), RT_MAIN_THREAD_PRIORITY, 20);RT_ASSERT(result == RT_EOK);/* if not define RT_USING_HEAP, using to eliminate the warning */(void)result;
#endifrt_thread_startup(tid);
}

静态创建实例:

/*  变量分配4字节对齐 */
ALIGN(RT_ALIGN_SIZE)
/*  静态线程的 线程堆栈*/
static rt_uint8_t led_stack[512];
/* 静态线程的 线程控制块 */
static struct rt_thread led_thread;static void led_thread_entry(void *parameter)
{while(1){rt_thread_delay(RT_TICK_PER_SECOND / 2);}
]rt_err_t result;result = rt_thread_init(&led_thread, "led", led_thread_entry, RT_NULL,(rt_uint8_t *)&led_stack[0], sizeof(led_stack), 2, 5);
if(result==RT_EOK)
{rt_thread_startup(&main_thread);
}

动态创建实例:

static void dynamic_thread_entry(void* parameter);/* 动态线程的 线程控制块指针 */
rt_thread_t led2_thread;
/* 创建动态线程 : 堆栈大小512 bytes ,优先级 21 ,时间片 2个系统滴答 */
led2_thread = rt_thread_create("led2", dynamic_thread_entry, RT_NULL, 512, 21,2);
if (led2_thread != RT_NULL)rt_thread_startup(led2_thread);

官网给的实例:

static struct rt_thread thread1;
static rt_uint8_t thread1_stack[512];/* 线程 1 入口 */
void thread1_entry(void* parameter)
{int i;while (1){for (i = 0; i < 10; i ++){rt_kprintf("%d\n", i);/* 延时 100ms */rt_thread_mdelay(100);}}
}/* 线程 2 入口 */
void thread2_entry(void* parameter)
{int count = 0;while (1){rt_kprintf("Thread2 count:%d\n", ++count);/* 延时 50ms */rt_thread_mdelay(50);}
}/* 线程例程初始化 */
int thread_sample_init()
{rt_thread_t thread2_ptr;rt_err_t result;/* 初始化线程 1 *//* 线程的入口是 thread1_entry,参数是 RT_NULL* 线程栈是 thread1_stack* 优先级是 200,时间片是 10 个 OS Tick*/result = rt_thread_init(&thread1,"thread1",thread1_entry, RT_NULL,&thread1_stack[0], sizeof(thread1_stack),200, 10);/* 启动线程 */if (result == RT_EOK) rt_thread_startup(&thread1);/* 创建线程 2 *//* 线程的入口是 thread2_entry, 参数是 RT_NULL* 栈空间是 512,优先级是 250,时间片是 25 个 OS Tick*/thread2_ptr = rt_thread_create("thread2",thread2_entry, RT_NULL,512, 250, 25);/* 启动线程 */if (thread2_ptr != RT_NULL) rt_thread_startup(thread2_ptr);return 0;
}

5.2 线程同步

5.2.1 信号量

信号量使用

六、网络通信

SAL:(套接字抽象层)、 Socket Adapter Layer、Socket Abstraction Layer
rt-thread之网络设备与BSD套接字组件
rt-thread示例代码(TCP/UDP)

启用 BSD Socket 的方法是在 env 中输入 menuconfig,找到 SAL 组件,再选择使用 BSD Socket 接口。
各选项顺序:
RT-Thread Components —-> Network —-> Socket abstraction layer —-> Enable BSD socket operated by file system API

七、Kconfig语法

kconfig常用语法,入门必看
Kconfig 语法分析详解

7.1 config条目

config TMPFS_POSIX_ACLbool “Tmpfs POSIX Access Control Lists”depends on TMPFSselect GENERIC_ACLhelpPOSIX Access Control Lists (ACLs) support permissions for users and groups beyond the owner/group/world scheme.
  • config是关键字,表示一个配置选项的开始;紧跟着的TMPFS_POSIX_ACL是配置选项的名称,省略了前缀"CONFIG_"
  • bool表示变量类型,即"CONFIG_ TMPFS_POSIX_ACL "的类型,有5种类型:bool、tristate、string、hex和int,其中tristate和string是基本的类型
    bool变量的值: y和n
    tristate变量的值:y、n和m
    string变量的值: 字符串
  • bool之后的字符串“Tmpfs POSIX Access Control Lists”是提示信息(在上面的配置界面中就是通过它来识别CONFIG_TMPFS_POSIX_ACL),在配置界面中上下移动光标选中它时,就可以通过按空格或回车键来设置CONFIG_ TMPFS_POSIX_ACL的值(即选择了哪个值就会把该值赋值给CONFIG_TMPFS_POSIX_ACL)
  • depends on:表示依赖于XXX,“depends on TMPFS”表示只有当TMPFS配置选项被选中时,当前配置选项的提示信息才会出现,才能设置当前配置选项
  • select:是反向依赖关系的意思,即当前配置选项被选中,则GENERIC_ACL就会被选中。

7.2 menu

用于生成菜单名

menu "Floating point emulation"config FPE_NWFPE..............config FPE_NWFPE_XP.............
endmenu

7.3 choice条目

choice条目将多个类似的配置选项组合在一起,供用户单选或多选,这不同于menu条目

choiceprompt "soc x1000 codec type select"depends on SOC_X1000
config SND_ASOC_INGENIC_PHOENIX_ICDCtristate "Audio support for phoenix with internal codec"select SND_ASOC_DMA_V13select SND_ASOC_JZ_AIC_I2S_V13select SND_ASOC_JZ_ICDC_D3#select SND_ASOC_JZ_PCM_V13#select SND_ASOC_FIIO_PCM5242config SND_ASOC_INGENIC_PHOENIX_SPDIFtristate "Audio support for phoenix with spdif"select SND_ASOC_DMA_V13select SND_ASOC_JZ_AIC_SPDIF_V13select SND_ASOC_JZ_SPDIF_V13#select SND_ASOC_JZ_PCM_V13endchoice

7.4 comment条目

显示注释信息

menu “Floating point emulation”
comment “At least one emulation must be selected”
config FPE_NWFPE
...
config FPE_NWFPE_XP
endmenu

7.5 rt-thread中的Kconfig示例

mainmenu "RT-Thread Configuration"config $BSP_DIRstringoption env="BSP_ROOT"default "."config $RTT_DIRstringoption env="RTT_ROOT"default "../../rt-thread"# you can change the RTT_ROOT default "../.." to your rtthread_root,
# example : default "F:/git_repositories/rt-thread"config $PKGS_DIRstringoption env="PKGS_ROOT"default "packages"config $ENV_DIRstringoption env="ENV_ROOT"default "/"source "$RTT_DIR/Kconfig"
source "$PKGS_DIR/Kconfig"
source "$BSP_DIR/../../drivers/Kconfig"
source "$BSP_DIR/../../libraries/Kconfig"
menu "RT-Thread Kernel"config RT_NAME_MAXint "The maximal size of kernel object name"range 2 32default 8helpEach kernel object, such as thread, timer, semaphore etc, has a name,the RT_NAME_MAX is the maximal size of this object name.config RT_USING_SMPbool "Enable SMP(Symmetric multiprocessing)"default nhelpThis option should be selected by machines which have an SMP-capable CPU.The only effect of this option is to make the SMP-relatedoptions available to the user for configuration.# 太长了,省略。。。endmenu
config LCD_TRULY_TFT240240_2_E tristate "SLCD TRULY TFT240240-2-E with control IC st7789s (240x240)"depends on BACKLIGHT_CLASS_DEVICEdefault n

7.6 使用对照

1、config

//Kconfig中:
config BSP_USING_WDTbool "Enable Watchdog Timer"select RT_USING_WDTdefault nconfig RT_CONSOLE_DEVICE_NAMEstring "the device name for console"default "uart1"config BSP_I2C1_SCL_PINint "I2C1 scl pin number"range 1 176default 116//rtconfig.h中:
#define BSP_USING_WDT
#define RT_USING_WDT#define RT_CONSOLE_DEVICE_NAME "uart1"
#define BSP_I2C1_SCL_PIN 116

2、menu

menu "Hardware Drivers Config"config BSP_USING_COM2bool "Enable COM2 (uart2 pin conflict with Ethernet and PWM)"select BSP_USING_UARTselect BSP_USING_UART2default nconfig BSP_USING_COM3bool "Enable COM3 (uart3 pin conflict with Ethernet)"select BSP_USING_UART3default n
endmenu

3、if/endif


menu "Hardware Drivers Config"menuconfig BSP_USING_CANbool "Enable CAN"default nselect RT_USING_CANif BSP_USING_CANconfig BSP_USING_CAN1bool "Enable CAN1"default nendif
endmenu

4、menuconfig

menu "Hardware Drivers Config"menuconfig BSP_USING_UARTbool "Enable UART"default yselect RT_USING_SERIALif BSP_USING_UARTconfig BSP_USING_UART1bool "Enable UART1"default yconfig BSP_UART1_RX_USING_DMAbool "Enable UART1 RX DMA"depends on BSP_USING_UART1 && RT_SERIAL_USING_DMAdefault nendif
endmenu

5、choice

menu "Hardware Drivers Config"menuconfig BSP_USING_ONCHIP_RTCbool "Enable RTC"select RT_USING_RTCselect RT_USING_LIBCdefault nif BSP_USING_ONCHIP_RTCchoiceprompt "Select clock source"default BSP_RTC_USING_LSEconfig BSP_RTC_USING_LSEbool "RTC USING LSE"config BSP_RTC_USING_LSIbool "RTC USING LSI"endchoiceendif
endmenu

8. env配置

Env官方文档
Env工程配置

8.1 环境配置

在env目录中运行env.exe或env.bat,右击标题栏->settings->Intergration->点击上半部分的register->save settings.
在bsp/stm32f407工程目录下右键->ConEmeu_here,进入当前目录的env控制台

8.2 env配置项目(menuconfig)

拷贝/env/sample/Kconfig文件拷贝至工程目录,修改"RTT_ROOT"路径,才能使用menuconfig。

config BSP_DIRstringoption env="BSP_ROOT"default "."config RTT_DIRstringoption env="RTT_ROOT"default "./rt-thread"# you can change the RTT_ROOT default "rt-thread"
# example : default "F:/git_repositories/rt-thread"
# default: "../../"

工程目录打开env,输入menuconfig(>rtthread3.0),最终配置修改rtconfig.h内容。
项目的配置保存在:.config文件中,而后根据.config内容重新生成rtconfig.h内容。

scons --genconfig 		#根据 rtconfig.h 逆向生成 .config

8.3 生成mdk5工程(scons)

scons通过读取rtconfig.h文件配置成mdk5、mdk4、iar工程并编译。
进入bsp目录下对应工程目录下,删除原有的project.eww、project.uvproj、project.uvprojx三个文件,在当前目录中打开env,输入:

scons --target=mdk5   	#根据rtconfig.h生成project.uvprojx工程文件
scons					#采用自带gcc编译

8.4 软件包管理(pkgs)

官网软件包 https://github.com/RT-Thread-packages
工程目录打开env->menuconfig->RT-Thread online packages按空格键选中所需软件包

pkgs --update    		#更新软件包(需要安装git)
scons --targer=mdk5		#重新生成mdk5工程

(5)env设置

menuconifg -s
#进入Env config可配置自动更新软件包、自动生成工程

9. 工程实践

9.1 GD32450IIH6上移植

RT-Thread-国产MCU移植系列教程汇总
(1)视频版1(没成功)
高手版:如何移植RT-Thread到GD32单片机上(非studio版)

  • (1)复制/rtthread/bsp目录下一个相近工程。
  • (2)修改gd32_rom.sct中的内存和flash的大小。
  • (3)修改template.uvprojx中的工程名和芯片型号等。
  • (4)替换/Library下的CMSIS、GD32F4xx_standard_peripheral、GD32F4xx_usb_driver,并修改/Libraries目录下的SConscript文件,将其中的目录进行替换、CPPDEFINES、.c文件、启动文件等。
  • (5)修改/drivers下的驱动,并修改board.h中的GD32_SRAM_SIZE改成实际大小(KB)
  • (6)修改工程目录下的Kconfig文件,
  • (7)menuconfig修改系统配置,并用scons --targer=mdk5生成mdk工程。
  • (8)编译修改错误。

(2)文档版(成功)
GD32F405VG 移植RTT
手工向GD32F450移植RT-Thread内核
综合了上面两篇文章,框架用了第1个,调试始终卡在main线程的动态生成那里,考虑是椎的配置有问题,开始以为是大小的配置,后来在受第2篇文章启发,查看board.c中的rt_hw_board_init中对堆的初始化,决定不使用外部SDRAM,将rtconfig.h中的#define BSP_USING_SDRAM注释掉。
(或者是把Kconfig中的注掉,其实用snv生成后,也是转成rhconfig.h中的定义)

//Kconfig中关于使用SDRAM的定义注掉
config BSP_USING_SDRAMbool "Using sdram"default y 
//board.c中关于堆初始化的两种方式选择(SDRAM、SRAM)
void rt_hw_board_init()
{/* NVIC Configuration */
#define NVIC_VTOR_MASK              0x3FFFFF80
#ifdef  VECT_TAB_RAM/* Set the Vector Table base location at 0x10000000 */SCB->VTOR  = (0x10000000 & NVIC_VTOR_MASK);
#else  /* VECT_TAB_FLASH  *//* Set the Vector Table base location at 0x08000000 */SCB->VTOR  = (0x08000000 & NVIC_VTOR_MASK);
#endifSystemClock_Config();#ifdef RT_USING_COMPONENTS_INITrt_components_board_init();
#endif#ifdef RT_USING_CONSOLErt_console_set_device(RT_CONSOLE_DEVICE_NAME);
#endif#ifdef BSP_USING_SDRAMrt_system_heap_init((void *)EXT_SDRAM_BEGIN, (void *)EXT_SDRAM_END);	//用SDRAM没成功
#elsert_system_heap_init((void *)HEAP_BEGIN, (void *)HEAP_END);				//用SRAM成功了
#endif
}
#ifndef __BOARD_H__
#define __BOARD_H__#include <gd32f4xx.h>#define GD32_FLASH_START_ADDRESS    ((uint32_t)0x8000000)	//自己加的
#define GD32_FLASH_SIZE             (2048*1024)#define EXT_SDRAM_BEGIN    (0xC0000000U) /* the begining address of external SDRAM */
#define EXT_SDRAM_END      (EXT_SDRAM_BEGIN + (32U * 1024 * 1024)) /* the end address of external SDRAM */// <o> Internal SRAM memory size[Kbytes] <8-64>
//	<i>Default: 64
#ifdef __ICCARM__
// Use *.icf ram symbal, to avoid hardcode.
extern char __ICFEDIT_region_RAM_end__;
#define GD32_SRAM_END          &__ICFEDIT_region_RAM_end__
#else
#define GD32_SRAM_SIZE         64  //128		//原来128,网上说大了有问题,就改成64------
#define GD32_SRAM_END          (0x20000000 + GD32_SRAM_SIZE * 1024)
#endif#ifdef __CC_ARM
extern int Image$$RW_IRAM1$$ZI$$Limit;
#define HEAP_BEGIN    (&Image$$RW_IRAM1$$ZI$$Limit)
#elif __ICCARM__
#pragma section="HEAP"
#define HEAP_BEGIN    (__segment_end("HEAP"))
#else
extern int __bss_end;
#define HEAP_BEGIN    (&__bss_end)
#endif#define HEAP_END          GD32_SRAM_END#endif
//components.c
int rtthread_startup(void)
{rt_hw_interrupt_disable();    rt_hw_board_init();					/* board level initialization 在这里进行堆初始化*/    rt_show_version();					/* show RT-Thread version */    rt_system_timer_init();				/* timer system initialization */    rt_system_scheduler_init();			/* scheduler system initialization */
#ifdef RT_USING_SIGNALS    rt_system_signal_init();			/* signal system initialization */
#endif    rt_application_init();				/* create init_thread */    rt_system_timer_thread_init();		/* timer thread initialization */   rt_thread_idle_init();				/* idle thread initialization */   rt_system_scheduler_start();		/* start scheduler */    return 0;							/* never reach here */
}

(3)用bsp中的复制移植
参考这篇:教你动手移植RT-Thread到国产MCU

//board.h
#define GD32_SRAM_SIZE         192	//128

board.h中的sram为64M时,开lwip就会在出问题。
board.h中的sram为512M时,堆初始化会出问题,因为不连续。

void rt_system_heap_init(void *begin_addr, void *end_addr)

board.h中的sram为连续的128或192时,才能正常。

9.2 更改kprintf()串口输出

一般 rt-thread 发布的 bsp 库默认的 rt_kprintf 函数的输出设备是串口1,想要更改输出设备为串口1,以 stm32 为例步骤如下:

首先,打开 UART2 设备   
其次,在 menuconfig 中 RT-Thread Kernel — Kernel Device Object — Using console for rt_kprintf 修改 the device name for console 的值为 uart2   
最后,在文件 <stm32f1xx_hal_msp.c> 中加入串口2相关的时钟、引脚配置信息即可

9.3 添加网络

基于STM32F429实现web服务器功能
RT-Thread进阶笔记之网络框架
RT-thread 项目实战–添加wifi和net双网卡

这个是没有添加drv_enet.c、synopsys_emac.c的报错:

9.3.1 添加网络驱动文件

修改/bsp/GD32450I/drivers/SConscript文件:使Kconfig中的配置与具体的驱动文件对应

# add uart drivers.
if GetDepend('RT_USING_SERIAL'):src += ['drv_usart.c']# add sdram drivers.
if GetDepend('BSP_USING_SDRAM'):src += ['drv_exmc_sdram.c']# add eth drivers.
if GetDepend('BSP_USING_ETH'):src += ['drv_enet.c']# add eth drivers.
if GetDepend('BSP_USING_ETH'):src += ['synopsys_emac.c']

9.3.2 mac结构体

eth_device:

struct eth_device
{/* inherit from rt_device */struct rt_device parent;/* network interface for lwip */struct netif *netif;struct rt_semaphore tx_ack;rt_uint16_t flags;rt_uint8_t  link_changed;rt_uint8_t  link_status;/* eth device interface */struct pbuf* (*eth_rx)(rt_device_t dev);rt_err_t (*eth_tx)(rt_device_t dev, struct pbuf* p);
};

gd32_emac:

struct gd32_emac
{/* inherit from Ethernet device */struct eth_device parent;rt_uint8_t phy_mode;/* interface address info. */rt_uint8_t  dev_addr[MAX_ADDR_LEN];		/* hw address	*/struct rt_synopsys_eth * ETHERNET_MAC;IRQn_Type ETHER_MAC_IRQ;EMAC_DMADESCTypeDef  *DMATxDescToSet;EMAC_DMADESCTypeDef  *DMARxDescToGet;#pragma pack(4)EMAC_DMADESCTypeDef DMARxDscrTab[EMAC_RXBUFNB];
#pragma pack(4)EMAC_DMADESCTypeDef DMATxDscrTab[EMAC_TXBUFNB];
#pragma pack(4)rt_uint8_t Rx_Buff[EMAC_RXBUFNB][EMAC_MAX_PACKET_SIZE];
#pragma pack(4)rt_uint8_t Tx_Buff[EMAC_TXBUFNB][EMAC_MAX_PACKET_SIZE];struct rt_semaphore tx_buf_free;
};

9.4 硬件初始化

RT-Thread 自动初始化详解

1	INIT_BOARD_EXPORT(fn)		非常早期的初始化,此时**调度器还未启动**
2	INIT_PREV_EXPORT(fn)		主要是用于纯软件的初始化、**没有太多依赖的函数**
3	INIT_DEVICE_EXPORT(fn)		外设驱动初始化相关,比如网卡设备
4	INIT_COMPONENT_EXPORT(fn)	组件初始化,比如文件系统或者 LWIP
5	INIT_ENV_EXPORT(fn)			系统环境初始化,比如挂载文件系统
6	INIT_APP_EXPORT(fn)			应用初始化,比如 GUI 应用
 #define INIT_EXPORT(fn, level)  RT_USED const init_fn_t __rt_init_##fn SECTION(".rti_fn."level) = fn
/* board init routines will be called in board_init() function */
#define INIT_BOARD_EXPORT(fn)           INIT_EXPORT(fn, "1")
//commponents.c
#ifdef RT_USING_COMPONENTS_INIT
/** Components Initialization will initialize some driver and components as following* order:* rti_start         --> 0* BOARD_EXPORT      --> 1* rti_board_end     --> 1.end** DEVICE_EXPORT     --> 2* COMPONENT_EXPORT  --> 3* FS_EXPORT         --> 4* ENV_EXPORT        --> 5* APP_EXPORT        --> 6** rti_end           --> 6.end** These automatically initializaiton, the driver or component initial function must* be defined with:* INIT_BOARD_EXPORT(fn);* INIT_DEVICE_EXPORT(fn);* ...* INIT_APP_EXPORT(fn);* etc.*/
static int rti_start(void)
{return 0;
}
INIT_EXPORT(rti_start, "0");static int rti_board_start(void)
{return 0;
}
INIT_EXPORT(rti_board_start, "0.end");static int rti_board_end(void)
{return 0;
}
INIT_EXPORT(rti_board_end, "1.end");static int rti_end(void)
{return 0;
}
INIT_EXPORT(rti_end, "6.end");/*** RT-Thread Components Initialization for board*/
void rt_components_board_init(void)
{
#if RT_DEBUG_INITint result;const struct rt_init_desc *desc;for (desc = &__rt_init_desc_rti_board_start; desc < &__rt_init_desc_rti_board_end; desc ++){rt_kprintf("initialize %s", desc->fn_name);result = desc->fn();rt_kprintf(":%d done\n", result);}
#elseconst init_fn_t *fn_ptr;for (fn_ptr = &__rt_init_rti_board_start; fn_ptr < &__rt_init_rti_board_end; fn_ptr++){(*fn_ptr)();}
#endif
}/*** RT-Thread Components Initialization*/
void rt_components_init(void)
{
#if RT_DEBUG_INITint result;const struct rt_init_desc *desc;rt_kprintf("do components intialization.\n");for (desc = &__rt_init_desc_rti_board_end; desc < &__rt_init_desc_rti_end; desc ++){rt_kprintf("initialize %s", desc->fn_name);result = desc->fn();rt_kprintf(":%d done\n", result);}
#elseconst init_fn_t *fn_ptr;for (fn_ptr = &__rt_init_rti_board_end; fn_ptr < &__rt_init_rti_end; fn_ptr ++){(*fn_ptr)();}
#endif
}
int rt_hw_usart_init(void)
{struct stm32_uart *uart;struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;uart = &uart1;config.baud_rate = BAUD_RATE_115200;serial1.ops    = &stm32_uart_ops;serial1.config = config;MX_USART_UART_Init(&uart->huart);/* register UART1 device */rt_hw_serial_register(&serial1, "uart1",RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,uart);return 0;
}
INIT_BOARD_EXPORT(rt_hw_usart_init);
int rt_hw_pin_init(void)
{int result;result = rt_device_pin_register("pin", &_stm32_pin_ops, RT_NULL);return result;
}
INIT_BOARD_EXPORT(rt_hw_pin_init);

9.5 堆的初始化

上面的移植出现问题,有两个部分,一个是使用sdram,而板子上没有sdram,另一个是sram的大小,太小lwip有问题,太大则超过了sram的连续部分,在初始化堆时报错。

//使用内存堆时,必须要在系统初始化的时候进行堆的初始化,这个函数会把参数 begin_addr,end_addr 区域的内存空间作为内存堆来使用:
void rt_system_heap_init(void* begin_addr, void* end_addr);
//在使用 memheap 堆内存时,必须要在系统初始化的时候进行堆内存的初始化
rt_err_t rt_memheap_init(struct rt_memheap  *memheap,const char  *name,void        *start_addr,rt_uint32_t size)
//如果有多个不连续的 memheap 可以多次调用该函数将其初始化并加入 memheap_item 链表。

9.6 关于程序的起始地址

9.6.1 设置一致性

三个地方的设置要一致:gd32_rom.sct、gd32_rom.ld、rt_hw_board_init()中断向量设置。
gd32_rom.ld是魔术棒Linker当中自定义,默认是取的魔术棒Target对话框中rom、ram的设置。其生成的定义在xxx

9.6.2 实际经历

rom起始设在0x800400,问题卡在:

void rt_mp_free(void *block)level = rt_hw_interrupt_disable();

rom起始设在0x800000,问题卡在:(原因是中断向量表向后偏了)

void rt_system_scheduler_start(void)rt_hw_context_switch_to((rt_uint32_t)&to_thread->sp);

KEIL工程boot跳转失败,死在rt_system_scheduler_start()问题的解决

//board.c中对中断向量偏移进行了改动
void rt_hw_board_init()//SCB->VTOR  = (0x08004000 & NVIC_VTOR_MASK);SCB->VTOR  = (0x08000000 & NVIC_VTOR_MASK);

10. bootloader实现OTA在线升级

基于STM32F4实现RT-Thread的串口OTA(Ymodem_ota方式)
RT-Thread在线升级(Ymodem_OTA)

11. webnet应用

【rt-thread官网】webnet介绍
【gitee】webnet参考文档
webnet使用指南(CGI)
rt-thread应用篇(03)—基于STM32F429实现web服务器功能
文件系统要求:
WebNet 软件包使用,需要文件系统的支持(FAT 文件系统,ROMFS 文件系统等,支持 RT-Thread 的设备虚拟文件系统),用于 WebNet 软件包中访问的静态页面的存储、上传下载文件的存储等功能。

解决struct timeval报错:

#include <sys/time.h>

默认网页的位置:

//wn_sample.c
static void asp_var_version(struct webnet_session* session)
{RT_ASSERT(session != RT_NULL);static const char *version = "<html><body><font size=\"+2\">RT-Thread %d.%d.%d</font><br><br>""<a href=\"javascript:history.go(-1);\">Go back to root</a></html></body>";webnet_session_printf(session, version, RT_VERSION_MAJOR, RT_VERSION_MINOR, RT_VERSION_PATCH);    //RT_VERSION, RT_SUBVERSION, RT_REVISION
}
int webnet_module_cgi(struct webnet_session* session, int event)
{if (event == WEBNET_EVENT_INIT){/* set default cgi path */if (_cgi_root[0] == '\0'){strcpy(_cgi_root, "/cgi-bin/");}}else if (event == WEBNET_EVENT_URI_PHYSICAL){struct webnet_request* request;char *cgi_path = RT_NULL;RT_ASSERT(session != RT_NULL);request = session->request;RT_ASSERT(request != RT_NULL);/* check whether a cgi request */cgi_path = strstr(request->path, _cgi_root);if (cgi_path != RT_NULL){char* cgi_name;rt_uint32_t index;//judge contain ".cgi"-------自己加的--------char* lastname = cgi_path + strlen(cgi_path)-4;           if(strncasecmp(lastname,".cgi",4) == 0){int len = strlen(cgi_path);cgi_path[len-4] = '\0';}//----------end-----------------------------cgi_name = cgi_path + strlen(_cgi_root);for (index = 0; index < _cgi_count; index ++){if ((strlen(cgi_name) == strlen(_cgi_items[index].name))&& strncasecmp(cgi_name, _cgi_items[index].name, strlen(_cgi_items[index].name)) == 0){/* found it */_cgi_items[index].handler(session);return WEBNET_MODULE_FINISHED;}}/* set 404 not found error */request->result_code = 404;}}return WEBNET_MODULE_CONTINUE;
}

12. 文件系统

官网fal介绍
fal的api介绍
DFS文件系统管理与devfs/elmfat示例

DFS( Device File System)框架:


没有开启fatfs:

12.1 虚拟文件系统使用步骤:

  • 初始化 DFS 组件。
  • 注册具体类型的文件系统。
  • 挂载文件系统
  • 当文件系统不再使用,可以将它卸载。
//初始化
int dfs_init(void)
//注册文件系统
int dfs_register(const struct dfs_filesystem_ops *ops);
//挂载
int dfs_mount(const char   *device_name,const char   *path,const char   *filesystemtype,unsigned long rwflag,const void   *data);
//格式化设备(device_name)为(fs_name)文件格式
int dfs_mkfs(const char *fs_name, const char *device_name)
int dfs_file_open(struct dfs_fd *fd, const char *path, int flags)
int open(const char *file, int flags, ...)
//卸载
int dfs_unmount(const char *specialfile);

12.2 初始化

加入自动初始化

INIT_PREV_EXPORT(dfs_init);

初始化 DFS:

  • 清除文件系统操作表
  • 清除文件系统表
  • 清除文件描述符表
  • 初始化互斥量
  • 设置当前工作目录为“/”

13.3 fal

官网FAL的API
1、这个是在lwip之前初始化fal:

///..\rt-thread\components\net\lwip-2.0.2\src\arch\sys_arch.c(214) : void sys_init(void)
#include <fal.h>
void sys_init(void)
{/* nothing on RT-Thread porting */rt_kprintf("in sys_init: fal_init()----\r\n");/*flash initial here for read to set ipaddr*/fal_init();         // ppp-----
}

2、错误解决
(1)“expected an expression” 错误解决

USED static const struct fal_partition partition_table_def[] SECTION("FalPartTable") = FAL_PART_TABLE;

把其中一行注释,而应该删除,且上面那个换行符后面有空格也不行。
(2)dfs_mount(FS_PARTITION_NAME, “/webnet”, “lfs”, 0, 0)失败
主要是在:dfs_mount()中的dfs_file_open()失败,调试时感觉走的不对,该返回的也不返回。
这个是dfs的问题,将/components/dfs整个文件夹替换成可用的。
后来仔细对了下,是/filesystems/romfs/romfs.c中直接将dummy换成webnet了,感觉没从根本上解决,只是取了个巧:

RT_WEAK const struct romfs_dirent _root_dirent[] =
{{ROMFS_DIRENT_DIR, "webnet", (rt_uint8_t *)_dummy, sizeof(_dummy) / sizeof(_dummy[0])},//{ROMFS_DIRENT_FILE, "dummy.txt", _dummy_txt, sizeof(_dummy_txt)},
};

(3)rtthread4.1.1以上的虚拟文件系统中由于结构体调整,在dfs_file_open()中没有对data进行赋值,导致文件打开失败,修改如下:

int dfs_file_open(struct dfs_fd *fd, const char *path, int flags)fd->flags = flags;   fd->data  = fs;         //fa->data没给值,加上  ppp----

3、打印分区表

void fal_show_part_table(void)
//fal_def.h
#define FAL_PRINTF                     rt_kprintf   //printf

4、设备表和分区表

  • 分区表名称不能重复
  • 设备名称必须与设备表里定义设备的名称一致(.name参数)
  • 分区表相对设备的起始地址
  • 该分区表的大小,以字节为单位。

board.h中的定义也以字节为单位:

13.4 littlefs(lfs)

rtthread利用片上flash挂载littlefs文件系统并操作
基于RTT系统的LITTLEFS文件系统移植说明(STM32片内FLASH)

13. TFTP

netutils应用笔记
TFTP:简单文件传输协议
netutils软件包中有TFTP小工具。TFTP (Trivial File Transfer Protocol),端口号为 69。在板卡上开启TFTP Server后,就可以在PC上使用TFTP Client软件将HTML网页文件上传到板卡的SPI FLASH中。

传输文件写出现错误,原因是创建tftpserver时的目录为"/",这个文件系统不可写,要改成“/webnet”。总之要根据自己创建的文件系统来决定。

static int _tftp_msh(int argc, char *argv[])//server = tftp_server_create(path[0], port);server = tftp_server_create("/webnet", port);

板子创建tftp服务端:

//finsh中输入
tftp -s

tftp工具软件选client:

14. 设备管理

RT-Thread IO设备管理模型
RT-Thread设备管理框架
RTThread IO设备和驱动学习

IO设备类型:

/* include/rtdef.h */
enum rt_device_class_type
{RT_Device_Class_Char = 0,                           /**< character device */RT_Device_Class_Block,                              /**< block device */RT_Device_Class_NetIf,                              /**< net interface */RT_Device_Class_MTD,                                /**< memory device */RT_Device_Class_CAN,                                /**< CAN device */RT_Device_Class_RTC,                                /**< RTC device */RT_Device_Class_Sound,                              /**< Sound device */RT_Device_Class_Graphic,                            /**< Graphic device */RT_Device_Class_I2CBUS,                             /**< I2C bus device */RT_Device_Class_USBDevice,                          /**< USB slave device */RT_Device_Class_USBHost,                            /**< USB host bus */RT_Device_Class_SPIBUS,                             /**< SPI bus device */RT_Device_Class_SPIDevice,                          /**< SPI device */RT_Device_Class_SDIO,                               /**< SDIO bus device */RT_Device_Class_PM,                                 /**< PM pseudo device */RT_Device_Class_Pipe,                               /**< Pipe device */RT_Device_Class_Portal,                             /**< Portal device */RT_Device_Class_Timer,                              /**< Timer device */RT_Device_Class_Miscellaneous,                      /**< Miscellaneous device */RT_Device_Class_Sensor,                             /**< Sensor device */RT_Device_Class_Touch,                              /**< Touch device */RT_Device_Class_Unknown                             /**< unknown device */
};

设备结构体:

/* include/rtdef.h */
struct rt_device
{struct rt_object          parent;                   /**< inherit from rt_object */enum rt_device_class_type type;                     /**< device type */rt_uint16_t               flag;                     /**< device flag */rt_uint16_t               open_flag;                /**< device open flag */rt_uint8_t                ref_count;                /**< reference count */rt_uint8_t                device_id;                /**< 0 - 255 *//* device call back */rt_err_t (*rx_indicate)(rt_device_t dev, rt_size_t size);rt_err_t (*tx_complete)(rt_device_t dev, void *buffer);#ifdef RT_USING_DEVICE_OPSconst struct rt_device_ops *ops;
#else/* common device interface */rt_err_t  (*init)   (rt_device_t dev);rt_err_t  (*open)   (rt_device_t dev, rt_uint16_t oflag);rt_err_t  (*close)  (rt_device_t dev);rt_size_t (*read)   (rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size);rt_size_t (*write)  (rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size);rt_err_t  (*control)(rt_device_t dev, int cmd, void *args);
#endif#if defined(RT_USING_POSIX)const struct dfs_file_ops *fops;struct rt_wqueue wait_queue;
#endifvoid                     *user_data;                /**< device private data */
};
rt_device_create()
rt_device_destroy()
rt_device_register()
rt_device_find()
rt_device_init()
rt_device_open()
rt_device_close()
rt_device_control()
rt_device_read()
rt_device_write()
rt_device_set_rx_indicate()				//设置接收回调
rt_device_set_tx_complete()				//设置发送回调

14.1 i2c设备驱动

《rt-thread驱动框架分析》-i2c驱动
【rtthread设备】第六篇:i2c设备

15. lwip

lwip官方文档(重点)
【野火】LwIP应用开发实战指南—基于RT1052
LWIP学习笔记6——使用 NETCONN 接口编程
LWIP使用解析【网卡驱动 比较好】
LWIP使用经验—变态级(树状图比较好)

LwIP提供了三种编程接口,分别为 RAW/Callback API、Netconn API、Socket API。他们的易用性从左到右依次提高,而执行效率从左到右依次降低,用户可以根据实际情况,平衡利弊,选择合适的API进行网络应用程序的开发。
启动时序(图不错):

15.1 api

RAW:

err_t 	raw_bind (struct raw_pcb *pcb, const ip_addr_t *ipaddr) 
void 	raw_bind_netif (struct raw_pcb *pcb, const struct netif *netif) 
err_t 	raw_connect (struct raw_pcb *pcb, const ip_addr_t *ipaddr) 
void 	raw_disconnect (struct raw_pcb *pcb) 
void 	raw_recv (struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg) 
err_t 	raw_sendto (struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *ipaddr) 
err_t 	raw_sendto_if_src (struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_ip, struct netif *netif, const ip_addr_t *src_ip) 
err_t 	raw_send (struct raw_pcb *pcb, struct pbuf *p) 
void 	raw_remove (struct raw_pcb *pcb)

TCP:

//connect----
tcp_new()
tcp_bind()
tcp_listen() and tcp_listen_with_backlog()
tcp_accept()
tcp_connect()
//send----
tcp_write()
tcp_output()
tcp_sent()
//recv----
tcp_recv()
tcp_recved()
void 	tcp_backlog_delayed (struct tcp_pcb *pcb) 
void 	tcp_backlog_accepted (struct tcp_pcb *pcb) 
err_t 	tcp_close (struct tcp_pcb *pcb) 
err_t 	tcp_shutdown (struct tcp_pcb *pcb, int shut_rx, int shut_tx) 
void 	tcp_abort (struct tcp_pcb *pcb) 
err_t 	tcp_bind (struct tcp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port) 
void 	tcp_bind_netif (struct tcp_pcb *pcb, const struct netif *netif) 
struct tcp_pcb * 	tcp_listen_with_backlog (struct tcp_pcb *pcb, u8_t backlog) 
struct tcp_pcb * 	tcp_listen_with_backlog_and_err (struct tcp_pcb *pcb, u8_t backlog, err_t *err) 
void 	tcp_recved (struct tcp_pcb *pcb, u16_t len) 
err_t 	tcp_connect (struct tcp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port, tcp_connected_fn connected) 
struct tcp_pcb * 	tcp_new (void) 
struct tcp_pcb * 	tcp_new_ip_type (u8_t type) 
void 	tcp_arg (struct tcp_pcb *pcb, void *arg) 
void 	tcp_recv (struct tcp_pcb *pcb, tcp_recv_fn recv) 
void 	tcp_sent (struct tcp_pcb *pcb, tcp_sent_fn sent) 
void 	tcp_err (struct tcp_pcb *pcb, tcp_err_fn err) 
void 	tcp_accept (struct tcp_pcb *pcb, tcp_accept_fn accept) 
void 	tcp_poll (struct tcp_pcb *pcb, tcp_poll_fn poll, u8_t interval) 
err_t 	tcp_write (struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags) 
err_t 	tcp_output (struct tcp_pcb *pcb)

UDP:

err_t 	udp_send (struct udp_pcb *pcb, struct pbuf *p) 
err_t 	udp_sendto (struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_ip, u16_t dst_port) 
err_t 	udp_sendto_if (struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_ip, u16_t dst_port, struct netif *netif) 
err_t 	udp_sendto_if_src (struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_ip, u16_t dst_port, struct netif *netif, const ip_addr_t *src_ip) 
err_t 	udp_bind (struct udp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port) 
void 	udp_bind_netif (struct udp_pcb *pcb, const struct netif *netif) 
err_t 	udp_connect (struct udp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port) 
void 	udp_disconnect (struct udp_pcb *pcb) 
void 	udp_recv (struct udp_pcb *pcb, udp_recv_fn recv, void *recv_arg) 
void 	udp_remove (struct udp_pcb *pcb) 
struct udp_pcb * 	udp_new (void) 
struct udp_pcb * 	udp_new_ip_type (u8_t type)

http://chatgpt.dhexx.cn/article/OUVQ5Ghn.shtml

相关文章

RT Thread之ADC电压读取

官网连接&#xff1a;https://docs.rt-thread.org/#/rt-thread-version/rt-thread-standard/programming-manual/device/adc/adc 一、配置步骤&#xff1a; 1、用cubemx配置底层&#xff1b; 2、cubemx配置好的文件替换之前的配置文件&#xff1b; 3、修改Kconfig文件&…

rtthread mqtt

rtthread 以太网 (LAN8720A) 基于以太网的应用mqtt&#xff0c;在**rtthread 以太网 (LAN8720A)**中已经实现了tcp/ip通信正常&#xff0c;接下需要启用mqtt模块&#xff0c; 嵌入式mqtt设备 rtthread 启用mqtt 在rtthread中田间 pahomqtt 软件包&#xff0c;并右键详细配置…

【RTThread】修改Finsh打印串口波特率

这里需要注意得是一定要在hw_board_init初始化完成之后修改串口波特率。 /* 串口设备句柄 */static rt_device_t uart_device RT_NULL;/* 查找系统中的串口设备 */uart_device rt_device_find("uart1"); // 这里/* 串口配置结构体&#xff0c;使用serial.h的宏定义…

RT Thread之 Uart2 操作

官网连接&#xff1a;https://docs.rt-thread.org/#/rt-thread-version/rt-thread-standard/programming-manual/device/uart/uart 通过前面的学习&#xff0c;基本上RT Thread操作步骤都是&#xff0c;先配置单片机底层&#xff0c;然后再通过应用层映射到底层&#xff0c;最…

rtthread

链表 初始化双向链表 rt_inline void rt_list_init(rt_list_t *l) {l->next l->prev l; }插入 rt_inline void rt_list_insert_after(rt_list_t *l, rt_list_t *n) {l->next->prev n;n->next l->next;l->next n;n->prev l; }在NODE1后面插入节…

RT Thread根据开发板制作BSP方法

之前一直不懂怎么使用RT Thread的软件包&#xff0c;感谢网上的大神&#xff0c;看了你们的博客后大概了解一些&#xff0c;在此做下记录。用RT Thread软件包需要RT Thread的系统&#xff0c;但是RT Thread和RT Thread nano不一样&#xff0c;具体区别见 RT Thread官网&#xf…

rtthread开关中断

1 rtthread开关中断函数(cortex-m) /** rt_base_t rt_hw_interrupt_disable();*/ .global rt_hw_interrupt_disable .type rt_hw_interrupt_disable, %function rt_hw_interrupt_disable:MRS r0, PRIMASKCPSID IBX LR/** void rt_hw_interrupt_enable(rt_base_t le…

RTThread入门

RT-Thread入门 1.初识RT-Thread 嵌入式系统是一种完全嵌入在装置或设备内部&#xff0c;为满足特定需求而设计的计算机系统&#xff0c;譬如生活中常见的嵌入式系统就有&#xff1a;电视机顶盒、路由器、电冰箱、微波炉与移动电话等。 嵌入式操作系统是应用于嵌入式系统的软…

什么是RT-Thread?

一、RT-Thread的定义 RT-Thread&#xff0c;全称是 Real Time-Thread&#xff0c; 是一款主要由中国开源社区主导开发的开源实时操作系统&#xff08;许可证GPLv2&#xff09;&#xff0c;包含了实时、嵌入式系统相关的各个组件&#xff1a;TCP/IP协议栈、图形用户界面等。 相…

Redis启动失败的原因及解决方法

跑了近半年的Redis,今天早上来开启电脑运行程序的时候发现提示无法连接redis,暗想自己明明设置了开机自启的阿,以前也一直没问提,今天怎么就连不上了重启了下redis就提示如下错误 网上搜了好久都没找到解决办法,后来想起来去查看了下redis的日志文件 发现提示当前版本的redis无…

redis启动、获取密码及修改密码

一、启动redis服务的两种方式 查看密码是以redis服务已启动的前提下进行的&#xff0c;可直接在服务中右键启动redis或者安装根目录运行cmd输入《redis-server.exe》(不推荐不推荐不推荐&#xff0c;说三遍&#xff0c;命令行启动好像有bug&#xff0c;启动后redis能用&#x…

CentOS安装Redis及redis启动与关闭、配置(详细)

在项目使用redis过程中&#xff0c;在centos7上部署redis&#xff0c;查找相关资料并总结、记录&#xff0c;以备后续查看。 目录 一、Redis介绍 二、在CentOS上部署Redis 1、Redis安装包可以从官网上下载或者直接命令下载 升级到gcc 9.3&#xff1a; 3、Redis配置文件…

Redis启动和连接

一&#xff09;Redis简介 Redis不是简单的键值存储&#xff0c;它实际上是一个数据结构服务器&#xff0c;支持不同类型的值。 备注&#xff1a;由于我电脑是32位操作系统&#xff0c;所有就不提供redis软件下载地址了&#xff0c;请到官网下载使用。 软件解压之后&#xff0…

windows下Redis启动闪退问题解决经验汇总

最近使用Redis又遇到启动闪退的问题&#xff0c;之前记录的解决办法也失败了&#xff0c;一番研究后总算得到解决&#xff0c;感觉已经遇到了网上常见的各种问题&#xff0c;下面总结下。 我下载的是免安装版&#xff0c;解压便可使用。 官网下载传送门&#xff1a;Releases …

Windows下redis启动那些事儿

本文章主要描述我遇到的Windows下redis启动成功但Java项目无法连接问题 1.使用redis可视化工具可以连接&#xff0c;但是到Java项目中就报错连接失败 经过我的多方琢磨&#xff0c;还是密码没有配置正确&#xff0c;虽然是在redis.windows.conf配置文件中配置了 requirepass 密…

redis启动失败问题完美解决

1.输入启动命令redis-server.exe redis.windows.conf启动redis&#xff0c;发现启动失败报错&#xff1a;[8072] 07 May 09:28:52.241 # Creating Server TCP listening socket 127.0.0.1:6379: bind: No error D:\a\Main\redis> redis-server.exe redis.windows.conf[8072]…

windows redis启动

下载好redis后&#xff0c;只需解压。 然后打开dos窗口 进入redis解压目录 cd D:softwareRedis-x64-3.2.100运行下面命令启动 redis-server.exe redis.windows.conf成功启动 还可以把redis加入都开机自启动 redis-server --service-install redis.windows-service.conf …

redis启动和简单使用

redis启动和简单使用 1.redis启动 1.1 找到redis解压的位置,在里面输入cmd回车 1.2 输入redis-server redis.conf指令,然后回车,出现如下界面 注意&#xff1a;该界面不能关闭了 1.3 再进入一次redis解压的位置 输入cmd回车 1.4 输入redis-cli指令后的结果 1.5 补充 当出现…

Redis的启动方式三种

Redis的启动方式三种 启动一个 &#xff0c;进入到redis中的src目录下 在控制台输入指令&#xff1a;redis-server &#xff08;注意&#xff1a;这样启动默认端口是 6379 &#xff09; 进入客户端输入&#xff1a;redis-cli 查看进程&#xff0c;杀死进程 指定端口启动redi…

Redis的启动方法

一、Windows下 D: cd Redis //我的redis安装路径为D:\Redis redis-server.exe redis.windows.conf **如果报错creating server tcp listening socket 127.0.0.1:6379: bind No error D:\Redis>redis-cli.exe 127.0.0.1:6379> shutdown not connected> exit redi…