ATtinyのUSIを使ってSWD(Serial Wire Debug)に応用できないか検討してみます。FTDIでやってみたのでそれを移植しつつ、ACK待ち時間が短縮できるんじゃないかなっていう希望もある。
いきなりだけど、こんな感じで。データ順序とかパリティとかこねくり回すのにめっちゃ長いコードになってしまった。神が降りてきてもっと効率の良いコードが書けるといいのですが、、、
#include <avr/iotnx4.h> typedef union { uint32_t asU32; uint8_t asU8[4]; } u32u8_t; /*SWD command definition*/ #define APnDP_DP (0) #define APnDP_AP (1) #define RnW_W (0) #define RnW_R (1) #define ACK_OK (0x80) #define ACK_WAIT (0x40) #define ACK_FAULT (0x20) #define ACK_DISCONNECT_H (0xE0) #define ACK_DISCONNECT_L (0x00) #define ACK_MASK (0xE0) #define ACK_READ_PARITY_MASK (0x10) #define ACK_READ_PARITY_OK (0x00) #define ACK_READ_PARITY_ERR (0x10) #define ACK_ACCAP_ACKINFO_MASK (0x0C) #define ACK_ACCAP_ACKINFO_OK (0x00) #define ACK_ACCAP_ACKINFO_FAIL1 (0x04) #define ACK_ACCAP_ACKINFO_FAIL2 (0x08) #define ACK_ACCAP_ACKINFO_FAIL3 (0x0C) #define PIN_SWDI (0x40) #define PIN_SWDO (0x20) #define PIN_SWCLK (0x10) #define PIN_NRST (0x08) volatile uint8_t txCompleted; volatile uint8_t rxUSIDR; uint8_t txBuf[32]; uint8_t rxBuf[32]; ISR(TIM1_COMPA_vect){ USICR|=0x01;/*Toggle Clock Port Pin*/ } ISR(USI_OVF_vect){ TIMSK1&=~(0x02);/*clear Timer/Counter1 Output Compare A Match Interrupt Enable*/ TCCR1B&=~(0x01); USISR=0x40;/*Write 1 to clear Counter Overflow Interrupt Flag*/ txCompleted=1; rxUSIDR=USIDR; } uint8_t USISR_val[]={0xEE,0xEC,0xEA,0xE8,0xE6,0xE4,0xE2,0xE0}; void Send_or_Receive_Data(uint8_t tx_or_rx,uint8_t dataLength_in_bit,uint8_t NRST_const){ uint8_t data_num_remain,byte_pos,data_num_tx; if(txCompleted==1){ if(NRST_const){ PORTA|=PIN_NRST; }else{ PORTA&=~PIN_NRST; } data_num_remain=dataLength_in_bit; byte_pos=0; while(data_num_remain>0){ data_num_tx=data_num_remain; if(data_num_remain>8){ data_num_tx=8; } data_num_remain=data_num_remain-data_num_tx; if(tx_or_rx){ USICR=0x5E; rxBuf[byte_pos]=0x00; }else{ USICR=0x5A; } USIDR = txBuf[byte_pos]; USISR=USISR_val[data_num_tx-1]; txCompleted=0; TIFR1|=0x02; TCCR1B|=0x01; TIMSK1=0x02; while(txCompleted==0){ // } rxBuf[byte_pos]=rxUSIDR<<(8-data_num_tx); byte_pos=byte_pos+1; } }else{ rxBuf[0]=0x00; } } uint8_t flip_8bit(uint8_t src,uint8_t num_bit){ uint8_t ret=0x00; if(src&0x80){ret|=0x01;} if(src&0x40){ret|=0x02;} if(src&0x20){ret|=0x04;} if(src&0x10){ret|=0x08;} if(src&0x08){ret|=0x10;} if(src&0x04){ret|=0x20;} if(src&0x02){ret|=0x40;} if(src&0x01){ret|=0x80;} return ret<<(8-num_bit); } void JTAG_to_SWD(uint8_t NRST_const){ int i,j; for(i=0,j=0;j<7;i++,j++){ txBuf[i]=0x00; } for(j=0;j<7;i++,j++){ txBuf[i]=0xFF; } txBuf[i+1]=flip_8bit(0xE7,8); txBuf[i]=flip_8bit(0x9E,8); i=i+2; for(j=0;j<7;i++,j++){ txBuf[i]=0xFF; } txBuf[i-1]=0xF0; Send_or_Receive_Data(0,i*8,NRST_const); } void SWD_SYNC(uint8_t NRST_const){ txBuf[0]=0xF0; Send_or_Receive_Data(0,8,NRST_const); } int CheckParity32(uint8_t* data){ uint32_t ret=-1; uint32_t i,j; uint8_t par=0; for(i=0;i<4;i++){ for(j=0;j<8;j++){ if((data[i]<>1)&0x18); txBuf[0]|=((parity&0x01)<<2); Send_or_Receive_Data(0,9,nres_const); Send_or_Receive_Data(1,3,nres_const); ack=(rxBuf[0]&ACK_MASK); if(ack==ACK_OK){ Send_or_Receive_Data(1,34,nres_const); if(CheckParity32(rxBuf)==0){ u32u8_rxData.asU8[0]=flip_8bit(rxBuf[0],8); u32u8_rxData.asU8[1]=flip_8bit(rxBuf[1],8); u32u8_rxData.asU8[2]=flip_8bit(rxBuf[2],8); u32u8_rxData.asU8[3]=flip_8bit(rxBuf[3],8); *rxData32=u32u8_rxData.asU32; }else{ ack|=ACK_READ_PARITY_ERR; } } return ack; } uint8_t SWD_Read32_w_ACK_check(uint8_t APnDP,uint8_t ADDR,uint8_t nres_const,uint32_t* rxData32){ uint8_t ack=0; uint8_t cntr=0; while((ack!=ACK_OK)&&(cntr<3)){ ack=SWD_Read32(APnDP,ADDR,nres_const,rxData32); if(ack!=ACK_OK){ SWD_SYNC(nres_const); } cntr=cntr+1; } return ack; } uint8_t READ_DP(uint8_t ADDR,uint8_t nres_const,uint32_t* rxData32){ return SWD_Read32_w_ACK_check(APnDP_DP,ADDR,nres_const,rxData32); } void setup(void){ DDRA|=(PIN_SWDO|PIN_SWCLK|PIN_NRST); DDRA&=~(PIN_SWDI); PORTA|=(PIN_SWDI|PIN_SWCLK|PIN_NRST); TCCR1A=0x00; OCR1A=0x0040; TCCR1B=0x08; txCompleted=1; } void loop(void){ uint32_t rxData32; uint8_t ack; char buf[80]; u32u8_t u32u8_data; JTAG_to_SWD(1); ack= READ_DP(0x0,1,&rxData32); ack= READ_DP(0x4,1,&rxData32); delay(200); }
SeeeduinoXIAOで試した結果。
SeeeduinoXIAOはATSAMD21G18Aなので以前調べたArduinoM0と同じく0x0BC11477となったので、うまくいっているんだろう。BitBangみたいにACK受信で長時間待つことはなくなった。このあと、AP-IDR受信まで進めようとしたんだけど、なんかうまくいかん、クソッ。何か、、、しばらくしたら詳しく調べるかもしれないし、しないかもしれない。あと、LSB FirstかMSB Firstかうまい方法でデータをflipできんもんかね、、、
まぁすんなりいかないことが生きてるってことなんだろう。まぁしょーじきしんどい。
コメントをお書きください