一、看原理图、看 说明手册
一个程序可能会遇到内存泄漏问题,可能一次运行泄漏几M大小,执行几个小时才会泄漏到站崩溃,所以要查看是否有内存泄漏。
所用的开发板
硬件程序开发流程
最小系统:单片机、晶振电路、电源电路、复位电路、内存 flush、
第一步:
1.看开发板丝印
丝印找对应原理图引脚
第二步:
在原理图底板和核心板找到对应引脚和GPIO口
第三步:
找到对应引脚
第四步:
读手册,一般引脚操作就先
二、运行流水灯的详细步骤
1、所用的芯片:S3C2440A
2、设置rom,还有栈
3、对keil4的设置
4、代码
流水灯代码,通过按键1控制 led1 。
流水灯while(1)循环时,会导致看门狗定时器超时,进而引发系统复位或重启。看门狗定时器的主要目的是在系统软件陷入死循环或挂起时提供一种恢复机制。
解决方法:
关闭看门狗定时器: *(volatile unsigned long*)0x53000000 &=0x11111110; 0是关闭
#define GPBCON (*(volatile unsigned long *)0x56000010UL)
#define GPBDAT (*(volatile unsigned long *)0x56000014UL)
#define GPGCON (*(volatile unsigned long *)0x56000060UL)
#define GPGDAT (*(volatile unsigned long *)0x56000064UL)void c_deal_swi(unsigned int num)
{switch(num){case 0:break;case 7:break;default:break;}
}void led_init(void)
{GPBCON |=(0x1<<10);GPBCON |=(0x1<<12);GPBCON |=(0x1<<14);GPBCON |=(0x1<<16);GPBDAT |=(0x1<<5);GPBDAT |=(0x1<<6);GPBDAT |=(0x1<<7);GPBDAT |=(0x1<<8);
}void led_on(void)
{GPBDAT &= ~(1<<5) ;}void led_off(void)
{GPBDAT |=(0x1<<5);}void liushui(void)
{ int i=0;led_init();while(1){GPBDAT &= ~(1<<5);for(i=0;i<99999;i++){;} GPBDAT |=(0x1<<5);GPBDAT &= ~(1<<6);for(i=0;i<99999;i++){;} GPBDAT |=(0x1<<6);GPBDAT &= ~(1<<7);for(i=0;i<99999;i++){;} GPBDAT |=(0x1<<7);GPBDAT &= ~(1<<8);for(i=0;i<99999;i++){;} GPBDAT |=(0x1<<8);}
}int key(void)
{if(GPGDAT&(0x1<<0))return 0;elsereturn 1;
}
int main(void)
{ *(volatile unsigned long*)0x53000000 &=0x11111110;GPGCON &= ~(0x3<<0);GPBCON |=(0x1<<10);GPBDAT |=(0x1<<5);while(1){if(key()){led_on();}else{led_off();}}return 0;}
#define GPGCON_KEY (*( volatile unsigned long *)0x56000060UL)
#define GPGDAT_KEY (*( volatile unsigned long *)0x56000064UL)
unsigned long:无符号是因为地址都为正数,long是因为32位操作系统long为4个字节,64位操作系统,long为8个字节,如果写int 32位64位都是4字节,不同操作系统地址存放也不一样,所以为unsigned long型
地址写入值,先强转为指针,再修改其值
UL:表示这个数是无符号长整型
volatile关键字
volatile
关键字是 C 和 C++(以及某些其他编程语言)中的一个重要修饰符,它用于告诉编译器该变量的值可能会在程序的控制之外被改变。因此,编译器在编译涉及 volatile
变量的代码时,会生成代码来确保每次访问该变量时都直接从其内存地址中读取它的值,而不是使用可能已经缓存在寄存器中的值。
使用场景
多线程编程:在多线程程序中,一个线程可能会修改另一个线程正在读取的变量的值。为了确保读取到的是最新的值,可以使用
volatile
关键字。但需要注意的是,volatile
并不保证操作的原子性,也不提供线程之间的同步机制。因此,在复杂的多线程场景中,通常需要配合其他同步机制(如互斥锁、信号量等)一起使用。硬件访问:在嵌入式系统或系统编程中,程序可能会直接访问硬件设备的寄存器。这些寄存器的值可能会由硬件自动更新,或者由中断服务例程修改。为了确保读取到的是硬件设备的最新状态,需要将这些寄存器映射的变量声明为
volatile
。中断服务例程:在中断服务例程(ISR)中,可能会修改全局变量的值,而这些变量在主程序中也可能被访问。为了防止编译器对这些变量进行不必要的优化(如缓存到寄存器中),应该将它们声明为
volatile
。
注意事项
- 慎用:
volatile
关键字的使用需要谨慎,因为它会禁用编译器的一些优化。如果滥用volatile
,可能会导致程序性能下降。- 不是万能的:虽然
volatile
可以确保变量值的实时性,但它并不提供原子性保证,也不解决多线程之间的同步问题。- 编译器实现:不同的编译器对
volatile
的处理可能有所不同,因此在使用时需要参考具体编译器的文档。