Often after power up and code execution ... with the UART producing output ... Id touch the level converter and it will burn to the touch ... like really really hot. I have had this problem since I began setting up UART communication
Google turned up the following hits:
http://www.avrfreaks.net/forum/max232-heating-hell
http://www.electro-tech-online.com/threads/max232-gets-overheated.107364/
And rereading the documentation for the MAX232E indicates that (pg 9)
**********
The unused drivers’ inputs on the MAX205E–MAX208E,MAX211E, MAX213E, and MAX241E can be left unconnected because 400kΩ pull up resistors to VCC are included on-chip. Since all drivers invert, the pull up resistors force the unused drivers’ outputs low. The MAX202E, MAX203E, and MAX232E do not have pull up resistors on the transmitter inputs.
***********************
Seems the the floating input TX2? maybe be picking up stray noise or getting amplified through the op-amp
So going forward I should either
a) connect together the TTL TX1 and TX2 inputs
b) tied the TTL TX* inputs to a pullup resistor ?
c) replace the MAX232E SMD with MAX232 SIP where this problem doesnt exist
So for now I connected the two TX* inputs and pulled it up to VCC via a ~260k resistor. For the DB9-ttl-rs232 adapter external circuit I simply soldered a wire between TX1_in and TX2_in
Tuesday, December 8, 2015
Friday, December 4, 2015
Phase 2: IE_egwu_monitor
/*
*****************************************************************
*name: IE_egwu_monitor.h
*author: Samuel Igwe
*date: 12/03/2015
*description: IE_egwu_monitor program/command interpreter header.
*****************************************************************
*/
#ifndef IE_EGWU_MONITOR_H
#define IE_EGWU_MONITOR_H
#include "chip.h"
#include "chip_lpc177x_8x.h"
#include "uart_17xx_40xx.h"
#include "IE_egwu_uartio.h"
/*
*************************************************************
*support variables
*************************************************************
*/
enum {
MON_ERROR_CMD=0,
MON_ERROR_ADDRESS,
MON_ERROR_TOKEN,
MON_ERROR_COMMANDS};
enum {
MON_CMD_GO=0,
MON_CMD_HELP,
MON_CMD_LDUSB,
MON_CMD_LDXMODEM,
MON_CMD_MDB,
MON_CMD_MDH,
MON_CMD_MDW,
MON_CMD_MWB,
MON_CMD_MWH,
MON_CMD_MWW,
MON_CMD_RESET,
NUM_MONITOR_COMMANDS};
union UN_ADDR {
volatile unsigned int *ptrInt;
volatile unsigned short *ptrShort;
volatile unsigned char *ptrChar;
}unAddr;
struct MONITOR_CMDLINE {
volatile int wdCmd;
volatile int wdAddr;
volatile int wdOpSize;
volatile int wdVallen;
}strCmdline;
/*
*************************************************************
*routines
*************************************************************
*/
void monitor_assist_reset(struct MONITOR_CMDLINE *ptrStrCmdline);
void monitor_assist_go(struct MONITOR_CMDLINE *ptrStrCmdline);
void monitor_assist_ldxmodem(struct MONITOR_CMDLINE *ptrStrCmdline);
void monitor_assist_ldusb(struct MONITOR_CMDLINE *ptrStrCmdline);
void monitor_assist_mwx(struct MONITOR_CMDLINE *ptrStrCmdline);
void monitor_assist_mdx(struct MONITOR_CMDLINE *ptrStrCmdline);
void monitor_assist_help(struct MONITOR_CMDLINE *ptrStrCmdline);
void monitor_execution(struct MONITOR_CMDLINE *ptrStrCmdline);
void monitor_flag_error(int wdErrorNum);
int monitor_parse_cmdline(unsigned char *ptrCmdString, struct MONITOR_CMDLINE *ptrStrCmdline);
int monitor_get_next_token(unsigned char *ptrSrc, unsigned char *ptrDst, int DstSize);
int monitor_search_table(unsigned char *ptrString, char *ptrTable[], int wdSize);
#endif
/*
*****************************************************************
*name: IE_egwu_monitor.c
*author: Samuel Igwe
*date: 12/03/2015
*description: monitor program/command interpreter and support
* functions.
*****************************************************************
*/
#ifndef IE_EGWU_MONITOR_C
#define IE_EGWU_MONITOR_C
#include "IE_egwu_monitor.h"
void (*ptrMonCmdFuncTable[NUM_MONITOR_COMMANDS])(struct \
MONITOR_CMDLINE *ptrStrCmdline) ={
monitor_assist_go,
monitor_assist_help,
monitor_assist_ldusb,
monitor_assist_ldxmodem,
monitor_assist_mdx,
monitor_assist_mdx,
monitor_assist_mdx,
monitor_assist_mwx,
monitor_assist_mwx,
monitor_assist_mwx,
monitor_assist_reset};
char *ptrMonErrorStrings[] = {
"\r\ncommand error",
"\r\ninvalid or non existent address",
"\r\ntoken error"};
char *ptrMonCmdStrings[] = {
"go",
"help",
"ldusb",
"ldxmodem",
"mdb",
"mdh",
"mdw",
"mwb",
"mwh",
"mww",
"reset"};
char *ptrBanner = {
"\r\n..ie........\
\r\n..ieieie....\
\r\n..ie........\
\r\n..ieieie....\
\r\n..ie........\tIgbo Embedded\
\r\n..ieieie....\tEGWU v1,1 (c) 2015\
\r\n..ie........\tSamuel Igwe\n\n"};
char *ptrPrompt = "\r\negwu-> ";
char *ptrMonUsage = {
"\r\ngo address :\t jump to address\
\r\nldusb address :\t load file to address using USB\
\r\nldxmodem address :\t load file to address using xmodem+serial port\
\r\nhelp :\t display command table\
\r\nmdb|mdh|mdw addr len :\t display byte|word|dword at address\
\r\nmwb|mwh|mww addr val :\t write byte|word|dword to address\
\r\nreset :\t reset the lpc1778\n\n"};
/*
*****************************************************************
*description: monitor executioner
*inputs: struct MONITOR_CMDLINE *ptrStrCmdline = pointer to
* cmdline structure
*note: clear screen
* print banner
* loop:
* get string
* call monitor_parse_string()
* check result != -1
* take action
* loop loop
*............
*..ie........
*..ieieie....
*..ie........
*..ieieie....
*..ie........
*..ie........
*..ieieie....
*..ie........
*............
*****************************************************************
*/
void
monitor_execution(struct MONITOR_CMDLINE *ptrStrCmdline)
{
volatile unsigned int wdTemp;
unsigned char sbTemp[80+1];
uartio_printf("%s", (unsigned int)ptrBanner);
while(1)
{
tclib_memset((unsigned char *)ptrStrCmdline, 0, sizeof(struct MONITOR_CMDLINE));
uartio_printf("%s", (unsigned int)ptrPrompt);
if((uartio_gets((char *)sbTemp, 80)) < 4)
continue;
wdTemp = monitor_parse_cmdline(sbTemp, ptrStrCmdline);
if(wdTemp >= MON_CMD_GO && wdTemp <= MON_CMD_RESET)
ptrMonCmdFuncTable[wdTemp](ptrStrCmdline);
}
}
/*
*****************************************************************
*description: "reset" command
*inputs: struct MONITOR_CMDLINE *ptrStrCmdline = pointer to
* cmdline structure
*****************************************************************
*/
void
monitor_assist_reset(struct MONITOR_CMDLINE *ptrStrCmdline)
{
uartio_printf("\n\rpreparing to reset board \n", 0);
timer_delay_mS(1000);
/*NVIC_SystemReset();
asm ("ldr r0, =0x10000004");
asm ("mov pc, [r0]"); Error: r15 not allowed here -- `mov pc,[r0]'
*/
/*do something with a register write to the FPGA that resets the
entire system ... although this is only useful for rom code
for now just jump to main*/
main();
}
/*
*****************************************************************
*description: "go" command
*inputs: struct MONITOR_CMDLINE *ptrStrCmdline = pointer to
* cmdline structure
*****************************************************************
*/
void
monitor_assist_go(struct MONITOR_CMDLINE *ptrStrCmdline)
{
unsigned int wdTemp = ptrStrCmdline->wdAddr;
uartio_printf("preparing to jump to address %x\n", wdTemp);
timer_delay_mS(1000);
// asm ("ldr r0, =wdTemp");
asm ("ldr sp, =0x10010000");
asm ("mov pc, r0");
}
/*
*****************************************************************
*description: "ldxmodem" command
*inputs: struct MONITOR_CMDLINE *ptrStrCmdline = pointer to
* cmdline structure
*****************************************************************
*/
void
monitor_assist_ldxmodem(struct MONITOR_CMDLINE *ptrStrCmdline)
{
}
/*
*****************************************************************
*description: "ldusb" command
*inputs: struct MONITOR_CMDLINE *ptrStrCmdline = pointer to
* cmdline structure
*****************************************************************
*/
void
monitor_assist_ldusb(struct MONITOR_CMDLINE *ptrStrCmdline)
{
}
/*
*****************************************************************
*description: "mwb/mwh/mww" commands
*inputs: struct MONITOR_CMDLINE *ptrStrCmdline = pointer to
* cmdline structure
*****************************************************************
*/
void
monitor_assist_mwx(struct MONITOR_CMDLINE *ptrStrCmdline)
{
unsigned int wdTemp;
union UN_ADDR *ptrAddr = &unAddr;
ptrAddr->ptrInt = (volatile unsigned int *)ptrStrCmdline->wdAddr;
if(ptrStrCmdline->wdOpSize == 1)
{
*ptrAddr->ptrChar = ptrStrCmdline->wdVallen;
wdTemp = *ptrAddr->ptrChar;
}
else
{
if(ptrStrCmdline->wdOpSize == 2)
{
*ptrAddr->ptrShort = ptrStrCmdline->wdVallen;
wdTemp = *ptrAddr->ptrShort;
}
else
{
*ptrAddr->ptrInt = ptrStrCmdline->wdVallen;
wdTemp = *ptrAddr->ptrInt;
}
}
uartio_printf("\n\r%x", wdTemp);
}
/*
*****************************************************************
*description: "mdb/mdh/mdw" commands
*inputs: struct MONITOR_CMDLINE *ptrStrCmdline = pointer to
* cmdline structure
*****************************************************************
*/
void
monitor_assist_mdx(struct MONITOR_CMDLINE *ptrStrCmdline)
{
volatile unsigned int wdRow, wdMaxRow, wdTemp, wdValPerRow = 8;
volatile unsigned int wdCol, wdMaxCol, wdLastCol;
volatile union UN_ADDR *ptrAddr = &unAddr;
if(ptrStrCmdline->wdAddr== 0)
{
monitor_flag_error(MON_ERROR_ADDRESS);
return;
}
else
ptrAddr->ptrInt = (volatile unsigned int *)ptrStrCmdline->wdAddr;
if(ptrStrCmdline->wdVallen == 0)
ptrStrCmdline->wdVallen++;
wdMaxRow = (ptrStrCmdline->wdVallen)/wdValPerRow;
if(wdMaxRow == 0)
wdMaxRow++;
wdLastCol= (ptrStrCmdline->wdVallen)%16;
for(wdRow = 0; wdRow < wdMaxRow; wdRow++)
{
uartio_printf("\r\n%x:\t", (unsigned int)ptrAddr->ptrInt);
if(wdRow == (wdMaxRow - 1))
wdMaxCol = wdLastCol;
else
wdMaxCol = wdValPerRow;
for(wdCol = 0; wdCol < wdMaxCol; wdCol++)
{
if(ptrStrCmdline->wdOpSize == 1)
{
wdTemp = *ptrAddr->ptrChar;
ptrAddr->ptrChar++;
wdTemp &= 0x0ff;
}
else
{
if(ptrStrCmdline->wdOpSize == 2)
{
wdTemp = *ptrAddr->ptrShort;
ptrAddr->ptrShort++;
wdTemp &= 0x0ffff;
}
else
{
wdTemp = *ptrAddr->ptrInt;
ptrAddr->ptrInt++;
}
}
switch(ptrStrCmdline->wdOpSize)
{
case 4:
{
uartio_printf("%x", ((wdTemp >> 24)&0x0ff));
uartio_printf("%x", ((wdTemp >> 16)&0x0ff));
wdTemp &= 0x0ffff;
/*slide down to code below*/
}
case 2:
{
uartio_printf("%x", ((wdTemp >> 8)&0x0ff));
wdTemp &= 0x0ff;
/*slide down to code below*/
}
case 1:
{
uartio_printf("%x ",(wdTemp));
break;
}
default:
{
}
}
}
}
uartio_printf("\n", 0);
}
/*
*****************************************************************
*description: "help" command
*inputs: struct MONITOR_CMDLINE *ptrStrCmdline = pointer to
* cmdline structure
*****************************************************************
*/
void
monitor_assist_help(struct MONITOR_CMDLINE *ptrStrCmdline)
{
uartio_printf("%s", (unsigned int)ptrMonUsage);
}
/*
*****************************************************************
*description: command line parsing routine
*inputs: char *ptrString = pointer to input string
* struct MONITOR_CMDLINE *ptrStrCmdline = pointer to
* cmdline structure
*output: int = 0 on success
*****************************************************************
*/
int
monitor_parse_cmdline(unsigned char *ptrString,\
struct MONITOR_CMDLINE *ptrStrCmdline)
{
int wdTemp, wdArgCnt = 0;
unsigned char sbToken[80+1];
tclib_memset((unsigned char *)ptrStrCmdline, 0, sizeof(struct MONITOR_CMDLINE));
ptrStrCmdline->wdCmd = -1; /*0 is a valid cmd index*/
while(1)
{
if((wdTemp = monitor_get_next_token(ptrString, sbToken, 80)) == 0)
return (ptrStrCmdline->wdCmd);
wdArgCnt++;
switch(wdArgCnt)
{
case 1: /*command*/
{
if((wdTemp = monitor_search_table(sbToken, ptrMonCmdStrings, NUM_MONITOR_COMMANDS)) == -1)
{
monitor_flag_error(MON_ERROR_CMD);
return -1;
}
ptrStrCmdline->wdCmd = wdTemp;
switch(wdTemp)
{
case MON_CMD_HELP:
case MON_CMD_RESET:
{
ptrStrCmdline->wdOpSize = 0;
break;
}
case MON_CMD_MDB:
case MON_CMD_MWB:
{
ptrStrCmdline->wdOpSize = 1;
break;
}
case MON_CMD_MDH:
case MON_CMD_MWH:
{
ptrStrCmdline->wdOpSize = 2;
break;
}
case MON_CMD_MDW:
case MON_CMD_MWW:
case MON_CMD_GO:
case MON_CMD_LDXMODEM:
case MON_CMD_LDUSB:
default:
{
ptrStrCmdline->wdOpSize = 4;
break;
}
}
break;
}
case 2: /*address*/
{
if(sbToken[1] == 'x' || sbToken[1] == 'X')
ptrStrCmdline->wdAddr = tclib_atoi(sbToken+2);
else
ptrStrCmdline->wdAddr = tclib_atoi(sbToken);
break;
}
case 3: /*value or length*/
{
if(sbToken[1] == 'x' || sbToken[1] == 'X')
ptrStrCmdline->wdVallen = tclib_atoi(sbToken+2);
else
ptrStrCmdline->wdVallen = tclib_atoi(sbToken);
break;
}
default:
{
monitor_flag_error(MON_ERROR_TOKEN);
return -1;
}
}
}
if(wdArgCnt < 4)
return ptrStrCmdline->wdCmd;
else
return -1;
}
/*
*****************************************************************
*description: token extraction routine
*inputs: char *ptrSrc = pointer to input string
* char *ptrDst = pointer to destination buffer
* int wdSize = size of destination buffer
*output: int = string length on success or 0
*operation: a) scan through ptrSrc extracting a string
* b) see a non space char extract into ptrDst and
* replace with space (convert to lower)
* c) when space or NULL is encountered exit
* d) return 0 on error or string lenght on success
*****************************************************************
*/
int
monitor_get_next_token(unsigned char *ptrSrc,\
unsigned char *ptrDst,\
int wdSize)
{
int wdCount;
char byValue;
while(((*ptrSrc) != 0) && (*(ptrSrc) == ' '))
ptrSrc++;
if((*ptrSrc) == 0)
return 0;
//for(wdCount = 0; ((*ptrSrc) != 0 && (*ptrSrc) != ' '); wdCount++)
for(wdCount = 0; wdCount <wdSize; wdCount++)
{
if((*ptrSrc) == 0 || (*ptrSrc) == ' ')
break;
byValue = (*ptrSrc);
*(ptrSrc++) = ' ';
if(byValue >='A' && byValue <='Z')
{
byValue =('Z'- byValue);
byValue += 'a';
}
*(ptrDst++) = byValue;
}
(*ptrDst) = 0;
return wdCount;
}
/*
*****************************************************************
*description: error routine
*inputs: int wdErrorNum = index into error table
*****************************************************************
*/
void
monitor_flag_error(int wdErrorNum)
{
unsigned int wdAddr;
if(wdErrorNum >= MON_ERROR_COMMANDS)
return;
else
wdAddr = (unsigned int)ptrMonErrorStrings[wdErrorNum];
uartio_printf("%s\n", wdAddr);
}
/*
*****************************************************************
*description: table search routine
*inputs: char *ptrString = pointer to input string
* char *ptrTable[] = pointer to MonCmdStrings table
* int wdSize = NUM_MONITOR_COMMANDS
*output: int = enum index into *ptrMonCmdStrings
*****************************************************************
*/
int
monitor_search_table(unsigned char *ptrString,\
char *ptrTable[],\
int wdSize)
{
short wdTop = wdSize - 1;
short wdMiddle = 0;
short wdBottom = 0;
short wdResult = 0;
while(wdBottom <= wdTop)
{
wdMiddle = (wdTop + wdBottom);
wdMiddle >>= 1;
wdResult = tclib_strcmp(ptrString, (unsigned char *)ptrTable[wdMiddle]);
if(wdResult == 0)
return wdMiddle;
if(wdResult < 0)
wdTop = (wdMiddle - 1);
else
wdBottom = (wdMiddle + 1);
}
return -1;
}
#endif
Thursday, December 3, 2015
Phase 2: UART the one
Finally resolved.
Modified test_determine_fractional_divider_values() to not read back the values and instead just write 0, 1, and 2 followed by the current MULVAL and DIVADDVAL values. I saw several times where it appeared ("012") under minicom so once again I dumped the data to a file
stty raw
cat >/tmp/serial.dat </dev/ttyS0
hexdump /tmp/serial.dat
Got back the following:
0000200 c0e0 4416 0327 fe0f 24c0 e6ce 40b6 fe18
0000210 6c80 8c1c 806c f823 4c80 8c3c 804c f04c
0000220 c800 c678 361c 0660 00ff f0d8 380c 0032
0000230 c0e0 e098 7818 e666 9880 18e0 98c3 3006
0000240 e07e c038 8738 0638 0060 aab4 4c82 0c15
0000250 2b88 e108 a458 144b 90ff 962c f880 3130
0000260 0632 7005 7271 0606 8d60 6626 e0d0 1ae0
0000270 2364 0460 34c0 7347 b073 c006 8e24 c4c4
0000280 16c0 80fc 1c6c 8c8c 2780 80f8 384c 8c8c
0000290 7080 00f0 78c8 1e42 6038 fc0e c800 84f0
00002a0 c338 f800 00c0 e098 7818 0086 80fe eab4
00002b0 0482 0c55 a128 e08d 5648 c11c 2498 48d2
00002c0 b0fc 9999 f890 3130 0732 7006 7271 0707
00002d0 8560 7626 e118 0ae0 f424 82b0 16c0 8c23
00002e0 220f c0f0 c624 f2e2 8360 24c0 c48e c0e4
00002f0 fc38 6c80 8c1c 80ec f87b 4c80 8c38 80cc
0000300 f07c cc00 6378 3e0e c060 2aa4 04c2 1955
0000310 d52c f848 42c8 c110 a458 248b 98ff 1624
0000320 fc50 b130 88b2 3086 3231 0708 7170 0872
0000330 6008 2685 5886 e0e1 240b 1004 e0c1 6412
0000340 0423 fe17 34c0 7347 1081 c007 8e24 04c6
0000350 0720 2cc0 cc8e 810c f83c 6c80 8c1c 030c
0000360 f07e 6ab4 1482 10d5 b56c fe01 2b88 e114
0000370 9658 1211 a418 5433 90fe 562c fc68 3130
0000380 0932 3007 3231 0809 7170 0972 6019 2685
0000390 8896 60f0 260b d096 e0c1 641a 06a3 fe18
00003a0 16c0 3127 9633 c0f0 c624 12e2 e020 24c0
00003b0 c48e 8124 fc3f 2aa4 14c2 0055 356c ff28
00003c0 aba8 f891 52c8 c218 a458 24cb 98ff 9624
00003d0 fc60 99b0 4599 30f0 3231 080a 3130 0a32
Randomly chose one occurance of 3130 0732 xx06. This amounts to a MULVAL of 7 and a DIVADDVAL of 6.
Then i modified IE_setup.c's setup_uart() with the above fractional divide values then main.c to write out 0's non stop. This produced the following output under minicom (using the db8 external ttl-rs232 adapter).
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Occasionally, it would deteriorate and when I checked the output of RX (null modem) on a scope I saw the signal attenuated to between 0 and 3v but squeezing the max232 chip fixed it ... which means its probably a solder issue (now that the fractional divider value has been found).
Ill fix up the mainboard db9 connector and use that. I might even wire it up in a null modem (swap RX and TX) so I can stick with the straight through serial cable I am using ...
Modified test_determine_fractional_divider_values() to not read back the values and instead just write 0, 1, and 2 followed by the current MULVAL and DIVADDVAL values. I saw several times where it appeared ("012") under minicom so once again I dumped the data to a file
stty raw
cat >/tmp/serial.dat </dev/ttyS0
hexdump /tmp/serial.dat
Got back the following:
0000200 c0e0 4416 0327 fe0f 24c0 e6ce 40b6 fe18
0000210 6c80 8c1c 806c f823 4c80 8c3c 804c f04c
0000220 c800 c678 361c 0660 00ff f0d8 380c 0032
0000230 c0e0 e098 7818 e666 9880 18e0 98c3 3006
0000240 e07e c038 8738 0638 0060 aab4 4c82 0c15
0000250 2b88 e108 a458 144b 90ff 962c f880 3130
0000260 0632 7005 7271 0606 8d60 6626 e0d0 1ae0
0000270 2364 0460 34c0 7347 b073 c006 8e24 c4c4
0000280 16c0 80fc 1c6c 8c8c 2780 80f8 384c 8c8c
0000290 7080 00f0 78c8 1e42 6038 fc0e c800 84f0
00002a0 c338 f800 00c0 e098 7818 0086 80fe eab4
00002b0 0482 0c55 a128 e08d 5648 c11c 2498 48d2
00002c0 b0fc 9999 f890 3130 0732 7006 7271 0707
00002d0 8560 7626 e118 0ae0 f424 82b0 16c0 8c23
00002e0 220f c0f0 c624 f2e2 8360 24c0 c48e c0e4
00002f0 fc38 6c80 8c1c 80ec f87b 4c80 8c38 80cc
0000300 f07c cc00 6378 3e0e c060 2aa4 04c2 1955
0000310 d52c f848 42c8 c110 a458 248b 98ff 1624
0000320 fc50 b130 88b2 3086 3231 0708 7170 0872
0000330 6008 2685 5886 e0e1 240b 1004 e0c1 6412
0000340 0423 fe17 34c0 7347 1081 c007 8e24 04c6
0000350 0720 2cc0 cc8e 810c f83c 6c80 8c1c 030c
0000360 f07e 6ab4 1482 10d5 b56c fe01 2b88 e114
0000370 9658 1211 a418 5433 90fe 562c fc68 3130
0000380 0932 3007 3231 0809 7170 0972 6019 2685
0000390 8896 60f0 260b d096 e0c1 641a 06a3 fe18
00003a0 16c0 3127 9633 c0f0 c624 12e2 e020 24c0
00003b0 c48e 8124 fc3f 2aa4 14c2 0055 356c ff28
00003c0 aba8 f891 52c8 c218 a458 24cb 98ff 9624
00003d0 fc60 99b0 4599 30f0 3231 080a 3130 0a32
Randomly chose one occurance of 3130 0732 xx06. This amounts to a MULVAL of 7 and a DIVADDVAL of 6.
Then i modified IE_setup.c's setup_uart() with the above fractional divide values then main.c to write out 0's non stop. This produced the following output under minicom (using the db8 external ttl-rs232 adapter).
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Occasionally, it would deteriorate and when I checked the output of RX (null modem) on a scope I saw the signal attenuated to between 0 and 3v but squeezing the max232 chip fixed it ... which means its probably a solder issue (now that the fractional divider value has been found).
Ill fix up the mainboard db9 connector and use that. I might even wire it up in a null modem (swap RX and TX) so I can stick with the straight through serial cable I am using ...
Saturday, November 28, 2015
Phase 2: Makefile
########################################################################
#name: Makefile
#description: IgboEmbedded' EGWU Makefile
#date: 06/09/2015
#author: Samuel Igwe
########################################################################
CC = arm-none-eabi-gcc
LD = arm-none-eabi-ld
OBJCPY = arm-none-eabi-objcopy
AR = arm-none-eabi-ar
RM = rm -f
MV = mv -f
CFLAGS = -g -c -Wall -nostdlib -mcpu=cortex-m3 -mlittle-endian -mthumb -mabi=atpcs -DDEBUG \
-O2 -DEXT_CLK
#-O2 -DEXT_CLK -DDIVADDVAL=1 -DMULVAL=2
LDFLAGS= -nostdlib -e main -Map flash.map -L linker -T IE_lpc177x.ld --cref
ARFLAGS= -r
all:
make lpcopen.lib
make egwu_core
make egwu_app
make clean
lpcopen.lib:
$(CC) $(CFLAGS) -DCORE_M3 -I lpcopen/include lpcopen/source/*.c
$(AR) $(ARFLAGS) lpcopen.lib *.o
$(RM) *.o
egwu_core:
$(CC) $(CFLAGS) -o ivt.o core/IE_egwu_ivt.S
$(CC) $(CFLAGS) -DCORE_M3 -I core -I lpcopen/include -I tclib -o setup.o core/IE_egwu_setup.c
$(CC) $(CFLAGS) -DCORE_M3 -I core -I lpcopen/include -I tclib -o uartio.o core/IE_egwu_uartio.c
$(CC) $(CFLAGS) -DCORE_M3 -I core -I lpcopen/include -I tclib -o monitor.o core/IE_egwu_monitor.c
$(CC) $(CFLAGS) -I tclib -o tclib.o tclib/IE_tclib.S
egwu_app:
$(CC) $(CFLAGS) -DCORE_M3 -I core -I lpcopen/include -I tclib -o main.o app/main.c
$(LD) $(LDFLAGS) -o main.out ivt.o\
setup.o\
uartio.o\
monitor.o\
tclib.o\
main.o\
lpcopen.lib
clean:
$(RM) *.o
$(RM) lpcopen.lib
binimage:
$(OBJCPY) -O binary flash.out flash.bin
Phase 2: UART not out of the woods yet
I modified the fractional divide test some more ... to write and check for 3 values. Everything held in place with 0/1 and 1/1 as the DivAddVal/MulVal values using a loop back cable (paper clip on pins 2 and 3 of serial null modem cable).
However when I connected to my PC's serial port and ran minicom ... I still got back gibberish ... I have to consider that perhaps I left something out ... the PC's rs232 level converter is damaged ? or I should be driving the db9 ttl-to-rs232 adapter with 5v and not 3v?
One other small note:
start compiling with -O2 optimization!!!
However when I connected to my PC's serial port and ran minicom ... I still got back gibberish ... I have to consider that perhaps I left something out ... the PC's rs232 level converter is damaged ? or I should be driving the db9 ttl-to-rs232 adapter with 5v and not 3v?
One other small note:
start compiling with -O2 optimization!!!
/*
***********************************************************************
*name: Samuel Igwe
*date: 07/04/2015
*description: main ... what else
* phase 1: system initialization
* led + timer
* phase 2: the above with
* uart communication 115200
* simple monitor program
* phase 3: the above with
* fpga setup in order to control LED's
* enabling static and dram memory controller
* phase 4: the above with
* usb host support in place for gamepads
* /mouse/keyboards
* phase 5: the above with
* extended fpga support for usb controller
* glue logic.
***********************************************************************
*/
#include "main.h"
void test_determine_fractional_divider_values(void);
int
main(void)
{
volatile unsigned int wdTemp;
const int wdGpio=18, wdTestVal='0';
asm ("ldr sp, =0x10010000");
setup_pll();
setup_nvic();
setup_gpio();
setup_gpdma();
setup_uart();
gpio_set_lpc_biled(0);
while(1)
{
//wdTemp++;
//uartio_printf("%d\r", wdTemp);
// (LPC_GPIO1->SET) = (1 << wdGpio);
//uartio_putc(wdTestVal);
// (LPC_GPIO1->CLR) = (1 << wdGpio);
test_determine_fractional_divider_values();
}
}
/*
***********************************************************************
description: fractional divider test routine. used to tweak the uart
baud rate clock
notes: for this to work - put a paper clip between pin 2(rx)
and pin 3(tx) of the serial cable. which effectively
creates a loop back.
then set a break point where the "if" test of the data
read back evaluates as true
***********************************************************************
*/
void
test_determine_fractional_divider_values(void)
{
volatile unsigned int wdTemp, wdCount, wdErrorFlag;
volatile unsigned int wdMulVal, wdDivAddVal;
const int wdGpio=18, wdTestVal='0';
/*
*******************************************************************
cycle through the 14 x 15 fractional divider values
reset RX fifo
wait 1mS after setting fractional dividers
write and read back three values in succession
turn on flag if any error
evaluate results
*******************************************************************
*/
for(wdMulVal = 1; wdMulVal <= 15; wdMulVal++)
{
for(wdDivAddVal = 0; wdDivAddVal <= 15; wdDivAddVal++)
{
wdTemp = (wdMulVal << 4);
wdTemp |= wdDivAddVal;
EGWU_ONBOARD_UART->FDR = wdTemp;
timer_delay_mS(1);
EGWU_ONBOARD_UART->FCR |= UART_FCR_RX_RS;
for(wdCount = 0, wdErrorFlag = 0; wdCount < 3; wdCount++)
{
uartio_putc(wdTestVal + wdCount);
if((uartio_getc()) != (wdTestVal + wdCount))
wdErrorFlag++;
}
if(wdErrorFlag == 0)
{
uartio_putc(wdMulVal);
uartio_putc(wdDivAddVal);
}
}
}
/*
*******************************************************************
flash bi-LED in a sequence every 500mS
*******************************************************************
*/
do
{
wdTemp++;
gpio_set_lpc_biled(wdTemp);
timer_delay_mS(500);
}while(1);
}
Friday, November 27, 2015
Phase 2: UART the sunshine of my life ...
I took thanksgiving week off (as I do every year) and decided to put an end to a problem that has plagued me off and on for almost a month. I would love to say I was focused on it in all that time but alas I wasnt ... but this week I was.
So I modified the test program to toggle a GPIO pin that I am to use as external trigger for the scope. I needed a clear picture of what the output looked like. Then I simple configured the uart channel 0 and wrote '0' or 0x30 (ascii code) to the data register
Originally my configuration settings for the LPC1788 uart is based on the peripheral clock which is the cpu clock/4 (for my test case). Thats 40Mhz.
So if you did the math based on the data sheet you can generate both a Uart clock divider and a fractional divider (divaddval and mulval).
This is nicely summarized in the comment section of the function setup_uart in the file IE_egwu_setup.c
A close look at the scope showed that value 0x30 was there, but compressed in time.
It occupied 3.6*20e-6 or 72uS. That means there are 13,888 bytes transmitted in one second. Thats verses the ideal of 115200/10 (1 start bit, 8 bits of data and 1 stop bit) = 11,520
The MulVal and DivAddVal fractional clock divider values can be experimented with. The result is an improvement in uart baud clock and a reduction of bit error rates. But there are 14 such values for MulVal and 15 for DivAddVal.
My first thought was to modify my test program to cycle through the 210 possible combinations while writing 0x30 or '0'. Then I can look at the minicom logs searching for when '0' occurs.
That worked but was tedious in terms of finding out which combination generated that.
A further modification of my program involved
1. setting fractional divider values
2. writing '0'
3. in a loop - emptying receiver fifo
4. looking for '0'
5. displaying the value of MulVal and DivAddVal
On the cable end I just put a paper clip between pins 2 and 3 (RX and TX) creating a loop back. Then just set a break point for when the "if" statement becomes true.
That worked marvelously.
When the breakpoint hit, I examined wdMulVal and wdDivAddVal (both equal to 1). Fearing a mistake, I then proceeded to write a read a bunch of values to the uart data register (both RX and TX fifos are 16 bytes wide).
I was satisfied with the results.
I looked at the scope output to verify what I expected to see ~4.2 * 20e-6 = 84uS. Which means a new character is generated roughly 11,904 times a second. I can live with that and so can the UART ;)
Things should move more swiftly after this. I can proceed with the monitor program (already written in my notebook) after I test DMA controlled UART transmission later this weekend ... Phase 3 cant come soon enough for me ....
So I modified the test program to toggle a GPIO pin that I am to use as external trigger for the scope. I needed a clear picture of what the output looked like. Then I simple configured the uart channel 0 and wrote '0' or 0x30 (ascii code) to the data register
Originally my configuration settings for the LPC1788 uart is based on the peripheral clock which is the cpu clock/4 (for my test case). Thats 40Mhz.
So if you did the math based on the data sheet you can generate both a Uart clock divider and a fractional divider (divaddval and mulval).
This is nicely summarized in the comment section of the function setup_uart in the file IE_egwu_setup.c
************************************************************************
*governing formula is as follows:
*Uart(baudrate) = PCLK (40Mhz)/16 x (256 x DLM) + DLL x (1 + DivVal/MulVal)
*constraints
* 1 <= MulVal <= 15
* 0 <= DivAddVal <= 14
* DivAddVal < MulVal
*[for 115200]
************************************************************************
*115200 = 40Mhz/16 x [(256 x DLM) + DLL x (1 + D/M)
*115200 = 40Mhz/16 x DLest
*DLest = 21.7
*FRest = 1.5
************************************************************************
*DLest = INT(40Mhz/(16 x 115200 x FRest)
*FRest = 40Mhz/(16 x 115200 x DLest)
************************************************************************
*DLest = INT(14.46) = 14
*FRest = 1.55
************************************************************************
*this satisfies the condition 1.1 < Frest < 1.9
*DL = INT(40Mhz/(16 x 115200 x 1.55) = 14
*DL*FR = 14 x 1.55 = 21.7
************************************************************************
*from the table
*DivAdd = 5
*MulVal = 9
************************************************************************
The problem however is that this setting the the fractional dividers above and below the chosen value above ... produce gibberish under minicom on my PC. Transmits and Receives have FRAMING errors - alignment issues.
A close look at the scope showed that value 0x30 was there, but compressed in time.
It occupied 3.6*20e-6 or 72uS. That means there are 13,888 bytes transmitted in one second. Thats verses the ideal of 115200/10 (1 start bit, 8 bits of data and 1 stop bit) = 11,520
The MulVal and DivAddVal fractional clock divider values can be experimented with. The result is an improvement in uart baud clock and a reduction of bit error rates. But there are 14 such values for MulVal and 15 for DivAddVal.
My first thought was to modify my test program to cycle through the 210 possible combinations while writing 0x30 or '0'. Then I can look at the minicom logs searching for when '0' occurs.
That worked but was tedious in terms of finding out which combination generated that.
A further modification of my program involved
1. setting fractional divider values
2. writing '0'
3. in a loop - emptying receiver fifo
4. looking for '0'
5. displaying the value of MulVal and DivAddVal
On the cable end I just put a paper clip between pins 2 and 3 (RX and TX) creating a loop back. Then just set a break point for when the "if" statement becomes true.
#include "main.h"
#define FRAC_TEST 1
#define TEST_VALUE '0'
int
main(void)
{
volatile unsigned int wdTemp, wdCount, wdLast;
volatile unsigned int wdMulVal, wdDivAddVal;
const int wdGpio=18;
unsigned char sbString[10];
asm ("ldr sp, =0x10010000");
setup_pll();
setup_nvic();
setup_gpio();
gpio_set_lpc_biled(0x3);
wdTemp = 0;
setup_gpdma();
setup_uart();
gpio_set_lpc_biled(0x0);
while(1)
{
//wdTemp++;
//uartio_printf("%d\r", wdTemp);
#ifdef FRAC_TEST
for(wdMulVal = 1; wdMulVal <= 15; wdMulVal++)
{
for(wdDivAddVal = 0; wdDivAddVal <= 15; wdDivAddVal++)
{
wdTemp = (wdMulVal << 4);
wdTemp |= wdDivAddVal;
EGWU_ONBOARD_UART->FDR = wdTemp;
#endif
(LPC_GPIO1->SET) = (1 << wdGpio);
uartio_putc(TEST_VALUE);
(LPC_GPIO1->CLR) = (1 << wdGpio);
wdLast = 0;
while((wdTemp = uartio_getch()) != 0)
wdLast = wdTemp;
if(wdLast == TEST_VALUE)
{
sbString[0] = 'D';
sbString[1] = '=';
IE_tclib_itoa(wdDivAddVal,sbString+2);
uartio_putc(0xd);
for(wdCount = 0; wdCount <10; wdCount++)
{
if(sbString[wdCount] == 0)
break;
else
uartio_putc(sbString[wdCount]);
}
sbString[0] = 'M';
sbString[1] = '=';
IE_tclib_itoa(wdMulVal,sbString+2);
uartio_putc(0xd);
for(wdCount = 0; wdCount <10; wdCount++)
{
if(sbString[wdCount] == 0)
break;
else
uartio_putc(sbString[wdCount]);
}
while(1)
;
}
#ifdef FRAC_TEST
timer_delay_mS(1);
}
}
#endif
}
}
That worked marvelously.
When the breakpoint hit, I examined wdMulVal and wdDivAddVal (both equal to 1). Fearing a mistake, I then proceeded to write a read a bunch of values to the uart data register (both RX and TX fifos are 16 bytes wide).
(gdb) load Loading section .data, size 0x160 lma 0x10000000 Loading section .text, size 0x3470 lma 0x10000160 Start address 0x10001a54, load size 13776 Transfer rate: 20 KB/sec, 2755 bytes/write. (gdb) c Continuing. Breakpoint 1, main () at app/main.c:34 34 const int wdGpio=18; (gdb) c Continuing. Breakpoint 2, main () at app/main.c:76 76 sbString[0] = 'D'; (gdb) p wdDivAddVal $1 = 15 (gdb) p wdMulVal $2 = 1 (gdb)
I was satisfied with the results.
Breakpoint 2, main () at app/main.c:76
76 sbString[0] = 'D';
(gdb) p wdMulVal
$5 = 1
(gdb) p wdDivAddVal
$6 = 1
(gdb) monitor mdw 0x4000c000
0x4000c000: 00000030
(gdb)
0x4000c000: 00000000
(gdb) monitor mww 0x4000c000 0x34
(gdb) monitor mdw 0x4000c000
0x4000c000: 00000034
(gdb) monitor mww 0x4000c000 0x32
(gdb) monitor mdw 0x4000c000
0x4000c000: 00000032
(gdb) monitor mww 0x4000c000 'a'
Invalid command argument
value option value (''a'') is not valid
in procedure 'mww'
(gdb) monitor mww 0x4000c000 0xd
(gdb) monitor mdw 0x4000c000
0x4000c000: 0000000d
(gdb) set wdTemp = 'c'
(gdb) print /x wdTemp
$7 = 0x63
(gdb) monitor mww 0x4000c000 0x61
(gdb) monitor mww 0x4000c000 0x62
(gdb) monitor mww 0x4000c000 0x63
(gdb) monitor mww 0x4000c000 0x30
(gdb) monitor mww 0x4000c000 0xd
(gdb) monitor mww 0x4000c000 0x0
(gdb) monitor mdw 0x4000c000
0x4000c000: 00000061
(gdb)
0x4000c000: 00000062
(gdb)
0x4000c000: 00000063
(gdb)
0x4000c000: 00000030
(gdb)
0x4000c000: 0000000d
(gdb)
0x4000c000: 00000000
(gdb)
0x4000c000: 00000000
(gdb)
0x4000c000: 00000000
(gdb) print wdDivAddVal
$8 = 1
(gdb) print wdMulVal
$9 = 1
(gdb) monitor mdw 0x4000c000 10
0x4000c000: 00000000 00000001 000000c1 00000003 00000000 00000060 00000000 00000000
0x4000c020: 00000000 00000000
(gdb) monitor mdw 0x4000c000 20
0x4000c000: 00000000 00000001 000000c1 00000003 00000000 00000060 00000000 00000000
0x4000c020: 00000000 00000000 00000011 00000000 00000080 00000000 00000000 00000000
0x4000c040: 00000000 00000000 00000000 00000000
I looked at the scope output to verify what I expected to see ~4.2 * 20e-6 = 84uS. Which means a new character is generated roughly 11,904 times a second. I can live with that and so can the UART ;)
Things should move more swiftly after this. I can proceed with the monitor program (already written in my notebook) after I test DMA controlled UART transmission later this weekend ... Phase 3 cant come soon enough for me ....
Monday, November 9, 2015
Phase 2: RS-232 blues continued ...
To make debugging with the scope easier ... I modified the code to toggle a pin high before writing to the uart, so I can use it as an external trigger for scope channel A.
But I discovered problems with its MAX232 part and had it replaced, then I got the expected output. The pin out of a DB9 viewed from left to right is (female) x = dont care
1. x
2. RX
3. TX
4. x
5. GND
ON this part I detected output on pin 2 which meanth it had a NULL modem wiring (RX-to-TX) so I needed a straight feed through serial cable between it and my development PC' serial port.
The ascii code above represents the value 0x30 or '0' (decimal 0). The length of the character transmission (on the scope) is ~70uS (3.5 bars at 20uS). That means ~14,285 characters are transmitted a second.
Makes sense since 115200/8 bits = 14,400 and I was eyeballing the above values.
On the scope everything looks fine for uart-TTL and uart-RS232. But I see gibberish under minicom and the uart line status register on the lpc1778 reports framing errors (missing stop/start bits?)
`�H `�H �
I even switched the baud rate down to 9600 to the same results.
Ill start looking at cabling later this week. I already tested one set of cables with an stm32 devel board I had lying around ... and it was fine.
Note to self:
here is a method for reading raw values out of the serial port
stty raw
cat >/tmp/received.dat </dev/ttyS0
(i wonder what setting it inherits for baudrate)
hexdump -n 256 /tmp/received.dat
stty normal or stty sane
returns the terminal emulator to its sane setting
while(1)
{
//wdTemp++;
//uartio_printf("%d\r", wdTemp);
(LPC_GPIO1->SET) = (1 << wdGpio);
//timer_delay_mS(1);
uartio_putc(0x30);
(LPC_GPIO1->CLR) = (1 << wdGpio);
//timer_delay_mS(1);
}
Was able to verify UART TTL output on the TX line and later the level converted value out of the MAX232. But there were problems with the db9 connector so I set that aside to test out connector K1 the second serial port (uart0) (db9 was uart1) and the ttl-to-uart adapter pictured below
But I discovered problems with its MAX232 part and had it replaced, then I got the expected output. The pin out of a DB9 viewed from left to right is (female) x = dont care
1. x
2. RX
3. TX
4. x
5. GND
ON this part I detected output on pin 2 which meanth it had a NULL modem wiring (RX-to-TX) so I needed a straight feed through serial cable between it and my development PC' serial port.
The ascii code above represents the value 0x30 or '0' (decimal 0). The length of the character transmission (on the scope) is ~70uS (3.5 bars at 20uS). That means ~14,285 characters are transmitted a second.
Makes sense since 115200/8 bits = 14,400 and I was eyeballing the above values.
On the scope everything looks fine for uart-TTL and uart-RS232. But I see gibberish under minicom and the uart line status register on the lpc1778 reports framing errors (missing stop/start bits?)
`�H `�H �
I even switched the baud rate down to 9600 to the same results.
Ill start looking at cabling later this week. I already tested one set of cables with an stm32 devel board I had lying around ... and it was fine.
Note to self:
here is a method for reading raw values out of the serial port
stty raw
cat >/tmp/received.dat </dev/ttyS0
(i wonder what setting it inherits for baudrate)
hexdump -n 256 /tmp/received.dat
stty normal or stty sane
returns the terminal emulator to its sane setting
Subscribe to:
Posts (Atom)





