Linux的芯片驱动firmware自动升级之二:MELFAS的TP升级实例

以MELFAS的MS6000芯片固件升级实例,说明一般的数组格式的IMAGE文件烧录的过程。该芯片需要PIN脚组合完成一定的时序并实现一组命令码进入烧录模式,并且在烧录模式下的I2C地址是0XFA(跟芯片正常工作时的地址0X40不同),在烧录完毕后进行复位并开始相应正常的TP操作。芯片大致的烧录了流程图如下:

         

实现代码如下:

(1)基础宏定义

  1. #define FIAMWARE_NAME   "MELFAS_W105.h"                     //数组格式IMAGE的名字 
  2. static unsigned char MS6000CTPM_FW[] =                      //以数组划分空间存储烧录映象 
  3.     #include FIAMWARE_NAME 
  4. }; 
  5. #define MS6000_ADDR_MODULE_REVISION                 0x98 
  6. #define MS6000_ADDR_FIRMWARE_VERSION                    0x9C        //烧录IMAGE中对应的特定字节地址 
  7. #define MS6000_TRANSFER_LENGTH                      64  //一次烧录的packet字节数 
  8.  
  9. /*ISP command*/ 
  10. #define MS6000_ISP_CMD_ERASE                    0x02 
  11. #define MS6000_ISP_CMD_ERASE_TIMING                 0x0F 
  12. #define MS6000_ISP_CMD_PROGRAM_FLASH                    0x03 
  13. #define MS6000_ISP_CMD_READ_FLASH                   0x04 
  14. #define MS6000_ISP_CMD_PROGRAM_TIMING               0x0F 
  15. #define MS6000_ISP_CMD_READ_INFORMATION             0x06 
  16. #define MS6000_ISP_CMD_RESET                            0x07 
  17.  
  18. #define MS6000_7BIT_DOWNLOAD_ADDR                   0x7D         
  19. #define MS6000_8BIT_DOWNLOAD_ADDR                   (MS6000_7BIT_DOWNLOAD_ADDR<<1) //linux的i2Cclient需8位地址  
  20. #define MS6000_I2C_SLAVE_READY_STATUS               0x55 
  21.  
  22. // MCS6000's responses 
  23. #define MS6000_ISP_ACK_ERASE_DONE                   0x82 
  24. #define MS6000_ISP_ACK_PREPARE_ERASE_DONE           0x8F 
  25. #define MS6000_I2C_ACK_PREPARE_PROGRAM              0x8F 
  26. #define MS6000_MDS_ACK_PROGRAM_FLASH                    0x83 
  27. #define MS6000_MDS_ACK_READ_FLASH                   0x84 
  28. #define MS6000_MDS_ACK_PROGRAM_INFORMATION          0x88 
  29. #define MS6000_MDS_ACK_PROGRAM_LOCKED               0xFE 
  30. #define MS6000_MDS_ACK_READ_LOCKED                  0xFE 
  31. #define MS6000_MDS_ACK_FAIL                         0xFE 
  32.  
  33. #define MS6000_ISP_ERASE_TIMING_VALUE_0             0x01 
  34. #define MS6000_ISP_ERASE_TIMING_VALUE_1             0xD4 
  35. #define MS6000_ISP_ERASE_TIMING_VALUE_2             0xC0 
  36.  
  37. #define MS6000_ISP_PROGRAM_TIMING_VALUE_0           0x00 
  38. #define MS6000_ISP_PROGRAM_TIMING_VALUE_1           0x00 
  39. #define MS6000_ISP_PROGRAM_TIMING_VALUE_2           0x78 
#define FIAMWARE_NAME 	"MELFAS_W105.h"    					//数组格式IMAGE的名字
static unsigned char MS6000CTPM_FW[] =						//以数组划分空间存储烧录映象
{
	#include FIAMWARE_NAME
};
#define MS6000_ADDR_MODULE_REVISION					0x98
#define MS6000_ADDR_FIRMWARE_VERSION					0x9C		//烧录IMAGE中对应的特定字节地址
#define MS6000_TRANSFER_LENGTH						64	//一次烧录的packet字节数

/*ISP command*/
#define MS6000_ISP_CMD_ERASE					0x02
#define MS6000_ISP_CMD_ERASE_TIMING					0x0F
#define MS6000_ISP_CMD_PROGRAM_FLASH					0x03
#define MS6000_ISP_CMD_READ_FLASH					0x04
#define MS6000_ISP_CMD_PROGRAM_TIMING				0x0F
#define MS6000_ISP_CMD_READ_INFORMATION				0x06
#define MS6000_ISP_CMD_RESET							0x07

#define MS6000_7BIT_DOWNLOAD_ADDR					0x7D		
#define MS6000_8BIT_DOWNLOAD_ADDR					(MS6000_7BIT_DOWNLOAD_ADDR<<1) //linux的i2Cclient需8位地址	
#define MS6000_I2C_SLAVE_READY_STATUS				0x55

// MCS6000's responses
#define MS6000_ISP_ACK_ERASE_DONE					0x82
#define MS6000_ISP_ACK_PREPARE_ERASE_DONE			0x8F
#define MS6000_I2C_ACK_PREPARE_PROGRAM				0x8F
#define MS6000_MDS_ACK_PROGRAM_FLASH					0x83
#define MS6000_MDS_ACK_READ_FLASH					0x84
#define MS6000_MDS_ACK_PROGRAM_INFORMATION			0x88
#define MS6000_MDS_ACK_PROGRAM_LOCKED				0xFE
#define MS6000_MDS_ACK_READ_LOCKED					0xFE
#define MS6000_MDS_ACK_FAIL							0xFE

#define MS6000_ISP_ERASE_TIMING_VALUE_0				0x01
#define MS6000_ISP_ERASE_TIMING_VALUE_1				0xD4
#define MS6000_ISP_ERASE_TIMING_VALUE_2				0xC0

#define MS6000_ISP_PROGRAM_TIMING_VALUE_0			0x00
#define MS6000_ISP_PROGRAM_TIMING_VALUE_1			0x00
#define MS6000_ISP_PROGRAM_TIMING_VALUE_2			0x78

(2)I2C烧写和读TP FLASH的函数
       注意:该芯片在烧录模式下的单字节读操作和写操作都不需要寄存器地址,只send芯片地址就行。里面用到的i2c_client->address已变换地址。

  1. static bool mfs_i2c_write_single_byte(unsigned char bufVal) 
  2.     int ret; 
  3.     unsigned char buf; 
  4.     buf = bufVal; 
  5.  
  6.     ret = i2c_master_send(i2c_client, &buf, 1); 
  7.     if(ret <= 0){ 
  8.                 printk("mfs_i2c_write_single_byte error line = %d, ret = %d\n", __LINE__, ret); 
  9.                 return false
  10.         } 
  11.     return true
  12. static bool mfs_i2c_read_single_byte(unsigned char *buf) 
  13.     int ret; 
  14.     ret = i2c_master_recv(i2c_client, buf, 1); 
  15.     if(ret <= 0){ 
  16.                 printk("mfs_i2c_read_single_byte error line = %d, ret = %d\n", __LINE__, ret); 
  17.                 return false
  18.         } 
  19.     return true
  20. static int mfs_i2c_read_flash(unsigned char *pBuffer,UINT16 nAddr_start,unsigned char cLength) 
  21. {                               //将nAddr_start开始的cLength个字节读到pBuffer所指的空间中 
  22.     int nRet = MS6000_RET_READ_FLASH_FAILED,i; 
  23.     BOOL bRet; 
  24.     unsigned char cmd[4],ucTemp; 
  25.  
  26. // Send Read Flash command   [ Read code - address high - address low - size ]   
  27.     cmd[0] = MS6000_ISP_CMD_READ_FLASH; 
  28.     cmd[1] = (UINT8)((nAddr_start >> 8 ) & 0xFF); 
  29.     cmd[2] = (UINT8)((nAddr_start      ) & 0xFF); 
  30.     cmd[3] = cLength; 
  31.  
  32.     for(i=0;i<4;i++){ 
  33.         bRet = mfs_i2c_write_single_byte(cmd[i]); 
  34.         udelay(15); 
  35.         if(bRet == FALSE) 
  36.             goto MS6000_I2C_READ_FLASH_FINISH; 
  37.     } 
  38. // Read 'Result of command' 
  39.     bRet = mfs_i2c_read_single_byte(&ucTemp); 
  40.     if( !bRet || ucTemp != MS6000_MDS_ACK_READ_FLASH){ 
  41.         goto MS6000_I2C_READ_FLASH_FINISH; 
  42.     } 
  43. // Read Data  [ pCmd[3] == Size ] 
  44.     for(i=0; i<(int)cmd[3]; i++){ 
  45.         udelay(100); 
  46.         bRet = mfs_i2c_read_single_byte(pBuffer++); 
  47.         if( bRet == FALSE && i!=(int)(cmd[3]-1) ) 
  48.             goto MS6000_I2C_READ_FLASH_FINISH; 
  49.     } 
  50.     nRet = MS6000_RET_SUCCESS; 
  51.      
  52. MS6000_I2C_READ_FLASH_FINISH: 
  53.     return nRet; 
static bool mfs_i2c_write_single_byte(unsigned char bufVal)
{
	int ret;
	unsigned char buf;
	buf = bufVal;

	ret = i2c_master_send(i2c_client, &buf, 1);
	if(ret <= 0){
        		printk("mfs_i2c_write_single_byte error line = %d, ret = %d\n", __LINE__, ret);
        		return false;
    	}
	return true;
}
static bool mfs_i2c_read_single_byte(unsigned char *buf)
{
	int ret;
	ret = i2c_master_recv(i2c_client, buf, 1);
	if(ret <= 0){
        		printk("mfs_i2c_read_single_byte error line = %d, ret = %d\n", __LINE__, ret);
        		return false;
    	}
	return true;
}
static int mfs_i2c_read_flash(unsigned char *pBuffer,UINT16 nAddr_start,unsigned char cLength)
{								//将nAddr_start开始的cLength个字节读到pBuffer所指的空间中
	int nRet = MS6000_RET_READ_FLASH_FAILED,i;
	BOOL bRet;
	unsigned char cmd[4],ucTemp;

// Send Read Flash command   [ Read code - address high - address low - size ]	
	cmd[0] = MS6000_ISP_CMD_READ_FLASH;
	cmd[1] = (UINT8)((nAddr_start >> 8 ) & 0xFF);
	cmd[2] = (UINT8)((nAddr_start      ) & 0xFF);
	cmd[3] = cLength;

	for(i=0;i<4;i++){
		bRet = mfs_i2c_write_single_byte(cmd[i]);
		udelay(15);
		if(bRet == FALSE)
			goto MS6000_I2C_READ_FLASH_FINISH;
	}
// Read 'Result of command'
	bRet = mfs_i2c_read_single_byte(&ucTemp);
	if( !bRet || ucTemp != MS6000_MDS_ACK_READ_FLASH){
		goto MS6000_I2C_READ_FLASH_FINISH;
	}
// Read Data  [ pCmd[3] == Size ]
	for(i=0; i<(int)cmd[3]; i++){
		udelay(100);
		bRet = mfs_i2c_read_single_byte(pBuffer++);
		if( bRet == FALSE && i!=(int)(cmd[3]-1) )
			goto MS6000_I2C_READ_FLASH_FINISH;
	}
	nRet = MS6000_RET_SUCCESS;
	
MS6000_I2C_READ_FLASH_FINISH:
	return nRet;
}

(3)进入download功能

  1. static void ms6000_write_download_mode_signal(void)                 //通过RESET脚和EINT脚发出一组组合电平 
  2.     int i; 
  3.     unsigned char enter_code[14] = { 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1 }; 
  4.  
  5.     for(i=0; i<14; i++){ 
  6.         if(enter_code[i]){ 
  7.             mt_set_gpio_out(GPIO_CTP_RST_PIN, GPIO_OUT_ONE);     
  8.             mt_set_gpio_out(GPIO_CTP_EINT_PIN, GPIO_OUT_ONE); 
  9.         } 
  10.         else
  11.             mt_set_gpio_out(GPIO_CTP_RST_PIN, GPIO_OUT_ZERO);    
  12.             mt_set_gpio_out(GPIO_CTP_EINT_PIN, GPIO_OUT_ZERO); 
  13.         } 
  14.         mt_set_gpio_out(GPIO_I2C0_SCA_PIN, GPIO_OUT_ONE); 
  15.         udelay(15); 
  16.         mt_set_gpio_out(GPIO_I2C0_SCA_PIN, GPIO_OUT_ZERO); 
  17.  
  18.         mt_set_gpio_out(GPIO_CTP_RST_PIN, GPIO_OUT_ZERO);    
  19.         mt_set_gpio_out(GPIO_CTP_EINT_PIN, GPIO_OUT_ZERO); 
  20.         udelay(100); 
  21.     } 
  22.     mt_set_gpio_out(GPIO_I2C0_SCA_PIN, GPIO_OUT_ONE); 
  23.     udelay(100); 
  24.     mt_set_gpio_out(GPIO_CTP_EINT_PIN, GPIO_OUT_ONE); 
  25.     mt_set_gpio_out(GPIO_CTP_RST_PIN, GPIO_OUT_ONE);     
  26. static int ms6000_enter_download_mode(void
  27.     bool bRet; 
  28.     int nRet = MS6000_RET_ENTER_DOWNLOAD_MODE_FAILED; 
  29.  
  30.     unsigned char cData=0; 
  31.  
  32.     hwPowerDown(MT65XX_POWER_LDO_VGP2, "TP");   //TKEY_VDD_SET_LOW();     
  33.  
  34.     mt_set_gpio_mode(GPIO_I2C0_SCA_PIN, GPIO_I2C0_SCA_PIN_M_GPIO); 
  35.     mt_set_gpio_dir(GPIO_I2C0_SCA_PIN, GPIO_DIR_OUT); 
  36.     mt_set_gpio_out(GPIO_I2C0_SCA_PIN, GPIO_OUT_ZERO);   
  37.     mt_set_gpio_mode(GPIO_I2C0_SDA_PIN, GPIO_I2C0_SDA_PIN_M_GPIO); 
  38.     mt_set_gpio_dir(GPIO_I2C0_SDA_PIN, GPIO_DIR_OUT); 
  39.     mt_set_gpio_out(GPIO_I2C0_SDA_PIN, GPIO_OUT_ZERO);      //I2C变GPIO功能 
  40.  
  41.     mt_set_gpio_mode(GPIO_CTP_EINT_PIN, GPIO_CTP_EINT_PIN_M_GPIO); 
  42.     mt_set_gpio_dir(GPIO_CTP_EINT_PIN, GPIO_DIR_OUT);           //TKEY_INTR_SET_OUTPUT(); 
  43.     mt_set_gpio_out(GPIO_CTP_EINT_PIN, GPIO_OUT_ZERO);      //TKEY_INTR_SET_LOW(); 
  44.  
  45.     mt_set_gpio_mode(GPIO_CTP_RST_PIN, GPIO_CTP_RST_PIN_M_GPIO); 
  46.         mt_set_gpio_dir(GPIO_CTP_RST_PIN, GPIO_DIR_OUT);        //TKEY_RESETB_SET_OUTPUT(); 
  47.         mt_set_gpio_out(GPIO_CTP_RST_PIN, GPIO_OUT_ZERO);       //若干功能脚均需完成电平拉低的作用   
  48.  
  49.     mdelay(90);     //Delay for Stable VDD 
  50.  
  51.     hwPowerOn(MT65XX_POWER_LDO_VGP2, VOL_2800, "TP");   //TKEY_VDD_SET_HIGH(); 
  52.     mt_set_gpio_out(GPIO_CTP_RST_PIN, GPIO_OUT_ONE);        //TKEY_CE_SET_HIGH(); 
  53.     mt_set_gpio_out(GPIO_I2C0_SDA_PIN, GPIO_OUT_ONE);       //TKEY_I2C_SDA_SET_HIGH(); 
  54.     mdelay(25); 
  55.  
  56.     ms6000_write_download_mode_signal();                    //写命令码 
  57.     mt_set_gpio_mode(GPIO_I2C0_SCA_PIN, GPIO_I2C0_SCA_PIN_M_SCL); 
  58.     mt_set_gpio_mode(GPIO_I2C0_SDA_PIN, GPIO_I2C0_SDA_PIN_M_SDA);      //使能I2C的PIN脚恢复I2C功能 
  59.     mdelay(2); 
  60.     bRet = mfs_i2c_read_single_byte(&cData); 
  61.     if( bRet != TRUE || cData != MS6000_I2C_SLAVE_READY_STATUS ){ 
  62.         goto MS6000_ENTER_DOWNLOAD_MODE_FINISH; 
  63.     } 
  64.     else 
  65.         printk("respond from download mode commande is 0x55 \r\n");   //只有芯片状态返回0x55,才说明进入DOWNLOAD模式 
  66.     nRet = MS6000_RET_SUCCESS;  //Entering MDS ISP mode finished. 
  67.  
  68. MS6000_ENTER_DOWNLOAD_MODE_FINISH: 
  69.     return nRet; 
static void ms6000_write_download_mode_signal(void)					//通过RESET脚和EINT脚发出一组组合电平
{
	int i;
	unsigned char enter_code[14] = { 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1 };

	for(i=0; i<14; i++){
		if(enter_code[i]){
			mt_set_gpio_out(GPIO_CTP_RST_PIN, GPIO_OUT_ONE);	
			mt_set_gpio_out(GPIO_CTP_EINT_PIN, GPIO_OUT_ONE);
		}
		else{
			mt_set_gpio_out(GPIO_CTP_RST_PIN, GPIO_OUT_ZERO);	
			mt_set_gpio_out(GPIO_CTP_EINT_PIN, GPIO_OUT_ZERO);
		}
		mt_set_gpio_out(GPIO_I2C0_SCA_PIN, GPIO_OUT_ONE);
		udelay(15);
		mt_set_gpio_out(GPIO_I2C0_SCA_PIN, GPIO_OUT_ZERO);

		mt_set_gpio_out(GPIO_CTP_RST_PIN, GPIO_OUT_ZERO);	
		mt_set_gpio_out(GPIO_CTP_EINT_PIN, GPIO_OUT_ZERO);
		udelay(100);
	}
	mt_set_gpio_out(GPIO_I2C0_SCA_PIN, GPIO_OUT_ONE);
	udelay(100);
	mt_set_gpio_out(GPIO_CTP_EINT_PIN, GPIO_OUT_ONE);
	mt_set_gpio_out(GPIO_CTP_RST_PIN, GPIO_OUT_ONE);	
}
static int ms6000_enter_download_mode(void)
{
	bool bRet;
	int nRet = MS6000_RET_ENTER_DOWNLOAD_MODE_FAILED;

	unsigned char cData=0;

	hwPowerDown(MT65XX_POWER_LDO_VGP2, "TP");	//TKEY_VDD_SET_LOW();    

	mt_set_gpio_mode(GPIO_I2C0_SCA_PIN, GPIO_I2C0_SCA_PIN_M_GPIO);
	mt_set_gpio_dir(GPIO_I2C0_SCA_PIN, GPIO_DIR_OUT);
	mt_set_gpio_out(GPIO_I2C0_SCA_PIN, GPIO_OUT_ZERO);	
	mt_set_gpio_mode(GPIO_I2C0_SDA_PIN, GPIO_I2C0_SDA_PIN_M_GPIO);
	mt_set_gpio_dir(GPIO_I2C0_SDA_PIN, GPIO_DIR_OUT);
	mt_set_gpio_out(GPIO_I2C0_SDA_PIN, GPIO_OUT_ZERO);		//I2C变GPIO功能

	mt_set_gpio_mode(GPIO_CTP_EINT_PIN, GPIO_CTP_EINT_PIN_M_GPIO);
	mt_set_gpio_dir(GPIO_CTP_EINT_PIN, GPIO_DIR_OUT);			//TKEY_INTR_SET_OUTPUT();
	mt_set_gpio_out(GPIO_CTP_EINT_PIN, GPIO_OUT_ZERO);		//TKEY_INTR_SET_LOW();

	mt_set_gpio_mode(GPIO_CTP_RST_PIN, GPIO_CTP_RST_PIN_M_GPIO);
    	mt_set_gpio_dir(GPIO_CTP_RST_PIN, GPIO_DIR_OUT);		//TKEY_RESETB_SET_OUTPUT();
    	mt_set_gpio_out(GPIO_CTP_RST_PIN, GPIO_OUT_ZERO);		//若干功能脚均需完成电平拉低的作用	

	mdelay(90);		//Delay for Stable VDD

	hwPowerOn(MT65XX_POWER_LDO_VGP2, VOL_2800, "TP");	//TKEY_VDD_SET_HIGH();
	mt_set_gpio_out(GPIO_CTP_RST_PIN, GPIO_OUT_ONE);		//TKEY_CE_SET_HIGH();
	mt_set_gpio_out(GPIO_I2C0_SDA_PIN, GPIO_OUT_ONE);		//TKEY_I2C_SDA_SET_HIGH();
	mdelay(25);

	ms6000_write_download_mode_signal();					//写命令码
	mt_set_gpio_mode(GPIO_I2C0_SCA_PIN, GPIO_I2C0_SCA_PIN_M_SCL);
	mt_set_gpio_mode(GPIO_I2C0_SDA_PIN, GPIO_I2C0_SDA_PIN_M_SDA);      //使能I2C的PIN脚恢复I2C功能
	mdelay(2);
	bRet = mfs_i2c_read_single_byte(&cData);
	if( bRet != TRUE || cData != MS6000_I2C_SLAVE_READY_STATUS ){
		goto MS6000_ENTER_DOWNLOAD_MODE_FINISH;
	}
	else
		printk("respond from download mode commande is 0x55 \r\n");   //只有芯片状态返回0x55,才说明进入DOWNLOAD模式
	nRet = MS6000_RET_SUCCESS;	//Entering MDS ISP mode finished.

MS6000_ENTER_DOWNLOAD_MODE_FINISH:
	return nRet;
}

(4)芯片复位和TP FLASH擦除

  1. static void ms6000_reset_command(void)                  //不管是升级过程失败还是成功,最后都需要复位并使能芯片 
  2.     unsigned char buf; 
  3.     mdelay(1); 
  4.     buf = MS6000_ISP_CMD_RESET; 
  5.     if(mfs_i2c_write_single_byte(buf) == true
  6.         printk("mfs6000_reset_command reset success \r\n"); 
  7.     mt_set_gpio_mode(GPIO_CTP_EINT_PIN, GPIO_CTP_EINT_PIN_M_EINT); 
  8.     mt_set_gpio_dir(GPIO_CTP_EINT_PIN, GPIO_DIR_IN); 
  9.     mt_set_gpio_pull_enable(GPIO_CTP_EINT_PIN, GPIO_PULL_ENABLE); 
  10.     mt_set_gpio_pull_select(GPIO_CTP_EINT_PIN, GPIO_PULL_UP);           //恢复EINT的pin功能 
  11.     mdelay(180); 
  12. static unsigned char ms6000_GetLibVer(void)                     //取得新固件中的版本号,以便比较 
  13.      unsigned int sz; 
  14.         sz = sizeof(MS6000CTPM_FW); 
  15.  
  16.         if(sz > 2){ 
  17.                 return (MS6000CTPM_FW[157]-0x30);                   //版本号字节数据 
  18.         } 
  19.         else
  20.                 return 0xff; 
  21.         } 
  22. static int ms6000_i2c_prepare_erase_flash(void
  23.     int   nRet = MS6000_RET_PREPARE_ERASE_FLASH_FAILED,i; 
  24.     BOOL bRet; 
  25.  
  26.     UINT8 i2c_buffer[4] = { MS6000_ISP_CMD_ERASE_TIMING, 
  27.                             MS6000_ISP_ERASE_TIMING_VALUE_0, 
  28.                             MS6000_ISP_ERASE_TIMING_VALUE_1, 
  29.                             MS6000_ISP_ERASE_TIMING_VALUE_2   }; 
  30.     UINT8   ucTemp; 
  31. // Send Erase Setting code 
  32.     for(i=0; i<4; i++){ 
  33.         bRet = mfs_i2c_write_single_byte(i2c_buffer[i]); 
  34.         if( !bRet ){ 
  35.             goto MS6000_I2C_PREPARE_ERASE_FLASH_FINISH; 
  36.         } 
  37.         udelay(15); 
  38.     } 
  39. // Read Result 
  40.     udelay(500); 
  41.     bRet = mfs_i2c_read_single_byte(&ucTemp); 
  42.     if( bRet && ucTemp == MS6000_ISP_ACK_PREPARE_ERASE_DONE ){ 
  43.         nRet = MS6000_RET_SUCCESS; 
  44.     } 
  45.  
  46. MS6000_I2C_PREPARE_ERASE_FLASH_FINISH: 
  47.     return nRet; 
  48. static int ms6000_i2c_erase_flash(void
  49.     int   nRet = MS6000_RET_ERASE_FLASH_FAILED,i; 
  50.     BOOL bRet; 
  51.     UINT8   i2c_buffer[1] = {   MS6000_ISP_CMD_ERASE}; 
  52.     UINT8   ucTemp; 
  53. // Send Erase code 
  54.     for(i=0; i<1; i++){ 
  55.         bRet = mfs_i2c_write_single_byte(i2c_buffer[i]); 
  56.         if( !bRet ) 
  57.             goto MS6000_I2C_ERASE_FLASH_FINISH; 
  58.         udelay(15); 
  59.     } 
  60. // Read Result 
  61.     mdelay(45); 
  62.     bRet = mfs_i2c_read_single_byte(&ucTemp); 
  63.     if( bRet && ucTemp == MS6000_ISP_ACK_ERASE_DONE ){ 
  64.         nRet = MS6000_RET_SUCCESS; 
  65.     } 
  66.  
  67. MS6000_I2C_ERASE_FLASH_FINISH:   
  68.     return nRet; 
static void ms6000_reset_command(void)					//不管是升级过程失败还是成功,最后都需要复位并使能芯片
{
	unsigned char buf;
	mdelay(1);
	buf = MS6000_ISP_CMD_RESET;
	if(mfs_i2c_write_single_byte(buf) == true)
		printk("mfs6000_reset_command reset success \r\n");
	mt_set_gpio_mode(GPIO_CTP_EINT_PIN, GPIO_CTP_EINT_PIN_M_EINT);
	mt_set_gpio_dir(GPIO_CTP_EINT_PIN, GPIO_DIR_IN);
	mt_set_gpio_pull_enable(GPIO_CTP_EINT_PIN, GPIO_PULL_ENABLE);
	mt_set_gpio_pull_select(GPIO_CTP_EINT_PIN, GPIO_PULL_UP);			//恢复EINT的pin功能
	mdelay(180);
}
static unsigned char ms6000_GetLibVer(void)						//取得新固件中的版本号,以便比较
{
	 unsigned int sz;
    	sz = sizeof(MS6000CTPM_FW);

    	if(sz > 2){
        		return (MS6000CTPM_FW[157]-0x30);					//版本号字节数据
    	}
    	else{
        		return 0xff;
    	}
}
static int ms6000_i2c_prepare_erase_flash(void)
{
	int   nRet = MS6000_RET_PREPARE_ERASE_FLASH_FAILED,i;
	BOOL bRet;

	UINT8 i2c_buffer[4] = {	MS6000_ISP_CMD_ERASE_TIMING,
	                        MS6000_ISP_ERASE_TIMING_VALUE_0,
	                        MS6000_ISP_ERASE_TIMING_VALUE_1,
	                        MS6000_ISP_ERASE_TIMING_VALUE_2   };
	UINT8	ucTemp;
// Send Erase Setting code
	for(i=0; i<4; i++){
		bRet = mfs_i2c_write_single_byte(i2c_buffer[i]);
		if( !bRet ){
			goto MS6000_I2C_PREPARE_ERASE_FLASH_FINISH;
		}
		udelay(15);
   	}
// Read Result
	udelay(500);
	bRet = mfs_i2c_read_single_byte(&ucTemp);
	if( bRet && ucTemp == MS6000_ISP_ACK_PREPARE_ERASE_DONE ){
		nRet = MS6000_RET_SUCCESS;
	}

MS6000_I2C_PREPARE_ERASE_FLASH_FINISH:
	return nRet;
}
static int ms6000_i2c_erase_flash(void)
{
	int   nRet = MS6000_RET_ERASE_FLASH_FAILED,i;
	BOOL bRet;
	UINT8 	i2c_buffer[1] = {	MS6000_ISP_CMD_ERASE};
	UINT8 	ucTemp;
// Send Erase code
	for(i=0; i<1; i++){
		bRet = mfs_i2c_write_single_byte(i2c_buffer[i]);
		if( !bRet )
			goto MS6000_I2C_ERASE_FLASH_FINISH;
		udelay(15);
   	}
// Read Result
	mdelay(45);
	bRet = mfs_i2c_read_single_byte(&ucTemp);
	if( bRet && ucTemp == MS6000_ISP_ACK_ERASE_DONE ){
		nRet = MS6000_RET_SUCCESS;
	}

MS6000_I2C_ERASE_FLASH_FINISH:	
	return nRet;
}

(5)预编程和编程函数,以及download映象主函数

  1. static int ms6000_i2c_prepare_program(void
  2.     int nRet = MS6000_RET_PREPARE_PROGRAM_FAILED,i; 
  3.     BOOL bRet; 
  4.     UINT8 i2c_buffer[4] = { MS6000_ISP_CMD_PROGRAM_TIMING, 
  5.                             MS6000_ISP_PROGRAM_TIMING_VALUE_0, 
  6.                             MS6000_ISP_PROGRAM_TIMING_VALUE_1, 
  7.                             MS6000_ISP_PROGRAM_TIMING_VALUE_2}; 
  8. //   Write Program timing information 
  9.     for(i=0; i<4; i++){ 
  10.         bRet = mfs_i2c_write_single_byte(i2c_buffer[i]); 
  11.         if( bRet == FALSE ) 
  12.             goto MS6000_I2C_PREPARE_PROGRAM_FINISH; 
  13.         udelay(15); 
  14.     } 
  15.     udelay(500); 
  16. //   Read command's result 
  17.     bRet = mfs_i2c_read_single_byte(&i2c_buffer[4]); 
  18.     if( bRet == FALSE || i2c_buffer[4] != MS6000_I2C_ACK_PREPARE_PROGRAM) 
  19.         goto MS6000_I2C_PREPARE_PROGRAM_FINISH; 
  20.     mdelay(100); 
  21.     nRet = MS6000_RET_SUCCESS; 
  22.  
  23. MS6000_I2C_PREPARE_PROGRAM_FINISH:   
  24.     return nRet; 
  25. static int ms6000_i2c_program_flash( UINT8 *pData, UINT16 nAddr_start, UINT8 cLength )  //FLASH one packet编程主函数 
  26. {                                   //参数是待编程数据,写入地址,待编程数据长度 
  27.     int nRet = MS6000_RET_PROGRAM_FLASH_FAILED; 
  28.     int     i,j; 
  29.     BOOL   bRet; 
  30.     UINT8    cData; 
  31.     UINT8    tmp; 
  32.     UINT8    cmd[4]; 
  33. // Send program code     
  34.     cmd[0] = MS6000_ISP_CMD_PROGRAM_FLASH; 
  35.     cmd[1] = (UINT8)((nAddr_start >> 8 ) & 0xFF); 
  36.     cmd[2] = (UINT8)((nAddr_start      ) & 0xFF); 
  37.     cmd[3] = cLength; 
  38.     for(i=0; i<4; i++){ 
  39.         bRet = mfs_i2c_write_single_byte(cmd[i]); 
  40.         udelay(15); 
  41.         if( bRet == FALSE ) 
  42.             goto MS6000_I2C_PROGRAM_FLASH_FINISH; 
  43.     } 
  44. // Check command result 
  45.     bRet = mfs_i2c_read_single_byte(&cData); 
  46.     if( bRet == FALSE || cData != MS6000_MDS_ACK_PROGRAM_FLASH ){ 
  47.         goto MS6000_I2C_PROGRAM_FLASH_FINISH; 
  48.     } 
  49. // Program Data 
  50.     udelay(150); 
  51.     for(i=0; i<(int)cmd[3]; i+=2){               //一次写入两个字节,先写高位,再写低位 
  52.         bRet = mfs_i2c_write_single_byte(pData[i+1]); 
  53.         if( bRet == FALSE ) 
  54.             goto MS6000_I2C_PROGRAM_FLASH_FINISH; 
  55.         udelay(100);              // Delay about 150us 
  56.         bRet = mfs_i2c_write_single_byte(pData[i]); 
  57.         udelay(150);                   // Delay about 150us 
  58.         if( bRet == FALSE ) 
  59.             goto MS6000_I2C_PROGRAM_FLASH_FINISH; 
  60.     } 
  61.     nRet = MS6000_RET_SUCCESS; 
  62.  
  63. MS6000_I2C_PROGRAM_FLASH_FINISH:     
  64.     return nRet; 
  65. static int ms6000_download(const UINT8 *pData, const UINT16 nLength )   //download主函数,参数是映象内存首地址及映象长度 
  66.     int i,nRet; 
  67.     unsigned char cLength,buffer[MS6000_TRANSFER_LENGTH]; 
  68.     uint16_t nStart_address=0; 
  69.     unsigned char *pOriginal_data; 
  70. //enter in download mode 
  71.     nRet = ms6000_enter_download_mode(); 
  72.     if(nRet != MS6000_RET_SUCCESS) 
  73.         goto MS6000_DOWNLOAD_FINISH; 
  74.  
  75.     mdelay(1); 
  76. // Erase Flash 
  77.     nRet = ms6000_i2c_prepare_erase_flash(); 
  78.     if(nRet !=MS6000_RET_SUCCESS){ 
  79.         goto MS6000_DOWNLOAD_FINISH;     
  80.     } 
  81.     mdelay(1); 
  82.     nRet = ms6000_i2c_erase_flash(); 
  83.     if(nRet !=MS6000_RET_SUCCESS) 
  84.         goto MS6000_DOWNLOAD_FINISH; 
  85.     mdelay(1); 
  86. // Verify erase 
  87.     nRet = mfs_i2c_read_flash( buffer, 0x00, 16 );      // Must be '0xFF' after erase 
  88.     if( nRet != MS6000_RET_SUCCESS ) 
  89.         goto MS6000_DOWNLOAD_FINISH; 
  90.     for(i=0; i<16; i++){ 
  91.         if( buffer[i] != 0xFF ){ 
  92.             nRet = MS6000_RET_ERASE_VERIFY_FAILED; 
  93.             goto MS6000_DOWNLOAD_FINISH; 
  94.         } 
  95.     } 
  96.     mdelay(1); 
  97. // Prepare for Program flash.    
  98.     nRet = ms6000_i2c_prepare_program(); 
  99.     if( nRet != MS6000_RET_SUCCESS ) 
  100.         goto MS6000_DOWNLOAD_FINISH; 
  101.     mdelay(1); 
  102. // Program flash 
  103. #if 1 
  104.     pOriginal_data  = (UINT8 *)pData;                   //保留原始首地址 
  105.     nStart_address = 0;                     //烧录起始地址 
  106.     cLength  = MS6000_TRANSFER_LENGTH;                  //一次烧录长度,64B 
  107.     for( nStart_address = 0; nStart_address < nLength; nStart_address+=cLength ){ 
  108.         if( ( nLength - nStart_address ) < MS6000_TRANSFER_LENGTH ){ 
  109.             cLength  = (UINT8)(nLength - nStart_address); 
  110.             cLength += (cLength%2);     // For odd length.最后不足64B的,补上1字节当偶数处理,因为以WORD烧录 
  111.         } 
  112.         nRet = ms6000_i2c_program_flash( pOriginal_data, nStart_address, cLength ); 
  113.         if( nRet != MS6000_RET_SUCCESS ){ 
  114.             goto MS6000_DOWNLOAD_FINISH; 
  115.         } 
  116.         pOriginal_data  += cLength; 
  117.         udelay(500); 
  118.         printk("#"); 
  119.     } 
  120.     printk("mfs6000 program finished \r\n"); 
  121. #endif   
  122. // Verify flash 
  123. #if 1 
  124.     pOriginal_data  = (UINT8 *) pData;                  //保留原始首地址 
  125.     nStart_address = 0; 
  126.     cLength  = MS6000_TRANSFER_LENGTH; 
  127.     for( nStart_address = 0; nStart_address < nLength; nStart_address+=cLength ){ 
  128.         if( ( nLength - nStart_address ) < MS6000_TRANSFER_LENGTH ){ 
  129.             cLength = (UINT8)(nLength - nStart_address); 
  130.             cLength += (cLength%2);             // For odd length. 
  131.         } 
  132.         // Read flash 
  133.         nRet = mfs_i2c_read_flash( buffer, nStart_address, cLength ); 
  134.         // Comparing 
  135.         for(i=0; i<(int)cLength; i++){ 
  136.             if( buffer[i] != pOriginal_data[i] ){       //如果读出的对应地址字节与原始对应地址数据不同 
  137.                 nRet = MS6000_RET_PROGRAM_VERIFY_FAILED; 
  138.                 goto MS6000_DOWNLOAD_FINISH; 
  139.             } 
  140.         } 
  141.         pOriginal_data += cLength; 
  142.         udelay(500); 
  143.         printk("*"); 
  144.     } 
  145.     printk("mfs6000 Verify finished \r\n"); 
  146. #endif   
  147.     nRet = MS6000_RET_SUCCESS; 
  148.  
  149. MS6000_DOWNLOAD_FINISH: 
  150.     ms6000_reset_command(); 
  151.     return nRet; 
static int ms6000_i2c_prepare_program(void)
{
	int nRet = MS6000_RET_PREPARE_PROGRAM_FAILED,i;
	BOOL bRet;
	UINT8 i2c_buffer[4] = { MS6000_ISP_CMD_PROGRAM_TIMING,
		                    MS6000_ISP_PROGRAM_TIMING_VALUE_0,
		                    MS6000_ISP_PROGRAM_TIMING_VALUE_1,
		                    MS6000_ISP_PROGRAM_TIMING_VALUE_2};
//   Write Program timing information
	for(i=0; i<4; i++){
		bRet = mfs_i2c_write_single_byte(i2c_buffer[i]);
		if( bRet == FALSE )
			goto MS6000_I2C_PREPARE_PROGRAM_FINISH;
		udelay(15);
	}
	udelay(500);
//   Read command's result
	bRet = mfs_i2c_read_single_byte(&i2c_buffer[4]);
	if( bRet == FALSE || i2c_buffer[4] != MS6000_I2C_ACK_PREPARE_PROGRAM)
		goto MS6000_I2C_PREPARE_PROGRAM_FINISH;
	mdelay(100);
	nRet = MS6000_RET_SUCCESS;

MS6000_I2C_PREPARE_PROGRAM_FINISH:	
	return nRet;
}
static int ms6000_i2c_program_flash( UINT8 *pData, UINT16 nAddr_start, UINT8 cLength )	//FLASH one packet编程主函数
{									//参数是待编程数据,写入地址,待编程数据长度
	int nRet = MS6000_RET_PROGRAM_FLASH_FAILED;
	int     i,j;
	BOOL   bRet;
	UINT8    cData;
	UINT8    tmp;
	UINT8    cmd[4];
// Send program code	
	cmd[0] = MS6000_ISP_CMD_PROGRAM_FLASH;
	cmd[1] = (UINT8)((nAddr_start >> 8 ) & 0xFF);
	cmd[2] = (UINT8)((nAddr_start      ) & 0xFF);
	cmd[3] = cLength;
	for(i=0; i<4; i++){
		bRet = mfs_i2c_write_single_byte(cmd[i]);
		udelay(15);
		if( bRet == FALSE )
			goto MS6000_I2C_PROGRAM_FLASH_FINISH;
	}
// Check command result
	bRet = mfs_i2c_read_single_byte(&cData);
	if( bRet == FALSE || cData != MS6000_MDS_ACK_PROGRAM_FLASH ){
		goto MS6000_I2C_PROGRAM_FLASH_FINISH;
	}
// Program Data
	udelay(150);
	for(i=0; i<(int)cmd[3]; i+=2){				//一次写入两个字节,先写高位,再写低位
		bRet = mfs_i2c_write_single_byte(pData[i+1]);
		if( bRet == FALSE )
			goto MS6000_I2C_PROGRAM_FLASH_FINISH;
		udelay(100);              // Delay about 150us
		bRet = mfs_i2c_write_single_byte(pData[i]);
		udelay(150);                   // Delay about 150us
		if( bRet == FALSE )
			goto MS6000_I2C_PROGRAM_FLASH_FINISH;
	}
	nRet = MS6000_RET_SUCCESS;

MS6000_I2C_PROGRAM_FLASH_FINISH:	
	return nRet;
}
static int ms6000_download(const UINT8 *pData, const UINT16 nLength )	//download主函数,参数是映象内存首地址及映象长度
{
	int i,nRet;
	unsigned char cLength,buffer[MS6000_TRANSFER_LENGTH];
	uint16_t nStart_address=0;
	unsigned char *pOriginal_data;
//enter in download mode
	nRet = ms6000_enter_download_mode();
	if(nRet != MS6000_RET_SUCCESS)
		goto MS6000_DOWNLOAD_FINISH;

	mdelay(1);
// Erase Flash
	nRet = ms6000_i2c_prepare_erase_flash();
	if(nRet !=MS6000_RET_SUCCESS){
		goto MS6000_DOWNLOAD_FINISH;	
	}
	mdelay(1);
	nRet = ms6000_i2c_erase_flash();
	if(nRet !=MS6000_RET_SUCCESS)
		goto MS6000_DOWNLOAD_FINISH;
	mdelay(1);
// Verify erase
	nRet = mfs_i2c_read_flash( buffer, 0x00, 16 );		// Must be '0xFF' after erase
	if( nRet != MS6000_RET_SUCCESS )
		goto MS6000_DOWNLOAD_FINISH;
	for(i=0; i<16; i++){
		if( buffer[i] != 0xFF ){
			nRet = MS6000_RET_ERASE_VERIFY_FAILED;
			goto MS6000_DOWNLOAD_FINISH;
		}
	}
	mdelay(1);
// Prepare for Program flash.	
	nRet = ms6000_i2c_prepare_program();
	if( nRet != MS6000_RET_SUCCESS )
		goto MS6000_DOWNLOAD_FINISH;
	mdelay(1);
// Program flash
#if 1
	pOriginal_data  = (UINT8 *)pData;					//保留原始首地址
	nStart_address = 0;						//烧录起始地址
	cLength  = MS6000_TRANSFER_LENGTH;					//一次烧录长度,64B
	for( nStart_address = 0; nStart_address < nLength; nStart_address+=cLength ){
		if( ( nLength - nStart_address ) < MS6000_TRANSFER_LENGTH ){
			cLength  = (UINT8)(nLength - nStart_address);
			cLength += (cLength%2);		// For odd length.最后不足64B的,补上1字节当偶数处理,因为以WORD烧录
		}
		nRet = ms6000_i2c_program_flash( pOriginal_data, nStart_address, cLength );
		if( nRet != MS6000_RET_SUCCESS ){
			goto MS6000_DOWNLOAD_FINISH;
		}
		pOriginal_data  += cLength;
		udelay(500);
		printk("#");
	}
	printk("mfs6000 program finished \r\n");
#endif	
// Verify flash
#if 1
	pOriginal_data  = (UINT8 *) pData;					//保留原始首地址
	nStart_address = 0;
	cLength  = MS6000_TRANSFER_LENGTH;
	for( nStart_address = 0; nStart_address < nLength; nStart_address+=cLength ){
		if( ( nLength - nStart_address ) < MS6000_TRANSFER_LENGTH ){
			cLength = (UINT8)(nLength - nStart_address);
			cLength += (cLength%2);				// For odd length.
		}
		// Read flash
		nRet = mfs_i2c_read_flash( buffer, nStart_address, cLength );
		// Comparing
		for(i=0; i<(int)cLength; i++){
			if( buffer[i] != pOriginal_data[i] ){		//如果读出的对应地址字节与原始对应地址数据不同
				nRet = MS6000_RET_PROGRAM_VERIFY_FAILED;
				goto MS6000_DOWNLOAD_FINISH;
			}
		}
		pOriginal_data += cLength;
		udelay(500);
		printk("*");
	}
	printk("mfs6000 Verify finished \r\n");
#endif	
	nRet = MS6000_RET_SUCCESS;

MS6000_DOWNLOAD_FINISH:
	ms6000_reset_command();
	return nRet;
}

(6)升级主函数,以及TP probe函数中的处理

  1. static int ms6000_firmware_upgrade() 
  2.     unsigned char NewFwVersion,OldFwVersion; 
  3.     uint16_t nBinary_length = 0; 
  4.     int nRead = 0; 
  5.     unsigned char *ptrBuff = NULL; 
  6.     int ret = MS6000_RET_FILE_ACCESS_FAILED; 
  7.  
  8.     if(mfs_i2c_read_single_reg(0x21,&OldFwVersion) == true){        //在此之前,TP的供电及初始化一定要有,否则读不出来 
  9.         NewFwVersion = ms6000_GetLibVer(); 
  10.         printk("mfs6000 OldFwVersion is %d,and  NewFwVersion is %d \r\n",OldFwVersion,NewFwVersion); 
  11.     } 
  12. i2c_client->addr = MS6000_8BIT_DOWNLOAD_ADDR;                    //变换成TP的升级I2C地址 
  13.     if(NewFwVersion != OldFwVersion){                   //如果版本号不同就升级 
  14.         ptrBuff = MS6000CTPM_FW; 
  15.         nBinary_length = sizeof(MS6000CTPM_FW); 
  16.          
  17. //download process 
  18.         printk("start download \r\n"); 
  19.         mtk_wdt_disable(); 
  20.         ret = ms6000_download(ptrBuff,nBinary_length); 
  21.         mtk_wdt_get_en_setting();                   //升级前后必须有禁止WDT和使能WDT的动作,否则易重启 
  22. //check process 
  23.     } 
  24.     else{                               //如果版本号相同则不动作 
  25.         printk("because of the same lib, update abort!\r\n"); 
  26.     } 
  27.  
  28.     return ret; 
  29. //如下是TPD_RROBE中的改动 
  30.     mt65xx_eint_mask(CUST_EINT_TOUCH_PANEL_NUM);                    //mask TP中断 
  31.     int UpResult; 
  32.     UpResult = ms6000_firmware_upgrade(); 
  33.     if(UpResult== MS6000_RET_SUCCESS) 
  34.         printk("MFS6000 DOWNLOAD SUCCESS \r\n"); 
  35.     else 
  36.         mfs6000_print_fail_result(UpResult); 
  37.     i2c_client->addr = MS6000_8BIT_I2CADDR;                  //恢复TP的正常操作时I2C地址 
  38.     mt_set_gpio_mode(GPIO_I2C0_SCA_PIN, GPIO_I2C0_SCA_PIN_M_SCL); 
  39.     mt_set_gpio_mode(GPIO_I2C0_SDA_PIN, GPIO_I2C0_SDA_PIN_M_SDA);           //恢复I2C功能脚 
  40.     mt65xx_eint_unmask(CUST_EINT_TOUCH_PANEL_NUM);              //unmask TP中断 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值