近段时间一个项目使用了atsha204,硬件电路设计好后,需要设计一个程序来测试芯片是否正常工作,于是写了一个读Serial Number的程序。
本文参考了博文 《atsha204a加密芯片使用攻略——配置篇》,该博文比较详细地说明了芯片该如何使用,更详细的芯片使用可以参考该文,这里不赘述了。但是我也发现文章中的一些问题,以下内容都是我测试过可行的。
一、目标
我设定的测试目标是读取芯片的Serial Number。Serial Number在Config区域中。
二、数据包的格式
1、芯片通讯包基本格式
Word Address |
Count |
Data |
CRC |
1 byte |
1 byte |
N byte |
2 byte |
2、查找datasheet中Read Command的具体样式
可以具体看到Read Command的数据包具体样式如下所示。其中Count的长度不包括Word Address,但包括Count本身
Word Address
|
Count
|
Opcode
|
Param1
|
Param2
|
CRC
|
1 byte
|
1 byte
|
1 byte
|
1 byte
|
1 byte
|
2 byte
|
3、填充其它内容
接下来分别填充Qpcode、Param1和Param2的内容
3.1 Qpcode值
Read指令,所以Qpcode = 0x02
3.2 Param1值
Param1表示的是访问的区域,有三个区域Config、OTP和Data,分别对应的值为:0、1、2、
3.3 Param2值
Param2中的Block指明操作哪个block和要offset多少个地址。这里是要读取 word 0 的值,所以Block和offset都是0
所以Read Command数据包的样式如下:
Word Address
|
Count |
Opcode
|
Param1
|
Param2(byte0)
|
Param2(byte1) |
CRC |
0x03
|
0x07
|
0x02
|
0x00
|
0x00
|
0x00
|
2 byte
|
4、计算CRC的值
使用Atmel官方提供的库中的sha204c_calculate_crc()函数算出后面的CRC的值,
库下载地址:http://www.atmel.com/tools/CRYPTOAUTHENTICATIONATSHA204DEVELOPMENTLIBRARY.aspx
sha204c_calculate_crc函数在sha204_comm.c中
void sha204c_calculate_crc(uint8_t length, uint8_t *data, uint8_t *crc) ;
第一个参数:Count ~ Param2(byte1)的个数,总共5个
第二个参数:需要计算的数据起始地址,即Count的地址
第三个参数:写入crc数据的起始地址(算出来的值为:0x1e, 0x2d)
最终Read Command数据包格式如下:
Word Address
|
Count |
Opcode
|
Param1
|
Param2(byte0)
|
Param2(byte1) |
CRC1 |
CRC2 |
0x03
|
0x07
|
0x02
|
0x00
|
0x00
|
0x00
|
0x1e
|
0x2d
|
三、程序设计
芯片在读写之前,需要进行唤醒。Datasheet中的描述如下:
我写的程序思路如下:
1、设备需要Wake up才能读写数据。
2、查看slave是否有响应,此时读出4个字节,值分别为:0x04 0x11 0x33 0x43
3、发送Read Command
4、读出数据
四、实验结果
五、程序
#include
#include
#include
#include
#include
#include
#define SHA204_WRITE 0x01
#define SHA204_READ 0x03
struct my_i2c_msg {
unsigned short addr; /* slave address */
unsigned short flags;
unsigned short len; /* msg length */
unsigned char buf[64]; /* pointer to msg data */
};
static void sha204c_calculate_crc( unsigned char length, unsigned char *data, unsigned char *crc)
{
unsigned char counter;
unsigned short crc_register = 0;
unsigned short polynom = 0x8005;
unsigned char shift_register;
unsigned char data_bit, crc_bit;
for (counter = 0; counter < length; counter++) {
for (shift_register = 0x01; shift_register > 0x00; shift_register <<= 1) {
data_bit = (data[counter] & shift_register) ? 1 : 0;
crc_bit = crc_register >> 15;
crc_register <<= 1;
if (data_bit != crc_bit)
crc_register ^= polynom;
}
}
crc[0] = (unsigned char)(crc_register & 0x00FF);
crc[1] = (unsigned char)(crc_register >> 8);
}
struct my_i2c_msg packet;
int main()
{
int fd;
fd = open("/dev/sha204", O_RDWR);
if(fd < 0){
printf("sha204 open failed!");
}
//1.wake up
packet.addr = 0x00;
packet.len = 1;
packet.buf[0] = 0;
ioctl(fd, SHA204_WRITE, &packet);
usleep(2600);
//2.read feedback bytes (4 bytes)
packet.addr = 0xc8;
packet.len = 4;
ioctl(fd, SHA204_READ, &packet);
printf("Feedback bytes: %x %x %x %x\n", packet.buf[0],packet.buf[1],packet.buf[2],packet.buf[3]);
//3.send read command
packet.addr = 0xc8;
packet.len = 8;
packet.buf[0] = 0x03; //0x03, 0x07, 0x02, 0x00, 0x00, 0x00
packet.buf[1] = 0x07;
packet.buf[2] = 0x02;
packet.buf[3] = 0x00;
packet.buf[4] = 0x00;
packet.buf[5] = 0x00;
sha204c_calculate_crc(5 ,&packet.buf[1],&packet.buf[6]);
printf("Read command: %x %x %x %x %x %x %x %x\n", packet.buf[0],packet.buf[1],packet.buf[2],packet.buf[3],\
packet.buf[4],packet.buf[5],packet.buf[6],packet.buf[7]);\
ioctl(fd, SHA204_WRITE, &packet);
usleep(3000);
//4.read data
packet.addr = 0xc8;
packet.len = 7;
memset(packet.buf, 0, 7);
ioctl(fd, SHA204_READ, &packet);
printf("Reading Data: %x %x %x %x %x %x %x\n", packet.buf[0],packet.buf[1],packet.buf[2],packet.buf[3],\
packet.buf[4],packet.buf[5],packet.buf[6]);
close(fd);
return 0;
}