Преглед изворни кода

add hard fault handler to bsp.c
rename class_install_subtask to class_open_subtask
add class_close for unmount
adding code for usbh_device_unplugged_isr & invoke it in hcd_isr

hathach пре 13 година
родитељ
комит
97c9001d40

+ 86 - 0
demos/bsp/boards/board.c

@@ -50,3 +50,89 @@ void check_failed(uint8_t *file, uint32_t line)
   (void) file;
   (void) line;
 }
+
+/**
+ * HardFault_HandlerAsm:
+ * Alternative Hard Fault handler to help debug the reason for a fault.
+ * To use, edit the vector table to reference this function in the HardFault vector
+ * This code is suitable for Cortex-M3 and Cortex-M0 cores
+ */
+
+// Use the 'naked' attribute so that C stacking is not used.
+__attribute__((naked))
+void HardFault_HandlerAsm(void){
+  /*
+   * Get the appropriate stack pointer, depending on our mode,
+   * and use it as the parameter to the C handler. This function
+   * will never return
+   */
+
+  __asm(  ".syntax unified\n"
+      "MOVS   R0, #4  \n"
+      "MOV    R1, LR  \n"
+      "TST    R0, R1  \n"
+      "BEQ    _MSP    \n"
+      "MRS    R0, PSP \n"
+      "B      HardFault_HandlerC      \n"
+      "_MSP:  \n"
+      "MRS    R0, MSP \n"
+      "B      HardFault_HandlerC      \n"
+      ".syntax divided\n") ;
+}
+
+/**
+ * HardFaultHandler_C:
+ * This is called from the HardFault_HandlerAsm with a pointer the Fault stack
+ * as the parameter. We can then read the values from the stack and place them
+ * into local variables for ease of reading.
+ * We then read the various Fault Status and Address Registers to help decode
+ * cause of the fault.
+ * The function ends with a BKPT instruction to force control back into the debugger
+ */
+void HardFault_HandlerC(unsigned long *hardfault_args){
+  volatile unsigned long stacked_r0 ;
+  volatile unsigned long stacked_r1 ;
+  volatile unsigned long stacked_r2 ;
+  volatile unsigned long stacked_r3 ;
+  volatile unsigned long stacked_r12 ;
+  volatile unsigned long stacked_lr ;
+  volatile unsigned long stacked_pc ;
+  volatile unsigned long stacked_psr ;
+  volatile unsigned long _CFSR ;
+  volatile unsigned long _HFSR ;
+  volatile unsigned long _DFSR ;
+  volatile unsigned long _AFSR ;
+  volatile unsigned long _BFAR ;
+  volatile unsigned long _MMAR ;
+
+  stacked_r0  = ((unsigned long)hardfault_args[0]) ;
+  stacked_r1  = ((unsigned long)hardfault_args[1]) ;
+  stacked_r2  = ((unsigned long)hardfault_args[2]) ;
+  stacked_r3  = ((unsigned long)hardfault_args[3]) ;
+  stacked_r12 = ((unsigned long)hardfault_args[4]) ;
+  stacked_lr  = ((unsigned long)hardfault_args[5]) ;
+  stacked_pc  = ((unsigned long)hardfault_args[6]) ;
+  stacked_psr = ((unsigned long)hardfault_args[7]) ;
+
+  // Configurable Fault Status Register
+  // Consists of MMSR, BFSR and UFSR
+  _CFSR = (*((volatile unsigned long *)(0xE000ED28))) ;
+
+  // Hard Fault Status Register
+  _HFSR = (*((volatile unsigned long *)(0xE000ED2C))) ;
+
+  // Debug Fault Status Register
+  _DFSR = (*((volatile unsigned long *)(0xE000ED30))) ;
+
+  // Auxiliary Fault Status Register
+  _AFSR = (*((volatile unsigned long *)(0xE000ED3C))) ;
+
+  // Read the Fault Address Registers. These may not contain valid values.
+  // Check BFARVALID/MMARVALID to see if they are valid values
+  // MemManage Fault Address Register
+  _MMAR = (*((volatile unsigned long *)(0xE000ED34))) ;
+  // Bus Fault Address Register
+  _BFAR = (*((volatile unsigned long *)(0xE000ED38))) ;
+
+  __asm("BKPT #0\n") ; // Break into the debugger
+}

+ 10 - 0
tests/test/host/ehci/test_ehci_isr.c

@@ -97,3 +97,13 @@ void test_isr_device_connect_slowspeed(void)
   //------------- Code Under Test -------------//
   hcd_isr(hostid);
 }
+
+void test_isr_device_disconnect(void)
+{
+  ehci_controller_device_unplug(hostid);
+  usbh_device_unplugged_isr_Expect(hostid);
+
+  //------------- Code Under Test -------------//
+  hcd_isr(hostid);
+
+}

+ 1 - 1
tests/test/host/test_enum_task.c

@@ -232,7 +232,7 @@ void test_enum_failed_get_full_config_desc(void)
 
 void class_install_expect(void)
 {
-  hidh_install_subtask_StubWithCallback(hidh_install_stub);
+  hidh_open_subtask_StubWithCallback(hidh_install_stub);
 }
 
 void test_enum_parse_config_desc(void)

+ 19 - 0
tests/test/host/test_usbh.c

@@ -156,3 +156,22 @@ void test_usbh_init_ok(void)
   TEST_ASSERT_EQUAL_MEMORY(device_info_zero, usbh_device_info_pool, sizeof(usbh_device_info_t)*(TUSB_CFG_HOST_DEVICE_MAX+1));
 
 }
+
+void class_close_expect(void)
+{
+  hidh_close_Expect(1);
+}
+
+void test_usbh_device_unplugged_isr(void)
+{
+  usbh_device_info_pool[1].status = TUSB_DEVICE_STATUS_READY;
+  usbh_device_info_pool[1].core_id = 0;
+  usbh_device_info_pool[1].hub_addr = 0;
+  usbh_device_info_pool[1].hub_port = 0;
+
+  class_close_expect();
+
+  usbh_device_unplugged_isr(0);
+
+  TEST_ASSERT_EQUAL(TUSB_DEVICE_STATUS_REMOVING, usbh_device_info_pool[1].status);
+}

+ 9 - 0
tests/test/support/ehci_controller.c

@@ -86,3 +86,12 @@ void ehci_controller_device_plug(uint8_t hostid, tusb_speed_t speed)
   regs->portsc_bit.current_connect_status = 1;
   regs->portsc_bit.nxp_port_speed = speed;
 }
+
+void ehci_controller_device_unplug(uint8_t hostid)
+{
+  ehci_registers_t* const regs = get_operational_register(hostid);
+
+  regs->usb_sts_bit.port_change_detect = 1;
+  regs->portsc_bit.connect_status_change = 1;
+  regs->portsc_bit.current_connect_status = 0;
+}

+ 1 - 0
tests/test/support/ehci_controller.h

@@ -57,6 +57,7 @@
 
 void ehci_controller_run(uint8_t hostid);
 void ehci_controller_device_plug(uint8_t hostid, tusb_speed_t speed);
+void ehci_controller_device_unplug(uint8_t hostid);
 
 #ifdef __cplusplus
  }

+ 2 - 1
tinyusb/class/hid_host.h

@@ -88,8 +88,9 @@ tusb_error_t hidh_keyboard_install(uint8_t dev_addr, uint8_t const *descriptor)
 // CLASS DRIVER FUNCTION (all declared with WEAK)
 //--------------------------------------------------------------------+
 void         hidh_init(void) ATTR_WEAK;
-tusb_error_t hidh_install_subtask(uint8_t dev_addr, uint8_t const *descriptor, uint16_t *p_length) ATTR_WEAK ATTR_WARN_UNUSED_RESULT;
+tusb_error_t hidh_open_subtask(uint8_t dev_addr, uint8_t const *descriptor, uint16_t *p_length) ATTR_WEAK ATTR_WARN_UNUSED_RESULT;
 void hidh_isr(pipe_handle_t pipe_hdl) ATTR_WEAK;
+void hidh_close(uint8_t dev_addr) ATTR_WEAK;
 
 #endif
 

+ 2 - 2
tinyusb/class/msc_host.h

@@ -69,9 +69,9 @@
 #ifdef _TINY_USB_SOURCE_FILE_
 
 void         msch_init(void) ATTR_WEAK;
-tusb_error_t msch_install_subtask(uint8_t dev_addr, uint8_t const *descriptor, uint16_t *p_length) ATTR_WEAK ATTR_WARN_UNUSED_RESULT;
+tusb_error_t msch_open_subtask(uint8_t dev_addr, uint8_t const *descriptor, uint16_t *p_length) ATTR_WEAK ATTR_WARN_UNUSED_RESULT;
 void msch_isr(pipe_handle_t pipe_hdl) ATTR_WEAK;
-
+void msch_close(uint8_t dev_addr) ATTR_WEAK;
 #endif
 
 #ifdef __cplusplus

+ 2 - 1
tinyusb/host/ehci/ehci.c

@@ -175,7 +175,7 @@ void port_connect_status_isr(uint8_t hostid)
     usbh_device_plugged_isr(hostid, regs->portsc_bit.nxp_port_speed); // NXP specific port speed
   }else // device unplugged
   {
-//    usbh_device_
+    usbh_device_unplugged_isr(hostid);
   }
 
 }
@@ -578,6 +578,7 @@ static inline ehci_qtd_t* get_control_qtds(uint8_t dev_addr)
 
 static void init_qhd(ehci_qhd_t *p_qhd, uint8_t dev_addr, uint16_t max_packet_size, uint8_t endpoint_addr, uint8_t xfer_type)
 {
+  // address 0 uses async head, which always on the list --> cannot be cleared (ehci halted otherwise)
   if (dev_addr != 0)
   {
     memclr_(p_qhd, sizeof(ehci_qhd_t));

+ 27 - 6
tinyusb/host/usbh.c

@@ -65,14 +65,16 @@ class_driver_t const usbh_class_drivers[TUSB_CLASS_MAX_CONSEC_NUMBER] =
 {
     [TUSB_CLASS_HID] = {
         .init = hidh_init,
-        .install_subtask = hidh_install_subtask,
-        .isr = hidh_isr
+        .open_subtask = hidh_open_subtask,
+        .isr = hidh_isr,
+        .close = hidh_close
     },
 
     [TUSB_CLASS_MSC] = {
         .init = msch_init,
-        .install_subtask = msch_install_subtask,
-        .isr = msch_isr
+        .open_subtask = msch_open_subtask,
+        .isr = msch_isr,
+        .close = msch_close
     }
 };
 
@@ -190,7 +192,23 @@ void usbh_device_plugged_isr(uint8_t hostid, tusb_speed_t speed)
 
 void usbh_device_unplugged_isr(uint8_t hostid)
 {
+  uint8_t dev_addr=1;
+  while ( dev_addr <= TUSB_CFG_HOST_DEVICE_MAX && ! (usbh_device_info_pool[dev_addr].core_id == hostid &&
+      usbh_device_info_pool[dev_addr].hub_addr == 0 &&
+      usbh_device_info_pool[dev_addr].hub_port ==0))
+  {
+    dev_addr++;
+  }
+
+  ASSERT(dev_addr <= TUSB_CFG_HOST_DEVICE_MAX, (void) 0 );
+
+  for (uint8_t class_code = 1; class_code < TUSB_CLASS_MAX_CONSEC_NUMBER; class_code++)
+  {
+    if (usbh_class_drivers[class_code].close)
+      usbh_class_drivers[class_code].close(dev_addr);
+  }
 
+  usbh_device_info_pool[dev_addr].status = TUSB_DEVICE_STATUS_REMOVING;
 }
 
 
@@ -260,6 +278,8 @@ OSAL_TASK_DECLARE(usbh_enumeration_task)
   usbh_device_info_pool[new_addr].status   = TUSB_DEVICE_STATUS_ADDRESSED;
   hcd_pipe_control_close(0);
 
+//  hcd_port_reset( usbh_device_info_pool[new_addr].core_id ); TODO verified
+
   // open control pipe for new address
   TASK_ASSERT_STATUS ( usbh_pipe_control_open(new_addr, ((tusb_descriptor_device_t*) enum_data_buffer)->bMaxPacketSize0 ) );
 
@@ -335,11 +355,11 @@ OSAL_TASK_DECLARE(usbh_enumeration_task)
       TASK_ASSERT( false ); // corrupted data, abort enumeration
     } else if ( class_code < TUSB_CLASS_MAX_CONSEC_NUMBER)
     {
-      if ( usbh_class_drivers[class_code].install_subtask )
+      if ( usbh_class_drivers[class_code].open_subtask )
       {
         uint16_t length;
         OSAL_SUBTASK_INVOKED_AND_WAIT ( // parameters in task/sub_task must be static storage (static or global)
-            usbh_class_drivers[ ((tusb_descriptor_interface_t*) p_desc)->bInterfaceClass ].install_subtask(new_addr, p_desc, &length) );
+            usbh_class_drivers[ ((tusb_descriptor_interface_t*) p_desc)->bInterfaceClass ].open_subtask(new_addr, p_desc, &length) );
         p_desc += length;
       }
     } else // unsupported class (not enable or yet implemented)
@@ -366,6 +386,7 @@ OSAL_TASK_DECLARE(usbh_enumeration_task)
     )
   );
 
+  usbh_device_info_pool[new_addr].status = TUSB_DEVICE_STATUS_READY;
   tusbh_device_mount_succeed_cb(new_addr);
 
   // TODO invoke mounted callback

+ 2 - 1
tinyusb/host/usbh.h

@@ -151,8 +151,9 @@ typedef uint8_t  tusbh_device_status_t;
 
 typedef struct {
   void (* const init) (void);
-  tusb_error_t (* const install_subtask)(uint8_t, uint8_t const *, uint16_t*);
+  tusb_error_t (* const open_subtask)(uint8_t, uint8_t const *, uint16_t*);
   void (* const isr) (pipe_handle_t);
+  void (* const close) (uint8_t)
 } class_driver_t;
 //--------------------------------------------------------------------+
 // INTERNAL OBJECT & FUNCTION DECLARATION