stm32cubemx IAP升级(四)

stm32cubemx IAP升级- 配置i2c从机

上一章讲了串口的方式升级,但是在android平台上,对mcu的升级还是i2c用的多一点,所以我们还配置了i2c从机,也是多一种升级方案嘛!

stm32 配置i2c从机,且采用dma的方式收发数据。

1、收发协议
cmd + data_lenght + data0 + …+ datax + checksum
1、获取版本号 0x01 0x02 0x00 0x00 checksum
2、升级
1、进入升级模式 0x02 0x02 0x00 0x00 checksum
2、升级文件大小 0x03 0x04 0x00 0x00 0x00 0x00 checksum
3、数据包发送 0x04 0x80 0x00 0x00 0x00 0x00 … checksum
4、数据包发送完成 0x05 0x02 0x00 0x00 checksum

2、在main.c 中while循环前添加
HAL_I2C_Slave_Seq_Receive_DMA(&hi2c2,I2C_ReceiveBuff,I2C_RECEIVE_DATA_LEN,I2C_LAST_FRAME);

其中I2C_ReceiveBuff 、I2C_RECEIVE_DATA_LEN为全局变量
uint8_t isRunningUpdate = 0;
uint16_t u16ReceiveBufLen = I2C_RECEIVE_DATA_LEN;
uint8_t I2C_ReceiveBuff[MAX_DATA_LENGTH];

因为iic收发数据要一致,比如主机发送6个数据,从机就要接收6 个数据。如果发送升级包的时候,要发送131个数据,那么从机也要相应的修改为接收131个数据,修改的就是u16ReceiveBufLen的值。

3、修改stm32l4xx_it.c的中断回调函数。

// I2c相关的回调函数

void HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef *hi2c)
{
  //printf("HAL_I2C_SlaveTxCpltCallback\r\n");
}

// Slave 接收完成的回掉
void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c)
{
  if(hi2c->Instance == hi2c2.Instance)
  {
    int len =  u16ReceiveBufLen - __HAL_DMA_GET_COUNTER(&hdma_i2c2_rx);
    //printf("Slave I2c recvice data length == %d\r\n",len);
    handle_i2c_message(I2C_ReceiveBuff,len);
  }
}


void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode)
{
  __HAL_I2C_CLEAR_FLAG(&hi2c2, I2C_FLAG_ADDR);

  if(TransferDirection == I2C_DIRECTION_RECEIVE)  
	{
    int len =  u16ReceiveBufLen - __HAL_DMA_GET_COUNTER(&hdma_i2c2_rx);
    send_i2c_message(I2C_ReceiveBuff, len);
  }
  else if (TransferDirection == I2C_DIRECTION_TRANSMIT)
  {
    change_receiver_buff_len(I2C_ReceiveBuff);
    HAL_I2C_Slave_Seq_Receive_DMA(&hi2c2,I2C_ReceiveBuff,u16ReceiveBufLen,I2C_FIRST_AND_NEXT_FRAME);
  }
}

void HAL_I2C_ListenCpltCallback(I2C_HandleTypeDef *hi2c)
{
  
  if(HAL_I2C_EnableListen_IT(&hi2c2) != HAL_OK)
	{
		printf("HAL_I2C_EnableListen_IT Error\r\n");
	}
}

void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c)
{
  uint32_t lastErrorCode;
  lastErrorCode = HAL_I2C_GetError(hi2c); 

  if (lastErrorCode >0)
    printf("HAL_I2C_ErrorCallback == %ld\r\n",lastErrorCode);

  if (lastErrorCode == HAL_I2C_ERROR_AF){

    if (__HAL_I2C_GET_FLAG(&hi2c2,I2C_FLAG_RXNE) == RESET) 
    {
      int16_t u16ReceivedBufLen =  u16ReceiveBufLen - __HAL_DMA_GET_COUNTER(&hdma_i2c2_rx);
      printf("error recvice data length == %d\r\n",u16ReceivedBufLen);
    }
  } 
}

4、在i2c.c MX_I2C2_Init函数中添加。

if(HAL_I2C_EnableListen_IT(&hi2c2) != HAL_OK)
{
	printf("HAL_I2C_EnableListen_IT Error\r\n");
}

5、收发数据的处理函数

// 主机读 从机发送 处理函数
MI_BOOL send_i2c_message(MI_U8 *p_buff,MI_U32 len)
{
    switch (p_buff[UART_CMD_INDEX])
    {
    case I2C_GET_SYSTEM_VERSION_CMD/* constant-expression */:
        /* 获取系统版本号 */
        if (calculate_checksum_and_length(p_buff,len) == MI_TRUE)
        {
            system_info_get_system_version(version);
            HAL_I2C_Slave_Seq_Transmit_DMA(&hi2c2, (MI_U8 *)version, 
                    strlen((MI_CHAR *)version), I2C_LAST_FRAME);
        }
        break;
    
    default:
        break;
    }    
    return MI_TRUE;
}

// 主机写 从机读处理函数

	MI_BOOL handle_i2c_message(MI_U8 *p_buff,MI_U32 len)
	{
	    switch (p_buff[I2C_CMD_INDEX])
	    {
	    case I2C_GET_SYSTEM_VERSION_CMD/* constant-expression */:
	        /* 获取系统版本号 */
	        /* Noting to do send_i2c_message 中处理*/
	        break;
	    case I2C_ENTER_SYSTEM_UPDATE_MODE_CMD:
	        /* 进入升级模式命令 指示灯变为100ms闪烁一次*/
	        if (calculate_checksum_and_length(p_buff,len) == MI_TRUE)
	        {
	            led_freq = LED_TOGGLE_100_MS;
	            w_time = 0;
	            packets_numer = 0;
	            upgrade_file_size = 0;
	            remain_packets_numer = 0;
	            isRunningUpdate = 1;
	            printf("Mcu Receive Update Command and Wait Receive Data Packets \r\n");
	            printf("Now to Erase Download Pages \r\n");
	            printf("\r\n");
	            int ret = stm32_erase_flash(DOWNLOAD_START_SECTOR_ADDR,DOWNLOAD_END_SECTOR_ADDR);
	
	            printf("\r\n");
	
	        }
	        break; 
	    case I2C_GET_SYSTEM_FILE_SIZE_CMD:
	        if (calculate_checksum_and_length(p_buff,len) == MI_TRUE)
	        {
	            int a = (int)p_buff[2];
	            int b = (int)p_buff[3];
	            int c = (int)p_buff[4];
	            int d = (int)p_buff[5];
	            upgrade_file_size = (a<<24) | (b<<16) | (c<<8) | (d);
	
	            if (upgrade_file_size % UPGRADE_DATA_PACKAGES_LENGHT == 0)  //如果整除128 
	            {
	                packets_numer = upgrade_file_size/128;
	            }
	            else
	            {
	                packets_numer = ((upgrade_file_size/128) + 1);
	            }
	            printf("End Erase Download Pages Down\r\n");
	            printf("\r\n");
	
	            printf("receive upgrade file size %d\r\n",upgrade_file_size);
	            printf("data packets number  %d\r\n",packets_numer);
	            printf("\r\n");
	        }
	        break; 
	    case I2C_RECEIVE_SYSTEM_UPDATE_CMD:
	        if (calculate_checksum_and_length(p_buff,len) == MI_TRUE)
	        {
	            printf("receive packets........................%03d [100] \r\n",(((w_time + 1) * 100) / packets_numer));
	            memset(w_buff,0,sizeof(w_buff));
	            memcpy(w_buff,&p_buff[2],sizeof(w_buff));
	
	            stm32_flash_write(DOWNLOAD_START_SECTOR_ADDR+(w_time * UPGRADE_DATA_PACKAGES_LENGHT),w_buff,sizeof(w_buff));
	
	            if (w_time + 1 == packets_numer)
	            {
	                led_freq = LED_TOGGLE_1000_MS;
	                printf("receive packets........................ done!\r\n");
	            }
	            w_time ++;
	        }
	        break;
	    case I2C_COMPLETE_SYSTEM_UPDATE_CMD:
	        if (calculate_checksum_and_length(p_buff,len) == MI_TRUE)
	        {
	            system_info_set_update_flag(SYSTEM_UPDATE);
	            printf("Now Reboot !\r\n");
	            app_soft_reset();
	        }
	        break;                       
	        
	    default:
	        break;
	    }    
	    return MI_TRUE;
	}

更改接收数据长度的函数

MI_BOOL change_receiver_buff_len(MI_U8 *p_buff)
{

    switch (p_buff[0])
    {
    case I2C_ENTER_SYSTEM_UPDATE_MODE_CMD/* constant-expression */:
        /* code */
        u16ReceiveBufLen = 8; //File size cmd lenght = 8,so receive enter mcu upgrade mode and change this vaule to 8
        break;
    case I2C_GET_SYSTEM_FILE_SIZE_CMD:
        u16ReceiveBufLen = 132;  //file package cmd length = 132
        break;
    case I2C_RECEIVE_SYSTEM_UPDATE_CMD:
        if (w_time == packets_numer)  //file pcakage receive end and change receiver buff length equal = 6;
        {
            u16ReceiveBufLen = I2C_RECEIVE_DATA_LEN;
        }
        break;
    default:
        break;
    }

    return MI_TRUE;
}

收到的数据一包包写入download分区即可。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值