一、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_HI;
delay_us(8);
CM_CLK_LO;
delay_us(8);
rd_ptr[bytecounter+4]=temp;
}
read_out:
SMSTOP();
#ifdef AT88SC_DISABLE_INTERRUPT
__enable_irq();
#endif
}
/**
* write data to at88sc.
* protocol:cmd addr1 addr2 len data*N.
* @param[in] wd_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_write(uint8_t *wd_ptr){
#ifdef AT88SC_DISABLE_INTERRUPT
__disable_irq();
#endif
uint8_t bitcounter;
uint8_t temp;
uint8_t bytecounter;
uint8_t cmd_send_counter;
temp=wd_ptr[0];
bytecounter=0;
cmd_send_counter=0;
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_IN;
delay_us(8);
CM_CLK_HI;
delay_us(8);
if(!(CM_DATA_RD)){
CM_CLK_LO;
delay_us(8);
bytecounter++;
temp=wd_ptr[bytecounter];
}
else{
CM_CLK_LO;
SMSTART();
temp=wd_ptr[0];
bytecounter=0;
cmd_send_counter++;
}
if(cmd_send_counter>8){
bytecounter=wd_ptr[3]+4;
}
}while(bytecounter<wd_ptr[3]+4);
SMSTOP();
#ifdef AT88SC_DISABLE_INTERRUPT
__enable_irq();
#endif
}
/**
* authentication arithmetic function.
* Functions Brief:i don`t know.
* @param[in] i don`t know.
* @param[out] noen.
* @retval none
* @par TAG
* reserved
* @par other
* none
* @par modify
* ken 2018-11-15 create
*/
void at88sc_gpa_clock(uint8_t Datain,uint8_t times){
uint8_t t;
uint8_t d;
uint8_t din_gpa;
uint8_t Ri;
uint8_t R_Sum;
uint8_t Si;
uint8_t S_Sum;
uint8_t Ti;
uint8_t T_Sum;
for(t=0x00;t<times;t++){
din_gpa=Datain ^ GPA[0];
Ri= din_gpa&0x1f;
Si= ((din_gpa&0x0f)<<3)+((din_gpa&0xe0)>>5);
Ti=(din_gpa&0xf8)>>3;
//r parameter
if(((GPA[4])+((GPA[1]&0x0f)<<1)+((GPA[1]&0x10)>>4))>31){
R_Sum=((GPA[4])+((GPA[1]&0x0f)<<1)+((GPA[1]&0x10)>>4))-31;
}
else{
R_Sum=((GPA[4])+((GPA[1]&0x0f)<<1)+((GPA[1]&0x10)>>4));
}
GPA[1]=GPA[2];
GPA[2]=GPA[3];
GPA[3]=GPA[4];
GPA[4]=GPA[5]^Ri;
GPA[5]=GPA[6];
GPA[6]=GPA[7];
GPA[7]=R_Sum;
//s parameter
if ((GPA[9]+((GPA[8]&0x3f)<<1)+((GPA[8]&0x40)>>6) )>127){
S_Sum=( (GPA[9]) + ((GPA[8]&0x3f)<<1)+((GPA[8]&0x40)>>6) )-127;
}
else{
S_Sum= (GPA[9]) + ((GPA[8]&0x3f)<<1)+((GPA[8]&0x40)>>6) ;
}
GPA[8]=GPA[9];
GPA[9]=Si^GPA[10];
GPA[10]=GPA[11];
GPA[11]=GPA[12];
GPA[12]=GPA[13];
GPA[13]=GPA[14];
GPA[14]=S_Sum;
//t parameter
if ((GPA[15]+GPA[17])> 31){
T_Sum=GPA[15]+GPA[17]-31;
}
else{
T_Sum=GPA[15]+GPA[17];
}
GPA[15]=GPA[16];
GPA[16]=GPA[17];
GPA[17]=GPA[18]^Ti;
GPA[18]=GPA[19];
GPA[19]=T_Sum;
///Output
if((GPA[14]&0x01)==0){
d=((GPA[7]^GPA[3])&0x01);
}
else{
d=((GPA[19]^GPA[16])&0x01);
}
if((GPA[14]&0x02)==0){
d=d+((GPA[7]^GPA[3])&0x02);
}
else{
d=d+((GPA[19]^GPA[16])&0x02);
}
if((GPA[14]&0x04)==0){
d=d+((GPA[7]^GPA[3])&0x04);
}
else{
d=d+((GPA[19]^GPA[16])&0x04);
}
if((GPA[14]&0x08)==0){
d=d+((GPA[7]^GPA[3])&0x08);
}
else{
d=d+((GPA[19]^GPA[16])&0x08);
}
GPA[0]= ( (((GPA[0])&0x0f)<<4) +d);
}
}
/**
* authentication the selected gc code.
* authentication the selected gc code.
* @param[in] GC_select:gc code num.
* @param[out] noen.
* @retval return 0xff:success, other:failed
* @par TAG
* reserved
* @par other
* none
* @par modify
* ken 2018-11-15 create
*/
uint8_t at88sc_authentication(uint8_t GC_select){
#ifdef AT88SC_NO_NEED_AUTHENTICATION
return 0xff;
#endif
uint8_t SK[8];
uint8_t Q_CH[0x14];
uint8_t j;
for(j=0;j<=19;j++){
GPA[j]=0x00;
}
Q_CH[0]=0xb6;
Q_CH[1]=0x00;
Q_CH[2]=GC_select<<4;
Q_CH[2]=Q_CH[2]+0x50;
Q_CH[3]=0x08;
at88sc_read(Q_CH);
for(j=0;j<8;j++){
Q_CH[j+12]=Q_CH[j+4];//CI
}
for(j=0;j<8;j++){
Q_CH[j+4]=0xAA; //$$can modify random number
}
for(j=0;j<4;j++){
at88sc_gpa_clock(Q_CH[12+2*j],0x03);
at88sc_gpa_clock(Q_CH[12+2*j+1],0x03);
at88sc_gpa_clock(Q_CH[4+j],0x01);
}
if ((GC_select&0x0f)==0x00)
for(j=0;j<8;j++){
Q_CH[12+j]=GC0[j];
}
else if ((GC_select&0x0f)==0x01)
for(j=0;j<8;j++){
Q_CH[12+j]=GC1[j];
}
else if ((GC_select&0x0f)==0x02)
for(j=0;j<8;j++){
Q_CH[12+j]=GC2[j];
}
else
for(j=0;j<8;j++){
Q_CH[12+j]=GC3[j];
}
for(j=0;j<4;j++){
at88sc_gpa_clock(Q_CH[12+2*j],0x03);
at88sc_gpa_clock(Q_CH[12+2*j+1],0x03);
at88sc_gpa_clock(Q_CH[8+j],0x01);
}
at88sc_gpa_clock(0x00,0x06);
Q_CH[12]=GPA[0];
for(j=1;j<8;j++){
at88sc_gpa_clock(0x00,0x07);
Q_CH[12+j]=GPA[0];
}
Q_CH[0]=0xb8;//send ch
Q_CH[2]=0x00;
Q_CH[3]=0x10;
Q_CH[1]=GC_select;
at88sc_write(Q_CH);
at88sc_ack_polling();
//new ci
Q_CH[12]=0xFF;
for(j=1;j<8;j++){
at88sc_gpa_clock(0x00,0x02);
Q_CH[12+j]=GPA[0];
}
//new sk
for(j=0;j<8;j++){
at88sc_gpa_clock(0x00,0x02);
SK[j]=GPA[0];
}
at88sc_gpa_clock(0x00,0x03);
Q_CH[0]=0XB6;
Q_CH[1]=0X00;
Q_CH[2]=GC_select<<4;
Q_CH[2]=Q_CH[2]+0x50;
Q_CH[3]=0x08;
at88sc_read(Q_CH);
at88sc_ack_polling();
if (Q_CH[4]!=0xff){
goto Aut_Report;
}
for(j=0;j<8;j++){
if(Q_CH[4+j]!= Q_CH[12+j]){
goto Aut_Report;
}
}
at88sc_gpa_clock(0x00,0x05);
at88sc_gpa_clock(Q_CH[2],0x01);
at88sc_gpa_clock(0x00,0x05);
at88sc_gpa_clock(0x08,0x01);
for(j=0;j<8;j++){
at88sc_gpa_clock(Q_CH[4+j],0x01);
at88sc_gpa_clock(0x00,0x05);
}
//crypto_Authentication
for(j=0;j<=19;j++){
GPA[j]=0x00;
}
for(j=0;j<8;j++){
Q_CH[j+4]=0xAA; //$$can modify random number
}
for(j=0;j<4;j++){
at88sc_gpa_clock(Q_CH[12+2*j],0x03);
at88sc_gpa_clock(Q_CH[12+2*j+1],0x03);
at88sc_gpa_clock(Q_CH[4+j],0x01);
}
for(j=0;j<4;j++){
at88sc_gpa_clock(SK[2*j],0x03);
at88sc_gpa_clock(SK[2*j+1],0x03);
at88sc_gpa_clock(Q_CH[8+j],0x01);
}
at88sc_gpa_clock(0x00,0x06);
Q_CH[12]=GPA[0];
for(j=1;j<8;j++){
at88sc_gpa_clock(0x00,0x07);
Q_CH[12+j]=GPA[0];
}
Q_CH[0]=0xb8;
Q_CH[1]=GC_select+0x10;
Q_CH[2]=0x00;
Q_CH[3]=0x10;
at88sc_write(Q_CH);
at88sc_ack_polling();
//new ci
Q_CH[12]=0xFF;
for(j=1;j<8;j++){
at88sc_gpa_clock(0x00,0x02);
Q_CH[12+j]=GPA[0];
}
//new sk
for(j=0;j<8;j++){
at88sc_gpa_clock(0x00,0x02);
SK[j]=GPA[0];
}
at88sc_gpa_clock(0x00,0x03);
Q_CH[0]=0XB6;
Q_CH[1]=0X00;
Q_CH[2]=GC_select<<4;
Q_CH[2]=Q_CH[2]+0x50;
Q_CH[3]=0x08;
at88sc_read(Q_CH);
at88sc_ack_polling();
if (Q_CH[4]!=0xff){
goto Aut_Report;
}
for(j=0;j<8;j++){
if(Q_CH[4+j]!= Q_CH[12+j]){
goto Aut_Report;
}
}
at88sc_gpa_clock(0x00,0x05);
at88sc_gpa_clock(Q_CH[2],0x01);
at88sc_gpa_clock(0x00,0x05);
at88sc_gpa_clock(0x08,0x01);
for(j=0;j<8;j++){
at88sc_gpa_clock(Q_CH[4+j],0x01);
at88sc_gpa_clock(0x00,0x05);
}
Aut_Report:
return Q_CH[4];
}
/**
* verify the user zone write password.
* verify the user zone write password.
* @param[in] pw_select:write code num.
* @param[out] noen.
* @retval return 0xff:success, other:failed
* @par TAG
* reserved
* @par other
* none
* @par modify
* ken 2018-11-15 create
*/
uint8_t at88sc_verify_write_password(uint8_t pw_select){
#ifdef AT88SC_NO_NEED_PASSWORD
return 0xff;
#endif
uint8_t j;
uint8_t pw[7];
if ((pw_select&0x0f)==0x00)
for(j=0;j<3;j++){
pw[4+j]=PW_WRITE0[j];
}
else if ((pw_select&0x0f)==0x01)
for(j=0;j<3;j++){
pw[4+j]=PW_WRITE1[j];
}
else if ((pw_select&0x0f)==0x02)
for(j=0;j<3;j++){
pw[4+j]=PW_WRITE2[j];
}
else if ((pw_select&0x0f)==0x03)
for(j=0;j<3;j++){
pw[4+j]=PW_WRITE3[j];
}
else if ((pw_select&0x0f)==0x04)
for(j=0;j<3;j++){
pw[4+j]=PW_WRITE4[j];
}
else if ((pw_select&0x0f)==0x05)
for(j=0;j<3;j++)
{pw[4+j]=PW_WRITE5[j];}
else if ((pw_select&0x0f)==0x06)
for(j=0;j<3;j++)
{pw[4+j]=PW_WRITE6[j];}
else
for(j=0;j<3;j++)
{pw[4+j]=PW_WRITE7[j];}
for(j=0;j<3;j++){
at88sc_gpa_clock(pw[4+j],0x05);
pw[4+j]=GPA[0];
}
pw[0]=0xba;
pw[1]=pw_select&0x0f;
pw[2]=0x00;
pw[3]=0x03;
at88sc_write(pw);
at88sc_ack_polling();
pw[0]=0XB6;
pw[1]=0X00;
pw[2]=pw_select&0x0f;
pw[2]=pw[2]*0x08;
pw[2]=pw[2]+0xb0;
pw[3]=0x01;
at88sc_read(pw);
at88sc_ack_polling();
at88sc_gpa_clock(0x00,0x05);
at88sc_gpa_clock(pw[2],0x01);
at88sc_gpa_clock(0x00,0x05);
at88sc_gpa_clock(0x01,0x01);
pw[4]=pw[4]^GPA[0];
at88sc_gpa_clock(pw[4],0x01);
at88sc_gpa_clock(0x00,0x05);
return pw[4];
}
/**
* verify the user zone read password.
* verify the user zone read password.
* @param[in] pw_select:read code num.
* @param[out] noen.
* @retval return 0xff:success, other:failed
* @par TAG
* reserved
* @par other
* none
* @par modify
* ken 2018-11-15 create
*/
uint8_t at88sc_verify_read_password(uint8_t pw_select){
uint8_t j;
uint8_t pw[7];
if ((pw_select&0x0f)==0x00){
for(j=0;j<3;j++){
pw[4+j]=PW_READ0[j];
}
}//{*(p+42+j)=PW_WRITE0[j];}}
else if ((pw_select&0x0f)==0x01)
for(j=0;j<3;j++){
pw[4+j]=PW_READ1[j];
}
else if ((pw_select&0x0f)==0x02)
for(j=0;j<3;j++){
pw[4+j]=PW_READ2[j];
}
else if ((pw_select&0x0f)==0x03)
for(j=0;j<3;j++){
pw[4+j]=PW_READ3[j];
}
else if ((pw_select&0x0f)==0x04)
for(j=0;j<3;j++){
pw[4+j]=PW_READ4[j];
}
else if ((pw_select&0x0f)==0x05)
for(j=0;j<3;j++){
pw[4+j]=PW_READ5[j];
}
else if ((pw_select&0x0f)==0x06)
for(j=0;j<3;j++){
pw[4+j]=PW_READ6[j];
}
else
for(j=0;j<3;j++){
pw[4+j]=PW_READ7[j];
}
for(j=0;j<3;j++){
at88sc_gpa_clock(pw[4+j],0x05);//GPA[0]=pw[4+j];at88sc_gpa_clock(0x05);
pw[4+j]=GPA[0];//*(p+42+j)=*(p+11);
}
pw[0]=0xba;//*(p+38)=0xba; //
pw[1]=pw_select&0x0f;//*(p+39)=*(p+1)&0x0f;
pw[1]=pw[1]+0x10;
pw[2]=0x00;//*(p+40)=0x00;
pw[3]=0x03;//*(p+41)=0x03;
at88sc_write(pw);
delay_ms(10);// delay_ms(1);delay_ms(1);
pw[0]=0XB6;
pw[1]=0X00;
pw[2]=pw_select&0x0f;
pw[2]=pw[2]*0x08;
pw[2]=pw[2]+0xb4;
pw[3]=0x01;
at88sc_read(pw);
at88sc_gpa_clock(0x00,0x05);//GPA[0]=0x00;at88sc_gpa_clock(5);
at88sc_gpa_clock(pw[2],0x01);//GPA[0]=pw[2];at88sc_gpa_clock(1);
at88sc_gpa_clock(0x00,0x05);//GPA[0]=0x00;at88sc_gpa_clock(5);
at88sc_gpa_clock(0x01,0x01);//GPA[0]=0x01;at88sc_gpa_clock(1);
pw[4]=pw[4]^GPA[0];
at88sc_gpa_clock(pw[4],0x01);//GPA[0]=pw[4];at88sc_gpa_clock(1);
at88sc_gpa_clock(0x00,0x05);//GPA[0]=0x00;at88sc_gpa_clock(5);
return pw[4];
}
/**
* select user zone by the parameter.
* select user zone by the parameter.
* @param[in] zone:zone num.
* @param[out] noen.
* @retval none
* @par TAG
* reserved
* @par other
* none
* @par modify
* ken 2018-11-15 create
*/
void at88sc_select_user_zone(uint8_t zone){
uint8_t zon[4];
#if !defined(AT88SC_NO_NEED_AUTHENTICATION) && !defined(AT88SC_NO_NEED_PASSWORD)
at88sc_gpa_clock(zone,0x01);
#endif
zon[0]=0xb4;
zon[1]=0x03;
zon[2]=zone;
zon[3]=0x00;
at88sc_write(zon);
at88sc_ack_polling();
}
/**
* read data from the user zone.
* call this fuction before authentication & verify the password.
* @param[in] rd_high_addr:high 8 addr,rd_low_addr:low 8 addr,rd_number:read length, recv_ptr:reply data pointer.
* @param[out] 1:success,0:failed.
* @retval none
* @par TAG
* reserved
* @par other
* none
* @par modify
* ken 2018-11-15 create
*/
uint8_t at88sc_read_user_zone(uint16_t addr,uint16_t rd_number,uint8_t *recv_ptr){
if( rd_number<=READ_BUF_MAX_SIZE ){
uint8_t j;
uint8_t recv_buf[READ_BUF_MAX_SIZE+4];
uint8_t rd_high_addr,rd_low_addr;
rd_high_addr = addr>>8;
rd_low_addr = addr&0xff;
recv_buf[0]=0xb2;
recv_buf[1]=rd_high_addr;
recv_buf[2]=rd_low_addr;
recv_buf[3]=rd_number;
at88sc_read(recv_buf);
at88sc_ack_polling();
#if !defined(AT88SC_NO_NEED_AUTHENTICATION) && !defined(AT88SC_NO_NEED_PASSWORD)
at88sc_gpa_clock(0x00,0x05);
at88sc_gpa_clock(rd_low_addr,0x01);
at88sc_gpa_clock(0x00,0x05);
at88sc_gpa_clock(rd_number,0x01);
for(j=0;j<rd_number;j++){
recv_buf[4+j]=recv_buf[4+j]^GPA[0];
at88sc_gpa_clock(recv_buf[4+j],0x01);
at88sc_gpa_clock(0x00,0x05);
}
#endif
memcpy(recv_ptr,&recv_buf[4],rd_number);
return 1;
}
else{
return 0;
}
}
/**
* read data from the config zone.
* read encryption data decode to original data.
* @param[in] rd_high_addr:high 8 addr,rd_low_addr:low 8 addr,rd_number:read length, recv_ptr:reply data pointer.
* @param[out] 1:success,0:failed.
* @retval none
* @par TAG
* reserved
* @par other
* none
* @par modify
* ken 2018-11-15 create
*/
uint8_t at88sc_read_config_zone(unsigned char rd_high_addr,unsigned char rd_low_addr,unsigned char rd_number,uint8_t *recv_ptr){
if( rd_number+4<=READ_BUF_MAX_SIZE ){
unsigned char j;
uint8_t send_buf[READ_BUF_MAX_SIZE];
send_buf[0]=0xb6;
send_buf[1]=rd_high_addr;
send_buf[2]=rd_low_addr;
send_buf[3]=rd_number;
at88sc_read(send_buf);
at88sc_ack_polling();
at88sc_gpa_clock(0x00,0x05);
at88sc_gpa_clock(rd_low_addr,0x01);
at88sc_gpa_clock(0x00,0x05);
at88sc_gpa_clock(rd_number,0x01);
for(j=0;j<rd_number;j++){
if(rd_low_addr>=0xb0){
send_buf[4+j]=send_buf[4+j]^GPA[0];}
at88sc_gpa_clock(send_buf[4+j],0x01);
at88sc_gpa_clock(0x00,0x05);
}
memcpy(recv_ptr,&send_buf[4],rd_number);
return 1;
}
else{
return 0;
}
}
/**
* encryption to send at88sc.
* encryption original data .
* @param[in] encryptodatanumber:data length,ptr:data pointer.
* @param[out] none.
* @retval none
* @par TAG
* reserved
* @par other
* none
* @par modify
* ken 2018-11-15 create
*/
void at88sc_encrypto_data(uint8_t encryptodatanumber,uint8_t *ptr){
uint8_t j;
uint8_t temp;
for(j=0;j<encryptodatanumber;j++){
at88sc_gpa_clock(0x00,0x05);
temp=ptr[4+j];
ptr[4+j]=ptr[4+j]^GPA[0];
at88sc_gpa_clock(temp,0x01);
}
}
/**
* count protocol checksum.
* count protocol checksum.
* @param[in] none.
* @param[out] none.
* @retval none
* @par TAG
* reserved
* @par other
* none
* @par modify
* ken 2018-11-15 create
*/
void at88sc_send_checksum(void){
uint8_t dat6[6];
dat6[0]=0xb4;
dat6[1]=0x02;
dat6[2]=0x00;
dat6[3]=0x02;
at88sc_gpa_clock(0x00,0x0f);
dat6[4]=GPA[0];
at88sc_gpa_clock(0x00,0x05);
dat6[5]=GPA[0];
at88sc_write(dat6);
}
/**
* write data to user zone.
* call this fuction before authentication & verify the password.
* @param[in] rd_high_addr:high 8 addr,rd_low_addr:low 8 addr,rd_number:read length, send_ptr:send data pointer.
* @param[out] none.
* @retval none
* @par TAG
* reserved
* @par other
* none
* @par modify
* ken 2018-11-15 create
*/
uint8_t at88sc_write_user_zone(uint16_t addr,uint8_t wr_number,uint8_t *send_ptr){
if( wr_number<=WRITE_BUF_MAX_SIZE ){
uint8_t send_buf[WRITE_BUF_MAX_SIZE+4];
uint8_t wr_high_addr,wr_low_addr;
wr_high_addr = addr>>8;
wr_low_addr = addr&0xff;
#if !defined(AT88SC_NO_NEED_AUTHENTICATION) && !defined(AT88SC_NO_NEED_PASSWORD)
at88sc_gpa_clock(0x00,0x05);
at88sc_gpa_clock(wr_low_addr,0x01);
at88sc_gpa_clock(0x00,0x05);
at88sc_gpa_clock(wr_number,0x01);
#endif
send_buf[0]=0xb0;
send_buf[1]=wr_high_addr;
send_buf[2]=wr_low_addr;
send_buf[3]=wr_number;
memcpy(&send_buf[4],send_ptr,wr_number);
#if !defined(AT88SC_NO_NEED_AUTHENTICATION) && !defined(AT88SC_NO_NEED_PASSWORD)
at88sc_encrypto_data(wr_number,send_buf);
#endif
at88sc_write(send_buf);
delay_ms(5);
at88sc_send_checksum();
at88sc_ack_polling();
return 1;
}
else{
return 0;
}
}
/**
* write data to config zone.
* write data to config zone.
* @param[in] rd_high_addr:high 8 addr,rd_low_addr:low 8 addr,rd_number:read length, send_ptr:send data pointer.
* @param[out] none.
* @retval none
* @par TAG
* reserved
* @par other
* none
* @par modify
* ken 2018-11-15 create
*/
uint8_t at88sc_write_config_zone(uint8_t wr_high_addr,uint8_t wr_low_addr,uint8_t wr_number,uint8_t *send_ptr){
if( wr_number+4 < WRITE_BUF_MAX_SIZE ){
uint8_t send_buf[WRITE_BUF_MAX_SIZE];
uint8_t j;
uint8_t temp;
at88sc_gpa_clock(0x00,0x05);
at88sc_gpa_clock(wr_low_addr,0x01);
at88sc_gpa_clock(0x00,0x05);
at88sc_gpa_clock(wr_number,0x01);
send_buf[0]=0xb4;
send_buf[1]=wr_high_addr;
send_buf[2]=wr_low_addr;
send_buf[3]=wr_number;
//at88sc_encrypto_data(wr_number);
memcpy(&send_buf[4],send_ptr,wr_number);
for(j=0;j<wr_number;j++){
at88sc_gpa_clock(0x00,0x05);
temp=send_buf[4+j];
if(wr_low_addr>=0xb0){
send_buf[4+j]=send_buf[4+j]^GPA[0];
}
at88sc_gpa_clock(temp,0x01);
}
at88sc_write(send_buf);
delay_ms(5);
at88sc_send_checksum();
at88sc_ack_polling();
return 1;
}
else{
return 0;
}
}
/**
* plaintext verify config zone sceure code.
* for verify config passoword must after the chip reset,nor the case the verfiy well failed.
* @param[in] sc_first_byte:sc first byte,sc_second_byte:sc second byte,sc_third_byte: sc third byte.
* @param[out] none.
* @retval return 0xff:success, 0:failed
* @par TAG
* reserved
* @par other
* none
* @par modify
* ken 2018-11-15 create
*/
uint8_t at88sc_verify_sc_plaintext(uint8_t sc_first_byte,uint8_t sc_second_byte,uint8_t sc_third_byte){
uint8_t scdata[7];
scdata[0]=0xBA;
scdata[1]=0x07;
scdata[2]=0x00;
scdata[3]=0x03;
scdata[4]=sc_first_byte;
scdata[5]=sc_second_byte;
scdata[6]=sc_third_byte;
at88sc_write(scdata);
scdata[0]=0xb6;
scdata[1]=0x00;
scdata[2]=0xE8;
scdata[3]=0x01;
at88sc_read(scdata);
return scdata[4];
}
/**
* plaintext set user zone num.
* plaintext set user zone num.
* @param[in] zonep:zone num.
* @param[out] none.
* @retval none
* @par TAG
* reserved
* @par other
* none
* @par modify
* ken 2018-11-15 create
*/
void at88sc_set_user_zone_plaintext(uint8_t zonep){
uint8_t zon[4];
zon[0]=0xb4;
zon[1]=0x03;
zon[2]=zonep;
zon[3]=0x00;
at88sc_write(zon);
}
/**
* plaintext read data.
* plaintext read data.
* @param[in] rd_cmd:command,A1:high 8byte,A2:low 8byte,N:length, recv_ptr:recvive pointer
* @param[out] none.
* @retval 1:success 0:failed
* @par TAG
* reserved
* @par other
* none
* @par modify
* ken 2018-11-15 create
*/
uint8_t at88sc_read_paintext(uint8_t rd_cmd,uint8_t A1,uint8_t A2,uint8_t N, uint8_t *recv_ptr){
if( N+4 < READ_BUF_MAX_SIZE ){
uint8_t send_buf[READ_BUF_MAX_SIZE];
send_buf[0]=rd_cmd;//0xb2 or 0xb6
send_buf[1]=A1; //A1
send_buf[2]=A2; //A2
send_buf[3]=N; //N
at88sc_read(send_buf);
memcpy(recv_ptr,&send_buf[4],N);
return 1;
}
else{
return 0;
}
}
/**
* plaintext write data.
* plaintext write data.
* @param[in] rd_cmd:command,A1:high 8byte,A2:low 8byte,N:length, recv_ptr:send pointer
* @param[out] none.
* @retval none
* @par TAG
* reserved
* @par other
* none
* @par modify
* ken 2018-11-15 create
*/
uint8_t at88sc_write_paintext(uint8_t wr_cmd,uint8_t A1,uint8_t A2,uint8_t N,uint8_t *send_ptr){
if( N+4 < WRITE_BUF_MAX_SIZE ){
uint8_t send_buf[WRITE_BUF_MAX_SIZE];
send_buf[0]=wr_cmd;//0xb0 or 0xb4
send_buf[1]=A1; //A1
send_buf[2]=A2; //A2
send_buf[3]=N; //N
memcpy(&send_buf[4],send_ptr,N);
at88sc_write(send_buf);
return 1;
}
else{
return 0;
}
}
/**
* at88sc write block.
* send data support more than block size.
* @param[in] zone:block num,addr:user zone addr,len:read length,ptr:send data pointer.
* @param[out] none.
* @retval >0:send data length,0: failed.
* @par TAG
* reserved
* @par other
* none
* @par modify
* ken 2018-11-15 create
*/
uint16_t at88sc_write_user_block(uint8_t zone, uint16_t addr, uint16_t len, uint8_t *ptr){
uint16_t send=0;
uint16_t seg;
uint8_t gc,pw;
#if !defined(AT88SC_NO_NEED_AUTHENTICATION) && !defined(AT88SC_NO_NEED_PASSWORD)
///<last use the block and this times use is the same, with no need for to do
if( st88sc_sta.curr_use_block != zone ){
gc = block_admini[zone]>>4;
pw = block_admini[zone]&0x0f;
if( at88sc_authentication(gc)!=0xff ){
return 0;
}
else {
if( at88sc_verify_write_password(pw)!=0xff )
return 0;
}
st88sc_sta.curr_use_block = zone;
}
#endif
if( addr+len <= AT88SC_BLOCK_SIZE ){
at88sc_select_user_zone(zone);
while( send<len ){
if( len-send < WRITE_BUF_MAX_SIZE ){
seg = (len-send);
}
else{
seg = WRITE_BUF_MAX_SIZE;
}
if( addr/WRITE_BUF_MAX_SIZE != (addr+seg)/WRITE_BUF_MAX_SIZE )
seg = WRITE_BUF_MAX_SIZE-addr%WRITE_BUF_MAX_SIZE;
at88sc_write_user_zone(addr,seg,ptr);
addr += seg;
send += seg;
ptr += seg;
//for use in rtos, release system
delay_ms(1);
}
return len;
}
else{
return 0;
}
}
/**
* at88sc read block.
* read data from the at88sc within a block.
* @param[in] zone:block num,addr:user zone addr,len:read length,ptr:save data pointer.
* @param[out] none.
* @retval >0:receive data length,0: failed.
* @par TAG
* reserved
* @par other
* none
* @par modify
* ken 2018-11-15 create
*/
uint16_t at88sc_read_user_block(uint8_t zone, uint16_t addr, uint16_t len, uint8_t *ptr){
uint8_t gc,pw;
uint16_t recv=0;
uint16_t seg;
///<last use the block and this times use is the same, with no need for to do
if( st88sc_sta.curr_use_block != zone ){
gc = block_admini[zone]>>4;
pw = block_admini[zone]&0x0f;
if( at88sc_authentication(gc)!=0xff ){
return 0;
}
else {
if( at88sc_verify_write_password(pw)!=0xff )
return 0;
}
st88sc_sta.curr_use_block = zone;
}
if( addr+len <= AT88SC_BLOCK_SIZE ){
at88sc_select_user_zone(zone);
while( recv<len ){
if( len-recv < READ_BUF_MAX_SIZE ){
seg = (len-recv);
}
else{
seg = READ_BUF_MAX_SIZE;
}
// if( addr/READ_BUF_MAX_SIZE != (addr+seg)/READ_BUF_MAX_SIZE )
// seg = READ_BUF_MAX_SIZE-addr%READ_BUF_MAX_SIZE;
at88sc_read_user_zone(addr,seg,ptr);
addr += seg;
recv += seg;
ptr += seg;
//for use in rtos, release system
delay_ms(1);
}
return len;
}
else{
return 0;
}
}
/**
* read at88sc config register.
* read config register into variate.
* @param[in] reg:contain address & read or write length,ptr:read data pointer.
* @param[out] none.
* @retval 1:success,0: failed.
* @par TAG
* reserved
* @par other
* none
* @par modify
* ken 2018-11-16 create
*/
uint8_t at88sc_read_config_register( uint16_t reg, uint8_t *ptr){
uint8_t addr,len;
addr = reg&0xff;
len = reg>>8; return at88sc_read_paintext(SYS_READ,0x00,addr,len,ptr);
}
/**
* write at88sc config register.
* write config register from variate.
* @param[in] reg:contain address & read or write length,ptr:read data pointer.
* @param[out] none.
* @retval 1:success,0: failed.
* @par TAG
* reserved
* @par other
* none
* @par modify
* ken 2018-11-16 create
*/
uint8_t at88sc_write_config_register( uint16_t reg, uint8_t *ptr){
uint8_t addr,len;
addr = reg&0xff;
len = reg>>8;
return at88sc_write_paintext(SYS_WRITE,0x00,addr,len,ptr);
}
/**
* write at88sc storage.
* write at88sc all the block in continuous address,such as 0x0000-0x8000 for at88sc25616.
* @param[in] addr:write address,len:write length,ptr:write data pointer.
* @param[out] none.
* @retval >0:send data length,0: failed.
* @par TAG
* reserved
* @par other
* none
* @par modify
* ken 2018-11-20 create
*/
uint16_t at88sc_write_storage(CARD_MANAGE_TypeDef *card_manage, uint16_t addr, uint16_t len, uint8_t *ptr){
uint16_t block_addr,write_len;
uint16_t start_addr,count=0;
uint8_t block_num;
start_addr = addr;
if( addr+len <= AT88SC_STORAGE_SIZE ){
while( count < len ){
block_addr = start_addr%AT88SC_BLOCK_SIZE;
block_num = start_addr/AT88SC_BLOCK_SIZE;
write_len = AT88SC_BLOCK_SIZE-block_addr;
if( write_len > (len-count) )
write_len = len-count;
at88sc_write_user_block(block_num, block_addr, write_len, ptr);
count += write_len;
start_addr += write_len;
ptr += write_len;
}
return count;
}
else{
return 0;
}
}
/**
* at88sc read storage.
* read at88sc all the block in continuous address,such as 0x0000-0x8000 for at88sc25616.
* @param[in] addr:write address,len:write length,ptr:write data pointer.
* @param[out] none.
* @retval >0:receive data length,0: failed.
* @par TAG
* reserved
* @par other
* none
* @par modify
* ken 2018-11-20 create
*/
uint16_t at88sc_read_storage(CARD_MANAGE_TypeDef *card_manage, uint16_t addr, uint16_t len, uint8_t *ptr){
uint16_t block_addr,write_len;
uint16_t start_addr,count=0;
uint8_t block_num;
start_addr = addr;
if( addr+len <= AT88SC_STORAGE_SIZE ){
while( count < len ){
block_addr = start_addr%AT88SC_BLOCK_SIZE;
block_num = start_addr/AT88SC_BLOCK_SIZE;
write_len = AT88SC_BLOCK_SIZE-block_addr;
if( write_len > (len-count) )
write_len = len-count;
at88sc_read_user_block(block_num, block_addr, write_len, ptr);
count += write_len;
start_addr += write_len;
ptr += write_len;
}
return count;
}
else{
return 0;
}
}
/**
* read at88sc fuse status.
* read at88sc fuse status.
* @param[in] none.
* @param[out] stata:return fuse state.
* @retval none.
* @par TAG
* reserved
* @par other
* none
* @par modify
* ken 2018-11-20 create
*/
void at88sc_read_fuse_state(uint8_t *state){
uint8_t send_buf[READ_BUF_MAX_SIZE];
send_buf[0]=SYS_READ;//0xb2 or 0xb6
send_buf[1]=0x01; //A1
send_buf[2]=0x00; //A2
send_buf[3]=0x01; //N
at88sc_read(send_buf);
*state = send_buf[4];
}
/**
* at88sc initialize.
* initialize i2c gpio, data struct.
* @param[in] none.
* @param[out] none.
* @retval none
* @par TAG
* reserved
* @par other
* none
* @par modify
* ken 2018-11-15 create
*/
FUN_STATUS_T at88sc_init(void)
{
AT88SC_GPIO_CLK_ENABLE();
IIC_Initial();
if(!at88sc_mtz_test()){
// Error_Handler(SYSTEM_I2C_INIT_ERROR);
return FUN_ERROR;
}
st88sc_sta.curr_use_block = 0xff;
uint8_t state=0;
static uint8_t vc_flag=0,wr_flag=0;
uint8_t buf[128],temp[128];
if( vc_flag )
state = at88sc_verify_sc_plaintext(0x17,0xc3,0x3a);
// state = at88sc_verify_sc_plaintext(0x05,0x05,0xc7);
if( state>0 ){
buf[0] = 0xaa;
at88sc_write_config_register(DCR_R,buf); ///<ETA设为0 认证及密码校验不会错误计数
at88sc_read_config_register(ATR_R,buf);
at88sc_log("DCR_R %02X\r\n",buf[0]);
buf[0] = 0xFF;
at88sc_write_config_register(AR0_R,buf);
at88sc_write_config_register(AR1_R,buf);
at88sc_write_config_register(AR2_R,buf);
at88sc_write_config_register(AR3_R,buf);
at88sc_write_config_register(AR4_R,buf);
at88sc_write_config_register(AR5_R,buf);
at88sc_write_config_register(AR6_R,buf);
at88sc_write_config_register(AR7_R,buf);
at88sc_write_config_register(PACW0_R,buf);
at88sc_write_config_register(PACW1_R,buf);
at88sc_write_config_register(PACW2_R,buf);
at88sc_write_config_register(PACW3_R,buf);
at88sc_write_config_register(PACW4_R,buf);
at88sc_write_config_register(PACW5_R,buf);
at88sc_write_config_register(PACW6_R,buf);
at88sc_write_config_register(PACW7_R,buf);
buf[0] = 0x08;
at88sc_write_config_register(PR0_R,buf);
at88sc_write_config_register(PR1_R,buf);
at88sc_write_config_register(PR2_R,buf);
at88sc_write_config_register(PR3_R,buf);
at88sc_write_config_register(PR4_R,buf);
at88sc_write_config_register(PR5_R,buf);
at88sc_write_config_register(PR6_R,buf);
at88sc_write_config_register(PR7_R,buf);
at88sc_write_config_register(SSG0_R,(uint8_t *)GC0);
at88sc_write_config_register(SSG1_R,(uint8_t *)GC1);
at88sc_write_config_register(SSG2_R,(uint8_t *)GC2);
at88sc_write_config_register(SSG3_R,(uint8_t *)GC3);
at88sc_write_config_register(W0_R,(uint8_t *)PW_WRITE0);
at88sc_write_config_register(R0_R,(uint8_t *)PW_READ0);
at88sc_write_config_register(W1_R,(uint8_t *)PW_WRITE1);
at88sc_write_config_register(R1_R,(uint8_t *)PW_READ1);
at88sc_write_config_register(W2_R,(uint8_t *)PW_WRITE2);
at88sc_write_config_register(R2_R,(uint8_t *)PW_READ2);
at88sc_write_config_register(W3_R,(uint8_t *)PW_WRITE3);
at88sc_write_config_register(R3_R,(uint8_t *)PW_READ3);
at88sc_write_config_register(W4_R,(uint8_t *)PW_WRITE4);
at88sc_write_config_register(R4_R,(uint8_t *)PW_READ4);
at88sc_write_config_register(W5_R,(uint8_t *)PW_WRITE5);
at88sc_write_config_register(R5_R,(uint8_t *)PW_READ5);
at88sc_write_config_register(W6_R,(uint8_t *)PW_WRITE6);
at88sc_write_config_register(R6_R,(uint8_t *)PW_READ6);
// at88sc_write_config_register(W7_R,(uint8_t *)PW_WRITE7);
at88sc_write_config_register(R7_R,(uint8_t *)PW_READ7);
at88sc_read_config_register(SSG0_R,buf);
at88sc_log("SSG0 ");
at88sc_dump(buf,8);
at88sc_read_config_register(SSG1_R,buf);
at88sc_log("SSG1 ");
at88sc_dump(buf,8);
at88sc_read_config_register(SSG2_R,buf);
at88sc_log("SSG2 ");
at88sc_dump(buf,8);
at88sc_read_config_register(SSG3_R,buf);
at88sc_log("SSG3 ");
at88sc_dump(buf,8);
at88sc_read_config_register(W0_R,buf);
at88sc_log("W0 ");
at88sc_dump(buf,3);
at88sc_read_config_register(R0_R,buf);
at88sc_log("R0 ");
at88sc_dump(buf,3);
at88sc_read_config_register(W1_R,buf);
at88sc_log("W1 ");
at88sc_dump(buf,3);
at88sc_read_config_register(R1_R,buf);
at88sc_log("R1 ");
at88sc_dump(buf,3);
at88sc_read_config_register(W2_R,buf);
at88sc_log("W2 ");
at88sc_dump(buf,3);
at88sc_read_config_register(R2_R,buf);
at88sc_log("R2 ");
at88sc_dump(buf,3);
at88sc_read_config_register(W3_R,buf);
at88sc_log("W3 ");
at88sc_dump(buf,3);
at88sc_read_config_register(R3_R,buf);
at88sc_log("R3 ");
at88sc_dump(buf,3);
at88sc_read_config_register(W4_R,buf);
at88sc_log("W4 ");
at88sc_dump(buf,3);
at88sc_read_config_register(R4_R,buf);
at88sc_log("R4 ");
at88sc_dump(buf,3);
at88sc_read_config_register(W5_R,buf);
at88sc_log("W5 ");
at88sc_dump(buf,3);
at88sc_read_config_register(R5_R,buf);
at88sc_log("R5 ");
at88sc_dump(buf,3);
at88sc_read_config_register(W6_R,buf);
at88sc_log("W6 ");
at88sc_dump(buf,3);
at88sc_read_config_register(R6_R,buf);
at88sc_log("R6 ");
at88sc_dump(buf,3);
at88sc_read_config_register(W7_R,buf);
at88sc_log("W7 ");
at88sc_dump(buf,3);
at88sc_read_config_register(R7_R,buf);
at88sc_log("R7 ");
at88sc_dump(buf,3);
// at88sc_read_config_register(SSG0_R,buf)
// at88sc_log("SSG0 %02X\r\n",buf[0]);
// at88sc_read_config_register(SSG1_R,buf);
// at88sc_log("SSG1 %02X\r\n",buf[0]);
// at88sc_read_config_register(SSG2_R,buf);
// at88sc_log("SSG2 %02X\r\n",buf[0]);
// at88sc_read_config_register(SSG3_R,buf);
// at88sc_log("SSG3 %02X\r\n",buf[0]);
// buf[0]=0xff;
// at88sc_write_config_register(AR0_R,buf);
// at88sc_write_config_register(AR1_R,buf);
// at88sc_write_config_register(AR2_R,buf);
// at88sc_write_config_register(AR3_R,buf);
at88sc_log("printf AT88SC register\r\n");
at88sc_read_config_register(DCR_R,buf);
at88sc_log("DCR_R %02X\r\n",buf[0]);
at88sc_read_config_register(SSG0_R,buf);
at88sc_log("SSG0_R ");
at88sc_dump(buf,8);
at88sc_read_config_register(SSG1_R,buf);
at88sc_log("SSG1_R ");
at88sc_dump(buf,8);
at88sc_read_config_register(SSG2_R,buf);
at88sc_log("SSG2_R ");
at88sc_dump(buf,8);
at88sc_read_config_register(SSG3_R,buf);
at88sc_log("SSG3_R ");
at88sc_dump(buf,8);
at88sc_read_config_register(AR0_R,buf);
at88sc_log("AR0 %02X\r\n",buf[0]);
at88sc_read_config_register(PR0_R,buf);
at88sc_log("PR0 %02X\r\n",buf[0]);
at88sc_read_config_register(AR1_R,buf);
at88sc_log("AR1 %02X\r\n",buf[0]);
at88sc_read_config_register(PR1_R,buf);
at88sc_log("PR1 %02X\r\n",buf[0]);
at88sc_read_config_register(AR2_R,buf);
at88sc_log("AR2 %02X\r\n",buf[0]);
at88sc_read_config_register(PR2_R,buf);
at88sc_log("PR2 %02X\r\n",buf[0]);
at88sc_read_config_register(AR3_R,buf);
at88sc_log("AR3 %02X\r\n",buf[0]);
at88sc_read_config_register(PR3_R,buf);
at88sc_log("PR3 %02X\r\n",buf[0]);
at88sc_read_config_register(PACW0_R,buf);
at88sc_log("PACW0 %02X\r\n",buf[0]);
at88sc_read_config_register(PACW1_R,buf);
at88sc_log("PACW1 %02X\r\n",buf[0]);
at88sc_read_config_register(PACW2_R,buf);
at88sc_log("PACW2 %02X\r\n",buf[0]);
at88sc_read_config_register(PACW3_R,buf);
at88sc_log("PACW3 %02X\r\n",buf[0]);
at88sc_read_config_register(W0_R,buf);
at88sc_log("W0 ");
at88sc_dump(buf,3);
at88sc_read_config_register(W1_R,buf);
at88sc_log("W1 ");
at88sc_dump(buf,3);
at88sc_read_config_register(W2_R,buf);
at88sc_log("W2 ");
at88sc_dump(buf,3);
at88sc_read_config_register(W3_R,buf);
at88sc_log("W3 ");
at88sc_dump(buf,3);
at88sc_read_config_register(W4_R,buf);
at88sc_log("W4 ");
at88sc_dump(buf,3);
at88sc_read_config_register(W5_R,buf);
at88sc_log("W5 ");
at88sc_dump(buf,3);
at88sc_read_config_register(W6_R,buf);
at88sc_log("W6 ");
at88sc_dump(buf,3);
at88sc_read_config_register(W6_R,buf);
at88sc_log("W7 ");
at88sc_dump(buf,3);
buf[0]=0xff;
at88sc_write_config_register(AAC0_R,buf);
at88sc_read_config_register(AAC0_R,buf);
at88sc_log("AAC0 %02X\r\n",buf[0]);
at88sc_read_config_register(AAC1_R,buf);
at88sc_log("AAC1 %02X\r\n",buf[0]);
at88sc_read_config_register(AAC2_R,buf);
at88sc_log("AAC2 %02X\r\n",buf[0]);
at88sc_read_config_register(AAC3_R,buf);
at88sc_log("AAC3 %02X\r\n",buf[0]);
}
if( wr_flag ){
for( uint16_t i=0; i<128; i++ )
buf[i] = i;
at88sc_write_storage(NULL,0, 128, buf);
memset(buf,0,128);
st88sc_sta.curr_use_block = 0xff;
at88sc_read_storage(NULL,0, 128, buf);
at88sc_log("read data ");
at88sc_dump(&buf[0],32);
at88sc_dump(&buf[32],32);
at88sc_dump(&buf[64],32);
at88sc_dump(&buf[96],32);
}
sys_status.have_sc_eeprom = 1;
return FUN_OK;
// while(1);
}