506 lines
13 KiB
C
506 lines
13 KiB
C
/*==============================================================================
|
||
* Инициализация тактирования с использованием бибилотеки PLIB035
|
||
*------------------------------------------------------------------------------
|
||
* ЦНИИ СЭТ, Разваляев Алексей <wot890089@mail.ru>
|
||
*==============================================================================
|
||
* ЦНИИ СЭТ
|
||
*==============================================================================
|
||
*/
|
||
|
||
//-- Includes ------------------------------------------------------------------
|
||
#include "periph_config.h"
|
||
|
||
UART_HandleTypeDef huart0;
|
||
UART_HandleTypeDef huart1;
|
||
|
||
|
||
|
||
static int __uart_fifo_receive(UART_HandleTypeDef *huart, uint8_t it_mode);
|
||
static int __uart_fifo_transmit(UART_HandleTypeDef *huart, uint8_t it_mode);
|
||
//-- Defines -------------------------------------------------------------------
|
||
|
||
|
||
|
||
|
||
//-- Peripheral init functions -------------------------------------------------
|
||
void uart_init_first(void)
|
||
{
|
||
|
||
#if (USE_UART0==1)
|
||
// Настройка пинов для UART0
|
||
uart0_gpio_init();
|
||
|
||
// Включаем тактирование UART0
|
||
RCU_UARTClkConfig(UART0_Num, RCU_PeriphClk_PLLClk, 0, DISABLE);
|
||
RCU_UARTClkCmd(UART0_Num, ENABLE);
|
||
UART_DeInit(UART0);
|
||
// Инициализируем UART0
|
||
huart0.UART = UART0;
|
||
uart_init(&huart0, &uart0_config);
|
||
NVIC_EnableIRQ(UART0_TD_IRQn);
|
||
NVIC_EnableIRQ(UART0_RX_IRQn);
|
||
NVIC_EnableIRQ(UART0_TX_IRQn);
|
||
NVIC_EnableIRQ(UART0_E_RT_IRQn);
|
||
#endif
|
||
|
||
|
||
#if (USE_UART1==1)
|
||
// Настройка пинов для UART1
|
||
uart1_gpio_init();
|
||
|
||
// Включаем тактирование UART1
|
||
RCU_UARTClkConfig(UART1_Num, RCU_PeriphClk_PLLClk, 0, DISABLE);
|
||
RCU_UARTClkCmd(UART1_Num, ENABLE);
|
||
UART_DeInit(UART1);
|
||
|
||
// Инициализируем UART1
|
||
NVIC_EnableIRQ(UART1_TD_IRQn);
|
||
NVIC_EnableIRQ(UART1_RX_IRQn);
|
||
NVIC_EnableIRQ(UART1_TX_IRQn);
|
||
NVIC_EnableIRQ(UART1_E_RT_IRQn);
|
||
|
||
huart1.UART = UART1;
|
||
uart_init(&huart1, &uart1_config);
|
||
|
||
#endif
|
||
}
|
||
|
||
|
||
|
||
|
||
/**
|
||
* @brief Инициализация UART
|
||
* @param htmr указатель на хендл UART
|
||
* @param NewConfig указатель на новую конфигурацию UART, иначе используется та, что в структуре
|
||
* @retval OperationStatus OK - если всё хорошо, ERROR - если ошибка
|
||
*/
|
||
OperationStatus uart_init(UART_HandleTypeDef *huart, UART_ExtInitTypeDef *NewConfig)
|
||
{
|
||
if(huart->UART == NULL)
|
||
{
|
||
return ERROR;
|
||
}
|
||
if(NewConfig != NULL)
|
||
{
|
||
huart->Config = NewConfig;
|
||
}
|
||
if(huart->Config == NULL)
|
||
{
|
||
return ERROR;
|
||
}
|
||
|
||
UART_Init(huart->UART, &huart->Config->UART_Init);
|
||
|
||
return OK;
|
||
}
|
||
|
||
OperationStatus uart_start(UART_HandleTypeDef *huart, UART_FIFOLevel_TypeDef TxFifoLevel, UART_FIFOLevel_TypeDef RxFifoLevel)
|
||
{
|
||
if (huart == NULL)
|
||
return ERROR;
|
||
|
||
UART_ITFIFOLevelRxConfig(huart->UART, RxFifoLevel);
|
||
UART_ITFIFOLevelTxConfig(huart->UART, TxFifoLevel);
|
||
|
||
|
||
huart->TxBufPtr = NULL;
|
||
huart->TxCount = 0;
|
||
huart->TxSize = 0;
|
||
huart->TxBusy = 0;
|
||
|
||
huart->RxBufPtr = NULL;
|
||
huart->RxCount = 0;
|
||
huart->RxSize = 0;
|
||
huart->RxBusy = 0;
|
||
|
||
UART_Cmd(huart->UART, ENABLE);
|
||
|
||
return OK;
|
||
}
|
||
|
||
OperationStatus uart_transmit(UART_HandleTypeDef *huart,
|
||
uint8_t *buf,
|
||
uint16_t size,
|
||
uint32_t timeout)
|
||
{
|
||
if (!huart || !buf || size == 0)
|
||
return ERROR;
|
||
|
||
// Если TX занят, возвращаем ERROR
|
||
if (huart->TxBusy)
|
||
return ERROR;
|
||
|
||
huart->TxBufPtr = buf;
|
||
huart->TxSize = size;
|
||
huart->TxCount = 0;
|
||
huart->TxBusy = 1;
|
||
|
||
uint32_t starttick = millis();
|
||
// Отправляем пока всё не отправится
|
||
while(__uart_fifo_transmit(huart, 0) == 0)
|
||
{
|
||
if(millis() - starttick > timeout)
|
||
return ERROR;
|
||
}
|
||
|
||
return OK;
|
||
}
|
||
|
||
OperationStatus uart_receive(UART_HandleTypeDef *huart,
|
||
uint8_t *buf,
|
||
uint16_t size,
|
||
uint32_t timeout)
|
||
{
|
||
if (!huart || !buf || size == 0)
|
||
return ERROR;
|
||
|
||
// Если RX занят, возвращаем ERROR
|
||
if (huart->RxBusy)
|
||
return ERROR;
|
||
|
||
huart->RxBufPtr = buf;
|
||
huart->RxSize = size;
|
||
huart->RxCount = 0;
|
||
huart->RxBusy = 1;
|
||
|
||
uint32_t starttick = millis();
|
||
// Принимаем всё пока всё не примется
|
||
while(__uart_fifo_transmit(huart, 0) == 0)
|
||
{
|
||
if(millis() - starttick > timeout)
|
||
return ERROR;;
|
||
}
|
||
|
||
return OK;
|
||
}
|
||
|
||
|
||
OperationStatus uart_transmit_it(UART_HandleTypeDef *huart,
|
||
uint8_t *buf,
|
||
uint16_t size)
|
||
{
|
||
if (!huart || !buf || size == 0)
|
||
return ERROR;
|
||
|
||
// Если TX занят, возвращаем ERROR
|
||
if (huart->TxBusy)
|
||
return ERROR;
|
||
|
||
huart->TxBufPtr = buf;
|
||
huart->TxSize = size;
|
||
huart->TxCount = 0;
|
||
huart->TxBusy = 1;
|
||
|
||
// Включаем прерывания по TX FIFO
|
||
UART_ITCmd(huart->UART, UART_ITSource_TxFIFOLevel, ENABLE);
|
||
|
||
__uart_fifo_transmit(huart, 1);
|
||
|
||
return OK;
|
||
}
|
||
|
||
|
||
|
||
OperationStatus uart_receive_it(UART_HandleTypeDef *huart,
|
||
uint8_t *buf,
|
||
uint16_t size)
|
||
{
|
||
if (!huart || !buf || size == 0)
|
||
return ERROR;
|
||
|
||
// Если RX занят, возвращаем ERROR
|
||
if (huart->RxBusy)
|
||
return ERROR;
|
||
|
||
huart->RxBufPtr = buf;
|
||
huart->RxSize = size;
|
||
huart->RxCount = 0;
|
||
huart->RxBusy = 1;
|
||
|
||
// Включаем только RX прерывания
|
||
UART_ITCmd(huart->UART,
|
||
UART_ITSource_RxFIFOLevel |
|
||
UART_ITSource_RecieveTimeout |
|
||
UART_ITSource_ErrorFrame |
|
||
UART_ITSource_ErrorParity |
|
||
UART_ITSource_ErrorOverflow |
|
||
UART_ITSource_ErrorBreak,
|
||
ENABLE);
|
||
|
||
return OK;
|
||
}
|
||
|
||
|
||
void uart_handler(UART_HandleTypeDef *huart)
|
||
{
|
||
if (!huart || !huart->UART || !huart->Config)
|
||
return;
|
||
|
||
UART_TypeDef *uart = huart->UART;
|
||
uint32_t mis = uart->MIS;
|
||
|
||
// Ошибки
|
||
if (mis & (UART_ITSource_ErrorFrame |
|
||
UART_ITSource_ErrorParity |
|
||
UART_ITSource_ErrorOverflow |
|
||
UART_ITSource_ErrorBreak))
|
||
{
|
||
if (huart->Config->ErrCallback)
|
||
huart->Config->ErrCallback();
|
||
|
||
UART_ErrorStatusClear(uart, UART_Error_All);
|
||
UART_ITStatusClear(uart, mis);
|
||
}
|
||
|
||
// RX FIFO
|
||
if (mis & UART_ITSource_RxFIFOLevel)
|
||
{
|
||
// Принимаем
|
||
if(__uart_fifo_receive(huart, 1))
|
||
{ // Когда всё приняли, флаги сбросили внутри функции
|
||
}
|
||
|
||
UART_ITStatusClear(uart, UART_ITSource_RxFIFOLevel);
|
||
}
|
||
|
||
// IDLE / Receive Timeout
|
||
if (mis & UART_ITSource_RecieveTimeout)
|
||
{
|
||
UART_ITStatusClear(uart, UART_ITSource_RecieveTimeout);
|
||
|
||
huart->RxBusy = 0;
|
||
// Выключаем RX прерывания до следующего вызова uart_receive_it
|
||
UART_ITCmd(uart,
|
||
UART_ITSource_RxFIFOLevel |
|
||
UART_ITSource_RecieveTimeout,
|
||
DISABLE);
|
||
|
||
if (huart->Config->IdleCallback)
|
||
huart->Config->IdleCallback();
|
||
}
|
||
|
||
// TX FIFO
|
||
if (mis & UART_ITSource_TxFIFOLevel)
|
||
{
|
||
// Отправляем
|
||
if(__uart_fifo_transmit(huart, 1))
|
||
{ // Когда всё отправили, флаги сбросили внутри функции
|
||
}
|
||
|
||
UART_ITStatusClear(uart, UART_ITSource_TxFIFOLevel);
|
||
}
|
||
// Конец передачи
|
||
if (mis & UART_ITSource_TransmitDone)
|
||
{
|
||
UART_ITStatusClear(uart, UART_ITSource_TransmitDone);
|
||
huart->TxBusy = 0;
|
||
|
||
if (huart->Config->TxCallback)
|
||
huart->Config->TxCallback();
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
/**
|
||
* @brief Установка коллбека UART
|
||
* @param htmr указатель на хендл UART
|
||
* @param cb_type Тип коллбека
|
||
* @param Callback Функция коллбека
|
||
* @retval void
|
||
*/
|
||
OperationStatus uart_set_callback(UART_HandleTypeDef* huart, UART_CallbackTypeDef cb_type, void (*Callback)(void))
|
||
{
|
||
if((huart->UART == NULL) || (huart->Config == NULL))
|
||
{
|
||
return ERROR;
|
||
}
|
||
|
||
switch(cb_type)
|
||
{
|
||
case UART_Callback_Rx:
|
||
huart->Config->RxCallback = Callback;
|
||
break;
|
||
case UART_Callback_Tx:
|
||
huart->Config->TxCallback = Callback;
|
||
break;
|
||
case UART_Callback_Idle:
|
||
huart->Config->IdleCallback = Callback;
|
||
break;
|
||
case UART_Callback_Error:
|
||
huart->Config->ErrCallback = Callback;
|
||
break;
|
||
|
||
default:
|
||
return ERROR;
|
||
}
|
||
return OK;
|
||
}
|
||
|
||
|
||
void uart0_gpio_init(void)
|
||
{
|
||
#if USE_UART0==1
|
||
// Получаем структуры
|
||
GPIO_Init_TypeDef *tx_config = gpio_get_init(UART0_GPIO_Port, UART0_Tx_Pin);
|
||
GPIO_Init_TypeDef *rx_config = gpio_get_init(UART0_GPIO_Port, UART0_Rx_Pin);
|
||
|
||
// TX пин
|
||
if (uart0_config.UART_Init.Tx == ENABLE && tx_config != NULL)
|
||
{
|
||
GPIO_StructInit(tx_config);
|
||
tx_config->AltFunc = ENABLE;
|
||
tx_config->Digital = ENABLE;
|
||
tx_config->Pin = UART0_Tx_Pin;
|
||
GPIO_Init(UART0_GPIO_Port, tx_config);
|
||
}
|
||
|
||
// RX пин
|
||
if (uart0_config.UART_Init.Rx == ENABLE && rx_config != NULL)
|
||
{
|
||
GPIO_StructInit(rx_config);
|
||
rx_config->AltFunc = ENABLE;
|
||
rx_config->Digital = ENABLE;
|
||
rx_config->Pin = UART0_Rx_Pin;
|
||
GPIO_Init(UART0_GPIO_Port, rx_config);
|
||
}
|
||
#endif
|
||
}
|
||
|
||
void uart0_gpio_deinit(void)
|
||
{
|
||
#if USE_UART0==1
|
||
// Получаем структуры
|
||
GPIO_Init_TypeDef *tx_config = gpio_get_init(UART0_GPIO_Port, UART0_Tx_Pin);
|
||
GPIO_Init_TypeDef *rx_config = gpio_get_init(UART0_GPIO_Port, UART0_Rx_Pin);
|
||
|
||
// Восстанавливаем оригинальные настройки из таблицы
|
||
if (tx_config != NULL)
|
||
{
|
||
GPIO_StructInit(rx_config);
|
||
rx_config->Pin = UART0_Tx_Pin;
|
||
GPIO_Init(UART0_GPIO_Port, tx_config);
|
||
}
|
||
|
||
if (rx_config != NULL)
|
||
{
|
||
GPIO_StructInit(rx_config);
|
||
rx_config->Pin = UART0_Rx_Pin;
|
||
GPIO_Init(UART0_GPIO_Port, rx_config);
|
||
}
|
||
#endif
|
||
}
|
||
|
||
void uart1_gpio_init(void)
|
||
{
|
||
#if USE_UART1==1
|
||
// Получаем структуры
|
||
GPIO_Init_TypeDef *tx_config = gpio_get_init(UART1_GPIO_Port, UART1_Tx_Pin);
|
||
GPIO_Init_TypeDef *rx_config = gpio_get_init(UART1_GPIO_Port, UART1_Rx_Pin);
|
||
|
||
// TX пин
|
||
if (uart1_config.UART_Init.Tx == ENABLE && tx_config != NULL)
|
||
{
|
||
GPIO_StructInit(tx_config);
|
||
tx_config->AltFunc = ENABLE;
|
||
tx_config->Digital = ENABLE;
|
||
tx_config->Pin = UART1_Tx_Pin;
|
||
GPIO_Init(UART1_GPIO_Port, tx_config);
|
||
}
|
||
|
||
// RX пин
|
||
if (uart1_config.UART_Init.Rx == ENABLE && rx_config != NULL)
|
||
{
|
||
;
|
||
GPIO_StructInit(rx_config);
|
||
rx_config->AltFunc = ENABLE;
|
||
rx_config->Digital = ENABLE;
|
||
rx_config->Pin = UART1_Rx_Pin;
|
||
GPIO_Init(UART1_GPIO_Port, rx_config);
|
||
}
|
||
#endif
|
||
}
|
||
|
||
void uart1_gpio_deinit(void)
|
||
{
|
||
#if USE_UART1==1
|
||
// Получаем структуры
|
||
GPIO_Init_TypeDef *tx_config = gpio_get_init(UART1_GPIO_Port, UART1_Tx_Pin);
|
||
GPIO_Init_TypeDef *rx_config = gpio_get_init(UART1_GPIO_Port, UART1_Rx_Pin);
|
||
|
||
// Восстанавливаем оригинальные настройки из таблицы
|
||
if (tx_config != NULL)
|
||
{
|
||
GPIO_StructInit(rx_config);
|
||
rx_config->Pin = UART1_Tx_Pin;
|
||
GPIO_Init(UART1_GPIO_Port, tx_config);
|
||
}
|
||
|
||
if (rx_config != NULL)
|
||
{
|
||
GPIO_StructInit(rx_config);
|
||
rx_config->Pin = UART1_Rx_Pin;
|
||
GPIO_Init(UART1_GPIO_Port, rx_config);
|
||
}
|
||
#endif
|
||
}
|
||
|
||
|
||
static int __uart_fifo_receive(UART_HandleTypeDef *huart, uint8_t it_mode)
|
||
{
|
||
while (!UART_FlagStatus(huart->UART, UART_Flag_RxFIFOEmpty) &&
|
||
huart->RxCount < huart->RxSize)
|
||
{
|
||
huart->RxBufPtr[huart->RxCount++] = UART_RecieveData(huart->UART);
|
||
|
||
if (huart->RxCount == huart->RxSize)
|
||
{
|
||
huart->RxBusy = 0;
|
||
|
||
if(it_mode)
|
||
{
|
||
// Выключаем RX прерывания
|
||
UART_ITCmd(huart->UART,
|
||
UART_ITSource_RxFIFOLevel |
|
||
UART_ITSource_RecieveTimeout,
|
||
DISABLE);
|
||
}
|
||
|
||
if (huart->Config->RxCallback)
|
||
huart->Config->RxCallback();
|
||
return 1;
|
||
}
|
||
}
|
||
return 0;
|
||
}
|
||
static int __uart_fifo_transmit(UART_HandleTypeDef *huart, uint8_t it_mode)
|
||
{
|
||
while (!UART_FlagStatus(huart->UART, UART_Flag_TxFIFOFull) &&
|
||
huart->TxCount < huart->TxSize)
|
||
{
|
||
UART_SendData(huart->UART, huart->TxBufPtr[huart->TxCount++]);
|
||
}
|
||
|
||
if (huart->TxCount == huart->TxSize)
|
||
{
|
||
if(it_mode)
|
||
{
|
||
// Выключаем FIFO прерывание
|
||
UART_ITCmd(huart->UART, UART_ITSource_TxFIFOLevel, DISABLE);
|
||
// Включаем TransmitDone прерывание, коллбек будет по нему
|
||
UART_ITCmd(huart->UART, UART_ITSource_TransmitDone, ENABLE);
|
||
}
|
||
else
|
||
{
|
||
while(!UART_FlagStatus(huart->UART, UART_Flag_TxFIFOEmpty)); // ждем пока не опустошится буфер
|
||
|
||
huart->TxBusy = 0;
|
||
if (huart->Config->TxCallback)
|
||
huart->Config->TxCallback();
|
||
}
|
||
|
||
return 1;
|
||
}
|
||
return 0;
|
||
} |