int crcSIGN(void) { int i=-1,crc; #if defined (STM32F10X_HD) RCC_AHBPeriphClockCmd(RCC_AHBPeriph_CRC, ENABLE); #elif defined (STM32F2XX) RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_CRC, ENABLE); #endif if(_Words32Received) { i=EraseFLASH(_SIGN_PAGE); CRC_ResetDR(); crc=CRC_CalcBlockCRC((uint32_t *)_FLASH_TOP,_Words32Received); i |= FlashProgram32((int)_FW_CRC,crc); // vpisi !!! i |= FlashProgram32((int)_FW_SIZE,_Words32Received); CRC_ResetDR(); crc=CRC_CalcBlockCRC(_FW_SIZE,2); i |= FlashProgram32((int)_SIGN_CRC,crc); } return i; }
/******************************************************************************* * Function Name : PollCAN * Description : periodièno procesiranje CAN protokola v glavni zanki * Input : * Output : * Return : FLASH_COMPLETE na bootloader strani, FLASH_STATUS na strani * klienta (glej stm32f10x_flash.h) *******************************************************************************/ int PollCAN(CanRxMsg *p) { static int addr,n=0; // statièni register za zaèetno. adreso, index IAP stringa int i; // .... CanRxMsg Rx; if(!p) { if(!CAN_MessagePending(CAN1, CAN_FIFO0)) return(EOF); p=&Rx; CAN_Receive(CAN1,CAN_FIFO0, p); } switch(p->StdId) { //---------------------------------------------------------------------------------------------- // client - deep sleep (watchdog), no ack. case _ID_IAP_GO: NVIC_SystemReset(); break; //---------------------------------------------------------------------------------------------- // client - sign FW case _ID_IAP_SIGN: SendAck(crcSIGN()); break; //---------------------------------------------------------------------------------------------- // client - setup adrese, no ack case _ID_IAP_ADDRESS: addr=*(int *)p->Data; break; //---------------------------------------------------------------------------------------------- // client - programiranje 2x4 bytov, ack case _ID_IAP_DWORD: for(i=p->DLC; i<8; ++i) p->Data[i]=((char *)addr)[i]; i=FlashProgram32(addr,*(int *)(&p->Data[0])); addr+=4; ++_Words32Received; if(p->DLC>4) { i |= FlashProgram32(addr,*(int *)(&p->Data[4])); } addr+=4; ++_Words32Received; SendAck(i); break; //---------------------------------------------------------------------------------------------- // client - brisanje, ack case _ID_IAP_ERASE: _Words32Received=0; Watchdog(); SendAck(EraseFLASH(*(int *)p->Data)); break; //---------------------------------------------------------------------------------------------- // client - brisanje, ack case _ID_IAP_STRING: for(i=0; i<p->DLC && n<_IAP_STRING_LEN; ++i, ++n) _Iap_string[n]=p->Data[i]; if(_Iap_string[n-1]=='\0' || _Iap_string[n-1]=='\r' || _Iap_string[n-1]=='\n' || n==_IAP_STRING_LEN) { n=0; CanHexProg(NULL); } break; //---------------------------------------------------------------------------------------------- // client - brisanje, ack case _ID_IAP_PING: SendAck(0); break; //---------------------------------------------------------------------------------------------- // server - acknowledge received case _ID_IAP_ACK: return(p->Data[0]); //---------------------------------------------------------------------------------------------- default: break; } return(EOF); }
/** Handle incomming frames from the serial port. */ void rxhandler(void) { switch (serRxBuf.header.type) { case ACK: case NACK: break; case T_CONNECT: //connect JTAG to the target InitTarget(); if (GetDevice() == STATUS_OK) { txACK(); //printf("Device type: %04x\n", DEVICE); } else{ txNACKstr("no target"); } break; case T_RELEASE: //release JTAG from target ClrTCLK(); IR_Shift(IR_CNTRL_SIG_16BIT); DR_Shift16(0x3001); //lch IR_Shift(IR_CNTRL_SIG_RELEASE); SetTCLK(); ReleaseTarget(); txACK(); break; case T_RESET: //reset the target and release JTAG ReleaseDevice(V_RESET); ReleaseTarget(); txACK(); break; case T_PUC: //reset the target through JTAG, keep connection ExecutePUC(); txACK(); break; case T_MEMREAD: //ream memory from target { //use a new block for local vars word size = serRxBuf.data.memread.size; word address = serRxBuf.data.memread.address; word offset; txACK(); HaltCPU(); if (size > sizeof(serTxBuf.data.memdata.data)) { size = sizeof(serTxBuf.data.memdata.data); } if (address <= 0xff) { //peripherals in bytemode for (offset = 0; offset < size; offset++) { serTxBuf.data.memdata.data[offset] = ReadMem(F_BYTE, address+offset); } } else { //peripherals in wordmode as well as RAM and Flash address = address & 0xfffe; //startaddress has to be even! for (offset = 0; offset < size/2; offset++) { ((word *)serTxBuf.data.memdata.data)[offset] = ReadMem(F_WORD, address+offset*2); } if (size & 1) { //odd size, read last byte separate //odd sizes on word-mode peripherals yield wrong results //in the last word!! serTxBuf.data.memdata.data[size-1] = ReadMem(F_BYTE, address+size-1); } } serTxBuf.data.memdata.address = address; serTxBuf.header.type = T_MEMDATA; serTxBuf.header.size = 2+size; sendMessage(&serTxBuf); } break; case T_MEMWRITE: //write target memory (Peripherals, RAM, Flash) { word offset; word size = serRxBuf.header.size - 2; HaltCPU(); if ((serRxBuf.data.memwrite.address >= 0x100) && (serRxBuf.data.memwrite.address <= 0x1ff)) { //peripherals in wordmode for (offset = 0; offset < size; offset+=2) { WriteMem(F_WORD, serRxBuf.data.memwrite.address+offset, ((word*)serRxBuf.data.memwrite.data)[offset/2] ); } } else if (serRxBuf.data.memwrite.address < 0x1000) { //ram + peripherals, bytemode for (offset = 0; offset < size; offset++) { WriteMem(F_BYTE, serRxBuf.data.memwrite.address+offset, serRxBuf.data.memwrite.data[offset] ); } } else { //flash memory, wordmode WriteFLASH(serRxBuf.data.memwrite.address, size/2, (word *)serRxBuf.data.memwrite.data ); } txACK(); } break; case T_EXEC: //execute target program located at given address ReleaseDevice(serRxBuf.data.exec.address); txACK(); break; case T_MEMERASE: //erase target flash (Segment, Main or All) HaltCPU(); EraseFLASH( serRxBuf.data.memerase.mode, serRxBuf.data.memerase.address ); txACK(); break; case T_MCLK: //provide MCLKs, allows sort of single stepping ClrTCLK(); IR_Shift(IR_CNTRL_SIG_16BIT); DR_Shift16(0x3401); //lch while (serRxBuf.data.step.numsteps--) { SetTCLK(); ClrTCLK(); } SetTCLK(); txACK(); break; case MEMREAD: //host memory read { word size = serRxBuf.data.memread.size; byte *address = (byte*)serRxBuf.data.memread.address; word offset; txACK(); if (size > sizeof(serTxBuf.data.memdata.data)) { size = sizeof(serTxBuf.data.memdata.data); } if (address <= (byte *)0xff) { //bytemode for (offset = 0; offset < size; offset++) { serTxBuf.data.memdata.data[offset] = address[offset]; } } else { //wordmode address = (byte *)((word)address & 0xfffe); //startaddress has to be even! size &= 0xfffe; //size has to be even for (offset = 0; offset < size/2; offset++) { ((word *)serTxBuf.data.memdata.data)[offset] = ((word *)address)[offset]; } } serTxBuf.data.memdata.address = (word)address; serTxBuf.header.type = MEMDATA; serTxBuf.header.size = 2+size; sendMessage(&serTxBuf); } break; case MEMWRITE: //host memory write, used to download user programs { void *adr = (byte *)serRxBuf.data.memwrite.address; word offset; word size = serRxBuf.header.size - 2; if ((adr >= (void *)0x100) && (adr <= (void *)0x1ff)) { //peripherals, wordmode for (offset = 0; offset < size/2; offset++) { ((word *)adr)[offset] = ((word *)serRxBuf.data.memwrite.data)[offset]; } txACK(); return; } if (adr < (void *)0x1000) { //ram + peripherals, bytemode for (offset = 0; offset < size; offset++) { ((byte *)adr)[offset] = serRxBuf.data.memwrite.data[offset]; } } else { //flash flashWriteBlock( serRxBuf.data.memwrite.data, (void *)serRxBuf.data.memwrite.address, size); } txACK(); } break; case MEMERASE: //erase one segemnt on host flashErase((void *)serRxBuf.data.memerase.address); txACK(); break; //~ case MEMEXEC: //exec code on host //~ serRxBuf.memexec.function( //~ serRxBuf.memexec.arg1, //~ serRxBuf.memexec.arg2 //~ ); //~ txACK(); //~ break; case STARTBSL: //start BSL for firmware upgrade txACK(); while((UTCTL0 & TXEPT) == 0) {} //wait until last byte is sent FCTL3 = 0; //generate a flash key violation -> POR reset, see main() break; default: txNACKstr("unknown command"); //serialComm error: unknown command } }