专家
公告
财富商城
电子网
旗下网站
首页
问题库
专栏
标签库
话题
专家
NEW
门户
发布
提问题
发文章
神奇的bootloader !大神们进来看看!
2019-03-24 20:22
发布
×
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
站内问答
/
Atmel MCU
2651
4
1029
本帖最后由 285844685 于 2015-9-3 08:45 编辑
代码是往5922恒流led驱动里写数, 用jtag往里烧的时候都能正常运行,但是第三种写法用bootloader往里刷的程序就不能正常运行 ,上电后会卡死,程序跑飞。第一种写法用bootloader就正常。
复制代码
Program Memory Usage : 27030 bytes 19.4 % Full
Data Memory Usage : 1159 bytes 14.1 % Full
大神们帮看看是什么情况。
void TLC5922_WriteDC(unsigned char dc)
{
unsigned char i,j;
TLC5922_Mode_DC; //MODE = 1;
XTAL1_Output_is_Low; //XLAT = 0;
Sclk_Output_is_Low; //SCLK = 0;
Sin1_Output_is_Low; //SIN = 0;
for(i=0;i<112;i++) //每?个?led一°?个?dc字á?节¨2
{
for(j=0;j<7;j++) //dc_number范¤?围¡ì0~127 dc7bit依°¨¤次ä?串ä?行D写¡ä入¨?
{
Sclk_Output_is_Low; //SCLK = 0;
if((dc&0x40)==0x40)
{
Sin1_Output_is_Hig; //SIN = 1;
}
else if((dc&0x40)==0)
{
Sin1_Output_is_Low; //SIN = 0;
}
Sclk_Output_is_Low;
delay_us(1);
Sclk_Output_is_Hig;
delay_us(1);
Sclk_Output_is_Low;
dc <<= 1; //左ᨮ移°?一°?位?
}
dc=127; //下?一°?个?字á?节¨2
}
XTAL1_Output_is_Low;
XTAL2_Output_is_Low;
XTAL3_Output_is_Low;
XTAL4_Output_is_Low;
XTAL5_Output_is_Low;
XTAL6_Output_is_Low;
XTAL7_Output_is_Low;
delay_us(1);
XTAL1_Output_is_Hig;
XTAL2_Output_is_Hig;
XTAL3_Output_is_Hig;
XTAL4_Output_is_Hig;
XTAL5_Output_is_Hig;
XTAL6_Output_is_Hig;
XTAL7_Output_is_Hig;
delay_us(1);
XTAL1_Output_is_Low;
XTAL2_Output_is_Low;
XTAL3_Output_is_Low;
XTAL4_Output_is_Low;
XTAL5_Output_is_Low;
XTAL6_Output_is_Low;
XTAL7_Output_is_Low; //XLAT = 1//XLAT 高?电ì?平?将?点ì?校¡ê正y数oy据Y锁?存ä?到ì? 7Bit DC Register
delay_us(1);
}
void TLC5922_WriteDC(unsigned char dc)
{
unsigned char i,j;
unsigned char temp;
TLC5922_Mode_DC; //MODE = 1;
XTAL1_Output_is_Low; //XLAT = 0;
Sclk_Output_is_Low; //SCLK = 0;
Sin1_Output_is_Low; //SIN = 0;
temp=dc;
for(i=0;i<LED_NUMBER;i++) //每个led一个dc字节
{
for(j=0;j<7;j++) //dc_number范围0~127 dc7bit依次串行写入
{
Sclk_Output_is_Low; //SCLK = 0;
if((temp&0x40)==0x40)
{
Sin1_Output_is_Hig; //SIN = 1;
}
else if((temp&0x40)==0)
{
Sin1_Output_is_Low; //SIN = 0;
}
Sclk_Output_is_Low;
delay_us(1);
Sclk_Output_is_Hig;
delay_us(1);
Sclk_Output_is_Low;
temp <<= 1; //左移一位
}
temp=dc; //下一个字节
}
XTAL1_Output_is_Low;
XTAL2_Output_is_Low;
XTAL3_Output_is_Low;
XTAL4_Output_is_Low;
XTAL5_Output_is_Low;
XTAL6_Output_is_Low;
XTAL7_Output_is_Low;
delay_us(1);
XTAL1_Output_is_Hig;
XTAL2_Output_is_Hig;
XTAL3_Output_is_Hig;
XTAL4_Output_is_Hig;
XTAL5_Output_is_Hig;
XTAL6_Output_is_Hig;
XTAL7_Output_is_Hig;
delay_us(1);
XTAL1_Output_is_Low;
XTAL2_Output_is_Low;
XTAL3_Output_is_Low;
XTAL4_Output_is_Low;
XTAL5_Output_is_Low;
XTAL6_Output_is_Low;
XTAL7_Output_is_Low; //XLAT = 1//XLAT 高电平将点校正数据锁存到 7Bit DC Register
delay_us(1);
}
void TLC5922_WriteDC(unsigned char *dc)
{
unsigned char i,j;
TLC5922_Mode_DC; //MODE = 1;
XTAL1_Output_is_Low; //XLAT = 0;
Sclk_Output_is_Low; //SCLK = 0;
Sin1_Output_is_Low; //SIN = 0;
for(i=0;i<LED_NUMBER;i++) //每个led一个dc字节
{
for(j=0;j<7;j++) //dc_number范围0~127 dc7bit依次串行写入
{
Sclk_Output_is_Low; //SCLK = 0;
if((*dc&0x40)==0x40)
{
Sin1_Output_is_Hig; //SIN = 1;
}
else if((*dc&0x40)==0)
{
Sin1_Output_is_Low; //SIN = 0;
}
Sclk_Output_is_Low;
delay_us(1);
Sclk_Output_is_Hig;
delay_us(1);
Sclk_Output_is_Low;
*dc <<= 1; //左移一位
}
dc ++; //下一个字节
}
XTAL1_Output_is_Low;
XTAL2_Output_is_Low;
XTAL3_Output_is_Low;
XTAL4_Output_is_Low;
XTAL5_Output_is_Low;
XTAL6_Output_is_Low;
delay_us(1);
XTAL1_Output_is_Hig;
XTAL2_Output_is_Hig;
XTAL3_Output_is_Hig;
XTAL4_Output_is_Hig;
XTAL5_Output_is_Hig;
XTAL6_Output_is_Hig;;
delay_us(1);
XTAL1_Output_is_Low;
XTAL2_Output_is_Low;
XTAL3_Output_is_Low;
XTAL4_Output_is_Low;
XTAL5_Output_is_Low;
XTAL6_Output_is_Low;; //XLAT = 1//XLAT 高电平将点校正数据锁存到 7Bit DC Register
delay_us(1);
}
复制代码
此帖出自
小平头技术问答
友情提示:
此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
4条回答
dcexpert
1楼-- · 2019-03-25 02:31
不同用法在哪里?
加载中...
285844685
2楼-- · 2019-03-25 04:42
dcexpert 发表于 2015-9-3 09:57
不同用法在哪里?
就是一个是常值 一个是去数组里按地址取数
加载中...
285844685
3楼-- · 2019-03-25 10:20
用的是xmega128
加载中...
285844685
4楼-- · 2019-03-25 13:35
#include "usart.h"
#include "bootcfg.h"
#include "sp_driver.h"
#include "XMODEM.h"
#include "timer.h"
#include "clksys_driver.h"
//使用UARTD0 定义下载串口
#define USART USARTD0
#define USART_PORT PORTD
#define USART_TX PIN3_bm
#define USART_RX PIN2_bm
//flash页的大小
#define BUFSIZE SPM_PAGESIZE
//用户程序起始地
#define PROG_START PROGMEM_START
//flashaddr偏移地址
#define flashAddr_offset 51200
//----------------------------------------------------------------------------
//接收缓冲区
uint8_t XmodemBuffer[128]; //用于接收XMODEM发送的128字节一帧数据
uint8_t WriteBuffer[BUFSIZE]; //用于装载flash缓冲页
uint8_t buf1[BUFSIZE];
uint8_t ReadBuffer[BUFSIZE]; //读取flash页缓冲区
uint8_t upgrade_ok_flag=0;
uint8_t Packnum=0;
uint8_t temp_ch,temp_cl;
uint8_t Update_state[10]={0x5B,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x5B};
uint8_t cnt,j;
uint8_t blockcount=0;
uint8_t App_sourcecodes_page_count;
//Flash地址指针
unsigned long int FlashAddr= PROG_START;
unsigned long int FlashAddr_temp;
//unsigned long int FlashAddr= PROG_START;
//----------------------------------------------------------------------------
void putstr(const char *str);
void repay_sysclk();
//写入数据到串口
void WriteCom(unsigned char data)
{
do{
/* Wait until it is possible to put data into TX data register.
* NOTE: If TXDataRegister never becomes empty this will be a DEADLOCK. */
}while(!USART_IsTXDataRegisterEmpty(&USART));
USART_PutChar(&USART, data);
}
//----------------------------------------------------------------------------
//发送字符串并添加回车
void putstr(const char *str)
{
while(*str)
WriteCom(*str++);
// WriteCom(0x0D);
// WriteCom(0x0A); //发送回车
//WriteCom(0x0A); //发送回车
}
//----------------------------------------------------------------------------
//等待串口数据
unsigned char WaitCom(void)
{
do{
/* Wait until data received */
}while(!USART_IsRXComplete(&USART));
return(USART_GetChar(&USART));
}
//----------------------------------------------------------------------------
//更新一个Flash页
void write_one_page(unsigned char *buf,unsigned long int flashaddr)
{
FlashAddr_temp=flashaddr;
//数据填入Flash缓冲页
/* Load the flashbuffer with the test buffer. */
SP_LoadFlashPage(buf);
/* Perform page erase. *///将缓冲页数据写入一个Flash页
SP_EraseWriteApplicationPage(FlashAddr_temp);
/* Wait for NVM to finish. */
SP_WaitForSPM();//等待页编程完成
//FlashAddr=FlashAddr+BUFSIZE;
}
//----------------------------------------------------------------------------
//跳转到用户程序
void quit()
{
// putstr(msg7); //提示进入Application
EIND=0x00;
asm("ldi r30,0x00");
asm("ldi r31,0x00");
asm("eijmp");
}
void jmp_bootloader()
{
//putstr(msg5); //提示写入Flash数据错误,重新操作一次
// putstr(msg6);
WriteCom(0x5a);
WriteCom(0x02);
WriteCom(0x5a);
EIND=0x01;
asm("ldi r30,0x00");
asm("ldi r31,0x00");
asm("eijmp");
}
//----------------------------------------------------------------------------
//串口初始化9600,8,N,1,@32M CPU时钟
void USART_initial(void)
{
/* (TXD) as output. */
USART_PORT.DIRSET = USART_TX;
/* (RXD) as input. */
USART_PORT.DIRCLR = USART_RX;
/* USART, 8 Data bits, No Parity, 1 Stop bit. */
USART_Format_Set(&USART, USART_CHSIZE_8BIT_gc, USART_PMODE_DISABLED_gc, 0);
/* Set Baudrate to 9600 bps:
* Use the default I/O clock fequency that is 16 MHz.
* Do not use the baudrate scale factor
* Baudrate select = (1/(16*(((I/O clock frequency)/Baudrate)-1)
* = 103
*/
//USART_Baudrate_Set(&USART, 2484 , 12); //9600
USART_Baudrate_Set(&USART, 1539 , 9); //9600
/* Enable both RX and TX. */
USART_Rx_Enable(&USART);
USART_Tx_Enable(&USART);
}
//----------------------------------------------------------------------------
//设置系统时钟 为外部晶振 12M
//----------------------------------------------------------------------------
void sysclk_XOSCinitial()
{
/* Enable
internal 32 MHz ring oscillator and wait until it's
* stable. Divide clock by two with the prescaler C and set the
* 32 MHz ring oscillator as the main clock source.
*/
CLKSYS_XOSC_Config(OSC_FRQRANGE_12TO16_gc,1,OSC_XOSCSEL_XTAL_1KCLK_gc);
CLKSYS_Enable( OSC_XOSCEN_bm );
//OSC_XOSCCTRL=0x83;
CLKSYS_Prescalers_Config( CLK_PSADIV_1_gc, CLK_PSBCDIV_1_1_gc ); //Pc为2分频,T0工作在16M
do {} while ( CLKSYS_IsReady( OSC_XOSCRDY_bm ) == 0 );
//CLKSYS_Prescalers_Config( CLK_PSADIV_1_gc, CLK_PSBCDIV_1_1_gc ); //Pc为2分频,T0工作在16M
CLKSYS_Main_ClockSource_Select( CLK_SCLKSEL_XOSC_gc );
}
//----------------------------------------------------------------------------
//设置系统时钟 锁相环倍频 24M
//----------------------------------------------------------------------------
void sysclk_PLLinitial()
{
/* Enable
internal 32 MHz ring oscillator and wait until it's
* stable. Divide clock by two with the prescaler C and set the
* 32 MHz ring oscillator as the main clock source.
*/
CLKSYS_XOSC_Config(OSC_FRQRANGE_12TO16_gc,1,OSC_XOSCSEL_XTAL_1KCLK_gc);
//CLKSYS_Enable( OSC_XOSCEN_bm );
CLKSYS_Enable( OSC_XOSCEN_bm | OSC_RC2MCREF_bm);
do {} while ( CLKSYS_IsReady( OSC_XOSCRDY_bm ) == 0 );
//CLKSYS_PLL_Config(OSC_PLLSRC_XOSC_gc,OSC_PLLFAC1_bm);
CLKSYS_PLL_Config(OSC_PLLSRC_XOSC_gc,4); //change 20140916
CLKSYS_Enable( OSC_PLLEN_bm );
//CLKSYS_Prescalers_Config( CLK_PSADIV_1_gc, CLK_PSBCDIV_1_1_gc );
CLKSYS_Prescalers_Config( CLK_PSADIV_2_gc, CLK_PSBCDIV_1_1_gc ); //change 20140916
// CLKSYS_Configuration_Lock( );
do {} while ( CLKSYS_IsReady( OSC_PLLRDY_bm ) == 0 );
//CLKSYS_Prescalers_Config( CLK_PSADIV_1_gc, CLK_PSBCDIV_1_1_gc );
CLKSYS_Main_ClockSource_Select( CLK_SCLKSEL_PLL_gc );
}
//----------------------------------------------------------------------------
//设置系统时钟 为内部RC 32M
//----------------------------------------------------------------------------
void sysclk_initial()
{
/* Enable internal 32 MHz ring oscillator and wait until it's
* stable. Divide clock by two with the prescaler C and set the
* 32 MHz ring oscillator as the main clock source.
*/
CLKSYS_Enable( OSC_RC32MEN_bm );
CLKSYS_Prescalers_Config( CLK_PSADIV_1_gc, CLK_PSBCDIV_1_2_gc ); //Pc为2分频,T0工作在16M
do {} while ( CLKSYS_IsReady( OSC_RC32MRDY_bm ) == 0 );
CLKSYS_Main_ClockSource_Select( CLK_SCLKSEL_RC32M_gc );
}
//设置系统时钟 为内部RC 2M
//----------------------------------------------------------------------------
void repay_sysclk()
{
/* Select 2 MHz RC oscillator as main clock source and diable
* unused clock.
*/
do {} while ( CLKSYS_IsReady( OSC_RC2MRDY_bm ) == 0 );
CLKSYS_Prescalers_Config( CLK_PSADIV_1_gc, CLK_PSBCDIV_1_1_gc );
CLKSYS_Main_ClockSource_Select( CLK_SCLKSEL_RC2M_gc );
CLKSYS_Disable( OSC_PLLEN_bm ); //关掉PLL
}
void delay(uint32_t delay)
{
uint32_t i;
for (i=delay;i>0;i--)
{
asm("NOP");
}
}
uint16_t calcrc(uint8_t *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;
else
crc = crc << 1;
} while(--i);
}
return (crc);
}
void LED_initial()
{
PORTF_DIR=0xff;
PORTF_OUTSET=0xff;
LED1_select_enable;
LED2_select_enable;
LED3_select_enable;
LED4_select_enable;
delay(1200000);
PORTF_OUTCLR=0xff;
delay(1200000);
PORTF_OUTSET=0xff;
delay(1200000);
PORTF_OUTCLR=0xff;
delay(1200000);
PORTF_OUTSET=0xff;
delay(1200000);
PORTF_OUTCLR=0xff;
delay(1200000);
PORTF_OUTSET=0xff;
LED1_select_enable;
LED1_select_LOCK;
LED3_select_enable;
LED3_select_LOCK;
LED4_select_enable;
LED4_select_LOCK;
PORTF_OUTCLR=3<<6;
LED2_select_enable;
LED2_select_LOCK;
}
//主程序
//----------------------------------------------------------------------------
int main(void)
{
uint8_t get_char,signal=0;
uint8_t crch, crcl;
uint16_t crc0;
uint16_t i,k;
sysclk_PLLinitial(); //设定系统时钟
USART_initial(); //串口初始化
Timertc0_initial(); //定时器初始化 时隙:200MS
USB_INTFLAGSACLR=0x00;
USB_INTFLAGSASET=0x00;
cnt = TimeOutCntC;
signal=0;
while(signal==0)
{
if(TC_GetOverflowFlag(&TCC0)) //T1溢出
{
TC_ClearOverflowFlag(&TCC0);
WriteCom(XMODEM_RWC); //发送 "C"
cnt--;
if(cnt==0) //超时
{
/* Update_state[1]=0x02;
Update_state[8]=0x00;
for(j=0;j<10;j++)
{
WriteCom(Update_state[j]);
//delay_us(240000);
}
//delay_us(240000);
FlashAddr=flashAddr_offset-BUFSIZE*2;
SP_ReadFlashPage(ReadBuffer,FlashAddr);
App_sourcecodes_page_count=ReadBuffer[0];
FlashAddr=flashAddr_offset-BUFSIZE;
SP_ReadFlashPage(WriteBuffer,FlashAddr);
for(i=0;i<10;i++)
{
if(i!=WriteBuffer[i])
{
FlashAddr=0;
j=0;
while(j<App_sourcecodes_page_count)
{
SP_ReadFlashPage(WriteBuffer,(FlashAddr+flashAddr_offset+512*j));
write_one_page(WriteBuffer,(FlashAddr+512*j));
SP_ReadFlashPage(ReadBuffer,(FlashAddr+512*j));
j++;
for(i=0;i<512;i++)
{
if(ReadBuffer[i]!=WriteBuffer[i])
{
j--;
break;
}
}
}
for(k=0;k<512;k++)
WriteBuffer[k]=k;
FlashAddr=flashAddr_offset-BUFSIZE;
write_one_page(WriteBuffer,FlashAddr);
while(1)
{
write_one_page(WriteBuffer,FlashAddr);
SP_ReadFlashPage(ReadBuffer,FlashAddr);
if((ReadBuffer[1]==WriteBuffer[1])&&(ReadBuffer[1]==1))
break;
}
break;
}
}*/
delay_us(240000);
repay_sysclk(); //change 20140827
quit(); //退出 bootloader
}
}
if(USART_IsRXComplete(&USART)) //收到字符?
{
get_char=USART_GetChar(&USART);
if(get_char == XMODEM_SOH) //XMODEM命令开始
{
signal=1;
break;
}
}
}
//已经收到一个起启字符了 开始更新Application
//----------------------------------------------------------------
Timertc0_Stop(); //关闭定时器0
//开始接受数据
cnt = 0;
do
{
Packnum++;
temp_ch=WaitCom();
temp_cl=WaitCom();
if((Packnum==temp_ch)&&(temp_cl==(255-temp_ch))) //包序号对上了!
{
for(i =0; i <128; i++) //接收完整一帧数据
{
XmodemBuffer[i] = WaitCom();
}
temp_ch = WaitCom(); //获取校验字节
temp_cl = WaitCom();
crc0=calcrc(&XmodemBuffer[0],128); //计算校验
crch=(crc0>>8)&0xff;
crcl=crc0&0xff;
if((crch == temp_ch) && (crcl == temp_cl)) //校验成功
{
for(i=0;i<128;i++)
{
if((XmodemBuffer[i]==0x1a)&&(XmodemBuffer[i]==XmodemBuffer[127]))
XmodemBuffer[i]=0xff;
}
for(i=0;i<128;i++)
{
WriteBuffer[128*blockcount+i]=XmodemBuffer[i]; //凑满flash缓冲页256字节
}
blockcount++;
if(blockcount>=4)
{
blockcount=0;
write_one_page(WriteBuffer,(FlashAddr+flashAddr_offset)); //写入flash一页
SP_ReadFlashPage(ReadBuffer,(FlashAddr+flashAddr_offset)); //读取flash内容
FlashAddr=FlashAddr+512;
for(i=0;i<512;i++)
{
if(ReadBuffer[i]!=WriteBuffer[i]) //flash内容与缓冲区内容进行比较,不同则重新进入bootloader
{
WriteCom(XMODEM_CAN);
jmp_bootloader();
}
}
for (i=0;i<512;i++)
{
WriteBuffer[i]=0xff;
}
//PORTE_IN&0xff;
}
WriteCom(XMODEM_ACK);
}
else
{
WriteCom(XMODEM_NAK);
}
}
else
{
WriteCom(XMODEM_NAK);
}
}while(WaitCom()!=XMODEM_EOT);
WriteCom(XMODEM_ACK);
write_one_page(WriteBuffer,(FlashAddr+flashAddr_offset));
SP_ReadFlashPage(ReadBuffer,(FlashAddr+flashAddr_offset));
for(i=0;i<512;i++)
{
if(ReadBuffer[i]!=WriteBuffer[i])
jmp_bootloader();
}
for(i=0;i<512;i++)
{
WriteBuffer[i]=0xff;
ReadBuffer[i]=0x00;
}
App_sourcecodes_page_count=FlashAddr>>9;
FlashAddr=flashAddr_offset-BUFSIZE;
while(1)
{
// SP_EraseApplicationPage(FlashAddr);
write_one_page(WriteBuffer,FlashAddr);
SP_ReadFlashPage(ReadBuffer,FlashAddr);
if((ReadBuffer[1]==WriteBuffer[1])&&(ReadBuffer[1]==0xff))
break;
}
for(i=0;i<512;i++)
WriteBuffer[i]=App_sourcecodes_page_count;
FlashAddr=flashAddr_offset-BUFSIZE*2;
while(1)
{
write_one_page(WriteBuffer,FlashAddr);
SP_ReadFlashPage(ReadBuffer,FlashAddr);
if(ReadBuffer[0]==App_sourcecodes_page_count)
break;
}
FlashAddr=0;
j=0;
while(j<App_sourcecodes_page_count)
{
SP_ReadFlashPage(WriteBuffer,(FlashAddr+flashAddr_offset+512*j));
write_one_page(WriteBuffer,(FlashAddr+512*j));
SP_ReadFlashPage(ReadBuffer,(FlashAddr+512*j));
j++;
for(i=0;i<512;i++)
{
if(ReadBuffer[i]!=WriteBuffer[i])
{
j--;
break;
}
}
}
FlashAddr=0;
for(i=0;i<512;i++)
WriteBuffer[i]=i;
FlashAddr=flashAddr_offset-BUFSIZE;
//write_one_page(WriteBuffer,FlashAddr);
while(1)
{
write_one_page(WriteBuffer,FlashAddr);
SP_ReadFlashPage(ReadBuffer,FlashAddr);
if((ReadBuffer[1]==WriteBuffer[1])&&(ReadBuffer[1]==1))
break;
}
/*for(i=0;i<512;i++)
WriteBuffer[i]=App_sourcecodes_page_count;
FlashAddr=flashAddr_offset-BUFSIZE*2;
write_one_page(WriteBuffer,FlashAddr);*/
Update_state[1]=0x02;
Update_state[8]=0x01;
for(j=0;j<11;j++)
{
WriteCom(Update_state[j]);
}
delay_us(240000);
repay_sysclk(); //change 20140827
quit();
}
复制代码
感觉像是boot代码有问题。有大神帮看看擦写的部分吗
加载中...
一周热门
更多
>
相关问题
相关文章
Arduino-每个人的微控制器
0个评论
一款由长短音密码控制的门禁密码锁的设计
0个评论
IAR Embedded Workbench for Atmel AVR 6.10 环境配置
0个评论
×
关闭
采纳回答
向帮助了您的网友说句感谢的话吧!
非常感谢!
确 认
×
关闭
编辑标签
最多设置5个标签!
保存
关闭
×
关闭
举报内容
检举类型
检举内容
检举用户
检举原因
广告推广
恶意灌水
回答内容与提问无关
抄袭答案
其他
检举说明(必填)
提交
关闭
×
关闭
您已邀请
15
人回答
查看邀请
擅长该话题的人
回答过该话题的人
我关注的人
就是一个是常值 一个是去数组里按地址取数
- #include "usart.h"
- #include "bootcfg.h"
- #include "sp_driver.h"
- #include "XMODEM.h"
- #include "timer.h"
- #include "clksys_driver.h"
- //使用UARTD0 定义下载串口
- #define USART USARTD0
- #define USART_PORT PORTD
- #define USART_TX PIN3_bm
- #define USART_RX PIN2_bm
- //flash页的大小
- #define BUFSIZE SPM_PAGESIZE
- //用户程序起始地
- #define PROG_START PROGMEM_START
- //flashaddr偏移地址
- #define flashAddr_offset 51200
- //----------------------------------------------------------------------------
- //接收缓冲区
- uint8_t XmodemBuffer[128]; //用于接收XMODEM发送的128字节一帧数据
- uint8_t WriteBuffer[BUFSIZE]; //用于装载flash缓冲页
- uint8_t buf1[BUFSIZE];
- uint8_t ReadBuffer[BUFSIZE]; //读取flash页缓冲区
- uint8_t upgrade_ok_flag=0;
- uint8_t Packnum=0;
- uint8_t temp_ch,temp_cl;
- uint8_t Update_state[10]={0x5B,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x5B};
- uint8_t cnt,j;
- uint8_t blockcount=0;
- uint8_t App_sourcecodes_page_count;
- //Flash地址指针
- unsigned long int FlashAddr= PROG_START;
- unsigned long int FlashAddr_temp;
- //unsigned long int FlashAddr= PROG_START;
- //----------------------------------------------------------------------------
- void putstr(const char *str);
- void repay_sysclk();
- //写入数据到串口
- void WriteCom(unsigned char data)
- {
- do{
- /* Wait until it is possible to put data into TX data register.
- * NOTE: If TXDataRegister never becomes empty this will be a DEADLOCK. */
- }while(!USART_IsTXDataRegisterEmpty(&USART));
- USART_PutChar(&USART, data);
- }
- //----------------------------------------------------------------------------
- //发送字符串并添加回车
- void putstr(const char *str)
- {
- while(*str)
- WriteCom(*str++);
- // WriteCom(0x0D);
- // WriteCom(0x0A); //发送回车
- //WriteCom(0x0A); //发送回车
- }
- //----------------------------------------------------------------------------
- //等待串口数据
- unsigned char WaitCom(void)
- {
- do{
- /* Wait until data received */
- }while(!USART_IsRXComplete(&USART));
- return(USART_GetChar(&USART));
- }
- //----------------------------------------------------------------------------
- //更新一个Flash页
- void write_one_page(unsigned char *buf,unsigned long int flashaddr)
- {
- FlashAddr_temp=flashaddr;
- //数据填入Flash缓冲页
- /* Load the flashbuffer with the test buffer. */
- SP_LoadFlashPage(buf);
- /* Perform page erase. *///将缓冲页数据写入一个Flash页
- SP_EraseWriteApplicationPage(FlashAddr_temp);
- /* Wait for NVM to finish. */
- SP_WaitForSPM();//等待页编程完成
- //FlashAddr=FlashAddr+BUFSIZE;
- }
- //----------------------------------------------------------------------------
- //跳转到用户程序
- void quit()
- {
- // putstr(msg7); //提示进入Application
- EIND=0x00;
- asm("ldi r30,0x00");
- asm("ldi r31,0x00");
- asm("eijmp");
- }
- void jmp_bootloader()
- {
- //putstr(msg5); //提示写入Flash数据错误,重新操作一次
- // putstr(msg6);
- WriteCom(0x5a);
- WriteCom(0x02);
- WriteCom(0x5a);
- EIND=0x01;
- asm("ldi r30,0x00");
- asm("ldi r31,0x00");
- asm("eijmp");
- }
- //----------------------------------------------------------------------------
- //串口初始化9600,8,N,1,@32M CPU时钟
- void USART_initial(void)
- {
- /* (TXD) as output. */
- USART_PORT.DIRSET = USART_TX;
- /* (RXD) as input. */
- USART_PORT.DIRCLR = USART_RX;
- /* USART, 8 Data bits, No Parity, 1 Stop bit. */
- USART_Format_Set(&USART, USART_CHSIZE_8BIT_gc, USART_PMODE_DISABLED_gc, 0);
- /* Set Baudrate to 9600 bps:
- * Use the default I/O clock fequency that is 16 MHz.
- * Do not use the baudrate scale factor
- * Baudrate select = (1/(16*(((I/O clock frequency)/Baudrate)-1)
- * = 103
- */
- //USART_Baudrate_Set(&USART, 2484 , 12); //9600
- USART_Baudrate_Set(&USART, 1539 , 9); //9600
- /* Enable both RX and TX. */
- USART_Rx_Enable(&USART);
- USART_Tx_Enable(&USART);
- }
- //----------------------------------------------------------------------------
- //设置系统时钟 为外部晶振 12M
- //----------------------------------------------------------------------------
- void sysclk_XOSCinitial()
- {
- /* Enable
- internal 32 MHz ring oscillator and wait until it's
- * stable. Divide clock by two with the prescaler C and set the
- * 32 MHz ring oscillator as the main clock source.
- */
- CLKSYS_XOSC_Config(OSC_FRQRANGE_12TO16_gc,1,OSC_XOSCSEL_XTAL_1KCLK_gc);
- CLKSYS_Enable( OSC_XOSCEN_bm );
- //OSC_XOSCCTRL=0x83;
- CLKSYS_Prescalers_Config( CLK_PSADIV_1_gc, CLK_PSBCDIV_1_1_gc ); //Pc为2分频,T0工作在16M
- do {} while ( CLKSYS_IsReady( OSC_XOSCRDY_bm ) == 0 );
- //CLKSYS_Prescalers_Config( CLK_PSADIV_1_gc, CLK_PSBCDIV_1_1_gc ); //Pc为2分频,T0工作在16M
- CLKSYS_Main_ClockSource_Select( CLK_SCLKSEL_XOSC_gc );
- }
- //----------------------------------------------------------------------------
- //设置系统时钟 锁相环倍频 24M
- //----------------------------------------------------------------------------
- void sysclk_PLLinitial()
- {
- /* Enable
- internal 32 MHz ring oscillator and wait until it's
- * stable. Divide clock by two with the prescaler C and set the
- * 32 MHz ring oscillator as the main clock source.
- */
- CLKSYS_XOSC_Config(OSC_FRQRANGE_12TO16_gc,1,OSC_XOSCSEL_XTAL_1KCLK_gc);
- //CLKSYS_Enable( OSC_XOSCEN_bm );
- CLKSYS_Enable( OSC_XOSCEN_bm | OSC_RC2MCREF_bm);
- do {} while ( CLKSYS_IsReady( OSC_XOSCRDY_bm ) == 0 );
- //CLKSYS_PLL_Config(OSC_PLLSRC_XOSC_gc,OSC_PLLFAC1_bm);
- CLKSYS_PLL_Config(OSC_PLLSRC_XOSC_gc,4); //change 20140916
- CLKSYS_Enable( OSC_PLLEN_bm );
- //CLKSYS_Prescalers_Config( CLK_PSADIV_1_gc, CLK_PSBCDIV_1_1_gc );
- CLKSYS_Prescalers_Config( CLK_PSADIV_2_gc, CLK_PSBCDIV_1_1_gc ); //change 20140916
- // CLKSYS_Configuration_Lock( );
- do {} while ( CLKSYS_IsReady( OSC_PLLRDY_bm ) == 0 );
- //CLKSYS_Prescalers_Config( CLK_PSADIV_1_gc, CLK_PSBCDIV_1_1_gc );
- CLKSYS_Main_ClockSource_Select( CLK_SCLKSEL_PLL_gc );
- }
- //----------------------------------------------------------------------------
- //设置系统时钟 为内部RC 32M
- //----------------------------------------------------------------------------
- void sysclk_initial()
- {
- /* Enable internal 32 MHz ring oscillator and wait until it's
- * stable. Divide clock by two with the prescaler C and set the
- * 32 MHz ring oscillator as the main clock source.
- */
- CLKSYS_Enable( OSC_RC32MEN_bm );
- CLKSYS_Prescalers_Config( CLK_PSADIV_1_gc, CLK_PSBCDIV_1_2_gc ); //Pc为2分频,T0工作在16M
- do {} while ( CLKSYS_IsReady( OSC_RC32MRDY_bm ) == 0 );
- CLKSYS_Main_ClockSource_Select( CLK_SCLKSEL_RC32M_gc );
- }
- //设置系统时钟 为内部RC 2M
- //----------------------------------------------------------------------------
- void repay_sysclk()
- {
- /* Select 2 MHz RC oscillator as main clock source and diable
- * unused clock.
- */
- do {} while ( CLKSYS_IsReady( OSC_RC2MRDY_bm ) == 0 );
- CLKSYS_Prescalers_Config( CLK_PSADIV_1_gc, CLK_PSBCDIV_1_1_gc );
- CLKSYS_Main_ClockSource_Select( CLK_SCLKSEL_RC2M_gc );
- CLKSYS_Disable( OSC_PLLEN_bm ); //关掉PLL
- }
- void delay(uint32_t delay)
- {
- uint32_t i;
- for (i=delay;i>0;i--)
- {
- asm("NOP");
- }
- }
- uint16_t calcrc(uint8_t *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;
- else
- crc = crc << 1;
- } while(--i);
- }
- return (crc);
- }
- void LED_initial()
- {
- PORTF_DIR=0xff;
- PORTF_OUTSET=0xff;
- LED1_select_enable;
- LED2_select_enable;
- LED3_select_enable;
- LED4_select_enable;
- delay(1200000);
- PORTF_OUTCLR=0xff;
- delay(1200000);
- PORTF_OUTSET=0xff;
- delay(1200000);
- PORTF_OUTCLR=0xff;
- delay(1200000);
- PORTF_OUTSET=0xff;
- delay(1200000);
- PORTF_OUTCLR=0xff;
- delay(1200000);
- PORTF_OUTSET=0xff;
- LED1_select_enable;
- LED1_select_LOCK;
- LED3_select_enable;
- LED3_select_LOCK;
- LED4_select_enable;
- LED4_select_LOCK;
- PORTF_OUTCLR=3<<6;
- LED2_select_enable;
- LED2_select_LOCK;
- }
- //主程序
- //----------------------------------------------------------------------------
- int main(void)
- {
- uint8_t get_char,signal=0;
- uint8_t crch, crcl;
- uint16_t crc0;
- uint16_t i,k;
- sysclk_PLLinitial(); //设定系统时钟
- USART_initial(); //串口初始化
- Timertc0_initial(); //定时器初始化 时隙:200MS
- USB_INTFLAGSACLR=0x00;
- USB_INTFLAGSASET=0x00;
- cnt = TimeOutCntC;
- signal=0;
- while(signal==0)
- {
- if(TC_GetOverflowFlag(&TCC0)) //T1溢出
- {
- TC_ClearOverflowFlag(&TCC0);
- WriteCom(XMODEM_RWC); //发送 "C"
- cnt--;
- if(cnt==0) //超时
- {
- /* Update_state[1]=0x02;
- Update_state[8]=0x00;
- for(j=0;j<10;j++)
- {
- WriteCom(Update_state[j]);
- //delay_us(240000);
- }
- //delay_us(240000);
- FlashAddr=flashAddr_offset-BUFSIZE*2;
- SP_ReadFlashPage(ReadBuffer,FlashAddr);
- App_sourcecodes_page_count=ReadBuffer[0];
- FlashAddr=flashAddr_offset-BUFSIZE;
- SP_ReadFlashPage(WriteBuffer,FlashAddr);
- for(i=0;i<10;i++)
- {
- if(i!=WriteBuffer[i])
- {
- FlashAddr=0;
- j=0;
- while(j<App_sourcecodes_page_count)
- {
- SP_ReadFlashPage(WriteBuffer,(FlashAddr+flashAddr_offset+512*j));
- write_one_page(WriteBuffer,(FlashAddr+512*j));
- SP_ReadFlashPage(ReadBuffer,(FlashAddr+512*j));
- j++;
- for(i=0;i<512;i++)
- {
- if(ReadBuffer[i]!=WriteBuffer[i])
- {
- j--;
- break;
- }
- }
- }
- for(k=0;k<512;k++)
- WriteBuffer[k]=k;
- FlashAddr=flashAddr_offset-BUFSIZE;
- write_one_page(WriteBuffer,FlashAddr);
- while(1)
- {
- write_one_page(WriteBuffer,FlashAddr);
- SP_ReadFlashPage(ReadBuffer,FlashAddr);
- if((ReadBuffer[1]==WriteBuffer[1])&&(ReadBuffer[1]==1))
- break;
- }
- break;
- }
- }*/
- delay_us(240000);
- repay_sysclk(); //change 20140827
- quit(); //退出 bootloader
- }
- }
- if(USART_IsRXComplete(&USART)) //收到字符?
- {
- get_char=USART_GetChar(&USART);
- if(get_char == XMODEM_SOH) //XMODEM命令开始
- {
- signal=1;
- break;
- }
- }
-
- }
- //已经收到一个起启字符了 开始更新Application
- //----------------------------------------------------------------
- Timertc0_Stop(); //关闭定时器0
- //开始接受数据
- cnt = 0;
- do
- {
- Packnum++;
- temp_ch=WaitCom();
- temp_cl=WaitCom();
- if((Packnum==temp_ch)&&(temp_cl==(255-temp_ch))) //包序号对上了!
- {
- for(i =0; i <128; i++) //接收完整一帧数据
- {
- XmodemBuffer[i] = WaitCom();
- }
- temp_ch = WaitCom(); //获取校验字节
- temp_cl = WaitCom();
- crc0=calcrc(&XmodemBuffer[0],128); //计算校验
- crch=(crc0>>8)&0xff;
- crcl=crc0&0xff;
- if((crch == temp_ch) && (crcl == temp_cl)) //校验成功
- {
- for(i=0;i<128;i++)
- {
- if((XmodemBuffer[i]==0x1a)&&(XmodemBuffer[i]==XmodemBuffer[127]))
- XmodemBuffer[i]=0xff;
- }
- for(i=0;i<128;i++)
- {
- WriteBuffer[128*blockcount+i]=XmodemBuffer[i]; //凑满flash缓冲页256字节
- }
- blockcount++;
- if(blockcount>=4)
- {
- blockcount=0;
- write_one_page(WriteBuffer,(FlashAddr+flashAddr_offset)); //写入flash一页
- SP_ReadFlashPage(ReadBuffer,(FlashAddr+flashAddr_offset)); //读取flash内容
- FlashAddr=FlashAddr+512;
- for(i=0;i<512;i++)
- {
- if(ReadBuffer[i]!=WriteBuffer[i]) //flash内容与缓冲区内容进行比较,不同则重新进入bootloader
- {
- WriteCom(XMODEM_CAN);
- jmp_bootloader();
- }
- }
- for (i=0;i<512;i++)
- {
- WriteBuffer[i]=0xff;
- }
- //PORTE_IN&0xff;
- }
- WriteCom(XMODEM_ACK);
- }
- else
- {
- WriteCom(XMODEM_NAK);
- }
- }
- else
- {
- WriteCom(XMODEM_NAK);
- }
- }while(WaitCom()!=XMODEM_EOT);
- WriteCom(XMODEM_ACK);
- write_one_page(WriteBuffer,(FlashAddr+flashAddr_offset));
- SP_ReadFlashPage(ReadBuffer,(FlashAddr+flashAddr_offset));
- for(i=0;i<512;i++)
- {
- if(ReadBuffer[i]!=WriteBuffer[i])
- jmp_bootloader();
- }
- for(i=0;i<512;i++)
- {
- WriteBuffer[i]=0xff;
- ReadBuffer[i]=0x00;
- }
- App_sourcecodes_page_count=FlashAddr>>9;
- FlashAddr=flashAddr_offset-BUFSIZE;
- while(1)
- {
- // SP_EraseApplicationPage(FlashAddr);
- write_one_page(WriteBuffer,FlashAddr);
- SP_ReadFlashPage(ReadBuffer,FlashAddr);
- if((ReadBuffer[1]==WriteBuffer[1])&&(ReadBuffer[1]==0xff))
- break;
- }
- for(i=0;i<512;i++)
- WriteBuffer[i]=App_sourcecodes_page_count;
- FlashAddr=flashAddr_offset-BUFSIZE*2;
- while(1)
- {
- write_one_page(WriteBuffer,FlashAddr);
- SP_ReadFlashPage(ReadBuffer,FlashAddr);
- if(ReadBuffer[0]==App_sourcecodes_page_count)
- break;
- }
- FlashAddr=0;
- j=0;
- while(j<App_sourcecodes_page_count)
- {
- SP_ReadFlashPage(WriteBuffer,(FlashAddr+flashAddr_offset+512*j));
- write_one_page(WriteBuffer,(FlashAddr+512*j));
- SP_ReadFlashPage(ReadBuffer,(FlashAddr+512*j));
- j++;
- for(i=0;i<512;i++)
- {
- if(ReadBuffer[i]!=WriteBuffer[i])
- {
- j--;
- break;
- }
- }
- }
- FlashAddr=0;
- for(i=0;i<512;i++)
- WriteBuffer[i]=i;
- FlashAddr=flashAddr_offset-BUFSIZE;
- //write_one_page(WriteBuffer,FlashAddr);
- while(1)
- {
- write_one_page(WriteBuffer,FlashAddr);
- SP_ReadFlashPage(ReadBuffer,FlashAddr);
- if((ReadBuffer[1]==WriteBuffer[1])&&(ReadBuffer[1]==1))
- break;
- }
- /*for(i=0;i<512;i++)
- WriteBuffer[i]=App_sourcecodes_page_count;
- FlashAddr=flashAddr_offset-BUFSIZE*2;
- write_one_page(WriteBuffer,FlashAddr);*/
- Update_state[1]=0x02;
- Update_state[8]=0x01;
- for(j=0;j<11;j++)
- {
- WriteCom(Update_state[j]);
- }
- delay_us(240000);
- repay_sysclk(); //change 20140827
- quit();
- }
复制代码感觉像是boot代码有问题。有大神帮看看擦写的部分吗
一周热门 更多>