Linux环境开发STM32,从环境到调试

发布者:MysticGarden最新更新时间:2019-04-26 来源: eefocus关键字:Linux环境  STM32  调试 手机看文章 扫描二维码
随时随地手机看文章

首先简单地描述一下软硬件开发环境。


宿主机:

    操作系统:CentOS7 x86_64 ( grome桌面版 )

    IDE:Eclipse Luna

    JLink驱动:JLink_Linux_V434a

    工具链:GNU-ARM-Toolchains-4.9-2014q4

    GDB:arm-linux-gdb V7.8.1


硬件平台:

    CPU:STM32F103C8T6

    JLink:V8

    USB转串口:Silicon Labs CP2101


    环境的搭配都是比较简单的,编译工具链都比较容易装。这里就不再介绍了。下面就只附上工具链的下载链接。

    https://launchpad.net/gcc-arm-embedded

    IDE环境Eclipse Luna,可以直接在官网上下载。还有CDT,也可以在Eclipse官网上下载。

    有一个比较重要的 GNU ARM Eclipse开发插件,附上个链接。

    http://sourceforge.net/projects/gnuarmeclipse/

    还有一个Eclipse插件,用于GDB调试的,叫Zylin-embedded CDT。下载网址如下:

    http://opensource.zylin.com/zylincdt

    另外,是JLink的驱动,当中包含GDBServer,我用的是V434a的版本,是买其它教学视频的时候附上的。Segger官网上好像已经找不到这个下载链接了,可以百度一下,也可以在Segger官网上下载其它版本的。(只要有正版JLink的其实啥版本都没问题,不过用D版的就要注意一下了,不建议用那么高的版本,不然会用不了)这里就不附链接了。

    最后还有Arm-linux-GDB,可以从下面的官网上下载。编译和安装只要按照README去做就ok了。非常简单。

    http://lists.gnu.org/archive/html/info-gnu/2014-10/msg00018.html


    说了这么久的环境,一开始自己摸索的时候觉得配环境很麻烦,而且也装了很多不必要的东西,后来发现其实只要装上述的就够了,非常简单。希望能帮助大家少走点弯路。下面就用一个简单的示例程序来说一下怎么编译、下载、调试。在原来的windows环境中,我是用Keil uVision5进行开发的,也留了一些代码,所以就直接拿了个串口的发送程序作为这一次的示例,代码如下。


/*=====================================

Include headers

=====================================*/

#include "stm32f10x.h"

 

 

/*=====================================

Functions definition

=====================================*/

void UART_DefaultConfiguration( void );

 

 

/*=====================================

Implementation of functions

=====================================*/

 

/**

  * @brief  

 * Main program.

  * @parameter  

 * None

  * @returnvalue

 * None

  */

int main(void)

{

 UART_DefaultConfiguration();

 

  while(1)

  {

  if( USART_GetFlagStatus( USART1, USART_FLAG_TC ) == SET )

  {

   USART_SendData( USART1, 'A' );

  }

  }  

}

 

 

/**

  * @brief  

 * Initialize the UART with the default configuration.

  * @parameter  

 * None

  * @returnvalue

 * None

  */

void UART_DefaultConfiguration( void )

{

 GPIO_InitTypeDef GPIO_InitStruct;

 USART_InitTypeDef USART_InitStruct;

 

 

 /* Turn on the Clock for the UART and GPIO. */

 RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA

            | RCC_APB2Periph_AFIO

            | RCC_APB2Periph_USART1, ENABLE );

 

 

 /* Configure the UART1. */

 GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;

 GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9; /* TX */

 GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;

 GPIO_Init( GPIOA, &GPIO_InitStruct );

 

 GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;

 GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10; /* RX */

 GPIO_Init( GPIOA, &GPIO_InitStruct );

 

 USART_InitStruct.USART_BaudRate = 115200;

 USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;

 USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

 USART_InitStruct.USART_Parity = USART_Parity_No;

 USART_InitStruct.USART_StopBits = USART_StopBits_1;

 USART_InitStruct.USART_WordLength = USART_WordLength_8b;

 USART_Init( USART1, &USART_InitStruct );

 

 USART_Cmd( USART1, ENABLE );

}


   代码很短,也就八十来行。整个工程的结构如下:

    说明整个工程在windows下是能编译通过的。至于在开发板上的测试就不贴出来了,测试的结果就是在串口上可以看到不断地有字母‘A'输出。


    下面说一下整个工程怎么搬到Linux的开发平台上。

    首先,在Linux上打开Eclipse。新建一个C Project.如果环境搭建成功的话,可以看到有如下选项,在Executable中选择STM32F10x C/C++ Project,工具链就选Cross ARM GCC,填写好工程名字TestSTM32后点击下一步:

    由于我的CPU是STM32F103C8T6,所以Chip family是选STM32f10x Medium Density,Flash大小是64KB,RAM大小是20KB。可以根据自己的硬件实际情况进行填写。其它的可以按图配置。点击下一步:

    其实之后两页都可以按下一步,直到最后这一页,一定要选好工具链是GN Tools for ARM Embedded Processors ( arm-none-eabi-gcc ),并且填好工具链位置。最后点击完成。


   工程建立后,可以看到Eclipse已经将工程建好在Project Explorer中了。


    然后把工程中的src、system、include三个文件夹去掉,只剩下ldscripts文件夹。把我们示例程序的代码复制过来。如下图所示:

    其实为什么要把之前说的三个文件夹删去而不是直接在模板上把代码复制过去呢?其实直接在模板上添代码也行,模板用的也是3.5版本的固件库,但是要是以后固件库升级了或者不想用固件库呢?删去的目的就是为了可以让我们构建的工程更具有自由性。所以我选择直接把原来的工程代码复制过来。

    接下来是比较重要的一步,把启动文件startup_stm32f10x_md.s替换掉,从ST官网上下载的固件库包中,把STM32F10x_StdPeriph_Lib_V3.5.0/Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x/startup/gcc_ride7/startup_stm32f10x_md.s复制到工程中,并把启动文件的后缀s改为大写的S。如下图所示:

    要这样替换的原因是在windows中,所用的启动文件是针对Keil MDK这个IDE环境的,而现在我们要用GNU的工具链,所以应该要用回针对GNU启动文件。不然链接的时候会有问题。


    接下来就要开始配置一些东西了,右键工程打开属性。首先在C/C++ Build->Settings->Tool Settings标签中,找到Target Processor,在右边找到Instruction set,选择Thumb。找到Endianness,选择Little endian。如下图所示。

    然后,在Cross ARM GNU Assembler、Cross ARM C Compiler和Cross ARM C++ Compiler中的Preprocessor中定义两个宏:STM32F10X_MD和USE_STDPERIPH_DRIVER。其它的全部删去,这一个很重要,关系到后面的编译问题。一开始Eclipse会帮你定义好多宏,但都不需要,只留这两个就行了。


    然后,还是在Cross ARM GNU Assembler、Cross ARM C Compiler和Cross ARM C++ Compiler中的Includes修改为你包含有头文件的路径。如下图所示。


    接下来,是在Cross ARM C++ Linker和General中,把原本工程里的链接脚本路径补全。如下图所示:


    好了,这些设置好了之后,可以编译了吗?理论上是可以的,不过还有些代码要修改。这是由于固件库写的地方有些问题,参考文章如下:

    https://answers.launchpad.net/gcc-arm-embedded/+question/217817

    修改如下:

    在core_cm3.c中,找到uint32_t __STREXB(uint8_t value, uint8_t *addr)和uint32_t __STREXH(uint16_t value, uint16_t *addr)。把这两个函数中的"=r"改为"=&r",如下图所示:

    好,现在编译可以编译了。



    可以看到最后是编译成功了,而且对比于在Keil MDK里编译的文件大小,代码段所占的大小更小。这个编译效率还是令人满意的。

    编译了程序之后,怎么样才能下载到板子里并且进行调试呢?下面开始说明一下。

    在调试按钮旁边有个下拉箭头,点击箭头后点击Debug Configurations。然后双击Zylin Embedded debug( Native )。这样就会生成一个名称和工程名字相同的调试配置界面。如下图所示。



    在界面中点击Debugger标签。找到GDB debugger的文本框,通过浏览定位到上面提到要安装的arm-linux-gdb,然后点击应用。如下图所示。


    接着点击Commands标签。在'Initalize' commands里输入对JLink的初始化命令。点击应用。如下图所示。


    好了,问题就来了,这个初始化命令是怎么呢?究竟要怎么写呢?在这里我先给出我自己的初始化命令脚本。大家可以根据自己的实际情况进行修改。


target remote localhost:2331

monitor halt

monitor interface JTAG

monitor speed 1000

monitor endian little

monitor flash cpuclock = 72000000

monitor flash device = STM32F103C8

monitor flash download = 1

monitor flash breakpoints = 1

load Debug/TestSTM32.elf

monitor reg r13 = (0x00000000)

monitor reg pc = (0x00000004)


    这个脚本做了些什么呢?首先定义了gdb server的端口,接下来不断地往stm32和jlink下达命令:让stm32停机、设置使用JTAG接口,速度设置为1000kHz等等。最后下载程序并复位stm32。

    一开始的时候我也不知道要写怎么样的初始化脚本以及初始化命令。后来在Segger官网上找到了关于JLinkGDBServer的用户手册,其官网页面及下载地址如下:

官网页面:https://www.segger.com/jlink-gdb-server.html

用户手册下载地址:https://www.segger.com/admin/uploads/productDocs/UM08005_JLinkGDBServer.pdf

   重点参考3.4 Debugging on Cortex-M Devices和3.5 Supported remote commands这两节,脚本模板和命令解析都在这里了。

   设置好了这个页面之后不要急着关掉,一会调试就从这个页面开始的。插上JLink,连接好硬件到PC里。现在要手动启动gdb server。在JLink的驱动包里面,有一个可执行文件叫JLinkGDBServer。通过命令行启动它(最好就直接用root用户启动)。如下图所示。如果你硬件已经连接好了,驱动什么的都连接好了之后,就会提示你找到了Cortex-M3的设备。这样就正常了。注意,在调试的过程中不能关闭JLinkGDBServer,就让它这样开着就ok了。不然会调试不了的。

    接下来,在刚才Eclipse的Debug Configurations页面里,点击Debug。开始调试。这样就会跳到Eclipse的调试视图里,并且调试停留在启动文件的第一行汇编指令里。这样就说明调试已经成功了,之后怎么样调试程序就和在eclipse里调试其它pc程序一样。这里就不多说了。


    好了,在Linux环境里开发STM32的整个流程就已经介绍完了。写这一篇文章的目的只是为了记录一下过程,方便日后忘了步骤的时候进行查看,也希望能够帮助其他想在linux环境下开发stm32的人少走些弯路。

关键字:Linux环境  STM32  调试 引用地址:Linux环境开发STM32,从环境到调试

上一篇:STM32只开启SWD模式调试程序
下一篇:STM32 中断向量表的位置 、重定向

推荐阅读最新更新时间:2024-11-04 13:57

STM32什么时候使用AFIO?
什么时候要开启AFIO呢?参考手册: 说的很明白,操作AFIO的三类寄存器时需要开启: AFIO_EVCR AFIO_MAPR AFIO_EXTICRx 这三类其实是AFIO的全部寄存器, AFIO_EVCR是事件相关的,AFIO_MAPR是与重映射相关的,AFIO_EXTICRx是与外部中断相关的。 因此管脚重映射、外部中断、事件时开启AFIO。
[单片机]
STM32之使用PWM控制多路舵机
前言 最近在玩一个6自由度的机械臂,我手上这台机械臂的核心控制器件就是那六个能够180度旋转的舵机了。想想之前在学校还没有系统性的把舵机给玩明白,所以就索性拿手上的STM32来自己写驱动代码,将6个舵机给驱动起来。 舵机控制原理 舵机的控制原理还是比较简单的,而且控制的角度和精度能够比较好的按照开发者的意愿来进行,因此经常被应用与一些控制类器械中,如机械手、云台、2自由度摄像头等产品中。 舵机的外接线一般分为3根线,电源线、地线和信号线,而控制舵机转动,就是通过信号线给舵机发送一系列的周期信号(一般的舵机的能接收的信号周期为20ms),然后通过控制周期信号的高电平的持续时间来达到控制舵机转动的目的。我手上的
[单片机]
<font color='red'>STM32</font>之使用PWM控制多路舵机
STM32 进阶教程 8 - 位带操作
前言 有过51单片机开发经历的朋友应该都对51的IO口或一些特殊寄存器可以直接按位操作的方式不陌生吧,那么在stm32中有没有类似的操作呢,答案是肯定的,本节将给大家介绍如何在STM32中实现位带操作。 在《ARM Cortex-M3权为指南》中的第87页对位带操作如下描述: 位带操作 支持了位带操作后,可以使用普通的加载/存储指令来对单一的比特进行读写。在 CM3中,有两个区中实现了位带。其中一个是 SRAM 区的最低 1MB 范围,第二个则是片内外设区的最低 1MB 范围。这两个区中的地址除了可以像普通的 RAM 一样使用外,它们还都有自己的“位带别名区”,位带别名区把每个比特膨胀成一个 32 位的字。当你通过
[单片机]
<font color='red'>STM32</font> 进阶教程 8 - 位带操作
STM32 定时器输出比较时间模式
之前在《SM32定时器要点》中曾经讲过,定时器可以配置成六种模式,如下: TIM_OCMode 函数库描述 解释 TIM_OCMode_Timing TIM输出比较时间模式 冻结,输出比较不起作用 TIM_OOCMode_Active TIM输出比较主动模式 当比较发生时,强制输出高电平 TIM_OCMode_Inactiive TIM输出比较非主动模式 当比较发生时,强制输出低电平 TIM_OCMode_Toggle TIM输出比较触发模式 当比较发生时,输出翻转 TIM_OCMode_PWM1 TIM脉冲宽
[单片机]
<font color='red'>STM32</font> 定时器输出比较时间模式
STM32之时钟树笔记
1 STM32有五个时钟源:HSI、HSE、LSI、LSE、PLL 1.1 HSI:高速内部时钟、RC振荡器、频率为8MHz、时钟精度较差,可作为备用时钟源(时钟安全系统CSS)。 1.2 HSE:高速外部时钟、可接外部晶体/陶瓷谐振器(4MHz~16MHz)或外部时钟源(HSE旁路,Max 25MHz)。 1.3 LSI:低速内部时钟、RC振荡器、频率为40kHz,大容量MCU可进行LSI时钟校准。 1.4 LSE:低速外部时钟、接频率为32.768kHz的外部晶体/陶瓷谐振器。 1.5 PLL:锁相环倍频输出,时钟输入源可选择HSI/2、HSE或HSE/2。倍频可选择为2~16倍,最大输出72MHz。 用户可通过多
[单片机]
STM32之USART库函数USART_SendData的bug
1.最近在调试ATM32F103CB时发现,一串数据的最后一个字节总是发送不出去,用的是RS485收发; 2.代码如下: void uartReturn(unsigned char childBoardAddr) { uchar temp = 0; //must have temp += 0xAB; temp += childBoardAddr; temp += 0x30; temp += 0x01; temp += childBoardAddr; RS485_TX_EN; //enable rs485 tx sendByte(0xAB); sendByte(childBoardAddr); se
[单片机]
STM32控制16路舵机控制板PCA9685
介绍 PCA9685 是最新的快速模式 Plus(Fm+)系列中的一员。 Fm+器件可以提供更高的频率 (高达 1MHz)和更频繁(densely populated) 的总线操作(高达 4000pF)。 OE引脚一定要至低使能,或者直接接地 网上Arduino的教程很多,商家给的也是Arduino的驱动文件,那怎么在STM32上用呢? STM32与驱动板的连接 驱动板 STM32 VCC 3.3V GND GND SCL I2C_SCL SDA I2C_SDA OE GND(低电平) V+ 不接 V+可以不接而采用电源接线柱使用外部供电,用5V的充电宝即可 由于PCA9685是使用IIC的,那么如何使用I
[单片机]
STM32下uIP移植问题
就我个人认为在uIP的移植中除了驱动之处有以下几点需要注意: 1.uip_timer 时钟要加入到中断中去。 2.各种appcall实现。如在tcp_client_demo.c 有如下语句 if(uip_len 199) { ((u8*)uip_appdata) =0; } strcpy((char*)tcp_client_databuf,uip_appdata); 这样在处理数据长时都是以tcp_client_databuf 数组的长来处理,这样不灵活,client从网络中接收到的数据长本来就是用一个全局变量uip_len来存储的。
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved