2011年10月4日星期二
Arduino LCD programming
2011年9月12日星期一
Be the change you want to see!
2011年8月10日星期三
AMCC 1.0 release
AMCC github
/*
* AMCC (Anders Ma Copter Control)
*/
General Information
===================
AMCC is an utility for copter development.
With AMCC you can monitor copter's sensors data, you can use sensors data
to develop flight control algorithm. In the future, you can use AMCC to
config and operate copter.
Licensing
=========
AMCC is released under BSD license.
Requirements
============
To compile AMCC, you must install following packages:
* libgtk2.0-dev
* libgtkglext1-dev
* freeglut3-dev
* lib3ds-dev
* libxml2-dev
HOW-TO
============
To use AMCC to monitor/control copter, copter must support AMCC protocol, How?
1) Copter MCU software must contain following code and linked with src/packet.c:
#include "packet.h"
char buffer[50];
packet_t p;
p.type = ANALOG_DATA_RESPONSE;
p.raw.analog_data.channel_number = 6;
p.raw.analog_data.value[0] = accx; /* accelerometer X axes data got from ADC */
p.raw.analog_data.value[1] = accy; /* accelerometer Y axes data got from ADC */
p.raw.analog_data.value[2] = accz; /* accelerometer Z axes data got from ADC */
p.raw.analog_data.value[3] = gyrox; /* gyroscope X axes data got from ADC */
p.raw.analog_data.value[4] = gyroy; /* gyroscope Y axes data got from ADC */
p.raw.analog_data.value[5] = gyroz; /* gyroscope Z axes data got from ADC */
packet_encode(&p);
memcpy(buffer, &p.data, p.data_length);
txd_buffer[p.data_length] = 0;
printf("%s", buffer); /* output data over serial port */
2)connecting PC with copter as below:
[PC] ---serial line----- [Copter]
3) #./amcc -d /dev/SERIALDEV
(replace SERIALDEV and SPEED according your environment, default is ttyUSB0, 57600)
4) Click menuitem "Monitor->Start", if copter is sending sensors data, AMCC will draw Acc & Gyro voltage graph and render 3D copter.
2011年8月6日星期六
日记 2009 07~09
8/22/2009
深圳市龙岗区布吉荣超花园xx栋x单元xxx,胡先生,13392xxxxxx
8/25/2009~8/26/2009
1. 拿回来了板子,在家做测试
2. 目前串口可以烧写程序了,之前烧写不成功主要是速度过快的问题,设置低速比较好
3. 烧写程序应该使用hex的格式,bin的烧进去不能执行
8/26/2009
1. 晚上花了2个小时对加速度传感器模块进行实验,得出如下结论
a. SLEEP PIN 需要拉高(3.3V),才能使加速度传感器进入工作模式
b. Z轴长期处于+-g的输出电压模式,其他轴如果水平状态下呈0g电压状态
备注:中途实验不成功,我打算明天焊接实验班再做实验,不过时间足够,我逼迫自己继续下去,我又一次战胜自己的懒惰!
8/27/2009
1. 白天在公司写了ADC数据处理程序,带串口和LCD数据输出
2. 晚上回来对程序进行验证,串口和LCD都正常,靠,有点佩服自己了,哈~
3. 接好ADC线,发现数据正常,ADC用[0~4096]来诠释[0~3.3v]电压,目前我的XYZ轴数据分别为
3. 晚上回来调试程序,目前可以用MK的程序来显示我ADC的变化了,哈哈啊哈~
8/28/2009
1.开始重头学习高等数学
2. 尝试使用SD卡程序,结果不能读,看来是SD卡读那块有问题,需要继续解决。
5/9/2009
1 飞控算法电机调整口诀: 左+右-;前+后- (+-pd_result)
1 为什么MK中计算陀螺仪的积分就变成了单纯的ADC差值?
2011年7月29日星期五
2011年7月17日星期日
Linux 0.11 内核完全注释 笔记(三)
>半斤回答:准备LDT,TSS,页目录,页表...
在Linux内核中,一个进程是用struct task_struct类型的变量来标记。所以fork首先是创建了一个新的struct task_struct类型的变量,对其进行相应的赋值。
重要的是,新建进程的TSS,LDT表,页目录和页表是全新创建的,在存储上和父进程完全没有关系,不同的两个实体。但新进程LDT所指向的数据段和代码段完全照抄父亲进程,指令指针也同父进程一致。也就是说,父子进程共享代码段,数据段和堆栈段都是相同的地址空间。好比两个锦囊装着同一妙计,嘿嘿!
插一句:从这里看fork的两次返回是那么的自然,两个进程指令指针(EIP)都一样,能没有两个返回吗?
更重要的事,fork过程中将父子进程所有页表都设置成了Read Only, 为啥子啊? 为了实现Copy On Write技术。由于页表项设置成了只读模式,每次写页表项所对应的页面时(比如函数调用把参数放入堆栈)都会引起写保护页异常,CPU会自动执行异常处理函数,进而调用 do_wp_page 函数来分配一个新的页面,挂载到引起写异常的页表项目,之后设置页表项可读可写。这个技术就叫Copy On Write。Copy On Write 完全是一种按需分配的技术,缺页/写保护页面异常是伟大的设计,因为它缔造了Copy On Write,缔造了虚拟内存技术!
这里还有一个问题值得思考,假设fork之后的程序马上会对数据段进行写动作,进而导致CPU进入写保护页面异常处理程序,谁的页表项会指向新分配的空间呢?父 or 子?
答案取决于谁先引起写保护页面异常。假设儿子引起了异常,那么儿子的页表项会指向新的分配空间;假设是父亲引起了异常,父亲的页表项会指向新空间,这样之前父亲占用的空间就归儿子所有了。很有趣的逻辑啊!
代码参考:
sys_fork -> copy_process
http://oldlinux.org/lxr/http/source/kernel/fork.c#L68
un_wp_page
http://oldlinux.org/lxr/http/source/mm/memory.c#L221
2011年7月16日星期六
Linux 0.11 内核完全注释 笔记(二)
进程管理
1 进程如何切换?
半斤回答:JMP 到预切换到任务的 TSS
2 fork 做什么?
半斤回答:准备LDT,TSS,页目录,页表...
3 exec 做什么?
4 进程调度算法?
内存管理
5 系统的发动机,缺页异常具体实现?
半斤回答:就是从SWAP/FS往内存放数据
设备管理
6 磁盘请求队列算法?
半斤回答:电梯算法,插入使链表排序。
7 键盘驱动?
8 显示器如何折腾?
文件系统
9 fd管理与pipe通信?
10 知识盲区啊,提不出什么好问题了?!
2011年7月13日星期三
Linux 0.11 内核完全注释 笔记(一)
五年后,再读此书,感触颇多,当读到move_to_user_mode这个神器时不由自主在weibo上像文人骚客一样发出如下感叹:
”一生至少该有一次,为了某段代码而陶醉自己,不求年代,不求国籍,不求编程语言,甚至不求编译运行,只求在我思索的年华里,遇到你。“
http://oldlinux.org/lxr/http/source/include/asm/system.h#L1
言归正传,笔记开始!
写操作系统不读CPU手册和上厕所不带纸是一个概念,不是扯淡就是高手!所以此书上来先介绍了X86保护模式编程的东东,只有弄清楚这些东东,才能9浅1深的去理解Kernel。X86的保护模式编程个人感觉还是挺复杂的,毕竟要游走于N多概念之间。
Q1 逻辑地址如何转换到物理地址?
Logical Address (逻辑地址)
Linear Address (线性地址)
Physical Address (物理地址)
这些是地址,我们的程序编译完的地址可以粗略理解成逻辑地址,在开启保护模式的情况下,CPU在指令运算时,都需要把程序的逻辑地址转换到真实的物理地址上。怎么转换?靠查表!怎么查?要查表首先要知道表在哪里,然后要知道表的Index,进而得到表项,得到表项后再分析就可以得到真实的物理地址。顺藤摸瓜也!Intel的X86 CPU已经把藤和瓜所需的数据结构都准备好了。
Local Descriptor Table (局部描述符表)LDT
Gloal Descriptor Table (全局描述符表)GDT
Local Descriptor Table Register (局部描述符表寄存器)LDTR
Gloal Descriptor Table Register (全局描述符表寄存器)GDTR
LDT/GDT是表,表的线性地址放在了LDTR/GDTR寄存器中,这是“藤1”。
Code Segment Selector (代码断选择符) CS
Data Segment Selector (数据段选择符) DS
Stack Segment Selector (堆栈段选择符) SS
{C|D|S}S这些是段选择符,Bit2标识使用GDT or IDT,bit3~15是Index信息,这是“藤2”。
Code Segment Descriptor (代码段描述符)
Data Segment Descriptor (数据段描述符)
System Segment Descriptor (系统段描述符)
系统断描述符又可分为:
1 LDT段描述符
2 TSS(Task State Segment)描述符
3 中断门描述符
4 调用门描述符
5 任务门描述符
6 陷阱门描述符
LDT/GDT中的表项就是这些{断|门}描述符,每个描述符都占用8个Byte空间,这是“藤3”。
所以CPU在逻辑地址转换到物理地址过程中,顺着藤1,藤2,找到了藤3。
找到藤3之后,CPU解剖了藤3,挖出了段基地址,然后与逻辑地址相加,这样就得出线性地址。
在没有开启分页机制情况下,线性地址就是真实的物理地址。如果已经开启分页,那就要再顺着“藤4”去摸。CR3寄存器存放着当前任务使用页目录的物理地址。这是"藤4“。经过分析后直接找到物理地址,顺藤摸瓜结束。
Intel还算厚道,没来个18摸,最多也就是Inception的3重梦境。累了,以后再写!
2011年6月16日星期四
LFS 纪念
目前LFS Linux进入Shell大概需要20s,速度有些慢,主要时间是花在从U盘拷贝 kernel到RAM。后续还需要多多折腾。
我所使用的是LFS 6.8 http://www.linuxfromscratch.org/lfs/downloads/stable/LFS-BOOK-6.8-HTML.tar.bz2 只要从头到尾做,基本可以确定会顺利启动属于你自己的Linux。期间唯一遇到的问题是Kernel无法挂载ROOT文件系统,主要是没包含NVidia的SATA驱动,去Menuconig打*瞬间解决。出于对GRUB的恐惧,没有在机器大硬盘折腾GRUB,只在grub.cfg加个选项,用原有硬盘GRUB启动我的LFS Linux。
为了制作U盘版本,首先fdisk new a primary partition which is bootable,然后将GRUB放到U盘中。大致命令如下:
#
#sudo mount /dev/sdb1 /mnt
#sudo grub-install --root-directory=/mnt /dev/sdb
#sudo grub
grub>find /boot/grub/stage1
(hd1, 0)
grub>root (hd1)
grub>setup (hd1)
#
而后干了一个比较SB的事情,去Windows下玩了这个U盘,U盘还有另一个无用分区,我在Windows下点选删除此分区,结果整个U盘的分区都被删除了,U盘变成砖头!我晕!!!!!
无奈去Linux下重新fdisk建立分区,还好我之前fdisk建立分区的尺寸是+2G,我这次也用同一参数,找回了之前的分区,数据索性还在。只是我不得不承认我很贱,为何去Windows里面折腾带有Ext3的U盘!
Windows在分区这块太过傲慢,插个自己不认识的U盘,就问你是否需要格式化,一副当带头大哥的嘴脸!Windows何时能放下傲慢?拥抱非FAT/NTFS分区?
2011年6月2日星期四
partition algorithm
int partition(int array[], int start, int end)
{
int i, j, tmp;
int key = array[start];
i = start;
for (j = start + 1; j <= end; ++j) {
if (array[j] <= key && ++i != j) {
// array[j] <=> array[i]
tmp = array[j];
array[j] = array[i];
array[i] = tmp;
}
}
array[start] = array[i];
array[i] = key;
return i;
}
void printf_array(int array[], int from, int len)
{
int i;
for (i = 0; i < len; ++i)
printf("%d,", array[from + i]);
printf("\n");
}
int main(int argc, char** argv)
{
int array[10] = {3, 7, 21, 6, 2, -3, 90, 23443, -3000, 5};
printf("partition=%d\n", partition(array, 0, 9));
printf_array(array, 0, 10);
return 0;
}
2011年5月15日星期日
config.guess - guess the build system triplet
config.guess - guess the build system triplet
SYNOPSIS
config.guess [OPTION]
DESCRIPTION
The GNU build system distinguishes three types of machines,
the 'build' machine on which the compilers are
run, the 'host' machine on which the package being built will
run, and, exclusively when you build a compiler,
assembler etc., the 'target' machine, for which the compiler
being built will produce code.
This script will guess the type of the 'build' machine.
Output the configuration name of the system 'config.guess' is run on.
Operation modes:
-h, --help
print this help, then exit
-t, --time-stamp
print date of last modification, then exit
-v, --version
print version number, then exit
ENVIRONMENT VARIABLES
config.guess might need to compile and run C code, hence it
needs a compiler for the 'build' machine: use the
environment variable 'CC_FOR_BUILD' to specify the compiler for
the build machine. If 'CC_FOR_BUILD' is not
specified, 'CC' will be used. Be sure to specify
'CC_FOR_BUILD' is 'CC' is a cross-compiler to the 'host'
machine.
CC_FOR_BUILD a native C compiler, defaults to 'cc'
CC a native C compiler, the previous variable is preferred
REPORTING BUGS
Report bugs and patches to <config-patches AT gnu.org>.
Originally written by Per Bothner. Copyright (C) 1992, 1993,
1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
Free Software Foundation, Inc.
This is free software; see the source for copying
conditions. There is NO warranty; not even for MER-
CHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
SEE ALSO
autoconf(1), automake(1), autoreconf(1), autoupdate(1),
autoheader(1), autoscan(1), config.guess(1), con-
fig.sub(1), ifnames(1), libtool(1).
config.guess (2003-10-03) October 2003
CONFIG.GUESS(1)
2011年4月19日星期二
A algorithm to enumerate all the combinations of given numbers
A algorithm to enumerate all the combinations of given numbers
Author : Anders Ma [2011_0419]
*/
#include
int array[100];
int cursor = 0;
void enumerate(int n)
{
int i;
for(i = 0; i < cursor; ++i)
printf("%d,", array[i]);
if (cursor != 0)
printf("\n");
for (i = 0; i < n; ++i) {
array[cursor++] = i + 1;
enumerate(i);
cursor--;
}
}
int
main(int argc, char **argv)
{
enumerate(5);
return 0;
}
anders@ubuntu:~/c$ ./enum
1,
2,
2,1,
3,
3,1,
3,2,
3,2,1,
4,
4,1,
4,2,
4,2,1,
4,3,
4,3,1,
4,3,2,
4,3,2,1,
5,
5,1,
5,2,
5,2,1,
5,3,
5,3,1,
5,3,2,
5,3,2,1,
5,4,
5,4,1,
5,4,2,
5,4,2,1,
5,4,3,
5,4,3,1,
5,4,3,2,
5,4,3,2,1,