Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Valued Contributor III
688 Views

Serial communication and interval timer integration problems

I'm required to build a Nios based fpga firmware for a specific system, which includes UART RS-232 communication. The communication itself based on packets of 20 bytes, with time outs between bytes receive. For example: if data receive process started if the next byte is not received within 1ms, discard, the received data, until 20 bytes are received. I've written in Nios IDE functions for communication and timer control: uart interrupt handling, enable/disable interrupts, checksum check, start timer, stop timer, restart timer, time out handling, set period and etc. 

 

All the functions are working fine except there is a problem with some nesting: 

If I get to uart interrupt handling due to received byte, and within those interrupt routine I'm calling some timer control functions, I miss some of received bytes. It makes it look like those timer control functions take more than 100,000 CPU cycles, which is of course not true. UART baud rate is 115200, the whole system frequency is 50MHz. 

 

I can't copy for you the code, but here is the pseudo code of UART interrupt handling: 

 

int index = 0; 

unsigned char rx_packet[20]; 

 

void timer_interrupt_handling(){ 

if time out occurred 

timer_stop(); 

index = 0; 

clear_timeout(); 

 

void uart_interrupt_handling(){ 

if byte is received 

restart_timer(); 

rx_packet[index] = read_uart_rx(); 

index++; 

if index > 19 

timer_stop(); 

index = 0; 

packet_handling(); 

clear_uart_interrupt(); 

 

If I run this code rx_packet ={rx[0], rx[5], rx[10], rx[15], non_valid, non_valid, ........} 

If I remove the timer functions calling, everything works fine.
0 Kudos
5 Replies
Highlighted
Valued Contributor III
4 Views

I doubt that the timer functions are interrupt-safe. 

Also I've not seen any hint of any of the Alera suppplied code being 'high performance'. 

All I would do is take keep a timestamp of when the last byte was received. 

When you get a new byte look at how old the partial record is, and discard if old. 

 

I don't know if one of the Altera Avalon slaves is a 32bit clock counter (or a 32bit usec counter - which would save the software knowing the clock speed) - but one wouldn't be difficult to write. Probably worth having 4 counters: clocks, usec, ms and sec.
0 Kudos
Highlighted
Valued Contributor III
4 Views

Thanks for the answer. I'm new to this ans studying by myself. 

I'm not using sys_clk_timer nor timerstamp_timer. Is it necessary to create them in QSYS and define in Nios IDE? 

In examples I've noticed that usually interrupt handling functions defined as static and some variables defined as volatile. When do I have to use this definitions? 

I'm also using timers for a fan control: PWM and tachometer. Timer for a PWM is very dynamic, but still it works without any problems.
0 Kudos
Highlighted
Valued Contributor III
4 Views

If a variable (or structure member) is marked 'volatile' then the compiled has to assume that unknown (to the code flow) accesses to that variable might happen, and the compiler must not cache the value in a register. 

For example, if you want to wait for an interrupt to change something, the code: 

int x = 0; ... while (x == 0) continue; 

won't work becuse the compiler will generate code that only read 'x' once. 

Use 'volatile int x;' and the compiler will generate code that reads 'x' every time around the loop. 

 

'static' just indicates that the symbol is only visible in current source file. 

 

What you might find is that just getting into your ISR is taking so many instructions that there aren't enough left for any useful work.
0 Kudos
Highlighted
Valued Contributor III
4 Views

When I use those functions for a creation a PWM signal, it works fine. Here is a real example: 

I've created a PWM signal with a frequency of 10KHz, duty cyle is 1%. Period of 10KHz is 100us, DC of 1% means that output '1' should be for a 1us. With CPU clock of 50MHz, that means that the timer has to count 50 cycles, for a time out, and than process the ISR. It works, maybe I get the real DC of 1.5%, but this accuracy is fine for me. 

Those hardware control functions, that I've written, they're just 1-10 lines of IORD/IOWR commands. How many CPU cycles those commands require?
0 Kudos
Highlighted
Valued Contributor III
4 Views

You have 50000 clocks there. 

What you can't see is the delay between the timer hitting its count and the cpu performing the first IORD/IOWR. 

It is likely to be the same for every expiry - so everything will look fine - until your ISR processing takes all the cpu time. 

IORD/IOWR themselves are likely to be 3 clocks (plus time to get the data to write, and fetch any code from external memory if you aren't executing from tightly coupled instruction memory and the code isn't still in the cache), but the time to save the registers and then call your ISR is a lot.
0 Kudos