RT-Thread调试中Stm32_putc卡死与分散加载文件关联分析

Cortex-M 开发中实现stdout(printf, puts, putc) Cortex-M 开发中实现stdout(printf, puts, putc)开发嵌入式程序时,由于没有标准输出设备,通常要把标准库的stdout定向到串口或usb等,用于调试;也就是说,在使用printf,puts,putc 等函数时,要先提供stdout基本功能的实现,标准的printf等会调用用户定义的实现函数作为stdout.使用armcc和Microlib 实现fputc函数 armc 阅读详情

1. 问题现象与背景

最近在玩RT-Thread的时候遇到了一个非常奇怪的问题:使用STM32开发板进行调试时,串口输出经常会卡死在Stm32_putc函数中。这个问题表现得极不稳定——有时候重新上电就能正常打印,有时候又会卡死,完全看运气。作为有多年嵌入式开发经验的工程师,我深知这种随机性问题往往最难排查,因为它可能涉及到内存初始化、编译器配置甚至是硬件时序等深层因素。

具体来说,当我在调试过程中单步执行到Stm32_putc函数时,程序会突然卡住,没有任何错误提示,也没有触发硬件错误中断。通过Keil MDK的调试器查看调用栈,发现程序停滞在串口发送函数中,仿佛在等待某个永远无法满足的条件。这种问题在嵌入式开发中非常常见,但背后的原因却可能千差万别。如果你也遇到过类似的问题,相信今天的分享会对你有所帮助。

2. 问题根因分析

2.1 串口初始化异常

首先,我怀疑是串口初始化出了问题。因为Stm32_putc函数依赖串口外设的正确配置,如果初始化不完整,就可能导致发送数据时卡死。于是我在drv_usart.c中的串口初始化函数里设置了断点,发现程序确实会执行到这里,但在调用HAL_UART_MspInit时却出现了异常。

进一步查看发现,huart->gState的值竟然不是HAL_UART_STATE_RESET,而是HAL_UART_STATE_READY。这意味着HAL库认为串口已经初始化完成,但实际上硬件并未正确配置。为什么会这样呢?因为HAL库的状态机机制要求每次初始化前必须将状态重置为HAL_UART_STATE_RESET,否则初始化函数会直接跳过硬件配置步骤。

2.2 未初始化的全局变量

通过全局搜索HAL_UART_STATE_READY的赋值位置,我发现没有任何代码在启动阶段对这个状态位进行赋值。这就很奇怪了——这个值是从哪里来的?继续追查huart指针的来源,发现它指向一个stm32_uart结构体,这个结构体在rt_hw_usart_init函数中定义为静态全局变量:

static struct stm32_uart uart_obj[sizeof(uart_config) / sizeof(uart_config[0])] = {0};

虽然这里使用了{0}进行初始化,但实际上MDK编译器在处理ZI(Zero Initialized)数据段时,并不保证所有变量都会被清零。特别是在使用默认内存分配方式时,编译器可能会省略某些初始化代码。

2.3 ZI段初始化问题

ZI段是指那些在程序中声明但未显式初始化的全局变量和静态变量。在正常情况下,启动代码会在main函数执行前将这些内存区域清零。但是,当我查看map文件时,发现使用默认内存配置时,编译器确实没有生成足够的ZI段初始化代码。

这就是问题的根源:由于ZI段没有正确初始化,uart_obj数组中的状态变量gState包含了随机值,导致HAL库误以为串口已经初始化完成,从而跳过关键的硬件配置步骤。最终结果就是串口无法正常工作,Stm32_putc函数在尝试发送数据时无限等待。

3. 分散加载文件的作用

3.1 什么是分散加载文件

分散加载文件(Scatter File)是ARM编译器中使用的一种内存布局描述文件,它详细定义了代码和数据在内存中的存放位置。与简单的默认配置不同,分散加载文件允许开发者精确控制每个段(如代码段、数据段、ZI段)的存放地址和大小。

在RT-Thread中,分散加载文件特别重要,因为实时操作系统通常需要更精细的内存管理。比如,你可以将频繁访问的数据放在高速RAM中,或者为不同的内存区域设置不同的访问权限。

3.2 默认配置与自定义配置的差异

MDK编译器提供了两种内存配置方式:一种是基于GUI界面设置的默认配置,另一种是使用自定义的分散加载文件。这两种方式在ZI段处理上有显著差异:

配置方式ZI段初始化稳定性灵活性
默认配置可能不完整较低较低
分散加载文件完整初始化较高较高

通过对比生成的map文件,我发现使用自定义分散加载文件时,编译器会自动添加完整的ZI段初始化代码,确保所有全局变量都从正确的初始状态开始。这就是为什么官方SDK默认使用分散加载文件的原因。

4. 解决方案与实操步骤

4.1 启用自定义分散加载文件

在MDK中启用分散加载文件非常简单。首先打开Options for Target对话框,切换到Linker选项卡,然后取消勾选"Use Memory Layout from Target Dialog"选项。接着在Scatter File栏中指定你的分散加载文件(通常是.sct后缀)。

如果你还没有分散加载文件,可以参考以下模板创建一个:

LR_IROM1 0x08000000 0x00100000 {    ; 加载区域
  ER_IROM1 0x08000000 0x00100000 {  ; 代码段
   *.o (RESET, +First)
   *(InRoot$$Sections)
   .ANY (+RO)
  }
  RW_IRAM1 0x20000000 0x00020000 {  ; 数据段
   .ANY (+RW +ZI)
  }
}

这个简单的分散加载文件定义了代码段存放在Flash中(起始地址0x08000000),数据段存放在RAM中(起始地址0x20000000)。关键的是最后一行.ANY (+RW +ZI),它确保了所有RW和ZI段都会被正确初始化。

4.2 手动初始化关键变量

如果你暂时不想修改编译配置,也可以在代码中添加手动初始化。在rt_hw_usart_init函数中,显式地对uart_obj数组进行清零:

for (rt_size_t i = 0; i < sizeof(uart_obj) / sizeof(struct stm32_uart); i++) {
    rt_memset(&uart_obj[i], 0, sizeof(struct stm32_uart));
    // 其他初始化代码...
}

这种方法虽然能解决问题,但不够优雅,而且可能会遗漏其他需要初始化的全局变量。建议还是使用分散加载文件作为长期解决方案。

4.3 验证解决方案

修改配置后,需要重新编译并下载程序。为了验证ZI段是否正确初始化,可以在main函数开始时添加以下检查代码:

extern uint8_t Image$$RW_IRAM1$$ZI$$Base[];
extern uint8_t Image$$RW_IRAM1$$ZI$$Limit[];

rt_kprintf("ZI segment range: %p - %p\n", 
           Image$$RW_IRAM1$$ZI$$Base,
           Image$$RW_IRAM1$$ZI$$Limit);

如果输出显示正确的地址范围,说明分散加载文件已经生效。你还可以在调试模式下查看这些地址范围内的内存值,确认它们已经被正确清零。

5. 预防措施与最佳实践

5.1 编译器配置检查

在开始新项目时,建议首先检查编译器的内存配置。对于MDK用户,最好始终使用自定义分散加载文件,而不是依赖默认配置。这样可以确保内存布局的一致性,避免因编译器版本更新导致的不可预知问题。

同时,建议定期查看生成的map文件,确认各个段的地址和大小是否符合预期。特别是要注意ZI段的大小是否与代码中实际使用的未初始化变量数量匹配。

5.2 代码编写规范

在编写嵌入式代码时,要特别注意全局变量的使用。尽量避免使用未初始化的全局变量,而是显式地给它们赋初值。对于结构体变量,不要依赖编译器的默认初始化,而是在定义时就用memset或类似的函数进行清零。

另外,对于HAL库这类依赖状态机的代码,要确保在使用前正确初始化所有状态变量。虽然HAL库提供了初始化函数,但如果底层的内存初始化不完整,这些函数也可能无法正常工作。

5.3 调试技巧分享

当遇到随机性问题时,可以尝试以下调试方法:首先使用调试器查看问题出现时的变量值,特别是那些应该在启动阶段初始化的全局变量。如果发现异常值,就很可能是ZI段初始化问题。

其次,可以尝试在启动代码的__main函数处设置断点,单步执行观察ZI段初始化的过程。在MDK中,__main函数负责完成ZI段的初始化工作,如果这个函数没有被正确调用,就会导致各种随机性问题。

最后,记得充分利用RT-Thread提供的调试工具,如list_thread、list_device等命令,可以帮助你快速了解系统的运行状态。当串口无法使用时,还可以尝试使用SEGGER RTT等替代的调试输出方式。

由串口驱动分析rt-thread设备驱动框架 rt-thread中,线程、信号量、互斥锁、设备等等都是“**内核对象**”,`_object_container`是一个数组,包含所有的内核对象信息。 对象信息的定义 ```c struct rt_object_information { enum rt_object_class_type type; /**< object class type */ rt_list_t object_list; 阅读详情

相关推荐

STM32串口读写

#Include void USART_printf(const char *fmt,...) { va_list ap; char string[128]; va_start(ap,fmt); vsprintf(string,fmt,ap); USART_puts(string); va_end(ap); }

Calcular的博客 3415

RT-Thread debug 卡死在Stm32_putc问题分析解决

RT-Thread debug 卡死在Stm32_putc问题分析解决

qq_36720691的博客 1730

stm32F407的串口6卡死问题

环境 操作系统:RT-Thread 板子:STM32F407VET6 现象 UART1做控制台串口、UART6做通讯串口,但一旦使用UART6就会卡死,调试后发现程序卡死在函数static int stm32_putc(struct rt_serial_device *serial, char c)中的 while (__HAL_UART_GET_FLAG(&(uart->handle), UART_FLAG_TC) == RESET); 解决思路 代码需要看 stm32f4xx_hal_ms

道亦无名 2456

rt-thread------串口(二)发送篇

这篇文章主要讲一下rt-thread的串口的三种发送,轮询、中断、DMA发送。rt-thread提供的串口驱动V1版本中断发送有问题,这边只提供中断的发送思路,或者大家可以去研究一下V2版本。后续会有V2版本的文章更新。首先需要提出两个概念阻塞和非阻塞,阻塞顾名思义程序会在这里等待到阻塞结束。非阻塞则会立马执行结束跑到后面的程序。里面本质上会调用(中断发送)(dma发送)轮询发送。

qq_39854159的博客 5013

MOSFET和IGBT栅极驱动器电路的基本原理学习(2)

1.PWM直接驱动 驱动主开关晶体管栅极的最简单方法是利用 PWM 控制器的栅极驱动输出,如图 (1)如 图 8中所示,PWM 控制器和 MOSFET 之间可能有较大距离。由于栅极驱动和接地环路迹线形成的环路,这个距离形成了寄生电感,从而降低了开关速度,并导致栅极驱动波形中形成振铃。为了降低与栅极驱动连接相关的电感,需要更宽的 PCB 迹线。 (2)直接栅极驱动的另一个问题是PWM 控制器的驱动电流能力有限。极少有集成电路能提供高于 1A 的峰值栅极驱动能力。 2.旁路电容的确定 (1)位置 如果是独立的

weixin_43732932的博客 5834

智能网联汽车电子电气架构(下)

从资产的表现形式, 可以分为数据、 软件、 硬件、 服务等, 而从需要保护的业务过程和活动、 所关注信息的角度, 资产类型可包括基于 ECU 的控制功能、 与特定车辆相关的信息、 车辆状态信息、 用户信息、 配置信息、 特定的软件、 内容等。面向新一代 EEA 的安全需求, 基于芯片提供的 OTP, 或SHE\HSM 的安全存储能力, 实现系统关键数据(身份、 密钥等关键信息) 的安全存储, 保证系统的关键数据不被盗取、 破坏、 改写。结合攻击者的动机与识别出的系统用例, 分析对汽车电子系统可能的攻击。

m0_58838529的博客 1473

STM32串口卡死问题

本次遇到的问题是USART串口发送函数卡死程序,究其原因原来是串口发送函数中的发送空寄存器没有置位,且超时时间设置的太大导致程序死循环,直到发送超时退出。 在调用CUBE的串口发送函数时一定要注意写的方式。关于传送完毕,有人用如下方法等待传送完毕虽然方案可行 while(HAL_OK !=HAL_UART_Transmit(&amp;huart2, transmit,len, timeout))...

九月天空的博客 1万+

L298N电机驱动模块的接线使用与代码实现

#include "iostm8s208mb.h" #define u8 uint8_t #define u16 uint16_t #define u32 uint32_t typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned long uint32_t; // 关于LED灯的宏定义 #define LED2 PI_ODR_ODR2 //输出量 #define LE

Clichong 13万+

stm32 输出重定向

系统初始化的时候: printfSerialInit(); 是怎么定义的: void printfSerialInit(void) {     init_printf(NULL, _putc); } static void _putc(void *p, char c) {  ...

孙亖的专栏 987

VS2015与QT界面开发中解决‘ui_xxx.h‘文件类名不一致导致的编译错误

本文详细解析了在VS2015与QT界面开发中,因.ui文件顶层部件objectName与生成类名不一致导致'ui_xxx.h'文件出现'不完整的类型'编译错误的根本原因。通过分步排查,指导开发者统一Qt设计师对象名、自动生成文件类名及代码引用名,并提供强制重新编译UI文件、清理中间文件等解决方案,有效解决此类常见编译问题。

weixin_29009339的博客 248

微纳加工技术中的自对准硅化物(Silicide)工艺:关键步骤与应用场景解析

本文深入解析了微纳加工技术中的自对准硅化物(Silicide)工艺,详细介绍了其关键步骤与应用场景。从表面清洁、金属沉积到两步退火法,全面拆解工艺全流程,并探讨了不同技术节点下的工艺演进。文章还提供了实际应用中的问题排查方法和新兴技术对Silicide工艺的挑战,为芯片制造领域的工程师提供了实用参考。

weixin_30613727的博客 431

STM32串口接收数据卡死问题解决办法。

在使用STM32串口时,有时候串口接受一段时间数据之后便会卡死不在进入中断接收数据。原因是串口中断标志没有清除,导致终端锁死,此时需要判断对应的标志位,重新启动中断。 if((huart1.Instance->CR1 & 0x20)==0) { HAL_UART_Receive_IT(&huart1,bsp_uart1.rx_tmp,1); } ``` ...

weixin_43482414的博客 9348

从软体机器人到鞋垫分析:Abaqus超弹性材料(Ogden模型)仿真配置全流程

本文详细介绍了Abaqus中Ogden模型在超弹性材料仿真中的应用全流程,涵盖从实验数据导入、参数拟合到模型构建与求解优化的关键步骤。特别针对鞋垫分析等生物力学场景,提供了单元选择、接触设置和并行计算等实用技巧,帮助工程师实现高精度仿真分析。

weixin_42525385的博客 400

rt-thread源码分析篇十一:rt_show_version函数分析

一、rt_show_version函数调用关系 二、rt_show_version函数分析 /** * This function will show the version of rt-thread rtos */ void rt_show_version(void) { rt_kprintf("\n \\ | /\n"); rt_kprintf("- RT - Thread Operating System\n"); rt_kprintf(" / | \\

OnlyLove_的博客 1016

工业音频故障检测:从CNN到Transformer的技术演进

音频信号处理是工业设备预测性维护的核心技术之一,通过分析设备运行时产生的声波特征实现故障预警。传统方法依赖梅尔频率倒谱系数(MFCC)等手工特征,而深度学习技术尤其是Transformer架构,通过自注意力机制突破了CNN在跨频段特征提取上的局限。Audio Spectrogram Transformer(AST)等先进模型在工业场景中展现出91.2%的高召回率,显著优于传统方案。这种非接触式监测技术结合边缘计算优化,已成功应用于石油化工、电力能源等领域,实现提前72小时预测轴承故障,单项目可避免数百万元的

weixin_30467861的博客 328

机器学习-02 模型的评估与选择

2.1 误差与过拟合 我们将学习器对样本的实际预测结果与样本的真实值之间的差异成为:误差(error)。定义: 在训练集上的误差称为训练误差(training error)或经验误差(empirical error)。 在测试集上的误差称为测试误差(test error)。 学习器在所有新样本上的误差称为泛化误差(generalization error)。 显然,我们希望得到的是在新样本上表现得很好的学习器,即泛化误差小的学习器。因此,我们应该让学习器尽可能地从训练集中学出普适性的“一般特征”,这

一个小白 1707

stm32f051移植RT-Thread串口注意点

1.STM32_SRAM_SIZE RAM的大小,051是8K #define STM32_SRAM_SIZE 8 2. 时钟配置,默认是8M,我的外接HSE晶振是24M,那需要修改倍频参数 查看SetSysClock这个函数, RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_PREDIV1 | RCC_...

spicy_xu的专栏 1003

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

RTT串口V1版本的使用分析及问题排查指南(三)

本文由RT-Thread论坛用户123原创发布,原文:https://club.rt-thread.org/ask/article/2904.html 应用层的串口问题 应用层使用串口时,需要先指定以何种方式(轮询、中断或者DMA)去打开串口,然后再进行串口的操作。这部分相关的内容在第一章已经说过,这里主要用来总结串口使用时遇到的一些问题。 串口注册时候的默认规则慢慢道来: 串口注册的默认规则 我们都知道,串口设备需要先注册,才能通过rt_device_open API 去访问,那么串口注册时候的默认规则是

rtthreadiotos的博客 1159

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

STM32 fputc函数(重定向)

在需要用到显示功能的代码中,用printf写法会快很多。 struct __FILE { int handle; }; FILE __stdout; //定义_sys_exit()以避免使用半主机模式 void _sys_exit(int x) { x = x; } //重定义fputc函数 int fputc(int ch, FILE *f){ ...

Cypher的博客 4441

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

关于STM32串口卡死问题

1.操作系统:RT-Thread 板子:STM32F407 2.现象:想要UART1做控制台串口、UART3做通讯串口,但一旦使用UART3就会卡死,调试后发现程序卡死在函数static int stm32_putc(struct rt_serial_device *serial, char c)中的 while (__HAL_UART_GET_FLAG(&(uart->handle), UART_FLAG_TC) == RESET); 3.解决:注意关注函数void...

heermu的博客 3316

STM32学习笔记(一)----基本位操作

1)不改变其他位的值的状态下,对某几位进行设置初始值 这个场景,单片机开发中经常使用,方法就是先对需要设置的位用&符号进行清零操作,然后用|操作符设定数值,比如我们经常改变GPIO的状态,可以先对寄存器的值进行清零操作  GPIOA ->CRL &= 0xFFFF FF0F;  //将第4-7位清零 GPIOA ->CRL &= 0x0000 0040; //设置相应位的值,不改变其他位置的

博闻天下-lei的博客 6439

RT thread 设备驱动组件之USART设备

本文以stm32f4xx平台介绍串口驱动,主要目的是:1、RTT中如何编写中断处理程序;2、如何编写RTT设备驱动接口代码;3、了解串行设备的常见处理机制。所涉及的主要源码文件有:驱动框架文件(usart.c,usart.h),底层硬件驱动文件(serial.c,serial.h)。应用串口设备驱动时,需要在rtconfig.h中宏定义#define RT_USING_SERIAL。 ...

weixin_34092370的博客 1305

STM32串口接收发送子程序

/*上传STM32串口接收发送子程序,调试验证OK,供参考*/ #include static UART_HandleTypeDef* pstm32uart_entry = NULL;  int STM32_SendBuffer(const char* pcmd); const char* STM32_GetBuffer(void); #define UAR

Yelsin的博客 3724

STM32 的 SWD调试模式

嵌入式开发

wabil的专栏 2万+
上一篇: Ubuntu 22.04下RISC-V QEMU虚拟化环境构建与内核调试实战
下一篇: AGV视觉巡线:基于天花板特征的运动控制实践
python9snake
博客等级 码龄1天 0粉丝 1724原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值