分类目录归档:嵌入式开发

关于嵌入式开发的软硬件技术

Android内核编译过程全解

之前编译过锤子的坚果手机内核,摸索了很长时间,遗憾的是没有把一些填坑的细节记录下来,免不了有些细节还得摸索一遍。这次要编译三星的Galaxy Note 5内核,加上已经有了一次成功经历,所以想把它系统化的记录下来,供自己或其他需要的人参考。

我这里主要讲内核的编译,至于关联到的一些其他工具的安装或配置,这里就不展开了,碰到这样的问题请移步问问Google。

1.  获取CPU信息

要为某手机编译内核,首先要了解手机所用的CPU,不同厂商生产的CPU,对应的linux内核是不一样的。

查看CPU信息的一种方法是利用adb,“adb shell cat /roc/cpuinfo”可以得到cpu架构和生产厂商。另外,利用“adb shell cat /proc/version”还可以得到手机中正在使用的内核信息。以下是我的Galaxy note 5的信息:将手机与PC通过usb线相连,首先查看adb是否已经可以访问、然后获取cpu信息、最后获取linux内核信息:

C:\Users\yuanhui>adb devices
List of devices attached
0715e7e408981f38 device

C:\Users\yuanhui>adb shell cat /proc/cpuinfo
Processor : AArch64 Processor rev 2 (aarch64)
processor : 0
processor : 1
processor : 2
processor : 3
processor : 4
processor : 5
processor : 6
processor : 7
Features : fp asimd aes pmull sha1 sha2 crc32
CPU implementer : 0x41
CPU architecture: AArch64
CPU variant : 0x0
CPU part : 0xd03
CPU revision : 2

Hardware : SAMSUNG Exynos7420

C:\Users\yuanhui>adb shell cat /proc/version
Linux version 3.10.61-6137732 (dpi@SWDC3312) (gcc version 4.9 20140514 (prerelea
se) (GCC) ) #1 SMP PREEMPT Fri Feb 5 13:33:23 KST 2016
另外,通过官网也可以获得比较详细的硬件信息及参数:

QQ截图20160401115714

2. 下载源代码

得到CPU信息后,就可以到Android网站去下载linux内核源码了,下载地址说明:

http://source.android.com/source/building-kernels.html#figuring-out-which-kernel-to-build

这里需要特别注意,三星的源码树有两个,一个是kernel/exynos,一个是kernel/samsung,Galaxy note 5 用的是exynos芯片,所以一定要下载exynos的源码。

QQ截图20160401115941

所以,git命令为:

$ git clone https://android.googlesource.com/kernel/exynos

这里稍微注意一下,由于国内googlesource.com被墙了,只能通过VPN才能下载。

我为了方便,所有下载及编译都是在Ubuntu里完成的:

hyh@ubuntu:~$ git clone https://android.googlesource.com/kernel/exynos
Cloning into ‘exynos’…
remote: Sending approximately 733.06 MiB …
remote: Counting objects: 9, done
remote: Finding sources: 100% (9/9)
Receiving objects: 100% (3159494/3159494), 733.07 MiB | 631.00 KiB/s, done.
remote: Total 3159494 (delta 2631328), reused 3159494 (delta 2631328)
Resolving deltas: 100% (2631328/2631328), done.
Checking connectivity… done.
hyh@ubuntu:~$

这样,在我的home下就生成了一个exynos目录,源码就在这个文件夹里。

为了后面使用方便,把目录改成了linux-kernel-exynos。

到里面看看都有些什么分支:

hyh@ubuntu:~$ cd linux-kernel-exynos/
hyh@ubuntu:~/linux-kernel-exynos$ git branch -r
origin/HEAD -> origin/master
origin/android-exynos-3.4
origin/android-exynos-koi-3.10-marshmallow-mr1-wear-release
origin/android-exynos-manta-3.4-adf
origin/android-exynos-manta-3.4-jb-mr1
origin/android-exynos-manta-3.4-jb-mr1-fr
origin/android-exynos-manta-3.4-jb-mr1.1
origin/android-exynos-manta-3.4-jb-mr2
origin/android-exynos-manta-3.4-kitkat-mr0
origin/android-exynos-manta-3.4-kitkat-mr1
origin/android-exynos-manta-3.4-kitkat-mr2
origin/android-exynos-manta-3.4-lollipop-mr1
origin/android-exynos-manta-3.4-lollipop-release
origin/master
hyh@ubuntu:~/linux-kernel-exynos$

之前看到手机用的是3.10的内核,那就把3.10的分支checkout出来:

hyh@ubuntu:~/linux-kernel-exynos$ git checkout origin/android-exynos-koi-3.10-marshmallow-mr1-wear-release
Checking out files: 100% (45351/45351), done.
Note: checking out ‘origin/android-exynos-koi-3.10-marshmallow-mr1-wear-release’.

You are in ‘detached HEAD’ state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

git checkout -b <new-branch-name>

HEAD is now at 0f9bded… Merge “Fix that wrong eint information is displayed” into android-exynos-koi-3.10
hyh@ubuntu:~/linux-kernel-exynos$

这时候才能看到目录下有了源代码(之前目录里面实际有个800多兆的.git文件夹,隐藏了,看不到而已)。

3. 配置/定制内核

通常情况下,各个厂商都会针对自己的手机做大量定制,如果编译内核时选择生成相应的配置文件,则我们可以从手机中直接得到。能拿到这个内核配置文件编译内核就会顺利很多。

C:\Users\yuanhui>adb pull /proc/config.gz

大部分情况都能拿到这个config文件,然后解压出其中的.config文件放到linux-kernel-exynos目录下,直接调用make ARCH=arm menuconfig即可定制内核。

但是很不幸,三星的这款手机没有此文件:

C:\Users\yuanhui>adb pull /proc/config.gz
remote object ‘/proc/config.gz’ does not exist

好吧,没有也没关系,直接make ARCH=arm menuconfig,通常情况也是能顺利编译的……

我这里为了把CP210x的驱动编译进去,从Silicon官网下载了Android内核编译CP210x驱动的文档,照着把CP210x驱动编译选项勾选好,保存退出,在linux-kernel-exynos目录下生成了一个.config的文件:

hyh@ubuntu:~/linux-kernel-exynos$ make ARCH=arm menuconfig
HOSTCC scripts/basic/fixdep
HOSTCC scripts/kconfig/conf.o
HOSTCC scripts/kconfig/lxdialog/checklist.o
HOSTCC scripts/kconfig/lxdialog/inputbox.o
HOSTCC scripts/kconfig/lxdialog/menubox.o
HOSTCC scripts/kconfig/lxdialog/textbox.o
HOSTCC scripts/kconfig/lxdialog/util.o
HOSTCC scripts/kconfig/lxdialog/yesno.o
HOSTCC scripts/kconfig/mconf.o
SHIPPED scripts/kconfig/zconf.tab.c
SHIPPED scripts/kconfig/zconf.lex.c
SHIPPED scripts/kconfig/zconf.hash.c
HOSTCC scripts/kconfig/zconf.tab.o
In file included from scripts/kconfig/zconf.tab.c:2503:0:
scripts/kconfig/menu.c: In function ‘get_symbol_str’:
scripts/kconfig/menu.c:567:18: warning: ‘jump’ may be used uninitialized in this function [-Wmaybe-uninitialized]
jump->offset = r->len – 1;
^
scripts/kconfig/menu.c:528:19: note: ‘jump’ was declared here
struct jump_key *jump;
^
HOSTLD scripts/kconfig/mconf
scripts/kconfig/mconf Kconfig
#
# using defaults found in /boot/config-4.2.0-23-generic
#
/boot/config-4.2.0-23-generic:928:warning: symbol value ‘m’ invalid for BRIDGE_NETFILTER
/boot/config-4.2.0-23-generic:2668:warning: symbol value ‘m’ invalid for STMMAC_PLATFORM
/boot/config-4.2.0-23-generic:3834:warning: symbol value ‘m’ invalid for GPIO_UCB1400
/boot/config-4.2.0-23-generic:4336:warning: symbol value ‘m’ invalid for MFD_WM8994
/boot/config-4.2.0-23-generic:4343:warning: symbol value ‘m’ invalid for REGULATOR_88PM8607
/boot/config-4.2.0-23-generic:4365:warning: symbol value ‘m’ invalid for REGULATOR_LP872X
/boot/config-4.2.0-23-generic:4367:warning: symbol value ‘m’ invalid for REGULATOR_LP8788
/boot/config-4.2.0-23-generic:4410:warning: symbol value ‘m’ invalid for REGULATOR_TWL4030
/boot/config-4.2.0-23-generic:5453:warning: symbol value ‘m’ invalid for SND_HDA_CODEC_REALTEK
/boot/config-4.2.0-23-generic:5454:warning: symbol value ‘m’ invalid for SND_HDA_CODEC_ANALOG
/boot/config-4.2.0-23-generic:5455:warning: symbol value ‘m’ invalid for SND_HDA_CODEC_SIGMATEL
/boot/config-4.2.0-23-generic:5456:warning: symbol value ‘m’ invalid for SND_HDA_CODEC_VIA
/boot/config-4.2.0-23-generic:5457:warning: symbol value ‘m’ invalid for SND_HDA_CODEC_HDMI
/boot/config-4.2.0-23-generic:5458:warning: symbol value ‘m’ invalid for SND_HDA_CODEC_CIRRUS
/boot/config-4.2.0-23-generic:5459:warning: symbol value ‘m’ invalid for SND_HDA_CODEC_CONEXANT
/boot/config-4.2.0-23-generic:5460:warning: symbol value ‘m’ invalid for SND_HDA_CODEC_CA0110
/boot/config-4.2.0-23-generic:5461:warning: symbol value ‘m’ invalid for SND_HDA_CODEC_CA0132
/boot/config-4.2.0-23-generic:5463:warning: symbol value ‘m’ invalid for SND_HDA_CODEC_CMEDIA
/boot/config-4.2.0-23-generic:5464:warning: symbol value ‘m’ invalid for SND_HDA_CODEC_SI3054
/boot/config-4.2.0-23-generic:5465:warning: symbol value ‘m’ invalid for SND_HDA_GENERIC
/boot/config-4.2.0-23-generic:6539:warning: symbol value ‘m’ invalid for COMEDI_PCI_DRIVERS
/boot/config-4.2.0-23-generic:6594:warning: symbol value ‘m’ invalid for COMEDI_PCMCIA_DRIVERS
/boot/config-4.2.0-23-generic:6602:warning: symbol value ‘m’ invalid for COMEDI_USB_DRIVERS
/boot/config-4.2.0-23-generic:7036:warning: symbol value ‘m’ invalid for LP8788_ADC
/boot/config-4.2.0-23-generic:8176:warning: symbol value ‘m’ invalid for KVM
configuration written to .config

*** End of the configuration.
*** Execute ‘make’ to start the build or try ‘make help’.

hyh@ubuntu:~/linux-kernel-exynos$

 

4. 编译内核

 

不同的CPU架构,就得选择不同架构的工具链。我们在刚开始的时候通过adb shell cat /proc/cpuinfo已经得到了CPU的家规信息,为aarch64,所以我们要选择的aarch64工具链来编译,Google Source 网站上同时提供了各个版本的编译工具:

https://android.googlesource.com/platform/prebuilts/

我们选择aarch64 gcc 4.9的版本来编译:

hyh@ubuntu:~$ git clone https://android.googlesource.com/platform/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9
Cloning into ‘aarch64-linux-android-4.9’…
remote: Sending approximately 180.15 MiB …
remote: Counting objects: 108, done
remote: Finding sources: 100% (108/108)
remote: Total 1641 (delta 990), reused 1641 (delta 990)
Receiving objects: 100% (1641/1641), 180.18 MiB | 620.00 KiB/s, done.
Resolving deltas: 100% (990/990), done.
Checking connectivity… done.
hyh@ubuntu:~$

把这个路径加入到$PATH中,以便编译时省去冗长的路径:

hyh@ubuntu:~/linux-kernel-exynos$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
hyh@ubuntu:~/linux-kernel-exynos$ export PATH=$PATH:~/aarch64-linux-android-4.9/bin
hyh@ubuntu:~/linux-kernel-exynos$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/home/hyh/aarch64-linux-android-4.9/bin

可以看到,用于编译内核的编译器路径已经添加到了$PATH中。

下面开始编译:
hyh@ubuntu:~/linux-kernel-exynos$ make ARCH=arm CROSS_COMPILE=arm-linux-androideabi- zImage
CHK include/generated/uapi/linux/version.h
CHK include/generated/utsrelease.h
make[1]: ‘include/generated/mach-types.h’ is up to date.
CC kernel/bounds.s
GEN include/generated/bounds.h
CC arch/arm/kernel/asm-offsets.s
In file included from include/linux/scatterlist.h:10:0,
from include/linux/dma-mapping.h:9,
from arch/arm/kernel/asm-offsets.c:15:
/home/hyh/linux-kernel-exynos/arch/arm/include/asm/io.h:30:28: fatal error: mach/exynos-ss.h: No such file or directory
#include <mach/exynos-ss.h>
^
compilation terminated.
/home/hyh/linux-kernel-exynos/./Kbuild:81: recipe for target ‘arch/arm/kernel/asm-offsets.s’ failed
make[1]: *** [arch/arm/kernel/asm-offsets.s] Error 1
Makefile:836: recipe for target ‘prepare0’ failed
make: *** [prepare0] Error 2
hyh@ubuntu:~/linux-kernel-exynos$

出错了,改个编译工具,网上下载了一个arm-eabi-4.8,放到hyh目录下,在$PATH中加入目录/home/hyh/arm-eabi-4.8/bin,编译。这次好点,编译了大部分代码,但是在编译驱动时出错了:

hyh@ubuntu:~/linux-kernel-exynos$ make ARCH=arm CROSS_COMPILE=arm-eabi- zImage
CHK include/linux/version.h
CHK include/generated/utsrelease.h
make[1]: ‘include/generated/mach-types.h’ is up to date.
CALL scripts/checksyscalls.sh
CHK include/generated/compile.h
CC drivers/mfd/ezx-pcap.o
drivers/mfd/ezx-pcap.c: In function ‘pcap_isr_work’:
drivers/mfd/ezx-pcap.c:205:2: error: implicit declaration of function ‘irq_to_gpio’ [-Werror=implicit-function-declaration]
} while (gpio_get_value(irq_to_gpio(pcap->spi->irq)));
^
cc1: some warnings being treated as errors
scripts/Makefile.build:305: recipe for target ‘drivers/mfd/ezx-pcap.o’ failed
make[2]: *** [drivers/mfd/ezx-pcap.o] Error 1
scripts/Makefile.build:441: recipe for target ‘drivers/mfd’ failed
make[1]: *** [drivers/mfd] Error 2
Makefile:945: recipe for target ‘drivers’ failed
make: *** [drivers] Error 2
hyh@ubuntu:~/linux-kernel-samsung$

发现ezx-pcap.c文件中有一段如下代码:

static void pcap_isr_work(struct work_struct *work)
{
struct pcap_chip *pcap = container_of(work, struct pcap_chip, isr_work);
struct pcap_platform_data *pdata = pcap->spi->dev.platform_data;
u32 msr, isr, int_sel, service;
int irq;

do {
ezx_pcap_read(pcap, PCAP_REG_MSR, &msr);
ezx_pcap_read(pcap, PCAP_REG_ISR, &isr);

/* We can’t service/ack irqs that are assigned to port 2 */
if (!(pdata->config & PCAP_SECOND_PORT)) {
ezx_pcap_read(pcap, PCAP_REG_INT_SEL, &int_sel);
isr &= ~int_sel;
}

ezx_pcap_write(pcap, PCAP_REG_MSR, isr | msr);
ezx_pcap_write(pcap, PCAP_REG_ISR, isr);

local_irq_disable();
service = isr & ~msr;
for (irq = pcap->irq_base; service; service >>= 1, irq++) {
if (service & 1)
generic_handle_irq(irq);
}
local_irq_enable();
ezx_pcap_write(pcap, PCAP_REG_MSR, pcap->msr);
} while (gpio_get_value(irq_to_gpio(pcap->spi->irq)));
}

定位到申明的位置:<linux/gpio.h>,在gpio.h文件中有这样一段申明:

static inline int irq_to_gpio(unsigned irq)
{
/* irq can never have been returned from gpio_to_irq() */
WARN_ON(1);
return -EINVAL;
}

可见被加了static,外部无法访问。而且,看到注释,以及返回值,可见这个函数是无用的。分析在ezx-pcap.c文件中的这段代码,do while会执行一次这段代码,但irq_to_gpio()永远只会返回失败,所以一定只会执行一次,所以果断把 “do{” 和 “}while”  这两行代码屏蔽:

static void pcap_isr_work(struct work_struct *work)
{
struct pcap_chip *pcap = container_of(work, struct pcap_chip, isr_work);
struct pcap_platform_data *pdata = pcap->spi->dev.platform_data;
u32 msr, isr, int_sel, service;
int irq;

//do {
ezx_pcap_read(pcap, PCAP_REG_MSR, &msr);
ezx_pcap_read(pcap, PCAP_REG_ISR, &isr);

/* We can’t service/ack irqs that are assigned to port 2 */
if (!(pdata->config & PCAP_SECOND_PORT)) {
ezx_pcap_read(pcap, PCAP_REG_INT_SEL, &int_sel);
isr &= ~int_sel;
}

ezx_pcap_write(pcap, PCAP_REG_MSR, isr | msr);
ezx_pcap_write(pcap, PCAP_REG_ISR, isr);

local_irq_disable();
service = isr & ~msr;
for (irq = pcap->irq_base; service; service >>= 1, irq++) {
if (service & 1)
generic_handle_irq(irq);
}
local_irq_enable();
ezx_pcap_write(pcap, PCAP_REG_MSR, pcap->msr);
//} while (gpio_get_value(irq_to_gpio(pcap->spi->irq)));
}

再次编译,过了:

……

LD vmlinux.o
MODPOST vmlinux.o
GEN .version
CHK include/generated/compile.h
UPD include/generated/compile.h
CC init/version.o
LD init/built-in.o
LD .tmp_vmlinux1
KSYM .tmp_kallsyms1.S
AS .tmp_kallsyms1.o
LD .tmp_vmlinux2
KSYM .tmp_kallsyms2.S
AS .tmp_kallsyms2.o
LD vmlinux
SYSMAP System.map
SYSMAP .tmp_System.map
OBJCOPY arch/arm/boot/Image
Kernel: arch/arm/boot/Image is ready
GZIP arch/arm/boot/compressed/piggy.gzip
AS arch/arm/boot/compressed/piggy.gzip.o
SHIPPED arch/arm/boot/compressed/lib1funcs.S
AS arch/arm/boot/compressed/lib1funcs.o
LD arch/arm/boot/compressed/vmlinux
OBJCOPY arch/arm/boot/zImage
Kernel: arch/arm/boot/zImage is ready
hyh@ubuntu:~/linux-kernel-exynos$

5. 后记

最后一步的编译经常会出一些具体的问题,比如某个包含文件找不到、某段代码编译出错,这种错误需要仔细分析错误提示,往往能定位到问题。源码过于庞大,而实际的应用千差万别,导致自定义后的某些模块之间出现问题。所以这样的问题只能是具体问题具体分析,没用的代码甚至可以屏蔽。这恰恰也是导致部分自定义代码无法编译通过的原因。

 

在命令模式下编译Android NDK 的 *.so 库

为Android编译c++写的库文件(*.so文件)有很多种方式,实际上就是有很多种不同的工具可以选择:Eclipse+ADT、Android Studio,本质上还是调用android-ndk下的build-ndk(.bat)指令来编译arm版本的、针对Android操作系统的so文件。

我们在用Eclipse编译so文件时基本上就是建一个Android工程,为其定义一个编译配置(配置好的Android ndk路径、src路径、workspace路径等等),然后为其增加Application.mk和Android.mk两个文件,Eclipse就会自动调用Application.mk和Android.mk make文件去编译、生成so文件了。

我一直都在用Eclipse配置、编译so库,但说实话,Eclipse不但配置繁琐、容易出错,Eclipse对工程的管理也是非常不灵活的:我要是有多个不相关的so库需要编译,每次打开时都会全部加载(也许是我用的不好吧),编译时又得指定要编译的库单独编译;如果某个库的路径变了,Eclipse得重新配置,否则一大堆错误,真正要编译的项目却淹没其中。

既然Eclipse也不过是调用了Android-ndk的指令去结合Application.mk和Android.mk文件实现编译,为什么不能从命令模式直接调用android-ndk命令结合Application.mk和Android.mk文件来编译呢?这样每个项目各自不会纠缠在一起,干净利落,岂不美哉?

下面拿一个项目做个测试。

step 1: 建立一个目录,名称为:PerceptionNeuronPrj

step 2: 将项目的源码拷贝进去

这里是PerceptionNeuronSDK目录,可以看到此SDK的所有源代码都放在了PerceptionNeuronSDK目录下的src下(文件太多,打印此目录树时暂时移走了),对外的头文件直接放在PerceptionNeuronSDK目录下;

step 3: 加入依赖的第三方库或源码

与PerceptionNeuronSDK目录同级的是Eigen-3.2.2和InhouseLibs,即PerceptionNeuronSDK依赖的第三方库或源代码;

step 4: 创建用于编译PerceptionNeuronSDK的NDK配置文件

在PerceptionNeuronSDK目录下新建一个目录,这里命名为build_Android,同时在build_Android下新建jni目录、libs目录;

step 5: 为PerceptionNeuronSDK增加Application.mk及Android.mk配置文件

这里一定要小心,不能再Android.mk里通过脚本加载第三方的源码进去,而应该在PerceptionNeuronSDK的src目录中,在使用到诸如Eigen的地方通过#include引用!

附1:Application.mk文件内容

APP_ABI           := all
#APP_ABI          := armeabi armeabi-v7a x86

APP_OPTIM         := release
APP_PLATFORM      := android-8
#APP_BUILD_SCRIPT := Android.mk

# GNU STL implements most C++11 features. Use either gnustl_static or gnustl_shared
# Without this your C++ code will not be able to access headers like <thread>, <mutex>
#APP_STL      := stlport_static
#APP_CPPFLAGS := -std=c++11 -frtti -fexceptions 
APP_STL       := gnustl_static
APP_CPPFLAGS  := -std=gnu++11 -pthread -frtti -fexceptions -DNDEBUG #-NDEBUG -mfpu=neon -fomit-frame-pointer -DULM_BLOCKED -msse3 -mfpmath=sse

附2: Android.mk文件内容

# Copyright (C) 2009 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE   := PNLib

# 锟斤拷锟斤拷锟皆硷拷锟斤拷源锟侥硷拷目录锟斤拷源锟侥硷拷锟斤拷缀锟斤拷
MY_FILES_PATH  :=  $(LOCAL_PATH)/../../src

#$(warning $(MY_FILES_PATH))

MY_FILES_SUFFIX := %.cpp %.c

# 递归遍历目录下的所有的文件
rwildcard=$(wildcard $1$2) $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2))

# 获取相应的源文件
MY_ALL_FILES := $(foreach src_path,$(MY_FILES_PATH), $(call rwildcard,$(src_path),*.*) ) 
MY_ALL_FILES := $(MY_ALL_FILES:$(MY_CPP_PATH)/./%=$(MY_CPP_PATH)%)
MY_SRC_LIST  := $(filter $(MY_FILES_SUFFIX),$(MY_ALL_FILES)) 
MY_SRC_LIST  := $(MY_SRC_LIST:$(LOCAL_PATH)/%=%)

# 去除字串的重复单词
define uniq =
  $(eval seen :=)
  $(foreach _,$1,$(if $(filter $_,${seen}),,$(eval seen += $_)))
  ${seen}
endef

# 递归遍历获取所有目录
MY_ALL_DIRS := $(dir $(foreach src_path,$(MY_FILES_PATH), $(call rwildcard,$(src_path),*/) ) )
MY_ALL_DIRS := $(call uniq,$(MY_ALL_DIRS))

# 赋值给NDK编译系统
LOCAL_SRC_FILES  := $(MY_SRC_LIST)
LOCAL_C_INCLUDES := $(MY_ALL_DIRS)

# Add additional include directories
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../
#LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../../Eigen-3.2.2   
#必须从Android.mk配置文件中拿掉对Eigen的直接包含,放到程序代码中用相对路径包含:
# #include "../../Eigen-3.2.2/Eigen"
# using namespace Eigen;

#$(warning $(LOCAL_SRC_FILES))
#$(warning $(LOCAL_C_INCLUDES))

# use log system in NDK
LOCAL_LDLIBS += -llog

include $(BUILD_SHARED_LIBRARY)

step 6: 为了方便使用,增加一个build.bat文件

在里面加入如下脚本:

ndk-build NDK_APPLICATION_MK=./Application.mk

pause

至此,所需文件及配置均已建立完毕,在windows中通过 ‘tree /f’ 指令可以看到其中的目录结构如下所示:

 

 

1

双击build.bat或通过命令行加载build.bat文件,即可编译出结果:

D:\PerceptionNeuronPrj\PerceptionNeuronSDK\build_Android\jni>build.bat

D:\PerceptionNeuronPrj\PerceptionNeuronSDK\build_Android\jni>ndk-build NDK_APPLI
CATION_MK=./Application.mk
[arm64-v8a] Compile++      : PNLib <= AntiJointCompensation.cpp
[arm64-v8a] Compile++      : PNLib <= BVHPlayerWrapper.cpp
[arm64-v8a] Compile++      : PNLib <= BoneMapping.cpp
[arm64-v8a] Compile++      : PNLib <= BoneMass.cpp
[arm64-v8a] Compile++      : PNLib <= BoneTable.cpp
[arm64-v8a] Compile++      : PNLib <= BvhBinaryOutputPacker.cpp
[arm64-v8a] Compile++      : PNLib <= BvhDataConvert.cpp
In file included from D:/PerceptionNeuronPrj/PerceptionNeuronSDK/build_Android/j
ni/../../src/./AvatarManagement/../PluginMngr/Interface/IPluginActionRecog.h:3:0
,
                 from D:/PerceptionNeuronPrj/PerceptionNeuronSDK/build_Android/j
ni/../../src/./AvatarManagement/Avatar.h:13,
                 from D:/PerceptionNeuronPrj/PerceptionNeuronSDK/build_Android/j
ni/../../src/BvhDataConvert.cpp:9:
D:/PerceptionNeuronPrj/PerceptionNeuronSDK/build_Android/jni/../../src/./AvatarM
anagement/../PluginMngr/Interface/IPluginObject.h:55:69: warning: 'visibility' a
ttribute ignored [-Wattributes]
         PNLIB_PLUGIN_EXPORT typedef IPluginObject* (*GetPluginFunc)();
....................
.....
.                                                                 ^

 

编译速度非常慢,看项目大小和编译的架构多少,十几分钟几十分钟不等。

编译完成后,so文件自动放到libs下的相应架构目录下,目录结构如下:

QQ截图20160311143749

 

QQ截图20160311143406

step 7: 清除及重新编译

由于ndk-build.bat编译完项目后会缓存所有中间文件(*.obj及其他中间文件),再次运行ndk-build.bat只是简单的从缓冲拷贝so文件,所以需要增加一个build clean,以便清除缓冲:

附3:build_clean.bat

#自动到NDK_PROJECT_PATH目录下找jni目录,利用其中的Android.mk清除上次编译的结果
ndk-build NDK_PROJECT_PATH=../ clean

pause

 

十大滤波算法程序大全(Arduino精编无错版)

最近用Arduino做电子秤,为了解决数据的跳变研究了不少滤波算法。网上能找到大把的十大滤波算法帖子,每一篇都不太一样,都号称精编啊,除错啊什么的,可是放到板子里却没一个能正常跑起来的。于是决定自己整理一下这些程序,完美移植到Arduino中。

所以大家看到这个帖子的时候,不要怀疑我重复发帖。我的代码都是经过反复试验,复制到Arduino中就能开跑的成品代码,移植到自己的程序中非常方便。而且都仔细研究了各个算法,把错误都修正了的(别的程序连冒泡算法都是溢出的,不信自己找来细看看),所以也算个小原创吧,在别人基础上的原创。

转载请注明出处:极客工坊  http://www.geek-workshop.com/thread-7694-1-1.html

By shenhaiyu 2013-11-01

 

1、限幅滤波法(又称程序判断滤波法)
2、中位值滤波法
3、算术平均滤波法
4、递推平均滤波法(又称滑动平均滤波法)
5、中位值平均滤波法(又称防脉冲干扰平均滤波法)
6、限幅平均滤波法
7、一阶滞后滤波法
8、加权递推平均滤波法
9、消抖滤波法
10、限幅消抖滤波法
11、新增加 卡尔曼滤波(非扩展卡尔曼),感谢zhangzhe0617分享

程序默认对int类型数据进行滤波,如需要对其他类型进行滤波,只需要把程序中所有int替换成long、float或者double即可。

1、限幅滤波法(又称程序判断滤波法)

ARDUINO 代码
/*
A、名称:限幅滤波法(又称程序判断滤波法)
B、方法:
    根据经验判断,确定两次采样允许的最大偏差值(设为A),
    每次检测到新值时判断:
    如果本次值与上次值之差<=A,则本次值有效,
    如果本次值与上次值之差>A,则本次值无效,放弃本次值,用上次值代替本次值。
C、优点:
    能有效克服因偶然因素引起的脉冲干扰。
D、缺点:
    无法抑制那种周期性的干扰。
    平滑度差。
E、整理:shenhaiyu 2013-11-01
*/
 
int Filter_Value;
int Value;
 
void setup() {
  Serial.begin(9600);       // 初始化串口通信
  randomSeed(analogRead(0)); // 产生随机种子
  Value = 300;
}
 
void loop() {
  Filter_Value = Filter();       // 获得滤波器输出值
  Value = Filter_Value;          // 最近一次有效采样的值,该变量为全局变量
  Serial.println(Filter_Value); // 串口输出
  delay(50);
}
 
// 用于随机产生一个300左右的当前值
int Get_AD() {
  return random(295, 305);
}
 
// 限幅滤波法(又称程序判断滤波法)
#define FILTER_A 1
int Filter() {
  int NewValue;
  NewValue = Get_AD();
  if(((NewValue - Value) > FILTER_A) || ((Value - NewValue) > FILTER_A))
    return Value;
  else
    return NewValue;
}

2、中位值滤波法

ARDUINO 代码
/*
A、名称:中位值滤波法
B、方法:
    连续采样N次(N取奇数),把N次采样值按大小排列,
    取中间值为本次有效值。
C、优点:
    能有效克服因偶然因素引起的波动干扰;
    对温度、液位的变化缓慢的被测参数有良好的滤波效果。
D、缺点:
    对流量、速度等快速变化的参数不宜。
E、整理:shenhaiyu 2013-11-01
*/
 
int Filter_Value;
 
void setup() {
  Serial.begin(9600);       // 初始化串口通信
  randomSeed(analogRead(0)); // 产生随机种子
}
 
void loop() {
  Filter_Value = Filter();       // 获得滤波器输出值
  Serial.println(Filter_Value); // 串口输出
  delay(50);
}
 
// 用于随机产生一个300左右的当前值
int Get_AD() {
  return random(295, 305);
}
 
// 中位值滤波法
#define FILTER_N 101
int Filter() {
  int filter_buf[FILTER_N];
  int i, j;
  int filter_temp;
  for(i = 0; i < FILTER_N; i++) {
    filter_buf[i] = Get_AD();
    delay(1);
  }
  // 采样值从小到大排列(冒泡法)
  for(j = 0; j < FILTER_N - 1; j++) {
    for(i = 0; i < FILTER_N - 1 - j; i++) {
      if(filter_buf[i] > filter_buf[i + 1]) {
        filter_temp = filter_buf[i];
        filter_buf[i] = filter_buf[i + 1];
        filter_buf[i + 1] = filter_temp;
      }
    }
  }
  return filter_buf[(FILTER_N - 1) / 2];
}

3、算术平均滤波法

ARDUINO 代码
/*
A、名称:算术平均滤波法
B、方法:
    连续取N个采样值进行算术平均运算:
    N值较大时:信号平滑度较高,但灵敏度较低;
    N值较小时:信号平滑度较低,但灵敏度较高;
    N值的选取:一般流量,N=12;压力:N=4。
C、优点:
    适用于对一般具有随机干扰的信号进行滤波;
    这种信号的特点是有一个平均值,信号在某一数值范围附近上下波动。
D、缺点:
    对于测量速度较慢或要求数据计算速度较快的实时控制不适用;
    比较浪费RAM。
E、整理:shenhaiyu 2013-11-01
*/
 
int Filter_Value;
 
void setup() {
  Serial.begin(9600);       // 初始化串口通信
  randomSeed(analogRead(0)); // 产生随机种子
}
 
void loop() {
  Filter_Value = Filter();       // 获得滤波器输出值
  Serial.println(Filter_Value); // 串口输出
  delay(50);
}
 
// 用于随机产生一个300左右的当前值
int Get_AD() {
  return random(295, 305);
}
 
// 算术平均滤波法
#define FILTER_N 12
int Filter() {
  int i;
  int filter_sum = 0;
  for(i = 0; i < FILTER_N; i++) {
    filter_sum += Get_AD();
    delay(1);
  }
  return (int)(filter_sum / FILTER_N);
}

4、递推平均滤波法(又称滑动平均滤波法)

ARDUINO 代码
/*
A、名称:递推平均滤波法(又称滑动平均滤波法)
B、方法:
    把连续取得的N个采样值看成一个队列,队列的长度固定为N,
    每次采样到一个新数据放入队尾,并扔掉原来队首的一次数据(先进先出原则),
    把队列中的N个数据进行算术平均运算,获得新的滤波结果。
    N值的选取:流量,N=12;压力,N=4;液面,N=4-12;温度,N=1-4。
C、优点:
    对周期性干扰有良好的抑制作用,平滑度高;
    适用于高频振荡的系统。
D、缺点:
    灵敏度低,对偶然出现的脉冲性干扰的抑制作用较差;
    不易消除由于脉冲干扰所引起的采样值偏差;
    不适用于脉冲干扰比较严重的场合;
    比较浪费RAM。
E、整理:shenhaiyu 2013-11-01
*/
 
int Filter_Value;
 
void setup() {
  Serial.begin(9600);       // 初始化串口通信
  randomSeed(analogRead(0)); // 产生随机种子
}
 
void loop() {
  Filter_Value = Filter();       // 获得滤波器输出值
  Serial.println(Filter_Value); // 串口输出
  delay(50);
}
 
// 用于随机产生一个300左右的当前值
int Get_AD() {
  return random(295, 305);
}
 
// 递推平均滤波法(又称滑动平均滤波法)
#define FILTER_N 12
int filter_buf[FILTER_N + 1];
int Filter() {
  int i;
  int filter_sum = 0;
  filter_buf[FILTER_N] = Get_AD();
  for(i = 0; i < FILTER_N; i++) {
    filter_buf[i] = filter_buf[i + 1]; // 所有数据左移,低位仍掉
    filter_sum += filter_buf[i];
  }
  return (int)(filter_sum / FILTER_N);
}

5、中位值平均滤波法(又称防脉冲干扰平均滤波法)

ARDUINO 代码
/*
A、名称:中位值平均滤波法(又称防脉冲干扰平均滤波法)
B、方法:
    采一组队列去掉最大值和最小值后取平均值,
    相当于“中位值滤波法”+“算术平均滤波法”。
    连续采样N个数据,去掉一个最大值和一个最小值,
    然后计算N-2个数据的算术平均值。
    N值的选取:3-14。
C、优点:
    融合了“中位值滤波法”+“算术平均滤波法”两种滤波法的优点。
    对于偶然出现的脉冲性干扰,可消除由其所引起的采样值偏差。
    对周期干扰有良好的抑制作用。
    平滑度高,适于高频振荡的系统。
D、缺点:
    计算速度较慢,和算术平均滤波法一样。
    比较浪费RAM。
E、整理:shenhaiyu 2013-11-01
*/
 
int Filter_Value;
 
void setup() {
  Serial.begin(9600);       // 初始化串口通信
  randomSeed(analogRead(0)); // 产生随机种子
}
 
void loop() {
  Filter_Value = Filter();       // 获得滤波器输出值
  Serial.println(Filter_Value); // 串口输出
  delay(50);
}
 
// 用于随机产生一个300左右的当前值
int Get_AD() {
  return random(295, 305);
}
 
// 中位值平均滤波法(又称防脉冲干扰平均滤波法)(算法1)
#define FILTER_N 100
int Filter() {
  int i, j;
  int filter_temp, filter_sum = 0;
  int filter_buf[FILTER_N];
  for(i = 0; i < FILTER_N; i++) {
    filter_buf[i] = Get_AD();
    delay(1);
  }
  // 采样值从小到大排列(冒泡法)
  for(j = 0; j < FILTER_N - 1; j++) {
    for(i = 0; i < FILTER_N - 1 - j; i++) {
      if(filter_buf[i] > filter_buf[i + 1]) {
        filter_temp = filter_buf[i];
        filter_buf[i] = filter_buf[i + 1];
        filter_buf[i + 1] = filter_temp;
      }
    }
  }
  // 去除最大最小极值后求平均
  for(i = 1; i < FILTER_N - 1; i++) filter_sum += filter_buf[i];
  return filter_sum / (FILTER_N - 2);
}
 
 
//  中位值平均滤波法(又称防脉冲干扰平均滤波法)(算法2)
/*
#define FILTER_N 100
int Filter() {
  int i;
  int filter_sum = 0;
  int filter_max, filter_min;
  int filter_buf[FILTER_N];
  for(i = 0; i < FILTER_N; i++) {
    filter_buf[i] = Get_AD();
    delay(1);
  }
  filter_max = filter_buf[0];
  filter_min = filter_buf[0];
  filter_sum = filter_buf[0];
  for(i = FILTER_N - 1; i > 0; i--) {
    if(filter_buf[i] > filter_max)
      filter_max=filter_buf[i];
    else if(filter_buf[i] < filter_min)
      filter_min=filter_buf[i];
    filter_sum = filter_sum + filter_buf[i];
    filter_buf[i] = filter_buf[i - 1];
  }
  i = FILTER_N - 2;
  filter_sum = filter_sum - filter_max - filter_min + i / 2; // +i/2 的目的是为了四舍五入
  filter_sum = filter_sum / i;
  return filter_sum;
}*/

6、限幅平均滤波法

ARDUINO 代码
/*
A、名称:限幅平均滤波法
B、方法:
    相当于“限幅滤波法”+“递推平均滤波法”;
    每次采样到的新数据先进行限幅处理,
    再送入队列进行递推平均滤波处理。
C、优点:
    融合了两种滤波法的优点;
    对于偶然出现的脉冲性干扰,可消除由于脉冲干扰所引起的采样值偏差。
D、缺点:
    比较浪费RAM。
E、整理:shenhaiyu 2013-11-01
*/
 
#define FILTER_N 12
int Filter_Value;
int filter_buf[FILTER_N];
 
void setup() {
  Serial.begin(9600);       // 初始化串口通信
  randomSeed(analogRead(0)); // 产生随机种子
  filter_buf[FILTER_N - 2] = 300;
}
 
void loop() {
  Filter_Value = Filter();       // 获得滤波器输出值
  Serial.println(Filter_Value); // 串口输出
  delay(50);
}
 
// 用于随机产生一个300左右的当前值
int Get_AD() {
  return random(295, 305);
}
 
// 限幅平均滤波法
#define FILTER_A 1
int Filter() {
  int i;
  int filter_sum = 0;
  filter_buf[FILTER_N - 1] = Get_AD();
  if(((filter_buf[FILTER_N - 1] - filter_buf[FILTER_N - 2]) > FILTER_A) || ((filter_buf[FILTER_N - 2] - filter_buf[FILTER_N - 1]) > FILTER_A))
    filter_buf[FILTER_N - 1] = filter_buf[FILTER_N - 2];
  for(i = 0; i < FILTER_N - 1; i++) {
    filter_buf[i] = filter_buf[i + 1];
    filter_sum += filter_buf[i];
  }
  return (int)filter_sum / (FILTER_N - 1);
}

7、一阶滞后滤波法

ARDUINO 代码
/*
A、名称:一阶滞后滤波法
B、方法:
    取a=0-1,本次滤波结果=(1-a)*本次采样值+a*上次滤波结果。
C、优点:
    对周期性干扰具有良好的抑制作用;
    适用于波动频率较高的场合。
D、缺点:
    相位滞后,灵敏度低;
    滞后程度取决于a值大小;
    不能消除滤波频率高于采样频率1/2的干扰信号。
E、整理:shenhaiyu 2013-11-01
*/
 
int Filter_Value;
int Value;
 
void setup() {
  Serial.begin(9600);       // 初始化串口通信
  randomSeed(analogRead(0)); // 产生随机种子
  Value = 300;
}
 
void loop() {
  Filter_Value = Filter();       // 获得滤波器输出值
  Serial.println(Filter_Value); // 串口输出
  delay(50);
}
 
// 用于随机产生一个300左右的当前值
int Get_AD() {
  return random(295, 305);
}
 
// 一阶滞后滤波法
#define FILTER_A 0.01
int Filter() {
  int NewValue;
  NewValue = Get_AD();
  Value = (int)((float)NewValue * FILTER_A + (1.0 - FILTER_A) * (float)Value);
  return Value;
}

8、加权递推平均滤波法

ARDUINO 代码
/*
A、名称:加权递推平均滤波法
B、方法:
    是对递推平均滤波法的改进,即不同时刻的数据加以不同的权;
    通常是,越接近现时刻的数据,权取得越大。
    给予新采样值的权系数越大,则灵敏度越高,但信号平滑度越低。
C、优点:
    适用于有较大纯滞后时间常数的对象,和采样周期较短的系统。
D、缺点:
    对于纯滞后时间常数较小、采样周期较长、变化缓慢的信号;
    不能迅速反应系统当前所受干扰的严重程度,滤波效果差。
E、整理:shenhaiyu 2013-11-01
*/
 
int Filter_Value;
 
void setup() {
  Serial.begin(9600);       // 初始化串口通信
  randomSeed(analogRead(0)); // 产生随机种子
}
 
void loop() {
  Filter_Value = Filter();       // 获得滤波器输出值
  Serial.println(Filter_Value); // 串口输出
  delay(50);
}
 
// 用于随机产生一个300左右的当前值
int Get_AD() {
  return random(295, 305);
}
 
// 加权递推平均滤波法
#define FILTER_N 12
int coe[FILTER_N] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};    // 加权系数表
int sum_coe = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12; // 加权系数和
int filter_buf[FILTER_N + 1];
int Filter() {
  int i;
  int filter_sum = 0;
  filter_buf[FILTER_N] = Get_AD();
  for(i = 0; i < FILTER_N; i++) {
    filter_buf[i] = filter_buf[i + 1]; // 所有数据左移,低位仍掉
    filter_sum += filter_buf[i] * coe[i];
  }
  filter_sum /= sum_coe;
  return filter_sum;
}

9、消抖滤波法

ARDUINO 代码
/*
A、名称:消抖滤波法
B、方法:
    设置一个滤波计数器,将每次采样值与当前有效值比较:
    如果采样值=当前有效值,则计数器清零;
    如果采样值<>当前有效值,则计数器+1,并判断计数器是否>=上限N(溢出);
    如果计数器溢出,则将本次值替换当前有效值,并清计数器。
C、优点:
    对于变化缓慢的被测参数有较好的滤波效果;
    可避免在临界值附近控制器的反复开/关跳动或显示器上数值抖动。
D、缺点:
    对于快速变化的参数不宜;
    如果在计数器溢出的那一次采样到的值恰好是干扰值,则会将干扰值当作有效值导入系统。
E、整理:shenhaiyu 2013-11-01
*/
 
int Filter_Value;
int Value;
 
void setup() {
  Serial.begin(9600);       // 初始化串口通信
  randomSeed(analogRead(0)); // 产生随机种子
  Value = 300;
}
 
void loop() {
  Filter_Value = Filter();       // 获得滤波器输出值
  Serial.println(Filter_Value); // 串口输出
  delay(50);
}
 
// 用于随机产生一个300左右的当前值
int Get_AD() {
  return random(295, 305);
}
 
// 消抖滤波法
#define FILTER_N 12
int i = 0;
int Filter() {
  int new_value;
  new_value = Get_AD();
  if(Value != new_value) {
    i++;
    if(i > FILTER_N) {
      i = 0;
      Value = new_value;
    }
  }
  else
    i = 0;
  return Value;
}

10、限幅消抖滤波法

ARDUINO 代码
/*
A、名称:限幅消抖滤波法
B、方法:
    相当于“限幅滤波法”+“消抖滤波法”;
    先限幅,后消抖。
C、优点:
    继承了“限幅”和“消抖”的优点;
    改进了“消抖滤波法”中的某些缺陷,避免将干扰值导入系统。
D、缺点:
    对于快速变化的参数不宜。
E、整理:shenhaiyu 2013-11-01
*/
 
int Filter_Value;
int Value;
 
void setup() {
  Serial.begin(9600);       // 初始化串口通信
  randomSeed(analogRead(0)); // 产生随机种子
  Value = 300;
}
 
void loop() {
  Filter_Value = Filter();       // 获得滤波器输出值
  Serial.println(Filter_Value); // 串口输出
  delay(50);
}
 
// 用于随机产生一个300左右的当前值
int Get_AD() {
  return random(295, 305);
}
 
// 限幅消抖滤波法
#define FILTER_A 1
#define FILTER_N 5
int i = 0;
int Filter() {
  int NewValue;
  int new_value;
  NewValue = Get_AD();
  if(((NewValue - Value) > FILTER_A) || ((Value - NewValue) > FILTER_A))
    new_value = Value;
  else
    new_value = NewValue;
  if(Value != new_value) {
    i++;
    if(i > FILTER_N) {
      i = 0;
      Value = new_value;
    }
  }
  else
    i = 0;
  return Value;
}

 

11、卡尔曼滤波(非扩展卡尔曼)

ARDUINO 代码
#include <Wire.h> // I2C library, gyroscope

// Accelerometer ADXL345
#define ACC (0x53)    //ADXL345 ACC address
#define A_TO_READ (6)        //num of bytes we are going to read each time (two bytes for each axis)


// Gyroscope ITG3200 
#define GYRO 0x68 // gyro address, binary = 11101000 when AD0 is connected to Vcc (see schematics of your breakout board)
#define G_SMPLRT_DIV 0x15   
#define G_DLPF_FS 0x16   
#define G_INT_CFG 0x17
#define G_PWR_MGM 0x3E

#define G_TO_READ 8 // 2 bytes for each axis x, y, z


// offsets are chip specific. 
int a_offx = 0;
int a_offy = 0;
int a_offz = 0;

int g_offx = 0;
int g_offy = 0;
int g_offz = 0;
////////////////////////

////////////////////////
char str[512]; 

void initAcc() {
  //Turning on the ADXL345
  writeTo(ACC, 0x2D, 0);      
  writeTo(ACC, 0x2D, 16);
  writeTo(ACC, 0x2D, 8);
  //by default the device is in +-2g range reading
}

void getAccelerometerData(int* result) {
  int regAddress = 0x32;    //first axis-acceleration-data register on the ADXL345
  byte buff[A_TO_READ];
  
  readFrom(ACC, regAddress, A_TO_READ, buff); //read the acceleration data from the ADXL345
  
  //each axis reading comes in 10 bit resolution, ie 2 bytes.  Least Significat Byte first!!
  //thus we are converting both bytes in to one int
  result[0] = (((int)buff[1]) << 8) | buff[0] + a_offx;   
  result[1] = (((int)buff[3]) << 8) | buff[2] + a_offy;
  result[2] = (((int)buff[5]) << 8) | buff[4] + a_offz;
}

//initializes the gyroscope
void initGyro()
{
  /*****************************************
  * ITG 3200
  * power management set to:
  * clock select = internal oscillator
  *     no reset, no sleep mode
  *   no standby mode
  * sample rate to = 125Hz
  * parameter to +/- 2000 degrees/sec
  * low pass filter = 5Hz
  * no interrupt
  ******************************************/
  writeTo(GYRO, G_PWR_MGM, 0x00);
  writeTo(GYRO, G_SMPLRT_DIV, 0x07); // EB, 50, 80, 7F, DE, 23, 20, FF
  writeTo(GYRO, G_DLPF_FS, 0x1E); // +/- 2000 dgrs/sec, 1KHz, 1E, 19
  writeTo(GYRO, G_INT_CFG, 0x00);
}


void getGyroscopeData(int * result)
{
  /**************************************
  Gyro ITG-3200 I2C
  registers:
  temp MSB = 1B, temp LSB = 1C
  x axis MSB = 1D, x axis LSB = 1E
  y axis MSB = 1F, y axis LSB = 20
  z axis MSB = 21, z axis LSB = 22
  *************************************/

  int regAddress = 0x1B;
  int temp, x, y, z;
  byte buff[G_TO_READ];
  
  readFrom(GYRO, regAddress, G_TO_READ, buff); //read the gyro data from the ITG3200
  
  result[0] = ((buff[2] << 8) | buff[3]) + g_offx;
  result[1] = ((buff[4] << 8) | buff[5]) + g_offy;
  result[2] = ((buff[6] << 8) | buff[7]) + g_offz;
  result[3] = (buff[0] << 8) | buff[1]; // temperature
  
}


float xz=0,yx=0,yz=0;
float p_xz=1,p_yx=1,p_yz=1;
float q_xz=0.0025,q_yx=0.0025,q_yz=0.0025;
float k_xz=0,k_yx=0,k_yz=0;
float r_xz=0.25,r_yx=0.25,r_yz=0.25;
  //int acc_temp[3];
  //float acc[3];
  int acc[3];
  int gyro[4];
  float Axz;
  float Ayx;
  float Ayz;
  float t=0.025;
void setup()
{
  Serial.begin(9600);
  Wire.begin();
  initAcc();
  initGyro();
  
}

//unsigned long timer = 0;
//float o;
void loop()
{
  
  getAccelerometerData(acc);
  getGyroscopeData(gyro);
  //timer = millis();
  sprintf(str, "%d,%d,%d,%d,%d,%d", acc[0],acc[1],acc[2],gyro[0],gyro[1],gyro[2]);
  
  //acc[0]=acc[0];
  //acc[2]=acc[2];
  //acc[1]=acc[1];
  //r=sqrt(acc[0]*acc[0]+acc[1]*acc[1]+acc[2]*acc[2]);
  gyro[0]=gyro[0]/ 14.375;
  gyro[1]=gyro[1]/ (-14.375);
  gyro[2]=gyro[2]/ 14.375;
  
   
  Axz=(atan2(acc[0],acc[2]))*180/PI;
  Ayx=(atan2(acc[0],acc[1]))*180/PI;
  /*if((acc[0]!=0)&&(acc[1]!=0))
    {
      Ayx=(atan2(acc[0],acc[1]))*180/PI;
    }
    else
    {
      Ayx=t*gyro[2];
    }*/
  Ayz=(atan2(acc[1],acc[2]))*180/PI;
  
  
//kalman filter
  calculate_xz();
  calculate_yx();
  calculate_yz();
  
  //sprintf(str, "%d,%d,%d", xz_1, xy_1, x_1);
  //Serial.print(xz);Serial.print(",");
  //Serial.print(yx);Serial.print(",");
  //Serial.print(yz);Serial.print(",");
  //sprintf(str, "%d,%d,%d,%d,%d,%d", acc[0],acc[1],acc[2],gyro[0],gyro[1],gyro[2]);
  //sprintf(str, "%d,%d,%d",gyro[0],gyro[1],gyro[2]);
    Serial.print(Axz);Serial.print(",");
    //Serial.print(Ayx);Serial.print(",");
    //Serial.print(Ayz);Serial.print(",");
  //Serial.print(str);
  //o=gyro[2];//w=acc[2];
  //Serial.print(o);Serial.print(",");
  //Serial.print(w);Serial.print(",");
  Serial.print("\n");

  
  //delay(50);
}
void calculate_xz()
{

xz=xz+t*gyro[1];
p_xz=p_xz+q_xz;
k_xz=p_xz/(p_xz+r_xz);
xz=xz+k_xz*(Axz-xz);
p_xz=(1-k_xz)*p_xz;
}
void calculate_yx()
{
  
  yx=yx+t*gyro[2];
  p_yx=p_yx+q_yx;
  k_yx=p_yx/(p_yx+r_yx);
  yx=yx+k_yx*(Ayx-yx);
  p_yx=(1-k_yx)*p_yx;

}
void calculate_yz()
{
  yz=yz+t*gyro[0];
  p_yz=p_yz+q_yz;
  k_yz=p_yz/(p_yz+r_yz);
  yz=yz+k_yz*(Ayz-yz);
  p_yz=(1-k_yz)*p_yz;

}


//---------------- Functions
//Writes val to address register on ACC
void writeTo(int DEVICE, byte address, byte val) {
   Wire.beginTransmission(DEVICE); //start transmission to ACC 
   Wire.write(address);        // send register address
   Wire.write(val);        // send value to write
   Wire.endTransmission(); //end transmission
}


//reads num bytes starting from address register on ACC in to buff array
void readFrom(int DEVICE, byte address, int num, byte buff[]) {
  Wire.beginTransmission(DEVICE); //start transmission to ACC 
  Wire.write(address);        //sends address to read from
  Wire.endTransmission(); //end transmission
  
  Wire.beginTransmission(DEVICE); //start transmission to ACC
  Wire.requestFrom(DEVICE, num);    // request 6 bytes from ACC
  
  int i = 0;
  while(Wire.available())    //ACC may send less than requested (abnormal)
  { 
    buff[i] = Wire.read(); // receive a byte
    i++;
  }
  Wire.endTransmission(); //end transmission
}

 

本文转自:http://www.geek-workshop.com/thread-7694-1-1.html

 

三步实现在 Raspberry Pi 上运行 JavaFX 应用

英文原文:JavaFX on Raspberry Pi – 3 Easy Steps

参与翻译者(4人)Tom LinGrisson寂寞沙洲ksc

 期待已久的Raspberry Pi JavaFX的开发者预览版终于出来了。这是一个很棒的平台对做小的嵌入式项目,低成本的计算机系统的教学和非常有趣爱好者来说。它的成本只有35美元的B型版本,拥有512MB RAM,700MHz的ARM处理器和I / O的HDMI,Composite,音频,以太网,和2 USB端口。

那么,你可以用 JavaFX 在一个 Raspberry Pi 上做什么呢?一个很棒的例子是,我们为 Devoxx 制作了一个会议日程表运行在数字标牌上,这个会议日程表通过一个飞行在太空的宇宙飞船动画显示出来:

更新:如果你不信任运行在 Pi 的 Java 应用程序的性能,那么看看 Rich Bair 在网站 fxexperience.com 上发布的文章:http://fxexperience.com/2012/12/javafx-on-raspberry-pi/

只需要简单的三个步骤既可让你的Pi跑上JavaFx, 如果你决定开始动手的话。

1. 安装Linux到你的Raspberry Pi上
2. 下载并拷贝Java/JavaFX 8到你的Pi上
3. 部署和运行JavaFX 应用在你的Pi上

当然,这里的前提是你已经入手了Raspberry Pi. 如果你还不知道哪里可以买到Raspberry Pi, 或怎么启动它的话. 我推荐你去看看Raspberry Pi的官网. Raspberry Pi Site

第一步 – 在你的 Raspberry Pi 上安装 Linux

最新发布的 Java 8 支持硬件浮点运算了,这是一件好事,因为这将为您带来更高的性能,同时其推荐的 Raspberry Pi 编译器也是用硬件进行浮点运算了。现在可以抛弃那些 soft, sofrfp 等等了,因为这些已经不再兼容支持硬件浮点运算的 JVM 了。

注:为什么原来一直为浮点运算而烦恼呢?主要是以前小的嵌入式系统芯片都不提供用于浮点运算模块以节省成本(如 ARM Cortex M0-M3 等)。幸运的是,用于支持 Raspberry Pi 运行的 ARMv6 芯片已经提供真正的硬件浮点运算了。

要在你的SD卡上部署Linux, 你首先要有一台具有SD card 读写能力的Windows, Mac 或者linux 机器。你所需要的安装版本是Raspbian Wheezy hard float , 这也是Respberry Pi上推荐安装版本。 下载地址是 http://www.raspberrypi.org/downloads

有好几种方法可以烧录镜像文件到SD card上,具体说明在这里,但基本上可以归类为:

windows: 使用 Win32DiskImager
Mac: 使用 RPi-sd Card Builder
Linux: 使用dd命令

一旦搞好你的 SD 卡,那就把它取出并连接到你的显示器上,并插上一个好点的 usb 电源(5v 700mA 或更高)。

注意:顺序很重要! – 如果你在给你的 Pi 接通电源前没有连接好HDMI显示器。那结果可能会是,虽然指示灯在闪烁,但你却只得到了一个空白的屏幕,这时你应该尝试重新启动的你的PI(拔下并重新插入它)。

这时,你的 Pi 应该已经启动起来了,并在屏幕上显示出你的 Raspberry Pi 的配置。这里有些参数你可能需要考虑调整,包括:

  • CPU/GPU 内存分配 – 要给予  GPU 最少 128MB 的内存,以使得一些对图形要求较高的应用能跑得更流畅 (这点对 JavaFX 很重要!)
  • 更改区域设置/键盘/时区 – 这些默认设置是英国的,因此每个非英国的人都应该修改这些设置,否则在试图输入标点符号时,你会骂你的键盘的!
  • Overscan – 如果你的显示器在显示时有黑框,那么你把这个选项设为关闭,那么你就可以看到全屏了。
  • 扩大根文件系统 – 这点不需要重启就可以重新指定你的卡的大小以便使用你的卡的全部空间(默认的映像文件只有 2GB 的根分区)。高度推荐,但如果在一个较大的卡上,完成这个操作可能需要花费点时间。
  • SSH – 如果你想要通过网络来访问你的 Pi,那么就把这个选项打开 (这是除了重启之外的、关闭空闲 JavaFX 进程的唯一方法)

在  JavaFX Raspberry Pi 的官方文档 里,他们也推荐通过修改配置文件  (/boot/config.txt) 来设置视频缓存区为 720p,把配置文件里下面两行前的注释符号去掉即可:

framebuffer_width=1280
framebuffer_height=720

当然这是可选的,但如果让 Pi 的输出分辨率低些,你肯定可以获得更好的性能。但在你明白这样改动会带来什么后果之前,不要修改这个配置。(同时,如果要改的话,你必须先通过 ssh 远程登录进 Pi 中,以防改动后显示不正常的话,你还可以改回来)。更多相关 HDMI 显示的问题,可以到 这里 来查询文档。

第2步 – 下载并复制 Java/JavaFX 8 到你的 Pi

你可以从下面地址中下载兼容的 Java/JavaFX 8 到你的 Raspberry Pi 上:

http://jdk8.java.net/fxarmpreview

如果你的 Pi 是通过以太网连接到网络的话,你可以直接下载到你的设备中。否则的话,你可以通过 sftp(通过 ssh)或 sneakernet 拷贝进去。

下载下来后,你就可以解压到你指定的路径下:

sudo tar -zxvf file_name -C /opt

然后,用以下命令运行:

sudo /opt/jdk1.8.0/bin/java -version

第 3 步– 在你的 Pi 上配置和运行 JavaFX 应用

几乎所有的 JavaFX 桌面应用都可以不经修改,仅需简单复制进去就可以在你的 Pi 上运行了。(有两种应用例外,这两种应用是为 WebView 或者 MediaView 开发的,当前的设备还没实现些应用的兼容)

一个更好的开始构建你的 Pi 的 JavaFX 应用的方法是,先使用 Scene Builder 可视化设计工具来设计你的用户界面,并把设计好的用户界面放到你的应用中,然后再配置到你的 Pi 上。我昨晚就在 Davis 的 Linux 用户组 (LUGOD) 上,在其他非常精明的与会者 的帮助下完成了这个工作(我还跟其他人学会了一些 linux 的命令技巧)。

我提交了一个花了我们15分钟的应用到 GitHub 上,你可以到下面的地址中下下来试试:

https://github.com/steveonjava/LUGOD-Pi-Test

要在你的 Pi 上运行这个例子,先用你喜欢的 IDE 构建好源码(或者直接在命令行里构建)并发布 Jar 包文件。然后把 jar 复制到你的 Pi 中,并用类似下面的命令来运行它:

sudo /opt/jdk1.8.0/bin/java -Djavafx.platform=eglfb \
-cp /opt/jdk1.8.0/jre/lib/jfxrt.jar:LUGODTest.jar lugodtest.LUGODTest

下图是我们在 LUGOD 会议上展出的运行在 Raspberry Pi 的 Scene Builder 工程界面和运行输出结果。

然而,让你感受最深的,还是你自己开发的应用。试着发布一个你自己的 JavaFX 应用,然后在后面的评论中,请留下你发布成功的应用的链接。

本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们

Raspberry Pi快速上手教程

当你收到好不容易发货的Raspberry Pi(树莓派)之后会发现包装中只包含了一块板子和简单的说明书,没有任何附件,想要让它工作起来必须DIY自己配置各种附件。本文就是一个简单的快速上手教程,使你提前做好准备能够很快的让Raspberry Pi奔跑起来。

首先看看除了Raspberry Pi之外还需要哪些附件吧:

  • USB接口键盘和鼠标:其中USB键盘是必不可少的。
  • SD存储卡:Raspberry Pi的系统都是放在SD卡上。可以选择标准大小的SD卡或者micro SD卡,如果是micro SD卡还必须有一个适配器(adapter),板上的插槽是SD/MMC式的,当然还要准备一个读卡器。SD卡最少要选择4GB容量以上以及速度CLASS4以上,Raspberry Pi上大部分可用的系统需求都超过2GB。
  • Micro USB连接线:做电源线用。
  • USB口适配器:Raspberry Pi最少需要5V@700ma电流,因此不能通过计算机USB口供电。
  • 视频线:可以是HDMI线或者是接电视的复合视频线。如果显示器不带HDMI接口,还需要配置HDMI转DVI或者HDMI转VGA的线缆。
  • 以太网线:网线虽然不是必需的但是却很重要。
  • USB集线器:这不是必须的,Raspberry Pi只有2个USB口,如果配置一个带电源的USB集线器,能减轻Raspberry Pi的负荷而且能扩展更多USB设备。

Raspberry Pi Wiki上列举了非常多可支持的硬件外设以及可能有问题的外设,上图是我们准备的一些外设,并没有刻意选择型号:

  • Raspberry Pi B型
  • 普通USB键盘鼠标
  • Kingston 4GB micro SD(Class4)以及micro SD Adapter
  • 一个旧手机的USB电源适配器(5V@1A)
  • 一根HDMI-DVI连接线
  • 一台带DVI接口液晶显示器
  • 一根网线

安装系统

Raspberry Pi的系统是在SD卡上运行,必须先将系统安装到SD卡上。目前支持Raspberry Pi的Linux有很多版本。开始的时候我们还是选择一个官方量身定制的Raspian ”wheezy“,这是一个在Debian基础上优化的版本,可以在官网下载。

如果使用Windows系统,官方建议使用Wi32DiskImager来复制image文件到SD卡(如果是Linux系统可以用工具dd)。这里就在常用的Windows系统下说明,下载最新的Raspian wheezy(目前是2012-8-16),解压缩zip文件。

解压缩后的img文件有1.8G左右,插入读卡器,打开下载的Win32DiskImager软件,将img写入到SD卡中。

上电启动

Raspberry Pi最有可能碰到的问题就是供电电压不足或者USB适配器不能提供足够电流。Raspberry Pi的供电电压范围为4.75V~5.25V,而且板上留了两个测试点TP1、TP2(电源和地)用来检测供电电压。如下图可以用万用表首先测量下供电电压。

连接好所有的外设,插好SD卡。

Raspian系统第一次启动会多花点时间,而且启动后程序首先会进入系统设置画面。

Raspian系统设置:

  • info:系统设置工具的信息
  • expand-rootfs:扩大Linux系统root分区的大小
  • overscan:使能overscan
  • configure_keyboard:选择键盘布局(Raspberry Pi键盘布局默认英式,这里可以调整)
  • change_pass:修改用户密码(Raspbian默认用户名为pi,密码raspberry)
  • change_local:修改输入法(可以修改成中文输入,不过先要安装字体,暂时不修改)
  • change_timezone:修改系统时区(Raspberry Pi没有实时时钟,靠网络同步时间)
  • memory_split:修改内存划分(一共256MB内存,修改ARM处理器和图形加速器的分配)
  • ssh:使能ssh服务器(建议开启,这样可以通过ssh访问Raspberry Pi)
  • boot_behaviour:设置系统启动进入命令行界面还是图形界面(在命令行模式输入startx可以进入图形界面)
  • update:可以在线升级

设置完成后选择finish退出设置界面,重启系统,Raspberry Pi就首次进入了命令行模式

设置网络

Raspian系统的网络设置文件包括dns设置/etc/resolv.conf 和dhcp设置 /etc/network/interfaces,笔者的网络采用了固定IP,因此需要修改文件设定静态IP,如果网络遇到问题可以查看这两个文件。

输入

sudo vi /etc/resolv.conf

显示

domain router
search router
nameserver 192.168.0.111

其中的nameserver就是指DNS服务器IP,上面这个IP不正确,修改nameserver 的IP地址。

输入

sudo vi /etc/network/interfaces

显示

auto lo
iface lo inet loopback
iface eth0 inet dhcp

其中iface eth0 inet dhcp代表网口目前是采用自动dhcp分配IP,修改成:

atuo eth0
iface eth0 inet static
address 192.168.0.160
network 192.168.0.0
netmask 255.255.255.0
broadcast 192.168.0.255
gateway 192.168.0.1

设置了Raspberry Pi的静态IP为192.168.0.160,这些可以根据自己网络修改设置。

保存退出重启网络,输入:

sudo /etc/init.d/networking restart

网络重启后可以通过ping命令看看网络有没有连通。

中文设置

网络连通后其实Raspberry Pi的初步设置已经完成了,软件环境已经可以使用。对于我们来说中文更习惯,而Raspian系统是支持中文显示的,所以我们来看看怎么设置中文。

还是在命令行模式下,因为网络已经连通,先进行在线升级,输入:

sudo apt-get update

安装中文字体:

sudo apt-get install ttf-wqy-microhei

安装完成后设置中文:

sudo dpkg-reconfigure locales

将zh_CN前缀的都选上,然后选择zh_CN.UTF-8,这就设置系统默认环境语言为中文。

当然我们也可以输入

sudo raspi-config

进入系统最初的那个设置界面设置中文(change_locale)。

接下来安装中文输入法。输入:

sudo apt-get install scim

sudo apt-get install scim-pinyin

重启系统进入图形界面模式,可以看到一个中文的Linux系统了。

用Raspian自带的Midori浏览器可以上网冲浪了!

小结

介绍了Raspberry Pi B型开发板如何快速上手,所需要的基本外设以及网络配置。设置了Raspian系统以及中文环境,快速的搭好了一个中文的Linux系统。

参考链接

Enable Secure Shell (SSH) On Your Raspberry Pi

Posted on May 31, 2012 by Matt

Secure Shell or SSH is a network protocol that allows you to run commands on a remote device. In the case of the Raspberry Pi can you execute commands over your network from another device such as a PC or laptop. This allows you to control the Pi without attaching a keyboard, mouse or even a monitor.

The free utility “PuTTY” can be used to connect to your Pi using SSH once it is enabled.

Update : The newer Debian “Wheezy” image enabled SSH by default so Methods 1 & 2 below are not required if you are using this image.

Method 1

To start the SSH server on a Pi you can open a terminal window (i.e. LXTerminal) and type :

sudo /etc/init.d/ssh start

followed by Enter. This needs to be done every time the Pi boots.

Method 2 

To enable SSH automatically every time the Pi starts you need to :

  • Prepare an SD card with the Debian “Squeeze” image
  • Insert the SD card in your PC
  • Rename ” boot_enable_ssh.rc” as “boot.rc”
  • Eject the SD card and insert into your Pi

When the Pi boots SSH is enabled by default.

Using SSH

You can now open a remote terminal window using PuTTY or any other SSH enabled client. This will allow you to type commands as if you were using the Pi directly.

You can even use SSH to transfer files using a file explorer style interface on your PC. I recommend the free utility WinSCP which will allow you to drag and drop. Transfering files is easy and similar to using FTP.

 

转自:http://www.raspberrypi-spy.co.uk/2012/05/enable-secure-shell-ssh-on-your-raspberry-pi/

 

嵌入式设计之:初学扫盲场

导语:

软硬结合才是王道!

搞了10多年的软件,始终抱有对底层机制的极大兴趣,不可避免的凯觎起硬件的地盘。苦于没有机会接触硬件设计方面的东西,所以只是纸上“看”兵,更别说动手做了。最近做了一些modbus协议方面的软件,加之对Linux还算比较熟悉,遂产生了使用硬件实现modbus数据集合的想法。

临渊羡鱼不如退而结网,说做就做吧,此时不动手更待老死墓中?

一、MUC简介和选型:RAM or Flash

一度分不清MCU中的Flash和RAM充当什么角色。

实际上,MCU中的RAM相当于PC的内存,程序都是装在在这里供MCU执行单元执行的。而Flash相当于PC的硬盘,如果是裸奔,那么写的固件都是烧在这个Flash里面的。MCU中的Flash一般都很小,只有几十K或者几百K,一度以为Flash才是内存或者二级缓存啥的,汗。

如果你规划中的系统需要运行Linux,那么你需要给它加个“硬盘”,而读写硬盘的地址就是通过Flash来映射的。具体的可能在后面会涉及到。

RAM:MCU的片上内存;

FLASH:MCU的片上“硬盘”,有擦写次数限制,一般为10^4次;

EEPROM:用来存储参数的区域,据说可以用Flash模拟EERPOM;

SRAM:通俗讲,就是扩展的内存。

二、电路设计:自定义元件库

有些元件在库中是找不到的,比如新出的MCU。这个时候只有自己做了,方法是在orCAD Capture中新建Library,制作完毕后就可以在电路设计时使用。

但是我碰到一个悲催的问题,设计完元件图,然后在电路设计时使用,添加完元件后,缺发现有个地方不对,需要到元件库中修改此元件,改完之后,再在电路设计图中使用,却总是提示:

Part is out of date with respect to the design cache.use update cache to synchronize the part in the cache with the library.

郁闷的是此问题卡了我两天!

解决俄方法也很简单,网上查到的(悲催的百度只能搜国内的内容,而且基本都是广告,真的是一点用的没有,纯粹一个无赖废物。今天在打开google主页之前默认三遍上帝保佑,还真打开了,感谢上帝顾念苍生!):

选择File目录树,点file.dsn前面的”+”,再点Design Cache前面的”+”,找到你所出错的Part名称,右击,Update一下,问题解决!!!

 

STM32 keil mdk启动代码分析

;// <h> Stack Configuration
;//   <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
;// </h>
Stack_Size      EQU     0x00000200                           ;//定义堆栈大小
AREA    STACK, NOINIT, READWRITE, ALIGN=3    ;//定义一个数据段 按8字节对齐
    ;//AREA 伪指令用于定义一个代码段或数据段 NOINIT:指定此数据段仅仅保留了内存单元,而没有将各初始值写入内存单元,或者将各个内存单元值初始化为0Stack_Mem       SPACE   Stack_Size                           ;//保留Stack_Size大小的堆栈空间 分 配连续 Stack_Size 字节的存储单元并初始化为 0

__initial_sp                                                 ;//标号,代表堆栈顶部地址,后面有用

;// <h> Heap Configuration
;//   <o> Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
;// </h>
Heap_Size       EQU     0x00000020                            ;//定义堆空间大小
AREA    HEAP, NOINIT, READWRITE, ALIGN=3      ;//定义一个数据段,8字节对齐
__heap_base
Heap_Mem        SPACE   Heap_Size                             ;//保留Heap_Size的堆空间
__heap_limit                                                  ;//标号,代表堆末尾地址,后面有用

PRESERVE8                                     ;//指示编译器8字节对齐
THUMB                                         ;//指示编译器为THUMB指令

; Vector Table Mapped to Address 0 at Reset
AREA    RESET, DATA, READONLY                  ;//定义只读数据段,其实放在CODE区,位于0地址

EXTERN NMIException
EXTERN HardFaultException
EXTERN MemManageException
EXTERN BusFaultException
EXTERN UsageFaultException
EXTERN SVCHandler
EXTERN DebugMonitor
EXTERN PendSVC
EXTERN SysTickHandler               ;//声明这些符号在外部定义,同C
;//在××it.c中实现这些函数 ,中断就能自动调用了
EXPORT __Vectors
EXPORT __initial_sp                     ;//EXPORT:在程序中声明一个全局的标号__Vectors,该标号可在其他的文件中引用
;//IMPORT:伪指令用于通知编译器要使用的标号在其他的源文件中定义,
;//但要在当前源文件中引用,而且无论当前源文件是否引用该标号,该标号均会被加入到当前源文件的符号表中

__Vectors       DCD     __initial_sp              ;// Top of Stack         //Cotex-M 要求此处为堆栈顶部地址
DCD     Reset_Handler                ;// Reset Handler
DCD     NMIException                   ;// NMI Handler
DCD     HardFaultException        ;// Hard Fault Handler
DCD     MemManageException        ;// MPU Fault Handler
DCD     BusFaultException         ;// Bus Fault Handler
DCD     UsageFaultException       ;// Usage Fault Handler
DCD     0                         ;// Reserved
DCD     0                         ;// Reserved
DCD     0                         ;// Reserved
DCD     0                         ;// Reserved
DCD     SVCHandler                ;// SVCall Handler
DCD     DebugMonitor              ;// Debug Monitor Handler
DCD     0                         ;// Reserved
DCD     PendSVC                   ;// PendSV Handler
DCD     SysTickHandler            ;// SysTick Handler      //一大堆的异常处理函数地址
;// External Interrupts
EXTERN WWDG_IRQHandler
EXTERN PVD_IRQHandler
EXTERN TAMPER_IRQHandler
EXTERN RTC_IRQHandler
EXTERN FLASH_IRQHandler
EXTERN RCC_IRQHandler
EXTERN EXTI0_IRQHandler
EXTERN EXTI1_IRQHandler
EXTERN EXTI2_IRQHandler
EXTERN EXTI3_IRQHandler
EXTERN EXTI4_IRQHandler
EXTERN DMAChannel1_IRQHandler
EXTERN DMAChannel2_IRQHandler
EXTERN DMAChannel3_IRQHandler
EXTERN DMAChannel4_IRQHandler
EXTERN DMAChannel5_IRQHandler
EXTERN DMAChannel6_IRQHandler
EXTERN DMAChannel7_IRQHandler
EXTERN ADC_IRQHandler
EXTERN USB_HP_CAN_TX_IRQHandler
EXTERN USB_LP_CAN_RX0_IRQHandler
EXTERN CAN_RX1_IRQHandler
EXTERN CAN_SCE_IRQHandler
EXTERN EXTI9_5_IRQHandler
EXTERN TIM1_BRK_IRQHandler
EXTERN TIM1_UP_IRQHandler
EXTERN TIM1_TRG_COM_IRQHandler
EXTERN TIM1_CC_IRQHandler
EXTERN TIM2_IRQHandler
EXTERN TIM3_IRQHandler
EXTERN TIM4_IRQHandler
EXTERN I2C1_EV_IRQHandler
EXTERN I2C1_ER_IRQHandler
EXTERN I2C2_EV_IRQHandler
EXTERN I2C2_ER_IRQHandler
EXTERN SPI1_IRQHandler
EXTERN SPI2_IRQHandler
EXTERN USART1_IRQHandler
EXTERN USART2_IRQHandler
EXTERN USART3_IRQHandler
EXTERN EXTI15_10_IRQHandler
EXTERN RTCAlarm_IRQHandler
EXTERN USBWakeUp_IRQHandler                    ;//同上,

DCD     WWDG_IRQHandler           ;// Window Watchdog
DCD     PVD_IRQHandler            ;// PVD through EXTI Line detect
DCD     TAMPER_IRQHandler         ;// Tamper
DCD     RTC_IRQHandler            ;// RTC
DCD     FLASH_IRQHandler          ;// Flash
DCD     RCC_IRQHandler            ;// RCC
DCD     EXTI0_IRQHandler          ;// EXTI Line 0
DCD     EXTI1_IRQHandler          ;// EXTI Line 1
DCD     EXTI2_IRQHandler          ;// EXTI Line 2
DCD     EXTI3_IRQHandler          ;// EXTI Line 3
DCD     EXTI4_IRQHandler          ;// EXTI Line 4
DCD     DMAChannel1_IRQHandler    ;// DMA Channel 1
DCD     DMAChannel2_IRQHandler    ;// DMA Channel 2
DCD     DMAChannel3_IRQHandler    ;// DMA Channel 3
DCD     DMAChannel4_IRQHandler    ;// DMA Channel 4
DCD     DMAChannel5_IRQHandler    ;// DMA Channel 5
DCD     DMAChannel6_IRQHandler    ;// DMA Channel 6
DCD     DMAChannel7_IRQHandler    ;// DMA Channel 7
DCD     ADC_IRQHandler            ;// ADC
DCD     USB_HP_CAN_TX_IRQHandler ;// USB High Priority or CAN TX
DCD     USB_LP_CAN_RX0_IRQHandler ;// USB Low Priority or CAN RX0
DCD     CAN_RX1_IRQHandler        ;// CAN RX1
DCD     CAN_SCE_IRQHandler        ;// CAN SCE
DCD     EXTI9_5_IRQHandler        ;// EXTI Line 9..5
DCD     TIM1_BRK_IRQHandler       ;// TIM1 Break
DCD     TIM1_UP_IRQHandler        ;// TIM1 Update
DCD     TIM1_TRG_COM_IRQHandler   ;// TIM1 Trigger and Commutation
DCD     TIM1_CC_IRQHandler        ;// TIM1 Capture Compare
DCD     TIM2_IRQHandler           ;// TIM2
DCD     TIM3_IRQHandler           ;// TIM3
DCD     TIM4_IRQHandler           ;// TIM4
DCD     I2C1_EV_IRQHandler        ;// I2C1 Event
DCD     I2C1_ER_IRQHandler        ;// I2C1 Error
DCD     I2C2_EV_IRQHandler        ;// I2C2 Event
DCD     I2C2_ER_IRQHandler        ;// I2C2 Error
DCD     SPI1_IRQHandler           ;// SPI1
DCD     SPI2_IRQHandler           ;// SPI2
DCD     USART1_IRQHandler         ;// USART1
DCD     USART2_IRQHandler         ;// USART2
DCD     USART3_IRQHandler         ;// USART3
DCD     EXTI15_10_IRQHandler      ;// EXTI Line 15..10
DCD     RTCAlarm_IRQHandler       ;// RTC Alarm through EXTI Line
DCD     USBWakeUp_IRQHandler      ;// USB Wakeup from suspend   ;//同上

AREA    |.text|, CODE, READONLY        ;//定义代码段

; Reset Handler
Reset_Handler   PROC                              ;//过程的开始
;//Rset_Handler的实现   利用PROC、ENDP这一对伪指令把程序段分为若干个过程,使程序的结构加清晰

EXPORT Reset_Handler             [WEAK]    ;//在外部没有定义该符号时导出该符号,见HELP中[WEAK]
IMPORT __main                              ;//导入符号,__main为 运行时库提供的函数;完成堆栈,堆的初始话
LDR     R0, =__main                         ;//等工作,会调用下面定义的__user_initial_stackheap;
BX      R0                                  ;//跳到__main,进入C的世界
ENDP                                      ;过程的结束

ALIGN

; User Initial Stack & Heap
IF      :DEF:__MICROLIB                     ;//如果使用micro lib,micro lib 描述见armlib.chm

EXPORT __heap_base
EXPORT __heap_limit                        ;//只导出几个定义

ELSE                                        ;//如果使用默认C运行时库

IMPORT __use_two_region_memory
EXPORT __user_initial_stackheap
__user_initial_stackheap                                    ;//则进行堆栈和堆的赋值,在__main函数执行过程中调用。
LDR     R0, = Heap_Mem
LDR     R1, =(Stack_Mem + Stack_Size)
LDR     R2, = (Heap_Mem + Heap_Size)
LDR     R3, = Stack_Mem
BX      LR
ALIGN
ENDIF

END                                         ;//OK ,完了

 

Processor of the iPods

What processor do the iPod, iPod mini, iPod nano, iPod touch, and iPod shuffle models use?

Apple provides no official information regarding the processors used to power the iPod models.

Starting with the iPod nano 2nd Gen, the company has gone as far as having the processor custom branded with an Apple logo to make it more difficult to determine its origins. However, the below chart is believed to be accurate.

iPod Name Processor Details
iPod (Original/Scroll) PP5002 PortalPlayer PP5002 “system on a chip” with dual embedded 90 MHz ARM 7TDMI processors.
iPod 2nd Gen PP5002  
iPod 3rd Gen 10/15/30 PP5002  
iPod 3rd Gen 10/20/40 PP5002  
iPod 3rd Gen 15/20/40 PP5002  
iPod 4th Gen ClickWheel PP5020 PortalPlayer PP5020 “system on a chip” with dual embedded variable speed 80 MHz ARM 7TDMI processors.
iPod U2 4th Gen PP5020  
iPod photo (30) PP5020  
iPod photo (40/60) PP5020  
iPod Color Display PP5020  
iPod U2 Edition (Color) PP5020  
iPod mini PP5020  
iPod mini 2nd Gen PP5020  
iPod 5th Gen (Video) PP5021C PortalPlayer PP5021C “system on a chip” with dual embedded variable speed 80 MHz ARM 7TDMI processors. For video decoding, these models use a Broadcom VideoCore BCM2722 processor.
iPod U2 5th Gen PP5021C  
iPod 5th Gen – Enhanced PP5021C The “Enhanced” 5th Gen iPod models are believed to use the same processors as the 5th Gen models.
iPod U2 5th Gen Enh. PP5021C  
iPod classic 6th Gen Samsung ARM Apple provides no information on the processor used in the iPod classic (6th Gen) models, but it uses an Apple branded processor, believed to be a Samsung ARM. For more information, please refer to iFixit’s disassembly guide.
iPod classic (2008) Samsung ARM Apple provides no information on the processor used in the iPod classic (6th Gen/Late 2008) models, but it uses an Apple branded processor, believed to be a Samsung ARM like its predecessor.
iPod nano PP5021C PortalPlayer PP5021C “system on a chip” with dual embedded 80 MHz ARM 7TDMI processors.
iPod nano 2nd Gen Samsung ARM Apple provides no information on the processor used in the iPod nano 2nd Gen models, but each uses an Apple branded processor, believed to be a Samsung ARM. For in-depth speculation regarding all of the chips used, please refer to ArsTechnica’s iPod nano 2nd Gen “autopsy.”
iPod nano 2nd Gen RED Samsung ARM  
iPod nano 3rd Gen/Fat Samsung ARM Apple provides no information on the processor used in the iPod nano 3rd Gen models, but each uses an Apple branded processor, believed to be a Samsung ARM. For more information, please refer to iFixit’s disassembly guide.
iPod nano 4th Gen Samsung ARM Apple provides no information on the processor used in the iPod nano 4th Gen models, but each uses an Apple branded processor, believed to be a Samsung ARM. For more information, please refer to iFixit’s disassembly guide.
iPod nano 5th Gen Samsung ARM Apple provides no information on the processor used in the iPod nano 5th Gen models, but each uses an Apple branded processor, believed to be a Samsung ARM. For more information, please refer to iFixit’s disassembly guide.
iPod nano 6th Gen Samsung ARM Apple provides no information on the processor used in the iPod nano 6th Gen models, but it is believed to use a Samsung ARM like its predecessors.
iPod shuffle STMP 3550 Uses a 75 MHz SigmaTel D-Major STMP 3550 processor.
iPod shuffle 2nd Gen Samsung ARM Apple provides no information on the processor used in the iPod shuffle 2nd Gen models, but it uses an Apple branded processor, believed to be a Samsung ARM. For more information, please refer to iFixit’s “teardown.”
iPod shuffle 3rd Gen Samsung ARM Apple provides no information on the processor used in the iPod shuffle 3rd Gen models, but it uses an Apple branded processor, believed to be a Samsung ARM. For more information, please refer to iFixit’s “teardown.”
iPod shuffle 3rd Gen Color Samsung ARM Apple provides no information on the processor used in the iPod shuffle 3rd Gen (Colors) models, but it uses an Apple branded processor, believed to be a Samsung ARM. For more information, please refer to iFixit’s “teardown.”
iPod shuffle 4th Gen Samsung ARM Apple provides no information on the processor used in the iPod shuffle 4th Generation models, but it uses an Apple branded processor, believed to be a Samsung ARM.
iPod touch Samsung ARM Apple provides no information on the processor used in the iPod touch models, but it uses an Apple branded processor, believed to be a Samsung ARM running at 400 MHz. For more information, please refer to iFixit’s disassemblyguide.
iPod touch 2nd Gen Samsung ARM Apple provides no information on the processor used in the iPod touch 2nd Gen models, but third-party “teardowns” indicate that it uses an Apple branded Samsung ARM processor running at 533 MHz. For more information, please refer to iFixit’s disassemblyguide.
iPod touch 3rd Gen Samsung ARM Apple provides no information on the processor used in the iPod touch 3rd Gen models, but third-party “teardowns” indicate that the 32 GB and 64 GB configurations use an Apple branded Samsung ARM processor running at 800 MHz. For more information, please refer to iFixit’s disassemblyguide.
iPod touch 4th Gen Apple A4 Like the original iPad and iPhone 4, the iPod touch (4th Generation) uses a custom ARM-based “system on a chip” that Apple refers to as an “Apple A4” processor. It integrates the CPU, graphics, the memory controller, and I/O functions.
iPod touch “4.5” Gen Apple A4 The iPod touch “4.5” Gen uses the same Apple A4 processor as the 4th Gen model.

Should you have additional, or alternate, information about the processors used in the iPod please share.

ARM处理器芯片选型指南

  要选好一款处理器,要考虑的因素很多,不单单是纯粹的硬件接口,还需要考虑相关的操作系统、配套的开发工具、仿真器,以及工程师微处理器的经验和软件支持情况等。微处理器选型是否得当,将决定项目成败。当然,并不是说选好微处理器,就意味着成功,因为项目的成败取决于许多因素;但可以肯定的一点是,微处理器选型不当,将会给项目带来无限的烦恼,甚至导致项目的流产。

  1 嵌入式微处理器选型的考虑因素

在产品开发中,作为核心芯片的微处理器,其自身的功能、性能、可靠性被寄予厚望,因为它的资源越丰富、自带功能越强大,产品开发周期就越短,项目成功率就越高。但是,任何一款微处理器都不可能尽善尽美,满足每个用户的需要,所以这就涉及选型的问题。

(1)应用领域

一个产品的功能、性能一旦定制下来,其所在的应用领域也随之确定。应用领域的确定将缩小选型的范围,例如:工业控制领域产品的工作条件通常比较苛刻,因此对芯片的工作温度通常是宽温的,这样就得选择工业级的芯片,民用级的就被排除在外。目前,比较常见的应用领域分类有航天航空、通信、计算机、工业控制、医疗系统、消费电子、汽车电子等。

(2)自带资源

经常会看到或听到这样的问题:主频是多少?有无内置的以太网MAC?有多少个I/O口?自带哪些接口?支持在线仿真吗?是否支持OS,能支持哪些OS?是否有外部存储接口?……以上都涉及芯片资源的问题,微处理器自带什么样的资源是选型的一个重要考虑因素。芯片自带资源越接近产品的需求,产品开发相对就越简单。

(3)可扩展资源

硬件平台要支持OS、RAM和ROM,对资源的要求就比较高。芯片一般都有内置RAM和ROM,但其容量一般都很小,内置512 KB就算很大了,但是运行OS一般都是兆级以上。这就要求芯片可扩展存储器。

(4)功 耗

单看“功耗”是一个较为抽象的名词。这里举几个形象的例子:

①夏天使用空调时,家里的电费会猛增。这是因为空调是高功耗的家用电器,这时人们会想,“要是空调能像日光灯那样省电就好了”。

②随身的MP3、MP4都使用电池。正当听音乐看视频时,系统因为没电自动关机,谁都会抱怨“又没电了!”

③目前手机一般使用锂电池,手机的待机和通话时间成了人们选择手机的重要指标。待机及通话时间越长,电池的使用寿命就可以提高,手机的寿命也相对提高了。

以上体现了人们对低功耗的渴求。低功耗的产品即节能又节财,甚至可以减少环境污染,它有如此多的优点,因此低功耗也成了芯片选型时的一个重要指标。

(5)封 装

常见的微处理器芯片封装主要有QFP、BGA两大类型。BGA类型的封装焊接比较麻烦,一般的小公司都不会焊,但BGA封装的芯片体积会小很多。如果产品对芯片体积要求不严格,选型时最好选择QFP封装。

(6)芯片的可延续性及技术的可继承性

目前,产品更新换代的速度很快,所以在选型时要考虑芯片的可升级性。如果是同一厂家同一内核系列的芯片,其技术可继承性就较好。应该考虑知名半导体公司,然后查询其相关产品,再作出判断。

(7)价格及供货保证

芯片的价格和供货也是必须考虑的因素。许多芯片目前处于试用阶段(Sampling),其价格和供货就会处于不稳定状态,所以选型时尽量选择有量产的芯片。

(8)仿真器

仿真器是硬件和底层软件调试时要用到的工具,开发初期如果没有它基本上会寸步难行。选择配套适合的仿真器,将会给开发带来许多便利。对于已经有仿真器的人们,在选型过程中要考虑它是否支持所选的芯片。

(9)OS及开发工具

作为产品开发,在选型芯片时必须考虑其对软件的支持情况,如支持什么样的OS等。对于已有OS的人们,在选型过程中要考虑所选的芯片是否支持该OS,也可以反过来说,即这种OS是否支持该芯片。

(10)技术支持

现在的趋势是买服务,也就是买技术支持。一个好的公司的技术支持能力相对比较有保证,所以选芯片时最好选择知名的半导体公司。

另外,芯片的成熟度取决于用户的使用规模及使用情况。选择市面上使用较广的芯片,将会有比较多的共享资源,给开发带来许多便利.

  2 ARM公司及相关产品介绍

ARM公司于1991年成立于英国剑桥,主要出售ARM IP的授权。目前,ARM处理器(即采用ARM IP核的处理器)已遍及工业控制、消费类电子产品、通信系统、网络系统、无线系统等各类产品市场。ARM处理器应用占据了32位RISC微处理器很大的市场,ARM技术已渗入生活的各个方面。

目前市面上常见的ARM处理器架构可分为ARM7、ARM9、ARM10、ARM11以及Cortex系列,每个系列又包括很多种IP内核的产品。ARM 也是嵌入式处理器中首先推出多核架构的厂商。生产ARM芯片的厂家很多,主流半导体厂商的产品比较齐全,供货也相对更有保障。Samsung、NXP、 Cirrus Logic、Atmel、Freescale、TI、ST、Winbond等主流半导体厂商的ARM芯片产品列表见本刊网站,其中有些产品已供货,有些正在样片阶段,有些正在开发,还有许多产品不支持外部存储器的扩展。

  3 嵌入式微处理器选型示例

(1)需 求

①适合于工业控制的温度。

②支持VxWorks、Linux操作系统。

③存储方面,SDRAM大于16 MB,Flash大于8 MB。

④主频方面,60 MHz以上。

⑤接口方面具有带DMA控制的Ethernet MAC、2个以上RS232串口、1个USB 2.O接口、1个SPI接口,以及大于30个GPIO引脚(不包括数据总线、地址总线和CPU内置接口总线)。

⑥提供实时时钟或实时定时器。

⑦引脚封装为QFP。

⑧价格为<200元。

(2)选型需求分析

根据需求①,参照前述选购的考虑因素中的“应用领域”,把要选的芯片定位于工业控制领域。目前市场上生产较适合用于作工业控制的微处理器的半导体公司有 NXP、Atmel、ST公司(Samsung公司的产品较适合用于PDA、多媒体产品,Cirrus Logic公司的产品较适合音频产品。)根据需求②,参照选购的考虑因素中的“OS及开发工具”,VxWorks5.5对于ARM核支持到V5T架构,所以把选型范围缩小到ARM7和ARM9系列。由于需要支持Linux操作系统,所以最好选择带有MMU的内核,因为不带MMU内核(ARM7TMDI)支持的Linux操作系统非常有限,只能支持UCLinux。

根据需求③,结合各种型号的芯片资源介绍,不难看出要求芯片必须带有可扩展存储接口,因为芯片的内置存储量不可能那么大。所以只能选择带可扩展存储接口的芯片。NXP公司的LPC2400系列和LH7A具备此项功能,Atmel公司的AT91SAM7SE系列、AT91RM9200、AT91SAM9系列也满足此项需求。

根据需求④、⑤、⑥、⑦,参照选购的考虑因素中的“价格及供货保证”,结合NXP、Atmel公司的芯片资源介绍,把选型范围框定在LPC2468 (LPC2400系列中的其他产品要么处于样片阶段,要么处于开发阶段,而LH7A资源不满足要求)、AT91RM9200和AT91SAM9260 (AT91SAM7SE系列处理速度太慢,AT91SAM9261和AT91SAM9263封装不满足需求)型号上。根据需求⑧,上一步所选的3个型号都能满足要求。

(3)选型结论

综合需求和芯片各方面的资源,选型结论如下:

①从产品开发周期角度考虑,AT91RM9200最为适合,它在这4个芯片中开发周期应该最短;

②从技术可继承性角度考虑,且对开发周期没有严格限制的话,AT91SAM9260较为合适;

③如果单支持VxWorks,对Linux支持要求不高,且对开发周期没有严格限制的话,LPC2468较为合适;

④综合各方面考虑,STR912排在其他三者之后。

选型满意度从高到低的排列顺序是:AT91RM9200、AT91SAM9260、LPC2468、STR912。

2011年11月09日 17:18 来源:本站整理 作者:秩名

原址:http://www.elecfans.com/emb/arm/20111109240239_2.html

iSuppli: iPod Nano 材料费才 $43.73

  新款iPod nano改用了触摸屏,但却去掉了上代的视频摄像头和传统的转盘操作,闪存容量最少也仅为8GB。事实上自从2008年NAND闪存价格不再大幅下跌以来,苹果就放弃了每代容量翻番的做法。苹果iPod nano 6代成本分析:为售价三成

 苹果的产品总是在备受关注的同时也饱受争议,比如苹果上个月发布的新产品ipod nano第六代,目前iSuppli分析认为:这个小东西凭借精巧的尺寸、低廉的成本、丰富的功能,再次验证了那句传统格言:“少即是多”(Less is More)。经过细致分析,iSupplli认为新款触摸屏iPod nano 8GB版本的物料成本(BOM)为43.73美元,只比第四代的40.80美元略贵一些,在历代iPod产品中是第二低廉的。

  iSuppli首席分析师、拆解服务经理Andrew Rassweiler指出:“很多品牌的最新产品都是拼命增加功能,但是苹果的第六代iPod却维持甚至移除了部分属性,以满足尺寸和功能的需要。这让苹 果拥有了最小巧的iPod,不但有触摸屏,还严格限制了元件成本。

  第六代iPod nano 8GB物料成本一览:

  - 存储芯片(东芝8GB MLC NAND和三星512Mb Mobile DDR):14.40美元

  - 显示和触摸屏模块:11.50美元

  - 应用处理器(三星APL3278A01/ARM架构)和相关DRAM:4.95美元

  - 用户界面(Cirrus Logic音频编码器、意法半导体加速计、Cypress半导体触摸屏控制器、Silicon Laboratories FM收音机、Intersil视频驱动等等):3.49美元

  - 附件(耳机、USB数据线、包装、说明书):2.42美元

  - 机械元件(金属、塑料等等):2.00美元

  - 电源管理(Dialog电源管理电路、MOSFET、二极管等等):1.33美元

  - 电子机械元件(PCB、接头等等):0.89美元

  - 电池(锂离子聚合物):0.70美元

  - 其他:2.05美元

  如果再算上1.37美元的制造成本,第六代iPod nano 8GB的总成本将为45.10美元,相当于建议零售价149美元的30%。

文/驱动之家

串口通讯简单回顾

最近几个小项目都是与串口有关的,前段时间用C++实现了一个串口通讯类,高效稳定,效果还不错;后来由于一个同事用C#的SerialPort类与设备通讯时效率很低,让我帮他自己包装了一个C#的Comm通讯类。

串口通讯中对串口的设置基本上很简单,大部分时候只需要设置串口号和波特率、数据位、停止位,其他的很少改动,默认就行了。

在使用C#与设备通讯时,发现一个比较贵的USB转串口线通讯速度不稳定,至少前面几分钟速度会非常的慢,之后就恢复正常了。但是用sscom32调试助手看却很快,所以怀疑打开串口的时候是不是对其他几个参数的设置上的区别导致通讯速度的不同?更奇怪的是另一根相当便宜的USB转串口线,在任何情况下速度都很正常,汗……

简单讲解

串口是计算机上一种非常通用的通信设备,大多数计算机包含两个基于RS232的串口,由于其使用简单造价低廉而被普遍应用。

奇怪的是近几年出产的笔记本和PC机基本都没有串口这种设备了,而简单易用、成本低廉的特性,让很多硬件设计工程师还是选择了串口作为设备与其他设备的通讯方式。因此,usb串口转换线使用的非常多,它的RS232-485接口连接串口设备,另一端转换为USB接入PC等上位机,在上位机上模拟出多个串口,以实现PC机通过串口与外围串口设备通讯。

串口通信的概念非常简单,串口按位(bit)发送和接收字节。尽管比按字节(byte)的并行通信慢,但是串口可以在使用一根线发送数据的同时用另一根线接收数据。它很简单并且能够实现远距离通信。而IEEE488定义规定,对于并行通讯,设备线总常不得超过20米,并且任意两个设备间的长度不得超过2米;而对于串口而言,长度可达1200米。

典型地,串口用于ASCII码字符的传输。通信使用3根线完成:(1)地线,(2)发送,(3)接收。由于串口通信是异步,端口能够在一根线上发送数据同时在另一根线上接收数据。其他线用于握手,但是不是必须的。

串口通信最重要的参数是波特率、数据位、停止位和奇偶校验。对于两个进行通行的端口,这些参数必须匹配。

高深一点,通讯过程中的硬件知识

由于 CPU 与接口之间按并行方式传输,接口与外设之间按串行方式传输,因此,在串行接口中,必须要有“接收移位寄存器” (串→并)和 “发送移位寄存器 ”(并→串)。在数据输入过程中,数据 1 位 1 位地从外设进入接口的 “接收移位寄存器” ,当“接收移位寄存器”中已接收完 1 个字符的各位后,数据就从“接收移位寄存器”进入“数据输入寄存器”。CPU 从“数据输入寄存器”中读取接收到的字符。(并行读取,即 D7~D0 同时被读至累加器中)。“接收移位寄存器”的移位速度由“ 接收时钟”确定。

在数据输出过程中,CPU 把要输出的字符(并行地)送入“数据输出寄存器”,“数据输出寄存器”的内容传输到“发送移位寄存器”,然后由“发送移位寄存器”移位,把数据 1 位 1 位地送到外设。“发送移位寄存器”的移位速度由“发送时钟”确定。

接口中的“控制寄存器”用来容纳 CPU 送给此接口的各种控制信息,这些控制信息决定接口的工作方式。

“状态寄存器”的各位称为“状态位”,每一个状态位都可以用来指示数据传输过程中的状态或某种错误。例如,用状态寄存器的 D5 位为 ‘1’ 表示“数据输出寄存器”空,用 D0 位表示“数据输入寄存器满”,用 D2 位表示“奇偶检验错”等。

实际上,上面所说的”串→并”转换的功能由一块叫UART(Universal Asynchronous Receiver and Transmitter)的芯片完成,典型的芯片有: Intel 8250/8251,16550。

从电气特性上说,串口就使用接收线和发送线传输数据。无论是发送还是接收一个逻辑1,发送或者接收线被置成了低电压,相反,如果是逻辑0,则被置成了高电压。当传输一个字节时,UART首先发送一个‘开始位’,为逻辑0,即,高电压,然后是数据位(通常是8位,当然也可以设置成5、6或者7位,上位机通常以一个字节为单位来处理串口数据的,所以,如果不想给自己找麻烦,或者不想被人看的很高深,还是老老实实用默认的8位吧:-)。PS:前两天用串口通讯,发现接收到的数据总是不大于127,原因就是在用C#定义DCB结构体时把几个flag定义错了,导致覆盖到了数据位的标志位为7,所以肯定完蛋,把第8为当成了下一个字节的起始标示位了),最后接着来的是1位或者两位停止位,是逻辑1,即低电平。这样,一个字节就传输出去了,其它字节依次周而复始。

上个图给你look look,应该就很形象了:

流控制:XON/XOFF

到这里就有点复杂了,一般情况下没必要了解,如果很好奇,那就看看,毕竟了解的越多,动起手来才得心应手!

下面的文字来自网络,讲的很清楚,直接摘了:
XON/XOFF 是一种流控制协议(通信速率匹配协议),用于数据传输速率大于等于1200b/s时进行速率匹配,方法是控制发送方的发速率以匹配双方的速率。
XMODEM是一种低速文件传输协议。KERMIT是异步通信环境中使用的一种文件传输协议。它与XMODEM的主要区别是:KERMIT一次可传送多个文件,而XMODEM一次只能传送一个文件;KERMIT在接收方以完整的信息包应答,而XMODEM以单字节应答;KERMIT提供多种错误校验技术,而XMODEM只提供一种错误校验技术。
在流量控制方面,可以从不同侧面采取不同的控制方案。最简单的方法就是增加接收端的缓冲存储空间,使得接收端可以缓存更多的数据。但这只是一种被动、消极的方法。因为,一方面系统不允许开设过大的缓冲空间;另一方面对于速率显著失配,并且又传送大量数据的场合,即使缓存空间再大也会出现不够的现象。目前普遍采取一种称之为“XON/XOFF”的发送控制字符的方案,通过控制字符来确定发送方是否继续发送数据,相比之下更主动、更积极、更有效。
XON/XOFF(继续/停止)是异步串行连接的计算机和其他元件之间的数据流控制协议。例如,计算机向打印机发送数据的速度通常快于打印机打印的速度,打印机包含一个缓冲器,用来存储数据,使打印机能够赶上计算机。如果在打印机赶上之前缓冲器变满了,打印机的小微处理器便发回一个XOFF信号来停止数据传送,打印完相当多的数据,缓冲存储器变空时,打印机发送XON信号,让计算机继续发送数据。“X”表示“发送器”,X/ON和X/OFF为开启和关闭发送器的信号。X/ON的实际信号为ASCII的Ctrl-Q键盘组合的位组合,X/OFF信号为Ctrl-S字符。在为计算机操作系统定义调制解调器时,可能需要用XON/XOFF或CTS/RTS来指定流控制的使用。在发送二进制数据时,XON/XOFF可能不能识别,因为它被译成了字符。
XON/XOFF是一种异步通信协议,接收设备或计算机使用特殊字符来控制发送设备或计算机传送的数据流。当接收计算机不能继续接收数据时,发送一个XOFF控制字符告诉发送方停止传送;当传输可以恢复时,该计算机发送一个XON字符来通知发送方。其中XON采用ASCII字符集中的控制字符DC1,XOFF采用ASCII字符集中的控制字符DC3。当通信线路上的接收方发生过载时,便向发送方发送一个XOFF字符,发送方接收XOFF字符后便暂停发送数据;等接收方处理完缓冲器中的数据,过载恢复后,再向发送方发送一个XON字符,以通知发送方恢复数据发送。在一次数据传输过程中,XOFF、XON的周期可重复多次,但这些操作对用户来说是透明的,也就是说用户不用管它。
许多异步数据通信软件包均支持XON/XOFF协议。这种方案也可用于计算机向打印机或其他终端设备(如MODEM的串行通信)发送字符,在这种情况下,打印机或终端设备中的控制部件用以控制字符流量。

用SD卡制作Linux启动盘

搞嵌入式开发的朋友对从SD卡引导系统并不陌生,尤其是对类Linux的引导,一般把SD卡分成两个分区,一个是boot,基本上都是FAT32的,因为支持范围比较多,兼容性好。另一个就是Linux文件系统了。由于要把SD卡分成两个分区,不像通常一样格式化这么简单,需要一些不一样的操作手段。

前两天看了一篇文章《Linux Boot Disk Format》,虽然讲得相当详细,但是毕竟有些版本不一致的地方,很容易导致失败。所以将我的操作过程记录于此,希望能帮到需要的人。

按照Linux Boot Disk Format一文中介绍的方法,虽然成功格式化了我的SD卡,但有些地方不太一样,需要特别注意,因为一旦弄错,比如格式化了别的硬盘,那你就搬个小凳子墙角哭去吧:)

首先,用[dmesg | tail]命令显示如下信息:

[27544.407777] mmc0: new SD card at address 00c3
[27544.408026] mmcblk0: mmc0:00c3       475 MiB
[27544.408173]  mmcblk0: p1
[27577.892153] mmc0: card 00c3 removed
[27587.296689] mmc0: card claims to support voltages below the defined range. These will be ignored.
[27587.296700] mmc0: SD card claims to support the incompletely defined ‘low voltage range’. This will be ignored.

这个需要仔细看的,刚开始我去找‘sdx’,结果没有,很是奇怪。实际上,我的Ubuntu已经是10.04了,很多地方与ubuntu7还是不太一样的,比如设备显示信息会有些不同:)。
Linux Boot Disk Format》中的显示

[ 6854.215659] sdc: sdc1

我这里显示

[27544.408173]  mmcblk0: p1

所以,下面的[df -h]命令也会不太一样:

hyh@hyh-laptop:~$ df -h
文件系统            容量  已用 可用 已用% 挂载点
/dev/sdb6              49G  5.2G   41G  12% /
none                  490M  360K  489M   1% /dev
none                  494M  1.3M  492M   1% /dev/shm
none                  494M   88K  494M   1% /var/run
none                  494M     0  494M   0% /var/lock
none                  494M     0  494M   0% /lib/init/rw
/dev/sdb2              98G   59G   40G  60% /media/photo
/dev/sdb3             391G  161G  231G  41% /media/software
/dev/sdb5              49G  2.2G   47G   5% /media/sys
/dev/sdb4             346G  129G  217G  38% /media/doc
/dev/mmcblk0p1        476M   32M  444M   7% /media/A46E-7FA0

你可以看到,我的SD卡挂载到了mmcblk0,分区是p1:

/dev/mmcblk0p1        476M   32M  444M   7% /media/A46E-7FA0

现在非常非常非常的确认了我的SD卡是mmcblk0了,因为你也得非常非常非常的肯定你没搞错分区,否则又要找小凳子去了…
其实有一种可以非常非常肯定的手段来看你的SD卡是哪个的:
首先拔出SD卡,然后敲入[df -h],看看显示列表;然后插入SD卡,正确识别出来后,敲入[df -h],再看看显示列表,看看多出来的就是你的SD卡信息。

下面umount SD卡:

hyh@hyh-laptop:~$ umount /media/A46E-7FA0

选择/dev/mmcblk0,进入fdisk

hyh@hyh-laptop:~$ sudo fdisk /dev/mmcblk0
[sudo] password for hyh:

WARNING: DOS-compatible mode is deprecated. It’s strongly recommended to
switch off the mode (command ‘c’) and change display units to
sectors (command ‘u’).

显示“Command (m for help):”就是已经进入fdisk了,并且所有操作都是针对mmcblk0的,打印一下mmcblk0的信息看看:

Command (m for help): p

Disk /dev/mmcblk0: 498 MB, 498860032 bytes
255 heads, 63 sectors/track, 60 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00819e01

Device Boot      Start         End      Blocks   Id  System
/dev/mmcblk0p1   *           1          61      487136+   e  W95 FAT16 (LBA)
Partition 1 has different physical/logical endings:
phys=(59, 254, 63) logical=(60, 165, 41)

删除已有分区:

Command (m for help): d
Selected partition 1

如果上面你pint你的sd卡没有显示255 heads, 63 sectors/track信息,那么你还的重做一下你的SD卡,具体操作见Linux Boot Disk Format第七步。
我的当然显示正常,所以现在略过第七步,继续往下走:

新建一个FAT32分区:

Command (m for help): n
Command action
e   extended
p   primary partition (1-4)
p
Partition number (1-4): 1
First cylinder (1-60, default 1):
Using default value 1
Last cylinder, +cylinders or +size{K,M,G} (1-60, default 60): +5

Command (m for help): t
Selected partition 1
Hex code (type L to list codes): c
Changed system type of partition 1 to c (W95 FAT32 (LBA))

OK了,把它标记为启动盘:

Command (m for help): a
Partition number (1-4): 1

创建Linux分区:

Command (m for help): n
Command action
e   extended
p   primary partition (1-4)
p
Partition number (1-4): 2
First cylinder (7-60, default 7):
Using default value 7
Last cylinder, +cylinders or +size{K,M,G} (7-60, default 60):
Using default value 60

打印一下看看:

Command (m for help): p

Disk /dev/mmcblk0: 498 MB, 498860032 bytes
255 heads, 63 sectors/track, 60 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00819e01

Device Boot      Start         End      Blocks   Id  System
/dev/mmcblk0p1   *           1           6       48163+   c  W95 FAT32 (LBA)
/dev/mmcblk0p2               7          60      433755   83  Linux

一切OK,保存以上所有操作,注意,上面的所有操作实际上只是yy,没有真正修改SD卡!这也是高明之处!!!

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.

WARNING: If you have created or modified any DOS 6.x
partitions, please see the fdisk manual page for additional
information.
Syncing disks.

格式化FAT32分区,并将卷标设为“LABEL1”,当然你可以另外叫个你喜欢的名字:

hyh@hyh-laptop:~$ sudo mkfs.msdos -F 32 /dev/mmcblk0p1 -n LABEL1
mkfs.msdos 3.0.7 (24 Dec 2009)

格式化Linux分区,并将卷标设为“LABEL2”,当然你可以另外叫个你喜欢的名字:
hyh@hyh-laptop:~$ sudo mkfs.ext3 -L LABEL2 /dev/mmcblk0p2
mke2fs 1.41.11 (14-Mar-2010)
文件系统标签=LABEL2
操作系统:Linux
块大小=1024 (log=0)
分块大小=1024 (log=0)
Stride=0 blocks, Stripe width=0 blocks
108544 inodes, 433752 blocks
21687 blocks (5.00%) reserved for the super user
第一个数据块=1
Maximum filesystem blocks=67633152
53 block groups
8192 blocks per group, 8192 fragments per group
2048 inodes per group
Superblock backups stored on blocks:
8193, 24577, 40961, 57345, 73729, 204801, 221185, 401409

正在写入inode表: 完成
Creating journal (8192 blocks): 完成
Writing superblocks and filesystem accounting information: 完成

This filesystem will be automatically checked every 38 mounts or
180 days, whichever comes first.  Use tune2fs -c or -i to override.
hyh@hyh-laptop:~$

现在再输入[dmesg | tail],显示如下:

[27544.407777] mmc0: new SD card at address 00c3
[27544.408026] mmcblk0: mmc0:00c3       475 MiB
[27544.408173]  mmcblk0: p1
[27577.892153] mmc0: card 00c3 removed
[27587.296689] mmc0: card claims to support voltages below the defined range. These will be ignored.
[27587.296700] mmc0: SD card claims to support the incompletely defined ‘low voltage range’. This will be ignored.
[27587.323780] mmc0: new SD card at address 00c3
[27587.324030] mmcblk0: mmc0:00c3       475 MiB
[27587.324687]  mmcblk0: p1
[28479.035485]  mmcblk0: p1 p2

下面多了这么几行:

[27587.323780] mmc0: new SD card at address 00c3
[27587.324030] mmcblk0: mmc0:00c3       475 MiB
[27587.324687]  mmcblk0: p1
[28479.035485]  mmcblk0: p1 p2

打完收工!

注意:在 ubuntu 下格式化好 FAT 和 EXT3 双分区后,FAT 分区需要在 window 下重新
格式化一次,否则可能会出现无法从 SD 卡启动的情况.

另外,有时候SD卡分区被搞得很乱,或者有很多个分区,所以在清除已有分区时,一定要清除干净。比如我的一个SD卡,由于第一次分区不成功,导致里面余留了很多很奇怪的信息,其实就是分区表被破坏了,所以必须清除干净。

hyh@hyh-laptop:/media$ sudo fdisk /dev/mmcblk0
[sudo] password for hyh:

WARNING: DOS-compatible mode is deprecated. It’s strongly recommended to
switch off the mode (command ‘c’) and change display units to
sectors (command ‘u’).

Command (m for help): p

Disk /dev/mmcblk0: 498 MB, 498860032 bytes
4 heads, 16 sectors/track, 15224 cylinders
Units = cylinders of 64 * 512 = 32768 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x6f20736b

This doesn’t look like a partition table
Probably you selected the wrong device.

Device Boot Start End Blocks Id System
/dev/mmcblk0p1 ? 12158374 29994462 570754815+ 72 Unknown
Partition 1 does not end on cylinder boundary.
/dev/mmcblk0p2 ? 2635774 32886216 968014120 65 Novell Netware 386
Partition 2 does not end on cylinder boundary.
/dev/mmcblk0p3 ? 29216898 59467339 968014096 79 Unknown
Partition 3 does not end on cylinder boundary.
/dev/mmcblk0p4 ? 45088769 45089636 27749+ d Unknown
Partition 4 does not end on cylinder boundary.

Partition table entries are not in disk order

Command (m for help):

够乱吧?4 heads, 16 sectors/track, 15224 cylinders、四个分区。。。

那就先清了吧,重做一下SD卡!

删除第一分区:

Command (m for help): d
Partition number (1-4): 1

显示看看

Command (m for help): p

Disk /dev/mmcblk0: 498 MB, 498860032 bytes
4 heads, 16 sectors/track, 15224 cylinders
Units = cylinders of 64 * 512 = 32768 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x6f20736b

This doesn’t look like a partition table
Probably you selected the wrong device.

Device Boot Start End Blocks Id System
/dev/mmcblk0p2 ? 2635774 32886216 968014120 65 Novell Netware 386
Partition 2 does not end on cylinder boundary.
/dev/mmcblk0p3 ? 29216898 59467339 968014096 79 Unknown
Partition 3 does not end on cylinder boundary.
/dev/mmcblk0p4 ? 45088769 45089636 27749+ d Unknown
Partition 4 does not end on cylinder boundary.

由于分区表被破坏,没法对分区表做正确操作,还是先把heads和簇修正。

进入专家模式,重建分区表:

Command (m for help):
Command (m for help): x

Expert command (m for help): h
Number of heads (1-256, default 4): 255

Expert command (m for help): s
Number of sectors (1-63, default 16): 63
Warning: setting sector offset for DOS compatiblity

Expert command (m for help): c
Number of cylinders (1-1048576, default 15224): 60

Expert command (m for help): r

退出专家模式,打印看看:

Command (m for help): p

Disk /dev/mmcblk0: 498 MB, 498860032 bytes
255 heads, 63 sectors/track, 60 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x6f20736b

This doesn’t look like a partition table
Probably you selected the wrong device.

Device Boot Start End Blocks Id System
/dev/mmcblk0p2 ? 10501 131013 968014120 65 Novell Netware 386
Partition 2 has different physical/logical beginnings (non-Linux?):
phys=(288, 115, 43) logical=(10500, 111, 30)
Partition 2 has different physical/logical endings:
phys=(367, 114, 50) logical=(131012, 158, 28)
Partition 2 does not end on cylinder boundary.
/dev/mmcblk0p3 ? 116395 236907 968014096 79 Unknown
Partition 3 has different physical/logical beginnings (non-Linux?):
phys=(366, 32, 33) logical=(116394, 188, 12)
Partition 3 has different physical/logical endings:
phys=(357, 32, 43) logical=(236906, 234, 25)
Partition 3 does not end on cylinder boundary.
/dev/mmcblk0p4 ? 179626 179629 27749+ d Unknown
Partition 4 has different physical/logical beginnings (non-Linux?):
phys=(372, 97, 50) logical=(179625, 87, 47)
Partition 4 has different physical/logical endings:
phys=(0, 10, 0) logical=(179628, 203, 42)
Partition 4 does not end on cylinder boundary.

Command (m for help):

255 heads, 63 sectors/track, 60 cylinders,一切正常。

手工清除所有分区:

Command (m for help): p

Disk /dev/mmcblk0: 498 MB, 498860032 bytes
255 heads, 63 sectors/track, 60 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x6f20736b

This doesn’t look like a partition table
Probably you selected the wrong device.

Device Boot Start End Blocks Id System
/dev/mmcblk0p1 * 1 6 48163+ c W95 FAT32 (LBA)
/dev/mmcblk0p2 ? 10501 131013 968014120 65 Novell Netware 386
Partition 2 has different physical/logical beginnings (non-Linux?):
phys=(288, 115, 43) logical=(10500, 111, 30)
Partition 2 has different physical/logical endings:
phys=(367, 114, 50) logical=(131012, 158, 28)
Partition 2 does not end on cylinder boundary.
/dev/mmcblk0p3 ? 116395 236907 968014096 79 Unknown
Partition 3 has different physical/logical beginnings (non-Linux?):
phys=(366, 32, 33) logical=(116394, 188, 12)
Partition 3 has different physical/logical endings:
phys=(357, 32, 43) logical=(236906, 234, 25)
Partition 3 does not end on cylinder boundary.
/dev/mmcblk0p4 ? 179626 179629 27749+ d Unknown
Partition 4 has different physical/logical beginnings (non-Linux?):
phys=(372, 97, 50) logical=(179625, 87, 47)
Partition 4 has different physical/logical endings:
phys=(0, 10, 0) logical=(179628, 203, 42)
Partition 4 does not end on cylinder boundary.

看看上面有很多分区,分区太多,分区表可能在Windows下格式化的时候就被破坏了。

一个一个的收工删除:

Command (m for help): d
Partition number (1-4): 1

Command (m for help): d
Partition number (1-4): 2

Command (m for help): p

Disk /dev/mmcblk0: 498 MB, 498860032 bytes
255 heads, 63 sectors/track, 60 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x6f20736b

This doesn’t look like a partition table
Probably you selected the wrong device.

Device Boot Start End Blocks Id System
/dev/mmcblk0p3 ? 116395 236907 968014096 79 Unknown
Partition 3 has different physical/logical beginnings (non-Linux?):
phys=(366, 32, 33) logical=(116394, 188, 12)
Partition 3 has different physical/logical endings:
phys=(357, 32, 43) logical=(236906, 234, 25)
Partition 3 does not end on cylinder boundary.
/dev/mmcblk0p4 ? 179626 179629 27749+ d Unknown
Partition 4 has different physical/logical beginnings (non-Linux?):
phys=(372, 97, 50) logical=(179625, 87, 47)
Partition 4 has different physical/logical endings:
phys=(0, 10, 0) logical=(179628, 203, 42)
Partition 4 does not end on cylinder boundary.

Command (m for help): d
Partition number (1-4): 3

Command (m for help): d
Selected partition 4

Command (m for help): 4
4: unknown command
Command action
a toggle a bootable flag
b edit bsd disklabel
c toggle the dos compatibility flag
d delete a partition
l list known partition types
m print this menu
n add a new partition
o create a new empty DOS partition table
p print the partition table
q quit without saving changes
s create a new empty Sun disklabel
t change a partition’s system id
u change display/entry units
v verify the partition table
w write table to disk and exit
x extra functionality (experts only)

Command (m for help): p

Disk /dev/mmcblk0: 498 MB, 498860032 bytes
255 heads, 63 sectors/track, 60 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x6f20736b

Device Boot Start End Blocks Id System

Command (m for help):

没有了,看看输出,与第八步一致。可以开始第九步,开始分区了。

新建一个分区:

Command (m for help): n
Command action
e extended
p primary partition (1-4)
p
Partition number (1-4): 1
First cylinder (1-60, default 1):
Using default value 1
Last cylinder, +cylinders or +size{K,M,G} (1-60, default 60): +5

将新分区改为与DOS兼容

Command (m for help): t
Selected partition 1
Hex code (type L to list codes): c
Changed system type of partition 1 to c (W95 FAT32 (LBA))

Command (m for help):

将刚刚分的第一分区设置为启动盘:

Command (m for help): a
Partition number (1-4): 1

Command (m for help):

添加第二个分区:Linux分区:

Command (m for help): n
Command action
e extended
p primary partition (1-4)
p
Partition number (1-4): 2
First cylinder (7-60, default 7):
Using default value 7
Last cylinder, +cylinders or +size{K,M,G} (7-60, default 60):
Using default value 60

打印看看:

Command (m for help): p

Disk /dev/mmcblk0: 498 MB, 498860032 bytes
255 heads, 63 sectors/track, 60 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x6f20736b

Device Boot Start End Blocks Id System
/dev/mmcblk0p1 * 1 6 48163+ c W95 FAT32 (LBA)
/dev/mmcblk0p2 7 60 433755 83 Linux

Command (m for help):

OK了,保存工作成功:

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.

WARNING: If you have created or modified any DOS 6.x
partitions, please see the fdisk manual page for additional
information.
Syncing disks.
hyh@hyh-laptop:/media$

格式化一下第一分区,命名为boot:

hyh@hyh-laptop:/media$ sudo mkfs.msdos -F 32 /dev/mmcblk0p1 -n boot
[sudo] password for hyh:
mkfs.msdos 3.0.7 (24 Dec 2009)

格式化第二分区,命名为Linux:

hyh@hyh-laptop:/media$ sudo mkfs.ext3 -L Linux /dev/mmcblk0p2
mke2fs 1.41.11 (14-Mar-2010)
文件系统标签=Linux
操作系统:Linux
块大小=1024 (log=0)
分块大小=1024 (log=0)
Stride=0 blocks, Stripe width=0 blocks
108544 inodes, 433752 blocks
21687 blocks (5.00%) reserved for the super user
第一个数据块=1
Maximum filesystem blocks=67633152
53 block groups
8192 blocks per group, 8192 fragments per group
2048 inodes per group
Superblock backups stored on blocks:
8193, 24577, 40961, 57345, 73729, 204801, 221185, 401409

正在写入inode表: 完成
Creating journal (8192 blocks): 完成
Writing superblocks and filesystem accounting information: 完成

This filesystem will be automatically checked every 23 mounts or
180 days, whichever comes first. Use tune2fs -c or -i to override.
hyh@hyh-laptop:/media$

退出,到Windows下再格式化一下第一分区。
我第一次就是没做这一步就直接往里面考东西了,启动时没成功。本以为在Windows下格式化一下第一分区,再重新把东西拷贝进去不就行了吗?结果格式化时根本没看到第一分区(上次是LABEL,这次是boot),看那容量,应该是第二分区,把第二分区给干了。。。

Linux Boot Disk Format

本文介绍了如何为DevKit8000格式化SD卡,以便通过SD卡启动安装在SD卡中的Linux操作系统!


How to create a dual-partition card for DevKit8000 to boot Linux from first partition and have root file system at second partition.

一、Introduction

This guide is meant for those looking to create a dual-partition card, booting from a FAT partition that can be read by the OMAP3 ROM bootloader and Linux/Windows, then utilizing an ext3 partition for the Linux root file system.

二、Details

Text marked with [] shows user input.

1Determine which device the SD Card Reader is on your system

Plug the SD Card into the SD Card Reader and then plug the SD Card Reader into your system. After doing that, do the following to determine which device it is on your system.

$ [dmesg | tail]

[ 6854.215650] sd 7:0:0:0: [sdc] Mode Sense: 0b 00 00 08 [ 6854.215653] sd 7:0:0:0: [sdc] Assuming drive cache: write through

[ 6854.215659] sdc: sdc1

[ 6854.218079] sd 7:0:0:0: [sdc] Attached SCSI removable disk

[ 6854.218135] sd 7:0:0:0: Attached scsi generic sg2 type 0

In this case, it shows up as /dev/sdc (note sdc inside the square brackets above).

2Check to see if the automounter has mounted the SD Card

Note there may be more than one partition (only one shown in the example below).

$ [df -h]

Filesystem Size Used Avail Use% Mounted on

/dev/sdc1 400M 94M 307M 24% /media/disk

Note the “Mounted on” field in the above and use that name in the umount commands below.

3If so, unmount it

$ [umount /media/disk]

4Start fdisk

Be sure to choose the whole device (/dev/sdc), not a single partition (/dev/sdc1).

$ [sudo fdisk /dev/sdc]

5Print the partition record

So you know your starting point. Make sure to write down the number of bytes on the card (in this example, 2021654528).

Command (m for help): [p]

Disk /dev/sdc: 2021 MB, 2021654528 bytes

255 heads, 63 sectors/track, 245 cylinders

Units = cylinders of 16065 * 512 = 8225280 bytes

Device Boot Start End Blocks Id System

/dev/sdc1 * 1 246 1974240+ c W95 FAT32 (LBA)

Partition 1 has different physical/logical endings:

phys=(244, 254, 63) logical=(245, 200, 19)

6Delete any partitions that are there already

Command (m for help): [d]

Selected partition 1

7Set the Geometry of the SD Card

If the print out above does not show 255 heads, 63 sectors/track, then do the following expert mode steps to redo the SD Card:

1)、Go into expert mode.

Command (m for help): [x]

2)、Set the number of heads to 255.

Expert Command (m for help): [h]

Number of heads (1-256, default xxx): [255]

3Set the number of sectors to 63.

Expert Command (m for help): [s]

Number of sectors (1-63, default xxx): [63]

4Now Calculate the number of Cylinders for your SD Card.

#cylinders = FLOOR (the number of Bytes on the SD Card (from above) / 255 / 63 / 512 )

So for this example: 2021654528 / 255 / 63 / 512 = 245.79. So we use 245 (i.e. truncate, don’t round).

5Set the number of cylinders to the number calculated.

Expert Command (m for help): [c]

Number of cylinders (1-256, default xxx): [enter the number you calculated]

6Return to Normal mode.

Expert Command (m for help): [r]

8Print the partition record to check your work

Command (m for help): [p]

Disk /dev/sdc: 2021 MB, 2021654528 bytes

255 heads, 63 sectors/track, 245 cylinders

Units = cylinders of 16065 * 512 = 8225280 bytes

Device Boot Start End Blocks Id System

9Create the FAT32 partition for booting and transferring files from Windows

Command (m for help): [n]

Command action

e extended

p primary partition (1-4)

[p]

Partition number (1-4): [1]

First cylinder (1-245, default 1): [(press Enter)]

Using default value 1

Last cylinder or +size or +sizeM or +sizeK (1-61, default 61): [+5]

Command (m for help): [t]

Selected partition 1

Hex code (type L to list codes): [c]

Changed system type of partition 1 to c (W95 FAT32 (LBA))

10Mark it as bootable

Command (m for help): [a]

Partition number (1-4): [1]

11Create the Linux partition for the root file system

Command (m for help): [n]

Command action

e extended

p primary partition (1-4)

[p]

Partition number (1-4): [2]

First cylinder (7-61, default 7): [(press Enter)]

Using default value 52

Last cylinder or +size or +sizeM or +sizeK (7-61, default 61): [(press Enter)]

Using default value 245

12Print to Check Your Work

Command (m for help): [p]

Disk /dev/sdc: 2021 MB, 2021654528 bytes

255 heads, 63 sectors/track, 245 cylinders

Units = cylinders of 16065 * 512 = 8225280 bytes

Device Boot Start End Blocks Id System

/dev/sdc1 * 1 6 409626 c W95 FAT32 (LBA)

/dev/sdc2 7 61 1558305 83 Linux

13Save the new partition records on the SD Card

This is an important step. All the work up to now has been temporary.

Command (m for help): [w]

The partition table has been altered!

Calling ioctl() to re-read partition table.

WARNING: Re-reading the partition table failed with error 16: Device or resource busy.

The kernel still uses the old table.

The new table will be used at the next reboot.

WARNING: If you have created or modified any DOS 6.x

partitions, please see the fdisk manual page for additional

information.

Syncing disks.

14Format the partitions

The two partitions are given the volume names LABEL1 and LABEL2 by these commands. You can substitute your own volume labels.

$ [sudo mkfs.msdos -F 32 /dev/sdc1 -n LABEL1]

mkfs.msdos 2.11 (12 Mar 2005)

$ [sudo mkfs.ext3 -L LABEL2 /dev/sdc2]

mke2fs 1.40-WIP (14-Nov-2006)

Filesystem label=

OS type: Linux

Block size=4096 (log=2)

Fragment size=4096 (log=2)

195072 inodes, 389576 blocks

19478 blocks (5.00%) reserved for the super user

First data block=0

Maximum filesystem blocks=402653184

12 block groups

32768 blocks per group, 32768 fragments per group

16256 inodes per group

Superblock backups stored on blocks:

32768, 98304, 163840, 229376, 294912

Writing inode tables: done

Creating journal (8192 blocks): done

Writing superblocks and filesystem accounting information:

 

 

 

TI OMAP3530 数字媒体处理器

OMAP3530主要面向多媒体,此MCU片上集成了ARM9 Cortex-A8 600MHz内核、达芬奇C64X DSP 430MHz核、SX 2D/3D加速器,算是相当强悍的了,下面是一段来自TI官方的超声波扫面转换演示视频:

[flv]http://www.roboby.com/wp-content/uploads/2011/03/超声波扫描转换演示-OMAP3530-EVM-Basic-Small.flv[/flv]

TI还为此开发了DVSDK数字视频开发库,居然有500多兆,带源码,这对于那些基于此处理器开发DSP图像处理的人来说是相当宝贵的资源了!

从这里可以了解相关信息

http://www.ti.com

E文不好的还是从这里看中文的吧:

http://www.ti.com.cn

DevKit8000启动日志

周一到周五要上班,小孩子就我妈妈一个人照顾。老人家老了,不方便出去,所以小孩子很少能晒到太阳,哎,头疼的问题……

所以啊,周末得花多半时间陪陪孩子,带孩子出去走走,个人时间真是少啊……

今晚把玩了一下DevKit8000开发板,Linux的启动日志如下:

Texas Instruments X-Loader 1.41Starting OS Bootloader…

U-Boot 1.3.3-svn (Feb  6 2010 – 16:29:12)
OMAP3530-GP rev 2, CPU-OPP2 L3-165MHz

OMAP3 DevKit8000 Board + LPDDR/NAND

DRAM:  256 MB

NAND:  256 MiB

Using default environment
In:    serial

Out:   serial

Err:   serial

Hit any key to stop autoboot:  0
NAND read: device 0 offset 0x280000, size 0x240000 

2359296 bytes read: OK##

Booting kernel from Legacy Image at 80300000 …  

 Image Name:   Linux-2.6.28-rc9-omap1  

 Image Type:   ARM Linux Kernel Image (uncompressed)  

Data Size:    2165084

Texas Instruments X-Loader 1.41
Starting OS Bootloader…
U-Boot 1.3.3-svn (Feb  6 2010 – 16:29:12)

OMAP3530-GP rev 2, CPU-OPP2 L3-165MHz
OMAP3 DevKit8000 Board + LPDDR/NAND
DRAM:  256 MB
NAND:  256 MiB
Using default environment

In:    serial
Out:   serial
Err:   serial
Hit any key to stop autoboot:  0

NAND read: device 0 offset 0x280000, size 0x240000
 2359296 bytes read: OK
## Booting kernel from Legacy Image at 80300000 …
   Image Name:   Linux-2.6.28-rc9-omap1
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    2165084 Bytes =  2.1 MB
   Load Address: 80008000
   Entry Point:  80008000
   Verifying Checksum … OK
   Loading Kernel Image … OK
OK

Starting kernel …

Uncompressing Linux…………………………………………………….
…………………………………………………………………….
done, booting the kernel.
Linux version 2.6.28-rc9-omap1 (cyz@TIOP) (gcc version 4.2.1 (CodeSourcery Sourc
ery G++ Lite 2007q3-51)) #1 Wed Feb 24 15:49:35 CST 2010
CPU: ARMv7 Processor [411fc083] revision 3 (ARMv7), cr=10c5387f
CPU: VIPT nonaliasing data cache, VIPT nonaliasing instruction cache
Machine: OMAP3 DevKit8000 Board
Memory policy: ECC disabled, Data cache writeback
OMAP3430 Unknown revision

SRAM: Mapped pa 0x40200000 to va 0xd7000000 size: 0x100000
Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 65024
Kernel command line: console=ttyS2,115200n8 ubi.mtd=4 root=ubi0:rootfs rootfstyp
e=ubifs video=omapfb:mode:4.3inch_LCD
Clocking rate (Crystal/DPLL/ARM core): 26.0/266/500 MHz
GPMC revision 5.0
IRQ: Found an INTC at 0xd8200000 (revision 4.0) with 96 interrupts
Total of 96 interrupts on 1 active controller
OMAP34xx GPIO hardware version 2.5
PID hash table entries: 1024 (order: 10, 4096 bytes)
OMAP clockevent source: GPTIMER12 at 32768 Hz
Console: colour dummy device 80×30
Dentry cache hash table entries: 32768 (order: 5, 131072 bytes)
Inode-cache hash table entries: 16384 (order: 4, 65536 bytes)
Memory: 128MB 128MB = 256MB total
Memory: 255104KB available (3980K code, 355K data, 156K init)
Calibrating delay loop… 507.32 BogoMIPS (lpj=1982464)
Mount-cache hash table entries: 512
CPU: Testing write buffer coherency: ok
net_namespace: 288 bytes
NET: Registered protocol family 16
Found NAND on CS0
Registering NAND on CS0
omap3evmdc: Driver registration complete
OMAP DMA hardware revision 4.0
USB: No board-specific platform config found
OMAP DSS rev 2.0
OMAP DISPC rev 3.0
OMAP VENC rev 2
i2c_omap i2c_omap.1: bus 1 rev3.12 at 2600 kHz
twl4030: PIH (irq 7) chaining IRQs 368..375
twl4030: power (irq 373) chaining IRQs 376..383
twl4030: gpio (irq 368) chaining IRQs 384..401
i2c_omap i2c_omap.2: bus 2 rev3.12 at 400 kHz
i2c_omap i2c_omap.3: bus 3 rev3.12 at 400 kHz
SCSI subsystem initialized
twl4030_usb twl4030_usb: Initialized TWL4030 USB module
usbcore: registered new interface driver usbfs
usbcore: registered new interface driver hub
usbcore: registered new device driver usb
musb_hdrc: version 6.0, musb-dma, otg (peripheral+host), debug=0
musb_hdrc: USB OTG mode controller at d80ab000 using DMA, IRQ 92
NET: Registered protocol family 2
IP route cache hash table entries: 2048 (order: 1, 8192 bytes)
TCP established hash table entries: 8192 (order: 4, 65536 bytes)
TCP bind hash table entries: 8192 (order: 3, 32768 bytes)
TCP: Hash tables configured (established 8192 bind 8192)
TCP reno registered
NET: Registered protocol family 1
NetWinder Floating Point Emulator V0.97 (double precision)
VFS: Disk quotas dquot_6.5.1
Dquot-cache hash table entries: 1024 (order 0, 4096 bytes)
JFFS2 version 2.2. (NAND) 漏 2001-2006 Red Hat, Inc.
msgmni has been set to 498
alg: No test for stdrng (krng)
io scheduler noop registered
io scheduler anticipatory registered (default)
io scheduler deadline registered
io scheduler cfq registered
Serial: 8250/16550 driver4 ports, IRQ sharing enabled
serial8250.0: ttyS0 at MMIO 0x4806a000 (irq = 72) is a ST16654
serial8250.0: ttyS1 at MMIO 0x4806c000 (irq = 73) is a ST16654
serial8250.0: ttyS2 at MMIO 0x49020000 (irq = 74) is a ST16654
console [ttyS2] enabled
brd: module loaded
loop: module loaded
PPP generic driver version 2.4.2
PPP Deflate Compression module registered
PPP BSD Compression module registered
PPP MPPE Compression module registered
NET: Registered protocol family 24
PPPoL2TP kernel driver, V1.0
dm9000 Ethernet Driver, V1.31
eth0: dm9000a at d08ae000,d08b2400 IRQ 185 MAC: 00:11:22:33:44:55 (chip)
Linux video capture interface: v2.00
tvp514x 2-005d: Registered to v4l2 master omap34xxcam!!
i2c /dev entries driver
Driver ‘sd’ needs updating – please use bus_type methods
omap2-nand driver initializing
NAND device: Manufacturer ID: 0x2c, Chip ID: 0xba (Micron NAND 256MiB 1,8V 16-bi
t)
cmdlinepart partition parsing not available
Creating 5 MTD partitions on “omap2-nand”:
0x00000000-0x00080000 : “X-Loader”
0x00080000-0x00260000 : “U-Boot”
0x00260000-0x00280000 : “U-Boot Env”
0x00280000-0x00680000 : “Kernel”
0x00680000-0x10000000 : “File System”
UBI: attaching mtd4 to ubi0
UBI: physical eraseblock size:   131072 bytes (128 KiB)
UBI: logical eraseblock size:    129024 bytes
UBI: smallest flash I/O unit:    2048
UBI: sub-page size:              512
UBI: VID header offset:          512 (aligned 512)
UBI: data offset:                2048
UBI: attached mtd4 to ubi0
UBI: MTD device name:            “File System”
UBI: MTD device size:            249 MiB
UBI: number of good PEBs:        1996
UBI: number of bad PEBs:         0
UBI: max. allowed volumes:       128
UBI: wear-leveling threshold:    4096
UBI: number of internal volumes: 1
UBI: number of user volumes:     1
UBI: available PEBs:             0
UBI: total number of reserved PEBs: 1996
UBI: number of PEBs reserved for bad PEB handling: 19
UBI: max/mean erase counter: 2/0
usbmon: debugfs is not available
ehci_hcd: USB 2.0 ‘Enhanced’ Host Controller (EHCI) Driver
ehci-omap ehci-omap.0: OMAP-EHCI Host Controller
UBI: background thread “ubi_bgt0d” started, PID 396
ehci-omap ehci-omap.0: new USB bus registered, assigned bus number 1
ehci-omap ehci-omap.0: irq 77, io mem 0x48064800
ehci-omap ehci-omap.0: USB 2.0 started, EHCI 1.00
usb usb1: configuration #1 chosen from 1 choice
hub 1-0:1.0: USB hub found
hub 1-0:1.0: 3 ports detected
Initializing USB Mass Storage driver…
usbcore: registered new interface driver usb-storage
USB Mass Storage support registered.
g_ether gadget: using random self ethernet address
g_ether gadget: using random host ethernet address
usb0: MAC 6a:01:8d:f5:2a:30
usb0: HOST MAC 12:a5:ad:b2:c8:67
g_ether gadget: Ethernet Gadget, version: Memorial Day 2008
g_ether gadget: g_ether ready
musb_hdrc musb_hdrc: MUSB HDRC host driver
musb_hdrc musb_hdrc: new USB bus registered, assigned bus number 2
usb usb2: configuration #1 chosen from 1 choice
hub 2-0:1.0: USB hub found
hub 2-0:1.0: 1 port detected
input: omap_twl4030keypad as /class/input/input0
input: gpio-keys as /class/input/input1
ads7846 spi2.0: touchscreen, irq 187
input: ADS784x Touchscreen as /class/input/input2
twl4030_rtc twl4030_rtc: rtc core: registered twl4030_rtc as rtc0
twl4030_rtc twl4030_rtc: Power up reset detected.
twl4030_rtc twl4030_rtc: Enabling TWL4030-RTC.
Registered led device: led1
Registered led device: led2
Registered led device: ledB
Registered led device: led3
usbcore: registered new interface driver usbhid
usbhid: v2.6:USB HID core driver
Advanced Linux Sound Architecture Driver Version 1.0.18rc3.
ASoC version 0.13.2
OMAP3 omap3devkit8000 SoC init
TWL4030 Audio Codec init
asoc: twl4030 <-> omap-mcbsp-dai-(link_id) mapping ok
ALSA device list:
  #0: omap3devkit8000 (twl4030)
TCP cubic registered
NET: Registered protocol family 17
NET: Registered protocol family 15
RPC: Registered udp transport module.
RPC: Registered tcp transport module.
Power Management for TI OMAP3.
VFP support v0.3: implementor 41 architecture 3 part 30 variant c rev 1
omapfb: using mode 4.3inch_LCD
Console: switching to colour frame buffer device 60×34
clock: clksel_round_rate_div: dpll4_m4_ck target_rate 28800000
clock: new_div = 15, new_rate = 28800000
tvp514x 2-005d: Write: retry … 0
tvp514x 2-005d: Write: retry … 1
tvp514x 2-005d: Write: retry … 2
tvp514x 2-005d: Write: retry … 3
tvp514x 2-005d: Write: retry … 4
tvp514x 2-005d: Write: retry … 5
tvp514x 2-005d: Write: retry … 0
tvp514x 2-005d: Write: retry … 1
tvp514x 2-005d: Write: retry … 2
tvp514x 2-005d: Write: retry … 3
tvp514x 2-005d: Write: retry … 4
tvp514x 2-005d: Write: retry … 5
tvp514x 2-005d: chip id mismatch msb:0x87 lsb:0x87
tvp514x 2-005d: Unable to detect decoder
tvp514x 2-005d: Write: retry … 0
tvp514x 2-005d: Write: retry … 1
tvp514x 2-005d: Write: retry … 2
tvp514x 2-005d: Write: retry … 3
tvp514x 2-005d: Write: retry … 4
tvp514x 2-005d: Write: retry … 5
tvp514x 2-005d: Write: retry … 0
tvp514x 2-005d: Write: retry … 1
tvp514x 2-005d: Write: retry … 2
tvp514x 2-005d: Write: retry … 3
tvp514x 2-005d: Write: retry … 4
tvp514x 2-005d: Write: retry … 5
tvp514x 2-005d: chip id mismatch msb:0x87 lsb:0x87
tvp514x 2-005d: Unable to detect decoder
tvp514x 2-005d: Write: retry … 0
tvp514x 2-005d: Write: retry … 1
tvp514x 2-005d: Write: retry … 2
tvp514x 2-005d: Write: retry … 3
tvp514x 2-005d: Write: retry … 4
tvp514x 2-005d: Write: retry … 5
tvp514x 2-005d: Write: retry … 0
tvp514x 2-005d: Write: retry … 1
tvp514x 2-005d: Write: retry … 2
tvp514x 2-005d: Write: retry … 3
tvp514x 2-005d: Write: retry … 4
tvp514x 2-005d: Write: retry … 5
tvp514x 2-005d: chip id mismatch msb:0x87 lsb:0x87
tvp514x 2-005d: Unable to detect decoder
tvp514x 2-005d: Write: retry … 0
tvp514x 2-005d: Write: retry … 1
tvp514x 2-005d: Write: retry … 2
tvp514x 2-005d: Write: retry … 3
tvp514x 2-005d: Write: retry … 4
tvp514x 2-005d: Write: retry … 5
tvp514x 2-005d: Write: retry … 0
tvp514x 2-005d: Write: retry … 1
tvp514x 2-005d: Write: retry … 2
tvp514x 2-005d: Write: retry … 3
tvp514x 2-005d: Write: retry … 4
tvp514x 2-005d: Write: retry … 5
tvp514x 2-005d: chip id mismatch msb:0x87 lsb:0x87
tvp514x 2-005d: Unable to detect decoder
Display already enabled
Display already enabled
Buffer Size = 3686400
omap_vout: registered and initialized                   video device 0 [v4l2]
Buffer Size = 3686400
omap_vout: registered and initialized                   video device 1 [v4l2]
display->updated
twl4030_rtc twl4030_rtc: setting system clock to 2000-01-01 00:00:01 UTC (946684
801)
UBIFS: recovery needed
UBIFS: recovery completed
UBIFS: mounted UBI device 0, volume 0, name “rootfs”
UBIFS: file system size:   103348224 bytes (100926 KiB, 98 MiB, 801 LEBs)
UBIFS: journal size:       9033728 bytes (8822 KiB, 8 MiB, 71 LEBs)
UBIFS: media format:       4 (latest is 4)
UBIFS: default compressor: LZO
UBIFS: reserved for root:  0 bytes (0 KiB)
VFS: Mounted root (ubifs filesystem).
Freeing init memory: 156K
INIT: version 2.86 booting
eth0: link down
Starting udevuncorrectable error : <3>end_request: I/O error, dev mtdblock0, sec
tor 0
Buffer I/O error on device mtdblock0, logical block 0
uncorrectable error : <3>end_request: I/O error, dev mtdblock0, sector 8
Buffer I/O error on device mtdblock0, logical block 1
uncorrectable error : <3>uncorrectable error : <3>end_request: I/O error, dev mt
dblock0, sector 16
Buffer I/O error on device mtdblock0, logical block 2
uncorrectable error : <3>end_request: I/O error, dev mtdblock0, sector 0
Buffer I/O error on device mtdblock0, logical block 0
eth0: link up, 100Mbps, full-duplex, lpa 0xFFFF
tar: removing leading ‘/’ from member names

Remounting root file system…
root: mount: mounting rootfs on / failed: No such file or directory
mknod: /dev/initctl: File exists
Setting up IP spoofing protection: rp_filter.
Configuring network interfaces… udhcpc (v1.11.3) started
Sending discover…
Sending select for 192.168.0.103…
Lease of 192.168.0.103 obtained, lease time 604800
adding dns 202.112.176.2
done.
/sbin/ldconfig: /lib/libts-0.0.so.0 is not a symbolic link

Tue Jan 27 09:49:00 UTC 2009
INIT: Entering runlevel: 5
Starting syslogd/klogd: done

.——-.
|       |                  .-.
|   |   |—–.—–.—–.| |   .—-..—–.—–.
|       |     | __  |  —‘| ‘–.|  .-‘|     |     |
|   |   |  |  |     |—  ||  –‘|  |  |  ‘  | | | |
‘—‘—‘–‘–‘–.  |—–”—-”–‘  ‘—–‘-‘-‘-‘
                -‘  |
                ‘—‘

The Angstrom Distribution DevKit8000 ttyS2

Angstrom 2008.1-test-20090127 DevKit8000 ttyS2

DevKit8000 login: root
root@DevKit8000:~#
root@DevKit8000:~#
root@DevKit8000:~#
root@DevKit8000:~# shutdown now

Broadcast message from root (ttyS2) (Tue Jan 27 11:36:31 2009):

The system is going down to maintenance mode NOW!
INIT: Switching to runlevel: 1
INIT: Sending processes the TERM signal
INIT: Stopping syslogd/klogd: stopped syslogd (pid 1376)
stopped klogd (pid 1378)
done
Deconfiguring network interfaces… done.
INIT: no more processes left in this runlevel

对配置有些疑问,需要核实…

花了1680RMB拿下DevKit8000

今天终于拿到TI OMAP3530的开发板了,天漠的DevKit8000,花了1680人民币。

下一步,先熟悉熟悉Linux定制方面的知识。有了板子,也终于可以边看边实践了!

然后嘛,想做的东西就太多了,什么视觉系统啊、行走机构啊、蓝牙通讯啦……,每项都是重大课题,里面一点点东西都是好多公司花好多money在搞的东西,个人搞这个,有时候真觉得不现实。

但是,人不都得有点追求是不是?有追求,还得有点实现追求的实际行动是不是?搞就搞了,想这么多干嘛   :)~~~~~~~~~

 

 

最后决定购买DevKit8000及全部配件

最后决定购买DevKit8000评估套件完全配置,1680RMB,它具有强大的图形加速功能,如果能把OpenCV移植上去,那就太完美了!

http://www.broadon.cn/item.htm?id=4064505743

升级版套件:256MB SDRAM + 256MB NAND FLASH

– 基于OMAP3530处理器,板载256MByte DDR SDRAM及256MByte NAND Flash
– 支持DVI-D/S-Video/TFT-LCD三种显示输出,可输出高清信号
– 外扩USB OTG,串口,网口,摄像头,音频,SD/MMC,键盘等接口
– 支持WinCE 6.0及Linux2.6.28系统,完全兼容beagleboard

硬件特性

CPU单元:

OMAP3530应用处理器(Pin to Pin兼容OMAP3503,OMAP3515,OMAP3525处理器)
600-MHz ARM Cortex-A8 Core
430MHz TMS320C64x+ DSP Core
256MByte DDR SDRAM,32bit
256MByte NAND Flash
6层板设计
通讯接口:

1个S-VIDEO接口
1个音频输入接口
1个双声道音频输出接口
1个10/100M以太网(芯片:DM9000,RJ45接口)
1个高速USB2.0 OTG接口(芯片:TPS65930),速度达480Mbps
2个串口(1个3线RS232电平串口,1个5线TTL电平串口)
1个SD/MMC接口
1个6*6键盘接口
1个14针标准JTAG接口
1个CAMERA接口(可外接CCD和CMOS的摄像头)
4个按键(1个启动引导按键,1个复位按键及2个用户按键)
扩展接口(包含McSPI,McBSP,I2C,HDQ及SD/MMC接口)
显示单元:

1个HDMI接口(芯片:TFP410),可输出分辨率1280×720,码率30fps的DVI-D高清信号
24bit真彩色LCD接口(含4线触摸屏接口,分辨率可支持2048*2048)
电气参数:

工作温度:-40 ~ 85℃(芯片支持)
环境湿度:20% ~ 90% ,非冷凝
机械尺寸:110 mm * 95 mm
电气指标:+5V电源供电,电流150mA

订购信息

DevKit8000评估套件完全配置装箱清单:
一个DevKit8000单板  
一个4.3寸触摸屏
一个512MB SD卡
一条交叉网线
一条Mini USB A线转USB A型母头
一条Mini USB B线转USB A型公头
一个USB HUB(带电源)
一个HMDI转DVI-D转接线
一条S-Video线
一个5V 2A电源
一支触摸笔
一张光盘(使用文档、原理图、源代码及工具)

产品自需方购买日起质保半年,核心元器件除外,液晶屏不参与质保。长期提供免费的电话和Email技术支持。

DevKit8000开发板全部配件(12件)

苹果i系列产品的操作系统:iOS

iOS是由蘋果公司為 iPhone 開發的操作系統。它主要是給 iPhone、iPod touch、iPad 以及 Apple TV 使用。就像其基於的 Mac OS X 操作系統一樣,它也是以 Darwin 為基礎的。原本這個系統名為 iPhone OS,直到 2010 年 6 月 7 日 WWDC 大會上宣布改名為 iOS。 iOS的系統架構分為四個層次:核心操作系統層(the Core OS layer),核心服務層(the Core Services layer),媒體層(the Media layer),可輕觸層(the Cocoa Touch layer)。系統操作佔用大概240MB的記憶體空間。

2011年2月2日,苹果已经发布了其 iOS4.3 beta3 预览版。

更详细的信息,请到Wiki上浏览:http://zh.wikipedia.org/zh/IOS