[En-Nut-Discussion] Problems using PPP with HW handshake and with lcpin.c
Chris Gude
cg at tis-net.de
Thu Apr 24 11:11:33 CEST 2008
Hello all,
I´m using ethernut 2.1b and I want to establish a PPP-connection to a pc
via dect. So far I got everything to work, but I discovered a problem
with the AHDLC device driver("ahdlcavr.c") and with "lcpin.c".
The first thing is that the AHDLC-driver seems to support
hardware-handshake(RTS/CTS), but is it possible to change it
dynamically? Because the ctl function doens´t seem to change it when you
call it with UART_SETFLOWCONTROL and UART_HS_RTSCTS.
And since there is no possibility of changing or activiating the
flowcontrol in the configurator, as it is possible for USART, I just
changed the source code and added the missing defines(UART0_CTS_BIT,
...). But then I realised that it didn´t work anymore.
The problem is, that in AhdlcAvrInit() a "AVR UART transmit interrupt
handler"(CtsXInterrupt) was registered, which changed the triggering
from falling edge to low level triggering(register EICR). As I don´t
know why this is done, I just changed it back after the registration and
then it works perfect.
But why is this done? Is there any reason why it should be low level
triggering instead of falling edge?
Here is the code I´m talking about:
*(ahdlcavr.c)
#ifdef UART0_CTS_BIT
sbi(UART0_CTS_PORT, UART0_CTS_BIT);
cbi(UART0_CTS_DDR, UART0_CTS_BIT);
#if UART0_CTS_BIT == 4
sbi(EICR, 1);
#elif UART0_CTS_BIT == 5
sbi(EICR, 3);
#elif UART0_CTS_BIT == 6
sbi(EICR, 5);
#elif UART0_CTS_BIT == 7
sbi(EICR, 7);
#endif
#endif
...
#ifdef UART0_CTS_BIT
else if (NutRegisterIrqHandler(&UART0_CTS_SIGNAL, Cts0Interrupt,
dev))
**...*
whereas UART0_CTS_SIGNAL is defined as sig_INTERRUPT7. So
AvrInterrupt7Ctl gets called with cmd=NUT_IRQCTL_INIT:
*(ih_int7.c)
static int AvrInterrupt7Ctl(int cmd, void *param)
{
int rc = 0;
u_int *ival = (u_int *) param;
int enabled = bit_is_set(EIMSK, INT7);
u_char bval;
/* Disable interrupt. */
cbi(EIMSK, INT7);
switch (cmd) {
case NUT_IRQCTL_INIT:
/* Initialize to low level triggered. */
cbi(EICR, ISC70);
cbi(EICR, ISC71);
case NUT_IRQCTL_CLEAR:
/* Clear any pending interrupt. */
outb(EIFR, _BV(INTF7));
break;
...
*The next and more severe problem appeared as I wanted to connect the
ethernut-board via ppp to the pc. I had established a ppp-connection
before with a GPRS-modem and it worked good. But as I tried to do it
with the pc it got stock in an endless loop in "lcpin.c".
*(lcpin.c)*
*if (len) {
if (xcpr != xcpo) {
xcpr->xcpo_type = xcpo->xcpo_type;
xcpr->xcpo_len = len;
for (i = 0; i < len - 2; i++)
/* bug fix by Michel Hendriks. Thanks! */
xcpr->xcpo_.uc[i] = xcpo->xcpo_.uc[i];
}
xcpr = (XCPOPT *) ((char *) xcpr + len);
xcps += len;
}
xcpl -= xcpo->xcpo_len;
xcpo = (XCPOPT *) ((char *) xcpo + xcpo->xcpo_len);
*
With Wireshark I could see, that the pc sends me an ppp-option, which is
called "Multilink endpoint discriminator". It has a size of 23Bytes and
is rejected by this function. But the thing is, that the space between
the pointers xcpr and xcpo is not big enough(only 21Bytes) and the type
and the length of xcpo are erased. But because the length is used
afterwards to decrement xcpl, the while loop never ends.
I assume that the easiest way to solve this is by saving the length and
using it instead of xcpo->xcpo_len, or? For me it works fine.
Thanks in advance,
Chris
More information about the En-Nut-Discussion
mailing list