//// 进程空间区域写前验证函数。 // 对当前进程的地址addr 到addr+size 这一段进程空间以页为单位执行写操作前的检测操作。 // 若页面是只读的,则执行共享检验和复制页面操作(写时复制)。 void verify_area (void *addr, int size) { unsigned long start; start = (unsigned long) addr; // 将起始地址start 调整为其所在页的左边界开始位置,同时相应地调整验证区域大小。 // 此时start 是当前进程空间中的线性地址。 size += start & 0xfff; start &= 0xfffff000; start += get_base (current->ldt[2]);// 此时start 变成系统整个线性空间中的地址位置。 while (size > 0) { size -= 4096; // 写页面验证。若页面不可写,则复制页面。(mm/memory.c,261 行) write_verify (start); start += 4096; } }
/******************************************************************************* Routine Name: main Form: int main( void ) Parameters: void Return value: int but not return... Description: main ******************************************************************************/ int main( void ) { unsigned long write_addr; unsigned char status; // LED ON, when enter to boot mode P51D = 1; P56D = 1; P56DIR = 0; P56C1 = 1; P56C0 = 1; P56MD0 = 0; P56MD1 = 0; P51DIR = 0; P51C1 = 1; P51C0 = 1; P51MD0 = 0; P51MD1 = 0; memset(XmodemBuf,0,sizeof(XmodemBuf)); /* initialize variables */ #ifndef DEBUG write_addr = (unsigned long)USER_AREA_ADDR; #else write_addr = (unsigned long)0x2000; #endif /* initialize peripheral */ initPeri(); Xmodem_Init( XmodemBuf ); __EI(); // LED ON, when enter to boot mode /* Display program */ uart_send_sync((unsigned char*)msgIspProg, sizeof(msgIspProg)); Xmodem_SendByte('C'); P51D = 0; // Orange LED ON /* main loop */ for(;;){ /* clear WDT */ wdt_clear(); status = Xmodem_ReadStatus(); switch(status){ case RECV_END: P56D = 0; // BLUE LED ON if(write_verify(&write_addr, XmodemBuf+3) != OK){ error_proc(); /* endless loop in error_proc()*/ } else{ Xmodem_SendByte(ACK); } P56D = 1; // BLUE LED OFF break; case EOT_END: // original was remap. change to infinity loop. end_of_update(); // Remap((unsigned long)USER_AREA_ADDR); break; case TIMEOUT_ERR: case RETRY_ERR: case SEND_ERR: #ifdef DEBUG XmodemBuf[2] = status; #endif error_proc(); /* endless loop in error_proc()*/ break; default: break; } } }