Skip to content
Permalink
Browse files

[msp430] serial lib. TX with buffer is Ok. RX does not work

  • Loading branch information...
mbriday committed Oct 30, 2019
1 parent f705fe3 commit cd644a5f322c68803cd72c61e352ead22a859550
@@ -20,7 +20,20 @@ FUNC(int, OS_APPL_CODE) main(void)

TASK(serial)
{
tpl_serial_print_string("Hello world!\n");
static uint16_t size = 0;
if(size != tpl_serial_available())
{
size = tpl_serial_available();
tpl_serial_print_string("chars in rx buffer: ");
tpl_serial_print_int(size,0);
tpl_serial_print_string("\r\n");

if(size >= 10)
{
while(tpl_serial_available())
tpl_serial_putchar(tpl_serial_read());
}
}
TerminateTask();
}

@@ -17,15 +17,19 @@ CPU serial {
STATUS = EXTENDED;
PAINT_STACK = TRUE;
PAINT_REGISTERS = TRUE;
CPU_FREQ_MHZ = 8;
CPU_FREQ_MHZ = 24;
IDLE_POWER_MODE = LPM3;

BUILD = TRUE {
TRAMPOLINE_BASE_PATH = "../../../../../..";
APP_SRC = "serial.c";
APP_NAME = "serial_exe";
CFLAGS = "-O0 -g3 -gdwarf-2 -ggdb"; //gdb usage
LDFLAGS = "-Map=serial.map";
LIBRARY = serial;
LIBRARY = serial {
TXBUFFER = 0;
RXBUFFER = 16;
};
//use either msp-gcc (provided with Energia)..
COMPILER = "msp430-gcc";
ASSEMBLER = "msp430-gcc";
@@ -4,6 +4,20 @@
#include "tpl_os_interrupt_kernel.h"
#include "tpl_machine.h"
%
if exists OS::BUILD_S::LIBRARY then
let libMap := [OS::BUILD_S::LIBRARY mapBy: "VALUE"]
if exists libMap["serial"] then
let any_buffer := exists libMap["serial"]::VALUE_S::TXBUFFER default(16)+
exists libMap["serial"]::VALUE_S::RXBUFFER default(32)
if any_buffer > 0 then
let ISR += @{
SOURCE : "USCI_A0_VECTOR",
CATEGORY : 1,
PRIORITY : 1
}
end if
end if
end if

#------------------------------------------------------------------------------*
# Target specific initializations
@@ -1,6 +1,7 @@
#include "tpl_clocks.h"
#include <msp430.h>
#include <stdlib.h> //NULL
#include <stdlib.h> /* NULL */
#include "tpl_clocks.h"
#include "tpl_app_define.h" /* buffer sizes */

#define OS_START_SEC_CONST_16BIT
#include "tpl_memmap.h"
@@ -20,29 +21,79 @@ const uint16_t tpl_mctlwTab[] = {
#define OS_STOP_SEC_CONST_16BIT
#include "tpl_memmap.h"

#define OS_START_SEC_VAR_16BIT
#include "tpl_memmap.h"

/* TX buffer */
#if SERIAL_TX_BUFFER_SIZE > 0
#if SERIAL_TX_BUFFER_SIZE > 255
typedef uint16_t tpl_serial_tx_ring_buffer_index_t;
#else
typedef uint8_t tpl_serial_tx_ring_buffer_index_t;
#endif
struct tpl_serial_tx_ring_buffer
{
uint8_t buffer[SERIAL_TX_BUFFER_SIZE];
volatile tpl_serial_tx_ring_buffer_index_t head;
volatile tpl_serial_tx_ring_buffer_index_t tail;
};

struct tpl_serial_tx_ring_buffer tx_buffer = { { 0 }, 0, 0 };
#endif /* SERIAL_TX_BUFFER_SIZE */

/* RX buffer */
#if SERIAL_RX_BUFFER_SIZE > 0
#if SERIAL_RX_BUFFER_SIZE > 255
typedef uint16_t tpl_serial_rx_ring_buffer_index_t;
#else
typedef uint8_t tpl_serial_rx_ring_buffer_index_t;
#endif
struct tpl_serial_rx_ring_buffer
{
uint8_t buffer[SERIAL_RX_BUFFER_SIZE];
volatile tpl_serial_rx_ring_buffer_index_t head;
volatile tpl_serial_rx_ring_buffer_index_t tail;
};

struct tpl_serial_rx_ring_buffer rx_buffer = { { 0 }, 0, 0 };
#endif /* SERIAL_RX_BUFFER_SIZE */

#define OS_STOP_SEC_VAR_16BIT
#include "tpl_memmap.h"

#define OS_START_SEC_CODE
#include "tpl_memmap.h"

void tpl_serial_update_freq()
{
uint16_t dcoConfig = tpl_getDCOConfig();
//set Software reset (and reinit register)
/* set Software reset (and reinit register) */
UCA0CTLW0 = UCSWRST;
//default 8N1, lsb first, uart, input clk SMCLK
/* default 8N1, lsb first, uart, input clk SMCLK */
UCA0CTLW0 |= UCSSEL__SMCLK;
//baud rates are pre-calculated for 115200.
/* baud rates are pre-calculated for 115200. */
UCA0BRW = tpl_brwTab[dcoConfig];
UCA0MCTLW = tpl_mctlwTab[dcoConfig];
//get out of reset state
UCA0CTLW0 &= ~UCSWRST;
/* get out of reset state */
UCA0CTLW0 &= ~UCSWRST;
}

void tpl_serial_putchar(char c)
{
//wait until previous op is ok
#if SERIAL_TX_BUFFER_SIZE > 0
const uint16_t next = (tx_buffer.head + 1) % SERIAL_TX_BUFFER_SIZE;
while(next == tx_buffer.tail) LPM3; /* wait until it is not full */
/* add in ring buffer */
tx_buffer.buffer[tx_buffer.head] = c;
tx_buffer.head = next;
/* make sure interrupt is enabled */
UCA0IE |= UCTXIE;
#else
/* wait until previous op is ok */
while(!(UCA0IFG & UCTXIFG));
UCA0IFG &= ~UCTXIFG; //RAZ
UCA0IFG &= ~UCTXIFG; /* RAZ */
UCA0TXBUF = c;
#endif
}

void tpl_serial_print_string(char *str)
@@ -51,6 +102,36 @@ void tpl_serial_print_string(char *str)
tpl_serial_putchar(*str++);
}

void tpl_serial_print_int(int16_t val, uint8_t fieldWidth)
{
uint8_t negative = 0;
char buffer[6]; /* min val: -32768 => 6 chars */
int8_t index = 0;

if (val < 0)
{
negative = 1;
val = -val;
}
if (val == 0) buffer[index++] = '0';
else
{
while (val != 0)
{
int remaining = val % 10;
buffer[index++] = (char)remaining + '0';
val = val / 10;
}
}
if (negative) buffer[index++] = '-';
int8_t i;
for (i = index; i < (int8_t)fieldWidth; i++) tpl_serial_putchar(' ');
for (i = index - 1; i >= 0; i--)
{
tpl_serial_putchar(buffer[i]);
}
}

tpl_freq_update_item tpl_serial_callback = {&tpl_serial_update_freq,NULL};

void tpl_serial_begin()
@@ -71,8 +152,76 @@ void tpl_serial_begin()
* set the initial frequency
**/
tpl_serial_update_freq();
#if SERIAL_RX_BUFFER_SIZE > 0
/* RX interrupt only if there is a buffer */
UCA0IE |= UCRXIE;
#endif
}

uint16_t tpl_serial_available()
{
#if SERIAL_RX_BUFFER_SIZE > 0
return (SERIAL_RX_BUFFER_SIZE + rx_buffer.head - rx_buffer.tail) % SERIAL_RX_BUFFER_SIZE;
#else
return UCA0IFG & UCRXIFG; /* as UCRXIFG is bit 0 */
#endif
}

char tpl_serial_read(void)
{
char result;
#if SERIAL_RX_BUFFER_SIZE > 0
if (rx_buffer.head == rx_buffer.tail) {
result = 0xff;
} else {
result = rx_buffer.buffer[rx_buffer.tail];
rx_buffer.tail = (rx_buffer.tail + 1) % SERIAL_RX_BUFFER_SIZE;
}
#else
if(UCA0IFG & UCRXIFG) /* RX interrupt set*/
result = UCA0RXBUF;
else
result = 0xff;
#endif
return result;
}

/* ISR1 related to USCI_A0_VECTOR */
void __attribute__((interrupt(USCI_A0_VECTOR))) tpl_direct_irq_handler_USCI_A0_VECTOR()
{
#if SERIAL_TX_BUFFER_SIZE > 0
if(UCA0IFG & UCTXIFG) /* TX interrupt */
{
const uint8_t c = tx_buffer.buffer[tx_buffer.tail];
tx_buffer.tail = (tx_buffer.tail + 1) % SERIAL_TX_BUFFER_SIZE;
if(tx_buffer.tail == tx_buffer.head) /* empty */
UCA0IE &= ~UCTXIE; /* disable TX interrupt */
else
/* RAZ. If empty, does not remove the flag
* so that next time a char is written, the interrupt
* is re-enabled, and the interrupt will occur
* immediately
*/
UCA0IFG &= ~UCTXIFG;
UCA0TXBUF = c; /* send char */
LPM3_EXIT; /* if buffer is full, we entered in LPM */
}
#endif

#if SERIAL_RX_BUFFER_SIZE > 0
if(UCA0IFG & UCRXIFG) /* RX interrupt */
{
rx_buffer.buffer[rx_buffer.head] = UCA0RXBUF;
rx_buffer.head = (rx_buffer.head + 1) % SERIAL_RX_BUFFER_SIZE;
if(rx_buffer.head == rx_buffer.tail) /* overflow */
{
/* overwrite the oldest value */
rx_buffer.tail = (rx_buffer.tail + 1) % SERIAL_RX_BUFFER_SIZE;
}
UCA0IFG &= ~UCRXIFG;
}
#endif
}
#define OS_STOP_SEC_CODE
#include "tpl_memmap.h"

@@ -1,5 +1,6 @@
#ifndef __TPL_SERIAL_H__
#define __TPL_SERIAL_H__
#include <stdint.h>

/* function that should be called each time
* the DCO frequency is changed to recalculate the
@@ -13,6 +14,20 @@ void tpl_serial_putchar(char c);
/** print a standard null terminated string on the serial line*/
void tpl_serial_print_string(char *str);

/** print an integer to the serial line
* @param val value to be printed
* @param fieldWidth width (in char) of the value printed (right aligned)
**/
void tpl_serial_print_int(int16_t val, uint8_t fieldWidth);

/** configure the serial line. Should be called at startup.*/
void tpl_serial_begin();

/** return the nb of available chars in the rx buffer */
uint16_t tpl_serial_available();

/** @return the last value received. If the rx buffer is empty,
* it returns 0xff
*/
char tpl_serial_read();
#endif

0 comments on commit cd644a5

Please sign in to comment.
You can’t perform that action at this time.