From 1b66c148cce2699c3f5e470fa82f0efb192eb00a Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sun, 19 Nov 2023 15:55:24 +0100 Subject: UAC2: Implement feedback by fifo counting. --- src/class/audio/audio_device.c | 169 +++++++++++++++++++++++++++-------------- src/class/audio/audio_device.h | 11 +-- 2 files changed, 114 insertions(+), 66 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 9ba38a20c..4ca95d4e7 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -2,6 +2,7 @@ * The MIT License (MIT) * * Copyright (c) 2020 Reinhard Panhuber, Jerzy Kasenberg + * Copyright (c) 2023 HiFiPhile * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -319,7 +320,8 @@ typedef struct #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP struct { - CFG_TUSB_MEM_ALIGN uint32_t value; // Feedback value for asynchronous mode (in 16.16 format). + CFG_TUSB_MEM_ALIGN uint32_t send_buf; + uint32_t value; // Feedback value for asynchronous mode (in 16.16 format). uint32_t min_value; // min value according to UAC2 FMT-2.0 section 2.3.1.1. uint32_t max_value; // max value according to UAC2 FMT-2.0 section 2.3.1.1. @@ -335,12 +337,12 @@ typedef struct uint32_t mclk_freq; }fixed; -#if 0 // implement later struct { - uint32_t nominal_value; - uint32_t threshold_bytes; + uint32_t nom_value; // In 16.16 format + uint32_t fifo_lvl_avg; // In 16.16 format + uint16_t fifo_lvl_thr; // fifo level threshold + uint16_t rate_const[2]; // pre-computed feedback/fifo_depth rate }fifo_count; -#endif }compute; } feedback; @@ -473,7 +475,8 @@ static uint16_t audiod_tx_packet_size(const uint16_t* norminal_size, uint16_t da #endif #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -static bool set_fb_params_freq(audiod_function_t* audio, uint32_t sample_freq, uint32_t mclk_freq); +static bool audiod_set_fb_params_freq(audiod_function_t* audio, uint32_t sample_freq, uint32_t mclk_freq); +static void audiod_fb_fifo_count_update(audiod_function_t* audio, uint16_t lvl_new); #endif bool tud_audio_n_mounted(uint8_t func_id) @@ -566,7 +569,7 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_function_t* audio, uint16_t TU_VERIFY(tud_audio_rx_done_pre_read_cb(rhport, n_bytes_received, idx_audio_fct, audio->ep_out, audio->alt_setting[idxItf])); } -#if CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_EP_OUT +#if CFG_TUD_AUDIO_ENABLE_DECODING switch (audio->format_type_rx) { @@ -615,6 +618,13 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_function_t* audio, uint16_t TU_VERIFY(usbd_edpt_xfer_fifo(rhport, audio->ep_out, &audio->ep_out_ff, audio->ep_out_sz), false); #endif +#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP + if(audio->feedback.compute_method == AUDIO_FEEDBACK_METHOD_FIFO_COUNT) + { + audiod_fb_fifo_count_update(audio, tu_fifo_count(&audio->ep_out_ff)); + } +#endif + #endif // Call a weak callback here - a possibility for user to get informed decoding was completed @@ -725,6 +735,13 @@ static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_function_t* audio, u // Number of bytes should be a multiple of CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX but checking makes no sense - no way to correct it // TU_VERIFY(cnt != n_bytes); +#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP + if(audio->feedback.compute_method == AUDIO_FEEDBACK_METHOD_FIFO_COUNT) + { + audiod_fb_fifo_count_update(audio, tu_fifo_count(&audio->rx_supp_ff[0])); + } +#endif + return true; } #endif //CFG_TUD_AUDIO_ENABLE_DECODING @@ -1067,9 +1084,29 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi // This function is called once a transmit of a feedback packet was successfully completed. Here, we get the next feedback value to be sent #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -static inline bool audiod_fb_send(uint8_t rhport, audiod_function_t *audio) +static inline bool audiod_fb_send(audiod_function_t *audio) { - return usbd_edpt_xfer(rhport, audio->ep_fb, (uint8_t *) &audio->feedback.value, 4); + // Format the feedback value +#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION + if ( TUSB_SPEED_FULL == tud_speed_get() ) + { + uint8_t * fb = (uint8_t *) &audio->feedback.send_buf; + + // For FS format is 10.14 + *(fb++) = (audio->feedback.value >> 2) & 0xFF; + *(fb++) = (audio->feedback.value >> 10) & 0xFF; + *(fb++) = (audio->feedback.value >> 18) & 0xFF; + // 4th byte is needed to work correctly with MS Windows + *fb = 0; + } else + { + value = audio->feedback.value; + } +#else + audio->feedback.send_buf = audio->feedback.value; +#endif + + return usbd_edpt_xfer(audio->rhport, audio->ep_fb, (uint8_t *) &audio->feedback.send_buf, 4); } #endif @@ -1861,7 +1898,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * // Minimal/Maximum value in 16.16 format for full speed (1ms per frame) or high speed (125 us per frame) uint32_t const frame_div = (TUSB_SPEED_FULL == tud_speed_get()) ? 1000 : 8000; - audio->feedback.min_value = (fb_param.sample_freq/frame_div - 1) << 16; + audio->feedback.min_value = ((fb_param.sample_freq - 1)/frame_div) << 16; audio->feedback.max_value = (fb_param.sample_freq/frame_div + 1) << 16; switch(fb_param.method) @@ -1869,20 +1906,27 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * case AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED: case AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT: case AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2: - set_fb_params_freq(audio, fb_param.sample_freq, fb_param.frequency.mclk_freq); + audiod_set_fb_params_freq(audio, fb_param.sample_freq, fb_param.frequency.mclk_freq); break; - #if 0 // implement later case AUDIO_FEEDBACK_METHOD_FIFO_COUNT: { - uint64_t fb64 = ((uint64_t) fb_param.sample_freq) << 16; - audio->feedback.compute.fifo_count.nominal_value = (uint32_t) (fb64 / frame_div); - audio->feedback.compute.fifo_count.threshold_bytes = fb_param.fifo_count.threshold_bytes; - - tud_audio_fb_set(audio->feedback.compute.fifo_count.nominal_value); + /* Initialize the threshold level to half filled */ + uint16_t fifo_lvl_thr; +#if CFG_TUD_AUDIO_ENABLE_DECODING + fifo_lvl_thr = tu_fifo_depth(&audio->rx_supp_ff[0]) / 2; +#else + fifo_lvl_thr = tu_fifo_depth(&audio->ep_out_ff) / 2; +#endif + audio->feedback.compute.fifo_count.fifo_lvl_thr = fifo_lvl_thr; + audio->feedback.compute.fifo_count.fifo_lvl_avg = ((uint32_t)fifo_lvl_thr) << 16; + /* Avoid 64bit division */ + uint32_t nominal = ((fb_param.sample_freq / 100) << 16) / (frame_div / 100); + audio->feedback.compute.fifo_count.nom_value = nominal; + audio->feedback.compute.fifo_count.rate_const[0] = (audio->feedback.max_value - nominal) / fifo_lvl_thr; + audio->feedback.compute.fifo_count.rate_const[1] = (nominal - audio->feedback.min_value) / fifo_lvl_thr; } break; - #endif // nothing to do default: break; @@ -2198,7 +2242,7 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 if (!usbd_edpt_busy(rhport, audio->ep_fb)) { // Schedule next transmission - value is changed bytud_audio_n_fb_set() in the meantime or the old value gets sent - return audiod_fb_send(rhport, audio); + return audiod_fb_send(audio); } } #endif @@ -2210,7 +2254,7 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -static bool set_fb_params_freq(audiod_function_t* audio, uint32_t sample_freq, uint32_t mclk_freq) +static bool audiod_set_fb_params_freq(audiod_function_t* audio, uint32_t sample_freq, uint32_t mclk_freq) { // Check if frame interval is within sane limits // The interval value n_frames was taken from the descriptors within audiod_set_interface() @@ -2244,6 +2288,38 @@ static bool set_fb_params_freq(audiod_function_t* audio, uint32_t sample_freq, u return true; } +static void audiod_fb_fifo_count_update(audiod_function_t* audio, uint16_t lvl_new) +{ + /* Low-pass (averaging) filter */ + uint32_t lvl = audio->feedback.compute.fifo_count.fifo_lvl_avg; + lvl = (uint32_t)(((uint64_t)lvl * 63 + ((uint32_t)lvl_new << 16)) >> 6); + audio->feedback.compute.fifo_count.fifo_lvl_avg = lvl; + + uint32_t const ff_lvl = lvl >> 16; + uint16_t const ff_thr = audio->feedback.compute.fifo_count.fifo_lvl_thr; + uint16_t const *rate = audio->feedback.compute.fifo_count.rate_const; + + uint32_t feedback; + + if(ff_lvl < ff_thr) + { + feedback = audio->feedback.compute.fifo_count.nom_value + (ff_thr - ff_lvl) * rate[0]; + } else + { + feedback = audio->feedback.compute.fifo_count.nom_value - (ff_lvl - ff_thr) * rate[1]; + } + + if ( feedback > audio->feedback.max_value ) feedback = audio->feedback.max_value; + if ( feedback < audio->feedback.min_value ) feedback = audio->feedback.min_value; + audio->feedback.value = feedback; + + // Schedule a transmit with the new value if EP is not busy - this triggers repetitive scheduling of the feedback value + if (!usbd_edpt_busy(audio->rhport, audio->ep_fb)) + { + audiod_fb_send(audio); + } +} + uint32_t tud_audio_feedback_update(uint8_t func_id, uint32_t cycles) { audiod_function_t* audio = &_audiod_fct[func_id]; @@ -2280,6 +2356,21 @@ uint32_t tud_audio_feedback_update(uint8_t func_id, uint32_t cycles) return feedback; } + +bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback) +{ + TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); + + _audiod_fct[func_id].feedback.value = feedback; + + // Schedule a transmit with the new value if EP is not busy - this triggers repetitive scheduling of the feedback value + if (!usbd_edpt_busy(_audiod_fct[func_id].rhport, _audiod_fct[func_id].ep_fb)) + { + return audiod_fb_send(&_audiod_fct[func_id]); + } + + return true; +} #endif TU_ATTR_FAST_FUNC void audiod_sof_isr (uint8_t rhport, uint32_t frame_count) @@ -2691,44 +2782,8 @@ static uint16_t audiod_tx_packet_size(const uint16_t* norminal_size, uint16_t da #endif -#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - -bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback) -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); - - // Format the feedback value -#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION - if ( TUSB_SPEED_FULL == tud_speed_get() ) - { - uint8_t * fb = (uint8_t *) &_audiod_fct[func_id].feedback.value; - - // For FS format is 10.14 - *(fb++) = (feedback >> 2) & 0xFF; - *(fb++) = (feedback >> 10) & 0xFF; - *(fb++) = (feedback >> 18) & 0xFF; - // 4th byte is needed to work correctly with MS Windows - *fb = 0; - }else -#else - { - // Send value as-is, caller will choose the appropriate format - _audiod_fct[func_id].feedback.value = feedback; - } -#endif - - // Schedule a transmit with the new value if EP is not busy - this triggers repetitive scheduling of the feedback value - if (!usbd_edpt_busy(_audiod_fct[func_id].rhport, _audiod_fct[func_id].ep_fb)) - { - return audiod_fb_send(_audiod_fct[func_id].rhport, &_audiod_fct[func_id]); - } - - return true; -} -#endif - // No security checks here - internal function only which should always succeed -uint8_t audiod_get_audio_fct_idx(audiod_function_t * audio) +static uint8_t audiod_get_audio_fct_idx(audiod_function_t * audio) { for (uint8_t cnt=0; cnt < CFG_TUD_AUDIO; cnt++) { diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index b16514fd4..9c95ce1a9 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -3,6 +3,7 @@ * * Copyright (c) 2020 Ha Thach (tinyusb.org) * Copyright (c) 2020 Reinhard Panhuber + * Copyright (c) 2023 HiFiPhile * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -487,7 +488,6 @@ TU_ATTR_WEAK void tud_audio_fb_done_cb(uint8_t func_id); // feedback = n_cycles / n_frames * f_s / f_m in 16.16 format, where n_cycles are the number of main clock cycles within fb_n_frames bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback); -static inline bool tud_audio_fb_set(uint32_t feedback); // Update feedback value with passed cycles since last time this update function is called. // Typically called within tud_audio_sof_isr(). Required tud_audio_feedback_params_cb() is implemented @@ -500,9 +500,7 @@ enum { AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED, AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT, AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2, - - // impelemnt later - // AUDIO_FEEDBACK_METHOD_FIFO_COUNT + AUDIO_FEEDBACK_METHOD_FIFO_COUNT }; typedef struct { @@ -514,11 +512,6 @@ typedef struct { uint32_t mclk_freq; // Main clock frequency in Hz i.e. master clock to which sample clock is based on }frequency; -#if 0 // implement later - struct { - uint32_t threshold_bytes; // minimum number of bytes received to be considered as filled/ready - }fifo_count; -#endif }; }audio_feedback_params_t; -- cgit v1.3.1 From 187c3793315c422b99368d51204fa2b5acee93da Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sun, 24 Mar 2024 13:53:34 +0100 Subject: Add tu_static to global variables. --- src/class/audio/audio_device.c | 86 +++++++++++++++++++++--------------------- 1 file changed, 43 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 4ca95d4e7..16ba7fe65 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -119,23 +119,23 @@ // EP IN software buffers and mutexes #if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING #if CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0 - IN_SW_BUF_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_1[CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ]; + tu_static IN_SW_BUF_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_1[CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ]; #if CFG_FIFO_MUTEX - osal_mutex_def_t ep_in_ff_mutex_wr_1; // No need for read mutex as only USB driver reads from FIFO + tu_static osal_mutex_def_t ep_in_ff_mutex_wr_1; // No need for read mutex as only USB driver reads from FIFO #endif #endif // CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0 #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ > 0 - IN_SW_BUF_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_2[CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ]; + tu_static IN_SW_BUF_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_2[CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ]; #if CFG_FIFO_MUTEX - osal_mutex_def_t ep_in_ff_mutex_wr_2; // No need for read mutex as only USB driver reads from FIFO + tu_static osal_mutex_def_t ep_in_ff_mutex_wr_2; // No need for read mutex as only USB driver reads from FIFO #endif #endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ > 0 #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ > 0 - IN_SW_BUF_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_3[CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ]; + tu_static IN_SW_BUF_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_in_sw_buf_3[CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ]; #if CFG_FIFO_MUTEX - osal_mutex_def_t ep_in_ff_mutex_wr_3; // No need for read mutex as only USB driver reads from FIFO + tu_static osal_mutex_def_t ep_in_ff_mutex_wr_3; // No need for read mutex as only USB driver reads from FIFO #endif #endif // CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ > 0 #endif // CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING @@ -145,38 +145,38 @@ // - the software encoding is used - in this case the linear buffers serve as a target memory where logical channels are encoded into #if CFG_TUD_AUDIO_ENABLE_EP_IN && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_ENCODING) #if CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX > 0 - CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_1[CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX]; + tu_static CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_1[CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX]; #endif #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX > 0 - CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_2[CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX]; + tu_static CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_2[CFG_TUD_AUDIO_FUNC_2_EP_IN_SZ_MAX]; #endif #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX > 0 - CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_3[CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX]; + tu_static CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_in_3[CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX]; #endif #endif // CFG_TUD_AUDIO_ENABLE_EP_IN && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING) // EP OUT software buffers and mutexes #if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING #if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ > 0 - OUT_SW_BUF_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_1[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ]; + tu_static OUT_SW_BUF_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_1[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ]; #if CFG_FIFO_MUTEX - osal_mutex_def_t ep_out_ff_mutex_rd_1; // No need for write mutex as only USB driver writes into FIFO + tu_static osal_mutex_def_t ep_out_ff_mutex_rd_1; // No need for write mutex as only USB driver writes into FIFO #endif #endif // CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ > 0 #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ > 0 - OUT_SW_BUF_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_2[CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ]; + tu_static OUT_SW_BUF_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_2[CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ]; #if CFG_FIFO_MUTEX - osal_mutex_def_t ep_out_ff_mutex_rd_2; // No need for write mutex as only USB driver writes into FIFO + tu_static osal_mutex_def_t ep_out_ff_mutex_rd_2; // No need for write mutex as only USB driver writes into FIFO #endif #endif // CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ > 0 #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ > 0 - OUT_SW_BUF_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_3[CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ]; + tu_static OUT_SW_BUF_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t audio_ep_out_sw_buf_3[CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ]; #if CFG_FIFO_MUTEX - osal_mutex_def_t ep_out_ff_mutex_rd_3; // No need for write mutex as only USB driver writes into FIFO + tu_static osal_mutex_def_t ep_out_ff_mutex_rd_3; // No need for write mutex as only USB driver writes into FIFO #endif #endif // CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ > 0 #endif // CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING @@ -186,89 +186,89 @@ // - the software encoding is used - in this case the linear buffers serve as a target memory where logical channels are encoded into #if CFG_TUD_AUDIO_ENABLE_EP_OUT && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING) #if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX > 0 - CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_1[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX]; + tu_static CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_1[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX]; #endif #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX > 0 - CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_2[CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX]; + tu_static CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_2[CFG_TUD_AUDIO_FUNC_2_EP_OUT_SZ_MAX]; #endif #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX > 0 - CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_3[CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX]; + tu_static CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t lin_buf_out_3[CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX]; #endif #endif // CFG_TUD_AUDIO_ENABLE_EP_OUT && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING) // Control buffers -CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_1[CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ]; +tu_static CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_1[CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ]; #if CFG_TUD_AUDIO > 1 -CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_2[CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ]; +tu_static CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_2[CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ]; #endif #if CFG_TUD_AUDIO > 2 -CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_3[CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ]; +tu_static CFG_TUD_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf_3[CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ]; #endif // Active alternate setting of interfaces -uint8_t alt_setting_1[CFG_TUD_AUDIO_FUNC_1_N_AS_INT]; +tu_static uint8_t alt_setting_1[CFG_TUD_AUDIO_FUNC_1_N_AS_INT]; #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_N_AS_INT > 0 -uint8_t alt_setting_2[CFG_TUD_AUDIO_FUNC_2_N_AS_INT]; +tu_static uint8_t alt_setting_2[CFG_TUD_AUDIO_FUNC_2_N_AS_INT]; #endif #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_N_AS_INT > 0 -uint8_t alt_setting_3[CFG_TUD_AUDIO_FUNC_3_N_AS_INT]; +tu_static uint8_t alt_setting_3[CFG_TUD_AUDIO_FUNC_3_N_AS_INT]; #endif // Software encoding/decoding support FIFOs #if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING #if CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ > 0 - CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ]; - tu_fifo_t tx_supp_ff_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO]; + tu_static CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ]; + tu_static tu_fifo_t tx_supp_ff_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO]; #if CFG_FIFO_MUTEX - osal_mutex_def_t tx_supp_ff_mutex_wr_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO + tu_static osal_mutex_def_t tx_supp_ff_mutex_wr_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO #endif #endif #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0 - CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ]; - tu_fifo_t tx_supp_ff_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO]; + tu_static CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ]; + tu_static tu_fifo_t tx_supp_ff_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO]; #if CFG_FIFO_MUTEX - osal_mutex_def_t tx_supp_ff_mutex_wr_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO + tu_static osal_mutex_def_t tx_supp_ff_mutex_wr_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO #endif #endif #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ > 0 - CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ]; - tu_fifo_t tx_supp_ff_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO]; + tu_static CFG_TUSB_MEM_ALIGN uint8_t tx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ]; + tu_static tu_fifo_t tx_supp_ff_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO]; #if CFG_FIFO_MUTEX - osal_mutex_def_t tx_supp_ff_mutex_wr_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO + tu_static osal_mutex_def_t tx_supp_ff_mutex_wr_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO]; // No need for read mutex as only USB driver reads from FIFO #endif #endif #endif #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING #if CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ > 0 - CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ]; - tu_fifo_t rx_supp_ff_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO]; + tu_static CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ]; + tu_static tu_fifo_t rx_supp_ff_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO]; #if CFG_FIFO_MUTEX - osal_mutex_def_t rx_supp_ff_mutex_rd_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO + tu_static osal_mutex_def_t rx_supp_ff_mutex_rd_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO #endif #endif #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0 - CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ]; - tu_fifo_t rx_supp_ff_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO]; + tu_static CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ]; + tu_static tu_fifo_t rx_supp_ff_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO]; #if CFG_FIFO_MUTEX - osal_mutex_def_t rx_supp_ff_mutex_rd_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO + tu_static osal_mutex_def_t rx_supp_ff_mutex_rd_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO #endif #endif #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ > 0 - CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ]; - tu_fifo_t rx_supp_ff_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO]; + tu_static CFG_TUSB_MEM_ALIGN uint8_t rx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ]; + tu_static tu_fifo_t rx_supp_ff_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO]; #if CFG_FIFO_MUTEX - osal_mutex_def_t rx_supp_ff_mutex_rd_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO + tu_static osal_mutex_def_t rx_supp_ff_mutex_rd_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO]; // No need for write mutex as only USB driver writes into FIFO #endif #endif #endif @@ -432,7 +432,7 @@ typedef struct //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ -CFG_TUD_MEM_SECTION audiod_function_t _audiod_fct[CFG_TUD_AUDIO]; +tu_static CFG_TUD_MEM_SECTION audiod_function_t _audiod_fct[CFG_TUD_AUDIO]; #if CFG_TUD_AUDIO_ENABLE_EP_OUT static bool audiod_rx_done_cb(uint8_t rhport, audiod_function_t* audio, uint16_t n_bytes_received); -- cgit v1.3.1 From 02e129a38e14f0be1944290b6e68fafc571b0562 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sat, 23 Mar 2024 18:04:56 +0100 Subject: Guard ep_fb with usbd_edpt_claim(). --- src/class/audio/audio_device.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 16ba7fe65..dd82d54ac 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -2239,7 +2239,7 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 if (tud_audio_fb_done_cb) tud_audio_fb_done_cb(func_id); // Schedule a transmit with the new value if EP is not busy - if (!usbd_edpt_busy(rhport, audio->ep_fb)) + if (usbd_edpt_claim(rhport, audio->ep_fb)) { // Schedule next transmission - value is changed bytud_audio_n_fb_set() in the meantime or the old value gets sent return audiod_fb_send(audio); @@ -2314,7 +2314,7 @@ static void audiod_fb_fifo_count_update(audiod_function_t* audio, uint16_t lvl_n audio->feedback.value = feedback; // Schedule a transmit with the new value if EP is not busy - this triggers repetitive scheduling of the feedback value - if (!usbd_edpt_busy(audio->rhport, audio->ep_fb)) + if (usbd_edpt_claim(audio->rhport, audio->ep_fb)) { audiod_fb_send(audio); } @@ -2364,7 +2364,7 @@ bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback) _audiod_fct[func_id].feedback.value = feedback; // Schedule a transmit with the new value if EP is not busy - this triggers repetitive scheduling of the feedback value - if (!usbd_edpt_busy(_audiod_fct[func_id].rhport, _audiod_fct[func_id].ep_fb)) + if (usbd_edpt_claim(_audiod_fct[func_id].rhport, _audiod_fct[func_id].ep_fb)) { return audiod_fb_send(&_audiod_fct[func_id]); } -- cgit v1.3.1 From f69255e7355a7cd7c4cd08f50c6f1ba4fc3b5a45 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sun, 19 Nov 2023 23:59:20 +0100 Subject: Fix CI. --- src/portable/wch/dcd_ch32_usbhs.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src') diff --git a/src/portable/wch/dcd_ch32_usbhs.c b/src/portable/wch/dcd_ch32_usbhs.c index 1f1c0b876..43cda2566 100644 --- a/src/portable/wch/dcd_ch32_usbhs.c +++ b/src/portable/wch/dcd_ch32_usbhs.c @@ -135,6 +135,14 @@ void dcd_remote_wakeup(uint8_t rhport) (void) rhport; } +void dcd_sof_enable(uint8_t rhport, bool en) +{ + (void) rhport; + (void) en; + + // TODO implement later +} + void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const *request) { (void)rhport; -- cgit v1.3.1 From 0a70a66b07cebcdf1716ea0c1b301a6945c13839 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sun, 19 Nov 2023 23:43:36 +0100 Subject: Fix up TUD_AUDIO_SPEAKER_MONO_FB_DESCRIPTOR. --- src/device/usbd.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/device/usbd.h b/src/device/usbd.h index 0197628e2..17616f7b1 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -561,7 +561,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb /* Output Terminal Descriptor(4.7.2.5) */\ TUD_AUDIO_DESC_OUTPUT_TERM(/*_termid*/ 0x03, /*_termtype*/ AUDIO_TERM_TYPE_OUT_DESKTOP_SPEAKER, /*_assocTerm*/ 0x01, /*_srcid*/ 0x02, /*_clkid*/ 0x04, /*_ctrl*/ 0x0000, /*_stridx*/ 0x00),\ /* Feature Unit Descriptor(4.7.2.8) */\ - TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL(/*_unitid*/ 0x02, /*_srcid*/ 0x01, /*_ctrlch0master*/ 0 * (AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), /*_ctrlch1*/ 0 * (AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS), /*_stridx*/ 0x00),\ + TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL(/*_unitid*/ 0x02, /*_srcid*/ 0x01, /*_ctrlch0master*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_ctrlch1*/ AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_MUTE_POS | AUDIO_CTRL_RW << AUDIO_FEATURE_UNIT_CTRL_VOLUME_POS, /*_stridx*/ 0x00),\ /* Standard AS Interface Descriptor(4.9.1) */\ /* Interface 1, Alternate 0 - default alternate setting with 0 bandwidth */\ TUD_AUDIO_DESC_STD_AS_INT(/*_itfnum*/ (uint8_t)((_itfnum) + 1), /*_altset*/ 0x00, /*_nEPs*/ 0x00, /*_stridx*/ 0x00),\ @@ -577,7 +577,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000),\ /* Standard AS Isochronous Feedback Endpoint Descriptor(4.10.2.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_FB_EP(/*_ep*/ _epfb, /*_interval*/ 1)\ + TUD_AUDIO_DESC_STD_AS_ISO_FB_EP(/*_ep*/ _epfb, /*_interval*/ 1) // Calculate wMaxPacketSize of Endpoints #define TUD_AUDIO_EP_SIZE(_maxFrequency, _nBytesPerSample, _nChannels) \ -- cgit v1.3.1 From 73d61fa2b8af7ce01d1771a315775e01fc9b5825 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Wed, 8 May 2024 21:03:49 +0200 Subject: Migrate to weak default implementation. --- src/class/audio/audio_device.c | 252 ++++++++++++++++++++++++++--------------- src/class/audio/audio_device.h | 32 +++--- 2 files changed, 179 insertions(+), 105 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index dd82d54ac..555ecd4ea 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -429,6 +429,138 @@ typedef struct #define ITF_MEM_RESET_SIZE offsetof(audiod_function_t, ctrl_buf) +//--------------------------------------------------------------------+ +// WEAK FUNCTION STUBS +//--------------------------------------------------------------------+ + +#if CFG_TUD_AUDIO_ENABLE_EP_IN +TU_ATTR_WEAK bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t func_id, uint8_t ep_in, uint8_t cur_alt_setting) { + (void) rhport; + (void) func_id; + (void) ep_in; + (void) cur_alt_setting; + return true; +} + +TU_ATTR_WEAK bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uint8_t func_id, uint8_t ep_in, uint8_t cur_alt_setting) { + (void) rhport; + (void) n_bytes_copied; + (void) func_id; + (void) ep_in; + (void) cur_alt_setting; + return true; +} +#endif + +#if CFG_TUD_AUDIO_ENABLE_EP_OUT +TU_ATTR_WEAK bool tud_audio_rx_done_pre_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t func_id, uint8_t ep_out, uint8_t cur_alt_setting) { + (void) rhport; + (void) n_bytes_received; + (void) func_id; + (void) ep_out; + (void) cur_alt_setting; + return true; +} + +TU_ATTR_WEAK bool tud_audio_rx_done_post_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t func_id, uint8_t ep_out, uint8_t cur_alt_setting) { + (void) rhport; + (void) n_bytes_received; + (void) func_id; + (void) ep_out; + (void) cur_alt_setting; + return true; +} +#endif + +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP +TU_ATTR_WEAK void tud_audio_fb_done_cb(uint8_t func_id) { + (void) func_id; +} + +TU_ATTR_WEAK void tud_audio_feedback_params_cb(uint8_t func_id, uint8_t alt_itf, audio_feedback_params_t* feedback_param) { + (void) func_id; + (void) alt_itf; + feedback_param->method = AUDIO_FEEDBACK_METHOD_DISABLED; +} +#endif + +TU_ATTR_WEAK TU_ATTR_FAST_FUNC void tud_audio_feedback_interval_isr(uint8_t func_id, uint32_t frame_number, uint8_t interval_shift) { + (void) func_id; + (void) frame_number; + (void) interval_shift; +} + +#if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP +TU_ATTR_WEAK void tud_audio_int_done_cb(uint8_t rhport) { + (void) rhport; +} +#endif + +// Invoked when audio set interface request received +TU_ATTR_WEAK bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request) { + (void) rhport; + (void) p_request; + return true; +} + +// Invoked when audio set interface request received which closes an EP +TU_ATTR_WEAK bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const * p_request) { + (void) rhport; + (void) p_request; + return true; +} + +// Invoked when audio class specific set request received for an EP +TU_ATTR_WEAK bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff) { + (void) rhport; + (void) p_request; + (void) pBuff; + TU_LOG2(" No EP set request callback available!\r\n"); + return false; // In case no callback function is present or request can not be conducted we stall it +} + +// Invoked when audio class specific set request received for an interface +TU_ATTR_WEAK bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff) { + (void) rhport; + (void) p_request; + (void) pBuff; + TU_LOG2(" No interface set request callback available!\r\n"); + return false; // In case no callback function is present or request can not be conducted we stall it +} + +// Invoked when audio class specific set request received for an entity +TU_ATTR_WEAK bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff) { + (void) rhport; + (void) p_request; + (void) pBuff; + TU_LOG2(" No entity set request callback available!\r\n"); + return false; // In case no callback function is present or request can not be conducted we stall it +} + +// Invoked when audio class specific get request received for an EP +TU_ATTR_WEAK bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request) { + (void) rhport; + (void) p_request; + TU_LOG2(" No EP get request callback available!\r\n"); + return false; // Stall +} + +// Invoked when audio class specific get request received for an interface +TU_ATTR_WEAK bool tud_audio_get_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request) { + (void) rhport; + (void) p_request; + TU_LOG2(" No interface get request callback available!\r\n"); + return false; // Stall +} + +// Invoked when audio class specific get request received for an entity +TU_ATTR_WEAK bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request) { + (void) rhport; + (void) p_request; + TU_LOG2(" No entity get request callback available!\r\n"); + return false; // Stall +} + //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ @@ -557,17 +689,11 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_function_t* audio, uint16_t uint8_t const *dummy2; uint8_t idx_audio_fct = 0; - if (tud_audio_rx_done_pre_read_cb || tud_audio_rx_done_post_read_cb) - { - idx_audio_fct = audiod_get_audio_fct_idx(audio); - TU_VERIFY(audiod_get_AS_interface_index(audio->ep_out_as_intf_num, audio, &idxItf, &dummy2)); - } + idx_audio_fct = audiod_get_audio_fct_idx(audio); + TU_VERIFY(audiod_get_AS_interface_index(audio->ep_out_as_intf_num, audio, &idxItf, &dummy2)); // Call a weak callback here - a possibility for user to get informed an audio packet was received and data gets now loaded into EP FIFO (or decoded into support RX software FIFO) - if (tud_audio_rx_done_pre_read_cb) - { - TU_VERIFY(tud_audio_rx_done_pre_read_cb(rhport, n_bytes_received, idx_audio_fct, audio->ep_out, audio->alt_setting[idxItf])); - } + TU_VERIFY(tud_audio_rx_done_pre_read_cb(rhport, n_bytes_received, idx_audio_fct, audio->ep_out, audio->alt_setting[idxItf])); #if CFG_TUD_AUDIO_ENABLE_DECODING @@ -628,10 +754,7 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_function_t* audio, uint16_t #endif // Call a weak callback here - a possibility for user to get informed decoding was completed - if (tud_audio_rx_done_post_read_cb) - { - TU_VERIFY(tud_audio_rx_done_post_read_cb(rhport, n_bytes_received, idx_audio_fct, audio->ep_out, audio->alt_setting[idxItf])); - } + TU_VERIFY(tud_audio_rx_done_post_read_cb(rhport, n_bytes_received, idx_audio_fct, audio->ep_out, audio->alt_setting[idxItf])); return true; } @@ -865,7 +988,7 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_function_t * audio) // Call a weak callback here - a possibility for user to get informed former TX was completed and data gets now loaded into EP in buffer (in case FIFOs are used) or // if no FIFOs are used the user may use this call back to load its data into the EP IN buffer by use of tud_audio_n_write_ep_in_buffer(). - if (tud_audio_tx_done_pre_load_cb) TU_VERIFY(tud_audio_tx_done_pre_load_cb(rhport, idx_audio_fct, audio->ep_in, audio->alt_setting[idxItf])); + TU_VERIFY(tud_audio_tx_done_pre_load_cb(rhport, idx_audio_fct, audio->ep_in, audio->alt_setting[idxItf])); // Send everything in ISO EP FIFO uint16_t n_bytes_tx; @@ -928,7 +1051,7 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_function_t * audio) #endif // Call a weak callback here - a possibility for user to get informed former TX was completed and how many bytes were loaded for the next frame - if (tud_audio_tx_done_post_load_cb) TU_VERIFY(tud_audio_tx_done_post_load_cb(rhport, n_bytes_tx, idx_audio_fct, audio->ep_in, audio->alt_setting[idxItf])); + TU_VERIFY(tud_audio_tx_done_post_load_cb(rhport, n_bytes_tx, idx_audio_fct, audio->ep_in, audio->alt_setting[idxItf])); return true; } @@ -1723,7 +1846,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * #endif // Invoke callback - can be used to stop data sampling - if (tud_audio_set_itf_close_EP_cb) TU_VERIFY(tud_audio_set_itf_close_EP_cb(rhport, p_request)); + TU_VERIFY(tud_audio_set_itf_close_EP_cb(rhport, p_request)); audio->ep_in = 0; // Necessary? @@ -1754,7 +1877,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * #endif // Invoke callback - can be used to stop data sampling - if (tud_audio_set_itf_close_EP_cb) TU_VERIFY(tud_audio_set_itf_close_EP_cb(rhport, p_request)); + TU_VERIFY(tud_audio_set_itf_close_EP_cb(rhport, p_request)); audio->ep_out = 0; // Necessary? @@ -1870,9 +1993,6 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * { audio->ep_fb = ep_addr; audio->feedback.frame_shift = desc_ep->bInterval -1; - - // Enable SOF interrupt if callback is implemented - if (tud_audio_feedback_interval_isr) usbd_sof_enable(rhport, true); } #endif #endif // CFG_TUD_AUDIO_ENABLE_EP_OUT @@ -1885,11 +2005,11 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * TU_VERIFY(foundEPs == nEps); // Invoke one callback for a final set interface - if (tud_audio_set_itf_cb) TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); + TU_VERIFY(tud_audio_set_itf_cb(rhport, p_request)); #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - // Prepare feedback computation if callback is available - if (tud_audio_feedback_params_cb) + // Prepare feedback computation if endpoint is available + if(audio->ep_fb != 0) { audio_feedback_params_t fb_param; @@ -1907,6 +2027,8 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * case AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT: case AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2: audiod_set_fb_params_freq(audio, fb_param.sample_freq, fb_param.frequency.mclk_freq); + // Enable SOF interrupt + usbd_sof_enable(rhport, true); break; case AUDIO_FEEDBACK_METHOD_FIFO_COUNT: @@ -1983,35 +2105,19 @@ static bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const if (entityID != 0) { - if (tud_audio_set_req_entity_cb) - { - // Check if entity is present and get corresponding driver index - TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id)); + // Check if entity is present and get corresponding driver index + TU_VERIFY(audiod_verify_entity_exists(itf, entityID, &func_id)); - // Invoke callback - return tud_audio_set_req_entity_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); - } - else - { - TU_LOG2(" No entity set request callback available!\r\n"); - return false; // In case no callback function is present or request can not be conducted we stall it - } + // Invoke callback + return tud_audio_set_req_entity_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); } else { - if (tud_audio_set_req_itf_cb) - { - // Find index of audio driver structure and verify interface really exists - TU_VERIFY(audiod_verify_itf_exists(itf, &func_id)); + // Find index of audio driver structure and verify interface really exists + TU_VERIFY(audiod_verify_itf_exists(itf, &func_id)); - // Invoke callback - return tud_audio_set_req_itf_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); - } - else - { - TU_LOG2(" No interface set request callback available!\r\n"); - return false; // In case no callback function is present or request can not be conducted we stall it - } + // Invoke callback + return tud_audio_set_req_itf_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); } } break; @@ -2020,19 +2126,11 @@ static bool audiod_control_complete(uint8_t rhport, tusb_control_request_t const { uint8_t ep = TU_U16_LOW(p_request->wIndex); - if (tud_audio_set_req_ep_cb) - { - // Check if entity is present and get corresponding driver index - TU_VERIFY(audiod_verify_ep_exists(ep, &func_id)); + // Check if entity is present and get corresponding driver index + TU_VERIFY(audiod_verify_ep_exists(ep, &func_id)); - // Invoke callback - return tud_audio_set_req_ep_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); - } - else - { - TU_LOG2(" No EP set request callback available!\r\n"); - return false; // In case no callback function is present or request can not be conducted we stall it - } + // Invoke callback + return tud_audio_set_req_ep_cb(rhport, p_request, _audiod_fct[func_id].ctrl_buf); } break; // Unknown/Unsupported recipient @@ -2089,15 +2187,7 @@ static bool audiod_control_request(uint8_t rhport, tusb_control_request_t const // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) { - if (tud_audio_get_req_entity_cb) - { - return tud_audio_get_req_entity_cb(rhport, p_request); - } - else - { - TU_LOG2(" No entity get request callback available!\r\n"); - return false; // Stall - } + return tud_audio_get_req_entity_cb(rhport, p_request); } } else @@ -2108,15 +2198,7 @@ static bool audiod_control_request(uint8_t rhport, tusb_control_request_t const // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) { - if (tud_audio_get_req_itf_cb) - { - return tud_audio_get_req_itf_cb(rhport, p_request); - } - else - { - TU_LOG2(" No interface get request callback available!\r\n"); - return false; // Stall - } + return tud_audio_get_req_itf_cb(rhport, p_request); } } } @@ -2132,15 +2214,7 @@ static bool audiod_control_request(uint8_t rhport, tusb_control_request_t const // In case we got a get request invoke callback - callback needs to answer as defined in UAC2 specification page 89 - 5. Requests if (p_request->bmRequestType_bit.direction == TUSB_DIR_IN) { - if (tud_audio_get_req_ep_cb) - { - return tud_audio_get_req_ep_cb(rhport, p_request); - } - else - { - TU_LOG2(" No EP get request callback available!\r\n"); - return false; // Stall - } + return tud_audio_get_req_ep_cb(rhport, p_request); } } break; @@ -2195,7 +2269,7 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 // I assume here, that things above are handled by PHY // All transmission is done - what remains to do is to inform job was completed - if (tud_audio_int_done_cb) tud_audio_int_done_cb(rhport); + tud_audio_int_done_cb(rhport); return true; } @@ -2236,7 +2310,7 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 // Transmission of feedback EP finished if (audio->ep_fb == ep_addr) { - if (tud_audio_fb_done_cb) tud_audio_fb_done_cb(func_id); + tud_audio_fb_done_cb(func_id); // Schedule a transmit with the new value if EP is not busy if (usbd_edpt_claim(rhport, audio->ep_fb)) @@ -2397,7 +2471,7 @@ TU_ATTR_FAST_FUNC void audiod_sof_isr (uint8_t rhport, uint32_t frame_count) uint32_t const interval = 1UL << (audio->feedback.frame_shift - hs_adjust); if ( 0 == (frame_count & (interval-1)) ) { - if(tud_audio_feedback_interval_isr) tud_audio_feedback_interval_isr(i, frame_count, audio->feedback.frame_shift); + tud_audio_feedback_interval_isr(i, frame_count, audio->feedback.frame_shift); } } } diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 9c95ce1a9..0d658de7c 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -451,17 +451,17 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req //--------------------------------------------------------------------+ #if CFG_TUD_AUDIO_ENABLE_EP_IN -TU_ATTR_WEAK bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t func_id, uint8_t ep_in, uint8_t cur_alt_setting); -TU_ATTR_WEAK bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uint8_t func_id, uint8_t ep_in, uint8_t cur_alt_setting); +bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t func_id, uint8_t ep_in, uint8_t cur_alt_setting); +bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uint8_t func_id, uint8_t ep_in, uint8_t cur_alt_setting); #endif #if CFG_TUD_AUDIO_ENABLE_EP_OUT -TU_ATTR_WEAK bool tud_audio_rx_done_pre_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t func_id, uint8_t ep_out, uint8_t cur_alt_setting); -TU_ATTR_WEAK bool tud_audio_rx_done_post_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t func_id, uint8_t ep_out, uint8_t cur_alt_setting); +bool tud_audio_rx_done_pre_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t func_id, uint8_t ep_out, uint8_t cur_alt_setting); +bool tud_audio_rx_done_post_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t func_id, uint8_t ep_out, uint8_t cur_alt_setting); #endif #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -TU_ATTR_WEAK void tud_audio_fb_done_cb(uint8_t func_id); +void tud_audio_fb_done_cb(uint8_t func_id); // determined by the user itself and set by use of tud_audio_n_fb_set(). The feedback value may be determined e.g. from some fill status of some FIFO buffer. Advantage: No ISR interrupt is enabled, hence the CPU need not to handle an ISR every 1ms or 125us and thus less CPU load, disadvantage: typically a larger FIFO is needed to compensate for jitter (e.g. 8 frames), i.e. a larger delay is introduced. @@ -516,43 +516,43 @@ typedef struct { }audio_feedback_params_t; // Invoked when needed to set feedback parameters -TU_ATTR_WEAK void tud_audio_feedback_params_cb(uint8_t func_id, uint8_t alt_itf, audio_feedback_params_t* feedback_param); +void tud_audio_feedback_params_cb(uint8_t func_id, uint8_t alt_itf, audio_feedback_params_t* feedback_param); // Callback in ISR context, invoked periodically according to feedback endpoint bInterval. // Could be used to compute and update feedback value, should be placed in RAM if possible // frame_number : current SOF count // interval_shift: number of bit shift i.e log2(interval) from Feedback endpoint descriptor -TU_ATTR_WEAK TU_ATTR_FAST_FUNC void tud_audio_feedback_interval_isr(uint8_t func_id, uint32_t frame_number, uint8_t interval_shift); +TU_ATTR_FAST_FUNC void tud_audio_feedback_interval_isr(uint8_t func_id, uint32_t frame_number, uint8_t interval_shift); #endif // CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP #if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP -TU_ATTR_WEAK void tud_audio_int_done_cb(uint8_t rhport); +void tud_audio_int_done_cb(uint8_t rhport); #endif // Invoked when audio set interface request received -TU_ATTR_WEAK bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request); +bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request); // Invoked when audio set interface request received which closes an EP -TU_ATTR_WEAK bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const * p_request); +bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const * p_request); // Invoked when audio class specific set request received for an EP -TU_ATTR_WEAK bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff); +bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff); // Invoked when audio class specific set request received for an interface -TU_ATTR_WEAK bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff); +bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff); // Invoked when audio class specific set request received for an entity -TU_ATTR_WEAK bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff); +bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff); // Invoked when audio class specific get request received for an EP -TU_ATTR_WEAK bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request); +bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request); // Invoked when audio class specific get request received for an interface -TU_ATTR_WEAK bool tud_audio_get_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request); +bool tud_audio_get_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request); // Invoked when audio class specific get request received for an entity -TU_ATTR_WEAK bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request); +bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request); //--------------------------------------------------------------------+ // Inline Functions -- cgit v1.3.1 From 8dc767fa1dd768878ed8bd8541398b0722875066 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Wed, 8 May 2024 22:31:30 +0200 Subject: Fix cycle based feedback calculation. --- src/class/audio/audio_device.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 555ecd4ea..c0a8d1d72 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -66,8 +66,10 @@ //--------------------------------------------------------------------+ // Use ring buffer if it's available, some MCUs need extra RAM requirements +// For DWC2 enable ring buffer will disable DMA (if available) #ifndef TUD_AUDIO_PREFER_RING_BUFFER - #if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT1XXX + #if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT1XXX || \ + defined(TUP_USBIP_DWC2) #define TUD_AUDIO_PREFER_RING_BUFFER 0 #else #define TUD_AUDIO_PREFER_RING_BUFFER 1 @@ -2347,11 +2349,11 @@ static bool audiod_set_fb_params_freq(audiod_function_t* audio, uint32_t sample_ if ((mclk_freq % sample_freq) == 0 && tu_is_power_of_two(mclk_freq / sample_freq)) { audio->feedback.compute_method = AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2; - audio->feedback.compute.power_of_2 = 16 - audio->feedback.frame_shift - tu_log2(mclk_freq / sample_freq); + audio->feedback.compute.power_of_2 = 16 - (audio->feedback.frame_shift - 1) - tu_log2(mclk_freq / sample_freq); } else if ( audio->feedback.compute_method == AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT) { - audio->feedback.compute.float_const = (float)sample_freq / mclk_freq * (1UL << (16 - audio->feedback.frame_shift)); + audio->feedback.compute.float_const = (float)sample_freq / mclk_freq * (1UL << (16 - (audio->feedback.frame_shift - 1))); } else { @@ -2411,7 +2413,7 @@ uint32_t tud_audio_feedback_update(uint8_t func_id, uint32_t cycles) case AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED: { - uint64_t fb64 = (((uint64_t) cycles) * audio->feedback.compute.fixed.sample_freq) << (16 - audio->feedback.frame_shift); + uint64_t fb64 = (((uint64_t) cycles) * audio->feedback.compute.fixed.sample_freq) << (16 - (audio->feedback.frame_shift - 1)); feedback = (uint32_t) (fb64 / audio->feedback.compute.fixed.mclk_freq); } break; -- cgit v1.3.1 From ab539895a5be8138ae60aecedac6d32a1748bffc Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Wed, 8 May 2024 23:08:47 +0200 Subject: Reorganize feedback documentation. --- src/class/audio/audio_device.h | 53 +++++++++++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 0d658de7c..5a1c51eaf 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -243,7 +243,8 @@ // Enable encoding/decodings - for these to work, support FIFOs need to be setup in appropriate numbers and size // The actual coding parameters of active AS alternate interface is parsed from the descriptors -// The item size of the FIFO is always fixed to one i.e. bytes! Furthermore, the actively used FIFO depth is reconfigured such that the depth is a multiple of the current sample size in order to avoid samples to get split up in case of a wrap in the FIFO ring buffer (depth = (max_depth / sampe_sz) * sampe_sz)! +// The item size of the FIFO is always fixed to one i.e. bytes! Furthermore, the actively used FIFO depth is reconfigured such that the depth is a multiple +// of the current sample size in order to avoid samples to get split up in case of a wrap in the FIFO ring buffer (depth = (max_depth / sample_sz) * sample_sz)! // This is important to remind in case you use DMAs! If the sample sizes changes, the DMA MUST BE RECONFIGURED just like the FIFOs for a different depth!!! // For PCM encoding/decoding @@ -447,7 +448,7 @@ static inline bool tud_audio_int_write (const audio_interru bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_request_t const * p_request, void* data, uint16_t len); //--------------------------------------------------------------------+ -// Application Callback API (weak is optional) +// Application Callback API //--------------------------------------------------------------------+ #if CFG_TUD_AUDIO_ENABLE_EP_IN @@ -464,42 +465,62 @@ bool tud_audio_rx_done_post_read_cb(uint8_t rhport, uint16_t n_bytes_received, u void tud_audio_fb_done_cb(uint8_t func_id); -// determined by the user itself and set by use of tud_audio_n_fb_set(). The feedback value may be determined e.g. from some fill status of some FIFO buffer. Advantage: No ISR interrupt is enabled, hence the CPU need not to handle an ISR every 1ms or 125us and thus less CPU load, disadvantage: typically a larger FIFO is needed to compensate for jitter (e.g. 8 frames), i.e. a larger delay is introduced. - -// Feedback value is calculated within the audio driver by use of SOF interrupt. The driver needs information about the master clock f_m from which the audio sample frequency f_s is derived, f_s itself, and the cycle count of f_m at time of the SOF interrupt (e.g. by use of a hardware counter) - see tud_audio_set_fb_params(). Advantage: Reduced jitter in the feedback value computation, hence, the receive FIFO can be smaller (e.g. 2 frames) and thus a smaller delay is possible, disadvantage: higher CPU load due to SOF ISR handling every frame i.e. 1ms or 125us. This option is a great starting point to try the SOF ISR option but depending on your hardware setup (performance of the CPU) it might not work. If so, figure out why and use the next option. (The most critical point is the reading of the cycle counter value of f_m. It is read from within the SOF ISR - see: audiod_sof() -, hence, the ISR must has a high priority such that no software dependent "random" delay i.e. jitter is introduced). +// Note about feedback calculation +// +// Option 1 - AUDIO_FEEDBACK_METHOD_FIFO_COUNT +// Feedback value is calculated within the audio driver by regulating the FIFO level to half fill. +// Advantage: No ISR interrupt is enabled, hence the CPU need not to handle an ISR every 1ms or 125us and thus less CPU load, well tested +// (Windows, Linux, OSX) with a reliable result so far. +// Disadvantage: A FIFO of minimal 4 frames is needed to compensate for jitter, an average delay of 2 frames is introduced. +// +// Option 2 - AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED / AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT +// Feedback value is calculated within the audio driver by use of SOF interrupt. The driver needs information about the master clock f_m from +// which the audio sample frequency f_s is derived, f_s itself, and the cycle count of f_m at time of the SOF interrupt (e.g. by use of a hardware counter). +// See tud_audio_set_fb_params() and tud_audio_feedback_update() +// Advantage: Reduced jitter in the feedback value computation, hence, the receive FIFO can be smaller and thus a smaller delay is possible. +// Disadvantage: higher CPU load due to SOF ISR handling every frame i.e. 1ms or 125us. (The most critical point is the reading of the cycle counter value of f_m. +// It is read from within the SOF ISR - see: audiod_sof() -, hence, the ISR must has a high priority such that no software dependent "random" delay i.e. jitter is introduced). +// Long-term drift could occur since error is accumulated. +// +// Option 3 - manual +// Determined by the user itself and set by use of tud_audio_n_fb_set(). The feedback value may be determined e.g. from some fill status of some FIFO buffer. +// Advantage: No ISR interrupt is enabled, hence the CPU need not to handle an ISR every 1ms or 125us and thus less CPU load. +// Disadvantage: typically a larger FIFO is needed to compensate for jitter (e.g. 6 frames), i.e. a larger delay is introduced. -// Feedback value is determined by the user by use of SOF interrupt. The user may use tud_audio_sof_isr() which is called every SOF (of course only invoked when an alternate interface other than zero was set). The number of frames used to determine the feedback value for the currently active alternate setting can be get by tud_audio_get_fb_n_frames(). The feedback value must be set by use of tud_audio_n_fb_set(). // This function is used to provide data rate feedback from an asynchronous sink. Feedback value will be sent at FB endpoint interval till it's changed. // // The feedback format is specified to be 16.16 for HS and 10.14 for FS devices (see Universal Serial Bus Specification Revision 2.0 5.12.4.2). By default, -// the choice of format is left to the caller and feedback argument is sent as-is. If CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION is set, then tinyusb -// expects 16.16 format and handles the conversion to 10.14 on FS. +// the choice of format is left to the caller and feedback argument is sent as-is. If CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION is set +// then tinyusb expects 16.16 format and handles the conversion to 10.14 on FS. +// +// Note that due to a bug in its USB Audio 2.0 driver, Windows currently requires 16.16 format for _all_ USB 2.0 devices. On Linux and it seems the +// driver can work with either format. // -// Note that due to a bug in its USB Audio 2.0 driver, Windows currently requires 16.16 format for _all_ USB 2.0 devices. On Linux and macOS it seems the -// driver can work with either format. So a good compromise is to keep format correction disabled and stick to 16.16 format. - // Feedback value can be determined from within the SOF ISR of the audio driver. This should reduce jitter. If the feature is used, the user can not set the feedback value. - +// // Determine feedback value - The feedback method is described in 5.12.4.2 of the USB 2.0 spec // Boiled down, the feedback value Ff = n_samples / (micro)frame. -// Since an accuracy of less than 1 Sample / second is desired, at least n_frames = ceil(2^K * f_s / f_m) frames need to be measured, where K = 10 for full speed and K = 13 for high speed, f_s is the sampling frequency e.g. 48 kHz and f_m is the cpu clock frequency e.g. 100 MHz (or any other master clock whose clock count is available and locked to f_s) +// Since an accuracy of less than 1 Sample / second is desired, at least n_frames = ceil(2^K * f_s / f_m) frames need to be measured, where K = 10 for full speed and K = 13 +// for high speed, f_s is the sampling frequency e.g. 48 kHz and f_m is the cpu clock frequency e.g. 100 MHz (or any other master clock whose clock count is available and locked to f_s) // The update interval in the (4.10.2.1) Feedback Endpoint Descriptor must be less or equal to 2^(K - P), where P = min( ceil(log2(f_m / f_s)), K) // feedback = n_cycles / n_frames * f_s / f_m in 16.16 format, where n_cycles are the number of main clock cycles within fb_n_frames - bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback); -// Update feedback value with passed cycles since last time this update function is called. +// Update feedback value with passed MCLK cycles since last time this update function is called. // Typically called within tud_audio_sof_isr(). Required tud_audio_feedback_params_cb() is implemented // This function will also call tud_audio_feedback_set() // return feedback value in 16.16 for reference (0 for error) +// Example : +// binterval=3 (4ms); FS = 48kHz; MCLK = 12.288MHz +// In 4 SOF MCLK counted 49152 cycles uint32_t tud_audio_feedback_update(uint8_t func_id, uint32_t cycles); enum { AUDIO_FEEDBACK_METHOD_DISABLED, AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED, AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT, - AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2, + AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2, // For driver internal use only AUDIO_FEEDBACK_METHOD_FIFO_COUNT }; -- cgit v1.3.1 From 0e907b49c90d53023731dd1e21bbdcb1fdb95e11 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Wed, 8 May 2024 23:17:56 +0200 Subject: Add callback to to set feedback format correction at runtime. --- src/class/audio/audio_device.c | 23 +++++++++++++---------- src/class/audio/audio_device.h | 8 ++++++-- 2 files changed, 19 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index c0a8d1d72..77645c412 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -329,7 +329,7 @@ typedef struct uint8_t frame_shift; // bInterval-1 in unit of frame (FS), micro-frame (HS) uint8_t compute_method; - + bool format_correction; union { uint8_t power_of_2; // pre-computed power of 2 shift float float_const; // pre-computed float constant @@ -484,6 +484,11 @@ TU_ATTR_WEAK void tud_audio_feedback_params_cb(uint8_t func_id, uint8_t alt_itf, (void) alt_itf; feedback_param->method = AUDIO_FEEDBACK_METHOD_DISABLED; } + +TU_ATTR_WEAK bool tud_audio_feedback_format_correction_cb(uint8_t func_id) { + (void) func_id; + return CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION; +} #endif TU_ATTR_WEAK TU_ATTR_FAST_FUNC void tud_audio_feedback_interval_isr(uint8_t func_id, uint32_t frame_number, uint8_t interval_shift) { @@ -1211,9 +1216,9 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP static inline bool audiod_fb_send(audiod_function_t *audio) { + bool apply_correction = TUSB_SPEED_FULL == tud_speed_get() && audio->feedback.format_correction; // Format the feedback value -#if CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION - if ( TUSB_SPEED_FULL == tud_speed_get() ) + if (apply_correction) { uint8_t * fb = (uint8_t *) &audio->feedback.send_buf; @@ -1221,17 +1226,12 @@ static inline bool audiod_fb_send(audiod_function_t *audio) *(fb++) = (audio->feedback.value >> 2) & 0xFF; *(fb++) = (audio->feedback.value >> 10) & 0xFF; *(fb++) = (audio->feedback.value >> 18) & 0xFF; - // 4th byte is needed to work correctly with MS Windows - *fb = 0; } else { - value = audio->feedback.value; + audio->feedback.send_buf = audio->feedback.value; } -#else - audio->feedback.send_buf = audio->feedback.value; -#endif - return usbd_edpt_xfer(audio->rhport, audio->ep_fb, (uint8_t *) &audio->feedback.send_buf, 4); + return usbd_edpt_xfer(audio->rhport, audio->ep_fb, (uint8_t *) &audio->feedback.send_buf, apply_correction ? 3 : 4); } #endif @@ -2018,6 +2018,9 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * tud_audio_feedback_params_cb(func_id, alt, &fb_param); audio->feedback.compute_method = fb_param.method; + if(TUSB_SPEED_FULL == tud_speed_get()) + audio->feedback.format_correction = tud_audio_feedback_format_correction_cb(func_id); + // Minimal/Maximum value in 16.16 format for full speed (1ms per frame) or high speed (125 us per frame) uint32_t const frame_div = (TUSB_SPEED_FULL == tud_speed_get()) ? 1000 : 8000; audio->feedback.min_value = ((fb_param.sample_freq - 1)/frame_div) << 16; diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 5a1c51eaf..ae253f49d 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -193,6 +193,7 @@ #endif // Enable/disable conversion from 16.16 to 10.14 format on full-speed devices. See tud_audio_n_fb_set(). +// Can be override by tud_audio_feedback_format_correction_cb() #ifndef CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION #define CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION 0 // 0 or 1 #endif @@ -491,8 +492,8 @@ void tud_audio_fb_done_cb(uint8_t func_id); // This function is used to provide data rate feedback from an asynchronous sink. Feedback value will be sent at FB endpoint interval till it's changed. // // The feedback format is specified to be 16.16 for HS and 10.14 for FS devices (see Universal Serial Bus Specification Revision 2.0 5.12.4.2). By default, -// the choice of format is left to the caller and feedback argument is sent as-is. If CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION is set -// then tinyusb expects 16.16 format and handles the conversion to 10.14 on FS. +// the choice of format is left to the caller and feedback argument is sent as-is. If CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION is set or tud_audio_feedback_format_correction_cb() +// return true, then tinyusb expects 16.16 format and handles the conversion to 10.14 on FS. // // Note that due to a bug in its USB Audio 2.0 driver, Windows currently requires 16.16 format for _all_ USB 2.0 devices. On Linux and it seems the // driver can work with either format. @@ -545,6 +546,9 @@ void tud_audio_feedback_params_cb(uint8_t func_id, uint8_t alt_itf, audio_feedba // interval_shift: number of bit shift i.e log2(interval) from Feedback endpoint descriptor TU_ATTR_FAST_FUNC void tud_audio_feedback_interval_isr(uint8_t func_id, uint32_t frame_number, uint8_t interval_shift); +// (Full-Speed only) Callback to set feedback format correction is applied or not, +// default to CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION if not implemented. +bool tud_audio_feedback_format_correction_cb(uint8_t func_id); #endif // CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP #if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP -- cgit v1.3.1 From fc7647f9e4f06c8f56207f5ea7f34872887d099b Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 10 May 2024 00:11:04 +0200 Subject: Allow feedback EP size change. --- examples/device/uac2_speaker_fb/src/tusb_config.h | 3 +++ examples/device/uac2_speaker_fb/src/usb_descriptors.c | 4 ++-- examples/device/uac2_speaker_fb/src/usb_descriptors.h | 6 +++--- src/device/usbd.h | 10 +++++----- 4 files changed, 13 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/examples/device/uac2_speaker_fb/src/tusb_config.h b/examples/device/uac2_speaker_fb/src/tusb_config.h index 497104541..1cc1031c1 100644 --- a/examples/device/uac2_speaker_fb/src/tusb_config.h +++ b/examples/device/uac2_speaker_fb/src/tusb_config.h @@ -122,6 +122,9 @@ extern "C" { #define CFG_TUD_AUDIO_FUNC_1_DESC_LEN TUD_AUDIO_SPEAKER_STEREO_FB_DESC_LEN +// Enable if Full-Speed on OSX, also set feedback EP size to 3 +#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION 0 + // Audio format type I specifications #if defined(__RX__) #define CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE 48000 diff --git a/examples/device/uac2_speaker_fb/src/usb_descriptors.c b/examples/device/uac2_speaker_fb/src/usb_descriptors.c index 864b689ff..fa307674d 100644 --- a/examples/device/uac2_speaker_fb/src/usb_descriptors.c +++ b/examples/device/uac2_speaker_fb/src/usb_descriptors.c @@ -149,8 +149,8 @@ uint8_t const desc_configuration[] = // Config number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), - // Interface number, string index, byte per sample, bit per sample, EP Out, EP size, EP feedback - TUD_AUDIO_SPEAKER_STEREO_FB_DESCRIPTOR(0, 4, CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_RESOLUTION_RX, EPNUM_AUDIO_OUT, CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX, EPNUM_AUDIO_FB | 0x80), + // Interface number, string index, byte per sample, bit per sample, EP Out, EP size, EP feedback, feedback EP size, + TUD_AUDIO_SPEAKER_STEREO_FB_DESCRIPTOR(0, 4, CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_RESOLUTION_RX, EPNUM_AUDIO_OUT, CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX, EPNUM_AUDIO_FB | 0x80, 4), #if CFG_AUDIO_DEBUG // Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval diff --git a/examples/device/uac2_speaker_fb/src/usb_descriptors.h b/examples/device/uac2_speaker_fb/src/usb_descriptors.h index 8157f02a0..9511bf797 100644 --- a/examples/device/uac2_speaker_fb/src/usb_descriptors.h +++ b/examples/device/uac2_speaker_fb/src/usb_descriptors.h @@ -47,7 +47,7 @@ + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN\ + TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN) -#define TUD_AUDIO_SPEAKER_STEREO_FB_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epout, _epsize, _epfb) \ +#define TUD_AUDIO_SPEAKER_STEREO_FB_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epout, _epoutsize, _epfb, _epfbsize) \ /* Standard Interface Association Descriptor (IAD) */\ TUD_AUDIO_DESC_IAD(/*_firstitf*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\ /* Standard AC Interface Descriptor(4.7.1) */\ @@ -73,10 +73,10 @@ /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\ /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ASYNCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ 0x01),\ + TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ASYNCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epoutsize, /*_interval*/ 0x01),\ /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_MILLISEC, /*_lockdelay*/ 0x0001),\ /* Standard AS Isochronous Feedback Endpoint Descriptor(4.10.2.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_FB_EP(/*_ep*/ _epfb, /*_interval*/ TUD_OPT_HIGH_SPEED ? 4 : 1)\ + TUD_AUDIO_DESC_STD_AS_ISO_FB_EP(/*_ep*/ _epfb, /*_epsize*/ _epfbsize, /*_interval*/ TUD_OPT_HIGH_SPEED ? 4 : 1)\ #endif diff --git a/src/device/usbd.h b/src/device/usbd.h index d6f6f923d..3caaaca25 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -428,8 +428,8 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb /* Standard AS Isochronous Feedback Endpoint Descriptor(4.10.2.1) */ #define TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN 7 -#define TUD_AUDIO_DESC_STD_AS_ISO_FB_EP(_ep, _interval) \ - TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN, TUSB_DESC_ENDPOINT, _ep, (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_NO_SYNC | (uint8_t)TUSB_ISO_EP_ATT_EXPLICIT_FB), U16_TO_U8S_LE(4), _interval +#define TUD_AUDIO_DESC_STD_AS_ISO_FB_EP(_ep, _epsize, _interval) \ + TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN, TUSB_DESC_ENDPOINT, _ep, (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_NO_SYNC | (uint8_t)TUSB_ISO_EP_ATT_EXPLICIT_FB), U16_TO_U8S_LE(_epsize), _interval // AUDIO simple descriptor (UAC2) for 1 microphone input // - 1 Input Terminal, 1 Feature Unit (Mute and Volume Control), 1 Output Terminal, 1 Clock Source @@ -547,7 +547,7 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb + TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN\ + TUD_AUDIO_DESC_STD_AS_ISO_FB_EP_LEN) -#define TUD_AUDIO_SPEAKER_MONO_FB_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epout, _epsize, _epfb) \ +#define TUD_AUDIO_SPEAKER_MONO_FB_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epout, _epoutsize, _epfb, _epfbsize) \ /* Standard Interface Association Descriptor (IAD) */\ TUD_AUDIO_DESC_IAD(/*_firstitf*/ _itfnum, /*_nitfs*/ 0x02, /*_stridx*/ 0x00),\ /* Standard AC Interface Descriptor(4.7.1) */\ @@ -573,11 +573,11 @@ TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb /* Type I Format Type Descriptor(2.3.1.6 - Audio Formats) */\ TUD_AUDIO_DESC_TYPE_I_FORMAT(_nBytesPerSample, _nBitsUsedPerSample),\ /* Standard AS Isochronous Audio Data Endpoint Descriptor(4.10.1.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ASYNCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epsize, /*_interval*/ 0x01),\ + TUD_AUDIO_DESC_STD_AS_ISO_EP(/*_ep*/ _epout, /*_attr*/ (uint8_t) ((uint8_t)TUSB_XFER_ISOCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_ASYNCHRONOUS | (uint8_t)TUSB_ISO_EP_ATT_DATA), /*_maxEPsize*/ _epoutsize, /*_interval*/ 0x01),\ /* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */\ TUD_AUDIO_DESC_CS_AS_ISO_EP(/*_attr*/ AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, /*_ctrl*/ AUDIO_CTRL_NONE, /*_lockdelayunit*/ AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, /*_lockdelay*/ 0x0000),\ /* Standard AS Isochronous Feedback Endpoint Descriptor(4.10.2.1) */\ - TUD_AUDIO_DESC_STD_AS_ISO_FB_EP(/*_ep*/ _epfb, /*_interval*/ 1) + TUD_AUDIO_DESC_STD_AS_ISO_FB_EP(/*_ep*/ _epfb, /*_epsize*/ _epfbsize, /*_interval*/ 1) // Calculate wMaxPacketSize of Endpoints #define TUD_AUDIO_EP_SIZE(_maxFrequency, _nBytesPerSample, _nChannels) \ -- cgit v1.3.1 From 9ce44db56f145d2efeec6b67d0786230c1a735c4 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sat, 11 May 2024 12:32:47 +0200 Subject: Always send 4 bytes feedback despite 10.14 format (Apple wtf ?!) --- src/class/audio/audio_device.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 77645c412..5ee0a4007 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -1231,7 +1231,20 @@ static inline bool audiod_fb_send(audiod_function_t *audio) audio->feedback.send_buf = audio->feedback.value; } - return usbd_edpt_xfer(audio->rhport, audio->ep_fb, (uint8_t *) &audio->feedback.send_buf, apply_correction ? 3 : 4); + // About feedback format on FS + // + // 3 variables: Format | packetSize | sendSize | Working OS: + // 16.16 4 4 Linux, Windows + // 16.16 4 3 Linux + // 16.16 3 4 Linux + // 16.16 3 3 Linux + // 10.14 4 4 Linux + // 10.14 4 3 Linux + // 10.14 3 4 Linux, OSX + // 10.14 3 3 Linux + // + // OSX requires wMaxPacketSize=3 while sending 4 bytes (Wth ?!), so we still send 4 bytes even of correction is applied + return usbd_edpt_xfer(audio->rhport, audio->ep_fb, (uint8_t *) &audio->feedback.send_buf, 4); } #endif -- cgit v1.3.1 From ad85c37c039f9ef9fe2bf7e1fbc011609bcd98a6 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sat, 11 May 2024 12:51:18 +0200 Subject: Optimize SOF. --- src/class/audio/audio_device.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 719e71e12..a6139ee42 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -2045,8 +2045,6 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * case AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT: case AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2: audiod_set_fb_params_freq(audio, fb_param.sample_freq, fb_param.frequency.mclk_freq); - // Enable SOF interrupt - usbd_sof_enable(rhport, true); break; case AUDIO_FEEDBACK_METHOD_FIFO_COUNT: @@ -2084,16 +2082,19 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP // Disable SOF interrupt if no driver has any enabled feedback EP - bool disable = true; + bool enable_sof = false; for(uint8_t i=0; i < CFG_TUD_AUDIO; i++) { - if (_audiod_fct[i].ep_fb != 0) + if (_audiod_fct[i].ep_fb != 0 && + (_audiod_fct[i].feedback.compute_method == AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED || + _audiod_fct[i].feedback.compute_method == AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT || + _audiod_fct[i].feedback.compute_method == AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2 )) { - disable = false; + enable_sof = true; break; } } - if (disable) usbd_sof_enable(rhport, SOF_CONSUMER_AUDIO, false); + usbd_sof_enable(rhport, SOF_CONSUMER_AUDIO, enable_sof); #endif #if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL -- cgit v1.3.1 From 256ccc47571b36dd8f5aaeaebe583cb7640a4b8d Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sat, 11 May 2024 12:57:38 +0200 Subject: Fix CI. --- src/class/audio/audio_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index a6139ee42..0df24c163 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -1243,7 +1243,7 @@ static inline bool audiod_fb_send(audiod_function_t *audio) // 10.14 3 4 Linux, OSX // 10.14 3 3 Linux // - // OSX requires wMaxPacketSize=3 while sending 4 bytes (Wth ?!), so we still send 4 bytes even of correction is applied + // OSX requires wMaxPacketSize=3 while sending 4 bytes (WTF ?!), so we still send 4 bytes even of correction is applied return usbd_edpt_xfer(audio->rhport, audio->ep_fb, (uint8_t *) &audio->feedback.send_buf, 4); } #endif -- cgit v1.3.1 From 32d0baaaf81df65ec386ac6940dbfa897348b086 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sun, 12 May 2024 14:03:29 +0200 Subject: Tested 3 bytes feedback work on OSX. --- src/class/audio/audio_device.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 0df24c163..2a786725b 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -1216,7 +1216,7 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP static inline bool audiod_fb_send(audiod_function_t *audio) { - bool apply_correction = TUSB_SPEED_FULL == tud_speed_get() && audio->feedback.format_correction; + bool apply_correction = (TUSB_SPEED_FULL == tud_speed_get()) && audio->feedback.format_correction; // Format the feedback value if (apply_correction) { @@ -1226,6 +1226,7 @@ static inline bool audiod_fb_send(audiod_function_t *audio) *(fb++) = (audio->feedback.value >> 2) & 0xFF; *(fb++) = (audio->feedback.value >> 10) & 0xFF; *(fb++) = (audio->feedback.value >> 18) & 0xFF; + *fb = 0; } else { audio->feedback.send_buf = audio->feedback.value; @@ -1241,10 +1242,10 @@ static inline bool audiod_fb_send(audiod_function_t *audio) // 10.14 4 4 Linux // 10.14 4 3 Linux // 10.14 3 4 Linux, OSX - // 10.14 3 3 Linux + // 10.14 3 3 Linux, OSX // - // OSX requires wMaxPacketSize=3 while sending 4 bytes (WTF ?!), so we still send 4 bytes even of correction is applied - return usbd_edpt_xfer(audio->rhport, audio->ep_fb, (uint8_t *) &audio->feedback.send_buf, 4); + // We send 3 bytes since sending packet larger than wMaxPacketSize is pretty ugly + return usbd_edpt_xfer(audio->rhport, audio->ep_fb, (uint8_t *) &audio->feedback.send_buf, apply_correction ? 3 : 4); } #endif -- cgit v1.3.1 From 67456357c54ee81e8418a9e814df774b1a3dee85 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sun, 12 May 2024 18:59:32 +0200 Subject: Fix HS playback on OSX. --- src/class/audio/audio_device.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 2a786725b..e82d52a5b 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -2050,7 +2050,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * case AUDIO_FEEDBACK_METHOD_FIFO_COUNT: { - /* Initialize the threshold level to half filled */ + // Initialize the threshold level to half filled uint16_t fifo_lvl_thr; #if CFG_TUD_AUDIO_ENABLE_DECODING fifo_lvl_thr = tu_fifo_depth(&audio->rx_supp_ff[0]) / 2; @@ -2059,11 +2059,16 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * #endif audio->feedback.compute.fifo_count.fifo_lvl_thr = fifo_lvl_thr; audio->feedback.compute.fifo_count.fifo_lvl_avg = ((uint32_t)fifo_lvl_thr) << 16; - /* Avoid 64bit division */ + // Avoid 64bit division uint32_t nominal = ((fb_param.sample_freq / 100) << 16) / (frame_div / 100); audio->feedback.compute.fifo_count.nom_value = nominal; audio->feedback.compute.fifo_count.rate_const[0] = (audio->feedback.max_value - nominal) / fifo_lvl_thr; audio->feedback.compute.fifo_count.rate_const[1] = (nominal - audio->feedback.min_value) / fifo_lvl_thr; + // On HS feedback is more sensitive since packet size can vary every MSOF, could cause instability + if(tud_speed_get() == TUSB_SPEED_HIGH) { + audio->feedback.compute.fifo_count.rate_const[0] /= 8; + audio->feedback.compute.fifo_count.rate_const[1] /= 8; + } } break; -- cgit v1.3.1 From 4938128cccd3a76907caf546eacee41e53b989e7 Mon Sep 17 00:00:00 2001 From: Tinic Uro Date: Wed, 29 May 2024 12:54:15 -0700 Subject: Make it compile for STM32U545. --- src/portable/synopsys/dwc2/dwc2_stm32.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/portable/synopsys/dwc2/dwc2_stm32.h b/src/portable/synopsys/dwc2/dwc2_stm32.h index 3237a50f6..9957976a5 100644 --- a/src/portable/synopsys/dwc2/dwc2_stm32.h +++ b/src/portable/synopsys/dwc2/dwc2_stm32.h @@ -89,6 +89,12 @@ extern "C" { #define USB_OTG_FS_PERIPH_BASE USB_OTG_FS_BASE #define EP_MAX_FS 6 #define EP_FIFO_SIZE_FS 1280 + #define USB_OTG_FS_IRQN OTG_FS_IRQn + #elif defined(USB_DRD_FS) + #define USB_OTG_FS_PERIPH_BASE USB_DRD_BASE + #define EP_MAX_FS 6 + #define EP_FIFO_SIZE_FS 1280 + #define USB_OTG_FS_IRQN USB_IRQn #else #define USB_OTG_HS_PERIPH_BASE USB_OTG_HS_BASE #define EP_MAX_HS 9 @@ -109,7 +115,7 @@ extern "C" { // - Port0 to OTG_FS, and Port1 to OTG_HS static const dwc2_controller_t _dwc2_controller[] = { #ifdef USB_OTG_FS_PERIPH_BASE - { .reg_base = USB_OTG_FS_PERIPH_BASE, .irqnum = OTG_FS_IRQn, .ep_count = EP_MAX_FS, .ep_fifo_size = EP_FIFO_SIZE_FS }, + { .reg_base = USB_OTG_FS_PERIPH_BASE, .irqnum = USB_OTG_FS_IRQN, .ep_count = EP_MAX_FS, .ep_fifo_size = EP_FIFO_SIZE_FS }, #endif #ifdef USB_OTG_HS_PERIPH_BASE -- cgit v1.3.1 From 22e6b1130fa60b76ed0a1d9b6cc049179606c48c Mon Sep 17 00:00:00 2001 From: Tinic Uro Date: Wed, 29 May 2024 13:13:47 -0700 Subject: Cleaner approach. --- src/portable/synopsys/dwc2/dwc2_stm32.h | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/portable/synopsys/dwc2/dwc2_stm32.h b/src/portable/synopsys/dwc2/dwc2_stm32.h index 9957976a5..5743569db 100644 --- a/src/portable/synopsys/dwc2/dwc2_stm32.h +++ b/src/portable/synopsys/dwc2/dwc2_stm32.h @@ -84,17 +84,16 @@ extern "C" { #elif CFG_TUSB_MCU == OPT_MCU_STM32U5 #include "stm32u5xx.h" - // U59x/5Ax/5Fx/5Gx are highspeed with built-in HS PHY #ifdef USB_OTG_FS #define USB_OTG_FS_PERIPH_BASE USB_OTG_FS_BASE #define EP_MAX_FS 6 #define EP_FIFO_SIZE_FS 1280 - #define USB_OTG_FS_IRQN OTG_FS_IRQn + // U53x/U54x are fullspeed with built-in FS PHY but not OTG #elif defined(USB_DRD_FS) - #define USB_OTG_FS_PERIPH_BASE USB_DRD_BASE + #define USB_DRD_FS_PERIPH_BASE USB_DRD_BASE #define EP_MAX_FS 6 #define EP_FIFO_SIZE_FS 1280 - #define USB_OTG_FS_IRQN USB_IRQn + // U59x/5Ax/5Fx/5Gx are highspeed with built-in HS PHY #else #define USB_OTG_HS_PERIPH_BASE USB_OTG_HS_BASE #define EP_MAX_HS 9 @@ -114,6 +113,10 @@ extern "C" { // On STM32 for consistency we associate // - Port0 to OTG_FS, and Port1 to OTG_HS static const dwc2_controller_t _dwc2_controller[] = { + #ifdef USB_DRD_FS_PERIPH_BASE + { .reg_base = USB_DRD_FS_PERIPH_BASE, .irqnum = USB_IRQn, .ep_count = EP_MAX_FS, .ep_fifo_size = EP_FIFO_SIZE_FS }, + #endif + #ifdef USB_OTG_FS_PERIPH_BASE { .reg_base = USB_OTG_FS_PERIPH_BASE, .irqnum = USB_OTG_FS_IRQN, .ep_count = EP_MAX_FS, .ep_fifo_size = EP_FIFO_SIZE_FS }, #endif -- cgit v1.3.1 From 2e946ac77a8fda2b4b36c19df5294cd7213d46aa Mon Sep 17 00:00:00 2001 From: Tinic Uro Date: Wed, 29 May 2024 13:23:18 -0700 Subject: Use correct specs. --- src/portable/synopsys/dwc2/dwc2_stm32.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/portable/synopsys/dwc2/dwc2_stm32.h b/src/portable/synopsys/dwc2/dwc2_stm32.h index 5743569db..4f311782d 100644 --- a/src/portable/synopsys/dwc2/dwc2_stm32.h +++ b/src/portable/synopsys/dwc2/dwc2_stm32.h @@ -91,8 +91,8 @@ extern "C" { // U53x/U54x are fullspeed with built-in FS PHY but not OTG #elif defined(USB_DRD_FS) #define USB_DRD_FS_PERIPH_BASE USB_DRD_BASE - #define EP_MAX_FS 6 - #define EP_FIFO_SIZE_FS 1280 + #define EP_MAX_FS 8 + #define EP_FIFO_SIZE_FS 2048 // U59x/5Ax/5Fx/5Gx are highspeed with built-in HS PHY #else #define USB_OTG_HS_PERIPH_BASE USB_OTG_HS_BASE -- cgit v1.3.1 From 60d7fcb1ee8dcc4870221e97c1e3fba5463a9d45 Mon Sep 17 00:00:00 2001 From: Tinic Uro Date: Thu, 30 May 2024 13:26:14 -0700 Subject: Use correct backend. --- src/common/tusb_mcu.h | 25 +++++++++++++-------- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 2 +- src/portable/st/stm32_fsdev/fsdev_stm32.h | 31 +++++++++++++++++++++++++++ src/portable/synopsys/dwc2/dwc2_stm32.h | 11 +--------- 4 files changed, 49 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index c66996c4f..0f4fca8d1 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -271,17 +271,24 @@ #define TUP_DCD_ENDPOINT_MAX 8 #elif TU_CHECK_MCU(OPT_MCU_STM32U5) - #define TUP_USBIP_DWC2 - #define TUP_USBIP_DWC2_STM32 + #ifdef USB_DRD_FS + #define TUP_USBIP_FSDEV + #define TUP_USBIP_FSDEV_STM32 + #define TUP_DCD_ENDPOINT_MAX 8 - // U59x/5Ax/5Fx/5Gx are highspeed with built-in HS PHY - #if defined(STM32U595xx) || defined(STM32U599xx) || defined(STM32U5A5xx) || defined(STM32U5A9xx) || \ - defined(STM32U5F7xx) || defined(STM32U5F9xx) || defined(STM32U5G7xx) || defined(STM32U5G9xx) - #define TUP_DCD_ENDPOINT_MAX 9 - #define TUP_RHPORT_HIGHSPEED 1 - #define TUP_USBIP_DWC2_TEST_MODE #else - #define TUP_DCD_ENDPOINT_MAX 6 + #define TUP_USBIP_DWC2 + #define TUP_USBIP_DWC2_STM32 + + // U59x/5Ax/5Fx/5Gx are highspeed with built-in HS PHY + #if defined(STM32U595xx) || defined(STM32U599xx) || defined(STM32U5A5xx) || defined(STM32U5A9xx) || \ + defined(STM32U5F7xx) || defined(STM32U5F9xx) || defined(STM32U5G7xx) || defined(STM32U5G9xx) + #define TUP_DCD_ENDPOINT_MAX 9 + #define TUP_RHPORT_HIGHSPEED 1 + #define TUP_USBIP_DWC2_TEST_MODE + #else + #define TUP_DCD_ENDPOINT_MAX 6 + #endif #endif #elif TU_CHECK_MCU(OPT_MCU_STM32L5) diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 9ce37f992..5f230d86f 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -232,7 +232,7 @@ void dcd_init(uint8_t rhport) } USB->CNTR = 0; // Enable USB -#if !defined(STM32G0) && !defined(STM32H5) // BTABLE register does not exist any more on STM32G0, it is fixed to USB SRAM base address +#if !defined(STM32G0) && !defined(STM32H5) && !defined(STM32U5) // BTABLE register does not exist any more on STM32G0, it is fixed to USB SRAM base address USB->BTABLE = DCD_STM32_BTABLE_BASE; #endif USB->ISTR = 0; // Clear pending interrupts diff --git a/src/portable/st/stm32_fsdev/fsdev_stm32.h b/src/portable/st/stm32_fsdev/fsdev_stm32.h index b3fa11b88..a5199c9e3 100644 --- a/src/portable/st/stm32_fsdev/fsdev_stm32.h +++ b/src/portable/st/stm32_fsdev/fsdev_stm32.h @@ -159,6 +159,35 @@ #define USB_PMAADDR (USB_BASE + (USB_PMAADDR_NS - USB_BASE_NS)) #endif +#elif CFG_TUSB_MCU == OPT_MCU_STM32U5 + #include "stm32u5xx.h" + #define FSDEV_BUS_32BIT + + #define FSDEV_PMA_SIZE (2048u) + #undef USB_PMAADDR + #define USB_PMAADDR USB_DRD_PMAADDR + #define USB_TypeDef USB_DRD_TypeDef + #define EP0R CHEP0R + #define USB_EP_CTR_RX USB_EP_VTRX + #define USB_EP_CTR_TX USB_EP_VTTX + #define USB_EP_T_FIELD USB_CHEP_UTYPE + #define USB_EPREG_MASK USB_CHEP_REG_MASK + #define USB_EPTX_DTOGMASK USB_CHEP_TX_DTOGMASK + #define USB_EPRX_DTOGMASK USB_CHEP_RX_DTOGMASK + #define USB_EPTX_DTOG1 USB_CHEP_TX_DTOG1 + #define USB_EPTX_DTOG2 USB_CHEP_TX_DTOG2 + #define USB_EPRX_DTOG1 USB_CHEP_RX_DTOG1 + #define USB_EPRX_DTOG2 USB_CHEP_RX_DTOG2 + #define USB_EPRX_STAT USB_CH_RX_VALID + #define USB_EPKIND_MASK USB_EP_KIND_MASK + #define USB USB_DRD_FS + #define USB_CNTR_FRES USB_CNTR_USBRST + #define USB_CNTR_RESUME USB_CNTR_L2RES + #define USB_ISTR_EP_ID USB_ISTR_IDN + #define USB_EPADDR_FIELD USB_CHEP_ADDR + #define USB_CNTR_LPMODE USB_CNTR_SUSPRDY + #define USB_CNTR_FSUSP USB_CNTR_SUSPEN + #else #error You are using an untested or unimplemented STM32 variant. Please update the driver. // This includes L1x0, L1x1, L1x2, L4x2 and L4x3, G1x1, G1x3, and G1x4 @@ -211,6 +240,8 @@ static const IRQn_Type fsdev_irq[] = { #elif CFG_TUSB_MCU == OPT_MCU_STM32WB USB_HP_IRQn, USB_LP_IRQn, + #elif CFG_TUSB_MCU == OPT_MCU_STM32U5 + USB_IRQn, #else #error Unknown arch in USB driver #endif diff --git a/src/portable/synopsys/dwc2/dwc2_stm32.h b/src/portable/synopsys/dwc2/dwc2_stm32.h index 4f311782d..eaac2c44b 100644 --- a/src/portable/synopsys/dwc2/dwc2_stm32.h +++ b/src/portable/synopsys/dwc2/dwc2_stm32.h @@ -84,16 +84,11 @@ extern "C" { #elif CFG_TUSB_MCU == OPT_MCU_STM32U5 #include "stm32u5xx.h" + // U59x/5Ax/5Fx/5Gx are highspeed with built-in HS PHY #ifdef USB_OTG_FS #define USB_OTG_FS_PERIPH_BASE USB_OTG_FS_BASE #define EP_MAX_FS 6 #define EP_FIFO_SIZE_FS 1280 - // U53x/U54x are fullspeed with built-in FS PHY but not OTG - #elif defined(USB_DRD_FS) - #define USB_DRD_FS_PERIPH_BASE USB_DRD_BASE - #define EP_MAX_FS 8 - #define EP_FIFO_SIZE_FS 2048 - // U59x/5Ax/5Fx/5Gx are highspeed with built-in HS PHY #else #define USB_OTG_HS_PERIPH_BASE USB_OTG_HS_BASE #define EP_MAX_HS 9 @@ -113,10 +108,6 @@ extern "C" { // On STM32 for consistency we associate // - Port0 to OTG_FS, and Port1 to OTG_HS static const dwc2_controller_t _dwc2_controller[] = { - #ifdef USB_DRD_FS_PERIPH_BASE - { .reg_base = USB_DRD_FS_PERIPH_BASE, .irqnum = USB_IRQn, .ep_count = EP_MAX_FS, .ep_fifo_size = EP_FIFO_SIZE_FS }, - #endif - #ifdef USB_OTG_FS_PERIPH_BASE { .reg_base = USB_OTG_FS_PERIPH_BASE, .irqnum = USB_OTG_FS_IRQN, .ep_count = EP_MAX_FS, .ep_fifo_size = EP_FIFO_SIZE_FS }, #endif -- cgit v1.3.1 From 28c243337591f0ac7745f11737d907d47f0e6320 Mon Sep 17 00:00:00 2001 From: Tinic Uro Date: Wed, 12 Jun 2024 08:08:25 -0700 Subject: Add stm32u545nucleo board. --- hw/bsp/stm32u5/boards/stm32u575nucleo/board.mk | 1 + hw/bsp/stm32u5/boards/stm32u5a5nucleo/board.mk | 1 + hw/bsp/stm32u5/family.c | 17 ++++++++++++++++- hw/bsp/stm32u5/family.cmake | 14 ++++++++++---- hw/bsp/stm32u5/family.mk | 14 ++++++++++++-- src/portable/synopsys/dwc2/dwc2_stm32.h | 2 +- 6 files changed, 41 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/hw/bsp/stm32u5/boards/stm32u575nucleo/board.mk b/hw/bsp/stm32u5/boards/stm32u575nucleo/board.mk index 1dd157a68..c83ec3999 100644 --- a/hw/bsp/stm32u5/boards/stm32u575nucleo/board.mk +++ b/hw/bsp/stm32u5/boards/stm32u575nucleo/board.mk @@ -6,5 +6,6 @@ LD_FILE = ${FAMILY_PATH}/linker/STM32U575xx_FLASH.ld SRC_S += $(ST_CMSIS)/Source/Templates/gcc/startup_stm32u575xx.s +MCU_VARIANT = stm32u575xx # For flash-jlink target JLINK_DEVICE = stm32u575zi diff --git a/hw/bsp/stm32u5/boards/stm32u5a5nucleo/board.mk b/hw/bsp/stm32u5/boards/stm32u5a5nucleo/board.mk index e759cec24..4bebe3330 100644 --- a/hw/bsp/stm32u5/boards/stm32u5a5nucleo/board.mk +++ b/hw/bsp/stm32u5/boards/stm32u5a5nucleo/board.mk @@ -7,5 +7,6 @@ LD_FILE = ${BOARD_PATH}/STM32U5A5ZJTXQ_FLASH.ld SRC_S += $(ST_CMSIS)/Source/Templates/gcc/startup_stm32u5a5xx.s +MCU_VARIANT = stm32u5a5xx # For flash-jlink target JLINK_DEVICE = stm32u575zi diff --git a/hw/bsp/stm32u5/family.c b/hw/bsp/stm32u5/family.c index d779b5c96..0f0868839 100644 --- a/hw/bsp/stm32u5/family.c +++ b/hw/bsp/stm32u5/family.c @@ -72,7 +72,9 @@ void board_init(void) { __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); __HAL_RCC_GPIOE_CLK_ENABLE(); +#ifdef GPIOF __HAL_RCC_GPIOF_CLK_ENABLE(); +#endif __HAL_RCC_GPIOG_CLK_ENABLE(); __HAL_RCC_GPIOH_CLK_ENABLE(); @@ -140,6 +142,17 @@ void board_init(void) { GPIO_InitStruct.Alternate = GPIO_AF10_USB; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); +#ifdef USB_OTG_HS + // STM32U535/STM32U545 + + /* Enable USB power on Pwrctrl CR2 register */ + HAL_PWREx_EnableVddUSB(); + + /* USB clock enable */ + __HAL_RCC_USB_FS_CLK_ENABLE(); + +#endif + #ifdef USB_OTG_FS #if CFG_TUSB_OS == OPT_OS_FREERTOS // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) @@ -170,7 +183,9 @@ void board_init(void) { /* USB clock enable */ __HAL_RCC_USB_OTG_FS_CLK_ENABLE(); -#else +#endif + +#ifdef USB_OTG_HS // STM59x/Ax/Fx/Gx only have 1 USB HS port #if CFG_TUSB_OS == OPT_OS_FREERTOS diff --git a/hw/bsp/stm32u5/family.cmake b/hw/bsp/stm32u5/family.cmake index 7402540b7..c19bce64b 100644 --- a/hw/bsp/stm32u5/family.cmake +++ b/hw/bsp/stm32u5/family.cmake @@ -102,10 +102,16 @@ function(family_configure_example TARGET RTOS) # Add TinyUSB target and port source family_add_tinyusb(${TARGET} OPT_MCU_STM32U5 ${RTOS}) - target_sources(${TARGET}-tinyusb PUBLIC - ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c - #${TOP}/src/portable/st/typec/typec_stm32.c - ) + if ((${MCU_VARIANT} EQUAL "stm32u535xx") OR (${MCU_VARIANT} EQUAL "stm32u545xx")) + target_sources(${TARGET}-tinyusb PUBLIC + ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + ) + else () + target_sources(${TARGET}-tinyusb PUBLIC + ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c + #${TOP}/src/portable/st/typec/typec_stm32.c + ) + endif () target_link_libraries(${TARGET}-tinyusb PUBLIC board_${BOARD}) # Link dependencies diff --git a/hw/bsp/stm32u5/family.mk b/hw/bsp/stm32u5/family.mk index be5809340..45f9aa33e 100644 --- a/hw/bsp/stm32u5/family.mk +++ b/hw/bsp/stm32u5/family.mk @@ -27,18 +27,28 @@ LDFLAGS_GCC += \ --specs=nosys.specs --specs=nano.specs SRC_C += \ - src/portable/synopsys/dwc2/dcd_dwc2.c \ $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_gpio.c \ - $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_icache.c \ + $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_icache.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_pwr.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_pwr_ex.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc_ex.c \ $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_uart.c +ifeq ($(MCU_VARIANT),stm32u545xx) +SRC_C += \ + src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +else ($(MCU_VARIANT),stm32u535xx) +SRC_C += \ + src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +else +SRC_C += \ + src/portable/synopsys/dwc2/dcd_dwc2.c +endif + INC += \ $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ $(TOP)/$(ST_CMSIS)/Include \ diff --git a/src/portable/synopsys/dwc2/dwc2_stm32.h b/src/portable/synopsys/dwc2/dwc2_stm32.h index eaac2c44b..3237a50f6 100644 --- a/src/portable/synopsys/dwc2/dwc2_stm32.h +++ b/src/portable/synopsys/dwc2/dwc2_stm32.h @@ -109,7 +109,7 @@ extern "C" { // - Port0 to OTG_FS, and Port1 to OTG_HS static const dwc2_controller_t _dwc2_controller[] = { #ifdef USB_OTG_FS_PERIPH_BASE - { .reg_base = USB_OTG_FS_PERIPH_BASE, .irqnum = USB_OTG_FS_IRQN, .ep_count = EP_MAX_FS, .ep_fifo_size = EP_FIFO_SIZE_FS }, + { .reg_base = USB_OTG_FS_PERIPH_BASE, .irqnum = OTG_FS_IRQn, .ep_count = EP_MAX_FS, .ep_fifo_size = EP_FIFO_SIZE_FS }, #endif #ifdef USB_OTG_HS_PERIPH_BASE -- cgit v1.3.1 From bc576e7cee64fedfa977604f8e9e4043b3473ece Mon Sep 17 00:00:00 2001 From: Tinic Uro Date: Wed, 12 Jun 2024 08:33:10 -0700 Subject: Make it work. --- hw/bsp/stm32u5/boards/stm32u545nucleo/board.mk | 1 + hw/bsp/stm32u5/boards/stm32u575eval/board.mk | 1 + hw/bsp/stm32u5/family.mk | 2 +- src/common/tusb_mcu.h | 2 +- 4 files changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/hw/bsp/stm32u5/boards/stm32u545nucleo/board.mk b/hw/bsp/stm32u5/boards/stm32u545nucleo/board.mk index 66cba0c2b..072c595fb 100644 --- a/hw/bsp/stm32u5/boards/stm32u545nucleo/board.mk +++ b/hw/bsp/stm32u5/boards/stm32u545nucleo/board.mk @@ -6,5 +6,6 @@ LD_FILE = ${FAMILY_PATH}/linker/STM32U545xx_FLASH.ld SRC_S += $(ST_CMSIS)/Source/Templates/gcc/startup_stm32u545xx.s +MCU_VARIANT = stm32u545xx # For flash-jlink target JLINK_DEVICE = stm32u545re diff --git a/hw/bsp/stm32u5/boards/stm32u575eval/board.mk b/hw/bsp/stm32u5/boards/stm32u575eval/board.mk index 922d67f83..fee56f2ba 100644 --- a/hw/bsp/stm32u5/boards/stm32u575eval/board.mk +++ b/hw/bsp/stm32u5/boards/stm32u575eval/board.mk @@ -6,5 +6,6 @@ LD_FILE = ${FAMILY_PATH}/linker/STM32U575xx_FLASH.ld SRC_S += $(ST_CMSIS)/Source/Templates/gcc/startup_stm32u575xx.s +MCU_VARIANT = stm32u575xx # For flash-jlink target JLINK_DEVICE = stm32u575ai diff --git a/hw/bsp/stm32u5/family.mk b/hw/bsp/stm32u5/family.mk index 45f9aa33e..9ab8992a8 100644 --- a/hw/bsp/stm32u5/family.mk +++ b/hw/bsp/stm32u5/family.mk @@ -41,7 +41,7 @@ SRC_C += \ ifeq ($(MCU_VARIANT),stm32u545xx) SRC_C += \ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c -else ($(MCU_VARIANT),stm32u535xx) +else ifeq ($(MCU_VARIANT),stm32u535xx) SRC_C += \ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c else diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 0f4fca8d1..4b802138b 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -271,7 +271,7 @@ #define TUP_DCD_ENDPOINT_MAX 8 #elif TU_CHECK_MCU(OPT_MCU_STM32U5) - #ifdef USB_DRD_FS + #if defined (STM32U535xx) || defined (STM32U545xx) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 #define TUP_DCD_ENDPOINT_MAX 8 -- cgit v1.3.1 From 2ed027f2bdedae81f20d7417ad7f018a6de9357a Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 14 Jun 2024 12:51:28 +0700 Subject: use stock core_riscv.h for ch32 v2 v3 --- hw/bsp/ch32v20x/core_riscv.h | 572 ------------------------------- hw/bsp/ch32v20x/family.c | 12 + hw/bsp/ch32v20x/family.cmake | 1 + hw/bsp/ch32v20x/family.mk | 4 + hw/bsp/ch32v307/core_riscv.h | 379 -------------------- hw/bsp/ch32v307/debug_uart.c | 9 + hw/bsp/ch32v307/family.c | 13 + hw/bsp/ch32v307/family.cmake | 1 + hw/bsp/ch32v307/family.mk | 4 + src/portable/st/stm32_fsdev/fsdev_ch32.h | 12 +- src/portable/wch/ch32_usbfs_reg.h | 11 + src/portable/wch/ch32_usbhs_reg.h | 12 + 12 files changed, 78 insertions(+), 952 deletions(-) delete mode 100644 hw/bsp/ch32v20x/core_riscv.h delete mode 100644 hw/bsp/ch32v307/core_riscv.h (limited to 'src') diff --git a/hw/bsp/ch32v20x/core_riscv.h b/hw/bsp/ch32v20x/core_riscv.h deleted file mode 100644 index be1b52a6c..000000000 --- a/hw/bsp/ch32v20x/core_riscv.h +++ /dev/null @@ -1,572 +0,0 @@ -/********************************** (C) COPYRIGHT ******************************* - * File Name : core_riscv.h - * Author : WCH - * Version : V1.0.0 - * Date : 2021/06/06 - * Description : RISC-V Core Peripheral Access Layer Header File for CH32V20x -********************************************************************************* -* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. -* Attention: This software (modified or not) and binary are used for -* microcontroller manufactured by Nanjing Qinheng Microelectronics. -*******************************************************************************/ -#ifndef __CORE_RISCV_H__ -#define __CORE_RISCV_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -/* IO definitions */ -#ifdef __cplusplus - #define __I volatile /* defines 'read only' permissions */ -#else - #define __I volatile const /* defines 'read only' permissions */ -#endif -#define __O volatile /* defines 'write only' permissions */ -#define __IO volatile /* defines 'read / write' permissions */ - -/* Standard Peripheral Library old types (maintained for legacy purpose) */ -typedef __I uint64_t vuc64; /* Read Only */ -typedef __I uint32_t vuc32; /* Read Only */ -typedef __I uint16_t vuc16; /* Read Only */ -typedef __I uint8_t vuc8; /* Read Only */ - -typedef const uint64_t uc64; /* Read Only */ -typedef const uint32_t uc32; /* Read Only */ -typedef const uint16_t uc16; /* Read Only */ -typedef const uint8_t uc8; /* Read Only */ - -typedef __I int64_t vsc64; /* Read Only */ -typedef __I int32_t vsc32; /* Read Only */ -typedef __I int16_t vsc16; /* Read Only */ -typedef __I int8_t vsc8; /* Read Only */ - -typedef const int64_t sc64; /* Read Only */ -typedef const int32_t sc32; /* Read Only */ -typedef const int16_t sc16; /* Read Only */ -typedef const int8_t sc8; /* Read Only */ - -typedef __IO uint64_t vu64; -typedef __IO uint32_t vu32; -typedef __IO uint16_t vu16; -typedef __IO uint8_t vu8; - -typedef uint64_t u64; -typedef uint32_t u32; -typedef uint16_t u16; -typedef uint8_t u8; - -typedef __IO int64_t vs64; -typedef __IO int32_t vs32; -typedef __IO int16_t vs16; -typedef __IO int8_t vs8; - -typedef int64_t s64; -typedef int32_t s32; -typedef int16_t s16; -typedef int8_t s8; - -typedef enum {NoREADY = 0, READY = !NoREADY} ErrorStatus; - -typedef enum {DISABLE = 0, ENABLE = !DISABLE} FunctionalState; - -typedef enum {RESET = 0, SET = !RESET} FlagStatus, ITStatus; - -#define RV_STATIC_INLINE static inline - -/* memory mapped structure for Program Fast Interrupt Controller (PFIC) */ -typedef struct{ - __I uint32_t ISR[8]; - __I uint32_t IPR[8]; - __IO uint32_t ITHRESDR; - __IO uint32_t RESERVED; - __IO uint32_t CFGR; - __I uint32_t GISR; - __IO uint8_t VTFIDR[4]; - uint8_t RESERVED0[12]; - __IO uint32_t VTFADDR[4]; - uint8_t RESERVED1[0x90]; - __O uint32_t IENR[8]; - uint8_t RESERVED2[0x60]; - __O uint32_t IRER[8]; - uint8_t RESERVED3[0x60]; - __O uint32_t IPSR[8]; - uint8_t RESERVED4[0x60]; - __O uint32_t IPRR[8]; - uint8_t RESERVED5[0x60]; - __IO uint32_t IACTR[8]; - uint8_t RESERVED6[0xE0]; - __IO uint8_t IPRIOR[256]; - uint8_t RESERVED7[0x810]; - __IO uint32_t SCTLR; -}PFIC_Type; - -/* memory mapped structure for SysTick */ -typedef struct -{ - __IO uint32_t CTLR; - __IO uint32_t SR; - __IO uint64_t CNT; - __IO uint64_t CMP; -}SysTick_Type; - -#define PFIC ((PFIC_Type *) 0xE000E000 ) -#define NVIC PFIC -#define NVIC_KEY1 ((uint32_t)0xFA050000) -#define NVIC_KEY2 ((uint32_t)0xBCAF0000) -#define NVIC_KEY3 ((uint32_t)0xBEEF0000) - -#define SysTick ((SysTick_Type *) 0xE000F000) - -/********************************************************************* - * @fn __enable_irq - * - * @brief Enable Global Interrupt - * - * @return none - */ -__attribute__( ( always_inline ) ) RV_STATIC_INLINE void __enable_irq(void) -{ - __asm volatile ("csrw 0x800, %0" : : "r" (0x6088) ); -} - -/********************************************************************* - * @fn __disable_irq - * - * @brief Disable Global Interrupt - * - * @return none - */ -__attribute__( ( always_inline ) ) RV_STATIC_INLINE void __disable_irq(void) -{ - __asm volatile ("csrw 0x800, %0" : : "r" (0x6000) ); -} - -/********************************************************************* - * @fn __NOP - * - * @brief nop - * - * @return none - */ -__attribute__( ( always_inline ) ) RV_STATIC_INLINE void __NOP(void) -{ - __asm volatile ("nop"); -} - -/********************************************************************* - * @fn NVIC_EnableIRQ - * - * @brief Disable Interrupt - * - * @param IRQn - Interrupt Numbers - * - * @return none - */ -__attribute__( ( always_inline ) ) RV_STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) -{ - NVIC->IENR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); -} - -/********************************************************************* - * @fn NVIC_DisableIRQ - * - * @brief Disable Interrupt - * - * @param IRQn - Interrupt Numbers - * - * @return none - */ -__attribute__( ( always_inline ) ) RV_STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) -{ - NVIC->IRER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); -} - -/********************************************************************* - * @fn NVIC_GetStatusIRQ - * - * @brief Get Interrupt Enable State - * - * @param IRQn - Interrupt Numbers - * - * @return 1 - Interrupt Pending Enable - * 0 - Interrupt Pending Disable - */ -__attribute__( ( always_inline ) ) RV_STATIC_INLINE uint32_t NVIC_GetStatusIRQ(IRQn_Type IRQn) -{ - return((uint32_t) ((NVIC->ISR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); -} - -/********************************************************************* - * @fn NVIC_GetPendingIRQ - * - * @brief Get Interrupt Pending State - * - * @param IRQn - Interrupt Numbers - * - * @return 1 - Interrupt Pending Enable - * 0 - Interrupt Pending Disable - */ -__attribute__( ( always_inline ) ) RV_STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) -{ - return((uint32_t) ((NVIC->IPR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); -} - -/********************************************************************* - * @fn NVIC_SetPendingIRQ - * - * @brief Set Interrupt Pending - * - * @param IRQn - Interrupt Numbers - * - * @return none - */ -__attribute__( ( always_inline ) ) RV_STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) -{ - NVIC->IPSR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); -} - -/********************************************************************* - * @fn NVIC_ClearPendingIRQ - * - * @brief Clear Interrupt Pending - * - * @param IRQn - Interrupt Numbers - * - * @return none - */ -__attribute__( ( always_inline ) ) RV_STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) -{ - NVIC->IPRR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); -} - -/********************************************************************* - * @fn NVIC_GetActive - * - * @brief Get Interrupt Active State - * - * @param IRQn - Interrupt Numbers - * - * @return 1 - Interrupt Active - * 0 - Interrupt No Active - */ -__attribute__( ( always_inline ) ) RV_STATIC_INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn) -{ - return((uint32_t)((NVIC->IACTR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); -} - -/********************************************************************* - * @fn NVIC_SetPriority - * - * @brief Set Interrupt Priority - * - * @param IRQn - Interrupt Numbers - * priority - bit7 - Pre-emption Priority - * bit[6:5] - Subpriority - * - * @return none - */ -__attribute__( ( always_inline ) ) RV_STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint8_t priority) -{ - NVIC->IPRIOR[(uint32_t)(IRQn)] = priority; -} - -/********************************************************************* - * @fn __WFI - * - * @brief Wait for Interrupt - * - * @return none - */ -__attribute__( ( always_inline ) ) RV_STATIC_INLINE void __WFI(void) -{ - NVIC->SCTLR &= ~(1<<3); // wfi - asm volatile ("wfi"); -} - -/********************************************************************* - * @fn _SEV - * - * @brief Set Event - * - * @return none - */ -__attribute__( ( always_inline ) ) RV_STATIC_INLINE void _SEV(void) -{ - uint32_t t; - - t = NVIC->SCTLR; - NVIC->SCTLR |= (1<<3)|(1<<5); - NVIC->SCTLR = (NVIC->SCTLR & ~(1<<5)) | ( t & (1<<5)); -} - -/********************************************************************* - * @fn _WFE - * - * @brief Wait for Events - * - * @return none - */ -__attribute__( ( always_inline ) ) RV_STATIC_INLINE void _WFE(void) -{ - NVIC->SCTLR |= (1<<3); - asm volatile ("wfi"); -} - -/********************************************************************* - * @fn __WFE - * - * @brief Wait for Events - * - * @return none - */ -__attribute__( ( always_inline ) ) RV_STATIC_INLINE void __WFE(void) -{ - _SEV(); - _WFE(); - _WFE(); -} - -/********************************************************************* - * @fn SetVTFIRQ - * - * @brief Set VTF Interrupt - * - * @param addr - VTF interrupt service function base address. - * IRQn - Interrupt Numbers - * num - VTF Interrupt Numbers - * NewState - DISABLE or ENABLE - * - * @return none - */ -__attribute__( ( always_inline ) ) RV_STATIC_INLINE void SetVTFIRQ(uint32_t addr, IRQn_Type IRQn, uint8_t num, FunctionalState NewState){ - if(num > 3) return ; - - if (NewState != DISABLE) - { - NVIC->VTFIDR[num] = IRQn; - NVIC->VTFADDR[num] = ((addr&0xFFFFFFFE)|0x1); - } - else{ - NVIC->VTFIDR[num] = IRQn; - NVIC->VTFADDR[num] = ((addr&0xFFFFFFFE)&(~0x1)); - } -} - -/********************************************************************* - * @fn NVIC_SystemReset - * - * @brief Initiate a system reset request - * - * @return none - */ -__attribute__( ( always_inline ) ) RV_STATIC_INLINE void NVIC_SystemReset(void) -{ - NVIC->CFGR = NVIC_KEY3|(1<<7); -} - -/********************************************************************* - * @fn __AMOADD_W - * - * @brief Atomic Add with 32bit value - * Atomically ADD 32bit value with value in memory using amoadd.d. - * - * @param addr - Address pointer to data, address need to be 4byte aligned - * value - value to be ADDed - * - * @return return memory value + add value - */ -__attribute__( ( always_inline ) ) RV_STATIC_INLINE int32_t __AMOADD_W(volatile int32_t *addr, int32_t value) -{ - int32_t result; - - __asm volatile ("amoadd.w %0, %2, %1" : \ - "=r"(result), "+A"(*addr) : "r"(value) : "memory"); - return *addr; -} - -/********************************************************************* - * @fn __AMOAND_W - * - * @brief Atomic And with 32bit value - * Atomically AND 32bit value with value in memory using amoand.d. - * - * @param addr - Address pointer to data, address need to be 4byte aligned - * value - value to be ANDed - * - * @return return memory value & and value - */ -__attribute__( ( always_inline ) ) RV_STATIC_INLINE int32_t __AMOAND_W(volatile int32_t *addr, int32_t value) -{ - int32_t result; - - __asm volatile ("amoand.w %0, %2, %1" : \ - "=r"(result), "+A"(*addr) : "r"(value) : "memory"); - return *addr; -} - -/********************************************************************* - * @fn __AMOMAX_W - * - * @brief Atomic signed MAX with 32bit value - * Atomically signed max compare 32bit value with value in memory using amomax.d. - * - * @param addr - Address pointer to data, address need to be 4byte aligned - * value - value to be compared - * - * @return the bigger value - */ -__attribute__( ( always_inline ) ) RV_STATIC_INLINE int32_t __AMOMAX_W(volatile int32_t *addr, int32_t value) -{ - int32_t result; - - __asm volatile ("amomax.w %0, %2, %1" : \ - "=r"(result), "+A"(*addr) : "r"(value) : "memory"); - return *addr; -} - -/********************************************************************* - * @fn __AMOMAXU_W - * - * @brief Atomic unsigned MAX with 32bit value - * Atomically unsigned max compare 32bit value with value in memory using amomaxu.d. - * - * @param addr - Address pointer to data, address need to be 4byte aligned - * value - value to be compared - * - * @return return the bigger value - */ -__attribute__( ( always_inline ) ) RV_STATIC_INLINE uint32_t __AMOMAXU_W(volatile uint32_t *addr, uint32_t value) -{ - uint32_t result; - - __asm volatile ("amomaxu.w %0, %2, %1" : \ - "=r"(result), "+A"(*addr) : "r"(value) : "memory"); - return *addr; -} - -/********************************************************************* - * @fn __AMOMIN_W - * - * @brief Atomic signed MIN with 32bit value - * Atomically signed min compare 32bit value with value in memory using amomin.d. - * - * @param addr - Address pointer to data, address need to be 4byte aligned - * value - value to be compared - * - * @return the smaller value - */ -__attribute__( ( always_inline ) ) RV_STATIC_INLINE int32_t __AMOMIN_W(volatile int32_t *addr, int32_t value) -{ - int32_t result; - - __asm volatile ("amomin.w %0, %2, %1" : \ - "=r"(result), "+A"(*addr) : "r"(value) : "memory"); - return *addr; -} - -/********************************************************************* - * @fn __AMOMINU_W - * - * @brief Atomic unsigned MIN with 32bit value - * Atomically unsigned min compare 32bit value with value in memory using amominu.d. - * - * @param addr - Address pointer to data, address need to be 4byte aligned - * value - value to be compared - * - * @return the smaller value - */ -__attribute__( ( always_inline ) ) RV_STATIC_INLINE uint32_t __AMOMINU_W(volatile uint32_t *addr, uint32_t value) -{ - uint32_t result; - - __asm volatile ("amominu.w %0, %2, %1" : \ - "=r"(result), "+A"(*addr) : "r"(value) : "memory"); - return *addr; -} - -/********************************************************************* - * @fn __AMOOR_W - * - * @brief Atomic OR with 32bit value - * Atomically OR 32bit value with value in memory using amoor.d. - * - * @param addr - Address pointer to data, address need to be 4byte aligned - * value - value to be ORed - * - * @return return memory value | and value - */ -__attribute__( ( always_inline ) ) RV_STATIC_INLINE int32_t __AMOOR_W(volatile int32_t *addr, int32_t value) -{ - int32_t result; - - __asm volatile ("amoor.w %0, %2, %1" : \ - "=r"(result), "+A"(*addr) : "r"(value) : "memory"); - return *addr; -} - -/********************************************************************* - * @fn __AMOSWAP_W - * - * @brief Atomically swap new 32bit value into memory using amoswap.d. - * - * @param addr - Address pointer to data, address need to be 4byte aligned - * newval - New value to be stored into the address - * - * @return return the original value in memory - */ -__attribute__( ( always_inline ) ) RV_STATIC_INLINE uint32_t __AMOSWAP_W(volatile uint32_t *addr, uint32_t newval) -{ - uint32_t result; - - __asm volatile ("amoswap.w %0, %2, %1" : \ - "=r"(result), "+A"(*addr) : "r"(newval) : "memory"); - return result; -} - -/********************************************************************* - * @fn __AMOXOR_W - * - * @brief Atomic XOR with 32bit value - * Atomically XOR 32bit value with value in memory using amoxor.d. - * - * @param addr - Address pointer to data, address need to be 4byte aligned - * value - value to be XORed - * - * @return return memory value ^ and value - */ -__attribute__( ( always_inline ) ) RV_STATIC_INLINE int32_t __AMOXOR_W(volatile int32_t *addr, int32_t value) -{ - int32_t result; - - __asm volatile ("amoxor.w %0, %2, %1" : \ - "=r"(result), "+A"(*addr) : "r"(value) : "memory"); - return *addr; -} - -/* Core_Exported_Functions */ -extern uint32_t __get_MSTATUS(void); -extern void __set_MSTATUS(uint32_t value); -extern uint32_t __get_MISA(void); -extern void __set_MISA(uint32_t value); -extern uint32_t __get_MTVEC(void); -extern void __set_MTVEC(uint32_t value); -extern uint32_t __get_MSCRATCH(void); -extern void __set_MSCRATCH(uint32_t value); -extern uint32_t __get_MEPC(void); -extern void __set_MEPC(uint32_t value); -extern uint32_t __get_MCAUSE(void); -extern void __set_MCAUSE(uint32_t value); -extern uint32_t __get_MTVAL(void); -extern void __set_MTVAL(uint32_t value); -extern uint32_t __get_MVENDORID(void); -extern uint32_t __get_MARCHID(void); -extern uint32_t __get_MIMPID(void); -extern uint32_t __get_MHARTID(void); -extern uint32_t __get_SP(void); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/hw/bsp/ch32v20x/family.c b/hw/bsp/ch32v20x/family.c index c32cfd46e..8575f5699 100644 --- a/hw/bsp/ch32v20x/family.c +++ b/hw/bsp/ch32v20x/family.c @@ -1,6 +1,18 @@ #include + +// https://github.com/openwch/ch32v307/pull/90 +// https://github.com/openwch/ch32v20x/pull/12 +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-prototypes" +#endif + #include "ch32v20x.h" +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + #include "bsp/board_api.h" #include "board.h" diff --git a/hw/bsp/ch32v20x/family.cmake b/hw/bsp/ch32v20x/family.cmake index 1d574fdf8..28fd13697 100644 --- a/hw/bsp/ch32v20x/family.cmake +++ b/hw/bsp/ch32v20x/family.cmake @@ -49,6 +49,7 @@ function(add_board_target BOARD_TARGET) ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${BOARD_TARGET} PUBLIC + ${SDK_SRC_DIR}/Core ${SDK_SRC_DIR}/Peripheral/inc ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ) diff --git a/hw/bsp/ch32v20x/family.mk b/hw/bsp/ch32v20x/family.mk index 49d4d2feb..daf3148f8 100644 --- a/hw/bsp/ch32v20x/family.mk +++ b/hw/bsp/ch32v20x/family.mk @@ -24,6 +24,9 @@ CFLAGS += \ -DCH32V20x_${MCU_VARIANT} \ -DCFG_TUSB_MCU=OPT_MCU_CH32V20X +# https://github.com/openwch/ch32v20x/pull/12 +CFLAGS += -Wno-error=strict-prototypes + ifeq ($(PORT),0) $(info "Using FSDEV driver") CFLAGS += -DCFG_TUD_WCH_USBIP_FSDEV=1 @@ -51,6 +54,7 @@ SRC_S += $(SDK_SRC_DIR)/Startup/startup_ch32v20x_${MCU_VARIANT}.S INC += \ $(TOP)/$(BOARD_PATH) \ + $(TOP)/$(SDK_SRC_DIR)/Core \ $(TOP)/$(SDK_SRC_DIR)/Peripheral/inc \ FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/RISC-V diff --git a/hw/bsp/ch32v307/core_riscv.h b/hw/bsp/ch32v307/core_riscv.h deleted file mode 100644 index a7ce10a00..000000000 --- a/hw/bsp/ch32v307/core_riscv.h +++ /dev/null @@ -1,379 +0,0 @@ -/********************************** (C) COPYRIGHT ******************************* -* File Name : core_riscv.h -* Author : WCH -* Version : V1.0.0 -* Date : 2021/06/06 -* Description : RISC-V Core Peripheral Access Layer Header File for CH32V30x -* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. -* SPDX-License-Identifier: Apache-2.0 -*******************************************************************************/ -#ifndef __CORE_RISCV_H__ -#define __CORE_RISCV_H__ - -/* IO definitions */ -#ifdef __cplusplus - #define __I volatile /* defines 'read only' permissions */ -#else - #define __I volatile const /* defines 'read only' permissions */ -#endif -#define __O volatile /* defines 'write only' permissions */ -#define __IO volatile /* defines 'read / write' permissions */ - -/* Standard Peripheral Library old types (maintained for legacy purpose) */ -typedef __I uint64_t vuc64; /* Read Only */ -typedef __I uint32_t vuc32; /* Read Only */ -typedef __I uint16_t vuc16; /* Read Only */ -typedef __I uint8_t vuc8; /* Read Only */ - -typedef const uint64_t uc64; /* Read Only */ -typedef const uint32_t uc32; /* Read Only */ -typedef const uint16_t uc16; /* Read Only */ -typedef const uint8_t uc8; /* Read Only */ - -typedef __I int64_t vsc64; /* Read Only */ -typedef __I int32_t vsc32; /* Read Only */ -typedef __I int16_t vsc16; /* Read Only */ -typedef __I int8_t vsc8; /* Read Only */ - -typedef const int64_t sc64; /* Read Only */ -typedef const int32_t sc32; /* Read Only */ -typedef const int16_t sc16; /* Read Only */ -typedef const int8_t sc8; /* Read Only */ - -typedef __IO uint64_t vu64; -typedef __IO uint32_t vu32; -typedef __IO uint16_t vu16; -typedef __IO uint8_t vu8; - -typedef uint64_t u64; -typedef uint32_t u32; -typedef uint16_t u16; -typedef uint8_t u8; - -typedef __IO int64_t vs64; -typedef __IO int32_t vs32; -typedef __IO int16_t vs16; -typedef __IO int8_t vs8; - -typedef int64_t s64; -typedef int32_t s32; -typedef int16_t s16; -typedef int8_t s8; - -typedef enum {ERROR = 0, SUCCESS = !ERROR} ErrorStatus; - -typedef enum {DISABLE = 0, ENABLE = !DISABLE} FunctionalState; - -typedef enum {RESET = 0, SET = !RESET} FlagStatus, ITStatus; - -#define RV_STATIC_INLINE static inline - -/* memory mapped structure for Program Fast Interrupt Controller (PFIC) */ -typedef struct{ - __I uint32_t ISR[8]; - __I uint32_t IPR[8]; - __IO uint32_t ITHRESDR; - __IO uint32_t RESERVED; - __IO uint32_t CFGR; - __I uint32_t GISR; - uint8_t VTFIDR[4]; - uint8_t RESERVED0[12]; - __IO uint32_t VTFADDR[4]; - uint8_t RESERVED1[0x90]; - __O uint32_t IENR[8]; - uint8_t RESERVED2[0x60]; - __O uint32_t IRER[8]; - uint8_t RESERVED3[0x60]; - __O uint32_t IPSR[8]; - uint8_t RESERVED4[0x60]; - __O uint32_t IPRR[8]; - uint8_t RESERVED5[0x60]; - __IO uint32_t IACTR[8]; - uint8_t RESERVED6[0xE0]; - __IO uint8_t IPRIOR[256]; - uint8_t RESERVED7[0x810]; - __IO uint32_t SCTLR; -}PFIC_Type; - -/* memory mapped structure for SysTick */ -typedef struct -{ - __IO u32 CTLR; - __IO u32 SR; - __IO u64 CNT; - __IO u64 CMP; -}SysTick_Type; - - -#define PFIC ((PFIC_Type *) 0xE000E000 ) -#define NVIC PFIC -#define NVIC_KEY1 ((uint32_t)0xFA050000) -#define NVIC_KEY2 ((uint32_t)0xBCAF0000) -#define NVIC_KEY3 ((uint32_t)0xBEEF0000) - -#define SysTick ((SysTick_Type *) 0xE000F000) - - -/********************************************************************* - * @fn __enable_irq - * - * @brief Enable Global Interrupt - * - * @return none - */ -RV_STATIC_INLINE void __enable_irq(void) -{ - __asm volatile ("csrw 0x800, %0" : : "r" (0x6088) ); -} - -/********************************************************************* - * @fn __disable_irq - * - * @brief Disable Global Interrupt - * - * @return none - */ -RV_STATIC_INLINE void __disable_irq(void) -{ - __asm volatile ("csrw 0x800, %0" : : "r" (0x6000) ); -} - -/********************************************************************* - * @fn __NOP - * - * @brief nop - * - * @return none - */ -RV_STATIC_INLINE void __NOP(void) -{ - __asm volatile ("nop"); -} - -/********************************************************************* - * @fn NVIC_EnableIRQ - * - * @brief Enable Interrupt - * - * @param IRQn: Interrupt Numbers - * - * @return none - */ -RV_STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) -{ - NVIC->IENR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); -} - -/********************************************************************* - * @fn NVIC_DisableIRQ - * - * @brief Disable Interrupt - * - * @param IRQn: Interrupt Numbers - * - * @return none - */ -RV_STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) -{ - NVIC->IRER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); -} - -/********************************************************************* - * @fn NVIC_GetStatusIRQ - * - * @brief Get Interrupt Enable State - * - * @param IRQn: Interrupt Numbers - * - * @return 1 - Interrupt Enable - * 0 - Interrupt Disable - */ -RV_STATIC_INLINE uint32_t NVIC_GetStatusIRQ(IRQn_Type IRQn) -{ - return((uint32_t) ((NVIC->ISR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); -} - -/********************************************************************* - * @fn NVIC_GetPendingIRQ - * - * @brief Get Interrupt Pending State - * - * @param IRQn: Interrupt Numbers - * - * @return 1 - Interrupt Pending Enable - * 0 - Interrupt Pending Disable - */ -RV_STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) -{ - return((uint32_t) ((NVIC->IPR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); -} - -/********************************************************************* - * @fn NVIC_SetPendingIRQ - * - * @brief Set Interrupt Pending - * - * @param IRQn: Interrupt Numbers - * - * @return None - */ -RV_STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) -{ - NVIC->IPSR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); -} - -/********************************************************************* - * @fn NVIC_ClearPendingIRQ - * - * @brief Clear Interrupt Pending - * - * @param IRQn: Interrupt Numbers - * - * @return None - */ -RV_STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) -{ - NVIC->IPRR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); -} - -/********************************************************************* - * @fn NVIC_GetActive - * - * @brief Get Interrupt Active State - * - * @param IRQn: Interrupt Numbers - * - * @return 1 - Interrupt Active - * 0 - Interrupt No Active - */ -RV_STATIC_INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn) -{ - return((uint32_t)((NVIC->IACTR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); -} - -/********************************************************************* - * @fn NVIC_SetPriority - * - * @brief Set Interrupt Priority - * - * @param IRQn - Interrupt Numbers - * priority - - * bit7 - pre-emption priority - * bit6~bit4 - subpriority - * @return None - */ -RV_STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint8_t priority) -{ - NVIC->IPRIOR[(uint32_t)(IRQn)] = priority; -} - -/********************************************************************* - * @fn __WFI - * - * @brief Wait for Interrupt - * - * @return None - */ -__attribute__( ( always_inline ) ) RV_STATIC_INLINE void __WFI(void) -{ - NVIC->SCTLR &= ~(1<<3); // wfi - asm volatile ("wfi"); -} - -/********************************************************************* - * @fn __WFE - * - * @brief Wait for Events - * - * @return None - */ -__attribute__( ( always_inline ) ) RV_STATIC_INLINE void __WFE(void) -{ - uint32_t t; - - t = NVIC->SCTLR; - NVIC->SCTLR |= (1<<3)|(1<<5); // (wfi->wfe)+(__sev) - NVIC->SCTLR = (NVIC->SCTLR & ~(1<<5)) | ( t & (1<<5)); - asm volatile ("wfi"); - asm volatile ("wfi"); -} - -/********************************************************************* - * @fn SetVTFIRQ - * - * @brief Set VTF Interrupt - * - * @param add - VTF interrupt service function base address. - * IRQn -Interrupt Numbers - * num - VTF Interrupt Numbers - * NewState - DISABLE or ENABLE - * @return None - */ -RV_STATIC_INLINE void SetVTFIRQ(uint32_t addr, IRQn_Type IRQn, uint8_t num, FunctionalState NewState){ - if(num > 3) return ; - - if (NewState != DISABLE) - { - NVIC->VTFIDR[num] = IRQn; - NVIC->VTFADDR[num] = ((addr&0xFFFFFFFE)|0x1); - } - else{ - NVIC->VTFIDR[num] = IRQn; - NVIC->VTFADDR[num] = ((addr&0xFFFFFFFE)&(~0x1)); - } -} - -/********************************************************************* - * @fn NVIC_SystemReset - * - * @brief Initiate a system reset request - * - * @return None - */ -RV_STATIC_INLINE void NVIC_SystemReset(void) -{ - NVIC->CFGR = NVIC_KEY3|(1<<7); -} - - -/* Core_Exported_Functions */ -extern uint32_t __get_FFLAGS(void); -extern void __set_FFLAGS(uint32_t value); -extern uint32_t __get_FRM(void); -extern void __set_FRM(uint32_t value); -extern uint32_t __get_FCSR(void); -extern void __set_FCSR(uint32_t value); -extern uint32_t __get_MSTATUS(void); -extern void __set_MSTATUS(uint32_t value); -extern uint32_t __get_MISA(void); -extern void __set_MISA(uint32_t value); -extern uint32_t __get_MIE(void); -extern void __set_MIE(uint32_t value); -extern uint32_t __get_MTVEC(void); -extern void __set_MTVEC(uint32_t value); -extern uint32_t __get_MSCRATCH(void); -extern void __set_MSCRATCH(uint32_t value); -extern uint32_t __get_MEPC(void); -extern void __set_MEPC(uint32_t value); -extern uint32_t __get_MCAUSE(void); -extern void __set_MCAUSE(uint32_t value); -extern uint32_t __get_MTVAL(void); -extern void __set_MTVAL(uint32_t value); -extern uint32_t __get_MIP(void); -extern void __set_MIP(uint32_t value); -extern uint32_t __get_MCYCLE(void); -extern void __set_MCYCLE(uint32_t value); -extern uint32_t __get_MCYCLEH(void); -extern void __set_MCYCLEH(uint32_t value); -extern uint32_t __get_MINSTRET(void); -extern void __set_MINSTRET(uint32_t value); -extern uint32_t __get_MINSTRETH(void); -extern void __set_MINSTRETH(uint32_t value); -extern uint32_t __get_MVENDORID(void); -extern uint32_t __get_MARCHID(void); -extern uint32_t __get_MIMPID(void); -extern uint32_t __get_MHARTID(void); -extern uint32_t __get_SP(void); - - -#endif diff --git a/hw/bsp/ch32v307/debug_uart.c b/hw/bsp/ch32v307/debug_uart.c index fbabeeadc..2fd3a9d64 100644 --- a/hw/bsp/ch32v307/debug_uart.c +++ b/hw/bsp/ch32v307/debug_uart.c @@ -25,8 +25,17 @@ */ #include "debug_uart.h" + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-prototypes" +#endif + #include +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif #define UART_RINGBUFFER_SIZE_TX 128 #define UART_RINGBUFFER_MASK_TX (UART_RINGBUFFER_SIZE_TX-1) diff --git a/hw/bsp/ch32v307/family.c b/hw/bsp/ch32v307/family.c index 0846b10a9..adf2dbea5 100644 --- a/hw/bsp/ch32v307/family.c +++ b/hw/bsp/ch32v307/family.c @@ -25,9 +25,22 @@ */ #include "stdio.h" + +// https://github.com/openwch/ch32v307/pull/90 +// https://github.com/openwch/ch32v20x/pull/12 + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-prototypes" +#endif + #include "debug_uart.h" #include "ch32v30x.h" +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + #include "bsp/board_api.h" #include "board.h" diff --git a/hw/bsp/ch32v307/family.cmake b/hw/bsp/ch32v307/family.cmake index af26bfc31..d603af62d 100644 --- a/hw/bsp/ch32v307/family.cmake +++ b/hw/bsp/ch32v307/family.cmake @@ -49,6 +49,7 @@ function(add_board_target BOARD_TARGET) ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${BOARD_TARGET} PUBLIC + ${SDK_SRC_DIR}/Core ${SDK_SRC_DIR}/Peripheral/inc ${CMAKE_CURRENT_FUNCTION_LIST_DIR} ) diff --git a/hw/bsp/ch32v307/family.mk b/hw/bsp/ch32v307/family.mk index 30a070a9b..bf2732106 100644 --- a/hw/bsp/ch32v307/family.mk +++ b/hw/bsp/ch32v307/family.mk @@ -25,6 +25,9 @@ CFLAGS += \ -fsigned-char \ -DCFG_TUSB_MCU=OPT_MCU_CH32V307 \ +# https://github.com/openwch/ch32v307/pull/90 +CFLAGS += -Wno-error=strict-prototypes + ifeq ($(SPEED),high) $(info "Using USBHS driver for HighSpeed mode") CFLAGS += -DCFG_TUD_WCH_USBIP_USBHS=1 @@ -51,6 +54,7 @@ SRC_S += \ INC += \ $(TOP)/$(BOARD_PATH) \ + $(TOP)/$(SDK_SRC_DIR)/Core \ $(TOP)/$(SDK_SRC_DIR)/Peripheral/inc # For freeRTOS port source diff --git a/src/portable/st/stm32_fsdev/fsdev_ch32.h b/src/portable/st/stm32_fsdev/fsdev_ch32.h index 85fe3266c..dbf2a0289 100644 --- a/src/portable/st/stm32_fsdev/fsdev_ch32.h +++ b/src/portable/st/stm32_fsdev/fsdev_ch32.h @@ -36,13 +36,23 @@ #include "common/tusb_compiler.h" +// https://github.com/openwch/ch32v307/pull/90 +// https://github.com/openwch/ch32v20x/pull/12 +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-prototypes" +#endif + #if CFG_TUSB_MCU == OPT_MCU_CH32V20X #include - #elif CFG_TUSB_MCU == OPT_MCU_CH32F20X #include #endif +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + #define FSDEV_PMA_SIZE (512u) // volatile 32-bit aligned diff --git a/src/portable/wch/ch32_usbfs_reg.h b/src/portable/wch/ch32_usbfs_reg.h index 0a50a6169..ef6ebf2dc 100644 --- a/src/portable/wch/ch32_usbfs_reg.h +++ b/src/portable/wch/ch32_usbfs_reg.h @@ -28,6 +28,13 @@ #ifndef USB_CH32_USBFS_REG_H #define USB_CH32_USBFS_REG_H +// https://github.com/openwch/ch32v307/pull/90 +// https://github.com/openwch/ch32v20x/pull/12 +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-prototypes" +#endif + #if CFG_TUSB_MCU == OPT_MCU_CH32V307 #include #define USBHD_IRQn OTG_FS_IRQn @@ -39,6 +46,10 @@ #include #endif +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + // CTRL #define USBFS_CTRL_DMA_EN (1 << 0) #define USBFS_CTRL_CLR_ALL (1 << 1) diff --git a/src/portable/wch/ch32_usbhs_reg.h b/src/portable/wch/ch32_usbhs_reg.h index 130e4f223..87300b497 100644 --- a/src/portable/wch/ch32_usbhs_reg.h +++ b/src/portable/wch/ch32_usbhs_reg.h @@ -28,12 +28,24 @@ #ifndef USB_CH32_USBHS_REG_H #define USB_CH32_USBHS_REG_H +// https://github.com/openwch/ch32v307/pull/90 +// https://github.com/openwch/ch32v20x/pull/12 +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-prototypes" +#endif + #if CFG_TUSB_MCU == OPT_MCU_CH32V307 #include #elif CFG_TUSB_MCU == OPT_MCU_CH32F20X #include #endif +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + + /******************* GLOBAL ******************/ // USB CONTROL -- cgit v1.3.1 From 969b06d77c8a37510c9bed8dde377ff7bf462a30 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 14 Jun 2024 12:51:50 +0700 Subject: minor update --- src/class/hid/hid.h | 4 ++-- src/class/net/ncm_device.c | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index 2fe922136..c2b5a8a48 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -762,7 +762,7 @@ enum { HID_USAGE_PAGE_ALPHA_DISPLAY = 0x14, HID_USAGE_PAGE_MEDICAL = 0x40, HID_USAGE_PAGE_LIGHTING_AND_ILLUMINATION = 0x59, - HID_USAGE_PAGE_MONITOR = 0x80, //0x80 - 0x83 + HID_USAGE_PAGE_MONITOR = 0x80, // 0x80 - 0x83 HID_USAGE_PAGE_POWER = 0x84, // 0x084 - 0x87 HID_USAGE_PAGE_BARCODE_SCANNER = 0x8c, HID_USAGE_PAGE_SCALE = 0x8d, @@ -770,7 +770,7 @@ enum { HID_USAGE_PAGE_CAMERA = 0x90, HID_USAGE_PAGE_ARCADE = 0x91, HID_USAGE_PAGE_FIDO = 0xF1D0, // FIDO alliance HID usage page - HID_USAGE_PAGE_VENDOR = 0xFF00 // 0xFF00 - 0xFFFF + HID_USAGE_PAGE_VENDOR = 0xFF00 // 0xFF00 - 0xFFFF }; /// HID Usage Table - Table 6: Generic Desktop Page diff --git a/src/class/net/ncm_device.c b/src/class/net/ncm_device.c index 64aba011a..44a6a0de9 100644 --- a/src/class/net/ncm_device.c +++ b/src/class/net/ncm_device.c @@ -1,6 +1,8 @@ /* * The MIT License (MIT) * + * Copyright (c) 2020 Jacob Berg Potter + * Copyright (c) 2020 Peter Lawrence * Copyright (c) 2019 Ha Thach (tinyusb.org) * Copyright (c) 2024 Hardy Griech * -- cgit v1.3.1 From 33f5547ed435f33259afc2a8e906eb7a258fbdd6 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 14 Jun 2024 16:06:37 +0700 Subject: add ch32v103 bsp support, compile but does not run, probably due to compile/linker issue --- .../ch32v10x/boards/ch32v103r_r1_1v0/board.cmake | 8 + hw/bsp/ch32v10x/boards/ch32v103r_r1_1v0/board.h | 20 + hw/bsp/ch32v10x/boards/ch32v103r_r1_1v0/board.mk | 7 + hw/bsp/ch32v10x/ch32v10x_conf.h | 37 ++ hw/bsp/ch32v10x/ch32v10x_it.h | 15 + hw/bsp/ch32v10x/family.c | 147 +++++ hw/bsp/ch32v10x/family.cmake | 117 ++++ hw/bsp/ch32v10x/family.mk | 53 ++ hw/bsp/ch32v10x/linker/ch32v10x.ld | 165 ++++++ hw/bsp/ch32v10x/system_ch32v10x.c | 600 +++++++++++++++++++++ hw/bsp/ch32v10x/system_ch32v10x.h | 29 + hw/bsp/ch32v10x/wch-riscv.cfg | 17 + hw/bsp/ch32v20x/family.mk | 10 +- hw/bsp/family_support.cmake | 2 +- src/common/tusb_mcu.h | 9 + src/portable/wch/ch32_usbfs_reg.h | 67 ++- src/tusb_option.h | 6 +- tools/get_deps.py | 3 + 18 files changed, 1296 insertions(+), 16 deletions(-) create mode 100644 hw/bsp/ch32v10x/boards/ch32v103r_r1_1v0/board.cmake create mode 100644 hw/bsp/ch32v10x/boards/ch32v103r_r1_1v0/board.h create mode 100644 hw/bsp/ch32v10x/boards/ch32v103r_r1_1v0/board.mk create mode 100644 hw/bsp/ch32v10x/ch32v10x_conf.h create mode 100644 hw/bsp/ch32v10x/ch32v10x_it.h create mode 100644 hw/bsp/ch32v10x/family.c create mode 100644 hw/bsp/ch32v10x/family.cmake create mode 100644 hw/bsp/ch32v10x/family.mk create mode 100644 hw/bsp/ch32v10x/linker/ch32v10x.ld create mode 100644 hw/bsp/ch32v10x/system_ch32v10x.c create mode 100644 hw/bsp/ch32v10x/system_ch32v10x.h create mode 100644 hw/bsp/ch32v10x/wch-riscv.cfg (limited to 'src') diff --git a/hw/bsp/ch32v10x/boards/ch32v103r_r1_1v0/board.cmake b/hw/bsp/ch32v10x/boards/ch32v103r_r1_1v0/board.cmake new file mode 100644 index 000000000..f6e47ba30 --- /dev/null +++ b/hw/bsp/ch32v10x/boards/ch32v103r_r1_1v0/board.cmake @@ -0,0 +1,8 @@ +set(LD_FLASH_SIZE 64K) +set(LD_RAM_SIZE 20K) + +function(update_board TARGET) + target_compile_definitions(${TARGET} PUBLIC + CFG_EXAMPLE_MSC_DUAL_READONLY + ) +endfunction() diff --git a/hw/bsp/ch32v10x/boards/ch32v103r_r1_1v0/board.h b/hw/bsp/ch32v10x/boards/ch32v103r_r1_1v0/board.h new file mode 100644 index 000000000..3b1187c3a --- /dev/null +++ b/hw/bsp/ch32v10x/boards/ch32v103r_r1_1v0/board.h @@ -0,0 +1,20 @@ +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define LED_PORT GPIOA +#define LED_PIN GPIO_Pin_10 +#define LED_STATE_ON 0 + +#define BUTTON_PORT GPIOA +#define BUTTON_PIN GPIO_Pin_1 +#define BUTTON_STATE_ACTIVE 0 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hw/bsp/ch32v10x/boards/ch32v103r_r1_1v0/board.mk b/hw/bsp/ch32v10x/boards/ch32v103r_r1_1v0/board.mk new file mode 100644 index 000000000..7d7462312 --- /dev/null +++ b/hw/bsp/ch32v10x/boards/ch32v103r_r1_1v0/board.mk @@ -0,0 +1,7 @@ +MCU_VARIANT = D6 + +CFLAGS += -DCFG_EXAMPLE_MSC_DUAL_READONLY + +LDFLAGS += \ + -Wl,--defsym=__flash_size=64K \ + -Wl,--defsym=__ram_size=20K \ diff --git a/hw/bsp/ch32v10x/ch32v10x_conf.h b/hw/bsp/ch32v10x/ch32v10x_conf.h new file mode 100644 index 000000000..939c0fbde --- /dev/null +++ b/hw/bsp/ch32v10x/ch32v10x_conf.h @@ -0,0 +1,37 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : ch32v10x_conf.h + * Author : WCH + * Version : V1.0.0 + * Date : 2020/04/30 + * Description : Library configuration file. +********************************************************************************* +* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. +* Attention: This software (modified or not) and binary are used for +* microcontroller manufactured by Nanjing Qinheng Microelectronics. +*******************************************************************************/ +#ifndef __CH32V10x_CONF_H +#define __CH32V10x_CONF_H + +#include "ch32v10x_adc.h" +#include "ch32v10x_bkp.h" +#include "ch32v10x_crc.h" +#include "ch32v10x_dbgmcu.h" +#include "ch32v10x_dma.h" +#include "ch32v10x_exti.h" +#include "ch32v10x_flash.h" +#include "ch32v10x_gpio.h" +#include "ch32v10x_i2c.h" +#include "ch32v10x_iwdg.h" +#include "ch32v10x_pwr.h" +#include "ch32v10x_rcc.h" +#include "ch32v10x_rtc.h" +#include "ch32v10x_spi.h" +#include "ch32v10x_tim.h" +#include "ch32v10x_usart.h" +#include "ch32v10x_wwdg.h" +#include "ch32v10x_usb.h" +#include "ch32v10x_usb_host.h" +#include "ch32v10x_it.h" +#include "ch32v10x_misc.h" + +#endif /* __CH32V10x_CONF_H */ diff --git a/hw/bsp/ch32v10x/ch32v10x_it.h b/hw/bsp/ch32v10x/ch32v10x_it.h new file mode 100644 index 000000000..13afc2412 --- /dev/null +++ b/hw/bsp/ch32v10x/ch32v10x_it.h @@ -0,0 +1,15 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : ch32v10x_it.h + * Author : WCH + * Version : V1.0.0 + * Date : 2022/08/20 + * Description : This file contains the headers of the interrupt handlers. +********************************************************************************* +* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. +* Attention: This software (modified or not) and binary are used for +* microcontroller manufactured by Nanjing Qinheng Microelectronics. +*******************************************************************************/ +#ifndef __CH32V10x_IT_H +#define __CH32V10x_IT_H + +#endif /* __CH32V10x_IT_H */ diff --git a/hw/bsp/ch32v10x/family.c b/hw/bsp/ch32v10x/family.c new file mode 100644 index 000000000..6de17521e --- /dev/null +++ b/hw/bsp/ch32v10x/family.c @@ -0,0 +1,147 @@ +#include + +// https://github.com/openwch/ch32v307/pull/90 +// https://github.com/openwch/ch32v20x/pull/12 +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-prototypes" +#endif + +#include "ch32v10x.h" + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + +#include "bsp/board_api.h" +#include "board.h" + +__attribute__((interrupt)) __attribute__((used)) +void USBHD_IRQHandler(void) { + #if CFG_TUD_WCH_USBIP_USBFS + tud_int_handler(0); + #endif +} + +__attribute__((interrupt)) __attribute__((used)) +void USBHDWakeUp_IRQHandler(void) { + #if CFG_TUD_WCH_USBIP_USBFS + tud_int_handler(0); + #endif +} + +#if CFG_TUSB_OS == OPT_OS_NONE +volatile uint32_t system_ticks = 0; + +__attribute__((interrupt)) __attribute__((used)) +void SysTick_Handler(void) { + SysTick->CNTL0 = SysTick->CNTL1 = SysTick->CNTL2 = SysTick->CNTL3 = 0; + SysTick->CNTH0 = SysTick->CNTH1 = SysTick->CNTH2 = SysTick->CNTH3 = 0; + system_ticks++; +} + +uint32_t SysTick_Config(uint32_t ticks) { + NVIC_EnableIRQ(SysTicK_IRQn); + SysTick->CTLR = 0; + SysTick->CNTL0 = SysTick->CNTL1 = SysTick->CNTL2 = SysTick->CNTL3 = 0; + SysTick->CNTH0 = SysTick->CNTH1 = SysTick->CNTH2 = SysTick->CNTH3 = 0; + + SysTick->CMPLR0 = (u8)(ticks & 0xFF); + SysTick->CMPLR1 = (u8)(ticks >> 8); + SysTick->CMPLR2 = (u8)(ticks >> 16); + SysTick->CMPLR3 = (u8)(ticks >> 24); + + SysTick->CMPHR0 = SysTick->CMPHR1 = SysTick->CMPHR2 = SysTick->CMPHR3 = 0; + SysTick->CTLR = 1; + return 0; +} + +uint32_t board_millis(void) { + return system_ticks; +} +#endif + +void board_init(void) { + __disable_irq(); + +#if CFG_TUSB_OS == OPT_OS_NONE + SysTick_Config(SystemCoreClock / 1000); +#endif + + uint8_t usb_div; + switch (SystemCoreClock) { + case 48000000: usb_div = RCC_USBCLKSource_PLLCLK_Div1; break; + case 72000000: usb_div = RCC_USBCLKSource_PLLCLK_1Div5; break; + default: TU_ASSERT(0,); break; + } + RCC_USBCLKConfig(usb_div); + RCC_APB1PeriphClockCmd(RCC_APB1Periph_USB, ENABLE); + + RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); + + #ifdef LED_PIN + GPIO_InitTypeDef led_init = { + .GPIO_Pin = LED_PIN, + .GPIO_Mode = GPIO_Mode_Out_OD, + .GPIO_Speed = GPIO_Speed_50MHz, + }; + GPIO_Init(LED_PORT, &led_init); + #endif + + #ifdef BUTTON_PIN + GPIO_InitTypeDef button_init = { + .GPIO_Pin = BUTTON_PIN, + .GPIO_Mode = GPIO_Mode_IPU, + .GPIO_Speed = GPIO_Speed_50MHz, + }; + GPIO_Init(BUTTON_PORT, &button_init); + #endif + + // UART TX is PA9 + RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); + GPIO_InitTypeDef usart_init = { + .GPIO_Pin = GPIO_Pin_9, + .GPIO_Speed = GPIO_Speed_50MHz, + .GPIO_Mode = GPIO_Mode_AF_PP, + }; + GPIO_Init(GPIOA, &usart_init); + + USART_InitTypeDef usart = { + .USART_BaudRate = 115200, + .USART_WordLength = USART_WordLength_8b, + .USART_StopBits = USART_StopBits_1, + .USART_Parity = USART_Parity_No, + .USART_Mode = USART_Mode_Tx, + .USART_HardwareFlowControl = USART_HardwareFlowControl_None, + }; + USART_Init(USART1, &usart); + USART_Cmd(USART1, ENABLE); + + __enable_irq(); + + board_led_write(true); +} + +void board_led_write(bool state) { + GPIO_WriteBit(LED_PORT, LED_PIN, state ? LED_STATE_ON : (1-LED_STATE_ON)); +} + +uint32_t board_button_read(void) { + return BUTTON_STATE_ACTIVE == GPIO_ReadInputDataBit(BUTTON_PORT, BUTTON_PIN); +} + +int board_uart_read(uint8_t *buf, int len) { + (void) buf; + (void) len; + return 0; +} + +int board_uart_write(void const *buf, int len) { + const char *bufc = (const char *) buf; + for (int i = 0; i < len; i++) { + while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET); + USART_SendData(USART1, *bufc++); + } + + return len; +} diff --git a/hw/bsp/ch32v10x/family.cmake b/hw/bsp/ch32v10x/family.cmake new file mode 100644 index 000000000..b0d8241d3 --- /dev/null +++ b/hw/bsp/ch32v10x/family.cmake @@ -0,0 +1,117 @@ +include_guard() + +#set(UF2_FAMILY_ID 0x699b62ec) +set(CH32_FAMILY ch32v10x) +set(SDK_DIR ${TOP}/hw/mcu/wch/ch32v103) +set(SDK_SRC_DIR ${SDK_DIR}/EVT/EXAM/SRC) + +# include board specific +include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) + +# toolchain set up +set(CMAKE_SYSTEM_PROCESSOR rv32imac-ilp32 CACHE INTERNAL "System Processor") +set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/riscv_${TOOLCHAIN}.cmake) + +set(FAMILY_MCUS CH32V103 CACHE INTERNAL "") +set(OPENOCD_OPTION "-f ${CMAKE_CURRENT_LIST_DIR}/wch-riscv.cfg") + +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +# only need to be built ONCE for all examples +function(add_board_target BOARD_TARGET) + if (TARGET ${BOARD_TARGET}) + return() + endif() + + if (NOT DEFINED LD_FILE_GNU) + set(LD_FILE_GNU ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/linker/${CH32_FAMILY}.ld) + endif () + set(LD_FILE_Clang ${LD_FILE_GNU}) + + if (NOT DEFINED STARTUP_FILE_GNU) + set(STARTUP_FILE_GNU ${SDK_SRC_DIR}/Startup/startup_${CH32_FAMILY}.S) + endif () + set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) + + add_library(${BOARD_TARGET} STATIC + ${SDK_SRC_DIR}/Core/core_riscv.c + ${SDK_SRC_DIR}/Peripheral/src/${CH32_FAMILY}_gpio.c + ${SDK_SRC_DIR}/Peripheral/src/${CH32_FAMILY}_misc.c + ${SDK_SRC_DIR}/Peripheral/src/${CH32_FAMILY}_rcc.c + ${SDK_SRC_DIR}/Peripheral/src/${CH32_FAMILY}_usart.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/system_${CH32_FAMILY}.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} + ) + target_include_directories(${BOARD_TARGET} PUBLIC + ${SDK_SRC_DIR}/Core + ${SDK_SRC_DIR}/Peripheral/inc + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ) + target_compile_definitions(${BOARD_TARGET} PUBLIC + ) + + update_board(${BOARD_TARGET}) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_compile_options(${BOARD_TARGET} PUBLIC + -mcmodel=medany + ) + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -Wl,--defsym=__flash_size=${LD_FLASH_SIZE} + -Wl,--defsym=__ram_size=${LD_RAM_SIZE} + -nostartfiles + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + message(FATAL_ERROR "Clang is not supported for MSP432E4") + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () +endfunction() + + +#------------------------------------ +# Functions +#------------------------------------ +function(family_configure_example TARGET RTOS) + family_configure_common(${TARGET} ${RTOS}) + + # Board target + add_board_target(board_${BOARD}) + + #---------- Port Specific ---------- + # These files are built for each example since it depends on example's tusb_config.h + target_sources(${TARGET} PUBLIC + # BSP + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ) + target_include_directories(${TARGET} PUBLIC + # family, hw, board + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} + ) + + # Add TinyUSB target and port source + family_add_tinyusb(${TARGET} OPT_MCU_CH32V103 ${RTOS}) + + target_sources(${TARGET}-tinyusb PUBLIC + ${TOP}/src/portable/wch/dcd_ch32_usbfs.c + ) + target_link_libraries(${TARGET}-tinyusb PUBLIC board_${BOARD}) + + # Link dependencies + target_link_libraries(${TARGET} PUBLIC board_${BOARD} ${TARGET}-tinyusb) + + # Flashing + family_add_bin_hex(${TARGET}) + family_flash_openocd_wch(${TARGET}) + + #family_add_uf2(${TARGET} ${UF2_FAMILY_ID}) + #family_flash_uf2(${TARGET} ${UF2_FAMILY_ID}) +endfunction() diff --git a/hw/bsp/ch32v10x/family.mk b/hw/bsp/ch32v10x/family.mk new file mode 100644 index 000000000..d96d5012e --- /dev/null +++ b/hw/bsp/ch32v10x/family.mk @@ -0,0 +1,53 @@ +# https://www.embecosm.com/resources/tool-chain-downloads/#riscv-stable +#CROSS_COMPILE ?= riscv32-unknown-elf- + +# Toolchain from https://nucleisys.com/download.php +#CROSS_COMPILE ?= riscv-nuclei-elf- + +# Toolchain from https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack +CROSS_COMPILE ?= riscv-none-elf- + +CH32_FAMILY = ch32v10x +SDK_DIR = hw/mcu/wch/ch32v103 +SDK_SRC_DIR = $(SDK_DIR)/EVT/EXAM/SRC + +include $(TOP)/$(BOARD_PATH)/board.mk +CPU_CORE ?= rv32imac-ilp32 + +# Port0 use FSDev, Port1 use USBFS +PORT ?= 0 + +CFLAGS += \ + -mcmodel=medany \ + -ffat-lto-objects \ + -flto \ + -DCFG_TUSB_MCU=OPT_MCU_CH32V103 + +# https://github.com/openwch/ch32v20x/pull/12 +CFLAGS += -Wno-error=strict-prototypes + +LDFLAGS_GCC += \ + -nostdlib -nostartfiles \ + --specs=nosys.specs --specs=nano.specs \ + +LD_FILE = $(FAMILY_PATH)/linker/${CH32_FAMILY}.ld + +SRC_C += \ + src/portable/wch/dcd_ch32_usbfs.c \ + $(SDK_SRC_DIR)/Core/core_riscv.c \ + $(SDK_SRC_DIR)/Peripheral/src/${CH32_FAMILY}_gpio.c \ + $(SDK_SRC_DIR)/Peripheral/src/${CH32_FAMILY}_misc.c \ + $(SDK_SRC_DIR)/Peripheral/src/${CH32_FAMILY}_rcc.c \ + $(SDK_SRC_DIR)/Peripheral/src/${CH32_FAMILY}_usart.c \ + +SRC_S += $(SDK_SRC_DIR)/Startup/startup_${CH32_FAMILY}.S + +INC += \ + $(TOP)/$(BOARD_PATH) \ + $(TOP)/$(SDK_SRC_DIR)/Core \ + $(TOP)/$(SDK_SRC_DIR)/Peripheral/inc \ + +FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/RISC-V + +OPENOCD_WCH_OPTION=-f $(TOP)/$(FAMILY_PATH)/wch-riscv.cfg +flash: flash-openocd-wch diff --git a/hw/bsp/ch32v10x/linker/ch32v10x.ld b/hw/bsp/ch32v10x/linker/ch32v10x.ld new file mode 100644 index 000000000..cd5c8dc17 --- /dev/null +++ b/hw/bsp/ch32v10x/linker/ch32v10x.ld @@ -0,0 +1,165 @@ +/* Define default values if not already defined */ +__FLASH_SIZE = DEFINED(__flash_size) ? __flash_size : 64K; +__RAM_SIZE = DEFINED(__ram_size) ? __ram_size : 20K; + +MEMORY +{ + FLASH (rx) : ORIGIN = 0x00000000, LENGTH = __FLASH_SIZE + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = __RAM_SIZE +} + +ENTRY( _start ) + +__stack_size = 2048; + +PROVIDE( _stack_size = __stack_size ); + +SECTIONS +{ + .init : + { + _sinit = .; + . = ALIGN(4); + KEEP(*(SORT_NONE(.init))) + . = ALIGN(4); + _einit = .; + } >FLASH AT>FLASH + + .vector : + { + *(.vector); + . = ALIGN(64); + } >FLASH AT>FLASH + + .text : + { + . = ALIGN(4); + *(.text) + *(.text.*) + *(.rodata) + *(.rodata*) + *(.gnu.linkonce.t.*) + . = ALIGN(4); + } >FLASH AT>FLASH + + .fini : + { + KEEP(*(SORT_NONE(.fini))) + . = ALIGN(4); + } >FLASH AT>FLASH + + PROVIDE( _etext = . ); + PROVIDE( _eitcm = . ); + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >FLASH AT>FLASH + + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) + PROVIDE_HIDDEN (__init_array_end = .); + } >FLASH AT>FLASH + + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) + KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) + PROVIDE_HIDDEN (__fini_array_end = .); + } >FLASH AT>FLASH + + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } >FLASH AT>FLASH + + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } >FLASH AT>FLASH + + .dalign : + { + . = ALIGN(4); + PROVIDE(_data_vma = .); + } >RAM AT>FLASH + + .dlalign : + { + . = ALIGN(4); + PROVIDE(_data_lma = .); + } >FLASH AT>FLASH + + .data : + { + *(.gnu.linkonce.r.*) + *(.data .data.*) + *(.gnu.linkonce.d.*) + . = ALIGN(8); + PROVIDE( __global_pointer$ = . + 0x800 ); + *(.sdata .sdata.*) + *(.sdata2.*) + *(.gnu.linkonce.s.*) + . = ALIGN(8); + *(.srodata.cst16) + *(.srodata.cst8) + *(.srodata.cst4) + *(.srodata.cst2) + *(.srodata .srodata.*) + . = ALIGN(4); + PROVIDE( _edata = .); + } >RAM AT>FLASH + + .bss : + { + . = ALIGN(4); + PROVIDE( _sbss = .); + *(.sbss*) + *(.gnu.linkonce.sb.*) + *(.bss*) + *(.gnu.linkonce.b.*) + *(COMMON*) + . = ALIGN(4); + PROVIDE( _ebss = .); + } >RAM AT>FLASH + + PROVIDE( _end = _ebss); + PROVIDE( end = . ); + + .stack ORIGIN(RAM) + LENGTH(RAM) - __stack_size : + { + PROVIDE( _heap_end = . ); + . = ALIGN(4); + PROVIDE(_susrstack = . ); + . = . + __stack_size; + PROVIDE( _eusrstack = .); + } >RAM + +} diff --git a/hw/bsp/ch32v10x/system_ch32v10x.c b/hw/bsp/ch32v10x/system_ch32v10x.c new file mode 100644 index 000000000..b083b83b4 --- /dev/null +++ b/hw/bsp/ch32v10x/system_ch32v10x.c @@ -0,0 +1,600 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : system_ch32v10x.c + * Author : WCH + * Version : V1.0.0 + * Date : 2020/04/30 + * Description : CH32V10x Device Peripheral Access Layer System Source File. +********************************************************************************* +* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. +* Attention: This software (modified or not) and binary are used for +* microcontroller manufactured by Nanjing Qinheng Microelectronics. +*******************************************************************************/ +#include "ch32v10x.h" + +/* + * Uncomment the line corresponding to the desired System clock (SYSCLK) frequency (after + * reset the HSI is used as SYSCLK source). + * If none of the define below is enabled, the HSI is used as System clock source. + */ +//#define SYSCLK_FREQ_HSE HSE_VALUE +//#define SYSCLK_FREQ_48MHz_HSE 48000000 +//#define SYSCLK_FREQ_56MHz_HSE 56000000 +#define SYSCLK_FREQ_72MHz_HSE 72000000 +//#define SYSCLK_FREQ_HSI HSI_VALUE +//#define SYSCLK_FREQ_48MHz_HSI 48000000 +//#define SYSCLK_FREQ_56MHz_HSI 56000000 +//#define SYSCLK_FREQ_72MHz_HSI 72000000 + +/* Clock Definitions */ +#ifdef SYSCLK_FREQ_HSE +uint32_t SystemCoreClock = SYSCLK_FREQ_HSE; /* System Clock Frequency (Core Clock) */ +#elif defined SYSCLK_FREQ_48MHz_HSE +uint32_t SystemCoreClock = SYSCLK_FREQ_48MHz_HSE; /* System Clock Frequency (Core Clock) */ +#elif defined SYSCLK_FREQ_56MHz_HSE +uint32_t SystemCoreClock = SYSCLK_FREQ_56MHz_HSE; /* System Clock Frequency (Core Clock) */ +#elif defined SYSCLK_FREQ_72MHz_HSE +uint32_t SystemCoreClock = SYSCLK_FREQ_72MHz_HSE; /* System Clock Frequency (Core Clock) */ +#elif defined SYSCLK_FREQ_48MHz_HSI +uint32_t SystemCoreClock = SYSCLK_FREQ_48MHz_HSI; /* System Clock Frequency (Core Clock) */ +#elif defined SYSCLK_FREQ_56MHz_HSI +uint32_t SystemCoreClock = SYSCLK_FREQ_56MHz_HSI; /* System Clock Frequency (Core Clock) */ +#elif defined SYSCLK_FREQ_72MHz_HSI +uint32_t SystemCoreClock = SYSCLK_FREQ_72MHz_HSI; /* System Clock Frequency (Core Clock) */ +#else +uint32_t SystemCoreClock = HSI_VALUE; /* System Clock Frequency (Core Clock) */ + +#endif + +__I uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; + +/* ch32v10x_system_private_function_proto_types */ +static void SetSysClock(void); + +#ifdef SYSCLK_FREQ_HSE +static void SetSysClockToHSE( void ); +#elif defined SYSCLK_FREQ_48MHz_HSE +static void SetSysClockTo48_HSE( void ); +#elif defined SYSCLK_FREQ_56MHz_HSE +static void SetSysClockTo56_HSE( void ); +#elif defined SYSCLK_FREQ_72MHz_HSE +static void SetSysClockTo72_HSE( void ); +#elif defined SYSCLK_FREQ_48MHz_HSI +static void SetSysClockTo48_HSI( void ); +#elif defined SYSCLK_FREQ_56MHz_HSI +static void SetSysClockTo56_HSI( void ); +#elif defined SYSCLK_FREQ_72MHz_HSI +static void SetSysClockTo72_HSI( void ); + +#endif + +/********************************************************************* + * @fn SystemInit + * + * @brief Setup the microcontroller system Initialize the Embedded Flash Interface, + * the PLL and update the SystemCoreClock variable. + * + * @return none + */ +void SystemInit(void) +{ + RCC->CTLR |= (uint32_t)0x00000001; + RCC->CFGR0 &= (uint32_t)0xF8FF0000; + RCC->CTLR &= (uint32_t)0xFEF6FFFF; + RCC->CTLR &= (uint32_t)0xFFFBFFFF; + RCC->CFGR0 &= (uint32_t)0xFF80FFFF; + RCC->INTR = 0x009F0000; + SetSysClock(); +} + +/********************************************************************* + * @fn SystemCoreClockUpdate + * + * @brief Update SystemCoreClock variable according to Clock Register Values. + * + * @return none + */ +void SystemCoreClockUpdate(void) +{ + uint32_t tmp = 0, pllmull = 0, pllsource = 0; + + tmp = RCC->CFGR0 & RCC_SWS; + + switch(tmp) + { + case 0x00: + SystemCoreClock = HSI_VALUE; + break; + case 0x04: + SystemCoreClock = HSE_VALUE; + break; + case 0x08: + pllmull = RCC->CFGR0 & RCC_PLLMULL; + pllsource = RCC->CFGR0 & RCC_PLLSRC; + pllmull = (pllmull >> 18) + 2; + if(pllsource == 0x00) + { + if( EXTEN->EXTEN_CTR & EXTEN_PLL_HSI_PRE ) + { + SystemCoreClock = ( HSI_VALUE ) * pllmull; + } + else + { + SystemCoreClock = ( HSI_VALUE >> 1 ) * pllmull; + } + } + else + { + if((RCC->CFGR0 & RCC_PLLXTPRE) != (uint32_t)RESET) + { + SystemCoreClock = (HSE_VALUE >> 1) * pllmull; + } + else + { + SystemCoreClock = HSE_VALUE * pllmull; + } + } + break; + default: + SystemCoreClock = HSI_VALUE; + break; + } + + tmp = AHBPrescTable[((RCC->CFGR0 & RCC_HPRE) >> 4)]; + SystemCoreClock >>= tmp; +} + +/********************************************************************* + * @fn SetSysClock + * + * @brief Configures the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers. + * + * @return none + */ +static void SetSysClock(void) +{ + //GPIO_IPD_Unused(); +#ifdef SYSCLK_FREQ_HSE + SetSysClockToHSE(); +#elif defined SYSCLK_FREQ_48MHz_HSE + SetSysClockTo48_HSE(); +#elif defined SYSCLK_FREQ_56MHz_HSE + SetSysClockTo56_HSE(); +#elif defined SYSCLK_FREQ_72MHz_HSE + SetSysClockTo72_HSE(); +#elif defined SYSCLK_FREQ_48MHz_HSI + SetSysClockTo48_HSI(); +#elif defined SYSCLK_FREQ_56MHz_HSI + SetSysClockTo56_HSI(); +#elif defined SYSCLK_FREQ_72MHz_HSI + SetSysClockTo72_HSI(); + +#endif + + /* If none of the define above is enabled, the HSI is used as System clock + * source (default after reset) + */ +} + +#ifdef SYSCLK_FREQ_HSE + +/********************************************************************* + * @fn SetSysClockToHSE + * + * @brief Sets HSE as System clock source and configure HCLK, PCLK2 and PCLK1 prescalers. + * + * @return none + */ +static void SetSysClockToHSE(void) +{ + __IO uint32_t StartUpCounter = 0, HSEStatus = 0; + + RCC->CTLR |= ((uint32_t)RCC_HSEON); + + /* Wait till HSE is ready and if Time out is reached exit */ + do + { + HSEStatus = RCC->CTLR & RCC_HSERDY; + StartUpCounter++; + } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); + + if((RCC->CTLR & RCC_HSERDY) != RESET) + { + HSEStatus = (uint32_t)0x01; + } + else + { + HSEStatus = (uint32_t)0x00; + } + + if(HSEStatus == (uint32_t)0x01) + { + FLASH->ACTLR |= FLASH_ACTLR_PRFTBE; + /* Flash 0 wait state */ + FLASH->ACTLR &= (uint32_t)((uint32_t)~FLASH_ACTLR_LATENCY); + FLASH->ACTLR |= (uint32_t)FLASH_ACTLR_LATENCY_0; + + /* HCLK = SYSCLK */ + RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1; + /* PCLK2 = HCLK */ + RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1; + /* PCLK1 = HCLK */ + RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV1; + + /* Select HSE as system clock source */ + RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_SW)); + RCC->CFGR0 |= (uint32_t)RCC_SW_HSE; + + /* Wait till HSE is used as system clock source */ + while((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x04) + { + } + } + else + { + /* If HSE fails to start-up, the application will have wrong clock + * configuration. User can add here some code to deal with this error + */ + } +} + + +#elif defined SYSCLK_FREQ_48MHz_HSE + +/********************************************************************* + * @fn SetSysClockTo48_HSE + * + * @brief Sets System clock frequency to 48MHz and configure HCLK, PCLK2 and PCLK1 prescalers. + * + * @return none + */ +static void SetSysClockTo48_HSE(void) +{ + __IO uint32_t StartUpCounter = 0, HSEStatus = 0; + + RCC->CTLR |= ((uint32_t)RCC_HSEON); + /* Wait till HSE is ready and if Time out is reached exit */ + do + { + HSEStatus = RCC->CTLR & RCC_HSERDY; + StartUpCounter++; + } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); + + if((RCC->CTLR & RCC_HSERDY) != RESET) + { + HSEStatus = (uint32_t)0x01; + } + else + { + HSEStatus = (uint32_t)0x00; + } + + if(HSEStatus == (uint32_t)0x01) + { + /* Enable Prefetch Buffer */ + FLASH->ACTLR |= FLASH_ACTLR_PRFTBE; + + /* Flash 1 wait state */ + FLASH->ACTLR &= (uint32_t)((uint32_t)~FLASH_ACTLR_LATENCY); + FLASH->ACTLR |= (uint32_t)FLASH_ACTLR_LATENCY_1; + + /* HCLK = SYSCLK */ + RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1; + /* PCLK2 = HCLK */ + RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1; + /* PCLK1 = HCLK */ + RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2; + + /* PLL configuration: PLLCLK = HSE * 6 = 48 MHz */ + RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL)); + RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLMULL6); + + /* Enable PLL */ + RCC->CTLR |= RCC_PLLON; + /* Wait till PLL is ready */ + while((RCC->CTLR & RCC_PLLRDY) == 0) + { + } + /* Select PLL as system clock source */ + RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_SW)); + RCC->CFGR0 |= (uint32_t)RCC_SW_PLL; + /* Wait till PLL is used as system clock source */ + while((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08) + { + } + } + else + { + /* + * If HSE fails to start-up, the application will have wrong clock + * configuration. User can add here some code to deal with this error + */ + } +} + +#elif defined SYSCLK_FREQ_56MHz_HSE + +/********************************************************************* + * @fn SetSysClockTo56_HSE + * + * @brief Sets System clock frequency to 56MHz and configure HCLK, PCLK2 and PCLK1 prescalers. + * + * @return none + */ +static void SetSysClockTo56_HSE(void) +{ + __IO uint32_t StartUpCounter = 0, HSEStatus = 0; + + RCC->CTLR |= ((uint32_t)RCC_HSEON); + + /* Wait till HSE is ready and if Time out is reached exit */ + do + { + HSEStatus = RCC->CTLR & RCC_HSERDY; + StartUpCounter++; + } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); + + if((RCC->CTLR & RCC_HSERDY) != RESET) + { + HSEStatus = (uint32_t)0x01; + } + else + { + HSEStatus = (uint32_t)0x00; + } + + if(HSEStatus == (uint32_t)0x01) + { + /* Enable Prefetch Buffer */ + FLASH->ACTLR |= FLASH_ACTLR_PRFTBE; + + /* Flash 2 wait state */ + FLASH->ACTLR &= (uint32_t)((uint32_t)~FLASH_ACTLR_LATENCY); + FLASH->ACTLR |= (uint32_t)FLASH_ACTLR_LATENCY_2; + + /* HCLK = SYSCLK */ + RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1; + /* PCLK2 = HCLK */ + RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1; + /* PCLK1 = HCLK */ + RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2; + + /* PLL configuration: PLLCLK = HSE * 7 = 56 MHz */ + RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL)); + RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLMULL7); + /* Enable PLL */ + RCC->CTLR |= RCC_PLLON; + /* Wait till PLL is ready */ + while((RCC->CTLR & RCC_PLLRDY) == 0) + { + } + + /* Select PLL as system clock source */ + RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_SW)); + RCC->CFGR0 |= (uint32_t)RCC_SW_PLL; + /* Wait till PLL is used as system clock source */ + while((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08) + { + } + } + else + { + /* + * If HSE fails to start-up, the application will have wrong clock + * configuration. User can add here some code to deal with this error + */ + } +} + +#elif defined SYSCLK_FREQ_72MHz_HSE + +/********************************************************************* + * @fn SetSysClockTo72_HSE + * + * @brief Sets System clock frequency to 72MHz and configure HCLK, PCLK2 and PCLK1 prescalers. + * + * @return none + */ +static void SetSysClockTo72_HSE(void) +{ + __IO uint32_t StartUpCounter = 0, HSEStatus = 0; + + RCC->CTLR |= ((uint32_t)RCC_HSEON); + + /* Wait till HSE is ready and if Time out is reached exit */ + do + { + HSEStatus = RCC->CTLR & RCC_HSERDY; + StartUpCounter++; + } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); + + if((RCC->CTLR & RCC_HSERDY) != RESET) + { + HSEStatus = (uint32_t)0x01; + } + else + { + HSEStatus = (uint32_t)0x00; + } + + if(HSEStatus == (uint32_t)0x01) + { + /* Enable Prefetch Buffer */ + FLASH->ACTLR |= FLASH_ACTLR_PRFTBE; + + /* Flash 2 wait state */ + FLASH->ACTLR &= (uint32_t)((uint32_t)~FLASH_ACTLR_LATENCY); + FLASH->ACTLR |= (uint32_t)FLASH_ACTLR_LATENCY_2; + + /* HCLK = SYSCLK */ + RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1; + /* PCLK2 = HCLK */ + RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1; + /* PCLK1 = HCLK */ + RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2; + + /* PLL configuration: PLLCLK = HSE * 9 = 72 MHz */ + RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_PLLSRC | RCC_PLLXTPRE | + RCC_PLLMULL)); + RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLMULL9); + /* Enable PLL */ + RCC->CTLR |= RCC_PLLON; + /* Wait till PLL is ready */ + while((RCC->CTLR & RCC_PLLRDY) == 0) + { + } + /* Select PLL as system clock source */ + RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_SW)); + RCC->CFGR0 |= (uint32_t)RCC_SW_PLL; + /* Wait till PLL is used as system clock source */ + while((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08) + { + } + } + else + { + /* + * If HSE fails to start-up, the application will have wrong clock + * configuration. User can add here some code to deal with this error + */ + } +} + +#elif defined SYSCLK_FREQ_48MHz_HSI + +/********************************************************************* + * @fn SetSysClockTo48_HSI + * + * @brief Sets System clock frequency to 48MHz and configure HCLK, PCLK2 and PCLK1 prescalers. + * + * @return none + */ +static void SetSysClockTo48_HSI(void) +{ + EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE; + + /* Enable Prefetch Buffer */ + FLASH->ACTLR |= FLASH_ACTLR_PRFTBE; + + /* Flash 1 wait state */ + FLASH->ACTLR &= (uint32_t)((uint32_t)~FLASH_ACTLR_LATENCY); + FLASH->ACTLR |= (uint32_t)FLASH_ACTLR_LATENCY_1; + + /* HCLK = SYSCLK */ + RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1; + /* PCLK2 = HCLK */ + RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1; + /* PCLK1 = HCLK */ + RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2; + + /* PLL configuration: PLLCLK = HSI * 6 = 48 MHz */ + RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL)); + RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL6); + + /* Enable PLL */ + RCC->CTLR |= RCC_PLLON; + /* Wait till PLL is ready */ + while((RCC->CTLR & RCC_PLLRDY) == 0) + { + } + /* Select PLL as system clock source */ + RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_SW)); + RCC->CFGR0 |= (uint32_t)RCC_SW_PLL; + /* Wait till PLL is used as system clock source */ + while((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08) + { + } +} + +#elif defined SYSCLK_FREQ_56MHz_HSI + +/********************************************************************* + * @fn SetSysClockTo56_HSI + * + * @brief Sets System clock frequency to 56MHz and configure HCLK, PCLK2 and PCLK1 prescalers. + * + * @return none + */ +static void SetSysClockTo56_HSI(void) +{ + EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE; + + /* Enable Prefetch Buffer */ + FLASH->ACTLR |= FLASH_ACTLR_PRFTBE; + + /* Flash 1 wait state */ + FLASH->ACTLR &= (uint32_t)((uint32_t)~FLASH_ACTLR_LATENCY); + FLASH->ACTLR |= (uint32_t)FLASH_ACTLR_LATENCY_1; + + /* HCLK = SYSCLK */ + RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1; + /* PCLK2 = HCLK */ + RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1; + /* PCLK1 = HCLK */ + RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2; + + /* PLL configuration: PLLCLK = HSI * 7 = 56 MHz */ + RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL)); + RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL7); + + /* Enable PLL */ + RCC->CTLR |= RCC_PLLON; + /* Wait till PLL is ready */ + while((RCC->CTLR & RCC_PLLRDY) == 0) + { + } + /* Select PLL as system clock source */ + RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_SW)); + RCC->CFGR0 |= (uint32_t)RCC_SW_PLL; + /* Wait till PLL is used as system clock source */ + while((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08) + { + } +} + +#elif defined SYSCLK_FREQ_72MHz_HSI + +/********************************************************************* + * @fn SetSysClockTo72_HSI + * + * @brief Sets System clock frequency to 72MHz and configure HCLK, PCLK2 and PCLK1 prescalers. + * + * @return none + */ +static void SetSysClockTo72_HSI(void) +{ + EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE; + + /* Enable Prefetch Buffer */ + FLASH->ACTLR |= FLASH_ACTLR_PRFTBE; + + /* Flash 1 wait state */ + FLASH->ACTLR &= (uint32_t)((uint32_t)~FLASH_ACTLR_LATENCY); + FLASH->ACTLR |= (uint32_t)FLASH_ACTLR_LATENCY_1; + + /* HCLK = SYSCLK */ + RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1; + /* PCLK2 = HCLK */ + RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1; + /* PCLK1 = HCLK */ + RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2; + + /* PLL configuration: PLLCLK = HSI * 9 = 72 MHz */ + RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL)); + RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSI_Div2 | RCC_PLLMULL9); + + /* Enable PLL */ + RCC->CTLR |= RCC_PLLON; + /* Wait till PLL is ready */ + while((RCC->CTLR & RCC_PLLRDY) == 0) + { + } + /* Select PLL as system clock source */ + RCC->CFGR0 &= (uint32_t)((uint32_t) ~(RCC_SW)); + RCC->CFGR0 |= (uint32_t)RCC_SW_PLL; + /* Wait till PLL is used as system clock source */ + while((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08) + { + } +} + +#endif diff --git a/hw/bsp/ch32v10x/system_ch32v10x.h b/hw/bsp/ch32v10x/system_ch32v10x.h new file mode 100644 index 000000000..d15624520 --- /dev/null +++ b/hw/bsp/ch32v10x/system_ch32v10x.h @@ -0,0 +1,29 @@ +/********************************** (C) COPYRIGHT ******************************* + * File Name : system_ch32v10x.h + * Author : WCH + * Version : V1.0.0 + * Date : 2020/04/30 + * Description : CH32V10x Device Peripheral Access Layer System Header File. +********************************************************************************* +* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. +* Attention: This software (modified or not) and binary are used for +* microcontroller manufactured by Nanjing Qinheng Microelectronics. +*******************************************************************************/ +#ifndef __SYSTEM_CH32V10x_H +#define __SYSTEM_CH32V10x_H + +#ifdef __cplusplus +extern "C" { +#endif + +extern uint32_t SystemCoreClock; /* System Clock Frequency (Core Clock) */ + +/* System_Exported_Functions */ +extern void SystemInit(void); +extern void SystemCoreClockUpdate(void); + +#ifdef __cplusplus +} +#endif + +#endif /*__CH32V10x_SYSTEM_H */ diff --git a/hw/bsp/ch32v10x/wch-riscv.cfg b/hw/bsp/ch32v10x/wch-riscv.cfg new file mode 100644 index 000000000..aa35aa9c5 --- /dev/null +++ b/hw/bsp/ch32v10x/wch-riscv.cfg @@ -0,0 +1,17 @@ +adapter driver wlinke +adapter speed 6000 +transport select sdi + +wlink_set_address 0x00000000 +set _CHIPNAME wch_riscv +sdi newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x00001 + +set _TARGETNAME $_CHIPNAME.cpu + +target create $_TARGETNAME.0 wch_riscv -chain-position $_TARGETNAME +$_TARGETNAME.0 configure -work-area-phys 0x20000000 -work-area-size 10000 -work-area-backup 1 +set _FLASHNAME $_CHIPNAME.flash + +flash bank $_FLASHNAME wch_riscv 0x00000000 0 0 0 $_TARGETNAME.0 + +echo "Ready for Remote Connections" diff --git a/hw/bsp/ch32v20x/family.mk b/hw/bsp/ch32v20x/family.mk index daf3148f8..4485091dc 100644 --- a/hw/bsp/ch32v20x/family.mk +++ b/hw/bsp/ch32v20x/family.mk @@ -45,12 +45,12 @@ SRC_C += \ src/portable/wch/dcd_ch32_usbfs.c \ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ $(SDK_SRC_DIR)/Core/core_riscv.c \ - $(SDK_SRC_DIR)/Peripheral/src/ch32v20x_gpio.c \ - $(SDK_SRC_DIR)/Peripheral/src/ch32v20x_misc.c \ - $(SDK_SRC_DIR)/Peripheral/src/ch32v20x_rcc.c \ - $(SDK_SRC_DIR)/Peripheral/src/ch32v20x_usart.c \ + $(SDK_SRC_DIR)/Peripheral/src/${CH32_FAMILY}_gpio.c \ + $(SDK_SRC_DIR)/Peripheral/src/${CH32_FAMILY}_misc.c \ + $(SDK_SRC_DIR)/Peripheral/src/${CH32_FAMILY}_rcc.c \ + $(SDK_SRC_DIR)/Peripheral/src/${CH32_FAMILY}_usart.c \ -SRC_S += $(SDK_SRC_DIR)/Startup/startup_ch32v20x_${MCU_VARIANT}.S +SRC_S += $(SDK_SRC_DIR)/Startup/startup_${CH32_FAMILY}_${MCU_VARIANT}.S INC += \ $(TOP)/$(BOARD_PATH) \ diff --git a/hw/bsp/family_support.cmake b/hw/bsp/family_support.cmake index d9443f811..94d55f04a 100644 --- a/hw/bsp/family_support.cmake +++ b/hw/bsp/family_support.cmake @@ -443,7 +443,7 @@ function(family_flash_openocd TARGET) # note skip verify since it has issue with rp2040 add_custom_target(${TARGET}-openocd DEPENDS ${TARGET} - COMMAND ${OPENOCD} ${OPTION_LIST} -c "program $ reset" ${OPTION_LIST2} -c exit + COMMAND ${OPENOCD} ${OPTION_LIST} -c init -c halt -c "program $ reset" ${OPTION_LIST2} -c exit VERBATIM ) endfunction() diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index c66996c4f..d9d11e96d 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -420,6 +420,15 @@ #define TUP_RHPORT_HIGHSPEED CFG_TUD_WCH_USBIP_USBHS #define TUP_DCD_ENDPOINT_MAX (CFG_TUD_WCH_USBIP_USBHS ? 16 : 8) +#elif TU_CHECK_MCU(OPT_MCU_CH32V103) + #define TUP_USBIP_WCH_USBFS + + #if !defined(CFG_TUD_WCH_USBIP_USBFS) + #define CFG_TUD_WCH_USBIP_USBFS 1 + #endif + + #define TUP_DCD_ENDPOINT_MAX 8 + #elif TU_CHECK_MCU(OPT_MCU_CH32V20X) // v20x support both FSDEV (USBD) and USBFS, default to FSDEV #define TUP_USBIP_WCH_USBFS diff --git a/src/portable/wch/ch32_usbfs_reg.h b/src/portable/wch/ch32_usbfs_reg.h index ef6ebf2dc..68be64f5e 100644 --- a/src/portable/wch/ch32_usbfs_reg.h +++ b/src/portable/wch/ch32_usbfs_reg.h @@ -35,15 +35,68 @@ #pragma GCC diagnostic ignored "-Wstrict-prototypes" #endif -#if CFG_TUSB_MCU == OPT_MCU_CH32V307 - #include - #define USBHD_IRQn OTG_FS_IRQn - +#if CFG_TUSB_MCU == OPT_MCU_CH32F20X + #include +#elif CFG_TUSB_MCU == OPT_MCU_CH32V103 + #include + typedef struct + { + __IO uint8_t BASE_CTRL; + __IO uint8_t UDEV_CTRL; + __IO uint8_t INT_EN; + __IO uint8_t DEV_ADDR; + __IO uint8_t Reserve0; + __IO uint8_t MIS_ST; + __IO uint8_t INT_FG; + __IO uint8_t INT_ST; + __IO uint32_t RX_LEN; + __IO uint8_t UEP4_1_MOD; + __IO uint8_t UEP2_3_MOD; + __IO uint8_t UEP5_6_MOD; + __IO uint8_t UEP7_MOD; + __IO uint32_t UEP0_DMA; + __IO uint32_t UEP1_DMA; + __IO uint32_t UEP2_DMA; + __IO uint32_t UEP3_DMA; + __IO uint32_t UEP4_DMA; + __IO uint32_t UEP5_DMA; + __IO uint32_t UEP6_DMA; + __IO uint32_t UEP7_DMA; + __IO uint16_t UEP0_TX_LEN; + __IO uint8_t UEP0_TX_CTRL; + __IO uint8_t UEP0_RX_CTRL; + __IO uint16_t UEP1_TX_LEN; + __IO uint8_t UEP1_TX_CTRL; + __IO uint8_t UEP1_RX_CTRL; + __IO uint16_t UEP2_TX_LEN; + __IO uint8_t UEP2_TX_CTRL; + __IO uint8_t UEP2_RX_CTRL; + __IO uint16_t UEP3_TX_LEN; + __IO uint8_t UEP3_TX_CTRL; + __IO uint8_t UEP3_RX_CTRL; + __IO uint16_t UEP4_TX_LEN; + __IO uint8_t UEP4_TX_CTRL; + __IO uint8_t UEP4_RX_CTRL; + __IO uint16_t UEP5_TX_LEN; + __IO uint8_t UEP5_TX_CTRL; + __IO uint8_t UEP5_RX_CTRL; + __IO uint16_t UEP6_TX_LEN; + __IO uint8_t UEP6_TX_CTRL; + __IO uint8_t UEP6_RX_CTRL; + __IO uint16_t UEP7_TX_LEN; + __IO uint8_t UEP7_TX_CTRL; + __IO uint8_t UEP7_RX_CTRL; + __IO uint32_t Reserve1; + __IO uint32_t OTG_CR; + __IO uint32_t OTG_SR; + } USBOTG_FS_TypeDef; + + #define USBOTG_FS ((USBOTG_FS_TypeDef *) 0x40023400) #elif CFG_TUSB_MCU == OPT_MCU_CH32V20X #include - -#elif CFG_TUSB_MCU == OPT_MCU_CH32F20X - #include +#elif CFG_TUSB_MCU == OPT_MCU_CH32V307 + #include + #define USBHD_IRQn OTG_FS_IRQn #endif #ifdef __GNUC__ diff --git a/src/tusb_option.h b/src/tusb_option.h index db8b94580..1ca09e902 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_OPTION_H_ -#define _TUSB_OPTION_H_ +#ifndef TUSB_OPTION_H_ +#define TUSB_OPTION_H_ #include "common/tusb_compiler.h" @@ -182,7 +182,7 @@ #define OPT_MCU_CH32V307 2200 ///< WCH CH32V307 #define OPT_MCU_CH32F20X 2210 ///< WCH CH32F20x #define OPT_MCU_CH32V20X 2220 ///< WCH CH32V20X - +#define OPT_MCU_CH32V103 2230 ///< WCH CH32V103 // NXP LPC MCX #define OPT_MCU_MCXN9 2300 ///< NXP MCX N9 Series diff --git a/tools/get_deps.py b/tools/get_deps.py index 50cc5c893..92bfb86a2 100644 --- a/tools/get_deps.py +++ b/tools/get_deps.py @@ -168,6 +168,9 @@ deps_optional = { 'hw/mcu/ti': ['https://github.com/hathach/ti_driver.git', '143ed6cc20a7615d042b03b21e070197d473e6e5', 'msp430 msp432e4 tm4c'], + 'hw/mcu/wch/ch32v103': ['https://github.com/openwch/ch32v103.git', + '7578cae0b21f86dd053a1f781b2fc6ab99d0ec17', + 'ch32v10x'], 'hw/mcu/wch/ch32v20x': ['https://github.com/openwch/ch32v20x.git', 'de6d68c654340d7f27b00cebbfc9aa2740a1abc2', 'ch32v20x'], -- cgit v1.3.1 From 9ae00535737f6f442a9ca7ad3167f686c0d557b1 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 14 Jun 2024 16:08:26 +0700 Subject: newline --- src/portable/st/stm32_fsdev/fsdev_ch32.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/portable/st/stm32_fsdev/fsdev_ch32.h b/src/portable/st/stm32_fsdev/fsdev_ch32.h index dbf2a0289..f63a80d56 100644 --- a/src/portable/st/stm32_fsdev/fsdev_ch32.h +++ b/src/portable/st/stm32_fsdev/fsdev_ch32.h @@ -43,10 +43,10 @@ #pragma GCC diagnostic ignored "-Wstrict-prototypes" #endif -#if CFG_TUSB_MCU == OPT_MCU_CH32V20X - #include -#elif CFG_TUSB_MCU == OPT_MCU_CH32F20X +#if CFG_TUSB_MCU == OPT_MCU_CH32F20X #include +#elif CFG_TUSB_MCU == OPT_MCU_CH32V20X + #include #endif #ifdef __GNUC__ -- cgit v1.3.1 From f32851cf2ae6ec7aa3b39150c3f0f96d65af9b3a Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 14 Jun 2024 16:16:10 +0700 Subject: fix ci skip example for ch32v1 --- examples/device/audio_4_channel_mic_freertos/skip.txt | 1 + examples/device/audio_test_freertos/skip.txt | 1 + examples/device/cdc_msc_freertos/skip.txt | 1 + examples/device/hid_composite_freertos/skip.txt | 1 + examples/device/net_lwip_webserver/skip.txt | 1 + examples/device/video_capture/skip.txt | 1 + examples/device/video_capture_2ch/skip.txt | 1 + src/tusb_option.h | 4 ++-- 8 files changed, 9 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/examples/device/audio_4_channel_mic_freertos/skip.txt b/examples/device/audio_4_channel_mic_freertos/skip.txt index 4769af009..012ca4e74 100644 --- a/examples/device/audio_4_channel_mic_freertos/skip.txt +++ b/examples/device/audio_4_channel_mic_freertos/skip.txt @@ -1,3 +1,4 @@ +mcu:CH32V103 mcu:CH32V20X mcu:CH32V307 mcu:CXD56 diff --git a/examples/device/audio_test_freertos/skip.txt b/examples/device/audio_test_freertos/skip.txt index 6aaa27661..c13667f56 100644 --- a/examples/device/audio_test_freertos/skip.txt +++ b/examples/device/audio_test_freertos/skip.txt @@ -1,3 +1,4 @@ +mcu:CH32V103 mcu:CH32V20X mcu:CH32V307 mcu:CXD56 diff --git a/examples/device/cdc_msc_freertos/skip.txt b/examples/device/cdc_msc_freertos/skip.txt index 457ddb760..75a79aff4 100644 --- a/examples/device/cdc_msc_freertos/skip.txt +++ b/examples/device/cdc_msc_freertos/skip.txt @@ -1,3 +1,4 @@ +mcu:CH32V103 mcu:CH32V20X mcu:CH32V307 mcu:CXD56 diff --git a/examples/device/hid_composite_freertos/skip.txt b/examples/device/hid_composite_freertos/skip.txt index 6aaa27661..c13667f56 100644 --- a/examples/device/hid_composite_freertos/skip.txt +++ b/examples/device/hid_composite_freertos/skip.txt @@ -1,3 +1,4 @@ +mcu:CH32V103 mcu:CH32V20X mcu:CH32V307 mcu:CXD56 diff --git a/examples/device/net_lwip_webserver/skip.txt b/examples/device/net_lwip_webserver/skip.txt index 51af58667..85c450e82 100644 --- a/examples/device/net_lwip_webserver/skip.txt +++ b/examples/device/net_lwip_webserver/skip.txt @@ -1,3 +1,4 @@ +mcu:CH32V103 mcu:CH32V20X mcu:LPC11UXX mcu:LPC13XX diff --git a/examples/device/video_capture/skip.txt b/examples/device/video_capture/skip.txt index 714cabeec..cb0c7d2e6 100644 --- a/examples/device/video_capture/skip.txt +++ b/examples/device/video_capture/skip.txt @@ -1,3 +1,4 @@ +mcu:CH32V103 mcu:CH32V20X mcu:MSP430x5xx mcu:NUC121 diff --git a/examples/device/video_capture_2ch/skip.txt b/examples/device/video_capture_2ch/skip.txt index 1786297f9..af3b0de04 100644 --- a/examples/device/video_capture_2ch/skip.txt +++ b/examples/device/video_capture_2ch/skip.txt @@ -2,6 +2,7 @@ mcu:MSP430x5xx mcu:NUC121 mcu:SAMD11 mcu:GD32VF103 +mcu:CH32V103 mcu:CH32V20X mcu:CH32V307 mcu:STM32L0 diff --git a/src/tusb_option.h b/src/tusb_option.h index 1ca09e902..8990cf92b 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef TUSB_OPTION_H_ -#define TUSB_OPTION_H_ +#ifndef _TUSB_OPTION_H_ +#define _TUSB_OPTION_H_ #include "common/tusb_compiler.h" -- cgit v1.3.1 From 2be72a97b8fd4d08ca20a9b8815f2042c4ef7520 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 14 Jun 2024 17:55:36 +0700 Subject: minor update --- hw/bsp/ch32v10x/boards/ch32v103r_r1_1v0/board.mk | 2 -- hw/bsp/ch32v10x/family.c | 2 +- src/class/net/ncm_device.c | 4 ++-- 3 files changed, 3 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/hw/bsp/ch32v10x/boards/ch32v103r_r1_1v0/board.mk b/hw/bsp/ch32v10x/boards/ch32v103r_r1_1v0/board.mk index 7d7462312..70e65333c 100644 --- a/hw/bsp/ch32v10x/boards/ch32v103r_r1_1v0/board.mk +++ b/hw/bsp/ch32v10x/boards/ch32v103r_r1_1v0/board.mk @@ -1,5 +1,3 @@ -MCU_VARIANT = D6 - CFLAGS += -DCFG_EXAMPLE_MSC_DUAL_READONLY LDFLAGS += \ diff --git a/hw/bsp/ch32v10x/family.c b/hw/bsp/ch32v10x/family.c index c41b207e0..15f754e11 100644 --- a/hw/bsp/ch32v10x/family.c +++ b/hw/bsp/ch32v10x/family.c @@ -24,7 +24,7 @@ void USBHD_IRQHandler(void) { } __attribute__((interrupt)) __attribute__((used)) -void USBHDWakeUp_IRQHandler(void) { +void USBWakeUp_IRQHandler(void) { #if CFG_TUD_WCH_USBIP_USBFS tud_int_handler(0); #endif diff --git a/src/class/net/ncm_device.c b/src/class/net/ncm_device.c index 44a6a0de9..90d747185 100644 --- a/src/class/net/ncm_device.c +++ b/src/class/net/ncm_device.c @@ -1,10 +1,10 @@ /* * The MIT License (MIT) * - * Copyright (c) 2020 Jacob Berg Potter - * Copyright (c) 2020 Peter Lawrence * Copyright (c) 2019 Ha Thach (tinyusb.org) * Copyright (c) 2024 Hardy Griech + * Copyright (c) 2020 Jacob Berg Potter + * Copyright (c) 2020 Peter Lawrence * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal -- cgit v1.3.1 From 00062ddb0cda4e46750c7df09aa31026cc03b5ee Mon Sep 17 00:00:00 2001 From: Okarss <104319900+Okarss@users.noreply.github.com> Date: Fri, 14 Jun 2024 18:16:09 +0300 Subject: [STM32 FSDEV] Simplify toggle bit logic --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 12 ++++++------ src/portable/st/stm32_fsdev/fsdev_common.h | 24 ++---------------------- 2 files changed, 8 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 9ce37f992..b5b89c577 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -215,20 +215,20 @@ void dcd_init(uint8_t rhport) /* The RM mentions to use a special ordering of PDWN and FRES, but this isn't done in HAL. * Here, the RM is followed. */ - for (uint32_t i = 0; i < 200; i++) { // should be a few us - asm("NOP"); + for (volatile uint32_t i = 0; i < 200; i++) { // should be a few us + __DSB(); } // Perform USB peripheral reset USB->CNTR = USB_CNTR_FRES | USB_CNTR_PDWN; - for (uint32_t i = 0; i < 200; i++) { // should be a few us - asm("NOP"); + for (volatile uint32_t i = 0; i < 200; i++) { // should be a few us + __DSB(); } USB->CNTR &= ~USB_CNTR_PDWN; // Wait startup time, for F042 and F070, this is <= 1 us. - for (uint32_t i = 0; i < 200; i++) { // should be a few us - asm("NOP"); + for (volatile uint32_t i = 0; i < 200; i++) { // should be a few us + __DSB(); } USB->CNTR = 0; // Enable USB diff --git a/src/portable/st/stm32_fsdev/fsdev_common.h b/src/portable/st/stm32_fsdev/fsdev_common.h index af5d8afab..e8a6af8cb 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.h +++ b/src/portable/st/stm32_fsdev/fsdev_common.h @@ -295,18 +295,7 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_cnt(USB_TypeDef * USBx, u TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_status(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wState) { uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); regVal &= USB_EPTX_DTOGMASK; - - /* toggle first bit ? */ - if((USB_EPTX_DTOG1 & (wState))!= 0U) - { - regVal ^= USB_EPTX_DTOG1; - } - /* toggle second bit ? */ - if((USB_EPTX_DTOG2 & ((uint32_t)(wState)))!= 0U) - { - regVal ^= USB_EPTX_DTOG2; - } - + regVal ^= wState; regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX; pcd_set_endpoint(USBx, bEpIdx, regVal); } @@ -322,16 +311,7 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_status(USB_TypeDef * USBx TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_status(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wState) { uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); regVal &= USB_EPRX_DTOGMASK; - - /* toggle first bit ? */ - if((USB_EPRX_DTOG1 & wState)!= 0U) { - regVal ^= USB_EPRX_DTOG1; - } - /* toggle second bit ? */ - if((USB_EPRX_DTOG2 & wState)!= 0U) { - regVal ^= USB_EPRX_DTOG2; - } - + regVal ^= wState; regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX; pcd_set_endpoint(USBx, bEpIdx, regVal); } -- cgit v1.3.1 From fb6a6acbff81a98e37b86a0dc3370d4076bb356c Mon Sep 17 00:00:00 2001 From: Okarss <104319900+Okarss@users.noreply.github.com> Date: Fri, 14 Jun 2024 18:39:48 +0300 Subject: Revert the DSB because of RISC-V --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index b5b89c577..4e31c99fa 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -216,19 +216,19 @@ void dcd_init(uint8_t rhport) * Here, the RM is followed. */ for (volatile uint32_t i = 0; i < 200; i++) { // should be a few us - __DSB(); + asm("NOP"); } // Perform USB peripheral reset USB->CNTR = USB_CNTR_FRES | USB_CNTR_PDWN; for (volatile uint32_t i = 0; i < 200; i++) { // should be a few us - __DSB(); + asm("NOP"); } USB->CNTR &= ~USB_CNTR_PDWN; // Wait startup time, for F042 and F070, this is <= 1 us. for (volatile uint32_t i = 0; i < 200; i++) { // should be a few us - __DSB(); + asm("NOP"); } USB->CNTR = 0; // Enable USB -- cgit v1.3.1 From 5f060a357d34257f5a742ebf78c5e4e0873c7a13 Mon Sep 17 00:00:00 2001 From: Okarss <104319900+Okarss@users.noreply.github.com> Date: Fri, 14 Jun 2024 21:23:17 +0300 Subject: Update the STM32 documentation --- README.rst | 5 +++-- docs/reference/supported.rst | 20 +++++++++++++++++--- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 10 ++++++++-- src/portable/st/stm32_fsdev/fsdev_stm32.h | 2 +- 4 files changed, 29 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/README.rst b/README.rst index b5f9fc149..1ae8c5375 100644 --- a/README.rst +++ b/README.rst @@ -151,8 +151,9 @@ Following CPUs are supported, check out `Supported Devices`_ for comprehensive l +--------------+------------------------------------------------------------+ | Sony | CXD56 | +--------------+------------------------------------------------------------+ -| ST STM32 | F0, F1, F2, F3, F4, F7, H5, H7, G0, G4, L0, L1, L4, L4+, | -| | U5, WB | +| ST STM32 | F0, F1, F2, F3, F4, F7, G0, G4, H5, H7, | +| | | +| | L0, L1, L4, L4+, L5, U5, WB | +--------------+------------------------------------------------------------+ | TI | MSP430, MSP432E4, TM4C123 | +--------------+------------------------------------------------------------+ diff --git a/docs/reference/supported.rst b/docs/reference/supported.rst index 3ca203e88..d0e0bf1af 100644 --- a/docs/reference/supported.rst +++ b/docs/reference/supported.rst @@ -104,11 +104,17 @@ Supported MCUs | +-----------------------+--------+------+-----------+-------------------+--------------+ | | F7 | ✔ | | ✔ | dwc2 | | | +-----------------------+--------+------+-----------+-------------------+--------------+ -| | H7 | ✔ | | ✔ | dwc2 | | +| | G0 | ✔ | ✖ | ✖ | stm32_fsdev | | | +-----------------------+--------+------+-----------+-------------------+--------------+ | | G4 | ✔ | ✖ | ✖ | stm32_fsdev | | | +-----------------------+--------+------+-----------+-------------------+--------------+ -| | L0, L1 | ✔ | ✖ | ✖ | stm32_fsdev | | +| | H5 | ✔ | ✖ | ✖ | stm32_fsdev | | +| +-----------------------+--------+------+-----------+-------------------+--------------+ +| | H7 | ✔ | | ✔ | dwc2 | | +| +-----------------------+--------+------+-----------+-------------------+--------------+ +| | L0 | ✔ | ✖ | ✖ | stm32_fsdev | | +| +-----------------------+--------+------+-----------+-------------------+--------------+ +| | L1 | ✔ | ✖ | ✖ | stm32_fsdev | | | +----+------------------+--------+------+-----------+-------------------+--------------+ | | L4 | 4x2, 4x3 | ✔ | ✖ | ✖ | stm32_fsdev | | | | +------------------+--------+------+-----------+-------------------+--------------+ @@ -116,8 +122,14 @@ Supported MCUs | +----+------------------+--------+------+-----------+-------------------+--------------+ | | L4+ | ✔ | | | dwc2 | | | +-----------------------+--------+------+-----------+-------------------+--------------+ -| | U5 | ✔ | | ✔ | dwc2 | | +| | L5 | ✔ | ✖ | ✖ | stm32_fsdev | | | +-----------------------+--------+------+-----------+-------------------+--------------+ +| | U5 | 535, 545 | ✔ | ✖ | ✖ | stm32_fsdev | | +| | +------------------+--------+------+-----------+-------------------+--------------+ +| | | 575, 585 | ✔ | | ✖ | dwc2 | | +| | +------------------+--------+------+-----------+-------------------+--------------+ +| | | 59x,5Ax,5Fx,5Gx | ✔ | | ✔ | dwc2 | | +| +----+------------------+--------+------+-----------+-------------------+--------------+ | | WBx5 | ✔ | | | stm32_fsdev | | +--------------+-----------------------+--------+------+-----------+-------------------+--------------+ | TI | MSP430 | ✔ | ✖ | ✖ | msp430x5xx | | @@ -129,7 +141,9 @@ Supported MCUs | ValentyUSB | eptri | ✔ | ✖ | ✖ | eptri | | +--------------+-----------------------+--------+------+-----------+-------------------+--------------+ | WCH | CH32F20x | ✔ | | ✔ | ch32f205 | | +| +-----------------------+--------+------+-----------+-------------------+--------------+ | | CH32V20x | ✔ | | ✖ | ch32v20x | | +| +-----------------------+--------+------+-----------+-------------------+--------------+ | | CH32V307 | ✔ | | ✔ | ch32v307 | | +--------------+-----------------------+--------+------+-----------+-------------------+--------------+ diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 9ce37f992..0ecb6ea05 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -37,14 +37,20 @@ * It also should work with minimal changes for any ST MCU with an "USB A"/"PCD"/"HCD" peripheral. This * covers: * - * F04x, F072, F078, 070x6/B 1024 byte buffer + * F04x, F072, F078, F070x6/B 1024 byte buffer * F102, F103 512 byte buffer; no internal D+ pull-up (maybe many more changes?) * F302xB/C, F303xB/C, F373 512 byte buffer; no internal D+ pull-up * F302x6/8, F302xD/E2, F303xD/E 1024 byte buffer; no internal D+ pull-up + * G0 2048 byte buffer; 32-bit bus + * G4 1024 byte buffer + * H5 2048 byte buffer; 32-bit bus * L0x2, L0x3 1024 byte buffer * L1 512 byte buffer * L4x2, L4x3 1024 byte buffer - * G0 2048 byte buffer + * L5 1024 byte buffer + * U0 1024 byte buffer; 32-bit bus + * U535, U545 2048 byte buffer; 32-bit bus + * WB35, WB55 1024 byte buffer * * To use this driver, you must: * - If you are using a device with crystal-less USB, set up the clock recovery system (CRS) diff --git a/src/portable/st/stm32_fsdev/fsdev_stm32.h b/src/portable/st/stm32_fsdev/fsdev_stm32.h index b3fa11b88..524efc75f 100644 --- a/src/portable/st/stm32_fsdev/fsdev_stm32.h +++ b/src/portable/st/stm32_fsdev/fsdev_stm32.h @@ -161,7 +161,7 @@ #else #error You are using an untested or unimplemented STM32 variant. Please update the driver. - // This includes L1x0, L1x1, L1x2, L4x2 and L4x3, G1x1, G1x3, and G1x4 + // This includes U0 #endif // This checks if the device has "LPM" -- cgit v1.3.1 From d52d659261bd2bd680bdb5194bfd11349a2ed994 Mon Sep 17 00:00:00 2001 From: Ryzee119 Date: Tue, 18 Jun 2024 14:02:36 +0930 Subject: usbh: Set interface recipient should be interface --- src/host/usbh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/host/usbh.c b/src/host/usbh.c index 7a47f5056..a94c22c4c 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -1113,7 +1113,7 @@ bool tuh_interface_set(uint8_t daddr, uint8_t itf_num, uint8_t itf_alt, TU_LOG_USBH("Set Interface %u Alternate %u\r\n", itf_num, itf_alt); tusb_control_request_t const request = { .bmRequestType_bit = { - .recipient = TUSB_REQ_RCPT_DEVICE, + .recipient = TUSB_REQ_RCPT_INTERFACE, .type = TUSB_REQ_TYPE_STANDARD, .direction = TUSB_DIR_OUT }, -- cgit v1.3.1 From d945261aef7e2c922153e2a85d00791dd1930740 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 18 Jun 2024 12:53:02 +0700 Subject: LOG3 in isr --- examples/host/device_info/src/tusb_config.h | 2 +- src/portable/nordic/nrf5x/dcd_nrf5x.c | 4 ++-- src/portable/nxp/khci/dcd_khci.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/examples/host/device_info/src/tusb_config.h b/examples/host/device_info/src/tusb_config.h index 484f651b1..2e9731eaf 100644 --- a/examples/host/device_info/src/tusb_config.h +++ b/examples/host/device_info/src/tusb_config.h @@ -70,7 +70,7 @@ #define CFG_TUH_ENABLED 1 #if CFG_TUSB_MCU == OPT_MCU_RP2040 - #define CFG_TUH_RPI_PIO_USB 1 // use pio-usb as host controller + // #define CFG_TUH_RPI_PIO_USB 1 // use pio-usb as host controller // #define CFG_TUH_MAX3421 1 // use max3421 as host controller // host roothub port is 1 if using either pio-usb or max3421 diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index abce35245..1cc5c1836 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -907,9 +907,9 @@ void tusb_hal_nrf_power_event(uint32_t event) { USB_EVT_READY = 2 }; -#if CFG_TUSB_DEBUG >= 2 +#if CFG_TUSB_DEBUG >= 3 const char* const power_evt_str[] = {"Detected", "Removed", "Ready"}; - TU_LOG(2, "Power USB event: %s\r\n", power_evt_str[event]); + TU_LOG(3, "Power USB event: %s\r\n", power_evt_str[event]); #endif switch (event) { diff --git a/src/portable/nxp/khci/dcd_khci.c b/src/portable/nxp/khci/dcd_khci.c index dc71117b3..ef61146aa 100644 --- a/src/portable/nxp/khci/dcd_khci.c +++ b/src/portable/nxp/khci/dcd_khci.c @@ -540,7 +540,7 @@ void dcd_int_handler(uint8_t rhport) } if (is & USB_ISTAT_SLEEP_MASK) { - // TU_LOG2("Suspend: "); TU_LOG2_HEX(is); + // TU_LOG3("Suspend: "); TU_LOG2_HEX(is); // Note Host usually has extra delay after bus reset (without SOF), which could falsely // detected as Sleep event. Though usbd has debouncing logic so we are good -- cgit v1.3.1 From 5083d1eb3399d605d64b3e30a784731f330e7774 Mon Sep 17 00:00:00 2001 From: Okarss <104319900+Okarss@users.noreply.github.com> Date: Tue, 18 Jun 2024 12:12:44 +0300 Subject: Update Host mode information for FSDEV devices --- docs/reference/supported.rst | 13 +++++++------ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 6 +++--- 2 files changed, 10 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/docs/reference/supported.rst b/docs/reference/supported.rst index d0e0bf1af..441c885ac 100644 --- a/docs/reference/supported.rst +++ b/docs/reference/supported.rst @@ -104,11 +104,11 @@ Supported MCUs | +-----------------------+--------+------+-----------+-------------------+--------------+ | | F7 | ✔ | | ✔ | dwc2 | | | +-----------------------+--------+------+-----------+-------------------+--------------+ -| | G0 | ✔ | ✖ | ✖ | stm32_fsdev | | +| | G0 | ✔ | | ✖ | stm32_fsdev | | | +-----------------------+--------+------+-----------+-------------------+--------------+ | | G4 | ✔ | ✖ | ✖ | stm32_fsdev | | | +-----------------------+--------+------+-----------+-------------------+--------------+ -| | H5 | ✔ | ✖ | ✖ | stm32_fsdev | | +| | H5 | ✔ | | ✖ | stm32_fsdev | | | +-----------------------+--------+------+-----------+-------------------+--------------+ | | H7 | ✔ | | ✔ | dwc2 | | | +-----------------------+--------+------+-----------+-------------------+--------------+ @@ -124,13 +124,13 @@ Supported MCUs | +-----------------------+--------+------+-----------+-------------------+--------------+ | | L5 | ✔ | ✖ | ✖ | stm32_fsdev | | | +-----------------------+--------+------+-----------+-------------------+--------------+ -| | U5 | 535, 545 | ✔ | ✖ | ✖ | stm32_fsdev | | +| | U5 | 535, 545 | ✔ | | ✖ | stm32_fsdev | | | | +------------------+--------+------+-----------+-------------------+--------------+ | | | 575, 585 | ✔ | | ✖ | dwc2 | | | | +------------------+--------+------+-----------+-------------------+--------------+ | | | 59x,5Ax,5Fx,5Gx | ✔ | | ✔ | dwc2 | | | +----+------------------+--------+------+-----------+-------------------+--------------+ -| | WBx5 | ✔ | | | stm32_fsdev | | +| | WBx5 | ✔ | ✖ | ✖ | stm32_fsdev | | +--------------+-----------------------+--------+------+-----------+-------------------+--------------+ | TI | MSP430 | ✔ | ✖ | ✖ | msp430x5xx | | | +-----------------------+--------+------+-----------+-------------------+--------------+ @@ -153,8 +153,9 @@ Table Legend = =================== ✔ Supported -⚠ WIP/partial support -✖ Not supported +⚠ Partial support +✖ Not supported by hardware +[empty] Unknown = =================== Supported Boards diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 0ecb6ea05..fb499fa18 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -41,15 +41,15 @@ * F102, F103 512 byte buffer; no internal D+ pull-up (maybe many more changes?) * F302xB/C, F303xB/C, F373 512 byte buffer; no internal D+ pull-up * F302x6/8, F302xD/E2, F303xD/E 1024 byte buffer; no internal D+ pull-up - * G0 2048 byte buffer; 32-bit bus + * G0 2048 byte buffer; 32-bit bus; host mode * G4 1024 byte buffer - * H5 2048 byte buffer; 32-bit bus + * H5 2048 byte buffer; 32-bit bus; host mode * L0x2, L0x3 1024 byte buffer * L1 512 byte buffer * L4x2, L4x3 1024 byte buffer * L5 1024 byte buffer * U0 1024 byte buffer; 32-bit bus - * U535, U545 2048 byte buffer; 32-bit bus + * U535, U545 2048 byte buffer; 32-bit bus; host mode * WB35, WB55 1024 byte buffer * * To use this driver, you must: -- cgit v1.3.1 From 5e58ec127ff30ce48a9fcb819acfc05edc92f332 Mon Sep 17 00:00:00 2001 From: Ryzee119 Date: Thu, 20 Jun 2024 09:33:01 +0930 Subject: usbh: Add set address recovery time Ref USB Spec 9.2.6.3 --- src/host/usbh.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/host/usbh.c b/src/host/usbh.c index a94c22c4c..8c488aaa2 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -1421,6 +1421,9 @@ static void process_enumeration(tuh_xfer_t* xfer) { break; case ENUM_GET_DEVICE_DESC: { + // Allow 2ms for address recovery time, Ref USB Spec 9.2.6.3 + osal_task_delay(2); + uint8_t const new_addr = (uint8_t) tu_le16toh(xfer->setup->wValue); usbh_device_t* new_dev = get_device(new_addr); -- cgit v1.3.1 From 0d79da37e79b8abd04f7f9ba9c15114d84e9810a Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Thu, 20 Jun 2024 15:15:51 +1000 Subject: synopsys/dwc2_esp32: Add header for vTaskDelay. --- src/portable/synopsys/dwc2/dwc2_esp32.h | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/portable/synopsys/dwc2/dwc2_esp32.h b/src/portable/synopsys/dwc2/dwc2_esp32.h index c50dd66b8..932f52f40 100644 --- a/src/portable/synopsys/dwc2/dwc2_esp32.h +++ b/src/portable/synopsys/dwc2/dwc2_esp32.h @@ -35,6 +35,7 @@ #include "esp_intr_alloc.h" #include "soc/periph_defs.h" //#include "soc/usb_periph.h" +#include "freertos/task.h" #define DWC2_REG_BASE 0x60080000UL #define DWC2_EP_MAX 6 // USB_OUT_EP_NUM. TODO ESP32Sx only has 5 tx fifo (5 endpoint IN) -- cgit v1.3.1 From 85e1f423bf67776bf2c7113f3f287297f6e81404 Mon Sep 17 00:00:00 2001 From: Davide Gerhard Date: Thu, 27 Jun 2024 21:30:16 +0200 Subject: remove double semicolon since ISO C not allow it ISO C does not allow extra ';' outside of a function [-Werror=pedantic] --- src/osal/osal_freertos.h | 2 +- src/typec/tcd.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/osal/osal_freertos.h b/src/osal/osal_freertos.h index f1f05f353..a3a0f3a3f 100644 --- a/src/osal/osal_freertos.h +++ b/src/osal/osal_freertos.h @@ -78,7 +78,7 @@ typedef struct // _int_set is not used with an RTOS #define OSAL_QUEUE_DEF(_int_set, _name, _depth, _type) \ static _type _name##_##buf[_depth];\ - osal_queue_def_t _name = { .depth = _depth, .item_sz = sizeof(_type), .buf = _name##_##buf, _OSAL_Q_NAME(_name) }; + osal_queue_def_t _name = { .depth = _depth, .item_sz = sizeof(_type), .buf = _name##_##buf, _OSAL_Q_NAME(_name) } //--------------------------------------------------------------------+ // TASK API diff --git a/src/typec/tcd.h b/src/typec/tcd.h index 86499c951..bcbdab8ed 100644 --- a/src/typec/tcd.h +++ b/src/typec/tcd.h @@ -63,7 +63,7 @@ typedef struct TU_ATTR_PACKED { } xfer_complete; }; -} tcd_event_t;; +} tcd_event_t; //--------------------------------------------------------------------+ // -- cgit v1.3.1 From 8f699023f3ff2434efa4433ddc92a9c01756d1f1 Mon Sep 17 00:00:00 2001 From: Davide Gerhard Date: Fri, 28 Jun 2024 10:55:43 +0200 Subject: audio_device.c: fix strict-overflow warning with gcc >= 12 Fix the following error ~/libs/tinyusb/src/class/audio/audio_device.c:1493:23: error: assuming pointer wraparound does not occur when comparing P +- C1 with P +- C2 [-Werror=strict-overflow] 1493 | while (p_desc < p_desc_end) | ~~~~~~~^~~~~~~~~~~~ compilation terminated due to -Wfatal-errors. --- src/class/audio/audio_device.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 46db96ea9..65cac2fd5 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -1490,7 +1490,8 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uin #endif uint8_t const *p_desc = _audiod_fct[i].p_desc; uint8_t const *p_desc_end = p_desc + _audiod_fct[i].desc_length - TUD_AUDIO_DESC_IAD_LEN; - while (p_desc < p_desc_end) + // Condition modified from p_desc < p_desc_end to prevent gcc>=12 strict-overflow warning + while (p_desc_end - p_desc > 0) { if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT) { @@ -1740,7 +1741,8 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * uint8_t const *p_desc_end = audio->p_desc + audio->desc_length - TUD_AUDIO_DESC_IAD_LEN; // p_desc starts at required interface with alternate setting zero - while (p_desc < p_desc_end) + // Condition modified from p_desc < p_desc_end to prevent gcc>=12 strict-overflow warning + while (p_desc_end - p_desc > 0) { // Find correct interface if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bInterfaceNumber == itf && ((tusb_desc_interface_t const * )p_desc)->bAlternateSetting == alt) @@ -1750,7 +1752,8 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * #endif // From this point forward follow the EP descriptors associated to the current alternate setting interface - Open EPs if necessary uint8_t foundEPs = 0, nEps = ((tusb_desc_interface_t const * )p_desc)->bNumEndpoints; - while (foundEPs < nEps && p_desc < p_desc_end) + // Condition modified from p_desc < p_desc_end to prevent gcc>=12 strict-overflow warning + while (foundEPs < nEps && (p_desc_end - p_desc > 0)) { if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT) { @@ -2394,7 +2397,8 @@ static bool audiod_get_AS_interface_index(uint8_t itf, audiod_function_t * audio p_desc += ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength; uint8_t tmp = 0; - while (p_desc < p_desc_end) + // Condition modified from p_desc < p_desc_end to prevent gcc>=12 strict-overflow warning + while (p_desc_end - p_desc > 0) { // We assume the number of alternate settings is increasing thus we return the index of alternate setting zero! if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const * )p_desc)->bAlternateSetting == 0) @@ -2447,7 +2451,8 @@ static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t * uint8_t const *p_desc_end = ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength + p_desc; p_desc = tu_desc_next(p_desc); // Get past CS AC descriptor - while (p_desc < p_desc_end) + // Condition modified from p_desc < p_desc_end to prevent gcc>=12 strict-overflow warning + while (p_desc_end - p_desc > 0) { if (p_desc[3] == entityID) // Entity IDs are always at offset 3 { @@ -2471,8 +2476,8 @@ static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *func_id) // Get pointer at beginning and end uint8_t const *p_desc = _audiod_fct[i].p_desc; uint8_t const *p_desc_end = _audiod_fct[i].p_desc + _audiod_fct[i].desc_length - TUD_AUDIO_DESC_IAD_LEN; - - while (p_desc < p_desc_end) + // Condition modified from p_desc < p_desc_end to prevent gcc>=12 strict-overflow warning + while (p_desc_end - p_desc > 0) { if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const *)_audiod_fct[i].p_desc)->bInterfaceNumber == itf) { @@ -2500,7 +2505,8 @@ static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *func_id) uint8_t const *p_desc = tu_desc_next(_audiod_fct[i].p_desc); p_desc += ((audio_desc_cs_ac_interface_t const *)p_desc)->wTotalLength; - while (p_desc < p_desc_end) + // Condition modified from p_desc < p_desc_end to prevent gcc>=12 strict-overflow warning + while (p_desc_end - p_desc > 0) { if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT && ((tusb_desc_endpoint_t const * )p_desc)->bEndpointAddress == ep) { @@ -2531,8 +2537,8 @@ static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const * #endif p_desc = tu_desc_next(p_desc); // Exclude standard AS interface descriptor of current alternate interface descriptor - - while (p_desc < p_desc_end) + // Condition modified from p_desc < p_desc_end to prevent gcc>=12 strict-overflow warning + while (p_desc_end - p_desc > 0) { // Abort if follow up descriptor is a new standard interface descriptor - indicates the last AS descriptor was already finished if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE) break; -- cgit v1.3.1 From 8f9a57636c9ae6b51e272274ea79f01a7a2631c1 Mon Sep 17 00:00:00 2001 From: Davide Gerhard Date: Fri, 28 Jun 2024 19:57:59 +0200 Subject: audio.h: fix error ISO C restricts enumerator values to range of 'int' fix error ~/dsp/libs/tinyusb/src/class/audio/audio.h:643:53: error: ISO C restricts enumerator values to range of 'int' before C23 [-Werror=pedantic] 643 | AUDIO_CHANNEL_CONFIG_RAW_DATA = 0x80000000, // TODO | ^~~~~~~~~~ compilation terminated due to -Wfatal-errors. Closes: https://github.com/hathach/tinyusb/issues/2690 --- src/class/audio/audio.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio.h b/src/class/audio/audio.h index d6f3e22e2..49ccbe863 100644 --- a/src/class/audio/audio.h +++ b/src/class/audio/audio.h @@ -489,7 +489,7 @@ typedef enum AUDIO_DATA_FORMAT_TYPE_I_IEEE_FLOAT = (uint32_t) (1 << 2), AUDIO_DATA_FORMAT_TYPE_I_ALAW = (uint32_t) (1 << 3), AUDIO_DATA_FORMAT_TYPE_I_MULAW = (uint32_t) (1 << 4), - AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA = 0x80000000, + AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA = (int)(1U << 31U), } audio_data_format_type_I_t; /// All remaining definitions are taken from the descriptor descriptions in the UAC2 main specification @@ -640,7 +640,7 @@ typedef enum AUDIO_CHANNEL_CONFIG_BOTTOM_CENTER = 0x01000000, AUDIO_CHANNEL_CONFIG_BACK_LEFT_OF_CENTER = 0x02000000, AUDIO_CHANNEL_CONFIG_BACK_RIGHT_OF_CENTER = 0x04000000, - AUDIO_CHANNEL_CONFIG_RAW_DATA = 0x80000000, + AUDIO_CHANNEL_CONFIG_RAW_DATA = (int)(1U << 31U), } audio_channel_config_t; /// AUDIO Channel Cluster Descriptor (4.1) -- cgit v1.3.1 From bd562e418080d4d9e4213d38a123b93f30250c48 Mon Sep 17 00:00:00 2001 From: Ha Thach Date: Fri, 5 Jul 2024 15:15:00 +0700 Subject: Revert "audio.h: fix error ISO C restricts enumerator values to range of 'int'" --- src/class/audio/audio.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio.h b/src/class/audio/audio.h index 49ccbe863..d6f3e22e2 100644 --- a/src/class/audio/audio.h +++ b/src/class/audio/audio.h @@ -489,7 +489,7 @@ typedef enum AUDIO_DATA_FORMAT_TYPE_I_IEEE_FLOAT = (uint32_t) (1 << 2), AUDIO_DATA_FORMAT_TYPE_I_ALAW = (uint32_t) (1 << 3), AUDIO_DATA_FORMAT_TYPE_I_MULAW = (uint32_t) (1 << 4), - AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA = (int)(1U << 31U), + AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA = 0x80000000, } audio_data_format_type_I_t; /// All remaining definitions are taken from the descriptor descriptions in the UAC2 main specification @@ -640,7 +640,7 @@ typedef enum AUDIO_CHANNEL_CONFIG_BOTTOM_CENTER = 0x01000000, AUDIO_CHANNEL_CONFIG_BACK_LEFT_OF_CENTER = 0x02000000, AUDIO_CHANNEL_CONFIG_BACK_RIGHT_OF_CENTER = 0x04000000, - AUDIO_CHANNEL_CONFIG_RAW_DATA = (int)(1U << 31U), + AUDIO_CHANNEL_CONFIG_RAW_DATA = 0x80000000, } audio_channel_config_t; /// AUDIO Channel Cluster Descriptor (4.1) -- cgit v1.3.1 From ca12a579020184c0e3f6d66d8081d5bb927cb4b2 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 5 Jul 2024 15:19:16 +0700 Subject: add u for unsigned --- src/class/audio/audio.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio.h b/src/class/audio/audio.h index d6f3e22e2..2f97c0f23 100644 --- a/src/class/audio/audio.h +++ b/src/class/audio/audio.h @@ -489,7 +489,7 @@ typedef enum AUDIO_DATA_FORMAT_TYPE_I_IEEE_FLOAT = (uint32_t) (1 << 2), AUDIO_DATA_FORMAT_TYPE_I_ALAW = (uint32_t) (1 << 3), AUDIO_DATA_FORMAT_TYPE_I_MULAW = (uint32_t) (1 << 4), - AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA = 0x80000000, + AUDIO_DATA_FORMAT_TYPE_I_RAW_DATA = 0x80000000u, } audio_data_format_type_I_t; /// All remaining definitions are taken from the descriptor descriptions in the UAC2 main specification @@ -640,7 +640,7 @@ typedef enum AUDIO_CHANNEL_CONFIG_BOTTOM_CENTER = 0x01000000, AUDIO_CHANNEL_CONFIG_BACK_LEFT_OF_CENTER = 0x02000000, AUDIO_CHANNEL_CONFIG_BACK_RIGHT_OF_CENTER = 0x04000000, - AUDIO_CHANNEL_CONFIG_RAW_DATA = 0x80000000, + AUDIO_CHANNEL_CONFIG_RAW_DATA = 0x80000000u, } audio_channel_config_t; /// AUDIO Channel Cluster Descriptor (4.1) -- cgit v1.3.1 From 1f590c36287e26b6d189bf41f9b7704e957bf8af Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 12 Jul 2024 16:53:21 +0700 Subject: - add tud_cdc_configure_fifo() to replace CFG_TUD_CDC_PERSISTENT_TX_BUFF - new line, and code format --- src/class/cdc/cdc_device.c | 237 ++++++++++++++++++--------------------------- src/class/cdc/cdc_device.h | 195 ++++++++++++++----------------------- 2 files changed, 168 insertions(+), 264 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index f36725eba..681a1b852 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -45,8 +45,7 @@ //--------------------------------------------------------------------+ #define BULK_PACKET_SIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) -typedef struct -{ +typedef struct { uint8_t itf_num; uint8_t ep_notif; uint8_t ep_in; @@ -56,7 +55,7 @@ typedef struct uint8_t line_state; /*------------- From this point, data is not cleared by bus reset -------------*/ - char wanted_char; + char wanted_char; TU_ATTR_ALIGNED(4) cdc_line_coding_t line_coding; // FIFO @@ -72,18 +71,17 @@ typedef struct // Endpoint Transfer buffer CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_CDC_EP_BUFSIZE]; CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_CDC_EP_BUFSIZE]; - -}cdcd_interface_t; +} cdcd_interface_t; #define ITF_MEM_RESET_SIZE offsetof(cdcd_interface_t, wanted_char) //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ -CFG_TUD_MEM_SECTION tu_static cdcd_interface_t _cdcd_itf[CFG_TUD_CDC]; +CFG_TUD_MEM_SECTION static cdcd_interface_t _cdcd_itf[CFG_TUD_CDC]; +static tud_cdc_configure_fifo_t _cdcd_fifo_cfg; -static bool _prep_out_transaction (cdcd_interface_t* p_cdc) -{ +static bool _prep_out_transaction (cdcd_interface_t* p_cdc) { uint8_t const rhport = 0; uint16_t available = tu_fifo_remaining(&p_cdc->rx_ff); @@ -99,14 +97,11 @@ static bool _prep_out_transaction (cdcd_interface_t* p_cdc) // fifo can be changed before endpoint is claimed available = tu_fifo_remaining(&p_cdc->rx_ff); - if ( available >= sizeof(p_cdc->epout_buf) ) - { + if ( available >= sizeof(p_cdc->epout_buf) ) { return usbd_edpt_xfer(rhport, p_cdc->ep_out, p_cdc->epout_buf, sizeof(p_cdc->epout_buf)); - }else - { + }else { // Release endpoint since we don't make any transfer usbd_edpt_release(rhport, p_cdc->ep_out); - return false; } } @@ -114,51 +109,49 @@ static bool _prep_out_transaction (cdcd_interface_t* p_cdc) //--------------------------------------------------------------------+ // APPLICATION API //--------------------------------------------------------------------+ -bool tud_cdc_n_connected(uint8_t itf) -{ + +bool tud_cdc_configure_fifo(tud_cdc_configure_fifo_t const* cfg) { + TU_VERIFY(cfg); + _cdcd_fifo_cfg = (*cfg); + return true; +} + +bool tud_cdc_n_connected(uint8_t itf) { // DTR (bit 0) active is considered as connected return tud_ready() && tu_bit_test(_cdcd_itf[itf].line_state, 0); } -uint8_t tud_cdc_n_get_line_state (uint8_t itf) -{ +uint8_t tud_cdc_n_get_line_state(uint8_t itf) { return _cdcd_itf[itf].line_state; } -void tud_cdc_n_get_line_coding (uint8_t itf, cdc_line_coding_t* coding) -{ +void tud_cdc_n_get_line_coding(uint8_t itf, cdc_line_coding_t* coding) { (*coding) = _cdcd_itf[itf].line_coding; } -void tud_cdc_n_set_wanted_char (uint8_t itf, char wanted) -{ +void tud_cdc_n_set_wanted_char(uint8_t itf, char wanted) { _cdcd_itf[itf].wanted_char = wanted; } - //--------------------------------------------------------------------+ // READ API //--------------------------------------------------------------------+ -uint32_t tud_cdc_n_available(uint8_t itf) -{ +uint32_t tud_cdc_n_available(uint8_t itf) { return tu_fifo_count(&_cdcd_itf[itf].rx_ff); } -uint32_t tud_cdc_n_read(uint8_t itf, void* buffer, uint32_t bufsize) -{ +uint32_t tud_cdc_n_read(uint8_t itf, void* buffer, uint32_t bufsize) { cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; uint32_t num_read = tu_fifo_read_n(&p_cdc->rx_ff, buffer, (uint16_t) TU_MIN(bufsize, UINT16_MAX)); _prep_out_transaction(p_cdc); return num_read; } -bool tud_cdc_n_peek(uint8_t itf, uint8_t* chr) -{ +bool tud_cdc_n_peek(uint8_t itf, uint8_t* chr) { return tu_fifo_peek(&_cdcd_itf[itf].rx_ff, chr); } -void tud_cdc_n_read_flush (uint8_t itf) -{ +void tud_cdc_n_read_flush(uint8_t itf) { cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; tu_fifo_clear(&p_cdc->rx_ff); _prep_out_transaction(p_cdc); @@ -167,16 +160,15 @@ void tud_cdc_n_read_flush (uint8_t itf) //--------------------------------------------------------------------+ // WRITE API //--------------------------------------------------------------------+ -uint32_t tud_cdc_n_write(uint8_t itf, void const* buffer, uint32_t bufsize) -{ +uint32_t tud_cdc_n_write(uint8_t itf, void const* buffer, uint32_t bufsize) { cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; uint16_t ret = tu_fifo_write_n(&p_cdc->tx_ff, buffer, (uint16_t) TU_MIN(bufsize, UINT16_MAX)); // flush if queue more than packet size - if ( tu_fifo_count(&p_cdc->tx_ff) >= BULK_PACKET_SIZE - #if CFG_TUD_CDC_TX_BUFSIZE < BULK_PACKET_SIZE - || tu_fifo_full(&p_cdc->tx_ff) // check full if fifo size is less than packet size - #endif + if (tu_fifo_count(&p_cdc->tx_ff) >= BULK_PACKET_SIZE + #if CFG_TUD_CDC_TX_BUFSIZE < BULK_PACKET_SIZE + || tu_fifo_full(&p_cdc->tx_ff) // check full if fifo size is less than packet size + #endif ) { tud_cdc_n_write_flush(itf); } @@ -184,30 +176,27 @@ uint32_t tud_cdc_n_write(uint8_t itf, void const* buffer, uint32_t bufsize) return ret; } -uint32_t tud_cdc_n_write_flush (uint8_t itf) -{ +uint32_t tud_cdc_n_write_flush(uint8_t itf) { cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; // Skip if usb is not ready yet - TU_VERIFY( tud_ready(), 0 ); + TU_VERIFY(tud_ready(), 0); // No data to send - if ( !tu_fifo_count(&p_cdc->tx_ff) ) return 0; + if (!tu_fifo_count(&p_cdc->tx_ff)) return 0; uint8_t const rhport = 0; // Claim the endpoint - TU_VERIFY( usbd_edpt_claim(rhport, p_cdc->ep_in), 0 ); + TU_VERIFY(usbd_edpt_claim(rhport, p_cdc->ep_in), 0); // Pull data from FIFO uint16_t const count = tu_fifo_read_n(&p_cdc->tx_ff, p_cdc->epin_buf, sizeof(p_cdc->epin_buf)); - if ( count ) - { - TU_ASSERT( usbd_edpt_xfer(rhport, p_cdc->ep_in, p_cdc->epin_buf, count), 0 ); + if (count) { + TU_ASSERT(usbd_edpt_xfer(rhport, p_cdc->ep_in, p_cdc->epin_buf, count), 0); return count; - }else - { + } else { // Release endpoint since we don't make any transfer // Note: data is dropped if terminal is not connected usbd_edpt_release(rhport, p_cdc->ep_in); @@ -215,33 +204,30 @@ uint32_t tud_cdc_n_write_flush (uint8_t itf) } } -uint32_t tud_cdc_n_write_available (uint8_t itf) -{ +uint32_t tud_cdc_n_write_available(uint8_t itf) { return tu_fifo_remaining(&_cdcd_itf[itf].tx_ff); } -bool tud_cdc_n_write_clear (uint8_t itf) -{ +bool tud_cdc_n_write_clear(uint8_t itf) { return tu_fifo_clear(&_cdcd_itf[itf].tx_ff); } //--------------------------------------------------------------------+ // USBD Driver API //--------------------------------------------------------------------+ -void cdcd_init(void) -{ +void cdcd_init(void) { tu_memclr(_cdcd_itf, sizeof(_cdcd_itf)); + tu_memclr(&_cdcd_fifo_cfg, sizeof(_cdcd_fifo_cfg)); - for(uint8_t i=0; iwanted_char = (char) -1; // default line coding is : stop bit = 1, parity = none, data bits = 8 - p_cdc->line_coding.bit_rate = 115200; + p_cdc->line_coding.bit_rate = 115200; p_cdc->line_coding.stop_bits = 0; - p_cdc->line_coding.parity = 0; + p_cdc->line_coding.parity = 0; p_cdc->line_coding.data_bits = 8; // Config RX fifo @@ -285,35 +271,28 @@ bool cdcd_deinit(void) { return true; } -void cdcd_reset(uint8_t rhport) -{ +void cdcd_reset(uint8_t rhport) { (void) rhport; - for(uint8_t i=0; irx_ff); - #if !CFG_TUD_CDC_PERSISTENT_TX_BUFF - tu_fifo_clear(&p_cdc->tx_ff); - #endif + if (!_cdcd_fifo_cfg.rx_persistent) tu_fifo_clear(&p_cdc->rx_ff); + if (!_cdcd_fifo_cfg.tx_persistent) tu_fifo_clear(&p_cdc->tx_ff); tu_fifo_set_overwritable(&p_cdc->tx_ff, true); } } -uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) -{ +uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) { // Only support ACM subclass TU_VERIFY( TUSB_CLASS_CDC == itf_desc->bInterfaceClass && CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass, 0); // Find available interface - cdcd_interface_t * p_cdc = NULL; - for(uint8_t cdc_id=0; cdc_iditf_num = itf_desc->bInterfaceNumber; uint16_t drv_len = sizeof(tusb_desc_interface_t); - uint8_t const * p_desc = tu_desc_next( itf_desc ); + uint8_t const* p_desc = tu_desc_next(itf_desc); // Communication Functional Descriptors - while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len ) - { + while (TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len) { drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); + p_desc = tu_desc_next(p_desc); } - if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) - { + if (TUSB_DESC_ENDPOINT == tu_desc_type(p_desc)) { // notification endpoint - tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; + tusb_desc_endpoint_t const* desc_ep = (tusb_desc_endpoint_t const*) p_desc; - TU_ASSERT( usbd_edpt_open(rhport, desc_ep), 0 ); + TU_ASSERT(usbd_edpt_open(rhport, desc_ep), 0); p_cdc->ep_notif = desc_ep->bEndpointAddress; drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); + p_desc = tu_desc_next(p_desc); } //------------- Data Interface (if any) -------------// - if ( (TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) && - (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) ) - { + if ((TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) && + (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const*) p_desc)->bInterfaceClass)) { // next to endpoint descriptor drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); + p_desc = tu_desc_next(p_desc); // Open endpoint pair - TU_ASSERT( usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &p_cdc->ep_out, &p_cdc->ep_in), 0 ); + TU_ASSERT(usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &p_cdc->ep_out, &p_cdc->ep_in), 0); - drv_len += 2*sizeof(tusb_desc_endpoint_t); + drv_len += 2 * sizeof(tusb_desc_endpoint_t); } // Prepare for incoming data @@ -368,8 +344,7 @@ uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 // Invoked when a control transfer occurred on an interface of this class // Driver response accordingly to the request and the transfer stage (setup/data/ack) // return false to stall control endpoint (e.g unsupported request) -bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ +bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const* request) { // Handle class request only TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); @@ -377,42 +352,33 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t cdcd_interface_t* p_cdc = _cdcd_itf; // Identify which interface to use - for ( ; ; itf++, p_cdc++) - { + for (;; itf++, p_cdc++) { if (itf >= TU_ARRAY_SIZE(_cdcd_itf)) return false; - if ( p_cdc->itf_num == request->wIndex ) break; + if (p_cdc->itf_num == request->wIndex) break; } - switch ( request->bRequest ) - { + switch (request->bRequest) { case CDC_REQUEST_SET_LINE_CODING: - if (stage == CONTROL_STAGE_SETUP) - { + if (stage == CONTROL_STAGE_SETUP) { TU_LOG_DRV(" Set Line Coding\r\n"); tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t)); + } else if (stage == CONTROL_STAGE_ACK) { + if (tud_cdc_line_coding_cb) tud_cdc_line_coding_cb(itf, &p_cdc->line_coding); } - else if ( stage == CONTROL_STAGE_ACK) - { - if ( tud_cdc_line_coding_cb ) tud_cdc_line_coding_cb(itf, &p_cdc->line_coding); - } - break; + break; case CDC_REQUEST_GET_LINE_CODING: - if (stage == CONTROL_STAGE_SETUP) - { + if (stage == CONTROL_STAGE_SETUP) { TU_LOG_DRV(" Get Line Coding\r\n"); tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t)); } - break; + break; case CDC_REQUEST_SET_CONTROL_LINE_STATE: - if (stage == CONTROL_STAGE_SETUP) - { + if (stage == CONTROL_STAGE_SETUP) { tud_control_status(rhport, request); - } - else if (stage == CONTROL_STAGE_ACK) - { + } else if (stage == CONTROL_STAGE_ACK) { // CDC PSTN v1.2 section 6.3.12 // Bit 0: Indicates if DTE is present or not. // This signal corresponds to V.24 signal 108/2 and RS-232 signal DTR (Data Terminal Ready) @@ -429,61 +395,54 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t TU_LOG_DRV(" Set Control Line State: DTR = %d, RTS = %d\r\n", dtr, rts); // Invoke callback - if ( tud_cdc_line_state_cb ) tud_cdc_line_state_cb(itf, dtr, rts); + if (tud_cdc_line_state_cb) tud_cdc_line_state_cb(itf, dtr, rts); } - break; + break; + case CDC_REQUEST_SEND_BREAK: - if (stage == CONTROL_STAGE_SETUP) - { + if (stage == CONTROL_STAGE_SETUP) { tud_control_status(rhport, request); - } - else if (stage == CONTROL_STAGE_ACK) - { + } else if (stage == CONTROL_STAGE_ACK) { TU_LOG_DRV(" Send Break\r\n"); - if ( tud_cdc_send_break_cb ) tud_cdc_send_break_cb(itf, request->wValue); + if (tud_cdc_send_break_cb) tud_cdc_send_break_cb(itf, request->wValue); } - break; + break; - default: return false; // stall unsupported request + default: + return false; // stall unsupported request } return true; } -bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ +bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { (void) result; uint8_t itf; cdcd_interface_t* p_cdc; // Identify which interface to use - for (itf = 0; itf < CFG_TUD_CDC; itf++) - { + for (itf = 0; itf < CFG_TUD_CDC; itf++) { p_cdc = &_cdcd_itf[itf]; - if ( ( ep_addr == p_cdc->ep_out ) || ( ep_addr == p_cdc->ep_in ) ) break; + if ((ep_addr == p_cdc->ep_out) || (ep_addr == p_cdc->ep_in)) break; } TU_ASSERT(itf < CFG_TUD_CDC); // Received new data - if ( ep_addr == p_cdc->ep_out ) - { + if (ep_addr == p_cdc->ep_out) { tu_fifo_write_n(&p_cdc->rx_ff, p_cdc->epout_buf, (uint16_t) xferred_bytes); // Check for wanted char and invoke callback if needed - if ( tud_cdc_rx_wanted_cb && (((signed char) p_cdc->wanted_char) != -1) ) - { - for ( uint32_t i = 0; i < xferred_bytes; i++ ) - { - if ( (p_cdc->wanted_char == p_cdc->epout_buf[i]) && !tu_fifo_empty(&p_cdc->rx_ff) ) - { + if (tud_cdc_rx_wanted_cb && (((signed char) p_cdc->wanted_char) != -1)) { + for (uint32_t i = 0; i < xferred_bytes; i++) { + if ((p_cdc->wanted_char == p_cdc->epout_buf[i]) && !tu_fifo_empty(&p_cdc->rx_ff)) { tud_cdc_rx_wanted_cb(itf, p_cdc->wanted_char); } } } // invoke receive callback (if there is still data) - if (tud_cdc_rx_cb && !tu_fifo_empty(&p_cdc->rx_ff) ) tud_cdc_rx_cb(itf); + if (tud_cdc_rx_cb && !tu_fifo_empty(&p_cdc->rx_ff)) tud_cdc_rx_cb(itf); // prepare for OUT transaction _prep_out_transaction(p_cdc); @@ -492,19 +451,15 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ // Data sent to host, we continue to fetch from tx fifo to send. // Note: This will cause incorrect baudrate set in line coding. // Though maybe the baudrate is not really important !!! - if ( ep_addr == p_cdc->ep_in ) - { + if (ep_addr == p_cdc->ep_in) { // invoke transmit callback to possibly refill tx fifo - if ( tud_cdc_tx_complete_cb ) tud_cdc_tx_complete_cb(itf); + if (tud_cdc_tx_complete_cb) tud_cdc_tx_complete_cb(itf); - if ( 0 == tud_cdc_n_write_flush(itf) ) - { + if (0 == tud_cdc_n_write_flush(itf)) { // If there is no data left, a ZLP should be sent if // xferred_bytes is multiple of EP Packet size and not zero - if ( !tu_fifo_count(&p_cdc->tx_ff) && xferred_bytes && (0 == (xferred_bytes & (BULK_PACKET_SIZE-1))) ) - { - if ( usbd_edpt_claim(rhport, p_cdc->ep_in) ) - { + if (!tu_fifo_count(&p_cdc->tx_ff) && xferred_bytes && (0 == (xferred_bytes & (BULK_PACKET_SIZE - 1)))) { + if (usbd_edpt_claim(rhport, p_cdc->ep_in)) { usbd_edpt_xfer(rhport, p_cdc->ep_in, NULL, 0); } } diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index db709b3bc..5c2d07c5b 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_CDC_DEVICE_H_ -#define _TUSB_CDC_DEVICE_H_ +#ifndef TUSB_CDC_DEVICE_H_ +#define TUSB_CDC_DEVICE_H_ #include "cdc.h" @@ -41,213 +41,162 @@ #define CFG_TUD_CDC_EP_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) #endif -// By default the TX fifo buffer is cleared on connect / bus reset. -// Enable this to persist any data in the fifo instead. -#ifndef CFG_TUD_CDC_PERSISTENT_TX_BUFF - #define CFG_TUD_CDC_PERSISTENT_TX_BUFF (0) -#endif - #ifdef __cplusplus extern "C" { #endif -/** \addtogroup CDC_Serial Serial - * @{ - * \defgroup CDC_Serial_Device Device - * @{ */ +//--------------------------------------------------------------------+ +// Driver Configuration +//--------------------------------------------------------------------+ + +typedef struct TU_ATTR_PACKED { + uint8_t rx_persistent : 1; // keep rx fifo on bus reset or disconnect + uint8_t tx_persistent : 1; // keep tx fifo on bus reset or disconnect +} tud_cdc_configure_fifo_t; + +// Configure CDC FIFOs behavior +bool tud_cdc_configure_fifo(tud_cdc_configure_fifo_t const* cfg); //--------------------------------------------------------------------+ -// Application API (Multiple Ports) -// CFG_TUD_CDC > 1 +// Application API (Multiple Ports) i.e CFG_TUD_CDC > 1 //--------------------------------------------------------------------+ // Check if terminal is connected to this port -bool tud_cdc_n_connected (uint8_t itf); +bool tud_cdc_n_connected(uint8_t itf); // Get current line state. Bit 0: DTR (Data Terminal Ready), Bit 1: RTS (Request to Send) -uint8_t tud_cdc_n_get_line_state (uint8_t itf); +uint8_t tud_cdc_n_get_line_state(uint8_t itf); // Get current line encoding: bit rate, stop bits parity etc .. -void tud_cdc_n_get_line_coding (uint8_t itf, cdc_line_coding_t* coding); +void tud_cdc_n_get_line_coding(uint8_t itf, cdc_line_coding_t* coding); // Set special character that will trigger tud_cdc_rx_wanted_cb() callback on receiving -void tud_cdc_n_set_wanted_char (uint8_t itf, char wanted); +void tud_cdc_n_set_wanted_char(uint8_t itf, char wanted); // Get the number of bytes available for reading -uint32_t tud_cdc_n_available (uint8_t itf); +uint32_t tud_cdc_n_available(uint8_t itf); // Read received bytes -uint32_t tud_cdc_n_read (uint8_t itf, void* buffer, uint32_t bufsize); +uint32_t tud_cdc_n_read(uint8_t itf, void* buffer, uint32_t bufsize); // Read a byte, return -1 if there is none -static inline -int32_t tud_cdc_n_read_char (uint8_t itf); +TU_ATTR_ALWAYS_INLINE static inline int32_t tud_cdc_n_read_char(uint8_t itf) { + uint8_t ch; + return tud_cdc_n_read(itf, &ch, 1) ? (int32_t) ch : -1; +} // Clear the received FIFO -void tud_cdc_n_read_flush (uint8_t itf); +void tud_cdc_n_read_flush(uint8_t itf); // Get a byte from FIFO without removing it -bool tud_cdc_n_peek (uint8_t itf, uint8_t* ui8); +bool tud_cdc_n_peek(uint8_t itf, uint8_t* ui8); // Write bytes to TX FIFO, data may remain in the FIFO for a while -uint32_t tud_cdc_n_write (uint8_t itf, void const* buffer, uint32_t bufsize); +uint32_t tud_cdc_n_write(uint8_t itf, void const* buffer, uint32_t bufsize); // Write a byte -static inline -uint32_t tud_cdc_n_write_char (uint8_t itf, char ch); +TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_cdc_n_write_char(uint8_t itf, char ch) { + return tud_cdc_n_write(itf, &ch, 1); +} // Write a null-terminated string -static inline -uint32_t tud_cdc_n_write_str (uint8_t itf, char const* str); +TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_cdc_n_write_str(uint8_t itf, char const* str) { + return tud_cdc_n_write(itf, str, strlen(str)); +} // Force sending data if possible, return number of forced bytes -uint32_t tud_cdc_n_write_flush (uint8_t itf); +uint32_t tud_cdc_n_write_flush(uint8_t itf); // Return the number of bytes (characters) available for writing to TX FIFO buffer in a single n_write operation. -uint32_t tud_cdc_n_write_available (uint8_t itf); +uint32_t tud_cdc_n_write_available(uint8_t itf); // Clear the transmit FIFO -bool tud_cdc_n_write_clear (uint8_t itf); +bool tud_cdc_n_write_clear(uint8_t itf); //--------------------------------------------------------------------+ // Application API (Single Port) //--------------------------------------------------------------------+ -static inline bool tud_cdc_connected (void); -static inline uint8_t tud_cdc_get_line_state (void); -static inline void tud_cdc_get_line_coding (cdc_line_coding_t* coding); -static inline void tud_cdc_set_wanted_char (char wanted); - -static inline uint32_t tud_cdc_available (void); -static inline int32_t tud_cdc_read_char (void); -static inline uint32_t tud_cdc_read (void* buffer, uint32_t bufsize); -static inline void tud_cdc_read_flush (void); -static inline bool tud_cdc_peek (uint8_t* ui8); - -static inline uint32_t tud_cdc_write_char (char ch); -static inline uint32_t tud_cdc_write (void const* buffer, uint32_t bufsize); -static inline uint32_t tud_cdc_write_str (char const* str); -static inline uint32_t tud_cdc_write_flush (void); -static inline uint32_t tud_cdc_write_available (void); -static inline bool tud_cdc_write_clear (void); - -//--------------------------------------------------------------------+ -// Application Callback API (weak is optional) -//--------------------------------------------------------------------+ - -// Invoked when received new data -TU_ATTR_WEAK void tud_cdc_rx_cb(uint8_t itf); - -// Invoked when received `wanted_char` -TU_ATTR_WEAK void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char); - -// Invoked when a TX is complete and therefore space becomes available in TX buffer -TU_ATTR_WEAK void tud_cdc_tx_complete_cb(uint8_t itf); - -// Invoked when line state DTR & RTS are changed via SET_CONTROL_LINE_STATE -TU_ATTR_WEAK void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts); - -// Invoked when line coding is change via SET_LINE_CODING -TU_ATTR_WEAK void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* p_line_coding); - -// Invoked when received send break -TU_ATTR_WEAK void tud_cdc_send_break_cb(uint8_t itf, uint16_t duration_ms); - -//--------------------------------------------------------------------+ -// Inline Functions -//--------------------------------------------------------------------+ -static inline int32_t tud_cdc_n_read_char (uint8_t itf) -{ - uint8_t ch; - return tud_cdc_n_read(itf, &ch, 1) ? (int32_t) ch : -1; -} - -static inline uint32_t tud_cdc_n_write_char(uint8_t itf, char ch) -{ - return tud_cdc_n_write(itf, &ch, 1); -} - -static inline uint32_t tud_cdc_n_write_str (uint8_t itf, char const* str) -{ - return tud_cdc_n_write(itf, str, strlen(str)); -} - -static inline bool tud_cdc_connected (void) -{ +TU_ATTR_ALWAYS_INLINE static inline bool tud_cdc_connected(void) { return tud_cdc_n_connected(0); } -static inline uint8_t tud_cdc_get_line_state (void) -{ +TU_ATTR_ALWAYS_INLINE static inline uint8_t tud_cdc_get_line_state(void) { return tud_cdc_n_get_line_state(0); } -static inline void tud_cdc_get_line_coding (cdc_line_coding_t* coding) -{ +TU_ATTR_ALWAYS_INLINE static inline void tud_cdc_get_line_coding(cdc_line_coding_t* coding) { tud_cdc_n_get_line_coding(0, coding); } -static inline void tud_cdc_set_wanted_char (char wanted) -{ +TU_ATTR_ALWAYS_INLINE static inline void tud_cdc_set_wanted_char(char wanted) { tud_cdc_n_set_wanted_char(0, wanted); } -static inline uint32_t tud_cdc_available (void) -{ +TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_cdc_available(void) { return tud_cdc_n_available(0); } -static inline int32_t tud_cdc_read_char (void) -{ +TU_ATTR_ALWAYS_INLINE static inline int32_t tud_cdc_read_char(void) { return tud_cdc_n_read_char(0); } -static inline uint32_t tud_cdc_read (void* buffer, uint32_t bufsize) -{ +TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_cdc_read(void* buffer, uint32_t bufsize) { return tud_cdc_n_read(0, buffer, bufsize); } -static inline void tud_cdc_read_flush (void) -{ +TU_ATTR_ALWAYS_INLINE static inline void tud_cdc_read_flush(void) { tud_cdc_n_read_flush(0); } -static inline bool tud_cdc_peek (uint8_t* ui8) -{ +TU_ATTR_ALWAYS_INLINE static inline bool tud_cdc_peek(uint8_t* ui8) { return tud_cdc_n_peek(0, ui8); } -static inline uint32_t tud_cdc_write_char (char ch) -{ +TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_cdc_write_char(char ch) { return tud_cdc_n_write_char(0, ch); } -static inline uint32_t tud_cdc_write (void const* buffer, uint32_t bufsize) -{ +TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_cdc_write(void const* buffer, uint32_t bufsize) { return tud_cdc_n_write(0, buffer, bufsize); } -static inline uint32_t tud_cdc_write_str (char const* str) -{ +TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_cdc_write_str(char const* str) { return tud_cdc_n_write_str(0, str); } -static inline uint32_t tud_cdc_write_flush (void) -{ +TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_cdc_write_flush(void) { return tud_cdc_n_write_flush(0); } -static inline uint32_t tud_cdc_write_available(void) -{ +TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_cdc_write_available(void) { return tud_cdc_n_write_available(0); } -static inline bool tud_cdc_write_clear(void) -{ +TU_ATTR_ALWAYS_INLINE static inline bool tud_cdc_write_clear(void) { return tud_cdc_n_write_clear(0); } -/** @} */ -/** @} */ +//--------------------------------------------------------------------+ +// Application Callback API (weak is optional) +//--------------------------------------------------------------------+ + +// Invoked when received new data +TU_ATTR_WEAK void tud_cdc_rx_cb(uint8_t itf); + +// Invoked when received `wanted_char` +TU_ATTR_WEAK void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char); + +// Invoked when a TX is complete and therefore space becomes available in TX buffer +TU_ATTR_WEAK void tud_cdc_tx_complete_cb(uint8_t itf); + +// Invoked when line state DTR & RTS are changed via SET_CONTROL_LINE_STATE +TU_ATTR_WEAK void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts); + +// Invoked when line coding is change via SET_LINE_CODING +TU_ATTR_WEAK void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* p_line_coding); + +// Invoked when received send break +TU_ATTR_WEAK void tud_cdc_send_break_cb(uint8_t itf, uint16_t duration_ms); //--------------------------------------------------------------------+ // INTERNAL USBD-CLASS DRIVER API -- cgit v1.3.1 From 4ce1cce40a01dce56cab2c73745f4f2c9d212b25 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 12 Jul 2024 20:17:14 +0700 Subject: simplify dwc2 test mode - all dwc2 ip seems to support test mode in both fs/hs -> remove TUP_USBIP_DWC2_TEST_MODE - remove dcd_check_test_mode_support(), all should be supported - move enum tusb_feature_test_mode_t to tusb_types.h --- src/common/tusb_mcu.h | 3 -- src/common/tusb_types.h | 9 ++++++ src/device/dcd.h | 13 +------- src/device/usbd.c | 56 +++++++++++------------------------ src/portable/synopsys/dwc2/dcd_dwc2.c | 20 +++---------- src/tusb_option.h | 2 +- 6 files changed, 32 insertions(+), 71 deletions(-) (limited to 'src') diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 80826c895..637281bfc 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -195,7 +195,6 @@ #elif TU_CHECK_MCU(OPT_MCU_STM32F4) #define TUP_USBIP_DWC2 #define TUP_USBIP_DWC2_STM32 - #define TUP_USBIP_DWC2_TEST_MODE // For most mcu, FS has 4, HS has 6. TODO 446/469/479 HS has 9 #define TUP_DCD_ENDPOINT_MAX 6 @@ -210,7 +209,6 @@ // MCU with on-chip HS Phy #if defined(STM32F723xx) || defined(STM32F730xx) || defined(STM32F733xx) #define TUP_RHPORT_HIGHSPEED 1 // Port0: FS, Port1: HS - #define TUP_USBIP_DWC2_TEST_MODE #endif #elif TU_CHECK_MCU(OPT_MCU_STM32H7) @@ -285,7 +283,6 @@ defined(STM32U5F7xx) || defined(STM32U5F9xx) || defined(STM32U5G7xx) || defined(STM32U5G9xx) #define TUP_DCD_ENDPOINT_MAX 9 #define TUP_RHPORT_HIGHSPEED 1 - #define TUP_USBIP_DWC2_TEST_MODE #else #define TUP_DCD_ENDPOINT_MAX 6 #endif diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index b571f9b72..1501a5af6 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -214,6 +214,15 @@ enum { #define TUSB_DESC_CONFIG_POWER_MA(x) ((x)/2) +// USB 2.0 Spec Table 9-7: Test Mode Selectors +typedef enum { + TUSB_FEATURE_TEST_J = 1, + TUSB_FEATURE_TEST_K, + TUSB_FEATURE_TEST_SE0_NAK, + TUSB_FEATURE_TEST_PACKET, + TUSB_FEATURE_TEST_FORCE_ENABLE, +} tusb_feature_test_mode_t; + //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ diff --git a/src/device/dcd.h b/src/device/dcd.h index f6735b077..5356e9be1 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -89,14 +89,6 @@ typedef struct TU_ATTR_ALIGNED(4) { }; } dcd_event_t; -typedef enum { - TEST_J = 1, - TEST_K, - TEST_SE0_NAK, - TEST_PACKET, - TEST_FORCE_ENABLE, -} test_mode_t; - //TU_VERIFY_STATIC(sizeof(dcd_event_t) <= 12, "size is not correct"); //--------------------------------------------------------------------+ @@ -150,11 +142,8 @@ void dcd_disconnect(uint8_t rhport); void dcd_sof_enable(uint8_t rhport, bool en); #if CFG_TUD_TEST_MODE -// Check if the test mode is supported, returns true is test mode selector is supported -bool dcd_check_test_mode_support(test_mode_t test_selector) TU_ATTR_WEAK; - // Put device into a test mode (needs power cycle to quit) -void dcd_enter_test_mode(uint8_t rhport, test_mode_t test_selector) TU_ATTR_WEAK; +void dcd_enter_test_mode(uint8_t rhport, tusb_feature_test_mode_t test_selector); #endif //--------------------------------------------------------------------+ // Endpoint API diff --git a/src/device/usbd.c b/src/device/usbd.c index 800d9c824..4105a71a4 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -321,9 +321,17 @@ TU_ATTR_ALWAYS_INLINE static inline bool queue_event(dcd_event_t const * event, static bool process_control_request(uint8_t rhport, tusb_control_request_t const * p_request); static bool process_set_config(uint8_t rhport, uint8_t cfg_num); static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const * p_request); + #if CFG_TUD_TEST_MODE -static bool process_test_mode_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); +static bool process_test_mode_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) { + TU_VERIFY(CONTROL_STAGE_ACK == stage); + uint8_t const selector = tu_u16_high(request->wIndex); + TU_LOG_USBD(" Enter Test Mode (test selector index: %d)\r\n", selector); + dcd_enter_test_mode(rhport, (tusb_feature_test_mode_t) selector); + return true; +} #endif + // from usbd_control.c void usbd_control_reset(void); void usbd_control_set_request(tusb_control_request_t const *request); @@ -695,7 +703,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const } if ( TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type ) { - // Non standard request is not supported + // Non-standard request is not supported TU_BREAKPOINT(); return false; } @@ -759,43 +767,27 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const break; case TUSB_REQ_SET_FEATURE: - // Handle the feature selector - switch(p_request->wValue) - { - // Support for remote wakeup + switch(p_request->wValue) { case TUSB_REQ_FEATURE_REMOTE_WAKEUP: TU_LOG_USBD(" Enable Remote Wakeup\r\n"); - // Host may enable remote wake up before suspending especially HID device _usbd_dev.remote_wakeup_en = true; tud_control_status(rhport, p_request); break; -#if CFG_TUD_TEST_MODE - // Support for TEST_MODE + #if CFG_TUD_TEST_MODE case TUSB_REQ_FEATURE_TEST_MODE: { // Only handle the test mode if supported and valid - TU_VERIFY(dcd_enter_test_mode && dcd_check_test_mode_support && 0 == tu_u16_low(p_request->wIndex)); - - uint8_t selector = tu_u16_high(p_request->wIndex); - - // Stall request if the selected test mode isn't supported - if (!dcd_check_test_mode_support((test_mode_t)selector)) - { - TU_LOG_USBD(" Unsupported Test Mode (test selector index: %d)\r\n", selector); + TU_VERIFY(0 == tu_u16_low(p_request->wIndex)); - return false; - } - - // Acknowledge request - tud_control_status(rhport, p_request); - - TU_LOG_USBD(" Enter Test Mode (test selector index: %d)\r\n", selector); + uint8_t const selector = tu_u16_high(p_request->wIndex); + TU_VERIFY(TUSB_FEATURE_TEST_J <= selector && selector <= TUSB_FEATURE_TEST_FORCE_ENABLE); usbd_control_set_complete_callback(process_test_mode_cb); + tud_control_status(rhport, p_request); break; } -#endif /* CFG_TUD_TEST_MODE */ + #endif /* CFG_TUD_TEST_MODE */ // Stall unsupported feature selector default: return false; @@ -1127,20 +1119,6 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const } } -#if CFG_TUD_TEST_MODE -static bool process_test_mode_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ - // At this point it should already be ensured that dcd_enter_test_mode() is defined - - // Only enter the test mode after the request for it has completed - TU_VERIFY(CONTROL_STAGE_ACK == stage); - - dcd_enter_test_mode(rhport, (test_mode_t)tu_u16_high(request->wIndex)); - - return true; -} -#endif /* CFG_TUD_TEST_MODE */ - //--------------------------------------------------------------------+ // DCD Event Handler //--------------------------------------------------------------------+ diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index dbcd586c5..9a38b46dc 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -1195,25 +1195,13 @@ void dcd_int_handler(uint8_t rhport) { // } } -#if defined(TUP_USBIP_DWC2_TEST_MODE) && CFG_TUD_TEST_MODE - -bool dcd_check_test_mode_support(test_mode_t test_selector) { - // Check if test mode selector is unsupported - if (TEST_FORCE_ENABLE < test_selector || TEST_J > test_selector) { - return false; - } - - return true; -} - -void dcd_enter_test_mode(uint8_t rhport, test_mode_t test_selector) { - // Get port address... +#if CFG_TUD_TEST_MODE +void dcd_enter_test_mode(uint8_t rhport, tusb_feature_test_mode_t test_selector) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); // Enable the test mode - dwc2->dctl = (dwc2->dctl & ~DCTL_TCTL_Msk) | (test_selector << DCTL_TCTL_Pos); + dwc2->dctl = (dwc2->dctl & ~DCTL_TCTL_Msk) | (((uint8_t) test_selector) << DCTL_TCTL_Pos); } - -#endif /* TUP_USBIP_DWC2_TEST_MODE && CFG_TUD_TEST_MODE */ +#endif #endif diff --git a/src/tusb_option.h b/src/tusb_option.h index 8990cf92b..f2cc284dc 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -381,7 +381,7 @@ #error "CFG_TUD_ENDPPOINT_MAX must be less than or equal to TUP_DCD_ENDPOINT_MAX" #endif -// USB 2.0 compliance test mode support +// USB 2.0 7.1.20: compliance test mode support #ifndef CFG_TUD_TEST_MODE #define CFG_TUD_TEST_MODE 0 #endif -- cgit v1.3.1 From 0ecf15bc61b2684e53250437d295d6c43682a724 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 17 Jul 2024 14:35:23 +0700 Subject: follow up to #2253 - rename tud_hid_report_fail_cb() to tud_hid_report_failed_cb() and change its signature - use default implementation for hid callbacks to be compatible with keil compiler - code format --- src/class/cdc/cdc_device.h | 2 +- src/class/hid/hid_device.c | 268 +++++++++++++++++++++++---------------------- src/class/hid/hid_device.h | 106 +++++++----------- 3 files changed, 180 insertions(+), 196 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 5c2d07c5b..34670517a 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -58,7 +58,7 @@ typedef struct TU_ATTR_PACKED { bool tud_cdc_configure_fifo(tud_cdc_configure_fifo_t const* cfg); //--------------------------------------------------------------------+ -// Application API (Multiple Ports) i.e CFG_TUD_CDC > 1 +// Application API (Multiple Ports) i.e. CFG_TUD_CDC > 1 //--------------------------------------------------------------------+ // Check if terminal is connected to this port diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index ada01582e..7168ab3d5 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -61,28 +61,53 @@ typedef struct { CFG_TUD_MEM_SECTION tu_static hidd_interface_t _hidd_itf[CFG_TUD_HID]; /*------------- Helpers -------------*/ -static inline uint8_t get_index_by_itfnum(uint8_t itf_num) -{ +TU_ATTR_ALWAYS_INLINE static inline uint8_t get_index_by_itfnum(uint8_t itf_num) { for (uint8_t i = 0; i < CFG_TUD_HID; i++) { - if (itf_num == _hidd_itf[i].itf_num) + if (itf_num == _hidd_itf[i].itf_num) { return i; + } } - return 0xFF; } +//--------------------------------------------------------------------+ +// Weak stubs: invoked if no strong implementation is available +//--------------------------------------------------------------------+ +TU_ATTR_WEAK void tud_hid_set_protocol_cb(uint8_t instance, uint8_t protocol) { + (void) instance; + (void) protocol; +} + +TU_ATTR_WEAK bool tud_hid_set_idle_cb(uint8_t instance, uint8_t idle_rate) { + (void) instance; + (void) idle_rate; + return true; +} + +TU_ATTR_WEAK void tud_hid_report_complete_cb(uint8_t instance, uint8_t const* report, uint16_t len) { + (void) instance; + (void) report; + (void) len; +} + +// Invoked when a transfer wasn't successful +TU_ATTR_WEAK void tud_hid_report_failed_cb(uint8_t instance, hid_report_type_t report_type, uint8_t const* report, uint16_t xferred_bytes) { + (void) instance; + (void) report_type; + (void) report; + (void) xferred_bytes; +} + //--------------------------------------------------------------------+ // APPLICATION API //--------------------------------------------------------------------+ -bool tud_hid_n_ready(uint8_t instance) -{ +bool tud_hid_n_ready(uint8_t instance) { uint8_t const rhport = 0; uint8_t const ep_in = _hidd_itf[instance].ep_in; return tud_ready() && (ep_in != 0) && !usbd_edpt_busy(rhport, ep_in); } -bool tud_hid_n_report(uint8_t instance, uint8_t report_id, void const *report, uint16_t len) -{ +bool tud_hid_n_report(uint8_t instance, uint8_t report_id, void const *report, uint16_t len) { uint8_t const rhport = 0; hidd_interface_t *p_hid = &_hidd_itf[instance]; @@ -101,14 +126,16 @@ bool tud_hid_n_report(uint8_t instance, uint8_t report_id, void const *report, u return usbd_edpt_xfer(rhport, p_hid->ep_in, p_hid->epin_buf, len); } -uint8_t tud_hid_n_interface_protocol(uint8_t instance) { return _hidd_itf[instance].itf_protocol; } +uint8_t tud_hid_n_interface_protocol(uint8_t instance) { + return _hidd_itf[instance].itf_protocol; +} -uint8_t tud_hid_n_get_protocol(uint8_t instance) { return _hidd_itf[instance].protocol_mode; } +uint8_t tud_hid_n_get_protocol(uint8_t instance) { + return _hidd_itf[instance].protocol_mode; +} -bool tud_hid_n_keyboard_report(uint8_t instance, uint8_t report_id, uint8_t modifier, uint8_t keycode[6]) -{ +bool tud_hid_n_keyboard_report(uint8_t instance, uint8_t report_id, uint8_t modifier, uint8_t keycode[6]) { hid_keyboard_report_t report; - report.modifier = modifier; report.reserved = 0; @@ -121,8 +148,8 @@ bool tud_hid_n_keyboard_report(uint8_t instance, uint8_t report_id, uint8_t modi return tud_hid_n_report(instance, report_id, &report, sizeof(report)); } -bool tud_hid_n_mouse_report(uint8_t instance, uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal) -{ +bool tud_hid_n_mouse_report(uint8_t instance, uint8_t report_id, + uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal) { hid_mouse_report_t report = { .buttons = buttons, .x = x, @@ -134,8 +161,8 @@ bool tud_hid_n_mouse_report(uint8_t instance, uint8_t report_id, uint8_t buttons return tud_hid_n_report(instance, report_id, &report, sizeof(report)); } -bool tud_hid_n_abs_mouse_report(uint8_t instance, uint8_t report_id, uint8_t buttons, int16_t x, int16_t y, int8_t vertical, int8_t horizontal) -{ +bool tud_hid_n_abs_mouse_report(uint8_t instance, uint8_t report_id, + uint8_t buttons, int16_t x, int16_t y, int8_t vertical, int8_t horizontal) { hid_abs_mouse_report_t report = { .buttons = buttons, .x = x, @@ -146,8 +173,8 @@ bool tud_hid_n_abs_mouse_report(uint8_t instance, uint8_t report_id, uint8_t but return tud_hid_n_report(instance, report_id, &report, sizeof(report)); } -bool tud_hid_n_gamepad_report(uint8_t instance, uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons) -{ +bool tud_hid_n_gamepad_report(uint8_t instance, uint8_t report_id, + int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons) { hid_gamepad_report_t report = { .x = x, .y = y, @@ -165,28 +192,25 @@ bool tud_hid_n_gamepad_report(uint8_t instance, uint8_t report_id, int8_t x, int //--------------------------------------------------------------------+ // USBD-CLASS API //--------------------------------------------------------------------+ -void hidd_init(void) -{ +void hidd_init(void) { hidd_reset(0); } -bool hidd_deinit(void) -{ +bool hidd_deinit(void) { return true; } -void hidd_reset(uint8_t rhport) -{ +void hidd_reset(uint8_t rhport) { (void)rhport; tu_memclr(_hidd_itf, sizeof(_hidd_itf)); } -uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const *desc_itf, uint16_t max_len) -{ +uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const *desc_itf, uint16_t max_len) { TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass, 0); // len = interface + hid + n*endpoints - uint16_t const drv_len = (uint16_t)(sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + desc_itf->bNumEndpoints * sizeof(tusb_desc_endpoint_t)); + uint16_t const drv_len = (uint16_t) (sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + + desc_itf->bNumEndpoints * sizeof(tusb_desc_endpoint_t)); TU_ASSERT(max_len >= drv_len, 0); // Find available interface @@ -211,8 +235,9 @@ uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const *desc_itf, uint16 p_desc = tu_desc_next(p_desc); TU_ASSERT(usbd_open_edpt_pair(rhport, p_desc, desc_itf->bNumEndpoints, TUSB_XFER_INTERRUPT, &p_hid->ep_out, &p_hid->ep_in), 0); - if (desc_itf->bInterfaceSubClass == HID_SUBCLASS_BOOT) + if (desc_itf->bInterfaceSubClass == HID_SUBCLASS_BOOT) { p_hid->itf_protocol = desc_itf->bInterfaceProtocol; + } p_hid->protocol_mode = HID_PROTOCOL_REPORT; // Per Specs: default is report mode p_hid->itf_num = desc_itf->bInterfaceNumber; @@ -234,8 +259,7 @@ uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const *desc_itf, uint16 // Invoked when a control transfer occurred on an interface of this class // Driver response accordingly to the request and the transfer stage (setup/data/ack) // return false to stall control endpoint (e.g unsupported request) -bool hidd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const *request) -{ +bool hidd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const *request) { TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); uint8_t const hid_itf = get_index_by_itfnum((uint8_t)request->wIndex); @@ -262,90 +286,82 @@ bool hidd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t } else if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS) { //------------- Class Specific Request -------------// switch (request->bRequest) { - case HID_REQ_CONTROL_GET_REPORT: - if (stage == CONTROL_STAGE_SETUP) { - uint8_t const report_type = tu_u16_high(request->wValue); - uint8_t const report_id = tu_u16_low(request->wValue); - - uint8_t *report_buf = p_hid->ctrl_buf; - uint16_t req_len = tu_min16(request->wLength, CFG_TUD_HID_EP_BUFSIZE); - - uint16_t xferlen = 0; - - // If host request a specific Report ID, add ID to as 1 byte of response - if ((report_id != HID_REPORT_TYPE_INVALID) && (req_len > 1)) { - *report_buf++ = report_id; - req_len--; - - xferlen++; + case HID_REQ_CONTROL_GET_REPORT: + if (stage == CONTROL_STAGE_SETUP) { + uint8_t const report_type = tu_u16_high(request->wValue); + uint8_t const report_id = tu_u16_low(request->wValue); + + uint8_t* report_buf = p_hid->ctrl_buf; + uint16_t req_len = tu_min16(request->wLength, CFG_TUD_HID_EP_BUFSIZE); + uint16_t xferlen = 0; + + // If host request a specific Report ID, add ID to as 1 byte of response + if ((report_id != HID_REPORT_TYPE_INVALID) && (req_len > 1)) { + *report_buf++ = report_id; + req_len--; + xferlen++; + } + + xferlen += tud_hid_get_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, report_buf, req_len); + TU_ASSERT(xferlen > 0); + + tud_control_xfer(rhport, request, p_hid->ctrl_buf, xferlen); } - - xferlen += tud_hid_get_report_cb(hid_itf, report_id, (hid_report_type_t)report_type, report_buf, req_len); - TU_ASSERT(xferlen > 0); - - tud_control_xfer(rhport, request, p_hid->ctrl_buf, xferlen); - } - break; - - case HID_REQ_CONTROL_SET_REPORT: - if (stage == CONTROL_STAGE_SETUP) { - TU_VERIFY(request->wLength <= sizeof(p_hid->ctrl_buf)); - tud_control_xfer(rhport, request, p_hid->ctrl_buf, request->wLength); - } else if (stage == CONTROL_STAGE_ACK) { - uint8_t const report_type = tu_u16_high(request->wValue); - uint8_t const report_id = tu_u16_low(request->wValue); - - uint8_t const *report_buf = p_hid->ctrl_buf; - uint16_t report_len = tu_min16(request->wLength, CFG_TUD_HID_EP_BUFSIZE); - - // If host request a specific Report ID, extract report ID in buffer before invoking callback - if ((report_id != HID_REPORT_TYPE_INVALID) && (report_len > 1) && (report_id == report_buf[0])) { - report_buf++; - report_len--; + break; + + case HID_REQ_CONTROL_SET_REPORT: + if (stage == CONTROL_STAGE_SETUP) { + TU_VERIFY(request->wLength <= sizeof(p_hid->ctrl_buf)); + tud_control_xfer(rhport, request, p_hid->ctrl_buf, request->wLength); + } else if (stage == CONTROL_STAGE_ACK) { + uint8_t const report_type = tu_u16_high(request->wValue); + uint8_t const report_id = tu_u16_low(request->wValue); + + uint8_t const* report_buf = p_hid->ctrl_buf; + uint16_t report_len = tu_min16(request->wLength, CFG_TUD_HID_EP_BUFSIZE); + + // If host request a specific Report ID, extract report ID in buffer before invoking callback + if ((report_id != HID_REPORT_TYPE_INVALID) && (report_len > 1) && (report_id == report_buf[0])) { + report_buf++; + report_len--; + } + + tud_hid_set_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, report_buf, report_len); } + break; - tud_hid_set_report_cb(hid_itf, report_id, (hid_report_type_t)report_type, report_buf, report_len); - } - break; - - case HID_REQ_CONTROL_SET_IDLE: - if (stage == CONTROL_STAGE_SETUP) { - p_hid->idle_rate = tu_u16_high(request->wValue); - if (tud_hid_set_idle_cb) { - // stall request if callback return false - TU_VERIFY(tud_hid_set_idle_cb(hid_itf, p_hid->idle_rate)); + case HID_REQ_CONTROL_SET_IDLE: + if (stage == CONTROL_STAGE_SETUP) { + p_hid->idle_rate = tu_u16_high(request->wValue); + TU_VERIFY(tud_hid_set_idle_cb(hid_itf, p_hid->idle_rate)); // stall if false + tud_control_status(rhport, request); } + break; - tud_control_status(rhport, request); - } - break; - - case HID_REQ_CONTROL_GET_IDLE: - if (stage == CONTROL_STAGE_SETUP) { - // TODO idle rate of report - tud_control_xfer(rhport, request, &p_hid->idle_rate, 1); - } - break; + case HID_REQ_CONTROL_GET_IDLE: + if (stage == CONTROL_STAGE_SETUP) { + // TODO idle rate of report + tud_control_xfer(rhport, request, &p_hid->idle_rate, 1); + } + break; - case HID_REQ_CONTROL_GET_PROTOCOL: - if (stage == CONTROL_STAGE_SETUP) { - tud_control_xfer(rhport, request, &p_hid->protocol_mode, 1); - } - break; + case HID_REQ_CONTROL_GET_PROTOCOL: + if (stage == CONTROL_STAGE_SETUP) { + tud_control_xfer(rhport, request, &p_hid->protocol_mode, 1); + } + break; - case HID_REQ_CONTROL_SET_PROTOCOL: - if (stage == CONTROL_STAGE_SETUP) { - tud_control_status(rhport, request); - } else if (stage == CONTROL_STAGE_ACK) { - p_hid->protocol_mode = (uint8_t)request->wValue; - if (tud_hid_set_protocol_cb) { + case HID_REQ_CONTROL_SET_PROTOCOL: + if (stage == CONTROL_STAGE_SETUP) { + tud_control_status(rhport, request); + } else if (stage == CONTROL_STAGE_ACK) { + p_hid->protocol_mode = (uint8_t) request->wValue; tud_hid_set_protocol_cb(hid_itf, p_hid->protocol_mode); } - } - break; + break; - default: - return false; // stall unsupported request + default: + return false; // stall unsupported request } } else { return false; // stall unsupported request @@ -354,45 +370,35 @@ bool hidd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t return true; } -bool hidd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void)result; - +bool hidd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { uint8_t instance = 0; hidd_interface_t *p_hid = _hidd_itf; // Identify which interface to use for (instance = 0; instance < CFG_TUD_HID; instance++) { p_hid = &_hidd_itf[instance]; - if ((ep_addr == p_hid->ep_out) || (ep_addr == p_hid->ep_in)) + if ((ep_addr == p_hid->ep_out) || (ep_addr == p_hid->ep_in)) { break; + } } TU_ASSERT(instance < CFG_TUD_HID); - // Check if there was a problem - if (XFER_RESULT_SUCCESS != result) { // Inform application about the issue - if (tud_hid_report_fail_cb) { - tud_hid_report_fail_cb(instance, ep_addr, (uint16_t)xferred_bytes); + if (ep_addr == p_hid->ep_in) { + // Input report + if (XFER_RESULT_SUCCESS == result) { + tud_hid_report_complete_cb(instance, p_hid->epin_buf, (uint16_t) xferred_bytes); + } else { + tud_hid_report_failed_cb(instance, HID_REPORT_TYPE_INPUT, p_hid->epin_buf, (uint16_t) xferred_bytes); } - - // Allow a new transfer to be received if issue happened on an OUT endpoint - if (ep_addr == p_hid->ep_out) { - // Prepare the OUT endpoint to be able to receive a new transfer - TU_ASSERT(usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf))); + } else { + // Output report + if (XFER_RESULT_SUCCESS == result) { + tud_hid_set_report_cb(instance, 0, HID_REPORT_TYPE_OUTPUT, p_hid->epout_buf, (uint16_t)xferred_bytes); + } else { + tud_hid_report_failed_cb(instance, HID_REPORT_TYPE_OUTPUT, p_hid->epout_buf, (uint16_t) xferred_bytes); } - return true; - } - - // Sent report successfully - if (ep_addr == p_hid->ep_in) { - if (tud_hid_report_complete_cb) { - tud_hid_report_complete_cb(instance, p_hid->epin_buf, (uint16_t)xferred_bytes); - } - } - // Received report successfully - else if (ep_addr == p_hid->ep_out) { - tud_hid_set_report_cb(instance, 0, HID_REPORT_TYPE_OUTPUT, p_hid->epout_buf, (uint16_t)xferred_bytes); + // prepare for new transfer TU_ASSERT(usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf))); } diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index fcbf161c4..89c28e061 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_HID_DEVICE_H_ -#define _TUSB_HID_DEVICE_H_ +#ifndef TUSB_HID_DEVICE_H_ +#define TUSB_HID_DEVICE_H_ #include "hid.h" @@ -48,8 +48,7 @@ #endif //--------------------------------------------------------------------+ -// Application API (Multiple Instances) -// CFG_TUD_HID > 1 +// Application API (Multiple Instances) i.e. CFG_TUD_HID > 1 //--------------------------------------------------------------------+ // Check if the interface is ready to use @@ -76,12 +75,6 @@ bool tud_hid_n_mouse_report(uint8_t instance, uint8_t report_id, uint8_t buttons // use template layout report as defined by hid_abs_mouse_report_t bool tud_hid_n_abs_mouse_report(uint8_t instance, uint8_t report_id, uint8_t buttons, int16_t x, int16_t y, int8_t vertical, int8_t horizontal); - -static inline bool tud_hid_abs_mouse_report(uint8_t report_id, uint8_t buttons, int16_t x, int16_t y, int8_t vertical, int8_t horizontal) -{ - return tud_hid_n_abs_mouse_report(0, report_id, buttons, x, y, vertical, horizontal); -} - // Gamepad: convenient helper to send gamepad report if application // use template layout report TUD_HID_REPORT_DESC_GAMEPAD bool tud_hid_n_gamepad_report(uint8_t instance, uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons); @@ -89,16 +82,40 @@ bool tud_hid_n_gamepad_report(uint8_t instance, uint8_t report_id, int8_t x, int //--------------------------------------------------------------------+ // Application API (Single Port) //--------------------------------------------------------------------+ -static inline bool tud_hid_ready(void); -static inline uint8_t tud_hid_interface_protocol(void); -static inline uint8_t tud_hid_get_protocol(void); -static inline bool tud_hid_report(uint8_t report_id, void const* report, uint16_t len); -static inline bool tud_hid_keyboard_report(uint8_t report_id, uint8_t modifier, uint8_t keycode[6]); -static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal); -static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons); +TU_ATTR_ALWAYS_INLINE static inline bool tud_hid_ready(void) { + return tud_hid_n_ready(0); +} + +TU_ATTR_ALWAYS_INLINE static inline uint8_t tud_hid_interface_protocol(void) { + return tud_hid_n_interface_protocol(0); +} + +TU_ATTR_ALWAYS_INLINE static inline uint8_t tud_hid_get_protocol(void) { + return tud_hid_n_get_protocol(0); +} + +TU_ATTR_ALWAYS_INLINE static inline bool tud_hid_report(uint8_t report_id, void const* report, uint16_t len) { + return tud_hid_n_report(0, report_id, report, len); +} + +TU_ATTR_ALWAYS_INLINE static inline bool tud_hid_keyboard_report(uint8_t report_id, uint8_t modifier, uint8_t keycode[6]) { + return tud_hid_n_keyboard_report(0, report_id, modifier, keycode); +} + +TU_ATTR_ALWAYS_INLINE static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal) { + return tud_hid_n_mouse_report(0, report_id, buttons, x, y, vertical, horizontal); +} + +TU_ATTR_ALWAYS_INLINE static inline bool tud_hid_abs_mouse_report(uint8_t report_id, uint8_t buttons, int16_t x, int16_t y, int8_t vertical, int8_t horizontal) { + return tud_hid_n_abs_mouse_report(0, report_id, buttons, x, y, vertical, horizontal); +} + +TU_ATTR_ALWAYS_INLINE static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons) { + return tud_hid_n_gamepad_report(0, report_id, x, y, z, rz, rx, ry, hat, buttons); +} //--------------------------------------------------------------------+ -// Callbacks (Weak is optional) +// Application Callbacks //--------------------------------------------------------------------+ // Invoked when received GET HID REPORT DESCRIPTOR request @@ -111,63 +128,25 @@ uint8_t const * tud_hid_descriptor_report_cb(uint8_t instance); uint16_t tud_hid_get_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen); // Invoked when received SET_REPORT control request or -// received data on OUT endpoint ( Report ID = 0, Type = 0 ) +// received data on OUT endpoint (Report ID = 0, Type = OUTPUT) void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize); // Invoked when received SET_PROTOCOL request // protocol is either HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) -TU_ATTR_WEAK void tud_hid_set_protocol_cb(uint8_t instance, uint8_t protocol); +void tud_hid_set_protocol_cb(uint8_t instance, uint8_t protocol); // Invoked when received SET_IDLE request. return false will stall the request -// - Idle Rate = 0 : only send report if there is changes, i.e skip duplication +// - Idle Rate = 0 : only send report if there is changes, i.e. skip duplication // - Idle Rate > 0 : skip duplication, but send at least 1 report every idle rate (in unit of 4 ms). -TU_ATTR_WEAK bool tud_hid_set_idle_cb(uint8_t instance, uint8_t idle_rate); +bool tud_hid_set_idle_cb(uint8_t instance, uint8_t idle_rate); // Invoked when sent REPORT successfully to host // Application can use this to send the next report // Note: For composite reports, report[0] is report ID -TU_ATTR_WEAK void tud_hid_report_complete_cb(uint8_t instance, uint8_t const* report, uint16_t len); +void tud_hid_report_complete_cb(uint8_t instance, uint8_t const* report, uint16_t len); // Invoked when a transfer wasn't successful -TU_ATTR_WEAK void tud_hid_report_fail_cb(uint8_t instance, uint8_t ep_addr, uint16_t len); - -//--------------------------------------------------------------------+ -// Inline Functions -//--------------------------------------------------------------------+ -static inline bool tud_hid_ready(void) -{ - return tud_hid_n_ready(0); -} - -static inline uint8_t tud_hid_interface_protocol(void) -{ - return tud_hid_n_interface_protocol(0); -} - -static inline uint8_t tud_hid_get_protocol(void) -{ - return tud_hid_n_get_protocol(0); -} - -static inline bool tud_hid_report(uint8_t report_id, void const* report, uint16_t len) -{ - return tud_hid_n_report(0, report_id, report, len); -} - -static inline bool tud_hid_keyboard_report(uint8_t report_id, uint8_t modifier, uint8_t keycode[6]) -{ - return tud_hid_n_keyboard_report(0, report_id, modifier, keycode); -} - -static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal) -{ - return tud_hid_n_mouse_report(0, report_id, buttons, x, y, vertical, horizontal); -} - -static inline bool tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons) -{ - return tud_hid_n_gamepad_report(0, report_id, x, y, z, rz, rx, ry, hat, buttons); -} +void tud_hid_report_failed_cb(uint8_t instance, hid_report_type_t report_type, uint8_t const* report, uint16_t xferred_bytes); /* --------------------------------------------------------------------+ * HID Report Descriptor Template @@ -645,9 +624,8 @@ uint16_t hidd_open (uint8_t rhport, tusb_desc_interface_t const * itf bool hidd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); bool hidd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); - #ifdef __cplusplus } #endif -#endif /* _TUSB_HID_DEVICE_H_ */ +#endif -- cgit v1.3.1 From 0004faca83f3fa3128fa69b6f97ac711f30d2d20 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 17 Jul 2024 19:29:21 +0700 Subject: minor update hid device --- src/class/hid/hid_device.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 7168ab3d5..00f6fc474 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -46,16 +46,16 @@ typedef struct { uint8_t itf_protocol; // Boot mouse or keyboard uint16_t report_desc_len; - CFG_TUSB_MEM_ALIGN uint8_t protocol_mode; // Boot (0) or Report protocol (1) - CFG_TUSB_MEM_ALIGN uint8_t idle_rate; // up to application to handle idle rate - - CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_HID_EP_BUFSIZE]; - CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_HID_EP_BUFSIZE]; - CFG_TUSB_MEM_ALIGN uint8_t ctrl_buf[CFG_TUD_HID_EP_BUFSIZE]; + uint8_t protocol_mode; // Boot (0) or Report protocol (1) + uint8_t idle_rate; // up to application to handle idle rate // TODO save hid descriptor since host can specifically request this after enumeration // Note: HID descriptor may be not available from application after enumeration tusb_hid_descriptor_hid_t const *hid_descriptor; + + uint8_t ctrl_buf[CFG_TUD_HID_EP_BUFSIZE]; + CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_HID_EP_BUFSIZE]; + CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_HID_EP_BUFSIZE]; } hidd_interface_t; CFG_TUD_MEM_SECTION tu_static hidd_interface_t _hidd_itf[CFG_TUD_HID]; -- cgit v1.3.1 From 770efd9b46db0f8723beebe4bfa4d6694bac2901 Mon Sep 17 00:00:00 2001 From: Liam Fraser Date: Wed, 17 Jul 2024 13:03:09 +0100 Subject: RP2040: Use our own unaligned memcpy to avoid alignment faults with some memcpy implementations --- src/portable/raspberrypi/rp2040/rp2040_usb.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index 1ca711c77..c5d1ba3ce 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -53,6 +53,14 @@ TU_ATTR_ALWAYS_INLINE static inline bool is_host_mode(void) { //--------------------------------------------------------------------+ // Implementation //--------------------------------------------------------------------+ +// Provide own byte by byte memcpy as not all copies are aligned +static void unaligned_memcpy(void *dst, const void *src, size_t n) { + uint8_t *dst_byte = (uint8_t*)dst; + const uint8_t *src_byte = (const uint8_t*)src; + while (n--) { + *dst_byte++ = *src_byte++; + } +} void rp2040_usb_init(void) { // Reset usb controller @@ -125,7 +133,7 @@ static uint32_t __tusb_irq_path_func(prepare_ep_buffer)(struct hw_endpoint* ep, if (!ep->rx) { // Copy data from user buffer to hw buffer - memcpy(ep->hw_data_buf + buf_id * 64, ep->user_buf, buflen); + unaligned_memcpy(ep->hw_data_buf + buf_id * 64, ep->user_buf, buflen); ep->user_buf += buflen; // Mark as full @@ -230,7 +238,7 @@ static uint16_t __tusb_irq_path_func(sync_ep_buffer)(struct hw_endpoint* ep, uin // we have received AFTER we have copied it to the user buffer at the appropriate offset assert(buf_ctrl & USB_BUF_CTRL_FULL); - memcpy(ep->user_buf, ep->hw_data_buf + buf_id * 64, xferred_bytes); + unaligned_memcpy(ep->user_buf, ep->hw_data_buf + buf_id * 64, xferred_bytes); ep->xferred_len = (uint16_t) (ep->xferred_len + xferred_bytes); ep->user_buf += xferred_bytes; } -- cgit v1.3.1 From 3804ab9a67737732fe6bcc8e0b016ea00d47ff12 Mon Sep 17 00:00:00 2001 From: Liam Fraser Date: Wed, 17 Jul 2024 15:40:34 +0100 Subject: RP2040: no need to clear usb_hw (usb registers) as they are reset to default state by a hardware reset --- src/portable/raspberrypi/rp2040/rp2040_usb.c | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index c5d1ba3ce..43f48da39 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -75,7 +75,6 @@ void rp2040_usb_init(void) { #pragma GCC diagnostic ignored "-Wstringop-overflow" #endif #endif - memset(usb_hw, 0, sizeof(*usb_hw)); memset(usb_dpram, 0, sizeof(*usb_dpram)); #ifdef __GNUC__ #pragma GCC diagnostic pop -- cgit v1.3.1 From 0d72f153cf1614aaff0b5859d00fb5c0e1711f51 Mon Sep 17 00:00:00 2001 From: graham sanderson Date: Wed, 17 Jul 2024 15:46:35 -0500 Subject: fix arguable bug caught as warning by LLVM embedded toolchain for ARM 14.0.0 --- src/tusb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/tusb.c b/src/tusb.c index 0092267a1..860e8ac35 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -398,7 +398,7 @@ static void dump_str_line(uint8_t const* buf, uint16_t count) { tu_printf(" |"); // each line is 16 bytes for (uint16_t i = 0; i < count; i++) { - const char ch = buf[i]; + int ch = buf[i]; tu_printf("%c", isprint(ch) ? ch : '.'); } tu_printf("|\r\n"); -- cgit v1.3.1 From 31a979a6cccc2d4dc0a86474643710ae3b7f34fe Mon Sep 17 00:00:00 2001 From: graham sanderson Date: Wed, 17 Jul 2024 21:08:55 -0500 Subject: fix some clang compiler warnings --- examples/host/cdc_msc_hid/src/hid_app.c | 1 + examples/host/hid_controller/src/hid_app.c | 1 + src/class/hid/hid_host.c | 4 +++- 3 files changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/examples/host/cdc_msc_hid/src/hid_app.c b/examples/host/cdc_msc_hid/src/hid_app.c index f0d42a08f..6bb3a2072 100644 --- a/examples/host/cdc_msc_hid/src/hid_app.c +++ b/examples/host/cdc_msc_hid/src/hid_app.c @@ -235,6 +235,7 @@ static void process_mouse_report(hid_mouse_report_t const * report) static void process_generic_report(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) { (void) dev_addr; + (void) len; uint8_t const rpt_count = hid_info[instance].report_count; tuh_hid_report_info_t* rpt_info_arr = hid_info[instance].report_info; diff --git a/examples/host/hid_controller/src/hid_app.c b/examples/host/hid_controller/src/hid_app.c index bff830ca2..6ffe0b6d4 100644 --- a/examples/host/hid_controller/src/hid_app.c +++ b/examples/host/hid_controller/src/hid_app.c @@ -253,6 +253,7 @@ bool diff_report(sony_ds4_report_t const* rpt1, sony_ds4_report_t const* rpt2) void process_sony_ds4(uint8_t const* report, uint16_t len) { + (void)len; const char* dpad_str[] = { "N", "NE", "E", "SE", "S", "SW", "W", "NW", "none" }; // previous report used to compare for changes diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 115a8a4df..7639a8fc6 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -657,7 +657,9 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info_arr, uint8_t const data8 = desc_report[0]; TU_LOG(3, "tag = %d, type = %d, size = %d, data = ", tag, type, size); - for (uint32_t i = 0; i < size; i++) TU_LOG(3, "%02X ", desc_report[i]); + for (uint32_t i = 0; i < size; i++) { + TU_LOG(3, "%02X ", desc_report[i]); + } TU_LOG(3, "\r\n"); switch (type) { -- cgit v1.3.1 From ffe1d0664b6abe942c14ca540833e1e86a797184 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Thu, 18 Jul 2024 20:02:57 +0200 Subject: UAC2: Fix memclr on driver reset. --- src/class/audio/audio_device.c | 94 ++++++++++++++++++++++-------------------- 1 file changed, 50 insertions(+), 44 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 65cac2fd5..ed380424f 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -304,19 +304,6 @@ typedef struct uint16_t desc_length; // Length of audio function descriptor - // Buffer for control requests - uint8_t * ctrl_buf; - uint8_t ctrl_buf_sz; - - // Current active alternate settings - uint8_t * alt_setting; // We need to save the current alternate setting this way, because it is possible that there are AS interfaces which do not have an EP! - - // EP Transfer buffers and FIFOs -#if CFG_TUD_AUDIO_ENABLE_EP_OUT -#if !CFG_TUD_AUDIO_ENABLE_DECODING - tu_fifo_t ep_out_ff; -#endif - #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP struct { CFG_TUSB_MEM_ALIGN uint32_t value; // Feedback value for asynchronous mode (in 16.16 format). @@ -346,17 +333,6 @@ typedef struct } feedback; #endif // CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT - -#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING - tu_fifo_t ep_in_ff; -#endif - - // Audio control interrupt buffer - no FIFO - 6 Bytes according to UAC 2 specification (p. 74) -#if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP - CFG_TUSB_MEM_ALIGN uint8_t ep_int_buf[6]; -#endif - // Decoding parameters - parameters are set when alternate AS interface is set by host // Coding is currently only supported for EP. Software coding corresponding to AS interfaces without EPs are not supported currently. #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING @@ -365,8 +341,7 @@ typedef struct #if CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING audio_data_format_type_I_t format_type_I_rx; - uint8_t n_bytes_per_sampe_rx; - uint8_t n_channels_per_ff_rx; + uint8_t n_bytes_per_sample_rx; uint8_t n_ff_used_rx; #endif #endif @@ -382,26 +357,57 @@ typedef struct #if CFG_TUD_AUDIO_ENABLE_EP_IN && (CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL) audio_format_type_t format_type_tx; uint8_t n_channels_tx; - uint8_t n_bytes_per_sampe_tx; + uint8_t n_bytes_per_sample_tx; #if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING audio_data_format_type_I_t format_type_I_tx; - uint8_t n_channels_per_ff_tx; uint8_t n_ff_used_tx; #endif #endif + // Buffer for control requests + uint8_t * ctrl_buf; + uint8_t ctrl_buf_sz; + + // Current active alternate settings + uint8_t * alt_setting; // We need to save the current alternate setting this way, because it is possible that there are AS interfaces which do not have an EP! + + // EP Transfer buffers and FIFOs +#if CFG_TUD_AUDIO_ENABLE_EP_OUT +#if !CFG_TUD_AUDIO_ENABLE_DECODING + tu_fifo_t ep_out_ff; +#endif + + +#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT + +#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING + tu_fifo_t ep_in_ff; +#endif + + // Audio control interrupt buffer - no FIFO - 6 Bytes according to UAC 2 specification (p. 74) +#if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP + CFG_TUSB_MEM_ALIGN uint8_t ep_int_buf[6]; +#endif + + // Support FIFOs for software encoding and decoding #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING tu_fifo_t * rx_supp_ff; uint8_t n_rx_supp_ff; uint16_t rx_supp_ff_sz_max; +#if CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING + uint8_t n_channels_per_ff_rx; +#endif #endif #if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING tu_fifo_t * tx_supp_ff; uint8_t n_tx_supp_ff; uint16_t tx_supp_ff_sz_max; +#if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING + uint8_t n_channels_per_ff_tx; +#endif #endif // Linear buffer in case target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer is available or driver is would need to be changed dramatically OR the support FIFOs are used @@ -707,16 +713,16 @@ static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_function_t* audio, u if (info.len_lin != 0) { info.len_lin = tu_min16(nBytesPerFFToRead, info.len_lin); - src = &audio->lin_buf_out[cnt_ff*audio->n_channels_per_ff_rx * audio->n_bytes_per_sampe_rx]; + src = &audio->lin_buf_out[cnt_ff*audio->n_channels_per_ff_rx * audio->n_bytes_per_sample_rx]; dst_end = info.ptr_lin + info.len_lin; - src = audiod_interleaved_copy_bytes_fast_decode(audio->n_bytes_per_sampe_rx, info.ptr_lin, dst_end, src, n_ff_used); + src = audiod_interleaved_copy_bytes_fast_decode(audio->n_bytes_per_sample_rx, info.ptr_lin, dst_end, src, n_ff_used); // Handle wrapped part of FIFO info.len_wrap = tu_min16(nBytesPerFFToRead - info.len_lin, info.len_wrap); if (info.len_wrap != 0) { dst_end = info.ptr_wrap + info.len_wrap; - audiod_interleaved_copy_bytes_fast_decode(audio->n_bytes_per_sampe_rx, info.ptr_wrap, dst_end, src, n_ff_used); + audiod_interleaved_copy_bytes_fast_decode(audio->n_bytes_per_sample_rx, info.ptr_wrap, dst_end, src, n_ff_used); } tu_fifo_advance_write_pointer(&audio->rx_supp_ff[cnt_ff], info.len_lin + info.len_wrap); } @@ -1024,7 +1030,7 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi // Limit to maximum sample number - THIS IS A POSSIBLE ERROR SOURCE IF TOO MANY SAMPLE WOULD NEED TO BE SENT BUT CAN NOT! nBytesPerFFToSend = tu_min16(nBytesPerFFToSend, audio->ep_in_sz / n_ff_used); // Round to full number of samples (flooring) - uint16_t const nSlotSize = audio->n_channels_per_ff_tx * audio->n_bytes_per_sampe_tx; + uint16_t const nSlotSize = audio->n_channels_per_ff_tx * audio->n_bytes_per_sample_tx; nBytesPerFFToSend = (nBytesPerFFToSend / nSlotSize) * nSlotSize; #endif @@ -1036,7 +1042,7 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi for (cnt_ff = 0; cnt_ff < n_ff_used; cnt_ff++) { - dst = &audio->lin_buf_in[cnt_ff*audio->n_channels_per_ff_tx*audio->n_bytes_per_sampe_tx]; + dst = &audio->lin_buf_in[cnt_ff*audio->n_channels_per_ff_tx*audio->n_bytes_per_sample_tx]; tu_fifo_get_read_info(&audio->tx_supp_ff[cnt_ff], &info); @@ -1044,7 +1050,7 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi { info.len_lin = tu_min16(nBytesPerFFToSend, info.len_lin); // Limit up to desired length src_end = (uint8_t *)info.ptr_lin + info.len_lin; - dst = audiod_interleaved_copy_bytes_fast_encode(audio->n_bytes_per_sampe_tx, info.ptr_lin, src_end, dst, n_ff_used); + dst = audiod_interleaved_copy_bytes_fast_encode(audio->n_bytes_per_sample_tx, info.ptr_lin, src_end, dst, n_ff_used); // Limit up to desired length info.len_wrap = tu_min16(nBytesPerFFToSend - info.len_lin, info.len_wrap); @@ -1053,7 +1059,7 @@ static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t* audi if (info.len_wrap != 0) { src_end = (uint8_t *)info.ptr_wrap + info.len_wrap; - audiod_interleaved_copy_bytes_fast_encode(audio->n_bytes_per_sampe_tx, info.ptr_wrap, src_end, dst, n_ff_used); + audiod_interleaved_copy_bytes_fast_encode(audio->n_bytes_per_sample_tx, info.ptr_wrap, src_end, dst, n_ff_used); } tu_fifo_advance_read_pointer(&audio->tx_supp_ff[cnt_ff], info.len_lin + info.len_wrap); @@ -1782,8 +1788,8 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * // Reconfigure size of support FIFOs - this is necessary to avoid samples to get split in case of a wrap #if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING - const uint16_t active_fifo_depth = (uint16_t) ((audio->tx_supp_ff_sz_max / (audio->n_channels_per_ff_tx * audio->n_bytes_per_sampe_tx)) - * (audio->n_channels_per_ff_tx * audio->n_bytes_per_sampe_tx)); + const uint16_t active_fifo_depth = (uint16_t) ((audio->tx_supp_ff_sz_max / (audio->n_channels_per_ff_tx * audio->n_bytes_per_sample_tx)) + * (audio->n_channels_per_ff_tx * audio->n_bytes_per_sample_tx)); for (uint8_t cnt = 0; cnt < audio->n_tx_supp_ff; cnt++) { tu_fifo_config(&audio->tx_supp_ff[cnt], audio->tx_supp_ff[cnt].buffer, active_fifo_depth, 1, true); @@ -1813,7 +1819,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const * // Reconfigure size of support FIFOs - this is necessary to avoid samples to get split in case of a wrap #if CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING - const uint16_t active_fifo_depth = (audio->rx_supp_ff_sz_max / audio->n_bytes_per_sampe_rx) * audio->n_bytes_per_sampe_rx; + const uint16_t active_fifo_depth = (audio->rx_supp_ff_sz_max / audio->n_bytes_per_sample_rx) * audio->n_bytes_per_sample_rx; for (uint8_t cnt = 0; cnt < audio->n_rx_supp_ff; cnt++) { tu_fifo_config(&audio->rx_supp_ff[cnt], audio->rx_supp_ff[cnt].buffer, active_fifo_depth, 1, true); @@ -2587,14 +2593,14 @@ static void audiod_parse_for_AS_params(audiod_function_t* audio, uint8_t const * #if CFG_TUD_AUDIO_ENABLE_EP_IN if (as_itf == audio->ep_in_as_intf_num) { - audio->n_bytes_per_sampe_tx = ((audio_desc_type_I_format_t const * )p_desc)->bSubslotSize; + audio->n_bytes_per_sample_tx = ((audio_desc_type_I_format_t const * )p_desc)->bSubslotSize; } #endif #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING if (as_itf == audio->ep_out_as_intf_num) { - audio->n_bytes_per_sampe_rx = ((audio_desc_type_I_format_t const * )p_desc)->bSubslotSize; + audio->n_bytes_per_sample_rx = ((audio_desc_type_I_format_t const * )p_desc)->bSubslotSize; } #endif } @@ -2613,7 +2619,7 @@ static bool audiod_calc_tx_packet_sz(audiod_function_t* audio) { TU_VERIFY(audio->format_type_tx == AUDIO_FORMAT_TYPE_I); TU_VERIFY(audio->n_channels_tx); - TU_VERIFY(audio->n_bytes_per_sampe_tx); + TU_VERIFY(audio->n_bytes_per_sample_tx); TU_VERIFY(audio->interval_tx); TU_VERIFY(audio->sample_rate_tx); @@ -2622,9 +2628,9 @@ static bool audiod_calc_tx_packet_sz(audiod_function_t* audio) const uint16_t sample_normimal = (uint16_t)(audio->sample_rate_tx * interval / ((tud_speed_get() == TUSB_SPEED_FULL) ? 1000 : 8000)); const uint16_t sample_reminder = (uint16_t)(audio->sample_rate_tx * interval % ((tud_speed_get() == TUSB_SPEED_FULL) ? 1000 : 8000)); - const uint16_t packet_sz_tx_min = (uint16_t)((sample_normimal - 1) * audio->n_channels_tx * audio->n_bytes_per_sampe_tx); - const uint16_t packet_sz_tx_norm = (uint16_t)(sample_normimal * audio->n_channels_tx * audio->n_bytes_per_sampe_tx); - const uint16_t packet_sz_tx_max = (uint16_t)((sample_normimal + 1) * audio->n_channels_tx * audio->n_bytes_per_sampe_tx); + const uint16_t packet_sz_tx_min = (uint16_t)((sample_normimal - 1) * audio->n_channels_tx * audio->n_bytes_per_sample_tx); + const uint16_t packet_sz_tx_norm = (uint16_t)(sample_normimal * audio->n_channels_tx * audio->n_bytes_per_sample_tx); + const uint16_t packet_sz_tx_max = (uint16_t)((sample_normimal + 1) * audio->n_channels_tx * audio->n_bytes_per_sample_tx); // Endpoint size must larger than packet size TU_ASSERT(packet_sz_tx_max <= audio->ep_in_sz); -- cgit v1.3.1 From 60b3d14d1979b4a281f999e3a1861b44477f57b1 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Wed, 8 May 2024 14:05:58 +0200 Subject: Check tud ready check for OUT xfer. --- src/class/cdc/cdc_device.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 681a1b852..792aedf26 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -81,8 +81,13 @@ typedef struct { CFG_TUD_MEM_SECTION static cdcd_interface_t _cdcd_itf[CFG_TUD_CDC]; static tud_cdc_configure_fifo_t _cdcd_fifo_cfg; -static bool _prep_out_transaction (cdcd_interface_t* p_cdc) { +static bool _prep_out_transaction (cdcd_interface_t* p_cdc, bool itf_open) +{ uint8_t const rhport = 0; + + // Skip if usb is not ready yet + TU_VERIFY(tud_ready() || itf_open); + uint16_t available = tu_fifo_remaining(&p_cdc->rx_ff); // Prepare for incoming data but only allow what we can store in the ring buffer. @@ -143,7 +148,7 @@ uint32_t tud_cdc_n_available(uint8_t itf) { uint32_t tud_cdc_n_read(uint8_t itf, void* buffer, uint32_t bufsize) { cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; uint32_t num_read = tu_fifo_read_n(&p_cdc->rx_ff, buffer, (uint16_t) TU_MIN(bufsize, UINT16_MAX)); - _prep_out_transaction(p_cdc); + _prep_out_transaction(p_cdc, false); return num_read; } @@ -154,7 +159,7 @@ bool tud_cdc_n_peek(uint8_t itf, uint8_t* chr) { void tud_cdc_n_read_flush(uint8_t itf) { cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; tu_fifo_clear(&p_cdc->rx_ff); - _prep_out_transaction(p_cdc); + _prep_out_transaction(p_cdc, false); } //--------------------------------------------------------------------+ @@ -336,7 +341,7 @@ uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 } // Prepare for incoming data - _prep_out_transaction(p_cdc); + _prep_out_transaction(p_cdc, true); return drv_len; } @@ -445,7 +450,7 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ if (tud_cdc_rx_cb && !tu_fifo_empty(&p_cdc->rx_ff)) tud_cdc_rx_cb(itf); // prepare for OUT transaction - _prep_out_transaction(p_cdc); + _prep_out_transaction(p_cdc, false); } // Data sent to host, we continue to fetch from tx fifo to send. -- cgit v1.3.1 From a1fd43ebaf0a36683c0437ea258e2a024341ef6d Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Wed, 8 May 2024 14:07:32 +0200 Subject: Clear _usbd_dev prior to driver reset. --- src/device/usbd.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index 4105a71a4..b2fd54575 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -495,15 +495,16 @@ bool tud_deinit(uint8_t rhport) { } static void configuration_reset(uint8_t rhport) { + // Clear mounted status first to ensure tud_ready() return false before driver clean up. + tu_varclr(&_usbd_dev); + memset(_usbd_dev.itf2drv, DRVID_INVALID, sizeof(_usbd_dev.itf2drv)); // invalid mapping + memset(_usbd_dev.ep2drv, DRVID_INVALID, sizeof(_usbd_dev.ep2drv)); // invalid mapping + for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++) { usbd_class_driver_t const* driver = get_driver(i); TU_ASSERT(driver,); driver->reset(rhport); } - - tu_varclr(&_usbd_dev); - memset(_usbd_dev.itf2drv, DRVID_INVALID, sizeof(_usbd_dev.itf2drv)); // invalid mapping - memset(_usbd_dev.ep2drv, DRVID_INVALID, sizeof(_usbd_dev.ep2drv)); // invalid mapping } static void usbd_reset(uint8_t rhport) { -- cgit v1.3.1 From 772398f6ead893e6eb69399e11c725919c2f1e1a Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Wed, 8 May 2024 20:03:45 +0200 Subject: Save setup_count on bus reset. --- src/device/usbd.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index b2fd54575..2735e35fd 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -495,10 +495,13 @@ bool tud_deinit(uint8_t rhport) { } static void configuration_reset(uint8_t rhport) { + // Save setup_count for restore + uint8_t setup_count = _usbd_dev.setup_count; // Clear mounted status first to ensure tud_ready() return false before driver clean up. tu_varclr(&_usbd_dev); memset(_usbd_dev.itf2drv, DRVID_INVALID, sizeof(_usbd_dev.itf2drv)); // invalid mapping memset(_usbd_dev.ep2drv, DRVID_INVALID, sizeof(_usbd_dev.ep2drv)); // invalid mapping + _usbd_dev.setup_count = setup_count; for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++) { usbd_class_driver_t const* driver = get_driver(i); -- cgit v1.3.1 From be18af823591389a12e246f65784646f93443882 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 19 Jul 2024 17:10:53 +0700 Subject: revert changes to usbds configuration_reset() (deal with it in separated PR) --- src/class/cdc/cdc_device.c | 3 +-- src/device/usbd.c | 12 ++++-------- 2 files changed, 5 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 792aedf26..570c825ab 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -81,8 +81,7 @@ typedef struct { CFG_TUD_MEM_SECTION static cdcd_interface_t _cdcd_itf[CFG_TUD_CDC]; static tud_cdc_configure_fifo_t _cdcd_fifo_cfg; -static bool _prep_out_transaction (cdcd_interface_t* p_cdc, bool itf_open) -{ +static bool _prep_out_transaction (cdcd_interface_t* p_cdc, bool itf_open) { uint8_t const rhport = 0; // Skip if usb is not ready yet diff --git a/src/device/usbd.c b/src/device/usbd.c index 2735e35fd..4105a71a4 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -495,19 +495,15 @@ bool tud_deinit(uint8_t rhport) { } static void configuration_reset(uint8_t rhport) { - // Save setup_count for restore - uint8_t setup_count = _usbd_dev.setup_count; - // Clear mounted status first to ensure tud_ready() return false before driver clean up. - tu_varclr(&_usbd_dev); - memset(_usbd_dev.itf2drv, DRVID_INVALID, sizeof(_usbd_dev.itf2drv)); // invalid mapping - memset(_usbd_dev.ep2drv, DRVID_INVALID, sizeof(_usbd_dev.ep2drv)); // invalid mapping - _usbd_dev.setup_count = setup_count; - for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++) { usbd_class_driver_t const* driver = get_driver(i); TU_ASSERT(driver,); driver->reset(rhport); } + + tu_varclr(&_usbd_dev); + memset(_usbd_dev.itf2drv, DRVID_INVALID, sizeof(_usbd_dev.itf2drv)); // invalid mapping + memset(_usbd_dev.ep2drv, DRVID_INVALID, sizeof(_usbd_dev.ep2drv)); // invalid mapping } static void usbd_reset(uint8_t rhport) { -- cgit v1.3.1 From 6fb6602a097b2d2e026f150d6fde387803606f88 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 19 Jul 2024 18:08:04 +0700 Subject: - add tud_cdc_n_ready() though not used - usbd now change _usbd_dev.cfg_num before calling driver's open() --- src/class/cdc/cdc_device.c | 16 ++++++++++------ src/class/cdc/cdc_device.h | 8 ++++++++ src/common/tusb_verify.h | 10 +++++----- src/device/usbd.c | 10 ++++++++-- 4 files changed, 31 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 570c825ab..ebc408f5a 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -81,11 +81,11 @@ typedef struct { CFG_TUD_MEM_SECTION static cdcd_interface_t _cdcd_itf[CFG_TUD_CDC]; static tud_cdc_configure_fifo_t _cdcd_fifo_cfg; -static bool _prep_out_transaction (cdcd_interface_t* p_cdc, bool itf_open) { +static bool _prep_out_transaction (cdcd_interface_t* p_cdc) { uint8_t const rhport = 0; // Skip if usb is not ready yet - TU_VERIFY(tud_ready() || itf_open); + TU_VERIFY(tud_ready() && p_cdc->ep_out); uint16_t available = tu_fifo_remaining(&p_cdc->rx_ff); @@ -120,6 +120,10 @@ bool tud_cdc_configure_fifo(tud_cdc_configure_fifo_t const* cfg) { return true; } +bool tud_cdc_n_ready(uint8_t itf) { + return tud_ready() && _cdcd_itf[itf].ep_in != 0 && _cdcd_itf[itf].ep_out != 0; +} + bool tud_cdc_n_connected(uint8_t itf) { // DTR (bit 0) active is considered as connected return tud_ready() && tu_bit_test(_cdcd_itf[itf].line_state, 0); @@ -147,7 +151,7 @@ uint32_t tud_cdc_n_available(uint8_t itf) { uint32_t tud_cdc_n_read(uint8_t itf, void* buffer, uint32_t bufsize) { cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; uint32_t num_read = tu_fifo_read_n(&p_cdc->rx_ff, buffer, (uint16_t) TU_MIN(bufsize, UINT16_MAX)); - _prep_out_transaction(p_cdc, false); + _prep_out_transaction(p_cdc); return num_read; } @@ -158,7 +162,7 @@ bool tud_cdc_n_peek(uint8_t itf, uint8_t* chr) { void tud_cdc_n_read_flush(uint8_t itf) { cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; tu_fifo_clear(&p_cdc->rx_ff); - _prep_out_transaction(p_cdc, false); + _prep_out_transaction(p_cdc); } //--------------------------------------------------------------------+ @@ -340,7 +344,7 @@ uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 } // Prepare for incoming data - _prep_out_transaction(p_cdc, true); + _prep_out_transaction(p_cdc); return drv_len; } @@ -449,7 +453,7 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ if (tud_cdc_rx_cb && !tu_fifo_empty(&p_cdc->rx_ff)) tud_cdc_rx_cb(itf); // prepare for OUT transaction - _prep_out_transaction(p_cdc, false); + _prep_out_transaction(p_cdc); } // Data sent to host, we continue to fetch from tx fifo to send. diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 34670517a..3ad7c8baf 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -61,6 +61,9 @@ bool tud_cdc_configure_fifo(tud_cdc_configure_fifo_t const* cfg); // Application API (Multiple Ports) i.e. CFG_TUD_CDC > 1 //--------------------------------------------------------------------+ +// Check if interface is ready +bool tud_cdc_n_ready(uint8_t itf); + // Check if terminal is connected to this port bool tud_cdc_n_connected(uint8_t itf); @@ -116,6 +119,11 @@ bool tud_cdc_n_write_clear(uint8_t itf); //--------------------------------------------------------------------+ // Application API (Single Port) //--------------------------------------------------------------------+ + +TU_ATTR_ALWAYS_INLINE static inline bool tud_cdc_ready(void) { + return tud_cdc_n_ready(0); +} + TU_ATTR_ALWAYS_INLINE static inline bool tud_cdc_connected(void) { return tud_cdc_n_connected(0); } diff --git a/src/common/tusb_verify.h b/src/common/tusb_verify.h index dde0550d3..4344575b7 100644 --- a/src/common/tusb_verify.h +++ b/src/common/tusb_verify.h @@ -56,8 +56,8 @@ * #define TU_VERIFY(cond) if(cond) return false; * #define TU_VERIFY(cond,ret) if(cond) return ret; * - * #define TU_ASSERT(cond) if(cond) {_MESS_FAILED(); TU_BREAKPOINT(), return false;} - * #define TU_ASSERT(cond,ret) if(cond) {_MESS_FAILED(); TU_BREAKPOINT(), return ret;} + * #define TU_ASSERT(cond) if(cond) {TU_MESS_FAILED(); TU_BREAKPOINT(), return false;} + * #define TU_ASSERT(cond,ret) if(cond) {TU_MESS_FAILED(); TU_BREAKPOINT(), return ret;} *------------------------------------------------------------------*/ #ifdef __cplusplus @@ -70,9 +70,9 @@ #if CFG_TUSB_DEBUG #include - #define _MESS_FAILED() tu_printf("%s %d: ASSERT FAILED\r\n", __func__, __LINE__) + #define TU_MESS_FAILED() tu_printf("%s %d: ASSERT FAILED\r\n", __func__, __LINE__) #else - #define _MESS_FAILED() do {} while (0) + #define TU_MESS_FAILED() do {} while (0) #endif // Halt CPU (breakpoint) when hitting error, only apply for Cortex M3, M4, M7, M33. M55 @@ -119,7 +119,7 @@ *------------------------------------------------------------------*/ #define TU_ASSERT_DEFINE(_cond, _ret) \ do { \ - if ( !(_cond) ) { _MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \ + if ( !(_cond) ) { TU_MESS_FAILED(); TU_BREAKPOINT(); return _ret; } \ } while(0) #define TU_ASSERT_1ARGS(_cond) TU_ASSERT_DEFINE(_cond, false) diff --git a/src/device/usbd.c b/src/device/usbd.c index 4105a71a4..4e723c8b9 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -747,17 +747,23 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const _usbd_dev.speed = speed; // restore speed } + _usbd_dev.cfg_num = cfg_num; + // Handle the new configuration and execute the corresponding callback if ( cfg_num ) { // switch to new configuration if not zero - TU_ASSERT( process_set_config(rhport, cfg_num) ); + if (!process_set_config(rhport, cfg_num)) { + TU_MESS_FAILED(); + TU_BREAKPOINT(); + _usbd_dev.cfg_num = 0; + return false; + } if ( tud_mount_cb ) tud_mount_cb(); } else { if ( tud_umount_cb ) tud_umount_cb(); } } - _usbd_dev.cfg_num = cfg_num; tud_control_status(rhport, p_request); } break; -- cgit v1.3.1 From d040644b6cb055532de7d3da3477e20067f1f15f Mon Sep 17 00:00:00 2001 From: Frank Voorburg Date: Sat, 29 Jun 2024 14:25:02 +0200 Subject: Additional fix related to issue #1018. Corrects the usage of TU_ATTR_WEAK for the Keil compiler for the callback functions: * tud_descriptor_bos_cb() * tud_vendor_control_xfer_cb() * tud_mount_cb() * tud_umount_cb() * tud_suspend_cb() * tud_resume_cb() Without the fix for the first two functions, the USB device won't enumerate properly, if the device makes use of a BOS description. For example when using a Microsoft OS 2.0 platform capability descriptor to set a specific Device Interface GUID for WinUSB. The fix for the other four functions were added, because it's probably just a matter of time before someone runs into the same problem with those callback functions. --- src/device/usbd.c | 34 +++++++++++++++++++++++++++++----- src/device/usbd.h | 12 ++++++------ 2 files changed, 35 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index 4e723c8b9..719183521 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -55,6 +55,30 @@ TU_ATTR_WEAK void tud_sof_cb(uint32_t frame_count) { (void)frame_count; } +TU_ATTR_WEAK uint8_t const * tud_descriptor_bos_cb(void) { + return NULL; +} + +TU_ATTR_WEAK void tud_mount_cb(void) { +} + +TU_ATTR_WEAK void tud_umount_cb(void) { +} + +TU_ATTR_WEAK void tud_suspend_cb(bool remote_wakeup_en) { + (void)remote_wakeup_en; +} + +TU_ATTR_WEAK void tud_resume_cb(void) { +} + +TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) { + (void)rhport; + (void)stage; + (void)request; + return false; +} + TU_ATTR_WEAK bool dcd_deinit(uint8_t rhport) { (void) rhport; return false; @@ -557,7 +581,7 @@ void tud_task_ext(uint32_t timeout_ms, bool in_isr) { case DCD_EVENT_UNPLUGGED: TU_LOG_USBD("\r\n"); usbd_reset(event.rhport); - if (tud_umount_cb) tud_umount_cb(); + tud_umount_cb(); break; case DCD_EVENT_SETUP_RECEIVED: @@ -617,7 +641,7 @@ void tud_task_ext(uint32_t timeout_ms, bool in_isr) { // e.g suspend -> resume -> unplug/plug. Skip suspend/resume if not connected if (_usbd_dev.connected) { TU_LOG_USBD(": Remote Wakeup = %u\r\n", _usbd_dev.remote_wakeup_en); - if (tud_suspend_cb) tud_suspend_cb(_usbd_dev.remote_wakeup_en); + tud_suspend_cb(_usbd_dev.remote_wakeup_en); } else { TU_LOG_USBD(" Skipped\r\n"); } @@ -626,7 +650,7 @@ void tud_task_ext(uint32_t timeout_ms, bool in_isr) { case DCD_EVENT_RESUME: if (_usbd_dev.connected) { TU_LOG_USBD("\r\n"); - if (tud_resume_cb) tud_resume_cb(); + tud_resume_cb(); } else { TU_LOG_USBD(" Skipped\r\n"); } @@ -758,9 +782,9 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const _usbd_dev.cfg_num = 0; return false; } - if ( tud_mount_cb ) tud_mount_cb(); + tud_mount_cb(); } else { - if ( tud_umount_cb ) tud_umount_cb(); + tud_umount_cb(); } } diff --git a/src/device/usbd.h b/src/device/usbd.h index e47f674ea..042f2b089 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -126,7 +126,7 @@ uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid); // Invoked when received GET BOS DESCRIPTOR request // Application return pointer to descriptor -TU_ATTR_WEAK uint8_t const * tud_descriptor_bos_cb(void); +uint8_t const * tud_descriptor_bos_cb(void); // Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete. @@ -140,17 +140,17 @@ TU_ATTR_WEAK uint8_t const* tud_descriptor_device_qualifier_cb(void); TU_ATTR_WEAK uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index); // Invoked when device is mounted (configured) -TU_ATTR_WEAK void tud_mount_cb(void); +void tud_mount_cb(void); // Invoked when device is unmounted -TU_ATTR_WEAK void tud_umount_cb(void); +void tud_umount_cb(void); // Invoked when usb bus is suspended // Within 7ms, device must draw an average of current less than 2.5 mA from bus -TU_ATTR_WEAK void tud_suspend_cb(bool remote_wakeup_en); +void tud_suspend_cb(bool remote_wakeup_en); // Invoked when usb bus is resumed -TU_ATTR_WEAK void tud_resume_cb(void); +void tud_resume_cb(void); // Invoked when there is a new usb event, which need to be processed by tud_task()/tud_task_ext() void tud_event_hook_cb(uint8_t rhport, uint32_t eventid, bool in_isr); @@ -159,7 +159,7 @@ void tud_event_hook_cb(uint8_t rhport, uint32_t eventid, bool in_isr); void tud_sof_cb(uint32_t frame_count); // Invoked when received control request with VENDOR TYPE -TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); +bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); //--------------------------------------------------------------------+ // Binary Device Object Store (BOS) Descriptor Templates -- cgit v1.3.1 From e92acf0a91b071a723c408385add083dfe337e8b Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 19 Jul 2024 20:53:23 +0700 Subject: also migrate tud_descriptor_device_qualifier_cb() / tud_descriptor_other_speed_configuration_cb() --- src/device/usbd.c | 58 ++++++++++++++++++++++++++----------------------------- src/device/usbd.h | 6 +++--- 2 files changed, 30 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index 719183521..f0d7c45b1 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -46,16 +46,25 @@ // Weak stubs: invoked if no strong implementation is available //--------------------------------------------------------------------+ TU_ATTR_WEAK void tud_event_hook_cb(uint8_t rhport, uint32_t eventid, bool in_isr) { - (void)rhport; - (void)eventid; - (void)in_isr; + (void) rhport; + (void) eventid; + (void) in_isr; } TU_ATTR_WEAK void tud_sof_cb(uint32_t frame_count) { - (void)frame_count; + (void) frame_count; +} + +TU_ATTR_WEAK uint8_t const* tud_descriptor_bos_cb(void) { + return NULL; +} + +TU_ATTR_WEAK uint8_t const* tud_descriptor_device_qualifier_cb(void) { + return NULL; } -TU_ATTR_WEAK uint8_t const * tud_descriptor_bos_cb(void) { +TU_ATTR_WEAK uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index) { + (void) index; return NULL; } @@ -66,16 +75,16 @@ TU_ATTR_WEAK void tud_umount_cb(void) { } TU_ATTR_WEAK void tud_suspend_cb(bool remote_wakeup_en) { - (void)remote_wakeup_en; + (void) remote_wakeup_en; } TU_ATTR_WEAK void tud_resume_cb(void) { } -TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) { - (void)rhport; - (void)stage; - (void)request; +TU_ATTR_WEAK bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const* request) { + (void) rhport; + (void) stage; + (void) request; return false; } @@ -1075,15 +1084,12 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const } // break; // unreachable - case TUSB_DESC_BOS: - { + case TUSB_DESC_BOS: { TU_LOG_USBD(" BOS\r\n"); // requested by host if USB > 2.0 ( i.e 2.1 or 3.x ) - if (!tud_descriptor_bos_cb) return false; - uintptr_t desc_bos = (uintptr_t) tud_descriptor_bos_cb(); - TU_ASSERT(desc_bos); + TU_VERIFY(desc_bos); // Use offsetof to avoid pointer to the odd/misaligned address uint16_t const total_len = tu_le16toh( tu_unaligned_read16((const void*) (desc_bos + offsetof(tusb_desc_bos_t, wTotalLength))) ); @@ -1093,24 +1099,20 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const // break; // unreachable case TUSB_DESC_CONFIGURATION: - case TUSB_DESC_OTHER_SPEED_CONFIG: - { + case TUSB_DESC_OTHER_SPEED_CONFIG: { uintptr_t desc_config; - if ( desc_type == TUSB_DESC_CONFIGURATION ) - { + if ( desc_type == TUSB_DESC_CONFIGURATION ) { TU_LOG_USBD(" Configuration[%u]\r\n", desc_index); desc_config = (uintptr_t) tud_descriptor_configuration_cb(desc_index); - }else - { + TU_ASSERT(desc_config); + }else { // Host only request this after getting Device Qualifier descriptor TU_LOG_USBD(" Other Speed Configuration\r\n"); - TU_VERIFY( tud_descriptor_other_speed_configuration_cb ); desc_config = (uintptr_t) tud_descriptor_other_speed_configuration_cb(desc_index); + TU_VERIFY(desc_config); } - TU_ASSERT(desc_config); - // Use offsetof to avoid pointer to the odd/misaligned address uint16_t const total_len = tu_le16toh( tu_unaligned_read16((const void*) (desc_config + offsetof(tusb_desc_configuration_t, wTotalLength))) ); @@ -1131,16 +1133,10 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const } // break; // unreachable - case TUSB_DESC_DEVICE_QUALIFIER: - { + case TUSB_DESC_DEVICE_QUALIFIER: { TU_LOG_USBD(" Device Qualifier\r\n"); - - TU_VERIFY( tud_descriptor_device_qualifier_cb ); - uint8_t const* desc_qualifier = tud_descriptor_device_qualifier_cb(); TU_VERIFY(desc_qualifier); - - // first byte of descriptor is its size return tud_control_xfer(rhport, p_request, (void*) (uintptr_t) desc_qualifier, tu_desc_len(desc_qualifier)); } // break; // unreachable diff --git a/src/device/usbd.h b/src/device/usbd.h index 042f2b089..3d3e83f41 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -109,7 +109,7 @@ bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const * request, vo bool tud_control_status(uint8_t rhport, tusb_control_request_t const * request); //--------------------------------------------------------------------+ -// Application Callbacks (WEAK is optional) +// Application Callbacks //--------------------------------------------------------------------+ // Invoked when received GET DEVICE DESCRIPTOR request @@ -132,12 +132,12 @@ uint8_t const * tud_descriptor_bos_cb(void); // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete. // device_qualifier descriptor describes information about a high-speed capable device that would // change if the device were operating at the other speed. If not highspeed capable stall this request. -TU_ATTR_WEAK uint8_t const* tud_descriptor_device_qualifier_cb(void); +uint8_t const* tud_descriptor_device_qualifier_cb(void); // Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete // Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa -TU_ATTR_WEAK uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index); +uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index); // Invoked when device is mounted (configured) void tud_mount_cb(void); -- cgit v1.3.1 From 8183433600a675a54964d0a36efb814f77f38a54 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 19 Jul 2024 21:05:10 +0700 Subject: fix compile with tud_vendor_control_xfer_cb() and check tud_descriptor_device_cb() --- src/device/usbd.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index f0d7c45b1..b93216006 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -708,8 +708,6 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const // Vendor request if ( p_request->bmRequestType_bit.type == TUSB_REQ_TYPE_VENDOR ) { - TU_VERIFY(tud_vendor_control_xfer_cb); - usbd_control_set_complete_callback(tud_vendor_control_xfer_cb); return tud_vendor_control_xfer_cb(rhport, CONTROL_STAGE_SETUP, p_request); } @@ -1060,25 +1058,23 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const switch(desc_type) { - case TUSB_DESC_DEVICE: - { + case TUSB_DESC_DEVICE: { TU_LOG_USBD(" Device\r\n"); void* desc_device = (void*) (uintptr_t) tud_descriptor_device_cb(); + TU_ASSERT(desc_device); // Only response with exactly 1 Packet if: not addressed and host requested more data than device descriptor has. // This only happens with the very first get device descriptor and EP0 size = 8 or 16. if ((CFG_TUD_ENDPOINT0_SIZE < sizeof(tusb_desc_device_t)) && !_usbd_dev.addressed && - ((tusb_control_request_t const*) p_request)->wLength > sizeof(tusb_desc_device_t)) - { + ((tusb_control_request_t const*) p_request)->wLength > sizeof(tusb_desc_device_t)) { // Hack here: we modify the request length to prevent usbd_control response with zlp // since we are responding with 1 packet & less data than wLength. tusb_control_request_t mod_request = *p_request; mod_request.wLength = CFG_TUD_ENDPOINT0_SIZE; return tud_control_xfer(rhport, &mod_request, desc_device, CFG_TUD_ENDPOINT0_SIZE); - }else - { + }else { return tud_control_xfer(rhport, p_request, desc_device, sizeof(tusb_desc_device_t)); } } -- cgit v1.3.1 From 4de46fcf975d57983192874feea9d94427f5de50 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 22 Jul 2024 16:01:39 +0700 Subject: fix a bug in fsdev introduced by #1942 --- hw/bsp/ch32v20x/boards/ch32v203c_r0_1v0/board.cmake | 1 - hw/bsp/ch32v20x/boards/ch32v203g_r0_1v0/board.cmake | 1 - hw/bsp/ch32v20x/boards/nanoch32v203/board.cmake | 1 - hw/bsp/ch32v20x/family.cmake | 6 ++++++ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 2 +- 5 files changed, 7 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/hw/bsp/ch32v20x/boards/ch32v203c_r0_1v0/board.cmake b/hw/bsp/ch32v20x/boards/ch32v203c_r0_1v0/board.cmake index adb0ea741..4aae6bdc2 100644 --- a/hw/bsp/ch32v20x/boards/ch32v203c_r0_1v0/board.cmake +++ b/hw/bsp/ch32v20x/boards/ch32v203c_r0_1v0/board.cmake @@ -10,7 +10,6 @@ set(LD_RAM_SIZE 20K) function(update_board TARGET) target_compile_definitions(${TARGET} PUBLIC SYSCLK_FREQ_144MHz_HSE=144000000 - CH32_FLASH_ENHANCE_READ_MODE=1 CFG_EXAMPLE_MSC_DUAL_READONLY ) endfunction() diff --git a/hw/bsp/ch32v20x/boards/ch32v203g_r0_1v0/board.cmake b/hw/bsp/ch32v20x/boards/ch32v203g_r0_1v0/board.cmake index 6fe3e05b2..ecb8b378f 100644 --- a/hw/bsp/ch32v20x/boards/ch32v203g_r0_1v0/board.cmake +++ b/hw/bsp/ch32v20x/boards/ch32v203g_r0_1v0/board.cmake @@ -8,7 +8,6 @@ set(LD_RAM_SIZE 10K) function(update_board TARGET) target_compile_definitions(${TARGET} PUBLIC SYSCLK_FREQ_144MHz_HSI=144000000 - CH32_FLASH_ENHANCE_READ_MODE=1 CFG_EXAMPLE_MSC_DUAL_READONLY ) endfunction() diff --git a/hw/bsp/ch32v20x/boards/nanoch32v203/board.cmake b/hw/bsp/ch32v20x/boards/nanoch32v203/board.cmake index ed7365797..a0bf12b5c 100644 --- a/hw/bsp/ch32v20x/boards/nanoch32v203/board.cmake +++ b/hw/bsp/ch32v20x/boards/nanoch32v203/board.cmake @@ -8,7 +8,6 @@ set(LD_RAM_SIZE 20K) function(update_board TARGET) target_compile_definitions(${TARGET} PUBLIC SYSCLK_FREQ_144MHz_HSE=144000000 - CH32_FLASH_ENHANCE_READ_MODE=1 CFG_EXAMPLE_MSC_DUAL_READONLY ) endfunction() diff --git a/hw/bsp/ch32v20x/family.cmake b/hw/bsp/ch32v20x/family.cmake index bf929b862..380ef190d 100644 --- a/hw/bsp/ch32v20x/family.cmake +++ b/hw/bsp/ch32v20x/family.cmake @@ -72,6 +72,12 @@ function(add_board_target BOARD_TARGET) update_board(${BOARD_TARGET}) + if (LD_FLASH_SIZE STREQUAL 224K) + target_compile_definitions(${BOARD_TARGET} PUBLIC + CH32_FLASH_ENHANCE_READ_MODE=1 + ) + endif() + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") target_compile_options(${BOARD_TARGET} PUBLIC -mcmodel=medany diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 8bfb899ca..39f33bc34 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -1004,7 +1004,7 @@ static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, ui srcVal++; } - if (wNBytes) { + if (wNBytes & 0x01) { temp1 = (uint16_t) *srcVal; *pdwVal = temp1; } -- cgit v1.3.1 From c0f38ebf8d483da02a9074eaf021e1660a55fd75 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 23 Jul 2024 19:53:41 +0700 Subject: fsdev read/write packet use unaligned function --- hw/bsp/ch32v20x/family.c | 11 +++ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 108 +++++++++++--------------- src/portable/st/stm32_fsdev/fsdev_common.h | 13 +++- 3 files changed, 64 insertions(+), 68 deletions(-) (limited to 'src') diff --git a/hw/bsp/ch32v20x/family.c b/hw/bsp/ch32v20x/family.c index 542d4b5db..43dd7e032 100644 --- a/hw/bsp/ch32v20x/family.c +++ b/hw/bsp/ch32v20x/family.c @@ -173,6 +173,17 @@ uint32_t board_button_read(void) { return false; } +size_t board_get_unique_id(uint8_t id[], size_t max_len) { + (void) max_len; + volatile uint32_t* ch32_uuid = ((volatile uint32_t*) 0x1FFFF7E8UL); + uint32_t* serial_32 = (uint32_t*) (uintptr_t) id; + serial_32[0] = ch32_uuid[0]; + serial_32[1] = ch32_uuid[1]; + serial_32[2] = ch32_uuid[2]; + + return 12; +} + int board_uart_read(uint8_t *buf, int len) { (void) buf; (void) len; diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 39f33bc34..8c2b10691 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -426,6 +426,8 @@ static void dcd_ep_ctr_rx_handler(uint32_t wIstr) dcd_read_packet_memory(userMemBuf, pcd_get_ep_rx_address(USB, EPindex), 8); dcd_event_setup_received(0, (uint8_t *)userMemBuf, true); #endif + } else { + TU_BREAKPOINT(); } } else { // Clear RX CTR interrupt flag @@ -941,27 +943,26 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) } #ifdef FSDEV_BUS_32BIT -static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t wNBytes) -{ - const uint8_t *srcVal = src; +static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t wNBytes) { + const uint8_t *src8 = src; volatile uint32_t *dst32 = (volatile uint32_t *)(USB_PMAADDR + dst); for (uint32_t n = wNBytes / 4; n > 0; --n) { - *dst32++ = tu_unaligned_read32(srcVal); - srcVal += 4; + *dst32++ = tu_unaligned_read32(src8); + src8 += 4; } - wNBytes = wNBytes & 0x03; - if (wNBytes) { - uint32_t wrVal = *srcVal; - wNBytes--; + uint16_t odd = wNBytes & 0x03; + if (odd) { + uint32_t wrVal = *src8; + odd--; - if (wNBytes) { - wrVal |= *++srcVal << 8; - wNBytes--; + if (odd) { + wrVal |= *++src8 << 8; + odd--; - if (wNBytes) { - wrVal |= *++srcVal << 16; + if (odd) { + wrVal |= *++src8 << 16; } } @@ -974,39 +975,26 @@ static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, ui // Packet buffer access can only be 8- or 16-bit. /** * @brief Copy a buffer from user memory area to packet memory area (PMA). - * This uses byte-access for user memory (so support non-aligned buffers) - * and 16-bit access for packet memory. + * This uses un-aligned for user memory and 16-bit access for packet memory. * @param dst, byte address in PMA; must be 16-bit aligned * @param src pointer to user memory area. * @param wPMABufAddr address into PMA. * @param wNBytes no. of bytes to be copied. * @retval None */ -static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t wNBytes) -{ +static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t wNBytes) { uint32_t n = (uint32_t)wNBytes >> 1U; - uint16_t temp1, temp2; - const uint8_t *srcVal; - - // The GCC optimizer will combine access to 32-bit sizes if we let it. Force - // it volatile so that it won't do that. - __IO uint16_t *pdwVal; - - srcVal = src; - pdwVal = &pma[FSDEV_PMA_STRIDE * (dst >> 1)]; + const uint8_t *src8 = src; + volatile uint16_t *pdw16 = &pma[FSDEV_PMA_STRIDE * (dst >> 1)]; while (n--) { - temp1 = (uint16_t)*srcVal; - srcVal++; - temp2 = temp1 | ((uint16_t)(((uint16_t)(*srcVal)) << 8U)); - *pdwVal = temp2; - pdwVal += FSDEV_PMA_STRIDE; - srcVal++; + *pdw16 = tu_unaligned_read16(src8); + src8 += 2; + pdw16 += FSDEV_PMA_STRIDE; } if (wNBytes & 0x01) { - temp1 = (uint16_t) *srcVal; - *pdwVal = temp1; + *pdw16 = (uint16_t) *src8; } return true; @@ -1091,27 +1079,27 @@ static bool dcd_write_packet_memory_ff(tu_fifo_t *ff, uint16_t dst, uint16_t wNB #ifdef FSDEV_BUS_32BIT static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t wNBytes) { - uint8_t *dstVal = dst; + uint8_t *dst8 = dst; volatile uint32_t *src32 = (volatile uint32_t *)(USB_PMAADDR + src); for (uint32_t n = wNBytes / 4; n > 0; --n) { - tu_unaligned_write32(dstVal, *src32++); - dstVal += 4; + tu_unaligned_write32(dst8, *src32++); + dst8 += 4; } - wNBytes = wNBytes & 0x03; - if (wNBytes) { + uint16_t odd = wNBytes & 0x03; + if (odd) { uint32_t rdVal = *src32; - *dstVal = tu_u32_byte0(rdVal); - wNBytes--; + *dst8 = tu_u32_byte0(rdVal); + odd--; - if (wNBytes) { - *++dstVal = tu_u32_byte1(rdVal); - wNBytes--; + if (odd) { + *++dst8 = tu_u32_byte1(rdVal); + odd--; - if (wNBytes) { - *++dstVal = tu_u32_byte2(rdVal); + if (odd) { + *++dst8 = tu_u32_byte2(rdVal); } } } @@ -1121,33 +1109,25 @@ static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t #else /** * @brief Copy a buffer from packet memory area (PMA) to user memory area. - * Uses byte-access of system memory and 16-bit access of packet memory + * Uses unaligned for system memory and 16-bit access of packet memory * @param wNBytes no. of bytes to be copied. * @retval None */ -static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t wNBytes) -{ +static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t wNBytes) { uint32_t n = (uint32_t)wNBytes >> 1U; - // The GCC optimizer will combine access to 32-bit sizes if we let it. Force - // it volatile so that it won't do that. - __IO const uint16_t *pdwVal; - uint32_t temp; - - pdwVal = &pma[FSDEV_PMA_STRIDE * (src >> 1)]; - uint8_t *dstVal = (uint8_t *)dst; + volatile const uint16_t *pdw16 = &pma[FSDEV_PMA_STRIDE * (src >> 1)]; + uint8_t *dst8 = (uint8_t *)dst; while (n--) { - temp = *pdwVal; - pdwVal += FSDEV_PMA_STRIDE; - *dstVal++ = ((temp >> 0) & 0xFF); - *dstVal++ = ((temp >> 8) & 0xFF); + tu_unaligned_write16(dst8, *pdw16); + dst8 += 2; + pdw16 += FSDEV_PMA_STRIDE; } if (wNBytes & 0x01) { - temp = *pdwVal; - pdwVal += FSDEV_PMA_STRIDE; - *dstVal++ = ((temp >> 0) & 0xFF); + *dst8++ = tu_u16_low(*pdw16); } + return true; } #endif diff --git a/src/portable/st/stm32_fsdev/fsdev_common.h b/src/portable/st/stm32_fsdev/fsdev_common.h index e8a6af8cb..920c17a04 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.h +++ b/src/portable/st/stm32_fsdev/fsdev_common.h @@ -35,14 +35,19 @@ #include "stdint.h" // FSDEV_PMA_SIZE is PMA buffer size in bytes. -// On 512-byte devices, access with a stride of two words (use every other 16-bit address) -// On 1024-byte devices, access with a stride of one word (use every 16-bit address) +// - 512-byte devices, access with a stride of two words (use every other 16-bit address) +// - 1024-byte devices, access with a stride of one word (use every 16-bit address) +// - 2048-byte devices, access with 32-bit address // For purposes of accessing the packet -#if ((FSDEV_PMA_SIZE) == 512u) +#if FSDEV_PMA_SIZE == 512 #define FSDEV_PMA_STRIDE (2u) -#elif ((FSDEV_PMA_SIZE) == 1024u) +#elif FSDEV_PMA_SIZE == 1024 #define FSDEV_PMA_STRIDE (1u) +#elif FSDEV_PMA_SIZE == 2048 + #ifndef FSDEV_BUS_32BIT + #warning "FSDEV_PMA_SIZE is 2048, but FSDEV_BUS_32BIT is not defined" + #endif #endif // The fsdev_bus_t type can be used for both register and PMA access necessities -- cgit v1.3.1 From 2f8078f5b57568f32e0d4d87c95fb32e00389b3d Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 24 Jul 2024 16:59:12 +0700 Subject: minor changes --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 111 ++++++++++---------------- 1 file changed, 43 insertions(+), 68 deletions(-) (limited to 'src') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 8c2b10691..8eb463351 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -180,7 +180,7 @@ static uint8_t remoteWakeCountdown; // When wake is requested //--------------------------------------------------------------------+ // into the stack. -static void dcd_handle_bus_reset(void); +static void handle_bus_reset(uint8_t rhport); static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix); static bool edpt_xfer(uint8_t rhport, uint8_t ep_addr); static void dcd_ep_ctr_handler(void); @@ -212,18 +212,12 @@ TU_ATTR_ALWAYS_INLINE static inline xfer_ctl_t *xfer_ctl_ptr(uint32_t ep_addr) //--------------------------------------------------------------------+ // Controller API //--------------------------------------------------------------------+ - -void dcd_init(uint8_t rhport) -{ - /* Clocks should already be enabled */ - /* Use __HAL_RCC_USB_CLK_ENABLE(); to enable the clocks before calling this function */ - - /* The RM mentions to use a special ordering of PDWN and FRES, but this isn't done in HAL. - * Here, the RM is followed. */ - +void dcd_init(uint8_t rhport) { + // Follow the RM mentions to use a special ordering of PDWN and FRES for (volatile uint32_t i = 0; i < 200; i++) { // should be a few us asm("NOP"); } + // Perform USB peripheral reset USB->CNTR = USB_CNTR_FRES | USB_CNTR_PDWN; for (volatile uint32_t i = 0; i < 200; i++) { // should be a few us @@ -238,9 +232,11 @@ void dcd_init(uint8_t rhport) } USB->CNTR = 0; // Enable USB -#if !defined(STM32G0) && !defined(STM32H5) && !defined(STM32U5) // BTABLE register does not exist any more on STM32G0, it is fixed to USB SRAM base address +#if !defined(STM32G0) && !defined(STM32H5) && !defined(STM32U5) + // BTABLE register does not exist any more on STM32G0, it is fixed to USB SRAM base address USB->BTABLE = DCD_STM32_BTABLE_BASE; #endif + USB->ISTR = 0; // Clear pending interrupts // Reset endpoints to disabled @@ -250,17 +246,14 @@ void dcd_init(uint8_t rhport) } USB->CNTR |= USB_CNTR_RESETM | USB_CNTR_ESOFM | USB_CNTR_CTRM | USB_CNTR_SUSPM | USB_CNTR_WKUPM; - dcd_handle_bus_reset(); + handle_bus_reset(rhport); // Enable pull-up if supported dcd_connect(rhport); } - -void dcd_sof_enable(uint8_t rhport, bool en) -{ +void dcd_sof_enable(uint8_t rhport, bool en) { (void)rhport; - (void)en; if (en) { USB->CNTR |= USB_CNTR_SOFM; @@ -270,9 +263,7 @@ void dcd_sof_enable(uint8_t rhport, bool en) } // Receive Set Address request, mcu port must also include status IN response -void dcd_set_address(uint8_t rhport, uint8_t dev_addr) -{ - (void)rhport; +void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { (void)dev_addr; // Respond with status @@ -282,35 +273,15 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) // do it at dcd_edpt0_status_complete() } -void dcd_remote_wakeup(uint8_t rhport) -{ +void dcd_remote_wakeup(uint8_t rhport) { (void)rhport; USB->CNTR |= USB_CNTR_RESUME; remoteWakeCountdown = 4u; // required to be 1 to 15 ms, ESOF should trigger every 1ms. } -static const tusb_desc_endpoint_t ep0OUT_desc = { - .bLength = sizeof(tusb_desc_endpoint_t), - .bDescriptorType = TUSB_DESC_ENDPOINT, - .bEndpointAddress = 0x00, - .bmAttributes = {.xfer = TUSB_XFER_CONTROL}, - .wMaxPacketSize = CFG_TUD_ENDPOINT0_SIZE, - .bInterval = 0 -}; - -static const tusb_desc_endpoint_t ep0IN_desc = { - .bLength = sizeof(tusb_desc_endpoint_t), - .bDescriptorType = TUSB_DESC_ENDPOINT, - .bEndpointAddress = 0x80, - .bmAttributes = {.xfer = TUSB_XFER_CONTROL}, - .wMaxPacketSize = CFG_TUD_ENDPOINT0_SIZE, - .bInterval = 0 -}; - -static void dcd_handle_bus_reset(void) -{ - USB->DADDR = 0u; // disable USB peripheral by clearing the EF flag +static void handle_bus_reset(uint8_t rhport) { + USB->DADDR = 0u; // disable USB Function for (uint32_t i = 0; i < FSDEV_EP_COUNT; i++) { // Clear EP allocation status @@ -323,17 +294,26 @@ static void dcd_handle_bus_reset(void) // Reset PMA allocation ep_buf_ptr = DCD_STM32_BTABLE_BASE + 8 * CFG_TUD_ENDPPOINT_MAX; - dcd_edpt_open(0, &ep0OUT_desc); - dcd_edpt_open(0, &ep0IN_desc); + tusb_desc_endpoint_t ep0_desc = { + .bLength = sizeof(tusb_desc_endpoint_t), + .bDescriptorType = TUSB_DESC_ENDPOINT, + .bEndpointAddress = 0x00, + .bmAttributes = {.xfer = TUSB_XFER_CONTROL}, + .wMaxPacketSize = CFG_TUD_ENDPOINT0_SIZE, + .bInterval = 0 + }; + + dcd_edpt_open(rhport, &ep0_desc); + + ep0_desc.bEndpointAddress = 0x80; + dcd_edpt_open(rhport, &ep0_desc); - USB->DADDR = USB_DADDR_EF; // Set enable flag, and leaving the device address as zero. + USB->DADDR = USB_DADDR_EF; // Enable USB Function } // Handle CTR interrupt for the TX/IN direction -// // Upon call, (wIstr & USB_ISTR_DIR) == 0U -static void dcd_ep_ctr_tx_handler(uint32_t wIstr) -{ +static void dcd_ep_ctr_tx_handler(uint32_t wIstr) { uint32_t EPindex = wIstr & USB_ISTR_EP_ID; uint32_t wEPRegVal = pcd_get_endpoint(USB, EPindex); uint8_t ep_addr = (wEPRegVal & USB_EPADDR_FIELD) | TUSB_DIR_IN_MASK; @@ -406,6 +386,7 @@ static void dcd_ep_ctr_rx_handler(uint32_t wIstr) // Verify the CTR_RX bit is set. This was in the ST Micro code, // but I'm not sure it's actually necessary? if ((wEPRegVal & USB_EP_CTR_RX) == 0U) { + // TU_ASSERT(false, ); return; } @@ -504,10 +485,7 @@ static void dcd_ep_ctr_handler(void) } } -void dcd_int_handler(uint8_t rhport) -{ - (void)rhport; - +void dcd_int_handler(uint8_t rhport) { uint32_t int_status = USB->ISTR; // const uint32_t handled_ints = USB_ISTR_CTR | USB_ISTR_RESET | USB_ISTR_WKUP // | USB_ISTR_SUSP | USB_ISTR_SOF | USB_ISTR_ESOF; @@ -526,7 +504,7 @@ void dcd_int_handler(uint8_t rhport) if (int_status & USB_ISTR_RESET) { // USBRST is start of reset. USB->ISTR = (fsdev_bus_t)~USB_ISTR_RESET; - dcd_handle_bus_reset(); + handle_bus_reset(rhport); dcd_event_bus_reset(0, TUSB_SPEED_FULL, true); return; // Don't do the rest of the things here; perhaps they've been cleared? } @@ -659,13 +637,12 @@ static uint8_t dcd_ep_alloc(uint8_t ep_addr, uint8_t ep_type) // The STM32F0 doesn't seem to like |= or &= to manipulate the EP#R registers, // so I'm using the #define from HAL here, instead. -bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *p_endpoint_desc) -{ +bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) { (void)rhport; - uint8_t const ep_addr = p_endpoint_desc->bEndpointAddress; - uint8_t const ep_idx = dcd_ep_alloc(ep_addr, p_endpoint_desc->bmAttributes.xfer); + uint8_t const ep_addr = desc_ep->bEndpointAddress; + uint8_t const ep_idx = dcd_ep_alloc(ep_addr, desc_ep->bmAttributes.xfer); uint8_t const dir = tu_edpt_dir(ep_addr); - const uint16_t packet_size = tu_edpt_packet_size(p_endpoint_desc); + const uint16_t packet_size = tu_edpt_packet_size(desc_ep); const uint16_t buffer_size = pcd_aligned_buffer_size(packet_size); uint16_t pma_addr; uint32_t wType; @@ -674,7 +651,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *p_endpoint_desc) TU_ASSERT(buffer_size <= 64); // Set type - switch (p_endpoint_desc->bmAttributes.xfer) { + switch (desc_ep->bmAttributes.xfer) { case TUSB_XFER_CONTROL: wType = USB_EP_CONTROL; break; @@ -807,7 +784,6 @@ bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *p_endpoin } // Currently, single-buffered, and only 64 bytes at a time (max) - static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix) { uint16_t len = (uint16_t)(xfer->total_len - xfer->queued_len); @@ -1007,8 +983,7 @@ static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, ui * @param wNBytes no. of bytes to be copied. * @retval None */ -static bool dcd_write_packet_memory_ff(tu_fifo_t *ff, uint16_t dst, uint16_t wNBytes) -{ +static bool dcd_write_packet_memory_ff(tu_fifo_t *ff, uint16_t dst, uint16_t wNBytes) { // Since we copy from a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies tu_fifo_buffer_info_t info; tu_fifo_get_read_info(ff, &info); @@ -1042,8 +1017,9 @@ static bool dcd_write_packet_memory_ff(tu_fifo_t *ff, uint16_t dst, uint16_t wNB dst += 4; // Copy rest of wrapped byte - if (wCnt) + if (wCnt) { dcd_write_packet_memory(dst, info.ptr_wrap, wCnt); + } } #else if ((cnt_lin & 0x01) && cnt_wrap) { @@ -1077,8 +1053,7 @@ static bool dcd_write_packet_memory_ff(tu_fifo_t *ff, uint16_t dst, uint16_t wNB } #ifdef FSDEV_BUS_32BIT -static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t wNBytes) -{ +static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t wNBytes) { uint8_t *dst8 = dst; volatile uint32_t *src32 = (volatile uint32_t *)(USB_PMAADDR + src); @@ -1138,8 +1113,7 @@ static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t * @param wNBytes no. of bytes to be copied. * @retval None */ -static bool dcd_read_packet_memory_ff(tu_fifo_t *ff, uint16_t src, uint16_t wNBytes) -{ +static bool dcd_read_packet_memory_ff(tu_fifo_t *ff, uint16_t src, uint16_t wNBytes) { // Since we copy into a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies // Check for first linear part tu_fifo_buffer_info_t info; @@ -1173,8 +1147,9 @@ static bool dcd_read_packet_memory_ff(tu_fifo_t *ff, uint16_t src, uint16_t wNBy } // Copy rest of wrapped byte - if (wCnt) + if (wCnt) { dcd_read_packet_memory(info.ptr_wrap, src, wCnt); + } } #else if ((cnt_lin & 0x01) && cnt_wrap) { -- cgit v1.3.1 From 0eb0baed190ea671b74528942e4fda87acd259a8 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 25 Jul 2024 11:53:42 +0700 Subject: fsdev: remove unused _setup_packet --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 38 +++++++++++---------------- 1 file changed, 16 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 8eb463351..602b220ab 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -168,11 +168,8 @@ typedef struct { } ep_alloc_t; static xfer_ctl_t xfer_status[CFG_TUD_ENDPPOINT_MAX][2]; - static ep_alloc_t ep_alloc_status[FSDEV_EP_COUNT]; -static TU_ATTR_ALIGNED(4) uint32_t _setup_packet[6]; - static uint8_t remoteWakeCountdown; // When wake is requested //--------------------------------------------------------------------+ @@ -386,18 +383,28 @@ static void dcd_ep_ctr_rx_handler(uint32_t wIstr) // Verify the CTR_RX bit is set. This was in the ST Micro code, // but I'm not sure it's actually necessary? if ((wEPRegVal & USB_EP_CTR_RX) == 0U) { - // TU_ASSERT(false, ); return; } - if ((ep_addr == 0U) && ((wEPRegVal & USB_EP_SETUP) != 0U)) { + if (wEPRegVal & USB_EP_SETUP) { /* Setup packet */ uint32_t count = pcd_get_ep_rx_cnt(USB, EPindex); // Setup packet should always be 8 bytes. If not, ignore it, and try again. if (count == 8) { - // Must reset EP to NAK (in case it had been stalling) (though, maybe too late here) + // Must reset EP to NAK (in case it had been stalling) pcd_set_ep_rx_status(USB, 0u, USB_EP_RX_NAK); pcd_set_ep_tx_status(USB, 0u, USB_EP_TX_NAK); + + // set both data toggle to 1 + uint32_t regVal = pcd_get_endpoint(USB, 0); + if ((regVal & USB_EP_DTOG_TX) == 0) { + pcd_tx_dtog(USB, 0); + } + + if ((regVal & USB_EP_DTOG_RX) == 0) { + pcd_rx_dtog(USB, 0); + } + #ifdef FSDEV_BUS_32BIT dcd_event_setup_received(0, (uint8_t *)(USB_PMAADDR + pcd_get_ep_rx_address(USB, EPindex)), true); #else @@ -405,17 +412,14 @@ static void dcd_ep_ctr_rx_handler(uint32_t wIstr) // user memory, to allow for the 32-bit access that memcpy performs. uint8_t userMemBuf[8]; dcd_read_packet_memory(userMemBuf, pcd_get_ep_rx_address(USB, EPindex), 8); - dcd_event_setup_received(0, (uint8_t *)userMemBuf, true); + dcd_event_setup_received(0, (uint8_t*) userMemBuf, true); #endif - } else { - TU_BREAKPOINT(); } } else { // Clear RX CTR interrupt flag if (ep_addr != 0u) { pcd_clear_rx_ep_ctr(USB, EPindex); } - uint32_t count; uint16_t addr; /* Read from correct register when ISOCHRONOUS (double buffered) */ @@ -553,18 +557,14 @@ void dcd_int_handler(uint8_t rhport) { // Invoked when a control transfer's status stage is complete. // May help DCD to prepare for next control transfer, this API is optional. -void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const *request) -{ +void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const *request) { (void)rhport; if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE && request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && request->bRequest == TUSB_REQ_SET_ADDRESS) { uint8_t const dev_addr = (uint8_t)request->wValue; - - // Setting new address after the whole request is complete - USB->DADDR &= ~USB_DADDR_ADD; - USB->DADDR |= dev_addr; // leave the enable bit set + USB->DADDR = (USB_DADDR_EF | dev_addr); } } @@ -834,12 +834,6 @@ static bool edpt_xfer(uint8_t rhport, uint8_t ep_addr) if (dir == TUSB_DIR_IN) { dcd_transmit_packet(xfer, ep_idx); } else { - // A setup token can occur immediately after an OUT STATUS packet so make sure we have a valid - // buffer for the control endpoint. - if (ep_idx == 0 && xfer->buffer == NULL) { - xfer->buffer = (uint8_t *)_setup_packet; - } - uint32_t cnt = (uint32_t ) tu_min16(xfer->total_len, xfer->max_packet_size); uint16_t ep_reg = pcd_get_endpoint(USB, ep_idx); -- cgit v1.3.1 From a5bc0430f75c4e2088690467b369db7e24bba97b Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 25 Jul 2024 16:49:01 +0700 Subject: fix race condition where reset event cleaar setup count --- src/device/dcd.h | 22 +++++++++------------- src/device/usbd.c | 11 +++++++---- 2 files changed, 16 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/device/dcd.h b/src/device/dcd.h index 5356e9be1..b25b47025 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -40,19 +40,15 @@ //--------------------------------------------------------------------+ typedef enum { - DCD_EVENT_INVALID = 0, - DCD_EVENT_BUS_RESET, - DCD_EVENT_UNPLUGGED, - DCD_EVENT_SOF, - DCD_EVENT_SUSPEND, // TODO LPM Sleep L1 support - DCD_EVENT_RESUME, - - DCD_EVENT_SETUP_RECEIVED, - DCD_EVENT_XFER_COMPLETE, - - // Not an DCD event, just a convenient way to defer ISR function - USBD_EVENT_FUNC_CALL, - + DCD_EVENT_INVALID = 0, // 0 + DCD_EVENT_BUS_RESET, // 1 + DCD_EVENT_UNPLUGGED, // 2 + DCD_EVENT_SOF, // 3 + DCD_EVENT_SUSPEND, // 4 TODO LPM Sleep L1 support + DCD_EVENT_RESUME, // 5 + DCD_EVENT_SETUP_RECEIVED, // 6 + DCD_EVENT_XFER_COMPLETE, // 7 + USBD_EVENT_FUNC_CALL, // 8 Not an DCD event, just a convenient way to defer ISR function DCD_EVENT_COUNT } dcd_eventid_t; diff --git a/src/device/usbd.c b/src/device/usbd.c index b93216006..d9b20d26d 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -120,7 +120,6 @@ typedef struct { }; volatile uint8_t cfg_num; // current active configuration (0x00 is not configured) uint8_t speed; - volatile uint8_t setup_count; volatile uint8_t sof_consumer; uint8_t itf2drv[CFG_TUD_INTERFACE_MAX]; // map interface number to driver (0xff is invalid) @@ -131,6 +130,7 @@ typedef struct { }usbd_device_t; tu_static usbd_device_t _usbd_dev; +static volatile uint8_t _usbd_queued_setup; //--------------------------------------------------------------------+ // Class Driver @@ -459,6 +459,7 @@ bool tud_init(uint8_t rhport) { TU_LOG_INT(CFG_TUD_LOG_LEVEL, sizeof(tu_edpt_stream_t)); tu_varclr(&_usbd_dev); + _usbd_queued_setup = 0; #if OSAL_MUTEX_REQUIRED // Init device mutex @@ -594,9 +595,10 @@ void tud_task_ext(uint32_t timeout_ms, bool in_isr) { break; case DCD_EVENT_SETUP_RECEIVED: - _usbd_dev.setup_count--; + TU_ASSERT(_usbd_queued_setup > 0,); + _usbd_queued_setup--; TU_LOG_BUF(CFG_TUD_LOG_LEVEL, &event.setup_received, 8); - if (_usbd_dev.setup_count) { + if (_usbd_queued_setup) { TU_LOG_USBD(" Skipped since there is other SETUP in queue\r\n"); break; } @@ -1199,7 +1201,8 @@ TU_ATTR_FAST_FUNC void dcd_event_handler(dcd_event_t const* event, bool in_isr) break; case DCD_EVENT_SETUP_RECEIVED: - _usbd_dev.setup_count++; + // TU_ASSERT(event->setup_received.bRequest != 0,); + _usbd_queued_setup++; send = true; break; -- cgit v1.3.1 From 02caf007723551f878ab3675c14681801f16354e Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 25 Jul 2024 19:00:59 +0700 Subject: simplify btable rx/tx count/address access --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 20 +--- src/portable/st/stm32_fsdev/fsdev_common.h | 136 ++++++++++++++++++-------- 2 files changed, 98 insertions(+), 58 deletions(-) (limited to 'src') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 602b220ab..927ecac85 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -129,21 +129,7 @@ // Configuration //--------------------------------------------------------------------+ -// hardware limit endpoint -#define FSDEV_EP_COUNT 8 -// If sharing with CAN, one can set this to be non-zero to give CAN space where it wants it -// Both of these MUST be a multiple of 2, and are in byte units. -#ifndef DCD_STM32_BTABLE_BASE -#define DCD_STM32_BTABLE_BASE 0U -#endif - -#ifndef DCD_STM32_BTABLE_SIZE -#define DCD_STM32_BTABLE_SIZE (FSDEV_PMA_SIZE - DCD_STM32_BTABLE_BASE) -#endif - -TU_VERIFY_STATIC(((DCD_STM32_BTABLE_BASE) + (DCD_STM32_BTABLE_SIZE)) <= (FSDEV_PMA_SIZE), "BTABLE does not fit in PMA RAM"); -TU_VERIFY_STATIC(((DCD_STM32_BTABLE_BASE) % 8) == 0, "BTABLE base must be aligned to 8 bytes"); //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF @@ -231,7 +217,7 @@ void dcd_init(uint8_t rhport) { #if !defined(STM32G0) && !defined(STM32H5) && !defined(STM32U5) // BTABLE register does not exist any more on STM32G0, it is fixed to USB SRAM base address - USB->BTABLE = DCD_STM32_BTABLE_BASE; + USB->BTABLE = FSDEV_BTABLE_BASE; #endif USB->ISTR = 0; // Clear pending interrupts @@ -289,7 +275,7 @@ static void handle_bus_reset(uint8_t rhport) { } // Reset PMA allocation - ep_buf_ptr = DCD_STM32_BTABLE_BASE + 8 * CFG_TUD_ENDPPOINT_MAX; + ep_buf_ptr = FSDEV_BTABLE_BASE + 8 * FSDEV_EP_COUNT; tusb_desc_endpoint_t ep0_desc = { .bLength = sizeof(tusb_desc_endpoint_t), @@ -705,7 +691,7 @@ void dcd_edpt_close_all(uint8_t rhport) } // Reset PMA allocation - ep_buf_ptr = DCD_STM32_BTABLE_BASE + 8 * CFG_TUD_ENDPPOINT_MAX + 2 * CFG_TUD_ENDPOINT0_SIZE; + ep_buf_ptr = FSDEV_BTABLE_BASE + 8 * CFG_TUD_ENDPPOINT_MAX + 2 * CFG_TUD_ENDPOINT0_SIZE; } /** diff --git a/src/portable/st/stm32_fsdev/fsdev_common.h b/src/portable/st/stm32_fsdev/fsdev_common.h index 920c17a04..d0f928552 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.h +++ b/src/portable/st/stm32_fsdev/fsdev_common.h @@ -34,6 +34,14 @@ #include "stdint.h" +// If sharing with CAN, one can set this to be non-zero to give CAN space where it wants it +// Both of these MUST be a multiple of 2, and are in byte units. +#ifndef FSDEV_BTABLE_BASE +#define FSDEV_BTABLE_BASE 0U +#endif + +TU_VERIFY_STATIC(FSDEV_BTABLE_BASE % 8 == 0, "BTABLE base must be aligned to 8 bytes"); + // FSDEV_PMA_SIZE is PMA buffer size in bytes. // - 512-byte devices, access with a stride of two words (use every other 16-bit address) // - 1024-byte devices, access with a stride of one word (use every 16-bit address) @@ -41,15 +49,50 @@ // For purposes of accessing the packet #if FSDEV_PMA_SIZE == 512 - #define FSDEV_PMA_STRIDE (2u) + #define FSDEV_PMA_STRIDE (2u) // 1x16 bit access scheme + #define pma_aligned TU_ATTR_ALIGNED(4) #elif FSDEV_PMA_SIZE == 1024 - #define FSDEV_PMA_STRIDE (1u) + #define FSDEV_PMA_STRIDE (1u) // 2x16 bit access scheme + #define pma_aligned #elif FSDEV_PMA_SIZE == 2048 #ifndef FSDEV_BUS_32BIT #warning "FSDEV_PMA_SIZE is 2048, but FSDEV_BUS_32BIT is not defined" #endif + #define FSDEV_PMA_STRIDE (1u) // 32 bit access scheme + #define pma_aligned #endif +// hardware limit endpoint +#define FSDEV_EP_COUNT 8 + +// Buffer Table is located in Packet Memory Area (PMA) and therefore its address access is forced to either +// 16-bit or 32-bit depending on FSDEV_BUS_32BIT. +typedef struct { + union { + struct { + volatile pma_aligned uint16_t tx_addr; + volatile pma_aligned uint16_t tx_count; + volatile pma_aligned uint16_t rx_addr; + volatile pma_aligned uint16_t rx_count; + } ep16[FSDEV_EP_COUNT]; + + struct { + volatile uint32_t tx_count_addr; + volatile uint32_t rx_count_addr; + } ep32[FSDEV_EP_COUNT]; + }; +} fsdev_btable_t; + +TU_VERIFY_STATIC(sizeof(fsdev_btable_t) == FSDEV_EP_COUNT*8*FSDEV_PMA_STRIDE, "size is not correct"); +TU_VERIFY_STATIC(FSDEV_BTABLE_BASE + FSDEV_EP_COUNT*8 <= FSDEV_PMA_SIZE, "BTABLE does not fit in PMA RAM"); + + +#define FSDEV_BTABLE ((volatile fsdev_btable_t*) (USB_PMAADDR+FSDEV_BTABLE_BASE)) + +//--------------------------------------------------------------------+ +// Helper +//--------------------------------------------------------------------+ + // The fsdev_bus_t type can be used for both register and PMA access necessities // For type-safety create a new macro for the volatile address of PMAADDR // The compiler should warn us if we cast it to a non-volatile type? @@ -110,6 +153,21 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_endpoint(USB_TypeDef * USBx return *reg; } +/** + * @brief Sets address in an endpoint register. + * @param USBx USB peripheral instance register address. + * @param bEpIdx Endpoint Number. + * @param bAddr Address. + * @retval None + */ +TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_address(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t bAddr) { + uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); + regVal &= USB_EPREG_MASK; + regVal |= bAddr; + regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX; + pcd_set_endpoint(USBx, bEpIdx,regVal); +} + TU_ATTR_ALWAYS_INLINE static inline void pcd_set_eptype(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wType) { uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); regVal &= (uint32_t)USB_EP_T_MASK; @@ -153,58 +211,47 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_tx_ep_ctr(USB_TypeDef * USBx, * @retval Counter value */ TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_tx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx) { -#ifdef FSDEV_BUS_32BIT (void) USBx; - return (pma32[2*bEpIdx] & 0x03FF0000) >> 16; + uint16_t count; +#ifdef FSDEV_BUS_32BIT + count = (FSDEV_BTABLE->ep32[bEpIdx].tx_count_addr >> 16); #else - volatile const uint16_t *regPtr = pcd_ep_tx_cnt_ptr(USBx, bEpIdx); - return *regPtr & 0x3ffU; + count = FSDEV_BTABLE->ep16[bEpIdx].tx_count; #endif + + return count & 0x3FFU; } TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx) { -#ifdef FSDEV_BUS_32BIT (void) USBx; - return (pma32[2*bEpIdx + 1] & 0x03FF0000) >> 16; + uint16_t count; +#ifdef FSDEV_BUS_32BIT + count = (FSDEV_BTABLE->ep32[bEpIdx].rx_count_addr >> 16); #else - volatile const uint16_t *regPtr = pcd_ep_rx_cnt_ptr(USBx, bEpIdx); - return *regPtr & 0x3ffU; + count = FSDEV_BTABLE->ep16[bEpIdx].rx_count; #endif + + return count & 0x3FFU; } #define pcd_get_ep_dbuf0_cnt pcd_get_ep_tx_cnt #define pcd_get_ep_dbuf1_cnt pcd_get_ep_rx_cnt -/** - * @brief Sets address in an endpoint register. - * @param USBx USB peripheral instance register address. - * @param bEpIdx Endpoint Number. - * @param bAddr Address. - * @retval None - */ -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_address(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t bAddr) { - uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); - regVal &= USB_EPREG_MASK; - regVal |= bAddr; - regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX; - pcd_set_endpoint(USBx, bEpIdx,regVal); -} - TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_tx_address(USB_TypeDef * USBx, uint32_t bEpIdx) { -#ifdef FSDEV_BUS_32BIT (void) USBx; - return pma32[2*bEpIdx] & 0x0000FFFFu ; +#ifdef FSDEV_BUS_32BIT + return FSDEV_BTABLE->ep32[bEpIdx].tx_count_addr & 0x0000FFFFu; #else - return *pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 0u); + return FSDEV_BTABLE->ep16[bEpIdx].tx_addr; #endif } TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_address(USB_TypeDef * USBx, uint32_t bEpIdx) { -#ifdef FSDEV_BUS_32BIT (void) USBx; - return pma32[2*bEpIdx + 1] & 0x0000FFFFu; +#ifdef FSDEV_BUS_32BIT + return FSDEV_BTABLE->ep32[bEpIdx].rx_count_addr & 0x0000FFFFu; #else - return *pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 2u); + return FSDEV_BTABLE->ep16[bEpIdx].rx_addr; #endif } @@ -212,20 +259,24 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_address(USB_TypeDef * #define pcd_get_ep_dbuf1_address pcd_get_ep_rx_address TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_address(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t addr) { -#ifdef FSDEV_BUS_32BIT (void) USBx; - pma32[2*bEpIdx] = (pma32[2*bEpIdx] & 0xFFFF0000u) | (addr & 0x0000FFFCu); +#ifdef FSDEV_BUS_32BIT + uint32_t count_addr = FSDEV_BTABLE->ep32[bEpIdx].tx_count_addr; + count_addr = (count_addr & 0xFFFF0000u) | (addr & 0x0000FFFCu); + FSDEV_BTABLE->ep32[bEpIdx].tx_count_addr = count_addr; #else - *pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 0u) = addr; + FSDEV_BTABLE->ep16[bEpIdx].tx_addr = addr; #endif } TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_address(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t addr) { -#ifdef FSDEV_BUS_32BIT (void) USBx; - pma32[2*bEpIdx + 1] = (pma32[2*bEpIdx + 1] & 0xFFFF0000u) | (addr & 0x0000FFFCu); +#ifdef FSDEV_BUS_32BIT + uint32_t count_addr = FSDEV_BTABLE->ep32[bEpIdx].rx_count_addr; + count_addr = (count_addr & 0xFFFF0000u) | (addr & 0x0000FFFCu); + FSDEV_BTABLE->ep32[bEpIdx].rx_count_addr = count_addr; #else - *pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 2u) = addr; + FSDEV_BTABLE->ep16[bEpIdx].rx_addr = addr; #endif } @@ -233,12 +284,15 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_address(USB_TypeDef * USB #define pcd_set_ep_dbuf1_address pcd_set_ep_rx_address TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount) { -#ifdef FSDEV_BUS_32BIT (void) USBx; - pma32[2*bEpIdx] = (pma32[2*bEpIdx] & ~0x03FF0000u) | ((wCount & 0x3FFu) << 16); +#ifdef FSDEV_BUS_32BIT + uint32_t count_addr = FSDEV_BTABLE->ep32[bEpIdx].tx_count_addr; + count_addr = (count_addr & ~0x03FF0000u) | ((wCount & 0x3FFu) << 16); + FSDEV_BTABLE->ep32[bEpIdx].tx_count_addr = count_addr; #else - volatile uint16_t * reg = pcd_ep_tx_cnt_ptr(USBx, bEpIdx); - *reg = (uint16_t) (*reg & (uint16_t) ~0x3FFU) | (wCount & 0x3FFU); + uint16_t count = FSDEV_BTABLE->ep16[bEpIdx].tx_count; + count = (count & ~0x3FFU) | (wCount & 0x3FFU); + FSDEV_BTABLE->ep16[bEpIdx].tx_count = count; #endif } -- cgit v1.3.1 From 3b8f9a2b1f43a8353c1556e30a61dd0c2416c57f Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 25 Jul 2024 23:51:20 +0700 Subject: refactor btable tx/rx into arr[2] --- src/portable/st/stm32_fsdev/fsdev_common.h | 95 ++++++++++++++++-------------- 1 file changed, 51 insertions(+), 44 deletions(-) (limited to 'src') diff --git a/src/portable/st/stm32_fsdev/fsdev_common.h b/src/portable/st/stm32_fsdev/fsdev_common.h index d0f928552..7d1f7fd90 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.h +++ b/src/portable/st/stm32_fsdev/fsdev_common.h @@ -69,17 +69,18 @@ TU_VERIFY_STATIC(FSDEV_BTABLE_BASE % 8 == 0, "BTABLE base must be aligned to 8 b // 16-bit or 32-bit depending on FSDEV_BUS_32BIT. typedef struct { union { + // 0: tx, 1: rx + + // strictly 16-bit access (could be 32-bit aligned) struct { - volatile pma_aligned uint16_t tx_addr; - volatile pma_aligned uint16_t tx_count; - volatile pma_aligned uint16_t rx_addr; - volatile pma_aligned uint16_t rx_count; - } ep16[FSDEV_EP_COUNT]; + volatile pma_aligned uint16_t addr; + volatile pma_aligned uint16_t count; + } ep16[FSDEV_EP_COUNT][2]; + // strictly 32-bit access struct { - volatile uint32_t tx_count_addr; - volatile uint32_t rx_count_addr; - } ep32[FSDEV_EP_COUNT]; + volatile uint32_t count_addr; + } ep32[FSDEV_EP_COUNT][2]; }; } fsdev_btable_t; @@ -204,6 +205,24 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_tx_ep_ctr(USB_TypeDef * USBx, pcd_set_endpoint(USBx, bEpIdx,regVal); } +TU_ATTR_ALWAYS_INLINE static inline uint32_t btable_get_count(uint32_t ep_id, uint8_t is_rx) { + uint16_t count; +#ifdef FSDEV_BUS_32BIT + count = (FSDEV_BTABLE->ep32[ep_id][is_rx].count_addr >> 16); +#else + count = FSDEV_BTABLE->ep16[ep_id][is_rx].count; +#endif + return count & 0x3FFU; +} + +TU_ATTR_ALWAYS_INLINE static inline uint32_t btable_get_addr(uint32_t ep_id, uint8_t is_rx) { +#ifdef FSDEV_BUS_32BIT + return FSDEV_BTABLE->ep32[ep_id][is_rx].count_addr & 0x0000FFFFu; +#else + return FSDEV_BTABLE->ep16[ep_id][is_rx].addr; +#endif +} + /** * @brief gets counter of the tx buffer. * @param USBx USB peripheral instance register address. @@ -212,26 +231,12 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_tx_ep_ctr(USB_TypeDef * USBx, */ TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_tx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx) { (void) USBx; - uint16_t count; -#ifdef FSDEV_BUS_32BIT - count = (FSDEV_BTABLE->ep32[bEpIdx].tx_count_addr >> 16); -#else - count = FSDEV_BTABLE->ep16[bEpIdx].tx_count; -#endif - - return count & 0x3FFU; + return btable_get_count(bEpIdx, 0); } TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx) { (void) USBx; - uint16_t count; -#ifdef FSDEV_BUS_32BIT - count = (FSDEV_BTABLE->ep32[bEpIdx].rx_count_addr >> 16); -#else - count = FSDEV_BTABLE->ep16[bEpIdx].rx_count; -#endif - - return count & 0x3FFU; + return btable_get_count(bEpIdx, 1); } #define pcd_get_ep_dbuf0_cnt pcd_get_ep_tx_cnt @@ -239,44 +244,46 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_cnt(USB_TypeDef * USB TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_tx_address(USB_TypeDef * USBx, uint32_t bEpIdx) { (void) USBx; -#ifdef FSDEV_BUS_32BIT - return FSDEV_BTABLE->ep32[bEpIdx].tx_count_addr & 0x0000FFFFu; -#else - return FSDEV_BTABLE->ep16[bEpIdx].tx_addr; -#endif + return btable_get_addr(bEpIdx, 0); } TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_address(USB_TypeDef * USBx, uint32_t bEpIdx) { (void) USBx; -#ifdef FSDEV_BUS_32BIT - return FSDEV_BTABLE->ep32[bEpIdx].rx_count_addr & 0x0000FFFFu; -#else - return FSDEV_BTABLE->ep16[bEpIdx].rx_addr; -#endif + return btable_get_addr(bEpIdx, 1); } #define pcd_get_ep_dbuf0_address pcd_get_ep_tx_address #define pcd_get_ep_dbuf1_address pcd_get_ep_rx_address + +//TU_ATTR_ALWAYS_INLINE static inline uint32_t btable_set_addr(uint32_t ep_id, uint8_t is_rx, uint16_t addr) { +// +//} +// +//TU_ATTR_ALWAYS_INLINE static inline uint32_t btable_set_count(uint32_t ep_id, uint8_t is_rx, uint16_t count) { +// +//} + + TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_address(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t addr) { (void) USBx; #ifdef FSDEV_BUS_32BIT - uint32_t count_addr = FSDEV_BTABLE->ep32[bEpIdx].tx_count_addr; + uint32_t count_addr = FSDEV_BTABLE->ep32[bEpIdx][0].count_addr; count_addr = (count_addr & 0xFFFF0000u) | (addr & 0x0000FFFCu); - FSDEV_BTABLE->ep32[bEpIdx].tx_count_addr = count_addr; + FSDEV_BTABLE->ep32[bEpIdx][0].count_addr = count_addr; #else - FSDEV_BTABLE->ep16[bEpIdx].tx_addr = addr; + FSDEV_BTABLE->ep16[bEpIdx][0].addr = addr; #endif } TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_address(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t addr) { (void) USBx; #ifdef FSDEV_BUS_32BIT - uint32_t count_addr = FSDEV_BTABLE->ep32[bEpIdx].rx_count_addr; + uint32_t count_addr = FSDEV_BTABLE->ep32[bEpIdx][1].count_addr; count_addr = (count_addr & 0xFFFF0000u) | (addr & 0x0000FFFCu); - FSDEV_BTABLE->ep32[bEpIdx].rx_count_addr = count_addr; + FSDEV_BTABLE->ep32[bEpIdx][1].count_addr = count_addr; #else - FSDEV_BTABLE->ep16[bEpIdx].rx_addr = addr; + FSDEV_BTABLE->ep16[bEpIdx][1].addr = addr; #endif } @@ -286,13 +293,13 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_address(USB_TypeDef * USB TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount) { (void) USBx; #ifdef FSDEV_BUS_32BIT - uint32_t count_addr = FSDEV_BTABLE->ep32[bEpIdx].tx_count_addr; + uint32_t count_addr = FSDEV_BTABLE->ep32[bEpIdx][0].count_addr; count_addr = (count_addr & ~0x03FF0000u) | ((wCount & 0x3FFu) << 16); - FSDEV_BTABLE->ep32[bEpIdx].tx_count_addr = count_addr; + FSDEV_BTABLE->ep32[bEpIdx][0].count_addr = count_addr; #else - uint16_t count = FSDEV_BTABLE->ep16[bEpIdx].tx_count; + uint16_t count = FSDEV_BTABLE->ep16[bEpIdx][0].count; count = (count & ~0x3FFU) | (wCount & 0x3FFU); - FSDEV_BTABLE->ep16[bEpIdx].tx_count = count; + FSDEV_BTABLE->ep16[bEpIdx][0].count = count; #endif } -- cgit v1.3.1 From 75d3a3be84fa50abd5519e1879aa5dafc4a5c37d Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 26 Jul 2024 00:02:06 +0700 Subject: implement btable_set_addr/count --- src/portable/st/stm32_fsdev/fsdev_common.h | 51 +++++++++++++----------------- 1 file changed, 22 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/portable/st/stm32_fsdev/fsdev_common.h b/src/portable/st/stm32_fsdev/fsdev_common.h index 7d1f7fd90..58a9ed96d 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.h +++ b/src/portable/st/stm32_fsdev/fsdev_common.h @@ -256,51 +256,44 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_address(USB_TypeDef * #define pcd_get_ep_dbuf1_address pcd_get_ep_rx_address -//TU_ATTR_ALWAYS_INLINE static inline uint32_t btable_set_addr(uint32_t ep_id, uint8_t is_rx, uint16_t addr) { -// -//} -// -//TU_ATTR_ALWAYS_INLINE static inline uint32_t btable_set_count(uint32_t ep_id, uint8_t is_rx, uint16_t count) { -// -//} - - -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_address(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t addr) { - (void) USBx; +TU_ATTR_ALWAYS_INLINE static inline void btable_set_addr(uint32_t ep_id, uint8_t is_rx, uint16_t addr) { #ifdef FSDEV_BUS_32BIT - uint32_t count_addr = FSDEV_BTABLE->ep32[bEpIdx][0].count_addr; + uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][is_rx].count_addr; count_addr = (count_addr & 0xFFFF0000u) | (addr & 0x0000FFFCu); - FSDEV_BTABLE->ep32[bEpIdx][0].count_addr = count_addr; + FSDEV_BTABLE->ep32[ep_id][is_rx].count_addr = count_addr; #else - FSDEV_BTABLE->ep16[bEpIdx][0].addr = addr; + FSDEV_BTABLE->ep16[ep_id][is_rx].addr = addr; #endif } -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_address(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t addr) { - (void) USBx; +TU_ATTR_ALWAYS_INLINE static inline void btable_set_count(uint32_t ep_id, uint8_t is_rx, uint16_t byte_count) { #ifdef FSDEV_BUS_32BIT - uint32_t count_addr = FSDEV_BTABLE->ep32[bEpIdx][1].count_addr; - count_addr = (count_addr & 0xFFFF0000u) | (addr & 0x0000FFFCu); - FSDEV_BTABLE->ep32[bEpIdx][1].count_addr = count_addr; + uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][is_rx].count_addr; + count_addr = (count_addr & ~0x03FF0000u) | ((byte_count & 0x3FFu) << 16); + FSDEV_BTABLE->ep32[ep_id][is_rx].count_addr = count_addr; #else - FSDEV_BTABLE->ep16[bEpIdx][1].addr = addr; + uint16_t cnt = FSDEV_BTABLE->ep16[ep_id][is_rx].count; + cnt = (cnt & ~0x3FFU) | (byte_count & 0x3FFU); + FSDEV_BTABLE->ep16[ep_id][is_rx].count = cnt; #endif } +TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_address(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t addr) { + (void) USBx; + btable_set_addr(bEpIdx, 0, addr); +} + +TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_address(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t addr) { + (void) USBx; + btable_set_addr(bEpIdx, 1, addr); +} + #define pcd_set_ep_dbuf0_address pcd_set_ep_tx_address #define pcd_set_ep_dbuf1_address pcd_set_ep_rx_address TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount) { (void) USBx; -#ifdef FSDEV_BUS_32BIT - uint32_t count_addr = FSDEV_BTABLE->ep32[bEpIdx][0].count_addr; - count_addr = (count_addr & ~0x03FF0000u) | ((wCount & 0x3FFu) << 16); - FSDEV_BTABLE->ep32[bEpIdx][0].count_addr = count_addr; -#else - uint16_t count = FSDEV_BTABLE->ep16[bEpIdx][0].count; - count = (count & ~0x3FFU) | (wCount & 0x3FFU); - FSDEV_BTABLE->ep16[bEpIdx][0].count = count; -#endif + btable_set_count(bEpIdx, 0, wCount); } #define pcd_set_ep_tx_dbuf0_cnt pcd_set_ep_tx_cnt -- cgit v1.3.1 From 4a48544aebf362e77095c52ddcfcde6a65876acf Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sun, 28 Jul 2024 12:04:25 +0200 Subject: audiod_function_t clean up. --- src/class/audio/audio_device.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 75bb0b883..8c86de433 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -303,8 +303,6 @@ typedef struct bool mounted; // Device opened - /*------------- From this point, data is not cleared by bus reset -------------*/ - uint16_t desc_length; // Length of audio function descriptor #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP @@ -369,6 +367,8 @@ typedef struct #endif #endif + /*------------- From this point, data is not cleared by bus reset -------------*/ + // Buffer for control requests uint8_t * ctrl_buf; uint8_t ctrl_buf_sz; @@ -377,14 +377,10 @@ typedef struct uint8_t * alt_setting; // We need to save the current alternate setting this way, because it is possible that there are AS interfaces which do not have an EP! // EP Transfer buffers and FIFOs -#if CFG_TUD_AUDIO_ENABLE_EP_OUT -#if !CFG_TUD_AUDIO_ENABLE_DECODING +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING tu_fifo_t ep_out_ff; #endif - -#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT - #if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING tu_fifo_t ep_in_ff; #endif @@ -394,7 +390,6 @@ typedef struct CFG_TUSB_MEM_ALIGN uint8_t ep_int_buf[6]; #endif - // Support FIFOs for software encoding and decoding #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING tu_fifo_t * rx_supp_ff; -- cgit v1.3.1 From 6771ef35d9fd61bcddb305dedef7d9f4addf86a5 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 30 Jul 2024 11:17:55 +0700 Subject: more btable set/get clean up --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 54 +++++++++------------------ src/portable/st/stm32_fsdev/fsdev_common.h | 24 +----------- 2 files changed, 19 insertions(+), 59 deletions(-) (limited to 'src') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 927ecac85..fc1627a1c 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -320,12 +320,8 @@ static void dcd_ep_ctr_tx_handler(uint32_t wIstr) { return; } xfer->iso_in_sending = false; - - if (wEPRegVal & USB_EP_DTOG_TX) { - pcd_set_ep_tx_dbuf0_cnt(USB, EPindex, 0); - } else { - pcd_set_ep_tx_dbuf1_cnt(USB, EPindex, 0); - } + uint8_t buf_id = (wEPRegVal & USB_EP_DTOG_TX) ? 0 : 1; + btable_set_count(EPindex, buf_id, 0); } if ((xfer->total_len != xfer->queued_len)) { @@ -406,21 +402,16 @@ static void dcd_ep_ctr_rx_handler(uint32_t wIstr) if (ep_addr != 0u) { pcd_clear_rx_ep_ctr(USB, EPindex); } - uint32_t count; - uint16_t addr; - /* Read from correct register when ISOCHRONOUS (double buffered) */ + + uint8_t buf_id; if ((wEPRegVal & USB_EP_TYPE_MASK) == USB_EP_ISOCHRONOUS) { - if (wEPRegVal & USB_EP_DTOG_RX) { - count = pcd_get_ep_dbuf0_cnt(USB, EPindex); - addr = pcd_get_ep_dbuf0_address(USB, EPindex); - } else { - count = pcd_get_ep_dbuf1_cnt(USB, EPindex); - addr = pcd_get_ep_dbuf1_address(USB, EPindex); - } + // ISO endpoints are double buffered + buf_id = (wEPRegVal & USB_EP_DTOG_RX) ? 0 : 1; } else { - count = pcd_get_ep_rx_cnt(USB, EPindex); - addr = pcd_get_ep_rx_address(USB, EPindex); + buf_id = 1; } + uint32_t count = btable_get_count(EPindex, buf_id); + uint16_t addr = (uint16_t) btable_get_addr(EPindex, buf_id); TU_ASSERT(count <= xfer->max_packet_size, /**/); @@ -630,7 +621,6 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) { uint8_t const dir = tu_edpt_dir(ep_addr); const uint16_t packet_size = tu_edpt_packet_size(desc_ep); const uint16_t buffer_size = pcd_aligned_buffer_size(packet_size); - uint16_t pma_addr; uint32_t wType; TU_ASSERT(ep_idx < FSDEV_EP_COUNT); @@ -658,7 +648,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) { pcd_set_ep_address(USB, ep_idx, tu_edpt_number(ep_addr)); /* Create a packet memory buffer area. */ - pma_addr = dcd_pma_alloc(buffer_size, false); + uint16_t pma_addr = dcd_pma_alloc(buffer_size, false); if (dir == TUSB_DIR_IN) { pcd_set_ep_tx_address(USB, ep_idx, pma_addr); @@ -732,11 +722,9 @@ bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet uint32_t pma_addr = dcd_pma_alloc(buffer_size, true); uint16_t pma_addr2 = pma_addr; #endif - pcd_set_ep_tx_address(USB, ep_idx, pma_addr); - pcd_set_ep_rx_address(USB, ep_idx, pma_addr2); - + btable_set_addr(ep_idx, 0, pma_addr); + btable_set_addr(ep_idx, 1, pma_addr2); pcd_set_eptype(USB, ep_idx, USB_EP_ISOCHRONOUS); - xfer_ctl_ptr(ep_addr)->ep_idx = ep_idx; return true; @@ -770,8 +758,7 @@ bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *p_endpoin } // Currently, single-buffered, and only 64 bytes at a time (max) -static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix) -{ +static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix) { uint16_t len = (uint16_t)(xfer->total_len - xfer->queued_len); if (len > xfer->max_packet_size) { len = xfer->max_packet_size; @@ -779,20 +766,15 @@ static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix) uint16_t ep_reg = pcd_get_endpoint(USB, ep_ix); bool const is_iso = (ep_reg & USB_EP_TYPE_MASK) == USB_EP_ISOCHRONOUS; - uint16_t addr_ptr; + uint8_t buf_id; if (is_iso) { - if (ep_reg & USB_EP_DTOG_TX) { - addr_ptr = pcd_get_ep_dbuf1_address(USB, ep_ix); - pcd_set_ep_tx_dbuf1_cnt(USB, ep_ix, len); - } else { - addr_ptr = pcd_get_ep_dbuf0_address(USB, ep_ix); - pcd_set_ep_tx_dbuf0_cnt(USB, ep_ix, len); - } + buf_id = (ep_reg & USB_EP_DTOG_TX) ? 1 : 0; } else { - addr_ptr = pcd_get_ep_tx_address(USB, ep_ix); - pcd_set_ep_tx_cnt(USB, ep_ix, len); + buf_id = 0; } + uint16_t addr_ptr = (uint16_t) btable_get_addr(ep_ix, buf_id); + btable_set_count(ep_ix, buf_id, len); if (xfer->ff) { dcd_write_packet_memory_ff(xfer->ff, addr_ptr, len); diff --git a/src/portable/st/stm32_fsdev/fsdev_common.h b/src/portable/st/stm32_fsdev/fsdev_common.h index 58a9ed96d..72db609cb 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.h +++ b/src/portable/st/stm32_fsdev/fsdev_common.h @@ -69,7 +69,7 @@ TU_VERIFY_STATIC(FSDEV_BTABLE_BASE % 8 == 0, "BTABLE base must be aligned to 8 b // 16-bit or 32-bit depending on FSDEV_BUS_32BIT. typedef struct { union { - // 0: tx, 1: rx + // 0: TX (IN), 1: RX (OUT) // strictly 16-bit access (could be 32-bit aligned) struct { @@ -239,9 +239,6 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_cnt(USB_TypeDef * USB return btable_get_count(bEpIdx, 1); } -#define pcd_get_ep_dbuf0_cnt pcd_get_ep_tx_cnt -#define pcd_get_ep_dbuf1_cnt pcd_get_ep_rx_cnt - TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_tx_address(USB_TypeDef * USBx, uint32_t bEpIdx) { (void) USBx; return btable_get_addr(bEpIdx, 0); @@ -252,10 +249,6 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_address(USB_TypeDef * return btable_get_addr(bEpIdx, 1); } -#define pcd_get_ep_dbuf0_address pcd_get_ep_tx_address -#define pcd_get_ep_dbuf1_address pcd_get_ep_rx_address - - TU_ATTR_ALWAYS_INLINE static inline void btable_set_addr(uint32_t ep_id, uint8_t is_rx, uint16_t addr) { #ifdef FSDEV_BUS_32BIT uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][is_rx].count_addr; @@ -288,26 +281,11 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_address(USB_TypeDef * USB btable_set_addr(bEpIdx, 1, addr); } -#define pcd_set_ep_dbuf0_address pcd_set_ep_tx_address -#define pcd_set_ep_dbuf1_address pcd_set_ep_rx_address - TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount) { (void) USBx; btable_set_count(bEpIdx, 0, wCount); } -#define pcd_set_ep_tx_dbuf0_cnt pcd_set_ep_tx_cnt - -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_dbuf1_cnt(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount) { -#ifdef FSDEV_BUS_32BIT - (void) USBx; - pma32[2*bEpIdx + 1] = (pma32[2*bEpIdx + 1] & ~0x03FF0000u) | ((wCount & 0x3FFu) << 16); -#else - volatile uint16_t * reg = pcd_ep_rx_cnt_ptr(USBx, bEpIdx); - *reg = (uint16_t) (*reg & (uint16_t) ~0x3FFU) | (wCount & 0x3FFU); -#endif -} - TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_blsize_num_blocks(USB_TypeDef * USBx, uint32_t rxtx_idx, uint32_t blocksize, uint32_t numblocks) { /* Encode into register. When BLSIZE==1, we need to subtract 1 block count */ -- cgit v1.3.1 From 749f0921745ffe3647e6955b41b15e9643f3f3c4 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 30 Jul 2024 12:46:09 +0700 Subject: refactor btable_set_rx_bufsize() --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 23 ++--- src/portable/st/stm32_fsdev/fsdev_common.h | 122 ++++++-------------------- 2 files changed, 41 insertions(+), 104 deletions(-) (limited to 'src') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index fc1627a1c..cd00e6395 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -370,7 +370,7 @@ static void dcd_ep_ctr_rx_handler(uint32_t wIstr) if (wEPRegVal & USB_EP_SETUP) { /* Setup packet */ - uint32_t count = pcd_get_ep_rx_cnt(USB, EPindex); + uint32_t count = btable_get_count(EPindex, BTABLE_BUF_RX); // Setup packet should always be 8 bytes. If not, ignore it, and try again. if (count == 8) { // Must reset EP to NAK (in case it had been stalling) @@ -387,13 +387,14 @@ static void dcd_ep_ctr_rx_handler(uint32_t wIstr) pcd_rx_dtog(USB, 0); } + uint16_t rx_addr = btable_get_addr(EPindex, BTABLE_BUF_RX); #ifdef FSDEV_BUS_32BIT - dcd_event_setup_received(0, (uint8_t *)(USB_PMAADDR + pcd_get_ep_rx_address(USB, EPindex)), true); + dcd_event_setup_received(0, (uint8_t *)(USB_PMAADDR + rx_addr), true); #else // The setup_received function uses memcpy, so this must first copy the setup data into // user memory, to allow for the 32-bit access that memcpy performs. uint8_t userMemBuf[8]; - dcd_read_packet_memory(userMemBuf, pcd_get_ep_rx_address(USB, EPindex), 8); + dcd_read_packet_memory(userMemBuf, rx_addr, 8); dcd_event_setup_received(0, (uint8_t*) userMemBuf, true); #endif } @@ -434,7 +435,7 @@ static void dcd_ep_ctr_rx_handler(uint32_t wIstr) if ((wEPRegVal & USB_EP_TYPE_MASK) != USB_EP_ISOCHRONOUS) { uint16_t remaining = xfer->total_len - xfer->queued_len; uint16_t cnt = tu_min16(remaining, xfer->max_packet_size); - pcd_set_ep_rx_cnt(USB, EPindex, cnt); + btable_set_rx_bufsize(EPindex, BTABLE_BUF_RX, cnt); } pcd_set_ep_rx_status(USB, EPindex, USB_EP_RX_VALID); } @@ -445,7 +446,7 @@ static void dcd_ep_ctr_rx_handler(uint32_t wIstr) // (Based on the docs, it seems SETUP will always be accepted after CTR is cleared) if (ep_addr == 0u) { // Always be prepared for a status packet... - pcd_set_ep_rx_cnt(USB, EPindex, CFG_TUD_ENDPOINT0_SIZE); + btable_set_rx_bufsize(EPindex, BTABLE_BUF_RX, CFG_TUD_ENDPOINT0_SIZE); pcd_clear_rx_ep_ctr(USB, EPindex); } } @@ -651,11 +652,11 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) { uint16_t pma_addr = dcd_pma_alloc(buffer_size, false); if (dir == TUSB_DIR_IN) { - pcd_set_ep_tx_address(USB, ep_idx, pma_addr); + btable_set_addr(ep_idx, BTABLE_BUF_TX, pma_addr); pcd_set_ep_tx_status(USB, ep_idx, USB_EP_TX_NAK); pcd_clear_tx_dtog(USB, ep_idx); } else { - pcd_set_ep_rx_address(USB, ep_idx, pma_addr); + btable_set_addr(ep_idx, BTABLE_BUF_RX, pma_addr); pcd_set_ep_rx_status(USB, ep_idx, USB_EP_RX_NAK); pcd_clear_rx_dtog(USB, ep_idx); } @@ -771,7 +772,7 @@ static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix) { if (is_iso) { buf_id = (ep_reg & USB_EP_DTOG_TX) ? 1 : 0; } else { - buf_id = 0; + buf_id = BTABLE_BUF_TX; } uint16_t addr_ptr = (uint16_t) btable_get_addr(ep_ix, buf_id); btable_set_count(ep_ix, buf_id, len); @@ -806,10 +807,10 @@ static bool edpt_xfer(uint8_t rhport, uint8_t ep_addr) uint16_t ep_reg = pcd_get_endpoint(USB, ep_idx); if ((ep_reg & USB_EP_TYPE_MASK) == USB_EP_ISOCHRONOUS) { - pcd_set_ep_rx_dbuf0_cnt(USB, ep_idx, cnt); - pcd_set_ep_rx_dbuf1_cnt(USB, ep_idx, cnt); + btable_set_rx_bufsize(ep_idx, 0, cnt); + btable_set_rx_bufsize(ep_idx, 1, cnt); } else { - pcd_set_ep_rx_cnt(USB, ep_idx, cnt); + btable_set_rx_bufsize(ep_idx, BTABLE_BUF_RX, cnt); } pcd_set_ep_rx_status(USB, ep_idx, USB_EP_RX_VALID); diff --git a/src/portable/st/stm32_fsdev/fsdev_common.h b/src/portable/st/stm32_fsdev/fsdev_common.h index 72db609cb..05354d705 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.h +++ b/src/portable/st/stm32_fsdev/fsdev_common.h @@ -62,6 +62,11 @@ TU_VERIFY_STATIC(FSDEV_BTABLE_BASE % 8 == 0, "BTABLE base must be aligned to 8 b #define pma_aligned #endif +enum { + BTABLE_BUF_TX = 0, + BTABLE_BUF_RX = 1 +}; + // hardware limit endpoint #define FSDEV_EP_COUNT 8 @@ -105,20 +110,6 @@ static volatile uint32_t * const pma32 = (volatile uint32_t*)USB_PMAADDR; typedef uint16_t fsdev_bus_t; // Volatile is also needed to prevent the optimizer from changing access to 32-bit (as 32-bit access is forbidden) static volatile uint16_t * const pma = (volatile uint16_t*)USB_PMAADDR; - -TU_ATTR_ALWAYS_INLINE static inline volatile uint16_t * pcd_btable_word_ptr(USB_TypeDef * USBx, size_t x) { - size_t total_word_offset = (((USBx)->BTABLE)>>1) + x; - total_word_offset *= FSDEV_PMA_STRIDE; - return &(pma[total_word_offset]); -} - -TU_ATTR_ALWAYS_INLINE static inline volatile uint16_t* pcd_ep_tx_cnt_ptr(USB_TypeDef * USBx, uint32_t bEpIdx) { - return pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 1u); -} - -TU_ATTR_ALWAYS_INLINE static inline volatile uint16_t* pcd_ep_rx_cnt_ptr(USB_TypeDef * USBx, uint32_t bEpIdx) { - return pcd_btable_word_ptr(USBx,(bEpIdx)*4u + 3u); -} #endif /* Aligned buffer size according to hardware */ @@ -205,100 +196,47 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_tx_ep_ctr(USB_TypeDef * USBx, pcd_set_endpoint(USBx, bEpIdx,regVal); } -TU_ATTR_ALWAYS_INLINE static inline uint32_t btable_get_count(uint32_t ep_id, uint8_t is_rx) { +TU_ATTR_ALWAYS_INLINE static inline uint32_t btable_get_count(uint32_t ep_id, uint8_t buf_id) { uint16_t count; #ifdef FSDEV_BUS_32BIT - count = (FSDEV_BTABLE->ep32[ep_id][is_rx].count_addr >> 16); + count = (FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr >> 16); #else - count = FSDEV_BTABLE->ep16[ep_id][is_rx].count; + count = FSDEV_BTABLE->ep16[ep_id][buf_id].count; #endif return count & 0x3FFU; } -TU_ATTR_ALWAYS_INLINE static inline uint32_t btable_get_addr(uint32_t ep_id, uint8_t is_rx) { +TU_ATTR_ALWAYS_INLINE static inline uint32_t btable_get_addr(uint32_t ep_id, uint8_t buf_id) { #ifdef FSDEV_BUS_32BIT - return FSDEV_BTABLE->ep32[ep_id][is_rx].count_addr & 0x0000FFFFu; + return FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr & 0x0000FFFFu; #else - return FSDEV_BTABLE->ep16[ep_id][is_rx].addr; + return FSDEV_BTABLE->ep16[ep_id][buf_id].addr; #endif } -/** - * @brief gets counter of the tx buffer. - * @param USBx USB peripheral instance register address. - * @param bEpIdx Endpoint Number. - * @retval Counter value - */ -TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_tx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx) { - (void) USBx; - return btable_get_count(bEpIdx, 0); -} - -TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx) { - (void) USBx; - return btable_get_count(bEpIdx, 1); -} - -TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_tx_address(USB_TypeDef * USBx, uint32_t bEpIdx) { - (void) USBx; - return btable_get_addr(bEpIdx, 0); -} - -TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_address(USB_TypeDef * USBx, uint32_t bEpIdx) { - (void) USBx; - return btable_get_addr(bEpIdx, 1); -} - -TU_ATTR_ALWAYS_INLINE static inline void btable_set_addr(uint32_t ep_id, uint8_t is_rx, uint16_t addr) { +TU_ATTR_ALWAYS_INLINE static inline void btable_set_addr(uint32_t ep_id, uint8_t buf_id, uint16_t addr) { #ifdef FSDEV_BUS_32BIT - uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][is_rx].count_addr; + uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr; count_addr = (count_addr & 0xFFFF0000u) | (addr & 0x0000FFFCu); - FSDEV_BTABLE->ep32[ep_id][is_rx].count_addr = count_addr; + FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr = count_addr; #else - FSDEV_BTABLE->ep16[ep_id][is_rx].addr = addr; + FSDEV_BTABLE->ep16[ep_id][buf_id].addr = addr; #endif } -TU_ATTR_ALWAYS_INLINE static inline void btable_set_count(uint32_t ep_id, uint8_t is_rx, uint16_t byte_count) { +TU_ATTR_ALWAYS_INLINE static inline void btable_set_count(uint32_t ep_id, uint8_t buf_id, uint16_t byte_count) { #ifdef FSDEV_BUS_32BIT - uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][is_rx].count_addr; + uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr; count_addr = (count_addr & ~0x03FF0000u) | ((byte_count & 0x3FFu) << 16); - FSDEV_BTABLE->ep32[ep_id][is_rx].count_addr = count_addr; + FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr = count_addr; #else - uint16_t cnt = FSDEV_BTABLE->ep16[ep_id][is_rx].count; + uint16_t cnt = FSDEV_BTABLE->ep16[ep_id][buf_id].count; cnt = (cnt & ~0x3FFU) | (byte_count & 0x3FFU); - FSDEV_BTABLE->ep16[ep_id][is_rx].count = cnt; + FSDEV_BTABLE->ep16[ep_id][buf_id].count = cnt; #endif } -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_address(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t addr) { - (void) USBx; - btable_set_addr(bEpIdx, 0, addr); -} - -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_address(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t addr) { - (void) USBx; - btable_set_addr(bEpIdx, 1, addr); -} - -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount) { - (void) USBx; - btable_set_count(bEpIdx, 0, wCount); -} - -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_blsize_num_blocks(USB_TypeDef * USBx, uint32_t rxtx_idx, - uint32_t blocksize, uint32_t numblocks) { - /* Encode into register. When BLSIZE==1, we need to subtract 1 block count */ -#ifdef FSDEV_BUS_32BIT - (void) USBx; - pma32[rxtx_idx] = (pma32[rxtx_idx] & 0x0000FFFFu) | (blocksize << 31) | ((numblocks - blocksize) << 26); -#else - volatile uint16_t *pdwReg = pcd_btable_word_ptr(USBx, rxtx_idx*2u + 1u); - *pdwReg = (blocksize << 15) | ((numblocks - blocksize) << 10); -#endif -} - -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_bufsize(USB_TypeDef * USBx, uint32_t rxtx_idx, uint32_t wCount) { +TU_ATTR_ALWAYS_INLINE static inline void btable_set_rx_bufsize(uint32_t ep_id, uint8_t buf_id, uint32_t wCount) { wCount = pcd_aligned_buffer_size(wCount); /* We assume that the buffer size is already aligned to hardware requirements. */ @@ -309,19 +247,17 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_bufsize(USB_TypeDef * USBx, TU_ASSERT((wCount - (numblocks * (blocksize ? 32 : 2))) == 0, /**/); /* Encode into register. When BLSIZE==1, we need to subtract 1 block count */ - pcd_set_ep_blsize_num_blocks(USBx, rxtx_idx, blocksize, numblocks); -} + uint16_t bl_nb = (blocksize << 15) | ((numblocks - blocksize) << 10); -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_dbuf0_cnt(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount) { - pcd_set_ep_bufsize(USBx, 2*bEpIdx, wCount); -} - -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_cnt(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wCount) { - pcd_set_ep_bufsize(USBx, 2*bEpIdx + 1, wCount); +#ifdef FSDEV_BUS_32BIT + uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr; + count_addr = (bl_nb << 16) | (count_addr & 0x0000FFFFu); + FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr = count_addr; +#else + FSDEV_BTABLE->ep16[ep_id][buf_id].count = bl_nb; +#endif } -#define pcd_set_ep_rx_dbuf1_cnt pcd_set_ep_rx_cnt - /** * @brief sets the status for tx transfer (bits STAT_TX[1:0]). * @param USBx USB peripheral instance register address. -- cgit v1.3.1 From b15814b2f9579ef126b2ad30b6fff0e338ead3ef Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 30 Jul 2024 16:29:54 +0700 Subject: move align buffer to pma_alloc() --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 32 +++--- src/portable/st/stm32_fsdev/fsdev_common.h | 140 +++++++++++++------------- 2 files changed, 85 insertions(+), 87 deletions(-) (limited to 'src') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index cd00e6395..2be6ef031 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -170,7 +170,7 @@ static void dcd_ep_ctr_handler(void); // PMA allocation/access static uint16_t ep_buf_ptr; ///< Points to first free memory location -static uint32_t dcd_pma_alloc(uint16_t length, bool dbuf); +static uint32_t dcd_pma_alloc(uint16_t len, bool dbuf); static uint8_t dcd_ep_alloc(uint8_t ep_addr, uint8_t ep_type); static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t wNBytes); static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t wNBytes); @@ -551,21 +551,19 @@ void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const *req * In case of double buffering, high 16bit is the address of 2nd buffer * During failure, TU_ASSERT is used. If this happens, rework/reallocate memory manually. */ -static uint32_t dcd_pma_alloc(uint16_t length, bool dbuf) +static uint32_t dcd_pma_alloc(uint16_t len, bool dbuf) { - // Ensure allocated buffer is aligned -#ifdef FSDEV_BUS_32BIT - length = (length + 3) & ~0x03; -#else - length = (length + 1) & ~0x01; -#endif + uint8_t blsize, num_block; + uint16_t aligned_len = pma_align_buffer_size(len, &blsize, &num_block); + (void) blsize; + (void) num_block; uint32_t addr = ep_buf_ptr; - ep_buf_ptr = (uint16_t)(ep_buf_ptr + length); // increment buffer pointer + ep_buf_ptr = (uint16_t)(ep_buf_ptr + aligned_len); // increment buffer pointer if (dbuf) { addr |= ((uint32_t)ep_buf_ptr) << 16; - ep_buf_ptr = (uint16_t)(ep_buf_ptr + length); // increment buffer pointer + ep_buf_ptr = (uint16_t)(ep_buf_ptr + aligned_len); // increment buffer pointer } // Verify packet buffer is not overflowed @@ -621,11 +619,9 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) { uint8_t const ep_idx = dcd_ep_alloc(ep_addr, desc_ep->bmAttributes.xfer); uint8_t const dir = tu_edpt_dir(ep_addr); const uint16_t packet_size = tu_edpt_packet_size(desc_ep); - const uint16_t buffer_size = pcd_aligned_buffer_size(packet_size); uint32_t wType; TU_ASSERT(ep_idx < FSDEV_EP_COUNT); - TU_ASSERT(buffer_size <= 64); // Set type switch (desc_ep->bmAttributes.xfer) { @@ -649,7 +645,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) { pcd_set_ep_address(USB, ep_idx, tu_edpt_number(ep_addr)); /* Create a packet memory buffer area. */ - uint16_t pma_addr = dcd_pma_alloc(buffer_size, false); + uint16_t pma_addr = dcd_pma_alloc(packet_size, false); if (dir == TUSB_DIR_IN) { btable_set_addr(ep_idx, BTABLE_BUF_TX, pma_addr); @@ -707,22 +703,20 @@ void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) } } -bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) -{ +bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { (void)rhport; uint8_t const ep_idx = dcd_ep_alloc(ep_addr, TUSB_XFER_ISOCHRONOUS); - const uint16_t buffer_size = pcd_aligned_buffer_size(largest_packet_size); /* Create a packet memory buffer area. Enable double buffering for devices with 2048 bytes PMA, for smaller devices double buffering occupy too much space. */ + uint32_t pma_addr = dcd_pma_alloc(largest_packet_size, true); #if FSDEV_PMA_SIZE > 1024u - uint32_t pma_addr = dcd_pma_alloc(buffer_size, true); uint16_t pma_addr2 = pma_addr >> 16; #else - uint32_t pma_addr = dcd_pma_alloc(buffer_size, true); uint16_t pma_addr2 = pma_addr; #endif + btable_set_addr(ep_idx, 0, pma_addr); btable_set_addr(ep_idx, 1, pma_addr2); pcd_set_eptype(USB, ep_idx, USB_EP_ISOCHRONOUS); @@ -803,7 +797,7 @@ static bool edpt_xfer(uint8_t rhport, uint8_t ep_addr) if (dir == TUSB_DIR_IN) { dcd_transmit_packet(xfer, ep_idx); } else { - uint32_t cnt = (uint32_t ) tu_min16(xfer->total_len, xfer->max_packet_size); + uint32_t cnt = (uint32_t) tu_min16(xfer->total_len, xfer->max_packet_size); uint16_t ep_reg = pcd_get_endpoint(USB, ep_idx); if ((ep_reg & USB_EP_TYPE_MASK) == USB_EP_ISOCHRONOUS) { diff --git a/src/portable/st/stm32_fsdev/fsdev_common.h b/src/portable/st/stm32_fsdev/fsdev_common.h index 05354d705..c8d259cfa 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.h +++ b/src/portable/st/stm32_fsdev/fsdev_common.h @@ -96,7 +96,7 @@ TU_VERIFY_STATIC(FSDEV_BTABLE_BASE + FSDEV_EP_COUNT*8 <= FSDEV_PMA_SIZE, "BTABLE #define FSDEV_BTABLE ((volatile fsdev_btable_t*) (USB_PMAADDR+FSDEV_BTABLE_BASE)) //--------------------------------------------------------------------+ -// Helper +// BTable //--------------------------------------------------------------------+ // The fsdev_bus_t type can be used for both register and PMA access necessities @@ -112,18 +112,84 @@ typedef uint16_t fsdev_bus_t; static volatile uint16_t * const pma = (volatile uint16_t*)USB_PMAADDR; #endif +TU_ATTR_ALWAYS_INLINE static inline uint32_t btable_get_addr(uint32_t ep_id, uint8_t buf_id) { +#ifdef FSDEV_BUS_32BIT + return FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr & 0x0000FFFFu; +#else + return FSDEV_BTABLE->ep16[ep_id][buf_id].addr; +#endif +} + +TU_ATTR_ALWAYS_INLINE static inline void btable_set_addr(uint32_t ep_id, uint8_t buf_id, uint16_t addr) { +#ifdef FSDEV_BUS_32BIT + uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr; + count_addr = (count_addr & 0xFFFF0000u) | (addr & 0x0000FFFCu); + FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr = count_addr; +#else + FSDEV_BTABLE->ep16[ep_id][buf_id].addr = addr; +#endif +} + +TU_ATTR_ALWAYS_INLINE static inline uint32_t btable_get_count(uint32_t ep_id, uint8_t buf_id) { + uint16_t count; +#ifdef FSDEV_BUS_32BIT + count = (FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr >> 16); +#else + count = FSDEV_BTABLE->ep16[ep_id][buf_id].count; +#endif + return count & 0x3FFU; +} + +TU_ATTR_ALWAYS_INLINE static inline void btable_set_count(uint32_t ep_id, uint8_t buf_id, uint16_t byte_count) { +#ifdef FSDEV_BUS_32BIT + uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr; + count_addr = (count_addr & ~0x03FF0000u) | ((byte_count & 0x3FFu) << 16); + FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr = count_addr; +#else + uint16_t cnt = FSDEV_BTABLE->ep16[ep_id][buf_id].count; + cnt = (cnt & ~0x3FFU) | (byte_count & 0x3FFU); + FSDEV_BTABLE->ep16[ep_id][buf_id].count = cnt; +#endif +} + /* Aligned buffer size according to hardware */ -TU_ATTR_ALWAYS_INLINE static inline uint16_t pcd_aligned_buffer_size(uint16_t size) { +TU_ATTR_ALWAYS_INLINE static inline uint16_t pma_align_buffer_size(uint16_t size, uint8_t* blsize, uint8_t* num_block) { /* The STM32 full speed USB peripheral supports only a limited set of * buffer sizes given by the RX buffer entry format in the USB_BTABLE. */ - uint16_t blocksize = (size > 62) ? 32 : 2; + uint16_t block_in_bytes; + if (size > 62) { + block_in_bytes = 32; + *blsize = 1; + } else { + block_in_bytes = 2; + *blsize = 0; + } + + *num_block = tu_div_ceil(size, block_in_bytes); - // Round up while dividing requested size by blocksize - uint16_t numblocks = (size + blocksize - 1) / blocksize ; + return (*num_block) * block_in_bytes; +} + +TU_ATTR_ALWAYS_INLINE static inline void btable_set_rx_bufsize(uint32_t ep_id, uint8_t buf_id, uint32_t wCount) { + uint8_t blsize, num_block; + (void) pma_align_buffer_size(wCount, &blsize, &num_block); - return numblocks * blocksize; + /* Encode into register. When BLSIZE==1, we need to subtract 1 block count */ + uint16_t bl_nb = (blsize << 15) | ((num_block - blsize) << 10); + +#ifdef FSDEV_BUS_32BIT + uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr; + count_addr = (bl_nb << 16) | (count_addr & 0x0000FFFFu); + FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr = count_addr; +#else + FSDEV_BTABLE->ep16[ep_id][buf_id].count = bl_nb; +#endif } +//--------------------------------------------------------------------+ +// Endpoint +//--------------------------------------------------------------------+ + TU_ATTR_ALWAYS_INLINE static inline void pcd_set_endpoint(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wRegValue) { #ifdef FSDEV_BUS_32BIT (void) USBx; @@ -196,68 +262,6 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_tx_ep_ctr(USB_TypeDef * USBx, pcd_set_endpoint(USBx, bEpIdx,regVal); } -TU_ATTR_ALWAYS_INLINE static inline uint32_t btable_get_count(uint32_t ep_id, uint8_t buf_id) { - uint16_t count; -#ifdef FSDEV_BUS_32BIT - count = (FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr >> 16); -#else - count = FSDEV_BTABLE->ep16[ep_id][buf_id].count; -#endif - return count & 0x3FFU; -} - -TU_ATTR_ALWAYS_INLINE static inline uint32_t btable_get_addr(uint32_t ep_id, uint8_t buf_id) { -#ifdef FSDEV_BUS_32BIT - return FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr & 0x0000FFFFu; -#else - return FSDEV_BTABLE->ep16[ep_id][buf_id].addr; -#endif -} - -TU_ATTR_ALWAYS_INLINE static inline void btable_set_addr(uint32_t ep_id, uint8_t buf_id, uint16_t addr) { -#ifdef FSDEV_BUS_32BIT - uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr; - count_addr = (count_addr & 0xFFFF0000u) | (addr & 0x0000FFFCu); - FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr = count_addr; -#else - FSDEV_BTABLE->ep16[ep_id][buf_id].addr = addr; -#endif -} - -TU_ATTR_ALWAYS_INLINE static inline void btable_set_count(uint32_t ep_id, uint8_t buf_id, uint16_t byte_count) { -#ifdef FSDEV_BUS_32BIT - uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr; - count_addr = (count_addr & ~0x03FF0000u) | ((byte_count & 0x3FFu) << 16); - FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr = count_addr; -#else - uint16_t cnt = FSDEV_BTABLE->ep16[ep_id][buf_id].count; - cnt = (cnt & ~0x3FFU) | (byte_count & 0x3FFU); - FSDEV_BTABLE->ep16[ep_id][buf_id].count = cnt; -#endif -} - -TU_ATTR_ALWAYS_INLINE static inline void btable_set_rx_bufsize(uint32_t ep_id, uint8_t buf_id, uint32_t wCount) { - wCount = pcd_aligned_buffer_size(wCount); - - /* We assume that the buffer size is already aligned to hardware requirements. */ - uint16_t blocksize = (wCount > 62) ? 1 : 0; - uint16_t numblocks = wCount / (blocksize ? 32 : 2); - - /* There should be no remainder in the above calculation */ - TU_ASSERT((wCount - (numblocks * (blocksize ? 32 : 2))) == 0, /**/); - - /* Encode into register. When BLSIZE==1, we need to subtract 1 block count */ - uint16_t bl_nb = (blocksize << 15) | ((numblocks - blocksize) << 10); - -#ifdef FSDEV_BUS_32BIT - uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr; - count_addr = (bl_nb << 16) | (count_addr & 0x0000FFFFu); - FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr = count_addr; -#else - FSDEV_BTABLE->ep16[ep_id][buf_id].count = bl_nb; -#endif -} - /** * @brief sets the status for tx transfer (bits STAT_TX[1:0]). * @param USBx USB peripheral instance register address. -- cgit v1.3.1 From 1cf8e34ae5fc6466d07ac438691391c7a5a809ff Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 30 Jul 2024 20:32:26 +0700 Subject: improve set endpoint --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 41 +++++----- src/portable/st/stm32_fsdev/fsdev_ch32.h | 35 ++++----- src/portable/st/stm32_fsdev/fsdev_common.h | 104 +++++++++++++++++--------- src/portable/st/stm32_fsdev/fsdev_stm32.h | 17 +++++ 4 files changed, 125 insertions(+), 72 deletions(-) (limited to 'src') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 2be6ef031..6007b4a02 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -616,24 +616,24 @@ static uint8_t dcd_ep_alloc(uint8_t ep_addr, uint8_t ep_type) bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) { (void)rhport; uint8_t const ep_addr = desc_ep->bEndpointAddress; - uint8_t const ep_idx = dcd_ep_alloc(ep_addr, desc_ep->bmAttributes.xfer); uint8_t const dir = tu_edpt_dir(ep_addr); const uint16_t packet_size = tu_edpt_packet_size(desc_ep); - uint32_t wType; - + uint8_t const ep_idx = dcd_ep_alloc(ep_addr, desc_ep->bmAttributes.xfer); TU_ASSERT(ep_idx < FSDEV_EP_COUNT); + uint32_t ep_reg = FSDEV_REG->ep[ep_idx].reg & ~USB_EPREG_MASK; + ep_reg |= tu_edpt_number(ep_addr) | USB_EP_CTR_RX | USB_EP_CTR_TX; + // Set type switch (desc_ep->bmAttributes.xfer) { case TUSB_XFER_CONTROL: - wType = USB_EP_CONTROL; + ep_reg |= USB_EP_CONTROL; break; case TUSB_XFER_BULK: - wType = USB_EP_CONTROL; + ep_reg |= USB_EP_CONTROL; // FIXME should it be bulk? break; - case TUSB_XFER_INTERRUPT: - wType = USB_EP_INTERRUPT; + ep_reg |= USB_EP_INTERRUPT; break; default: @@ -641,24 +641,23 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) { TU_ASSERT(false); } - pcd_set_eptype(USB, ep_idx, wType); - pcd_set_ep_address(USB, ep_idx, tu_edpt_number(ep_addr)); - /* Create a packet memory buffer area. */ uint16_t pma_addr = dcd_pma_alloc(packet_size, false); + btable_set_addr(ep_idx, dir == TUSB_DIR_IN ? BTABLE_BUF_TX : BTABLE_BUF_RX, pma_addr); + + xfer_ctl_ptr(ep_addr)->max_packet_size = packet_size; + xfer_ctl_ptr(ep_addr)->ep_idx = ep_idx; if (dir == TUSB_DIR_IN) { - btable_set_addr(ep_idx, BTABLE_BUF_TX, pma_addr); - pcd_set_ep_tx_status(USB, ep_idx, USB_EP_TX_NAK); - pcd_clear_tx_dtog(USB, ep_idx); + ep_reg = ep_add_tx_status(ep_reg, USB_EP_TX_NAK); + ep_reg = ep_add_tx_dtog(ep_reg, 0); + ep_reg &= ~(USB_EPRX_STAT | USB_EP_DTOG_RX); } else { - btable_set_addr(ep_idx, BTABLE_BUF_RX, pma_addr); - pcd_set_ep_rx_status(USB, ep_idx, USB_EP_RX_NAK); - pcd_clear_rx_dtog(USB, ep_idx); + ep_reg = ep_add_rx_status(ep_reg, USB_EP_RX_NAK); + ep_reg = ep_add_rx_dtog(ep_reg, 0); + ep_reg &= ~(USB_EPTX_STAT | USB_EP_DTOG_TX); } - - xfer_ctl_ptr(ep_addr)->max_packet_size = packet_size; - xfer_ctl_ptr(ep_addr)->ep_idx = ep_idx; + pcd_set_endpoint(USB, ep_idx, ep_reg); return true; } @@ -731,7 +730,8 @@ bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *p_endpoin uint8_t const ep_addr = p_endpoint_desc->bEndpointAddress; uint8_t const ep_idx = xfer_ctl_ptr(ep_addr)->ep_idx; uint8_t const dir = tu_edpt_dir(ep_addr); - const uint16_t packet_size = tu_edpt_packet_size(p_endpoint_desc); + + xfer_ctl_ptr(ep_addr)->max_packet_size = tu_edpt_packet_size(p_endpoint_desc); pcd_set_ep_tx_status(USB, ep_idx, USB_EP_TX_DIS); pcd_set_ep_rx_status(USB, ep_idx, USB_EP_RX_DIS); @@ -747,7 +747,6 @@ bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *p_endpoin pcd_tx_dtog(USB, ep_idx); } - xfer_ctl_ptr(ep_addr)->max_packet_size = packet_size; return true; } diff --git a/src/portable/st/stm32_fsdev/fsdev_ch32.h b/src/portable/st/stm32_fsdev/fsdev_ch32.h index f63a80d56..81ef08b8a 100644 --- a/src/portable/st/stm32_fsdev/fsdev_ch32.h +++ b/src/portable/st/stm32_fsdev/fsdev_ch32.h @@ -55,28 +55,29 @@ #define FSDEV_PMA_SIZE (512u) +#if 1 // volatile 32-bit aligned -#define _va32 volatile TU_ATTR_ALIGNED(4) +#define _vaa32 volatile TU_ATTR_ALIGNED(4) typedef struct { - _va32 uint16_t EP0R; // 00: USB Endpoint 0 register - _va32 uint16_t EP1R; // 04: USB Endpoint 1 register - _va32 uint16_t EP2R; // 08: USB Endpoint 2 register - _va32 uint16_t EP3R; // 0C: USB Endpoint 3 register - _va32 uint16_t EP4R; // 10: USB Endpoint 4 register - _va32 uint16_t EP5R; // 14: USB Endpoint 5 register - _va32 uint16_t EP6R; // 18: USB Endpoint 6 register - _va32 uint16_t EP7R; // 1C: USB Endpoint 7 register - _va32 uint16_t RESERVED7[16]; // Reserved - _va32 uint16_t CNTR; // 40: Control register - _va32 uint16_t ISTR; // 44: Interrupt status register - _va32 uint16_t FNR; // 48: Frame number register - _va32 uint16_t DADDR; // 4C: Device address register - _va32 uint16_t BTABLE; // 50: Buffer Table address register + _vaa32 uint16_t EP0R; // 00: USB Endpoint 0 register + _vaa32 uint16_t EP1R; // 04: USB Endpoint 1 register + _vaa32 uint16_t EP2R; // 08: USB Endpoint 2 register + _vaa32 uint16_t EP3R; // 0C: USB Endpoint 3 register + _vaa32 uint16_t EP4R; // 10: USB Endpoint 4 register + _vaa32 uint16_t EP5R; // 14: USB Endpoint 5 register + _vaa32 uint16_t EP6R; // 18: USB Endpoint 6 register + _vaa32 uint16_t EP7R; // 1C: USB Endpoint 7 register + _vaa32 uint16_t RESERVED7[16]; // Reserved + _vaa32 uint16_t CNTR; // 40: Control register + _vaa32 uint16_t ISTR; // 44: Interrupt status register + _vaa32 uint16_t FNR; // 48: Frame number register + _vaa32 uint16_t DADDR; // 4C: Device address register + _vaa32 uint16_t BTABLE; // 50: Buffer Table address register } USB_TypeDef; +#endif -TU_VERIFY_STATIC(sizeof(USB_TypeDef) == 0x54, "Size is not correct"); -TU_VERIFY_STATIC(offsetof(USB_TypeDef, CNTR) == 0x40, "Wrong offset"); +#define FSDEV_REG_BASE 0x40005C00UL #define USB_BASE (APB1PERIPH_BASE + 0x00005C00UL) /*!< USB_IP Peripheral Registers base address */ #define USB_PMAADDR (APB1PERIPH_BASE + 0x00006000UL) /*!< USB_IP Packet Memory Area base address */ diff --git a/src/portable/st/stm32_fsdev/fsdev_common.h b/src/portable/st/stm32_fsdev/fsdev_common.h index c8d259cfa..3d1e1fe4a 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.h +++ b/src/portable/st/stm32_fsdev/fsdev_common.h @@ -95,9 +95,8 @@ TU_VERIFY_STATIC(FSDEV_BTABLE_BASE + FSDEV_EP_COUNT*8 <= FSDEV_PMA_SIZE, "BTABLE #define FSDEV_BTABLE ((volatile fsdev_btable_t*) (USB_PMAADDR+FSDEV_BTABLE_BASE)) -//--------------------------------------------------------------------+ -// BTable -//--------------------------------------------------------------------+ +// volatile 32-bit aligned +#define _va32 volatile TU_ATTR_ALIGNED(4) // The fsdev_bus_t type can be used for both register and PMA access necessities // For type-safety create a new macro for the volatile address of PMAADDR @@ -112,6 +111,39 @@ typedef uint16_t fsdev_bus_t; static volatile uint16_t * const pma = (volatile uint16_t*)USB_PMAADDR; #endif +typedef struct { +// _va32 fsdev_bus_t EP0R; // 00: USB Endpoint 0 register +// _va32 fsdev_bus_t EP1R; // 04: USB Endpoint 1 register +// _va32 fsdev_bus_t EP2R; // 08: USB Endpoint 2 register +// _va32 fsdev_bus_t EP3R; // 0C: USB Endpoint 3 register +// _va32 fsdev_bus_t EP4R; // 10: USB Endpoint 4 register +// _va32 fsdev_bus_t EP5R; // 14: USB Endpoint 5 register +// _va32 fsdev_bus_t EP6R; // 18: USB Endpoint 6 register +// _va32 fsdev_bus_t EP7R; // 1C: USB Endpoint 7 register + struct { + _va32 fsdev_bus_t reg; + }ep[FSDEV_EP_COUNT]; + + _va32 uint32_t RESERVED7[8]; // Reserved + _va32 fsdev_bus_t CNTR; // 40: Control register + _va32 fsdev_bus_t ISTR; // 44: Interrupt status register + _va32 fsdev_bus_t FNR; // 48: Frame number register + _va32 fsdev_bus_t DADDR; // 4C: Device address register + _va32 fsdev_bus_t BTABLE; // 50: Buffer Table address register (16-bit only) + _va32 fsdev_bus_t LPMCSR; // 54: LPM Control and Status Register (32-bit only) + _va32 fsdev_bus_t BCDR; // 58: Battery Charging Detector Register (32-bit only) +} fsdev_regs_t; + +TU_VERIFY_STATIC(offsetof(fsdev_regs_t, CNTR) == 0x40, "Wrong offset"); +TU_VERIFY_STATIC(sizeof(fsdev_regs_t) == 0x5C, "Size is not correct"); + +#define FSDEV_REG ((fsdev_regs_t*) FSDEV_REG_BASE) + + +//--------------------------------------------------------------------+ +// BTable +//--------------------------------------------------------------------+ + TU_ATTR_ALWAYS_INLINE static inline uint32_t btable_get_addr(uint32_t ep_id, uint8_t buf_id) { #ifdef FSDEV_BUS_32BIT return FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr & 0x0000FFFFu; @@ -191,24 +223,13 @@ TU_ATTR_ALWAYS_INLINE static inline void btable_set_rx_bufsize(uint32_t ep_id, u //--------------------------------------------------------------------+ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_endpoint(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wRegValue) { -#ifdef FSDEV_BUS_32BIT (void) USBx; - volatile uint32_t *reg = (volatile uint32_t *)(USB_DRD_BASE + bEpIdx*4); - *reg = wRegValue; -#else - volatile uint16_t *reg = (volatile uint16_t *)((&USBx->EP0R) + bEpIdx*2u); - *reg = (uint16_t)wRegValue; -#endif + FSDEV_REG->ep[bEpIdx].reg = (fsdev_bus_t) wRegValue; } TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_endpoint(USB_TypeDef * USBx, uint32_t bEpIdx) { -#ifdef FSDEV_BUS_32BIT (void) USBx; - volatile const uint32_t *reg = (volatile const uint32_t *)(USB_DRD_BASE + bEpIdx*4); -#else - volatile const uint16_t *reg = (volatile const uint16_t *)((&USBx->EP0R) + bEpIdx*2u); -#endif - return *reg; + return FSDEV_REG->ep[bEpIdx].reg; } /** @@ -262,6 +283,21 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_tx_ep_ctr(USB_TypeDef * USBx, pcd_set_endpoint(USBx, bEpIdx,regVal); } +TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_add_tx_status(uint32_t reg, uint32_t state) { + return reg | ((reg ^ state) & USB_EPTX_STAT); +} +TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_add_rx_status(uint32_t reg, uint32_t state) { + return reg | ((reg ^ state) & USB_EPRX_STAT); +} + +TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_add_tx_dtog(uint32_t reg, uint32_t state) { + return reg | ((reg ^ state) & USB_EP_DTOG_TX); +} + +TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_add_rx_dtog(uint32_t reg, uint32_t state) { + return reg | ((reg ^ state) & USB_EP_DTOG_RX); +} + /** * @brief sets the status for tx transfer (bits STAT_TX[1:0]). * @param USBx USB peripheral instance register address. @@ -293,10 +329,10 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_status(USB_TypeDef * USBx pcd_set_endpoint(USBx, bEpIdx, regVal); } -TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_status(USB_TypeDef * USBx, uint32_t bEpIdx) { - uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); - return (regVal & USB_EPRX_STAT) >> (12u); -} +//TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_status(USB_TypeDef * USBx, uint32_t bEpIdx) { +// uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); +// return (regVal & USB_EPRX_STAT) >> (12u); +//} TU_ATTR_ALWAYS_INLINE static inline void pcd_rx_dtog(USB_TypeDef * USBx, uint32_t bEpIdx) { uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); @@ -326,20 +362,20 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_tx_dtog(USB_TypeDef * USBx, } } -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_kind(USB_TypeDef * USBx, uint32_t bEpIdx) { - uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); - regVal |= USB_EP_KIND; - regVal &= USB_EPREG_MASK; - regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX; - pcd_set_endpoint(USBx, bEpIdx, regVal); -} - -TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_ep_kind(USB_TypeDef * USBx, uint32_t bEpIdx) { - uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); - regVal &= USB_EPKIND_MASK; - regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX; - pcd_set_endpoint(USBx, bEpIdx, regVal); -} +//TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_kind(USB_TypeDef * USBx, uint32_t bEpIdx) { +// uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); +// regVal |= USB_EP_KIND; +// regVal &= USB_EPREG_MASK; +// regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX; +// pcd_set_endpoint(USBx, bEpIdx, regVal); +//} +// +//TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_ep_kind(USB_TypeDef * USBx, uint32_t bEpIdx) { +// uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); +// regVal &= USB_EPKIND_MASK; +// regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX; +// pcd_set_endpoint(USBx, bEpIdx, regVal); +//} #ifdef __cplusplus } diff --git a/src/portable/st/stm32_fsdev/fsdev_stm32.h b/src/portable/st/stm32_fsdev/fsdev_stm32.h index a8f61a35f..f89882e0d 100644 --- a/src/portable/st/stm32_fsdev/fsdev_stm32.h +++ b/src/portable/st/stm32_fsdev/fsdev_stm32.h @@ -35,6 +35,7 @@ #if CFG_TUSB_MCU == OPT_MCU_STM32F0 #include "stm32f0xx.h" #define FSDEV_PMA_SIZE (1024u) + #define FSDEV_REG_BASE USB_BASE // F0x2 models are crystal-less // All have internal D+ pull-up // 070RB: 2 x 16 bits/word memory LPM Support, BCD Support @@ -193,6 +194,22 @@ // This includes U0 #endif +#if defined(USB_BASE) + #define FSDEV_REG_BASE USB_BASE +#elif defined(USB_DRD_BASE) + #define FSDEV_REG_BASE USB_DRD_BASE +#else + #error "FSDEV_REG_BASE not defined" +#endif + +#ifndef USB_EPTX_STAT +#define USB_EPTX_STAT 0x0030U +#endif + +#ifndef USB_EPRX_STAT +#define USB_EPRX_STAT 0x3000U +#endif + // This checks if the device has "LPM" #if defined(USB_ISTR_L1REQ) #define USB_ISTR_L1REQ_FORCED (USB_ISTR_L1REQ) -- cgit v1.3.1 From f4aaad6869db74a4fba6eeb716d20be85978a311 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 30 Jul 2024 21:35:24 +0700 Subject: add edpt0_open(), slightly update dtog --- src/device/dcd.h | 2 +- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 74 +++++++++++++++------------ src/portable/st/stm32_fsdev/fsdev_common.h | 30 +++++++---- src/portable/st/stm32_fsdev/fsdev_stm32.h | 8 --- 4 files changed, 62 insertions(+), 52 deletions(-) (limited to 'src') diff --git a/src/device/dcd.h b/src/device/dcd.h index b25b47025..41e0fbee3 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -180,7 +180,7 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr); TU_ATTR_WEAK bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size); // Configure and enable an ISO endpoint according to descriptor -TU_ATTR_WEAK bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc); +TU_ATTR_WEAK bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep); //--------------------------------------------------------------------+ // Event API (implemented by stack) diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 6007b4a02..834de6998 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -178,6 +178,8 @@ static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t static bool dcd_write_packet_memory_ff(tu_fifo_t *ff, uint16_t dst, uint16_t wNBytes); static bool dcd_read_packet_memory_ff(tu_fifo_t *ff, uint16_t src, uint16_t wNBytes); +TU_ATTR_UNUSED static void edpt0_open(uint8_t rhport); + //--------------------------------------------------------------------+ // Inline helper //--------------------------------------------------------------------+ @@ -277,19 +279,7 @@ static void handle_bus_reset(uint8_t rhport) { // Reset PMA allocation ep_buf_ptr = FSDEV_BTABLE_BASE + 8 * FSDEV_EP_COUNT; - tusb_desc_endpoint_t ep0_desc = { - .bLength = sizeof(tusb_desc_endpoint_t), - .bDescriptorType = TUSB_DESC_ENDPOINT, - .bEndpointAddress = 0x00, - .bmAttributes = {.xfer = TUSB_XFER_CONTROL}, - .wMaxPacketSize = CFG_TUD_ENDPOINT0_SIZE, - .bInterval = 0 - }; - - dcd_edpt_open(rhport, &ep0_desc); - - ep0_desc.bEndpointAddress = 0x80; - dcd_edpt_open(rhport, &ep0_desc); + edpt0_open(rhport); // open control endpoint (both IN & OUT) USB->DADDR = USB_DADDR_EF; // Enable USB Function } @@ -610,8 +600,32 @@ static uint8_t dcd_ep_alloc(uint8_t ep_addr, uint8_t ep_type) TU_ASSERT(0); } -// The STM32F0 doesn't seem to like |= or &= to manipulate the EP#R registers, -// so I'm using the #define from HAL here, instead. +void edpt0_open(uint8_t rhport) { + (void) rhport; + + dcd_ep_alloc(0x0, TUSB_XFER_CONTROL); + dcd_ep_alloc(0x80, TUSB_XFER_CONTROL); + + xfer_status[0][0].max_packet_size = CFG_TUD_ENDPOINT0_SIZE; + xfer_status[0][0].ep_idx = 0; + + xfer_status[0][1].max_packet_size = CFG_TUD_ENDPOINT0_SIZE; + xfer_status[0][1].ep_idx = 0; + + uint16_t pma_addr0 = dcd_pma_alloc(CFG_TUD_ENDPOINT0_SIZE, false); + uint16_t pma_addr1 = dcd_pma_alloc(CFG_TUD_ENDPOINT0_SIZE, false); + + btable_set_addr(0, BTABLE_BUF_RX, pma_addr0); + btable_set_addr(0, BTABLE_BUF_TX, pma_addr1); + + uint32_t ep_reg = FSDEV_REG->ep[0].reg & ~USB_EPREG_MASK; + ep_reg |= USB_EP_CONTROL | USB_EP_CTR_RX | USB_EP_CTR_TX; + ep_reg = ep_add_tx_status(ep_reg, USB_EP_TX_NAK); + ep_reg = ep_add_rx_status(ep_reg, USB_EP_RX_NAK); + // no need to explicitly set DTOG bits since we aren't masked DTOG bit + + pcd_set_endpoint(USB, 0, ep_reg); +} bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) { (void)rhport; @@ -626,9 +640,6 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) { // Set type switch (desc_ep->bmAttributes.xfer) { - case TUSB_XFER_CONTROL: - ep_reg |= USB_EP_CONTROL; - break; case TUSB_XFER_BULK: ep_reg |= USB_EP_CONTROL; // FIXME should it be bulk? break; @@ -718,35 +729,34 @@ bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet btable_set_addr(ep_idx, 0, pma_addr); btable_set_addr(ep_idx, 1, pma_addr2); - pcd_set_eptype(USB, ep_idx, USB_EP_ISOCHRONOUS); xfer_ctl_ptr(ep_addr)->ep_idx = ep_idx; + pcd_set_eptype(USB, ep_idx, USB_EP_ISOCHRONOUS); + return true; } -bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *p_endpoint_desc) -{ +bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) { (void)rhport; - uint8_t const ep_addr = p_endpoint_desc->bEndpointAddress; + uint8_t const ep_addr = desc_ep->bEndpointAddress; uint8_t const ep_idx = xfer_ctl_ptr(ep_addr)->ep_idx; uint8_t const dir = tu_edpt_dir(ep_addr); - xfer_ctl_ptr(ep_addr)->max_packet_size = tu_edpt_packet_size(p_endpoint_desc); - - pcd_set_ep_tx_status(USB, ep_idx, USB_EP_TX_DIS); - pcd_set_ep_rx_status(USB, ep_idx, USB_EP_RX_DIS); + xfer_ctl_ptr(ep_addr)->max_packet_size = tu_edpt_packet_size(desc_ep); - pcd_set_ep_address(USB, ep_idx, tu_edpt_number(ep_addr)); - - pcd_clear_tx_dtog(USB, ep_idx); - pcd_clear_rx_dtog(USB, ep_idx); + uint32_t ep_reg = FSDEV_REG->ep[0].reg & ~USB_EPREG_MASK; + ep_reg |= tu_edpt_number(ep_addr) | USB_EP_ISOCHRONOUS | USB_EP_CTR_RX | USB_EP_CTR_TX; + ep_reg = ep_add_tx_status(ep_reg, USB_EP_TX_DIS); + ep_reg = ep_add_rx_status(ep_reg, USB_EP_RX_DIS); + // no need to explicitly set DTOG bits since we aren't masked DTOG bit if (dir == TUSB_DIR_IN) { - pcd_rx_dtog(USB, ep_idx); + ep_reg = ep_add_rx_dtog(ep_reg, 1); } else { - pcd_tx_dtog(USB, ep_idx); + ep_reg = ep_add_tx_dtog(ep_reg, 1); } + pcd_set_endpoint(USB, ep_idx, ep_reg); return true; } diff --git a/src/portable/st/stm32_fsdev/fsdev_common.h b/src/portable/st/stm32_fsdev/fsdev_common.h index 3d1e1fe4a..53b2af0a2 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.h +++ b/src/portable/st/stm32_fsdev/fsdev_common.h @@ -112,14 +112,6 @@ static volatile uint16_t * const pma = (volatile uint16_t*)USB_PMAADDR; #endif typedef struct { -// _va32 fsdev_bus_t EP0R; // 00: USB Endpoint 0 register -// _va32 fsdev_bus_t EP1R; // 04: USB Endpoint 1 register -// _va32 fsdev_bus_t EP2R; // 08: USB Endpoint 2 register -// _va32 fsdev_bus_t EP3R; // 0C: USB Endpoint 3 register -// _va32 fsdev_bus_t EP4R; // 10: USB Endpoint 4 register -// _va32 fsdev_bus_t EP5R; // 14: USB Endpoint 5 register -// _va32 fsdev_bus_t EP6R; // 18: USB Endpoint 6 register -// _va32 fsdev_bus_t EP7R; // 1C: USB Endpoint 7 register struct { _va32 fsdev_bus_t reg; }ep[FSDEV_EP_COUNT]; @@ -140,6 +132,22 @@ TU_VERIFY_STATIC(sizeof(fsdev_regs_t) == 0x5C, "Size is not correct"); #define FSDEV_REG ((fsdev_regs_t*) FSDEV_REG_BASE) +#ifndef USB_EPTX_STAT +#define USB_EPTX_STAT 0x0030U +#endif + +#ifndef USB_EPRX_STAT +#define USB_EPRX_STAT 0x3000U +#endif + +#ifndef USB_EP_DTOG_TX_Pos +#define USB_EP_DTOG_TX_Pos (6U) +#endif + +#ifndef USB_EP_DTOG_RX_Pos +#define USB_EP_DTOG_RX_Pos (14U) +#endif + //--------------------------------------------------------------------+ // BTable //--------------------------------------------------------------------+ @@ -244,7 +252,7 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_address(USB_TypeDef * USBx, regVal &= USB_EPREG_MASK; regVal |= bAddr; regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX; - pcd_set_endpoint(USBx, bEpIdx,regVal); + pcd_set_endpoint(USBx, bEpIdx, regVal); } TU_ATTR_ALWAYS_INLINE static inline void pcd_set_eptype(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wType) { @@ -291,11 +299,11 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_add_rx_status(uint32_t reg, uint } TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_add_tx_dtog(uint32_t reg, uint32_t state) { - return reg | ((reg ^ state) & USB_EP_DTOG_TX); + return reg | ((reg ^ (state << USB_EP_DTOG_TX_Pos)) & USB_EP_DTOG_TX); } TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_add_rx_dtog(uint32_t reg, uint32_t state) { - return reg | ((reg ^ state) & USB_EP_DTOG_RX); + return reg | ((reg ^ (state << USB_EP_DTOG_RX_Pos)) & USB_EP_DTOG_RX); } /** diff --git a/src/portable/st/stm32_fsdev/fsdev_stm32.h b/src/portable/st/stm32_fsdev/fsdev_stm32.h index f89882e0d..f20505f28 100644 --- a/src/portable/st/stm32_fsdev/fsdev_stm32.h +++ b/src/portable/st/stm32_fsdev/fsdev_stm32.h @@ -202,14 +202,6 @@ #error "FSDEV_REG_BASE not defined" #endif -#ifndef USB_EPTX_STAT -#define USB_EPTX_STAT 0x0030U -#endif - -#ifndef USB_EPRX_STAT -#define USB_EPRX_STAT 0x3000U -#endif - // This checks if the device has "LPM" #if defined(USB_ISTR_L1REQ) #define USB_ISTR_L1REQ_FORCED (USB_ISTR_L1REQ) -- cgit v1.3.1 From 0c8d41e25ec3f691f3125f634659f52d084e8995 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 31 Jul 2024 09:46:31 +0700 Subject: correct ep toggle bit --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 32 +++++++++------------------ src/portable/st/stm32_fsdev/fsdev_common.h | 8 +++---- 2 files changed, 15 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 834de6998..5cba9ca40 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -350,8 +350,6 @@ static void dcd_ep_ctr_rx_handler(uint32_t wIstr) uint32_t wEPRegVal = pcd_get_endpoint(USB, EPindex); uint8_t ep_addr = wEPRegVal & USB_EPADDR_FIELD; - xfer_ctl_t *xfer = xfer_ctl_ptr(ep_addr); - // Verify the CTR_RX bit is set. This was in the ST Micro code, // but I'm not sure it's actually necessary? if ((wEPRegVal & USB_EP_CTR_RX) == 0U) { @@ -359,34 +357,26 @@ static void dcd_ep_ctr_rx_handler(uint32_t wIstr) } if (wEPRegVal & USB_EP_SETUP) { - /* Setup packet */ uint32_t count = btable_get_count(EPindex, BTABLE_BUF_RX); // Setup packet should always be 8 bytes. If not, ignore it, and try again. if (count == 8) { - // Must reset EP to NAK (in case it had been stalling) - pcd_set_ep_rx_status(USB, 0u, USB_EP_RX_NAK); - pcd_set_ep_tx_status(USB, 0u, USB_EP_TX_NAK); - - // set both data toggle to 1 - uint32_t regVal = pcd_get_endpoint(USB, 0); - if ((regVal & USB_EP_DTOG_TX) == 0) { - pcd_tx_dtog(USB, 0); - } - - if ((regVal & USB_EP_DTOG_RX) == 0) { - pcd_rx_dtog(USB, 0); - } - uint16_t rx_addr = btable_get_addr(EPindex, BTABLE_BUF_RX); #ifdef FSDEV_BUS_32BIT dcd_event_setup_received(0, (uint8_t *)(USB_PMAADDR + rx_addr), true); #else // The setup_received function uses memcpy, so this must first copy the setup data into // user memory, to allow for the 32-bit access that memcpy performs. - uint8_t userMemBuf[8]; + uint32_t userMemBuf[2]; dcd_read_packet_memory(userMemBuf, rx_addr, 8); dcd_event_setup_received(0, (uint8_t*) userMemBuf, true); #endif + + // Reset EP to NAK (in case it had been stalling) + wEPRegVal = ep_add_tx_status(wEPRegVal, USB_EP_TX_NAK); + wEPRegVal = ep_add_rx_status(wEPRegVal, USB_EP_RX_NAK); + wEPRegVal = ep_add_tx_dtog(wEPRegVal, 1); + wEPRegVal = ep_add_rx_dtog(wEPRegVal, 1); + pcd_set_endpoint(USB, 0, wEPRegVal | USB_EP_CTR_RX | USB_EP_CTR_TX); } } else { // Clear RX CTR interrupt flag @@ -394,6 +384,8 @@ static void dcd_ep_ctr_rx_handler(uint32_t wIstr) pcd_clear_rx_ep_ctr(USB, EPindex); } + xfer_ctl_t *xfer = xfer_ctl_ptr(ep_addr); + uint8_t buf_id; if ((wEPRegVal & USB_EP_TYPE_MASK) == USB_EP_ISOCHRONOUS) { // ISO endpoints are double buffered @@ -404,13 +396,11 @@ static void dcd_ep_ctr_rx_handler(uint32_t wIstr) uint32_t count = btable_get_count(EPindex, buf_id); uint16_t addr = (uint16_t) btable_get_addr(EPindex, buf_id); - TU_ASSERT(count <= xfer->max_packet_size, /**/); - if (count != 0U) { if (xfer->ff) { dcd_read_packet_memory_ff(xfer->ff, addr, count); } else { - dcd_read_packet_memory(&(xfer->buffer[xfer->queued_len]), addr, count); + dcd_read_packet_memory(xfer->buffer + xfer->queued_len, addr, count); } xfer->queued_len = (uint16_t)(xfer->queued_len + count); diff --git a/src/portable/st/stm32_fsdev/fsdev_common.h b/src/portable/st/stm32_fsdev/fsdev_common.h index 53b2af0a2..09bf4c2ca 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.h +++ b/src/portable/st/stm32_fsdev/fsdev_common.h @@ -292,18 +292,18 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_tx_ep_ctr(USB_TypeDef * USBx, } TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_add_tx_status(uint32_t reg, uint32_t state) { - return reg | ((reg ^ state) & USB_EPTX_STAT); + return reg ^ state; } TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_add_rx_status(uint32_t reg, uint32_t state) { - return reg | ((reg ^ state) & USB_EPRX_STAT); + return reg ^ state; } TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_add_tx_dtog(uint32_t reg, uint32_t state) { - return reg | ((reg ^ (state << USB_EP_DTOG_TX_Pos)) & USB_EP_DTOG_TX); + return reg ^ (state << USB_EP_DTOG_TX_Pos); } TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_add_rx_dtog(uint32_t reg, uint32_t state) { - return reg | ((reg ^ (state << USB_EP_DTOG_RX_Pos)) & USB_EP_DTOG_RX); + return reg ^ (state << USB_EP_DTOG_RX_Pos); } /** -- cgit v1.3.1 From 126778298e6ab23f2117b60d479d31e4de7d276f Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 31 Jul 2024 11:35:09 +0700 Subject: enhance dcd_ep_ctr_rx_handler() --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 128 ++++++++++++-------------- 1 file changed, 58 insertions(+), 70 deletions(-) (limited to 'src') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 5cba9ca40..c7a25ba5e 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -178,7 +178,7 @@ static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t static bool dcd_write_packet_memory_ff(tu_fifo_t *ff, uint16_t dst, uint16_t wNBytes); static bool dcd_read_packet_memory_ff(tu_fifo_t *ff, uint16_t src, uint16_t wNBytes); -TU_ATTR_UNUSED static void edpt0_open(uint8_t rhport); +static void edpt0_open(uint8_t rhport); //--------------------------------------------------------------------+ // Inline helper @@ -285,10 +285,8 @@ static void handle_bus_reset(uint8_t rhport) { } // Handle CTR interrupt for the TX/IN direction -// Upon call, (wIstr & USB_ISTR_DIR) == 0U -static void dcd_ep_ctr_tx_handler(uint32_t wIstr) { - uint32_t EPindex = wIstr & USB_ISTR_EP_ID; - uint32_t wEPRegVal = pcd_get_endpoint(USB, EPindex); +static void dcd_ep_ctr_tx_handler(uint32_t ep_id) { + uint32_t wEPRegVal = pcd_get_endpoint(USB, ep_id); uint8_t ep_addr = (wEPRegVal & USB_EPADDR_FIELD) | TUSB_DIR_IN_MASK; // Verify the CTR_TX bit is set. This was in the ST Micro code, @@ -298,7 +296,7 @@ static void dcd_ep_ctr_tx_handler(uint32_t wIstr) { } /* clear int flag */ - pcd_clear_tx_ep_ctr(USB, EPindex); + pcd_clear_tx_ep_ctr(USB, ep_id); xfer_ctl_t *xfer = xfer_ctl_ptr(ep_addr); @@ -311,20 +309,18 @@ static void dcd_ep_ctr_tx_handler(uint32_t wIstr) { } xfer->iso_in_sending = false; uint8_t buf_id = (wEPRegVal & USB_EP_DTOG_TX) ? 0 : 1; - btable_set_count(EPindex, buf_id, 0); + btable_set_count(ep_id, buf_id, 0); } if ((xfer->total_len != xfer->queued_len)) { - dcd_transmit_packet(xfer, EPindex); + dcd_transmit_packet(xfer, ep_id); } else { dcd_event_xfer_complete(0, ep_addr, xfer->total_len, XFER_RESULT_SUCCESS, true); } } // Handle CTR interrupt for the RX/OUT direction -// Upon call, (wIstr & USB_ISTR_DIR) == 0U -static void dcd_ep_ctr_rx_handler(uint32_t wIstr) -{ +static void dcd_ep_ctr_rx_handler(uint32_t ep_id) { #ifdef FSDEV_BUS_32BIT /* https://www.st.com/resource/en/errata_sheet/es0561-stm32h503cbebkbrb-device-errata-stmicroelectronics.pdf * From STM32H503 errata 2.15.1: Buffer description table update completes after CTR interrupt triggers @@ -346,103 +342,92 @@ static void dcd_ep_ctr_rx_handler(uint32_t wIstr) } #endif - uint32_t EPindex = wIstr & USB_ISTR_EP_ID; - uint32_t wEPRegVal = pcd_get_endpoint(USB, EPindex); - uint8_t ep_addr = wEPRegVal & USB_EPADDR_FIELD; + uint32_t ep_reg = pcd_get_endpoint(USB, ep_id); + uint8_t ep_addr = ep_reg & USB_EPADDR_FIELD; // Verify the CTR_RX bit is set. This was in the ST Micro code, // but I'm not sure it's actually necessary? - if ((wEPRegVal & USB_EP_CTR_RX) == 0U) { + if ((ep_reg & USB_EP_CTR_RX) == 0U) { return; } - if (wEPRegVal & USB_EP_SETUP) { - uint32_t count = btable_get_count(EPindex, BTABLE_BUF_RX); + // Clear RX CTR and reserved TX CTR + ep_reg = (ep_reg & ~USB_EP_CTR_RX) | USB_EP_CTR_TX; + + if (ep_reg & USB_EP_SETUP) { + uint32_t count = btable_get_count(ep_id, BTABLE_BUF_RX); // Setup packet should always be 8 bytes. If not, ignore it, and try again. if (count == 8) { - uint16_t rx_addr = btable_get_addr(EPindex, BTABLE_BUF_RX); -#ifdef FSDEV_BUS_32BIT - dcd_event_setup_received(0, (uint8_t *)(USB_PMAADDR + rx_addr), true); -#else - // The setup_received function uses memcpy, so this must first copy the setup data into - // user memory, to allow for the 32-bit access that memcpy performs. - uint32_t userMemBuf[2]; - dcd_read_packet_memory(userMemBuf, rx_addr, 8); - dcd_event_setup_received(0, (uint8_t*) userMemBuf, true); -#endif + uint16_t rx_addr = btable_get_addr(ep_id, BTABLE_BUF_RX); + uint32_t setup_packet[2]; + dcd_read_packet_memory(setup_packet, rx_addr, 8); + dcd_event_setup_received(0, (uint8_t*) setup_packet, true); // Reset EP to NAK (in case it had been stalling) - wEPRegVal = ep_add_tx_status(wEPRegVal, USB_EP_TX_NAK); - wEPRegVal = ep_add_rx_status(wEPRegVal, USB_EP_RX_NAK); - wEPRegVal = ep_add_tx_dtog(wEPRegVal, 1); - wEPRegVal = ep_add_rx_dtog(wEPRegVal, 1); - pcd_set_endpoint(USB, 0, wEPRegVal | USB_EP_CTR_RX | USB_EP_CTR_TX); + ep_reg = ep_add_tx_status(ep_reg, USB_EP_TX_NAK); + ep_reg = ep_add_rx_status(ep_reg, USB_EP_RX_NAK); + ep_reg = ep_add_tx_dtog(ep_reg, 1); + ep_reg = ep_add_rx_dtog(ep_reg, 1); + } else { + ep_reg &= USB_EPREG_MASK; // reversed all toggle } } else { - // Clear RX CTR interrupt flag - if (ep_addr != 0u) { - pcd_clear_rx_ep_ctr(USB, EPindex); - } + ep_reg &= USB_EPRX_STAT | USB_EPREG_MASK; // reversed all toggle except RX Status + bool const is_iso = (ep_reg & USB_EP_TYPE_MASK) == USB_EP_ISOCHRONOUS; xfer_ctl_t *xfer = xfer_ctl_ptr(ep_addr); uint8_t buf_id; - if ((wEPRegVal & USB_EP_TYPE_MASK) == USB_EP_ISOCHRONOUS) { - // ISO endpoints are double buffered - buf_id = (wEPRegVal & USB_EP_DTOG_RX) ? 0 : 1; + if (is_iso) { + buf_id = (ep_reg & USB_EP_DTOG_RX) ? 0 : 1; // ISO are double buffered } else { - buf_id = 1; + buf_id = BTABLE_BUF_RX; } - uint32_t count = btable_get_count(EPindex, buf_id); - uint16_t addr = (uint16_t) btable_get_addr(EPindex, buf_id); + uint32_t rx_count = btable_get_count(ep_id, buf_id); + uint16_t pma_addr = (uint16_t) btable_get_addr(ep_id, buf_id); - if (count != 0U) { + if (rx_count != 0) { if (xfer->ff) { - dcd_read_packet_memory_ff(xfer->ff, addr, count); + dcd_read_packet_memory_ff(xfer->ff, pma_addr, rx_count); } else { - dcd_read_packet_memory(xfer->buffer + xfer->queued_len, addr, count); + dcd_read_packet_memory(xfer->buffer + xfer->queued_len, pma_addr, rx_count); } - xfer->queued_len = (uint16_t)(xfer->queued_len + count); + xfer->queued_len = (uint16_t)(xfer->queued_len + rx_count); } - if ((count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) { + if ((rx_count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) { // all bytes received or short packet dcd_event_xfer_complete(0, ep_addr, xfer->queued_len, XFER_RESULT_SUCCESS, true); + + if (ep_addr == 0u) { + // prepared for status packet + btable_set_rx_bufsize(ep_id, BTABLE_BUF_RX, CFG_TUD_ENDPOINT0_SIZE); + } + + ep_reg = ep_add_rx_status(ep_reg, USB_EP_RX_NAK); } else { - /* Set endpoint active again for receiving more data. - * Note that isochronous endpoints stay active always */ - if ((wEPRegVal & USB_EP_TYPE_MASK) != USB_EP_ISOCHRONOUS) { - uint16_t remaining = xfer->total_len - xfer->queued_len; - uint16_t cnt = tu_min16(remaining, xfer->max_packet_size); - btable_set_rx_bufsize(EPindex, BTABLE_BUF_RX, cnt); + // Set endpoint active again for receiving more data. Note that isochronous endpoints stay active always + if (!is_iso) { + uint16_t const cnt = tu_min16(xfer->total_len - xfer->queued_len, xfer->max_packet_size); + btable_set_rx_bufsize(ep_id, BTABLE_BUF_RX, cnt); } - pcd_set_ep_rx_status(USB, EPindex, USB_EP_RX_VALID); + ep_reg = ep_add_rx_status(ep_reg, USB_EP_RX_VALID); } } - // For EP0, prepare to receive another SETUP packet. - // Clear CTR last so that a new packet does not overwrite the packing being read. - // (Based on the docs, it seems SETUP will always be accepted after CTR is cleared) - if (ep_addr == 0u) { - // Always be prepared for a status packet... - btable_set_rx_bufsize(EPindex, BTABLE_BUF_RX, CFG_TUD_ENDPOINT0_SIZE); - pcd_clear_rx_ep_ctr(USB, EPindex); - } + pcd_set_endpoint(USB, ep_id, ep_reg); } -static void dcd_ep_ctr_handler(void) -{ +static void dcd_ep_ctr_handler(void) { uint32_t wIstr; - /* stay in loop while pending interrupts */ while (((wIstr = USB->ISTR) & USB_ISTR_CTR) != 0U) { + uint32_t ep_id = wIstr & USB_ISTR_EP_ID; if ((wIstr & USB_ISTR_DIR) == 0U) { - /* TX/IN */ - dcd_ep_ctr_tx_handler(wIstr); + dcd_ep_ctr_tx_handler(ep_id); // TX/IN } else { - /* RX/OUT*/ - dcd_ep_ctr_rx_handler(wIstr); + dcd_ep_ctr_rx_handler(ep_id); // RX/OUT } } } @@ -609,11 +594,14 @@ void edpt0_open(uint8_t rhport) { btable_set_addr(0, BTABLE_BUF_TX, pma_addr1); uint32_t ep_reg = FSDEV_REG->ep[0].reg & ~USB_EPREG_MASK; - ep_reg |= USB_EP_CONTROL | USB_EP_CTR_RX | USB_EP_CTR_TX; + ep_reg |= USB_EP_CONTROL; // | USB_EP_CTR_RX | USB_EP_CTR_TX; ep_reg = ep_add_tx_status(ep_reg, USB_EP_TX_NAK); ep_reg = ep_add_rx_status(ep_reg, USB_EP_RX_NAK); // no need to explicitly set DTOG bits since we aren't masked DTOG bit + // prepare for setup packet + btable_set_rx_bufsize(0, BTABLE_BUF_RX, CFG_TUD_ENDPOINT0_SIZE); + pcd_set_endpoint(USB, 0, ep_reg); } -- cgit v1.3.1 From e60efec6b71701946677440629437bedbd5bef9b Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 31 Jul 2024 12:09:50 +0700 Subject: improve using ep_add_status/ep_add_dtog --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 68 +++++++++------------------ src/portable/st/stm32_fsdev/fsdev_common.h | 26 +++++----- 2 files changed, 37 insertions(+), 57 deletions(-) (limited to 'src') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index c7a25ba5e..c1d550ea8 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -364,10 +364,11 @@ static void dcd_ep_ctr_rx_handler(uint32_t ep_id) { dcd_event_setup_received(0, (uint8_t*) setup_packet, true); // Reset EP to NAK (in case it had been stalling) - ep_reg = ep_add_tx_status(ep_reg, USB_EP_TX_NAK); - ep_reg = ep_add_rx_status(ep_reg, USB_EP_RX_NAK); - ep_reg = ep_add_tx_dtog(ep_reg, 1); - ep_reg = ep_add_rx_dtog(ep_reg, 1); + ep_reg = ep_add_status(ep_reg, TUSB_DIR_IN, EP_STAT_NAK); + ep_reg = ep_add_status(ep_reg, TUSB_DIR_OUT, EP_STAT_NAK); + + ep_reg = ep_add_dtog(ep_reg, TUSB_DIR_IN, 1); + ep_reg = ep_add_dtog(ep_reg, TUSB_DIR_OUT, 1); } else { ep_reg &= USB_EPREG_MASK; // reversed all toggle } @@ -404,15 +405,14 @@ static void dcd_ep_ctr_rx_handler(uint32_t ep_id) { // prepared for status packet btable_set_rx_bufsize(ep_id, BTABLE_BUF_RX, CFG_TUD_ENDPOINT0_SIZE); } - - ep_reg = ep_add_rx_status(ep_reg, USB_EP_RX_NAK); + ep_reg = ep_add_status(ep_reg, TUSB_DIR_OUT, EP_STAT_NAK); } else { // Set endpoint active again for receiving more data. Note that isochronous endpoints stay active always if (!is_iso) { uint16_t const cnt = tu_min16(xfer->total_len - xfer->queued_len, xfer->max_packet_size); btable_set_rx_bufsize(ep_id, BTABLE_BUF_RX, cnt); } - ep_reg = ep_add_rx_status(ep_reg, USB_EP_RX_VALID); + ep_reg = ep_add_status(ep_reg, TUSB_DIR_OUT, EP_STAT_VALID); } } @@ -594,9 +594,9 @@ void edpt0_open(uint8_t rhport) { btable_set_addr(0, BTABLE_BUF_TX, pma_addr1); uint32_t ep_reg = FSDEV_REG->ep[0].reg & ~USB_EPREG_MASK; - ep_reg |= USB_EP_CONTROL; // | USB_EP_CTR_RX | USB_EP_CTR_TX; - ep_reg = ep_add_tx_status(ep_reg, USB_EP_TX_NAK); - ep_reg = ep_add_rx_status(ep_reg, USB_EP_RX_NAK); + ep_reg |= USB_EP_CONTROL; + ep_reg = ep_add_status(ep_reg, TUSB_DIR_IN, EP_STAT_NAK); + ep_reg = ep_add_status(ep_reg, TUSB_DIR_OUT, EP_STAT_NAK); // no need to explicitly set DTOG bits since we aren't masked DTOG bit // prepare for setup packet @@ -637,15 +637,16 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) { xfer_ctl_ptr(ep_addr)->max_packet_size = packet_size; xfer_ctl_ptr(ep_addr)->ep_idx = ep_idx; + ep_reg = ep_add_status(ep_reg, dir, EP_STAT_NAK); + ep_reg = ep_add_dtog(ep_reg, dir, 0); + + // reserve other direction toggle bits if (dir == TUSB_DIR_IN) { - ep_reg = ep_add_tx_status(ep_reg, USB_EP_TX_NAK); - ep_reg = ep_add_tx_dtog(ep_reg, 0); ep_reg &= ~(USB_EPRX_STAT | USB_EP_DTOG_RX); } else { - ep_reg = ep_add_rx_status(ep_reg, USB_EP_RX_NAK); - ep_reg = ep_add_rx_dtog(ep_reg, 0); ep_reg &= ~(USB_EPTX_STAT | USB_EP_DTOG_TX); } + pcd_set_endpoint(USB, ep_idx, ep_reg); return true; @@ -669,28 +670,6 @@ void dcd_edpt_close_all(uint8_t rhport) ep_buf_ptr = FSDEV_BTABLE_BASE + 8 * CFG_TUD_ENDPPOINT_MAX + 2 * CFG_TUD_ENDPOINT0_SIZE; } -/** - * Close an endpoint. - * - * This function may be called with interrupts enabled or disabled. - * - * This also clears transfers in progress, should there be any. - */ -void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) -{ - (void)rhport; - - xfer_ctl_t *xfer = xfer_ctl_ptr(ep_addr); - uint8_t const ep_idx = xfer->ep_idx; - uint8_t const dir = tu_edpt_dir(ep_addr); - - if (dir == TUSB_DIR_IN) { - pcd_set_ep_tx_status(USB, ep_idx, USB_EP_TX_DIS); - } else { - pcd_set_ep_rx_status(USB, ep_idx, USB_EP_RX_DIS); - } -} - bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { (void)rhport; @@ -724,15 +703,11 @@ bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) uint32_t ep_reg = FSDEV_REG->ep[0].reg & ~USB_EPREG_MASK; ep_reg |= tu_edpt_number(ep_addr) | USB_EP_ISOCHRONOUS | USB_EP_CTR_RX | USB_EP_CTR_TX; - ep_reg = ep_add_tx_status(ep_reg, USB_EP_TX_DIS); - ep_reg = ep_add_rx_status(ep_reg, USB_EP_RX_DIS); + ep_reg = ep_add_status(ep_reg, TUSB_DIR_IN, EP_STAT_DISABLED); + ep_reg = ep_add_status(ep_reg, TUSB_DIR_OUT, EP_STAT_DISABLED); - // no need to explicitly set DTOG bits since we aren't masked DTOG bit - if (dir == TUSB_DIR_IN) { - ep_reg = ep_add_rx_dtog(ep_reg, 1); - } else { - ep_reg = ep_add_tx_dtog(ep_reg, 1); - } + ep_add_dtog(ep_reg, dir, 0); + ep_add_dtog(ep_reg, 1-dir, 1); pcd_set_endpoint(USB, ep_idx, ep_reg); @@ -838,14 +813,15 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) } } -void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) -{ +void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { (void)rhport; xfer_ctl_t *xfer = xfer_ctl_ptr(ep_addr); uint8_t const ep_idx = xfer->ep_idx; uint8_t const dir = tu_edpt_dir(ep_addr); +// uint32_t ep_reg = pcd_get_endpoint(USB, ep_idx); + if (dir == TUSB_DIR_IN) { // IN if (pcd_get_eptype(USB, ep_idx) != USB_EP_ISOCHRONOUS) { pcd_set_ep_tx_status(USB, ep_idx, USB_EP_TX_NAK); diff --git a/src/portable/st/stm32_fsdev/fsdev_common.h b/src/portable/st/stm32_fsdev/fsdev_common.h index 09bf4c2ca..676596c73 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.h +++ b/src/portable/st/stm32_fsdev/fsdev_common.h @@ -140,6 +140,10 @@ TU_VERIFY_STATIC(sizeof(fsdev_regs_t) == 0x5C, "Size is not correct"); #define USB_EPRX_STAT 0x3000U #endif +#ifndef USB_EPTX_STAT_Pos +#define USB_EPTX_STAT_Pos (4U) +#endif + #ifndef USB_EP_DTOG_TX_Pos #define USB_EP_DTOG_TX_Pos (6U) #endif @@ -148,6 +152,13 @@ TU_VERIFY_STATIC(sizeof(fsdev_regs_t) == 0x5C, "Size is not correct"); #define USB_EP_DTOG_RX_Pos (14U) #endif +typedef enum { + EP_STAT_DISABLED = 0, + EP_STAT_STALL = 1, + EP_STAT_NAK = 2, + EP_STAT_VALID = 3 +}ep_stat_t; + //--------------------------------------------------------------------+ // BTable //--------------------------------------------------------------------+ @@ -291,19 +302,12 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_tx_ep_ctr(USB_TypeDef * USBx, pcd_set_endpoint(USBx, bEpIdx,regVal); } -TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_add_tx_status(uint32_t reg, uint32_t state) { - return reg ^ state; -} -TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_add_rx_status(uint32_t reg, uint32_t state) { - return reg ^ state; -} - -TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_add_tx_dtog(uint32_t reg, uint32_t state) { - return reg ^ (state << USB_EP_DTOG_TX_Pos); +TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_add_status(uint32_t reg, tusb_dir_t dir, ep_stat_t state) { + return reg ^ (state << (USB_EPTX_STAT_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); } -TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_add_rx_dtog(uint32_t reg, uint32_t state) { - return reg ^ (state << USB_EP_DTOG_RX_Pos); +TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_add_dtog(uint32_t reg, tusb_dir_t dir, uint8_t state) { + return reg ^ (state << (USB_EP_DTOG_TX_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); } /** -- cgit v1.3.1 From 76cc721e8f508a02f6d4f5a1f27b24ffb9a63b7b Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 31 Jul 2024 12:44:02 +0700 Subject: clean up dcd_edpt_stall/clear_statll --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 53 ++++++++----------- src/portable/st/stm32_fsdev/fsdev_common.h | 75 +++------------------------ 2 files changed, 28 insertions(+), 100 deletions(-) (limited to 'src') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index c1d550ea8..1d3d8cd96 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -375,7 +375,7 @@ static void dcd_ep_ctr_rx_handler(uint32_t ep_id) { } else { ep_reg &= USB_EPRX_STAT | USB_EPREG_MASK; // reversed all toggle except RX Status - bool const is_iso = (ep_reg & USB_EP_TYPE_MASK) == USB_EP_ISOCHRONOUS; + bool const is_iso = ep_is_iso(ep_reg); xfer_ctl_t *xfer = xfer_ctl_ptr(ep_addr); uint8_t buf_id; @@ -748,9 +748,8 @@ static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix) { dcd_int_enable(0); } -static bool edpt_xfer(uint8_t rhport, uint8_t ep_addr) -{ - (void)rhport; +static bool edpt_xfer(uint8_t rhport, uint8_t ep_addr) { + (void) rhport; xfer_ctl_t *xfer = xfer_ctl_ptr(ep_addr); uint8_t const ep_idx = xfer->ep_idx; @@ -762,7 +761,7 @@ static bool edpt_xfer(uint8_t rhport, uint8_t ep_addr) uint32_t cnt = (uint32_t) tu_min16(xfer->total_len, xfer->max_packet_size); uint16_t ep_reg = pcd_get_endpoint(USB, ep_idx); - if ((ep_reg & USB_EP_TYPE_MASK) == USB_EP_ISOCHRONOUS) { + if (ep_is_iso(ep_reg)) { btable_set_rx_bufsize(ep_idx, 0, cnt); btable_set_rx_bufsize(ep_idx, 1, cnt); } else { @@ -775,10 +774,8 @@ static bool edpt_xfer(uint8_t rhport, uint8_t ep_addr) return true; } -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) -{ +bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) { xfer_ctl_t *xfer = xfer_ctl_ptr(ep_addr); - xfer->buffer = buffer; xfer->ff = NULL; xfer->total_len = total_bytes; @@ -787,8 +784,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to return edpt_xfer(rhport, ep_addr); } -bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t *ff, uint16_t total_bytes) -{ +bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t *ff, uint16_t total_bytes) { xfer_ctl_t *xfer = xfer_ctl_ptr(ep_addr); xfer->buffer = NULL; xfer->ff = ff; @@ -798,19 +794,19 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t *ff, uint16_t return edpt_xfer(rhport, ep_addr); } -void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) -{ +void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { (void)rhport; xfer_ctl_t *xfer = xfer_ctl_ptr(ep_addr); uint8_t const ep_idx = xfer->ep_idx; uint8_t const dir = tu_edpt_dir(ep_addr); - if (dir == TUSB_DIR_IN) { - pcd_set_ep_tx_status(USB, ep_idx, USB_EP_TX_STALL); - } else { - pcd_set_ep_rx_status(USB, ep_idx, USB_EP_RX_STALL); - } + uint32_t ep_reg = pcd_get_endpoint(USB, ep_idx); + ep_reg |= USB_EP_CTR_RX | USB_EP_CTR_TX; // reserve CTR bits + ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(dir); + ep_reg = ep_add_status(ep_reg, dir, EP_STAT_STALL); + + pcd_set_endpoint(USB, ep_idx, ep_reg); } void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { @@ -819,23 +815,16 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { xfer_ctl_t *xfer = xfer_ctl_ptr(ep_addr); uint8_t const ep_idx = xfer->ep_idx; uint8_t const dir = tu_edpt_dir(ep_addr); + uint32_t ep_reg = pcd_get_endpoint(USB, ep_idx); + ep_reg |= USB_EP_CTR_RX | USB_EP_CTR_TX; // reserve CTR bits + ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(dir) | EP_DTOG_MASK(dir); -// uint32_t ep_reg = pcd_get_endpoint(USB, ep_idx); - - if (dir == TUSB_DIR_IN) { // IN - if (pcd_get_eptype(USB, ep_idx) != USB_EP_ISOCHRONOUS) { - pcd_set_ep_tx_status(USB, ep_idx, USB_EP_TX_NAK); - } - - /* Reset to DATA0 if clearing stall condition. */ - pcd_clear_tx_dtog(USB, ep_idx); - } else { // OUT - if (pcd_get_eptype(USB, ep_idx) != USB_EP_ISOCHRONOUS) { - pcd_set_ep_rx_status(USB, ep_idx, USB_EP_RX_NAK); - } - /* Reset to DATA0 if clearing stall condition. */ - pcd_clear_rx_dtog(USB, ep_idx); + if (!ep_is_iso(ep_reg)) { + ep_reg = ep_add_status(ep_reg, dir, EP_STAT_NAK); } + ep_reg = ep_add_dtog(ep_reg, dir, 0); // Reset to DATA0 + + pcd_set_endpoint(USB, ep_idx, ep_reg); } #ifdef FSDEV_BUS_32BIT diff --git a/src/portable/st/stm32_fsdev/fsdev_common.h b/src/portable/st/stm32_fsdev/fsdev_common.h index 676596c73..3b14c0334 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.h +++ b/src/portable/st/stm32_fsdev/fsdev_common.h @@ -159,6 +159,9 @@ typedef enum { EP_STAT_VALID = 3 }ep_stat_t; +#define EP_STAT_MASK(_dir) (3u << (USB_EPTX_STAT_Pos + ((_dir) == TUSB_DIR_IN ? 0 : 8))) +#define EP_DTOG_MASK(_dir) (1u << (USB_EP_DTOG_TX_Pos + ((_dir) == TUSB_DIR_IN ? 0 : 8))) + //--------------------------------------------------------------------+ // BTable //--------------------------------------------------------------------+ @@ -274,26 +277,6 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_eptype(USB_TypeDef * USBx, uint pcd_set_endpoint(USBx, bEpIdx, regVal); } -TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_eptype(USB_TypeDef * USBx, uint32_t bEpIdx) { - uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); - regVal &= USB_EP_T_FIELD; - return regVal; -} - -/** - * @brief Clears bit CTR_RX / CTR_TX in the endpoint register. - * @param USBx USB peripheral instance register address. - * @param bEpIdx Endpoint Number. - * @retval None - */ -TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_rx_ep_ctr(USB_TypeDef * USBx, uint32_t bEpIdx) { - uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); - regVal &= USB_EPREG_MASK; - regVal &= ~USB_EP_CTR_RX; - regVal |= USB_EP_CTR_TX; // preserve CTR_TX (clears on writing 0) - pcd_set_endpoint(USBx, bEpIdx, regVal); -} - TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_tx_ep_ctr(USB_TypeDef * USBx, uint32_t bEpIdx) { uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); regVal &= USB_EPREG_MASK; @@ -310,6 +293,10 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_add_dtog(uint32_t reg, tusb_dir_ return reg ^ (state << (USB_EP_DTOG_TX_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); } +TU_ATTR_ALWAYS_INLINE static inline bool ep_is_iso(uint32_t reg) { + return (reg & USB_EP_TYPE_MASK) == USB_EP_ISOCHRONOUS; +} + /** * @brief sets the status for tx transfer (bits STAT_TX[1:0]). * @param USBx USB peripheral instance register address. @@ -341,54 +328,6 @@ TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_status(USB_TypeDef * USBx pcd_set_endpoint(USBx, bEpIdx, regVal); } -//TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_ep_rx_status(USB_TypeDef * USBx, uint32_t bEpIdx) { -// uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); -// return (regVal & USB_EPRX_STAT) >> (12u); -//} - -TU_ATTR_ALWAYS_INLINE static inline void pcd_rx_dtog(USB_TypeDef * USBx, uint32_t bEpIdx) { - uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); - regVal &= USB_EPREG_MASK; - regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX|USB_EP_DTOG_RX; - pcd_set_endpoint(USBx, bEpIdx, regVal); -} - -TU_ATTR_ALWAYS_INLINE static inline void pcd_tx_dtog(USB_TypeDef * USBx, uint32_t bEpIdx) { - uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); - regVal &= USB_EPREG_MASK; - regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX|USB_EP_DTOG_TX; - pcd_set_endpoint(USBx, bEpIdx, regVal); -} - -TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_rx_dtog(USB_TypeDef * USBx, uint32_t bEpIdx) { - uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); - if((regVal & USB_EP_DTOG_RX) != 0) { - pcd_rx_dtog(USBx,bEpIdx); - } -} - -TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_tx_dtog(USB_TypeDef * USBx, uint32_t bEpIdx) { - uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); - if((regVal & USB_EP_DTOG_TX) != 0) { - pcd_tx_dtog(USBx,bEpIdx); - } -} - -//TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_kind(USB_TypeDef * USBx, uint32_t bEpIdx) { -// uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); -// regVal |= USB_EP_KIND; -// regVal &= USB_EPREG_MASK; -// regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX; -// pcd_set_endpoint(USBx, bEpIdx, regVal); -//} -// -//TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_ep_kind(USB_TypeDef * USBx, uint32_t bEpIdx) { -// uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); -// regVal &= USB_EPKIND_MASK; -// regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX; -// pcd_set_endpoint(USBx, bEpIdx, regVal); -//} - #ifdef __cplusplus } #endif -- cgit v1.3.1 From 8139840d7ace72be6829eb1b879747ac5352cc31 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 31 Jul 2024 15:32:37 +0700 Subject: fix ep_add_dtog() --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 5 ++--- src/portable/st/stm32_fsdev/fsdev_common.h | 17 +++-------------- 2 files changed, 5 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 1d3d8cd96..6d185ced1 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -705,9 +705,8 @@ bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) ep_reg |= tu_edpt_number(ep_addr) | USB_EP_ISOCHRONOUS | USB_EP_CTR_RX | USB_EP_CTR_TX; ep_reg = ep_add_status(ep_reg, TUSB_DIR_IN, EP_STAT_DISABLED); ep_reg = ep_add_status(ep_reg, TUSB_DIR_OUT, EP_STAT_DISABLED); - - ep_add_dtog(ep_reg, dir, 0); - ep_add_dtog(ep_reg, 1-dir, 1); + ep_reg = ep_add_dtog(ep_reg, dir, 0); + ep_reg = ep_add_dtog(ep_reg, 1-dir, 1); pcd_set_endpoint(USB, ep_idx, ep_reg); diff --git a/src/portable/st/stm32_fsdev/fsdev_common.h b/src/portable/st/stm32_fsdev/fsdev_common.h index 3b14c0334..73dc070ed 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.h +++ b/src/portable/st/stm32_fsdev/fsdev_common.h @@ -254,20 +254,9 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_endpoint(USB_TypeDef * USBx return FSDEV_REG->ep[bEpIdx].reg; } -/** - * @brief Sets address in an endpoint register. - * @param USBx USB peripheral instance register address. - * @param bEpIdx Endpoint Number. - * @param bAddr Address. - * @retval None - */ -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_address(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t bAddr) { - uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); - regVal &= USB_EPREG_MASK; - regVal |= bAddr; - regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX; - pcd_set_endpoint(USBx, bEpIdx, regVal); -} +//TU_ATTR_ALWAYS_INLINE static inline void ep_write(uint32_t ep_id, uint32_t value) { +// FSDEV_REG->ep[ep_id].reg = (fsdev_bus_t) value; +//} TU_ATTR_ALWAYS_INLINE static inline void pcd_set_eptype(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wType) { uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); -- cgit v1.3.1 From 3156f1c4a75e0aa7d506631a50da41ea7f38280d Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 31 Jul 2024 16:52:00 +0700 Subject: remove all pcd ep read, modify write --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 63 ++++++++++----------- src/portable/st/stm32_fsdev/fsdev_common.h | 79 ++++++++------------------- 2 files changed, 52 insertions(+), 90 deletions(-) (limited to 'src') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 6d185ced1..58de125d9 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -286,21 +286,15 @@ static void handle_bus_reset(uint8_t rhport) { // Handle CTR interrupt for the TX/IN direction static void dcd_ep_ctr_tx_handler(uint32_t ep_id) { - uint32_t wEPRegVal = pcd_get_endpoint(USB, ep_id); - uint8_t ep_addr = (wEPRegVal & USB_EPADDR_FIELD) | TUSB_DIR_IN_MASK; + uint32_t ep_reg = pcd_get_endpoint(USB, ep_id) & USB_EPREG_MASK; - // Verify the CTR_TX bit is set. This was in the ST Micro code, - // but I'm not sure it's actually necessary? - if ((wEPRegVal & USB_EP_CTR_TX) == 0U) { - return; - } - - /* clear int flag */ - pcd_clear_tx_ep_ctr(USB, ep_id); + // Verify the CTR bit is set. This was in the ST Micro code, but I'm not sure it's actually necessary? + TU_VERIFY(ep_reg & USB_EP_CTR_TX, ); + uint8_t ep_addr = (ep_reg & USB_EPADDR_FIELD) | TUSB_DIR_IN_MASK; xfer_ctl_t *xfer = xfer_ctl_ptr(ep_addr); - if ((wEPRegVal & USB_EP_TYPE_MASK) == USB_EP_ISOCHRONOUS) { + if (ep_is_iso(ep_reg)) { // Ignore spurious interrupts that we don't schedule // host can send IN token while there is no data to send, since ISO does not have NAK // this will result to zero length packet --> trigger interrupt (which cannot be masked) @@ -308,14 +302,19 @@ static void dcd_ep_ctr_tx_handler(uint32_t ep_id) { return; } xfer->iso_in_sending = false; - uint8_t buf_id = (wEPRegVal & USB_EP_DTOG_TX) ? 0 : 1; + uint8_t buf_id = (ep_reg & USB_EP_DTOG_TX) ? 0 : 1; btable_set_count(ep_id, buf_id, 0); } - if ((xfer->total_len != xfer->queued_len)) { - dcd_transmit_packet(xfer, ep_id); + if (xfer->total_len != xfer->queued_len) { + dcd_transmit_packet(xfer, ep_id); // also clear CTR bit } else { dcd_event_xfer_complete(0, ep_addr, xfer->total_len, XFER_RESULT_SUCCESS, true); + + // Clear CTR TX and reserved CTR RX + ep_reg = (ep_reg & ~USB_EP_CTR_TX) | USB_EP_CTR_RX; + + pcd_set_endpoint(USB, ep_id, ep_reg); } } @@ -343,15 +342,13 @@ static void dcd_ep_ctr_rx_handler(uint32_t ep_id) { #endif uint32_t ep_reg = pcd_get_endpoint(USB, ep_id); - uint8_t ep_addr = ep_reg & USB_EPADDR_FIELD; - // Verify the CTR_RX bit is set. This was in the ST Micro code, - // but I'm not sure it's actually necessary? - if ((ep_reg & USB_EP_CTR_RX) == 0U) { - return; - } + // Verify the CTR bit is set. This was in the ST Micro code, but I'm not sure it's actually necessary? + TU_VERIFY(ep_reg & USB_EP_CTR_RX, ); - // Clear RX CTR and reserved TX CTR + uint8_t const ep_addr = ep_reg & USB_EPADDR_FIELD; + + // Clear CTR RX and reserved CTR TX ep_reg = (ep_reg & ~USB_EP_CTR_RX) | USB_EP_CTR_TX; if (ep_reg & USB_EP_SETUP) { @@ -688,8 +685,6 @@ bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet btable_set_addr(ep_idx, 1, pma_addr2); xfer_ctl_ptr(ep_addr)->ep_idx = ep_idx; - pcd_set_eptype(USB, ep_idx, USB_EP_ISOCHRONOUS); - return true; } @@ -715,13 +710,9 @@ bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) // Currently, single-buffered, and only 64 bytes at a time (max) static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix) { - uint16_t len = (uint16_t)(xfer->total_len - xfer->queued_len); - if (len > xfer->max_packet_size) { - len = xfer->max_packet_size; - } - - uint16_t ep_reg = pcd_get_endpoint(USB, ep_ix); - bool const is_iso = (ep_reg & USB_EP_TYPE_MASK) == USB_EP_ISOCHRONOUS; + uint16_t len = tu_min16(xfer->total_len - xfer->queued_len, xfer->max_packet_size); + uint16_t ep_reg = pcd_get_endpoint(USB, ep_ix) | EP_CTR_TXRX; + bool const is_iso = ep_is_iso(ep_reg); uint8_t buf_id; if (is_iso) { @@ -739,8 +730,12 @@ static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix) { } xfer->queued_len = (uint16_t)(xfer->queued_len + len); + ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(TUSB_DIR_IN); + ep_reg = ep_add_status(ep_reg, TUSB_DIR_IN, EP_STAT_VALID); + ep_reg = ep_clear_ctr(ep_reg, TUSB_DIR_IN); + dcd_int_disable(0); - pcd_set_ep_tx_status(USB, ep_ix, USB_EP_TX_VALID); + pcd_set_endpoint(USB, ep_ix, ep_reg); if (is_iso) { xfer->iso_in_sending = true; } @@ -758,7 +753,9 @@ static bool edpt_xfer(uint8_t rhport, uint8_t ep_addr) { dcd_transmit_packet(xfer, ep_idx); } else { uint32_t cnt = (uint32_t) tu_min16(xfer->total_len, xfer->max_packet_size); - uint16_t ep_reg = pcd_get_endpoint(USB, ep_idx); + uint16_t ep_reg = pcd_get_endpoint(USB, ep_idx) | USB_EP_CTR_TX; + ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(dir); // keep CTR TX, clear CTR RX + ep_reg = ep_add_status(ep_reg, dir, EP_STAT_VALID); if (ep_is_iso(ep_reg)) { btable_set_rx_bufsize(ep_idx, 0, cnt); @@ -767,7 +764,7 @@ static bool edpt_xfer(uint8_t rhport, uint8_t ep_addr) { btable_set_rx_bufsize(ep_idx, BTABLE_BUF_RX, cnt); } - pcd_set_ep_rx_status(USB, ep_idx, USB_EP_RX_VALID); + pcd_set_endpoint(USB, ep_idx, ep_reg); } return true; diff --git a/src/portable/st/stm32_fsdev/fsdev_common.h b/src/portable/st/stm32_fsdev/fsdev_common.h index 73dc070ed..67ee72d0e 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.h +++ b/src/portable/st/stm32_fsdev/fsdev_common.h @@ -141,17 +141,20 @@ TU_VERIFY_STATIC(sizeof(fsdev_regs_t) == 0x5C, "Size is not correct"); #endif #ifndef USB_EPTX_STAT_Pos -#define USB_EPTX_STAT_Pos (4U) +#define USB_EPTX_STAT_Pos 4u #endif #ifndef USB_EP_DTOG_TX_Pos -#define USB_EP_DTOG_TX_Pos (6U) +#define USB_EP_DTOG_TX_Pos 6u #endif -#ifndef USB_EP_DTOG_RX_Pos -#define USB_EP_DTOG_RX_Pos (14U) +#ifndef USB_EP_CTR_TX_Pos +#define USB_EP_CTR_TX_Pos 7u #endif + +#define EP_CTR_TXRX (USB_EP_CTR_TX | USB_EP_CTR_RX) + typedef enum { EP_STAT_DISABLED = 0, EP_STAT_STALL = 1, @@ -244,34 +247,23 @@ TU_ATTR_ALWAYS_INLINE static inline void btable_set_rx_bufsize(uint32_t ep_id, u // Endpoint //--------------------------------------------------------------------+ -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_endpoint(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wRegValue) { +TU_ATTR_ALWAYS_INLINE static inline void pcd_set_endpoint(USB_TypeDef * USBx, uint32_t ep_id, uint32_t value) { (void) USBx; - FSDEV_REG->ep[bEpIdx].reg = (fsdev_bus_t) wRegValue; + FSDEV_REG->ep[ep_id].reg = (fsdev_bus_t) value; } -TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_endpoint(USB_TypeDef * USBx, uint32_t bEpIdx) { - (void) USBx; - return FSDEV_REG->ep[bEpIdx].reg; -} - -//TU_ATTR_ALWAYS_INLINE static inline void ep_write(uint32_t ep_id, uint32_t value) { +// write ep register with clear CTR_RX and CTR_TX mask (0 is no clear) +//TU_ATTR_ALWAYS_INLINE static inline void ep_write_with_clear_ctr(uint32_t ep_id, uint32_t value, uint32_t clear_ctr_mask) { +// value |= USB_EP_CTR_RX | USB_EP_CTR_TX; +// if (clear_ctr_mask) { +// value &= ~clear_ctr_mask; +// } // FSDEV_REG->ep[ep_id].reg = (fsdev_bus_t) value; //} -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_eptype(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wType) { - uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); - regVal &= (uint32_t)USB_EP_T_MASK; - regVal |= wType; - regVal |= USB_EP_CTR_RX | USB_EP_CTR_TX; // These clear on write0, so must set high - pcd_set_endpoint(USBx, bEpIdx, regVal); -} - -TU_ATTR_ALWAYS_INLINE static inline void pcd_clear_tx_ep_ctr(USB_TypeDef * USBx, uint32_t bEpIdx) { - uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); - regVal &= USB_EPREG_MASK; - regVal &= ~USB_EP_CTR_TX; - regVal |= USB_EP_CTR_RX; // preserve CTR_RX (clears on writing 0) - pcd_set_endpoint(USBx, bEpIdx,regVal); +TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_endpoint(USB_TypeDef * USBx, uint32_t ep_id) { + (void) USBx; + return FSDEV_REG->ep[ep_id].reg; } TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_add_status(uint32_t reg, tusb_dir_t dir, ep_stat_t state) { @@ -282,39 +274,12 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_add_dtog(uint32_t reg, tusb_dir_ return reg ^ (state << (USB_EP_DTOG_TX_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); } -TU_ATTR_ALWAYS_INLINE static inline bool ep_is_iso(uint32_t reg) { - return (reg & USB_EP_TYPE_MASK) == USB_EP_ISOCHRONOUS; +TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_clear_ctr(uint32_t reg, tusb_dir_t dir) { + return reg & ~(1 << (USB_EP_CTR_TX_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); } -/** - * @brief sets the status for tx transfer (bits STAT_TX[1:0]). - * @param USBx USB peripheral instance register address. - * @param bEpIdx Endpoint Number. - * @param wState new state - * @retval None - */ -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_tx_status(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wState) { - uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); - regVal &= USB_EPTX_DTOGMASK; - regVal ^= wState; - regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX; - pcd_set_endpoint(USBx, bEpIdx, regVal); -} - -/** - * @brief sets the status for rx transfer (bits STAT_TX[1:0]) - * @param USBx USB peripheral instance register address. - * @param bEpIdx Endpoint Number. - * @param wState new state - * @retval None - */ - -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_ep_rx_status(USB_TypeDef * USBx, uint32_t bEpIdx, uint32_t wState) { - uint32_t regVal = pcd_get_endpoint(USBx, bEpIdx); - regVal &= USB_EPRX_DTOGMASK; - regVal ^= wState; - regVal |= USB_EP_CTR_RX|USB_EP_CTR_TX; - pcd_set_endpoint(USBx, bEpIdx, regVal); +TU_ATTR_ALWAYS_INLINE static inline bool ep_is_iso(uint32_t reg) { + return (reg & USB_EP_TYPE_MASK) == USB_EP_ISOCHRONOUS; } #ifdef __cplusplus -- cgit v1.3.1 From ee831d27ac692d33ea6240b8bce24dc98f3bf74b Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 31 Jul 2024 16:53:16 +0700 Subject: rename to ep_read/write(), drop USBx argument --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 34 ++++++------ src/portable/st/stm32_fsdev/fsdev_common.h | 76 +++++++++++++-------------- 2 files changed, 54 insertions(+), 56 deletions(-) (limited to 'src') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 58de125d9..47b3264b1 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -227,7 +227,7 @@ void dcd_init(uint8_t rhport) { // Reset endpoints to disabled for (uint32_t i = 0; i < FSDEV_EP_COUNT; i++) { // This doesn't clear all bits since some bits are "toggle", but does set the type to DISABLED. - pcd_set_endpoint(USB, i, 0u); + ep_write(i, 0u); } USB->CNTR |= USB_CNTR_RESETM | USB_CNTR_ESOFM | USB_CNTR_CTRM | USB_CNTR_SUSPM | USB_CNTR_WKUPM; @@ -286,7 +286,7 @@ static void handle_bus_reset(uint8_t rhport) { // Handle CTR interrupt for the TX/IN direction static void dcd_ep_ctr_tx_handler(uint32_t ep_id) { - uint32_t ep_reg = pcd_get_endpoint(USB, ep_id) & USB_EPREG_MASK; + uint32_t ep_reg = ep_read(ep_id) & USB_EPREG_MASK; // Verify the CTR bit is set. This was in the ST Micro code, but I'm not sure it's actually necessary? TU_VERIFY(ep_reg & USB_EP_CTR_TX, ); @@ -314,7 +314,7 @@ static void dcd_ep_ctr_tx_handler(uint32_t ep_id) { // Clear CTR TX and reserved CTR RX ep_reg = (ep_reg & ~USB_EP_CTR_TX) | USB_EP_CTR_RX; - pcd_set_endpoint(USB, ep_id, ep_reg); + ep_write(ep_id, ep_reg); } } @@ -341,7 +341,7 @@ static void dcd_ep_ctr_rx_handler(uint32_t ep_id) { } #endif - uint32_t ep_reg = pcd_get_endpoint(USB, ep_id); + uint32_t ep_reg = ep_read(ep_id); // Verify the CTR bit is set. This was in the ST Micro code, but I'm not sure it's actually necessary? TU_VERIFY(ep_reg & USB_EP_CTR_RX, ); @@ -413,7 +413,7 @@ static void dcd_ep_ctr_rx_handler(uint32_t ep_id) { } } - pcd_set_endpoint(USB, ep_id, ep_reg); + ep_write(ep_id, ep_reg); } static void dcd_ep_ctr_handler(void) { @@ -599,7 +599,7 @@ void edpt0_open(uint8_t rhport) { // prepare for setup packet btable_set_rx_bufsize(0, BTABLE_BUF_RX, CFG_TUD_ENDPOINT0_SIZE); - pcd_set_endpoint(USB, 0, ep_reg); + ep_write(0, ep_reg); } bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) { @@ -644,7 +644,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) { ep_reg &= ~(USB_EPTX_STAT | USB_EP_DTOG_TX); } - pcd_set_endpoint(USB, ep_idx, ep_reg); + ep_write(ep_idx, ep_reg); return true; } @@ -655,7 +655,7 @@ void dcd_edpt_close_all(uint8_t rhport) for (uint32_t i = 1; i < FSDEV_EP_COUNT; i++) { // Reset endpoint - pcd_set_endpoint(USB, i, 0); + ep_write(i, 0); // Clear EP allocation status ep_alloc_status[i].ep_num = 0xFF; ep_alloc_status[i].ep_type = 0xFF; @@ -703,7 +703,7 @@ bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) ep_reg = ep_add_dtog(ep_reg, dir, 0); ep_reg = ep_add_dtog(ep_reg, 1-dir, 1); - pcd_set_endpoint(USB, ep_idx, ep_reg); + ep_write(ep_idx, ep_reg); return true; } @@ -711,7 +711,7 @@ bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) // Currently, single-buffered, and only 64 bytes at a time (max) static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix) { uint16_t len = tu_min16(xfer->total_len - xfer->queued_len, xfer->max_packet_size); - uint16_t ep_reg = pcd_get_endpoint(USB, ep_ix) | EP_CTR_TXRX; + uint16_t ep_reg = ep_read(ep_ix) | EP_CTR_TXRX; bool const is_iso = ep_is_iso(ep_reg); uint8_t buf_id; @@ -735,7 +735,7 @@ static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix) { ep_reg = ep_clear_ctr(ep_reg, TUSB_DIR_IN); dcd_int_disable(0); - pcd_set_endpoint(USB, ep_ix, ep_reg); + ep_write(ep_ix, ep_reg); if (is_iso) { xfer->iso_in_sending = true; } @@ -753,7 +753,7 @@ static bool edpt_xfer(uint8_t rhport, uint8_t ep_addr) { dcd_transmit_packet(xfer, ep_idx); } else { uint32_t cnt = (uint32_t) tu_min16(xfer->total_len, xfer->max_packet_size); - uint16_t ep_reg = pcd_get_endpoint(USB, ep_idx) | USB_EP_CTR_TX; + uint16_t ep_reg = ep_read(ep_idx) | USB_EP_CTR_TX; ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(dir); // keep CTR TX, clear CTR RX ep_reg = ep_add_status(ep_reg, dir, EP_STAT_VALID); @@ -764,7 +764,7 @@ static bool edpt_xfer(uint8_t rhport, uint8_t ep_addr) { btable_set_rx_bufsize(ep_idx, BTABLE_BUF_RX, cnt); } - pcd_set_endpoint(USB, ep_idx, ep_reg); + ep_write(ep_idx, ep_reg); } return true; @@ -797,12 +797,12 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { uint8_t const ep_idx = xfer->ep_idx; uint8_t const dir = tu_edpt_dir(ep_addr); - uint32_t ep_reg = pcd_get_endpoint(USB, ep_idx); + uint32_t ep_reg = ep_read(ep_idx); ep_reg |= USB_EP_CTR_RX | USB_EP_CTR_TX; // reserve CTR bits ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(dir); ep_reg = ep_add_status(ep_reg, dir, EP_STAT_STALL); - pcd_set_endpoint(USB, ep_idx, ep_reg); + ep_write(ep_idx, ep_reg); } void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { @@ -811,7 +811,7 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { xfer_ctl_t *xfer = xfer_ctl_ptr(ep_addr); uint8_t const ep_idx = xfer->ep_idx; uint8_t const dir = tu_edpt_dir(ep_addr); - uint32_t ep_reg = pcd_get_endpoint(USB, ep_idx); + uint32_t ep_reg = ep_read(ep_idx); ep_reg |= USB_EP_CTR_RX | USB_EP_CTR_TX; // reserve CTR bits ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(dir) | EP_DTOG_MASK(dir); @@ -820,7 +820,7 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { } ep_reg = ep_add_dtog(ep_reg, dir, 0); // Reset to DATA0 - pcd_set_endpoint(USB, ep_idx, ep_reg); + ep_write(ep_idx, ep_reg); } #ifdef FSDEV_BUS_32BIT diff --git a/src/portable/st/stm32_fsdev/fsdev_common.h b/src/portable/st/stm32_fsdev/fsdev_common.h index 67ee72d0e..4ada26895 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.h +++ b/src/portable/st/stm32_fsdev/fsdev_common.h @@ -165,6 +165,43 @@ typedef enum { #define EP_STAT_MASK(_dir) (3u << (USB_EPTX_STAT_Pos + ((_dir) == TUSB_DIR_IN ? 0 : 8))) #define EP_DTOG_MASK(_dir) (1u << (USB_EP_DTOG_TX_Pos + ((_dir) == TUSB_DIR_IN ? 0 : 8))) +//--------------------------------------------------------------------+ +// Endpoint +//--------------------------------------------------------------------+ + +TU_ATTR_ALWAYS_INLINE static inline void ep_write(uint32_t ep_id, uint32_t value) { + FSDEV_REG->ep[ep_id].reg = (fsdev_bus_t) value; +} + +// write ep register with clear CTR_RX and CTR_TX mask (0 is no clear) +//TU_ATTR_ALWAYS_INLINE static inline void ep_write_with_clear_ctr(uint32_t ep_id, uint32_t value, uint32_t clear_ctr_mask) { +// value |= USB_EP_CTR_RX | USB_EP_CTR_TX; +// if (clear_ctr_mask) { +// value &= ~clear_ctr_mask; +// } +// FSDEV_REG->ep[ep_id].reg = (fsdev_bus_t) value; +//} + +TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_read(uint32_t ep_id) { + return FSDEV_REG->ep[ep_id].reg; +} + +TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_add_status(uint32_t reg, tusb_dir_t dir, ep_stat_t state) { + return reg ^ (state << (USB_EPTX_STAT_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); +} + +TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_add_dtog(uint32_t reg, tusb_dir_t dir, uint8_t state) { + return reg ^ (state << (USB_EP_DTOG_TX_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); +} + +TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_clear_ctr(uint32_t reg, tusb_dir_t dir) { + return reg & ~(1 << (USB_EP_CTR_TX_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); +} + +TU_ATTR_ALWAYS_INLINE static inline bool ep_is_iso(uint32_t reg) { + return (reg & USB_EP_TYPE_MASK) == USB_EP_ISOCHRONOUS; +} + //--------------------------------------------------------------------+ // BTable //--------------------------------------------------------------------+ @@ -243,45 +280,6 @@ TU_ATTR_ALWAYS_INLINE static inline void btable_set_rx_bufsize(uint32_t ep_id, u #endif } -//--------------------------------------------------------------------+ -// Endpoint -//--------------------------------------------------------------------+ - -TU_ATTR_ALWAYS_INLINE static inline void pcd_set_endpoint(USB_TypeDef * USBx, uint32_t ep_id, uint32_t value) { - (void) USBx; - FSDEV_REG->ep[ep_id].reg = (fsdev_bus_t) value; -} - -// write ep register with clear CTR_RX and CTR_TX mask (0 is no clear) -//TU_ATTR_ALWAYS_INLINE static inline void ep_write_with_clear_ctr(uint32_t ep_id, uint32_t value, uint32_t clear_ctr_mask) { -// value |= USB_EP_CTR_RX | USB_EP_CTR_TX; -// if (clear_ctr_mask) { -// value &= ~clear_ctr_mask; -// } -// FSDEV_REG->ep[ep_id].reg = (fsdev_bus_t) value; -//} - -TU_ATTR_ALWAYS_INLINE static inline uint32_t pcd_get_endpoint(USB_TypeDef * USBx, uint32_t ep_id) { - (void) USBx; - return FSDEV_REG->ep[ep_id].reg; -} - -TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_add_status(uint32_t reg, tusb_dir_t dir, ep_stat_t state) { - return reg ^ (state << (USB_EPTX_STAT_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); -} - -TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_add_dtog(uint32_t reg, tusb_dir_t dir, uint8_t state) { - return reg ^ (state << (USB_EP_DTOG_TX_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); -} - -TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_clear_ctr(uint32_t reg, tusb_dir_t dir) { - return reg & ~(1 << (USB_EP_CTR_TX_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); -} - -TU_ATTR_ALWAYS_INLINE static inline bool ep_is_iso(uint32_t reg) { - return (reg & USB_EP_TYPE_MASK) == USB_EP_ISOCHRONOUS; -} - #ifdef __cplusplus } #endif -- cgit v1.3.1 From ce0fdc56097efda926c2c3776eec345c920b6cc6 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 31 Jul 2024 17:10:43 +0700 Subject: refactor dcd_ep_ctr_handler --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 37 +++++++++++---------------- src/portable/st/stm32_fsdev/fsdev_common.h | 2 ++ 2 files changed, 17 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 47b3264b1..381dfdd94 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -166,7 +166,6 @@ static uint8_t remoteWakeCountdown; // When wake is requested static void handle_bus_reset(uint8_t rhport); static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix); static bool edpt_xfer(uint8_t rhport, uint8_t ep_addr); -static void dcd_ep_ctr_handler(void); // PMA allocation/access static uint16_t ep_buf_ptr; ///< Points to first free memory location @@ -285,7 +284,7 @@ static void handle_bus_reset(uint8_t rhport) { } // Handle CTR interrupt for the TX/IN direction -static void dcd_ep_ctr_tx_handler(uint32_t ep_id) { +static void handle_ctr_tx(uint32_t ep_id) { uint32_t ep_reg = ep_read(ep_id) & USB_EPREG_MASK; // Verify the CTR bit is set. This was in the ST Micro code, but I'm not sure it's actually necessary? @@ -319,7 +318,7 @@ static void dcd_ep_ctr_tx_handler(uint32_t ep_id) { } // Handle CTR interrupt for the RX/OUT direction -static void dcd_ep_ctr_rx_handler(uint32_t ep_id) { +static void handle_ctr_rx(uint32_t ep_id) { #ifdef FSDEV_BUS_32BIT /* https://www.st.com/resource/en/errata_sheet/es0561-stm32h503cbebkbrb-device-errata-stmicroelectronics.pdf * From STM32H503 errata 2.15.1: Buffer description table update completes after CTR interrupt triggers @@ -416,19 +415,6 @@ static void dcd_ep_ctr_rx_handler(uint32_t ep_id) { ep_write(ep_id, ep_reg); } -static void dcd_ep_ctr_handler(void) { - uint32_t wIstr; - /* stay in loop while pending interrupts */ - while (((wIstr = USB->ISTR) & USB_ISTR_CTR) != 0U) { - uint32_t ep_id = wIstr & USB_ISTR_EP_ID; - if ((wIstr & USB_ISTR_DIR) == 0U) { - dcd_ep_ctr_tx_handler(ep_id); // TX/IN - } else { - dcd_ep_ctr_rx_handler(ep_id); // RX/OUT - } - } -} - void dcd_int_handler(uint8_t rhport) { uint32_t int_status = USB->ISTR; // const uint32_t handled_ints = USB_ISTR_CTR | USB_ISTR_RESET | USB_ISTR_WKUP @@ -453,12 +439,6 @@ void dcd_int_handler(uint8_t rhport) { return; // Don't do the rest of the things here; perhaps they've been cleared? } - if (int_status & USB_ISTR_CTR) { - /* servicing of the endpoint correct transfer interrupt */ - /* clear of the CTR flag into the sub */ - dcd_ep_ctr_handler(); - } - if (int_status & USB_ISTR_WKUP) { USB->CNTR &= ~USB_CNTR_LPMODE; USB->CNTR &= ~USB_CNTR_FSUSP; @@ -489,6 +469,19 @@ void dcd_int_handler(uint8_t rhport) { } USB->ISTR = (fsdev_bus_t)~USB_ISTR_ESOF; } + + // loop to handle all pending CTR interrupts + while (int_status & USB_ISTR_CTR) { + uint32_t const ep_id = int_status & USB_ISTR_EP_ID; + + if ((int_status & USB_ISTR_DIR) == 0U) { + handle_ctr_tx(ep_id); // TX/IN + } else { + handle_ctr_rx(ep_id); // RX/OUT or both (RX/TX !!) + } + + int_status = USB->ISTR; + } } //--------------------------------------------------------------------+ diff --git a/src/portable/st/stm32_fsdev/fsdev_common.h b/src/portable/st/stm32_fsdev/fsdev_common.h index 4ada26895..dd030652b 100644 --- a/src/portable/st/stm32_fsdev/fsdev_common.h +++ b/src/portable/st/stm32_fsdev/fsdev_common.h @@ -167,6 +167,8 @@ typedef enum { //--------------------------------------------------------------------+ // Endpoint +// - CTR is write 0 to clear +// - DTOG and STAT are write 1 to toggle //--------------------------------------------------------------------+ TU_ATTR_ALWAYS_INLINE static inline void ep_write(uint32_t ep_id, uint32_t value) { -- cgit v1.3.1 From 26b0df2c26d31eef1a0d4012d42534f9c434f4eb Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 31 Jul 2024 17:24:41 +0700 Subject: refactor xfer_ctl_ptr() to take epnum/dir to reduce computation --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 77 +++++++++++++++------------ 1 file changed, 43 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 381dfdd94..d0a51d48e 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -165,7 +165,7 @@ static uint8_t remoteWakeCountdown; // When wake is requested // into the stack. static void handle_bus_reset(uint8_t rhport); static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix); -static bool edpt_xfer(uint8_t rhport, uint8_t ep_addr); +static bool edpt_xfer(uint8_t rhport, uint8_t ep_num, uint8_t dir); // PMA allocation/access static uint16_t ep_buf_ptr; ///< Points to first free memory location @@ -183,13 +183,7 @@ static void edpt0_open(uint8_t rhport); // Inline helper //--------------------------------------------------------------------+ -TU_ATTR_ALWAYS_INLINE static inline xfer_ctl_t *xfer_ctl_ptr(uint32_t ep_addr) -{ - uint8_t epnum = tu_edpt_number(ep_addr); - uint8_t dir = tu_edpt_dir(ep_addr); - // Fix -Werror=null-dereference - TU_ASSERT(epnum < CFG_TUD_ENDPPOINT_MAX, &xfer_status[0][0]); - +TU_ATTR_ALWAYS_INLINE static inline xfer_ctl_t *xfer_ctl_ptr(uint8_t epnum, uint8_t dir) { return &xfer_status[epnum][dir]; } @@ -290,8 +284,9 @@ static void handle_ctr_tx(uint32_t ep_id) { // Verify the CTR bit is set. This was in the ST Micro code, but I'm not sure it's actually necessary? TU_VERIFY(ep_reg & USB_EP_CTR_TX, ); + uint8_t const ep_num = ep_reg & USB_EPADDR_FIELD; uint8_t ep_addr = (ep_reg & USB_EPADDR_FIELD) | TUSB_DIR_IN_MASK; - xfer_ctl_t *xfer = xfer_ctl_ptr(ep_addr); + xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, TUSB_DIR_IN); if (ep_is_iso(ep_reg)) { // Ignore spurious interrupts that we don't schedule @@ -344,11 +339,9 @@ static void handle_ctr_rx(uint32_t ep_id) { // Verify the CTR bit is set. This was in the ST Micro code, but I'm not sure it's actually necessary? TU_VERIFY(ep_reg & USB_EP_CTR_RX, ); + ep_reg = (ep_reg & ~USB_EP_CTR_RX) | USB_EP_CTR_TX; // Clear CTR RX and reserved CTR TX - uint8_t const ep_addr = ep_reg & USB_EPADDR_FIELD; - - // Clear CTR RX and reserved CTR TX - ep_reg = (ep_reg & ~USB_EP_CTR_RX) | USB_EP_CTR_TX; + uint8_t const ep_num = ep_reg & USB_EPADDR_FIELD; if (ep_reg & USB_EP_SETUP) { uint32_t count = btable_get_count(ep_id, BTABLE_BUF_RX); @@ -372,7 +365,7 @@ static void handle_ctr_rx(uint32_t ep_id) { ep_reg &= USB_EPRX_STAT | USB_EPREG_MASK; // reversed all toggle except RX Status bool const is_iso = ep_is_iso(ep_reg); - xfer_ctl_t *xfer = xfer_ctl_ptr(ep_addr); + xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, TUSB_DIR_OUT); uint8_t buf_id; if (is_iso) { @@ -394,10 +387,11 @@ static void handle_ctr_rx(uint32_t ep_id) { } if ((rx_count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) { + uint8_t const ep_addr = ep_num; // all bytes received or short packet dcd_event_xfer_complete(0, ep_addr, xfer->queued_len, XFER_RESULT_SUCCESS, true); - if (ep_addr == 0u) { + if (ep_num == 0) { // prepared for status packet btable_set_rx_bufsize(ep_id, BTABLE_BUF_RX, CFG_TUD_ENDPOINT0_SIZE); } @@ -598,6 +592,7 @@ void edpt0_open(uint8_t rhport) { bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) { (void)rhport; uint8_t const ep_addr = desc_ep->bEndpointAddress; + uint8_t const ep_num = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); const uint16_t packet_size = tu_edpt_packet_size(desc_ep); uint8_t const ep_idx = dcd_ep_alloc(ep_addr, desc_ep->bmAttributes.xfer); @@ -624,8 +619,9 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) { uint16_t pma_addr = dcd_pma_alloc(packet_size, false); btable_set_addr(ep_idx, dir == TUSB_DIR_IN ? BTABLE_BUF_TX : BTABLE_BUF_RX, pma_addr); - xfer_ctl_ptr(ep_addr)->max_packet_size = packet_size; - xfer_ctl_ptr(ep_addr)->ep_idx = ep_idx; + xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); + xfer->max_packet_size = packet_size; + xfer->ep_idx = ep_idx; ep_reg = ep_add_status(ep_reg, dir, EP_STAT_NAK); ep_reg = ep_add_dtog(ep_reg, dir, 0); @@ -663,6 +659,8 @@ void dcd_edpt_close_all(uint8_t rhport) bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { (void)rhport; + uint8_t const ep_num = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); uint8_t const ep_idx = dcd_ep_alloc(ep_addr, TUSB_XFER_ISOCHRONOUS); /* Create a packet memory buffer area. Enable double buffering for devices with 2048 bytes PMA, @@ -676,7 +674,9 @@ bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet btable_set_addr(ep_idx, 0, pma_addr); btable_set_addr(ep_idx, 1, pma_addr2); - xfer_ctl_ptr(ep_addr)->ep_idx = ep_idx; + + xfer_ctl_t* xfer = xfer_ctl_ptr(ep_num, dir); + xfer->ep_idx = ep_idx; return true; } @@ -684,10 +684,13 @@ bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) { (void)rhport; uint8_t const ep_addr = desc_ep->bEndpointAddress; - uint8_t const ep_idx = xfer_ctl_ptr(ep_addr)->ep_idx; + uint8_t const ep_num = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); + xfer_ctl_t* xfer = xfer_ctl_ptr(ep_num, dir); - xfer_ctl_ptr(ep_addr)->max_packet_size = tu_edpt_packet_size(desc_ep); + uint8_t const ep_idx = xfer->ep_idx; + + xfer->max_packet_size = tu_edpt_packet_size(desc_ep); uint32_t ep_reg = FSDEV_REG->ep[0].reg & ~USB_EPREG_MASK; ep_reg |= tu_edpt_number(ep_addr) | USB_EP_ISOCHRONOUS | USB_EP_CTR_RX | USB_EP_CTR_TX; @@ -735,12 +738,11 @@ static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix) { dcd_int_enable(0); } -static bool edpt_xfer(uint8_t rhport, uint8_t ep_addr) { +static bool edpt_xfer(uint8_t rhport, uint8_t ep_num, uint8_t dir) { (void) rhport; - xfer_ctl_t *xfer = xfer_ctl_ptr(ep_addr); + xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); uint8_t const ep_idx = xfer->ep_idx; - uint8_t const dir = tu_edpt_dir(ep_addr); if (dir == TUSB_DIR_IN) { dcd_transmit_packet(xfer, ep_idx); @@ -764,31 +766,37 @@ static bool edpt_xfer(uint8_t rhport, uint8_t ep_addr) { } bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) { - xfer_ctl_t *xfer = xfer_ctl_ptr(ep_addr); + uint8_t const ep_num = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); + xfer->buffer = buffer; xfer->ff = NULL; xfer->total_len = total_bytes; xfer->queued_len = 0; - return edpt_xfer(rhport, ep_addr); + return edpt_xfer(rhport, ep_num, dir); } bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t *ff, uint16_t total_bytes) { - xfer_ctl_t *xfer = xfer_ctl_ptr(ep_addr); + uint8_t const ep_num = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); + xfer->buffer = NULL; xfer->ff = ff; xfer->total_len = total_bytes; xfer->queued_len = 0; - return edpt_xfer(rhport, ep_addr); + return edpt_xfer(rhport, ep_num, dir); } void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { (void)rhport; - - xfer_ctl_t *xfer = xfer_ctl_ptr(ep_addr); - uint8_t const ep_idx = xfer->ep_idx; + uint8_t const ep_num = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); + xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); + uint8_t const ep_idx = xfer->ep_idx; uint32_t ep_reg = ep_read(ep_idx); ep_reg |= USB_EP_CTR_RX | USB_EP_CTR_TX; // reserve CTR bits @@ -801,11 +809,12 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { (void)rhport; - xfer_ctl_t *xfer = xfer_ctl_ptr(ep_addr); - uint8_t const ep_idx = xfer->ep_idx; + uint8_t const ep_num = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); - uint32_t ep_reg = ep_read(ep_idx); - ep_reg |= USB_EP_CTR_RX | USB_EP_CTR_TX; // reserve CTR bits + xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); + uint8_t const ep_idx = xfer->ep_idx; + + uint32_t ep_reg = ep_read(ep_idx) | EP_CTR_TXRX; ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(dir) | EP_DTOG_MASK(dir); if (!ep_is_iso(ep_reg)) { -- cgit v1.3.1 From 7954d9cb4c486b263bed8984b7dd7553092150f9 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 31 Jul 2024 18:15:22 +0700 Subject: rename to fsdev_type.h, use FSDDEV_REG instead of USB --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 57 ++--- src/portable/st/stm32_fsdev/fsdev_common.h | 289 -------------------------- src/portable/st/stm32_fsdev/fsdev_stm32.h | 2 + src/portable/st/stm32_fsdev/fsdev_type.h | 286 +++++++++++++++++++++++++ 4 files changed, 317 insertions(+), 317 deletions(-) delete mode 100644 src/portable/st/stm32_fsdev/fsdev_common.h create mode 100644 src/portable/st/stm32_fsdev/fsdev_type.h (limited to 'src') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index d0a51d48e..29e1ca111 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -123,7 +123,7 @@ #error "Unknown USB IP" #endif -#include "fsdev_common.h" +#include "fsdev_type.h" //--------------------------------------------------------------------+ // Configuration @@ -197,25 +197,25 @@ void dcd_init(uint8_t rhport) { } // Perform USB peripheral reset - USB->CNTR = USB_CNTR_FRES | USB_CNTR_PDWN; + FSDEV_REG->CNTR = USB_CNTR_FRES | USB_CNTR_PDWN; for (volatile uint32_t i = 0; i < 200; i++) { // should be a few us asm("NOP"); } - USB->CNTR &= ~USB_CNTR_PDWN; + FSDEV_REG->CNTR &= ~USB_CNTR_PDWN; // Wait startup time, for F042 and F070, this is <= 1 us. for (volatile uint32_t i = 0; i < 200; i++) { // should be a few us asm("NOP"); } - USB->CNTR = 0; // Enable USB + FSDEV_REG->CNTR = 0; // Enable USB -#if !defined(STM32G0) && !defined(STM32H5) && !defined(STM32U5) - // BTABLE register does not exist any more on STM32G0, it is fixed to USB SRAM base address - USB->BTABLE = FSDEV_BTABLE_BASE; +#if !defined(FSDEV_BUS_32BIT) + // BTABLE register does not exist any more on 32-bit bus devices + FSDEV_REG->BTABLE = FSDEV_BTABLE_BASE; #endif - USB->ISTR = 0; // Clear pending interrupts + FSDEV_REG->ISTR = 0; // Clear pending interrupts // Reset endpoints to disabled for (uint32_t i = 0; i < FSDEV_EP_COUNT; i++) { @@ -223,7 +223,7 @@ void dcd_init(uint8_t rhport) { ep_write(i, 0u); } - USB->CNTR |= USB_CNTR_RESETM | USB_CNTR_ESOFM | USB_CNTR_CTRM | USB_CNTR_SUSPM | USB_CNTR_WKUPM; + FSDEV_REG->CNTR |= USB_CNTR_RESETM | USB_CNTR_ESOFM | USB_CNTR_CTRM | USB_CNTR_SUSPM | USB_CNTR_WKUPM; handle_bus_reset(rhport); // Enable pull-up if supported @@ -234,9 +234,9 @@ void dcd_sof_enable(uint8_t rhport, bool en) { (void)rhport; if (en) { - USB->CNTR |= USB_CNTR_SOFM; + FSDEV_REG->CNTR |= USB_CNTR_SOFM; } else { - USB->CNTR &= ~USB_CNTR_SOFM; + FSDEV_REG->CNTR &= ~USB_CNTR_SOFM; } } @@ -254,12 +254,12 @@ void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { void dcd_remote_wakeup(uint8_t rhport) { (void)rhport; - USB->CNTR |= USB_CNTR_RESUME; + FSDEV_REG->CNTR |= USB_CNTR_RESUME; remoteWakeCountdown = 4u; // required to be 1 to 15 ms, ESOF should trigger every 1ms. } static void handle_bus_reset(uint8_t rhport) { - USB->DADDR = 0u; // disable USB Function + FSDEV_REG->DADDR = 0u; // disable USB Function for (uint32_t i = 0; i < FSDEV_EP_COUNT; i++) { // Clear EP allocation status @@ -274,7 +274,7 @@ static void handle_bus_reset(uint8_t rhport) { edpt0_open(rhport); // open control endpoint (both IN & OUT) - USB->DADDR = USB_DADDR_EF; // Enable USB Function + FSDEV_REG->DADDR = USB_DADDR_EF; // Enable USB Function } // Handle CTR interrupt for the TX/IN direction @@ -410,7 +410,7 @@ static void handle_ctr_rx(uint32_t ep_id) { } void dcd_int_handler(uint8_t rhport) { - uint32_t int_status = USB->ISTR; + uint32_t int_status = FSDEV_REG->ISTR; // const uint32_t handled_ints = USB_ISTR_CTR | USB_ISTR_RESET | USB_ISTR_WKUP // | USB_ISTR_SUSP | USB_ISTR_SOF | USB_ISTR_ESOF; // unused IRQs: (USB_ISTR_PMAOVR | USB_ISTR_ERR | USB_ISTR_L1REQ ) @@ -421,23 +421,23 @@ void dcd_int_handler(uint8_t rhport) { /* Put SOF flag at the beginning of ISR in case to get least amount of jitter if it is used for timing purposes */ if (int_status & USB_ISTR_SOF) { - USB->ISTR = (fsdev_bus_t)~USB_ISTR_SOF; - dcd_event_sof(0, USB->FNR & USB_FNR_FN, true); + FSDEV_REG->ISTR = (fsdev_bus_t)~USB_ISTR_SOF; + dcd_event_sof(0, FSDEV_REG->FNR & USB_FNR_FN, true); } if (int_status & USB_ISTR_RESET) { // USBRST is start of reset. - USB->ISTR = (fsdev_bus_t)~USB_ISTR_RESET; + FSDEV_REG->ISTR = (fsdev_bus_t)~USB_ISTR_RESET; handle_bus_reset(rhport); dcd_event_bus_reset(0, TUSB_SPEED_FULL, true); return; // Don't do the rest of the things here; perhaps they've been cleared? } if (int_status & USB_ISTR_WKUP) { - USB->CNTR &= ~USB_CNTR_LPMODE; - USB->CNTR &= ~USB_CNTR_FSUSP; + FSDEV_REG->CNTR &= ~USB_CNTR_LPMODE; + FSDEV_REG->CNTR &= ~USB_CNTR_FSUSP; - USB->ISTR = (fsdev_bus_t)~USB_ISTR_WKUP; + FSDEV_REG->ISTR = (fsdev_bus_t)~USB_ISTR_WKUP; dcd_event_bus_signal(0, DCD_EVENT_RESUME, true); } @@ -446,22 +446,22 @@ void dcd_int_handler(uint8_t rhport) { * these events cannot be differentiated, so we only trigger suspend. */ /* Force low-power mode in the macrocell */ - USB->CNTR |= USB_CNTR_FSUSP; - USB->CNTR |= USB_CNTR_LPMODE; + FSDEV_REG->CNTR |= USB_CNTR_FSUSP; + FSDEV_REG->CNTR |= USB_CNTR_LPMODE; /* clear of the ISTR bit must be done after setting of CNTR_FSUSP */ - USB->ISTR = (fsdev_bus_t)~USB_ISTR_SUSP; + FSDEV_REG->ISTR = (fsdev_bus_t)~USB_ISTR_SUSP; dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true); } if (int_status & USB_ISTR_ESOF) { if (remoteWakeCountdown == 1u) { - USB->CNTR &= ~USB_CNTR_RESUME; + FSDEV_REG->CNTR &= ~USB_CNTR_RESUME; } if (remoteWakeCountdown > 0u) { remoteWakeCountdown--; } - USB->ISTR = (fsdev_bus_t)~USB_ISTR_ESOF; + FSDEV_REG->ISTR = (fsdev_bus_t)~USB_ISTR_ESOF; } // loop to handle all pending CTR interrupts @@ -474,7 +474,7 @@ void dcd_int_handler(uint8_t rhport) { handle_ctr_rx(ep_id); // RX/OUT or both (RX/TX !!) } - int_status = USB->ISTR; + int_status = FSDEV_REG->ISTR; } } @@ -488,10 +488,11 @@ void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const *req (void)rhport; if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE && + request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && request->bRequest == TUSB_REQ_SET_ADDRESS) { uint8_t const dev_addr = (uint8_t)request->wValue; - USB->DADDR = (USB_DADDR_EF | dev_addr); + FSDEV_REG->DADDR = (USB_DADDR_EF | dev_addr); } } diff --git a/src/portable/st/stm32_fsdev/fsdev_common.h b/src/portable/st/stm32_fsdev/fsdev_common.h deleted file mode 100644 index dd030652b..000000000 --- a/src/portable/st/stm32_fsdev/fsdev_common.h +++ /dev/null @@ -1,289 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright(c) 2016 STMicroelectronics - * Copyright(c) N Conrad - * Copyright (c) 2024, hathach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - */ - -#ifndef TUSB_FSDEV_COMMON_H -#define TUSB_FSDEV_COMMON_H - -#ifdef __cplusplus - extern "C" { -#endif - -#include "stdint.h" - -// If sharing with CAN, one can set this to be non-zero to give CAN space where it wants it -// Both of these MUST be a multiple of 2, and are in byte units. -#ifndef FSDEV_BTABLE_BASE -#define FSDEV_BTABLE_BASE 0U -#endif - -TU_VERIFY_STATIC(FSDEV_BTABLE_BASE % 8 == 0, "BTABLE base must be aligned to 8 bytes"); - -// FSDEV_PMA_SIZE is PMA buffer size in bytes. -// - 512-byte devices, access with a stride of two words (use every other 16-bit address) -// - 1024-byte devices, access with a stride of one word (use every 16-bit address) -// - 2048-byte devices, access with 32-bit address - -// For purposes of accessing the packet -#if FSDEV_PMA_SIZE == 512 - #define FSDEV_PMA_STRIDE (2u) // 1x16 bit access scheme - #define pma_aligned TU_ATTR_ALIGNED(4) -#elif FSDEV_PMA_SIZE == 1024 - #define FSDEV_PMA_STRIDE (1u) // 2x16 bit access scheme - #define pma_aligned -#elif FSDEV_PMA_SIZE == 2048 - #ifndef FSDEV_BUS_32BIT - #warning "FSDEV_PMA_SIZE is 2048, but FSDEV_BUS_32BIT is not defined" - #endif - #define FSDEV_PMA_STRIDE (1u) // 32 bit access scheme - #define pma_aligned -#endif - -enum { - BTABLE_BUF_TX = 0, - BTABLE_BUF_RX = 1 -}; - -// hardware limit endpoint -#define FSDEV_EP_COUNT 8 - -// Buffer Table is located in Packet Memory Area (PMA) and therefore its address access is forced to either -// 16-bit or 32-bit depending on FSDEV_BUS_32BIT. -typedef struct { - union { - // 0: TX (IN), 1: RX (OUT) - - // strictly 16-bit access (could be 32-bit aligned) - struct { - volatile pma_aligned uint16_t addr; - volatile pma_aligned uint16_t count; - } ep16[FSDEV_EP_COUNT][2]; - - // strictly 32-bit access - struct { - volatile uint32_t count_addr; - } ep32[FSDEV_EP_COUNT][2]; - }; -} fsdev_btable_t; - -TU_VERIFY_STATIC(sizeof(fsdev_btable_t) == FSDEV_EP_COUNT*8*FSDEV_PMA_STRIDE, "size is not correct"); -TU_VERIFY_STATIC(FSDEV_BTABLE_BASE + FSDEV_EP_COUNT*8 <= FSDEV_PMA_SIZE, "BTABLE does not fit in PMA RAM"); - - -#define FSDEV_BTABLE ((volatile fsdev_btable_t*) (USB_PMAADDR+FSDEV_BTABLE_BASE)) - -// volatile 32-bit aligned -#define _va32 volatile TU_ATTR_ALIGNED(4) - -// The fsdev_bus_t type can be used for both register and PMA access necessities -// For type-safety create a new macro for the volatile address of PMAADDR -// The compiler should warn us if we cast it to a non-volatile type? -#ifdef FSDEV_BUS_32BIT -typedef uint32_t fsdev_bus_t; -static volatile uint32_t * const pma32 = (volatile uint32_t*)USB_PMAADDR; - -#else -typedef uint16_t fsdev_bus_t; -// Volatile is also needed to prevent the optimizer from changing access to 32-bit (as 32-bit access is forbidden) -static volatile uint16_t * const pma = (volatile uint16_t*)USB_PMAADDR; -#endif - -typedef struct { - struct { - _va32 fsdev_bus_t reg; - }ep[FSDEV_EP_COUNT]; - - _va32 uint32_t RESERVED7[8]; // Reserved - _va32 fsdev_bus_t CNTR; // 40: Control register - _va32 fsdev_bus_t ISTR; // 44: Interrupt status register - _va32 fsdev_bus_t FNR; // 48: Frame number register - _va32 fsdev_bus_t DADDR; // 4C: Device address register - _va32 fsdev_bus_t BTABLE; // 50: Buffer Table address register (16-bit only) - _va32 fsdev_bus_t LPMCSR; // 54: LPM Control and Status Register (32-bit only) - _va32 fsdev_bus_t BCDR; // 58: Battery Charging Detector Register (32-bit only) -} fsdev_regs_t; - -TU_VERIFY_STATIC(offsetof(fsdev_regs_t, CNTR) == 0x40, "Wrong offset"); -TU_VERIFY_STATIC(sizeof(fsdev_regs_t) == 0x5C, "Size is not correct"); - -#define FSDEV_REG ((fsdev_regs_t*) FSDEV_REG_BASE) - - -#ifndef USB_EPTX_STAT -#define USB_EPTX_STAT 0x0030U -#endif - -#ifndef USB_EPRX_STAT -#define USB_EPRX_STAT 0x3000U -#endif - -#ifndef USB_EPTX_STAT_Pos -#define USB_EPTX_STAT_Pos 4u -#endif - -#ifndef USB_EP_DTOG_TX_Pos -#define USB_EP_DTOG_TX_Pos 6u -#endif - -#ifndef USB_EP_CTR_TX_Pos -#define USB_EP_CTR_TX_Pos 7u -#endif - - -#define EP_CTR_TXRX (USB_EP_CTR_TX | USB_EP_CTR_RX) - -typedef enum { - EP_STAT_DISABLED = 0, - EP_STAT_STALL = 1, - EP_STAT_NAK = 2, - EP_STAT_VALID = 3 -}ep_stat_t; - -#define EP_STAT_MASK(_dir) (3u << (USB_EPTX_STAT_Pos + ((_dir) == TUSB_DIR_IN ? 0 : 8))) -#define EP_DTOG_MASK(_dir) (1u << (USB_EP_DTOG_TX_Pos + ((_dir) == TUSB_DIR_IN ? 0 : 8))) - -//--------------------------------------------------------------------+ -// Endpoint -// - CTR is write 0 to clear -// - DTOG and STAT are write 1 to toggle -//--------------------------------------------------------------------+ - -TU_ATTR_ALWAYS_INLINE static inline void ep_write(uint32_t ep_id, uint32_t value) { - FSDEV_REG->ep[ep_id].reg = (fsdev_bus_t) value; -} - -// write ep register with clear CTR_RX and CTR_TX mask (0 is no clear) -//TU_ATTR_ALWAYS_INLINE static inline void ep_write_with_clear_ctr(uint32_t ep_id, uint32_t value, uint32_t clear_ctr_mask) { -// value |= USB_EP_CTR_RX | USB_EP_CTR_TX; -// if (clear_ctr_mask) { -// value &= ~clear_ctr_mask; -// } -// FSDEV_REG->ep[ep_id].reg = (fsdev_bus_t) value; -//} - -TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_read(uint32_t ep_id) { - return FSDEV_REG->ep[ep_id].reg; -} - -TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_add_status(uint32_t reg, tusb_dir_t dir, ep_stat_t state) { - return reg ^ (state << (USB_EPTX_STAT_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); -} - -TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_add_dtog(uint32_t reg, tusb_dir_t dir, uint8_t state) { - return reg ^ (state << (USB_EP_DTOG_TX_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); -} - -TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_clear_ctr(uint32_t reg, tusb_dir_t dir) { - return reg & ~(1 << (USB_EP_CTR_TX_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); -} - -TU_ATTR_ALWAYS_INLINE static inline bool ep_is_iso(uint32_t reg) { - return (reg & USB_EP_TYPE_MASK) == USB_EP_ISOCHRONOUS; -} - -//--------------------------------------------------------------------+ -// BTable -//--------------------------------------------------------------------+ - -TU_ATTR_ALWAYS_INLINE static inline uint32_t btable_get_addr(uint32_t ep_id, uint8_t buf_id) { -#ifdef FSDEV_BUS_32BIT - return FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr & 0x0000FFFFu; -#else - return FSDEV_BTABLE->ep16[ep_id][buf_id].addr; -#endif -} - -TU_ATTR_ALWAYS_INLINE static inline void btable_set_addr(uint32_t ep_id, uint8_t buf_id, uint16_t addr) { -#ifdef FSDEV_BUS_32BIT - uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr; - count_addr = (count_addr & 0xFFFF0000u) | (addr & 0x0000FFFCu); - FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr = count_addr; -#else - FSDEV_BTABLE->ep16[ep_id][buf_id].addr = addr; -#endif -} - -TU_ATTR_ALWAYS_INLINE static inline uint32_t btable_get_count(uint32_t ep_id, uint8_t buf_id) { - uint16_t count; -#ifdef FSDEV_BUS_32BIT - count = (FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr >> 16); -#else - count = FSDEV_BTABLE->ep16[ep_id][buf_id].count; -#endif - return count & 0x3FFU; -} - -TU_ATTR_ALWAYS_INLINE static inline void btable_set_count(uint32_t ep_id, uint8_t buf_id, uint16_t byte_count) { -#ifdef FSDEV_BUS_32BIT - uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr; - count_addr = (count_addr & ~0x03FF0000u) | ((byte_count & 0x3FFu) << 16); - FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr = count_addr; -#else - uint16_t cnt = FSDEV_BTABLE->ep16[ep_id][buf_id].count; - cnt = (cnt & ~0x3FFU) | (byte_count & 0x3FFU); - FSDEV_BTABLE->ep16[ep_id][buf_id].count = cnt; -#endif -} - -/* Aligned buffer size according to hardware */ -TU_ATTR_ALWAYS_INLINE static inline uint16_t pma_align_buffer_size(uint16_t size, uint8_t* blsize, uint8_t* num_block) { - /* The STM32 full speed USB peripheral supports only a limited set of - * buffer sizes given by the RX buffer entry format in the USB_BTABLE. */ - uint16_t block_in_bytes; - if (size > 62) { - block_in_bytes = 32; - *blsize = 1; - } else { - block_in_bytes = 2; - *blsize = 0; - } - - *num_block = tu_div_ceil(size, block_in_bytes); - - return (*num_block) * block_in_bytes; -} - -TU_ATTR_ALWAYS_INLINE static inline void btable_set_rx_bufsize(uint32_t ep_id, uint8_t buf_id, uint32_t wCount) { - uint8_t blsize, num_block; - (void) pma_align_buffer_size(wCount, &blsize, &num_block); - - /* Encode into register. When BLSIZE==1, we need to subtract 1 block count */ - uint16_t bl_nb = (blsize << 15) | ((num_block - blsize) << 10); - -#ifdef FSDEV_BUS_32BIT - uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr; - count_addr = (bl_nb << 16) | (count_addr & 0x0000FFFFu); - FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr = count_addr; -#else - FSDEV_BTABLE->ep16[ep_id][buf_id].count = bl_nb; -#endif -} - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/src/portable/st/stm32_fsdev/fsdev_stm32.h b/src/portable/st/stm32_fsdev/fsdev_stm32.h index f20505f28..bb2c72fd1 100644 --- a/src/portable/st/stm32_fsdev/fsdev_stm32.h +++ b/src/portable/st/stm32_fsdev/fsdev_stm32.h @@ -198,6 +198,8 @@ #define FSDEV_REG_BASE USB_BASE #elif defined(USB_DRD_BASE) #define FSDEV_REG_BASE USB_DRD_BASE +#elif defined(USB_DRD_FS_BASE) + #define FSDEV_REG_BASE USB_DRD_FS_BASE #else #error "FSDEV_REG_BASE not defined" #endif diff --git a/src/portable/st/stm32_fsdev/fsdev_type.h b/src/portable/st/stm32_fsdev/fsdev_type.h new file mode 100644 index 000000000..116017f63 --- /dev/null +++ b/src/portable/st/stm32_fsdev/fsdev_type.h @@ -0,0 +1,286 @@ +/* + * The MIT License (MIT) + * + * Copyright(c) 2016 STMicroelectronics + * Copyright(c) N Conrad + * Copyright (c) 2024, hathach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#ifndef TUSB_FSDEV_TYPE_H +#define TUSB_FSDEV_TYPE_H + +#ifdef __cplusplus + extern "C" { +#endif + +#include "stdint.h" + +// If sharing with CAN, one can set this to be non-zero to give CAN space where it wants it +// Both of these MUST be a multiple of 2, and are in byte units. +#ifndef FSDEV_BTABLE_BASE +#define FSDEV_BTABLE_BASE 0U +#endif + +TU_VERIFY_STATIC(FSDEV_BTABLE_BASE % 8 == 0, "BTABLE base must be aligned to 8 bytes"); + +// FSDEV_PMA_SIZE is PMA buffer size in bytes. +// - 512-byte devices, access with a stride of two words (use every other 16-bit address) +// - 1024-byte devices, access with a stride of one word (use every 16-bit address) +// - 2048-byte devices, access with 32-bit address + +// For purposes of accessing the packet +#if FSDEV_PMA_SIZE == 512 + #define FSDEV_PMA_STRIDE (2u) // 1x16 bit access scheme + #define pma_aligned TU_ATTR_ALIGNED(4) +#elif FSDEV_PMA_SIZE == 1024 + #define FSDEV_PMA_STRIDE (1u) // 2x16 bit access scheme + #define pma_aligned +#elif FSDEV_PMA_SIZE == 2048 + #ifndef FSDEV_BUS_32BIT + #warning "FSDEV_PMA_SIZE is 2048, but FSDEV_BUS_32BIT is not defined" + #endif + #define FSDEV_PMA_STRIDE (1u) // 32 bit access scheme + #define pma_aligned +#endif + +//--------------------------------------------------------------------+ +// BTable Typedef +//--------------------------------------------------------------------+ +enum { + BTABLE_BUF_TX = 0, + BTABLE_BUF_RX = 1 +}; + +// hardware limit endpoint +#define FSDEV_EP_COUNT 8 + +// Buffer Table is located in Packet Memory Area (PMA) and therefore its address access is forced to either +// 16-bit or 32-bit depending on FSDEV_BUS_32BIT. +typedef struct { + union { + // 0: TX (IN), 1: RX (OUT) + + // strictly 16-bit access (could be 32-bit aligned) + struct { + volatile pma_aligned uint16_t addr; + volatile pma_aligned uint16_t count; + } ep16[FSDEV_EP_COUNT][2]; + + // strictly 32-bit access + struct { + volatile uint32_t count_addr; + } ep32[FSDEV_EP_COUNT][2]; + }; +} fsdev_btable_t; + +TU_VERIFY_STATIC(sizeof(fsdev_btable_t) == FSDEV_EP_COUNT*8*FSDEV_PMA_STRIDE, "size is not correct"); +TU_VERIFY_STATIC(FSDEV_BTABLE_BASE + FSDEV_EP_COUNT*8 <= FSDEV_PMA_SIZE, "BTABLE does not fit in PMA RAM"); + +#define FSDEV_BTABLE ((volatile fsdev_btable_t*) (USB_PMAADDR+FSDEV_BTABLE_BASE)) + +//--------------------------------------------------------------------+ +// Registers Typedef +//--------------------------------------------------------------------+ + +// volatile 32-bit aligned +#define _va32 volatile TU_ATTR_ALIGNED(4) + +// The fsdev_bus_t type can be used for both register and PMA access necessities +// For type-safety create a new macro for the volatile address of PMAADDR +// The compiler should warn us if we cast it to a non-volatile type? +#ifdef FSDEV_BUS_32BIT +typedef uint32_t fsdev_bus_t; +static volatile uint32_t * const pma32 = (volatile uint32_t*)USB_PMAADDR; + +#else +typedef uint16_t fsdev_bus_t; +// Volatile is also needed to prevent the optimizer from changing access to 32-bit (as 32-bit access is forbidden) +static volatile uint16_t * const pma = (volatile uint16_t*)USB_PMAADDR; +#endif + +typedef struct { + struct { + _va32 fsdev_bus_t reg; + }ep[FSDEV_EP_COUNT]; + + _va32 uint32_t RESERVED7[8]; // Reserved + _va32 fsdev_bus_t CNTR; // 40: Control register + _va32 fsdev_bus_t ISTR; // 44: Interrupt status register + _va32 fsdev_bus_t FNR; // 48: Frame number register + _va32 fsdev_bus_t DADDR; // 4C: Device address register + _va32 fsdev_bus_t BTABLE; // 50: Buffer Table address register (16-bit only) + _va32 fsdev_bus_t LPMCSR; // 54: LPM Control and Status Register (32-bit only) + _va32 fsdev_bus_t BCDR; // 58: Battery Charging Detector Register (32-bit only) +} fsdev_regs_t; + +TU_VERIFY_STATIC(offsetof(fsdev_regs_t, CNTR) == 0x40, "Wrong offset"); +TU_VERIFY_STATIC(sizeof(fsdev_regs_t) == 0x5C, "Size is not correct"); + +#define FSDEV_REG ((fsdev_regs_t*) FSDEV_REG_BASE) + + +#ifndef USB_EPTX_STAT +#define USB_EPTX_STAT 0x0030U +#endif + +#ifndef USB_EPRX_STAT +#define USB_EPRX_STAT 0x3000U +#endif + +#ifndef USB_EPTX_STAT_Pos +#define USB_EPTX_STAT_Pos 4u +#endif + +#ifndef USB_EP_DTOG_TX_Pos +#define USB_EP_DTOG_TX_Pos 6u +#endif + +#ifndef USB_EP_CTR_TX_Pos +#define USB_EP_CTR_TX_Pos 7u +#endif + + +#define EP_CTR_TXRX (USB_EP_CTR_TX | USB_EP_CTR_RX) + +typedef enum { + EP_STAT_DISABLED = 0, + EP_STAT_STALL = 1, + EP_STAT_NAK = 2, + EP_STAT_VALID = 3 +}ep_stat_t; + +#define EP_STAT_MASK(_dir) (3u << (USB_EPTX_STAT_Pos + ((_dir) == TUSB_DIR_IN ? 0 : 8))) +#define EP_DTOG_MASK(_dir) (1u << (USB_EP_DTOG_TX_Pos + ((_dir) == TUSB_DIR_IN ? 0 : 8))) + +//--------------------------------------------------------------------+ +// Endpoint Helper +// - CTR is write 0 to clear +// - DTOG and STAT are write 1 to toggle +//--------------------------------------------------------------------+ + +TU_ATTR_ALWAYS_INLINE static inline void ep_write(uint32_t ep_id, uint32_t value) { + FSDEV_REG->ep[ep_id].reg = (fsdev_bus_t) value; +} + +TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_read(uint32_t ep_id) { + return FSDEV_REG->ep[ep_id].reg; +} + +TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_add_status(uint32_t reg, tusb_dir_t dir, ep_stat_t state) { + return reg ^ (state << (USB_EPTX_STAT_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); +} + +TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_add_dtog(uint32_t reg, tusb_dir_t dir, uint8_t state) { + return reg ^ (state << (USB_EP_DTOG_TX_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); +} + +TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_clear_ctr(uint32_t reg, tusb_dir_t dir) { + return reg & ~(1 << (USB_EP_CTR_TX_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); +} + +TU_ATTR_ALWAYS_INLINE static inline bool ep_is_iso(uint32_t reg) { + return (reg & USB_EP_TYPE_MASK) == USB_EP_ISOCHRONOUS; +} + +//--------------------------------------------------------------------+ +// BTable Helper +//--------------------------------------------------------------------+ + +TU_ATTR_ALWAYS_INLINE static inline uint32_t btable_get_addr(uint32_t ep_id, uint8_t buf_id) { +#ifdef FSDEV_BUS_32BIT + return FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr & 0x0000FFFFu; +#else + return FSDEV_BTABLE->ep16[ep_id][buf_id].addr; +#endif +} + +TU_ATTR_ALWAYS_INLINE static inline void btable_set_addr(uint32_t ep_id, uint8_t buf_id, uint16_t addr) { +#ifdef FSDEV_BUS_32BIT + uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr; + count_addr = (count_addr & 0xFFFF0000u) | (addr & 0x0000FFFCu); + FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr = count_addr; +#else + FSDEV_BTABLE->ep16[ep_id][buf_id].addr = addr; +#endif +} + +TU_ATTR_ALWAYS_INLINE static inline uint32_t btable_get_count(uint32_t ep_id, uint8_t buf_id) { + uint16_t count; +#ifdef FSDEV_BUS_32BIT + count = (FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr >> 16); +#else + count = FSDEV_BTABLE->ep16[ep_id][buf_id].count; +#endif + return count & 0x3FFU; +} + +TU_ATTR_ALWAYS_INLINE static inline void btable_set_count(uint32_t ep_id, uint8_t buf_id, uint16_t byte_count) { +#ifdef FSDEV_BUS_32BIT + uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr; + count_addr = (count_addr & ~0x03FF0000u) | ((byte_count & 0x3FFu) << 16); + FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr = count_addr; +#else + uint16_t cnt = FSDEV_BTABLE->ep16[ep_id][buf_id].count; + cnt = (cnt & ~0x3FFU) | (byte_count & 0x3FFU); + FSDEV_BTABLE->ep16[ep_id][buf_id].count = cnt; +#endif +} + +/* Aligned buffer size according to hardware */ +TU_ATTR_ALWAYS_INLINE static inline uint16_t pma_align_buffer_size(uint16_t size, uint8_t* blsize, uint8_t* num_block) { + /* The STM32 full speed USB peripheral supports only a limited set of + * buffer sizes given by the RX buffer entry format in the USB_BTABLE. */ + uint16_t block_in_bytes; + if (size > 62) { + block_in_bytes = 32; + *blsize = 1; + } else { + block_in_bytes = 2; + *blsize = 0; + } + + *num_block = tu_div_ceil(size, block_in_bytes); + + return (*num_block) * block_in_bytes; +} + +TU_ATTR_ALWAYS_INLINE static inline void btable_set_rx_bufsize(uint32_t ep_id, uint8_t buf_id, uint32_t wCount) { + uint8_t blsize, num_block; + (void) pma_align_buffer_size(wCount, &blsize, &num_block); + + /* Encode into register. When BLSIZE==1, we need to subtract 1 block count */ + uint16_t bl_nb = (blsize << 15) | ((num_block - blsize) << 10); + +#ifdef FSDEV_BUS_32BIT + uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr; + count_addr = (bl_nb << 16) | (count_addr & 0x0000FFFFu); + FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr = count_addr; +#else + FSDEV_BTABLE->ep16[ep_id][buf_id].count = bl_nb; +#endif +} + +#ifdef __cplusplus + } +#endif + +#endif -- cgit v1.3.1 From 7d9b39946601e1c7cd393d09db40892bca5cf477 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 31 Jul 2024 18:28:17 +0700 Subject: fix ep type bulk typo --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 29e1ca111..346cf8164 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -488,7 +488,6 @@ void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const *req (void)rhport; if (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_DEVICE && - request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && request->bRequest == TUSB_REQ_SET_ADDRESS) { uint8_t const dev_addr = (uint8_t)request->wValue; @@ -605,7 +604,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) { // Set type switch (desc_ep->bmAttributes.xfer) { case TUSB_XFER_BULK: - ep_reg |= USB_EP_CONTROL; // FIXME should it be bulk? + ep_reg |= USB_EP_BULK; break; case TUSB_XFER_INTERRUPT: ep_reg |= USB_EP_INTERRUPT; -- cgit v1.3.1 From 332f75cd44b58d340d36f30dbeb64742767a521c Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 31 Jul 2024 20:53:42 +0700 Subject: simplify read/write 16-bit packet --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 139 +++++++++++++------------- src/portable/st/stm32_fsdev/fsdev_ch32.h | 23 ----- src/portable/st/stm32_fsdev/fsdev_type.h | 38 ++++--- 3 files changed, 87 insertions(+), 113 deletions(-) (limited to 'src') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 346cf8164..cff328418 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -171,8 +171,8 @@ static bool edpt_xfer(uint8_t rhport, uint8_t ep_num, uint8_t dir); static uint16_t ep_buf_ptr; ///< Points to first free memory location static uint32_t dcd_pma_alloc(uint16_t len, bool dbuf); static uint8_t dcd_ep_alloc(uint8_t ep_addr, uint8_t ep_type); -static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t wNBytes); -static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t wNBytes); +static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t nbytes); +static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t nbytes); static bool dcd_write_packet_memory_ff(tu_fifo_t *ff, uint16_t dst, uint16_t wNBytes); static bool dcd_read_packet_memory_ff(tu_fifo_t *ff, uint16_t src, uint16_t wNBytes); @@ -828,10 +828,10 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { #ifdef FSDEV_BUS_32BIT static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t wNBytes) { const uint8_t *src8 = src; - volatile uint32_t *dst32 = (volatile uint32_t *)(USB_PMAADDR + dst); + volatile uint32_t *pma32 = (volatile uint32_t *)(USB_PMAADDR + dst); for (uint32_t n = wNBytes / 4; n > 0; --n) { - *dst32++ = tu_unaligned_read32(src8); + *pma32++ = tu_unaligned_read32(src8); src8 += 4; } @@ -849,11 +849,41 @@ static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, ui } } - *dst32 = wrVal; + *pma32 = wrVal; } return true; } + +static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t wNBytes) { + uint8_t *dst8 = dst; + volatile uint32_t *src32 = (volatile uint32_t *)(USB_PMAADDR + src); + + for (uint32_t n = wNBytes / 4; n > 0; --n) { + tu_unaligned_write32(dst8, *src32++); + dst8 += 4; + } + + uint16_t odd = wNBytes & 0x03; + if (odd) { + uint32_t rdVal = *src32; + + *dst8 = tu_u32_byte0(rdVal); + odd--; + + if (odd) { + *++dst8 = tu_u32_byte1(rdVal); + odd--; + + if (odd) { + *++dst8 = tu_u32_byte2(rdVal); + } + } + } + + return true; +} + #else // Packet buffer access can only be 8- or 16-bit. /** @@ -862,26 +892,52 @@ static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, ui * @param dst, byte address in PMA; must be 16-bit aligned * @param src pointer to user memory area. * @param wPMABufAddr address into PMA. - * @param wNBytes no. of bytes to be copied. + * @param nbytes no. of bytes to be copied. * @retval None */ -static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t wNBytes) { - uint32_t n = (uint32_t)wNBytes >> 1U; +static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t nbytes) { + uint32_t n16 = (uint32_t)nbytes >> 1U; const uint8_t *src8 = src; - volatile uint16_t *pdw16 = &pma[FSDEV_PMA_STRIDE * (dst >> 1)]; + fsdev_pma16_t* pma16 = (fsdev_pma16_t*) (USB_PMAADDR + FSDEV_PMA_STRIDE * dst); - while (n--) { - *pdw16 = tu_unaligned_read16(src8); + while (n16--) { + pma16->u16 = tu_unaligned_read16(src8); src8 += 2; - pdw16 += FSDEV_PMA_STRIDE; + pma16++; + } + + if (nbytes & 0x01) { + pma16->u16 = (uint16_t) *src8; + } + + return true; +} + +/** + * @brief Copy a buffer from packet memory area (PMA) to user memory area. + * Uses unaligned for system memory and 16-bit access of packet memory + * @param nbytes no. of bytes to be copied. + * @retval None + */ +static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t nbytes) { + uint32_t n16 = (uint32_t)nbytes >> 1U; + fsdev_pma16_t* pma16 = (fsdev_pma16_t*) (USB_PMAADDR + FSDEV_PMA_STRIDE * src); + uint8_t *dst8 = (uint8_t *)dst; + + while (n16--) { + uint16_t temp16 = pma16->u16; + tu_unaligned_write16(dst8, temp16); + dst8 += 2; + pma16++; } - if (wNBytes & 0x01) { - *pdw16 = (uint16_t) *src8; + if (nbytes & 0x01) { + *dst8++ = tu_u16_low(pma16->u16); } return true; } + #endif /** @@ -959,61 +1015,6 @@ static bool dcd_write_packet_memory_ff(tu_fifo_t *ff, uint16_t dst, uint16_t wNB return true; } -#ifdef FSDEV_BUS_32BIT -static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t wNBytes) { - uint8_t *dst8 = dst; - volatile uint32_t *src32 = (volatile uint32_t *)(USB_PMAADDR + src); - - for (uint32_t n = wNBytes / 4; n > 0; --n) { - tu_unaligned_write32(dst8, *src32++); - dst8 += 4; - } - - uint16_t odd = wNBytes & 0x03; - if (odd) { - uint32_t rdVal = *src32; - - *dst8 = tu_u32_byte0(rdVal); - odd--; - - if (odd) { - *++dst8 = tu_u32_byte1(rdVal); - odd--; - - if (odd) { - *++dst8 = tu_u32_byte2(rdVal); - } - } - } - - return true; -} -#else -/** - * @brief Copy a buffer from packet memory area (PMA) to user memory area. - * Uses unaligned for system memory and 16-bit access of packet memory - * @param wNBytes no. of bytes to be copied. - * @retval None - */ -static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t wNBytes) { - uint32_t n = (uint32_t)wNBytes >> 1U; - volatile const uint16_t *pdw16 = &pma[FSDEV_PMA_STRIDE * (src >> 1)]; - uint8_t *dst8 = (uint8_t *)dst; - - while (n--) { - tu_unaligned_write16(dst8, *pdw16); - dst8 += 2; - pdw16 += FSDEV_PMA_STRIDE; - } - - if (wNBytes & 0x01) { - *dst8++ = tu_u16_low(*pdw16); - } - - return true; -} -#endif - /** * @brief Copy a buffer from user packet memory area (PMA) to FIFO. * Uses byte-access of system memory and 16-bit access of packet memory diff --git a/src/portable/st/stm32_fsdev/fsdev_ch32.h b/src/portable/st/stm32_fsdev/fsdev_ch32.h index 81ef08b8a..8c0961bb9 100644 --- a/src/portable/st/stm32_fsdev/fsdev_ch32.h +++ b/src/portable/st/stm32_fsdev/fsdev_ch32.h @@ -54,29 +54,6 @@ #endif #define FSDEV_PMA_SIZE (512u) - -#if 1 -// volatile 32-bit aligned -#define _vaa32 volatile TU_ATTR_ALIGNED(4) - -typedef struct { - _vaa32 uint16_t EP0R; // 00: USB Endpoint 0 register - _vaa32 uint16_t EP1R; // 04: USB Endpoint 1 register - _vaa32 uint16_t EP2R; // 08: USB Endpoint 2 register - _vaa32 uint16_t EP3R; // 0C: USB Endpoint 3 register - _vaa32 uint16_t EP4R; // 10: USB Endpoint 4 register - _vaa32 uint16_t EP5R; // 14: USB Endpoint 5 register - _vaa32 uint16_t EP6R; // 18: USB Endpoint 6 register - _vaa32 uint16_t EP7R; // 1C: USB Endpoint 7 register - _vaa32 uint16_t RESERVED7[16]; // Reserved - _vaa32 uint16_t CNTR; // 40: Control register - _vaa32 uint16_t ISTR; // 44: Interrupt status register - _vaa32 uint16_t FNR; // 48: Frame number register - _vaa32 uint16_t DADDR; // 4C: Device address register - _vaa32 uint16_t BTABLE; // 50: Buffer Table address register -} USB_TypeDef; -#endif - #define FSDEV_REG_BASE 0x40005C00UL #define USB_BASE (APB1PERIPH_BASE + 0x00005C00UL) /*!< USB_IP Peripheral Registers base address */ diff --git a/src/portable/st/stm32_fsdev/fsdev_type.h b/src/portable/st/stm32_fsdev/fsdev_type.h index 116017f63..e4a0f3f28 100644 --- a/src/portable/st/stm32_fsdev/fsdev_type.h +++ b/src/portable/st/stm32_fsdev/fsdev_type.h @@ -75,21 +75,19 @@ enum { // Buffer Table is located in Packet Memory Area (PMA) and therefore its address access is forced to either // 16-bit or 32-bit depending on FSDEV_BUS_32BIT. -typedef struct { - union { - // 0: TX (IN), 1: RX (OUT) - - // strictly 16-bit access (could be 32-bit aligned) - struct { - volatile pma_aligned uint16_t addr; - volatile pma_aligned uint16_t count; - } ep16[FSDEV_EP_COUNT][2]; - - // strictly 32-bit access - struct { - volatile uint32_t count_addr; - } ep32[FSDEV_EP_COUNT][2]; - }; +typedef union { + // 0: TX (IN), 1: RX (OUT) + + // strictly 16-bit access (could be 32-bit aligned) + struct { + volatile pma_aligned uint16_t addr; + volatile pma_aligned uint16_t count; + } ep16[FSDEV_EP_COUNT][2]; + + // strictly 32-bit access + struct { + volatile uint32_t count_addr; + } ep32[FSDEV_EP_COUNT][2]; } fsdev_btable_t; TU_VERIFY_STATIC(sizeof(fsdev_btable_t) == FSDEV_EP_COUNT*8*FSDEV_PMA_STRIDE, "size is not correct"); @@ -97,6 +95,10 @@ TU_VERIFY_STATIC(FSDEV_BTABLE_BASE + FSDEV_EP_COUNT*8 <= FSDEV_PMA_SIZE, "BTABLE #define FSDEV_BTABLE ((volatile fsdev_btable_t*) (USB_PMAADDR+FSDEV_BTABLE_BASE)) +typedef struct { + volatile pma_aligned uint16_t u16; +} fsdev_pma16_t; + //--------------------------------------------------------------------+ // Registers Typedef //--------------------------------------------------------------------+ @@ -105,16 +107,10 @@ TU_VERIFY_STATIC(FSDEV_BTABLE_BASE + FSDEV_EP_COUNT*8 <= FSDEV_PMA_SIZE, "BTABLE #define _va32 volatile TU_ATTR_ALIGNED(4) // The fsdev_bus_t type can be used for both register and PMA access necessities -// For type-safety create a new macro for the volatile address of PMAADDR -// The compiler should warn us if we cast it to a non-volatile type? #ifdef FSDEV_BUS_32BIT typedef uint32_t fsdev_bus_t; -static volatile uint32_t * const pma32 = (volatile uint32_t*)USB_PMAADDR; - #else typedef uint16_t fsdev_bus_t; -// Volatile is also needed to prevent the optimizer from changing access to 32-bit (as 32-bit access is forbidden) -static volatile uint16_t * const pma = (volatile uint16_t*)USB_PMAADDR; #endif typedef struct { -- cgit v1.3.1 From 46fd82299040ff8c572f2b991f5226bf18405ffe Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 1 Aug 2024 14:24:23 +0700 Subject: increase freerto min task stack for some stm32 --- hw/bsp/family_support.cmake | 19 +++++++++++++++++++ hw/bsp/stm32f0/FreeRTOSConfig/FreeRTOSConfig.h | 2 +- hw/bsp/stm32g0/FreeRTOSConfig/FreeRTOSConfig.h | 2 +- hw/bsp/stm32g0/family.cmake | 5 +++-- hw/bsp/stm32h5/FreeRTOSConfig/FreeRTOSConfig.h | 2 +- src/device/usbd.c | 2 +- 6 files changed, 26 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/hw/bsp/family_support.cmake b/hw/bsp/family_support.cmake index 6a1e96624..9a7eaeb92 100644 --- a/hw/bsp/family_support.cmake +++ b/hw/bsp/family_support.cmake @@ -428,6 +428,19 @@ function(family_flash_stlink TARGET) endfunction() +# Add flash st-flash target +function(family_flash_stflash TARGET) + if (NOT DEFINED ST_FLASH) + set(ST_FLASH st-flash) + endif () + + add_custom_target(${TARGET}-stflash + DEPENDS ${TARGET} + COMMAND ${ST_FLASH} write $/${TARGET}.bin 0x8000000 + ) +endfunction() + + # Add flash openocd target function(family_flash_openocd TARGET) if (NOT DEFINED OPENOCD) @@ -449,6 +462,7 @@ function(family_flash_openocd TARGET) ) endfunction() + # Add flash openocd-wch target # compiled from https://github.com/hathach/riscv-openocd-wch or https://github.com/dragonlock2/miscboards/blob/main/wch/SDK/riscv-openocd.tar.xz function(family_flash_openocd_wch TARGET) @@ -459,6 +473,7 @@ function(family_flash_openocd_wch TARGET) family_flash_openocd(${TARGET}) endfunction() + # Add flash with https://github.com/ch32-rs/wlink function(family_flash_wlink_rs TARGET) if (NOT DEFINED WLINK_RS) @@ -471,6 +486,7 @@ function(family_flash_wlink_rs TARGET) ) endfunction() + # Add flash pycod target function(family_flash_pyocd TARGET) if (NOT DEFINED PYOC) @@ -483,6 +499,7 @@ function(family_flash_pyocd TARGET) ) endfunction() + # Flash with UF2 function(family_flash_uf2 TARGET FAMILY_ID) add_custom_target(${TARGET}-uf2 @@ -491,6 +508,7 @@ function(family_flash_uf2 TARGET FAMILY_ID) ) endfunction() + # Add flash teensy_cli target function(family_flash_teensy TARGET) if (NOT DEFINED TEENSY_CLI) @@ -503,6 +521,7 @@ function(family_flash_teensy TARGET) ) endfunction() + # Add flash using NXP's LinkServer (redserver) # https://www.nxp.com/design/software/development-software/mcuxpresso-software-and-tools-/linkserver-for-microcontrollers:LINKERSERVER function(family_flash_nxplink TARGET) diff --git a/hw/bsp/stm32f0/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/stm32f0/FreeRTOSConfig/FreeRTOSConfig.h index 37e7e0943..999dbfe9e 100644 --- a/hw/bsp/stm32f0/FreeRTOSConfig/FreeRTOSConfig.h +++ b/hw/bsp/stm32f0/FreeRTOSConfig/FreeRTOSConfig.h @@ -58,7 +58,7 @@ #define configCPU_CLOCK_HZ SystemCoreClock #define configTICK_RATE_HZ ( 1000 ) #define configMAX_PRIORITIES ( 5 ) -#define configMINIMAL_STACK_SIZE ( 128 ) +#define configMINIMAL_STACK_SIZE ( 200 ) #define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*4*1024 ) #define configMAX_TASK_NAME_LEN 16 #define configUSE_16_BIT_TICKS 0 diff --git a/hw/bsp/stm32g0/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/stm32g0/FreeRTOSConfig/FreeRTOSConfig.h index 82cb0cdb3..76133ea2d 100644 --- a/hw/bsp/stm32g0/FreeRTOSConfig/FreeRTOSConfig.h +++ b/hw/bsp/stm32g0/FreeRTOSConfig/FreeRTOSConfig.h @@ -58,7 +58,7 @@ #define configCPU_CLOCK_HZ SystemCoreClock #define configTICK_RATE_HZ ( 1000 ) #define configMAX_PRIORITIES ( 5 ) -#define configMINIMAL_STACK_SIZE ( 128 ) +#define configMINIMAL_STACK_SIZE ( 200 ) #define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*4*1024 ) #define configMAX_TASK_NAME_LEN 16 #define configUSE_16_BIT_TICKS 0 diff --git a/hw/bsp/stm32g0/family.cmake b/hw/bsp/stm32g0/family.cmake index b6838c619..0dafa9c0a 100644 --- a/hw/bsp/stm32g0/family.cmake +++ b/hw/bsp/stm32g0/family.cmake @@ -15,7 +15,7 @@ set(CMAKE_SYSTEM_PROCESSOR cortex-m0plus CACHE INTERNAL "System Processor") set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake) set(FAMILY_MCUS STM32G0 CACHE INTERNAL "") - +set(OPENOCD_OPTION "-f interface/stlink.cfg -f target/stm32g0x.cfg") #------------------------------------ # BOARD_TARGET @@ -112,6 +112,7 @@ function(family_configure_example TARGET RTOS) target_link_libraries(${TARGET} PUBLIC board_${BOARD} ${TARGET}-tinyusb) # Flashing - family_flash_stlink(${TARGET}) family_flash_jlink(${TARGET}) + family_flash_stlink(${TARGET}) + #family_flash_openocd(${TARGET}) endfunction() diff --git a/hw/bsp/stm32h5/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/stm32h5/FreeRTOSConfig/FreeRTOSConfig.h index cf6e23c1b..6a9c90a4a 100644 --- a/hw/bsp/stm32h5/FreeRTOSConfig/FreeRTOSConfig.h +++ b/hw/bsp/stm32h5/FreeRTOSConfig/FreeRTOSConfig.h @@ -58,7 +58,7 @@ #define configCPU_CLOCK_HZ SystemCoreClock #define configTICK_RATE_HZ ( 1000 ) #define configMAX_PRIORITIES ( 5 ) -#define configMINIMAL_STACK_SIZE ( 128 ) +#define configMINIMAL_STACK_SIZE ( 200 ) #define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*4*1024 ) #define configMAX_TASK_NAME_LEN 16 #define configUSE_16_BIT_TICKS 0 diff --git a/src/device/usbd.c b/src/device/usbd.c index d9b20d26d..6d27a3735 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1201,7 +1201,7 @@ TU_ATTR_FAST_FUNC void dcd_event_handler(dcd_event_t const* event, bool in_isr) break; case DCD_EVENT_SETUP_RECEIVED: - // TU_ASSERT(event->setup_received.bRequest != 0,); + // TU_ASSERT(event->setup_received.bRequest != 0,); // for catching issue with ch32v203 and windows with -O0/-Og _usbd_queued_setup++; send = true; break; -- cgit v1.3.1 From af8609e96e269a423449cfb679977c150494c3a4 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 1 Aug 2024 18:36:28 +0700 Subject: fsdev improve ep bit manipulation --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 46 +++++++++++++-------------- src/portable/st/stm32_fsdev/fsdev_type.h | 17 +++++----- 2 files changed, 31 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index cff328418..d1c40deb6 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -353,11 +353,11 @@ static void handle_ctr_rx(uint32_t ep_id) { dcd_event_setup_received(0, (uint8_t*) setup_packet, true); // Reset EP to NAK (in case it had been stalling) - ep_reg = ep_add_status(ep_reg, TUSB_DIR_IN, EP_STAT_NAK); - ep_reg = ep_add_status(ep_reg, TUSB_DIR_OUT, EP_STAT_NAK); + ep_add_status(&ep_reg, TUSB_DIR_IN, EP_STAT_NAK); + ep_add_status(&ep_reg, TUSB_DIR_OUT, EP_STAT_NAK); - ep_reg = ep_add_dtog(ep_reg, TUSB_DIR_IN, 1); - ep_reg = ep_add_dtog(ep_reg, TUSB_DIR_OUT, 1); + ep_add_dtog(&ep_reg, TUSB_DIR_IN, 1); + ep_add_dtog(&ep_reg, TUSB_DIR_OUT, 1); } else { ep_reg &= USB_EPREG_MASK; // reversed all toggle } @@ -395,14 +395,14 @@ static void handle_ctr_rx(uint32_t ep_id) { // prepared for status packet btable_set_rx_bufsize(ep_id, BTABLE_BUF_RX, CFG_TUD_ENDPOINT0_SIZE); } - ep_reg = ep_add_status(ep_reg, TUSB_DIR_OUT, EP_STAT_NAK); + ep_add_status(&ep_reg, TUSB_DIR_OUT, EP_STAT_NAK); } else { // Set endpoint active again for receiving more data. Note that isochronous endpoints stay active always if (!is_iso) { uint16_t const cnt = tu_min16(xfer->total_len - xfer->queued_len, xfer->max_packet_size); btable_set_rx_bufsize(ep_id, BTABLE_BUF_RX, cnt); } - ep_reg = ep_add_status(ep_reg, TUSB_DIR_OUT, EP_STAT_VALID); + ep_add_status(&ep_reg, TUSB_DIR_OUT, EP_STAT_VALID); } } @@ -579,8 +579,8 @@ void edpt0_open(uint8_t rhport) { uint32_t ep_reg = FSDEV_REG->ep[0].reg & ~USB_EPREG_MASK; ep_reg |= USB_EP_CONTROL; - ep_reg = ep_add_status(ep_reg, TUSB_DIR_IN, EP_STAT_NAK); - ep_reg = ep_add_status(ep_reg, TUSB_DIR_OUT, EP_STAT_NAK); + ep_add_status(&ep_reg, TUSB_DIR_IN, EP_STAT_NAK); + ep_add_status(&ep_reg, TUSB_DIR_OUT, EP_STAT_NAK); // no need to explicitly set DTOG bits since we aren't masked DTOG bit // prepare for setup packet @@ -623,8 +623,8 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) { xfer->max_packet_size = packet_size; xfer->ep_idx = ep_idx; - ep_reg = ep_add_status(ep_reg, dir, EP_STAT_NAK); - ep_reg = ep_add_dtog(ep_reg, dir, 0); + ep_add_status(&ep_reg, dir, EP_STAT_NAK); + ep_add_dtog(&ep_reg, dir, 0); // reserve other direction toggle bits if (dir == TUSB_DIR_IN) { @@ -694,10 +694,10 @@ bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) uint32_t ep_reg = FSDEV_REG->ep[0].reg & ~USB_EPREG_MASK; ep_reg |= tu_edpt_number(ep_addr) | USB_EP_ISOCHRONOUS | USB_EP_CTR_RX | USB_EP_CTR_TX; - ep_reg = ep_add_status(ep_reg, TUSB_DIR_IN, EP_STAT_DISABLED); - ep_reg = ep_add_status(ep_reg, TUSB_DIR_OUT, EP_STAT_DISABLED); - ep_reg = ep_add_dtog(ep_reg, dir, 0); - ep_reg = ep_add_dtog(ep_reg, 1-dir, 1); + ep_add_status(&ep_reg, TUSB_DIR_IN, EP_STAT_DISABLED); + ep_add_status(&ep_reg, TUSB_DIR_OUT, EP_STAT_DISABLED); + ep_add_dtog(&ep_reg, dir, 0); + ep_add_dtog(&ep_reg, 1-dir, 1); ep_write(ep_idx, ep_reg); @@ -707,7 +707,7 @@ bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) // Currently, single-buffered, and only 64 bytes at a time (max) static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix) { uint16_t len = tu_min16(xfer->total_len - xfer->queued_len, xfer->max_packet_size); - uint16_t ep_reg = ep_read(ep_ix) | EP_CTR_TXRX; + uint32_t ep_reg = ep_read(ep_ix) | EP_CTR_TXRX; bool const is_iso = ep_is_iso(ep_reg); uint8_t buf_id; @@ -727,8 +727,8 @@ static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix) { xfer->queued_len = (uint16_t)(xfer->queued_len + len); ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(TUSB_DIR_IN); - ep_reg = ep_add_status(ep_reg, TUSB_DIR_IN, EP_STAT_VALID); - ep_reg = ep_clear_ctr(ep_reg, TUSB_DIR_IN); + ep_add_status(&ep_reg, TUSB_DIR_IN, EP_STAT_VALID); + ep_clear_ctr(&ep_reg, TUSB_DIR_IN); dcd_int_disable(0); ep_write(ep_ix, ep_reg); @@ -748,9 +748,9 @@ static bool edpt_xfer(uint8_t rhport, uint8_t ep_num, uint8_t dir) { dcd_transmit_packet(xfer, ep_idx); } else { uint32_t cnt = (uint32_t) tu_min16(xfer->total_len, xfer->max_packet_size); - uint16_t ep_reg = ep_read(ep_idx) | USB_EP_CTR_TX; - ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(dir); // keep CTR TX, clear CTR RX - ep_reg = ep_add_status(ep_reg, dir, EP_STAT_VALID); + uint32_t ep_reg = ep_read(ep_idx) | USB_EP_CTR_TX; // keep CTR TX, clear CTR RX + ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(dir); + ep_add_status(&ep_reg, dir, EP_STAT_VALID); if (ep_is_iso(ep_reg)) { btable_set_rx_bufsize(ep_idx, 0, cnt); @@ -801,7 +801,7 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { uint32_t ep_reg = ep_read(ep_idx); ep_reg |= USB_EP_CTR_RX | USB_EP_CTR_TX; // reserve CTR bits ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(dir); - ep_reg = ep_add_status(ep_reg, dir, EP_STAT_STALL); + ep_add_status(&ep_reg, dir, EP_STAT_STALL); ep_write(ep_idx, ep_reg); } @@ -818,9 +818,9 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(dir) | EP_DTOG_MASK(dir); if (!ep_is_iso(ep_reg)) { - ep_reg = ep_add_status(ep_reg, dir, EP_STAT_NAK); + ep_add_status(&ep_reg, dir, EP_STAT_NAK); } - ep_reg = ep_add_dtog(ep_reg, dir, 0); // Reset to DATA0 + ep_add_dtog(&ep_reg, dir, 0); // Reset to DATA0 ep_write(ep_idx, ep_reg); } diff --git a/src/portable/st/stm32_fsdev/fsdev_type.h b/src/portable/st/stm32_fsdev/fsdev_type.h index e4a0f3f28..a44d8b35b 100644 --- a/src/portable/st/stm32_fsdev/fsdev_type.h +++ b/src/portable/st/stm32_fsdev/fsdev_type.h @@ -75,10 +75,9 @@ enum { // Buffer Table is located in Packet Memory Area (PMA) and therefore its address access is forced to either // 16-bit or 32-bit depending on FSDEV_BUS_32BIT. +// 0: TX (IN), 1: RX (OUT) typedef union { - // 0: TX (IN), 1: RX (OUT) - - // strictly 16-bit access (could be 32-bit aligned) + // data is strictly 16-bit access (address could be 32-bit aligned) struct { volatile pma_aligned uint16_t addr; volatile pma_aligned uint16_t count; @@ -181,16 +180,16 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_read(uint32_t ep_id) { return FSDEV_REG->ep[ep_id].reg; } -TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_add_status(uint32_t reg, tusb_dir_t dir, ep_stat_t state) { - return reg ^ (state << (USB_EPTX_STAT_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); +TU_ATTR_ALWAYS_INLINE static inline void ep_add_status(uint32_t* reg, tusb_dir_t dir, ep_stat_t state) { + *reg ^= (state << (USB_EPTX_STAT_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); } -TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_add_dtog(uint32_t reg, tusb_dir_t dir, uint8_t state) { - return reg ^ (state << (USB_EP_DTOG_TX_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); +TU_ATTR_ALWAYS_INLINE static inline void ep_add_dtog(uint32_t* reg, tusb_dir_t dir, uint8_t state) { + *reg ^= (state << (USB_EP_DTOG_TX_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); } -TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_clear_ctr(uint32_t reg, tusb_dir_t dir) { - return reg & ~(1 << (USB_EP_CTR_TX_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); +TU_ATTR_ALWAYS_INLINE static inline void ep_clear_ctr(uint32_t* reg, tusb_dir_t dir) { + *reg &= ~(1 << (USB_EP_CTR_TX_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); } TU_ATTR_ALWAYS_INLINE static inline bool ep_is_iso(uint32_t reg) { -- cgit v1.3.1 From e180d915c64c98ce7349cf4696f23abd55a91e19 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 1 Aug 2024 23:08:12 +0700 Subject: read/write packet enhancement, merge 16-bit and 32-bit together --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 139 +++++++++----------------- src/portable/st/stm32_fsdev/fsdev_type.h | 24 +++-- 2 files changed, 60 insertions(+), 103 deletions(-) (limited to 'src') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index d1c40deb6..2aa776dbb 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -825,121 +825,76 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { ep_write(ep_idx, ep_reg); } -#ifdef FSDEV_BUS_32BIT -static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t wNBytes) { - const uint8_t *src8 = src; - volatile uint32_t *pma32 = (volatile uint32_t *)(USB_PMAADDR + dst); - - for (uint32_t n = wNBytes / 4; n > 0; --n) { - *pma32++ = tu_unaligned_read32(src8); - src8 += 4; - } - - uint16_t odd = wNBytes & 0x03; - if (odd) { - uint32_t wrVal = *src8; - odd--; - - if (odd) { - wrVal |= *++src8 << 8; - odd--; - - if (odd) { - wrVal |= *++src8 << 16; - } - } - - *pma32 = wrVal; - } +// Write to packet memory area (PMA) from user memory +// - Packet memory must be either strictly 16-bit or 32-bit depending on FSDEV_BUS_32BIT +// - Uses unaligned for RAM (since M0 cannot access unaligned address) +static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t nbytes) { + enum { BUS_SIZE = sizeof(fsdev_bus_t) }; + uint32_t n_write = nbytes / BUS_SIZE; - return true; -} + fsdev_pma_buf_t* pma_buf = PMA_BUF_AT(dst); + const uint8_t *src8 = src; -static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t wNBytes) { - uint8_t *dst8 = dst; - volatile uint32_t *src32 = (volatile uint32_t *)(USB_PMAADDR + src); + while (n_write--) { + #ifdef FSDEV_BUS_32BIT + pma_buf->value = tu_unaligned_read32(src8); + #else + pma_buf->value = tu_unaligned_read16(src8); + #endif - for (uint32_t n = wNBytes / 4; n > 0; --n) { - tu_unaligned_write32(dst8, *src32++); - dst8 += 4; + src8 += BUS_SIZE; + pma_buf++; } - uint16_t odd = wNBytes & 0x03; + // odd bytes e.g 1 for 16-bit or 1-3 for 32-bit + uint16_t odd = nbytes & (BUS_SIZE - 1); if (odd) { - uint32_t rdVal = *src32; - - *dst8 = tu_u32_byte0(rdVal); - odd--; - - if (odd) { - *++dst8 = tu_u32_byte1(rdVal); - odd--; - - if (odd) { - *++dst8 = tu_u32_byte2(rdVal); - } + fsdev_bus_t temp = 0; + for(uint16_t i = 0; i < odd; i++) { + temp |= *src8++ << (i * 8); } + pma_buf->value = temp; } return true; } -#else -// Packet buffer access can only be 8- or 16-bit. -/** - * @brief Copy a buffer from user memory area to packet memory area (PMA). - * This uses un-aligned for user memory and 16-bit access for packet memory. - * @param dst, byte address in PMA; must be 16-bit aligned - * @param src pointer to user memory area. - * @param wPMABufAddr address into PMA. - * @param nbytes no. of bytes to be copied. - * @retval None - */ -static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t nbytes) { - uint32_t n16 = (uint32_t)nbytes >> 1U; - const uint8_t *src8 = src; - fsdev_pma16_t* pma16 = (fsdev_pma16_t*) (USB_PMAADDR + FSDEV_PMA_STRIDE * dst); - - while (n16--) { - pma16->u16 = tu_unaligned_read16(src8); - src8 += 2; - pma16++; - } +// Read from packet memory area (PMA) to user memory. +// - Packet memory must be either strictly 16-bit or 32-bit depending on FSDEV_BUS_32BIT +// - Uses unaligned for RAM (since M0 cannot access unaligned address) +static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t nbytes) { + enum { BUS_SIZE = sizeof(fsdev_bus_t) }; + uint32_t n_write = nbytes / BUS_SIZE; - if (nbytes & 0x01) { - pma16->u16 = (uint16_t) *src8; - } + fsdev_pma_buf_t* pma_buf = PMA_BUF_AT(src); + uint8_t *dst8 = (uint8_t *)dst; - return true; -} + while (n_write--) { + fsdev_bus_t temp = pma_buf->value; -/** - * @brief Copy a buffer from packet memory area (PMA) to user memory area. - * Uses unaligned for system memory and 16-bit access of packet memory - * @param nbytes no. of bytes to be copied. - * @retval None - */ -static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t nbytes) { - uint32_t n16 = (uint32_t)nbytes >> 1U; - fsdev_pma16_t* pma16 = (fsdev_pma16_t*) (USB_PMAADDR + FSDEV_PMA_STRIDE * src); - uint8_t *dst8 = (uint8_t *)dst; + #ifdef FSDEV_BUS_32BIT + tu_unaligned_write32(dst8, temp); + #else + tu_unaligned_write16(dst8, temp); + #endif - while (n16--) { - uint16_t temp16 = pma16->u16; - tu_unaligned_write16(dst8, temp16); - dst8 += 2; - pma16++; + dst8 += BUS_SIZE; + pma_buf++; } - if (nbytes & 0x01) { - *dst8++ = tu_u16_low(pma16->u16); + // odd bytes e.g 1 for 16-bit or 1-3 for 32-bit + uint16_t odd = nbytes & (BUS_SIZE - 1); + if (odd) { + fsdev_bus_t temp = pma_buf->value; + while (odd--) { + *dst8++ = (uint8_t) (temp & 0xfful); + temp >>= 8; + } } return true; } -#endif - /** * @brief Copy from FIFO to packet memory area (PMA). * Uses byte-access of system memory and 16-bit access of packet memory diff --git a/src/portable/st/stm32_fsdev/fsdev_type.h b/src/portable/st/stm32_fsdev/fsdev_type.h index a44d8b35b..cac3b4386 100644 --- a/src/portable/st/stm32_fsdev/fsdev_type.h +++ b/src/portable/st/stm32_fsdev/fsdev_type.h @@ -1,9 +1,8 @@ /* * The MIT License (MIT) * - * Copyright(c) 2016 STMicroelectronics * Copyright(c) N Conrad - * Copyright (c) 2024, hathach (tinyusb.org) + * Copyright(c) 2024, hathach (tinyusb.org) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,6 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * + * This file is part of the TinyUSB stack. */ #ifndef TUSB_FSDEV_TYPE_H @@ -62,6 +62,13 @@ TU_VERIFY_STATIC(FSDEV_BTABLE_BASE % 8 == 0, "BTABLE base must be aligned to 8 b #define pma_aligned #endif +// The fsdev_bus_t type can be used for both register and PMA access necessities +#ifdef FSDEV_BUS_32BIT + typedef uint32_t fsdev_bus_t; +#else + typedef uint16_t fsdev_bus_t; +#endif + //--------------------------------------------------------------------+ // BTable Typedef //--------------------------------------------------------------------+ @@ -95,8 +102,10 @@ TU_VERIFY_STATIC(FSDEV_BTABLE_BASE + FSDEV_EP_COUNT*8 <= FSDEV_PMA_SIZE, "BTABLE #define FSDEV_BTABLE ((volatile fsdev_btable_t*) (USB_PMAADDR+FSDEV_BTABLE_BASE)) typedef struct { - volatile pma_aligned uint16_t u16; -} fsdev_pma16_t; + volatile pma_aligned fsdev_bus_t value; +} fsdev_pma_buf_t; + +#define PMA_BUF_AT(_addr) ((fsdev_pma_buf_t*) (USB_PMAADDR + FSDEV_PMA_STRIDE*(_addr))) //--------------------------------------------------------------------+ // Registers Typedef @@ -105,13 +114,6 @@ typedef struct { // volatile 32-bit aligned #define _va32 volatile TU_ATTR_ALIGNED(4) -// The fsdev_bus_t type can be used for both register and PMA access necessities -#ifdef FSDEV_BUS_32BIT -typedef uint32_t fsdev_bus_t; -#else -typedef uint16_t fsdev_bus_t; -#endif - typedef struct { struct { _va32 fsdev_bus_t reg; -- cgit v1.3.1 From 91e5a066c5b259c38d663d21e3485b2feecb779d Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 2 Aug 2024 17:12:28 +0700 Subject: more fsdev clean up hil test boards in parallel --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 8 -- src/portable/st/stm32_fsdev/fsdev_ch32.h | 18 +--- src/portable/st/stm32_fsdev/fsdev_stm32.h | 50 +++++------ src/portable/st/stm32_fsdev/fsdev_type.h | 29 ++++--- test/hil/hil_test.py | 120 +++++++++++++------------- 5 files changed, 102 insertions(+), 123 deletions(-) (limited to 'src') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 2aa776dbb..cbd240ca1 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -114,8 +114,6 @@ #include "device/dcd.h" #if defined(TUP_USBIP_FSDEV_STM32) - // Undefine to reduce the dependence on HAL - #undef USE_HAL_DRIVER #include "fsdev_stm32.h" #elif defined(TUP_USBIP_FSDEV_CH32) #include "fsdev_ch32.h" @@ -125,12 +123,6 @@ #include "fsdev_type.h" -//--------------------------------------------------------------------+ -// Configuration -//--------------------------------------------------------------------+ - - - //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ diff --git a/src/portable/st/stm32_fsdev/fsdev_ch32.h b/src/portable/st/stm32_fsdev/fsdev_ch32.h index 8c0961bb9..518197c47 100644 --- a/src/portable/st/stm32_fsdev/fsdev_ch32.h +++ b/src/portable/st/stm32_fsdev/fsdev_ch32.h @@ -54,22 +54,8 @@ #endif #define FSDEV_PMA_SIZE (512u) -#define FSDEV_REG_BASE 0x40005C00UL - -#define USB_BASE (APB1PERIPH_BASE + 0x00005C00UL) /*!< USB_IP Peripheral Registers base address */ -#define USB_PMAADDR (APB1PERIPH_BASE + 0x00006000UL) /*!< USB_IP Packet Memory Area base address */ -#define USB ((USB_TypeDef *)USB_BASE) - -/******************************************************************************/ -/* */ -/* USB Device General registers */ -/* */ -/******************************************************************************/ -#define USB_CNTR (USB_BASE + 0x40U) /*!< Control register */ -#define USB_ISTR (USB_BASE + 0x44U) /*!< Interrupt status register */ -#define USB_FNR (USB_BASE + 0x48U) /*!< Frame number register */ -#define USB_DADDR (USB_BASE + 0x4CU) /*!< Device address register */ -#define USB_BTABLE (USB_BASE + 0x50U) /*!< Buffer Table address register */ +#define FSDEV_REG_BASE (APB1PERIPH_BASE + 0x00005C00UL) +#define FSDEV_PMA_BASE (APB1PERIPH_BASE + 0x00006000UL) /**************************** ISTR interrupt events *************************/ #define USB_ISTR_CTR ((uint16_t)0x8000U) /*!< Correct TRansfer (clear-only bit) */ diff --git a/src/portable/st/stm32_fsdev/fsdev_stm32.h b/src/portable/st/stm32_fsdev/fsdev_stm32.h index bb2c72fd1..99fe8d55f 100644 --- a/src/portable/st/stm32_fsdev/fsdev_stm32.h +++ b/src/portable/st/stm32_fsdev/fsdev_stm32.h @@ -82,12 +82,9 @@ #elif CFG_TUSB_MCU == OPT_MCU_STM32G0 #include "stm32g0xx.h" - #define FSDEV_BUS_32BIT #define FSDEV_PMA_SIZE (2048u) - #undef USB_PMAADDR - #define USB_PMAADDR USB_DRD_PMAADDR - #define USB_TypeDef USB_DRD_TypeDef - #define EP0R CHEP0R + #define USB USB_DRD_FS + #define USB_EP_CTR_RX USB_EP_VTRX #define USB_EP_CTR_TX USB_EP_VTTX #define USB_EP_T_FIELD USB_CHEP_UTYPE @@ -100,7 +97,6 @@ #define USB_EPRX_DTOG2 USB_CHEP_RX_DTOG2 #define USB_EPRX_STAT USB_CH_RX_VALID #define USB_EPKIND_MASK USB_EP_KIND_MASK - #define USB USB_DRD_FS #define USB_CNTR_FRES USB_CNTR_USBRST #define USB_CNTR_RESUME USB_CNTR_L2RES #define USB_ISTR_EP_ID USB_ISTR_IDN @@ -110,17 +106,9 @@ #elif CFG_TUSB_MCU == OPT_MCU_STM32H5 #include "stm32h5xx.h" - #define FSDEV_BUS_32BIT - - #if !defined(USB_DRD_BASE) && defined(USB_DRD_FS_BASE) - #define USB_DRD_BASE USB_DRD_FS_BASE - #endif - #define FSDEV_PMA_SIZE (2048u) - #undef USB_PMAADDR - #define USB_PMAADDR USB_DRD_PMAADDR - #define USB_TypeDef USB_DRD_TypeDef - #define EP0R CHEP0R + #define USB USB_DRD_FS + #define USB_EP_CTR_RX USB_EP_VTRX #define USB_EP_CTR_TX USB_EP_VTTX #define USB_EP_T_FIELD USB_CHEP_UTYPE @@ -133,7 +121,6 @@ #define USB_EPRX_DTOG2 USB_CHEP_RX_DTOG2 #define USB_EPRX_STAT USB_CH_RX_VALID #define USB_EPKIND_MASK USB_EP_KIND_MASK - #define USB USB_DRD_FS #define USB_CNTR_FRES USB_CNTR_USBRST #define USB_CNTR_RESUME USB_CNTR_L2RES #define USB_ISTR_EP_ID USB_ISTR_IDN @@ -144,9 +131,8 @@ #elif CFG_TUSB_MCU == OPT_MCU_STM32WB #include "stm32wbxx.h" #define FSDEV_PMA_SIZE (1024u) - /* ST provided header has incorrect value */ - #undef USB_PMAADDR - #define USB_PMAADDR USB1_PMAADDR + /* ST provided header has incorrect value of USB_PMAADDR */ + #define FSDEV_PMA_BASE USB1_PMAADDR #elif CFG_TUSB_MCU == OPT_MCU_STM32L4 #include "stm32l4xx.h" @@ -162,13 +148,9 @@ #elif CFG_TUSB_MCU == OPT_MCU_STM32U5 #include "stm32u5xx.h" - #define FSDEV_BUS_32BIT - #define FSDEV_PMA_SIZE (2048u) - #undef USB_PMAADDR - #define USB_PMAADDR USB_DRD_PMAADDR - #define USB_TypeDef USB_DRD_TypeDef - #define EP0R CHEP0R + #define USB USB_DRD_FS + #define USB_EP_CTR_RX USB_EP_VTRX #define USB_EP_CTR_TX USB_EP_VTTX #define USB_EP_T_FIELD USB_CHEP_UTYPE @@ -181,7 +163,6 @@ #define USB_EPRX_DTOG2 USB_CHEP_RX_DTOG2 #define USB_EPRX_STAT USB_CH_RX_VALID #define USB_EPKIND_MASK USB_EP_KIND_MASK - #define USB USB_DRD_FS #define USB_CNTR_FRES USB_CNTR_USBRST #define USB_CNTR_RESUME USB_CNTR_L2RES #define USB_ISTR_EP_ID USB_ISTR_IDN @@ -194,6 +175,10 @@ // This includes U0 #endif +//--------------------------------------------------------------------+ +// Register and PMA Base Address +//--------------------------------------------------------------------+ +#ifndef FSDEV_REG_BASE #if defined(USB_BASE) #define FSDEV_REG_BASE USB_BASE #elif defined(USB_DRD_BASE) @@ -203,6 +188,17 @@ #else #error "FSDEV_REG_BASE not defined" #endif +#endif + +#ifndef FSDEV_PMA_BASE +#if defined(USB_PMAADDR) + #define FSDEV_PMA_BASE USB_PMAADDR +#elif defined(USB_DRD_PMAADDR) + #define FSDEV_PMA_BASE USB_DRD_PMAADDR +#else + #error "FSDEV_PMA_BASE not defined" +#endif +#endif // This checks if the device has "LPM" #if defined(USB_ISTR_L1REQ) diff --git a/src/portable/st/stm32_fsdev/fsdev_type.h b/src/portable/st/stm32_fsdev/fsdev_type.h index cac3b4386..bdff2c940 100644 --- a/src/portable/st/stm32_fsdev/fsdev_type.h +++ b/src/portable/st/stm32_fsdev/fsdev_type.h @@ -49,17 +49,18 @@ TU_VERIFY_STATIC(FSDEV_BTABLE_BASE % 8 == 0, "BTABLE base must be aligned to 8 b // For purposes of accessing the packet #if FSDEV_PMA_SIZE == 512 - #define FSDEV_PMA_STRIDE (2u) // 1x16 bit access scheme - #define pma_aligned TU_ATTR_ALIGNED(4) + // 1x16 bit / word access scheme + #define FSDEV_PMA_STRIDE 2 + #define pma_access_scheme TU_ATTR_ALIGNED(4) #elif FSDEV_PMA_SIZE == 1024 - #define FSDEV_PMA_STRIDE (1u) // 2x16 bit access scheme - #define pma_aligned + // 2x16 bit / word access scheme + #define FSDEV_PMA_STRIDE 1 + #define pma_access_scheme #elif FSDEV_PMA_SIZE == 2048 - #ifndef FSDEV_BUS_32BIT - #warning "FSDEV_PMA_SIZE is 2048, but FSDEV_BUS_32BIT is not defined" - #endif - #define FSDEV_PMA_STRIDE (1u) // 32 bit access scheme - #define pma_aligned + // 32 bit access scheme + #define FSDEV_BUS_32BIT + #define FSDEV_PMA_STRIDE 1 + #define pma_access_scheme #endif // The fsdev_bus_t type can be used for both register and PMA access necessities @@ -86,8 +87,8 @@ enum { typedef union { // data is strictly 16-bit access (address could be 32-bit aligned) struct { - volatile pma_aligned uint16_t addr; - volatile pma_aligned uint16_t count; + volatile pma_access_scheme uint16_t addr; + volatile pma_access_scheme uint16_t count; } ep16[FSDEV_EP_COUNT][2]; // strictly 32-bit access @@ -99,13 +100,13 @@ typedef union { TU_VERIFY_STATIC(sizeof(fsdev_btable_t) == FSDEV_EP_COUNT*8*FSDEV_PMA_STRIDE, "size is not correct"); TU_VERIFY_STATIC(FSDEV_BTABLE_BASE + FSDEV_EP_COUNT*8 <= FSDEV_PMA_SIZE, "BTABLE does not fit in PMA RAM"); -#define FSDEV_BTABLE ((volatile fsdev_btable_t*) (USB_PMAADDR+FSDEV_BTABLE_BASE)) +#define FSDEV_BTABLE ((volatile fsdev_btable_t*) (FSDEV_PMA_BASE + FSDEV_PMA_STRIDE*(FSDEV_BTABLE_BASE))) typedef struct { - volatile pma_aligned fsdev_bus_t value; + volatile pma_access_scheme fsdev_bus_t value; } fsdev_pma_buf_t; -#define PMA_BUF_AT(_addr) ((fsdev_pma_buf_t*) (USB_PMAADDR + FSDEV_PMA_STRIDE*(_addr))) +#define PMA_BUF_AT(_addr) ((fsdev_pma_buf_t*) (FSDEV_PMA_BASE + FSDEV_PMA_STRIDE*(_addr))) //--------------------------------------------------------------------+ // Registers Typedef diff --git a/test/hil/hil_test.py b/test/hil/hil_test.py index bdc48591e..6b8ba0675 100644 --- a/test/hil/hil_test.py +++ b/test/hil/hil_test.py @@ -34,6 +34,7 @@ import subprocess import json import glob import platform +from multiprocessing import Pool # for RPI double reset if platform.machine() == 'aarch64': @@ -130,10 +131,11 @@ def run_cmd(cmd): def flash_jlink(board, firmware): script = ['halt', 'r', f'loadfile {firmware}.elf', 'r', 'go', 'exit'] - with open('flash.jlink', 'w') as f: + f_jlink = f'{board["name"]}_{os.path.basename(firmware)}.jlink' + with open(f_jlink, 'w') as f: f.writelines(f'{s}\n' for s in script) - ret = run_cmd(f'JLinkExe -USB {board["flasher_sn"]} {board["flasher_args"]} -if swd -JTAGConf -1,-1 -speed auto -NoGui 1 -ExitOnError 1 -CommandFile flash.jlink') - os.remove('flash.jlink') + ret = run_cmd(f'JLinkExe -USB {board["flasher_sn"]} {board["flasher_args"]} -if swd -JTAGConf -1,-1 -speed auto -NoGui 1 -ExitOnError 1 -CommandFile {f_jlink}') + os.remove(f_jlink) return ret @@ -327,6 +329,61 @@ def test_hid_composite_freertos(id): # ------------------------------------------------------------- # Main # ------------------------------------------------------------- +# all possible tests: board_test is added last to disable board's usb +all_tests = [ + 'cdc_dual_ports', + 'cdc_msc', + #'cdc_msc_freertos', + 'dfu', + #'dfu_runtime', + 'hid_boot_interface', + 'board_test' +] + + +def test_board(item): + name = item['name'] + flasher = item['flasher'].lower() + + # default to all tests + if 'tests' in item: + test_list = item['tests'] + ['board_test'] + else: + test_list = list(all_tests) + + # remove skip_tests + if 'tests_skip' in item: + for skip in item['tests_skip']: + if skip in test_list: + test_list.remove(skip) + + for test in test_list: + fw_dir = f'cmake-build/cmake-build-{name}/device/{test}' + if not os.path.exists(fw_dir): + fw_dir = f'examples/cmake-build-{name}/device/{test}' + fw_name = f'{fw_dir}/{test}' + print(f'{name:20} {test:20} ... ', end='') + + if not os.path.exists(fw_dir): + print('Skip') + continue + + # flash firmware. It may fail randomly, retry a few times + for i in range(3): + ret = globals()[f'flash_{flasher}'](item, fw_name) + if ret.returncode == 0: + break + else: + print(f'Flashing failed, retry {i+1}') + time.sleep(1) + + assert ret.returncode == 0, 'Flash failed\n' + ret.stdout.decode() + + # run test + globals()[f'test_{test}'](item['uid']) + print('OK') + + def main(): """ Hardware test on specified boards @@ -345,66 +402,13 @@ def main(): with open(config_file) as f: config = json.load(f) - # all possible tests: board_test is added last to disable board's usb - all_tests = [ - 'cdc_dual_ports', - 'cdc_msc', - 'cdc_msc_freertos', - 'dfu', - 'dfu_runtime', - 'hid_boot_interface', - 'board_test' - ] - if len(boards) == 0: config_boards = config['boards'] else: config_boards = [e for e in config['boards'] if e['name'] in boards] - for item in config_boards: - name = item['name'] - print(f'Testing board:{name}') - flasher = item['flasher'].lower() - - # default to all tests - if 'tests' in item: - test_list = item['tests'] + ['board_test'] - else: - test_list = list(all_tests) - - # remove skip_tests - if 'tests_skip' in item: - for skip in item['tests_skip']: - if skip in test_list: - test_list.remove(skip) - - for test in test_list: - fw_dir = f'cmake-build/cmake-build-{name}/device/{test}' - if not os.path.exists(fw_dir): - fw_dir = f'examples/cmake-build-{name}/device/{test}' - fw_name = f'{fw_dir}/{test}' - print(f' {test} ... ', end='') - sys.stdout.flush() - - if not os.path.exists(fw_dir): - print('Skip') - continue - - # flash firmware. It may fail randomly, retry a few times - for i in range(3): - ret = globals()[f'flash_{flasher}'](item, fw_name) - if ret.returncode == 0: - break - else: - print(f'Flashing failed, retry {i+1}') - time.sleep(1) - - assert ret.returncode == 0, 'Flash failed\n' + ret.stdout.decode() - - # run test - globals()[f'test_{test}'](item['uid']) - - print('OK') + with Pool(processes=os.cpu_count()) as pool: + pool.map(test_board, config_boards) if __name__ == '__main__': -- cgit v1.3.1 From 315dae6a85cbb3df5b30429b28d8c74130f44db6 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 5 Aug 2024 17:43:27 +0700 Subject: finally fixed fsdev setup handling, which cause race condition for ch32v203 --- src/device/usbd.c | 1 - src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 59 ++++++++++++++------------- src/portable/st/stm32_fsdev/fsdev_type.h | 3 -- 3 files changed, 30 insertions(+), 33 deletions(-) (limited to 'src') diff --git a/src/device/usbd.c b/src/device/usbd.c index 6d27a3735..7089e9cf1 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1201,7 +1201,6 @@ TU_ATTR_FAST_FUNC void dcd_event_handler(dcd_event_t const* event, bool in_isr) break; case DCD_EVENT_SETUP_RECEIVED: - // TU_ASSERT(event->setup_received.bRequest != 0,); // for catching issue with ch32v203 and windows with -O0/-Og _usbd_queued_setup++; send = true; break; diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index cbd240ca1..43636198a 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -147,7 +147,6 @@ typedef struct { static xfer_ctl_t xfer_status[CFG_TUD_ENDPPOINT_MAX][2]; static ep_alloc_t ep_alloc_status[FSDEV_EP_COUNT]; - static uint8_t remoteWakeCountdown; // When wake is requested //--------------------------------------------------------------------+ @@ -171,6 +170,10 @@ static bool dcd_read_packet_memory_ff(tu_fifo_t *ff, uint16_t src, uint16_t wNBy static void edpt0_open(uint8_t rhport); +TU_ATTR_ALWAYS_INLINE static inline void edpt0_prepare_setup(void) { + btable_set_rx_bufsize(0, BTABLE_BUF_RX, 8); +} + //--------------------------------------------------------------------+ // Inline helper //--------------------------------------------------------------------+ @@ -340,21 +343,24 @@ static void handle_ctr_rx(uint32_t ep_id) { // Setup packet should always be 8 bytes. If not, ignore it, and try again. if (count == 8) { uint16_t rx_addr = btable_get_addr(ep_id, BTABLE_BUF_RX); - uint32_t setup_packet[2]; + uint8_t setup_packet[8] TU_ATTR_ALIGNED(4); + dcd_read_packet_memory(setup_packet, rx_addr, 8); dcd_event_setup_received(0, (uint8_t*) setup_packet, true); - // Reset EP to NAK (in case it had been stalling) + // Reset EP to NAK and set both toggle to 1 ep_add_status(&ep_reg, TUSB_DIR_IN, EP_STAT_NAK); ep_add_status(&ep_reg, TUSB_DIR_OUT, EP_STAT_NAK); - ep_add_dtog(&ep_reg, TUSB_DIR_IN, 1); ep_add_dtog(&ep_reg, TUSB_DIR_OUT, 1); } else { + // Missed an setup packet !!! + TU_BREAKPOINT(); ep_reg &= USB_EPREG_MASK; // reversed all toggle + edpt0_prepare_setup(); } } else { - ep_reg &= USB_EPRX_STAT | USB_EPREG_MASK; // reversed all toggle except RX Status + ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(TUSB_DIR_OUT); // reversed all toggle except RX Status bool const is_iso = ep_is_iso(ep_reg); xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, TUSB_DIR_OUT); @@ -374,20 +380,13 @@ static void handle_ctr_rx(uint32_t ep_id) { } else { dcd_read_packet_memory(xfer->buffer + xfer->queued_len, pma_addr, rx_count); } - xfer->queued_len = (uint16_t)(xfer->queued_len + rx_count); } if ((rx_count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) { - uint8_t const ep_addr = ep_num; // all bytes received or short packet - dcd_event_xfer_complete(0, ep_addr, xfer->queued_len, XFER_RESULT_SUCCESS, true); - - if (ep_num == 0) { - // prepared for status packet - btable_set_rx_bufsize(ep_id, BTABLE_BUF_RX, CFG_TUD_ENDPOINT0_SIZE); - } ep_add_status(&ep_reg, TUSB_DIR_OUT, EP_STAT_NAK); + dcd_event_xfer_complete(0, ep_num, xfer->queued_len, XFER_RESULT_SUCCESS, true); } else { // Set endpoint active again for receiving more data. Note that isochronous endpoints stay active always if (!is_iso) { @@ -485,6 +484,8 @@ void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const *req uint8_t const dev_addr = (uint8_t)request->wValue; FSDEV_REG->DADDR = (USB_DADDR_EF | dev_addr); } + + edpt0_prepare_setup(); } /*** @@ -569,15 +570,13 @@ void edpt0_open(uint8_t rhport) { btable_set_addr(0, BTABLE_BUF_RX, pma_addr0); btable_set_addr(0, BTABLE_BUF_TX, pma_addr1); - uint32_t ep_reg = FSDEV_REG->ep[0].reg & ~USB_EPREG_MASK; + uint32_t ep_reg = ep_read(0) & ~USB_EPREG_MASK; // only get toggle bits ep_reg |= USB_EP_CONTROL; ep_add_status(&ep_reg, TUSB_DIR_IN, EP_STAT_NAK); ep_add_status(&ep_reg, TUSB_DIR_OUT, EP_STAT_NAK); // no need to explicitly set DTOG bits since we aren't masked DTOG bit - // prepare for setup packet - btable_set_rx_bufsize(0, BTABLE_BUF_RX, CFG_TUD_ENDPOINT0_SIZE); - + edpt0_prepare_setup(); // prepare for setup packet ep_write(0, ep_reg); } @@ -590,7 +589,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) { uint8_t const ep_idx = dcd_ep_alloc(ep_addr, desc_ep->bmAttributes.xfer); TU_ASSERT(ep_idx < FSDEV_EP_COUNT); - uint32_t ep_reg = FSDEV_REG->ep[ep_idx].reg & ~USB_EPREG_MASK; + uint32_t ep_reg = ep_read(ep_idx) & ~USB_EPREG_MASK; ep_reg |= tu_edpt_number(ep_addr) | USB_EP_CTR_RX | USB_EP_CTR_TX; // Set type @@ -684,7 +683,7 @@ bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) xfer->max_packet_size = tu_edpt_packet_size(desc_ep); - uint32_t ep_reg = FSDEV_REG->ep[0].reg & ~USB_EPREG_MASK; + uint32_t ep_reg = ep_read(ep_idx) & ~USB_EPREG_MASK; ep_reg |= tu_edpt_number(ep_addr) | USB_EP_ISOCHRONOUS | USB_EP_CTR_RX | USB_EP_CTR_TX; ep_add_status(&ep_reg, TUSB_DIR_IN, EP_STAT_DISABLED); ep_add_status(&ep_reg, TUSB_DIR_OUT, EP_STAT_DISABLED); @@ -699,7 +698,7 @@ bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) // Currently, single-buffered, and only 64 bytes at a time (max) static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix) { uint16_t len = tu_min16(xfer->total_len - xfer->queued_len, xfer->max_packet_size); - uint32_t ep_reg = ep_read(ep_ix) | EP_CTR_TXRX; + uint32_t ep_reg = ep_read(ep_ix) | USB_EP_CTR_TX | USB_EP_CTR_RX; // reserve CTR bits bool const is_iso = ep_is_iso(ep_reg); uint8_t buf_id; @@ -709,14 +708,17 @@ static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix) { buf_id = BTABLE_BUF_TX; } uint16_t addr_ptr = (uint16_t) btable_get_addr(ep_ix, buf_id); - btable_set_count(ep_ix, buf_id, len); - if (xfer->ff) { - dcd_write_packet_memory_ff(xfer->ff, addr_ptr, len); - } else { - dcd_write_packet_memory(addr_ptr, &(xfer->buffer[xfer->queued_len]), len); + if (len) { + if (xfer->ff) { + dcd_write_packet_memory_ff(xfer->ff, addr_ptr, len); + } else { + dcd_write_packet_memory(addr_ptr, &(xfer->buffer[xfer->queued_len]), len); + } + xfer->queued_len = (uint16_t) (xfer->queued_len + len); } - xfer->queued_len = (uint16_t)(xfer->queued_len + len); + + btable_set_count(ep_ix, buf_id, len); ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(TUSB_DIR_IN); ep_add_status(&ep_reg, TUSB_DIR_IN, EP_STAT_VALID); @@ -790,8 +792,7 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); uint8_t const ep_idx = xfer->ep_idx; - uint32_t ep_reg = ep_read(ep_idx); - ep_reg |= USB_EP_CTR_RX | USB_EP_CTR_TX; // reserve CTR bits + uint32_t ep_reg = ep_read(ep_idx) | USB_EP_CTR_TX | USB_EP_CTR_RX; // reserve CTR bits ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(dir); ep_add_status(&ep_reg, dir, EP_STAT_STALL); @@ -806,7 +807,7 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); uint8_t const ep_idx = xfer->ep_idx; - uint32_t ep_reg = ep_read(ep_idx) | EP_CTR_TXRX; + uint32_t ep_reg = ep_read(ep_idx) | USB_EP_CTR_TX | USB_EP_CTR_RX; // reserve CTR bits ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(dir) | EP_DTOG_MASK(dir); if (!ep_is_iso(ep_reg)) { diff --git a/src/portable/st/stm32_fsdev/fsdev_type.h b/src/portable/st/stm32_fsdev/fsdev_type.h index bdff2c940..8432df4b0 100644 --- a/src/portable/st/stm32_fsdev/fsdev_type.h +++ b/src/portable/st/stm32_fsdev/fsdev_type.h @@ -156,9 +156,6 @@ TU_VERIFY_STATIC(sizeof(fsdev_regs_t) == 0x5C, "Size is not correct"); #define USB_EP_CTR_TX_Pos 7u #endif - -#define EP_CTR_TXRX (USB_EP_CTR_TX | USB_EP_CTR_RX) - typedef enum { EP_STAT_DISABLED = 0, EP_STAT_STALL = 1, -- cgit v1.3.1 From d680424f62b0d677158af7219b319a24f5497d1c Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 6 Aug 2024 22:18:25 +0700 Subject: improve dcd_int_handler() - skip DIR and use CTR TX/RX to handle complete transfer - clear CTR first, except for setup which we need to get data first - separate handle_ctr_setup() --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 238 ++++++++++++-------------- src/portable/st/stm32_fsdev/fsdev_type.h | 26 ++- 2 files changed, 132 insertions(+), 132 deletions(-) (limited to 'src') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 43636198a..97529997d 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -4,7 +4,6 @@ * Copyright (c) 2019 Nathan Conrad * * Portions: - * Copyright (c) 2016 STMicroelectronics * Copyright (c) 2019 Ha Thach (tinyusb.org) * Copyright (c) 2022 Simon Küppers (skuep) * Copyright (c) 2022 HiFiPhile @@ -215,10 +214,11 @@ void dcd_init(uint8_t rhport) { // Reset endpoints to disabled for (uint32_t i = 0; i < FSDEV_EP_COUNT; i++) { // This doesn't clear all bits since some bits are "toggle", but does set the type to DISABLED. - ep_write(i, 0u); + ep_write(i, 0u, false); } FSDEV_REG->CNTR |= USB_CNTR_RESETM | USB_CNTR_ESOFM | USB_CNTR_CTRM | USB_CNTR_SUSPM | USB_CNTR_WKUPM; + //| USB_CNTR_ERRM | USB_CNTR_PMAOVRM; handle_bus_reset(rhport); // Enable pull-up if supported @@ -274,13 +274,10 @@ static void handle_bus_reset(uint8_t rhport) { // Handle CTR interrupt for the TX/IN direction static void handle_ctr_tx(uint32_t ep_id) { - uint32_t ep_reg = ep_read(ep_id) & USB_EPREG_MASK; - - // Verify the CTR bit is set. This was in the ST Micro code, but I'm not sure it's actually necessary? - TU_VERIFY(ep_reg & USB_EP_CTR_TX, ); + uint32_t ep_reg = ep_read(ep_id) | USB_EP_CTR_TX | USB_EP_CTR_RX; + ep_reg &= USB_EPREG_MASK; uint8_t const ep_num = ep_reg & USB_EPADDR_FIELD; - uint8_t ep_addr = (ep_reg & USB_EPADDR_FIELD) | TUSB_DIR_IN_MASK; xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, TUSB_DIR_IN); if (ep_is_iso(ep_reg)) { @@ -296,108 +293,72 @@ static void handle_ctr_tx(uint32_t ep_id) { } if (xfer->total_len != xfer->queued_len) { - dcd_transmit_packet(xfer, ep_id); // also clear CTR bit + dcd_transmit_packet(xfer, ep_id); } else { - dcd_event_xfer_complete(0, ep_addr, xfer->total_len, XFER_RESULT_SUCCESS, true); + dcd_event_xfer_complete(0, ep_num | TUSB_DIR_IN_MASK, xfer->queued_len, XFER_RESULT_SUCCESS, true); + } +} - // Clear CTR TX and reserved CTR RX - ep_reg = (ep_reg & ~USB_EP_CTR_TX) | USB_EP_CTR_RX; +static void handle_ctr_setup(uint32_t ep_id) { + uint16_t rx_count = btable_get_count(ep_id, BTABLE_BUF_RX); + uint16_t rx_addr = btable_get_addr(ep_id, BTABLE_BUF_RX); + uint8_t setup_packet[8] TU_ATTR_ALIGNED(4); - ep_write(ep_id, ep_reg); + dcd_read_packet_memory(setup_packet, rx_addr, rx_count); + + // Clear CTR RX if another setup packet arrived before this, it will be discarded + ep_write_clear_ctr(ep_id, TUSB_DIR_OUT); + + // Setup packet should always be 8 bytes. If not, we probably missed the packet + if (rx_count == 8) { + dcd_event_setup_received(0, (uint8_t*) setup_packet, true); + // Hardware should reset EP0 RX/TX to NAK and both toggle to 1 + } else { + // Missed setup packet !!! + TU_BREAKPOINT(); + edpt0_prepare_setup(); } } // Handle CTR interrupt for the RX/OUT direction static void handle_ctr_rx(uint32_t ep_id) { -#ifdef FSDEV_BUS_32BIT - /* https://www.st.com/resource/en/errata_sheet/es0561-stm32h503cbebkbrb-device-errata-stmicroelectronics.pdf - * From STM32H503 errata 2.15.1: Buffer description table update completes after CTR interrupt triggers - * Description: - * - During OUT transfers, the correct transfer interrupt (CTR) is triggered a little before the last USB SRAM accesses - * have completed. If the software responds quickly to the interrupt, the full buffer contents may not be correct. - * Workaround: - * - Software should ensure that a small delay is included before accessing the SRAM contents. This delay - * should be 800 ns in Full Speed mode and 6.4 μs in Low Speed mode - * - Since H5 can run up to 250Mhz -> 1 cycle = 4ns. Per errata, we need to wait 200 cycles. Though executing code - * also takes time, so we'll wait 60 cycles (count = 20). - * - Since Low Speed mode is not supported/popular, we will ignore it for now. - * - * Note: this errata also seems to apply to G0, U5, H5 etc. - */ - volatile uint32_t cycle_count = 20; // defined as PCD_RX_PMA_CNT in stm32 hal_driver - while (cycle_count > 0U) { - cycle_count--; // each count take 3 cycles (1 for sub, jump, and compare) - } -#endif - - uint32_t ep_reg = ep_read(ep_id); - - // Verify the CTR bit is set. This was in the ST Micro code, but I'm not sure it's actually necessary? - TU_VERIFY(ep_reg & USB_EP_CTR_RX, ); - ep_reg = (ep_reg & ~USB_EP_CTR_RX) | USB_EP_CTR_TX; // Clear CTR RX and reserved CTR TX + uint32_t ep_reg = ep_read(ep_id) | USB_EP_CTR_TX | USB_EP_CTR_RX; + ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(TUSB_DIR_OUT); // will change RX Status, reserved other toggle bits uint8_t const ep_num = ep_reg & USB_EPADDR_FIELD; + bool const is_iso = ep_is_iso(ep_reg); + xfer_ctl_t* xfer = xfer_ctl_ptr(ep_num, TUSB_DIR_OUT); - if (ep_reg & USB_EP_SETUP) { - uint32_t count = btable_get_count(ep_id, BTABLE_BUF_RX); - // Setup packet should always be 8 bytes. If not, ignore it, and try again. - if (count == 8) { - uint16_t rx_addr = btable_get_addr(ep_id, BTABLE_BUF_RX); - uint8_t setup_packet[8] TU_ATTR_ALIGNED(4); - - dcd_read_packet_memory(setup_packet, rx_addr, 8); - dcd_event_setup_received(0, (uint8_t*) setup_packet, true); - - // Reset EP to NAK and set both toggle to 1 - ep_add_status(&ep_reg, TUSB_DIR_IN, EP_STAT_NAK); - ep_add_status(&ep_reg, TUSB_DIR_OUT, EP_STAT_NAK); - ep_add_dtog(&ep_reg, TUSB_DIR_IN, 1); - ep_add_dtog(&ep_reg, TUSB_DIR_OUT, 1); - } else { - // Missed an setup packet !!! - TU_BREAKPOINT(); - ep_reg &= USB_EPREG_MASK; // reversed all toggle - edpt0_prepare_setup(); - } + uint8_t buf_id; + if (is_iso) { + buf_id = (ep_reg & USB_EP_DTOG_RX) ? 0 : 1; // ISO are double buffered } else { - ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(TUSB_DIR_OUT); // reversed all toggle except RX Status - - bool const is_iso = ep_is_iso(ep_reg); - xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, TUSB_DIR_OUT); + buf_id = BTABLE_BUF_RX; + } + uint16_t const rx_count = btable_get_count(ep_id, buf_id); + uint16_t pma_addr = (uint16_t) btable_get_addr(ep_id, buf_id); - uint8_t buf_id; - if (is_iso) { - buf_id = (ep_reg & USB_EP_DTOG_RX) ? 0 : 1; // ISO are double buffered + if (rx_count != 0) { + if (xfer->ff) { + dcd_read_packet_memory_ff(xfer->ff, pma_addr, rx_count); } else { - buf_id = BTABLE_BUF_RX; - } - uint32_t rx_count = btable_get_count(ep_id, buf_id); - uint16_t pma_addr = (uint16_t) btable_get_addr(ep_id, buf_id); - - if (rx_count != 0) { - if (xfer->ff) { - dcd_read_packet_memory_ff(xfer->ff, pma_addr, rx_count); - } else { - dcd_read_packet_memory(xfer->buffer + xfer->queued_len, pma_addr, rx_count); - } - xfer->queued_len = (uint16_t)(xfer->queued_len + rx_count); + dcd_read_packet_memory(xfer->buffer + xfer->queued_len, pma_addr, rx_count); } + xfer->queued_len += rx_count; + } - if ((rx_count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) { - // all bytes received or short packet - ep_add_status(&ep_reg, TUSB_DIR_OUT, EP_STAT_NAK); - dcd_event_xfer_complete(0, ep_num, xfer->queued_len, XFER_RESULT_SUCCESS, true); - } else { - // Set endpoint active again for receiving more data. Note that isochronous endpoints stay active always - if (!is_iso) { - uint16_t const cnt = tu_min16(xfer->total_len - xfer->queued_len, xfer->max_packet_size); - btable_set_rx_bufsize(ep_id, BTABLE_BUF_RX, cnt); - } - ep_add_status(&ep_reg, TUSB_DIR_OUT, EP_STAT_VALID); + if ((rx_count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) { + // all bytes received or short packet + dcd_event_xfer_complete(0, ep_num, xfer->queued_len, XFER_RESULT_SUCCESS, true); + } else { + // Set endpoint active again for receiving more data. Note that isochronous endpoints stay active always + if (!is_iso) { + uint16_t const cnt = tu_min16(xfer->total_len - xfer->queued_len, xfer->max_packet_size); + btable_set_rx_bufsize(ep_id, BTABLE_BUF_RX, cnt); } + ep_add_status(&ep_reg, TUSB_DIR_OUT, EP_STAT_VALID); + ep_write(ep_id, ep_reg, false); } - - ep_write(ep_id, ep_reg); } void dcd_int_handler(uint8_t rhport) { @@ -406,10 +367,6 @@ void dcd_int_handler(uint8_t rhport) { // | USB_ISTR_SUSP | USB_ISTR_SOF | USB_ISTR_ESOF; // unused IRQs: (USB_ISTR_PMAOVR | USB_ISTR_ERR | USB_ISTR_L1REQ ) - // The ST driver loops here on the CTR bit, but that loop has been moved into the - // dcd_ep_ctr_handler(), so less need to loop here. The other interrupts shouldn't - // be triggered repeatedly. - /* Put SOF flag at the beginning of ISR in case to get least amount of jitter if it is used for timing purposes */ if (int_status & USB_ISTR_SOF) { FSDEV_REG->ISTR = (fsdev_bus_t)~USB_ISTR_SOF; @@ -455,17 +412,51 @@ void dcd_int_handler(uint8_t rhport) { FSDEV_REG->ISTR = (fsdev_bus_t)~USB_ISTR_ESOF; } +// if (int_status & (USB_ISTR_ERR | USB_ISTR_PMAOVR)) { +// TU_BREAKPOINT(); +// } + // loop to handle all pending CTR interrupts - while (int_status & USB_ISTR_CTR) { - uint32_t const ep_id = int_status & USB_ISTR_EP_ID; + while (FSDEV_REG->ISTR & USB_ISTR_CTR) { + // skip DIR bit, and use CTR TX/RX instead, since there is chance we have both TX/RX completed in one interrupt + uint32_t const ep_id = FSDEV_REG->ISTR & USB_ISTR_EP_ID; + uint32_t const ep_reg = ep_read(ep_id); + + if (ep_reg & USB_EP_CTR_RX) { + #ifdef FSDEV_BUS_32BIT + /* https://www.st.com/resource/en/errata_sheet/es0561-stm32h503cbebkbrb-device-errata-stmicroelectronics.pdf + * https://www.st.com/resource/en/errata_sheet/es0587-stm32u535xx-and-stm32u545xx-device-errata-stmicroelectronics.pdf + * From H503/U535 errata: Buffer description table update completes after CTR interrupt triggers + * Description: + * - During OUT transfers, the correct transfer interrupt (CTR) is triggered a little before the last USB SRAM accesses + * have completed. If the software responds quickly to the interrupt, the full buffer contents may not be correct. + * Workaround: + * - Software should ensure that a small delay is included before accessing the SRAM contents. This delay + * should be 800 ns in Full Speed mode and 6.4 μs in Low Speed mode + * - Since H5 can run up to 250Mhz -> 1 cycle = 4ns. Per errata, we need to wait 200 cycles. Though executing code + * also takes time, so we'll wait 60 cycles (count = 20). + * - Since Low Speed mode is not supported/popular, we will ignore it for now. + * + * Note: this errata may also apply to G0, U5, H5 etc. + */ + volatile uint32_t cycle_count = 20; // defined as PCD_RX_PMA_CNT in stm32 hal_driver + while (cycle_count > 0U) { + cycle_count--; // each count take 3 cycles (1 for sub, jump, and compare) + } + #endif - if ((int_status & USB_ISTR_DIR) == 0U) { - handle_ctr_tx(ep_id); // TX/IN - } else { - handle_ctr_rx(ep_id); // RX/OUT or both (RX/TX !!) + if (ep_reg & USB_EP_SETUP) { + handle_ctr_setup(ep_id); + } else { + ep_write_clear_ctr(ep_id, TUSB_DIR_OUT); + handle_ctr_rx(ep_id); + } } - int_status = FSDEV_REG->ISTR; + if (ep_reg & USB_EP_CTR_TX) { + ep_write_clear_ctr(ep_id, TUSB_DIR_IN); + handle_ctr_tx(ep_id); + } } } @@ -577,7 +568,7 @@ void edpt0_open(uint8_t rhport) { // no need to explicitly set DTOG bits since we aren't masked DTOG bit edpt0_prepare_setup(); // prepare for setup packet - ep_write(0, ep_reg); + ep_write(0, ep_reg, false); } bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) { @@ -590,7 +581,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) { TU_ASSERT(ep_idx < FSDEV_EP_COUNT); uint32_t ep_reg = ep_read(ep_idx) & ~USB_EPREG_MASK; - ep_reg |= tu_edpt_number(ep_addr) | USB_EP_CTR_RX | USB_EP_CTR_TX; + ep_reg |= tu_edpt_number(ep_addr) | USB_EP_CTR_TX | USB_EP_CTR_RX; // Set type switch (desc_ep->bmAttributes.xfer) { @@ -624,18 +615,17 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) { ep_reg &= ~(USB_EPTX_STAT | USB_EP_DTOG_TX); } - ep_write(ep_idx, ep_reg); + ep_write(ep_idx, ep_reg, true); return true; } -void dcd_edpt_close_all(uint8_t rhport) -{ - (void)rhport; +void dcd_edpt_close_all(uint8_t rhport) { + dcd_int_disable(rhport); for (uint32_t i = 1; i < FSDEV_EP_COUNT; i++) { // Reset endpoint - ep_write(i, 0); + ep_write(i, 0, false); // Clear EP allocation status ep_alloc_status[i].ep_num = 0xFF; ep_alloc_status[i].ep_type = 0xFF; @@ -643,6 +633,8 @@ void dcd_edpt_close_all(uint8_t rhport) ep_alloc_status[i].allocated[1] = false; } + dcd_int_enable(rhport); + // Reset PMA allocation ep_buf_ptr = FSDEV_BTABLE_BASE + 8 * CFG_TUD_ENDPPOINT_MAX + 2 * CFG_TUD_ENDPOINT0_SIZE; } @@ -684,13 +676,13 @@ bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) xfer->max_packet_size = tu_edpt_packet_size(desc_ep); uint32_t ep_reg = ep_read(ep_idx) & ~USB_EPREG_MASK; - ep_reg |= tu_edpt_number(ep_addr) | USB_EP_ISOCHRONOUS | USB_EP_CTR_RX | USB_EP_CTR_TX; + ep_reg |= tu_edpt_number(ep_addr) | USB_EP_ISOCHRONOUS | USB_EP_CTR_TX | USB_EP_CTR_RX; ep_add_status(&ep_reg, TUSB_DIR_IN, EP_STAT_DISABLED); ep_add_status(&ep_reg, TUSB_DIR_OUT, EP_STAT_DISABLED); ep_add_dtog(&ep_reg, dir, 0); ep_add_dtog(&ep_reg, 1-dir, 1); - ep_write(ep_idx, ep_reg); + ep_write(ep_idx, ep_reg, true); return true; } @@ -698,7 +690,9 @@ bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) // Currently, single-buffered, and only 64 bytes at a time (max) static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix) { uint16_t len = tu_min16(xfer->total_len - xfer->queued_len, xfer->max_packet_size); - uint32_t ep_reg = ep_read(ep_ix) | USB_EP_CTR_TX | USB_EP_CTR_RX; // reserve CTR bits + uint32_t ep_reg = ep_read(ep_ix) | USB_EP_CTR_TX | USB_EP_CTR_RX; // reserve CTR RX + ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(TUSB_DIR_IN); // only change TX Status, reserve other toggle bits + bool const is_iso = ep_is_iso(ep_reg); uint8_t buf_id; @@ -715,21 +709,16 @@ static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix) { } else { dcd_write_packet_memory(addr_ptr, &(xfer->buffer[xfer->queued_len]), len); } - xfer->queued_len = (uint16_t) (xfer->queued_len + len); + xfer->queued_len += len; } btable_set_count(ep_ix, buf_id, len); - - ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(TUSB_DIR_IN); ep_add_status(&ep_reg, TUSB_DIR_IN, EP_STAT_VALID); - ep_clear_ctr(&ep_reg, TUSB_DIR_IN); - dcd_int_disable(0); - ep_write(ep_ix, ep_reg); if (is_iso) { xfer->iso_in_sending = true; } - dcd_int_enable(0); + ep_write(ep_ix, ep_reg, true); } static bool edpt_xfer(uint8_t rhport, uint8_t ep_num, uint8_t dir) { @@ -741,8 +730,8 @@ static bool edpt_xfer(uint8_t rhport, uint8_t ep_num, uint8_t dir) { if (dir == TUSB_DIR_IN) { dcd_transmit_packet(xfer, ep_idx); } else { - uint32_t cnt = (uint32_t) tu_min16(xfer->total_len, xfer->max_packet_size); - uint32_t ep_reg = ep_read(ep_idx) | USB_EP_CTR_TX; // keep CTR TX, clear CTR RX + uint16_t cnt = tu_min16(xfer->total_len, xfer->max_packet_size); + uint32_t ep_reg = ep_read(ep_idx) | USB_EP_CTR_TX | USB_EP_CTR_RX; // keep CTR TX ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(dir); ep_add_status(&ep_reg, dir, EP_STAT_VALID); @@ -753,7 +742,7 @@ static bool edpt_xfer(uint8_t rhport, uint8_t ep_num, uint8_t dir) { btable_set_rx_bufsize(ep_idx, BTABLE_BUF_RX, cnt); } - ep_write(ep_idx, ep_reg); + ep_write(ep_idx, ep_reg, true); } return true; @@ -796,7 +785,7 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(dir); ep_add_status(&ep_reg, dir, EP_STAT_STALL); - ep_write(ep_idx, ep_reg); + ep_write(ep_idx, ep_reg, true); } void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { @@ -814,8 +803,7 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { ep_add_status(&ep_reg, dir, EP_STAT_NAK); } ep_add_dtog(&ep_reg, dir, 0); // Reset to DATA0 - - ep_write(ep_idx, ep_reg); + ep_write(ep_idx, ep_reg, true); } // Write to packet memory area (PMA) from user memory diff --git a/src/portable/st/stm32_fsdev/fsdev_type.h b/src/portable/st/stm32_fsdev/fsdev_type.h index 8432df4b0..f29abd703 100644 --- a/src/portable/st/stm32_fsdev/fsdev_type.h +++ b/src/portable/st/stm32_fsdev/fsdev_type.h @@ -172,8 +172,24 @@ typedef enum { // - DTOG and STAT are write 1 to toggle //--------------------------------------------------------------------+ -TU_ATTR_ALWAYS_INLINE static inline void ep_write(uint32_t ep_id, uint32_t value) { +TU_ATTR_ALWAYS_INLINE static inline void ep_write(uint32_t ep_id, uint32_t value, bool need_exclusive) { + if (need_exclusive) { + dcd_int_disable(0); + } + FSDEV_REG->ep[ep_id].reg = (fsdev_bus_t) value; + + if (need_exclusive) { + dcd_int_enable(0); + } +} + +TU_ATTR_ALWAYS_INLINE static inline void ep_write_clear_ctr(uint32_t ep_id, tusb_dir_t dir) { + uint32_t reg = FSDEV_REG->ep[ep_id].reg; + reg |= USB_EP_CTR_TX | USB_EP_CTR_RX; + reg &= USB_EPREG_MASK; + reg &= ~(1 << (USB_EP_CTR_TX_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); + ep_write(ep_id, reg, false); } TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_read(uint32_t ep_id) { @@ -188,10 +204,6 @@ TU_ATTR_ALWAYS_INLINE static inline void ep_add_dtog(uint32_t* reg, tusb_dir_t d *reg ^= (state << (USB_EP_DTOG_TX_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); } -TU_ATTR_ALWAYS_INLINE static inline void ep_clear_ctr(uint32_t* reg, tusb_dir_t dir) { - *reg &= ~(1 << (USB_EP_CTR_TX_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); -} - TU_ATTR_ALWAYS_INLINE static inline bool ep_is_iso(uint32_t reg) { return (reg & USB_EP_TYPE_MASK) == USB_EP_ISOCHRONOUS; } @@ -218,7 +230,7 @@ TU_ATTR_ALWAYS_INLINE static inline void btable_set_addr(uint32_t ep_id, uint8_t #endif } -TU_ATTR_ALWAYS_INLINE static inline uint32_t btable_get_count(uint32_t ep_id, uint8_t buf_id) { +TU_ATTR_ALWAYS_INLINE static inline uint16_t btable_get_count(uint32_t ep_id, uint8_t buf_id) { uint16_t count; #ifdef FSDEV_BUS_32BIT count = (FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr >> 16); @@ -258,7 +270,7 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t pma_align_buffer_size(uint16_t size return (*num_block) * block_in_bytes; } -TU_ATTR_ALWAYS_INLINE static inline void btable_set_rx_bufsize(uint32_t ep_id, uint8_t buf_id, uint32_t wCount) { +TU_ATTR_ALWAYS_INLINE static inline void btable_set_rx_bufsize(uint32_t ep_id, uint8_t buf_id, uint16_t wCount) { uint8_t blsize, num_block; (void) pma_align_buffer_size(wCount, &blsize, &num_block); -- cgit v1.3.1 From 0860cd3b5e95a7366bc2c68eb7648e8479059172 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 6 Aug 2024 22:20:24 +0700 Subject: minor rename --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 28 +++++++++++++-------------- src/portable/st/stm32_fsdev/fsdev_type.h | 4 ++-- 2 files changed, 16 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 97529997d..2075babe3 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -356,7 +356,7 @@ static void handle_ctr_rx(uint32_t ep_id) { uint16_t const cnt = tu_min16(xfer->total_len - xfer->queued_len, xfer->max_packet_size); btable_set_rx_bufsize(ep_id, BTABLE_BUF_RX, cnt); } - ep_add_status(&ep_reg, TUSB_DIR_OUT, EP_STAT_VALID); + ep_change_status(&ep_reg, TUSB_DIR_OUT, EP_STAT_VALID); ep_write(ep_id, ep_reg, false); } } @@ -563,8 +563,8 @@ void edpt0_open(uint8_t rhport) { uint32_t ep_reg = ep_read(0) & ~USB_EPREG_MASK; // only get toggle bits ep_reg |= USB_EP_CONTROL; - ep_add_status(&ep_reg, TUSB_DIR_IN, EP_STAT_NAK); - ep_add_status(&ep_reg, TUSB_DIR_OUT, EP_STAT_NAK); + ep_change_status(&ep_reg, TUSB_DIR_IN, EP_STAT_NAK); + ep_change_status(&ep_reg, TUSB_DIR_OUT, EP_STAT_NAK); // no need to explicitly set DTOG bits since we aren't masked DTOG bit edpt0_prepare_setup(); // prepare for setup packet @@ -605,8 +605,8 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) { xfer->max_packet_size = packet_size; xfer->ep_idx = ep_idx; - ep_add_status(&ep_reg, dir, EP_STAT_NAK); - ep_add_dtog(&ep_reg, dir, 0); + ep_change_status(&ep_reg, dir, EP_STAT_NAK); + ep_change_dtog(&ep_reg, dir, 0); // reserve other direction toggle bits if (dir == TUSB_DIR_IN) { @@ -677,10 +677,10 @@ bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) uint32_t ep_reg = ep_read(ep_idx) & ~USB_EPREG_MASK; ep_reg |= tu_edpt_number(ep_addr) | USB_EP_ISOCHRONOUS | USB_EP_CTR_TX | USB_EP_CTR_RX; - ep_add_status(&ep_reg, TUSB_DIR_IN, EP_STAT_DISABLED); - ep_add_status(&ep_reg, TUSB_DIR_OUT, EP_STAT_DISABLED); - ep_add_dtog(&ep_reg, dir, 0); - ep_add_dtog(&ep_reg, 1-dir, 1); + ep_change_status(&ep_reg, TUSB_DIR_IN, EP_STAT_DISABLED); + ep_change_status(&ep_reg, TUSB_DIR_OUT, EP_STAT_DISABLED); + ep_change_dtog(&ep_reg, dir, 0); + ep_change_dtog(&ep_reg, 1 - dir, 1); ep_write(ep_idx, ep_reg, true); @@ -713,7 +713,7 @@ static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix) { } btable_set_count(ep_ix, buf_id, len); - ep_add_status(&ep_reg, TUSB_DIR_IN, EP_STAT_VALID); + ep_change_status(&ep_reg, TUSB_DIR_IN, EP_STAT_VALID); if (is_iso) { xfer->iso_in_sending = true; @@ -733,7 +733,7 @@ static bool edpt_xfer(uint8_t rhport, uint8_t ep_num, uint8_t dir) { uint16_t cnt = tu_min16(xfer->total_len, xfer->max_packet_size); uint32_t ep_reg = ep_read(ep_idx) | USB_EP_CTR_TX | USB_EP_CTR_RX; // keep CTR TX ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(dir); - ep_add_status(&ep_reg, dir, EP_STAT_VALID); + ep_change_status(&ep_reg, dir, EP_STAT_VALID); if (ep_is_iso(ep_reg)) { btable_set_rx_bufsize(ep_idx, 0, cnt); @@ -783,7 +783,7 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { uint32_t ep_reg = ep_read(ep_idx) | USB_EP_CTR_TX | USB_EP_CTR_RX; // reserve CTR bits ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(dir); - ep_add_status(&ep_reg, dir, EP_STAT_STALL); + ep_change_status(&ep_reg, dir, EP_STAT_STALL); ep_write(ep_idx, ep_reg, true); } @@ -800,9 +800,9 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(dir) | EP_DTOG_MASK(dir); if (!ep_is_iso(ep_reg)) { - ep_add_status(&ep_reg, dir, EP_STAT_NAK); + ep_change_status(&ep_reg, dir, EP_STAT_NAK); } - ep_add_dtog(&ep_reg, dir, 0); // Reset to DATA0 + ep_change_dtog(&ep_reg, dir, 0); // Reset to DATA0 ep_write(ep_idx, ep_reg, true); } diff --git a/src/portable/st/stm32_fsdev/fsdev_type.h b/src/portable/st/stm32_fsdev/fsdev_type.h index f29abd703..d5028c702 100644 --- a/src/portable/st/stm32_fsdev/fsdev_type.h +++ b/src/portable/st/stm32_fsdev/fsdev_type.h @@ -196,11 +196,11 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_read(uint32_t ep_id) { return FSDEV_REG->ep[ep_id].reg; } -TU_ATTR_ALWAYS_INLINE static inline void ep_add_status(uint32_t* reg, tusb_dir_t dir, ep_stat_t state) { +TU_ATTR_ALWAYS_INLINE static inline void ep_change_status(uint32_t* reg, tusb_dir_t dir, ep_stat_t state) { *reg ^= (state << (USB_EPTX_STAT_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); } -TU_ATTR_ALWAYS_INLINE static inline void ep_add_dtog(uint32_t* reg, tusb_dir_t dir, uint8_t state) { +TU_ATTR_ALWAYS_INLINE static inline void ep_change_dtog(uint32_t* reg, tusb_dir_t dir, uint8_t state) { *reg ^= (state << (USB_EP_DTOG_TX_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); } -- cgit v1.3.1 From 3a2216306769f0af0ceb3dde7528dfb182fec8f5 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 7 Aug 2024 15:16:22 +0700 Subject: fix v203 race condition between rx bufsize and RX_STAT which cause PMAOVR fix set_rx_bufsize with invalid value for zero length packet --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 28 ++++++++++++++++----------- src/portable/st/stm32_fsdev/fsdev_type.h | 17 ++++++++++------ 2 files changed, 28 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 2075babe3..cd7410488 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -217,8 +217,8 @@ void dcd_init(uint8_t rhport) { ep_write(i, 0u, false); } - FSDEV_REG->CNTR |= USB_CNTR_RESETM | USB_CNTR_ESOFM | USB_CNTR_CTRM | USB_CNTR_SUSPM | USB_CNTR_WKUPM; - //| USB_CNTR_ERRM | USB_CNTR_PMAOVRM; + FSDEV_REG->CNTR |= USB_CNTR_RESETM | USB_CNTR_ESOFM | USB_CNTR_CTRM | + USB_CNTR_SUSPM | USB_CNTR_WKUPM | USB_CNTR_PMAOVRM; handle_bus_reset(rhport); // Enable pull-up if supported @@ -349,6 +349,10 @@ static void handle_ctr_rx(uint32_t ep_id) { if ((rx_count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) { // all bytes received or short packet + + // reset rx bufsize to mps to prevent race condition to cause PMAOVR (occurs with ch32v203 with msc write10) + btable_set_rx_bufsize(ep_id, BTABLE_BUF_RX, xfer->max_packet_size); + dcd_event_xfer_complete(0, ep_num, xfer->queued_len, XFER_RESULT_SUCCESS, true); } else { // Set endpoint active again for receiving more data. Note that isochronous endpoints stay active always @@ -412,9 +416,10 @@ void dcd_int_handler(uint8_t rhport) { FSDEV_REG->ISTR = (fsdev_bus_t)~USB_ISTR_ESOF; } -// if (int_status & (USB_ISTR_ERR | USB_ISTR_PMAOVR)) { -// TU_BREAKPOINT(); -// } + if (int_status & USB_ISTR_PMAOVR) { + TU_BREAKPOINT(); + FSDEV_REG->ISTR = (fsdev_bus_t)~USB_ISTR_PMAOVR; + } // loop to handle all pending CTR interrupts while (FSDEV_REG->ISTR & USB_ISTR_CTR) { @@ -446,7 +451,7 @@ void dcd_int_handler(uint8_t rhport) { #endif if (ep_reg & USB_EP_SETUP) { - handle_ctr_setup(ep_id); + handle_ctr_setup(ep_id); // CTR will be clear after copied setup packet } else { ep_write_clear_ctr(ep_id, TUSB_DIR_OUT); handle_ctr_rx(ep_id); @@ -690,7 +695,7 @@ bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) // Currently, single-buffered, and only 64 bytes at a time (max) static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix) { uint16_t len = tu_min16(xfer->total_len - xfer->queued_len, xfer->max_packet_size); - uint32_t ep_reg = ep_read(ep_ix) | USB_EP_CTR_TX | USB_EP_CTR_RX; // reserve CTR RX + uint32_t ep_reg = ep_read(ep_ix) | USB_EP_CTR_TX | USB_EP_CTR_RX; // reserve CTR ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(TUSB_DIR_IN); // only change TX Status, reserve other toggle bits bool const is_iso = ep_is_iso(ep_reg); @@ -730,10 +735,10 @@ static bool edpt_xfer(uint8_t rhport, uint8_t ep_num, uint8_t dir) { if (dir == TUSB_DIR_IN) { dcd_transmit_packet(xfer, ep_idx); } else { - uint16_t cnt = tu_min16(xfer->total_len, xfer->max_packet_size); - uint32_t ep_reg = ep_read(ep_idx) | USB_EP_CTR_TX | USB_EP_CTR_RX; // keep CTR TX + uint32_t ep_reg = ep_read(ep_idx) | USB_EP_CTR_TX | USB_EP_CTR_RX; // reserve CTR ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(dir); - ep_change_status(&ep_reg, dir, EP_STAT_VALID); + + uint16_t cnt = tu_min16(xfer->total_len, xfer->max_packet_size); if (ep_is_iso(ep_reg)) { btable_set_rx_bufsize(ep_idx, 0, cnt); @@ -742,7 +747,8 @@ static bool edpt_xfer(uint8_t rhport, uint8_t ep_num, uint8_t dir) { btable_set_rx_bufsize(ep_idx, BTABLE_BUF_RX, cnt); } - ep_write(ep_idx, ep_reg, true); + ep_change_status(&ep_reg, dir, EP_STAT_VALID); + ep_write(ep_idx, ep_reg, false); } return true; diff --git a/src/portable/st/stm32_fsdev/fsdev_type.h b/src/portable/st/stm32_fsdev/fsdev_type.h index d5028c702..6c5ccae89 100644 --- a/src/portable/st/stm32_fsdev/fsdev_type.h +++ b/src/portable/st/stm32_fsdev/fsdev_type.h @@ -172,6 +172,10 @@ typedef enum { // - DTOG and STAT are write 1 to toggle //--------------------------------------------------------------------+ +TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_read(uint32_t ep_id) { + return FSDEV_REG->ep[ep_id].reg; +} + TU_ATTR_ALWAYS_INLINE static inline void ep_write(uint32_t ep_id, uint32_t value, bool need_exclusive) { if (need_exclusive) { dcd_int_disable(0); @@ -192,10 +196,6 @@ TU_ATTR_ALWAYS_INLINE static inline void ep_write_clear_ctr(uint32_t ep_id, tusb ep_write(ep_id, reg, false); } -TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_read(uint32_t ep_id) { - return FSDEV_REG->ep[ep_id].reg; -} - TU_ATTR_ALWAYS_INLINE static inline void ep_change_status(uint32_t* reg, tusb_dir_t dir, ep_stat_t state) { *reg ^= (state << (USB_EPTX_STAT_Pos + (dir == TUSB_DIR_IN ? 0 : 8))); } @@ -260,13 +260,13 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t pma_align_buffer_size(uint16_t size if (size > 62) { block_in_bytes = 32; *blsize = 1; + *num_block = tu_div_ceil(size, 32); } else { block_in_bytes = 2; *blsize = 0; + *num_block = tu_div_ceil(size, 2); } - *num_block = tu_div_ceil(size, block_in_bytes); - return (*num_block) * block_in_bytes; } @@ -276,6 +276,10 @@ TU_ATTR_ALWAYS_INLINE static inline void btable_set_rx_bufsize(uint32_t ep_id, u /* Encode into register. When BLSIZE==1, we need to subtract 1 block count */ uint16_t bl_nb = (blsize << 15) | ((num_block - blsize) << 10); + if (bl_nb == 0) { + // 0 is invalid, set up blsize to 1 + bl_nb = 1 << 15; + } #ifdef FSDEV_BUS_32BIT uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr; @@ -284,6 +288,7 @@ TU_ATTR_ALWAYS_INLINE static inline void btable_set_rx_bufsize(uint32_t ep_id, u #else FSDEV_BTABLE->ep16[ep_id][buf_id].count = bl_nb; #endif + } #ifdef __cplusplus -- cgit v1.3.1 From 57c26fdc72dccee1da569e90f46b4060a97d47a7 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 8 Aug 2024 00:27:51 +0700 Subject: use EP_KIND for STATUS OUT to fix OUT packet is auto accepted after SETUP without usbd consent --- .idea/cmake.xml | 15 +++++------ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 36 +++++++++++++++++---------- src/portable/st/stm32_fsdev/fsdev_type.h | 4 +-- 3 files changed, 33 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/.idea/cmake.xml b/.idea/cmake.xml index 67e793016..bf5696725 100644 --- a/.idea/cmake.xml +++ b/.idea/cmake.xml @@ -89,19 +89,20 @@ - - + + + - + - + - + @@ -133,8 +134,8 @@ - - + + diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index cd7410488..89697106d 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -147,6 +147,7 @@ typedef struct { static xfer_ctl_t xfer_status[CFG_TUD_ENDPPOINT_MAX][2]; static ep_alloc_t ep_alloc_status[FSDEV_EP_COUNT]; static uint8_t remoteWakeCountdown; // When wake is requested +static uint8_t _setup_dir; // for detecting status OUT //--------------------------------------------------------------------+ // Prototypes @@ -311,6 +312,7 @@ static void handle_ctr_setup(uint32_t ep_id) { // Setup packet should always be 8 bytes. If not, we probably missed the packet if (rx_count == 8) { + _setup_dir = (setup_packet[0] & 0x80 ? TUSB_DIR_IN : TUSB_DIR_OUT); dcd_event_setup_received(0, (uint8_t*) setup_packet, true); // Hardware should reset EP0 RX/TX to NAK and both toggle to 1 } else { @@ -323,8 +325,6 @@ static void handle_ctr_setup(uint32_t ep_id) { // Handle CTR interrupt for the RX/OUT direction static void handle_ctr_rx(uint32_t ep_id) { uint32_t ep_reg = ep_read(ep_id) | USB_EP_CTR_TX | USB_EP_CTR_RX; - ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(TUSB_DIR_OUT); // will change RX Status, reserved other toggle bits - uint8_t const ep_num = ep_reg & USB_EPADDR_FIELD; bool const is_iso = ep_is_iso(ep_reg); xfer_ctl_t* xfer = xfer_ctl_ptr(ep_num, TUSB_DIR_OUT); @@ -345,6 +345,13 @@ static void handle_ctr_rx(uint32_t ep_id) { dcd_read_packet_memory(xfer->buffer + xfer->queued_len, pma_addr, rx_count); } xfer->queued_len += rx_count; + } else { + // ZLP Status OUT + if (ep_num == 0 && (ep_reg & USB_EP_KIND) ) { + ep_reg &= USB_EPREG_MASK; + ep_reg &= ~USB_EP_KIND; // clear kind bit + ep_write(ep_id, ep_reg, false); + } } if ((rx_count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) { @@ -360,6 +367,7 @@ static void handle_ctr_rx(uint32_t ep_id) { uint16_t const cnt = tu_min16(xfer->total_len - xfer->queued_len, xfer->max_packet_size); btable_set_rx_bufsize(ep_id, BTABLE_BUF_RX, cnt); } + ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(TUSB_DIR_OUT); // will change RX Status, reserved other toggle bits ep_change_status(&ep_reg, TUSB_DIR_OUT, EP_STAT_VALID); ep_write(ep_id, ep_reg, false); } @@ -367,9 +375,6 @@ static void handle_ctr_rx(uint32_t ep_id) { void dcd_int_handler(uint8_t rhport) { uint32_t int_status = FSDEV_REG->ISTR; - // const uint32_t handled_ints = USB_ISTR_CTR | USB_ISTR_RESET | USB_ISTR_WKUP - // | USB_ISTR_SUSP | USB_ISTR_SOF | USB_ISTR_ESOF; - // unused IRQs: (USB_ISTR_PMAOVR | USB_ISTR_ERR | USB_ISTR_L1REQ ) /* Put SOF flag at the beginning of ISR in case to get least amount of jitter if it is used for timing purposes */ if (int_status & USB_ISTR_SOF) { @@ -738,17 +743,22 @@ static bool edpt_xfer(uint8_t rhport, uint8_t ep_num, uint8_t dir) { uint32_t ep_reg = ep_read(ep_idx) | USB_EP_CTR_TX | USB_EP_CTR_RX; // reserve CTR ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(dir); - uint16_t cnt = tu_min16(xfer->total_len, xfer->max_packet_size); - - if (ep_is_iso(ep_reg)) { - btable_set_rx_bufsize(ep_idx, 0, cnt); - btable_set_rx_bufsize(ep_idx, 1, cnt); + if ( ep_num == 0 && dir == TUSB_DIR_OUT && _setup_dir == TUSB_DIR_IN ) { + // use EP0 OUT status stage, otherwise OUT packet right after SETUP will be accepted without + // the usbd (software) consent + ep_reg |= USB_EP_KIND; } else { - btable_set_rx_bufsize(ep_idx, BTABLE_BUF_RX, cnt); - } + uint16_t cnt = tu_min16(xfer->total_len, xfer->max_packet_size); + if (ep_is_iso(ep_reg)) { + btable_set_rx_bufsize(ep_idx, 0, cnt); + btable_set_rx_bufsize(ep_idx, 1, cnt); + } else { + btable_set_rx_bufsize(ep_idx, BTABLE_BUF_RX, cnt); + } + } ep_change_status(&ep_reg, dir, EP_STAT_VALID); - ep_write(ep_idx, ep_reg, false); + ep_write(ep_idx, ep_reg, true); } return true; diff --git a/src/portable/st/stm32_fsdev/fsdev_type.h b/src/portable/st/stm32_fsdev/fsdev_type.h index 6c5ccae89..7ebc32255 100644 --- a/src/portable/st/stm32_fsdev/fsdev_type.h +++ b/src/portable/st/stm32_fsdev/fsdev_type.h @@ -277,8 +277,8 @@ TU_ATTR_ALWAYS_INLINE static inline void btable_set_rx_bufsize(uint32_t ep_id, u /* Encode into register. When BLSIZE==1, we need to subtract 1 block count */ uint16_t bl_nb = (blsize << 15) | ((num_block - blsize) << 10); if (bl_nb == 0) { - // 0 is invalid, set up blsize to 1 - bl_nb = 1 << 15; + // zlp but 0 is invalid value, set num_block to 1 (2 bytes) + bl_nb = 1 << 10; } #ifdef FSDEV_BUS_32BIT -- cgit v1.3.1 From bd64625df271c461c3d6008f96c630c61218f451 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 8 Aug 2024 12:40:11 +0700 Subject: revert the use of EP_KIND. ch32v203 seems to unconditionally accept ZLP on EP0 OUT, which can incorrectly use queued_len of previous transfer. So reset total_len and queued_len to 0. --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 38 +++++++++------------------ 1 file changed, 13 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 89697106d..bbdfbaa09 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -147,7 +147,6 @@ typedef struct { static xfer_ctl_t xfer_status[CFG_TUD_ENDPPOINT_MAX][2]; static ep_alloc_t ep_alloc_status[FSDEV_EP_COUNT]; static uint8_t remoteWakeCountdown; // When wake is requested -static uint8_t _setup_dir; // for detecting status OUT //--------------------------------------------------------------------+ // Prototypes @@ -312,7 +311,6 @@ static void handle_ctr_setup(uint32_t ep_id) { // Setup packet should always be 8 bytes. If not, we probably missed the packet if (rx_count == 8) { - _setup_dir = (setup_packet[0] & 0x80 ? TUSB_DIR_IN : TUSB_DIR_OUT); dcd_event_setup_received(0, (uint8_t*) setup_packet, true); // Hardware should reset EP0 RX/TX to NAK and both toggle to 1 } else { @@ -345,22 +343,17 @@ static void handle_ctr_rx(uint32_t ep_id) { dcd_read_packet_memory(xfer->buffer + xfer->queued_len, pma_addr, rx_count); } xfer->queued_len += rx_count; - } else { - // ZLP Status OUT - if (ep_num == 0 && (ep_reg & USB_EP_KIND) ) { - ep_reg &= USB_EPREG_MASK; - ep_reg &= ~USB_EP_KIND; // clear kind bit - ep_write(ep_id, ep_reg, false); - } } - if ((rx_count < xfer->max_packet_size) || (xfer->queued_len == xfer->total_len)) { + if ((rx_count < xfer->max_packet_size) || (xfer->queued_len >= xfer->total_len)) { // all bytes received or short packet + dcd_event_xfer_complete(0, ep_num, xfer->queued_len, XFER_RESULT_SUCCESS, true); - // reset rx bufsize to mps to prevent race condition to cause PMAOVR (occurs with ch32v203 with msc write10) + // For ch32v203: reset rx bufsize to mps to prevent race condition to cause PMAOVR (occurs with msc write10) + // also ch32 seems to unconditionally accept ZLP on EP0 OUT, which can incorrectly use queued_len of previous + // transfer. So reset total_len and queued_len to 0. btable_set_rx_bufsize(ep_id, BTABLE_BUF_RX, xfer->max_packet_size); - - dcd_event_xfer_complete(0, ep_num, xfer->queued_len, XFER_RESULT_SUCCESS, true); + xfer->total_len = xfer->queued_len = 0; } else { // Set endpoint active again for receiving more data. Note that isochronous endpoints stay active always if (!is_iso) { @@ -743,20 +736,15 @@ static bool edpt_xfer(uint8_t rhport, uint8_t ep_num, uint8_t dir) { uint32_t ep_reg = ep_read(ep_idx) | USB_EP_CTR_TX | USB_EP_CTR_RX; // reserve CTR ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(dir); - if ( ep_num == 0 && dir == TUSB_DIR_OUT && _setup_dir == TUSB_DIR_IN ) { - // use EP0 OUT status stage, otherwise OUT packet right after SETUP will be accepted without - // the usbd (software) consent - ep_reg |= USB_EP_KIND; - } else { - uint16_t cnt = tu_min16(xfer->total_len, xfer->max_packet_size); + uint16_t cnt = tu_min16(xfer->total_len, xfer->max_packet_size); - if (ep_is_iso(ep_reg)) { - btable_set_rx_bufsize(ep_idx, 0, cnt); - btable_set_rx_bufsize(ep_idx, 1, cnt); - } else { - btable_set_rx_bufsize(ep_idx, BTABLE_BUF_RX, cnt); - } + if (ep_is_iso(ep_reg)) { + btable_set_rx_bufsize(ep_idx, 0, cnt); + btable_set_rx_bufsize(ep_idx, 1, cnt); + } else { + btable_set_rx_bufsize(ep_idx, BTABLE_BUF_RX, cnt); } + ep_change_status(&ep_reg, dir, EP_STAT_VALID); ep_write(ep_idx, ep_reg, true); } -- cgit v1.3.1 From 1ea38ebe13f07c4db99ae39f207e55815d3701b3 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 8 Aug 2024 15:43:11 +0700 Subject: refactor read/write pma from/to fifo --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 247 ++++++++++---------------- src/portable/st/stm32_fsdev/fsdev_type.h | 8 + 2 files changed, 98 insertions(+), 157 deletions(-) (limited to 'src') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index bbdfbaa09..252969648 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -336,14 +336,12 @@ static void handle_ctr_rx(uint32_t ep_id) { uint16_t const rx_count = btable_get_count(ep_id, buf_id); uint16_t pma_addr = (uint16_t) btable_get_addr(ep_id, buf_id); - if (rx_count != 0) { - if (xfer->ff) { - dcd_read_packet_memory_ff(xfer->ff, pma_addr, rx_count); - } else { - dcd_read_packet_memory(xfer->buffer + xfer->queued_len, pma_addr, rx_count); - } - xfer->queued_len += rx_count; + if (xfer->ff) { + dcd_read_packet_memory_ff(xfer->ff, pma_addr, rx_count); + } else { + dcd_read_packet_memory(xfer->buffer + xfer->queued_len, pma_addr, rx_count); } + xfer->queued_len += rx_count; if ((rx_count < xfer->max_packet_size) || (xfer->queued_len >= xfer->total_len)) { // all bytes received or short packet @@ -706,14 +704,12 @@ static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix) { } uint16_t addr_ptr = (uint16_t) btable_get_addr(ep_ix, buf_id); - if (len) { - if (xfer->ff) { - dcd_write_packet_memory_ff(xfer->ff, addr_ptr, len); - } else { - dcd_write_packet_memory(addr_ptr, &(xfer->buffer[xfer->queued_len]), len); - } - xfer->queued_len += len; + if (xfer->ff) { + dcd_write_packet_memory_ff(xfer->ff, addr_ptr, len); + } else { + dcd_write_packet_memory(addr_ptr, &(xfer->buffer[xfer->queued_len]), len); } + xfer->queued_len += len; btable_set_count(ep_ix, buf_id, len); ep_change_status(&ep_reg, TUSB_DIR_IN, EP_STAT_VALID); @@ -814,25 +810,20 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { // - Packet memory must be either strictly 16-bit or 32-bit depending on FSDEV_BUS_32BIT // - Uses unaligned for RAM (since M0 cannot access unaligned address) static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t nbytes) { - enum { BUS_SIZE = sizeof(fsdev_bus_t) }; - uint32_t n_write = nbytes / BUS_SIZE; + if (nbytes == 0) return true; + uint32_t n_write = nbytes / FSDEV_BUS_SIZE; fsdev_pma_buf_t* pma_buf = PMA_BUF_AT(dst); const uint8_t *src8 = src; while (n_write--) { - #ifdef FSDEV_BUS_32BIT - pma_buf->value = tu_unaligned_read32(src8); - #else - pma_buf->value = tu_unaligned_read16(src8); - #endif - - src8 += BUS_SIZE; + pma_buf->value = fsdevbus_unaligned_read(src8); + src8 += FSDEV_BUS_SIZE; pma_buf++; } // odd bytes e.g 1 for 16-bit or 1-3 for 32-bit - uint16_t odd = nbytes & (BUS_SIZE - 1); + uint16_t odd = nbytes & (FSDEV_BUS_SIZE - 1); if (odd) { fsdev_bus_t temp = 0; for(uint16_t i = 0; i < odd; i++) { @@ -848,27 +839,20 @@ static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, ui // - Packet memory must be either strictly 16-bit or 32-bit depending on FSDEV_BUS_32BIT // - Uses unaligned for RAM (since M0 cannot access unaligned address) static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t nbytes) { - enum { BUS_SIZE = sizeof(fsdev_bus_t) }; - uint32_t n_write = nbytes / BUS_SIZE; + if (nbytes == 0) return true; + uint32_t n_read = nbytes / FSDEV_BUS_SIZE; fsdev_pma_buf_t* pma_buf = PMA_BUF_AT(src); uint8_t *dst8 = (uint8_t *)dst; - while (n_write--) { - fsdev_bus_t temp = pma_buf->value; - - #ifdef FSDEV_BUS_32BIT - tu_unaligned_write32(dst8, temp); - #else - tu_unaligned_write16(dst8, temp); - #endif - - dst8 += BUS_SIZE; + while (n_read--) { + fsdevbus_unaligned_write(dst8, (fsdev_bus_t ) pma_buf->value); + dst8 += FSDEV_BUS_SIZE; pma_buf++; } // odd bytes e.g 1 for 16-bit or 1-3 for 32-bit - uint16_t odd = nbytes & (BUS_SIZE - 1); + uint16_t odd = nbytes & (FSDEV_BUS_SIZE - 1); if (odd) { fsdev_bus_t temp = pma_buf->value; while (odd--) { @@ -880,156 +864,105 @@ static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t return true; } -/** - * @brief Copy from FIFO to packet memory area (PMA). - * Uses byte-access of system memory and 16-bit access of packet memory - * @param wNBytes no. of bytes to be copied. - * @retval None - */ +// Write to PMA from FIFO static bool dcd_write_packet_memory_ff(tu_fifo_t *ff, uint16_t dst, uint16_t wNBytes) { + if (wNBytes == 0) return true; + // Since we copy from a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies tu_fifo_buffer_info_t info; tu_fifo_get_read_info(ff, &info); - uint16_t cnt_lin = TU_MIN(wNBytes, info.len_lin); - uint16_t cnt_wrap = TU_MIN(wNBytes - cnt_lin, info.len_wrap); + uint16_t cnt_lin = tu_min16(wNBytes, info.len_lin); + uint16_t cnt_wrap = tu_min16(wNBytes - cnt_lin, info.len_wrap); + uint16_t const cnt_total = cnt_lin + cnt_wrap; // We want to read from the FIFO and write it into the PMA, if LIN part is ODD and has WRAPPED part, - // last lin byte will be combined with wrapped part - // To ensure PMA is always access aligned (dst aligned to 16 or 32 bit) -#ifdef FSDEV_BUS_32BIT - if ((cnt_lin & 0x03) && cnt_wrap) { - // Copy first linear part - dcd_write_packet_memory(dst, info.ptr_lin, cnt_lin & ~0x03); - dst += cnt_lin & ~0x03; - - // Copy last linear bytes & first wrapped bytes to buffer - uint32_t i; - uint8_t tmp[4]; - for (i = 0; i < (cnt_lin & 0x03); i++) { - tmp[i] = ((uint8_t *)info.ptr_lin)[(cnt_lin & ~0x03) + i]; - } - uint32_t wCnt = cnt_wrap; - for (; i < 4 && wCnt > 0; i++, wCnt--) { - tmp[i] = *(uint8_t *)info.ptr_wrap; - info.ptr_wrap = (uint8_t *)info.ptr_wrap + 1; + // last lin byte will be combined with wrapped part To ensure PMA is always access aligned + uint16_t lin_even = cnt_lin & ~(FSDEV_BUS_SIZE - 1); + uint16_t lin_odd = cnt_lin & (FSDEV_BUS_SIZE - 1); + uint8_t const *src8 = (uint8_t const*) info.ptr_lin; + + // write even linear part + dcd_write_packet_memory(dst, src8, lin_even); + dst += lin_even; + src8 += lin_even; + + if (lin_odd == 0) { + src8 = (uint8_t const*) info.ptr_wrap; + } else { + // Combine last linear bytes + first wrapped bytes to form fsdev bus width data + fsdev_bus_t temp = 0; + uint16_t i; + for(i = 0; i < lin_odd; i++) { + temp |= *src8++ << (i * 8); } - // Write unaligned buffer - dcd_write_packet_memory(dst, &tmp, 4); - dst += 4; - - // Copy rest of wrapped byte - if (wCnt) { - dcd_write_packet_memory(dst, info.ptr_wrap, wCnt); - } - } -#else - if ((cnt_lin & 0x01) && cnt_wrap) { - // Copy first linear part - dcd_write_packet_memory(dst, info.ptr_lin, cnt_lin & ~0x01); - dst += cnt_lin & ~0x01; - - // Copy last linear byte & first wrapped byte - uint16_t tmp = ((uint8_t *)info.ptr_lin)[cnt_lin - 1] | ((uint16_t)(((uint8_t *)info.ptr_wrap)[0]) << 8U); - dcd_write_packet_memory(dst, &tmp, 2); - dst += 2; - - // Copy rest of wrapped byte - dcd_write_packet_memory(dst, ((uint8_t *)info.ptr_wrap) + 1, cnt_wrap - 1); - } -#endif - else { - // Copy linear part - dcd_write_packet_memory(dst, info.ptr_lin, cnt_lin); - dst += info.len_lin; - - if (info.len_wrap) { - // Copy wrapped byte - dcd_write_packet_memory(dst, info.ptr_wrap, cnt_wrap); + src8 = (uint8_t const*) info.ptr_wrap; + for(; i < FSDEV_BUS_SIZE && cnt_wrap > 0; i++, cnt_wrap--) { + temp |= *src8++ << (i * 8); } + + dcd_write_packet_memory(dst, &temp, FSDEV_BUS_SIZE); + dst += FSDEV_BUS_SIZE; } - tu_fifo_advance_read_pointer(ff, cnt_lin + cnt_wrap); + // write the rest of the wrapped part + dcd_write_packet_memory(dst, src8, cnt_wrap); + tu_fifo_advance_read_pointer(ff, cnt_total); return true; } -/** - * @brief Copy a buffer from user packet memory area (PMA) to FIFO. - * Uses byte-access of system memory and 16-bit access of packet memory - * @param wNBytes no. of bytes to be copied. - * @retval None - */ +// Read from PMA to FIFO static bool dcd_read_packet_memory_ff(tu_fifo_t *ff, uint16_t src, uint16_t wNBytes) { + if (wNBytes == 0) return true; + // Since we copy into a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies // Check for first linear part tu_fifo_buffer_info_t info; tu_fifo_get_write_info(ff, &info); // We want to read from the FIFO - uint16_t cnt_lin = TU_MIN(wNBytes, info.len_lin); - uint16_t cnt_wrap = TU_MIN(wNBytes - cnt_lin, info.len_wrap); - - // We want to read from PMA and write it into the FIFO, if LIN part is ODD and has WRAPPED part, - // last lin byte will be combined with wrapped part - // To ensure PMA is always access aligned (src aligned to 16 or 32 bit) -#ifdef FSDEV_BUS_32BIT - if ((cnt_lin & 0x03) && cnt_wrap) { - // Copy first linear part - dcd_read_packet_memory(info.ptr_lin, src, cnt_lin & ~0x03); - src += cnt_lin & ~0x03; - - // Copy last linear bytes & first wrapped bytes - uint8_t tmp[4]; - dcd_read_packet_memory(tmp, src, 4); - src += 4; - - uint32_t i; - for (i = 0; i < (cnt_lin & 0x03); i++) { - ((uint8_t *)info.ptr_lin)[(cnt_lin & ~0x03) + i] = tmp[i]; - } - uint32_t wCnt = cnt_wrap; - for (; i < 4 && wCnt > 0; i++, wCnt--) { - *(uint8_t *)info.ptr_wrap = tmp[i]; - info.ptr_wrap = (uint8_t *)info.ptr_wrap + 1; - } + uint16_t cnt_lin = tu_min16(wNBytes, info.len_lin); + uint16_t cnt_wrap = tu_min16(wNBytes - cnt_lin, info.len_wrap); + uint16_t cnt_total = cnt_lin + cnt_wrap; - // Copy rest of wrapped byte - if (wCnt) { - dcd_read_packet_memory(info.ptr_wrap, src, wCnt); - } - } -#else - if ((cnt_lin & 0x01) && cnt_wrap) { - // Copy first linear part - dcd_read_packet_memory(info.ptr_lin, src, cnt_lin & ~0x01); - src += cnt_lin & ~0x01; + // We want to read from the FIFO and write it into the PMA, if LIN part is ODD and has WRAPPED part, + // last lin byte will be combined with wrapped part To ensure PMA is always access aligned - // Copy last linear byte & first wrapped byte - uint8_t tmp[2]; - dcd_read_packet_memory(tmp, src, 2); - src += 2; + uint16_t lin_even = cnt_lin & ~(FSDEV_BUS_SIZE - 1); + uint16_t lin_odd = cnt_lin & (FSDEV_BUS_SIZE - 1); + uint8_t *dst8 = (uint8_t *) info.ptr_lin; - ((uint8_t *)info.ptr_lin)[cnt_lin - 1] = tmp[0]; - ((uint8_t *)info.ptr_wrap)[0] = tmp[1]; + // read even linear part + dcd_read_packet_memory(dst8, src, lin_even); + dst8 += lin_even; + src += lin_even; - // Copy rest of wrapped byte - dcd_read_packet_memory(((uint8_t *)info.ptr_wrap) + 1, src, cnt_wrap - 1); - } -#endif - else { - // Copy linear part - dcd_read_packet_memory(info.ptr_lin, src, cnt_lin); - src += cnt_lin; - - if (info.len_wrap) { - // Copy wrapped byte - dcd_read_packet_memory(info.ptr_wrap, src, cnt_wrap); + if (lin_odd == 0) { + dst8 = (uint8_t *) info.ptr_wrap; + } else { + // Combine last linear bytes + first wrapped bytes to form fsdev bus width data + fsdev_bus_t temp; + dcd_read_packet_memory(&temp, src, FSDEV_BUS_SIZE); + src += FSDEV_BUS_SIZE; + + uint16_t i; + for (i = 0; i < lin_odd; i++) { + *dst8++ = (uint8_t) (temp & 0xfful); + temp >>= 8; + } + + dst8 = (uint8_t *) info.ptr_wrap; + for (; i < FSDEV_BUS_SIZE && cnt_wrap > 0; i++, cnt_wrap--) { + *dst8++ = (uint8_t) (temp & 0xfful); + temp >>= 8; } } - tu_fifo_advance_write_pointer(ff, cnt_lin + cnt_wrap); + // read the rest of the wrapped part + dcd_read_packet_memory(dst8, src, cnt_wrap); + tu_fifo_advance_write_pointer(ff, cnt_total); return true; } diff --git a/src/portable/st/stm32_fsdev/fsdev_type.h b/src/portable/st/stm32_fsdev/fsdev_type.h index 7ebc32255..26717fab0 100644 --- a/src/portable/st/stm32_fsdev/fsdev_type.h +++ b/src/portable/st/stm32_fsdev/fsdev_type.h @@ -66,10 +66,18 @@ TU_VERIFY_STATIC(FSDEV_BTABLE_BASE % 8 == 0, "BTABLE base must be aligned to 8 b // The fsdev_bus_t type can be used for both register and PMA access necessities #ifdef FSDEV_BUS_32BIT typedef uint32_t fsdev_bus_t; + #define fsdevbus_unaligned_read(_addr) tu_unaligned_read32(_addr) + #define fsdevbus_unaligned_write(_addr, _value) tu_unaligned_write32(_addr, _value) #else typedef uint16_t fsdev_bus_t; + #define fsdevbus_unaligned_read(_addr) tu_unaligned_read16(_addr) + #define fsdevbus_unaligned_write(_addr, _value) tu_unaligned_write16(_addr, _value) #endif +enum { + FSDEV_BUS_SIZE = sizeof(fsdev_bus_t), +}; + //--------------------------------------------------------------------+ // BTable Typedef //--------------------------------------------------------------------+ -- cgit v1.3.1 From 00eb0144cbb11d1c37dcce5cd8ba8afe10e1b6b5 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Thu, 8 Aug 2024 12:55:30 -0700 Subject: Fix ESPs without device support The newer tusb_option.h assumes that there is a number of device endpoints to check against. --- src/common/tusb_mcu.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 637281bfc..e3ad0f627 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -336,8 +336,11 @@ #define TUP_USBIP_DWC2 #define TUP_DCD_ENDPOINT_MAX 6 -#elif TU_CHECK_MCU(OPT_MCU_ESP32, OPT_MCU_ESP32C2, OPT_MCU_ESP32C3, OPT_MCU_ESP32C6, OPT_MCU_ESP32H2) && (CFG_TUD_ENABLED || !(defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421)) +#elif TU_CHECK_MCU(OPT_MCU_ESP32, OPT_MCU_ESP32C2, OPT_MCU_ESP32C3, OPT_MCU_ESP32C6, OPT_MCU_ESP32H2) + #if (CFG_TUD_ENABLED || !(defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421)) #error "MCUs are only supported with CFG_TUH_MAX3421 enabled" + #endif + #define TUP_DCD_ENDPOINT_MAX 0 //--------------------------------------------------------------------+ // Dialog -- cgit v1.3.1 From b786d6f4e632654a356932115bfc0c1621f6333b Mon Sep 17 00:00:00 2001 From: Hjalmar Date: Fri, 9 Aug 2024 21:08:32 +0200 Subject: Marked the keycode parameter of the keyboard_report functions as const since the functions don't modifies the value --- src/class/hid/hid_device.c | 2 +- src/class/hid/hid_device.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 00f6fc474..ef6c7f3af 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -134,7 +134,7 @@ uint8_t tud_hid_n_get_protocol(uint8_t instance) { return _hidd_itf[instance].protocol_mode; } -bool tud_hid_n_keyboard_report(uint8_t instance, uint8_t report_id, uint8_t modifier, uint8_t keycode[6]) { +bool tud_hid_n_keyboard_report(uint8_t instance, uint8_t report_id, uint8_t modifier, const uint8_t keycode[6]) { hid_keyboard_report_t report; report.modifier = modifier; report.reserved = 0; diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index 89c28e061..ab2e27373 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -65,7 +65,7 @@ bool tud_hid_n_report(uint8_t instance, uint8_t report_id, void const* report, u // KEYBOARD: convenient helper to send keyboard report if application // use template layout report as defined by hid_keyboard_report_t -bool tud_hid_n_keyboard_report(uint8_t instance, uint8_t report_id, uint8_t modifier, uint8_t keycode[6]); +bool tud_hid_n_keyboard_report(uint8_t instance, uint8_t report_id, uint8_t modifier, const uint8_t keycode[6]); // MOUSE: convenient helper to send mouse report if application // use template layout report as defined by hid_mouse_report_t @@ -98,7 +98,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool tud_hid_report(uint8_t report_id, void return tud_hid_n_report(0, report_id, report, len); } -TU_ATTR_ALWAYS_INLINE static inline bool tud_hid_keyboard_report(uint8_t report_id, uint8_t modifier, uint8_t keycode[6]) { +TU_ATTR_ALWAYS_INLINE static inline bool tud_hid_keyboard_report(uint8_t report_id, uint8_t modifier, const uint8_t keycode[6]) { return tud_hid_n_keyboard_report(0, report_id, modifier, keycode); } -- cgit v1.3.1 From a621c4b6fcd89df9b86d2911414e05e2e15184ec Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 12 Aug 2024 16:39:25 +0700 Subject: fix more race with ch32v203 and setup when queuing zlp. improve hil test failed output --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 22 ++++--- src/portable/st/stm32_fsdev/fsdev_type.h | 5 +- test/hil/hil_test.py | 93 ++++++++++++++++----------- 3 files changed, 73 insertions(+), 47 deletions(-) (limited to 'src') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 252969648..1e0e9c447 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -345,12 +345,14 @@ static void handle_ctr_rx(uint32_t ep_id) { if ((rx_count < xfer->max_packet_size) || (xfer->queued_len >= xfer->total_len)) { // all bytes received or short packet - dcd_event_xfer_complete(0, ep_num, xfer->queued_len, XFER_RESULT_SUCCESS, true); // For ch32v203: reset rx bufsize to mps to prevent race condition to cause PMAOVR (occurs with msc write10) - // also ch32 seems to unconditionally accept ZLP on EP0 OUT, which can incorrectly use queued_len of previous - // transfer. So reset total_len and queued_len to 0. btable_set_rx_bufsize(ep_id, BTABLE_BUF_RX, xfer->max_packet_size); + + dcd_event_xfer_complete(0, ep_num, xfer->queued_len, XFER_RESULT_SUCCESS, true); + + // ch32 seems to unconditionally accept ZLP on EP0 OUT, which can incorrectly use queued_len of previous + // transfer. So reset total_len and queued_len to 0. xfer->total_len = xfer->queued_len = 0; } else { // Set endpoint active again for receiving more data. Note that isochronous endpoints stay active always @@ -412,11 +414,6 @@ void dcd_int_handler(uint8_t rhport) { FSDEV_REG->ISTR = (fsdev_bus_t)~USB_ISTR_ESOF; } - if (int_status & USB_ISTR_PMAOVR) { - TU_BREAKPOINT(); - FSDEV_REG->ISTR = (fsdev_bus_t)~USB_ISTR_PMAOVR; - } - // loop to handle all pending CTR interrupts while (FSDEV_REG->ISTR & USB_ISTR_CTR) { // skip DIR bit, and use CTR TX/RX instead, since there is chance we have both TX/RX completed in one interrupt @@ -459,6 +456,11 @@ void dcd_int_handler(uint8_t rhport) { handle_ctr_tx(ep_id); } } + + if (int_status & USB_ISTR_PMAOVR) { + TU_BREAKPOINT(); + FSDEV_REG->ISTR = (fsdev_bus_t)~USB_ISTR_PMAOVR; + } } //--------------------------------------------------------------------+ @@ -806,6 +808,10 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { ep_write(ep_idx, ep_reg, true); } +//--------------------------------------------------------------------+ +// PMA read/write +//--------------------------------------------------------------------+ + // Write to packet memory area (PMA) from user memory // - Packet memory must be either strictly 16-bit or 32-bit depending on FSDEV_BUS_32BIT // - Uses unaligned for RAM (since M0 cannot access unaligned address) diff --git a/src/portable/st/stm32_fsdev/fsdev_type.h b/src/portable/st/stm32_fsdev/fsdev_type.h index 26717fab0..cf36576bb 100644 --- a/src/portable/st/stm32_fsdev/fsdev_type.h +++ b/src/portable/st/stm32_fsdev/fsdev_type.h @@ -285,8 +285,9 @@ TU_ATTR_ALWAYS_INLINE static inline void btable_set_rx_bufsize(uint32_t ep_id, u /* Encode into register. When BLSIZE==1, we need to subtract 1 block count */ uint16_t bl_nb = (blsize << 15) | ((num_block - blsize) << 10); if (bl_nb == 0) { - // zlp but 0 is invalid value, set num_block to 1 (2 bytes) - bl_nb = 1 << 10; + // zlp but 0 is invalid value, set blsize to 1 (32 bytes) + // Note: lower value can cause PMAOVR on setup with ch32v203 + bl_nb = 1 << 15; } #ifdef FSDEV_BUS_32BIT diff --git a/test/hil/hil_test.py b/test/hil/hil_test.py index b67520576..01ca93c7a 100644 --- a/test/hil/hil_test.py +++ b/test/hil/hil_test.py @@ -36,7 +36,7 @@ import glob import platform from multiprocessing import Pool -ENUM_TIMEOUT = 30 +ENUM_TIMEOUT = 20 # get usb serial by id @@ -110,7 +110,8 @@ def run_cmd(cmd): #print(cmd) r = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) if r.returncode != 0: - title = 'command error' + title = f'COMMAND FAILED: {cmd}' + print() if os.getenv('CI'): print(f"::group::{title}") print(r.stdout.decode("utf-8")) @@ -198,14 +199,15 @@ def flash_esptool(board, firmware): # ------------------------------------------------------------- # Tests # ------------------------------------------------------------- -def test_board_test(id): +def test_board_test(board): # Dummy test pass -def test_cdc_dual_ports(id): - port1 = get_serial_dev(id, 'TinyUSB', "TinyUSB_Device", 0) - port2 = get_serial_dev(id, 'TinyUSB', "TinyUSB_Device", 2) +def test_cdc_dual_ports(board): + uid = board['uid'] + port1 = get_serial_dev(uid, 'TinyUSB', "TinyUSB_Device", 0) + port2 = get_serial_dev(uid, 'TinyUSB', "TinyUSB_Device", 2) ser1 = open_serial_dev(port1) ser2 = open_serial_dev(port2) @@ -224,9 +226,10 @@ def test_cdc_dual_ports(id): assert ser2.read(100) == str2.upper(), 'Port2 wrong data' -def test_cdc_msc(id): +def test_cdc_msc(board): + uid = board['uid'] # Echo test - port = get_serial_dev(id, 'TinyUSB', "TinyUSB_Device", 0) + port = get_serial_dev(uid, 'TinyUSB', "TinyUSB_Device", 0) ser = open_serial_dev(port) str = b"test_str" @@ -235,7 +238,7 @@ def test_cdc_msc(id): assert ser.read(100) == str, 'CDC wrong data' # Block test - data = read_disk_file(id, 'README.TXT') + data = read_disk_file(uid, 'README.TXT') readme = \ b"This is tinyusb's MassStorage Class demo.\r\n\r\n\ If you find any bugs or get any questions, feel free to file an\r\n\ @@ -244,26 +247,28 @@ issue at github.com/hathach/tinyusb" assert data == readme, 'MSC wrong data' -def test_cdc_msc_freertos(id): - test_cdc_msc(id) +def test_cdc_msc_freertos(board): + test_cdc_msc(board) -def test_dfu(id): +def test_dfu(board): + uid = board['uid'] + # Wait device enum timeout = ENUM_TIMEOUT while timeout: ret = subprocess.run(f'dfu-util -l', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) stdout = ret.stdout.decode() - if f'serial="{id}"' in stdout and 'Found DFU: [cafe:4000]' in stdout: + if f'serial="{uid}"' in stdout and 'Found DFU: [cafe:4000]' in stdout: break time.sleep(1) timeout = timeout - 1 assert timeout, 'Device not available' - f_dfu0 = f'dfu0_{id}' - f_dfu1 = f'dfu1_{id}' + f_dfu0 = f'dfu0_{uid}' + f_dfu1 = f'dfu1_{uid}' # Test upload try: @@ -272,10 +277,10 @@ def test_dfu(id): except OSError: pass - ret = run_cmd(f'dfu-util -S {id} -a 0 -U {f_dfu0}') + ret = run_cmd(f'dfu-util -S {uid} -a 0 -U {f_dfu0}') assert ret.returncode == 0, 'Upload failed' - ret = run_cmd(f'dfu-util -S {id} -a 1 -U {f_dfu1}') + ret = run_cmd(f'dfu-util -S {uid} -a 1 -U {f_dfu1}') assert ret.returncode == 0, 'Upload failed' with open(f_dfu0) as f: @@ -288,14 +293,16 @@ def test_dfu(id): os.remove(f_dfu1) -def test_dfu_runtime(id): +def test_dfu_runtime(board): + uid = board['uid'] + # Wait device enum timeout = ENUM_TIMEOUT while timeout: ret = subprocess.run(f'dfu-util -l', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) stdout = ret.stdout.decode() - if f'serial="{id}"' in stdout and 'Found Runtime: [cafe:4000]' in stdout: + if f'serial="{uid}"' in stdout and 'Found Runtime: [cafe:4000]' in stdout: break time.sleep(1) timeout = timeout - 1 @@ -303,10 +310,11 @@ def test_dfu_runtime(id): assert timeout, 'Device not available' -def test_hid_boot_interface(id): - kbd = get_hid_dev(id, 'TinyUSB', 'TinyUSB_Device', 'event-kbd') - mouse1 = get_hid_dev(id, 'TinyUSB', 'TinyUSB_Device', 'if01-event-mouse') - mouse2 = get_hid_dev(id, 'TinyUSB', 'TinyUSB_Device', 'if01-mouse') +def test_hid_boot_interface(board): + uid = board['uid'] + kbd = get_hid_dev(uid, 'TinyUSB', 'TinyUSB_Device', 'event-kbd') + mouse1 = get_hid_dev(uid, 'TinyUSB', 'TinyUSB_Device', 'if01-event-mouse') + mouse2 = get_hid_dev(uid, 'TinyUSB', 'TinyUSB_Device', 'if01-mouse') # Wait device enum timeout = ENUM_TIMEOUT while timeout: @@ -338,22 +346,23 @@ all_tests = [ ] -def test_board(item): - name = item['name'] - flasher = item['flasher'].lower() +def test_board(board): + name = board['name'] + flasher = board['flasher'].lower() # default to all tests - if 'tests' in item: - test_list = item['tests'] + ['board_test'] + if 'tests' in board: + test_list = board['tests'] + ['board_test'] else: test_list = list(all_tests) # remove skip_tests - if 'tests_skip' in item: - for skip in item['tests_skip']: + if 'tests_skip' in board: + for skip in board['tests_skip']: if skip in test_list: test_list.remove(skip) + err_count = 0 for test in test_list: fw_dir = f'cmake-build/cmake-build-{name}/device/{test}' if not os.path.exists(fw_dir): @@ -367,19 +376,26 @@ def test_board(item): # flash firmware. It may fail randomly, retry a few times for i in range(3): - ret = globals()[f'flash_{flasher}'](item, fw_name) + ret = globals()[f'flash_{flasher}'](board, fw_name) if ret.returncode == 0: break else: print(f'Flashing failed, retry {i+1}') time.sleep(1) - assert ret.returncode == 0, 'Flash failed\n' + ret.stdout.decode() - - # run test - globals()[f'test_{test}'](item['uid']) - print('OK') + if ret.returncode == 0: + try: + ret = globals()[f'test_{test}'](board) + print('OK') + except AssertionError as e: + err_count += 1 + print('Failed') + print(f' {e}') + else: + err_count += 1 + print('Flash failed') + return err_count def main(): """ @@ -404,8 +420,11 @@ def main(): else: config_boards = [e for e in config['boards'] if e['name'] in boards] + err_count_list = 0 with Pool(processes=os.cpu_count()) as pool: - pool.map(test_board, config_boards) + err_count_list = pool.map(test_board, config_boards) + + sys.exit(sum(err_count_list)) if __name__ == '__main__': -- cgit v1.3.1 From 5666aa196f99e323e025179559ef8ac1db390749 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Mon, 12 Aug 2024 15:38:22 +0200 Subject: Fix tusb_dir_t warning. --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 1e0e9c447..ed9036d19 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -155,7 +155,7 @@ static uint8_t remoteWakeCountdown; // When wake is requested // into the stack. static void handle_bus_reset(uint8_t rhport); static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix); -static bool edpt_xfer(uint8_t rhport, uint8_t ep_num, uint8_t dir); +static bool edpt_xfer(uint8_t rhport, uint8_t ep_num, tusb_dir_t dir); // PMA allocation/access static uint16_t ep_buf_ptr; ///< Points to first free memory location @@ -578,7 +578,7 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) { (void)rhport; uint8_t const ep_addr = desc_ep->bEndpointAddress; uint8_t const ep_num = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); + tusb_dir_t const dir = tu_edpt_dir(ep_addr); const uint16_t packet_size = tu_edpt_packet_size(desc_ep); uint8_t const ep_idx = dcd_ep_alloc(ep_addr, desc_ep->bmAttributes.xfer); TU_ASSERT(ep_idx < FSDEV_EP_COUNT); @@ -671,7 +671,7 @@ bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) (void)rhport; uint8_t const ep_addr = desc_ep->bEndpointAddress; uint8_t const ep_num = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); + tusb_dir_t const dir = tu_edpt_dir(ep_addr); xfer_ctl_t* xfer = xfer_ctl_ptr(ep_num, dir); uint8_t const ep_idx = xfer->ep_idx; @@ -683,7 +683,7 @@ bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) ep_change_status(&ep_reg, TUSB_DIR_IN, EP_STAT_DISABLED); ep_change_status(&ep_reg, TUSB_DIR_OUT, EP_STAT_DISABLED); ep_change_dtog(&ep_reg, dir, 0); - ep_change_dtog(&ep_reg, 1 - dir, 1); + ep_change_dtog(&ep_reg, (tusb_dir_t)(1 - dir), 1); ep_write(ep_idx, ep_reg, true); @@ -722,7 +722,7 @@ static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix) { ep_write(ep_ix, ep_reg, true); } -static bool edpt_xfer(uint8_t rhport, uint8_t ep_num, uint8_t dir) { +static bool edpt_xfer(uint8_t rhport, uint8_t ep_num, tusb_dir_t dir) { (void) rhport; xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); @@ -752,7 +752,7 @@ static bool edpt_xfer(uint8_t rhport, uint8_t ep_num, uint8_t dir) { bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes) { uint8_t const ep_num = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); + tusb_dir_t const dir = tu_edpt_dir(ep_addr); xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); xfer->buffer = buffer; @@ -765,7 +765,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t to bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t *ff, uint16_t total_bytes) { uint8_t const ep_num = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); + tusb_dir_t const dir = tu_edpt_dir(ep_addr); xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); xfer->buffer = NULL; @@ -779,7 +779,7 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t *ff, uint16_t void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { (void)rhport; uint8_t const ep_num = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); + tusb_dir_t const dir = tu_edpt_dir(ep_addr); xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); uint8_t const ep_idx = xfer->ep_idx; @@ -794,7 +794,7 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { (void)rhport; uint8_t const ep_num = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); + tusb_dir_t const dir = tu_edpt_dir(ep_addr); xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, dir); uint8_t const ep_idx = xfer->ep_idx; -- cgit v1.3.1 From 549f20d1793d1896a376a1ea978a4f02217de4ed Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Mon, 12 Aug 2024 15:39:02 +0200 Subject: Fix buf_id read for ISO transfer. --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index ed9036d19..0cdc3eef9 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -275,7 +275,6 @@ static void handle_bus_reset(uint8_t rhport) { // Handle CTR interrupt for the TX/IN direction static void handle_ctr_tx(uint32_t ep_id) { uint32_t ep_reg = ep_read(ep_id) | USB_EP_CTR_TX | USB_EP_CTR_RX; - ep_reg &= USB_EPREG_MASK; uint8_t const ep_num = ep_reg & USB_EPADDR_FIELD; xfer_ctl_t *xfer = xfer_ctl_ptr(ep_num, TUSB_DIR_IN); @@ -694,7 +693,6 @@ bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix) { uint16_t len = tu_min16(xfer->total_len - xfer->queued_len, xfer->max_packet_size); uint32_t ep_reg = ep_read(ep_ix) | USB_EP_CTR_TX | USB_EP_CTR_RX; // reserve CTR - ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(TUSB_DIR_IN); // only change TX Status, reserve other toggle bits bool const is_iso = ep_is_iso(ep_reg); @@ -719,6 +717,7 @@ static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix) { if (is_iso) { xfer->iso_in_sending = true; } + ep_reg &= USB_EPREG_MASK | EP_STAT_MASK(TUSB_DIR_IN); // only change TX Status, reserve other toggle bits ep_write(ep_ix, ep_reg, true); } -- cgit v1.3.1 From 96c5c72e971674ba3a4023aed02bf31cc8c994dc Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Mon, 12 Aug 2024 18:38:23 +0200 Subject: Fix double buffer not disabled for smaller devices. --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 0cdc3eef9..6eea1ab32 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -650,10 +650,11 @@ bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet /* Create a packet memory buffer area. Enable double buffering for devices with 2048 bytes PMA, for smaller devices double buffering occupy too much space. */ - uint32_t pma_addr = dcd_pma_alloc(largest_packet_size, true); #if FSDEV_PMA_SIZE > 1024u + uint32_t pma_addr = dcd_pma_alloc(largest_packet_size, true); uint16_t pma_addr2 = pma_addr >> 16; #else + uint32_t pma_addr = dcd_pma_alloc(largest_packet_size, false); uint16_t pma_addr2 = pma_addr; #endif -- cgit v1.3.1