STM32L071CBTX操做ECC508

由於我是在stm32上面作的加密操做,因此我只對stm32的方案作總結。bash

1.ATECC508的底層接口是i2c的,工程中跟i2c相關的操做放在文件hal_stm32l0_ateccx08_i2c.c中,文件應該放在cryptoauthlib\lib\hal\目錄下。app

2.Armel對這個庫封裝的比較深,分析下應用程序是如何調用底層的:ide

atecc508_init
   atcab_init( gIfaceCfg )      //這個全局變量很重要,底層的驅動結構體就是綁定在這個全局變量上,後面調用底層驅動,就直接調用這個指針了。
       _gDevice = newATCADevice( cfg );
            cadev->mIface    = (ATCAIface)newATCAIface(cfg);
                 atinit(caiface) 
                     _atinit( caiface, &hal );

能夠看看_atinit(ATCAIface caiface, ATCAHAL_t *hal)這個函數:函數

ATCA_STATUS _atinit(ATCAIface caiface, ATCAHAL_t *hal)
{
	// get method mapping to HAL methods for this interface
	hal_iface_init( caiface->mIfaceCFG, hal );
	caiface->atinit     = hal->halinit;
	caiface->atpostinit = hal->halpostinit;
	caiface->atsend     = hal->halsend;
	caiface->atreceive  = hal->halreceive;
	caiface->atwake     = hal->halwake;
	caiface->atsleep    = hal->halsleep;
	caiface->atidle     = hal->halidle;
	caiface->hal_data   = hal->hal_data;

	return ATCA_SUCCESS;
}  

先看最開始的那個函數,我粗體標識的:post

ATCA_STATUS hal_iface_init( ATCAIfaceCfg *cfg, ATCAHAL_t *hal )
{
    // Because C isn't a real object oriented language or dynamically typed, some switch in the overall system is unavoidable
    // The key here is to provide the flexibility to include just the types of interfaces you want/need without breaking the
    // object model.  The former is needed so in an embedded, constrained memory environment, you don't have to pay the price
    // (in terms of memory) for interfaces you don't use in your application.
    ATCA_STATUS status = ATCA_COMM_FAIL;

    switch (cfg->iface_type) {
    case ATCA_I2C_IFACE:
        #ifdef ATCA_HAL_I2C
        hal->halinit = &hal_i2c_init;
        hal->halpostinit = &hal_i2c_post_init;
        hal->halreceive = &hal_i2c_receive;
        hal->halsend = &hal_i2c_send;
        hal->halsleep = &hal_i2c_sleep;
        hal->halwake = &hal_i2c_wake;
        hal->halidle = &hal_i2c_idle;
        hal->halrelease = &hal_i2c_release;
        hal->hal_data = NULL;

        status = ATCA_SUCCESS;
        #endif
        break;
            
            。。。。。。。。。。。。

只截取了跟i2c相關的部分,清楚了函數的調用關係了吧。咱們須要在hal_stm32l0_ateccx08_i2c.c裏面實現這些函數:flex

ATCA_STATUS hal_i2c_send(ATCAIface iface, uint8_t *txdata, int txlength)
{
	ATCAIfaceCfg *cfg = atgetifacecfg(iface);
	txdata[0] = 0x03;	//!< Word Address Value = Command
	txlength++; 		//!< count Word Address byte towards txlength
	
	uint32_t status = HAL_ERROR;
	
	do{
	      status = HAL_I2C_Master_Transmit(&hi2c1, ECC508_IIC_ADDRESS, txdata, txlength, ECC508_TX_TIMEOUT);
		  if(status != HAL_OK)
		  {				
			  I2C_Reset();
			  __HAL_I2C_CLEAR_FLAG(&hi2c1, I2C_FLAG_STOPF); /* Clear STOP Flag */
			  I2C_RESET_CR2(&hi2c1);					   /* Clear Configuration Register 2 */
			  hi2c1.State = HAL_I2C_STATE_READY;
			  hi2c1.Mode	= HAL_I2C_MODE_NONE;
			  __HAL_UNLOCK(&hi2c1);						  /* Process Unlocked */				
			  hal_i2c_wake(iface);
		  }
	}while(status != HAL_OK);
	
	return ATCA_SUCCESS;

}
ATCA_STATUS hal_i2c_receive( ATCAIface iface, uint8_t *rxdata, uint16_t *rxlength)
{
	uint32_t status = HAL_ERROR;
		
	do{
	      status = HAL_I2C_Master_Receive(&hi2c1, ECC508_IIC_ADDRESS,rxdata,*rxlength,ECC508_RX_TIMEOUT);
		  if(status != HAL_OK)
		  {
		      I2C_Reset();
			  __HAL_I2C_CLEAR_FLAG(&hi2c1, I2C_FLAG_STOPF); /* Clear STOP Flag */
			  I2C_RESET_CR2(&hi2c1);						  /* Clear Configuration Register 2 */
			  hi2c1.State = HAL_I2C_STATE_READY;
			  hi2c1.Mode	= HAL_I2C_MODE_NONE;
			  __HAL_UNLOCK(&hi2c1);						  /* Process Unlocked */
			  hal_i2c_wake(iface);
		  }
	}while(status != HAL_OK);
	
	return ATCA_SUCCESS;

}
ATCA_STATUS hal_i2c_wake(ATCAIface iface)
{
    I2C_As_Normal_Gpio();
    SCL_H;
    SDA_L;
    HAL_Delay(1);     /*86us*/
    SDA_H;    
    HAL_Delay(1);    /*830us*/                                        // wait tWHI + tWLO which is configured based on device type and configuration structure
    I2C_As_I2c_Gpio();    
    return ATCA_SUCCESS;
}

2.我遇到的問題:ui

   1.延時函數,如上hal_i2c_wake裏面有些延時函數,HAL_Delay()這個函數在ATECC508裏面處處用到了,因此不一樣的芯片須要不一樣的實現,根本點就是要保證時間儘可能準確。this

   2.遇到的最嚴重的問題仍是stm32自己I2C的問題,設置的傳輸速率是400kbps,可是常常傳着傳着i2c就收不到數據了,這個在前面已經說過,沒什麼好說的。加密

      我用普通io模擬了I2C,可是傳輸速率只能作到300kbps左右,再高上不去,雖然傳輸不存在問題,可是遇到了新的問題,看下面的函數,spa

ATCA_STATUS atcab_read_zone(uint8_t zone, uint8_t slot, uint8_t block, uint8_t offset, uint8_t *data, uint8_t len)
{
    ATCA_STATUS status = ATCA_SUCCESS;
    ATCAPacket packet;
    uint16_t addr;
    uint16_t execution_time = 0;

    do {
        // Check the input parameters
        if (data == NULL)
            return ATCA_BAD_PARAM;

        if ( len != 4 && len != 32 )
            return ATCA_BAD_PARAM;

        // The get address function checks the remaining variables
        if ( (status = atcab_get_addr(zone, slot, block, offset, &addr)) != ATCA_SUCCESS )
            break;

        // If there are 32 bytes to write, then xor the bit into the mode
        if (len == ATCA_BLOCK_SIZE)
            zone = zone | ATCA_ZONE_READWRITE_32;

        // build a read command
        packet.param1 = zone;
        packet.param2 = addr;

        if ( (status = atRead( _gCommandObj, &packet )) != ATCA_SUCCESS )
            break;

        execution_time = atGetExecTime( _gCommandObj, CMD_READMEM);

        if ( (status = atcab_wakeup()) != ATCA_SUCCESS ) break; // send the command if ( (status = atsend( _gIface, (uint8_t*)&packet, packet.txsize )) != ATCA_SUCCESS ) break; // delay the appropriate amount of time for command to execute  atca_delay_ms(execution_time); // receive the response if ( (status = atreceive( _gIface, packet.data, &(packet.rxsize) )) != ATCA_SUCCESS ) break; // Check response size
        if (packet.rxsize < 4) {
            if (packet.rxsize > 0)
                status = ATCA_RX_FAIL;
            else
                status = ATCA_RX_NO_RESPONSE;
            break;
        }

        if ( (status = isATCAError(packet.data)) != ATCA_SUCCESS )
            break;

        memcpy( data, &packet.data[1], len );
    } while (0);

    _atcab_exit();
    return status;
}

看看函數中粗斜體,執行的順序就是wake->send->delay->receive.

若是hal_delay函數不許,就會致使這個地方delay會不許,就要致使芯片已經休眠了,纔去發送receive命令,固然收不到。

還有一點,若是傳輸的速率比較低,也會致使在send的時候花不少時間,即便delay是準時的,也會致使芯片已經休眠,纔去發送receive。

由於不知道庫裏有多少個地方是這樣處理的,因此仍是儘可能將函數時間弄準確,I2C的速率儘可能高點。

3.關因而如何發現這些問題的,我用到了邏輯分析儀:

從下圖能夠看出,我send command以後,delay了0.7248s纔去receive,這個時候芯片早已休眠。

就是經過下圖看出ATECC508芯片沒有響應的。

最後上一張完整通信的截圖:

OpenSSL攻略.pdf

相關文章
相關標籤/搜索