Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LIN Bus support, USART hardware flow control configuration support #930

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions hal/inc/hal_dynalib_usart.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,10 @@ DYNALIB_FN(BASE_IDX + 12, hal_usart, USB_USART_Flush_Data, void(void))
#define BASE_IDX2 (BASE_IDX+11)
#endif

DYNALIB_FN(BASE_IDX2 + 0, hal_usart,HAL_USART_BeginConfig,void(HAL_USART_Serial serial, uint32_t baud, uint32_t config, void *ptr))
DYNALIB_FN(BASE_IDX2 + 1, hal_usart,HAL_USART_Write_NineBitData, uint32_t(HAL_USART_Serial serial, uint16_t data))

DYNALIB_FN(BASE_IDX2 + 0, hal_usart, HAL_USART_BeginConfig, void(HAL_USART_Serial serial, uint32_t baud, uint32_t config, void *ptr))
DYNALIB_FN(BASE_IDX2 + 1, hal_usart, HAL_USART_Write_NineBitData, uint32_t(HAL_USART_Serial serial, uint16_t data))
DYNALIB_FN(BASE_IDX2 + 2, hal_usart, HAL_USART_Send_Break, void(HAL_USART_Serial, void*))
DYNALIB_FN(BASE_IDX2 + 3, hal_usart, HAL_USART_Break_Detected, uint8_t(HAL_USART_Serial))

DYNALIB_END(hal_usart)

Expand Down
30 changes: 30 additions & 0 deletions hal/inc/usart_hal.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,34 @@
#define SERIAL_STOP_BITS (uint8_t)0b00000011
#define SERIAL_PARITY_BITS (uint8_t)0b00001100
#define SERIAL_NINE_BITS (uint8_t)0b00010000
#define SERIAL_FLOW_CONTROL ((uint8_t)0b11000000)

// Flow control settings
#define SERIAL_FLOW_CONTROL_NONE ((uint8_t)0b00000000)
#define SERIAL_FLOW_CONTROL_RTS ((uint8_t)0b01000000)
#define SERIAL_FLOW_CONTROL_CTS ((uint8_t)0b10000000)
#define SERIAL_FLOW_CONTROL_RTS_CTS ((uint8_t)0b11000000)

// LIN Configuration masks
#define LIN_MODE ((uint32_t)0x0300)
#define LIN_BREAK_BITS ((uint32_t)0x0C00)

// LIN modes
#define LIN_MODE_MASTER ((uint32_t)0x0100)
#define LIN_MODE_SLAVE ((uint32_t)0x0200)

// LIN break settings
// Supported only in Master mode
#define LIN_BREAK_13B ((uint32_t)0x0000)
// Supported only in Slave mode
#define LIN_BREAK_10B ((uint32_t)0x0800)
#define LIN_BREAK_11B ((uint32_t)0x0C00)

// Pre-defined LIN configurations
#define LIN_MASTER_13B (uint32_t)(((uint32_t)SERIAL_8N1) | LIN_MODE_MASTER | LIN_BREAK_13B)
#define LIN_SLAVE_10B (uint32_t)(((uint32_t)SERIAL_8N1) | LIN_MODE_SLAVE | LIN_BREAK_10B)
#define LIN_SLAVE_11B (uint32_t)(((uint32_t)SERIAL_8N1) | LIN_MODE_SLAVE | LIN_BREAK_11B)


/* Exported types ------------------------------------------------------------*/
typedef struct Ring_Buffer
Expand Down Expand Up @@ -97,6 +125,8 @@ bool HAL_USART_Is_Enabled(HAL_USART_Serial serial);
void HAL_USART_Half_Duplex(HAL_USART_Serial serial, bool Enable);
void HAL_USART_BeginConfig(HAL_USART_Serial serial, uint32_t baud, uint32_t config, void*);
uint32_t HAL_USART_Write_NineBitData(HAL_USART_Serial serial, uint16_t data);
void HAL_USART_Send_Break(HAL_USART_Serial serial, void* reserved);
uint8_t HAL_USART_Break_Detected(HAL_USART_Serial serial);

#ifdef __cplusplus
}
Expand Down
97 changes: 90 additions & 7 deletions hal/src/core/usart_hal.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "gpio_hal.h"
#include "stm32f10x.h"
#include <string.h>
#include "interrupts_hal.h"

/* Private typedef -----------------------------------------------------------*/
typedef enum USART_Num_Def {
Expand Down Expand Up @@ -55,12 +56,17 @@ typedef struct STM32_USART_Info {

uint32_t usart_pin_remap;

uint16_t usart_cts_pin;
uint16_t usart_rts_pin;

// Buffer pointers. These need to be global for IRQ handler access
Ring_Buffer* usart_tx_buffer;
Ring_Buffer* usart_rx_buffer;

bool usart_enabled;
bool usart_transmitting;

uint32_t usart_config;
} STM32_USART_Info;

/*
Expand All @@ -76,12 +82,14 @@ STM32_USART_Info USART_MAP[TOTAL_USARTS] =
* TX pin
* RX pin
* GPIO Remap (RCC_APB2Periph_USART2 or GPIO_Remap_None )
* CTS pin
* RTS pin
* <tx_buffer pointer> used internally and does not appear below
* <rx_buffer pointer> used internally and does not appear below
* <usart enabled> used internally and does not appear below
* <usart transmitting> used internally and does not appear below
*/
{ USART2, &RCC->APB1ENR, RCC_APB1Periph_USART2, USART2_IRQn, TX, RX, GPIO_Remap_None },
{ USART2, &RCC->APB1ENR, RCC_APB1Periph_USART2, USART2_IRQn, TX, RX, GPIO_Remap_None, A0, A1 },
{ USART1, &RCC->APB2ENR, RCC_APB2Periph_USART1, USART1_IRQn, D1, D0, GPIO_Remap_USART1 }
};

Expand Down Expand Up @@ -175,13 +183,43 @@ void HAL_USART_BeginConfig(HAL_USART_Serial serial, uint32_t baud, uint32_t conf
// USART configuration
USART_InitStructure.USART_BaudRate = baud;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
#if USE_USART3_HARDWARE_FLOW_CONTROL_RTS_CTS // Electron
if (serial == HAL_USART_SERIAL3)
{
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_RTS_CTS;

switch (config & SERIAL_FLOW_CONTROL) {
case SERIAL_FLOW_CONTROL_CTS:
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_CTS;
break;
case SERIAL_FLOW_CONTROL_RTS:
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_RTS;
break;
case SERIAL_FLOW_CONTROL_RTS_CTS:
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_RTS_CTS;
break;
case SERIAL_FLOW_CONTROL_NONE:
default:
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
break;
}

if (serial == HAL_USART_SERIAL2) {
// USART1 supports hardware flow control, but RTS and CTS pins are not exposed
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
}

switch (USART_InitStructure.USART_HardwareFlowControl) {
case USART_HardwareFlowControl_CTS:
HAL_Pin_Mode(usartMap[serial]->usart_cts_pin, AF_OUTPUT_PUSHPULL);
break;
case USART_HardwareFlowControl_RTS:
HAL_Pin_Mode(usartMap[serial]->usart_rts_pin, AF_OUTPUT_PUSHPULL);
break;
case USART_HardwareFlowControl_RTS_CTS:
HAL_Pin_Mode(usartMap[serial]->usart_cts_pin, AF_OUTPUT_PUSHPULL);
HAL_Pin_Mode(usartMap[serial]->usart_rts_pin, AF_OUTPUT_PUSHPULL);
break;
case USART_HardwareFlowControl_None:
default:
break;
}
#endif

// Stop bit configuration.
switch (config & SERIAL_STOP_BITS) {
Expand Down Expand Up @@ -222,16 +260,38 @@ void HAL_USART_BeginConfig(HAL_USART_Serial serial, uint32_t baud, uint32_t conf
}
}

// Disable LIN mode just in case
USART_LINCmd(usartMap[serial]->usart_peripheral, DISABLE);

// Configure USART
USART_Init(usartMap[serial]->usart_peripheral, &USART_InitStructure);

// LIN configuration
if (config & LIN_MODE) {
// Enable break detection
switch(config & LIN_BREAK_BITS) {
case LIN_BREAK_10B:
USART_LINBreakDetectLengthConfig(usartMap[serial]->usart_peripheral, USART_LINBreakDetectLength_10b);
break;
case LIN_BREAK_11B:
USART_LINBreakDetectLengthConfig(usartMap[serial]->usart_peripheral, USART_LINBreakDetectLength_11b);
break;
}
}


// Enable USART Receive and Transmit interrupts
USART_ITConfig(usartMap[serial]->usart_peripheral, USART_IT_RXNE, ENABLE);
USART_ITConfig(usartMap[serial]->usart_peripheral, USART_IT_TXE, ENABLE);

// Enable the USART
USART_Cmd(usartMap[serial]->usart_peripheral, ENABLE);

if (config & LIN_MODE) {
USART_LINCmd(usartMap[serial]->usart_peripheral, ENABLE);
}

usartMap[serial]->usart_config = config;
usartMap[serial]->usart_enabled = true;
usartMap[serial]->usart_transmitting = false;
}
Expand All @@ -244,6 +304,9 @@ void HAL_USART_End(HAL_USART_Serial serial)
// Disable the USART
USART_Cmd(usartMap[serial]->usart_peripheral, DISABLE);

// Disable LIN mode
USART_LINCmd(usartMap[serial]->usart_peripheral, DISABLE);

// Deinitialise USART
USART_DeInit(usartMap[serial]->usart_peripheral);

Expand Down Expand Up @@ -386,6 +449,26 @@ void HAL_USART_Half_Duplex(HAL_USART_Serial serial, bool Enable)
USART_HalfDuplexCmd(usartMap[serial]->usart_peripheral, Enable ? ENABLE : DISABLE);
}

void HAL_USART_Send_Break(HAL_USART_Serial serial, void* reserved)
{
int32_t state = HAL_disable_irq();
while((usartMap[serial]->usart_peripheral->CR1 & USART_CR1_SBK) == SET);
USART_SendBreak(usartMap[serial]->usart_peripheral);
while((usartMap[serial]->usart_peripheral->CR1 & USART_CR1_SBK) == SET);
HAL_enable_irq(state);
}

uint8_t HAL_USART_Break_Detected(HAL_USART_Serial serial)
{
if (USART_GetFlagStatus(usartMap[serial]->usart_peripheral, USART_FLAG_LBD)) {
// Clear LBD flag
USART_ClearFlag(usartMap[serial]->usart_peripheral, USART_FLAG_LBD);
return 1;
}

return 0;
}

// Shared Interrupt Handler for USART2/Serial1 and USART1/Serial2
// WARNING: This function MUST remain reentrance compliant -- no local static variables etc.
static void HAL_USART_Handler(HAL_USART_Serial serial)
Expand Down
9 changes: 9 additions & 0 deletions hal/src/gcc/usart_hal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -240,3 +240,12 @@ uint32_t HAL_USART_Write_NineBitData(HAL_USART_Serial serial, uint16_t data)
{
return usartMap(serial).write((uint8_t) data);
}

void HAL_USART_Send_Break(HAL_USART_Serial serial, void* reserved)
{
}

uint8_t HAL_USART_Break_Detected(HAL_USART_Serial serial)
{
return 0;
}
Loading