0%

2018年1月25日 下午9:37

先整体理解:

我觉得对arm编程就类似于一份这样的工作:

  1. 一个大的工厂,现在这个工厂已经实现了机器化生产,所有的机器就像我们电影中看到了一样它有一个总控,这个总控的操作形式就是一堆的开关、按键。当一个新的工人去这个工厂打工,他最终的目的是要学会如何操作那个总控,但是在这之前,他的绝大部分时间并不是去学习对应的开关是干什么的,因为即使有师傅告诉他这个开关是干啥的,他不一定能听懂这位师傅说的是什么,因为你对后面的这一大片的机器,以及各个机器之间的运作方式并不清楚,当让他做一个事情的时候,他必须分析出如何做到老板的要求。也就是说,其实这个人在开始阶段大部分时间的学习都放在了学习背后这些机器的原理上了
  2. 同样,在arm中我觉得写起程序的样子也是先找到对应的位置(地址),然后再判断这里是开或关或输入一个值(寄存器),我们学习arm的难点是取了解2440芯片的说明手册,以及芯片底盘原理图,这就是去了解整套机器本身的已经定死的运行原理,并不随你的操作不同而改变的内容,才是最最关键重要的内容

具体上来说有一些套路:

  1. 操作寄存器方式固定

    1. 就一步:赋值
    2. 连地址都给你封装到.h文件中了
    3. 简单的要死
  2. 清零,置位方法固定

    1. 一个原则:只操作我们需要改变的位,其他位我们不影响
    2. 结论:他俩并不是互逆的运算,而是各有各的功能,不被替代
    3. &一定用于清零 用1保护剩余位,清零位=0
    4. |一定用于置位 用0保护剩余位, 置位位=1
    5. 口诀:或的符号“|”,置位不就是1吗,其他的位置根据相反的关系记忆
      1
      2
      GPFCON &= ~((3<<8) | (3<<10) | (3<<12));#清零
      GPFCON |= ((1<<8) | (1<<10) | (1<<12));#置位
    6. &还有截取的能力
      1
      2
      tmp = ~val;
      tmp &= 7;
  3. 使用arm指令固定

    1. 在arm汇编中,指令会三个就行ldr str ldr(伪指令)
    2. 其他的cmp这些用的很少

两个问题:

C语言方便在哪里了?

  1. C语言有{},可以缩进写条件、循环,更加直观
  2. 不用记复杂指令,c会变量+条件+循环+函数+置位就可写各种程序

哪些是C语言无法方便的?

  1. 不管你使用哪种语言,查芯片手册是一定要做的,躲不了
  2. C语言带来的舒服可以理解成:他追求一种视觉上的舒服,分门别类的明显区分开来,一目了然,尤其针对代码比较多的项目,翻到哪页,我一看函数名就知道要干啥,我在接的看看条件和循环结构就知道他这个功能实现的大致步骤是个啥,这是汇编远远比不上的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include "s3c2440_soc.h"

void delay(volatile int d)
{
while (d--);
}

int main(void)
{
int val = 0; /* val: 0b000, 0b111 */
int tmp;

/* 设置GPFCON让GPF4/5/6配置为输出引脚 */
GPFCON &= ~((3<<8) | (3<<10) | (3<<12));
GPFCON |= ((1<<8) | (1<<10) | (1<<12));

/* 循环点亮 */
while (1)
{
tmp = ~val;
tmp &= 7;
GPFDAT &= ~(7<<4);
GPFDAT |= (tmp<<4);
delay(100000);
val++;
if (val == 8)
val =0;
}

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
.text
.global _start

_start:

/* 关闭看门狗 */
ldr r0, =0x53000000
ldr r1, =0
str r1, [r0]

/* 设置MPLL, FCLK : HCLK : PCLK = 400m : 100m : 50m */
/* LOCKTIME(0x4C000000) = 0xFFFFFFFF */
ldr r0, =0x4C000000
ldr r1, =0xFFFFFFFF
str r1, [r0]

/* CLKDIVN(0x4C000014) = 0X5, tFCLK:tHCLK:tPCLK = 1:4:8 */
ldr r0, =0x4C000014
ldr r1, =0x5
str r1, [r0]

/* 设置CPU工作于异步模式 */
mrc p15,0,r0,c1,c0,0
orr r0,r0,#0xc0000000 //R1_nF:OR:R1_iA
mcr p15,0,r0,c1,c0,0

/* 设置MPLLCON(0x4C000004) = (92<<12)|(1<<4)|(1<<0)
* m = MDIV+8 = 92+8=100
* p = PDIV+2 = 1+2 = 3
* s = SDIV = 1
* FCLK = 2*m*Fin/(p*2^s) = 2*100*12/(3*2^1)=400M
*/
ldr r0, =0x4C000004
ldr r1, =(92<<12)|(1<<4)|(1<<0)
str r1, [r0]

/* 一旦设置PLL, 就会锁定lock time直到PLL输出稳定
* 然后CPU工作于新的频率FCLK
*/



/* 设置内存: sp 栈 */
/* 分辨是nor/nand启动
* 写0到0地址, 再读出来
* 如果得到0, 表示0地址上的内容被修改了, 它对应ram, 这就是nand启动
* 否则就是nor启动
*/
mov r1, #0
ldr r0, [r1] /* 读出原来的值备份 */
str r1, [r1] /* 0->[0] */
ldr r2, [r1] /* r2=[0] */
cmp r1, r2 /* r1==r2? 如果相等表示是NAND启动 */
ldr sp, =0x40000000+4096 /* 先假设是nor启动 */
moveq sp, #4096 /* nand启动 */
streq r0, [r1] /* 恢复原来的值 */


bl main

halt:
b halt

注:这是第9课的代码

2018年1月23日 下午8:14

总结

  1. 以问题的形式说明知识点
  2. 一个关于指针的口诀
  3. 理解数组名

一:以问题的形式说明知识点

前提:

Int a=1;
TYPE *pa=&a
假设a的地址是:0x12345678

第一个问题 :where

1. **指针变量存放在哪里?**
    1. 存放在内存中
2. **存放在内存中哪里?**
    1. 存放在&pa处
3. **为啥放在那里?**
    1. 编译时就决定了地址位置(这个结论来源于arm,我没有验证)

第二个问题:how 存

1. **如何存放别人的地址值?**
2. 小端方式存放别人的地址值(eg地址:0x12345678)

第三个问题:how 取

1. **如何取对应地址的处的值?**
2. 根据”步长“,也就是sizeof TYPE 的结果

二:一个关于指针的口诀

两变,两不变

两变:
1. 指向的内存地址
2. 每次+1走的步长
两不变:
1. 在32位linux系统中,指针本身占内存空间4个字节
1. 64位系统中,指针占8个字节
2. 指针指向的是被指向对象的起始地址,被指向对象多长不管

三:理解数组名(说的太好了)

c语言中数组名和指针变量的区别 - 立体风 - 博客园

附录:
老师的笔记:

2018年1月23日 下午7:24

目的:

这篇文章的目的:是为了说明使用gcc的意义

hello.c(包含三处错误,分别对应图1中1~3)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>

#define MAX 20
#define MIN 10

#define _DEBUG
#define SetBit(x) (1<<x)

int mian(int argc, char* argv[])#3.这里mian不对
{
print("Hello world \n);#1.这里少引号
print("MAX = %d, MIN = %d, MAX + MIN = %d\n",MAX, MIN, MAX+MIN);#2.print应该是printf

#ifdef _DEBUG
print("SetBit(5) = %d, SetBit(6) = %d\n",SetBit(5),SetBit(6));
print("SetBit( SetBit(2) ) = %d\n",SetBit( SetBit(2) ));
#endif
return 0;
}

在ubuntu下hello.c的整体编译过程:


::图1::

总结:

  1. 这里的错误可以看出分别产生自预处理,编译,链接时,这就体现了gcc比我们一体化的IDE的优势,IDE总是一股脑的全部给你报错,不分阶段。
  2. 如我做一下工作,gcc会帮你解决
    1. 如何看到,如何工作?从预处理中.i文件最后就可以看出(E)
    2. 如何看到我们汇编代码?从编译后的.s文件就可以看出(S)
    3. 库文件函数,何时与自己的代码融合?从连接中就可看出
  3. 为此,我们要清楚的知道.c .i .s .o 文件内存的是啥?关于这个问题,可以看附录中的具体代码。

附录:

文件源码:
hello.chello.ihello.s
hello.o
hello

老师的笔记:
gcc常用编译选项.txt
ubuntu操作代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
book@www.100ask.org:/$ cd /work
book@www.100ask.org:/work$ ls
100ask hardware lost+found tools
book@www.100ask.org:/work$ mkdir gcc_option
book@www.100ask.org:/work$ ls
100ask gcc_option hardware lost+found tools
book@www.100ask.org:/work$ ls
100ask gcc_option hardware lost+found tools
book@www.100ask.org:/work$ cd gcc_option/
book@www.100ask.org:/work/gcc_option$ ls
hello.c
book@www.100ask.org:/work/gcc_option$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/5/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 5.4.0-6ubuntu1~16.04.4' --with-bugurl=file:///usr/share/doc/gcc-5/README.Bugs --enable-languages=c,ada,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-5 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-5-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-5-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-5-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.4)
book@www.100ask.org:/work/gcc_option$ gcc -V
gcc: error: unrecognized command line option ‘-V’
gcc: fatal error: no input files
compilation terminated.
book@www.100ask.org:/work/gcc_option$ gcc -E -o hello.i hello.c
hello.c:11:8: warning: missing terminating " character
print("Hello world \n);
^
book@www.100ask.org:/work/gcc_option$ gcc -E -o hello.i hello.c
book@www.100ask.org:/work/gcc_option$ ls
hello.c hello.i
book@www.100ask.org:/work/gcc_option$ gcc -S -o hello.s hello.i
hello.c: In function ‘mian’:
hello.c:11:2: warning: implicit declaration of function ‘print’ [-Wimplicit-function-declaration]
print("Hello world \n");
^
book@www.100ask.org:/work/gcc_option$ gcc -E -o hello.i hello.c
book@www.100ask.org:/work/gcc_option$ ls
hello.c hello.i hello.s
book@www.100ask.org:/work/gcc_option$ rm * -rf
book@www.100ask.org:/work/gcc_option$ ls
book@www.100ask.org:/work/gcc_option$ gcc -E -o hello.i hello.c
book@www.100ask.org:/work/gcc_option$ ls
hello.c hello.i
book@www.100ask.org:/work/gcc_option$ gcc -S -o hello.s hello.i
book@www.100ask.org:/work/gcc_option$ ls
hello.c hello.i hello.s
book@www.100ask.org:/work/gcc_option$ gcc -c -o hello.o hello.s
book@www.100ask.org:/work/gcc_option$ ls
hello.c hello.i hello.o hello.s
book@www.100ask.org:/work/gcc_option$ gcc -o hello hello.o
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: error: ld returned 1 exit status
book@www.100ask.org:/work/gcc_option$ ls
hello.c hello.i hello.o hello.s
book@www.100ask.org:/work/gcc_option$ ^C
book@www.100ask.org:/work/gcc_option$ rm * -rf
book@www.100ask.org:/work/gcc_option$ ls
book@www.100ask.org:/work/gcc_option$ gcc -E -o hello.i hello.c
book@www.100ask.org:/work/gcc_option$ gcc -S -o hello.s hello.i
book@www.100ask.org:/work/gcc_option$ gcc -c -o hello.o hello.s
book@www.100ask.org:/work/gcc_option$ gcc -o hello hello.o
book@www.100ask.org:/work/gcc_option$ ls
hello hello.c hello.i hello.o hello.s
book@www.100ask.org:/work/gcc_option$ ./hello
Hello world
MAX = 20, MIN = 10, MAX + MIN = 30
SetBit(5) = 32, SetBit(6) = 64
SetBit( SetBit(2) ) = 16

2018年1月22日 下午5:44

说在前面的:

  1. 先重启一次试试,我又一次就是这样弄好的!!
  2. 我使用的是arm-pc直连的方式:arm直接连接在pc的有限网卡,中间没路由器

环境(硬件准备):

  1. ubuntu是vmware
  2. Arm是TQ2440,用的是自带的uboot,我不知道这个uboot是否“使能网卡”
  3. pc通过无线网卡连接路由器
    1. pc无线网卡ip:192.168.0.107
  4. pc通过有线网卡连接arm,通过一条网线
    1. pc有线网卡的ip:192.168.1.17

环境(软件设置)

  1. 关闭pc防火墙,关闭ubuntu虚拟机防火墙
  2. ubuntu“设置”中,仅仅选中当前pc的有线网卡作为桥接器(此时无法上网,pc可以上网)
  3. 指令设置arm
    1
    2
    3
    set ipaddr 192.168.1.7
    set serverip 192.168.1.17
    save
  4. 指令设置ubuntu
    1
    sudo ifconfig ens33 192.168.1.117
  5. 不同网卡的ip一定要初一不同的网段
    1. pc有线网卡,ubuntu,arm的ip都是192.168.1.xxx网段,必须与pc无线网卡网段192.168.0.xxx不同

注意:如果此时拔出arm的连接网线,此时pc ping ubuntu是不通的。因为此时有线网卡,没有被arm激活,无线网卡无法处理ping指令,死过去了,怎么能给你干活呢。
方法:重设ubuntu”设置“为无线网卡桥接+修改ubuntu网段为192.168.0.xxx

最关键要素的提取:

  1. pc用哪个网卡(有线网卡/无线网卡)连接到arm,那么ubuntu就设置哪个网卡作为桥接网卡,仅仅选择这一项,其他的不选
  2. pc的两个网卡不能使用同一网段。一个门牌号怎么能上在两家!
  3. 使能的arm uboot(这一点有待考证)
  4. 关闭防火墙

2018年1月22日 下午3:43

基础知识:

一个地址指的的一个字节(1TYPE,8bit位)

总结:

  1. 我本来是想把自己的知识点总结出来,但是发现我根本脱离不了这份笔记,很多内容来源于其中,我所幸最后就直接写在这份pdf上面了
  2. 最后,我在补充一点我的一点点想法。
    1. 我老早就听说一句话:你要是知道高级语言是怎样翻译成汇编,汇编翻译成机器码,机器码给cpu去执行的执行过程,这就很牛逼了。
    2. pdf中记录了一个简单程序从c、汇编、机器码的过程,当你了解了这个过程之后,能够通过修改机器码去改变程序的功能,能够知道c翻译成机器码结果,以及放入到RAM中的cpu具体一条指令的执行过程。我觉得还会产生新的疑问:编译器如何将c编译成汇编,这个过程有他自己的准则PCS(Procedure Call Standard for Arm architecture)。我觉得这个过程和我们机器学习中涉及到的翻译中文等功能,他们之间又有啥相似的地方?


这幅图是整份pdf核心,表示的是程序在4KRAM(咱们认识的内存)中如何保存的
韦东山第八课.pdf

2018年1月20日 上午10:04

总结:

  1. 如何提问题?
  2. 明确针对的情景,能够解决的问题

Java异步技术原理和实践.pdf

这是我在小象学院看到的一个视频,简单的介绍了:从系统层I/O去解决复杂多层系统中,如果底层系统出现异常,导致上层调用系统也崩溃,导致雪崩效应

注意:这里不是解决负载问题的,这也提醒我学习是首先要注意它针对的解决的问题,然后在他讲的时候所提出的问题的出发点是:假设你现在就要开发一个这样的系统的角度,然后在结合讲师所讲的内容,看看你假设建立系统的同时,讲师的内容能否解决你的问题,如何没有,那么这就是我们要提出的新的问题?

2018年1月18日 下午5:59

第二次总结

  1. 现在我已近熟练的使用这些指令,返回头来看以前的总结,在下面”我的思考“中想的一些问题,在实际使用中其实一次没有想过,但是我觉得他对于我一开始学习vi来说还有有意义的,最大的好处就是:vi也不是有多神奇么,我可以理解创造vi的人的创造思路,万事开头难,现在我觉得vi的确很简单,区区十几个指令而已。

我的思考

  1. 还是保持着一个原则:从实际中出发的原则
    1. 对于下面的内容不要这样的去背诵,而是要先去问问自己“自己希望vi有啥功能,自己觉得舒服”
  2. 希望的功能有:
    1. 到文章开头,结尾
    2. 在处理一句话中,也可以方便的越:调到开头,结尾,某个字符
    3. 按行删除,而不是必须一个字符一个字符的删除
    4. 甚至,多行删除
    5. 删错了,可以返回
    6. 复制和删除一样,关键是给他们提供批量的感觉
    7. 其他:查找,替换:可能就会问:如何调到下一个,如何全局搜索,如何让他询问确定?
  3. 这样理解自己就会舒服很多,然后练起来也比较有意思
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    vi编辑器有三种模式
    1)一般模式(光标移动、复制、粘贴、删除、撤销)
    hjkl、ngg/G、0、$、fx
    yy/nyy
    p
    dd/ndd、x
    u
    2)编辑模式(编辑文本)
    i a o
    3)命令行模式(查找和替换、保存退出文件)
    /pattern、:%s/p1/p2/gc、:wq

配置:这点我原来不知道

vi编辑器的配置

  1. cd _etc_vim
  2. cp vimrc ~/.vimrc
  3. cd ~
  4. gedit .vimrc
  5. 在.vimrc中加入如下内容:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    "关闭兼容功能
    set nocompatible
    "显示行号
    set number
    "编辑时 backspace 键设置为2个空格
    set backspace=2
    "编辑时 tab 键设置为4个空格
    set tabstop=4
    "设置自动对齐为4个空格
    set shiftwidth=4
    "搜索时不区分大小写
    set ignorecase
    "搜索时高亮显示
    set hlsearch

vi常用命令汇总.docx
vi编辑器的使用.txt

2018年1月18日 下午5:46

总结:

  1. 我的态度是尽量的少记,所以一种命令记两个内容
    1. 一共有几项:find grep 四项 gzip/bzip2 三项
    2. 每项的内容在从实际中猜测:
      1. find 需要“去哪找” “找哪个”
      2. grep 需要 “去哪找”“找哪个”
      3. “找哪个”都要“”号包裹
  2. [选项]一般来说都是固定了,就一种/两种
    1. tar除外

find:记2目录地址 4“文件名”

find _work/001_linux_basic_dira/ -name “test1.txt”

grep:记3“字符串”4 文件名

grep -rn “字符串” 文件名

  1. r(recursive):递归查找
  2. n(number):显示目标位置的行号
  3. 字符串:要查找的字符串
  4. 文件名:要查找的目标文件,如果是*则表示查找当前目录下的所有文件和目录

gzip/bzip2:只记文件名

gzip的常用选项
-l(list) 列出压缩文件的内容
-k(keep) 在压缩或解压时,保留输入文件。
-d(decompress) 将压缩文件进行解压缩

tar常用选项:一、二部分选一个,三部分全要 ,四自愿

第一部分:

-c(create) 表示创建用来生成文件包
-x:表示提取,从文件包中提取文件

第二部分:

-t可以查看压缩的文件。
-z使用gzip方式进行处理,它与”c“结合就表示压缩,与”x“结合就表示解压缩。
-j使用bzip2方式进行处理,它与”c“结合就表示压缩,与”x“结合就表示解压缩。

第三部分

-v(verbose)详细报告tar处理的信息
-f(file)表示文件,后面接着一个tar.gz/tar.zb2结尾的文件名。

第四部分

-C <指定目录> 解压到指定目录

which和whereis

目的:查找命令或应用程序的所在位置
格式:which 命令名/应用程序名

linux进阶命令1.txt
linux进阶命令2.txt

2018年1月18日 下午5:19

从思维上说:

有一些思维的上的不足:

  1. 没有“跳跃”的思想。总想着文件夹得一步步的走,不能直接过去,这就是使用gui时间长了,就思维定式了
  2. 没有“选项”的观念。我们在使用gui时,也不会取管细节的显示,一般都是看这个文件有没有就完了
  3. 没有“偷懒”的思想。总是习惯着自己去打每一个字符,而忽略的tab
  4. 总的来说:就是没有一种思维,说是让自己更加舒服,比如说cat -n呀啥的选项,你意识不到用它

小总结:

  1. 除了pwd以外的所有linux命令,都可以隔空操作
  2. 保持两个习惯:
    1. 少用cd 多用隔空操作
    2. 少敲,多用tab
  3. 两个注意:
    1. mv 可以给文件/目录改名字
    2. rm -i 一定要加上-i
  4. 一个小口诀:两个创建touch mkdir 一个删除rm(rmdir 不能删除非空文件夹,直接忽略这个命令)
  5. -r 选项两个命令:cp rm 其他的不用
  6. 新建文件夹的能力:mkdir cp (mv不能有新建文件夹的能力,只能改名字,要不功能就重复了)

韦东山笔记

linux入门命令讲解1.txt