Display previously received UART values - c

This should be easy to answer to anyone familiar with C. I want to display the previous values of a variable (receive register of a UART (RS-232) on a microcontroller) on an LCD. This is my current implementation and it works ok. But I'd like to know if there is a way to spend less time in my interrupt routine. Currently, the peripheral is configured to jump to the interrupt routine as soon as it receives one new character in the UART feed. Suggestions anyone?
//Initialization
char U1RX_data = '\0';
char p0_U1RX_data = '\0';
char p1_U1RX_data = '\0';
char p2_U1RX_data = '\0';
char p3_U1RX_data = '\0';
char p4_U1RX_data = '\0';
char p5_U1RX_data = '\0';
char p6_U1RX_data = '\0';
char p7_U1RX_data = '\0';
char U1buf[] = {p7_U1RX_data, p6_U1RX_data, p5_U1RX_data,
p4_U1RX_data, p3_U1RX_data, p2_U1RX_data,
p1_U1RX_data, p0_U1RX_data, U1RX_data, '\0'};
disp_string(-61, 17, 1, U1buf); //X, Y, mode, string
void _U1RXInterrupt(void){
p7_U1RX_data = p6_U1RX_data;
p6_U1RX_data = p5_U1RX_data;
p5_U1RX_data = p4_U1RX_data;
p4_U1RX_data = p3_U1RX_data;
p3_U1RX_data = p2_U1RX_data;
p2_U1RX_data = p1_U1RX_data;
p1_U1RX_data = p0_U1RX_data;
p0_U1RX_data = U1RX_data;
U1RX_data = U1RXREG;
IFS0bits.U1RXIF = 0;
}

You can use memmove in your interrupt, like this:
void _U1RXInterrupt(void)
{
memmove(&U1Buf[0], &U1Buf[1], 7);
U1Buf[7] = U1RX_data;
...
}
That replaces the assignments that you're currently performing manually and is a bit more idiomatic.
I'm hoping I understood you properly; the main point is to use memmove to shift the buffer down by one byte. As an aside, it's important to use memmove instead of memcpy when the destination and source buffers overlap, as in this example.

You could always make a fixed length circular buffer
char buffer[8] = { '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',);
char position = 0;
/* useable if you have a version of disp_string that takes a "number of chars"*/
char buffer_nprint()
{
/* print from position to the end of the buffer*/
disp_string(-61, 17, 1, &buffer[position], 8 - position);
if (position > 0)
{
/* now print from start of buffer to position */
disp_string(-61, 17, 1, buffer, position);
}
}
/* if you _don't_ have a version of disp_string that takes a "number of chars"
and are able to do stack allocations*/
char buffer_print()
{
char temp[9];
temp[8] = '/0';
memcpy(temp, &buffer[position], 8 - position);
memcpy(temp, buffer, position);
temp[8] = '/0';
disp_string(-61, 17, 1, temp);
}
char buffer_add(char new_data)
{
char old_data = buffer[position];
buffer[position] = new_data;
position = ((position + 1) & 8);
}
void _U1RXInterrupt(void)
{
buffer_add(U1RXREG);
IFS0bits.U1RXIF = 0;
}

As Emerick noted, memmove() will work nicely if you have access to it. If not, just grab a simple implementation of it from Google, it shouldn't take up too much instruction memory.
What's your clock frequency on the microcontroller? Another thing to think about is that if your clock speed is significantly higher than your baud rate a lot of these things become non-issues. For example, if your clock speed is 16 MHz, you really don't have to worry about creating the world's shortest ISR as long as your not doing anything insanely computationally intensive inside it. Also, if you're clocking the system significantly faster than the baud rate, polling is also an option.
EDIT: Another option I just thought of, using interrupts.
You could store your buffer as an array of chars and then keep a global index to the next empty slot, like this:
#define UART_BUF_SIZE 16
char uart_buf[UART_BUF_SIZE] = {0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0};
char uart_buf_index = 0;
Then in your ISR, all you need to do is dump the new byte into the bucket that index points at and increment the index. This will automatically overwrite the oldest character in the buffer as the start position rotates back around the buffer.
void my_isr()
{
uart_buf[uart_buf_index] = get_uart_byte();
uart_buf_index = (uart_buf_index + 1) % UART_BUF_SIZE;
}
Basically at this point you've got a buffer with a rotating starting position, but it saves you from having to move 16 bytes of memory every ISR. The trick comes in reading it back out, because you have to account for the wrap-around.
char i;
for (i = uart_buf_index; i < UART_BUF_SIZE; i++)
{
lcd_write_byte(uart_buf[i]);
}
for (i = 0; i < uart_buf_index; i++)
{
lcd_write_byte(uart_buf[i]);
}

I would create an array of previous values, and treat it as a circular buffer. The interrupt routine then simply records the new value in the next slot, overwriting the last value, and incrementing the index.
#define DIM(x) (sizeof(x)/sizeof(*(x)))
static int index = 0;
static char uart[8];
void _U1RXInterrupt(void){
if (++index >= DIM(uart))
index = 0;
uart[index] = U1RXREG;
IFS0bits.U1RXIF = 0;
}
int uart_value(unsigned n)
{
int i = index + DIM(uart) - (n % DIM(uart));
if (i > DIM(uart))
i -= DIM(uart);
return(uart[i]);
}
I'm assuming synchronous, non-threaded operation; if you have to deal with multi-threaded, then there's work to protect the index variable from concurrent access. It also returns zeroes for the last but one reading before the buffer is full. Etc. If you are confident of your coding, you can remove the modulo operation, too.

Since it is a dspic, you might want to have a look at exaples ce214 and ce114 that handle uart DMA.
Go here and search for "uart":
http://www.microchip.com/TechDoc.aspx?type=CodeExamples&ctl00_MainContent_DocListGridChangePage=6
The DMA approach is block oriented, and with one interrupt per block the lightest. However the block orientation can also be an disadvantage if your information stream is not continuous, since bytes might be held up in a buffer.
Maybe you can remedy this by setting a timer.

Related

Array values reset in loop

So I am using poll() to read a couple gpio pins. I then compare previously read values to the newly read ones to see if they have changed. The reading of the values works just fine. My problem seems to be in the loop. This can be seen from the output where it looks like buffers is reset at the beginning of the loop. Why is this happening?
Note: In case anyone is wondering why I don't just use poll() as an interrupt with a delay of -1, it is because of a hardware issue that makes it unsupported.
Code
static const int num_buttons = 2;
void *routine(){
struct pollfd pfd[num_buttons];
int fds[num_buttons];
const char gpioValLocations[num_buttons][256];
int i;
for (i = 0; i < num_buttons ; i++){
sprintf(gpioValLocations[i], "/sys/class/gpio/gpio%d/value", gpios[i]);
}
char buffers[num_buttons][2];
char prev_buffers[num_buttons][2];
for (i = 0; i < num_buttons; i++){
if ((fds[i]= open(gpioValLocations[i],O_RDONLY)) < 0) {
LOGD("failed on 1st open");
exit(1);
}
pfd[i].fd = fds[i];
pfd[i].events = POLLIN;
lseek(fds[i], 0, SEEK_SET);
read(fds[i], buffers[i], sizeof buffers[i]);
}
for (;;) {
LOGD("at top: prev:%d%d buff:%d%d", atoi(prev_buffers[0]), atoi(prev_buffers[1]), atoi(buffers[0]), atoi(buffers[1]));
poll(pfd, num_buttons, 1);
for (i = 0; i < num_buttons; i++) {
if ((pfd[i].revents & POLLIN)) {
/* copy current values to compare to next to detected change */
strcpy(prev_buffers[i], buffers[i]);
LOGD("in loop: prev:%d%d buff:%d%d",
atoi(prev_buffers[0]), atoi(prev_buffers[1]),
atoi(buffers[0]), atoi(buffers[1]));
/* read new values */
lseek(fds[i], 0, SEEK_SET);
read(fds[i], buffers[i], sizeof buffers[i]);
/* compare new to previous */
if (atoi(prev_buffers[i]) != atoi(buffers[i])) {
// LOGD("change detected");
}
}
}
}
}
Output
at top: prev:00 buff:01
in loop: prev:01 buff:00
in loop: prev:00 buff:00
at top: prev:00 buff:01
in loop: prev:01 buff:00
in loop: prev:00 buff:00
This line seems risky:
strcpy(prev_buffers[i], buffers[i]);
prev_buffers[i] is only 2 bytes long. If buffers[i] has more than 1 character, you have a buffer overflow and invoke undefined behavior.
Furthermore, you must initialize buffers, they currently start with random junk, not single byte character strings: using strcpy to save the previous values invokes undefined behavior. Using memcpy() to save whatever previous contents is less risky as it will copy just 2 bytes, instead of scanning the buffers for a null terminator, potentially invoking undefined behavior both when reading past the end of buffers[i] and when writing past the end of prev_buffers[i].
Are you sure that read(fds[i], buffers[i], sizeof buffers[i]); reads an ASCII digit and a null terminator? If not, the code is incorrect.
Post a complete function that compiles, there might be more problems.

UART write buffer with PDC

I'm having a problem with writing to a USARt using const char buffer and char arrray.
Here is my UART write function:
unsigned int USART_Send( unsigned char *p_pucData,
unsigned int p_unLen)
{
AT91C_BASE_US2->US_TPR = (unsigned int)p_pucData;
AT91C_BASE_US2->US_TCR = p_unLen;
AT91C_BASE_US2->US_PTCR = AT91C_PDC_TXTEN;
while((AT91C_BASE_US2->US_CSR & ((0x1 << 11) | (0x1 << 4) ) ) == 0);
AT91C_BASE_US2->US_PTCR = AT91C_PDC_TXTDIS;
return p_unLen;
}
Below function working with const char* like:
USART_Send("IsitDone?",9); //Working
If I use a array buffer like below it is showing garbage characters, wonder why ?
unsigned char arr[10];
memcpy(arr, "HelloWorld", 10);
USART_Send(arr, sizeof(arr)); //Not working properly displaying Garbage chars
Ricardo Crudo is correct. You run into the following problem:
arr is created on the stack
arr is filled
call USART_Send
fill transmit pointer, counter, enable tx requests
/* peripheral state is TXBUFE = '0' and ENDTX = '0' because: */
/* TXBUFE = '0' when PERIPH_TCR != 0 and */
/* ENDTX = '0' when PERIPH_TCR != 0 */
/* but we just wrote to PERIPH_TCR, so it's != 0 */
/* both conditions are satisfied, b/c the transfer hasn't started yet! */
wait until (TXBUFE = '0' and ENDTX = '0')
/* your code thinks PDC is done here */
/* but in reality, PDC is getting started */
disable tx requests
return from sub-function
overwrite stack (and arr) with unrelated data here
/* PDC might push out last word(s) here due to pipelining/ */
/* instruction cache/side effects/you-name-it */
/* even though its matrix requests were disabled a few cycles ago */
Solutions:
copy to a global buffer or
wait some cycles between enabling tx requests and checking if the PDC is done (possibly a whole baud tick) or
read back PERIPH_TCR and check if it's zero instead of checking the flags
Ideally, you would allocate some dynamic memory for strings and deallocate it after the PDC is done asynchronously to your actual code. You might want to check if you can get some kind of interrupt after the PDC/peripheral is done, then deallocate the memory it read from.
If you don't have dynamic memory allocation, then use the a global ring buffer and abstract your string/char send function to use this buffer instead.

Get the character dominant from a string

Okay.. according to the title i am trying to figure out a way - function that returns the character that dominates in a string. I might be able to figure it out.. but it seems something is wrong with my logic and i failed on this. IF someome can come up with this without problems i will be extremelly glad thank you.
I say "in a string" to make it more simplified. I am actually doing that from a buffered data containing a BMP image. Trying to output the base color (the dominant pixel).
What i have for now is that unfinished function i started:
RGB
bitfox_get_primecolor_direct
(char *FILE_NAME)
{
dword size = bmp_dgets(FILE_NAME, byte);
FILE* fp = fopen(convert(FILE_NAME), "r");
BYTE *PIX_ARRAY = malloc(size-54+1), *PIX_CUR = calloc(sizeof(RGB), sizeof(BYTE));
dword readed, i, l;
RGB color, prime_color;
fseek(fp, 54, SEEK_SET); readed = fread(PIX_ARRAY, 1, size-54, fp);
for(i = 54; i<size-54; i+=3)
{
color = bitfox_pixel_init(PIXEL_ARRAY[i], PIXEL_ARRAY[i+1], PIXEL_ARRAY[i+2);
memmove(PIX_CUR, color, sizeof(RGB));
for(l = 54; l<size-54; l+=3)
{
if (PIX_CUR[2] == PIXEL_ARRAY[l] && PIX_CUR[1] == PIXEL_ARRAY[l+1] &&
PIX_CUR[0] == PIXEL_ARRAY[l+2])
{
}
Note that RGB is a struct containing 3 bytes (R, G and B).
I know thats nothing but.. thats all i have for now.
Is there any way i can finish this?
If you want this done fast throw a stack of RAM at it (if available, of course). You can use a large direct-lookup table with the RGB trio to manufacture a sequence of 24bit indexes into a contiguous array of counters. In partial-pseudo, partial code, something like this:
// create a zero-filled 2^24 array of unsigned counters.
uint32_t *counts = calloc(256*256*256, sizeof(*counts));
uint32_t max_count = 0
// enumerate your buffer of RGB values, three bytes at a time:
unsigned char rgb[3];
while (getNextRGB(src, rgb)) // returns false when no more data.
{
uint32_t idx = (((uint32_t)rgb[0]) << 16) | (((uint32_t)rgb[1]) << 8) | (uint32_t)rgb[2];
if (++counts[idx] > max_count)
max_count = idx;
}
R = (max_count >> 16) & 0xFF;
G = (max_count >> 8) & 0xFF;
B = max_count & 0xFF;
// free when you have no more images to process. for each new
// image you can memset the buffer to zero and reset the max
// for a fresh start.
free(counts);
Thats it. If you can afford to throw a big hulk of memory at this a (it would be 64MB in this case, at 4 bytes per entry at 16.7M entries), then performing this becomes O(N). If you have a succession of images to process you can simply memset() the array back to zeros, clear max_count, and repeat for each additional file. Finally, don't forget to free your memory when finished.
Best of luck.

C char array address issue

I am having a problem in C with addressing char array in a structure. When I write characters in the array it writes them in word boundaries and not character boundaries. Here is the structure declaration.
typedef struct RxBuffer {
int Status;
int ByteCount;
int Index;
char Data[SCI_BUFFER_LENGTH];
} RxBuffer;
and here is the code that actually does the write,
RxBuffer SciaRxBuffer;
char SciaRxData;
int LoopBackCrFlag;
int RxDataReady;
interrupt void scia_rx_isr()
{
// Get Rx Data and first LoopBack
SciaRxData = SciaRegs.SCIRXBUF.all; // Read data
SciaRegs.SCITXBUF = SciaRxData; // Send loop back Tx data
// Check to see if carriage return
if (SciaRxData == CR)
{
// Set the loopback flag so Line-feed is transmitted
LoopBackCrFlag = TRUE;
}
//!
//! Problem is right here. SciaRxData is being written into
//! SciaRxBuffer.Data[SciaRxBuffer.ByteCount++] on Word
//! boundaries instead of byte boundaries.
//!
// Stuff RxBuffer & Mark as busy
SciaRxBuffer.Data[SciaRxBuffer.ByteCount++] = SciaRxData;
SciaRxBuffer.Status = RX_BUSY;
if (SciaRxData == CR)
{
SciaRxBuffer.Status = RX_READY;
SciaRxBuffer.Index = 0;
RxDataReady = TRUE;
}
// Clear Overflow and interrupt flags
SciaRegs.SCIFFRX.bit.RXFFOVRCLR = 1; // Clear Overflow flag
SciaRegs.SCIFFRX.bit.RXFFINTCLR = 1; // Clear Interrupt flag
// Issue the PIE ack
PieCtrlRegs.PIEACK.all|=0x100;
}
Any help is welcome
Best Regards,
Steve Mansfield
Thank you for everyone's input. I just did some digging into the hardware and found out that the TI DSP that I am using does not support byte operations. It's smallest operation is a word (2 bytes). Even though I declared the array as a char array, when I write to the array it writes it as an integer. If I want to handle byte operations I will have to shift left the first character 8 bits and then OR the next character and then write it into the array. Like everyone always says, if there is a problem with the hardware -- fix it in software!
Best Regards,
Steve Mansfield

How is this tcp socket code handling the rx buffer?

I came across this tcp server example, provided with the Altera Nios II processor, and I'm not getting the section on handling the rx_buffer.
server.h
typedef struct SSS_SOCKET {
enum {
READY, COMPLETE, CLOSE
} state;
int fd;
int close;
INT8U rx_buffer[SSS_RX_BUF_SIZE];
INT8U *rx_rd_pos; /* position we've read up to */
INT8U *rx_wr_pos; /* position we've written up to */
} SSSConn;
server.c
int data_used = 0, rx_code = 0;
INT8U *lf_addr;
conn->rx_rd_pos = conn->rx_buffer;
conn->rx_wr_pos = conn->rx_buffer;
printf("[sss_handle_receive] processing RX data\n");
while (conn->state != CLOSE) {
/* Find the Carriage return which marks the end of the header */
lf_addr = strchr(conn->rx_buffer, '\n');
if (lf_addr) {
/* go off and do whatever the user wanted us to do */
sss_exec_command(conn);
}
/* No newline received? Then ask the socket for data */
else {
rx_code = recv(conn->fd, conn->rx_wr_pos,
SSS_RX_BUF_SIZE - (conn->rx_wr_pos - conn->rx_buffer) -1, 0);
if (rx_code > 0) {
conn->rx_wr_pos += rx_code;
/* Zero terminate so we can use string functions */
*(conn->rx_wr_pos + 1) = 0;
}
}
/*
* When the quit command is received, update our connection state so that
* we can exit the while() loop and close the connection
*/
conn->state = conn->close ? CLOSE : READY;
/* Manage buffer */
data_used = conn->rx_rd_pos - conn->rx_buffer;
memmove(conn->rx_buffer, conn->rx_rd_pos,
conn->rx_wr_pos - conn->rx_rd_pos);
conn->rx_rd_pos = conn->rx_buffer;
conn->rx_wr_pos -= data_used;
memset(conn->rx_wr_pos, 0, data_used);
}
Specifically, I don't see the purpose of the data_used variable. rx_rd_pos is pointing to rx_buffer and there doesn't appear to be an operation on either, so how will they be different? In fact, the only thing that seems to happen under Manage buffer is the copying of data into rx_buffer. I'm sure I'm missing something simple, but I can't seem to see it.
Thanks for any help in advance.
Edit: Here's the sss_exec_command() function.
void sss_exec_command(SSSConn* conn) {
int bytes_to_process = conn->rx_wr_pos - conn->rx_rd_pos;
INT8U tx_buf[SSS_TX_BUF_SIZE];
INT8U *tx_wr_pos = tx_buf;
INT8U error_code;
/*
* "SSSCommand" is declared static so that the data will reside
* in the BSS segment. This is done because a pointer to the data in
* SSSCommand
* will be passed via SSSLedCommandQ to the LEDManagementTask.
* Therefore SSSCommand cannot be placed on the stack of the
* SSSSimpleSocketServerTask, since the LEDManagementTask does not
* have access to the stack of the SSSSimpleSocketServerTask.
*/
static INT32U SSSCommand;
SSSCommand = CMD_LEDS_BIT_0_TOGGLE;
while (bytes_to_process--) {
SSSCommand = toupper(*(conn->rx_rd_pos++));
if (SSSCommand >= ' ' && SSSCommand <= '~') {
tx_wr_pos += sprintf(tx_wr_pos,
"--> Simple Socket Server Command %c.\n",
(char) SSSCommand);
if (SSSCommand == CMD_QUIT) {
tx_wr_pos += sprintf(tx_wr_pos,
"Terminating connection.\n\n\r");
conn->close = 1;
} else {
error_code = OSQPost(SSSLEDCommandQ, (void *) SSSCommand);
alt_SSSErrorHandler(error_code, 0);
}
}
}
send(conn->fd, tx_buf, tx_wr_pos - tx_buf, 0);
return;
}
Answers below are correct. I missed the pointer arithmetic on rx_rd in the command function :P
That section removes data from the buffer once it has been processed. The code you posted never uses the data stores in the buffer, but the sss_exec_command function will, after a newline is received. That function is passed the connection, so it can increment the read position by however much it uses.
After data is used, the buffer management section reclaims the space. The amount of data left in the buffer is the difference between the write and read positions. This much data is moved from the write position to the start of the buffer, then the read and write pointer are updated to their new positions. The read position is set to the start of the buffer, and the write position is decremented by data_used, which is the original difference between the start of the buffer and the read pointer, i.e. the amount of data used.
Assuming the code actually works, then data_used = conn->rx_rd_pos - conn->rx_buffer implies rx_rd_pos is being changed; this would be being changed when the code has consumed the data written into the buffer (it's written in at rx_wr_pos and consumed from rx_rd_pos). This would imply that sss_exec_command(conn) is adjusting conn. Is that the case?

Resources