|
楼主 |
发表于 2006-9-27 09:47:53
|
显示全部楼层
ICC环境下,下位机程序:
/*------------------------------------------------------------------------------
- Title : cuiboot.c
- Revision : Ver1.00
- Author : cqw
- Date : 10/09/2006
--------------------------------------------------------------------------------
- Function explain : 暂未加入熔丝位更改
--------------------------------------------------------------------------------
- Modify :
------------------------------------------------------------------------------*/
#include <iom32v.h>
#include <macros.h>
#define MCU_WRITE 0xAF
#define MCU_READ 0xA0
#define MCU_RUN 0xBF
#define MCU_SETPAGE 0xB0
#define MCU_UARTACK 0xAA
#define SPM_PageSize 128 // falsh页大小(按字节)
extern void boot_page_ew (unsigned int ,unsigned char);
extern void boot_page_fill (unsigned int ,unsigned int );
extern void wait_page_rw_ok (void);
extern void write_lock_bits (unsigned char);
extern unsigned char read_program_memory(unsigned int,unsigned char);
unsigned int count;
unsigned int g_wPageIndex=0; // 页索引
unsigned char g_aPageTemp[SPM_PageSize];// 缓存
void quitboot(void) // 退出Bootloader程序,从0x0000处执行应用程序
{
//MCUCR = 0x01;
//MCUCR = 0x00; // 将中断向量表迁移到应用程序区头部
GICR = (1<<IVCE);
GICR = (0<<IVCE)|(0<<IVSEL); // 将中断向量表迁移到应用程序区头部
asm("jmp 0x0000
"); // 跳转到Flash的0x0000处,执行用户的应用程序
}
void uart_putc(unsigned char c)
{
while( !(UCSRA & (1<<UDRE)) );
UDR=c;
}
unsigned char uart_getc(void)
{
while( !(UCSRA & (1<<RXC)) );
return UDR;
}
void WritePage(void)
{
unsigned char i;
for(i=0;i<SPM_PageSize;i++)
g_aPageTemp=uart_getc(); // 接收当前页面数据
boot_page_ew(g_wPageIndex,0x03); // 擦除页
wait_page_rw_ok(); // 等待擦除完成
for(i=0;i<SPM_PageSize;i+=2) // 将数据填入Flash缓冲页中
{
boot_page_fill(i,((g_aPageTemp[i+1]<<8)|g_aPageTemp));
}
boot_page_ew(g_wPageIndex,0x05); // 将缓冲页数据写入一个Flash页
wait_page_rw_ok(); // 等待写入完成
g_wPageIndex+=SPM_PageSize;
}
void ReadPage(void)
{
unsigned int i;
for(i=0;i<SPM_PageSize;i++)
uart_putc(read_program_memory((i+g_wPageIndex),0));
g_wPageIndex+=SPM_PageSize;
}
void main(void)
{
unsigned char tmp;
unsigned int i,j;
GICR = (1<<IVCE);
GICR = (0<<IVCE)|(1<<IVSEL); // 将中断向量表迁移到Boot区头部
CLI(); // 关闭中断
/*定时器初始化
TCNT0 = 0xB8; // 10ms prescale:1024
OCR0 = 0x47;
TCCR0 = 0x05; */
/*串口初始化*/
UBRRH=0;
UBRRL=0x5F; // 4800Mhz
UCSRB=(1<<RXEN)|(1<<TXEN);
count = 0; // 3s boot程序停留时间
g_wPageIndex = 0;
/*
while(1)
{
if(uart_getc()== MCU_UARTACK)
{
count = 0;
uart_putc(MCU_UARTACK);
break;
}
if (TIFR & (1<<OCF0)) // timer0 over flow
{
TCNT0 = 0xB8;
if ( ++count > 300 )
{
quitboot(); // 跳转到Flash的0x0000处,执行用户的应用程序
}
TIFR = TIFR|(1<<OCF0);
}
} */
i=0;
j=0;
while(1)
{
tmp=uart_getc(); // recv command
if ( tmp == MCU_SETPAGE ) // 设置页地址
{
g_wPageIndex=uart_getc();
}
else if ( tmp == MCU_WRITE ) // 写一页
{
WritePage();
uart_putc(MCU_UARTACK); // 应答
}
else if ( tmp == MCU_READ ) // 读
{
ReadPage();
}
else if ( tmp == MCU_RUN ) // 运行用户程序
{
quitboot();
}
else if ( tmp == MCU_UARTACK ) // 回应检测命令
{
uart_putc(MCU_UARTACK);
}/*
if (TIFR & (1<<OCF0)) // timer0 over flow
{
TCNT0 = 0xB8;
if ( count )
{
if ( --count <=1 )
{
quitboot(); // 跳转到Flash的0x0000处,执行用户的应用程序
}
}
TIFR = TIFR|(1<<OCF0);
}
if (++i>100)
j++;
if (j>100)
quitboot(); */
/*
for ( i=0;i<10; i++)
{
for( j=0;j<1000; j++);
}
GICR = (1<<IVCE);
GICR = (0<<IVCE)|(0<<IVSEL); // 将中断向量表迁移到应用程序区头部
asm("jmp 0x0000
"); // 跳转到Flash的0x0000处,执行用户的应用程序 */
}
}
********************************************************************************
/*------------------------------------------------------------------------------
- Title : selfprgo.c
- Revision : Ver1.00
- Author : cqw
- Date : 10/09/2006
--------------------------------------------------------------------------------
- Function explain :SPM操作函数,根据machao程序改编
--------------------------------------------------------------------------------
- Modify :
------------------------------------------------------------------------------*/
#include <iom32v.h>
#include <macros.h>
#define R0 (*(volatile unsigned char *)0x00)
/*------------------------------------------------------------------------------
functionName:void someNop(void)
description: 擦除(code=0x03)和写入(code=0x05)一个Flash页
------------------------------------------------------------------------------*/
void boot_page_ew(unsigned int pageAddr,unsigned char code)
{
asm("mov r30,r16
"
"mov r31,r17
"); // 将页地址放入Z寄存器和RAMPZ的Bit0中
SPMCR = code; // 寄存器SPMCSR中为操作码
asm("spm
"); // 对指定Flash页进行操作
}
/*------------------------------------------------------------------------------
functionName:void boot_page_fill(unsigned int address,unsigned int data)
description: 填充Flash缓冲页中的一个字
------------------------------------------------------------------------------*/
void boot_page_fill(unsigned int address,unsigned int data)
{
asm("mov r30,r16
"
"mov r31,r17
" // Z寄存器中为填冲页内地址
"mov r0,r18
"
"mov r1,r19
"); // R0R1中为一个指令字
SPMCR = 0x01;
asm("spm
");
}
/*------------------------------------------------------------------------------
functionName:void wait_page_rw_ok(void)
description: 等待一个Flash页的写完成
------------------------------------------------------------------------------*/
void wait_page_rw_ok(void)
{
while(SPMCR & 0x40)
{
while(SPMCR & 0x01);
SPMCR = 0x11;
asm("spm
");
}
}
/*------------------------------------------------------------------------------
functionName:void write_lock_bits (unsigned char val)
description:写锁定位
------------------------------------------------------------------------------*/
void write_lock_bits (unsigned char val)
{
asm("mov r0,r16
");
SPMCR=0x09;
asm("spm
");
while(SPMCR&BIT(0));
SPMCR = 0x11;
asm("spm
");
}
/*------------------------------------------------------------------------------
functionName:unsigned char read_program_memory (unsigned int addr,unsigned char cmd)
description: 返回addr地址数据,以字节为单位
cmd:
0:读flashrom
1:读熔丝位或者锁定位
addr=0x0001 锁定位
addr=0x0000 熔丝位低字节
addr=0x0003 熔丝位高字节
------------------------------------------------------------------------------*/
unsigned char read_program_memory(unsigned int addr,unsigned char cmd)
{
asm("mov r30,r16
"
"mov r31,r17
");
if(cmd)
{
SPMCR=0x09;
}
asm("lpm r0,z
");
return(R0);
} |
|