一、AT88SC系列加密芯片应用很广,接触式与非接触式IC都会使用这个芯片作为存储芯片,I2C接口,但与标准的I2C时序有点差别,最好是使用模拟时序驱动,加解密算法来自于ATmel官方对其进行了封装,at88sc_read_storage与at88sc_write_storage两个函数对于应用层来说很友好
/**
* @file at88sc.c
* @brief at88sc driver.
* @details Simulation time sequence, authentication read and write user zone and config zone.
* @author ken
* @date 2018-11-15
* @version A001
* @par Copyright (c):
* @par History:
* version: ken, 2018-11-15, create\n
*/
#include "system.h"
#include "at88sc.h"
#include "dwt.h"
#include "string.h"
#include "main.h"
#include "smartcard.h"
#ifdef AT88SC_DEBUG
#define at88sc_log(...) do{if(DEBUG(DEBUG_ENABLE)){DBG_LOG("[AT88SC](%ld) ",__LINE__);DBG_LOG(__VA_ARGS__);}}while(0)
#define at88sc_usr(...) do{if(DEBUG(DEBUG_ENABLE)){DBG_LOG("[AT88SC] ");DBG_USR(__VA_ARGS__);}}while(0)
#define at88sc_err(...) do{if(DEBUG(DEBUG_ENABLE)){DBG_LOG("[AT88SC] ");DBG_ERR(__VA_ARGS__);}}while(0)
#define at88sc_dump(...) if(DEBUG(DEBUG_ENABLE)){DBG_DUMP(__VA_ARGS__);}
#else
#define at88sc_log(...)
#define at88sc_usr(...)
#define at88sc_err(...)
#define at88sc_dump(...)
#endif
/** at88sc gpio port */
GPIO_InitTypeDef AT88SC_GPIO;
/** GPA units */
uint8_t GPA[20];
/** config zone */
//AT88SC_CONFIG_ZONE_T at88sc_config_zone;
static const uint8_t block_admini[]={BLOCK0_ADMINI,BLOCK1_ADMINI,BLOCK2_ADMINI,BLOCK3_ADMINI,BLOCK4_ADMINI,BLOCK5_ADMINI,BLOCK6_ADMINI,
BLOCK7_ADMINI,BLOCK8_ADMINI,BLOCK9_ADMINI,BLOCK10_ADMINI,BLOCK11_ADMINI,BLOCK12_ADMINI,BLOCK13_ADMINI,BLOCK14_ADMINI,BLOCK15_ADMINI};
/** at88sc status */
AT88SC_STA_T st88sc_sta;
/** GC_TABLE */
unsigned char const GC0[]={0x63,0x6A,0x56,0x56,0xD8,0x60,0x2F,0x25};//GC0
unsigned char const GC1[]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};//GC1
unsigned char const GC2[]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};//GC2
unsigned char const GC3[]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};//GC3
/** PASSWORD_TABLE */
unsigned char const PW_WRITE0[]={0x57,0x26,0xF1};//WRITE PASSWORD 0
unsigned char const PW_READ0[]= {0x57,0x26,0xF1};//READ PASSWORD 0
unsigned char const PW_WRITE1[]={0xFF,0xFF,0xFF};//WRITE PASSWORD 1
unsigned char const PW_READ1[]= {0xFF,0xFF,0xFF};//READ PASSWORD 1
unsigned char const PW_WRITE2[]={0xFF,0xFF,0xFF};//WRITE PASSWORD 2
unsigned char const PW_READ2[]= {0xFF,0xFF,0xFF};//READ PASSWORD 2
unsigned char const PW_WRITE3[]={0xFF,0xFF,0xFF};//WRITE PASSWORD 3
unsigned char const PW_READ3[]= {0xFF,0xFF,0xFF};//READ PASSWORD 3
unsigned char const PW_WRITE4[]={0xFF,0xFF,0xFF};//WRITE PASSWORD 4
unsigned char const PW_READ4[]= {0xFF,0xFF,0xFF};//READ PASSWORD 4
unsigned char const PW_WRITE5[]={0xFF,0xFF,0xFF};//WRITE PASSWORD 5
unsigned char const PW_READ5[]= {0xFF,0xFF,0xFF};//READ PASSWORD 5
unsigned char const PW_WRITE6[]={0xFF,0xFF,0xFF};//WRITE PASSWORD 6
unsigned char const PW_READ6[]= {0xFF,0xFF,0xFF};//READ PASSWORD 6
unsigned char const PW_WRITE7[]={0x05,0x05,0xC7};//WRITE PASSWORD 7
unsigned char const PW_READ7[]= {0xFF,0xFF,0xFF};//READ PASSWORD 7
static void SMSTART(void);
static void SMSTOP(void);
static void IIC_Initial(void);
static void at88sc_ack_polling(void);
static void at88sc_gpa_clock(uint8_t Datain,uint8_t times);
static void at88sc_read(uint8_t *rd_ptr);
static void at88sc_write(uint8_t *wd_ptr);
static void at88sc_encrypto_data(uint8_t encryptodatanumber,uint8_t *ptr);
static void at88sc_send_checksum(void);
static uint8_t at88sc_mtz_test(void);
/**
* test i2c communication normal with at88sc.
* write 2 register and read comparison,if the chip config zone lock well return 0xfx.
* @param[in] none.
* @param[out] noen.
* @retval 1 success, 0 failed
* @par TAG
* reserved
* @par other
* none
* @par modify
* ken 2018-11-15 create
*/
uint8_t at88sc_mtz_test(void){
uint8_t send_buf[2];
uint8_t recv_buf[2];
send_buf[0]=0xa5;
send_buf[1]=0x5a;
at88sc_write_config_register(MTZ_R,send_buf);
delay_ms(10);
at88sc_read_config_register(MTZ_R,recv_buf);
if (recv_buf[0]==0xa5 && recv_buf[1]==0x5a ){
return 1;
}
else
return 0;
}
/**
* i2c communication initialize.
* initialize the i2c gpio signal.
* @param[in] none.
* @param[out] noen.
* @retval none
* @par TAG
* reserved
* @par other
* none
* @par modify
* ken 2018-11-15 create
*/
static void IIC_Initial(void){
#ifdef AT88SC_DISABLE_INTERRUPT
__disable_irq();
#endif
CM_CLK_OUT;
CM_DATA_OUT;
CM_DATA_HI;
delay_us(12);
CM_CLK_HI;
delay_us(12);
CM_CLK_LO;
delay_us(12);
CM_CLK_HI;
delay_us(12);
CM_CLK_LO;
delay_us(12);
CM_CLK_HI;
delay_us(12);
CM_CLK_LO;
delay_us(12);
CM_CLK_HI;
delay_us(12);
CM_CLK_LO;
delay_us(12);
CM_CLK_HI;
delay_us(12);
CM_CLK_LO;
delay_us(12);// 5 CLK
#ifdef AT88SC_DISABLE_INTERRUPT
__enable_irq();
#endif
}
/**
* generate i2c start signal.
* generate i2c start signal.
* @param[in] none.
* @param[out] noen.
* @retval none
* @par TAG
* reserved
* @par other
* none
* @par modify
* ken 2018-11-15 create
*/
static void SMSTART(void){
#ifdef AT88SC_DISABLE_INTERRUPT
__disable_irq();
#endif
CM_DATA_OUT;
CM_CLK_LO;
delay_us(8);
CM_DATA_HI;
delay_us(8);
CM_CLK_HI;
delay_us(8);
CM_DATA_LO;
delay_us(8);
CM_CLK_LO;
delay_us(8);
#ifdef AT88SC_DISABLE_INTERRUPT
__enable_irq();
#endif
}
/**
* generate i2c stop signal.
* generate i2c stop signal.
* @param[in] none.
* @param[out] noen.
* @retval none
* @par TAG
* reserved
* @par other
* none
* @par modify
* ken 2018-11-15 create
*/
static void SMSTOP(void){
#ifdef AT88SC_DISABLE_INTERRUPT
__disable_irq();
#endif
CM_DATA_OUT;
CM_DATA_LO;
delay_us(8);
CM_CLK_HI;
delay_us(8);
CM_DATA_HI;
delay_us(8);
CM_CLK_LO;
delay_us(8);
#ifdef AT88SC_DISABLE_INTERRUPT
__enable_irq();
#endif
}
/**
* poll i2c ack signal.
* poll i2c ack signal.
* @param[in] none.
* @param[out] noen.
* @retval none
* @par TAG
* reserved
* @par other
* none
* @par modify
* ken 2018-11-15 create
*/
void at88sc_ack_polling(void){
#ifdef AT88SC_DISABLE_INTERRUPT
__disable_irq();
#endif
uint8_t AckPolling_return;
uint8_t temp, bitcounter;
uint8_t bytecounter;
SMSTART();
temp=0xb6;
bytecounter=0xff; //note:if CPU clk fast,inc bytecounter.
AckPolling_return=0;
do{
CM_DATA_OUT;
delay_us(8);
for(bitcounter=0;bitcounter<8;bitcounter++){
if (temp&0x80){
CM_DATA_HI;
}
else{
CM_DATA_LO;
}
delay_us(8);
CM_CLK_HI;
delay_us(8);
CM_CLK_LO;
delay_us(8);
temp=temp<<1;
}
bytecounter--;
CM_DATA_IN;
delay_us(8);
CM_CLK_HI;
delay_us(8);
if(!(CM_DATA_RD)){
CM_CLK_LO;
delay_us(8);
AckPolling_return=1;
}
else{
CM_CLK_LO;
AckPolling_return=0;
SMSTART();
temp=0xb6;
}
if(AckPolling_return==1){
break;
}
}while(bytecounter>0);
SMSTOP();
#ifdef AT88SC_DISABLE_INTERRUPT
__enable_irq();
#endif
}
/**
* read data from at88sc.
* protocol:cmd addr1 addr2 len data*N.
* @param[in] rd_ptr:read pointer, define command protocol.
* @param[out] noen.
* @retval none
* @par TAG
* reserved
* @par other
* none
* @par modify
* ken 2018-11-15 create
*/
static void at88sc_read(uint8_t *rd_ptr){
#ifdef AT88SC_DISABLE_INTERRUPT
__disable_irq();
#endif
uint8_t bitcounter;
uint8_t temp;
uint8_t cmd_send_counter;
uint8_t bytecounter;
temp=rd_ptr[0];
bytecounter=0;
cmd_send_counter=0;
uint8_t recv_len = rd_ptr[3];
SMSTART();
do{
CM_DATA_OUT;
delay_us(8);
for(bitcounter=0;bitcounter<8;bitcounter++){
if (temp&0x80){
CM_DATA_HI;
}
else{
CM_DATA_LO;
}
delay_us(8);
CM_CLK_HI;
delay_us(8);
CM_CLK_LO;
delay_us(8);
temp=temp<<1;
}
CM_DATA_HI;
delay_us(8);
CM_DATA_IN;
delay_us(8);
CM_CLK_HI;
delay_us(8);
if(!(CM_DATA_RD)){
CM_CLK_LO;
delay_us(8);
bytecounter++;
temp=rd_ptr[bytecounter];
}
else{
CM_CLK_LO;
SMSTART();
temp=rd_ptr[0];
bytecounter=0;
cmd_send_counter++;
}
if(cmd_send_counter>8){
bytecounter=4;
goto read_out;
}
}while(bytecounter<4);
for(bytecounter=0;bytecounter<recv_len;bytecounter++){
CM_DATA_IN;
delay_us(8);
for(bitcounter=0;bitcounter<8;bitcounter++){
CM_CLK_HI;
delay_us(8);
if (CM_DATA_RD){
temp=temp|0x01;
}
else{
temp=(temp&0xfe);
}
if(bitcounter<7){
temp=temp<<1;
}
else{
delay_us(4);
}
CM_CLK_LO;
delay_us(8);
}
CM_DATA_OUT;
delay_us(8);
CM_DATA_LO;
delay_us(8);
CM_CLK_H

AT88SC系列加密芯片应用广泛,用于接触式与非接触式IC的存储。它采用I2C接口,与标准I2C时序有差别,建议用模拟时序驱动。加解密算法由ATmel官方封装,at88sc_read_storage与at88sc_write_storage函数对应用层友好。

3961

被折叠的 条评论
为什么被折叠?



