無linux筆記4

linux 內(nèi)核定時(shí)器timer_list用法
作者 codercjg30 十月 2015, 2:27 下午

實(shí)現(xiàn)了一個(gè)秒定時(shí)器涌攻,每秒更新計(jì)數(shù)值。驅(qū)動(dòng)源碼second.c:

include <linux/init.h>#include <linux/module.h>#include <linux/fs.h>#include <linux/miscdevice.h>#include <linux/types.h>#include <linux/timer.h>#include <asm/atomic.h>#include <asm/uaccess.h>struct second_t{ atomic_t counter; struct timer_list timer;};struct second_t second;void second_timer_handler(unsigned long arg){ mod_timer(&second.timer, jiffies+HZ); atomic_inc(&second.counter); printk("second timer: %d\n", atomic_read(&second.counter));}int second_open(struct inode *inode, struct file *filp){ init_timer(&second.timer); second.timer.expires = jiffies + HZ; second.timer.function = second_timer_handler; atomic_set(&second.counter, 0); add_timer(&second.timer); return 0;}int second_release(struct inode *inode, struct file *filp){ del_timer(&second.timer); return 0;}static ssize_t second_read(struct file *filp, char __user *buf, size_t count, loff_t ppos){ int counter = atomic_read(&second.counter); if(put_user(counter, (int)buf)){ return -EFAULT; }else { return sizeof(int); }}static struct file_operations fops = { .owner = THIS_MODULE, .open = second_open, .release = second_release, .read = second_read,};static struct miscdevice misc = { .minor = MISC_DYNAMIC_MINOR, .name = "second", .fops = &fops,};static int __init second_init(void){ misc_register(&misc); return 0;}static void __exit second_exit(void){ misc_deregister(&misc);}MODULE_AUTHOR("codercjg");MODULE_LICENSE("Dual BSD/GPL");module_init(second_init);module_exit(second_exit);

測試源碼secondapp.c:

include <sys/types.h>#include <unistd.h>#include <fcntl.h>#include <stdlib.h>#include <errno.h>#include <stdio.h>int main(int argc, char *argv[]){ int second; int fd = open("/dev/second", O_RDONLY); if(fd<0){ perror("open"); exit(errno); } while(1){ read(fd, &second, 4); printf("%d\n", second); sleep(1); } close(fd); return 0;}

分類: Linux驅(qū)動(dòng) | 評(píng)論

mini2440 led驅(qū)動(dòng)
作者 codercjg28 十月 2015, 8:42 下午

datasheet上外設(shè)寄存器地址都是物理地址铃诬,而cpu訪問的是虛擬地址性含,通過mmu映射到實(shí)際物理地址。
在驅(qū)動(dòng)中要想讀寫外設(shè)寄存器首先要找到物理地址對應(yīng)的虛擬地址捉偏,這通過io內(nèi)存函數(shù)request_mem_region()和ioremap()實(shí)現(xiàn)物理地址到虛擬地址的轉(zhuǎn)換鸳君。
request_mem_region()用于判斷物理地址是否被占用农渊,ioremap()用于創(chuàng)建頁表實(shí)現(xiàn)物理地址到虛擬地址的映射。
led1 led2 led3 led4 分別對應(yīng)io口GPB5 GPB6 GPB7 GPB8或颊,需要設(shè)置寄存器GPBCON設(shè)置它們?yōu)檩敵鲈椅桑O(shè)置GPBUP禁用上拉電阻传于。
GPBDAT寄存器可用于點(diǎn)亮和熄滅led。GPB IO口寄存器物理基地址為0×56000010批糟,共占16字節(jié)格了。
驅(qū)動(dòng)源碼ledstest.c:
/* * for mini2440 board leds, GPB5-led1 GPB6-led2 GPB7-led3 GPB8-led4 */#include <linux/init.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/miscdevice.h>#include <linux/fs.h>#include <linux/ioport.h>#include <asm/io.h>MODULE_AUTHOR("codercjg");MODULE_LICENSE("Dual BSD/GPL");#define GPB_REG_BASE 0x56000010#define GPB_REG_SIZE 16 static void __iomem *gpbbase;static volatile unsigned int *gpbcon, *gpbdata, *gpbup;static struct resource *iomem; int leds_ioctl(struct inode *node, struct file *file, unsigned int cmd, unsigned long arg){ switch (cmd) { case 0: if (arg == 1) { *gpbdata |= (1 << 5); } else if (arg == 2) { *gpbdata |= (1 << 6); } else if (arg == 3) { *gpbdata |= (1 << 7); } else if (arg == 4) { *gpbdata |= (1 << 8); } else { return -EINVAL; } break; case 1: if (arg == 1) { gpbdata &= ~(1 << 5); } else if (arg == 2) { gpbdata &= ~(1 << 6); } else if (arg == 3) { gpbdata &= ~(1 << 7); } else if (arg == 4) { gpbdata &= ~(1 << 8); } else { return -EINVAL; } break; default: return -EINVAL; } return 0;}static struct file_operations fops = { .owner = THIS_MODULE, .ioctl= leds_ioctl,};static struct miscdevice misc = { .minor = MISC_DYNAMIC_MINOR, .name = "ledstest", .fops = &fops,}; static int leds_driver_init(void){ iomem = request_mem_region(GPB_REG_BASE, GPB_REG_SIZE, "leds"); if (iomem) { gpbbase = ioremap(GPB_REG_BASE, GPB_REG_SIZE); gpbcon = (unsigned int)gpbbase; gpbdata = (unsigned int)(gpbbase + 4); gpbup = (unsigned int)(gpbbase + 8); / config GPB5 GPB6 GPB7 GPB8 output */ *gpbcon &= ~(3 << 10) & ~(3 << 12) & ~(3 << 14) & ~(3 << 16); gpbcon |= (1 << 10) | (1 << 12) | (1 << 14) | (1 << 16); / disable pullup */ gpbup |= (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8); / leds off */ *gpbdata |= (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8); misc_register(&misc); printk("leds_driver_init\n"); return 0; } else { return -EBUSY; }}static void leds_driver_exit(void){ if (iomem) { misc_deregister(&misc); iounmap(gpbbase); release_mem_region(GPB_REG_BASE, GPB_REG_SIZE); iomem = NULL; } printk("leds_driver_exit\n");}module_init(leds_driver_init);module_exit(leds_driver_exit);
測試代碼ledsapp.c:

include <stdio.h>

include <sys/types.h>

include <sys/ioctl.h>

include <unistd.h>

include <fcntl.h>

include <stdlib.h>

int main(int argc, char *argv[])
{
int fd;
int cmd;
int no;
if(argc != 3 || sscanf(argv[1], "%d", &cmd) !=1 || sscanf(argv[2], "%d", &no) !=1){
perror("usage: ledsapp x x");
exit(1);
}
fd = open("/dev/ledstest", O_RDWR);
if(fd < 0){
perror("open /dev/ledstest");
exit(1);
}
if(ioctl(fd, cmd, no) < 0){
perror("ioctl");
exit(1);
}
close(fd);
return 0;
}

驅(qū)動(dòng)名為leds時(shí)會(huì)沖突,所以改成ledstest徽鼎。
加載led驅(qū)動(dòng)后盛末,發(fā)現(xiàn)還是流水燈。要想用ledapp控制它否淤,就得先停止控制led的程序悄但。
/etc/rc.d/init.d/leds stop
之后ledsapp 1 1就可以點(diǎn)亮led1, ledsapp 0 1就可以熄滅led1石抡。

分類: Linux驅(qū)動(dòng) | 評(píng)論

gprs使用外置協(xié)議棧lwip
作者 codercjg23 十月 2015, 4:53 下午

MG323 GPRS模塊檐嚣,內(nèi)置協(xié)議棧只支持TCP和UDP等上層協(xié)議,而我需要完成一個(gè)gprs ping 遠(yuǎn)程主機(jī)測延時(shí)的功能啰扛,所以需要一個(gè)外置協(xié)議棧來發(fā)送icmp ping request嚎京。一開始以為只要直接發(fā)送ip數(shù)據(jù)報(bào)就行了,后來發(fā)現(xiàn)還需要實(shí)現(xiàn)ppp隐解。因?yàn)樾枰猵pp,icmp和dns等功能鞍帝,偷懶采用了freertos+lwip1.3.2。
使用過程中走過的坑:
1.gprs的AT命令解析主要用到sscanf()和sprintf()煞茫,當(dāng)任務(wù)棧分配比較小時(shí)帕涌,這兩個(gè)函數(shù)很可能導(dǎo)致棧溢出。
2.lwip中用到動(dòng)態(tài)內(nèi)存分配時(shí)续徽,要注意下pbufalloc()和pbuffree()的使用蚓曼,發(fā)現(xiàn)當(dāng)ppp收到一個(gè)IP包后,會(huì)為它分配內(nèi)存钦扭,當(dāng)是tcp和udp時(shí)處理完成后都會(huì)釋放該內(nèi)存纫版,而當(dāng)識(shí)別出是icmp報(bào)文,做了相關(guān)處理后居然沒有釋放土全,直接導(dǎo)致內(nèi)存泄漏捎琐。解決方法是在raw.c 中rawinput()里加上一句pbuffree()。
/* receive callback function available /if (pcb->recv != NULL) {/ the receive callback function did not eat the packet? /if (pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src)) != 0) {* pbuf_free(p); / add by cjg, to fix ping memory leak bug // receive function ate the packet /p = NULL;eaten = 1;
3.當(dāng)發(fā)生內(nèi)存泄露后裹匙,最終會(huì)導(dǎo)致分配內(nèi)存失敗,此時(shí)調(diào)用memcpy()末秃,傳入空指針概页,直接導(dǎo)致訪存錯(cuò)誤。
4.創(chuàng)建lwip相關(guān)的任務(wù)要調(diào)用sys
thread
new()因?yàn)樗鼤?huì)同時(shí)創(chuàng)建一個(gè)定時(shí)器练慕,某些時(shí)刻會(huì)檢查惰匙,要是你不小心用到它而卻用xTaskCreate()創(chuàng)建的任務(wù)技掏,跑著跑著肯定出異常。
最后附一個(gè)流程:
撥號(hào)入網(wǎng):
gprssendcmd(“AT\r”);
gprssendcmd(“ATE0\r”);
gprssendcmd(“ATS0=0\r”);
gprssendcmd(“AT+CGDCONT=1,\”IP\”,\”CMNET\”\r”); /* 加入移動(dòng)網(wǎng)絡(luò)项鬼,移動(dòng)卡聯(lián)通卡都可以加入這個(gè)網(wǎng)絡(luò) /
gprs
sendcmd(“ATD99#\r”); /* 撥號(hào)上網(wǎng)/
之后不再發(fā)AT指令哑梳,而是用lwip ppp發(fā)數(shù)據(jù)了。
ppp獲取IP:
主要是為pppOpen()實(shí)現(xiàn)一個(gè)回調(diào)函數(shù)linkStatusCB()用于獲取ip和dns server等
pppInit();pppSetAuth(PPPAUTHTYPE_CHAP, NULL, NULL);pppOpen(fd, linkStatusCB, NULL);/
send lcp req to peer// ppp callback /void linkStatusCB(void ctx, int errCode, void arg){struct ppp_addrs addrs = arg;if (errCode == PPPERR_NONE) {/ connect ok. /GPRSDEBUG(("connected\n"));GPRSDEBUG(("ipaddr = %s ", inetntoa(addrs->our_ipaddr)));GPRSDEBUG(("netmask = %s ", inet_ntoa(addrs->netmask)));GPRSDEBUG(("dns1 = %s ", inet_ntoa(addrs->dns1)));GPRSDEBUG(("dns2 = %s \n", inet_ntoa(addrs->dns2)));pppaddrs = (struct ppp_addrs)arg;gprsstate = IP_GOT;} else {gprsstate = PPP_ERR;/* connect lost /GPRSDEBUG(("connection lost\n"));}}
dns解析:
主要是為dns
gethostbyname()實(shí)現(xiàn)一個(gè)回調(diào)函數(shù)dnsfound()用于解析成功時(shí)獲取IP地址
dns_init();dns_setserver(0, &pppaddrs.dns1); /
設(shè)置dns 服務(wù)器地址绘盟,由ppp獲得 /dnsresolve(hostname, &targetip); / 解析域名 // dns resolve callback /void dnsfound(const char name, struct ipaddr ipaddr, void callback_arg){if (!ipaddr) { / 解析成功時(shí)該值非空鸠真,解析失敗時(shí)該值為空/GPRSDEBUG(("dns resolve:%s failed\n", name));gprsstate = DNSRESOLVEDERR;} else {GPRSDEBUG(("dns resolve: %s===>%s\n", name, inet_ntoa(ipaddr)));dnsip = ipaddr;gprsstate = DNSRESOLVEDOK;}}/* dns resolve /errt dnsresolve(char hostname, struct ipaddr ip){errt err = dnsgethostbyname(hostname, ip, dns_found, NULL);switch (err) {case ERR_OK:GPRSDEBUG(("dns resolve: %s===>%s\n", hostname, inet_ntoa(ip)));dnsip = ip;gprsstate = DNSRESOLVEDOK;break;case ERR_INPROGRESS:/ need to udp ask, and then return result via callback function /GPRSDEBUG(("dns resolving...\n"));gprsstate = DNS_RESOLVING;break;default:GPRSDEBUG(("dns resolve error\n"));gprsstate = DNSRESOLVED*ERR;break;}return err;}
接下來就是ping、tcp和udp等應(yīng)用了龄毡。

分類: lwip協(xié)議棧 | 2個(gè)評(píng)論

lwip dns
作者 codercjg16 十月 2015, 10:28 上午

lwIP DNS OverviewThe lwIP stack provides a basic DNS client (introduced in 1.3.0) to allow other applications to resolve host names to addresses using the DNS (Domain Name System) protocol. LWIP_DNS must be #defined in lwipopts.h to a nonzero value to enable DNS support in your lwIP platform.
if DHCP is used in conjunction with the lwIP DNS client, DNS will automatically be configured to use the offered DNS server (if the DHCP server offers one).
Application DNS requests with Raw/Native APIRaw API applications can use the dns_gethostbyname() function to request a lookup, and specify a callback function to notify the application when the lookup is complete. As you can see from its header bellow, this function will return immediately. If the requested address is already known, it will be returned via the passed argument pointer. If a request to a DNS server needs to be made, your callback function will be called when it has finshed.

  • err_t* dns_gethostbyname(const char hostname, struct ip_addr addr, dns_found_callback found, void callback_arg) Resolve a hostname (string) into an IP address.* NON-BLOCKING callback version for use with raw API!!!** Returns immediately with one of err_t return codes:* – ERR_OK if hostname is a valid IP address string or the host* name is already in the local names table.* – ERR_INPROGRESS enqueue a request to be sent to the DNS server* for resolution if no errors are present.** @param hostname the hostname that is to be queried* @param addr pointer to a struct ip_addr where to store the address if it is already* cached in the dns_table (only valid if ERR_OK is returned!)* @param found a callback function to be called on success, failure or timeout (only if* ERR_INPROGRESS is returned!)* @param callback_arg argument to pass to the callback function* callback function and argument defined as follows:* A function of this type must be implemented by the application using the DNS resolver.* @param name pointer to the name that was looked up.* @param ipaddr pointer to a struct ip_addr containing the IP address of the hostname,* or NULL if the name could not be found (or on any other error).* @param callback_arg a user-specified callback argument passed to dns_gethostbyname:** typedef void (*dns_found_callback)(const char *name, struct ip_addr *ipaddr, void *callback_arg);
    A sample call:
    struct ip_addr resolved;switch(dns_gethostbyname("www.lwIP.com", &resolved, smtp_serverFound, NULL)){case ERR_OK:// numeric or cached, returned in resolvedsmtp.serverIP.addr = resolved->addr;smtp.state = SMTP_NAME_RESOLVED;break;case ERR_INPROGRESS:// need to ask, will return data via callbacksmtp.state = SMTP_NAME_RESOLVING;break;default:// bad arguments in function callbreak;}A sample DNS callback function:void smtp_serverFound(const char *name, struct ip_addr *ipaddr, void *arg){if ((ipaddr) && (ipaddr->addr)){smtp.serverIP.addr = ipaddr->addr;smtp.state = SMTP_NAME_RESOLVED;if (smtp_connect() == ERR_OK)return;smtp.lastError = SMTP_CONNECT_FAILED;}elsesmtp.lastError = SMTP_UNKNOWN_HOST;smtp.state = SMTP_IDLE;}
    Application DNS requests with Netconn APIerr_t netconn_gethostbyname(const char *name, ip_addr_t *addr)
    See also netconn_gethostbyname().
    Application DNS requests with Sockets APIFor socket based apps, a gethostbyname() wrapper function is provided that blocks during the lookup if necessary. Use the following functions:
    gethostbyname() – standard implementation, blocks if necessary until lookup complete or failsgethostbyname_r() – thread-safe version of gethostbyname (separate buffer for each invokation)
    http://lwip.wikia.com/wiki/DNS

分類: lwip協(xié)議棧 | 評(píng)論

MINI2440 開發(fā)環(huán)境搭建
作者 codercjg13 十月 2015, 10:19 下午

從搭好交叉編譯環(huán)境到在板子上跑第一個(gè)hello driver吠卷,其中的波折真是一言難盡。
其中要注意的地方有:
1.重新編譯光盤里的linux內(nèi)核源碼生成zImage, 并下載到板子上沦零。否則編譯出的linux 驅(qū)動(dòng)可能會(huì)和板子上跑的內(nèi)核不匹配祭隔,
從而導(dǎo)致insmod時(shí)出現(xiàn)莫名其妙的錯(cuò)誤。
make distcelan
cp config_mini2440_w35 .config
make zImage
2.下載zImage到板子上時(shí)路操,安裝usb驅(qū)動(dòng)折騰了好久疾渴。其實(shí)我的板子從Nor Flash啟動(dòng)時(shí)跑的是superboot, 不是supervivi,只需要
安裝光盤里的MiniTools-USB就可以。
3.然后用minitool下載之前編譯內(nèi)核生成的zImage
4.最后掛載nfs屯仗,我在vmware Ubuntu虛擬機(jī)里開發(fā)搞坝,省得下載編譯后的驅(qū)動(dòng)麻煩
ifconfig eth0 192.168.3.200 broadcast 192.168.3.255 netmask 255.255.255.0
mkdir /mnt/nfs
mount -t nfs -o nolock 192.168.3.102:/home/user/nfs /mnt/nfs
之后就可以直接insmod /mnt/nfs下的hello driver了。

分類: Linux驅(qū)動(dòng) | 評(píng)論

lwip ppp
作者 codercjg13 十月 2015, 11:04 上午

PPP from an application perspectiveThere are two ways to use lwIP with PPP support. Either PPPoE (PPP over Ethernet) or PPP-over-serial. lwIP supports being run in a threaded environment, where ppp is a separate task that runs alongside the main lwIP thread. lwIP also supports being run from a main loop, with lwIP functions being called from the main loop.****
PPP over serialTo setup a PPP connection over a serial link you will need to provide the Serial IO functions.Both the thread environment and a main loop require implemented sio_write() to be implemented./*** Writes to the serial device.** @param fd serial device handle* @param data pointer to data to send* @param len length (in bytes) of data to send* @return number of bytes actually sent** @note This function will block until all data can be sent./u32_t sio_write(sio_fd_t fd, u8_t data, u32_t len);
With Task SupportIn addition to sio_write(), sio_read(), sio_read_abort() and the linkStatusCB are required to be implemented by you. The first 2 functions are statically linked, while the last function is defined through a function pointer (so the name can be different, and could be dynamically created as well).The function sio_read() is called from the pppInputThread, repeatedly. It blocks until it fills the requested buffer size or times-out, reading data from the serial device. It must abort itself if there is a call to sio_read_abort(). The soft link between sio_read and sio_read_abort must be implemented by you, either via a global variable, RTOS event, etc. The timeout should be relatively small, just large enough so that data is actually buffered in more than 1 byte chunks but small enough to make the ppp stack responsive. A timeout of about 2 ms is reasonable./
* Reads from the serial device.** @param fd serial device handle* @param data pointer to data buffer for receiving* @param len maximum length (in bytes) of data to receive* @return number of bytes actually received – may be 0 if aborted by sio_read_abort/u32_t sio_read(sio_fd_t fd, u8_t data, u32_t len);The sio_read_abort() function must cause the sio_read command to exit immediately. This command is called by the tcpip_thread, mostly when ending a PPP session (terminated, link down or explicit close)./ Aborts a blocking sio_read() call.** @param fd serial device handle*/void sio_read_abort(sio_fd_t fd);****
**Required callback function *The callbackvoid (linkStatusCB)(void *ctx, int errCode, void arg)is called under the following events:Link Terminated. errCode is nonzero, arg is null.sifup (Interface Up).errCode is PPPERR_NONE, and arg is pointer to ppp_addrs structure, which contains IP address.sifdown (Interace Down). errCode is PPPERR_CONNECT, and arg is null.The errCode can be one of the following#define PPPERR_NONE 0 / No error. /#define PPPERR_PARAM -1 / Invalid parameter. /#define PPPERR_OPEN -2 / Unable to open PPP session. /#define PPPERR_DEVICE -3 / Invalid I/O device for PPP. /#define PPPERR_ALLOC -4 / Unable to allocate resources. /#define PPPERR_USER -5 / User interrupt. /#define PPPERR_CONNECT -6 / Connection lost. /#define PPPERR_AUTHFAIL -7 / Failed authentication challenge. /#define PPPERR_PROTOCOL -8 / Failed to meet protocol. /The ctx pointer is an optional user defined pointer that is defined as an argument in the call to pppOverSerialOpen, which can point to user defined data.
With no Task SupportYou need to receive the serial data in your main thread, then from your main thread callpppos_input(int pd, u_char
data, int len);****
Example Task Application codeThis example shows the initialization of the TCP and PPP threads. It assumes that you will do your socket handling in the context of the main() function.

include "ppp/ppp.h"#define PPP_SERIAL_PORT 0static void linkStatusCB(void* ctx, int errCode, void* arg);int main(void) { int connected = 0; int setup = 0; int pd; const char username = "myuser"; const char password = "mypassword"; / initialise lwIP. This creates a new thread, tcpip_thread, that * communicates with the pppInputThread (see below) / tcpip_init(tcpip_init_done, &setup); while (!setup) { sleep(1); } / initialise PPP. This needs to be done only once after boot up, to * initialize global variables, etc. / pppInit(); / set the method of authentication. Use PPPAUTHTYPE_PAP, or * PPPAUTHTYPE_CHAP for more security . * If this is not called, the default is PPPAUTHTYPE_NONE. / pppSetAuth(PPPAUTHTYPE_ANY, username, password); / call the board specific function that will open the specific serial * port hardware, for example, configuring pins, I/Os, UART, USART, * clocks, etc. This function is not part of lwip or ppp. You need to * supply this or find an example for your hardware. / OpenMySerialPortOrUART(PPP_SERIAL_PORT, ...); / call the board specific function that will connect to the modem, * ie dialing phone numbers, sending configuration AT commands, etc. * This function is not part of lwip or ppp. You need to supply this if (DialOutMyModem(PPP_SERIAL_PORT, ...) != 0) { printf("can't dial out"); } else { /* Open a new PPP connection using the given I/O device. * This initializes the PPP control block but does not * attempt to negotiate the LCP session. * Return a new PPP connection descriptor on success or * an error code (negative) on failure. * This call creates one new thread per call, to service the particular * serial port, serviced by the pppInputThread function. / pd = pppOverSerialOpen(PPP_SERIAL_PORT, linkStatusCB, &connected); if (pd >= 0) { // the thread was successfully started. while (!connected && timeout(60 seconds)) { sleep(100 ms); } if (!timeout) { // We are connected on lwIP over PPP! while (working) { / create some socket connections, * do writes and reads on the sockets, close them, etc / } } / calling pppClose will end the pppInputThread associated with pd*/ pppClose(pd); } // shut down the rest of your hardware.}static void tcpip_init_done(void *arg){ if (arg) { *((bool *)arg) = 1; }}static void linkStatusCB(void *ctx, int errCode, void *arg) { //DTRACE("ctx = 0x%04X, errCode = %d arg = 0x%04X", ctx, errCode, arg); int *connected = (int *) ctx; struct ppp_addrs addrs = arg; if (errCode == PPPERR_NONE) { / We are connected */ connected = 1; syslog(LOG_DEBUG, "ip_addr = %s", inet_ntoa(addrs->our_ipaddr)); syslog(LOG_DEBUG, "netmask = %s", inet_ntoa(addrs->netmask)); syslog(LOG_DEBUG, "dns1 = %s", inet_ntoa(addrs->dns1)); syslog(LOG_DEBUG, "dns2 = %s", inet_ntoa(addrs->dns2)); } else { / We have lost connection */ }}

**Debug Support **Add this to lwipopts.h#define PPP_THREAD_NAME “ppp”#define PPP_THREAD_STACKSIZE 200#define PPP_THREAD_PRIO 2#define LWIP_DEBUG 1#define PPP_DEBUG LWIP_DBG_ONPPP packets all start and end with 0x7E. If you don’t see these, something is wrong with your low level driverFurther packet debugging hints are here: http://lists.nongnu.org/archive/html/lwip-users/2011-06/msg00036.htmlIf you have trouble with the RTOS crashing on pppClose, look here :
http://lists.gnu.org/archive/html/lwip-users/2012-02/msg00124.html
quote from: http://lwip.wikia.com/wiki/PPP

分類: lwip協(xié)議棧 | 評(píng)論

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末祭钉,一起剝皮案震驚了整個(gè)濱河市瞄沙,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌慌核,老刑警劉巖距境,帶你破解...
    沈念sama閱讀 221,695評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異垮卓,居然都是意外死亡垫桂,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門粟按,熙熙樓的掌柜王于貴愁眉苦臉地迎上來诬滩,“玉大人,你說我怎么就攤上這事灭将√勰瘢” “怎么了?”我有些...
    開封第一講書人閱讀 168,130評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵庙曙,是天一觀的道長空镜。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么吴攒? 我笑而不...
    開封第一講書人閱讀 59,648評(píng)論 1 297
  • 正文 為了忘掉前任张抄,我火速辦了婚禮,結(jié)果婚禮上洼怔,老公的妹妹穿的比我還像新娘署惯。我一直安慰自己,他們只是感情好镣隶,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評(píng)論 6 397
  • 文/花漫 我一把揭開白布极谊。 她就那樣靜靜地躺著,像睡著了一般矾缓。 火紅的嫁衣襯著肌膚如雪怀酷。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,268評(píng)論 1 309
  • 那天嗜闻,我揣著相機(jī)與錄音蜕依,去河邊找鬼。 笑死琉雳,一個(gè)胖子當(dāng)著我的面吹牛样眠,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播翠肘,決...
    沈念sama閱讀 40,835評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼檐束,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了束倍?” 一聲冷哼從身側(cè)響起被丧,我...
    開封第一講書人閱讀 39,740評(píng)論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎绪妹,沒想到半個(gè)月后甥桂,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,286評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡邮旷,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評(píng)論 3 340
  • 正文 我和宋清朗相戀三年黄选,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片婶肩。...
    茶點(diǎn)故事閱讀 40,505評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡办陷,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出律歼,到底是詐尸還是另有隱情民镜,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布险毁,位于F島的核電站殃恒,受9級(jí)特大地震影響植旧,放射性物質(zhì)發(fā)生泄漏辱揭。R本人自食惡果不足惜离唐,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望问窃。 院中可真熱鬧亥鬓,春花似錦、人聲如沸域庇。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽听皿。三九已至熟呛,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間尉姨,已是汗流浹背庵朝。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評(píng)論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留又厉,地道東北人九府。 一個(gè)月前我還...
    沈念sama閱讀 48,921評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像覆致,于是被迫代替她去往敵國和親侄旬。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容