diff options
Diffstat (limited to 'core/usb')
-rw-r--r-- | core/usb/usb.c | 36 | ||||
-rw-r--r-- | core/usb/usb.h | 1 | ||||
-rw-r--r-- | core/usb/usb_callbacks.c | 10 | ||||
-rw-r--r-- | core/usb/usb_callbacks.h | 4 | ||||
-rw-r--r-- | core/usb/usb_hardware.h | 4 |
5 files changed, 53 insertions, 2 deletions
diff --git a/core/usb/usb.c b/core/usb/usb.c index a8298c0..bbea77d 100644 --- a/core/usb/usb.c +++ b/core/usb/usb.c @@ -332,6 +332,42 @@ if (wIstr & ISTR_CTR & wInterrupt_Mask) CTR_LP(); /* low priority ISR defined in the usb core lib */ } #endif + +/* if we are about to reset from the DTR signal, then dont return + to user, instead return from the ISR into a wait slide */ + if (reset_state == RESET_NOW) { + reset_state = START; + unsigned int target = (unsigned int)usbWaitReset | 0x1; + + 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. + } +} + +void usbWaitReset(void) { + static count=1000000; + while (count-- >0); + systemHardReset(); } /* copies data out of sendBuf into the packet memory for diff --git a/core/usb/usb.h b/core/usb/usb.h index c6377ab..e76772e 100644 --- a/core/usb/usb.h +++ b/core/usb/usb.h @@ -48,6 +48,7 @@ typedef enum /* overloaded ISR routine, this is the main usb ISR */ void usb_lpIRQHandler(void); + void usbWaitReset(void); /* blocking functions for send/receive */ int16 usbSendBytes(uint8* sendBuf,uint16 len); diff --git a/core/usb/usb_callbacks.c b/core/usb/usb_callbacks.c index f4c491b..08d62c5 100644 --- a/core/usb/usb_callbacks.c +++ b/core/usb/usb_callbacks.c @@ -232,11 +232,19 @@ RESULT usbNoDataSetup(u8 request) { case DTR_NRTS: if (new_signal == 0) { - systemHardReset(); + /* 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; + break; + case RESET_NOW: + /* do nothing, wait for reset */ + break; } return USB_SUCCESS; } diff --git a/core/usb/usb_callbacks.h b/core/usb/usb_callbacks.h index b95ea15..f8a2ef3 100644 --- a/core/usb/usb_callbacks.h +++ b/core/usb/usb_callbacks.h @@ -28,7 +28,9 @@ typedef struct { typedef enum { START, NDTR_NRTS, - DTR_NRTS + DTR_NRTS, + RESET_NEXT, + RESET_NOW } RESET_STATE; extern RESET_STATE reset_state; /* tracks DTR/RTS */ diff --git a/core/usb/usb_hardware.h b/core/usb/usb_hardware.h index 8258da9..208fa3a 100644 --- a/core/usb/usb_hardware.h +++ b/core/usb/usb_hardware.h @@ -28,6 +28,10 @@ #include "usb_type.h" /* macro'd register and peripheral definitions */ +#define EXC_RETURN 0xFFFFFFF9 +#define DEFAULT_CPSR 0x61000000 +#define STACK_TOP 0x20005000 + #define RCC ((u32)0x40021000) #define FLASH ((u32)0x40022000) #define GPIOA ((u32)0x40010800) |