uart.c
490 lines
| 12.8 KiB
| text/x-c
|
CLexer
r71 | /*------------------------------------------------------------------------------ | |||
-- This file is a part of the libuc, microcontroler library | ||||
-- Copyright (C) 2011, Alexis Jeandet | ||||
-- | ||||
-- This program is free software; you can redistribute it and/or modify | ||||
-- it under the terms of the GNU General Public License as published by | ||||
-- the Free Software Foundation; either version 3 of the License, or | ||||
-- (at your option) any later version. | ||||
-- | ||||
-- This program is distributed in the hope that it will be useful, | ||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
-- GNU General Public License for more details. | ||||
-- | ||||
-- You should have received a copy of the GNU General Public License | ||||
-- along with this program; if not, write to the Free Software | ||||
-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||||
------------------------------------------------------------------------------- | ||||
-- Author : Alexis Jeandet | ||||
-- Mail : alexis.jeandet@member.fsf.org | ||||
-------------------------------------------------------------------------------*/ | ||||
#include <uart.h> | ||||
#include <stm32f4xx_rcc.h> | ||||
#include <stm32f4xx_gpio.h> | ||||
#include <gpio.h> | ||||
#include <stdio.h> | ||||
#define GPIOGETPORT(gpio) ((GPIO_TypeDef*)(((((uint32_t)gpio) & (uint32_t)0x0000FF00)*(uint32_t)4) + (uint32_t)GPIOA)) | ||||
#define GPIOPORTNUM(gpio) (((uint32_t)(gpio) & (uint32_t)0x0000FF00)>>(uint32_t)8) | ||||
USART_TypeDef* _uart_dev_table[6]={USART1,USART2,USART3,UART4,UART5,USART6}; | ||||
int _uartstrsetpos(streamdevice* device,int pos); | ||||
int _uartstrread(streamdevice* device,void* data,int size, int n); | ||||
int _uartstrwrite(streamdevice* device,void* data,int size, int n); | ||||
|
r104 | typedef struct _dma_pointer_ | ||
{ | ||||
int pos; | ||||
int size; | ||||
}_dma_pointer_; | ||||
#ifdef UART_USES_DMA | ||||
static char _uart_dma_buff[1024]; | ||||
_dma_pointer_ _uart1_dma_pointer={0,0}; | ||||
_dma_pointer_ _uart2_dma_pointer={0,0}; | ||||
_dma_pointer_ _uart3_dma_pointer={0,0}; | ||||
_dma_pointer_ _uart4_dma_pointer={0,0}; | ||||
_dma_pointer_ _uart5_dma_pointer={0,0}; | ||||
_dma_pointer_ _uart6_dma_pointer={0,0}; | ||||
_dma_pointer_* _uart_dma_pointer_table[6]={&_uart1_dma_pointer,&_uart2_dma_pointer,&_uart3_dma_pointer,&_uart4_dma_pointer,&_uart5_dma_pointer,&_uart6_dma_pointer}; | ||||
#endif | ||||
r71 | streamdevice_ops UART_OPS= | |||
{ | ||||
.write = &_uartstrwrite, | ||||
.read = &_uartstrread, | ||||
.setpos= &_uartstrsetpos, | ||||
.close = NULL | ||||
}; | ||||
uart_t uartopen(int count) | ||||
{ | ||||
switch(count) | ||||
{ | ||||
case uart1: | ||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); | ||||
RCC_APB2PeriphResetCmd(RCC_APB2Periph_USART1, ENABLE); | ||||
RCC_APB2PeriphResetCmd(RCC_APB2Periph_USART1, DISABLE); | ||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); | ||||
USART1->CR3 &= ~((1<<8) + (1<<9)); | ||||
return uart1; | ||||
break; | ||||
case uart2: | ||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); | ||||
RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART2, ENABLE); | ||||
RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART2, DISABLE); | ||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); | ||||
USART2->CR3 &= ~((1<<8) + (1<<9)); | ||||
return uart2; | ||||
break; | ||||
case uart3: | ||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); | ||||
RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART3, ENABLE); | ||||
RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART3, DISABLE); | ||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); | ||||
USART3->CR3 &= ~((1<<8) + (1<<9)); | ||||
return uart3; | ||||
break; | ||||
case uart4: | ||||
RCC_APB1PeriphResetCmd(RCC_APB1Periph_UART4, ENABLE); | ||||
RCC_APB1PeriphResetCmd(RCC_APB1Periph_UART4, DISABLE); | ||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4, ENABLE); | ||||
UART4->CR3 &= ~((1<<8) + (1<<9)); | ||||
return uart4; | ||||
break; | ||||
case uart5: | ||||
RCC_APB1PeriphResetCmd(RCC_APB1Periph_UART5, ENABLE); | ||||
RCC_APB1PeriphResetCmd(RCC_APB1Periph_UART5, DISABLE); | ||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART5, ENABLE); | ||||
return uart5; | ||||
break; | ||||
case uart6: | ||||
RCC_APB2PeriphResetCmd(RCC_APB2Periph_USART6, ENABLE); | ||||
RCC_APB2PeriphResetCmd(RCC_APB2Periph_USART6, DISABLE); | ||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART6, ENABLE); | ||||
return uart6; | ||||
break; | ||||
default: | ||||
break; | ||||
} | ||||
return -1; | ||||
} | ||||
uart_t uartopenandconfig(int count, uint32_t cfg, uint32_t speed, uint32_t TXpin, uint32_t RXpin, uint32_t RTSpin, uint32_t CTSpin) | ||||
{ | ||||
uart_t dev= uartopen(count); | ||||
uartsetconfig(dev,cfg,speed); | ||||
uartsetpins(dev,TXpin,RXpin,RTSpin,CTSpin); | ||||
return dev; | ||||
} | ||||
int uartclose(uart_t uart) | ||||
{ | ||||
switch(uart) | ||||
{ | ||||
case uart1: | ||||
RCC_APB2PeriphResetCmd(RCC_APB2Periph_USART1, ENABLE); | ||||
break; | ||||
case uart2: | ||||
RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART2, ENABLE); | ||||
break; | ||||
case uart3: | ||||
RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART3, ENABLE); | ||||
break; | ||||
case uart4: | ||||
RCC_APB1PeriphResetCmd(RCC_APB1Periph_UART4, ENABLE); | ||||
break; | ||||
case uart5: | ||||
RCC_APB1PeriphResetCmd(RCC_APB1Periph_UART5, ENABLE); | ||||
break; | ||||
case uart6: | ||||
RCC_APB2PeriphResetCmd(RCC_APB2Periph_USART6, ENABLE); | ||||
break; | ||||
default: | ||||
return -1; | ||||
break; | ||||
} | ||||
return 1; | ||||
} | ||||
int uartsetpins(uart_t uart,uint32_t TXpin,uint32_t RXpin,uint32_t RTSpin,uint32_t CTSpin) | ||||
{ | ||||
if(uart >5)return -1; | ||||
if(uart <0)return -1; | ||||
gpio_t TX,RX,CTS,RTS; | ||||
TX = gpioopen(TXpin); | ||||
RX = gpioopen(RXpin); | ||||
|
r104 | gpiosetconfig(TX,gpioaf,gpiolowspeed,gpiopushpulltype,gpionopulltype); | ||
gpiosetconfig(RX,gpioaf,gpiolowspeed,gpiopushpulltype,gpionopulltype); | ||||
r71 | uint8_t gpioAFuartx = GPIO_AF_USART1; | |||
switch(uart) | ||||
{ | ||||
case uart1: | ||||
gpioAFuartx = GPIO_AF_USART1; | ||||
break; | ||||
case uart2: | ||||
gpioAFuartx = GPIO_AF_USART2; | ||||
break; | ||||
case uart3: | ||||
gpioAFuartx = GPIO_AF_USART3; | ||||
break; | ||||
case uart4: | ||||
gpioAFuartx = GPIO_AF_UART4; | ||||
break; | ||||
case uart5: | ||||
gpioAFuartx = GPIO_AF_UART5; | ||||
break; | ||||
case uart6: | ||||
gpioAFuartx = GPIO_AF_USART6; | ||||
break; | ||||
default: | ||||
return -1; | ||||
break; | ||||
} | ||||
GPIO_PinAFConfig(GPIOGETPORT(TX), (uint8_t)(TX & 0xF), gpioAFuartx); | ||||
GPIO_PinAFConfig(GPIOGETPORT(RX), (uint8_t)(RX & 0xF), gpioAFuartx); | ||||
if((gpioAFuartx!=GPIO_AF_UART5) && (gpioAFuartx!=GPIO_AF_UART4)) | ||||
{ | ||||
if(CTSpin!=-1) | ||||
{ | ||||
CTS = gpioopen(CTSpin); | ||||
|
r104 | gpiosetconfig(CTS,gpioaf,gpiolowspeed,gpiopushpulltype,gpionopulltype); | ||
r71 | GPIO_PinAFConfig(GPIOGETPORT(CTS), (uint8_t)(CTS & 0xF), gpioAFuartx); | |||
} | ||||
if(RTSpin!=-1) | ||||
{ | ||||
RTS = gpioopen(RTSpin); | ||||
|
r104 | gpiosetconfig(RTS,gpioaf,gpiolowspeed,gpiopushpulltype,gpionopulltype); | ||
r71 | GPIO_PinAFConfig(GPIOGETPORT(RTS), (uint8_t)(RTS & 0xF), gpioAFuartx); | |||
} | ||||
} | ||||
return 1; | ||||
} | ||||
int uartsetconfig(uart_t uart, uint32_t cfg, uint32_t speed) | ||||
{ | ||||
int res=1; | ||||
uartdisable(uart); | ||||
uartsetspeed(uart,speed); | ||||
uartsetparity(uart,cfg & UARTPARITYMASK); | ||||
uartsetdatabits(uart,cfg & UARTBITSMASK); | ||||
uartsetstopbits(uart,cfg & UARTSTOPBITSMASK); | ||||
uartenable(uart); | ||||
return res; | ||||
} | ||||
int uartenable(uart_t uart) | ||||
{ | ||||
if((uart<6)&&(uart>=0)) | ||||
{ | ||||
USART_TypeDef* _dev_ = _uart_dev_table[(int)uart]; | ||||
_dev_->CR1 |= (1<<13); | ||||
_dev_->CR1 |= (1<<2) + (1<<3); | ||||
_dev_->DR = ' '; | ||||
return 1; | ||||
} | ||||
return -1; | ||||
} | ||||
int uartdisable(uart_t uart) | ||||
{ | ||||
if((uart<6)&&(uart>=0)) | ||||
{ | ||||
USART_TypeDef* _dev_ = _uart_dev_table[(int)uart]; | ||||
if((_dev_->CR1 & ((1<<3) +(1<<13)))==((1<<3) +(1<<13))) | ||||
{ | ||||
while((_dev_->SR & (uint16_t)(1<<7))!=(uint16_t)(1<<7)); | ||||
} | ||||
_dev_->CR1 &= ~((1<<2) + (1<<3) +(1<<13)); | ||||
return 1; | ||||
} | ||||
return -1; | ||||
} | ||||
int uartsetspeed(uart_t uart,uint32_t speed) | ||||
{ | ||||
if((uart<6)&&(uart>=0)) | ||||
{ | ||||
USART_TypeDef* _dev_ = _uart_dev_table[(int)uart]; | ||||
uint32_t tmpreg = 0x00, apbclock = 0x00; | ||||
uint32_t integerdivider = 0x00; | ||||
uint32_t fractionaldivider = 0x00; | ||||
RCC_ClocksTypeDef RCC_ClocksStatus; | ||||
RCC_GetClocksFreq(&RCC_ClocksStatus); | ||||
if ((_dev_ == USART1) || ((_dev_ == USART6))) | ||||
{ | ||||
apbclock = RCC_ClocksStatus.PCLK2_Frequency; | ||||
} | ||||
else | ||||
{ | ||||
apbclock = RCC_ClocksStatus.PCLK1_Frequency; | ||||
} | ||||
if (((_dev_->CR1) & USART_CR1_OVER8) != (uint16_t)0) | ||||
{ | ||||
integerdivider = ((25 * apbclock) / (2 * (speed))); | ||||
} | ||||
else | ||||
{ | ||||
integerdivider = ((25 * apbclock) / (4 * (speed))); | ||||
} | ||||
tmpreg = (integerdivider / 100) << 4; | ||||
fractionaldivider = integerdivider - (100 * (tmpreg >> 4)); | ||||
if ((_dev_->CR1 & USART_CR1_OVER8) != (uint16_t)0) | ||||
{ | ||||
tmpreg |= ((((fractionaldivider * 8) + 50) / 100)) & ((uint8_t)0x07); | ||||
} | ||||
else | ||||
{ | ||||
tmpreg |= ((((fractionaldivider * 16) + 50) / 100)) & ((uint8_t)0x0F); | ||||
} | ||||
_dev_->BRR = (uint16_t)tmpreg; | ||||
return 1; | ||||
} | ||||
return -1; | ||||
} | ||||
int uartsetparity(uart_t uart,uartparity_t parity) | ||||
{ | ||||
if((uart<6)&&(uart>=0)) | ||||
{ | ||||
USART_TypeDef* _dev_ = _uart_dev_table[(int)uart]; | ||||
_dev_->CR1 &= ~(((1<<9)+(1<<10))); | ||||
switch(parity) | ||||
{ | ||||
case uartparityeven: | ||||
_dev_->CR1 |= (1<<10); | ||||
break; | ||||
case uartparityodd: | ||||
_dev_->CR1 |= (1<<10) + (1<<9); | ||||
break; | ||||
case uartparitynone: | ||||
break; | ||||
default : | ||||
return 0; | ||||
break; | ||||
} | ||||
return 1; | ||||
} | ||||
return -1; | ||||
} | ||||
int uartsetdatabits(uart_t uart,uartbits_t databits) | ||||
{ | ||||
if((uart<6)&&(uart>=0)) | ||||
{ | ||||
USART_TypeDef* _dev_ = _uart_dev_table[(int)uart]; | ||||
_dev_->CR1 &= ~(((1<<12))); | ||||
switch(databits) | ||||
{ | ||||
case uart7bits: | ||||
return 0; | ||||
break; | ||||
case uart8bits: | ||||
break; | ||||
case uart9bits: | ||||
_dev_->CR1 |= (1<<12); | ||||
break; | ||||
default : | ||||
return 0; | ||||
break; | ||||
} | ||||
return 1; | ||||
} | ||||
return -1; | ||||
} | ||||
int uartsetstopbits(uart_t uart,uartstopbits_t stopbits) | ||||
{ | ||||
if((uart<6)&&(uart>=0)) | ||||
{ | ||||
USART_TypeDef* _dev_ = _uart_dev_table[(int)uart]; | ||||
_dev_->CR2 &= ~(((1<<12)+(1<<13))); | ||||
switch(stopbits) | ||||
{ | ||||
case uarthalfstop: | ||||
_dev_->CR2 |= (1<<12); | ||||
break; | ||||
case uartonestop: | ||||
break; | ||||
case uartonehalfstop: | ||||
_dev_->CR2 |= (1<<12) + (1<<13); | ||||
break; | ||||
case uarttwostop: | ||||
_dev_->CR2 |= (1<<13); | ||||
break; | ||||
default : | ||||
return 0; | ||||
break; | ||||
} | ||||
return 1; | ||||
} | ||||
return -1; | ||||
} | ||||
|
r104 | #ifdef UART_USES_DMA | ||
r71 | int uartputc(uart_t uart,char c) | |||
{ | ||||
if((uart<6)&&(uart>=0)) | ||||
{ | ||||
USART_TypeDef* _dev_ = _uart_dev_table[(int)uart]; | ||||
while((_dev_->SR & (uint16_t)(1<<7))!=(uint16_t)(1<<7)); | ||||
_dev_->DR = c; | ||||
return 1; | ||||
} | ||||
return -1; | ||||
} | ||||
|
r104 | #else | ||
int uartputc(uart_t uart,char c) | ||||
{ | ||||
if((uart<6)&&(uart>=0)) | ||||
{ | ||||
USART_TypeDef* _dev_ = _uart_dev_table[(int)uart]; | ||||
while((_dev_->SR & (uint16_t)(1<<7))!=(uint16_t)(1<<7)); | ||||
_dev_->DR = c; | ||||
return 1; | ||||
} | ||||
return -1; | ||||
} | ||||
#endif | ||||
r71 | char uartgetc(uart_t uart) | |||
{ | ||||
if((uart<6)&&(uart>=0)) | ||||
{ | ||||
USART_TypeDef* _dev_ = _uart_dev_table[(int)uart]; | ||||
while(!(_dev_->SR & (1<<5))); | ||||
return (char)_dev_->DR; | ||||
} | ||||
return -1; | ||||
} | ||||
int uartputs(uart_t uart,char* s) | ||||
{ | ||||
while (*s) uartputc(uart,*s++); | ||||
return 1; | ||||
} | ||||
int uartgets(uart_t uart,char* s) | ||||
{ | ||||
do | ||||
{ | ||||
(*s) = uartgetc(uart); | ||||
} | ||||
while(*s++); | ||||
return 1; | ||||
} | ||||
int uartputnc(uart_t uart,char* c,int n) | ||||
{ | ||||
int l=0; | ||||
while(l<n) | ||||
{ | ||||
uartputc(uart,*c++); | ||||
l++; | ||||
} | ||||
return n; | ||||
} | ||||
int uartgetnc(uart_t uart,char* c,int n) | ||||
{ | ||||
int l=0; | ||||
while(l<n) | ||||
{ | ||||
*c++=uartgetc(uart); | ||||
l++; | ||||
} | ||||
return n; | ||||
} | ||||
int uartavailiabledata(uart_t uart) | ||||
{ | ||||
if((uart<6)&&(uart>=0)) | ||||
{ | ||||
USART_TypeDef* _dev_ = _uart_dev_table[(int)uart]; | ||||
if(!(_dev_->SR & (1<<5))) | ||||
return 0; | ||||
else | ||||
return 1; | ||||
} | ||||
return -1; | ||||
} | ||||
int _uartstrwrite(streamdevice* device,void* data,int size, int n) | ||||
{ | ||||
return uartputnc((uart_t) device->_stream,(char*) data,size*n); | ||||
} | ||||
int _uartstrread(streamdevice* device,void* data,int size, int n) | ||||
{ | ||||
return uartgetnc((uart_t) device->_stream,(char*) data,size*n); | ||||
} | ||||
int _uartstrsetpos(streamdevice* device,int pos) | ||||
{ | ||||
return 1; | ||||
} | ||||
int uartmkstreamdev(uart_t uart,streamdevice* strdev) | ||||
{ | ||||
strdev->_stream = (UHANDLE)uart;/* | ||||
strdev->write = (write_t)&_uartstrwrite; | ||||
strdev->read = (read_t)&_uartstrread; | ||||
strdev->setpos = (setpos_t)&_uartstrsetpos;*/ | ||||
strdev->ops = &UART_OPS; | ||||
strdev->streamPt = 0; | ||||
return 1; | ||||
} | ||||