A modified DAPLink firmware (from JiXin) for STM32F103C6T6
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

390 lines
11 KiB

#include <string.h>
#include <RTL.h>
#include <rl_usb.h>
#define __NO_USB_LIB_C
#include "usb_config.c"
#if (USBD_CDC_ACM_ENABLE == 1)
#include "DAP_Config.h"
#include "usbd_user_cdc_acm.h"
static struct {
volatile uint16_t idx_in;
volatile uint16_t idx_out;
volatile int16_t cnt_in;
volatile int16_t cnt_out;
uint8_t data[USART_BUFFER_SIZE];
} WrBuffer, RdBuffer;
static USART_InitTypeDef UART_Config;
static uint32_t StatusRegister;
static uint32_t SendBreakFlag;
static uint32_t BreakFlag;
static CDC_LINE_CODING line_coding_current;
/*------------------------------------------------------------------------------
* UART_Reset: Reset the Serial module variables
*----------------------------------------------------------------------------*/
int32_t UART_Reset(void)
{
NVIC_DisableIRQ(USART_IRQn); /* Disable USART interrupt */
SendBreakFlag = 0;
BreakFlag = 0;
line_coding_current.bCharFormat = UART_STOP_BITS_1;
line_coding_current.bDataBits = UART_DATA_BITS_8;
line_coding_current.bParityType = UART_PARITY_NONE;
line_coding_current.dwDTERate = 115200;
USBD_CDC_ACM_PortSetLineCoding(&line_coding_current);
NVIC_EnableIRQ(USART_IRQn); // Enable USART interrupt
return (1);
}
/** \brief Vitual COM Port initialization
The function inititalizes the hardware resources of the port used as
the Virtual COM Port.
\return 0 Function failed.
\return 1 Function succeeded.
*/
const GPIO_InitTypeDef UART_RX_INIT = { USART_RX_PIN, GPIO_Speed_50MHz, GPIO_Mode_IPU };
const GPIO_InitTypeDef UART_TX_INIT = { USART_TX_PIN, GPIO_Speed_50MHz, GPIO_Mode_AF_PP };
const GPIO_InitTypeDef UART_RX_DEINIT = { USART_RX_PIN, (GPIOSpeed_TypeDef)0, GPIO_Mode_IPU };
const GPIO_InitTypeDef UART_TX_DEINIT = { USART_TX_PIN, (GPIOSpeed_TypeDef)0, GPIO_Mode_IPU };
int32_t USBD_CDC_ACM_PortInitialize (void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
USART_REMAP();
USART_CLOCK(ENABLE);
UART_Reset();
GPIO_INIT(USART_GPIO, UART_RX_INIT);
GPIO_INIT(USART_GPIO, UART_TX_INIT);
return (1);
}
/** \brief Vitual COM Port uninitialization
The function uninititalizes/releases the hardware resources of the port used
as the Virtual COM Port.
\return 0 Function failed.
\return 1 Function succeeded.
*/
int32_t USBD_CDC_ACM_PortUninitialize (void)
{
USART_CLOCK(DISABLE);
GPIO_INIT(USART_GPIO, UART_RX_DEINIT);
GPIO_INIT(USART_GPIO, UART_TX_DEINIT);
return (1);
}
/** \brief Vitual COM Port reset
The function resets the internal states of the port used
as the Virtual COM Port.
\return 0 Function failed.
\return 1 Function succeeded.
*/
int32_t USBD_CDC_ACM_PortReset (void)
{
return UART_Reset();
}
/** \brief Virtual COM Port change communication settings
The function changes communication settings of the port used as the
Virtual COM Port.
\param [in] line_coding Pointer to the loaded CDC_LINE_CODING structure.
\return 0 Function failed.
\return 1 Function succeeded.
*/
int32_t USBD_CDC_ACM_PortSetLineCoding(CDC_LINE_CODING *line_coding)
{
USART_InitTypeDef * config = &UART_Config;
/* USART supports:
8bit data; even, odd and none parity; 1, 1.5 and 2 stop bits
*/
/* Data bits */
if (line_coding->bDataBits != UART_DATA_BITS_8)
return(0);
config->USART_WordLength = USART_WordLength_8b;
/* Parity */
switch (line_coding->bParityType)
{
case UART_PARITY_NONE: config->USART_Parity = USART_Parity_No; break;
case UART_PARITY_EVEN: config->USART_Parity = USART_Parity_Even; break;
case UART_PARITY_ODD: config->USART_Parity = USART_Parity_Odd; break;
default: return (0);
}
/* Stop bits */
switch (line_coding->bCharFormat)
{
case UART_STOP_BITS_1: config->USART_StopBits = USART_StopBits_1; break;
case UART_STOP_BITS_2: config->USART_StopBits = USART_StopBits_2; break;
case UART_STOP_BITS_1_5:config->USART_StopBits = USART_StopBits_1_5; break;
default: return (0);
}
line_coding_current.bCharFormat = line_coding->bCharFormat;
line_coding_current.bDataBits = line_coding->bDataBits;
line_coding_current.bParityType = line_coding->bParityType;
line_coding_current.dwDTERate = line_coding->dwDTERate;
config->USART_BaudRate = line_coding->dwDTERate;
config->USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
config->USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_Init(USART_PORT, config);
USART_ITConfig(USART_PORT, USART_IT_RXNE, ENABLE);
USART_Cmd(USART_PORT, ENABLE);
return (1);
}
/** \brief Vitual COM Port retrieve communication settings
The function retrieves communication settings of the port used as the
Virtual COM Port.
\param [in] line_coding Pointer to the CDC_LINE_CODING structure.
\return 0 Function failed.
\return 1 Function succeeded.
*/
int32_t USBD_CDC_ACM_PortGetLineCoding (CDC_LINE_CODING *line_coding)
{
line_coding->bCharFormat = line_coding_current.bCharFormat;
line_coding->bDataBits = line_coding_current.bDataBits;
line_coding->bParityType = line_coding_current.bParityType;
line_coding->dwDTERate = line_coding_current.dwDTERate;
return (1);
}
/** \brief Virtual COM Port set control line state
The function sets control line state on the port used as the
Virtual COM Port.
\param [in] ctrl_bmp Control line settings bitmap (
0. bit - DTR state,
1. bit - RTS state).
\return 0 Function failed.
\return 1 Function succeeded.
*/
int32_t USBD_CDC_ACM_PortSetControlLineState (uint16_t ctrl_bmp)
{
return (1);
}
/*------------------------------------------------------------------------------
* UART_WriteData: Write data from buffer
*----------------------------------------------------------------------------*/
int32_t UART_WriteData (uint8_t *data, uint16_t size)
{
int32_t cnt = 0;
int16_t len_in_buf;
uint16_t next;
while (size != 0)
{
--size;
len_in_buf = WrBuffer.cnt_in - WrBuffer.cnt_out;
if (len_in_buf < USART_BUFFER_SIZE)
{
next = WrBuffer.idx_in;
WrBuffer.data[next] = *data++;
next = (next + 1) & (USART_BUFFER_SIZE - 1);
WrBuffer.idx_in = next;
WrBuffer.cnt_in++;
cnt++;
}
}
if (cnt != 0)
USART_ITConfig(USART_PORT, USART_IT_TXE, ENABLE);
return cnt;
}
/*------------------------------------------------------------------------------
* UART_ReadData: Read data to buffer
*----------------------------------------------------------------------------*/
int32_t UART_ReadData (uint8_t *data, uint16_t size)
{
int32_t cnt = 0;
#if defined ( USART_CLOCK )
while (size != 0)
{
--size;
if (RdBuffer.cnt_in != RdBuffer.cnt_out)
{
*data++ = RdBuffer.data[RdBuffer.idx_out++];
RdBuffer.idx_out &= (USART_BUFFER_SIZE - 1);
RdBuffer.cnt_out++;
cnt++;
}
}
#endif
return (cnt);
}
/*------------------------------------------------------------------------------
* UART_GetChar: Read a received character
*----------------------------------------------------------------------------*/
int32_t UART_GetChar (void)
{
uint8_t ch;
if ((UART_ReadData(&ch, 1)) == 1)
return ((int32_t)ch);
else
return (-1);
}
/*------------------------------------------------------------------------------
* UART_PutChar: Write a character
*----------------------------------------------------------------------------*/
int32_t UART_PutChar (uint8_t ch)
{
if ((UART_WriteData (&ch, 1)) == 1)
return ((uint32_t) ch);
else
return (-1);
}
/*------------------------------------------------------------------------------
* UART_DataAvailable: returns number of bytes available in RdBuffer
*----------------------------------------------------------------------------*/
int32_t UART_DataAvailable (void)
{
return (RdBuffer.cnt_in - RdBuffer.cnt_out);
}
/*------------------------------------------------------------------------------
* UART_GetStatusLineState: Get state of status lines
*----------------------------------------------------------------------------*/
int32_t UART_GetStatusLineState (void)
{
return (0);
}
/*------------------------------------------------------------------------------
* UART_GetCommunicationErrorStatus: Get error status
*----------------------------------------------------------------------------*/
int32_t UART_GetCommunicationErrorStatus (void)
{
int32_t err = 0;
if (StatusRegister & USART_SR_PE)
err |= UART_PARITY_ERROR_Msk;
if (StatusRegister & USART_SR_NE)
err |= UART_OVERRUN_ERROR_Msk;
if (BreakFlag == 0 && (StatusRegister & USART_SR_FE))
err |= UART_PARITY_ERROR_Msk;
return (err);
}
/*------------------------------------------------------------------------------
* UART_SetBreak : set break condition
*----------------------------------------------------------------------------*/
int32_t UART_SetBreak (void)
{
SendBreakFlag = 1; /* Set send break flag and */
USART_SendBreak(USART_PORT); /* send 1 break character */
return (1);
}
/*------------------------------------------------------------------------------
* UART_GetBreak: if break character received, return 1
*----------------------------------------------------------------------------*/
int32_t UART_GetBreak (void)
{
return (BreakFlag);
}
/*------------------------------------------------------------------------------
* UART_IRQ: Serial interrupt handler routine
*----------------------------------------------------------------------------*/
#if defined ( USART_CLOCK )
void USART_IRQHandler(void)
{
uint8_t ch;
int16_t len_in_buf;
StatusRegister = USART_PORT->SR;
/* Read data register not empty interrupt */
if (USART_GetITStatus(USART_PORT, USART_IT_RXNE) != RESET)
{
len_in_buf = RdBuffer.cnt_in - RdBuffer.cnt_out;
if (len_in_buf < USART_BUFFER_SIZE) //<EFBFBD>жϽ<EFBFBD><EFBFBD>ջ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʣ<EFBFBD><EFBFBD><EFBFBD>
{
ch = (uint8_t)USART_ReceiveData(USART_PORT); //<EFBFBD><EFBFBD>ȡһ<EFBFBD>ֽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
RdBuffer.data[RdBuffer.idx_in++] = ch; //<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if ((ch == 0)
&& USART_GetFlagStatus(USART_PORT, USART_SR_FE) /* framing error */
)
{ /* break character */
BreakFlag = 1;
}
else
BreakFlag = 0;
RdBuffer.idx_in &= (USART_BUFFER_SIZE - 1);
RdBuffer.cnt_in++; //<EFBFBD><EFBFBD>¼<EFBFBD><EFBFBD><EFBFBD>յ<EFBFBD><EFBFBD>ֽ<EFBFBD><EFBFBD><EFBFBD>
}
else //<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
RdBuffer.cnt_in = 0;
RdBuffer.cnt_out = 0;
RdBuffer.idx_in = 0;
RdBuffer.idx_out = 0;
}
}
/* Transmit data register empty interrupt */
if (USART_GetITStatus(USART_PORT, USART_IT_TXE) != RESET)
{
if (SendBreakFlag == 1)
{
USART_SendBreak(USART_PORT);
}
else if (WrBuffer.cnt_in != WrBuffer.cnt_out)
{
USART_SendData(USART_PORT, WrBuffer.data[WrBuffer.idx_out++]);
WrBuffer.idx_out &= (USART_BUFFER_SIZE - 1);
WrBuffer.cnt_out++;
}
else
{
USART_ITConfig(USART_PORT, USART_IT_TXE, DISABLE);
}
}
}
#endif
#endif