EFM32 单片机调试总结

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/cheng401733277/article/details/83866128

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,不要使用内部低频晶振做输入,偏频较大

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!\r\n", sizeof("Please Input Command!\r\n")-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!\r\n", sizeof("Please Update!\r\n")-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!\r\n", sizeof("Update Success!\r\n")-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!\r\n", sizeof("Don't Have App!\r\n")-1);

		DRIVER_SYS_Halt();
	}else
	{
		DRIVER_UART_Write("Into App!\r\n", sizeof("Into App!\r\n")-1);
		T_S8 s8StartAddr[] = "Start Addr = 0x00000000\r\n";
		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!\r\n", sizeof("Update Fail!\r\n")-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 <stdio.h>
#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  找到发送文件即可

猜你喜欢

转载自blog.csdn.net/cheng401733277/article/details/83866128