[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