因为我是在stm32上面做的加密操作,所以我只对stm32的方案做总结。

1.ATECC508的底层接口是i2c的,工程中跟i2c相关的操作放在文件hal_stm32l0_ateccx08_i2c.c中,文件应该放在cryptoauthlib\lib\hal\目录下。

2.Armel对这个库封装的比较深,分析下应用程序是如何调用底层的:

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;
}  

先看最开始的那个函数,我粗体标识的:

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里面实现这些函数:

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(); /*86us*/
SDA_H;
HAL_Delay(); /*830us*/ // wait tWHI + tWLO which is configured based on device type and configuration structure
I2C_As_I2c_Gpio();
return ATCA_SUCCESS;
}

2.我遇到的问题:

1.延时函数,如上hal_i2c_wake里面有些延时函数,HAL_Delay()这个函数在ATECC508里面到处用到了,所以不同的芯片需要不同的实现,根本点就是要保证时间尽量准确。

2.遇到的最严重的问题还是stm32本身I2C的问题,设置的传输速率是400kbps,但是经常传着传着i2c就收不到数据了,这个在前面已经说过,没什么好说的。

我用普通io模拟了I2C,但是传输速率只能做到300kbps左右,再高上不去,虽然传输不存在问题,但是遇到了新的问题,看下面的函数,

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 = ; do {
// Check the input parameters
if (data == NULL)
return ATCA_BAD_PARAM; if ( len != && len != )
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 < ) {
if (packet.rxsize > )
status = ATCA_RX_FAIL;
else
status = ATCA_RX_NO_RESPONSE;
break;
} if ( (status = isATCAError(packet.data)) != ATCA_SUCCESS )
break; memcpy( data, &packet.data[], len );
} while (); _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

STM32L071CBTX操作ECC508的更多相关文章

  1. 关于DOM的操作以及性能优化问题-重绘重排

     写在前面: 大家都知道DOM的操作很昂贵. 然后贵在什么地方呢? 一.访问DOM元素 二.修改DOM引起的重绘重排 一.访问DOM 像书上的比喻:把DOM和JavaScript(这里指ECMScri ...

  2. Sql Server系列:分区表操作

    1. 分区表简介 分区表在逻辑上是一个表,而物理上是多个表.从用户角度来看,分区表和普通表是一样的.使用分区表的主要目的是为改善大型表以及具有多个访问模式的表的可伸缩性和可管理性. 分区表是把数据按设 ...

  3. C# ini文件操作【源码下载】

    介绍C#如何对ini文件进行读写操作,C#可以通过调用[kernel32.dll]文件中的 WritePrivateProfileString()和GetPrivateProfileString()函 ...

  4. js学习笔记:操作iframe

    iframe可以说是比较老得话题了,而且网上也基本上在说少用iframe,其原因大致为:堵塞页面加载.安全问题.兼容性问题.搜索引擎抓取不到等等,不过相对于这些缺点,iframe的优点更牛,跨域请求. ...

  5. jquery和Js的区别和基础操作

    jqery的语法和js的语法一样,算是把js升级了一下,这两种语法可以一起使用,只不过是用jqery更加方便 一个页面想要使用jqery的话,先要引入一下jqery包,jqery包从网上下一个就可以, ...

  6. ASP.NET Aries 入门开发教程7:DataGrid的行操作(主键操作区)

    前言: 抓紧勤奋,再接再励,预计共10篇来结束这个系列. 上一篇介绍:ASP.NET Aries 入门开发教程6:列表数据表格的格式化处理及行内编辑 本篇介绍主键操作区相关内容. 1:什么时候有默认的 ...

  7. 如何在高并发环境下设计出无锁的数据库操作(Java版本)

    一个在线2k的游戏,每秒钟并发都吓死人.传统的hibernate直接插库基本上是不可行的.我就一步步推导出一个无锁的数据库操作. 1. 并发中如何无锁. 一个很简单的思路,把并发转化成为单线程.Jav ...

  8. 【翻译】MongoDB指南/CRUD操作(四)

    [原文地址]https://docs.mongodb.com/manual/ CRUD操作(四) 1 查询方案(Query Plans) MongoDB 查询优化程序处理查询并且针对给定可利用的索引选 ...

  9. 【翻译】MongoDB指南/CRUD操作(三)

    [原文地址]https://docs.mongodb.com/manual/ CRUD操作(三) 主要内容: 原子性和事务(Atomicity and Transactions),读隔离.一致性和新近 ...

随机推荐

  1. Django框架教程之正则表达式URL误区详解

    问题:我学习的视频大概是2015年录的,里面用的Django版本比较老关于正则表达式URL这一块都是用的url(“url(r'^admin/', admin.site.urls),”)方法.而我自己练 ...

  2. MFC动态创建对话框中的按钮控件并创建其响应消息

    转自:http://www.cnblogs.com/huhu0013/p/4626686.html 动态按钮(多个)的创建: 1.在类中声明并定义按钮控件的ID #define IDC_D_BTN 1 ...

  3. mybatis 报The content of elements must consist of well-formed character data or markup. 语法格式错误

    最近在写sql的时候 同时使用到了 >= 和 <= 之前只使用一个的时候 没有什么问题,今天同时使用到了两个,结果xml出现了The content of elements must co ...

  4. angular 定时函数

    注入$interval,$timeout   服务 2.定义函数 var aa = $interval(function(){ $timout(function(){ ..... }) },,定时时间 ...

  5. 前段学习的roadmap

    引自http://www.cnblogs.com/IMxinu/p/9693041.html

  6. Linux 系统运行命令 > 查看系统信息

    查看系统运行状态 一 . 查看硬件信息 - 1. cpu信息(可以通过find,whereis,locate查出路径) #cat /proc/cpuinfo 2 . 内存信息:meminfo(可以用c ...

  7. java知识点总结----java入门(1)

    1.首先的明白什么是java? 1.java是一门编程语言 2.java是开发环境 3.java是运行环境 2.java概况--java构架 1.J2SE (Java2 Standard Editio ...

  8. commons-lang常用方法

    跟java.lang这个包的作用类似,Commons Lang这一组API也是提供一些基础的.通用的操作和处理,如自动生成toString()的结果.自动实现hashCode()和equals()方法 ...

  9. 丰富的else语句以及简介的with语句

    1.if···else略 2.while.for与else Python中的循环语句(无论是while 还是for)中,经常配合continue和break语句,此时,可以和else搭配使用,当循环正 ...

  10. Tensorflow描述张量的维度:阶,形状以及维数

    张量 TensorFlow用张量这种数据结构来表示所有的数据.你可以把一个张量想象成一个n维的数组或列表.一个张量有一个静态类型和动态类型的维数.张量可以在图中的节点之间流通. 阶 在TensorFl ...