aboutsummaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorAJM <poslathian@poslathian.(none)>2010-04-25 17:42:34 -0400
committerbnewbold <bnewbold@robocracy.org>2010-05-20 22:09:16 -0400
commitba9ff3861bbcc17c78086b1887691c324f13ba0e (patch)
tree15e3203954cc568065b219a576a344ebbeaeefdd /core
parentfc4b9b386a80d06c73e03d70767643aae3961e2a (diff)
downloadlibrambutan-ba9ff3861bbcc17c78086b1887691c324f13ba0e.tar.gz
librambutan-ba9ff3861bbcc17c78086b1887691c324f13ba0e.zip
added a delay to the resrt slide to allow enough time for graceul closures of the serial port
Diffstat (limited to 'core')
-rw-r--r--core/usb/usb.c36
-rw-r--r--core/usb/usb.h1
-rw-r--r--core/usb/usb_callbacks.c10
-rw-r--r--core/usb/usb_callbacks.h4
-rw-r--r--core/usb/usb_hardware.h4
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)