atmel Studio 6.1环境下的bootloader
Atmel Studio 6 微控制器开发环境介绍说明书
Atmel® Studio 6 is the integrated development environment (IDE) for developing and debugging embedded applications based on Atmel AVR® and ARM® Cortex™-M microcontrollers (MCUs) in C/C++ and assembly code. The IDE makes editing and debugging source code easier by seamlessly bringing together an intelligent editor with assisted code writing, a wizard for quickly creating new projects, the Atmel Software Framework with free source code library, a GNU C/C++ Compiler, a powerful simulator, and the front-end for all Atmel programmers and in-circuit debuggers.Atmel Studio 6 is free of charge and available for download at /atmelstudio.What’s New in Atmel Studio 6• Support for Atmel ARM Cortex-M based MCUs• Fully integrated Atmel QTouch® Composer• Full support for C++Your Avenue to Atmel AVR and ARM Cortex-M Based MCU DesignDesigners using AVR MCUs are already familiar with our IDE, previously known as AVR Studio® 5. Now, the communityof ARM Cortex-M design engineers can take advantage of the same easy-to-use, professional and highly integrated development platform.Integrated QTouch ComposerFully integrated into Atmel Studio 6, Atmel QTouch Composermakes it easy to build touch functionality into your design.QTouch Composer is the front-end software used to displayand evaluate the data reported from your touch design,making it easy for you to inspect how well your touchimplementation performs. With this integration, you can easilyand seamlessly develop capacitive touch functionality into yourapplication. You won’t need to toggle between different toolsto edit the code in Atmel Studio 6 and fine-tune your touchdesign in QTouch Composer.Atmel Software FrameworkThe Atmel Software Framework contains drivers for all peripherals,communication stacks, graphics, digital signal processing (DSP) and audiolibraries, and nearly 1,000 complete example designs. Using free source codefrom the Atmel Software Framework will accelerate the development of newapplications, while lowering your overall costs.Debugging Made EasyAtmel Studio 6 connects directly to Atmel debuggers and programmers. One of thebiggest advantages of modern MCUs is their ability to send debug data to your PC, givingyou a perfect view of what goes on inside. With a debugger connected, Atmel Studio 6can present the status of all processors, memories, communication interfaces and analoginterfaces in nicely formatted views, giving you access to critical system parameters. Theresimply is no faster way to identify bugs and optimize a design—in the lab or in the field.To learn more or download Atmel Studio 6 free of charge, visit /atmelstudio .© 2012 Atmel Corporation. All rights reserved. / Rev.: 8487B-Studio6-E-A4-09/12Atmel ®, Atmel logo and combinations thereof, and others are registered trademarks or trademarks of Atmel Corporation or its subsidiaries. ARM ®, ARMPowered ® logo and others are the registered trademarks or trademarks of ARM Ltd. Other terms and product names may be the trademarks of others. Atmel logo and combinations thereof, and others are registered trademarks or trademarks of Atmel Corporation or its subsidiaries.Disclaimer: The information in this document is provided in connection with Atmel products. No license, express or implied, by estoppel or otherwise, to any intellectual property right is granted by this document or in connection with the sale of Atmel products. EXCEPT AS SET FORTH IN THE ATMEL TERMS AND CONDITIONS OF SALES LOCATED ON THE ATMEL WEBSITE, ATMEL ASSUMES NO LIABILITY WHATSOEVER AND DISCLAIMS ANY EXPRESS, IMPLIED OR STATUTORY WARRANTY RELATING TO ITS PRODUCTS INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, CONSEQUENTIAL, PUNITIVE, SPECIAL OR INCIDENTAL DAMAGES (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS AND PROFITS, BUSINESS INTERRUPTION, OR LOSS OF INFORMATION) ARISING OUT OF THE USE OR INABILITY TO USE THIS DOCUMENT, EVEN IF ATMEL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. Atmel makes no representations or warranties with respect to the accuracy or completeness of the contents of this document and reserves the right to make changes to specifications and products descriptions at any time without notice. Atmel does not make any commitment to update the information contained herein. Unless specifically provided otherwise, Atmel products are not suitable for, and shall not be used in, automotive applications. Atmel products are not intended, authorized, or warranted for use as components in applications intended to support or sustain life. Atmel Corporation 1600 Technology Drive, San Jose, CA 95110 USA T: (+1)(408) 441-0311 F: (+1)(408) 487-2600 | 。
AtmelStudio-6.0简易入门教程(精炼实用)(2021年整理精品文档)
(完整word版)AtmelStudio-6.0简易入门教程(精炼实用)编辑整理:尊敬的读者朋友们:这里是精品文档编辑中心,本文档内容是由我和我的同事精心编辑整理后发布的,发布之前我们对文中内容进行仔细校对,但是难免会有疏漏的地方,但是任然希望((完整word 版)AtmelStudio-6.0简易入门教程(精炼实用))的内容能够给您的工作和学习带来便利。
同时也真诚的希望收到您的建议和反馈,这将是我们进步的源泉,前进的动力。
本文可编辑可修改,如果觉得对您有帮助请收藏以便随时查阅,最后祝您生活愉快业绩进步,以下为(完整word版)AtmelStudio-6.0简易入门教程(精炼实用)的全部内容。
一、建议工程文件AtmelStudi6。
0这个全新的环境使用起来极其不顺手,因为首先我对AtmelStudio以前的版本也根本没有使用经验,就根据很陌生,其次,这个新版本软件还根本没有人用,根本没有任何的相关教程资料,唯一可以参考的只是官网的比较简单的视频教程,还是英文讲解,反正没怎么搞透。
不过还是硬着头皮用下去,因为软件是免费的,而且当后来我知道代码编辑环境其实就是微软VS环境的时候,我就更不犹豫了,大家应该都了解VS的代码编写环境是很智能的,尤其自动补全功能。
现在,我已经能很熟练的使用AtmelStudio6。
0软件了,随着使用我也更加喜欢玩AVR单片机做一些小作品了,而不再用普通51和STC了。
当使用熟练以后也就感觉到其实这个免费智能的编译环境其实是很简单的,那现在我就帮助更多喜欢使用AVR而没用使用AtmelStudio软件的同学们轻松越过这一个门槛,进入一个美好的编程世界.该软件的不足之处:一是软件相对较大,打开比较慢,但是运行还是比较顺利的;二是不支持山寨仿真器,这可苦了没钱的劳苦电工们了。
(不过我都是用ISP烧录调试,一般不用仿真)最下面附件有一个简单的LED_test工程文件,编译通过的.大家可以试用。
AtmelStudio6.0 下程序的烧录操作
AtmelStudio6.0 下程序的烧录操作
点击tools->Device Programming
出现如下画面:
选择Tool->JTAGICE mkll070000004699,这个选项是选择仿真器类型的,根据自己的仿真器类型选择就行了。
选择Device下的下拉菜单,选择自己的单片机型号。
选择Interface下的下拉菜单,选择ISP,然后点击Apply。
依次点击Target Voltage和Device signature下的Read,此时会读出当前片子的电压和地址。
点击左边栏目中的Memories,在右侧的复选框中找到工程路径下的.hex文件,点击Program,即可将程序下载到单片机内。
下载完成后会出现如下界面:
点击Fuses,此处是对单片机熔丝位的设置,所以选择要谨慎,否则单片机会被锁。
根据自己的晶振选择系统时钟,INTRCOSC为内部时钟信号,EXTXOSC 为外部时钟信号;内部时钟信号是以单片机内部的时钟为参考,外部时钟信号是以外接晶振为参考;由于atmega88单片机内部的晶振是LC震荡,所以并不精确,因此要用到定时器或者时序等,建议用外部晶振。
选择内部晶振:
选择外部晶振:
选择完成之后点击Program ,之后会出现如下显示,表示下载完成;如果熔丝位没有更改此处就不需要点击Program,如果更改了则需要重新Program之后才能生效。
AtmelStudio-6.0简易入门教程(精炼实用).
一、建议工程文件AtmelStudi6.0这个全新的环境使用起来极其不顺手,因为首先我对AtmelStudio以前的版本也根本没有使用经验,就根据很陌生,其次,这个新版本软件还根本没有人用,根本没有任何的相关教程资料,唯一可以参考的只是官网的比较简单的视频教程,还是英文讲解,反正没怎么搞透。
不过还是硬着头皮用下去,因为软件是免费的,而且当后来我知道代码编辑环境其实就是微软VS环境的时候,我就更不犹豫了,大家应该都了解VS的代码编写环境是很智能的,尤其自动补全功能。
现在,我已经能很熟练的使用AtmelStudio6.0软件了,随着使用我也更加喜欢玩AVR单片机做一些小作品了,而不再用普通51和STC了。
当使用熟练以后也就感觉到其实这个免费智能的编译环境其实是很简单的,那现在我就帮助更多喜欢使用AVR而没用使用AtmelStudio软件的同学们轻松越过这一个门槛,进入一个美好的编程世界。
该软件的不足之处:一是软件相对较大,打开比较慢,但是运行还是比较顺利的;二是不支持山寨仿真器,这可苦了没钱的劳苦电工们了。
(不过我都是用ISP烧录调试,一般不用仿真)最下面附件有一个简单的LED_test工程文件,编译通过的。
大家可以试用。
下面开始介绍的软件工程的建立。
1. 软件总界面总体界面还是比较简洁的,和其他编译软件都是差不多的,而且和KEIL软件的界面是很相似的,使用很方便。
2. 新建工程新建工程很简单:FILE->NEW->Project 然后就看到下面的新建工程界面了,选择第一个GCC C Executable工程就可以,第二个GCC C static Library 是用来新建 .h文件的。
然后下面蓝圈1是C文件的名称,蓝圈2 Solution Name 是工程的文件,中间的Location是文件存放位置,自己选择合适的位置即可。
点击下面的OK3. 下面接着是单片机型号选择界面,选择合适的单片机就可以了。
Bootloader编译与下载
Bootloader编译与下载Bootloader编译与下载3.1 实验目的:完成Bootloader编译与下载。
3.2 实验内容:参照指导书给出的步骤,一步一步地完成Bootloader编译与下载。
3.3 实验设备:1)硬件环境(硬件连接方法与Android版本一样)设备硬件连接方法必用的设备:串口线一根,网线一根,USB OTG线缆一根。
UART port0 : 作为监测中使用的端口连接串行线。
Ethernet port : 利用 Ethernet,为了高速传送,连接 LAN 线缆。
USB OTG Cable : 利用 USB,为了更新映像时使用,进行连接。
引导模式开关位于试验箱的右下角在下载映像文件之前注意设置引导模式开关设定引导模式NAND Flash 引导模式IROM 引导模式2)软件环境Linux 开发环境- VMWare在XP系统安装虚拟机,通过虚拟机加载一个Linux系统开发环境- Linux内核(CD提供ubuntu 8.04版本)串口监测工具 : minicom开发工具 : 交叉编译器 (CD提供gcc 4.4.1)3.4 实验步骤:操作步骤:提供CD 中“ubuntu_8.04”目录复制到“D:\”目录中。
在这个目录中,双击“ubuntu8.04_android.vmx”文件,运行ubuntu 8.04。
运行Ubuntu 8.04 映像前,需要安装VMware Player 或者WMware Workstation。
出版 CD 中提供了 VMware Player (路径 : tools\vmware-player\VMware-player-3.1.2-301548.exe)。
如果双击“ubuntu8.04_android.vmx”文件,如错误!未找到引用源。
],运行已安装的VMware Player 或者VMware Workstation。
这时,按下 Power On this virtual machine按钮。
BootLoader
BootLoader锁定本词条由“科普中国”百科科学词条编写与应用工作项目审核。
行之前运行。
可以初始化硬件设备、建立内存空间映射图,从而将系统的软硬件环境带到一个合适状态,以便为最U也会内嵌一段短小的启动程序),因此整个系统的加载启动任务就完全由BootLoader来完成。
在一个基于ARM7TDM I00000000处开始执行,而在这个地址处安排的通常就是系统的BootLoader程序。
中文名启动装载外文名BootLoader说明系统启动前引导程序操作模式启动模式、交互模式1背景介绍Bootloader是嵌入式系统在加电后执行的第一段代码,在它完成CPU和相关硬件的初始化之后,再将操作系统映像或固化的嵌入式应用程序装在到内存中然后跳转到操作系统所在的空间,启动操作系统运行。
[1]对于嵌入式系统,Bootloader是基于特定硬件平台来实现的。
因此,几乎不可能为所有的嵌入式系统建立一个通用的Bootloader,不同的处理器架构都有不同的Bootloader 。
Bootloader不但依赖于CPU的体系结构,而且依赖于嵌入式系统板级设备的配置。
对于2块不同的嵌入式板而言,即使它们使用同一种处理器,要想让运行在一块板子上的B ootloader程序也能运行在另一块板子上,一般也都需要修改Bootloader的源程序。
反过来,大部分Bootloader仍然具有很多共性,某些Bo otloader也能够支持多种体系结构的嵌入式系统。
例如,U-Boot就同时支持PowerPC、ARM、MIPS和X86等体系结构2操作模式1.自启动模式:在这种模式下,bootloader从目标机上的某个固态存储设备上将操作系统加载到RAM中运行,整个过程并没有用户的介入。
2.交互模式:在这种模式下,目标机上的bootloader将通过串口或网络等通行手段从开发主机(Host)上下载内核映像等到RAM中。
可以被bootloader写到目标机上的固态存储媒质中,或者直接进入系统的引导。
实验一 交叉编译环境的建立和bootloader的使用
实验一交叉编译环境的建立和bootloader的使用实验目的1.建立嵌入式软件的交叉编译环境。
2.下载和使用bootloader。
实验内容1.安装串口支持文件。
2.安装编译器。
3.安装bootloader。
4.下载内核并运行。
嵌入式LINUX开发环境有几个方案:1.基于PC机WINDOWS操作系统下的CYGWIN;2.在WINDOWS下安装虚拟机后,再在虚拟机中安装LINXUX操作系统;3.直接安装LINUX操作系统。
基于WINDOWS的环境要么有兼容性问题,要么速度有影响,所以我推荐大家使用纯LINUX操作系统开发环境。
我们实际的开发环境为REDHAT9,它已经支持中文,并且包含了绝大部分的开发工具,不用担心装了LINUX就不能使用WINDOWS的问题。
一般的情况都是用户已经有了WINDOWS操作系统,再安装LINUX,LINUX会自动安装一个叫作GRUB的启动引导软件,可以选择引导多个操作系统。
绝大多数Linux 软件开发都是以native 方式进行的,即本机(HOST)开发、调试,本机运行的方式。
这种方式通常不适合于嵌入式系统的软件开发,因为对于嵌入式系统的开发,没有足够的资源在本机(即板子上系统)运行开发工具和调试工具。
通常的嵌入式系统的软件开发采用一种交叉编译调试的方式。
交叉编译调试环境建立在宿主机(即一台PC 机)上,对应的开发板叫做目标板。
运行Linux 的PC【宿主机】开发时使用宿主机上的交叉编译、汇编及连接工具形成可执行的二进制代码(这种可执行代码并不能在宿主机上执行,而只能在目标板上执行),然后把可执行文件下载到目标机上运行。
调试时的方法很多,可以使用串口,以太网口等,具体使用哪种调试方法可以根据目标机处理器提供的支持做出选择。
宿主机和目标板的处理器一般不相同,宿主机为Intel 处理器,而目标板如UP-NetARM2410-S 开发板为三星S3c2410.GNU 编译器提供这样的功能,在编译器编译时可以选择开发所需的宿主机和目标机从而建立开发环境。
离线加密编程器中的BootLoader程序设计
离线加密编程器中的BootLoader程序设计引言离线加密编程器是一种独立于PC 机,并通过SPI 接口直接对ATmega 系列单片机进行编程操作的设备。
在整个系统中,编程器与目标板之间的结合部分是一个最可能被解密的地方,因为可以通过抓取SPI 总线上的时序得到所传输的数据,因此编程器与目标板之间传输的数据必须是经过加密的。
而有效的编程数据不能为加密数据,所以加密数据需要经过解密还原才能用于单片机的编程。
本设计中BootLoader 程序的作用就是接收离线加密编程器的加密数据,对加密数据进行解密,然后完成目标板的编程操作。
首先编程目标板单片机的BootLoaoler 引导程序,最后与BootLoacler 程序建立连接。
编程器将加密数据传送给。
BootLoader 程序,由BootLoacler 程序对加密数据进行解密,然后完成编程操作。
这样做既可以确保数据不被外界破解,又能方便程序的升级操作。
BootLoader 程序的下载对具有知识产权保护要求的离线编程器设计是一个关键步骤,它的成功与否直接决定离线编程器设计能否成功。
本文将以ATmegal69 为例进行BootLoader 程序下载的介绍。
1 系统硬件设计本系统主要由单片机、显示部分、按键开关、存储部分和串行通信部分等组成,硬件结构框图如图1所示。
图1 中,AVR ATmegal69P(V)单片机是一种高性能、低功耗的8 位微处理器,采用先进的RISC 结构,130 条指令大多数可以在1 个时钟周期内完成,满足了本系统对执行速度的要求。
它具有非易失性的程序和数据存储器,16 KB 的系统内可编程Flash,具有4 乘以25 段的LCD 驱动器的ATmegal69P(V),输入电压3.3 V,串行USART,可工作于主机/从机模式的SPI 串行接口;存储部分采用ATmel 公司8 个引脚的串口存储芯片AT45DB041B,主存容量大小为528 KB,一共2 048 页,每页264B,具有2 个大小为265B 的数据缓存,允。
AVR单片机Bootloader程序
1.程序逻辑BootLoader的升级协议是基于128字节数据块的Xmodem通信协议,采用CRC16校验。
Xmodem 协议的帧格式Byte1Byte2Byte3Byte4~Byte131Byte132~Byte133控制字符包序号包序号反码128字节数据校验和升级协议具体流程:序程redaoLtooB机片单RVA下位机发送升级请求密码,等待上位机的升级密码boot96,5秒的时间内若上位机没有发送升级密码,下位机进入用户程序。
上位机有升级指令发送时,下位机间断发送’C’等待上位机接收并开始发送数据,若数据连续三次校验错误那么进入用户程序,成功发送后进入用户程序执行刚写入的程序。
2.平台及程序结构基于ATmega328PB 单片机,20M 晶振,AtmelStudio平台。
包括下图四个文件。
3.程序代码3.1.Bootloader.h 头文件#include <avr/io.h>#include <avr/wdt.h>#include <avr/boot.h>#include <avr/pgmspace.h>#ifndef BOOTLOADER_H_#defineBOOTLOADER_H_#ifndef F_CPU #define F_CPU20000000UL //20M 时钟频率#endif#define BAUDRATE 4800//串口波特率#define BAUDREG ((unsigned int)((F_CPU *10)/(16UL *BAUDRATE)-5)/10)//超时次数#define TimeOutCnt25//发送'C'的最大次数#define TimeOutCntC 10//同步时间间隔(ms)#define timeclk 200//同步密码长度#define CONNECTCNT 6//Boot 区起始地址#define BootStart 0x3C00UL //由具体硬件设置#define RS4850#ifRS485AVR单片机BootLoader程序#define RS485PORT xxxxx #define RS485TXEn xxxxx#define RS485Enable()PORTREG(RS485PORT)|=(1<<RS485TXEn)#define RS485Disable()PORTREG(RS485PORT)&=~(1<<RS485TXEn)#endif //同步密码unsigned char KEY []={'b','o','o','t','9','6',0x0E ,0x1C ,0x39,0x14,0x28,0x57,0xAA };//用户程序起始地址#define PROG_START 0x0000#define BUFFERSIZE 128#define BUFSIZE BUFFERSIZE//接收缓冲区unsigned char buf [BUFSIZE ];unsigned char bufptr ,pagptr ;unsigned char ch ,cl ;//Flash 地址unsigned int FlashAddr ;//提示信息const char msg1[20]="Waiting for password";const char msg2[8]="Time out";const char msg3[23]="Waiting to receive file";const char msg4[17]="Upgrade successed";const char msg5[14]="Upgrade failed";//Xmoden 控制字符#define XMODEM_NUL 0x00#define XMODEM_SOH 0x01#define XMODEM_STX 0x02#define XMODEM_EOT0x04#define XMODEM_ACK 0x06#define XMODEM_NAK0x15#define XMODEM_CAN 0x18#define XMODEM_EOF0x1A #define XMODEM_RWC 0x43//'C'#define DataInCom()((UCSR0A)&(1<<RXC0))#define ReadCom()UDR0#endif /*BOOTLOADER_H_*/AVR单片机BootLoader程序3.2.Bootloader.c 文件#include <avr/io.h>#include <compat/ina90.h>#include <avr/interrupt.h>#include <avr/sleep.h>#include <util/delay.h>#include <avr/pgmspace.h>#include <stdlib.h>#include "BootLoader.h"#include "usart.h"sram global ;//全局变量结构体//使用定时器1:产生以毫秒为单位的时间void TimerInit (){OCR1A =(unsigned int )(timeclk *(F_CPU /(1024*1000.0f )));//200msTCCR1A =0;//普通端口TCCR1B =(1<<WGM12)|(1<<CS12)|(1<<CS10);//CTC1024分频}//更新一个Flash 页void write_one_page (unsigned char *buf ){boot_page_erase (FlashAddr );//擦除FLASH 指定页boot_spm_busy_wait ();for (pagptr =0;pagptr <SPM_PAGESIZE ;pagptr +=2)//SPM_PAGESIZE 128{boot_page_fill (pagptr ,buf [pagptr ]+(buf [pagptr +1]<<8));//填充BootLoader 缓冲页}boot_page_write (FlashAddr );//缓冲写入FLASH 指定页boot_spm_busy_wait ();}//跳转到用户程序void quit (){boot_rww_enable ();//RWW 区读使能(*((void (*)(void ))PROG_START ))();//用户程序起始地址PROG_START 0x0000}int main (void ){AVR单片机BootLoader程序unsigned char cnt ;unsigned char packNO ;unsigned char crch ,crcl ;unsigned int crc ;unsigned char li ;_CLI ();//关中断USART_Init ();_delay_ms (1000);TimerInit ();//定时器初始化,CTC 普通端口USART_Transmit ((unsigned char *)msg1,20);//Waiting for passwordcnt =TimeOutCnt ;//超时次数255s 1s 发送一个等待密码cl =0;while (1){if (TIFR1&(1<<OCF1A ))//自动重载{TIFR1|=(1<<OCF1A );if (cl ==CONNECTCNT )//密码长度6break ;cnt --;if (cnt ==0){USART_Transmit ((unsigned char *)msg2,8);//Time outquit ();}if (cnt %5==0)USART_Transmit ((unsigned char *)msg1,20);//Waiting for password}if (DataInCom ()){if (ReadCom ()==KEY [cl ])//接收密码cl ++;elsecl =0;}}USART_Transmit ((unsigned char *)msg3,23);//Waiting to receive file cnt =TimeOutCntC ;//发送'C'超时次数10while (1){AVR单片机BootLoader程序if (TIFR1&(1<<OCF1A )){TIFR1|=(1<<OCF1A );WriteCom (XMODEM_RWC );//发送'C'cnt --;if (cnt ==0){USART_Transmit ((unsigned char *)msg2,8);//Time out quit ();}}if (DataInCom ()){if (ReadCom ()==XMODEM_SOH )//接收数据SOH 0x01break ;}}TCCR1B =0;packNO =0;cnt =0;FlashAddr =0x0000;do {packNO ++;bufptr =0;ch =WaitCom ();cl =~WaitCom ();if ((packNO ==ch )&&(packNO ==cl )){WriteCom (XMODEM_ACK );for (li =0;li <BUFFERSIZE ;li ++)//接收128个字节数据buf [bufptr ++]=WaitCom ();crch =WaitCom ();crcl =WaitCom ();crc =crc16(buf ,BUFFERSIZE );//CRC 校验ch =crc /256;cl =crc %256;if ((crch ==ch )&&(crcl ==cl ))//如果校验符合{if (FlashAddr <BootStart ){write_one_page (buf );//写flash 写一页FlashAddr +=SPM_PAGESIZE ;AVR单片机BootLoader程序}WriteCom (XMODEM_ACK );//发送ACKcnt =0;}else {WriteCom (XMODEM_NAK );//发送NAK cnt ++;}}else {WriteCom (XMODEM_NAK );//发送NAKcnt ++;}if (cnt >3)//无应答次数break ;}while (WaitCom ()!=XMODEM_EOT );//等待全部接收XMODEM_EOT 0x04WriteCom (XMODEM_ACK );_delay_ms (50);if (cnt ==0){USART_Transmit ((unsigned char *)msg4,17);//升级成功Upgrade successedquit ();}else {USART_Transmit ((unsigned char *)msg5,14);//Upgrade failed while (1);//应该是升级失败不让进入用户程序避免程序错乱带来不必要的麻烦}quit ();//跳转到用户程序return 0;}3.3.usart.h 头文件#ifndef USART_H_#define USART_H_#define RS485_RX PORTD &=~((1<<PORTD2)|(1<<PORTD3))//Receiving #define RS485_TXPORTD |=(1<<PORTD2)|(1<<PORTD3)//Transmitting#define RS485_HIGHZ PORTD |=(1<<PORTD3);PORTD &=~(1<<PORTD2)//High-Z void USART_Init (void );//串口初始化AVR单片机BootLoader程序unsigned char WaitCom ();//接收单字节void WriteCom (unsigned char dat );//发送单字节void USART_Transmit (unsigned char *data ,char num );//发送函数unsigned int crc16(unsigned char *buf ,unsigned char n );//CRC 校验//#define IDEL 0x00//#define ID_ACCORD 0X01//#define COMMAND 0x02//#define READ_COMMAND 0x03//#define WRITE_COMMAND 0x04#define TRANSMITTING 0x10//#define DATA_READY 0x08//#define KEY_MODE 0x07//按键模式//#define GetFreq_MODE 0x80//测试模式//#define BOOTLAODER_MODE 0xf0//Booterloader 升级#define USARTBUFNUM GPIOR1//串口字节个数typedef struct {unsigned char ptr ;unsigned char state ;unsigned char command ;unsigned char savestate ;//保存状态unsigned char *usartbuf ;unsigned char comBuffer [150];}sram ;extern sram global ;//全局变量结构体#endif /*USART_H_*/art.c 文件#include <avr/io.h>#include <compat/ina90.h>#include <avr/interrupt.h>#include <avr/sleep.h>#include <util/delay.h>#include <avr/wdt.h>#include "usart.h"//#include "wdtg.h"SIGNAL (USART0_RX_vect ){}AVR单片机BootLoader程序SIGNAL (USART0_UDRE_vect ){}SIGNAL (USART0_TX_vect ){}void USART_Init (void ){DDRD |=(1<<DDD1)|(1<<DDD2)|(1<<DDD3);//485芯片控制引脚输出PORTD |=(1<<PORTD2)|(1<<PORTD3);//184芯片引脚控制输出高TX PORTD |=(1<<PORTD1)|(1<<PORTD0);//TX 输出高,RX 上拉输入//UBRR0=143;//4800UBRR0=259;//1434800(11059200/16/4800-1)UCSR0B =(1<<RXEN0);//串口0接收使能UCSR0C =(1<<UCSZ01)|(1<<UCSZ00);RS485_RX ;}unsigned char WaitCom (){while (!(UCSR0A &(1<<RXC0)));return UDR0;}void WriteCom (unsigned char dat ){RS485_TX ;/*发送状态*/UCSR0B =(1<<TXEN0);/*发送使能*/UDR0=dat ;while (!(UCSR0A &(1<<TXC0)));UCSR0A |=(1<<TXC0);RS485_RX ;/*接收状态*/UCSR0B =(1<<RXEN0);/*接收使能*/}void USART_Transmit (unsigned char *data ,char num ){char i ;RS485_TX ;/*发送状态*/UCSR0B =(1<<TXEN0);/*发送使能*/for (i =0;i <num ;i ++){while (!(UCSR0A &(1<<UDRE0)));/*等待数据寄存器为空*/AVR单片机BootLoader程序UDR0=*data ;data ++;}UCSR0B =(1<<TXEN0);/*发送使能*/while ((UCSR0A &(1<<TXC0))==0);/*等待发送结束*/UCSR0A |=(1<<TXC0);/*发送结束标志位清零*/RS485_RX ;/*接收状态*/UCSR0B =(1<<RXEN0);/*接收使能*/}//CRC 校验unsigned int crc16(unsigned char *buf ,unsigned char n ){unsigned char j ;unsigned char i ;unsigned int crc ,t ;crc =0;for (j =n ;j >0;j --){crc =(crc ^(((unsigned int )*buf )<<8));for (i =8;i >0;i --){t =crc <<1;if (crc &0x8000)t =t ^0x1021;crc =t ;}buf ++;}//ch =crc /256;//cl =crc %256;return crc ;}AVR单片机BootLoader程序。
Atmel_Studio_6.1_简易使用教程
Atmel Studio 6.1简易使用教程 1 新建工程2 工程命名,以LED闪烁为例3 选择目标芯片,本例选择AT32UC3A02564 工程创建完成,在生成的main函数里编写相应代码5 Atmel Software Framework(简称ASF)为不同的MCU提供软件驱动和库来加快开发过程,ASF的架构如下图Your application对应要实现的软件应用Utilities对应开发工具和宏Boards对应开发板或者用户自定义板ASF由Drivers、Components和Services三部分组成:①Drivers对应片上设备的驱动,如ADC、FLASH、GPIO、INTC、PM、PWM、USART等②Components对应外设驱动,如存储器、显示屏、传感器等③Services对应FAT文件系统、DSP库、USB等6 导入ASF。
进行开发时,借用官方提供的驱动,可以大大简化开发进程在此添加Drivers/GPIO点击Apply将选择的模块添加到工程中7 此时编译发现报错双击错误进入错误位置查看Output,发现问题出在编译startup_uc3.S 文件时出现重复定义错误问题的原因在于:startup_uc3.S 文件是Atmel 官方自定义的启动文件,并非标准启动文件(crt0.o,指定main 函数的入口地址),在工程属性里应该设置不使用标准启动文件,否则就会出现重复定义的错误。
解决:在工程目录中右键选择工程属性再次编译,成功通过_start 和_stext 在startup_uc3.S 文件中重复定义,第一次定义在crt0.o 文件中8 在main函数中编写相应代码,实现LED闪烁控制。
9 编译通过后,将生成的.hex或.elf烧写文件下载到flash中看运行结果。
avr单片机boot_loader实现指导
//总加载页数
static volatile WORD m_PCPAGE = 0;
Байду номын сангаас
//指定要操作的页地址(16bit)
static volatile BYTE m_PCPAGE_H = 0;
static volatile BYTE m_PCPAGE_L = 0;
//Bootloader 主程序
void flash_update(void)
Bootloader 为通过 MCU 本身来下载和上传程序代码提供了一个真正的同时读写的 自编程机制。这一特点使得系统在单片机控制下,通过驻留在程序区的 Bootloader,灵 活地进行应用软件地升级,而且可以使用任何器件具有的数据接口和相关的协议获得代 码并把代码写入 flash,或者从程序存储器读取代码。
//宏定义加载程序命令
#define PRO_PAGE_SIZE
128 //定义每页的字节大小
#define Z_ADD_SHIFT
7
//PCPAGE 在 Z 地址寄存器中的具体位置
static volatile BYTE m_SPM = 0;
//SPMCR 寄存器状态
static volatile BYTE m_page = 0;
用户可以有以下两个方案来实现 IAP 功能
作者:Kevin Kung
第 1/7页
北天星国际贸易有限公司
方案 1: 写临时页缓冲器 执行页擦除操作 执行页写操作
方案 2: 执行页擦除操作 写临时页缓冲器 执行页写操作
以上操作都要通过 SPM 指令最终完成
四. 参考例程(Atmega16)
#define _SPM() asm("spm")
BOOTLOADER的原理及设计要点
MEGA128的Boot Loader区大小可以由BOOT- SZ熔丝位来配置, 这给用户带来了很大的选择灵 活 性 。 在 出 厂 默 认 配 置 下 , BOOTSZ=00, 也 即 Boot Loader区为从¥F000开始的4K 字。用户可以 通过改写BOOTSZ来更改其大小。如果boot loader 区程序非常小, 用户甚至可以将Boot Loader区设 定 为512字 以 扩 大 应 用 程 序 的 空 间 。 笔 者 认 为 , 如果应用程序不是非常大, 最好能保留其4K字的 配置, 这一方面可减少一步改写熔丝位的工作 量, 另一方面也预留了Boot Loader的扩展能力。
利 用 在 应 用 编 程 (IAP, In Application Pro- gram) 技术, 用户可在数据采集中心对远 程RTU 进行升级, 而且更新时间快, 基本不会影响系统 运 行 。 此 外 , 当 在 单 片 机 中 烧 入 这 样 一 个 Boot loader程序并建立IAP后, 其最基本的开发环境就 简化成了 “PC+RS232电缆+目标板”。
Boot Loader区 的 程 序 一 般 可 分 为 两 个 部 分 , 一 部 分 是 与 硬 件 单 片 机 相 关 的 FLASH 擦 写 功 能 模 块函数, 一般用汇编语言编写, 这也是整个Boot Loader的 核 心 模 块 ; 另 一 部 分 为 应 用 程 序 模 块 , 一般用C语言编写, 以增强程序的可读性。
2.2 Boot Loader程序进入方式的选择
Boot Loader的本质就是驻留在FLASH中的 一 段程序。要进入Boot Loader程序, 程序指针PC必 须指向该程序的起始位置。用户可以通过在应用 程序接收到特殊指令后, 通过JMP语句直接跳转 到Boot Loader程 序 的 开 始 位 置 去 执 行 更 新 流 程 。 此 外 , MEGA128还 可 通 过 更 改BOOTRST熔 丝 位 来 将 复 位 向 量 直 接 指 向Boot Loader程 序 , 这 样 , 每次MEGA128复位时, 都将直接运行Boot Loader 流程。但用户在Boot Loader中必须判断是否需要 更新应用程序, 如果不需要, 经过超时时间后则 退出Boot Loader, 接着进入应用程序。
atmega16中文资料.0004
29
PC6.Pullup_Enable
28
PC7.Data
27
PC7.Control
26
PC7.Pullup_Enable
25
TOSC
32 kHz 定时振荡器
24
TOSCON
23
PA7.Data
端口 A
22
PA7.Control
21
PA7.Pullup_Enable
20
PA6.Data
19
PA6.Control
RWW 区
如果 Boot Loader 软件是对 RWW 区内的某一页进行编程,则可以从 Flash 中读取代码, 但只限于 NRWW 区内的代码。在 Flash 编程期间,用户软件必须保证没有对 RWW 区的 读访问。如果用户软件在编程过程中试图读取位于 RWW 区的代码 ( 如通过 call/jmp/lpm 指令或中断 ),软件可能会终止于一个未知状态。为了避免这种情况的发生,需要禁止中 断或将其转移到 Boot Loader 区。 Boot Loader 总是位于 NRWW 存储区。只要 RWW 区 处于不能读访问的状态,存储程序存储器控制和状态寄存器 (SPMCSR) 的 RWW 区忙标 志位 RWWSB 置位。编程结束后,要在读取 位于 RWW 区的代码之前通过软件清除 RWWSB。具体如何清除RWWSB请参见P238 “保存程序存储器控制寄存器 – SPMCR” 。
No Read-While-Write (NRWW) Section
Z-pointer Addresses NRWW Section
CPU is Halted during the Operation
234 ATmega16(L)
Atmel Studio 6.2开发环境的搭建和使用
点击绿色的小三角图标(Starting Debugging)开始调试。
可能会弹出如(图2-8)的提示升级,点击升级即可。
再次点击StartingDebugging调试,待编译成功之后,可能会弹出如图2-
9所示的对话框
选择EDBG即可,然后点击StartingDebugging即可烧录程序进入调试模
下载成功之后安装即可。
安装完成以后,点击图标打开Atmel Studio 6.2(如图2-2所示)
图标还是挺可爱的(~。~)。。
打开atmelStudio(如图3所示)将开发板用USB连接到电脑的USB端
口,电脑会自动安装板子的驱动的。
个人认为学习任何一款软件,建议先去使用Help菜单,查看里面的帮助
式。
完成程序下载后,点击运行。
点击BUTTON1可以切换不同的功能,3个LED对应着不同的功能,分
别是温度计、光照强度、检查SD空间。
如果打开Atmel-42075-SAM4S-Xplained-Pro_User-Guide.pdf开发文档,
里面会有这幺一段话:
简单3步就可以实现对Atmel SAM4S Xplained Pro的开发:
1.下载并安装Atmel Studio
2.打开Atmel Studio
3.用USB线连接到AtmelSAM4S-Xplained-Pro的EDBUG(Embedded
Atmel Studio 6.2开发环境的搭建和使用
本篇搭建和使用的是AtmelStudio6.2开发环境。AtmelStudio6.2中也给
出了这个发板的示例程序,本篇文章就一步一步的通过下载和搭建开发环
境,下载程序到开发板中。我就先来试用ATMEL公司的官方开发环境atmel
学习使用AtmelStudio进行嵌入式系统开发
学习使用AtmelStudio进行嵌入式系统开发嵌入式系统是指将微处理器或微控制器嵌入到其他设备中,实现特定功能的系统。
AtmelStudio是一款由微处理器制造商Atmel 公司开发的集成开发环境,专门用于嵌入式系统开发。
本文将介绍如何使用AtmelStudio进行嵌入式系统开发,并按照不同的类别划分为几个章节。
第一章:AtmelStudio简介AtmelStudio是Atmel公司为自家产品Atmel AVR和ARM微控制器提供的集成开发环境。
它基于Visual Studio平台,提供了丰富的开发工具和调试功能。
使用这一工具可以大大加快嵌入式系统开发的速度并提高开发效率。
第二章:环境搭建在使用AtmelStudio进行嵌入式系统开发之前,我们首先需要搭建相应的开发环境。
具体步骤如下:1. 下载并安装最新版的AtmelStudio。
可以从Atmel公司官网上找到最新的版本并进行下载。
安装过程很简单,按照指导完成即可。
2. 配置编译器。
AtmelStudio支持多种编译器,包括GCC和IAR等。
根据项目需求选择所需的编译器,并进行相应的配置。
3. 配置调试工具。
AtmelStudio支持多种调试工具,如ICE和JTAG等。
选择合适的调试工具,并配置好与开发板的连接。
第三章:新建项目在AtmelStudio中创建新项目是进行嵌入式系统开发的第一步。
具体操作如下:1. 打开AtmelStudio,在开始界面点击"新建项目"按钮。
2. 在弹出的对话框中选择项目模板。
AtmelStudio提供了多种常见的项目模板,如Blink示例、USART通信和PWM控制等。
根据项目需求选择合适的模板。
3. 设置项目文件名和存储路径。
根据个人喜好设置合适的文件名和存储路径。
4. 配置项目属性。
根据具体需求配置项目属性,如选择使用的编译器和调试工具等。
第四章:编写代码在AtmelStudio中编写嵌入式系统代码是进行项目开发的核心步骤。
Bootloader过程简介
Bootloader过程简介
应用层 OS层 驱动层
电源管理
Flash
EEPROM
内
SDRAM SRAM
存
看门狗及复 位电路
应用程序 文件系统/图形用户应用程序接口
实时操作系统(RTOS) 设备驱动程序、HAL、BSP
SOC/SOPC
GPIO IIS USB LCD
ADC/DAC
back
Bootloader过程简介
3.3 Bootloader操作模式
大多数Bootloader都
有两种不同的操作模式:
loader
“启动加载”模式和“下
载”模式。其区别对于开
发人员才有意义。
从最终用户的角度看, Bootloader的作用就是用 flash 来加载操作系统,而并不 bits
存在所谓的启动加载模式
Bootloader过程简介
2、下载(Downloading)模式 下载方式:在这种模式下,目标机上的 Bootloader将通过串口连接或网络连接等通信手段 从主机下载文件。 下载内容及存储:主要是下载内核映像和根文件 系统映像等。从主机下载的文件通常首先被 Bootloader保存到目标机的RAM中,然后再被 Bootloader写到目标机上的FLASH 类固态存储设备 中。
Bootloader过程简介
1、vivi
vivi是韩国Mizi公司开发的Bootloader,适用于
ARM9处理器。
2、RedBoot RedBoot即红帽(Red Hat)嵌入式调试引导程序, 是一种用于嵌入式系统的独立开放源代码引导/装载器。
3、U-Boot U-Boot(Universal Bootloader)由德国DENX小组 开发,是一款目前功能较为强大的开源Bootloader程序,它支 持多种处理器平台,包括ARM、PowerPC、MIPS等。
嵌入式linux操作系统u-boot启动顺序以及代码解析
Bootloader/u-boot的启动模式对于计算机系统来说,从计算机开机上电的到操作系统的启动需要一个引导过程。
嵌入式Linux同样也需要一个引导的过程,及引导程序就叫做Bootloader。
Bootloader是在操作系统启动之前执行的一小段程序,通过这段小程序,我们可以初始化硬件设备、建立内存空间映射表,从而建立适当系统软硬件环境,为最终调用操作系统内核做好准备。
对于嵌入式系统,Bootloader是基于特定平台来实现的,因此几乎不可能为所有的计算机操作系统建立一个通用的Bootloader,不同的处理器架构都有不同的Bootloader,Bootloader不但依赖于CPU的体系结构,而且依赖于嵌入式系统板级的设备的配置。
对于两块不同的嵌入式开发板,即使他们使用同一种处理器,要想让运行于一块板子上的Bootloader运行在另一块板子上,一般都需要修改Bootloader源程序。
反过来大多数的Bootloader都具有很多的共性,某些Bootloader也能够支持多种体系结构的嵌入式系统。
例如:u-boot就同时支持Powerpc、ARm、MIPS和X86等等的体系结构,支持的板子有上百种,通常他们都能够自动从存储介质上启动,都能够引导操作系统启动,并且大部分都可以支持串口和网口的操作。
系统加电或者复位后,cpu通常都会从某个地址开始执行,这是由处理器决定的,对于ARM处理器而言会从0x00000000取第一条指令,嵌入式系统的开发板都要把ROM和FLASH映射到这个地址上,因此必须将Bootloader的程序存储在相应的FLASH位置,这样系统加电后就会首先执行它。
u-boot的启动一般流程:第一阶段:依赖cpu初始化外围硬件代码,通常用汇编代码实现1、设置cpu的工作模式;2、关中断,以防止意外发生;/************************************************** set the cpu to SVC32 mode,设置cpu工作模式为11010011,* 后五位表示cpu的工作模式设置为”管理”,并且关闭中断* 110则表示IRQ(普通中断)和FIQ(快速中断)都为禁止**************************************************/mrs r0,cpsr//读取cpsr中的数据到r0中bic r0,r0,#0x1f//将寄存器r0的值和0x1f的反码安位与之后将结果存储在r0中相当于清零orr r0,r0,#0xd3//将寄存器r0的值和0xd3 安位或之后将结果保存在r0寄存器之中,关闭中断msr cpsr,r0//将cpsr中的数值写到r0寄存器中3、关闭看门狗,避免系统重启;#ifdefined(CONFIG_S3C2400)||defined(CONFIG_S3C2410)||defined(CONFIG_S3 C2440)/* turn off the watchdog ,关闭开门狗*/# if defined(CONFIG_S3C2400)# define pWTCON 0x15300000# define INTMSK 0x14400008 /* Interupt-Controller base addresses */# define CLKDIVN 0x14800014 /* clock divisor register */#else# define pWTCON 0x53000000# define INTMSK 0x4A000008 /* Interupt-Controller base addresses */ # define INTSUBMSK 0x4A00001C# define CLKDIVN 0x4C000014 /* clock divisor register */# endif4、设置back初始化,设置cpu的工作频率;#if defined(CONFIG_S3C2440)/*FCLK HCLK PCLK = 1: 4: 8*/ldr r0, =CLKDIVNmov r1,#5str r1,[r0]mrc p15,0,r1,c1,c0,0orr r1, r1,#0xc0000000mcr p15,0,r1,c1,c0,0mov r1,#CLK_CTL_BASEmov r2,#MDIV_405add r2,r2,#PSDIV_405str r2,[r1,#0x4]#else/* FCLK:HCLK:PCLK = 1:2:4 *//* default FCLK is 120 MHz ! */ldr r0, =CLKDIVNmov r1, #3str r1, [r0]#endif /* CONFIG_S3C2400 || CONFIG_S3C2410 *5、从FLASH拷贝到RAM;#ifndef CONFIG_SKIP_RELOCATE_UBOOTrelocate: /* relocate U-Boot to RAM */adr r0, _start /* r0 <- current position of code *///adr是读取地址的伪指令,表示将_start标示的运行地址给r0ldr r1, _TEXT_BASE /* test if we run from flash or RAM */// 表示将_TEXT_BASE 指向的地址中的数据拷贝到r1中cmp r0, r1 /* don't reloc during debug *///比较是否相同beq stack_setup //相同跳转出去/*****************不同则执行以下代码***********************/ldr r2, _armboot_start //start起始地址,包含RO代码段+RW 数据段+ZI全局变量ldr r3, _bss_start //全局变量的地址sub r2, r3, r2 /* r2 <- size of armboot *///相减之后得到的是代码段+数据段的总大小add r2, r0 r2, /* r2 <- source end address *///r0是要烧录的内容,表示的是烧录的代码段+数据段的结束地址copy_loop:ldmia r0!, {r3-r10} /* copy from source address [r0] *///ldmia批量的拷贝,向后拷贝32位到r3-r10(将r0中的数据读出到r3-r10的,r0自动加一) stmia r1!, {r3-r10} /* copy to target address [r1] *///stmia批量的存储到r1上也就是目标运行的地址上(将r3-r10中的数据保存到r1指向的地址上,r1自动加一)cmp r0, r2 /* until source end addreee [r2] *///r0 烧录的起始地址,r2烧录的结束地址,相等则说明拷贝完成ble copy_loop#endif /* CONFIG_SKIP_RELOCATE_UBOOT */6、设置建立堆栈;7、执行内存地址上的程序,该工作可以使ldr pc来完成;start.s是u-boot启动所执行的第一个文件,它说做的是设置系统堆栈和cpu的工作方式,为进入c程序奠定基础。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
网上有关AVR的bootloader配置大部分都是关于ICCAVR的,我用Atmel Studio 6.1弄了好久才出来,这里给大家讲下(我用的AT90CAN32)首先程序和马老师的几乎一样,只是稍微有改进,因为Atmel Studio 6.1本身有boot.h文件,包含该文件之后可以省去一些汇编的语言。
程序会在最后附上。
下面主要说下配置问题。
1、熔丝位配置:如图1图1JTAGEN 或SPIEN一定要打勾使能,要不然如果bootloader烧写不成功以后就不能用JTAG或SPI了,那么单片机就锁死了,我就锁死了一个单片机,哭晕。
BOOTSZ;选择1k或2k或3k或4kBOOTRST:打勾,这样的话程序会从bootloader定义的地址开始烧写,比如我的程序会从0X3800开始写入2、如图2点击project——>文件名porperties——>toolchain出现如图3所示,点击memory settings,在FLASH segment 中输入.text=0x3800(注意0x3800是和熔丝位设置的bootloader 区的大小一样的)图2图3点击Misellaneous,输入-WI,--section-start=.text=0x7000(其中0x7000是0x3800的二倍,如果你设置的不是0x3800,那么也只需要按照你设置的乘以2就行)图4到这里就配置完成了。
如果配置完成了,那么正常情况下就可以把程序烧写进入单片机了,这时候用串口就可以从单片机向上位机发送指令了,如果三秒钟之内给单片机回复d的话,单片机回复C之后,就可以向单片机发送命令了,这里用的是超级终端,WIN7本身没有超级终端,需要下载,我下载的是如图5所示的超级终端。
打开超级终端时候注意配置波特率和结束位等,还有就是发送文件时注意选择XMODEM协议。
剩下的就可以按照ICCAVR的方法进行发送和接收了,这里主要说的是配置方法和ICCAVR的不同图5#include <avr/io.h>#include<avr/boot.h>#include <inttypes.h>#include <avr/interrupt.h>#include <avr/pgmspace.h>#include <util/delay.h>#define SPM_PAGESIZE 256 //M128的一个Flash页为256字节(128字)#define BAUD 9600//波特率采用38400bps#define CRYSTAL 10000000 //系统时钟8MHz#define baud_l(UCHAR)(baud_setting) //低位#define UCHAR unsigned char#define UINT unsigned int#define ULONG unsigned long#define USHOT unsigned short#define DATA_BUFFER_SIZE SPM_PAGESIZE //定义接收缓冲区长度//定义Xmoden控制字符#define XMODEM_NUL 0x00#define XMODEM_SOH 0x01#define XMODEM_STX 0x02#define XMODEM_EOT 0x04#define XMODEM_ACK 0x06#define XMODEM_NAK 0x15#define XMODEM_CAN 0x18#define XMODEM_EOF 0x1A#define XMODEM_RECIEVING_WAIT_CHAR 'C'//定义全局变量const char startupString[]="Type 'd' download, Others run app.\n\r\0"; UCHAR data[DATA_BUFFER_SIZE];long address = 0;#define USART0_T PORTE |= (1<<PORTE2) //USART0发送使能#define USART0_R PORTE &= ~(1<<PORTE2) //USART0接收使能/*void boot_page_ew(long p_address,char code){asm("mov r30,r22\n""mov r31,r23\n""out 0x3b,r24\n"); //将页地址放入Z 寄存器和RAMPZ 的Bit0 中SPMCSR = code; //寄存器SPMCSR 中为操作码asm("spm\n"); //对指定Flash 页进行操作}//填充Flash 缓冲页中的一个字void boot_page_fill_1(unsigned int address,int data){asm("mov r30,r24\n""mov r31,r25\n" //Z 寄存器中为填冲页内地址"mov r0,r22\n""mov r1,r23\n"); //R0R1 中为一个指令字SPMCSR = 0x01;asm("spm\n");}//等待一个Flash 页的写完成void wait_page_rw_ok(void){while(SPMCSR & 0x40){while(SPMCSR & 0x01);SPMCSR = 0x11;asm("spm\n");}}//更新一个Flash 页的完整处理void write_one_page(void){int i;boot_page_ew(address,0x03); //擦除一个Flash 页wait_page_rw_ok(); //等待擦除完成for(i=0;i<SPM_PAGESIZE;i+=2) //将数据填入Flash 缓冲页中{boot_page_fill_1(address+i, data[i]+(data[i+1]<<8));//boot_page_fill_1(0x5555, 0x4444);}boot_page_ew(address,0x05); //将缓冲页数据写入一个Flash 页wait_page_rw_ok(); //等待写入完成}*///更新一个Flash页的完整处理void write_one_page(void){int i;uint8_t sreg;sreg = SREG;UINT K;//cli();//eeprom_busy_wait ();boot_page_erase(address); //擦除一个Flash页boot_spm_busy_wait (); //等待擦除完成for(i=0;i<SPM_PAGESIZE;i+=2) //将数据填入Flash缓冲页中{K=data[i]+data[i+1]*256;boot_page_fill(address+i,K);//boot_page_fill(address+i,0x1234);}boot_page_write(address); //将缓冲页数据写入一个Flash页boot_spm_busy_wait (); //等待写入完成//boot_rww_enable ();SREG = sreg;}/*void boot_program_page (uint32_t page, uint8_t *buf){uint16_t i;uint8_t sreg;// Disable interrupts.sreg = SREG;cli();eeprom_busy_wait ();boot_page_erase (page);boot_spm_busy_wait (); // Wait until the memory is erased.for (i=0; i<SPM_PAGESIZE; i+=2){// Set up little-endian word.uint16_t w = *buf++;w += (*buf++) << 8;boot_page_fill (page + i, w);}boot_page_write (page); // Store buffer in flash page.boot_spm_busy_wait(); // Wait until the memory is written.// Reenable RWW-section again. We need this if we want to jump back// to the application after bootloading.boot_rww_enable ();// Re-enable interrupts (if they were ever enabled).SREG = sreg;}*///从RS232发送一个字节void uart_putchar(char c){while(!(UCSR0A & 0x20));UDR0 = c;}//从RS232接收一个字节int uart_getchar(void){unsigned char status,res;if(!(UCSR0A & 0x80)) return -1; //no data to be receivedstatus = UCSR0A;res = UDR0;if (status & 0x1c) return -1; // If error, return -1return res;}//等待从RS232接收一个有效的字节char uart_waitchar(void){int c;while((c=uart_getchar())==-1);return (char)c;}//计算CRCint calcrc(char *ptr, int count){int crc = 0;char i;while (--count >= 0){crc = crc ^ (int) *ptr++ << 8;i = 8;do{if (crc & 0x8000)crc = crc << 1 ^ 0x1021;elsecrc = crc << 1;} while(--i);}return (crc);}//退出Bootloader程序,从0x0000处执行应用程序void quit(void){uart_putchar('O');uart_putchar('K');uart_putchar(0x0d);uart_putchar(0x0a);while(!(UCSR0A & 0x20)); //等待结束提示信息回送完成MCUCR = 0x01;MCUCR = 0x00; //将中断向量表迁移到应用程序区头部RAMPZ = 0x00; //RAMPZ 清零初始化SPMCSR = SPMCSR&0XFE;boot_rww_enable();asm("jmp 0x0000\n"); //跳转到Flash 的0x0000 处,执行用户的应用程序uart_putchar('O');uart_putchar('K');}//主程序void main(void){int i = 0;unsigned int timercount = 0;unsigned char packNO = 1;int bufferPoint = 0;unsigned int crc;UCHAR K1,K2;//初始化M128的USART0(UINT)((ULONG)CRYSTAL/(8*(ULONG)BAUD)-1)//UBRR0H = (UINT)((ULONG)CRYSTAL/(8*(ULONG)BAUD)-1)>>8;//UBRR0L = (UINT)((ULONG)CRYSTAL/(8*(ULONG)BAUD)-1); //Set baud rateUBRR0H = (CRYSTAL/BAUD/16-1)>>8;UBRR0L = CRYSTAL/BAUD/16-1; //Set baud rateUCSR0B = 0x18; //Enable Receiver and TransmitterUCSR0C = 0x0E; //Set frame format: 8data, 2stop bit//初始化M128的T/C0,15ms自动重载TCCR3B = (1<<WGM32)|(1<<CS31)|(1<<CS30); //64分频,CTC模式TIMSK3 = (1<<OCIE3A);TIFR3 = (1<<TOV3);TCNT3H = 0;TCNT3L = 0;OCR3AH = 0x03;//定时为5ms,0x030D OCR3AL = 0x0D;//向PC机发送开始提示信息while(startupString[i]!='\0'){USART0_T;uart_putchar(startupString[i]);i++;}//3秒种等待PC下发“d”,否则退出Bootloader程序,从0x0000处执行应用程序while(1){if(uart_getchar()== 'd') break;if (TIFR3 & 0x02) //timer0 over flow{if (++timercount > 600)quit(); //600*5ms = 3sTIFR3 = TIFR3|0x02;}}//每秒向PC机发送一个控制字符“C”,等待控制字〈soh〉while(uart_getchar()!=XMODEM_SOH) //receive the start of Xmodem{if(TIFR3 & 0x02) //timer0 over flow{if(++timercount > 200) //wait about 1 second{USART0_T;uart_putchar(XMODEM_RECIEVING_WAIT_CHAR); //send a "C"timercount=0;}TIFR3=TIFR3 | 0x02;}}//开始接收数据块do{K1=uart_waitchar();K2=(~uart_waitchar());if ((packNO == K1) && (packNO ==K2)){ //核对数据块编号正确for(i=0;i<128;i++) //接收128个字节数据{data[bufferPoint]= uart_waitchar();bufferPoint++;}crc = (uart_waitchar()<<8);crc += uart_waitchar(); //接收2个字节的CRC效验字if(calcrc(&data[bufferPoint-128],128)==crc) //CRC校验验证{ //正确接收128个字节数据while(bufferPoint >= SPM_PAGESIZE){ //正确接受256个字节的数据write_one_page(); //收到256字节写入一页Flash中address += SPM_PAGESIZE; //Flash页加1bufferPoint = 0;}USART0_T;uart_putchar(XMODEM_ACK); //正确收到一个数据块packNO++; //数据块编号加1}else{USART0_T;uart_putchar(XMODEM_NAK); //要求重发数据块}}else{USART0_T;uart_putchar(XMODEM_NAK); //要求重发数据块}}while(uart_waitchar()!=XMODEM_EOT); //循环接收,直到全部发完USART0_T;uart_putchar(XMODEM_ACK); //通知PC机全部收到if(bufferPoint)write_one_page(); //把剩余的数据写入Flash中quit(); //退出Bootloader程序,从0x0000处执行应用程序}。