Norimasa Okamoto
/
LPC1114_USBProtocolAnalyzer
control:
interrupt in:
Revision 0:0faa55631ffe, committed 2014-06-18
- Comitter:
- va009039
- Date:
- Wed Jun 18 01:33:32 2014 +0000
- Commit message:
- first commit
Changed in this revision
diff -r 000000000000 -r 0faa55631ffe BaseUsbProtocolAnalyzer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BaseUsbProtocolAnalyzer.cpp Wed Jun 18 01:33:32 2014 +0000 @@ -0,0 +1,222 @@ +#include "mbed.h" +#include "BaseUsbProtocolAnalyzer.h" + + +uint8_t crc5usb(uint16_t data) +{ + uint16_t r = (data&0x7ff) ^ 0x1f; + for(int j = 0; j < 11; j++) { // 11bit + if (r & 1) { + r = (r>>1) ^ 0x14; + } else { + r = r>>1; + } + } + return r ^ 0x1f; +} + +uint16_t crc16usb(const uint8_t data[], int size) +{ + uint16_t r = 0xffff; + for(int i = 0; i < size; i++) { + r ^= data[i]; + for(int j = 0; j < 8; j++) { + if (r & 1) { + r = (r>>1) ^ 0xa001; + } else { + r = (r>>1); + } + } + } + return r ^ 0xffff; +} + + +BaseUsbProtocolAnalyzer::BaseUsbProtocolAnalyzer() +{ + init(); +} + +void BaseUsbProtocolAnalyzer::input(uint8_t data) +{ + char str[32]; + if (data == 0) { // EOP ? + if (seq == SEQ_DATA) { + output("["); + for(int i = 0; i < data_count-2; i++) { + snprintf(str, sizeof(str), "%s0x%02x", i == 0 ? "" : " ", packet.data[i]); + output(str); + } + output("]"); + if (data_count >= 2) { + uint16_t crc16 = packet.data[data_count-2]|(packet.data[data_count-1]<<8); + bool crc16_err = (crc16usb(packet.data, data_count-2) == crc16); + snprintf(str, sizeof(str), "[crc16=0x%04x%s]", crc16, crc16_err ? "" : " ERROR"); + output(str); + } + } + output("[EOP]"); + init(); + return; + } + + if (seq == SEQ_SYNC) { + if (disp_cycle) { + snprintf(str, sizeof(str), "(0x%02x)", data); + output(str); + } + output("[SYNC]"); + packet.pid = (pid_t)data; + switch(packet.pid) { + case ACK: + output("[ACK]"); + break; + case NAK: + output("[NAK]"); + break; + case STALL: + output("[STALL]"); + break; + case IN: + output("[IN]"); + bit_count = 7; + break; + case OUT: + output("[OUT]"); + bit_count = 4; + break; + case SETUP: + output("[SETUP]"); + bit_count = 7; + break; + case DATA0: + output("[DATA0]"); + bit_count = 5; + break; + case DATA1: + output("[DATA1]"); + bit_count = 7; + break; + default: + snprintf(str, sizeof(str), "[pid=0x%02x]", packet.pid); + output(str); + break; + } + seq = SEQ_PID; + return; + } + if (disp_cycle) { + snprintf(str, sizeof(str), "(%d)", data); + output(str); + } + int n = (data + CYCLE/2) / CYCLE - 1; + uint8_t pat = 0; + int len = 0; + if (bit_stuffing) { + const uint8_t table[] = {0x00,0x01,0x03,0x07,0x0f,0x1f,0x3f,0x7f,0xff}; + pat = table[n]; + len = n; + } else { + const uint8_t table[] = {0x00,0x02,0x06,0x0e,0x1e,0x3e,0x7e,0xfe}; + pat = table[n]; + len = n + 1; + } + bit_stuffing = false; + if (n >= 6) { + bit_stuffing = true; + } + inputBit(pat, len); +} + +void BaseUsbProtocolAnalyzer::inputBit(uint8_t pat, int len) +{ + if (disp_bit) { + output('{'); + for(int i = 0; i < len; i++) { + output(((pat>>i) & 1) ? '1' : '0'); + } + output('}'); + } + for(int i = 0; i < len; i++) { + inputLSB((pat>>i) & 1); + } +} + +void BaseUsbProtocolAnalyzer::inputLSB(int lsb) +{ + char str[32]; + seq_t prev_seq = seq; + switch(seq) { + case SEQ_PID: + if (++bit_count >= 8) { + if (packet.pid == IN || packet.pid == OUT || packet.pid == SETUP) { + seq = SEQ_ADDR; + } else if (packet.pid == DATA0 || packet.pid == DATA1) { + seq = SEQ_DATA; + } + } + break; + case SEQ_ADDR: + packet.addr >>= 1; + packet.addr |= lsb ? 0x40 : 0x00; + if (++bit_count >= 7) { + snprintf(str, sizeof(str), "[ADDR=%d]", packet.addr & 0x7f); + output(str); + seq = SEQ_ENDP; + } + break; + case SEQ_ENDP: + packet.endp >>= 1; + packet.endp |= lsb ? 0x08 : 0x00; + if (++bit_count >= 4) { + snprintf(str, sizeof(str), "[ENDP=%d]", packet.endp & 0x0f); + output(str); + seq = SEQ_CRC5; + } + break; + case SEQ_CRC5: + if (bit_count < 5) { + packet.crc5 >>= 1; + packet.crc5 |= lsb ? 0x10 : 0x00; + if (++bit_count >= 5) { + uint16_t u = packet.crc5<<11|packet.endp<<7|packet.addr; + bool crc5_err = (crc5usb(u) == packet.crc5); + snprintf(str, sizeof(str), "[CRC5=0x%02x%s]", + packet.crc5, crc5_err ? "" : " ERROR"); + output(str); + } + } + break; + case SEQ_DATA: + if (data_count < sizeof(packet.data)) { + packet.data[data_count] >>= 1; + packet.data[data_count] |= lsb ? 0x80 : 0x00; + if (++bit_count >= 8) { + bit_count = 0; + data_count++; + } + } + break; + } + if (prev_seq != seq) { + bit_count = 0; + data_count = 0; + } +} + +void BaseUsbProtocolAnalyzer::init() +{ + seq = SEQ_SYNC; + bit_stuffing = false; + bit_count = 0; + disp_bit = false; + disp_cycle = false; +} + +void BaseUsbProtocolAnalyzer::output(const char* s) +{ + while(*s) { + output(*s++); + } +} +
diff -r 000000000000 -r 0faa55631ffe BaseUsbProtocolAnalyzer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BaseUsbProtocolAnalyzer.h Wed Jun 18 01:33:32 2014 +0000 @@ -0,0 +1,50 @@ +#pragma once + +typedef enum { + ACK = 0x02, + NAK = 0x0a, + STALL = 0x0e, + DATA0 = 0x03, + DATA1 = 0x0b, + IN = 0x09, + OUT = 0x01, + SETUP = 0x0d, +} pid_t; + +typedef enum { + SEQ_SYNC, + SEQ_PID, + SEQ_ADDR, + SEQ_ENDP, + SEQ_CRC5, + SEQ_DATA, + SEQ_CRC16, +} seq_t; + +class BaseUsbProtocolAnalyzer { +public: + BaseUsbProtocolAnalyzer(); + void init(); + void input(uint8_t data); + bool disp_bit; + bool disp_cycle; +protected: + virtual void output(char c) = 0; + +private: + static const int CYCLE = 32; + void inputBit(uint8_t pat, int len); + void inputLSB(int lsb); + void output(const char* s); + bool bit_stuffing; + seq_t seq; + struct { + pid_t pid; + uint8_t addr; + uint8_t endp; + uint8_t crc5; + uint8_t data[8+2]; // data and crc16 + } packet; + int bit_count; + int data_count; +};
diff -r 000000000000 -r 0faa55631ffe UsbCapture.s --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/UsbCapture.s Wed Jun 18 01:33:32 2014 +0000 @@ -0,0 +1,250 @@ +; UsbCapture.s 2014/5/21 +; + AREA USBCAPTURE,CODE,READONLY + + +; uint8_t* usbcapture_lpc1114(uint8_t* buf, uint8_t* end) +; +;[ADDR][OUT ][SYNC] |1110}{0}{0}{0}{1|10}{0}{0}{0}{0}{0}{0} +;[ADDR][IN ][SYNC] |0}{110}{10}{0}{1|10}{0}{0}{0}{0}{0}{0} +;[ADDR][SETUP][SYNC] |0}{0}{10}{110}{1|10}{0}{0}{0}{0}{0}{0} +; +;[data][DATA0][SYNC] |110}{0}{0}{0}{11|10}{0}{0}{0}{0}{0}{0} +;[data][DATA1][SYNC] |0}{10}{0}{10}{11|10}{0}{0}{0}{0}{0}{0} +; +;[EOP ][ACK ][SYNC] |110}{10}{0}{10}|{10}{0}{0}{0}{0}{0}{0} +;[EOP ][NAK ][SYNC] |0}{10}{110}{10}|{10}{0}{0}{0}{0}{0}{0} +;[EOP ][STALL][SYNC] |0}{0}{0}{11110}|{10}{0}{0}{0}{0}{0}{0} +; +;{0} : 32 cycle +;{10} : 64 cycle +;{110} : 96 cycle +;{1110} : 128 cycle +;{11110} : 160 cycle +;{111110} : 192 cycle +;{1111110} : 224 cycle +; + + EXPORT usbcapture_lpc1114 + +CYCLE equ 32 +GPIO1 equ 0x50010c00 +CT16B1 equ 0x40010000 +_IR equ 0x00 +_TC equ 0x08 +_CR0 equ 0x2c +CR0Int equ (1<<4) + +; PID +ACK equ 0x02 +NAK equ 0x0a +STALL equ 0x0e +DATA0 equ 0x03 +DATA1 equ 0x0b +IN equ 0x09 +OUT equ 0x01 +SETUP equ 0x0d + + MACRO + init_param + LDR r4, =GPIO1 ; USB_DM(P1_9),USB_DP(P1_8) + LDR r5, =CT16B1 ; CT16B1 + MOVS r6, #CR0Int ; CR0 interrupt mask + MOVS r3, #1 ; prev_CR0 + MEND + + MACRO + save_raw + STRB r2,[r0] + ADDS r0, r0, #1 + MEND + + MACRO + read +1 LDR r2, [r5,#_IR] + TST r2, r6 + BEQ %b1 + LDR r2, [r5,#_CR0] + STR r6, [r5,#_IR] + SUBS r2, r2, r3 + ADDS r3, r3, r2 + UXTB r2, r2 + MEND + + MACRO + readNB $skip + LDR r2, [r5,#_IR] + TST r2, r6 + BEQ $skip + LDR r2, [r5,#_CR0] + STR r6, [r5,#_IR] + SUBS r2, r2, r3 + ADDS r3, r3, r2 + UXTB r2, r2 + MEND + + MACRO + read_TC + LDR r2, [r5,#_TC] + SUBS r2, r2, r3 + ADDS r3, r3, r2 + UXTB r2, r2 + MEND + + MACRO + if_1bit_gt $goto + CMP r2, #CYCLE+CYCLE/2 + BGT $goto + MEND + + MACRO + if_1bit_le $goto + CMP r2, #CYCLE+CYCLE/2 + BLE $goto + MEND + + MACRO + if_2bit_le $goto + CMP r2, #CYCLE*2+CYCLE/2 + BLE $goto + MEND + + MACRO + if_3bit_le $goto + CMP r2, #CYCLE*3+CYCLE/2 + BLE $goto + MEND + + MACRO + eopNB $skip + LDR r2, [r4] ; EOP(USB_DM=0,USB_DP=0) ? + TST r2, r2 + BNE $skip ; no + MEND + +usbcapture_lpc1114 +CAPTURE PUSH {r4-r7} + init_param + +SYNC + read + if_1bit_gt SYNC + read + if_1bit_gt SYNC + read + if_1bit_gt SYNC +SYNC_67bit + read + if_1bit_le SYNC_67bit + if_2bit_le PID_ACK_NAK_STALL + if_3bit_le PID_IN_OUT_SETUP + +PID_DATA0_DATA1 + read + if_1bit_le PID_DATA0 + +PID_DATA1 + read + read + MOVS r2, #DATA1 + save_raw + B DATA_CRC16 + +PID_DATA0 + read + read + MOVS r2, #DATA0 + save_raw + B DATA_CRC16 + +PID_ACK_NAK_STALL + read + if_2bit_le PID_ACK_NAK + +PID_STALL + read + read + MOVS r2, #STALL + save_raw + B EOP_WAIT + +PID_ACK_NAK + read + if_1bit_le PID_ACK + +PID_NAK + read ; 10b + read ; 0b + MOVS r2, #NAK + save_raw + B EOP_WAIT + +PID_ACK + read + MOVS r2, #ACK + save_raw + B EOP_WAIT + +PID_IN_OUT_SETUP + read + if_1bit_le PID_IN_OUT + +PID_SETUP + read + read + MOVS r2, #SETUP + save_raw + B ADDR_ENDP_CRC5 + +PID_IN_OUT + read + if_1bit_le PID_OUT + +PID_IN + read + MOVS r2, #IN + save_raw + +DATA_CRC16 +ADDR_ENDP_CRC5 +20 + readNB %f30 + save_raw + CMP r0, r1 + BGE %f90 ; buffer full ? + B %b20 +30 + eopNB %b20 + STRB r2, [r0,#1] + read_TC + STRB r2, [r0,#0] + ADDS r0, r0, #2 + B EOP + +PID_OUT + read + MOVS r2, #OUT + save_raw + B ADDR_ENDP_CRC5 + +EOP_WAIT +10 + eopNB %b10 + save_raw + CMP r0, r1 + BGE EXIT + B SYNC +EOP + CMP r0, r1 + BGE EXIT ; buffer full ? + B SYNC +EXIT +90 POP {r4-r7} + BX lr ; return, buf = r0 + +ERROR POP {r4-r7} + BX lr + + ALIGN + END +
diff -r 000000000000 -r 0faa55631ffe main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Wed Jun 18 01:33:32 2014 +0000 @@ -0,0 +1,66 @@ +#include "mbed.h" +#include "BaseUsbProtocolAnalyzer.h" +// +// USB LPC1114FN28 +// 1 VCC +// 2 DATA- dp18(P1_9) +// 3 DATA+ dp17(P1_8) +// 4 GND GND + +DigitalOut led1(LED1),led2(LED2); +DigitalIn usb_dm(P1_9); +DigitalIn usb_dp(P1_8); +RawSerial pc(USBTX, USBRX); + +const int BUF_SIZE = 512; +uint8_t buf[BUF_SIZE+256]; + +class USB_Protocol_Analyzer : public BaseUsbProtocolAnalyzer { + virtual void output(char c) { + pc.putc(c); + } +}; + +USB_Protocol_Analyzer analyzer; + +extern "C" { + uint8_t* usbcapture_lpc1114(uint8_t* buf, uint8_t* end); +} + +void usbcapture_setup() +{ + usb_dm.mode(PullNone); + usb_dp.mode(PullNone); + + LPC_SYSCON->SYSAHBCLKCTRL |= 1<<8; // CT16B1 + LPC_IOCON->PIO1_8 = (LPC_IOCON->PIO1_8 & ~0x7) | 0x1; // FUNC=CT16B1_CAP0 + LPC_TMR16B1->TCR |= 1; // Counter Enable + LPC_TMR16B1->CCR |= 7; // CAP0RE,CAP0FE,CAP0I +} + +int main() { + pc.baud(115200); + pc.puts(__FILE__); + pc.puts("\n"); + + usbcapture_setup(); + + for(int n = 0; ; n++) { + uint8_t* end = usbcapture_lpc1114(buf, buf+BUF_SIZE); + analyzer.init(); + for(uint8_t* p = buf; p < end; p++) { + analyzer.input(*p); + if (*p == 0) { + pc.puts("\n"); + } + } + pc.puts("\n\n"); + Timer t; + t.reset(); + t.start(); + while(t.read_ms() < 1000*3 + n%100) { + } + led1 = !led1; + } +} +
diff -r 000000000000 -r 0faa55631ffe mbed.bld --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Wed Jun 18 01:33:32 2014 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/024bf7f99721 \ No newline at end of file