IDA Pro学习笔记-1

0 概述

本文主要介绍常用的,简单的逆向和反汇编工具

1 分类工具

在遇到一个新文件时,我们需要知道,这是一个什么类型的文件;记得,看后缀名来判断是不准确的,下面的几个工具,用来帮助你检验文件类型

  1. file
    Linux下面的命令行工具,可以利用后缀名,文件头的特征码,文件开头的特殊命令行来判断类型,能识别绝大多数的文件类型

  2. PE Tools
    一组用于分析windows系统中正在运行的进程和可执行文件的工具。能捕获进程,并将内存映像转储,然后用PE
    sniffer来分析可执行文件是由何种编译器构建的

  3. PEiD
    windows工具,用于识别构建EXE文件所有的编译器,并确定混淆代码的工具类型

2 摘要工具

在分析到类型后,我们就需要分析文件内的详细信息,下面这些工具就该派上用场了

  1. nm
    显示出目标文件中的所有符号;我们知道,obj文件里面都有很多符号段,用于存储符号信息,nm就可以将这些信息给打印出来,便于分析

  2. ldd
    用于解析静态链接或者动态链接的库信息

  3. objdump
    大而全的工具,用于显示目标文件的所有信息,比如节头部,专用头部,调试信息,符号信息,反汇编代码等
    还有一个readelf工具,也有同样的功能;
    二者的区别是:objdump依赖于libbfd,readelf不依赖libbfd

  4. otool
    mac OS X底下的objdump工具

  5. dumpbin
    VS套件里面的一个工具,功能类似objdump和ldd

  6. C++filt
    C++会将重载函数进行重命名(name-mangling),从而保证符号唯一性,但这样为我们理解反编译函数名称造成了困难,filt就是复原原始函数名用的
    ,比如nm a.out | grep demo | c++filt就可以复原a.out里面所有的demo函数名

3 深度监测工具

  1. strings
    用于提取文件中的字符串内容,我们经常在windows里面可以看到提示性文字,通过这个工具,我们就知道文字的位置,然后反向找出调用文字的程序
    代码,最后修改代码即可
    但是记住,不要用文字信息来推断程序功能

  2. 反汇编器
    X86架构下的ndisasm和diStorm可以用来反汇编代码和数据

4 最后

这些工具很基础,都是linux下的常用工具,应该掌握

IDA Pro学习笔记-0

0 概述

IDA,懂的人自然懂,不懂的人请百度
这里不做过多介绍

本篇作为学习笔记的第一篇,主要介绍反汇编的理论和常见反汇编方式

1 反汇编简介

编程语言进化过程为:二进制-》汇编-》C/C++等编译语言-》python等动态脚本语言
二进制的,可以直接看ARM Thumb2指令集手册,里面有对应的编码介绍,汇编就是ARM中常见的启动代码,
C/python之类的,都是程序员常见的语言,都很熟悉,不多介绍

2 为什么要反汇编

反汇编的意义在于,很多时候,我们并不能拿到C级别的源码,只能拿到bin格式的固件,所以需要通过bin来反向成汇编代码,然后分析程序
其它的几个原因

  1. 分析恶意软件
  2. 分析闭源软件的漏洞
  3. 分析闭源软件的互操作性
  4. 分析编译器生成代码,以验证编译器性能和准确性
  5. 在调试时显示程序指令

3 反汇编的困难

理论上来讲,bin属于透明代码,大神可以直接看二进制格式,但这么做效率太低,所以很多人做了工具,IDA就是其中一种,虽然有了工具,
但分析过程,仍然困难重重,原因如下

  1. 编译过程会造成损失
    bin是给机器看的,所以它不需要任何变量或者函数,但我们需要,所以变量类型只能通过分析,才能知道具体类型
    现在ARM Thumb2指令集稍微好一点,会固化各种符号和类型,方便分析一些
  2. 编译属于多对多操作
    主要是因为编译优化,或者故意混淆的手段,或者IAR编译时,没有生成符号表,从而导致缺乏一些分析辅助信息
  3. 反编译器依赖于语言和库
    选对反编译器,才能正确反编译
  4. 反编译任何错误,都会影响反编译生成的效果

4 如何反汇编

最简单的工具,可以用各种IDE里面的binary工具,比如elfdump,直接导出符号表和汇编代码
但这种太简单了,不便于大型系统分析

理论上,反汇编的过程如下

  1. 确定反汇编的代码区域
    这个要看具体文件格式,比如elf之类的,直接包含各种section,可以分析
    但bin,就要区分哪些是代码,哪些是数据,这是一个难点
    我们可以换一个方向来看,对于STM32或者ARM Cortex系列的芯片来说,入口是固定的,我们直接找程序入口就可以了

  2. 找到入口地址,开始逐条分析
    这里,可能需要进行表查找来获取数据;对应C语言来说,就是字符串表,变量表或者函数表

  3. 找到操作符和操作数,反编译成汇编指令

  4. 继续反汇编下一条指令

5 反汇编算法

主要有两种,也很简单

  1. 线性法
  2. 递归下降法

线性法:就是逐条分析汇编,读取操作码,读取操作数,反汇编,然后下一条指令;理论上很简单,但容易出错,比如,我故意在汇编指令中
插入一些混淆数据,就可以扰乱反汇编器的输出;它的好处在于,能分析出所有的二进制代码
GDB和dbjdump都是采用线性分析法,他们因为有elf的各种辅助信息,在有代码的基础上调试,所以能知道哪些是有效数据,有效代码

递归下降法:则是从另外一个方向来反汇编,就是从程序入口地址,然后分析下一条指令,顺序指令则直接继续分析,分支指令,比如if或者switch,则
直接分成两个反编译方向,依次反编译;或者跳转指令,就跳转到对应到地址。
也就是说,反编译器会尝试理解bin程序流,然后给出最佳的反汇编代码,但这样,也会有问题,机器毕竟是机器
想一下,我们在函数中,故意设置LR返回地址,估计反编译器就无能为力了。针对这种情况,我们可以用动态模拟器来调试,百试百灵

6 最后

反汇编的过程就像填字游戏,给你有限信息,然后补齐整个游戏,还是挺好玩的

树莓派底层编程-GPIO篇

0 前言

本来是准备写一篇用python控制GPIO的例子,结果发现太简单了,还是深入一些吧,多深入底层

接下来,我会按照下面的顺序来介绍:
1)GPIO控制器地址映射
2)GPIO主要控制寄存器介绍
3)GPIO操作流程
4)用C语言控制GPIO
6)用python来控制GPIO

1 概述

树莓派2B采用的CPU为BCM2836,外设部分和BCM2835完全一致,所以就可以参考BCM2835的寄存器手册
但是,这个寄存器手册笔误有点多,建议配合着wiki的勘误手册来看

CPU总共有54个IO,每个IO都可以复用,配置输入或者输出模式,单从GPIO部分来看,比较简单,无非是输入/输出,触法模式等,和一般的MCU没有太大差异

2 地址映射

BCM2835将BUS的地址空间,通过MMU映射到线性寻址空间,如下所示

Note on compile libnfc and mfoc

概述

本文主要记录编译nfc-tools时遇到的问题以及解决方案

测试平台:Raspberry 2B+

1. 访问不了google code,无法下载源码

mfc-tools 仓库已经从google转移到github

2. 编译nfcuk和mfoc时,autoreconf失败

加入-vis参数,全部指令如下

1
autoreconf -vis
automake
autoconf
./configure
make

3. 按照网上教程,需要修改str_nfc_target函数

不需要,现已修复

4. 在树莓派2B+上使用配置nfc,无法打开SPI端口,提示”TFI error”

修改SPI速率参数,保持默认值即可,/etc/nfc/libnfc.conf全文如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# Allow device auto-detection (default: true)
# Note: if this auto-detection is disabled, user has to set manually a device
# configuration using file or environment variable
allow_autoscan = true

# Allow intrusive auto-detection (default: false)
# Warning: intrusive auto-detection can seriously disturb other devices
# This option is not recommended, user should prefer to add manually his device.
allow_intrusive_scan = false

# Set log level (default: error)
# Valid log levels are (in order of verbosity): 0 (none), 1 (error), 2 (info), 3 (debug)
# Note: if you compiled with --enable-debug option, the default log level is "debug"
log_level = 1

# Manually set default device (no default)
# To set a default device, you must set both name and connstring for your device
# Note: if autoscan is enabled, default device will be the first device available in device list.
# 错误配置
#device.name = "Itead_PN532_SPI"
#device.connstring = "pn532_spi:/dev/spidev0.0:500000"

# 正确配置
device.name = "Itead_PN532_SPI"
device.connstring = "pn532_spi:/dev/spidev0.0"

5. PN532无法识别门禁卡

可以识别13.56MHz 高频IC卡,但无法识别125KHz 低频ID卡
NOTE: 可以自制125KHz天线,软件模拟ID卡射频协议

something about BCM2709 and BCM2836

前言

最近玩树莓派和编译内核的时候,经常发现树莓派官方和内核开发者对CPU的称呼有两种

  • BCM2708/BCM2709
  • BCM2835/BCM2836

内核开发者喜欢称之为BCM2708/9,而树莓派和博通则喜欢称为BCM2835/6

被搞的晕晕呼呼,所以花了几个小时找资料,看手册,弄清楚了二者的区别

友情提醒

本文部分链接,需要翻墙访问,请自备梯子

二者区别

google了很多资料,发现

  • BCM2708/9 属于处理器的家族
  • BCM2835/6 属于处理的具体型号

树莓派内核开发者在github上有相关讨论

摘录部分如下

1
Q: What's the correct device model to reference as the machine type and in any device drivers?

A: Technically 2708 is the family, and 2835 is a specific implementation.
   We now know that 2835 is the only implementation in the family that can run linux,
   (and there won't be new models of this family), so it probably doesn't matter which model is used,
   although it should be consistent.

Q: So it would be reasonable to name all the drivers 2708 but the specific device tree file 2835?
   (assuming that if there is ever another model of that family that can run linux it would need a
	different list of devices)
A: That sounds reasonable.

网上的更进一步讨论,请访问why-is-the-cpu-sometimes-referred-to-as-bcm2708-sometimes-bcm2835

另外,从wiki得知,
博通联合树莓派已经完全开放BCM2835这颗CPU的资料,所以网上说的没有资料的情况,可以忽略

1

The Broadcom YouTube page has videos demonstrating the video processing capability, but their website only goes as
far as providing product briefs. Detailed data and development tools are only available under NDA, and then only for
manufacturers with a market for very many units. However, on 28 February 2014, on the day of the second anniversary of
the Raspberry PI Broadcom, together with the Raspberry PI foundation, announced the release of full documentation for
the VideoCore IV graphics core, and a complete source release of the graphics stack under a 3-clause BSD license.

树莓派BCM2835/6资料链接

  1. https://www.raspberrypi.org/documentation/hardware/raspberrypi/bcm2835/README.md
  2. https://www.raspberrypi.org/documentation/hardware/raspberrypi/bcm2836/README.md

对于博通BCM设计架构,他是将GPU作为MCU来使用,在启动时,加载bootloader,初始化RAM,外设等,然后启动ARM内核,开始全速运行状态
这样设计的好处是,ARM11或者ARM-A内核,完全作为运算核心;GPU处理视频和外设,系统可以无缝升级CPU,而对外设部分影响很小
就像这次的BCM升级到BCM2836,外设驱动,仅仅需要修改一下GPIO和DMA的偏移量,现有驱动代码,可以继续使用

Hello elua

概述

下文会简单的介绍elua,然后编译固件,烧录到STM32F4 Nucleo板子上,最后用lua来编写一个简单的hello程序

注意事项

在继续阅读之前,请看下面几点

  1. elua项目的版本比较多,代码文档和网站文档不一致,建议参考代码中的文档说明;本文档代码采用github master主分支0.9版本
  2. 本文以linux平台为例来说明编译过程,实际上,我是用树莓派来编译elua的,并用树莓派烧录,调试STM32;elua可以跨平台编译,具体请参考https://github.com/elua/elua/tree/master/doc/en building章节

STM32F7 Discovery 外部可用接口

前言

拿到板子后,我们重点需要考虑的是STM32F7的板子还有多少资源可供我们使用
这里重点关注的是通信接口(比如SPI/I2C/IO之类的),因为可以通过这些接口外挂器件,拓展功能
查看F7手册和Discovery板子原理图,可以知道Discovery采用的是216Pin管脚的F746NG芯片,虽然板子外设比较多,
但芯片IO足够用

板子功能框架如下所示

Discovery功能框图

大致将IO分为以下几个部分

  1. USB OTG(HS/FS)
  2. Camera
  3. Audio
  4. Ethernet

RT-Thread的小例子

概述

嵌入式中最简单的就是按键,点亮LED,很多入门教程中,将这个作为例子来讲解
下面我就用这个最简单的例子,来演示RT-Thread线程通讯组件的不同使用方法

  • 关中断
  • 关调度器
  • 信号量
  • 互斥量
  • 事件
  • 邮箱
  • 消息队列

关于按键检测,为了简单,我用了轮询的模式,100ms轮询一次,然后检测电平是否有变,并做判断;
当检测到按键按下时,就翻转LED电平

最后,我们尝试用消息队列来实现:按下键后,LED闪烁多次

测试环境

  1. RT-Thread stable 2.0.0
  2. STM32F446RE Nucleo板子
  3. IAR For ARM 7.4

准备工作

  1. 搭建IAR开发环境,调整启动代码和链接脚本
  2. 修改gpio.c里面的static const struct pin_index pins[]数组,因为我们的F446RE Nucleo板子按键和LED分别接到
    PC13和PA5上面,所以需要在pins表示里面包含这两个管脚,我这里显示的27和54,如下所示

使用RT-Thread Finsh

关于Finsh

了解一个东西,首先要知道组件的历史渊源,才能更好的理解它要解决的问题,这样就能更容易的理解它的架构和设计基础

官网对Finsh的介绍

finsh是RT-Thread的命令行外壳(shell),提供一套供用户在命令行的操作接口,主要用于调试、查看系统信息。 finsh支持两种模式:1. C语言解释器模式, 为行文方便称之为c-style;2. 传统命令行模式,此模式又称为msh(module shell)。

C语言表达式解释模式下, finsh能够解析执行大部分C语言的表达式,并使用类似C语言的函数调用方式访问系统中的函数及全局变量,此外它也能够通过命令行方式创建变量。

在msh模式下,finsh运行方式类似于dos/bash等传统shell。

在大部分嵌入式系统中,一般开发调试都使用硬件调试器和printf日志打印,在有些情况下,这两种方式并不是那么好用。比如对于RT-Thread这个多线程系统,我们想知道某个时刻系统中的线程运行状态、手动控制系统状态。如果有一个shell,就可以输入命令,直接相应的函数执行获得需要的信息,或者控制程序的行为。这无疑会十分方便。

在嵌入式领域,C语言是最常用的开发语言,如果shell程序的命令是C语言的风格,那无疑是非常易用且有趣的。嵌入式设备通常采用交叉编译,一般需要将开发板与PC机连接起来通讯,常见连接方式包括,串口、USB、以太网、wifi等。一个灵活的shell应该可以在多种连接方式上工作。

finsh正是基于这些考虑而诞生的,finsh运行于开发板,它可以使用串口/以太网/USB等与PC机进行通信。下图是finsh的实际运行运行效果图。开发板运行RT-Thread,并使能了finsh组件,通过串口与PC机连接,PC上运行Secure CRT。按下回车,然后输入list_thread()将会打印系统当前所有线程,以及状态。

传统的打印式手段,属于单向的;通过调试器来调试,不仅可以输出,而且可以输入,就属于双向的,但IDE的调试擅长于静态调试,比如设置断点,检查变量什么的;Finsh在一定程度上增强了动态调试功能,也使远程调试变得可能;RT-Thread为我们搭建了调试框架,用户不在需要单独编写解析命令机制,只需要关注需要导出的函数和变量;

Finsh里面动态线程的栈使用量,是一个很实用的功能
另,参考资料里面有个RT-Thread测试框架的介绍文章,可以构建自动化测试框架

初步体验

这部分,RT-Thread官方的手册和跟我学RT-Thread写的很好,我就不自己敲字了,避免重复造轮子
请参考 http://www.rt-thread.org/download/manual/study_rtt.pdf 第8篇和http://www.rt-thread.org/download/manual/rtthread_manual.zh.pdf 第11章

移植

首先参考http://www.rt-thread.org/download/manual/study_rtt.pdf 第8篇和http://www.rt-thread.org/download/manual/rtthread_manual.zh.pdf 第11章,在MDK环境下完成移植

如果您需要使用IAR工程,务必请阅读下一章的IAR工程问题

常见问题

1. IAR工程问题

RT-Thread scons脚本有一些bug,导致通过scons --target=iar -s生成的脚本,没有包含启动代码和链接脚本,从而致使IAR工程工作不正常,具体表现为1)FINSH无法获取函数名,变量名
2)不能使用中断 3)系统初始化不正常

修复手段:

1.    参考下面两个bug fix文件,修改BSP目录下对应的链接脚本和scons脚本
    1.    https://github.com/RT-Thread/rt-thread/pull/566/files
    2.    https://github.com/RT-Thread/rt-thread/pull/565/files
2.    删掉旧工程,重新使用`scons --target=iar -s`生成IAR工程
3.    手工在IAR工程中,添加link脚本(icf文件)

2. 如何禁用HISTORY

默认情况下,rtconfig.h没有出现FINSH_USING_HISTORY宏,RT-Thread启用HISTORY功能,并保持默认5条历史记录
可以通过在rtconfig.h中,显示定义#define FINSH_USING_HISTORY 0的方式来禁用HISTORY功能
通过定义#define FINSH_HISTORY_LINES 5来调整历史记录的长度

原理分析

0. 整体流程

[占位符]以后添加

1. 导出函数/变量

Finsh将需要导出的函数,添加信息后,封装到一个新的finsh_sysvarfinsh_syscall 结构体中,并将这个结构体放置在固定的段中FSymTab, VSymTab,最后通过__section_begin__section_end两个编译器函数来获取段的开始位置和结束位置
这些步骤等效于手工将导出结构体变量添加到一个预设的结构体数组中,如下所示

1
2
3
4
5
6
7
8
struct finsh_syscall _syscall_table[] =
{
{"hello", hello},
{"version", version},
{"list", list},
{"list_thread", list_thread},
...
}

但这么容易导致bug,因为注册表和函数实现的地方,往往不在同一个文件夹,过于分散,有时候,删除某个函数后,会忘记手工删除注册表的信息

RTT通过提供统一导出接口,将这个工作交给了编译器,最大程度的减少了bug的发生

岔开一个话题:对于某些静态驱动注册表来说,也可以利用这种方式实现。注意,仅仅是静态的,也就是说,段size在编译时就已经确定
RT-Thread的驱动架构没有这么做,而是提供驱动注册API,就是为了给静态驱动和动态驱动,提供统一的入口,更加方便灵活

3. 编译和虚拟机执行

这部分请参考阿莫论坛文章http://www.amobbs.com/thread-5539405-1-1.html

参考资料

  1. RT-Thread参考手册
  2. 跟我一起学习RT-Thread
  3. 体验Finsh组件
  4. Amobbs:Finsh原理分析
  5. RT-Thread测试框架的使用

试用树莓派2B

1. 致谢

最近一直想学linux驱动编程和学习内核,刚好得到一块儿树莓派2B,所以准备用心搞一下
在此特意感谢21ic 小跑堂美女和may美女,刘sir

2. 树莓派2B升级了什么

提到树莓派,大家都知道是什么东西,这里就不做背景介绍了,感兴趣的,可以参考树莓派官网介绍 https://www.raspberrypi.org/products/raspberry-pi-2-model-b/

这次拿到的是2B板子,主要升级了内存和CPU
下面是官方网站展示的2B的性能参数:

  • A 900MHz quad-core ARM Cortex-A7 CPU
  • 1GB RAM
  • 4 USB ports
  • 40 GPIO pins
  • Full HDMI port
  • Ethernet port
  • Combined 3.5mm audio jack and composite video
  • Camera interface (CSI)
  • Display interface (DSI)
  • Micro SD card slot
  • VideoCore IV 3D graphics core

相比于前代的树莓派,2B采用TF卡,尺寸更小,也去掉了不常用的RCA接口(俗称AV接口),完全采用HDMI接口
这么改,最大的好处就是树莓派形状变得很整齐,不再像原来那样突起一部分

从处理器来说,将原来的高通BCM2835更新到了BCM2836,增大RAM到1G,估计你对这些也不太感冒,只要知道速度提高了6倍就好了

6倍,6倍,6倍,重要的事情说三遍

因为处理器架构从ARM7TMDI变成了4核A7,所以能跑标准的操作系统,比如安卓或者ubuntu或者win10

大致看了win10烧录内核的步骤,看到“首先你需要一台运行win10的笔记本”,看到这里就没继续看了,哪位有兴趣的可以根据微软IOT团队官方博客来实战
https://www.raspberrypi.org/blog/windows-10-for-iot/
https://dev.windows.com/zh-cn/iot

对了,树莓派2B支持DSI显示接口和CSI相机接口,从而可以直接高速视频输入和屏幕输出
这个有什么用呢?理论上来说,你可以拿树莓派做一个平板电脑

无图无真相

一个图片胜千言,show me the images now

树莓派宣传图
树莓派包装正面
树莓派包装反面
树莓派正面
树莓派反面
树莓派合照
树莓派大眼睛

那个神秘的大眼睛是什么???
红外夜视摄像头,准备拿来做opencv人脸识别和视频监控,更多信息暂时保密

树莓派的简单介绍到这里,接下来介绍烧录系统,更新内核,跑opencv做人脸识别

树莓派性能体验

试用了一个星期,最大的体验是树莓派性能有显著提高,6X绝对不是夸大
主要体现在

  1. 编译opencv的时候,速度有很大提升
  2. 播放1080P的高清视频,硬解码,CPU占用率在2%左右,可以忽略不计

前几代树莓派产品,据说跑视觉算法的时候,总是卡顿,树莓派2B在这方面有极大的提升,适合做视觉和图像处理相关的任务

如果您在做这方面的工作,可以尝试树莓派2B,也欢迎和我交流

体验步骤

我玩树莓派的步骤大致包括

  1. 安装串口工具
  2. 连接树莓派串口,通过串口控制树莓派
  3. 连接无线网卡(360Wi-Fi),配置开机自动上网
  4. 通过SSH连接树莓派
  5. 如果你有屏幕和HDMI接口线,请连接树莓派;如果没有,则用realvnc在笔记本上显示远程桌面
  6. 编译源码,安装opencv
  7. 编写opencv测试程序
  8. 使用500W摄像头进行动作捕捉(进行中)

这里仅仅做一个简要性的概述,列出注意事项,详细的命令和步骤,请参考blog文章或者网站上的文章

注意事项:

  1. 树莓派2B的IO变为40Pin,但前26pin仍然兼容原来的树莓派,详细的GPIO列表,请参考http://www.element14.com/community/docs/DOC-73950/l/raspberry-pi-2-model-b-gpio-40-pin-block-pinout
  2. 最近的树莓派内核(4.0以上),直接支持360Wi-Fi 2代(MT7601芯片),所以不需要进行重新编译内核和驱动;网上很多教程都是以3.x版本的内核为案例来讲述编译Wi-Fi网卡驱动和内核,请有取舍的参考
  3. SSH连接,mac下可以直接用terminal,windows下可以用secure CRT
  4. 在编译opencv的时候,使用树莓派来wget或者git下载源码,可能会很慢;建议用PC机下载,然后通过scp命令来复制到树莓派主机上,实测Wi-Fi数据速率可以达到6M/S
  5. 编译opencv时,请参考opencv的官网3.0版本编译安装指南,网上教程很多是以opencv 2.4版本来介绍,因为新内核不在支持libtif4版本的库,所以会导致后面编译失败,,,切记,切记,我因为这个点,折腾了两天时间
  6. 安装VNC远程桌面时,请尽量使用realvnc server和viewer,网上很多人用tightvnc server,实际测试中,这个VNC会导致显示UI界面时,出现RANDER错误
  7. 在编译opencv时,会因为内存不够导致编译错误,显示4G内存完全用完,无法继续编译;解决方案就是重新调整linux扇区,来完全使用SD卡的8G内存,详情请参考http://cedar-renjun.github.io/2015/10/11/resize-raspberry-sd-volume/
  8. 播放1080P视频时,请使用omxplayer,这个播放器专门优化过,CPU占用率非常低,可以忽略不计,,,性能突出

最后

总体而言,树莓派2B的性能,有了显著的提升,可以跑各种操作系统,跑视觉和图像处理,值得购买

我正在通过树莓派学习opencv,欢迎交流

安装opencv

前言

一直对opencv比较好奇,所以就尝试着在树莓派上面编译安装了opencv,参考了网上不少资料,各种折腾,最终搞定
最大的体会是要有耐心,装opencv折腾了2天多,下文主要记录安装步骤和注意事项

树莓派系统4.1.7

开始折腾

首先参考了这个 http://www.pyimagesearch.com/2015/02/23/install-opencv-and-python-on-your-raspberry-pi-2-and-b/
文章,老外讲如何在树莓派上面利用opencv操纵CSI接口的摄像头,他用的是2.7版本的python和2.4版本的opencv,刚开始进行很顺利

到第二步的时候,找不到libjpeg8-dev libtiff4-dev这两个源,提示可以用libjpeg-dev libtiff5-dev来替换,替换就替换吧,以为没事儿呢,结果到最后编译时,提示找不到libtiff4-dev的库文件,编译失败,,,,,

又卸载了各种安装包,参考官网教程安装了oepncv3.0和相关的库,这里就不贴步骤了,请参考http://docs.opencv.org/3.0-last-rst/doc/tutorials/introduction/linux_install/linux_install.html

注意一点,在下面步骤之后

1
2
3
cd ~/<my_working_directory>
git clone https://github.com/Itseez/opencv.git
git clone https://github.com/Itseez/opencv_contrib.git

下载的两个目录文件,要合并到同一个目录中,比如source目录,然后在source同级目录下建立build目录,然后按照官方的编译步骤,一步步来进行
这些步骤耗时比较长,可以通过PC用迅雷下载好,然后scp拷贝到树莓派中,进行编译
消耗的大致时间,请参考资料1中的耗时,还是比较准确的

编译完成后,install进行安装

然后通过编译读取图片的例子,参考C语言版本的 http://blog.csdn.net/moc062066/article/details/6312216

编译完成后,记得terminal ssh
无法执行这个文件或者执行后看不到窗口,需要进入桌面环境来打开,如果你直接有一个显示器,那就可以直接运行,显示出来图片
没有的话,可以用VNC来远程显示桌面,不过记得要用realvnc的viewer和server,网上流行的tightvncserver会导致显示时出现RAND错误

当你按照步骤,执行完,opencv环境就搭建完毕

接下来,enjoy opencv

参考资料

  1. install-opencv-and-python-on-your-raspberry-pi-2-and-b
  2. opencv官网
  3. 官方编译指导
  4. Opencv例程显示图片

充分使用树莓派SD卡容量

前言

在编译opencv的时候,出现内存不够的情况,/root使用率100%,导致编译错误,所以需要拓展SD卡容量

google了一下,发现树莓派在默认情况下,仅仅使用了SD卡的4G容量,剩下的空间,属于空白分区,完全没有利用起来
所以,我们可以通过df命令,来调整linux分区的size

操作步骤

  1. 重新树莓派,进入命令行页面
  2. 登陆树莓派,用户名pi,密码raspberry
  3. sudo su
    切换至超级用户
  4. df -h
    显示出当前分区的状态和使用率
  5. 输入fdisk /dev/mmcblk0 加载SD卡
  6. p打印当前分区
    你应该会看到三个分区(mmcblk0, mmcblk0p1, mmcblk0p2),现在把分区2的信息写下来(/dev/mmcblk0p2)
    我主要记录了开始扇区(122880)和结束扇区(8447999)的数值
  7. d开始删除分区
  8. 系统提示输入删除分区号,输入2
  9. n新建分区,然后依次输入p, 2
  10. 接下来输入原来记录的2扇区开始号(122880),记得替换成你自己的数字
  11. w保持配置
  12. 输入reboot重启树莓派
  13. 输入sudo resize2fs /dev/mmcblk0p2 更新系统
  14. 输入df -h看看,是不是已经完全使用了剩余空间

参考文档

  1. http://ray.dotnetage.com/posts/2015-5-15/rpi-resize-sd/
  2. http://m.blog.csdn.net/blog/lichao_ustc/46740443
  3. http://www.rs-online.com/designspark/electronics/knowledge-item/raspberry-pi---%E8%B0%83%E6%95%B4%E4%BD%A0%E7%9A%84sd%E5%8D%A1%E5%88%86%E5%89%B2%E5%8C%BA%E7%9A%84%E5%A4%A7%E5%B0%8F
  4. http://www.computerhope.com/unix/udf.htm
  5. http://www.cnblogs.com/peida/archive/2012/12/07/2806483.html

编译树莓派内核

前言

拿到树莓派后,刚好手里有个360 Wi-Fi网卡(MT7601的芯片),就准备放树莓派上使用
插上去不识别,一搜才知道要重新编译内核,编译驱动什么的

原来没折腾过linux的编译,所以趁此机会,好好学习一下
期间查了网上很多资料,尝试,然后各种错误,最后还是官网资料英文资料最靠谱

搭建ubuntu环境

这个比较简单,请参考网上教程,完成ubuntu基本环境的搭建

搭建交叉编译环境

编译内核,可以在树莓派上进行,也可以在PC主机上进行编译,因为PC主机内存大,CPU性能高,所以一般都是在PC上进行
这里就引入了一个名次“交叉编译环境”

其实,刚听说交叉编译时,以为是多么高大上的技术,后来发现,就是在PC上安装工具,为CPU编译出可执行文件
我们一直以来用MDK,IAR开发STM32,AVR,也算是交叉编译了,,,哈哈

这里不做过多解释

树莓派官方为我们提供了对应的编译工具

官方推荐用git来下载,命令如下

1
$ git clone https://github.com/raspberrypi/tools

但实际下载时,git的速度实在难以恭维,建议直接用浏览器去github页面点击”Down as zip”下载

特别注意:下载完成后,注意检查下载包是否完整,不然在编译时会出现一堆莫名其妙的错误

下载完成后,将tools解压到某一个目录(XXX)下,那么tools的可执行目录为

1
2
3
4
5
32-bit 版本
XXX/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin

64-bit 版本
XXX/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin

接下来,我们将这个路径添加到PATH环境变量中

这里有一个小插曲,因为我用的是普通用户,添加路径到.bashrc文件中后,编译源码的时候,提示没有系统权限,所以又加了sudo来提升权限
但是仍然编译出错,提示找不到gcc和ld工具,找了半天原因,发现
1)下载的tools压缩包不完整,丢失了一些文件,所以重新下载了tools
2)普通用户的.bashrc和超级用户的.bashrc不在同一个目录,即便是把PATH添加到/etc/profile中也不能,仍然会提示超级用户找不到gcc之类的错误
解决方法就是先通过sudo su来切换为超级用户,然后把PATH添加到root的.bashrc文件中

添加方法如下

  1. 打开root/.bashrc
  2. 在最后一行,添加export PATH=$PATH:XXX/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin

添加完成后,注销超级用户,然后重新切换为超级用户,在shell下输入arm-linux-gnueabihf-gcc -v来验证PATH变量是否生效

下载内核源码

到git上下载源码

1
$ git clone --depth=1 https://github.com/raspberrypi/linux

还是那句话,git速度太慢,建议网页直接下载,但注意检查文件完整性
事后证明,很多错误,都是因为下载的源代码不完整导致的

下载后,随意放一个目录下,将目录名改为linux

编译内核

进入linux目录,输入下面的命令

树莓派1代

1
2
3
$ KERNEL=kernel
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- bcmrpi_defconfig
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zImage modules dtbs

树莓派2代

1
2
3
$ KERNEL=kernel7
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- bcm2709_defconfig
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zImage modules dtbs

然后就是漫长的编译时间,在mac下,大概编译了一个小时左右
如果你电脑是多核的,可以在make 命令中增加-jn进行多线程编译
原则上,n是你处理器个数多1.5倍,比如我是4核电脑,就可以-j6

1
$ make -j6 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zImage modules dtbs

编译完成后的安装过程,请参考INSTALL DIRECTLY ONTO THE SD
CARD

最后,当我编译完成后,突然发现树莓派4.1.y内核已经默认支持了我的360wifi 2代,所以就没有继续编译网卡驱动了
^_^

参考资料

  1. 官方:树莓派Linux文档主页
  2. 官方:内核编译
  3. 官方:无线连接

建立STM32 F7 MDK 开发环境

安装MDK5开发环境

  1. 下载最新版MDK5
  2. 利用工具 破解MDK5

以上两步比较简单,不详描述

安装CubeF7

CubeMX是ST提供的一套库和框架标准,也是一种工程模版

  1. 下载http://www.st.com/web/en/catalog/tools/PF261909
  2. 下载完成后,利用MDK5打开STM32Cube_FW_F7_V1.1.0\Projects\STM32746G-Discovery\Demonstration\MDK-ARM\Project.uvprojx

更新ST-Link驱动和固件

  1. 进入ST官网http://www.st.com/web/catalog/tools/FM146/CL1984/SC720/SS1450/PF251168?s_searchtype=partnumber
  2. 通过STSW-LINK009更新st-link驱动
  3. 通过STSW-LINK005来更新固件

连接F7 Discovery开发板

  1. JP1的跳帽安装到5V-link
  2. 找一根mini USB线,插入CN14
  3. 插入电脑USB口,这时系统会枚举出ST-link设备,然后F7会启动固件,在屏幕上显示图标

常见问题

1 插入USB后,屏幕没亮;将USB插入充电器口,屏幕不亮

因为默认通过ST-link来供电,插入电脑USB接口后,只有枚举成功后,才会开启MCU的供电系统
枚举的时候,100mA;枚举成功后,才能供电500mA,如果电脑USB不接受500mA或者使用USB,就会枚举失败
详细的信息,请参考手册Power章节

1
2
3
4
5
6
7
8
STM32F746G-DISCO discovery board can be powered from ST-LINK USB connector CN14 (5V link), but only ST-LINK circuit has
the power before USB enumeration, because the host PC only provides 100mA to the board at that time. During the USB
enumeration, STM32F746G-DISCO board asks for the 500mA power to the host PC. If the host is able to provide the required
power, the enumeration finishes by a “SetConfiguration” command and then, the power transistor U8 (ST890) is switched
ON, the red LED LD2 is turned ON, thus STM32F746G-DISCO board can consume maximum 500mA current, but no more. If the
host is not able to provide the requested current, the enumeration fails. Therefore the ST890 (U8) remains OFF and the
MCU part including the extension board won’t be powered. As a consequence the red LED LD2 remains turned OFF. In this
case it is mandatory to use an external power supply.

2 用MDK5编译工程后,下载到板子,图标显示不正常

MDK的download工具,默认没有支持外部Flash的算法,所以会导致没有图标的部分,没有烧录到FLASH芯片

解决方案

1
2
3
4
- Open STM32 ST-Link Utility V3.6, click on "External Loader" from the bar menu then check "N25Q128A_STM32F746G-DISCO" box 
- Connect the STM32746G-DISCOVERY board to PC with USB cable through CN14
- Use "STM32CubeDemo_STM32746G-DISCO_V1.0.1.hex" file with STM32 ST-Link Utility to program both internal Flash and external QSPI memory
- Run the demonstration

Networking and the BSD Sockets APIs

by Michael Beam
12/27/2002

原文链接: http://www.macdevcenter.com/pub/a/mac/2002/12/26/cocoa.html?page=1

We’ve spend a great deal of time talking about Rendezvous in the previous two columns, but Rendezvous can’t exist in a vacuum. Having user-friendly service discovery does us no good unless we can make our applications talk to one another. Indeed, Rendezvous has absolutely no provisions for facilitating general network communications between applications, as it is only a protocol for advertising and discovering services on a network. It is a discovery protocol, not a communications protocol.

Today we shift gears into the communications side of this business; we will have very little to say about Rendezvous. Due to its Unix lineage, Mac OS X is a wonderful platform for learning about networking, since it has such a rich set of APIs to offer; in particular, we can program with the venerable BSD sockets API. Today we’ll learn about this API, and in doing so we will write a tiny pair of C applications that demonstrate how clients and servers can be made to talk with one another. In the next column, we will finish RCE with what we learn today by adding some Cocoa.

Concerning Sockets

Most of us have likely heard of sockets in the course of our experiences programming. I had always heard about sockets, but up until about half a year ago, I had never had the pleasure of programming with them. Having heard of something is far from understanding it, which is essential to being able to effectively use a technology. In this column and the next, I hope to spark some interest in the subject to give you a feel for the technology. Hopefully, many of you who had previously shied away from sockets and networking will go on to learn more about this interesting and relevant topic.

So just what is a socket? The man page for the socket() function, which we use to create sockets, describes this little thing in four words: an endpoint for communication. The analogy often used to relate sockets to everyday experiences is that of a telephone, which, as we will see, is indeed an accurate comparison. A telephone is, after all, an endpoint, or an interface, to a communications network that we use to communicate with other people.

In the same way that we speak into and listen to a phone, applications both send data across a network by writing to a socket, and receive data sent by a remote host by reading from the socket. If you are familiar with the Unix APIs for reading and writing to a file, you will be comfortable with sockets, as the same functions for file I/O are used for socket I/O – namely, read() and write().

Like two telephones that facilitate a conversation between two people, network connections exist between a pair of sockets, one for each end of the connection. Sockets are often talked about in pairs: one for the server side of the application, and one for the client side. The networking model that we are accustomed to is that of the relationship between a client and a server. A server is an application that is listening for connection requests from clients, and handling them appropriately. A client is a program that connects to a server. Usually client and servers are two completely different applications, as is the case with a Web client and server: Apache is a Web server, while OmniWeb, Internet Explorer, and Mozilla are all Web clients.

We will see in the next column how this distinction between server and client blurs when we talk about peer-to-peer chat applications like RCE. Sometimes, one application is both a client and a server that allows connections from other like applications. This is especially true of peer-to-peer applications, such as the chat application we’re building. We’ll get into this more in the next column, but understand as we progress through our discussion today that RCE will have both server functionality and client functionality.

Working With Sockets

Because of the differing tasks of a server and a client, their use of sockets is accordingly different. The role each side takes in establishing a communications link is reflected in the nature of the sockets each side uses. To wit, servers use what are known as passive sockets, and clients use active sockets.

When a server process starts up, it must create a socket; bind it to a local, unused port; tell that socket to listen for new connections from clients; and finally, begin waiting for new connections. This socket is often referred to as a listening socket, or a passive socket, or a server socket. All of these names suggest that the role of the socket is to sit patiently while listening to its assigned port for clients requesting a connection with the server. In the analogy of the telephone, creating the socket is like buying a phone, binding is akin to getting a hookup from the phone company, listening is plugging your phone into the wall, and finally, accepting is the act of answering the phone when it rings.

When a connection is received by the listening socket, the server must accept the connection and return a new connected socket that is used to communicate with the client. This new socket has an established connection to the client’s remote socket. By creating a new socket to handle the new connection, the listening socket is free to continue doing its thing, listening for connections from other clients.

Clients use sockets in a different way. A client creates a socket in the same way as a server; however, after the socket is created the use of the socket differs. With a socket in hand, the client uses that socket to attempt to connect to a server. Once the connection has been accepted by the server, the client can begin sending and receiving data from the server. Referring back to our phone analogy, connecting is no different than dialing a phone number for someone you want to talk to.

ARM GCC移植指导

概述

本文主要介绍MDK代码移植到ARM GCC中的注意事项,以及对应的编译器指令

主要包括

  • 启动文件
  • 链接脚本
  • 汇编文件
  • 编译器指令
  • 其它

启动文件

选择适用于gcc as汇编器的启动文件,并注意添加bss的清零和data的复制代码,用于初始化C
runtime,如果使用到了C++,还需要手工复制构造函数表和全局变量表,并调用_start函数来初始化C lib

建立scons开发环境

概述

本文重点介绍win7环境下安装arm gcc编译器和scons编译系统的过程

注意:对于arm gcc和scons的介绍信息,请参考本博客《arm gcc简介》,《scons系统简介》

安装步骤

1. 安装gcc

这里采用launchapad的arm-none-eabi-gcc,官网https://launchpad.net/gcc-arm-embedded/
进入下载页面, 根据自己的系统,选择对应的版本,我这里下载32位最新版4.9gcc-arm-none-eabi-4_9-2015q3-20150921-win32.exe

点击安装,一路next,保持默认安装路径,安装完成界面,会有4个复选框,勾选

  • Add path to environment variable
  • Add registry information
    点击完成,arm gcc安装完成

2. 安装python 2.xx

注意: 一定要安装2.xx版本的python
进入python下载页面https://www.python.org/downloads/release/python-2710/, 选择对应系统的python
这里选择32位2.7自安装包版本
https://www.python.org/ftp/python/2.7.10/python-2.7.10.msi

点击安装,一路next,保持默认安装路径和配置选项,直到安装完成

3. 安装scons

进入scons下载页面http://www.scons.org/download.php
下载2.4版本的windows安装包http://prdownloads.sourceforge.net/scons/scons-2.4.0-setup.exe

点击安装,一路next,保持默认安装路径和配置选项,直到安装完成

4. 更新环境变量

打开系统环境变量配置页

1
开始-》计算机-》属性-》高级系统设置-》环境变量-》系统变量-》Path-》编辑

检查Path是否有下面三项,没有则添加

1
C:\Python27;C:\Python27\Scripts;C:\Program Files\GNU Tools ARM Embedded\4.9 2015q3\bin

注意: Path 用;来分割路径

5. 测试系统

打开Cmd窗口,输入arm-none-eabi-gcc -v, python -V, scons -v
注意: python -V中的V要大写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
PS C:\Users> arm-none-eabi-gcc -v
Using built-in specs.
COLLECT_GCC=C:\Program Files\GNU Tools ARM Embedded\4.9 2015q3\bin\arm-none-eabi-gcc.exe
COLLECT_LTO_WRAPPER=c:/program\ files/gnu\ tools\ arm\ embedded/4.9\ 2015q3/bin/../lib/gcc/arm-none-eabi/4.9.3/lto-wrapp
er.exe
Target: arm-none-eabi
Configured with: /home/build/work/GCC-4-9-build/src/gcc/configure --build=i686-linux-gnu --host=i686-w64-mingw32 --targe
t=arm-none-eabi --prefix=/home/build/work/GCC-4-9-build/install-mingw --libexecdir=/home/build/work/GCC-4-9-build/instal
l-mingw/lib --infodir=/home/build/work/GCC-4-9-build/install-mingw/share/doc/gcc-arm-none-eabi/info --mandir=/home/build
/work/GCC-4-9-build/install-mingw/share/doc/gcc-arm-none-eabi/man --htmldir=/home/build/work/GCC-4-9-build/install-mingw
/share/doc/gcc-arm-none-eabi/html --pdfdir=/home/build/work/GCC-4-9-build/install-mingw/share/doc/gcc-arm-none-eabi/pdf
--enable-languages=c,c++ --disable-decimal-float --disable-libffi --disable-libgomp --disable-libmudflap --disable-libqu
admath --disable-libssp --disable-libstdcxx-pch --disable-nls --disable-shared --disable-threads --disable-tls --with-gn
u-as --with-gnu-ld --with-headers=yes --with-newlib --with-python-dir=share/gcc-arm-none-eabi --with-sysroot=/home/build
/work/GCC-4-9-build/install-mingw/arm-none-eabi --with-libiconv-prefix=/home/build/work/GCC-4-9-build/build-mingw/host-l
ibs/usr --with-gmp=/home/build/work/GCC-4-9-build/build-mingw/host-libs/usr --with-mpfr=/home/build/work/GCC-4-9-build/b
uild-mingw/host-libs/usr --with-mpc=/home/build/work/GCC-4-9-build/build-mingw/host-libs/usr --with-isl=/home/build/work
/GCC-4-9-build/build-mingw/host-libs/usr --with-cloog=/home/build/work/GCC-4-9-build/build-mingw/host-libs/usr --with-li
belf=/home/build/work/GCC-4-9-build/build-mingw/host-libs/usr --with-host-libstdcxx='-static-libgcc -Wl,-Bstatic,-lstdc+
+,-Bdynamic -lm' --with-pkgversion='GNU Tools for ARM Embedded Processors' --with-multilib-list=armv6-m,armv7-m,armv7e-m
,cortex-m7,armv7-r
Thread model: single
gcc version 4.9.3 20150529 (release) [ARM/embedded-4_9-branch revision 227977] (GNU Tools for ARM Embedded Processors)
PS C:\Users> python -V
Python 2.7.10
PS C:\Users> scons -v
SCons by Steven Knight et al.:
script: v2.4.0.rel_2.4.0:3365:9259ea1c13d7, 2015/09/21 14:03:43, by bdbaddog on hpmicrodog
engine: v2.4.0.rel_2.4.0:3365:9259ea1c13d7, 2015/09/21 14:03:43, by bdbaddog on hpmicrodog
engine path: ['C:\\Python27\\scons-2.4.0\\SCons']
Copyright (c) 2001 - 2015 The SCons Foundation
PS C:\Users>

至此,所有的系统配置已经完成

用gdb调试Cortex-M系列芯片

准备工作

本文假设读者

  1. 已经熟悉arm gcc工具链
  2. 已经在win中安装好mingw或者arm-none-eabi-gcc工具
  3. 具有合适的代码工程和编译脚本,且编译输出elf文件时,已添加-g选项来生成调试信息
  4. 安装jlink调试工具和对应驱动
  5. 有对应的硬件电路

如果其中任何一项不满足,请自行google相关文档,完成基础准备工作

  1. 开始 -> SEGGER -> Jlink V4.90e -> Jlink GDB Server
  2. Jlink会显示GDB config配置选项,如下图配置
    GDB Server配置选项
  3. 点击OK,启动GDB server,在J-Link一栏会显示Connected字符,表示成功连接硬件,如下图所示
    GDB Server配置完成

启动GDB

  1. 打开CMD,输入arm-none-eabi-gdb,打开后,如下图所示;如果没有显示对应信息,属于没有配置环境变量的path,请添加gcc
    tools的路径进去
  2. 输入file Demo.elf加载调试文件,这里以Demo.elf为例,实际你可以替换为自己的elf文件
  3. 输入target remote localhost:2331,连接gdb server,连接成功后,会在Jlink GDB server中显示对应的状态,如下所示
    GDB Server连接成功
  4. 输入monitor reset来复位MCU,从而让MCU处于确定的状态
  5. 输入load往MCU中加载调试文件,也就是常见的烧录过程
  6. 输入break main设置main断点,让MCU执行到main中停止

下面是使用Power shell的交互过程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
PS C:\> arm-none-eabi-gdb
GNU gdb (GNU Tools for ARM Embedded Processors) 7.8.0.20150604-cvs
Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=i686-w64-mingw32 --target=arm-none-eabi".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word".
(gdb) file Demo.elf
Reading symbols from Demo.elf...done.
(gdb) target remote localhost:2331
Remote debugging using localhost:2331
0x00000000 in ?? ()
(gdb) monitor reset
Resetting target
(gdb) load
Loading section .text, size 0x434 lma 0x8000000
Loading section .data, size 0x14 lma 0x8000434
Start address 0x80003ec, load size 1096
Transfer rate: 59 KB/sec, 548 bytes/write.
(gdb) break main
Breakpoint 1 at 0x8000112: file src\App\main.c, line 27.
(gdb) c
Continuing.

Breakpoint 1, main () at src\App\main.c:27
27 int i = 0;
(gdb) l
22 /* Includes ------------------------------------------------------------------*/
23 #include "stm32f10x.h"
24 #include <stdio.h>
25 int main(void)
26 {
27 int i = 0;
28
29
30 for(int m = 0; m < 100; m++)
31 {
(gdb) l
32 i = m + i;
33 }
34
35 return 0;
36 }
(gdb) s
30 for(int m = 0; m < 100; m++)
(gdb) s
32 i = m + i;
(gdb) s
30 for(int m = 0; m < 100; m++)
(gdb) s
32 i = m + i;
(gdb) p m
$1 = 1
(gdb) break 35
Breakpoint 2 at 0x8000130: file src\App\main.c, line 35.
(gdb) c
Continuing.

Breakpoint 2, main () at src\App\main.c:35
35 return 0;
(gdb) p i
$2 = 4950
(gdb) q
A debugging session is active.

Inferior 1 [Remote target] will be killed.

Quit anyway? (y or n) y

参考资料:

  1. gcc manual
  2. gdb manual
  3. jlink user manual, charapter 3.3 J-link GDB Server
  4. scons user guide
  5. scons manual

创建IAR模版工程

前言

如果你用过IAR,用过STM32,那一定会知道创建新STM32工程时有多痛苦,创建空工程,添加group,添加代码,添加宏定义,选择STM32芯片等步骤
每次新建工程,都需要重新来一遍,那有没有更简单的步骤呢?答案是yes!

假设我们需要在IAR中添加一个STM32F4的工程模版,那么所需要的东西如下:

  1. IAR 7.20 For ARM
  2. Win7
  3. STM32F4xx 标准库文件

基本步骤包括

  1. 创建IAR标准模版工程
  2. 把模版放到IAR安装目录(patch)
  3. 修改配置文件

很简单,让我们一步一步来实现这个功能

1 创建IAR标准工程

像平时一样,根据自己的工程管理习惯,用IAR创建一个工程,然后调整代码和相关工程配置项,调试编译通过

特别注意:创建工程时,需要保证IAR工程文件在最顶层目录
工程目录组织结构

创建好的目录如下所示

创建好的IAR工程

2 添加模版工程

接下来,我们需要将标准工程修改为模版工程

  1. 删除Debugsettings目录,某些情况下,还有存在Release目录,请删除
  2. 删除*.dep, *.ewt, *.ewd,*.eww四种IAR工程文件,只保留*.ewp文件
    关于上面5种文件的详细分析,请参考本博客上篇文章IAR工程文件分析
  3. 修改*.ewp文件名为templproj.ewp

至此,修改完成,如下图所示
修改好的IAR工程

3 修改配置文件

接下来,我们将这个模块添加到IAR工程中

  1. 在桌面新建一个临时文件夹,名为tmp
  2. tmp中新建目录STM32,
  3. STM32中新建目录F4xx
  4. 将我们创建的模版工程拷入F4xx目录,如下所示

    1
    2
    3
    4
    5
    6
    7

    └─STM32

    └─F4xx
    │ templproj.ewp
    ├─App
    └─Libs
  5. 进入C:\Program Files\IAR Systems\Embedded Workbench 7.2\arm\config\template\project目录,拷贝C.ENU.projtempl文件到STM32F4xx同级目录,然后修改名字为STM32.ENU.projtempl,F4xx.ENU.projtempl,修改完成后,结构如下所示

    1
    2
    3
    4
    5
    6
    7
    │ STM32.ENU.projtempl
    └─STM32
    │ F4xx.ENU.projtempl
    └─F4xx
    │ templproj.ewp
    ├─App
    └─Libs

特别注意:projtempl的名字一定要和目录名字完全一致,不然IAR找不到对应的文件夹
*.projtempl文件用于展示工程模版的基本信息,比如名字和简介什么的
下面我们分别将两个文件修改为下面样式

1
2
3
4
5
6
<?xml version="1.0" encoding="iso-8859-1"?>
<!--STM32.ENU.projtempl file-->
<templategroup>
<description>STM32 Project template for f0/1/2/4/7 mcu</description>
<displayname>STM32</displayname>
</templategroup>

1
2
3
4
5
6
<?xml version="1.0" encoding="iso-8859-1"?>
<!--F4xx.ENU.projtempl file-->
<templategroup>
<description>STM32 Project template for f4xx mcu</description>
<displayname>F4xx</displayname>
</templategroup>

测试

上面几个步骤,看起来很复杂,但实际操作起来,也挺简单的

下面我们来测试效果,将上面tmp文件中所有文件,拷贝至C:\Program Files\IAR Systems\Embedded Workbench 7.2\arm\config\template\project目录

在IAR中,新建工程,这时便会出现STM32模版工程,如下图所示
选择工程模版

选择STM32,然后选择F4,新建工程,完成后如下图所示,finish
新建的IAR工程

后记

在IAR 7.2上测试时,时常出现不可复现的bug,也许和破解有关系,具体表现为
在显示层次模版目录时,无法显示子目录;UI层次上就是新建IAR工程时,能显示STM32模版,但不能显示F4xx模版信息

暂时无解

规避方案:直接复制IAR模版文件,然后适当修改即可,千万不要重写templproj!!!