274 lines
7.3 KiB
C
274 lines
7.3 KiB
C
//
|
|
// Created by cfif on 13.11.2023.
|
|
//
|
|
#include "SerialPort_USB.h"
|
|
#include "SystemDelayInterface.h"
|
|
#include "CmsisRtosThreadUtils.h"
|
|
|
|
otg_core_type otg_core_struct;
|
|
|
|
void usb_delay_ms(uint32_t ms) {
|
|
SystemDelayMs(ms);
|
|
}
|
|
|
|
void OTG_IRQ_HANDLER(void) {
|
|
usbd_irq_handler(&otg_core_struct);
|
|
}
|
|
|
|
void usb_clock48m_select(usb_clk48_s clk_s) {
|
|
if (clk_s == USB_CLK_HICK) {
|
|
crm_usb_clock_source_select(CRM_USB_CLOCK_SOURCE_HICK);
|
|
|
|
/* enable the acc calibration ready interrupt */
|
|
crm_periph_clock_enable(CRM_ACC_PERIPH_CLOCK, TRUE);
|
|
|
|
/* update the c1\c2\c3 value */
|
|
acc_write_c1(7980);
|
|
acc_write_c2(8000);
|
|
acc_write_c3(8020);
|
|
#if (USB_ID == 0)
|
|
acc_sof_select(ACC_SOF_OTG1);
|
|
#else
|
|
acc_sof_select(ACC_SOF_OTG2);
|
|
#endif
|
|
// open acc calibration
|
|
acc_calibration_mode_enable(ACC_CAL_HICKTRIM, TRUE);
|
|
} else {
|
|
switch (system_core_clock) {
|
|
// 48MHz
|
|
case 48000000:
|
|
crm_usb_clock_div_set(CRM_USB_DIV_1);
|
|
break;
|
|
|
|
// 72MHz
|
|
case 72000000:
|
|
crm_usb_clock_div_set(CRM_USB_DIV_1_5);
|
|
break;
|
|
|
|
// 96MHz
|
|
case 96000000:
|
|
crm_usb_clock_div_set(CRM_USB_DIV_2);
|
|
break;
|
|
|
|
// 120MHz
|
|
case 120000000:
|
|
crm_usb_clock_div_set(CRM_USB_DIV_2_5);
|
|
break;
|
|
|
|
// 144MHz
|
|
case 144000000:
|
|
crm_usb_clock_div_set(CRM_USB_DIV_3);
|
|
break;
|
|
|
|
// 168MHz
|
|
case 168000000:
|
|
crm_usb_clock_div_set(CRM_USB_DIV_3_5);
|
|
break;
|
|
|
|
// 192MHz
|
|
case 192000000:
|
|
crm_usb_clock_div_set(CRM_USB_DIV_4);
|
|
break;
|
|
|
|
// 216MHz
|
|
case 216000000:
|
|
crm_usb_clock_div_set(CRM_USB_DIV_4_5);
|
|
break;
|
|
|
|
// 240MHz
|
|
case 240000000:
|
|
crm_usb_clock_div_set(CRM_USB_DIV_5);
|
|
break;
|
|
|
|
// 264MHz
|
|
case 264000000:
|
|
crm_usb_clock_div_set(CRM_USB_DIV_5_5);
|
|
break;
|
|
|
|
// 288MHz
|
|
case 288000000:
|
|
crm_usb_clock_div_set(CRM_USB_DIV_6);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
void usb_gpio_config(void) {
|
|
gpio_init_type gpio_init_struct;
|
|
|
|
crm_periph_clock_enable(OTG_PIN_GPIO_CLOCK, TRUE);
|
|
gpio_default_para_init(&gpio_init_struct);
|
|
|
|
gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
|
|
gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
|
|
gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
|
|
gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
|
|
|
|
// dp and dm
|
|
gpio_init_struct.gpio_pins = OTG_PIN_DP | OTG_PIN_DM;
|
|
gpio_init(OTG_PIN_GPIO, &gpio_init_struct);
|
|
|
|
gpio_pin_mux_config(OTG_PIN_GPIO, OTG_PIN_DP_SOURCE, OTG_PIN_MUX);
|
|
gpio_pin_mux_config(OTG_PIN_GPIO, OTG_PIN_DM_SOURCE, OTG_PIN_MUX);
|
|
|
|
#ifdef USB_SOF_OUTPUT_ENABLE
|
|
crm_periph_clock_enable(OTG_PIN_SOF_GPIO_CLOCK, TRUE);
|
|
gpio_init_struct.gpio_pins = OTG_PIN_SOF;
|
|
gpio_init(OTG_PIN_SOF_GPIO, &gpio_init_struct);
|
|
gpio_pin_mux_config(OTG_PIN_SOF_GPIO, OTG_PIN_SOF_SOURCE, OTG_PIN_MUX);
|
|
#endif
|
|
|
|
#ifndef USB_VBUS_IGNORE
|
|
gpio_init_struct.gpio_pins = OTG_PIN_VBUS;
|
|
gpio_init_struct.gpio_pull = GPIO_PULL_DOWN;
|
|
gpio_pin_mux_config(OTG_PIN_GPIO, OTG_PIN_VBUS_SOURCE, OTG_PIN_MUX);
|
|
gpio_init(OTG_PIN_GPIO, &gpio_init_struct);
|
|
#endif
|
|
|
|
|
|
}
|
|
|
|
#ifdef USB_LOW_POWER_WAKUP
|
|
void usb_low_power_wakeup_config(void)
|
|
{
|
|
exint_init_type exint_init_struct;
|
|
|
|
crm_periph_clock_enable(CRM_SCFG_PERIPH_CLOCK, TRUE);
|
|
exint_default_para_init(&exint_init_struct);
|
|
|
|
exint_init_struct.line_enable = TRUE;
|
|
exint_init_struct.line_mode = EXINT_LINE_INTERRUPUT;
|
|
exint_init_struct.line_select = OTG_WKUP_EXINT_LINE;
|
|
exint_init_struct.line_polarity = EXINT_TRIGGER_RISING_EDGE;
|
|
exint_init(&exint_init_struct);
|
|
|
|
nvic_irq_enable(OTG_WKUP_IRQ, 0, 0);
|
|
}
|
|
|
|
/**
|
|
* @brief this function handles otgfs wakup interrupt.
|
|
* @param none
|
|
* @retval none
|
|
*/
|
|
void OTG_WKUP_HANDLER(void)
|
|
{
|
|
exint_flag_clear(OTG_WKUP_EXINT_LINE);
|
|
}
|
|
#endif
|
|
|
|
static uint16_t vSerialPortReceiveQueue(
|
|
tSerialPortUsbArtery *env, uint8_t *data, uint16_t size, uint32_t timeout, osMessageQueueId_t queueId
|
|
) {
|
|
uint16_t received = 0;
|
|
|
|
if (timeout) {
|
|
uint32_t endTimeout = SystemGetMs() + timeout;
|
|
uint32_t currentTimeout;
|
|
|
|
while (size && ((timeout == SystemWaitForever) || (endTimeout > SystemGetMs()))) {
|
|
currentTimeout = endTimeout - SystemGetMs();
|
|
if (osMessageQueueGet(queueId, data, NULL, currentTimeout) == osOK) {
|
|
--size;
|
|
++received;
|
|
++data;
|
|
}
|
|
}
|
|
} else {
|
|
while (size) {
|
|
if (osMessageQueueGet(queueId, data, NULL, 0) == osOK) {
|
|
--size;
|
|
++received;
|
|
++data;
|
|
} else {
|
|
return received;
|
|
}
|
|
}
|
|
}
|
|
|
|
return received;
|
|
}
|
|
|
|
static uint16_t vSerialPortUsbTransmit(tSerialPortUsbArtery *env, uint8_t *data, uint16_t size, uint32_t timeout) {
|
|
|
|
if (usb_vcp_send_data(&otg_core_struct.dev, data, size) == SUCCESS) {
|
|
return size;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static uint16_t vSerialPortUsbReceive(tSerialPortUsbArtery *env, uint8_t *data, uint16_t size, uint32_t timeout) {
|
|
return vSerialPortReceiveQueue(env, data, size, timeout, env->rxDataQueue);
|
|
}
|
|
|
|
static _Noreturn void UsbDriver_Thread(tSerialPortUsbArtery *env) {
|
|
for (;;) {
|
|
uint16_t data_len = usb_vcp_get_rxdata(&otg_core_struct.dev, env->usb_buffer);
|
|
|
|
if (data_len > 0) {
|
|
for (uint16_t i = 0; i < data_len; ++i) {
|
|
osMessageQueuePut(env->rxDataQueue, &env->usb_buffer[i], 0x0, 0U);
|
|
}
|
|
}
|
|
|
|
SystemDelayMs(1);
|
|
}
|
|
}
|
|
|
|
void UsbDriver_StartThread(tSerialPortUsbArtery *env) {
|
|
if (!env->thread.id) {
|
|
env->thread.id = osThreadNew((osThreadFunc_t) (UsbDriver_Thread), (void *) (env), &env->thread.attr);
|
|
} else {
|
|
osThreadResume(env->thread.id);
|
|
}
|
|
}
|
|
|
|
void SerialPortUsb_Init(
|
|
tSerialPortUsbArtery *env,
|
|
uint32_t rxBufferLength
|
|
) {
|
|
env->rxDataQueue = osMessageQueueNew(rxBufferLength, 1, NULL);
|
|
|
|
// usb gpio config
|
|
usb_gpio_config();
|
|
|
|
#ifdef USB_LOW_POWER_WAKUP
|
|
usb_low_power_wakeup_config();
|
|
#endif
|
|
|
|
// enable otgfs clock
|
|
crm_periph_clock_enable(OTG_CLOCK, TRUE);
|
|
|
|
// select usb 48m clcok source
|
|
usb_clock48m_select(USB_CLK_HEXT);
|
|
|
|
// enable otgfs irq
|
|
//nvic_irq_enable(OTG_IRQ, 0, 0);
|
|
NVIC_EnableIRQ(OTG_IRQ);
|
|
NVIC_SetPriority(OTG_IRQ, 0xFF);
|
|
|
|
// init usb
|
|
usbd_init(&otg_core_struct,
|
|
USB_FULL_SPEED_CORE_ID,
|
|
USB_ID,
|
|
&cdc_class_handler,
|
|
&cdc_desc_handler);
|
|
|
|
InitThreadAtrStatic(&env->thread.attr, "UsbDriver", env->thread.controlBlock, env->thread.stack, osPriorityNormal);
|
|
env->thread.id = 0;
|
|
|
|
UsbDriver_StartThread(env);
|
|
}
|
|
|
|
tSerialPortIO SerialPortUsb_GetIo(tSerialPortUsbArtery *env) {
|
|
tSerialPortIO io = {
|
|
.env = env,
|
|
.receive = (SerialPortIOTransaction) vSerialPortUsbReceive,
|
|
.transmit = (SerialPortIOTransaction) vSerialPortUsbTransmit
|
|
};
|
|
return io;
|
|
} |