SerialPortUSB_ARTERY_AT32F4.../SerialPort_USB.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;
}