BeRTOS
ser_stm32.c
Go to the documentation of this file.
00001 
00038 #include "ser_stm32.h"
00039 
00040 #include "cfg/cfg_ser.h"
00041 
00042 #include <cfg/macros.h> /* for BV() */
00043 #include <cfg/debug.h>
00044 
00045 #include <drv/gpio_stm32.h>
00046 #include <drv/irq_cm3.h>
00047 #include <drv/clock_stm32.h>
00048 #include <drv/ser_p.h>
00049 #include <drv/ser.h>
00050 
00051 
00052 /* From the high-level serial driver */
00053 extern struct Serial *ser_handles[SER_CNT];
00054 
00055 struct CM3Serial
00056 {
00057     struct SerialHardware hw;
00058     volatile bool sending;
00059     uint32_t base;
00060     sysirq_t irq;
00061 };
00062 
00063 /* Forward declaration */
00064 static struct CM3Serial UARTDesc[SER_CNT];
00065 
00066 /* GPIO descriptor for UART pins */
00067 struct gpio_uart_info
00068 {
00069     /* GPIO base address register */
00070     uint32_t base;
00071     /* Pin(s) bitmask */
00072     uint32_t rx_pin;
00073     uint32_t tx_pin;
00074     /* Sysctl */
00075     uint32_t sysctl_gpio;
00076     uint32_t sysctl_usart;
00077 
00078 };
00079 
00080 /* Table to retrieve GPIO pins configuration to work as UART pins */
00081 static const struct gpio_uart_info gpio_uart[SER_CNT] =
00082 {
00083     /* UART1 */
00084     {
00085         .base = GPIOA_BASE,
00086         .rx_pin = GPIO_USART1_RX_PIN,
00087         .tx_pin = GPIO_USART1_TX_PIN,
00088         .sysctl_gpio = RCC_APB2_GPIOA,
00089         .sysctl_usart = RCC_APB2_USART1,
00090     },
00091     /* UART2 */
00092     {
00093         .base = GPIOA_BASE,
00094         .rx_pin = GPIO_USART2_RX_PIN,
00095         .tx_pin = GPIO_USART2_TX_PIN,
00096         .sysctl_gpio = RCC_APB2_GPIOA,
00097         .sysctl_usart = RCC_APB1_USART2,
00098     },
00099 #if CPU_CM3_STM32F103RB || CPU_CM3_STM32F103RE
00100     /* UART3 */
00101     {
00102         .base = GPIOB_BASE,
00103         .rx_pin = GPIO_USART3_RX_PIN,
00104         .tx_pin = GPIO_USART3_TX_PIN,
00105         .sysctl_gpio = RCC_APB2_GPIOB,
00106         .sysctl_usart = RCC_APB1_USART3,
00107     },
00108 #endif
00109 };
00110 
00111 #define USART1_PORT                0
00112 #define USART2_PORT                1
00113 #define USART3_PORT                2
00114 
00115 void stm32_uartSetBaudRate(uint32_t base, unsigned long baud)
00116 {
00117     struct stm32_usart *_base = (struct stm32_usart *)base;
00118     _base->BRR = evaluate_brr(_base, CPU_FREQ, baud);
00119 }
00120 
00121 void stm32_uartSetParity(uint32_t base, int parity)
00122 {
00123     struct stm32_usart *_base = (struct stm32_usart *)base;
00124 
00125     /*  USART_WORD_LEN_8B */
00126     _base->CR1 &= ~BV(CR1_M);
00127 
00128     switch(parity)
00129     {
00130     case SER_PARITY_NONE:
00131         _base->CR1 &= ~BV(CR1_PCE);
00132         break;
00133     case SER_PARITY_ODD:
00134         _base->CR1 |= (BV(CR1_PCE) | BV(CR1_PS));
00135         break;
00136     case SER_PARITY_EVEN:
00137         _base->CR1 |= BV(CR1_PCE);
00138         _base->CR1 &= ~BV(CR1_PS);
00139         break;
00140     default:
00141         ASSERT(0);
00142         return;
00143     }
00144 }
00145 
00146 void stm32_uartInit(int port)
00147 {
00148     struct stm32_usart *base = (struct stm32_usart *)UARTDesc[port].base;
00149 
00150     ASSERT(port >= 0 && port < SER_CNT);
00151 
00152     /* Enable clocking on AFIO */
00153     RCC->APB2ENR |= RCC_APB2_AFIO;
00154     RCC->APB2ENR |= gpio_uart[port].sysctl_gpio;
00155 
00156     /* Configure USART pins */
00157     if (port == USART1_PORT)
00158     {
00159         RCC->APB2ENR |=  gpio_uart[port].sysctl_usart;
00160     }
00161     else
00162     {
00163         RCC->APB1ENR |=  gpio_uart[port].sysctl_usart;
00164     }
00165 
00166     stm32_gpioPinConfig((struct stm32_gpio *)gpio_uart[port].base,  gpio_uart[port].tx_pin,
00167                 GPIO_MODE_AF_PP, GPIO_SPEED_50MHZ);
00168 
00169     stm32_gpioPinConfig((struct stm32_gpio *)gpio_uart[port].base,  gpio_uart[port].rx_pin,
00170                 GPIO_MODE_IN_FLOATING, GPIO_SPEED_50MHZ);
00171 
00172     /* Clear control registry */
00173     base->CR2 = 0;
00174     base->CR1 = 0;
00175     base->CR3 = 0;
00176     base->SR = 0;
00177 
00178     /* Set serial param: 115.200 bps, no parity */
00179     stm32_uartSetBaudRate(UARTDesc[port].base, 115200);
00180     stm32_uartSetParity(UARTDesc[port].base, SER_PARITY_NONE);
00181 
00182 
00183     /* Enable trasmision and receiver */
00184     base->CR1 |= (BV(CR1_TE) | BV(CR1_RE));
00185 
00186 }
00187 
00188 static bool tx_sending(struct SerialHardware *_hw)
00189 {
00190     struct CM3Serial *hw = (struct CM3Serial *)_hw;
00191     return hw->sending;
00192 }
00193 
00194 static void uart_irq_rx(int port)
00195 {
00196     struct FIFOBuffer *rxfifo = &ser_handles[port]->rxfifo;
00197     struct stm32_usart *base = (struct stm32_usart *)UARTDesc[port].base;
00198     char c;
00199 
00200     while (stm32_uartRxReady(UARTDesc[port].base))
00201     {
00202         c = base->DR;
00203         if (fifo_isfull(rxfifo))
00204             ser_handles[port]->status |= SERRF_RXFIFOOVERRUN;
00205         else
00206             fifo_push(rxfifo, c);
00207     }
00208 }
00209 
00210 static void uart_irq_tx(int port)
00211 {
00212     struct FIFOBuffer *txfifo = &ser_handles[port]->txfifo;
00213     struct stm32_usart *base = (struct stm32_usart *)UARTDesc[port].base;
00214 
00215     if (fifo_isempty(txfifo))
00216     {
00217         /*
00218          * Disable TX empty interrupts if there're no more
00219          * characters to transmit.
00220          */
00221         base->CR1 &= ~BV(CR1_TXEIE);
00222         UARTDesc[port].sending = false;
00223     }
00224     else
00225     {
00226         base->DR = fifo_pop(txfifo);
00227     }
00228 }
00229 
00230 static void uart_common_irq_handler(int port)
00231 {
00232     struct stm32_usart *base = (struct stm32_usart *)UARTDesc[port].base;
00233     uint32_t status;
00234 
00235     /* Read and clear the IRQ status */
00236     status = base->SR;
00237 
00238     /* Check hw errors */
00239     ser_handles[port]->status = status &
00240         (BV(SR_ORE) | BV(SR_FE) | BV(SR_PE) | BV(SR_NE));
00241 
00242     /* Process the IRQ */
00243     if (status & BV(CR1_RXNEIE))
00244     {
00245         uart_irq_rx(port);
00246     }
00247     if (status & (BV(CR1_TXEIE) | BV(CR1_TCIE)))
00248     {
00249         uart_irq_tx(port);
00250     }
00251 }
00252 
00253 static void stm32_uartIRQEnable(int port, sysirq_handler_t handler)
00254 {
00255     struct stm32_usart *base = (struct stm32_usart *)UARTDesc[port].base;
00256 
00257     /* Register the IRQ handler */
00258     sysirq_setHandler(UARTDesc[port].irq, handler);
00259 
00260     base->CR1 |= BV(CR1_RXNEIE);
00261 }
00262 
00263 static void stm32_uartIRQDisable(int port)
00264 {
00265     struct stm32_usart *base = (struct stm32_usart *)UARTDesc[port].base;
00266 
00267     base->CR1 &= ~(BV(CR1_RXNEIE) | USART_FLAG_TXE);
00268 }
00269 
00270 
00271 /* UART class definition */
00272 #define UART_PORT(port)          \
00273     /* UART TX and RX buffers */ \
00274     static unsigned char uart ## port ## _txbuffer[CONFIG_UART ## port ## _TXBUFSIZE]; \
00275     static unsigned char uart ## port ## _rxbuffer[CONFIG_UART ## port ## _RXBUFSIZE];  \
00276                                         \
00277     /* UART interrupt handler */                        \
00278     static DECLARE_ISR(uart ## port ## _irq_handler)    \
00279     {                                   \
00280         uart_common_irq_handler(USART ## port ## _PORT);    \
00281     }                                   \
00282                                         \
00283     /* UART public methods */ \
00284     static void uart ## port ## _txStart(struct SerialHardware *_hw) \
00285     {                                                                \
00286         struct FIFOBuffer *txfifo = &ser_handles[USART ## port ## _PORT]->txfifo;        \
00287         struct CM3Serial *hw = (struct CM3Serial *)_hw;              \
00288         struct stm32_usart *base = (struct stm32_usart *)USART## port ## _BASE; \
00289         if (hw->sending)                        \
00290             return;                         \
00291         stm32_uartPutChar(USART ## port ## _BASE, fifo_pop(txfifo));    \
00292         if (!fifo_isempty(txfifo))                  \
00293         {                               \
00294             hw->sending = true;  \
00295             base->CR1 |= BV(CR1_TXEIE); \
00296         } \
00297     }                                   \
00298                                         \
00299     static void uart ## port ## _setbaudrate(UNUSED_ARG(struct SerialHardware *, hw), \
00300                         unsigned long baud)     \
00301     {                                   \
00302         stm32_uartSetBaudRate(USART## port ## _BASE, baud);     \
00303     }                                   \
00304                                         \
00305     static void uart ## port ## _setparity(UNUSED_ARG(struct SerialHardware *, hw), \
00306                         int parity)         \
00307     {                                   \
00308         stm32_uartSetParity(USART## port ## _BASE, parity);     \
00309     }                                   \
00310                                         \
00311     static void uart ## port ## _cleanup(struct SerialHardware *_hw)            \
00312     {                                   \
00313         struct CM3Serial *hw = (struct CM3Serial *)_hw;         \
00314         hw->sending = false; \
00315         stm32_uartIRQDisable(USART ## port ## _PORT);                   \
00316         stm32_uartClear(USART## port ## _BASE);             \
00317         stm32_uartDisable(USART## port ## _BASE);           \
00318     }                                   \
00319                                         \
00320     static void uart ## port ## _init(UNUSED_ARG(struct SerialHardware *, hw),      \
00321                 UNUSED_ARG(struct Serial *, ser))       \
00322     {                                   \
00323         stm32_uartInit(USART ## port ## _PORT);                     \
00324         stm32_uartEnable(USART## port ## _BASE);                \
00325         stm32_uartIRQEnable(USART ## port ## _PORT, uart ## port ## _irq_handler);      \
00326     }                                   \
00327                                         \
00328     /* UART operations */                           \
00329     static const struct SerialHardwareVT USART ## port ## _VT =     \
00330     {                                   \
00331         .init = uart ## port ## _init,                  \
00332         .cleanup = uart ## port ## _cleanup,                \
00333         .setBaudrate = uart ## port ## _setbaudrate,            \
00334         .setParity = uart ## port ## _setparity,            \
00335         .txStart = uart ## port ## _txStart,                \
00336         .txSending = tx_sending,                    \
00337     };
00338 
00339 /* UART port instances */
00340 UART_PORT(1)
00341 UART_PORT(2)
00342 #if CPU_CM3_STM32F103RB || CPU_CM3_STM32F103RE
00343 UART_PORT(3)
00344 #endif
00345 
00346 static struct CM3Serial UARTDesc[SER_CNT] =
00347 {
00348     {
00349         .hw = {
00350             .table = &USART1_VT,
00351             .txbuffer = uart1_txbuffer,
00352             .rxbuffer = uart1_rxbuffer,
00353             .txbuffer_size = sizeof(uart1_txbuffer),
00354             .rxbuffer_size = sizeof(uart1_rxbuffer),
00355         },
00356         .sending = false,
00357         .base = USART1_BASE,
00358         .irq = USART1_IRQHANDLER,
00359     },
00360     {
00361         .hw = {
00362             .table = &USART2_VT,
00363             .txbuffer = uart2_txbuffer,
00364             .rxbuffer = uart2_rxbuffer,
00365             .txbuffer_size = sizeof(uart2_txbuffer),
00366             .rxbuffer_size = sizeof(uart2_rxbuffer),
00367         },
00368         .sending = false,
00369         .base = USART2_BASE,
00370         .irq = USART2_IRQHANDLER,
00371     },
00372 #if CPU_CM3_STM32F103RB || CPU_CM3_STM32F103RE
00373     {
00374         .hw = {
00375             .table = &USART3_VT,
00376             .txbuffer = uart3_txbuffer,
00377             .rxbuffer = uart3_rxbuffer,
00378             .txbuffer_size = sizeof(uart3_txbuffer),
00379             .rxbuffer_size = sizeof(uart3_rxbuffer),
00380         },
00381         .sending = false,
00382         .base = USART3_BASE,
00383         .irq = USART3_IRQHANDLER,
00384     },
00385 #endif
00386 };
00387 
00388 struct SerialHardware *ser_hw_getdesc(int port)
00389 {
00390     ASSERT(port >= 0 && port < SER_CNT);
00391     return &UARTDesc[port].hw;
00392 }