Hi Ping,
I am using custom PCB. MCU is LPC11E68JBD48 There is two USART-s in use.
USART0 is connected to outside world through USB to SERIAL converter. Currently connected to PC, running terminal program (Putty).
USART1 (or USART3) is connected to modem(through level converters). Currently i disconnected it from modem and connected RX and TX together to form loopback. Also i can measure signal from there with scope.
MCU is running at 48MHz, Redlib(none), No optimizations. Pasted code below.
//----------------------------------------------------------------------------------------------------------------------
//main.c:
#include "chip.h"
#include <stdio.h>
#include <define.h>
#include "debug.h"
#include "modem.h"
#include "time.h"
volatile static int32_t ticks;
volatile static uint8_t rtcWake, rtcAlarm;
volatile static uint8_t us_timeout;
void SysTick_Handler(void)
{
ticks++;
}
void system_pause(uint32_t pause_ms)
{
int32_t last_ticks;
while (pause_ms)
{
last_ticks = ticks;
while(last_ticks == ticks);
pause_ms--;
}
}
void InitSysTick()
{
// Enable SysTick Timer, block if failed, this shall trigger WDT reset in future
if(SysTick_Config(SystemCoreClock / TICKRATE_HZ))
{
while(1);
}
}
int main(void)
{
uint32_t i;
//uint8_t buf[RESPONSE_BUFF_ITEM_SIZE+10];
//uint8_t b2[5], j;
void * pbuf;
// Read clock settings and update SystemCoreClock variable
SystemCoreClockUpdate();
//Enable IOCON clock - needed for Pinmux command
Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_IOCON);
Chip_GPIO_Init(LPC_GPIO);
//Init systick timer for delays
InitSysTick();
InitDebugSerial();
PrintLog("\r\nTesting modem uart\r\n");
ModemInit();
while (1) {
pbuf = debug_read_response();
if (pbuf != NULL)
{
ModemSendCommand(pbuf);
debug_responses_clear();
ModemSendCommand("\r\n");
//ModemSendCommand("a");
}
system_pause(1);
for (i = 0; i < RESPONSE_BUFF_SIZE; i++) {
pbuf = read_response((uint8_t) i);
if (pbuf != NULL) {
PrintLog(pbuf);
PrintLog("\r\n");
mark_response_read(i);
}
}
}
}
//----------------------------------------------------------------------------------------------------------------------
/*
* debug.c
*
* Created on: 16. juuni 2016
* Author: ergo
*/
#include "debug.h"
#include "time.h"
volatile static char debug_rx_buffer[DEBUG_RX_BUFF_SIZE];
volatile static int16_t debug_rx_buffer_len = 0;
volatile static uint8_t debug_handling_rx = 0;
volatile static RESPONSE_LINE_T debug_response_buffer[DEBUG_RESPONSE_BUFF_SIZE]; //52*39 = 2028bytes
void debug_responses_clear()
{
uint32_t i;
NVIC_DisableIRQ(MODEM_USART_IRQNUM);
//wait until rx receive procedure ends
while(debug_handling_rx)
system_pause(1);
debug_rx_buffer_len = 0;
for(i=0; i< DEBUG_RESPONSE_BUFF_SIZE; i++)
{
debug_response_buffer[i].r_new = 0;
}
NVIC_EnableIRQ(DEBUG_USART_IRQNUM);
}
void debug_response_add(char *s)
{
uint32_t i, len;
uint8_t result;
result = 0;
len = strlen(s);
//If string is too long, truncate
if(len > (RESPONSE_BUFF_ITEM_SIZE -1))
len = RESPONSE_BUFF_ITEM_SIZE -1;
//Copy response to first free slot as we don't care about response order
for(i=0; i< DEBUG_RX_BUFF_SIZE; i++)
{
if(debug_response_buffer[i].r_new == 0)
{
memcpy((char*)&debug_response_buffer[i].data,s,len);
debug_response_buffer[i].data[len] = '\0';
debug_response_buffer[i].r_new = 1;
result = 1;
break;
}
//If buffer is full, new item is ignored at moment
}
if(result == 0)
{
PrintLog("ERROR: debug_response_buffer full\r\n");
}
}
char * debug_read_response()
{
if(debug_response_buffer[0].r_new != 1)
return NULL;
return debug_response_buffer[0].data;
}
void debug_update_rx_buffer(uint8_t db) {
if ((db == (char) 0x0D) || (db == (char) 0x0A) || (db == (char) 0)) {
if (debug_rx_buffer_len > 0) {
debug_rx_buffer[debug_rx_buffer_len] = (char) 0;
debug_response_add(debug_rx_buffer);
debug_rx_buffer_len = 0;
}
} else if (debug_rx_buffer_len <= (MODEM_RX_BUFF_SIZE - 1)) {
debug_rx_buffer[debug_rx_buffer_len] = (char) db;
debug_rx_buffer_len++;
}
}
void USART0_IRQHandler(void)
{
uint32_t IIRValue, LSRValue;
uint8_t Dummy;
debug_handling_rx = 1;
IIRValue = DEBUG_UART->IIR;
if(IIRValue & UART0_IIR_INTID_RLS)
{
LSRValue = DEBUG_UART->LSR;
if (LSRValue & (LSR_OE | LSR_PE | LSR_FE | LSR_RXFE | LSR_BI))
{
Dummy = (uint8_t)DEBUG_UART->RBR; // Dummy read on RX to clear interrupt
debug_handling_rx = 0;
return;
}
if (LSRValue & LSR_RDR) // Receive Data Ready
{
debug_update_rx_buffer((uint8_t)DEBUG_UART->RBR);
}
}
else if(IIRValue & UART0_IIR_INTID_RDA)
{
debug_update_rx_buffer((uint8_t)DEBUG_UART->RBR);
}
else if(IIRValue & UART0_IIR_INTID_CTI)
{
//Character timeout indicator
}
else if(IIRValue & UART0_IIR_INTID_THRE)
{
//THRE, transmit holding register empty
}
//LPC_UART0D_API->uart_isr(uartHandle);
debug_handling_rx = 0;
}
void InitDebugSerial()
{
debug_responses_clear();
debug_rx_buffer_len = 0;
debug_handling_rx = 0;
//Chip_Clock_SetUSARTNBaseClockRate((DEBUG_UART_SPEED * 48), true);
Chip_IOCON_PinMuxSet(LPC_IOCON, IO_ISP_RX.Port, IO_ISP_RX.Pin, IO_ISP_RX.Mode);
Chip_IOCON_PinMuxSet(LPC_IOCON, IO_ISP_TX.Port, IO_ISP_TX.Pin, IO_ISP_TX.Mode);
Chip_UART0_Init(DEBUG_UART);
Chip_UART0_SetBaud(DEBUG_UART, DEBUG_UART_SPEED);
Chip_UART0_ConfigData(DEBUG_UART, (UART0_LCR_WLEN8 | UART0_LCR_SBS_1BIT));
//Chip_UART0_SetupFIFOS(DEBUG_UART, (UART0_FCR_FIFO_EN | UART0_FCR_TRG_LEV2));
Chip_UART0_TXEnable(DEBUG_UART);
Chip_UART0_IntEnable(DEBUG_UART, UARTN_INTEN_RXRDY);
NVIC_EnableIRQ(DEBUG_USART_IRQNUM);
}
void PrintLog(char *str)
{
uint32_t len;
len = strlen(str);
while (len != 0)
{
while ( !(DEBUG_UART->LSR & LSR_THRE) );
DEBUG_UART->THR = *str;
str++;
len--;
//Chip_UART0_SendByte(DEBUG_UART, *str++);
}
}
//----------------------------------------------------------------------------------------------------------------------
//modem.c
/*
* Modem functions
* */
#include "define.h"
#include "time.h"
#include "debug.h"
volatile static char modem_rx_buffer[MODEM_RX_BUFF_SIZE];
volatile static int16_t modem_rx_buffer_len = 0;
volatile static uint8_t modem_handling_rx = 0;
volatile static RESPONSE_LINE_T response_buffer[RESPONSE_BUFF_SIZE]; //52*39 = 2028bytes
const char* LF = "\r\n";
void responses_clear()
{
uint32_t i;
while(modem_handling_rx)
system_pause(1);
modem_rx_buffer_len = 0;
for(i=0; i< RESPONSE_BUFF_SIZE; i++)
{
response_buffer[i].r_new = 0;
}
}
void response_add(char *s)
{
uint32_t i, len;
uint8_t result;
result = 0;
len = strlen(s);
//If string is too long, truncate
if(len > (RESPONSE_BUFF_ITEM_SIZE -1))
len = RESPONSE_BUFF_ITEM_SIZE -1;
//Copy response to first free slot as we don't care about response order
for(i=0; i< RESPONSE_BUFF_SIZE; i++)
{
if(response_buffer[i].r_new == 0)
{
memcpy((char*)&response_buffer[i].data,s,len);
response_buffer[i].data[len] = '\0';
response_buffer[i].r_new = 1;
result = 1;
break;
}
//If buffer is full, new item is ignored at moment
}
if(result == 0)
{
PrintLog("ERROR: response_buffer full\r\n");
}
}
//Searches first response containing strin filter
//marks it as read/cleared if mark_as_read set
//returns index of matching response, if not found, return 0xff
uint8_t find_response(char * filter, bool mark_as_read)
{
uint32_t i, flen;
uint8_t result, idx;
result = 0;
flen = strlen(filter);
for(i=0; i< RESPONSE_BUFF_SIZE; i++)
{
if(response_buffer[i].r_new == 1 && flen <= strlen(response_buffer[i].data) && strstr(response_buffer[i].data, filter) != NULL)
{
if(mark_as_read)
response_buffer[i].r_new = 0;
idx = i;
result = 1;
break;
}
}
if(result)
return idx;
else
return 0xff;
}
//Searches response containing strin filter
//marks these as read/cleared if mark_as_read set
//returns count of matching responses
uint8_t find_responses(char * filter, bool mark_as_read)
{
uint32_t i, flen;
uint8_t count;
count = 0;
flen = strlen(filter);
for(i=0; i< RESPONSE_BUFF_SIZE; i++)
{
if(response_buffer[i].r_new == 1 && flen <= strlen(response_buffer[i].data) && strstr(response_buffer[i].data, filter) != NULL)
{
if(mark_as_read)
response_buffer[i].r_new = 0;
count++;
}
}
return count;
}
//Return response data pointer by id
char * read_response(uint8_t id)
{
if(response_buffer[id].r_new != 1)
return NULL;
return response_buffer[id].data;
}
void mark_response_read(uint8_t id)
{
response_buffer[id].r_new = 0;
}
//Adds symbols to RX buffer rxCommandBuff until new line symbol or 0 received.
//If new line, then adds content of RX buffer to response list with Response_Add() function and resets RX buf len
void update_rx_buffer(uint8_t db) {
if ((db == (char) 0x0D) || (db == (char) 0x0A) || (db == (char) 0)) {
if (modem_rx_buffer_len > 0) {
modem_rx_buffer[modem_rx_buffer_len] = (char) 0;
response_add(modem_rx_buffer);
modem_rx_buffer_len = 0;
}
} else if (modem_rx_buffer_len <= (MODEM_RX_BUFF_SIZE - 1)) {
modem_rx_buffer[modem_rx_buffer_len] = (char) db;
modem_rx_buffer_len++;
}
}
//void USART2_3_IRQHandler(void)
void USART1_4_IRQHandler(void)
{
uint32_t IIRValue, LSRValue;
//uint8_t Dummy;
modem_handling_rx = 1;
IIRValue = MODEM_USART->INTSTAT;
if(IIRValue == UARTN_INTEN_RXRDY)
{
update_rx_buffer((uint8_t) MODEM_USART->RXDATA & 0x000001FF);
}
/*
if (IIRValue & UART0_IIR_INTID_RLS) {
LSRValue = MODEM_USART->LSR;
if (LSRValue & (LSR_OE | LSR_PE | LSR_FE | LSR_RXFE | LSR_BI)) {
Dummy = (uint8_t) MODEM_USART->RBR;// Dummy read on RX to clear interrupt
return;
}
if (LSRValue & LSR_RDR) // Receive Data Ready
{
update_rx_buffer((uint8_t) MODEM_USART->RBR);
}
} else if (IIRValue & UART0_IIR_INTID_RDA) {
update_rx_buffer((uint8_t) MODEM_USART->RBR);
} else if (IIRValue & UART0_IIR_INTID_CTI) {
//Character timeout indicator
} else if (IIRValue & UART0_IIR_INTID_THRE) {
//THRE, transmit holding register empty
}
//Chip_UARTN_IRQRBHandler(LPC_USART, &rxring, &txring);
//modem_rx_buffer, modem_rx_buffer_len
//update_rx_buffer();
*/
modem_handling_rx = 0;
}
void ModemInit()
{
responses_clear();
modem_rx_buffer_len = 0;
modem_handling_rx = 0;
NVIC_DisableIRQ(USART1_4_IRQn);
Chip_Clock_SetUSARTNBaseClockRate((MODEM_USART_BAUD * 48), true);
Chip_IOCON_PinMuxSet(LPC_IOCON, IO_MDM_RX.Port, IO_MDM_RX.Pin, IO_MDM_RX.Mode);
Chip_IOCON_PinMuxSet(LPC_IOCON, IO_MDM_TX.Port, IO_MDM_TX.Pin, IO_MDM_TX.Mode);
Chip_IOCON_PinMuxSet(LPC_IOCON, IO_MDM_RX_RESERV.Port, IO_MDM_RX_RESERV.Pin, IO_MDM_RX_RESERV.Mode);
Chip_IOCON_PinMuxSet(LPC_IOCON, IO_MDM_TX_RESERV.Port, IO_MDM_TX_RESERV.Pin, IO_MDM_TX_RESERV.Mode);
Chip_UARTN_Init(MODEM_USART);
Chip_UARTN_ConfigData(MODEM_USART, UARTN_CFG_DATALEN_8 | UARTN_CFG_PARITY_NONE | UARTN_CFG_STOPLEN_1);
Chip_UARTN_SetBaud(MODEM_USART, MODEM_USART_BAUD);
Chip_UARTN_Enable(MODEM_USART);
Chip_UARTN_TXEnable(MODEM_USART);
NVIC_EnableIRQ(MODEM_USART_IRQNUM);
Chip_UARTN_IntEnable(MODEM_USART, UARTN_INTEN_RXRDY);
}
void ModemDeinit()
{
Chip_UARTN_IntDisable(MODEM_USART, UARTN_INTEN_RXRDY);
NVIC_DisableIRQ(MODEM_USART_IRQNUM);
Chip_UARTN_DeInit(MODEM_USART);
Chip_IOCON_PinMuxSet(LPC_IOCON, IO_MDM_RX.Port, IO_MDM_RX.Pin, IOCON_FUNC0);
Chip_IOCON_PinMuxSet(LPC_IOCON, IO_MDM_TX.Port, IO_MDM_TX.Pin, IOCON_FUNC0);
}
void ModemSendCommand(uint8_t * s)
{
uint32_t len;
uint8_t ch;
len = strlen(s);
Chip_UARTN_IntDisable(MODEM_USART, UARTN_INTEN_TXRDY);
while ( len != 0 )
{
while ( !(MODEM_USART->STAT & UARTN_STAT_TXRDY) );
ch = *s;
MODEM_USART->TXDATA = ch;
s++;
len--;
}
Chip_UARTN_IntEnable(MODEM_USART, UARTN_INTEN_TXRDY);
}
//----------------------------------------------------------------------------------------------------------------------
/*
* define.h
*
* Created on: 17. juuni 2016
* Author: ergo
*/
#include "chip.h"
#include <stdio.h>
#include <string.h>
#ifndef DEFINE_H_
#define DEFINE_H_
//Replaces define.h
#define BOOLEAN uint8_t
#define OFF 0
#define ON 1
//Systick timer parameters --------------------------
#define TICKRATE_HZ (1000) // tick per millisecond
//Debug Serial used to program the device and also put out log for inspection and bug-finding
#define DEBUG_UART LPC_USART0
#define DEBUG_USART_IRQNUM USART0_IRQn
#define DEBUG_UART_SPEED 115200
#define DEBUG_RX_BUFF_SIZE 100
#define DEBUG_RESPONSE_BUFF_SIZE 2
//I/O definitions ---------------------------------------------------------------------
typedef struct io_pin{
uint8_t Port;
uint8_t Pin;
uint32_t Mode;
}IO_PIN_T;
static const struct io_pin IO_ISP_RX = {.Port=0, .Pin=18, .Mode=(IOCON_FUNC1 | IOCON_MODE_INACT | IOCON_DIGMODE_EN)};
static const struct io_pin IO_ISP_TX = {.Port=0, .Pin=19, .Mode=(IOCON_FUNC1 | IOCON_MODE_INACT | IOCON_DIGMODE_EN)};
//static const struct io_pin IO_MDM_RX = {.Port=2, .Pin=3, .Mode=(IOCON_FUNC1 | IOCON_MODE_INACT | IOCON_DIGMODE_EN)};
//static const struct io_pin IO_MDM_TX = {.Port=2, .Pin=4, .Mode=(IOCON_FUNC1 | IOCON_MODE_INACT | IOCON_DIGMODE_EN)};
static const struct io_pin IO_MDM_RX_RESERV = {.Port=2, .Pin=3, .Mode=(IOCON_FUNC0 | IOCON_MODE_INACT | IOCON_DIGMODE_EN)};
static const struct io_pin IO_MDM_TX_RESERV = {.Port=2, .Pin=4, .Mode=(IOCON_FUNC0 | IOCON_MODE_INACT | IOCON_DIGMODE_EN)};
static const struct io_pin IO_MDM_RX = {.Port=0, .Pin=13, .Mode=(IOCON_FUNC4 | IOCON_MODE_INACT | IOCON_DIGMODE_EN)};
static const struct io_pin IO_MDM_TX = {.Port=0, .Pin=14, .Mode=(IOCON_FUNC4 | IOCON_MODE_INACT | IOCON_DIGMODE_EN)};
//#define MODEM_USART LPC_USART3
//#define MODEM_USART_IRQNUM USART2_3_IRQn
//#define MODEM_USART_BAUD 115200
#define MODEM_USART LPC_USART1
#define MODEM_USART_IRQNUM USART1_4_IRQn
#define MODEM_USART_BAUD 115200
#define MODEM_RX_BUFF_SIZE 200
#define RESPONSE_BUFF_ITEM_SIZE 50
//Defines one response line
typedef struct response_line{
uint8_t r_id;
uint8_t r_new;
uint8_t data[RESPONSE_BUFF_ITEM_SIZE];
}RESPONSE_LINE_T;
//Maximum size of received modem response, parsed into lines, separated by 0-s
#define RESPONSE_BUFF_SIZE 39
#define IER_RBR 0x01
#define IER_THRE 0x02
#define IER_RLS 0x04
#define IIR_PEND 0x01
#define IIR_RLS 0x03
#define IIR_RDA 0x02
#define IIR_CTI 0x06
#define IIR_THRE 0x01
#define LSR_RDR 0x01
#define LSR_OE 0x02
#define LSR_PE 0x04
#define LSR_FE 0x08
#define LSR_BI 0x10
#define LSR_THRE 0x20
#define LSR_TEMT 0x40
#define LSR_RXFE 0x80
#endif /* DEFINE_H_ */
//----------------------------------------------------------------------------------------------------------------------
/*
* debug.h
*
* Created on: 16. juuni 2016
* Author: ergo
*/
#ifndef DEBUG_H_
#define DEBUG_H_
#include <define.h>
void debug_responses_clear();
char * debug_read_response();
void InitDebugSerial();
void PrintLog(char *);
#endif /* DEBUG_H_ */
//----------------------------------------------------------------------------------------------------------------------
/*
* modem.h
*
* Created on: 16. juuni 2016
* Author: ergo
*/
#ifndef MODEM_H_
#define MODEM_H_
void ModemEnablePower(void);
void ModemInit(void);
void ModemDeinit(void);
void ModemSendCommand(uint8_t *);
void responses_clear(void);
void response_add(char *);
uint8_t find_response(char *, bool);
uint8_t find_responses(char *, bool);
char * read_response(uint8_t);
void mark_response_read(uint8_t);
#endif /* MODEM_H_ */
//----------------------------------------------------------------------------------------------------------------------
I cleaned code up a lot but i think there is still lot's of not needed functionality for this test :smileyhappy:
So please ignore as much you need.
BR,
Ergo