Forum: Mikrocontroller und Digitale Elektronik TCP/IP XMC4500 Relax Kit


von Peter L. (dermitdemwolftanzt)


Angehängte Dateien:

Lesenswert?

Moin Moin,

ich möchte gerne mein XMC4500 relax kit per Ethernet mit einem 
Messinstrument verbinden. klappt soweit auch ganz gut.. Das Problem ist 
nur, wenn ich die Verbindung aufbaue und der laser bestätigt mit dem 
ersten ack, macht das Board danach nichts mehr. Quellcode befindet sich 
unten und die wireshark datei im Anhang..

Vielen dank für mögliche Lösungsansätze

#include <DAVE3.h>      //Declarations from DAVE3 Code Generation 
(includes SFR declaration)
#include <string.h>

/*Test LED */
#define LED1 IO004_Handle0

void delay(long unsigned int i)
{
  while(i--)
  {
    __NOP();
  }
}

enum {
    LASER_STATUS_UNKNOWN = 0,
    LASER_STATUS_CONNECTING,
    LASER_STATUS_CONNECTED,
    LASER_STATUS_VV_SENT,
    LASER_STATUS_VV_RECEIVED,
    LASER_STATUS_DISTANCE_QUERY_SENT,
    LASER_STATUS_DISTANCE_QUERY_RECEIVED,

    LASER_STATUS_CONNECTION_CLOSED
};

int laser_status = LASER_STATUS_UNKNOWN;


// zentrale stelle un state-changes im programm-fluss zu kontrollieren 
u. evtl. zu dokumentieren
void setLaserStatus(int new_state)
{
    int old_state = new_state;

    if (old_state != new_state)
    {
       // toggle LED ?
       // printf ("Laser state change %d -> %d\n", old_state, 
new_state);
       laser_status = new_state;
    }
}


// send query-string to TCP connection
err_t sendLaserQuery(struct tcp_pcb * tpcb, char * laserQuery)
{
  err_t error;
    struct pbuf *pb;
    int queryLen;
    int bufspace = tcp_sndbuf(tpcb);

    if (bufspace < strlen(laserQuery))
    {
        // printf ("TCP sndbuf insufficient space (%d)\n", bufspace);
        tcp_close(tpcb);
        return ERR_MEM;
    }

    queryLen = strlen(laserQuery);
    pb = pbuf_alloc(PBUF_TRANSPORT, queryLen, PBUF_REF);
    memcpy(pb->payload, laserQuery, queryLen);
    pb->len = pb->tot_len = queryLen;

    // write data to TCP socket
    error = tcp_write(tpcb, pb->payload, pb->len, queryLen);
    if (error != ERR_OK) {
        return error;
    }

    // force data to be sent out
    error = tcp_output(tpcb);
    if (error != ERR_OK) {
        return error;
    }

    return ERR_OK;
}


// called by lwip to inidicate TCP connection is established (3way 
handshake is SYN, SYN-ACK, ACK, ...)
err_t laserConnect(void * arg, struct tcp_pcb * tpcb, err_t err)
{
    err_t error;
    setLaserStatus(LASER_STATUS_CONNECTED);

    error = sendLaserQuery(tpcb, "VV\r\n");
    if (error == ERR_OK) {
      setLaserStatus(LASER_STATUS_VV_SENT);
    }
    return error;
}


// called by lwip to inidicate incoming laser data
err_t laserReceive(void * arg, struct tcp_pcb * tpcb, struct pbuf * p, 
err_t err)
{
    err_t error = ERR_OK;

    switch (laser_status) {
        case LASER_STATUS_VV_SENT:
           // @TODO parse/analyse/display VV info (p->payload / p->len)
           // send distance query
           error = sendLaserQuery(tpcb, "WTF-DD-ETC-PP\r\n");
           if (error == ERR_OK) {
             setLaserStatus(LASER_STATUS_DISTANCE_QUERY_SENT);
           }
           break;

        case LASER_STATUS_DISTANCE_QUERY_SENT:
           // @TODO parse/analyse/display/store Distance info 
(p->payload / p->len)

           // @TODO set timer to send text query, or close connection

           /*
           error = sendLaserQuery(tpcb, "WTF-DD-ETC-PP\r\n");
           if (error == ERR_OK) {
               setlaserStatus(LASER_STATUS_DISTANCE_QUERY_SEND);
           }
           */
           break;
    }

    // mark data as process aka disposable by lwip
    tcp_recved(tpcb, p->tot_len);
    return error;
}


// callback to poll laser tcp connection
err_t laserPoll(void * arg, struct tcp_pcb * tpcb)
{
    // @TODO close connection on idle connection
    // z.B: wenn der Laser einfach nicht mehr antwortet, etc...
  return ERR_OK;
}


// callback on tcp error
void laserError(void * arg, err_t err)
{
    // @TODO handle error? wtf!
}


// close tcp connection
void closeLaserConnection(struct tcp_pcb *tpcb)
{
    tcp_arg(tpcb, NULL);
    tcp_sent(tpcb, NULL);
    tcp_recv(tpcb, NULL);
    tcp_close(tpcb);
    setLaserStatus(LASER_STATUS_CONNECTION_CLOSED);
}


/*
 * - establish TCP connection
 * - register receive/poll/error callbacks
 */
struct tcp_pcb * laserInitTCP(struct ip_addr * laserIp, uint16_t 
laserPort)
{
  err_t error;
    struct tcp_pcb * pcb = NULL;

    setLaserStatus(LASER_STATUS_CONNECTING);

    pcb = tcp_new();

    error = tcp_bind(pcb, IP_ADDR_ANY, 55555);
    error = tcp_connect(pcb, laserIp, laserPort, laserConnect);

    tcp_recv(pcb, laserReceive);
    tcp_poll(pcb, laserPoll, 1);
    tcp_err(pcb,  laserError);

    return pcb;
}


int main(void)
{
    struct ip_addr laserIp;
    struct tcp_pcb * laser_pcb = NULL;

    // do it! ;)
    DAVE_Init();
    lwIPStack_init();

    // establish TCP connetion
    IP4_ADDR(&laserIp, 192,168,0,10);
    laser_pcb = laserInitTCP(&laserIp, 10940);

    while (laser_status != LASER_STATUS_CONNECTION_CLOSED)
    {
        // app still running, do idle in main task
    }

    return 0;
}

von Little B. (lil-b)


Lesenswert?

Ich hab so das gefühl, dass eine leere main-loop hier falsch ist.
LWIP benötigt sicher eine polling-funktion. Die rufst du nur einmal beim 
Initialisieren deines Sockets auf, aber sonst nicht mehr.

Check das mal!

von Peter L. (dermitdemwolftanzt)


Lesenswert?

@Little Basdart
So jetzt habe ich das folgende geändert...

struct tcp_pcb * laserInitTCP(struct ip_addr * laserIp, uint16_t 
laserPort)
{
  err_t error;
    struct tcp_pcb * pcb = NULL;

    setLaserStatus(LASER_STATUS_CONNECTING);

    pcb = tcp_new();

    error = tcp_bind(pcb, IP_ADDR_ANY, 55555); // 'bind' brauchen wir 
nicht, oder doch!?
    error = tcp_connect(pcb, laserIp, laserPort, laserConnect);


    tcp_recv(pcb, laserReceive);
    while(laser_status != LASER_STATUS_VV_SENT)
    {
    tcp_poll(pcb, laserPoll, 1);
    }
    tcp_err(pcb,  laserError);


}

meintest du das in der Art? hier pollt er jetzt so lange bis sich der 
Laser_Status geändert hat und das VV gesendet wurden...

von Peter L. (dermitdemwolftanzt)


Lesenswert?

ich habe folgenden beispielcode gefunden:

int main(void)
{
 /* configure Ethernet (GPIOs, clocks, MAC, DMA) */
 ETH_BSP_Config();
 /* Initilaize the LwIP stack */
 LwIP_Init();
 /* tcp echo server Init */
 tcp_echoserver_init();
 /* Infinite loop */
 while (1)
 {
 /* check if any packet received */
 if (ETH_CheckFrameReceived())
 {
 /* process received Ethernet packet */
 LwIP_Pkt_Handle();
 }
 /* handle periodic timers for LwIP */
 LwIP_Periodic_Handle(LocalTime);
 }
}


das ist allerdings für ein anderes board.

Ich brauche etwas in der while schleie main funktion was dem lwIP stack 
Porzessorzeit gibt damit dieser auch was macht.. weiß da einer wie das 
auf dem XMC4500 geht?

von Peter L. (dermitdemwolftanzt)


Lesenswert?

up

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.