bootloader开发在嵌入式开发中是一个不可或缺的存在,就像bios /pc ,uboot/linux ,虽然现在的软件组件都是很成熟发达了。但是要深入嵌入式的本质还是需要从裸机开始,知道cpu是怎么启动,怎么中断跳转,怎么实现内核加载的,bootloader的编写基本上就可以覆盖这些内容。
以下是嵌入式程序在flash中分布的地址分配图,mcu在启动时会从0地址开始(也可能是一个其他什么固定地址,)运行第一行代码,这个代码一般是cpu自带的,她负责设置初始化并跳转指令将控制权交给程序员,程序员通过启动代码(汇编语言),设置堆栈以及中断向量表,然后将控制权跳转到c语言的man函数,在从里面我们就可以编写逻辑实现跟上位机交互获取固件文件并写入flash对应的地址区域,在每次启动时bootlaod先判断固件所在的区域程序是否完整,如果完整就将固件装载到ram中,然后跳转到内存的固件起始地址,并将控制权交由固件,如果没有发现固件就就进入shell等待交互,这一过程适用于所有的操作系统启动,只是复杂程度,外设驱动初始化不一样,其原理都差不多。
//片内flash为512k bytes 4k*128page
//0x9D07FFFF--0x9D000000 Program Flash
//
// PFM KERNEL AND USER MODE MAPPING
// Virtual Address Physical Address
// --------------- ----------------
// 0xBFC0_2FEF or ***************** 0x1FC0_2FEF
// 0X9FC0_2FEF * *
// * *
// * Boot Flash *
// 0xBFC0_0000 or * *
// 0x9FC0_0000 ***************** 0x1FC0_0000
// 0xBD07_FFFF or ***************** 0x1D07_FFFF
// 0x9D07_FFFF * * BL_CSUM_ADDR 0x1D07_FFF4
// * * BL_PROGSZ_ADDR 0x1D07_FFF0
// 0xBD07_E000 or ***************** 0x1D07_E000
// 0x9D07_E000 * *
// * User App * 500k User app
// * *
// * Program *
// * Flash *
// * *
// 0x9D00_1000 ***************** 0x1D00_1000//4k bootloader
// * BootLoader *
// 0xBD00_0000 or * *
// 0x9D00_0000 ***************** 0x1D00_0000
**********************************************************************/
启动代码是mcu厂家提供的demo,我们可以在这个里面进行按需更改,比如加上一些特殊的处理代码,一般bootloader类的代码直接可以采用原厂的代码,这个汇编语言也跟mcu采用的内核及指令集密切相关,但功能都相差无几,当你想了解一款mcu时从读懂他的启动代码是最快的一种方式,汇编语言难懂,主要是在于你记性好不好,就像想在网络流行的很多简写体,你没有功略可能就是天书,所以不清楚的差芯片指令手则就好了,无他为手熟尔,我相信隔一段时间你又会搞忘的,所以不要纠结这个,也没必要去背他,当然你是学霸除外。
#include <p32xxxx.h>
#ifdef __LIBBUILD__
.file 1 "crt0.S"
.loc 1 0
#endif
##################################################################
# Entry point of the entire application
##################################################################
.section .reset,"ax",@progbits
.set noreorder
.ent _reset
_reset:
la k0, _startup
jr k0 # Jump to startup code
nop
.end _reset
.globl _reset
##################################################################
# Startup code
##################################################################
.section .startup,"ax",@progbits
.set noreorder
.ent _startup
_startup:
##################################################################
# If entered because of an NMI, jump to the NMI handler.
##################################################################
mfc0 k0,_CP0_STATUS
ext k0,k0,19,1 # Extract NMI bit
beqz k0,_no_nmi
nop
la k0,_nmi_handler
jr k0
nop
_no_nmi:
##################################################################
# Initialize Stack Pointer
# _stack is initialized by the linker script to point to the
# starting location of the stack in DRM
##################################################################
la sp,_stack
##################################################################
# Initialize Global Pointer
# _gp is initialized by the linker script to point to "middle"
# of the small variables region
##################################################################
la gp,_gp
##################################################################
# Initialize Global Pointer in Shadow Set
# The SRSCtl's PSS field must be set to the shadow set in which
# to initialize the global pointer. Since we only have a
# single shadow set (besides the normal), we will initialize
# SRSCtl<PSS> to SRSCtl<HSS>. We then write the global pointer
# to the previous shadow set to ensure that on interrupt, the
# global pointer has been initialized.
##################################################################
mfc0 t1,_CP0_SRSCTL # Read SRSCtl register
add t3,t1,zero # Save off current SRSCtl
ext t2,t1,26,4 # to obtain HSS field
ins t1,t2,6,4 # Put HSS field
mtc0 t1,_CP0_SRSCTL # into SRSCtl<PSS>
wrpgpr gp,gp # Set global pointer in PSS
mtc0 t3,_CP0_SRSCTL # Restore SRSCtl
##################################################################
# Call the "on reset" procedure
##################################################################
la t0,_on_reset
jalr t0
nop
##################################################################
# Clear uninitialized data sections
##################################################################
la t0,_bss_begin
la t1,_bss_end
b _bss_check
nop
_bss_init:
sw zero,0x0(t0)
sw zero,0x4(t0)
sw zero,0x8(t0)
sw zero,0xc(t0)
addu t0,16
_bss_check:
bltu t0,t1,_bss_init
nop
##################################################################
# Copy initialized data from program flash to data memory
# src=_data_image_begin dst=_data_begin stop=_data_end
##################################################################
la t0,_data_image_begin
la t1,_data_begin
la t2,_data_end
b _init_check
nop
_init_data:
lw t3,(t0)
sw t3,(t1)
addu t0,4
addu t1,4
_init_check:
bltu t1,t2,_init_data
nop
##################################################################
# If there are no RAM functions, skip the next two sections --
# copying RAM functions from program flash to data memory and
# initializing bus matrix registers.
##################################################################
la t1,_ramfunc_length
beqz t1,_ramfunc_done
nop
##################################################################
# Copy RAM functions from program flash to data memory
# src=_ramfunc_image_begin dst=_ramfunc_begin stop=_ramfunc_end
##################################################################
la t0,_ramfunc_image_begin
la t1,_ramfunc_begin
la t2,_ramfunc_end
_init_ramfunc:
lw t3,(t0)
sw t3,(t1)
addu t0,4
addu t1,4
_ramfunc_check:
bltu t1,t2,_init_ramfunc
nop
##################################################################
# Initialize bus matrix registers if RAM functions exist in the
# application
##################################################################
la t1,_bmxdkpba_address
la t2,BMXDKPBA
sw t1,0(t2)
la t1,_bmxdudba_address
la t2,BMXDUDBA
sw t1,0(t2)
la t1,_bmxdupba_address
la t2,BMXDUPBA
sw t1,0(t2)
_ramfunc_done:
##################################################################
# Initialize CP0 registers
##################################################################
# Initialize Count register
##################################################################
mtc0 zero,_CP0_COUNT
##################################################################
# Initialize Compare register
##################################################################
li t2,-1
mtc0 t2,_CP0_COMPARE
##################################################################
# Initialize EBase register
##################################################################
la t1,_ebase_address
mtc0 t1,_CP0_EBASE
##################################################################
# Initialize IntCtl register
##################################################################
la t1,_vector_spacing
li t2,0 # Clear t2 and
ins t2,t1,5,5 # shift value to VS field
mtc0 t2,_CP0_INTCTL
##################################################################
# Initialize CAUSE registers
# - Enable counting of Count register <DC = 0>
# - Use special exception vector <IV = 1>
# - Clear pending software interrupts <IP1:IP0 = 0>
##################################################################
li t1,0x00800000
mtc0 t1,_CP0_CAUSE
##################################################################
# Initialize STATUS register
# - Access to Coprocessor 0 not allowed in user mode <CU0 = 0>
# - User mode uses configured endianness <RE = 0>
# - Preserve Bootstrap Exception vectors <BEV>
# - Preserve soft reset <SR> and non-maskable interrupt <NMI>
# - CorExtend enabled based on whether CorExtend User Defined
# Instructions have been implemented <CEE = Config<UDI>>
# - Disable any pending interrups <IM7..IM2 = 0, IM1..IM0 = 0>
# - Disable hardware interrupts <IPL7:IPL2 = 0>
# - Base mode is Kernel mode <UM = 0>
# - Error level is normal <ERL = 0>
# - Exception level is normal <EXL = 0>
# - Interrupts are disabled <IE = 0>
##################################################################
mfc0 t0,_CP0_CONFIG
ext t1,t0,22,1 # Extract UDI from Config register
sll t1,t1,17 # Move UDI to Status.CEE location
mfc0 t0,_CP0_STATUS
and t0,t0,0x00580000 # Preserve SR, NMI, and BEV
or t0,t1,t0 # Include Status.CEE (from UDI)
mtc0 t0,_CP0_STATUS
##################################################################
# Call the "on bootstrap" procedure
##################################################################
la t0,_on_bootstrap
jalr t0
nop
##################################################################
# Initialize Status<BEV> for normal exception vectors
##################################################################
mfc0 t0,_CP0_STATUS
and t0,t0,0xffbfffff # Clear BEV
mtc0 t0,_CP0_STATUS
##################################################################
# Call main. We do this via a thunk in the text section so that
# a normal jump and link can be used, enabling the startup code
# to work properly whether main is written in MIPS16 or MIPS32
# code. I.e., the linker will correctly adjust the JAL to JALX if
# necessary
##################################################################
and a0,a0,0
and a1,a1,0
la t0,_main_entry
jr t0
nop
.end _startup
##################################################################
# Boot Exception Vector Handler
# Jumps to _bootstrap_exception_handler
##################################################################
.section .bev_handler,"ax",@progbits
.set noreorder
.ent _bev_exception
_bev_exception:
la k0,_bootstrap_exception_handler
jr k0
nop
.end _bev_exception
##################################################################
# General Exception Vector Handler
# Jumps to _general_exception_handler
##################################################################
.section .gen_handler,"ax",@progbits
.set noreorder
.ent _gen_exception
_gen_exception:
la k0,_general_exception_context
jr k0
nop
.end _gen_exception
.text
.ent _main_entry
_main_entry:
##################################################################
# Call main
##################################################################
jal main
nop
##################################################################
# Call exit
##################################################################
jal exit
nop
##################################################################
# Just in case, go into infinite loop
##################################################################
1:
b 1b
nop
.end _main_entry
下面是bootlaoder的main主场了,这是你可能就顺眼多了,因为c里面你可以自己用拼音表达你的意思,当然你是英语学习委员也可以用英语,但我反对用123来表示,那是霸权行为,只有当时的你可以明白,我一直觉得代码没必要自己从头开始,快速掌握一门语言或者一款mcu从她自带的demo开始,一通ctl c v后你的kpi就完成了,所以人生苦短,不要太在意那么多,知识层出不穷,只有掌握了快速学习的要义你在能在有限的生命里,畅想无限的事情,当然,买块板子自己亲自跑一跑,那跑板子后面吃灰也是很有必要的,最后祝你顺利毕业找到好工作!
/*********************************************************************
*
* PIC32 Boot Loader
*
*********************************************************************
* FileName: main.c
* Dependencies:
* Processor: PIC32
*
* Complier: MPLAB C32
* MPLAB IDE
* Company: Microchip Technology, Inc.
*
* Software License Agreement
*
* The software supplied herewith by Microchip Technology Incorporated
* (the 揅ompany? for its PIC32 Microcontroller is intended
* and supplied to you, the Company抯 customer, for use solely and
* exclusively on Microchip PIC32 Microcontroller products.
* The software is owned by the Company and/or its supplier, and is
* protected under applicable copyright laws. All rights are reserved.
* Any use in violation of the foregoing restrictions may subject the
* user to criminal sanctions under applicable laws, as well as to
* civil liability for the breach of the terms and conditions of this
* license.
*
* THIS SOFTWARE IS PROVIDED IN AN 揂S IS?CONDITION. NO WARRANTIES,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
* TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
* IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*
*
* $Id: $
* $Name: $
*
//片内flash为512k bytes 4k*128page
//0x9D07FFFF--0x9D000000 Program Flash
//
// PFM KERNEL AND USER MODE MAPPING
// Virtual Address Physical Address
// --------------- ----------------
// 0xBFC0_2FEF or ***************** 0x1FC0_2FEF
// 0X9FC0_2FEF * *
// * *
// * Boot Flash *
// 0xBFC0_0000 or * *
// 0x9FC0_0000 ***************** 0x1FC0_0000
// 0xBD07_FFFF or ***************** 0x1D07_FFFF
// 0x9D07_FFFF * * BL_CSUM_ADDR 0x1D07_FFF4
// * * BL_PROGSZ_ADDR 0x1D07_FFF0
// 0xBD07_E000 or ***************** 0x1D07_E000
// 0x9D07_E000 * *
// * User App * 500k User app
// * *
// * Program *
// * Flash *
// * *
// 0x9D00_1000 ***************** 0x1D00_1000//4k bootloader
// * BootLoader *
// 0xBD00_0000 or * *
// 0x9D00_0000 ***************** 0x1D00_0000
**********************************************************************/
#include <stdlib.h>
#include <plib.h>
#include "GenericTypeDefs.h"
#include "msg_cmd.h"
//#include "utils.h"
#include <stdarg.h>
// 80Mhz Core/Periph, Pri Osc w/PLL, Write protect Boot Flash
//#pragma config FPLLODIV = DIV_1, FPLLMUL = MUL_20, FPLLIDIV = DIV_2, FWDTEN = OFF, FPBDIV = DIV_1, POSCMOD = XT, FNOSC = PRIPLL, CP = OFF
//#pragma config FPLLMUL = MUL_20, FPLLIDIV = DIV_2, FPLLODIV = DIV_1, FWDTEN = OFF
//#pragma config POSCMOD = HS, FNOSC = PRIPLL, FPBDIV = DIV_1
//#pragma config ICESEL = ICS_PGx2, BWP = ON
#pragma config FPLLMUL = MUL_20, FPLLIDIV = DIV_2, FPLLODIV = DIV_1, FWDTEN = OFF
#pragma config POSCMOD = XT, FNOSC = PRIPLL, FPBDIV = DIV_1
#pragma config ICESEL = ICS_PGx2, BWP = ON,CP = OFF
#define SHELL_CMD 0
#define BL_CSUM_ADDR 0x9D07FFF4
#define BL_PROGSZ_ADDR 0x9D07FFF0
#define FLASH_PROG_BASE 0x9D000000
#define USER_APP_ADDR 0x9D001000
#define FLASH_PAGE_SIZE 4096
#define __ROM_SIZE BL_PROGSZ_ADDR-FLASH_PROG_BASE
#define BIOS_LOAD USER_APP_ADDR
#define BL_MINOR_VERSION 1
#define BL_MAJOR_VERSION 0
#define MAX_CMD_LEN 30
#define MAX_ARGS MAX_CMD_LEN/4
#define UART1_RXREG_IS_NOTNULL (U1ASTAbits.URXDA==1)
#define ENTER_KEY 0x0d
#define BACK_KEY 0x08
#define ESC_KEY 0x1b
#define dog()
#define SYS_FREQ (80000000L)
#define mLED_1 LATBbits.LATB0
#define mLED_2 LATBbits.LATB1
#define mLED_3 LATBbits.LATB2
#define SECONDS (SYS_FREQ/2)
#define MILLI_SECONDS (SECONDS/1000)
#define MAX_DATA_BFR 4096
unsigned char gBuffer[MAX_DATA_BFR];
//unsigned int pagebuff[1024];
#define DFT_DOWNLOAD_ADDR ((int)&gBuffer[0])
void PutChar(BYTE txChar);
void HandleCommand();
BYTE gRxData;
void PutResponse(WORD responseLen);
void VerifyFlashOK(int filesize,WORD csum);
int SectorProg(unsigned int begin, unsigned short *data, unsigned int size);
unsigned char read_byte(unsigned char *recchar);
void Puts(char *s);
void Printf(char *fmt, ...);
#define next_line() Puts("\r\n")
#define prompt() Puts("\\>")
//#define DFT_DOWNLOAD_ADDR
#if SHELL_CMD==1
int LoadFromUart(int argc, char *argv[])
#else
int LoadFromUart()
#endif
{
unsigned int start, fileSize;
unsigned int write_addr,writedsize=0;
unsigned int load_addr =(int) DFT_DOWNLOAD_ADDR;
WORD checksum=0,mychecksum=0;
int bValue=0;
#if SHELL_CMD==1
if(argc>1)
{
start = strtoul(argv[1],0,10);
if(load_addr>0)
load_addr = start;
}
#endif
start = load_addr;
while(!kbhit());*((unsigned char *)load_addr++) = getkey();
while(!kbhit());*((unsigned char *)load_addr++) = getkey();
while(!kbhit());*((unsigned char *)load_addr++) = getkey();
while(!kbhit());*((unsigned char *)load_addr++) = getkey();
fileSize=
(*((unsigned char *)DFT_DOWNLOAD_ADDR+0)<<0)+
(*((unsigned char *)DFT_DOWNLOAD_ADDR+1)<<8)+
(*((unsigned char *)DFT_DOWNLOAD_ADDR+2)<<16)+
(*((unsigned char *)DFT_DOWNLOAD_ADDR+3)<<24);
fileSize=fileSize-6;
if(fileSize>=__ROM_SIZE)
{//Puts("Flash size overflow!!!\r\n");
return -1;
}
load_addr = (int)DFT_DOWNLOAD_ADDR;
write_addr = (int)FLASH_PROG_BASE;
writedsize=0;
while(writedsize <fileSize)
{
if(kbhit())
{
bValue=1-bValue;
mLED_1=bValue;
mychecksum+=*((unsigned char *)load_addr++) = getkey();
writedsize++;dog();
if( writedsize%0x1000==0 )
{
SectorProg(write_addr,(unsigned short*)DFT_DOWNLOAD_ADDR,0x1000);
write_addr=write_addr+0x1000;
load_addr = (int)DFT_DOWNLOAD_ADDR;
PutChar('.');dog();
}
}
}
if(load_addr%0x1000!=0)
{
SectorProg(write_addr,(unsigned short*)DFT_DOWNLOAD_ADDR,fileSize - (write_addr-BIOS_LOAD));
PutChar('.');dog();
}
load_addr = (int)DFT_DOWNLOAD_ADDR;
//check sum
while(!kbhit());*((unsigned char *)load_addr++) = getkey();
while(!kbhit());*((unsigned char *)load_addr++) = getkey();
//while(!kbhit());*((unsigned char *)load_addr++) = getkey();
//while(!kbhit());*((unsigned char *)load_addr++) = getkey();
checksum=
(*((unsigned char *)DFT_DOWNLOAD_ADDR+0)<<0)+
(*((unsigned char *)DFT_DOWNLOAD_ADDR+1)<<8);
//(*((unsigned char *)DFT_DOWNLOAD_ADDR+1)<<16)+
//(*((unsigned char *)DFT_DOWNLOAD_ADDR+1)<<24);
if(checksum==mychecksum)
VerifyFlashOK(fileSize,checksum);
//FILESIZE1 = fileSize;
return 0;
}
void VerifyFlashOK(int filesize,WORD csum)
{
//gBuffer[1] contains the prog size in bytes. must be on DWORD boundry
int temp;
//DWORD* fptr;
NVMErasePage( (void*)(BL_CSUM_ADDR&0xFFFFF000));
if( !((*(DWORD*)BL_CSUM_ADDR) == 0xFFFFFFFF &&
(*(DWORD*)BL_PROGSZ_ADDR) == 0xFFFFFFFF) )
{
//send the error response
Puts("Flash not Erase\r\n");
return;
}
//fptr = (DWORD*)FLASH_PROG_BASE;
NVMWriteWord((DWORD*)(BL_PROGSZ_ADDR), filesize); //write flash prog size in bytes
NVMWriteWord((WORD*)(BL_CSUM_ADDR), csum); //write checksum
if( !((*(WORD*)BL_CSUM_ADDR) == csum &&
(*(DWORD*)BL_PROGSZ_ADDR) ==filesize ) )
{
Puts("Flash Check sum Erro\r\n");
}
}
int SectorProg(unsigned int begin, unsigned short *data, unsigned int size)
{
/*
unsigned int tmp = 0x200;//0x1000-(begin&0xfff);
//if(tmp>size)
// tmp = size;
//SectorErase(begin&0xfffff000);
for(; size;)
{
mLED_3=0;
if((begin&0xFFF)==0)
NVMErasePage((void*)(begin&0xfffff000));
//FlashProg(begin, data, tmp/2);
// Write the pagebuff data to NVM_PROGRAM_PAGE + NVM_PAGE_SIZE
//NVMProgram((void *)begin, (const void *)data, size, (void*) pagebuff);
NVMWriteRow((DWORD*)begin, (DWORD*)data);
//Puts("Program ok\r\n");
size -= tmp;
begin += tmp;
data += tmp/2;
tmp = (size>0x1000)?0x1000:size;
}
*/
int RowCount, nRow;
unsigned char* ptr=(unsigned char*)data;
RowCount = size / 512;
if( size % 512 )
RowCount++;
nRow = 0;
while(nRow < RowCount)
{
int RowAddr;
RowAddr = nRow*512;
if( ((begin+RowAddr) & 0xFFF) == 0 )
NVMErasePage( (void*)(begin+RowAddr) );
// Write 128 words
NVMWriteRow((void*)(begin+RowAddr), (void*)&ptr[RowAddr]);
nRow++;
}
return 0;
}
void JumpToApp()
{
void (*fptr)(void);
fptr = (void (*)(void))USER_APP_ADDR;
fptr();
}
BOOL VerifyFlash()
{
DWORD temp, ProgSz;
DWORD* fptr;
BYTE* fbptr;
WORD csum = 0,mycsum=0;
fptr = (DWORD*)BL_PROGSZ_ADDR;
ProgSz = *fptr;
mycsum = *(WORD*)BL_CSUM_ADDR;
if( ProgSz > BMXPFMSZ )
return FALSE;
fbptr = (BYTE*)FLASH_PROG_BASE;
for( temp = 0; temp < ProgSz; temp++ )
csum += fbptr[temp];
//csum = ~csum + 1;
return (csum == mycsum);
}
/*********************************************************/
#if SHELL_CMD==1
int Help(int argc, char *argv[]);
int Auto(int argc, char *argv[]);
typedef int (*cmdproc)(int argc, char *argv[]);
typedef struct {
char *cmd;
char *hlp;
cmdproc proc;
}CMD_STRUC;
CMD_STRUC CMD_INNER[] =
{ {"?", "help", Help},
{"load", "load bin file from console", LoadFromUart},
// {"prog", "program from sdram to flash", ProgFlash},
// {"boot", "boot from flash", BootLoader},
// {"copy", "copy from flash to flash", CopyFlash},
// {"run", "run from sdram", RunProgram},
{"auto", "auto download and program",Auto},
{NULL, NULL, NULL}
};
/*
int Help(int argc, char *argv[])
{
int i;
for(i=0; CMD_INNER[i].cmd!=NULL; i++)
{
if(CMD_INNER[i].hlp!=NULL)
{
Puts(CMD_INNER[i].cmd);
Puts(" -----> ");
Puts(CMD_INNER[i].hlp);
Puts("\r\n");
}
}
return 0;
}
*/
//int Auto(void);
int Auto(int argc, char *argv[])
{
//1.download to sdram
char *para_ptr[4];
//char temp[10];
argc=argc;
LoadFromUart(0, para_ptr);
//2.program to flash
/*
para_ptr[1]="8000";
para_ptr[2]="44000000";
para_ptr[3]=temp;
ultostr(temp,FILESIZE1);
ProgFlash1(4, para_ptr);
*/
//3.boot
JumpToApp();
return 0;
}
/*********************************************************/
static void ParseArgs(char *cmdline, int *argc, char **argv)
{
#define STATE_WHITESPACE 0
#define STATE_WORD 1
char *c;
int state = STATE_WHITESPACE;
int i;
*argc = 0;
if(strlen(cmdline) == 0)
return;
// convert all tabs into single spaces
c = cmdline;
while(*c != '\0')
{
if(*c == '\t')
*c = ' ';
c++;
}
c = cmdline;
i = 0;
// now find all words on the command line
while(*c != '\0')
{
if(state == STATE_WHITESPACE)
{
if(*c != ' ')
{
argv[i] = c; //将argv[i]指向c
i++;
state = STATE_WORD;
}
}
else
{ // state == STATE_WORD
if(*c == ' ')
{
*c = '\0';
state = STATE_WHITESPACE;
}
}
c++;
}
*argc = i;
#undef STATE_WHITESPACE
#undef STATE_WORD
}
static int GetCmdMatche(char *cmdline)
{
int i;
for(i=0; CMD_INNER[i].cmd!=NULL; i++)
{
if(strncmp(CMD_INNER[i].cmd, cmdline, strlen(CMD_INNER[i].cmd))==0)
return i;
}
return -1;
}
static int ParseCmd(char *cmdline, int cmd_len)
{
int argc, num_commands;
char *argv[MAX_ARGS];
ParseArgs(cmdline, &argc, argv);
// only whitespace
if(argc == 0)
return -1;
num_commands = GetCmdMatche(argv[0]);
if(num_commands<0)
return -1;
if(CMD_INNER[num_commands].proc!=NULL)
{
CMD_INNER[num_commands].proc(argc, argv);
}
return 0;
}
#endif
/*********************************************************/
#define BlinkLED() {mLED_1 = ((ReadCoreTimer() & 0x0200000) != 0);}
#define BlinkLED2() {mLED_2 = ((ReadCoreTimer() & 0x0200000) != 0);}
#define BlinkLED3() {mLED_1 = ((ReadCoreTimer() & 0x2000000) != 0);}
BOOL PutMyDLChar()
{
if(ReadCoreTimer()>=SECONDS )
{
PutChar('>');
WriteCoreTimer(0);
return TRUE;
}
else return FALSE;
}
/*********************************************************/
int main (void)
{
//int s = DFT_DOWNLOAD_ADDR;
int i, key;
int time_out0;
char command[MAX_CMD_LEN];
unsigned int pb_clock;
SYSTEMConfig(SYS_FREQ, SYS_CFG_WAIT_STATES | SYS_CFG_PCACHE);
mCTClearIntFlag();
OpenCoreTimer(SECONDS);
//setup LED ports
TRISBbits.TRISB0 = 0;
TRISBbits.TRISB1 = 0;
TRISBbits.TRISB2 = 0;
BOOL FlashGood = FALSE;
// SETUP UART COMMS: No parity, one stop bit, autobaud, polled
// OpenUART1(UART_EN|UART_EN_ABAUD|UART_BRGH_FOUR, UART_RX_ENABLE | UART_TX_ENABLE, 0 );
//OpenUART1(UART_EN|UART_EN_ABAUD|UART_BRGH_FOUR, UART_RX_ENABLE | UART_TX_ENABLE, 0 );
// OpenUART1(UART_EN | UART_BRGH_FOUR, UART_RX_ENABLE | UART_TX_ENABLE, mUARTBRG(80000000, 115200));
UARTConfigure(UART1, UART_ENABLE_PINS_TX_RX_ONLY);
UARTSetFifoMode(UART1, UART_INTERRUPT_ON_TX_NOT_FULL | UART_INTERRUPT_ON_RX_NOT_EMPTY);
UARTSetLineControl(UART1,UART_DATA_SIZE_8_BITS | UART_PARITY_NONE | UART_STOP_BITS_1);
UARTSetDataRate(UART1, 80000000, 115200);//UART1_BAUDRATE);
UARTEnable(UART1, UART_ENABLE_FLAGS(UART_PERIPHERAL | UART_RX | UART_TX));
//U1MODEbits.ABAUD = 1; //set autobaud mode
mLED_3=0;mLED_2=0;
/*
while(U1MODEbits.ABAUD ) //wait for sync character U
{
if( FlashGood && mCTGetIntFlag() )
{
//timeout while waiting for sync from pc - jump to user app
JumpToApp();
}
BlinkLED();
}
*/
/*************************************/
/*
PutChar(0x0c);PutChar(0x0c);
next_line();
Puts("********************************************\r\n");
Puts("* VDC300 BIOS BOOT *\r\n");
Puts("* GT-BIOS GT-SS1-V1.0 *\r\n");
Puts("*VDC300 Design By XXD(xiang_xudong@163.com)*\r\n");
Puts("********************************************\r\n");
Puts("Build Date:");
Puts(__DATE__);
Puts(" Time:");
Puts(__TIME__);
next_line();
*/
//check flash contents
FlashGood = VerifyFlash();
if(FlashGood)
Puts("Program OK\r\n");
else
Puts("Program Not Complete\r\n");
// while(U1MODEbits.ABAUD ) //wait for sync character U
//#define WAIT_TIME0 0x20000
time_out0 = 10;//WAIT_TIME0;
do{
dog();
if(kbhit())
{
key = getkey();
if (key == ENTER_KEY) break;
//else if(key == '<') mLED_3=1;
}
BlinkLED2();
// PutMyDLChar();
if(PutMyDLChar())
{
if((--time_out0==0)&&FlashGood)
//timeout while waiting for sync from pc - jump to user app
JumpToApp();
}
}while(1);
#if SHELL_CMD==1
next_line();
prompt();
i = 0;
time_out0=0;
for(;;)
{dog();
if(kbhit())
{
key = getkey();
if(key == BACK_KEY)
{
i -= i?1:0;
PutChar(key);
}
else
if(key == ENTER_KEY)
{
int tmp;
command[i] = 0;
next_line();
tmp = ParseCmd(command, i);
if(tmp<0)
{
Puts("Bad command\r\n");
//Boot();
}
else
time_out0=0;
prompt();
i = 0;
}
else
{
if(i<MAX_CMD_LEN-1)
{
command[i++] = key;
PutChar(key);
}
}
}
else
{
BlinkLED3();
//if(time_out0++>=0x20000) Boot();
}
}
#else
next_line();
prompt();
i = 0;
time_out0=0;
for(;;)
{dog();
if(kbhit())
{
key = getkey();
if(key == BACK_KEY)
{
i -= i?1:0;
PutChar(key);
}
else
if(key == ENTER_KEY)
{
int tmp;
command[i] = 0;
next_line();
//tmp = ParseCmd(command, i);
if(strstr(command,"auto")!=NULL)
{
LoadFromUart();
JumpToApp();
}
/*
if(tmp<0)
{
Puts("Bad command\r\n");
//Boot();
}
else
time_out0=0;
prompt();
*/
i = 0;
}
else
{
if(i<MAX_CMD_LEN-1)
{
command[i++] = key;
PutChar(key);
}
}
}
else
{
BlinkLED3();
//if(time_out0++>=0x20000) Boot();
}
}
#endif
}
/********************************************************************
* Function: void PutChar(BYTE Char)
*
* Precondition: UART Setup
*
* Input: Char - Character to transmit
*
* Output: None
*
* Side Effects: Puts character into destination pointed to by ptrChar.
*
* Overview: Transmits a character on UART2.
* Waits for an empty spot in TXREG FIFO.
*
* Note: None
********************************************************************/
void PutChar(BYTE txChar)
{
while( BusyUART1() );
putcUART1(txChar);
}
void Puts(char *s)
{
while ( *s )
{
PutChar(*s++);
}
return;
}
/*
int vsprintf(char * , const char * , __va_list );
void Printf(char *fmt, ...)
{
va_list ap;
char string[256];
va_start(ap, fmt);
vsprintf(string, fmt, ap);
Puts(string); //UartSendString(CONSOLE_UART, string);
va_end(ap);
}
*/
int kbhit()
{
if(UART1_RXREG_IS_NOTNULL) return 1;
else return 0;
}
int getkey()
{
unsigned char recchar;
if(read_byte(&recchar)) //UartReceive(CONSOLE_UART);
return recchar;
else
return 0;
}
unsigned char read_byte(unsigned char *recchar)
{
BYTE dummy;
/*
//check for receive errors
if((U1STA & 0x000E) != 0x0000)
{
dummy = U1RXREG; //dummy read to clear FERR/PERR
U1STAbits.OERR = 0; //clear OERR to keep receiving
}
*/
//get the data
if(UART1_RXREG_IS_NOTNULL)
{
*recchar= U1RXREG; //get data from UART RX FIFO
return TRUE;
}
else
return FALSE;
} /* end read_serial_byte() */