使用芯片:ATSHA204A(8腳S0IC封裝)
目的:使用ATSHA204A的認證功能,防抄板
前提:了解IIC通信原理
資料:1.網上對於使用ATSHA204A的參考資料大概有三四個,很容易找到
2.ATSHA204A的datasheet
3.atmel官網下載的庫代碼或者代理商也應該會提供一些參考代碼或者網上也可以下載到。代理商給我的參考代碼把操作都封裝好了,只需要修改一個底層驅動文件和一個延時函數文件即可,代理商應該會提供這個,有需要也可以找我。
工具:IAR(IDE),JLINK-V8,邏輯分析儀,示波器,串口線。
使用的是硬件IIC,使用這個芯片可以分為三步,第一步是調通IIC,第二步是成功配置這個芯片,第三步是進行認證。
過程 1.在i2c_phys.c和timer_utilities.c文件里面修改IIC通信函數和延時函數。說說IIC通信函數,包括IIC使能,設置設備地址0xC8,設置傳輸速率,開始發送,結束發送,發送函數,接收函數,發送喚醒函數等。根據開發板的不同,庫代碼不同,自行修改。
2.參考代碼里有個atsha204_read_sn.c,調用里面的read_sn函數,哦哦哦,這里要說一個重要的事情,關於芯片的喚醒!!!IIC通信中,向發送一個0x00,延時至少2.5ms,就可以,用接收函數接收4個字節,成功喚醒會收到04,11,33,43。
3.成功喚醒之后,才可以做很多事情,實現它的命令功能。基本調用下面這個函數即可。
uint8_t sha204m_execute(uint8_t op_code, uint8_t param1, uint16_t param2,
uint8_t datalen1, uint8_t *data1, uint8_t datalen2, uint8_t *data2, uint8_t datalen3, uint8_t *data3,
uint8_t tx_size, uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer);
這之前我要說說這個芯片了。芯片分為三個區:88個字節的config區,512字節的slot區,64個字節的OTP區。
關於config區,放的是SN和每個slot的訪問權限信息等。喚醒之后,我們需要配置slot區的訪問權限,就在這個區。
關於slot區,這個區有16個slot,每個slot可以放32字節。在config區lock之后,data區(slot區和OTP區)lock之前,只能寫slot區而不能讀。在config區和data區都lock之后,按照config區對於slot的訪問權限進行讀寫。
關於OTP,我也沒有用,一次可編程。
config區關於16個slot的默認配置如下,我們需要修改。命令如下:

void config(void)
{
uint8_t data1[4]={0x80,0x80,0x80,0x80}; //
uint8_t data2[4]={0x80,0x00,0x80,0x00}; //
uint8_t data3[4]={0x00,0x00,0x00,0x00};//怎么配置的,看下圖!
uint8_t data4[4]={0xC0,0x80,0xC0,0x80};//
uint8_t data5[4]={0xC0,0x00,0xC0,0x00};//
/*說一下這個函數參數吧,0x12是寫,0x00是代表config區4字節寫(0x01是OTP區4字節寫,0x82是slot區32字節寫),0x05是slot0和slot1的權限信息位置,data是配置信息。*/
sha204m_execute(0x12, 0x00, 0x05,4, data1, 0, 0, 0, 0,LPI2C_DATA_LENGTH, g_slave_buff,LPI2C_DATA_LENGTH, g_master_buff);
sha204m_execute(0x12, 0x00, 0x06,4, data2, 0, 0, 0, 0,LPI2C_DATA_LENGTH, g_slave_buff,LPI2C_DATA_LENGTH, g_master_buff);
sha204m_execute(0x12, 0x00, 0x07,4, data3, 0, 0, 0, 0,LPI2C_DATA_LENGTH, g_slave_buff,LPI2C_DATA_LENGTH, g_master_buff);
sha204m_execute(0x12, 0x00, 0x08,4, data4, 0, 0, 0, 0,LPI2C_DATA_LENGTH, g_slave_buff,LPI2C_DATA_LENGTH, g_master_buff);
sha204m_execute(0x12, 0x00, 0x09,4, data5, 0, 0, 0, 0,LPI2C_DATA_LENGTH, g_slave_buff,LPI2C_DATA_LENGTH, g_master_buff);
sha204m_execute(0x12, 0x00, 0x0A,4, data3, 0, 0, 0, 0,LPI2C_DATA_LENGTH, g_slave_buff,LPI2C_DATA_LENGTH, g_master_buff);
sha204m_execute(0x12, 0x00, 0x0B,4, data3, 0, 0, 0, 0,LPI2C_DATA_LENGTH, g_slave_buff,LPI2C_DATA_LENGTH, g_master_buff);
sha204m_execute(0x12, 0x00, 0x0C,4, data3, 0, 0, 0, 0,LPI2C_DATA_LENGTH, g_slave_buff,LPI2C_DATA_LENGTH, g_master_buff);
}

之后可以通過read命令,讀出看看有沒有寫入。寫入成功的話會返回04 00 03 40。
4.在config區可以自由讀寫的話,進行下一步,lock住data區。
/* 3. lock config_ lock 參數1為0x80是config zone,0x81是Data和OTP zone */
sha204m_execute(0x17, 0x80, 0x00,0, 0, 0, 0, 0, 0,LPI2C_DATA_LENGTH, g_slave_buff,LPI2C_DATA_LENGTH, g_master_buff);
之后看config區0x15中config_lock的55有沒有變成00。變了的話,就lock成功。
5.ok的話,可以向slot區寫數據了。最主要還是放密鑰的那幾個slot要寫數據,如果配置為00,00,就是普通的eeprom。
// uint8_t data1[32]={0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x10,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x10,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x10,0x00,0x00};
// uint8_t data3[32]={0x55,0x55,0x55,0x55,0x55,0x55,0x55,0xAA,0xAA,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x55,0x55,0xAA};
// uint8_t data4[32]={0x11,0x11,0x23,0xB6,0xCC,0x53,0xB7,0xB9,0xE9,0xBB,0x51,0xFD,0x2F,0x74,0xCD,0x0E,0x91,0xD9,0x7F,0xEB,0x84,0x7B,0x98,0x09,0xF4,0xCD,0x93,0x6A,0xB6,0x48,0x11,0x11};
// sha204m_execute(0x12, 0x82, 0x0010,32, data1, 0, 0, 0, 0,LPI2C_DATA_LENGTH, g_slave_buff,LPI2C_DATA_LENGTH, g_master_buff);
//
// sha204m_execute(0x12, 0x82, 0x0000,32, data1, 0, 0, 0, 0,LPI2C_DATA_LENGTH, g_slave_buff,LPI2C_DATA_LENGTH, g_master_buff);
// sha204m_execute(0x12, 0x82, 0x0008,32, data1, 0, 0, 0, 0,LPI2C_DATA_LENGTH, g_slave_buff,LPI2C_DATA_LENGTH, g_master_buff);
//
// sha204m_execute(0x12, 0x82, 0x0010,32, data1, 0, 0, 0, 0,LPI2C_DATA_LENGTH, g_slave_buff,LPI2C_DATA_LENGTH, g_master_buff);
// sha204m_execute(0x12, 0x82, 0x0018,32, data1, 0, 0, 0, 0,LPI2C_DATA_LENGTH, g_slave_buff,LPI2C_DATA_LENGTH, g_master_buff);
//
// sha204m_execute(0x12, 0x82, 0x0020,32, data1, 0, 0, 0, 0,LPI2C_DATA_LENGTH, g_slave_buff,LPI2C_DATA_LENGTH, g_master_buff);
// sha204m_execute(0x12, 0x82, 0x0028,32, data1, 0, 0, 0, 0,LPI2C_DATA_LENGTH, g_slave_buff,LPI2C_DATA_LENGTH, g_master_buff);
//
// sha204m_execute(0x12, 0x82, 0x0030,32, data1, 0, 0, 0, 0,LPI2C_DATA_LENGTH, g_slave_buff,LPI2C_DATA_LENGTH, g_master_buff);
// sha204m_execute(0x12, 0x82, 0x0038,32, data1, 0, 0, 0, 0,LPI2C_DATA_LENGTH, g_slave_buff,LPI2C_DATA_LENGTH, g_master_buff);
//
// sha204m_execute(0x12, 0x82, 0x0040,32, data1, 0, 0, 0, 0,LPI2C_DATA_LENGTH, g_slave_buff,LPI2C_DATA_LENGTH, g_master_buff);
// sha204m_execute(0x12, 0x82, 0x0048,32, data1, 0, 0, 0, 0,LPI2C_DATA_LENGTH, g_slave_buff,LPI2C_DATA_LENGTH, g_master_buff);
//
// sha204m_execute(0x12, 0x82, 0x0050,32, data1, 0, 0, 0, 0,LPI2C_DATA_LENGTH, g_slave_buff,LPI2C_DATA_LENGTH, g_master_buff);
// sha204m_execute(0x12, 0x82, 0x0058,32, data1, 0, 0, 0, 0,LPI2C_DATA_LENGTH, g_slave_buff,LPI2C_DATA_LENGTH, g_master_buff);
6.成功的話,每個操作都會返回04,00,03,40。這里如果沒有返回值的話,根本不知道有沒有寫進去。因為現在是讀不了的。
7.lock data區
/* 6.lock data_lock 參數1為0x80是config zone,0x81是slot和OTP zone */
// sha204m_execute(0x17, 0x81, 0x00,0, 0, 0, 0, 0, 0,LPI2C_DATA_LENGTH, g_slave_buff,LPI2C_DATA_LENGTH, g_master_buff);
8. read config zone 0x15,看看有沒有鎖住 0x55應變為0x00
9.到這里配置就完成了,可以讀讀允許讀的slot中的數據。
10.認證其實有很多方法,我用的最簡單的,固定挑戰認證。slot0為密鑰區。
/* mac */
uint8_t data1[32]={0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22};
sha204m_execute(0x08,0x00,0x0000,32, data1, 0, 0, 0, 0,LPI2C_DATA_LENGTH, g_slave_buff,LPI2C_DATA_LENGTH, g_master_buff);
會有一個返回。
之后再用sha256算法。 /* sha256 */ //message發送的數據是88個字節。密鑰,挑戰碼,mac等,0x00等,sn,
static uint8 message1[]= { 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x10,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x10,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x10,0x00,0x00,
0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,
0x08,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0xee,
0x00,0x00,0x00,0x00,0x01,0x23,0x00,
0x00,
// };
sha256(message1, 88, digest);
這個digest如果和之前mac的返回一樣,那就成功了。
