summaryrefslogtreecommitdiffstatshomepage
path: root/stm
diff options
context:
space:
mode:
Diffstat (limited to 'stm')
-rw-r--r--stm/Makefile1
-rw-r--r--stm/led.c1
-rw-r--r--stm/main.c17
-rw-r--r--stm/pendsv.c49
-rw-r--r--stm/pendsv.h3
-rw-r--r--stm/stm32fxxx_it.c2
-rw-r--r--stm/stmusbd/usbd_cdc_vcp.c7
-rw-r--r--stm/usb.c26
-rw-r--r--stm/usb.h5
9 files changed, 105 insertions, 6 deletions
diff --git a/stm/Makefile b/stm/Makefile
index 1958252381..003bf32e79 100644
--- a/stm/Makefile
+++ b/stm/Makefile
@@ -45,6 +45,7 @@ SRC_C = \
string0.c \
malloc0.c \
systick.c \
+ pendsv.c \
gccollect.c \
lexerfatfs.c \
led.c \
diff --git a/stm/led.c b/stm/led.c
index 96fac58e2e..c517c3f6e8 100644
--- a/stm/led.c
+++ b/stm/led.c
@@ -103,6 +103,7 @@ void led_toggle(pyb_led_t led) {
return;
}
+ // XXX this assumes LED is driven by a low MCU output (true for PYBv3, false for PYBv4)
if (!(port->ODR & pin)) {
// turn LED off
PYB_LED_OFF(port, pin);
diff --git a/stm/main.c b/stm/main.c
index 313a868c41..b7d201cf02 100644
--- a/stm/main.c
+++ b/stm/main.c
@@ -30,6 +30,7 @@
#include "gc.h"
#include "gccollect.h"
#include "systick.h"
+#include "pendsv.h"
#include "led.h"
#include "servo.h"
#include "lcd.h"
@@ -327,7 +328,7 @@ int readline(vstr_t *line, const char *prompt) {
}
}
if (escape == 0) {
- if (c == 4 && vstr_len(line) == len) {
+ if (c == VCP_CHAR_CTRL_D && vstr_len(line) == len) {
return 0;
} else if (c == '\r') {
stdout_tx_str("\r\n");
@@ -435,10 +436,14 @@ void do_repl(void) {
nlr_buf_t nlr;
uint32_t start = sys_tick_counter;
if (nlr_push(&nlr) == 0) {
+ usb_vcp_set_interrupt_char(VCP_CHAR_CTRL_C); // allow ctrl-C to interrupt us
rt_call_function_0(module_fun);
+ usb_vcp_set_interrupt_char(VCP_CHAR_NONE); // disable interrupt
nlr_pop();
} else {
// uncaught exception
+ // FIXME it could be that an interrupt happens just before we disable it here
+ usb_vcp_set_interrupt_char(VCP_CHAR_NONE); // disable interrupt
mp_obj_print_exception((mp_obj_t)nlr.ret_val);
}
@@ -488,11 +493,15 @@ bool do_file(const char *filename) {
nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) {
+ usb_vcp_set_interrupt_char(VCP_CHAR_CTRL_C); // allow ctrl-C to interrupt us
rt_call_function_0(module_fun);
+ usb_vcp_set_interrupt_char(VCP_CHAR_NONE); // disable interrupt
nlr_pop();
return true;
} else {
// uncaught exception
+ // FIXME it could be that an interrupt happens just before we disable it here
+ usb_vcp_set_interrupt_char(VCP_CHAR_NONE); // disable interrupt
mp_obj_print_exception((mp_obj_t)nlr.ret_val);
return false;
}
@@ -560,6 +569,10 @@ mp_obj_t pyb_rng_get(void) {
return mp_obj_new_int(RNG_GetRandomNumber() >> 16);
}
+mp_obj_t pyb_millis(void) {
+ return mp_obj_new_int(sys_tick_counter);
+}
+
int main(void) {
// TODO disable JTAG
@@ -592,6 +605,7 @@ int main(void) {
// basic sub-system init
sys_tick_init();
+ pendsv_init();
led_init();
#if MICROPY_HW_ENABLE_RTC
@@ -693,6 +707,7 @@ soft_reset:
rt_store_attr(m, MP_QSTR_Usart, rt_make_function_n(2, pyb_Usart));
rt_store_attr(m, qstr_from_str("ADC_all"), (mp_obj_t)&pyb_ADC_all_obj);
rt_store_attr(m, MP_QSTR_ADC, (mp_obj_t)&pyb_ADC_obj);
+ rt_store_attr(m, qstr_from_str("millis"), rt_make_function_n(0, pyb_millis));
rt_store_name(MP_QSTR_pyb, m);
rt_store_name(MP_QSTR_open, rt_make_function_n(2, pyb_io_open));
diff --git a/stm/pendsv.c b/stm/pendsv.c
new file mode 100644
index 0000000000..e8e5b840c6
--- /dev/null
+++ b/stm/pendsv.c
@@ -0,0 +1,49 @@
+#include <stdlib.h>
+#include <stm32f4xx.h>
+
+#include "misc.h"
+#include "mpconfig.h"
+#include "qstr.h"
+#include "obj.h"
+#include "pendsv.h"
+
+static mp_obj_t pendsv_object = MP_OBJ_NULL;
+
+void pendsv_init(void) {
+ // set PendSV interrupt at lowest priority
+ NVIC_SetPriority(PendSV_IRQn, 0xff);
+}
+
+// call this function to raise a pending exception during an interrupt
+// it will wait until all interrupts are finished then raise the given
+// exception object using nlr_jump in the context of the top-level thread
+void pendsv_nlr_jump(mp_obj_t o) {
+ pendsv_object = o;
+ SCB->ICSR = SCB_ICSR_PENDSVSET_Msk;
+}
+
+void pendsv_isr_handler(void) {
+ // re-jig the stack so that when we return from this interrupt handler
+ // it returns instead to nlr_jump with argument pendsv_object
+ __asm volatile (
+ "ldr r0, pendsv_object_ptr\n"
+ "ldr r0, [r0]\n"
+ "str r0, [sp, #0]\n"
+ "ldr r0, nlr_jump_ptr\n"
+ "str r0, [sp, #24]\n"
+ "bx lr\n"
+ ".align 2\n"
+ "pendsv_object_ptr: .word pendsv_object\n"
+ "nlr_jump_ptr: .word nlr_jump\n"
+ );
+
+ /*
+ sp[0] = r0 = exception to raise
+ sp[6] = pc = nlr_jump
+ uint32_t x[2] = {0x424242, 0xdeaddead};
+ printf("PendSV: %p\n", x);
+ for (uint32_t *p = (uint32_t*)(((uint32_t)x - 15) & 0xfffffff0), i = 64; i > 0; p += 4, i -= 4) {
+ printf(" %p: %08x %08x %08x %08x\n", p, p[0], p[1], p[2], p[3]);
+ }
+ */
+}
diff --git a/stm/pendsv.h b/stm/pendsv.h
new file mode 100644
index 0000000000..b07ab71375
--- /dev/null
+++ b/stm/pendsv.h
@@ -0,0 +1,3 @@
+void pendsv_init(void);
+void pendsv_nlr_jump(mp_obj_t o);
+void pendsv_isr_handler(void);
diff --git a/stm/stm32fxxx_it.c b/stm/stm32fxxx_it.c
index 7b5030bc6e..97cdee6a84 100644
--- a/stm/stm32fxxx_it.c
+++ b/stm/stm32fxxx_it.c
@@ -151,6 +151,8 @@ void DebugMon_Handler(void)
*/
void PendSV_Handler(void)
{
+ extern void pendsv_isr_handler(void);
+ pendsv_isr_handler();
}
/**
diff --git a/stm/stmusbd/usbd_cdc_vcp.c b/stm/stmusbd/usbd_cdc_vcp.c
index 6885f7cffe..cb16b58f1d 100644
--- a/stm/stmusbd/usbd_cdc_vcp.c
+++ b/stm/stmusbd/usbd_cdc_vcp.c
@@ -48,6 +48,9 @@ LINE_CODING linecoding =
/* These are external variables imported from CDC core to be used for IN
transfer management. */
+
+extern uint32_t APP_dev_is_connected; // set if CDC device is connected
+
extern uint8_t APP_Rx_Buffer []; /* Write CDC received data in this buffer.
These data will be sent over USB IN endpoint
in the CDC core functions. */
@@ -62,8 +65,6 @@ static uint16_t VCP_Ctrl (uint32_t Cmd, uint8_t* Buf, uint32_t Len);
static uint16_t VCP_DataTx (const uint8_t* Buf, uint32_t Len);
static uint16_t VCP_DataRx (uint8_t* Buf, uint32_t Len);
-extern int dev_is_connected;
-
CDC_IF_Prop_TypeDef VCP_fops =
{
VCP_Init,
@@ -160,7 +161,7 @@ static uint16_t VCP_Ctrl (uint32_t Cmd, uint8_t* Buf, uint32_t Len)
break;
case SET_CONTROL_LINE_STATE:
- dev_is_connected = Len & 0x1; //wValue passed in Len
+ APP_dev_is_connected = Len & 0x1; // wValue is passed in Len (bit of a hack)
break;
case SEND_BREAK:
diff --git a/stm/usb.c b/stm/usb.c
index 8f408b7b15..0fe56d3212 100644
--- a/stm/usb.c
+++ b/stm/usb.c
@@ -11,6 +11,7 @@
#include "mpconfig.h"
#include "qstr.h"
#include "obj.h"
+#include "pendsv.h"
#include "usb.h"
#ifdef USE_DEVICE_MODE
@@ -20,10 +21,12 @@ extern CDC_IF_Prop_TypeDef VCP_fops;
USB_OTG_CORE_HANDLE USB_OTG_Core;
static int dev_is_enabled = 0;
-int dev_is_connected=0; /* used by usbd_cdc_vcp */
+uint32_t APP_dev_is_connected = 0; /* used by usbd_cdc_vcp */
static char rx_buf[64];
static int rx_buf_in;
static int rx_buf_out;
+static int interrupt_char = VCP_CHAR_NONE;
+mp_obj_t mp_const_vcp_interrupt = MP_OBJ_NULL;
void pyb_usb_dev_init(void) {
#ifdef USE_DEVICE_MODE
@@ -34,7 +37,11 @@ void pyb_usb_dev_init(void) {
}
rx_buf_in = 0;
rx_buf_out = 0;
+ interrupt_char = VCP_CHAR_NONE;
dev_is_enabled = 1;
+
+ // create an exception object for interrupting by VCP
+ mp_const_vcp_interrupt = mp_obj_new_exception(qstr_from_str("VCPInterrupt"));
#endif
}
@@ -43,12 +50,27 @@ bool usb_vcp_is_enabled(void) {
}
bool usb_vcp_is_connected(void) {
- return dev_is_connected;
+ return APP_dev_is_connected;
+}
+
+void usb_vcp_set_interrupt_char(int c) {
+ if (dev_is_enabled) {
+ interrupt_char = c;
+ }
}
void usb_vcp_receive(const char *buf, uint32_t len) {
if (dev_is_enabled) {
for (int i = 0; i < len; i++) {
+
+ // catch special interrupt character
+ if (buf[i] == interrupt_char) {
+ // raise exception when interrupts are finished
+ pendsv_nlr_jump(mp_const_vcp_interrupt);
+ interrupt_char = VCP_CHAR_NONE;
+ continue;
+ }
+
rx_buf[rx_buf_in++] = buf[i];
if (rx_buf_in >= sizeof(rx_buf)) {
rx_buf_in = 0;
diff --git a/stm/usb.h b/stm/usb.h
index 718255c25c..61931ffc8a 100644
--- a/stm/usb.h
+++ b/stm/usb.h
@@ -1,6 +1,11 @@
+#define VCP_CHAR_NONE (0)
+#define VCP_CHAR_CTRL_C (3)
+#define VCP_CHAR_CTRL_D (4)
+
void pyb_usb_dev_init(void);
bool usb_vcp_is_enabled(void);
bool usb_vcp_is_connected(void);
+void usb_vcp_set_interrupt_char(int c);
int usb_vcp_rx_any(void);
char usb_vcp_rx_get(void);
void usb_vcp_send_str(const char* str);