In the drive development process, we sometimes encounter this application: for example, the firmware of a chip is not fixed, can be upgraded later. Then, every time the system is powered on, a test is required, and if a new firmware is detected, the firmware is upgraded the first time it is powered on. After that, because a new firmware version number is saved for detection, no more boot upgrades are available.
Take a I2C touch screen chip For example, assuming that the new firmware file name provided by the vendor is us3x06eb_use.it, place the file on the touch screen driver. In the same directory as C, all that needs to be done is to add the corresponding version number detection in the touch screen probe function and decide whether to upgrade. If you need to upgrade, write the target firmware through I2C.
typedef enum {ERR_OK, Err_mode, Err_readid, Err_erase, Err_status, ERR_ECC,
Err_dl_erase_fail, Err_dl_program_fail, Err_dl_verify_fail}e_upgrade_err_type;
#define FTS_PACKET_LENGTH 2//write two bytes at a time, as a PACKET static unsigned char ctpm_fw[] =//load target firmware {
#include "us3x06eb_use.it"};
static int Fts_i2c_txdata (U8 *txdata, int length)//Once multi-byte data is transmitted through I2C {int ret;
struct i2c_msg msg;
MSG.ADDR = i2c_client->addr;
msg.flags = 0;
Msg.len = length;
Msg.buf = TxData;
ret = I2c_transfer (I2c_client->adapter, &msg, 1);
if (Ret < 0) {Pr_err ("%s I2C write Error:%d\n", __func__, ret);
return ret;
static bool I2c_write_interface (U8 *pbt_buf, int dw_lenth)//write multiple data by I2C {int ret;
ret = I2c_master_send (i2c_client, Pbt_buf, Dw_lenth); if (ret <= 0) {PRINTK ("[Tsp]i2c_write_interface Error line =%d, ret =%d\n ", __line__, ret);
return fts_false;
return fts_true;
static bool I2c_read_interface (U8 *pbt_buf, int dw_lenth)//Read multiple data by I2C {int ret;
ret = I2C_MASTER_RECV (i2c_client, Pbt_buf, Dw_lenth);
if (ret <= 0) {PRINTK ("[Tsp]i2c_read_interface error\n");
return fts_false;
return fts_true;
static bool Fts_register_write (U8 reg_name, U8 *tx_buf)//write Single-byte data to registers {U8 Write_cmd[2] = {0};
Write_cmd[0] = Reg_name;
WRITE_CMD[1] = *tx_buf;
Return I2c_write_interface (Write_cmd, 2);
static bool Fts_register_read (U8 reg_name, U8 *rx_buf, int rx_length)/read multiple data from registers {U8 Read_cmd[2] = {0};
U8 Cmd_len = 0;
Read_cmd[0] = Reg_name;
Cmd_len = 1;
/*send Register addr*/if (!i2c_write_interface (&read_cmd[0), Cmd_len)) {return fts_false;
}
if (!i2c_read_interface (Rx_buf, rx_length)) {return fts_false;
return fts_true;
}
E_upgrade_err_type Fts_ctpm_fw_upgrade (U8 *pbt_buf, int dw_lenth)//programming details not elaborated, the actual meeting is listed in the sequel to this blog
{
The data is divided into corresponding packet, once through the I2C to the chip. There are a few questions to note: (1) to pay attention to the convergence of the packet, the data length may not exactly be divided into an integer package, then the last package to separate
Processing, (2) data verification, such as chip with automatic or calibration, on the one hand, we send in the process of data validation in a timely manner, on the other hand, after the data is sent, you can check the value with the
Registers to determine whether the current transfer is valid.
}
int fts_ctpm_fw_upgrade_with_i_file (void)
{
U8 *pbt_buf = 0x0;
int ret;
Pbt_buf = CTPM_FW;
ret = Fts_ctpm_fw_upgrade (pbt_buf, sizeof (CTPM_FW)); Upgrade specific file return
ret;
}
The *client function
of the static int __devinit tpd_probe (struct i2c_client struct, const i2c_device_id *id//TP) probe .............
{
U8 reg_val=0;
Mdelay (m);
Fts_register_read (0xa6,®_val,1); read out the current version number
if (reg_val<tp_lib_version) //If the current version number is smaller than the version to be upgraded
{
PRINTK ("TP firmware version OK, start upgrade\n ");
Fts_ctpm_fw_upgrade_with_i_file ();
}
.............
}