EFM32 单片机调试总结

2019-07-13 23:39发布

1、基本问题

1.1、J-Link Failed to get CPU status after 4 retries Retry   1.2、CMU_ClockEnable(cmuClock_CORELE, true);   1.3、焊接了好几块板子,Jlink都连不上单片机,最后是把电源的旁路电容都加上才能连上。EFM32单片机对电源的要求较高,必须在芯片的电源上做好滤波和退耦,否则会影响j-link的连接和调试 1.4 EFM32 如果用LEUART,不要使用内部低频晶振做输入,偏频较大 1.5 void LEUART_Tx(LEUART_TypeDef *leuart, uint8_t data) 这个接口在多次发送会出现死循环的情况。所以还是换用 void LEUART_TxExt(LEUART_TypeDef *leuart, uint16_t data)

2、串口升级

2.1工具

          Tera Term            J-FLASH

2.2 代码

/********************************************* * @文件: main.c * @作者: cjx * @版本: v1.0.0 * @时间: 2018-06-22 * @电话: 18770053277 * @概要: *********************************************/ #include "apll.h" #include "ioctrl.h" #include "xmodem.h" #define UPDATE_COMMAND_WAIT_TIME 5000 #define UPDATE_WAIT_TIME 10000 int main(void) { T_U32 u32StartTime, u32StopTime; S_FlashInfo stFlashInfo; S_FlashRead stFlashRead; S_FlashWrite stFlashWrite; S_FlashErase stFlashErase; DRIVER_SYS_Open(); DRIVER_FLASH_Open(); DRIVER_UART_Open(); stFlashRead.u32Addr = FLASH_INFO_ADDR; stFlashRead.pu8Data = (T_U8 *)&stFlashInfo; stFlashRead.u32Len = sizeof(stFlashInfo); DRIVER_FLASH_Ioctl(E_FLASH_IOCTL_CMD_READ, &stFlashRead); if(stFlashInfo.u32Ver > 0xff) { //stFlashInfo.u32Ver = 0; stFlashInfo.u32AppAddr = FLASH_APP1_ADDR; stFlashInfo.u32UpdateAddr = FLASH_APP1_ADDR; } DRIVER_UART_Write("Please Input Command! ", sizeof("Please Input Command! ")-1); DRIVER_SYS_Ioctl(E_SYS_IOCTL_CMD_GET_TIME, &u32StartTime); while(1) { unsigned char c = 0; c = 0; xgetc_nowait(&c); switch(c) { case 'U': case 'u': // Upload. { stFlashErase.u32Addr = stFlashInfo.u32UpdateAddr; stFlashErase.u32Pages = FLASH_APP_PAGES; if(RET_FAILED==DRIVER_FLASH_Ioctl(E_FLASH_IOCTL_CMD_ERASE, &stFlashErase)) { goto error; } DRIVER_UART_Write("Please Update! ", sizeof("Please Update! ")-1); if(1 == xmodem(stFlashInfo.u32UpdateAddr, stFlashInfo.u32UpdateAddr+FLASH_APP_PAGES*FLASH_PAGE_SIZE)) { stFlashInfo.u32Ver = (stFlashInfo.u32Ver+1)%256; if(FLASH_APP1_ADDR == stFlashInfo.u32UpdateAddr) { stFlashInfo.u32AppAddr = FLASH_APP1_ADDR; stFlashInfo.u32UpdateAddr = FLASH_APP2_ADDR; }else { stFlashInfo.u32AppAddr = FLASH_APP2_ADDR; stFlashInfo.u32UpdateAddr = FLASH_APP1_ADDR; } stFlashWrite.u32Addr = FLASH_INFO_ADDR; stFlashWrite.pu8Data = (T_U8 *)&stFlashInfo; stFlashWrite.u32Len = sizeof(stFlashInfo); stFlashErase.u32Addr = FLASH_INFO_ADDR; stFlashErase.u32Pages = FLASH_INFO_PAGES; DRIVER_FLASH_Ioctl(E_FLASH_IOCTL_CMD_ERASE, &stFlashErase); DRIVER_FLASH_Ioctl(E_FLASH_IOCTL_CMD_WRITE, &stFlashWrite); DRIVER_UART_Write("Update Success! ", sizeof("Update Success! ")-1); }else { goto error; } goto end; #if 0 while(1) { if(xgetc(&c)) { u32StartTime = u32StopTime; } DRIVER_SYS_Ioctl(E_SYS_IOCTL_CMD_GET_TIME, &u32StopTime); if((u32StopTime-u32StartTime) > UPDATE_WAIT_TIME) { goto end; } } #endif } break; #if 0 case 'T': case 't': // Write to user page. //xmodem(USER_PAGE_START_ADDR, USER_PAGE_END_ADDR); break; case 'P': case 'p': // Write to lock bits. //xmodem(LOCK_PAGE_START_ADDR, LOCK_PAGE_END_ADDR); break; #endif case 'B': case 'b': // Boot into new program. goto end; break; default: break; } DRIVER_SYS_Ioctl(E_SYS_IOCTL_CMD_GET_TIME, &u32StopTime); if((u32StopTime-u32StartTime) > UPDATE_COMMAND_WAIT_TIME) { goto end; } } end: if(stFlashInfo.u32Ver > 0xff) { DRIVER_UART_Write("Don't Have App! ", sizeof("Don't Have App! ")-1); DRIVER_SYS_Halt(); }else { DRIVER_UART_Write("Into App! ", sizeof("Into App! ")-1); T_S8 s8StartAddr[] = "Start Addr = 0x00000000 "; T_U8 u8i=0,u8hex; T_S8 s8Addr[4]; T_U32 u32Addr = stFlashInfo.u32AppAddr; for(u8i=0; u8i<4; u8i++) { u8hex = u32Addr; u8hex %= 16; if(u8hex > 9) { s8Addr[u8i] = u8hex - 10+ 'a'; }else { s8Addr[u8i] = u8hex + '0'; } u32Addr >>= 4; } s8StartAddr[19] = s8Addr[3]; s8StartAddr[20] = s8Addr[2]; s8StartAddr[21] = s8Addr[1]; s8StartAddr[22] = s8Addr[0]; DRIVER_UART_Write(s8StartAddr, 25); typedef unsigned int (*ENTRY_FUNC_TYPE)(void); ENTRY_FUNC_TYPE Goto; Goto = (ENTRY_FUNC_TYPE)(*(unsigned int *)(stFlashInfo.u32AppAddr+4)); __set_MSP(*(unsigned int*)stFlashInfo.u32AppAddr); Goto(); while(1); } error: DRIVER_UART_Write("Update Fail! ", sizeof("Update Fail! ")-1); SCB->AIRCR = 0x05FA0004; while(1); } /********************************************* * @文件: driverFlash.c * @作者: cjx * @版本: v1.0.1 * @时间: 2018-11-09 * @概要: Flash驱动 *********************************************/ #include "baseType.h" #include "ioctrl.h" /******************************************** *功能:打开函数 *输入:无 *输出:无 *条件:无 *返回:成功:RET_SUCCESS 失败:RET_FAILED 注意: *********************************************/ T_S32 DRIVER_FLASH_Open(T_VOID) { MSC_Init(); #if 0 // Write MSC unlock code to enable interface. MSC->LOCK = MSC_UNLOCK_CODE; #if defined(EMU_CMD_EM01VSCALE2) // Scale voltage up to allow FLASH programming EMU->CMD = EMU_CMD_EM01VSCALE2; while (EMU->STATUS & EMU_STATUS_VSCALEBUSY); #endif // Enable memory controller. MSC->WRITECTRL |= MSC_WRITECTRL_WREN; #endif return RET_SUCCESS; } /******************************************** *功能:读取函数 *输入:输出数据 及 数据长度 *输出:无 *条件:无 *返回:成功:RET_SUCCESS 失败:RET_FAILED 或者长度 注意: *********************************************/ T_S32 DRIVER_FLASH_Read(T_S8 *ps8DataBuf, T_S32 s32BufLen) { T_S32 s32DataLen = 0; return s32DataLen; } /******************************************** *功能:事件标志 *输入:无 *输出:无 *条件:无 *返回:成功:RET_SUCCESS 失败:RET_FAILED 注意: *********************************************/ T_S32 DRIVER_FLASH_Pop(T_VOID) { return RET_SUCCESS; } /******************************************** *功能:控制接口 *输入:s32Cmd :命令类型 pvData:控制数据或者返回 数据 *条件:无 *返回:成功:RET_SUCCESS 失败:RET_FAILED *********************************************/ T_S32 DRIVER_FLASH_Ioctl(T_S32 s32Cmd, T_VOID *pvData) { T_S32 s32Ret = RET_SUCCESS; switch(s32Cmd) { case E_FLASH_IOCTL_CMD_ERASE: { T_U32 u32i = 0; S_FlashErase *pst = (S_FlashErase *)pvData; __disable_irq(); for(u32i = 0; u32i < pst->u32Pages; u32i++) { //DRIVER_FLASH_Open(); if(mscReturnOk != MSC_ErasePage((uint32_t *)(pst->u32Addr + u32i*FLASH_PAGE_SIZE))) { s32Ret = RET_FAILED; } #if 0 MSC->LOCK = MSC_UNLOCK_CODE; MSC->ADDRB = pst->u32Addr + u32i*FLASH_PAGE_SIZE;// Load address. MSC->LOCK = MSC_UNLOCK_CODE; MSC->WRITECMD = MSC_WRITECMD_LADDRIM; MSC->LOCK = MSC_UNLOCK_CODE; MSC->WRITECMD = MSC_WRITECMD_ERASEPAGE; // Send Erase Page command. while (MSC->STATUS & MSC_STATUS_BUSY); // Waiting for erase to complete. #endif } __enable_irq(); } break; case E_FLASH_IOCTL_CMD_WRITE: { S_FlashWrite *pst = (S_FlashWrite *)pvData; T_U32 u32WLen = pst->u32Len; if(u32WLen%4 != 0) { u32WLen = u32WLen + (4 - u32WLen%4); } //DRIVER_FLASH_Open(); __disable_irq(); if(MSC_WriteWord((uint32_t *)pst->u32Addr, pst->pu8Data, u32WLen)) { s32Ret = RET_FAILED; } __enable_irq(); #if 0 T_U32 u32i = 0; for(u32i = 0; u32i < pst->u32Len; u32i++) { MSC->LOCK = MSC_UNLOCK_CODE; MSC->WRITECTRL |= MSC_WRITECTRL_WREN; MSC->LOCK = MSC_UNLOCK_CODE; MSC->ADDRB = pst->u32Addr + 4*u32i; // Load address. MSC->WRITECMD = MSC_WRITECMD_LADDRIM; MSC->LOCK = MSC_UNLOCK_CODE; MSC->WDATA = 0x11111111;//pst->pu8Data[u32i]; // Load data. MSC->WRITECMD = MSC_WRITECMD_WRITEONCE; // Trigger write once. while (MSC->STATUS & MSC_STATUS_BUSY); // Waiting for the write to complete. } #endif } break; case E_FLASH_IOCTL_CMD_READ: { T_U32 u32i = 0; S_FlashRead *pst = (S_FlashRead *)pvData; for(u32i = 0; u32i < pst->u32Len; u32i++) { pst->pu8Data[u32i] = *(T_U8 *)(pst->u32Addr + u32i); } } break; } return s32Ret; } /******************************************** *功能:写入函数 *输入:无 *输出:无 *条件:无 *返回:成功:RET_SUCCESS 失败:RET_FAILED 或者长度 注意: *********************************************/ T_S32 DRIVER_FLASH_Write(T_S8 *ps8DataBuf, T_S32 s32BufLen) { return s32BufLen; } static unsigned int gRamBuf[256]; void BSP_FlashWrite(unsigned int Addr, unsigned char *lpBuf, unsigned short n) { unsigned char *lpOBJ = (unsigned char *)gRamBuf; unsigned int *lpAddr = gRamBuf; unsigned short i; for(i = 0; i < n; i++) { lpOBJ[i] = lpBuf[i]; } for(i = 0; i < n; i += 4) { MSC->ADDRB = Addr+i; // Load address. MSC->WRITECMD = MSC_WRITECMD_LADDRIM; MSC->WDATA = *lpAddr++; // Load data. MSC->WRITECMD = MSC_WRITECMD_WRITEONCE; // Trigger write once. while (MSC->STATUS & MSC_STATUS_BUSY); // Waiting for the write to complete. } }   #include #include "em_device.h" #include "ioctrl.h" #include "xmodem.h" static unsigned int gRawBuf[2][sizeof(XMODEM_PACKET_TYPE)>>2]; static unsigned short CRC16E(unsigned char *lpBuf, unsigned short n) { unsigned short crc = 0x0; unsigned short i; for (i = 0; i < n; i++) { crc = (crc >> 8) | (crc << 8); crc ^= lpBuf[i]; crc ^= (crc & 0xff) >> 4; crc ^= crc << 12; crc ^= (crc & 0xff) << 5; } return crc; } static unsigned short XMODEM_Verify(XMODEM_PACKET_TYPE *Struct, unsigned char Reference) { if (Struct->Number == Reference) { unsigned short crc = (Struct->CRCH<<8)|Struct->CRCL; if(crc == CRC16E(Struct->Data, XMODEM_DATA_SIZE)) { return 0; } } return -1; } static void XMODEM_Wait(void) { unsigned int i; while (1) { xputc(XMODEM_NCG); for (i = 0; i < 2000000; i++) { if(xkbhit()) { return; } } } } int xmodem(unsigned int Base, unsigned int End) { XMODEM_PACKET_TYPE *Struct; unsigned int Addr, i; unsigned char Sequence = 1; #if 0 for (Addr = Base; Addr < End; Addr += FLASH_PAGE_SIZE) { BSP_FlashErase(Addr); } #endif XMODEM_Wait(); Addr = Base; while (1) { // Swap buffer for packet buffer. Struct = (XMODEM_PACKET_TYPE *)gRawBuf[Sequence & 1]; // Fetch the first byte of the packet explicitly, as it defines the // rest of the packet. Struct->Header = xgetc(); // Check for end of transfer. if (Struct->Header == XMODEM_EOT) { // Acknowledget End of transfer. xputc(XMODEM_ACK); return 1; } // If the header is not a start of header (SOH), then cancel // the transfer. if (Struct->Header != XMODEM_SOH) { return -1; } // Fill the remaining bytes packet. // Byte 0 is padding, byte 1 is header. for (i = 2; i < sizeof(XMODEM_PACKET_TYPE); i++) { ((unsigned char *)Struct)[i] = xgetc(); } /* Packet Verify */ if(0 != XMODEM_Verify(Struct, Sequence)) { // On a malformed packet, we send a NAK, and start over. xputc(XMODEM_NAK); return -1; } Sequence++; // Write data to flash. if(Addr < End) { //BSP_FlashWrite(Addr, Struct->Data, XMODEM_DATA_SIZE); //memset(Struct->Data, 0x11, XMODEM_DATA_SIZE); S_FlashWrite stFlashWrite; stFlashWrite.u32Addr = Addr; stFlashWrite.pu8Data = Struct->Data; stFlashWrite.u32Len = XMODEM_DATA_SIZE; if(RET_FAILED==DRIVER_FLASH_Ioctl(E_FLASH_IOCTL_CMD_WRITE, &stFlashWrite)) { return -1; } Addr += XMODEM_DATA_SIZE; } // Send ACK. xputc(XMODEM_ACK); } }  

2.3 编写软件注意事项

      1)操作flash要关闭中断       2)flash写接口要是4的倍数       3)应用程序编译时需要修改起始地址             iar的话需要在  iar的安装路径下找到  Option->Linker->Config里面的  .icf文件

2.4升级步骤

         1)打开Tera Term,设置好 串口及 波特率,复位单片机出现下面的信息,按u进入升级 选择 File->Transfer->XMODEM->send  找到发送文件即可