39
39
#include "py/stream.h"
40
40
#include "py/mperrno.h"
41
41
#include "py/mphal.h"
42
+ #include "lib/utils/mpirq.h"
42
43
#include "bufhelper.h"
43
44
#include "storage.h"
44
45
#include "sdcard.h"
70
71
#define MAX_ENDPOINT (dev_id ) (8)
71
72
#endif
72
73
74
+ // Constants for USB_VCP.irq trigger.
75
+ #define USBD_CDC_IRQ_RX (1)
76
+
73
77
STATIC void pyb_usb_vcp_init0 (void );
74
78
75
79
// this will be persistent across a soft-reset
@@ -219,6 +223,7 @@ const mp_rom_obj_tuple_t pyb_usb_hid_keyboard_obj = {
219
223
220
224
void pyb_usb_init0 (void ) {
221
225
for (int i = 0 ; i < MICROPY_HW_USB_CDC_NUM ; ++ i ) {
226
+ usb_device .usbd_cdc_itf [i ].cdc_idx = i ;
222
227
usb_device .usbd_cdc_itf [i ].attached_to_repl = false;
223
228
}
224
229
#if MICROPY_HW_USB_HID
@@ -644,14 +649,42 @@ const pyb_usb_vcp_obj_t pyb_usb_vcp_obj[MICROPY_HW_USB_CDC_NUM] = {
644
649
#endif
645
650
};
646
651
652
+ STATIC bool pyb_usb_vcp_irq_scheduled [MICROPY_HW_USB_CDC_NUM ];
653
+
647
654
STATIC void pyb_usb_vcp_init0 (void ) {
655
+ for (size_t i = 0 ; i < MICROPY_HW_USB_CDC_NUM ; ++ i ) {
656
+ MP_STATE_PORT (pyb_usb_vcp_irq )[i ] = mp_const_none ;
657
+ pyb_usb_vcp_irq_scheduled [i ] = false;
658
+ }
659
+
648
660
// Activate USB_VCP(0) on dupterm slot 1 for the REPL
649
661
MP_STATE_VM (dupterm_objs [1 ]) = MP_OBJ_FROM_PTR (& pyb_usb_vcp_obj [0 ]);
650
662
usb_vcp_attach_to_repl (& pyb_usb_vcp_obj [0 ], true);
651
663
}
652
664
665
+ STATIC mp_obj_t pyb_usb_vcp_irq_run (mp_obj_t self_in ) {
666
+ pyb_usb_vcp_obj_t * self = MP_OBJ_TO_PTR (self_in );
667
+ uint8_t idx = self -> cdc_itf -> cdc_idx ;
668
+ mp_obj_t callback = MP_STATE_PORT (pyb_usb_vcp_irq )[idx ];
669
+ pyb_usb_vcp_irq_scheduled [idx ] = false;
670
+ if (callback != mp_const_none && usbd_cdc_rx_num (self -> cdc_itf )) {
671
+ mp_call_function_1 (callback , self_in );
672
+ }
673
+ return mp_const_none ;
674
+ }
675
+ STATIC MP_DEFINE_CONST_FUN_OBJ_1 (pyb_usb_vcp_irq_run_obj , pyb_usb_vcp_irq_run );
676
+
677
+ void usbd_cdc_rx_event_callback (usbd_cdc_itf_t * cdc ) {
678
+ uint8_t idx = cdc -> cdc_idx ;
679
+ mp_obj_t self = MP_OBJ_FROM_PTR (& pyb_usb_vcp_obj [idx ]);
680
+ mp_obj_t callback = MP_STATE_PORT (pyb_usb_vcp_irq )[idx ];
681
+ if (callback != mp_const_none && !pyb_usb_vcp_irq_scheduled [idx ]) {
682
+ pyb_usb_vcp_irq_scheduled [idx ] = mp_sched_schedule (MP_OBJ_FROM_PTR (& pyb_usb_vcp_irq_run_obj ), self );
683
+ }
684
+ }
685
+
653
686
STATIC void pyb_usb_vcp_print (const mp_print_t * print , mp_obj_t self_in , mp_print_kind_t kind ) {
654
- int id = ((pyb_usb_vcp_obj_t * )MP_OBJ_TO_PTR (self_in ))-> cdc_itf - & usb_device . usbd_cdc_itf [ 0 ] ;
687
+ int id = ((pyb_usb_vcp_obj_t * )MP_OBJ_TO_PTR (self_in ))-> cdc_itf -> cdc_idx ;
655
688
mp_printf (print , "USB_VCP(%u)" , id );
656
689
}
657
690
@@ -796,6 +829,40 @@ STATIC mp_obj_t pyb_usb_vcp_recv(size_t n_args, const mp_obj_t *args, mp_map_t *
796
829
}
797
830
STATIC MP_DEFINE_CONST_FUN_OBJ_KW (pyb_usb_vcp_recv_obj , 1 , pyb_usb_vcp_recv );
798
831
832
+ // irq(handler=None, trigger=0, hard=False)
833
+ STATIC mp_obj_t pyb_usb_vcp_irq (size_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args ) {
834
+ mp_arg_val_t args [MP_IRQ_ARG_INIT_NUM_ARGS ];
835
+ mp_arg_parse_all (n_args - 1 , pos_args + 1 , kw_args , MP_IRQ_ARG_INIT_NUM_ARGS , mp_irq_init_args , args );
836
+ pyb_usb_vcp_obj_t * self = MP_OBJ_TO_PTR (pos_args [0 ]);
837
+
838
+ if (n_args > 1 || kw_args -> used != 0 ) {
839
+ // Check the handler.
840
+ mp_obj_t handler = args [MP_IRQ_ARG_INIT_handler ].u_obj ;
841
+ if (handler != mp_const_none && !mp_obj_is_callable (handler )) {
842
+ mp_raise_ValueError (MP_ERROR_TEXT ("handler must be None or callable" ));
843
+ }
844
+
845
+ // Check the trigger.
846
+ mp_uint_t trigger = args [MP_IRQ_ARG_INIT_trigger ].u_int ;
847
+ if (trigger == 0 ) {
848
+ handler = mp_const_none ;
849
+ } else if (trigger != USBD_CDC_IRQ_RX ) {
850
+ mp_raise_ValueError (MP_ERROR_TEXT ("unsupported trigger" ));
851
+ }
852
+
853
+ // Check hard/soft.
854
+ if (args [MP_IRQ_ARG_INIT_hard ].u_bool ) {
855
+ mp_raise_ValueError (MP_ERROR_TEXT ("hard unsupported" ));
856
+ }
857
+
858
+ // Reconfigure the IRQ.
859
+ MP_STATE_PORT (pyb_usb_vcp_irq )[self -> cdc_itf -> cdc_idx ] = handler ;
860
+ }
861
+
862
+ return mp_const_none ;
863
+ }
864
+ STATIC MP_DEFINE_CONST_FUN_OBJ_KW (pyb_usb_vcp_irq_obj , 1 , pyb_usb_vcp_irq );
865
+
799
866
mp_obj_t pyb_usb_vcp___exit__ (size_t n_args , const mp_obj_t * args ) {
800
867
return mp_const_none ;
801
868
}
@@ -814,13 +881,15 @@ STATIC const mp_rom_map_elem_t pyb_usb_vcp_locals_dict_table[] = {
814
881
{ MP_ROM_QSTR (MP_QSTR_readlines ), MP_ROM_PTR (& mp_stream_unbuffered_readlines_obj )},
815
882
{ MP_ROM_QSTR (MP_QSTR_write ), MP_ROM_PTR (& mp_stream_write_obj ) },
816
883
{ MP_ROM_QSTR (MP_QSTR_close ), MP_ROM_PTR (& mp_identity_obj ) },
884
+ { MP_ROM_QSTR (MP_QSTR_irq ), MP_ROM_PTR (& pyb_usb_vcp_irq_obj ) },
817
885
{ MP_ROM_QSTR (MP_QSTR___del__ ), MP_ROM_PTR (& mp_identity_obj ) },
818
886
{ MP_ROM_QSTR (MP_QSTR___enter__ ), MP_ROM_PTR (& mp_identity_obj ) },
819
887
{ MP_ROM_QSTR (MP_QSTR___exit__ ), MP_ROM_PTR (& pyb_usb_vcp___exit___obj ) },
820
888
821
889
// class constants
822
890
{ MP_ROM_QSTR (MP_QSTR_RTS ), MP_ROM_INT (USBD_CDC_FLOWCONTROL_RTS ) },
823
891
{ MP_ROM_QSTR (MP_QSTR_CTS ), MP_ROM_INT (USBD_CDC_FLOWCONTROL_CTS ) },
892
+ { MP_ROM_QSTR (MP_QSTR_IRQ_RX ), MP_ROM_INT (USBD_CDC_IRQ_RX ) },
824
893
};
825
894
826
895
STATIC MP_DEFINE_CONST_DICT (pyb_usb_vcp_locals_dict , pyb_usb_vcp_locals_dict_table );
0 commit comments