diff options
-rw-r--r-- | libmaple/usb/usb.c | 5 | ||||
-rw-r--r-- | libmaple/usb/usb_callbacks.c | 148 | ||||
-rw-r--r-- | libmaple/usb/usb_callbacks.h | 11 | ||||
-rw-r--r-- | libmaple/usb/usb_config.h | 1 | ||||
-rwxr-xr-x | support/scripts/reset.py | 7 |
5 files changed, 90 insertions, 82 deletions
diff --git a/libmaple/usb/usb.c b/libmaple/usb/usb.c index 09b51ea..9755618 100644 --- a/libmaple/usb/usb.c +++ b/libmaple/usb/usb.c @@ -335,8 +335,7 @@ if (wIstr & ISTR_CTR & wInterrupt_Mask) } void usbWaitReset(void) { - int count = program_delay*100000000; - delay(program_delay*10); + delay(RESET_DELAY); systemHardReset(); } @@ -350,7 +349,7 @@ void usbWaitReset(void) { */ int16 usbSendBytes(uint8* sendBuf, uint16 len) { - if (reset_state != START || bDeviceState != CONFIGURED) { + if (((line_dtr_rts & 0x02) != 0) || bDeviceState != CONFIGURED) { return -1; /* indicates to caller to stop trying, were not connected */ } diff --git a/libmaple/usb/usb_callbacks.c b/libmaple/usb/usb_callbacks.c index cacfd02..4cdaf73 100644 --- a/libmaple/usb/usb_callbacks.c +++ b/libmaple/usb/usb_callbacks.c @@ -38,8 +38,8 @@ volatile uint8 recvBufIn = 0; volatile uint8 recvBufOut = 0; volatile uint8 maxNewBytes = VCOM_RX_EPSIZE; -RESET_STATE reset_state = START; -uint8 program_delay = 1; +RESET_STATE reset_state = DTR_UNSET; +uint8 line_dtr_rts = 0; void vcomDataTxCb(void) { /* do whatever after data has been sent to host */ @@ -63,44 +63,55 @@ void vcomDataRxCb(void) { uint8 newBytes = GetEPRxCount(VCOM_RX_ENDP); /* assert (newBytes <= maxNewBytes); */ + /* todo, not checking very carefully for edge cases. USUALLY, + if we emit the reset pulse and send 4 bytes, then newBytes + should be 4. But its POSSIBLE that this would be violated + in some cases */ - if (reset_state == RESET_NOW) { - /* todo, check for magic bytes */ - /* for now just grab the new byte as the delay argument */ - /* if theres anything in the recv buffer clear it, - then wait for the command byte and the delay argument. - if we dont get it, then just reset. todo, if we dont - get it, then revert back to user code */ - - - reset_state = START; - unsigned int target = (unsigned int)usbWaitReset | 0x1; - - PMAToUserBufferCopy(&program_delay,VCOM_RX_ADDR,1); - - asm volatile("mov r0, %[stack_top] \n\t" // Reset the stack - "mov sp, r0 \n\t" - "mov r0, #1 \n\t" - "mov r1, %[target_addr] \n\t" - "mov r2, %[cpsr] \n\t" - "push {r2} \n\t" // Fake xPSR - "push {r1} \n\t" // Target address for PC - "push {r0} \n\t" // Fake LR - "push {r0} \n\t" // Fake R12 - "push {r0} \n\t" // Fake R3 - "push {r0} \n\t" // Fake R2 - "push {r0} \n\t" // Fake R1 - "push {r0} \n\t" // Fake R0 - "mov lr, %[exc_return] \n\t" - "bx lr" - : - : [stack_top] "r" (STACK_TOP), - [target_addr] "r" (target), - [exc_return] "r" (EXC_RETURN), - [cpsr] "r" (DEFAULT_CPSR) - : "r0", "r1", "r2"); - // Should never get here. + /* magic number, {0x31, 0x45, 0x41, 0x46} is "1EAF" */ + char chkBuf[4]; + char cmpBuf[4] = {0x31, 0x45, 0x41, 0x46}; + if (reset_state == DTR_NEGEDGE) { + reset_state = DTR_LOW; + if (newBytes >= 4) { + unsigned int target = (unsigned int)usbWaitReset | 0x1; + + PMAToUserBufferCopy(chkBuf,VCOM_RX_ADDR,4); + + int i; + USB_Bool cmpMatch = TRUE; + for (i=0; i<4; i++) { + if (chkBuf[i] != cmpBuf[i]) { + cmpMatch = FALSE; + } + } + + if (cmpMatch) { + asm volatile("mov r0, %[stack_top] \n\t" // Reset the stack + "mov sp, r0 \n\t" + "mov r0, #1 \n\t" + "mov r1, %[target_addr] \n\t" + "mov r2, %[cpsr] \n\t" + "push {r2} \n\t" // Fake xPSR + "push {r1} \n\t" // Target address for PC + "push {r0} \n\t" // Fake LR + "push {r0} \n\t" // Fake R12 + "push {r0} \n\t" // Fake R3 + "push {r0} \n\t" // Fake R2 + "push {r0} \n\t" // Fake R1 + "push {r0} \n\t" // Fake R0 + "mov lr, %[exc_return] \n\t" + "bx lr" + : + : [stack_top] "r" (STACK_TOP), + [target_addr] "r" (target), + [exc_return] "r" (EXC_RETURN), + [cpsr] "r" (DEFAULT_CPSR) + : "r0", "r1", "r2"); + /* should never get here */ + } + } } @@ -256,40 +267,43 @@ RESULT usbNoDataSetup(u8 request) { /* to reset the board, pull both dtr and rts low then pulse dtr by itself */ new_signal = pInformation->USBwValues.bw.bb0 & (CONTROL_LINE_DTR | CONTROL_LINE_RTS); + line_dtr_rts = new_signal & 0x03; + switch (reset_state) { /* no default, covered enum */ - case START: - if (new_signal == 0) { - reset_state = NDTR_NRTS; - } - break; - - case NDTR_NRTS: - if (new_signal == CONTROL_LINE_DTR) { - reset_state = DTR_NRTS; - } else if (new_signal == 0) { - reset_state = NDTR_NRTS; - } else { - reset_state = START; - } - break; - - case DTR_NRTS: - if (new_signal == 0) { - /* dont reset here, otherwise - well likely crash the host! */ - reset_state = RESET_NOW; - } else { - reset_state = START; - } - break; - case RESET_NEXT: - reset_state = RESET_NOW; + case DTR_UNSET: + if ((new_signal & CONTROL_LINE_DTR) == 0 ) { + reset_state = DTR_LOW; + } else { + reset_state = DTR_HIGH; + } break; - case RESET_NOW: - /* do nothing, wait for reset */ + + case DTR_HIGH: + if ((new_signal & CONTROL_LINE_DTR) == 0 ) { + reset_state = DTR_NEGEDGE; + } else { + reset_state = DTR_HIGH; + } + break; + + case DTR_NEGEDGE: + if ((new_signal & CONTROL_LINE_DTR) == 0 ) { + reset_state = DTR_LOW; + } else { + reset_state = DTR_HIGH; + } + break; + + case DTR_LOW: + if ((new_signal & CONTROL_LINE_DTR) == 0 ) { + reset_state = DTR_LOW; + } else { + reset_state = DTR_HIGH; + } break; } + return USB_SUCCESS; } } diff --git a/libmaple/usb/usb_callbacks.h b/libmaple/usb/usb_callbacks.h index d77a9fd..a94de11 100644 --- a/libmaple/usb/usb_callbacks.h +++ b/libmaple/usb/usb_callbacks.h @@ -26,15 +26,14 @@ typedef struct { } USB_Line_Coding; typedef enum { - START, - NDTR_NRTS, - DTR_NRTS, - RESET_NEXT, - RESET_NOW + DTR_UNSET, + DTR_HIGH, + DTR_NEGEDGE, + DTR_LOW } RESET_STATE; extern RESET_STATE reset_state; /* tracks DTR/RTS */ -extern uint8 program_delay; +extern uint8 line_dtr_rts; extern volatile uint8 countTx; extern uint8 vcomBufferRx[VCOM_RX_EPSIZE]; /* no reason this has to be VCOM_RX_EPSIZE, could be bigger */ extern volatile uint8 recvBufIn; /* the FIFO in index to the recvbuffer */ diff --git a/libmaple/usb/usb_config.h b/libmaple/usb/usb_config.h index e1eabb3..06c81ff 100644 --- a/libmaple/usb/usb_config.h +++ b/libmaple/usb/usb_config.h @@ -9,6 +9,7 @@ #define VCOM_ID_PRODUCT 0x0004 #define USB_CONFIG_MAX_POWER (100 >> 1) +#define RESET_DELAY (100) /* choose addresses to give endpoints the max 64 byte buffers */ #define USB_BTABLE_ADDRESS 0x00 diff --git a/support/scripts/reset.py b/support/scripts/reset.py index 7594845..90ff331 100755 --- a/support/scripts/reset.py +++ b/support/scripts/reset.py @@ -7,16 +7,11 @@ try: ser = serial.Serial('/dev/ttyACM0', baudrate=115200) ser.open() - # pull dtr and rts low - ser.setRTS(0) - ser.setDTR(0) - # toggle DTR ser.setDTR(1) ser.setDTR(0) - programDelay = pack("b",35) - ser.write(programDelay) + ser.write("1EAF") # close ser.close() |