New Contiki port to STM32W108.
This commit is contained in:
parent
324796cd1a
commit
ec5e3ce0d7
130 changed files with 43157 additions and 0 deletions
259
cpu/stm32w108/hal/micro/cortexm3/uart.c
Normal file
259
cpu/stm32w108/hal/micro/cortexm3/uart.c
Normal file
|
@ -0,0 +1,259 @@
|
|||
/** @file hal/micro/cortexm3/uart.c
|
||||
* @brief STM32W uart drivers, supporting IAR's standard library
|
||||
* IO routines.
|
||||
*
|
||||
* <!--(C) COPYRIGHT 2010 STMicroelectronics. All rights reserved. -->
|
||||
*/
|
||||
|
||||
#include PLATFORM_HEADER
|
||||
#include "hal/micro/micro-common.h"
|
||||
#include "hal/micro/cortexm3/micro-common.h"
|
||||
#include "uart.h"
|
||||
#ifdef __GNUC__
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
#define _LLIO_STDIN ((int) stdin)
|
||||
#define _LLIO_STDOUT ((int) stdout)
|
||||
#define _LLIO_STDERR ((int) stderr)
|
||||
#define _LLIO_ERROR (-1)
|
||||
#define __write _write
|
||||
#define __read _read
|
||||
#undef putchar
|
||||
void __io_putchar( char c );
|
||||
int putchar (int c)
|
||||
{
|
||||
__io_putchar((char) c);
|
||||
return c;
|
||||
}
|
||||
#endif
|
||||
#define RECEIVE_QUEUE_SIZE (128)
|
||||
|
||||
int8u rxQ[RECEIVE_QUEUE_SIZE];
|
||||
int16u rxHead;
|
||||
int16u rxTail;
|
||||
int16u rxUsed;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Initialization
|
||||
|
||||
void uartInit(int32u baudrate, int8u databits, SerialParity parity, int8u stopbits)
|
||||
{
|
||||
int32u tempcfg;
|
||||
int32u tmp;
|
||||
|
||||
assert( (baudrate >= 300) && (baudrate <=921600) );
|
||||
|
||||
tmp = (2*12000000L + baudrate/2) / baudrate;
|
||||
SC1_UARTFRAC = tmp & 1;
|
||||
SC1_UARTPER = tmp / 2;
|
||||
|
||||
if(databits == 7) {
|
||||
tempcfg = 0;
|
||||
} else {
|
||||
tempcfg = SC_UART8BIT;
|
||||
}
|
||||
|
||||
if (parity == PARITY_ODD) {
|
||||
tempcfg |= SC_UARTPAR | SC_UARTODD;
|
||||
} else if( parity == PARITY_EVEN ) {
|
||||
tempcfg |= SC_UARTPAR;
|
||||
}
|
||||
|
||||
if ((stopbits & 0x0F) >= 2) {
|
||||
tempcfg |= SC_UART2STP;
|
||||
}
|
||||
SC1_UARTCFG = tempcfg;
|
||||
|
||||
SC1_MODE = SC1_MODE_UART;
|
||||
|
||||
rxHead=0;
|
||||
rxTail=0;
|
||||
rxUsed=0;
|
||||
|
||||
halGpioConfig(PORTB_PIN(1),GPIOCFG_OUT_ALT);
|
||||
halGpioConfig(PORTB_PIN(2),GPIOCFG_IN);
|
||||
|
||||
// Make the RX Valid interrupt level sensitive (instead of edge)
|
||||
SC1_INTMODE = SC_RXVALLEVEL;
|
||||
// Enable just RX interrupts; TX interrupts are controlled separately
|
||||
INT_SC1CFG |= (INT_SCRXVAL |
|
||||
INT_SCRXOVF |
|
||||
INT_SC1FRMERR |
|
||||
INT_SC1PARERR);
|
||||
INT_SC1FLAG = 0xFFFF; // Clear any stale interrupts
|
||||
INT_CFGSET = INT_SC1;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Transmit
|
||||
|
||||
// IAR Standard library hook for serial output
|
||||
size_t __write(int handle, const unsigned char * buffer, size_t size)
|
||||
{
|
||||
size_t nChars = 0;
|
||||
|
||||
/* This template only writes to "standard out" and "standard err",
|
||||
* for all other file handles it returns failure. */
|
||||
if (handle != _LLIO_STDOUT && handle != _LLIO_STDERR) {
|
||||
return _LLIO_ERROR;
|
||||
}
|
||||
|
||||
if (buffer == 0) {
|
||||
// This means that we should flush internal buffers.
|
||||
//spin until TX complete (TX is idle)
|
||||
while ((SC1_UARTSTAT&SC_UARTTXIDLE)!=SC_UARTTXIDLE) {}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ensure port is configured for UART
|
||||
if(SC1_MODE != SC1_MODE_UART) {
|
||||
return _LLIO_ERROR;
|
||||
}
|
||||
|
||||
while(size--) {
|
||||
//spin until data register has room for more data
|
||||
while ((SC1_UARTSTAT&SC_UARTTXFREE)!=SC_UARTTXFREE) {}
|
||||
SC1_DATA = *buffer;
|
||||
buffer++;
|
||||
|
||||
++nChars;
|
||||
}
|
||||
|
||||
return nChars;
|
||||
}
|
||||
#ifdef __GNUC__
|
||||
int fflush (FILE *f)
|
||||
#endif
|
||||
#ifdef __ICCARM__
|
||||
size_t fflush(int handle)
|
||||
#endif
|
||||
{
|
||||
return __write(_LLIO_STDOUT, NULL, 0);
|
||||
}
|
||||
|
||||
static void halInternalUart1TxIsr(void)
|
||||
{
|
||||
// Nothing for now, as ouput is blocking from the __write function
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Receive
|
||||
|
||||
// IAR Standard library hook for serial input
|
||||
size_t __read(int handle, unsigned char * buffer, size_t size)
|
||||
{
|
||||
int nChars = 0;
|
||||
|
||||
/* This template only reads from "standard in", for all other file
|
||||
* handles it returns failure. */
|
||||
if (handle != _LLIO_STDIN)
|
||||
{
|
||||
return _LLIO_ERROR;
|
||||
}
|
||||
|
||||
for(nChars = 0; (rxUsed>0) && (nChars < size); nChars++) {
|
||||
ATOMIC(
|
||||
*buffer++ = rxQ[rxTail];
|
||||
rxTail = (rxTail+1) % RECEIVE_QUEUE_SIZE;
|
||||
rxUsed--;
|
||||
)
|
||||
}
|
||||
|
||||
return nChars;
|
||||
}
|
||||
|
||||
static void halInternalUart1RxIsr(void)
|
||||
{
|
||||
|
||||
// At present we really don't care which interrupt(s)
|
||||
// occurred, just that one did. Loop reading RXVALID
|
||||
// data, processing any errors noted
|
||||
// along the way.
|
||||
while ( SC1_UARTSTAT & SC_UARTRXVAL ) {
|
||||
int8u errors = SC1_UARTSTAT & (SC_UARTFRMERR |
|
||||
SC_UARTRXOVF |
|
||||
SC_UARTPARERR );
|
||||
int8u incoming = (int8u) SC1_DATA;
|
||||
|
||||
if ( (errors == 0) && (rxUsed < (RECEIVE_QUEUE_SIZE-1)) ) {
|
||||
rxQ[rxHead] = incoming;
|
||||
rxHead = (rxHead+1) % RECEIVE_QUEUE_SIZE;
|
||||
rxUsed++;
|
||||
} else {
|
||||
// IAR standard library doesn't allow for any error handling in the
|
||||
// case of rx errors or not having space in the receive queue, so the
|
||||
// errors are just silently dropped.
|
||||
}
|
||||
} // end of while ( SC1_UARTSTAT & SC1_UARTRXVAL )
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Interrupts
|
||||
|
||||
void halSc1Isr(void)
|
||||
{
|
||||
int32u interrupt;
|
||||
|
||||
//this read and mask is performed in two steps otherwise the compiler
|
||||
//will complain about undefined order of volatile access
|
||||
interrupt = INT_SC1FLAG;
|
||||
interrupt &= INT_SC1CFG;
|
||||
|
||||
while (interrupt != 0) {
|
||||
|
||||
INT_SC1FLAG = interrupt; // acknowledge the interrupts early
|
||||
|
||||
// RX events
|
||||
if ( interrupt & (INT_SCRXVAL | // RX has data
|
||||
INT_SCRXOVF | // RX Overrun error
|
||||
INT_SC1FRMERR | // RX Frame error
|
||||
INT_SC1PARERR ) // RX Parity error
|
||||
) {
|
||||
halInternalUart1RxIsr();
|
||||
}
|
||||
|
||||
// TX events
|
||||
if ( interrupt & (INT_SCTXFREE | // TX has room
|
||||
INT_SCTXIDLE ) // TX idle (more room)
|
||||
) {
|
||||
halInternalUart1TxIsr();
|
||||
}
|
||||
|
||||
interrupt = INT_SC1FLAG;
|
||||
interrupt &= INT_SC1CFG;
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : __io_getcharNonBlocking
|
||||
* Description : Non blocking read
|
||||
* Input : none
|
||||
* Output : dataByte: buffer containing the read byte if any
|
||||
* Return : TRUE if there is a data, FALSE otherwise
|
||||
*******************************************************************************/
|
||||
boolean __io_getcharNonBlocking(int8u *data)
|
||||
{
|
||||
if (__read(_LLIO_STDIN,data,1))
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
}/* end serialReadByte() */
|
||||
|
||||
void __io_putchar( char c )
|
||||
{
|
||||
__write(_LLIO_STDOUT, (unsigned char *)&c, 1);
|
||||
}
|
||||
|
||||
int __io_getchar()
|
||||
{
|
||||
unsigned char c;
|
||||
__read(_LLIO_STDIN, &c, 1);
|
||||
return (int)(c);
|
||||
}
|
||||
|
||||
void __io_flush( void )
|
||||
{
|
||||
__write(_LLIO_STDOUT, NULL, 0);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue