As i intend to read all received characters i have choosen to use the first option , one interrupt for each received character. In order to read this character however i must read the whole fifo , 3 dummy reads before i can get to the char i received. Is there anyone who has a better solution , some way to disable the fifo perhaps ?21.6.3 Receive Interrupt
The UARTx Receive Interrupt Flag (UxRXIF) is located in the corresponding Interrupt Flag Status
(IFSx) register. The URXISEL<1:0> (UxSTA<7:6>) control bits determine when the UART
receiver generates an interrupt.
a) If URXISEL<1:0> = 00 or 01, an interrupt is generated each time a data word is transferred
from the Receive Shift Register (UxRSR) to the receive buffer. There may be one or more
characters in the receive buffer.
b) If URXISEL<1:0> = 10, an interrupt is generated when a word is transferred from the
Receive Shift Register (UxRSR) to the receive buffer, and as a result, the receive buffer
contains 3 or 4 characters.
c) If URXISEL<1:0> = 11, an interrupt is generated when a word is transferred from the
Receive Shift Register (UxRSR) to the receive buffer, and as a result, the receive buffer
contains 4 characters (i.e., becomes full).
is it possible to disable the Uart FIFO on p24 ?
is it possible to disable the Uart FIFO on p24 ?
after implementing my Uart ISR on p24fj64ga002 i have some problem with the 4 byte deep hardware fifo on this chip. the datasheet tell me :
Au royaume des aveugles, les borgnes sont rois.
Hi,
I also use URXISEL<1:0> = %00 for my uart receive interrupt because my receive data is in bursts, and I did not want to have data in the FIFO that is not processed.
The FIFO buffer does not require 3 dummy reads to get to the required data. If the receive interrupt can process fast enough, a single read is sufficient in the interrupt routine. If the receive interrupt cannot process the data fast enough before another character comes it, then the receive interrupt has to allow for multiple reads if necessary by checking the URXDA data available flag. Even then, the FIFO buffer is transparent and it is not necessary to decide how many dummy reads to do in different situations to get at the real data.
I use a straightforward read (I use mikroBasic for dsPIC):
In the main code, receive interrupt is turned on before enabling uart:
The other possibility is if the FIFO buffer overflows. The interrupt routine would need to check and clear OERR if necessary.
Interrupt processing is normally set up fast enough and no dummy reads, URXDA or OERR processing is necessary.
I also use URXISEL<1:0> = %00 for my uart receive interrupt because my receive data is in bursts, and I did not want to have data in the FIFO that is not processed.
The FIFO buffer does not require 3 dummy reads to get to the required data. If the receive interrupt can process fast enough, a single read is sufficient in the interrupt routine. If the receive interrupt cannot process the data fast enough before another character comes it, then the receive interrupt has to allow for multiple reads if necessary by checking the URXDA data available flag. Even then, the FIFO buffer is transparent and it is not necessary to decide how many dummy reads to do in different situations to get at the real data.
I use a straightforward read (I use mikroBasic for dsPIC):
Code: Select all
sub procedure U2RxInt org 0x50
u2rxif = 0
u2rxtmp = u2rxreg
if (u2rxtmp = 10) ...
Code: Select all
u2rxie = 1
uarten2 = 1
Interrupt processing is normally set up fast enough and no dummy reads, URXDA or OERR processing is necessary.
thanks for your reply skyline ,
i wonder if this is some anomaly of the chip i use here , i discovered in between that the same ISR i use for few years on P30 never gave me this issue. When i test it however on this 24fj64GA002 with this simple programi have to type 4 characters before the first one is echoed back. I am absolutly sure each character generates an individual interrupt , no data gets lost but there are allways 3 hiding in the fifo as it seems. The only way i can make it work is by reading the UxRXREG until UxSTA.URXDA becomes 0 as is shown in this ISR.
i wonder if this is some anomaly of the chip i use here , i discovered in between that the same ISR i use for few years on P30 never gave me this issue. When i test it however on this 24fj64GA002 with this simple program
Code: Select all
while true do
begin
if keypressed1 = true then
begin
k :=(readkey1);
uart1_write_char(k);
end;
end;
Code: Select all
procedure uart1_rx_irq; org $2A; // Uart1 receiver interrupt
var n : byte;
begin
if IFS0.11 = 1 then
begin
if U1STA and %000000001110 = 0 then // no error , get character
begin
while U1STA.0 = 1 do ik1 := U1RXREG; // fetch character
mrxbuf1[rxhead1]:= ik1; // store it in circular buffer
rxb1_empty := false;
inc(rxhead1);
if rxhead1 = rxbuf1size then
begin
rxhead1 := 0;
end;
if rxhead1 = rxtail1 then
begin
rxb1_full := true; // buffer full
end;
end else
begin
if U1STA.1 = 1 then // overrun error
begin
ClearBit(U1STA,1);
end;
if U1STA.2 = 1 then // framing error
begin
ClearBit(U1STA,2);
end;
if U1STA.3 = 1 then // parity error
begin
ClearBit(U1STA,3);
end;
end;
end;
IFS0.11 := 0; // clear interrupt-flag
end;
Au royaume des aveugles, les borgnes sont rois.
Hi jpc,
I'm using your IRQ Uart library on my PIC24Fs.
I've successfully used it on a
Please find the code here
Anton
I'm using your IRQ Uart library on my PIC24Fs.
I've successfully used it on a
Code: Select all
PIC24FJ16GA002
PIC24FJ32GA002
PIC24FJ64GA002
PIC24FJ96GA010
Code: Select all
unit irq_uart1;
var Delimiter : array[0..5] of byte;
implementation
const rxbufsize : word = 1023;
baudrate : longint = 19200;
var ik : byte; // private to interrupt !
RXBufHead,
RXBufTail : word;
RxBuf : array[0..rxbufsize] of byte;
RXbufempty : boolean
MessageCounter : byte;
Read_index,
Delim_index : word;
function IRQ_Uart1_DataReady : boolean; // returns true if receivebuffer contains message terminated by delimiter
begin
if MessageCounter > 0 then result := TRUE else result := FALSE;
end;
function IRQ_Uart1_MessageCount : byte; // returns true if receivebuffer contains message terminated by delimiter
begin
result := MessageCounter;
end;
Procedure IRQ_Uart1_ClearBuffer;
begin
RXBufHead := 0;
RXBufTail := 0;
RXbufempty := true;
Read_index := 0;
MessageCounter := 0;
Delim_index := 0;
end;
procedure IRQ_Uart1_SendByte(k : byte); // write a byte to the TX-FIFO
begin
// Uart1_Write(k);
Uart1_Write_Char(k);
end;
procedure IRQ_Uart1_Send(var s : string[100]);
var i : word;
begin
i := 0;
while s[i] <> 0 do
begin
Uart1_Write_Char(s[i]);
//Uart1_Write(s[i]);
inc(i);
end;
end;
function IRQ_Uart1_ReadByte : byte; // Read A Byte From The Input-fifo
var Rk : Byte;
Begin
Rk := 0;
If Rxbufempty = False then
Begin
Rk := Rxbuf[RxBufHead];
if Rk = Delimiter[Read_index] then
Begin
Inc(Read_index);
End
else
Begin
Read_index := 0;
if Rk = Delimiter[Read_index] then Inc(Read_index);
End;
if Delimiter[Read_index] = 0 then
begin
if MessageCounter > 0 then dec(MessageCounter);
Read_index := 0;
end;
Rxbuf[RxBufHead] := 0; // Destructive Read
Inc(RxBufHead);
If RxBufHead > Rxbufsize Then RxBufHead := 0;
If RxBufHead = RxBufTail Then Rxbufempty := True;
End;
Result := Rk;
End;
procedure IRQ_Uart1_Read(var data : String[100]);
var k : byte;
local_index : word;
data_index : word;
begin
local_index := 0;
data_index := 0;
while delimiter[local_index] <> 0 do
begin
k := IRQ_Uart1_ReadByte;
if k = delimiter[local_index] then
Begin
inc(local_index);
End
else
Begin
local_index := 0;
if k = Delimiter[local_index] then inc(local_index);
End;
data[data_index] := k;
inc(data_index);
end;
// data[data_index-2] := 0;
// data[data_index-1] := 0;
data[data_index] := 0;
// result := data_index; // - length(Delimiter);
end;
procedure IRQ_Uart1_Int; org $2A;
begin
IFS0 := IFS0 AND $F7FF; // Clear UART 1 Rx flag
ik := Uart1_Read_Char;
if (U1STA AND %0000000000000110) > 0 then
begin
U1STA := 0x0000;
U1MODE := 0x8000;
NOP;
U1STA := 0x0400;
NOP;
NOP;
NOP;
NOP;
exit;
end;
RxBuf[RxBufTail] := Ik;
Rxbufempty := False;
Inc(RxBufTail);
If RxBufTail > Rxbufsize Then RxBufTail := 0;
If Ik = Delimiter[Delim_index] Then
Begin
Inc(Delim_index);
End
else
Begin
Delim_index := 0;
if ik = Delimiter[Delim_index] then inc(Delim_index);
End;
If Delimiter[Delim_index] = 0 Then
Begin
Inc(MessageCounter);
Delim_index := 0;
End;
IFS0 := IFS0 AND $F7FF; // Clear UART 1 Rx flag
end;
procedure IRQ_Uart1_Init; // initialises interrupt's and variable's
begin
memset(@RXbuf, 0, rxbufsize);
Uart1_Init(19200);
RXBufHead := 0;
RXBufTail := 0;
RXbufempty := true;
Read_index := 0;
MessageCounter := 0;
Delim_index := 0;
Delimiter[0] := 0x0D;
Delimiter[1] := 0x0A; //0x0A;
Delimiter[2] := 0;
// Enable the interrupt
IFS0 := IFS0 AND 0xF7FF; // Clear UART 1 Rx flag
IEC0 := IEC0 OR 0x0800; // Enable UART 1 Rx Int
// IPC2 := IPC2 OR 0x7000;
Delay_Ms(1500);
end;
end.
Another proud user of LV 24-33A Development System and mikroPascal PRO for dsPIC :)
PortA not working? Add CMCON := 7; PortD not working? Add ADCON1 := 6;
To paste code on the forum, please use the [b] Code [/b] button !! ;)
PortA not working? Add CMCON := 7; PortD not working? Add ADCON1 := 6;
To paste code on the forum, please use the [b] Code [/b] button !! ;)
Thanks Anton ,
i do not understand what i did wrong , your version seems to work ok ! The only difference i see is that you use the Uart-libray functions .
There are a few issues i do not understand :
You are NOT configuring the URxISEL bits in U1STA or do you rely on them beeing zero after reset ?
Why do you clear the Uart RX flag twice in the ISR ?
Why do you NOT deal with error-flags ( besides clearing all)?
What is the motivation behind all these NOP's in case of an error ?
Regards jpc
i do not understand what i did wrong , your version seems to work ok ! The only difference i see is that you use the Uart-libray functions .
There are a few issues i do not understand :
You are NOT configuring the URxISEL bits in U1STA or do you rely on them beeing zero after reset ?
Why do you clear the Uart RX flag twice in the ISR ?
Why do you NOT deal with error-flags ( besides clearing all)?
What is the motivation behind all these NOP's in case of an error ?
Regards jpc
Au royaume des aveugles, les borgnes sont rois.
I make use of the build in UART library's Init_Uart1 procedure, otherwise you could do something like this to init the portjpc wrote: You are NOT configuring the URxISEL bits in U1STA or do you rely on them beeing zero after reset ?
Code: Select all
U1BRG := 0x0081; // BAUD - 9600 with 10 MHz PPL Enabled
U1MODE := 0x8000;
U1STA := 0x0400;
No need for this, it was accidentally and I'll remove it from my code. Thank youWhy do you clear the Uart RX flag twice in the ISR ?
What I'm doing is checking the error flags with the following lineWhy do you NOT deal with error-flags ( besides clearing all)?
Code: Select all
if (U1STA AND %0000000000000110) > 0 then
Code: Select all
begin
U1STA := 0x0000;
U1MODE := 0x0000;
NOP;
U1MODE := 0x8000;
NOP;
U1STA := 0x0400;
NOP;
end;
Hope I answered your question here.
There is only one NOP required in between setting U1MODE and U1STA but I added them hoping that it will be more fail save. In my application I'm using the power save functions alot and it helps on the wake from sleep where the PIC isn't running full speed yet. All of them aren't necessary.What is the motivation behind all these NOP's in case of an error ?
Anton
Another proud user of LV 24-33A Development System and mikroPascal PRO for dsPIC :)
PortA not working? Add CMCON := 7; PortD not working? Add ADCON1 := 6;
To paste code on the forum, please use the [b] Code [/b] button !! ;)
PortA not working? Add CMCON := 7; PortD not working? Add ADCON1 := 6;
To paste code on the forum, please use the [b] Code [/b] button !! ;)
Hi,
Back to your first question.
I also clear them when I set the U1STA register.
Anton
Back to your first question.
Yes, I accept that the URXISEL will be 0x00 after a reset. (Case a)The UARTx Receive Interrupt Flag (UxRXIF) is located in the corresponding Interrupt Flag Status
(IFSx) register. The URXISEL<1:0> (UxSTA<7:6>) control bits determine when the UART
receiver generates an interrupt.
a) If URXISEL<1:0> = 00 or 01, an interrupt is generated each time a data word is transferred
from the Receive Shift Register (UxRSR) to the receive buffer. There may be one or more
characters in the receive buffer.
b) If URXISEL<1:0> = 10, an interrupt is generated when a word is transferred from the
Receive Shift Register (UxRSR) to the receive buffer, and as a result, the receive buffer
contains 3 or 4 characters.
c) If URXISEL<1:0> = 11, an interrupt is generated when a word is transferred from the
Receive Shift Register (UxRSR) to the receive buffer, and as a result, the receive buffer
contains 4 characters (i.e., becomes full).
I also clear them when I set the U1STA register.
Anton
Another proud user of LV 24-33A Development System and mikroPascal PRO for dsPIC :)
PortA not working? Add CMCON := 7; PortD not working? Add ADCON1 := 6;
To paste code on the forum, please use the [b] Code [/b] button !! ;)
PortA not working? Add CMCON := 7; PortD not working? Add ADCON1 := 6;
To paste code on the forum, please use the [b] Code [/b] button !! ;)
Yes, now I remember I had the same problem. That is why I used the Uart1_Read_Char. What we can do is compile it with Uart1_Read_Char and check the asm output.jpc wrote:ok , some more info :
if i replace in my version ik1 := U1RXREG; by ik1 := Uart1_Read_Char; all is ok , still do not see why however. On P30 never had this issue with exactly the same code.
Anton
Another proud user of LV 24-33A Development System and mikroPascal PRO for dsPIC :)
PortA not working? Add CMCON := 7; PortD not working? Add ADCON1 := 6;
To paste code on the forum, please use the [b] Code [/b] button !! ;)
PortA not working? Add CMCON := 7; PortD not working? Add ADCON1 := 6;
To paste code on the forum, please use the [b] Code [/b] button !! ;)
Anton,
you can imagine i did that and this already.
and my source results in : which does not work ok.
you can imagine i did that and this already.
Code: Select all
;irq_uart_p24.dpas,53 :: ik1 := Uart1_Read_Char;
$0274 $07FFC5 RCALL _uart1_read_char
$0276 $88C020 MOV W0, irq_uart_p24_ik1
$0200 $ _uart1_read_char:
$0200 $FA0002 LNK #2
;__Lib_Uart1_p24_p33.dpas,185 ::
;__Lib_Uart1_p24_p33.dpas,186 ::
$0202 $801130 MOV U1RXREG, W0
$0204 $780F00 MOV W0, [W14]
$0206 $ __Lib_Uart1_p24_p33_L_65:
;__Lib_Uart1_p24_p33.dpas,187 ::
$0206 $78001E MOV [W14], W0
$0208 $ L_end__uart1_read_char:
$0208 $FA8000 ULNK
$020A $060000 RETURN
Code: Select all
;irq_uart_p24.dpas,51 :: ik1 := U1RXREG; // fetch character
$0268 $801130 MOV U1RXREG, W0
$026A $88C020 MOV W0, irq_uart_p24_ik1
Au royaume des aveugles, les borgnes sont rois.
Hi, this is the asm output
I don't see why shouldn't work but it doesn't.
Anton
Code: Select all
$13C4 $ _uart1_read_char:
$13C4 $FA0002 LNK #2
;__Lib_Uart1_p24_p33.dpas,185 ::
;__Lib_Uart1_p24_p33.dpas,186 ::
$13C6 $801130 MOV U1RXREG, W0
$13C8 $780F00 MOV W0, [W14]
$13CA $ __Lib_Uart1_p24_p33_L_65:
;__Lib_Uart1_p24_p33.dpas,187 ::
$13CA $78001E MOV [W14], W0
$13CC $ L_end__uart1_read_char:
$13CC $FA8000 ULNK
$13CE $060000 RETURN
Code: Select all
ik1 := U1RXREG;
Anton
Another proud user of LV 24-33A Development System and mikroPascal PRO for dsPIC :)
PortA not working? Add CMCON := 7; PortD not working? Add ADCON1 := 6;
To paste code on the forum, please use the [b] Code [/b] button !! ;)
PortA not working? Add CMCON := 7; PortD not working? Add ADCON1 := 6;
To paste code on the forum, please use the [b] Code [/b] button !! ;)
Nothing special there:
Code: Select all
function Uart1_Read_Char : word;
begin
result := U1RXREG;
end;