Skip to content

Commit

Permalink
Merge pull request #812 from avtolstoy/serialfixes
Browse files Browse the repository at this point in the history
Serial.availableForWrite() and Serial.blockOnOverrun() implementation, USB Serial fixes for STM32F2
  • Loading branch information
m-mcgowan committed Mar 10, 2016
2 parents 06374f9 + 3f495bf commit 8a43301
Show file tree
Hide file tree
Showing 13 changed files with 481 additions and 169 deletions.
4 changes: 4 additions & 0 deletions hal/inc/hal_dynalib_usart.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ DYNALIB_FN(hal_usart,HAL_USART_Flush_Data)
DYNALIB_FN(hal_usart,HAL_USART_Is_Enabled)
DYNALIB_FN(hal_usart,HAL_USART_Half_Duplex)
DYNALIB_FN(hal_usart,HAL_USART_Available_Data_For_Write)
#ifdef USB_CDC_ENABLE
DYNALIB_FN(hal_usart,USB_USART_Available_Data_For_Write)
DYNALIB_FN(hal_usart,USB_USART_Flush_Data)
#endif

DYNALIB_END(hal_usart)

Expand Down
14 changes: 14 additions & 0 deletions hal/inc/usb_hal.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,12 @@ void USB_USART_LineCoding_BitRate_Handler(void (*handler)(uint32_t bitRate));
*/
uint8_t USB_USART_Available_Data(void);

/**
* Retrieves the number of bytes of data available in the TX buffer.
* @return
*/
int32_t USB_USART_Available_Data_For_Write(void);

/**
* Reads data from the input buffer.
* @param peek If the data should be peeked reather than fetched.
Expand All @@ -93,8 +99,16 @@ int32_t USB_USART_Receive_Data(uint8_t peek);
/**
* Sends data to the USB serial.
* @param Data The data to write.
* @return
*/
void USB_USART_Send_Data(uint8_t Data);

/**
* Flushes TX buffer
* @return
*/
void USB_USART_Flush_Data(void);

#endif

#ifdef USB_HID_ENABLE
Expand Down
25 changes: 25 additions & 0 deletions hal/src/core/usb_hal.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,20 @@ int32_t USB_USART_Receive_Data(uint8_t peek)
return -1;
}

/*******************************************************************************
* Function Name : USB_USART_Available_Data_For_Write.
* Description : Return the length of available space in TX buffer
* Input : None.
* Return : Length.
*******************************************************************************/
int32_t USB_USART_Available_Data_For_Write(void)
{
if(bDeviceState == CONFIGURED)
return (USART_RX_DATA_SIZE - USART_Rx_ptr_in) % USART_RX_DATA_SIZE;
return -1;
}


/*******************************************************************************
* Function Name : USB_USART_Send_Data.
* Description : Send Data from USB_USART to USB Host.
Expand Down Expand Up @@ -224,6 +238,17 @@ void USB_USART_Send_Data(uint8_t Data)
}
}
}

/*******************************************************************************
* Function Name : USB_USART_Flush_Data.
* Description : Flushes TX buffer
* Input : None.
* Return : None.
*******************************************************************************/
void USB_USART_Flush_Data(void)
{
// Not implemented properly
}
#endif

#ifdef USB_HID_ENABLE
Expand Down
21 changes: 21 additions & 0 deletions hal/src/gcc/usb_hal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,17 @@ int32_t USB_USART_Receive_Data(uint8_t peek)
return result;
}

/*******************************************************************************
* Function Name : USB_USART_Available_Data_For_Write.
* Description : Return the length of available space in TX buffer
* Input : None.
* Return : Length.
*******************************************************************************/
int32_t USB_USART_Available_Data_For_Write(void)
{
return 1;
}

/*******************************************************************************
* Function Name : USB_USART_Send_Data.
* Description : Send Data from USB_USART to USB Host.
Expand All @@ -90,6 +101,16 @@ void USB_USART_Send_Data(uint8_t Data)
std::cout.write((const char*)&Data, 1);
}

/*******************************************************************************
* Function Name : USB_USART_Flush_Data.
* Description : Flushes TX buffer
* Input : None.
* Return : None.
*******************************************************************************/
void USB_USART_Flush_Data(void)
{
}

#ifdef USB_HID_ENABLE
/*******************************************************************************
* Function Name : USB_HID_Send_Report.
Expand Down
24 changes: 22 additions & 2 deletions hal/src/stm32f2xx/core_hal_stm32f2xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@
#include "dct.h"
#include "hal_platform.h"
#include "malloc.h"
#include "usb_hal.h"
#include "usart_hal.h"

#define STOP_MODE_EXIT_CONDITION_PIN 0x01
#define STOP_MODE_EXIT_CONDITION_RTC 0x02
Expand Down Expand Up @@ -383,7 +385,21 @@ void HAL_Core_Enter_Stop_Mode(uint16_t wakeUpPin, uint16_t edgeTriggerMode, long
if (!((wakeUpPin < TOTAL_PINS) && (wakeUpPin >= 0) && (edgeTriggerMode <= FALLING)) && seconds <= 0)
return;

HAL_disable_irq();
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;

// Disable USB Serial (detach)
USB_USART_Init(0);

// Flush all USARTs
for (int usart = 0; usart < TOTAL_USARTS; usart++)
{
if (HAL_USART_Is_Enabled(usart))
{
HAL_USART_Flush_Data(usart);
}
}

int32_t state = HAL_disable_irq();

uint32_t exit_conditions = 0x00;

Expand Down Expand Up @@ -455,7 +471,11 @@ void HAL_Core_Enter_Stop_Mode(uint16_t wakeUpPin, uint16_t edgeTriggerMode, long
HAL_Interrupts_Restore();

// Successfully exited STOP mode
HAL_enable_irq(0);
HAL_enable_irq(state);

SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;

USB_USART_Init(9600);
}

void HAL_Core_Execute_Stop_Mode(void)
Expand Down
130 changes: 94 additions & 36 deletions hal/src/stm32f2xx/usb_hal.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include "usb_conf.h"
#include "usbd_desc.h"
#include "delay_hal.h"
#include "interrupts_hal.h"

/* Private typedef -----------------------------------------------------------*/

Expand All @@ -54,12 +55,15 @@ extern uint32_t USBD_OTG_EP1OUT_ISR_Handler(USB_OTG_CORE_HANDLE *pdev);
extern volatile LINE_CODING linecoding;
extern volatile uint8_t USB_DEVICE_CONFIGURED;
extern volatile uint8_t USB_Rx_Buffer[];
extern volatile uint8_t APP_Rx_Buffer[];
extern volatile uint32_t APP_Rx_ptr_in;
extern volatile uint16_t USB_Rx_length;
extern volatile uint16_t USB_Rx_ptr;
extern volatile uint32_t USB_Rx_Buffer_head;
extern volatile uint32_t USB_Rx_Buffer_tail;
extern volatile uint32_t USB_Rx_Buffer_length;
extern volatile uint8_t USB_Tx_Buffer[];
extern volatile uint32_t USB_Tx_Buffer_head;
extern volatile uint32_t USB_Tx_Buffer_tail;
extern volatile uint8_t USB_Tx_State;
extern volatile uint8_t USB_Rx_State;
extern volatile uint8_t USB_Serial_Open;
#endif

#if defined (USB_CDC_ENABLE) || defined (USB_HID_ENABLE)
Expand Down Expand Up @@ -99,25 +103,44 @@ void Get_SerialNum(void)
/*******************************************************************************
* Function Name : USB_USART_Init
* Description : Start USB-USART protocol.
* Input : baudRate (0 : disconnect usb else init usb only once).
* Input : baudRate (0 : disconnect usb else init usb).
* Return : None.
*******************************************************************************/
void USB_USART_Init(uint32_t baudRate)
{
if (linecoding.bitrate != baudRate)
{
if (!baudRate)
if (!baudRate && linecoding.bitrate > 0)
{
// Deconfigure CDC class endpoints
USBD_ClrCfg(&USB_OTG_dev, 0);

// Class callbacks and descriptor should probably be cleared
// to use another USB class, but this causes a hardfault if no descriptor is set
// and detach/attach is performed.
// Leave them be for now.

// USB_OTG_dev.dev.class_cb = NULL;
// USB_OTG_dev.dev.usr_cb = NULL;
// USB_OTG_dev.dev.usr_device = NULL;

// Perform detach
USB_Cable_Config(DISABLE);

// Soft reattach
// USB_OTG_dev.regs.DREGS->DCTL |= 0x02;
}
else if (!linecoding.bitrate)
{
//Perform a Detach-Attach operation on USB bus
//Initialize USB device
SPARK_USB_Setup();

// Perform a hard Detach-Attach operation on USB bus
USB_Cable_Config(DISABLE);
USB_Cable_Config(ENABLE);

//Initialize USB device only once (if linecoding.bitrate==0)
SPARK_USB_Setup();
// Soft reattach
// USB_OTG_dev.regs.DREGS->DCTL |= 0x02;
}
//linecoding.bitrate will be overwritten by USB Host
linecoding.bitrate = baudRate;
Expand All @@ -134,12 +157,14 @@ void USB_USART_LineCoding_BitRate_Handler(void (*handler)(uint32_t bitRate))
//Init USB Serial first before calling the linecoding handler
USB_USART_Init(9600);

HAL_Delay_Milliseconds(1000);

//Set the system defined custom handler
SetLineCodingBitRateHandler(handler);
}

static inline bool USB_USART_Connected() {
return linecoding.bitrate > 0 && USB_OTG_dev.dev.device_status == USB_OTG_CONFIGURED && USB_Serial_Open;
}

/*******************************************************************************
* Function Name : USB_USART_Available_Data.
* Description : Return the length of available data received from USB.
Expand All @@ -148,12 +173,14 @@ void USB_USART_LineCoding_BitRate_Handler(void (*handler)(uint32_t bitRate))
*******************************************************************************/
uint8_t USB_USART_Available_Data(void)
{
if(USB_Rx_State == 1)
{
return (USB_Rx_length - USB_Rx_ptr);
}

return 0;
int32_t available = 0;
int state = HAL_disable_irq();
if (USB_Rx_Buffer_head >= USB_Rx_Buffer_tail)
available = USB_Rx_Buffer_head - USB_Rx_Buffer_tail;
else
available = USB_Rx_Buffer_length + USB_Rx_Buffer_head - USB_Rx_Buffer_tail;
HAL_enable_irq(state);
return available;
}

/*******************************************************************************
Expand All @@ -164,20 +191,36 @@ uint8_t USB_USART_Available_Data(void)
*******************************************************************************/
int32_t USB_USART_Receive_Data(uint8_t peek)
{
if(USB_Rx_State == 1)
if (USB_USART_Available_Data() > 0)
{
if(!peek && ((USB_Rx_length - USB_Rx_ptr) == 1))
{
USB_Rx_State = 0;

/* Prepare Out endpoint to receive next packet */
DCD_EP_PrepareRx(&USB_OTG_dev,
CDC_OUT_EP,
(uint8_t*)(USB_Rx_Buffer),
CDC_DATA_OUT_PACKET_SIZE);
int state = HAL_disable_irq();
uint8_t data = USB_Rx_Buffer[USB_Rx_Buffer_tail];
if (!peek) {
USB_Rx_Buffer_tail++;
if (USB_Rx_Buffer_tail == USB_Rx_Buffer_length)
USB_Rx_Buffer_tail = 0;
}
HAL_enable_irq(state);
return data;
}

return -1;
}

return USB_Rx_Buffer[peek ? USB_Rx_ptr : USB_Rx_ptr++];
/*******************************************************************************
* Function Name : USB_USART_Available_Data_For_Write.
* Description : Return the length of available space in TX buffer
* Input : None.
* Return : Length.
*******************************************************************************/
int32_t USB_USART_Available_Data_For_Write(void)
{
if (USB_USART_Connected())
{
uint32_t tail = USB_Tx_Buffer_tail;
int32_t available = USB_TX_BUFFER_SIZE - (USB_Tx_Buffer_head >= tail ?
USB_Tx_Buffer_head - tail : USB_TX_BUFFER_SIZE + USB_Tx_Buffer_head - tail) - 1;
return available;
}

return -1;
Expand All @@ -191,18 +234,33 @@ int32_t USB_USART_Receive_Data(uint8_t peek)
*******************************************************************************/
void USB_USART_Send_Data(uint8_t Data)
{
APP_Rx_Buffer[APP_Rx_ptr_in] = Data;
int32_t available = 0;
do {
available = USB_USART_Available_Data_For_Write();
}
while (available < 1 && available != -1);
// Confirm once again that the Host is connected
if (USB_USART_Connected())
{
uint32_t head = USB_Tx_Buffer_head;

APP_Rx_ptr_in++;
USB_Tx_Buffer[head] = Data;

/* To avoid buffer overflow */
if(APP_Rx_ptr_in == APP_RX_DATA_SIZE)
{
APP_Rx_ptr_in = 0;
USB_Tx_Buffer_head = ++head % USB_TX_BUFFER_SIZE;
}
}

//Delay 100us to avoid losing the data
HAL_Delay_Microseconds(100);
/*******************************************************************************
* Function Name : USB_USART_Flush_Data.
* Description : Flushes TX buffer
* Input : None.
* Return : None.
*******************************************************************************/
void USB_USART_Flush_Data(void)
{
while(USB_USART_Connected() && USB_USART_Available_Data_For_Write() != (USB_TX_BUFFER_SIZE - 1));
// We should also wait for USB_Tx_State to become 0, as hardware might still be busy transmitting data
while(USB_Tx_State == 1);
}
#endif

Expand Down
Loading

0 comments on commit 8a43301

Please sign in to comment.