2013年04月15日

折腾了一个星期,过程整理下放上来,希望能有些帮助。本来这事关意义就在于享受麻烦的过程, 要不直接找个线程的下载下来不就行了。

环境:

Fedora18 gcc4.7.2 glibc2.17 binutils2.23 linux2.6.38

在fedora上先要安装几个包,还要删除一个:

yum erase audit

yum install gcc

yum install mpc

yum install mpfr-devel

yum install ncurses-devel

yum install autoconf

yum install textinfo

然后下载这几个源码包:

mpc-0.8.1.tar.gz

gcc-4.7.2.tar.bz2

glibc-2.17.tar.bz2

binutils-2.23.tar.gz

linux-2.6.38.tar.gz

Gcc貌似4.x的版本编译gcc需要用到mpc mpfr gmp这些。Fedora单单没有mpc-devel这个包,所以要头文件还是要自己编译。

$tar zxvf mpc-0.8.1.tar.gz

$cd mpc-0.8

$mkdir mpc_install

$cd mpc_install

$../configure –prefix=/usr –with-gmp=/usr –with-mpfr=/usr

$make

$make install

 

现在开始编译toolchain,先要创建几个编译时放生成文件的目录,还要设置些环境变量。

 

crosstoolchain4.7.2

crosstoolchain4.7.2/build-tools

crosstoolchain4.7.2/kernel

crosstoolchain4.7.2/tools

crosstoolchain4.7.2/build-tools/build-binutils

crosstoolchain4.7.2/build-tools/build-boot-gcc

crosstoolchain4.7.2/build-tools/build-gcc

crosstoolchain4.7.2/build-tools/bulid-glibc

 

[uty@localhost crosstoolchain4.7.2]$ export PROJECT=crosstoolchain4.7.2

[uty@localhost crosstoolchain4.7.2]$ export PRJROOT=/home/uty/workplace/$PROJECT

[uty@localhost crosstoolchain4.7.2]$ export TARGET=arm-none-linux-gnueabi

[uty@localhost crosstoolchain4.7.2]$ export PREFIX=${PRJROOT}/tools

[uty@localhost crosstoolchain4.7.2]$ export TARGET_PREFIX=${PREFIX}/${TARGET}

[uty@localhost crosstoolchain4.7.2]$ export PATH=${PREFIX}/bin:${PATH}

这些事情还是挺重要的,目录一定要放对,要不编译的时候经常找不到.h .o lib什么的

 

编译binutils

Copy binutils-2.23.tar.gz to built-tools directory

[uty@localhost build-tools]$ tar zxvf binutils-2.23.tar.gz

[uty@localhost build-tools]$ cd build-binutils

[uty@localhost build-binutils]$ ../binutils-2.23/configure –target=$TARGET –prefix=$PREFIX

[uty@localhost build-binutils]$ make

[uty@localhost build-binutils]$ make install

设置内核头文件

Copy linux-2.6.38.tar.gz to kernel direcotry.

[uty@localhost kernel]$ tar zxvf linux-2.6.38.tar.gz

[uty@localhost kernel]$ cd linux-2.6.38/

[uty@localhost linux-2.6.38]$ make ARCH=arm CROSS_COMPILE=arm-linux- menuconfig

Select Exit and say YES to generate kernel headers.

[uty@localhost linux-2.6.38]$ make include/linux/version.h

CHK include/linux/version.h

UPD include/linux/version.h

[uty@localhost linux-2.6.38]$ mkdir -p $TARGET_PREFIX/include

[uty@localhost linux-2.6.38]$ cp -r include/linux/ $TARGET_PREFIX/include

[uty@localhost linux-2.6.38]$ cp -r arch/arm/include/asm/ $TARGET_PREFIX/include/asm

[uty@localhost linux-2.6.38]$ cp -r include/asm-generic/ $TARGET_PREFIX/include

编译bootstrap gcc

Copy glibc-2.17.tar.bz2 to build-tools directory.

[uty@localhost build-tools]$ tar jxvf gcc-4.7.2.tar.bz2

[uty@localhost build-tools]$ cd build-boot-gcc/

[uty@localhost build-boot-gcc]$ ../gcc-4.7.2/configure –target=$TARGET –prefix=$PREFIX –without-headers –with-newlib –enable-languages=c,c++ –with-gmp=/usr –with-mpfr=/usr –with-mpc=/usr –disable-libmudflap –disable-libssp –disable-libstdcxx-pch –disable-nls –disable-shared –disable-threads –disable-libgomp –disable-decimal-float –disable-libffi

[uty@localhost build-boot-gcc]$ make all-gcc

[uty@localhost build-boot-gcc]$ make install-gcc

[uty@localhost build-boot-gcc]$ make all-target-libgcc

[uty@localhost build-boot-gcc]$ make install-target-libgcc

编译glibc

Copy glibc-2.17.tar.bz2 to build-tools directory.

[uty@localhost build-tools]$ tar jxvf glibc-2.17.tar.bz2

[uty@localhost build-tools]$ cd build-glibc

[uty@localhost build-glibc]$ CC=arm-none-linux-gnueabi-gcc ../glibc-2.17/configure –host=$TARGET –prefix=$TARGET_PREFIX –enable-add-ons –with-headers=$TARGET_PREFIX/include

[uty@localhost build-glibc]$ make

[uty@localhost build-glibc]$ make install

编译完整的gcc

[uty@localhost build-tools]$ cd build-gcc

[uty@localhost build-gcc]$ ../gcc-4.7.2/configure –target=$TARGET –prefix=$PREFIX –enable-languages=c,c++

[uty@localhost build-gcc]$ make

[uty@localhost build-gcc]$ make install

 

应该说只有指定的这几个版本的配置这样编译才能通过。。。。。

2011年07月26日

error LNK2019: unresolved external symbol “unsigned int (__stdcall* ATL::g_pfnGetThreadACP)(void)

2011年04月29日

又郁闷了很久,后来按datasheet和示波器现实的调了下,总算是能显示了,先贴代码,以后再说从中学到的,要注意的吧。

main.c

   1: //  [4/8/2011 uty]

   2: #include <reg51.h> 

   3: #include <intrins.h>

   4: #include "time.h"

   5: #include "18b20.h"

   6: //-----------------------------------------------------------------------------//

   7: //此表为 LED 的字模, 共阴数码管 0-9  - 

   8: unsigned char code   Disp_Tab[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40};  //段码控制

   9: //此表为8个数码管位选控制, 共阴数码管 1-8个  - 

  10: unsigned char code   dispbit[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdF,0xbF,0x7F};    //位选控制   查表的方法控制

  11: //-----------------------------------------------------------------------------//

  12: void delay(unsigned int i)

  13: {

  14:     char j;

  15:     for(i; i > 0; i--)

  16:         for(j = 200; j > 0; j--);

  17: }

  18: //-----------------------------------------------------------------------------//

  19: void InterruptInit()

  20: {

  21:     TMOD|= 0x11;

  22:     TH1 = 0xD8;    //10

  23:     TL1 = 0xF0;    

  24:     IE = 0x8A;    

  25:     TR1  = 1;

  26: }

  27: //-----------------------------------------------------------------------------//

  28: void DisplayTemperature (unsigned int Temperature)

  29: {

  30:     unsigned char temp = 0;

  31:     unsigned int NegativeTemperature = 0;

  32:  

  33:     // 4位数最前面的0不显示,bFront控制是否是最前面的0

  34:     unsigned char bFront = 1;

  35:  

  36:     temp = Temperature % 10000 / 1000;

  37:  

  38:     if (0 != temp)

  39:     {

  40:         // negative number

  41:  

  42:         NegativeTemperature = 0x1000 - Temperature;

  43:  

  44:         temp = NegativeTemperature % 10000 / 1000;

  45:         if (0 != temp || !bFront)

  46:         {

  47:             bFront = 0;

  48:             P3 = ~dispbit[0];

  49:             P2 = ~Disp_Tab[temp];

  50:             STC89_12M_DelayMs(5);

  51:         }

  52:         else

  53:         {

  54:             // display '-'

  55:             if (0 != (NegativeTemperature % 1000 / 100))

  56:             {

  57:                 P3 = ~dispbit[0];

  58:                 P2 = ~Disp_Tab[10]; //'-'

  59:                 STC89_12M_DelayMs(5);

  60:             }

  61:         }

  62:  

  63:         temp = NegativeTemperature % 1000 / 100;

  64:         if (0 != temp || !bFront)

  65:         {

  66:             bFront = 0;

  67:             P3 = ~dispbit[1];

  68:             P2 = ~Disp_Tab[temp];

  69:             STC89_12M_DelayMs(5);

  70:         }

  71:         else

  72:         {

  73:             // display '-'

  74:             if (0 != (NegativeTemperature % 100 / 10))

  75:             {

  76:                 P3 = ~dispbit[1];

  77:                 P2 = ~Disp_Tab[10]; //'-'

  78:                 STC89_12M_DelayMs(5);

  79:             }

  80:         }

  81:  

  82:  

  83:         temp = NegativeTemperature % 100 / 10;

  84:         if (0 != temp || !bFront)

  85:         {

  86:             bFront = 0;

  87:             P3 = ~dispbit[2];

  88:             P2 = ~Disp_Tab[temp];

  89:             STC89_12M_DelayMs(5);

  90:         }

  91:         else

  92:         {

  93:             // display '-'

  94:             if (0 != (NegativeTemperature % 10))

  95:             {

  96:                 P3 = ~dispbit[2];

  97:                 P2 = ~Disp_Tab[10]; //'-'

  98:                 STC89_12M_DelayMs(5);

  99:             }

 100:         }

 101:  

 102:         temp = NegativeTemperature % 10;

 103:         P3 = ~dispbit[3];

 104:         P2 = ~Disp_Tab[temp];

 105:         STC89_12M_DelayMs(5);

 106:  

 107:     }

 108:     else

 109:     {

 110:         temp = Temperature % 10000 / 1000;

 111:         if (0 != temp || !bFront)

 112:         {

 113:             bFront = 0;

 114:             P3 = ~dispbit[0];

 115:             P2 = ~Disp_Tab[temp];

 116:             STC89_12M_DelayMs(5);

 117:         }

 118:  

 119:         temp = Temperature % 1000 / 100;

 120:         if (0 != temp || !bFront)

 121:         {

 122:             bFront = 0;

 123:             P3 = ~dispbit[1];

 124:             P2 = ~Disp_Tab[temp];

 125:             STC89_12M_DelayMs(5);

 126:         }

 127:  

 128:  

 129:         temp = Temperature % 100 / 10;

 130:         if (0 != temp || !bFront)

 131:         {

 132:             bFront = 0;

 133:             P3 = ~dispbit[2];

 134:             P2 = ~Disp_Tab[temp];

 135:             STC89_12M_DelayMs(5);

 136:         }

 137:  

 138:         // 如果温度是0  最后一位还是要显示

 139:         temp = Temperature % 10;

 140:         P3 = ~dispbit[3];

 141:         P2 = ~Disp_Tab[temp];

 142:         STC89_12M_DelayMs(5);

 143:     }    

 144: }

 145: //-----------------------------------------------------------------------------//

 146: void main (void)

 147: {

 148:     unsigned int idata nCounter = 0;

 149:     unsigned int idata nTemperature = 0;

 150:  

 151:     nCounter = 10000;

 152:  

 153:     while (1)

 154:     {      

 155:         if (nCounter >= 300)

 156:         {

 157:             nTemperature = GetTemperature ();

 158:             nCounter = 0;

 159:         }

 160:  

 161:         DisplayTemperature(nTemperature);

 162:  

 163:         nCounter++;                                                                                                                                   ;

 164:     }

 165: }

 166: //-----------------------------------------------------------------------------//

 

ds18b20.c

   1: //  [4/29/2011 uty]

   2: // 18b20 driver

   3: #include <reg52.H>

   4: #include <intrins.h>

   5: #include "time.h"

   6: #include "18b20.h"

   7: //-----------------------------------------------------------------------------//

   8: sbit    D18B20=P1^7;

   9: //-----------------------------------------------------------------------------//

  10: unsigned char code CrcTable [256]={

  11: 0,  94, 188,  226,  97,  63,  221,  131,  194,  156,  126,  32,  163,  253,  31,  65,

  12: 157,  195,  33,  127,  252,  162,  64,  30,  95,  1,  227,  189,  62,  96,  130,  220,

  13: 35,  125,  159,  193,  66,  28,  254,  160,  225,  191,  93,  3,  128,  222,  60,  98,

  14: 190,  224,  2,  92,  223,  129,  99,  61,  124,  34,  192,  158,  29,  67,  161,  255,

  15: 70,  24,  250,  164,  39,  121,  155,  197,  132,  218,  56,  102,  229,  187,  89,  7,

  16: 219,  133, 103,  57,  186,  228,  6,  88,  25,  71,  165,  251,  120,  38,  196,  154,

  17: 101,  59, 217,  135,  4,  90,  184,  230,  167,  249,  27,  69,  198,  152,  122,  36,

  18: 248,  166, 68,  26,  153,  199,  37,  123,  58,  100,  134,  216,  91,  5,  231,  185,

  19: 140,  210, 48,  110,  237,  179,  81,  15,  78,  16,  242,  172,  47,  113,  147,  205,

  20: 17,  79,  173,  243,  112,  46,  204,  146,  211,  141,  111,  49,  178,  236,  14,  80,

  21: 175,  241, 19,  77,  206,  144,  114,  44,  109,  51,  209,  143,  12,  82,  176,  238,

  22: 50,  108,  142,  208,  83,  13,  239,  177,  240,  174,  76,  18,  145,  207,  45,  115,

  23: 202,  148, 118,  40,  171,  245,  23,  73,  8,  86,  180,  234,  105,  55,  213, 139,

  24: 87,  9,  235,  181,  54,  104,  138,  212,  149,  203,  41,  119,  244,  170,  72,  22,

  25: 233,  183,  85,  11,  136,  214,  52,  106,  43,  117,  151,  201,  74,  20,  246,  168,

  26: 116,  42,  200,  150,  21,  75,  169,  247,  182,  232,  10,  84,  215,  137,  107,  53}; 

  27: //-----------------------------------------------------------------------------//

  28: #define Delay1us _nop_

  29: //-----------------------------------------------------------------------------//

  30: void Delay480us ()

  31: {

  32:     char i = 0;

  33:  

  34:     // 504 us

  35:     for (i = 0; i < 12; i++)

  36:     {

  37:         STC89_12M_Delay42us();

  38:     }    

  39: }

  40: //-----------------------------------------------------------------------------//

  41: void Delay240us ()

  42: {

  43:     char i = 0;

  44:  

  45:     // 462 us

  46:     for (i = 0; i < 5; i++)

  47:     {

  48:         STC89_12M_Delay42us();

  49:     }

  50:  

  51:     STC89_12M_Delay10us();

  52:     STC89_12M_Delay10us();

  53:     STC89_12M_Delay10us();

  54: }

  55: //-----------------------------------------------------------------------------//

  56: void Delay60us ()

  57: {

  58:     STC89_12M_Delay10us();

  59:     STC89_12M_Delay10us();

  60:     STC89_12M_Delay10us();

  61:     STC89_12M_Delay10us();

  62:     STC89_12M_Delay10us();

  63:     STC89_12M_Delay10us();

  64: }

  65: //-----------------------------------------------------------------------------//

  66: void Delay45us ()

  67: {

  68:     STC89_12M_Delay10us();

  69:     STC89_12M_Delay10us();

  70:     STC89_12M_Delay10us();

  71:     STC89_12M_Delay10us();

  72:  

  73:     Delay1us();

  74:     Delay1us();

  75:     Delay1us();

  76:     Delay1us();

  77:     Delay1us();

  78: }

  79: //-----------------------------------------------------------------------------//

  80: unsigned char reset(void)

  81: {

  82:     unsigned char ch = 0;

  83:  

  84:     D18B20 = 1;

  85:     Delay1us();

  86:     D18B20 = 0;  // 输入,外部上拉,等待18b20拉低

  87:     Delay480us();

  88:     D18B20 = 1;  // 输入,外部上拉,等待18b20拉低

  89:  

  90:     Delay60us();

  91:  

  92:     ch = D18B20;

  93:  

  94:     Delay480us();

  95:  

  96:     D18B20 = 1;

  97:  

  98:     if (1 == ch)

  99:     {

 100:         return 0;

 101:     }

 102:     else

 103:     {

 104:         return 1;

 105:     }

 106: }

 107: //-----------------------------------------------------------------------------//

 108: void write (unsigned char ch)

 109: {

 110:     unsigned char i = 0;

 111:  

 112:     for (i = 0;i < 8; i++)

 113:     {

 114:         D18B20 = 0;

 115:         Delay1us();

 116:         Delay1us();

 117:         Delay1us();

 118:         Delay1us();

 119:         Delay1us();

 120:         Delay1us();

 121:         Delay1us();

 122:         Delay1us();

 123:         Delay1us();

 124:         Delay1us();

 125:         D18B20 = (ch & 0x01);

 126:         Delay45us();

 127:         Delay45us();

 128:         D18B20 = 1;

 129:         ch >>= 1;

 130:     }

 131: }

 132: //-----------------------------------------------------------------------------//

 133: unsigned char read (void)

 134: {

 135:     unsigned char i = 0;

 136:     unsigned char u = 0;

 137:  

 138:     for (i = 0; i < 8; i++)

 139:     {

 140:         u >>= 1;

 141:  

 142:         D18B20 = 1;

 143:         Delay1us();

 144:         Delay1us();

 145:         Delay1us();

 146:         D18B20 = 0;

 147:         Delay1us();

 148:         Delay1us();

 149:         D18B20 = 1;

 150:         Delay1us();

 151:         Delay1us();

 152:         Delay1us();

 153:         Delay1us();

 154:         if (1 == D18B20)

 155:         {

 156:             u |= 0x80;

 157:         }

 158:  

 159:  

 160:         D18B20 = 1;

 161:         Delay60us();    

 162:     }

 163:  

 164:     return u;

 165: }

 166: //-----------------------------------------------------------------------------//

 167: void read_bytes (unsigned char* buffer, unsigned char len)

 168: {

 169:     unsigned char i = 0;

 170:  

 171:     for(i = 0; i < len; i++)

 172:     {

 173:         buffer[i] = read();

 174:     }

 175: }

 176: //-----------------------------------------------------------------------------//

 177: unsigned char CRC (unsigned char* buff, unsigned char j)

 178: {

 179:        unsigned char idata i,crc_data=0;

 180:       for(i=0;i<j;i++)  //查表校验

 181:         crc_data = CrcTable[crc_data^buff[i]];

 182:     return (crc_data);

 183: }

 184: //-----------------------------------------------------------------------------//

 185: unsigned int

 186: ReadTemperature (void)

 187: {

 188:     unsigned char ScratchpadBuffer[9] = {0};

 189:     unsigned int nTemperature = 0;

 190:  

 191:     read_bytes(ScratchpadBuffer, 9);

 192:     if (0 == CRC(ScratchpadBuffer, 9)) //校验正确

 193:     {

 194:         nTemperature = ScratchpadBuffer[1] * 0x100 + ScratchpadBuffer[0];

 195:         //nTemperature *= 0.625;

 196:         nTemperature /= 16;

 197:     }

 198:  

 199:     return nTemperature;

 200: }

 201: //-----------------------------------------------------------------------------//

 202: unsigned int

 203: GetTemperature (void)

 204: {

 205:     unsigned int nTemperature = 0;

 206:     // 先取温度,然后再去转换温度,新转换的数据下次再取

 207:     reset ();

 208:     write(0xcc);   //skip rom

 209:     write(0xbe);   //read Temperature

 210:     nTemperature = ReadTemperature();

 211:  

 212:     reset ();

 213:     write(0xcc);   //skip rom

 214:     write(0x44);   //Temperature convert

 215:  

 216:     return nTemperature;

 217: }

 218:  

 219: /*************************************

 220:  [ t1 (10ms)中断] 中断

 221: *************************************/

 222: // void T1zd(void) interrupt 3 

 223: // {

 224: //    TH1 = 0xD8;    //10

 225: //    TL1 = 0xF0;

 226: //    TIM++;

 227: // 

 228: // }

 229:  

 230: //-----------------------------------------------------------------------------//

 231:  

 232: /************************************************************

 233: *Function:内部配置

 234: *parameter:

 235: *Return:

 236: *Modify:

 237: *************************************************************/

 238: // void Config18b20 (void)  //重新配置报警限定值和分辨率

 239: // {

 240: //      reset();

 241: //      write(0xcc);  //skip rom

 242: //      write(0x4e);  //write scratchpad

 243: //      write(0x19);  //上限

 244: //      write(0x1a);  //下限

 245: //      write(0x7f);     //set 12 bit (0.125)

 246: // 

 247: //      reset();

 248: //      write(0xcc);  //skip rom

 249: //      write(0x48);  //保存设定值

 250: //      Init18b20();

 251: //      write(0xcc);  //skip rom

 252: //      write(0xb8);  //回调设定值

 253: // }

 254:  

 255: /************************************************************

 256: *Function:读18B20ID

 257: *parameter:

 258: *Return:

 259: *Modify:

 260: *************************************************************/

 261: // void ReadID (void)//读取器件 id

 262: // {

 263: //     reset();

 264: //     write(0x33);  //read rom

 265: //     read_bytes(8);

 266: // }

 

time.c

   1: //  [4/19/2011 uty]

   2: #include <intrins.h>

   3: //-----------------------------------------------------------------------------//

   4: void

   5: STC89_12M_Delay1ms (void)

   6: {

   7:     char i,j;

   8:     for(i = 110; i > 0; i--)

   9:         for(j = 200; j > 0; j--);

  10: }

  11: //-----------------------------------------------------------------------------//

  12: //

  13: // max 255 ms

  14: //

  15: void

  16: STC89_12M_DelayMs (

  17:     unsigned char i

  18:     )

  19: {

  20:     while (i--)

  21:     {

  22:         STC89_12M_Delay1ms();

  23:     }

  24: }

  25: //-----------------------------------------------------------------------------//

  26: void STC89_12M_Delay10us () 

  27: {

  28:     // LCALL指令(2 μs)

  29:  

  30:     _nop_( );

  31:     _nop_( );

  32:     _nop_( );

  33:     _nop_( );

  34:     _nop_( );

  35:     _nop_( );

  36:  

  37:     // RET指令(2 μs)

  38: }

  39: //-----------------------------------------------------------------------------//

  40: void STC89_12M_Delay42us ()

  41: {

  42:     STC89_12M_Delay10us();

  43:     STC89_12M_Delay10us();

  44:     STC89_12M_Delay10us();

  45:     STC89_12M_Delay10us();

  46: }

  47: //-----------------------------------------------------------------------------//

 

再上张图

照片-0027_1

2011年04月14日

AND 与门
ANTENNA 天线
BATTERY 直流电源
BELL 铃,钟
BVC 同轴电缆接插件
BRIDEG 1 整流桥(二极管)
BRIDEG 2 整流桥(集成块)
BUFFER 缓冲器
BUZZER 蜂鸣器
CAP 电容
CAPACITOR 电容
CAPACITOR POL 有极性电容
CAPVAR 可调电容
CIRCUIT BREAKER 熔断丝
COAX 同轴电缆
CON 插口
CRYSTAL 晶体整荡器
DB 并行插口
DIODE 二极管
DIODE SCHOTTKY 稳压二极管
DIODE VARACTOR 变容二极管
DPY_3-SEG 3段LED
DPY_7-SEG 7段LED
DPY_7-SEG_DP 7段LED(带小数点)
ELECTRO 电解电容
FUSE 熔断器
INDUCTOR 电感
INDUCTOR IRON 带铁芯电感
INDUCTOR3 可调电感
JFET N N沟道场效应管
JFET P P沟道场效应管
LAMP 灯泡
LAMP NEDN 起辉器
LED 发光二极管
METER 仪表
MICROPHONE 麦克风
MOSFET MOS管
MOTOR AC 交流电机
MOTOR SERVO 伺服电机
NAND 与非门
NOR 或非门
NOT 非门
NPN NPN三极管
NPN-PHOTO 感光三极管
OPAMP 运放
OR 或门
PHOTO 感光二极管
PNP 三极管
NPN DAR NPN三极管
PNP DAR PNP三极管
POT 滑线变阻器
PELAY-DPDT 双刀双掷继电器
RES1.2 电阻
RES3.4 可变电阻
RESISTOR BRIDGE ? 桥式电阻
RESPACK ? 电阻
SCR 晶闸管
PLUG ? 插头
PLUG AC FEMALE 三相交流插头
SOCKET ? 插座
SOURCE CURRENT 电流源
SOURCE VOLTAGE 电压源
SPEAKER 扬声器
SW ? 开关
SW-DPDY ? 双刀双掷开关
SW-SPST ? 单刀单掷开关
SW-PB 按钮
THERMISTOR 电热调节器
TRANS1 变压器
TRANS2 可调变压器
TRIAC ? 三端双向可控硅
TRIODE ? 三极真空管
VARISTOR 变阻器
ZENER ? 齐纳二极管
DPY_7-SEG_DP 数码管
SW-PB 开关

2011年03月25日
   1: #include <REG52.H>

   2: //-----------------------------------------------------------------------------//

   3: void delay(unsigned int i)

   4: {

   5:     unsigned char j;

   6:     for(i; i > 0; i--)

   7:         for(j = 200; j > 0; j--) ;

   8: }

   9: //-----------------------------------------------------------------------------//

  10: void

  11: InitSerial ()

  12: {

  13:     SCON = 0x50;

  14:     TMOD |= 0x20;

  15:     PCON |= 0x80;

  16:     TH1 = 0xF3;            // 晶振12.0 4800 baudrate

  17:     TL1 = 0xF3;

  18:     TR1 = 1;

  19:     ES = 1;

  20:     EA = 1;

  21:  

  22:     RI = 0;

  23:     TI = 0;

  24: }

  25: //-----------------------------------------------------------------------------//

  26: void

  27: SendByte (

  28:     unsigned char ch

  29:     )

  30: {

  31:     TI = 0;                // Be sure the bit is initially clear

  32:     SBUF = ch;            // Send the letter A to the serial port

  33:     while (0 == TI);    // Pause until the TI bit is set.    

  34: }

  35: //-----------------------------------------------------------------------------//

  36: void

  37: SendString (

  38:     unsigned char* String

  39:     )

  40: {

  41:     int i = 0;

  42:  

  43:     while ('' != String[i])

  44:     {

  45:         SendByte(String[i]);

  46:         i++;

  47:     }

  48: }

  49: //-----------------------------------------------------------------------------//

  50: void main (void)

  51: {

  52:     int a;

  53:  

  54:     InitSerial();

  55:  

  56:     while (1)

  57:     {

  58:         SendString("Hello world! ");

  59:         delay(100);

  60:     }

  61: }

  62: //-----------------------------------------------------------------------------//

本来很简单的一个小程序,但开始在用windows 超级终端接收的时候总是不成功,有时候能收到,但是断断续续的,每次连接只能收到几个字符,并且还总有一声咔的声音。后来发现是usb转串口的原因,可能是有bug吧,直接连外面的串口就一切正常了。

串口可以了,ISD51也就能用了,原来总不行的原因更郁闷,虽然#include <ISD51.h>,也把ISD51.A51和ISD51.h放到了工程目录下,但是忘了把ISD51.A51

加到工程里。。。结果编译器也没报错,我就当编进去了呢。用惯了vs哪怕vc6,用keil都不行了。。。。。 之后设置好baudrate就一切正常了。

超级终端接收的时候这样设置

serial

数据流不需要硬件控制,停止位貌似1 1.5 2 都可以,因为baudrate比较低,所以数据之间空的非常多。

结果就是这样了

hypertrm

 

 

 

串口各寄存器的作用,有篇非常详细的介绍

8051 Tutorial: Serial Communication


One of the 8051s many powerful features is its integrated UART, otherwise known as a serial port. The fact that the 8051 has an integrated serial port means that you may very easily read and write values to the serial port. If it were not for the integrated serial port, writing a byte to a serial line would be a rather tedious process requring turning on and off one of the I/O lines in rapid succession to properly "clock out" each individual bit, including start bits, stop bits, and parity bits.

However, we do not have to do this. Instead, we simply need to configure the serial ports operation mode and baud rate. Once configured, all we have to do is write to an SFR to write a value to the serial port or read the same SFR to read a value from the serial port. The 8051 will automatically let us know when it has finished sending the character we wrote and will also let us know whenever it has received a byte so that we can process it. We do not have to worry about transmission at the bit level–which saves us quite a bit of coding and processing time.

Setting the Serial Port Mode

The first thing we must do when using the 8051s integrated serial port is, obviously, configure it. This lets us tell the 8051 how many data bits we want, the baud rate we will be using, and how the baud rate will be determined.

First, lets present the "Serial Control" (SCON) SFR and define what each bit of the SFR represents:

    serial_2

Additionally, it is necessary to define the function of SM0 and SM1 by an additional table:

    serial_3

(*) Note: The baud rate indicated in this table is doubled if PCON.7 (SMOD) is set.

The SCON SFR allows us to configure the Serial Port. Thus, well go through each bit and review its function.

The first four bits (bits 4 through 7) are configuration bits.

Bits SM0 and SM1 let us set the serial mode to a value between 0 and 3, inclusive. The four modes are defined in the chart immediately above. As you can see, selecting the Serial Mode selects the mode of operation (8-bit/9-bit, UART or Shift Register) and also determines how the baud rate will be calculated. In modes 0 and 2 the baud rate is fixed based on the oscillators frequency. In modes 1 and 3 the baud rate is variable based on how often Timer 1 overflows. Well talk more about the various Serial Modes in a moment.

The next bit, SM2, is a flag for "Multiprocessor communication." Generally, whenever a byte has been received the 8051 will set the "RI" (Receive Interrupt) flag. This lets the program know that a byte has been received and that it needs to be processed. However, when SM2 is set the "RI" flag will only be triggered if the 9th bit received was a "1". That is to say, if SM2 is set and a byte is received whose 9th bit is clear, the RI flag will never be set. This can be useful in certain advanced serial applications. For now it is safe to say that you will almost always want to clear this bit so that the flag is set upon reception of any character.

The next bit, REN, is "Receiver Enable." This bit is very straightforward: If you want to receive data via the serial port, set this bit. You will almost always want to set this bit.

The last four bits (bits 0 through 3) are operational bits. They are used when actually sending and receiving data–they are not used to configure the serial port.

The TB8 bit is used in modes 2 and 3. In modes 2 and 3, a total of nine data bits are transmitted. The first 8 data bits are the 8 bits of the main value, and the ninth bit is taken from TB8. If TB8 is set and a value is written to the serial port, the datas bits will be written to the serial line followed by a "set" ninth bit. If TB8 is clear the ninth bit will be "clear."

The RB8 also operates in modes 2 and 3 and functions essentially the same way as TB8, but on the reception side. When a byte is received in modes 2 or 3, a total of nine bits are received. In this case, the first eight bits received are the data of the serial byte received and the value of the ninth bit received will be placed in RB8.

TI means "Transmit Interrupt." When a program writes a value to the serial port, a certain amount of time will pass before the individual bits of the byte are "clocked out" the serial port. If the program were to write another byte to the serial port before the first byte was completely output, the data being sent would be garbled. Thus, the 8051 lets the program know that it has "clocked out" the last byte by setting the TI bit. When the TI bit is set, the program may assume that the serial port is "free" and ready to send the next byte.

Finally, the RI bit means "Receive Interrupt." It funcions similarly to the "TI" bit, but it indicates that a byte has been received. That is to say, whenever the 8051 has received a complete byte it will trigger the RI bit to let the program know that it needs to read the value quickly, before another byte is read.

Setting the Serial Port Baud Rate

Once the Serial Port Mode has been configured, as explained above, the program must configure the serial ports baud rate. This only applies to Serial Port modes 1 and 3. The Baud Rate is determined based on the oscillators frequency when in mode 0 and 2. In mode 0, the baud rate is always the oscillator frequency divided by 12. This means if youre crystal is 11.059Mhz, mode 0 baud rate will always be 921,583 baud. In mode 2 the baud rate is always the oscillator frequency divided by 64, so a 11.059Mhz crystal speed will yield a baud rate of 172,797.

In modes 1 and 3, the baud rate is determined by how frequently timer 1 overflows. The more frequently timer 1 overflows, the higher the baud rate. There are many ways one can cause timer 1 to overflow at a rate that determines a baud rate, but the most common method is to put timer 1 in 8-bit auto-reload mode (timer mode 2) and set a reload value (TH1) that causes Timer 1 to overflow at a frequency appropriate to generate a baud rate.

To determine the value that must be placed in TH1 to generate a given baud rate, we may use the following equation (assuming PCON.7 is clear).

    TH1 = 256 – ((Crystal / 384) / Baud)

If PCON.7 is set then the baud rate is effectively doubled, thus the equation becomes:

    TH1 = 256 – ((Crystal / 192) / Baud)

For example, if we have an 11.059Mhz crystal and we want to configure the serial port to 19,200 baud we try plugging it in the first equation:

    TH1 = 256 – ((Crystal / 384) / Baud)

    TH1 = 256 – ((11059000 / 384) / 19200 )

    TH1 = 256 – ((28,799) / 19200)

    TH1 = 256 – 1.5 = 254.5

As you can see, to obtain 19,200 baud on a 11.059Mhz crystal wed have to set TH1 to 254.5. If we set it to 254 we will have achieved 14,400 baud and if we set it to 255 we will have achieved 28,800 baud. Thus were stuck…

But not quite… to achieve 19,200 baud we simply need to set PCON.7 (SMOD). When we do this we double the baud rate and utilize the second equation mentioned above. Thus we have:

    TH1 = 256 – ((Crystal / 192) / Baud)

    TH1 = 256 – ((11059000 / 192) / 19200)

    TH1 = 256 – ((57699) / 19200)

    TH1 = 256 – 3 = 253

Here we are able to calculate a nice, even TH1 value. Therefore, to obtain 19,200 baud with an 11.059MHz crystal we must:

    1. Configure Serial Port mode 1 or 3.

    2. Configure Timer 1 to timer mode 2 (8-bit auto-reload).

    3. Set TH1 to 253 to reflect the correct frequency for 19,200 baud.

    4. Set PCON.7 (SMOD) to double the baud rate.

Writing to the Serial Port

Once the Serial Port has been propertly configured as explained above, the serial port is ready to be used to send data and receive data. If you thought that configuring the serial port was simple, using the serial port will be a breeze.

To write a byte to the serial port one must simply write the value to the SBUF (99h) SFR. For example, if you wanted to send the letter "A" to the serial port, it could be accomplished as easily as:

    MOV SBUF,#A

Upon execution of the above instruction the 8051 will begin transmitting the character via the serial port. Obviously transmission is not instantaneous–it takes a measureable amount of time to transmit. And since the 8051 does not have a serial output buffer we need to be sure that a character is completely transmitted before we try to transmit the next character.

The 8051 lets us know when it is done transmitting a character by setting the TI bit in SCON. When this bit is set we know that the last character has been transmitted and that we may send the next character, if any. Consider the following code segment:

    CLR TI ;Be sure the bit is initially clear

    MOV SBUF,#A ;Send the letter A to the serial port

    JNB TI,$ ;Pause until the TI bit is set.

The above three instructions will successfully transmit a character and wait for the TI bit to be set before continuing. The last instruction says "Jump if the TI bit is not set to $"–$, in most assemblers, means "the same address of the current instruction." Thus the 8051 will pause on the JNB instruction until the TI bit is set by the 8051 upon successful transmission of the character.

Reading the Serial Port

Reading data received by the serial port is equally easy. To read a byte from the serial port one just needs to read the value stored in the SBUF (99h) SFR after the 8051 has automatically set the RI flag in SCON.

For example, if your program wants to wait for a character to be received and subsequently read it into the Accumulator, the following code segment may be used:

    JNB RI,$ ;Wait for the 8051 to set the RI flag

    MOV A,SBUF ;Read the character from the serial port

The first line of the above code segment waits for the 8051 to set the RI flag; again, the 8051 sets the RI flag automatically when it receives a character via the serial port. So as long as the bit is not set the program repeats the "JNB" instruction continuously.

Once the RI bit is set upon character reception the above condition automatically fails and program flow falls through to the "MOV" instruction which reads the value.


2011年03月24日
动NET_BUFFER还算行,动NET_BUFFER_LIST估计也可以,消耗就更大了。还有种方法就是换MDL,或者链在MdlChain后面, 然后改CurrentMdl,不过这种方法估计要自己维护个结构,看哪个Mdl是自己分配的,或者把相关的数据放到NET_BUFFER的MiniportReserved里,但原来的包在complete的时候要恢复的完全一样,想想还是替换NET_BUFFER最简单。
ndislwf可能还算较新的东西,网上相关的东西不多,希望这个例子能有帮助
晕 代码高亮的快疯了,就这样算了
 
   1: VOID

   2: FilterSendNetBufferListsComplete(

   3:         IN  NDIS_HANDLE         FilterModuleContext,

   4:         IN  PNET_BUFFER_LIST    NetBufferLists,

   5:         IN  ULONG               SendCompleteFlags

   6:         )

   7: /*++

   8:  

   9: Routine Description:

  10: 

  11:     SendNetBufferListComplete 

  12: 

  13: Arguments:

  14: 

  15:       

  16:      

  17: Return Value:

  18: 

  19:      NONE

  20:  

  21: --*/

  22: {

  23:     PMS_FILTER          pFilter = (PMS_FILTER)FilterModuleContext;

  24:     //ULONG              NumOfSendCompletes = 0;

  25:     //BOOLEAN            DispatchLevel;

  26:     //PNET_BUFFER_LIST   CurrNbl;

  27:  

  28:     PNET_BUFFER_LIST    pNetBufList = NULL;

  29:     PNET_BUFFER_LIST    pNextNetBufList = NULL;

  30:  

  31:     PMDL                pMdl = NULL;

  32:     PNDISPROT_ETH_HEADER pEthHeader = NULL;

  33:     ULONG               ulOffset = 0;

  34:     ULONG               ulBufferLength = 0;

  35:     PNET_BUFFER         pCurrentNetBuffer = NULL;

  36:     PNET_BUFFER         pPreviousNetBuffer = NULL;

  37:     PNET_BUFFER         pOriginalNetBuffer = NULL;

  38:     ULONG               ulTotalLength = 0;

  39:    

  40:     DEBUGP(DL_TRACE, ("===>SendNBLComplete, NetBufferList: %p.\n", NetBufferLists));

  41:  

  42:     //

  43:     // if necessary, undo any modifications to the NetBufferList thate were performed "on the way down"

  44:     //

  45:     //if (pFilter->TrackSends)

  46:     //{

  47:     //    CurrNbl = NetBufferLists;

  48:     //    while (CurrNbl)

  49:     //    {

  50:     //        NumOfSendCompletes++;

  51:     //        CurrNbl = NET_BUFFER_LIST_NEXT_NBL(CurrNbl);

  52:     //        

  53:     //    }

  54:     //    DispatchLevel = NDIS_TEST_SEND_AT_DISPATCH_LEVEL(SendCompleteFlags);

  55:     //    FILTER_ACQUIRE_LOCK(&pFilter->Lock, DispatchLevel);

  56:     //    pFilter->OutstandingSends -= NumOfSendCompletes;

  57:     //    FILTER_LOG_SEND_REF(2, pFilter, PrevNbl, pFilter->OutstandingSends);        

  58:     //    FILTER_RELEASE_LOCK(&pFilter->Lock, DispatchLevel);

  59:     //}

  60:  

  61:  

  62:     pNetBufList = NetBufferLists;

  63:  

  64:     while (pNetBufList != NULL)

  65:     {

  66:         pNextNetBufList = NET_BUFFER_LIST_NEXT_NBL(pNetBufList);

  67:  

  68:         for (pCurrentNetBuffer = NET_BUFFER_LIST_FIRST_NB(pNetBufList);

  69:             pCurrentNetBuffer != NULL;

  70:             pCurrentNetBuffer = NET_BUFFER_NEXT_NB(pCurrentNetBuffer)) 

  71:         {

  72:             pMdl = NET_BUFFER_CURRENT_MDL(pCurrentNetBuffer);

  73:             ulTotalLength = NET_BUFFER_DATA_LENGTH(pCurrentNetBuffer);

  74:             ulOffset = NET_BUFFER_CURRENT_MDL_OFFSET(pCurrentNetBuffer);

  75:  

  76:             do 

  77:             {

  78:                 ASSERT(pMdl != NULL);

  79:                 if (pMdl)

  80:                 {

  81:                     NdisQueryMdl(

  82:                         pMdl,

  83:                         &pEthHeader,

  84:                         &ulBufferLength,

  85:                         NormalPagePriority);

  86:                 }

  87:                 if (NULL == pEthHeader)

  88:                 {

  89:                     //

  90:                     //  The system is low on resources. Set up to handle failure

  91:                     //  below.

  92:                     //

  93:                     ulBufferLength = 0;

  94:                     break;

  95:                 }

  96:  

  97:                 if (0 == ulBufferLength)

  98:                 {

  99:                     break;

 100:                 }

 101:  

 102:                 ASSERT(ulBufferLength > ulOffset);

 103:  

 104:                 ulBufferLength -= ulOffset;

 105:                 pEthHeader = (PNDISPROT_ETH_HEADER)((PUCHAR)pEthHeader + ulOffset);

 106:  

 107:                 if (ulBufferLength < sizeof(NDISPROT_ETH_HEADER))

 108:                 {

 109:                     DEBUGP(DL_WARN,

 110:                         ("ReceiveNetBufferList: runt nbl %p, first buffer length %d\n",

 111:                         pNetBufList, ulBufferLength));

 112:  

 113:                     break;

 114:                 }

 115:  

 116:                 //

 117:                 //  Check the EtherType. If the Ether type indicates presence of

 118:                 //  a tag, then the "real" Ether type is 4 bytes further down.

 119:                 //

 120:                 if (pEthHeader->EthType == NPROT_8021P_TAG_TYPE)

 121:                 {

 122:                     USHORT UNALIGNED *pEthType;

 123:  

 124:                     if (ulBufferLength < (sizeof(NDISPROT_ETH_HEADER) + 4))

 125:                     {

 126:                         break;

 127:                     }

 128:  

 129:                     pEthType = (USHORT UNALIGNED *)((PUCHAR)&pEthHeader->EthType + 4);

 130:  

 131:                     if (*pEthType != NPROT_ETH_TYPE)

 132:                     {

 133:                         break;

 134:                     }

 135:                 }

 136:                 else if (pEthHeader->EthType != NPROT_ETH_TYPE)

 137:                 {

 138:                     break;

 139:                 }

 140:  

 141:                 //

 142:                 //  to do

 143:                 //

 144:  

 145:                 if (NdisGetPoolFromNetBuffer(pCurrentNetBuffer) == pFilter->NetBufferPool)

 146:                 {

 147:                     KdBreakPoint();

 148:  

 149:                     pOriginalNetBuffer = NET_BUFFER_LIST_MINIPORT_RESERVED(pCurrentNetBuffer)[0];

 150:  

 151:                     if (pCurrentNetBuffer == NET_BUFFER_LIST_FIRST_NB(pNetBufList))

 152:                     {

 153:                         NET_BUFFER_LIST_FIRST_NB(pNetBufList) = pOriginalNetBuffer;

 154:                     }

 155:                     else

 156:                     {

 157:                         pPreviousNetBuffer->Next = pOriginalNetBuffer;

 158:                     }

 159:  

 160:                     pOriginalNetBuffer->Next = pCurrentNetBuffer->Next;

 161:  

 162:  

 163:                     NdisFreeNetBuffer(pCurrentNetBuffer);

 164:  

 165:                     pCurrentNetBuffer = pOriginalNetBuffer;

 166:                 }

 167:  

 168:             } while (FALSE);

 169:  

 170:             pPreviousNetBuffer = pCurrentNetBuffer;

 171:         }

 172:  

 173:  

 174:         pNetBufList = pNextNetBufList;

 175:     }

 176:  

 177:  

 178:  

 179:     NdisFSendNetBufferListsComplete(pFilter->FilterHandle, NetBufferLists, SendCompleteFlags);

 180:  

 181:     DEBUGP(DL_TRACE, ("<===SendNBLComplete.\n"));

 182: }

 

   1: VOID

   2: FilterSendNetBufferLists(

   3:         IN  NDIS_HANDLE         FilterModuleContext,

   4:         IN  PNET_BUFFER_LIST    NetBufferLists,

   5:         IN  NDIS_PORT_NUMBER    PortNumber,

   6:         IN  ULONG               SendFlags

   7:         )

   8: /*++

   9:  

  10: Routine Description:

  11: 

  12:     Send Net Buffer List handler

  13:     This function is an optional function for filter drivers. If provided, NDIS

  14:     will call this function to transmit a linked list of NetBuffers, described by a 

  15:     NetBuferList, over the network. If this handler is NULL, NDIS will skip calling

  16:     this fitler when sending a NetBufferList and will call the next lower fitler 

  17:     in the stack with a non_NULL FilterSendNetBufferList handleror the miniport driver.

  18:     A filter that doesn't provide a FilerSendNetBufferList handler can not initiate a 

  19:     send o its own.

  20: 

  21: Arguments:

  22: 

  23:     FilterModuleContext: Pointer to our filter context area.

  24:     NetBufferLists: Pointer to a List of NetBufferLists.

  25:     PortNumber - Port Number to which this send is targetted

  26:     SendFlags-  Specifies if the call is at DISPATCH_LEVEL                     

  27:   

  28: 

  29: Return Value:

  30:  

  31:     NDIS_STATUS_SUCCESS: 

  32:     NDIS_STATUS_PENDING:

  33:     NDIS_STATUS_INVALID_PACKET:

  34:     NDIS_STATUS_RESOURCES:

  35:     NDIS_STATUS_FAILURE:

  36: 

  37: 

  38: NOTE: The filter will act like a passthru filter.       

  39:  

  40: --*/

  41: {

  42:     NDIS_STATUS         Status = NDIS_STATUS_FAILURE;

  43:     PMS_FILTER          pFilter = (PMS_FILTER)FilterModuleContext;

  44:     //PNET_BUFFER_LIST    CurrNbl;

  45:     //BOOLEAN             DispatchLevel;

  46:     //BOOLEAN             bFalse = FALSE;

  47:  

  48:     PNET_BUFFER_LIST    pNetBufList = NULL;

  49:     PNET_BUFFER_LIST    pNextNetBufList = NULL;

  50:  

  51:     PMDL                pMdl = NULL;

  52:     PNDISPROT_ETH_HEADER pEthHeader = NULL;

  53:     ULONG               ulOffset = 0;

  54:     ULONG               ulBufferLength = 0;

  55:     PNET_BUFFER         pCurrentNetBuffer = NULL;

  56:     PNET_BUFFER         pPreviousNetBuffer = NULL;

  57:     PNET_BUFFER         pNewNetBuffer = NULL;

  58:     ULONG               ulTotalLength = 0;

  59:     

  60:     DEBUGP(DL_TRACE, ("===>SendNetBufferList: NBL = %p.\n", NetBufferLists));

  61:  

  62: //    do

  63: //    {

  64: //

  65: //       DispatchLevel = NDIS_TEST_SEND_AT_DISPATCH_LEVEL(SendFlags);

  66: //#if DBG

  67: //        //

  68: //        // we should never get packets to send if we are not in running state

  69: //        //

  70: //        

  71: //        FILTER_ACQUIRE_LOCK(&pFilter->Lock, DispatchLevel);

  72: //        //

  73: //        // If the filter is not in running state, fail the send

  74: //        // 

  75: //        if (pFilter->State != FilterRunning)

  76: //        {

  77: //            FILTER_RELEASE_LOCK(&pFilter->Lock, DispatchLevel);

  78: //            

  79: //            CurrNbl = NetBufferLists;

  80: //            while (CurrNbl)

  81: //            {

  82: //                NET_BUFFER_LIST_STATUS(CurrNbl) = NDIS_STATUS_PAUSED;

  83: //                CurrNbl = NET_BUFFER_LIST_NEXT_NBL(CurrNbl);

  84: //            }

  85: //            NdisFSendNetBufferListsComplete(pFilter->FilterHandle, 

  86: //                        NetBufferLists, 

  87: //                        DispatchLevel ? NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL : 0);

  88: //            break;

  89: //            

  90: //        }

  91: //        FILTER_RELEASE_LOCK(&pFilter->Lock, DispatchLevel);

  92: //#endif

  93: //        if (pFilter->TrackSends)

  94: //        {

  95: //            FILTER_ACQUIRE_LOCK(&pFilter->Lock, DispatchLevel);

  96: //            CurrNbl = NetBufferLists;

  97: //            while (CurrNbl)

  98: //            {

  99: //                pFilter->OutstandingSends++;

 100: //                FILTER_LOG_SEND_REF(1, pFilter, CurrNbl, pFilter->OutstandingSends);

 101: //                

 102: //                CurrNbl = NET_BUFFER_LIST_NEXT_NBL(CurrNbl);

 103: //            }

 104: //            FILTER_RELEASE_LOCK(&pFilter->Lock, DispatchLevel);

 105: //        }

 106: //        //

 107: //        // If necessary, queue the NetBufferList in a local structure for later processing

 108: //        //

 109: //        NdisFSendNetBufferLists(pFilter->FilterHandle, NetBufferLists, PortNumber, SendFlags);

 110: //        

 111: //        

 112: //    }

 113: //    while (bFalse);

 114:  

 115:     KdBreakPoint();

 116:  

 117:  

 118:     pNetBufList = NetBufferLists;

 119:  

 120:     while (pNetBufList != NULL)

 121:     {

 122:         pNextNetBufList = NET_BUFFER_LIST_NEXT_NBL(pNetBufList);

 123:  

 124:         for (pCurrentNetBuffer = NET_BUFFER_LIST_FIRST_NB(pNetBufList);

 125:             pCurrentNetBuffer != NULL;

 126:             pCurrentNetBuffer = NET_BUFFER_NEXT_NB(pCurrentNetBuffer)) 

 127:         {

 128:             pMdl = NET_BUFFER_CURRENT_MDL(pCurrentNetBuffer);

 129:             ulTotalLength = NET_BUFFER_DATA_LENGTH(pCurrentNetBuffer);

 130:             ulOffset = NET_BUFFER_CURRENT_MDL_OFFSET(pCurrentNetBuffer);

 131:  

 132:             do 

 133:             {

 134:                 ASSERT(pMdl != NULL);

 135:                 if (pMdl)

 136:                 {

 137:                     NdisQueryMdl(

 138:                         pMdl,

 139:                         &pEthHeader,

 140:                         &ulBufferLength,

 141:                         NormalPagePriority);

 142:                 }

 143:                 if (NULL == pEthHeader)

 144:                 {

 145:                     //

 146:                     //  The system is low on resources. Set up to handle failure

 147:                     //  below.

 148:                     //

 149:                     ulBufferLength = 0;

 150:                     break;

 151:                 }

 152:  

 153:                 if (0 == ulBufferLength)

 154:                 {

 155:                     break;

 156:                 }

 157:  

 158:                 ASSERT(ulBufferLength > ulOffset);

 159:  

 160:                 ulBufferLength -= ulOffset;

 161:                 pEthHeader = (PNDISPROT_ETH_HEADER)((PUCHAR)pEthHeader + ulOffset);

 162:  

 163:                 if (ulBufferLength < sizeof(NDISPROT_ETH_HEADER))

 164:                 {

 165:                     DEBUGP(DL_WARN,

 166:                         ("ReceiveNetBufferList: runt nbl %p, first buffer length %d\n",

 167:                             pNetBufList, ulBufferLength));

 168:  

 169:                     break;

 170:                 }

 171:  

 172:                 //

 173:                 //  Check the EtherType. If the Ether type indicates presence of

 174:                 //  a tag, then the "real" Ether type is 4 bytes further down.

 175:                 //

 176:                 if (pEthHeader->EthType == NPROT_8021P_TAG_TYPE)

 177:                 {

 178:                     USHORT UNALIGNED *pEthType;

 179:  

 180:                     if (ulBufferLength < (sizeof(NDISPROT_ETH_HEADER) + 4))

 181:                     {

 182:                         break;

 183:                     }

 184:  

 185:                     pEthType = (USHORT UNALIGNED *)((PUCHAR)&pEthHeader->EthType + 4);

 186:  

 187:                     if (*pEthType != NPROT_ETH_TYPE)

 188:                     {

 189:                         break;

 190:                     }

 191:                 }

 192:                 else if (pEthHeader->EthType != NPROT_ETH_TYPE)

 193:                 {

 194:                     break;

 195:                 }

 196:  

 197:                 //

 198:                 //  to do

 199:                 //

 200:  

 201:                 //PrintDataBuffer((PUCHAR)pEthHeader, ulBufferLength);

 202:                 DbgPrint("Packet Length 0x%d,  pMdl->ByteCount 0x%x,  pMdl->Next 0x%x\n", ulBufferLength, pMdl->ByteCount, pMdl->Next);

 203:  

 204:                 Status = CopyNetBuffer(pFilter,pCurrentNetBuffer, &pNewNetBuffer);

 205:                 if (NDIS_STATUS_SUCCESS != Status)

 206:                 {

 207:                     break;

 208:                 }

 209:  

 210:                 if (pCurrentNetBuffer == NET_BUFFER_LIST_FIRST_NB(pNetBufList))

 211:                 {

 212:                     NET_BUFFER_LIST_FIRST_NB(pNetBufList) = pNewNetBuffer;

 213:                 }

 214:                 else

 215:                 {

 216:                     pPreviousNetBuffer->Next = pNewNetBuffer;

 217:                 }

 218:  

 219:                 pNewNetBuffer->Next = pCurrentNetBuffer->Next;

 220:                 NET_BUFFER_LIST_MINIPORT_RESERVED(pNewNetBuffer)[0] = pCurrentNetBuffer;

 221:  

 222:  

 223:                 pCurrentNetBuffer = pNewNetBuffer;

 224:  

 225:             } while (FALSE);

 226:  

 227:             pPreviousNetBuffer = pCurrentNetBuffer;

 228:         }

 229:  

 230:  

 231:         pNetBufList = pNextNetBufList;

 232:     }

 233:  

 234:  

 235:  

 236:     NdisFSendNetBufferLists(pFilter->FilterHandle, NetBufferLists, PortNumber, SendFlags);

 237:     

 238:     DEBUGP(DL_TRACE, ("<===SendNetBufferList. \n"));

 239: }

[MSFT.NTamd64]
%NdisLwf_Desc%=Install, MS_NdisLwf

;————————————————————————-
; Installation Section
;————————————————————————-
[Install]
AddReg=Inst_Ndi
Characteristics=0×40000
NetCfgInstanceId="{5cbf81bd-5055-47cd-9055-a76b2b4e3697}"
Copyfiles = ndislwf.copyfiles.sys

[SourceDisksNames]
1=%NdisLwf_Desc%,"",,

[SourceDisksFiles]
ndislwf.sys=1

[DestinationDirs]
DefaultDestDir=12
ndislwf.copyfiles.sys=12

[ndislwf.copyfiles.sys]
ndislwf.sys,,,2

;————————————————————————-
; Ndi installation support
;————————————————————————-
[Inst_Ndi]
HKR, Ndi,Service,,"NdisLwf"
HKR, Ndi,CoServices,0×00010000,"NdisLwf"
HKR, Ndi,HelpText,,%NdisLwf_HelpText%
HKR, Ndi,FilterClass,, Custom
HKR, Ndi,FilterType,0×00010001,0×00000001   ; 0×00000002 for a modifying filter
HKR, Ndi\Interfaces,UpperRange,,"noupper"
HKR, Ndi\Interfaces,LowerRange,,"noupper"
HKR, Ndi\Interfaces, FilterMediaTypes,,"wlan"  ; 只收raw wifi,也可以加上"ethernet"
HKR, Ndi,FilterRunType, 0×00010001, 2 ;this filter must run before any protocol can bind to the below miniport

;————————————————————————-
; Service installation support
;————————————————————————-
[Install.Services]
AddService=NdisLwf,,NdisLwf_Service_Inst

[NdisLwf_Service_Inst]
DisplayName     = %NdisLwf_Desc%
ServiceType     = 1 ;SERVICE_KERNEL_DRIVER
StartType       = 1 ;SERVICE_SYSTEM_START
ErrorControl    = 1 ;SERVICE_ERROR_NORMAL
ServiceBinary   = %12%\ndislwf.sys
LoadOrderGroup  = NDIS
Description     = %NdisLwf_Desc%
AddReg          = Common.Params.reg

[Install.Remove.Services]
DelService=NdisLwf,0×200

[Common.Params.reg]

HKR, FilterDriverParams\DriverParam,         ParamDesc,     , "Driverparam for lwf"
HKR, FilterDriverParams\DriverParam,         default,     , "5"
HKR, FilterDriverParams\DriverParam,         type,         , "int"

HKR, FilterAdapterParams\AdapterParam,         ParamDesc,     , "Adapterparam for lwf"
HKR, FilterAdapterParams\AdapterParam,         default,     , "10"
HKR, FilterAdapterParams\AdapterParam,         type,         , "int"

[Strings]
Msft = "Microsoft"
NdisLwf_Desc = "NDIS Sample LightWeight Filter"
NdisLwf_HelpText = "Sample to demonstrate NDIS LightWeight Filters"

The following NDIS filter driver installation issues are associated with modifying filter drivers. To create your own modifying filter driver INF file, you can also adapt the sample NDIS 6.0 filter driver.

  • Set the Class INF file entry to NetService in the INF file. The following example shows a sample Class entry for the INF file.

    Copy

    Class = NetService
  • The DDInstall section in a filter driver INF file must have a Characteristics entry. The following example shows how you should define the Characteristics entry in your filter INF file.

    Copy

    Characteristics=0x40000

    The 0×40000 value indicates that NCF_LW_FILTER (0×40000) is set. Filter drivers must not set the NCF_FILTER (0×400) flag. The values of the NCF_ Xxx flags are defined in Netcfgx.h. For more information about NCF_ Xxx flags, see DDInstall Section in a Network INF File.

  • Set the NetCfgInstanceId INF file entry in the INF file, as the following example shows.

    Copy

    NetCfgInstanceId="{5cbf81bd-5055-47cd-9055-a76b2b4e3697}"

    You can use the Uuidgen.exe tool to create the GUID for the NetCfgInstanceId entry.

  • The DDInstall section of the INF file for a filter driver must include an Addreg directive for an Ndi key. The INF file must specify the Service entry under the Ndi key. The ServiceBinary entry in the service-install section of the INF file specifies the path to the binary for the filter driver. For more information, see Adding Service-Related Values to the Ndi Key and DDInstall.Services Section in a Network INF File.

  • The DDInstall section in a filter driver INF file must have FilterType and FilterRunType entries. To specify a modifying filter, define the FilterType entry in your INF file, as the following example shows.

    Copy

    HKR, Ndi,FilterType,0x00010001 ,0x00000002

    The FilterType value 0×00000002 indicates that the filter is a modifying filter.

  • Define the FilterRunType entry in your INF file, as the following example shows.

    Copy

    HKR, Ndi,FilterRunType,0x00010001 ,0x00000001

    The 0×00000001 value in the preceding example indicates that the filter module is mandatory. To install an optional filer module, set the FilterRunType entry to 0×00000002.

  • The following example shows how a modifying filter driver INF file specifies the name of the service:

    Copy

    HKR, Ndi,Service,,"NdisLwf"

    In this example, NdisLwf is the name of the driver’s service as it is reported to NDIS. Note that the name of a filter driver’s service can be different from the name of the binary for the driver–but typically they are the same.

  • The following example shows how the filter INF file references the name of the filter driver’s service when it adds that service.

    Copy

    [Install.Services]
    AddService=NdisLwf,,NdisLwf_Service_Inst;, common.EventLog 
    
    [NdisLwf_Service_Inst]
    DisplayName     = %NdisLwf_Desc%
    ServiceType     = 1 ;SERVICE_KERNEL_DRIVER
    StartType       = 1 ;SERVICE_SYSTEM_START
    ErrorControl    = 1 ;SERVICE_ERROR_NORMAL
    ServiceBinary   = %12%\ndislwf.sys
    LoadOrderGroup  = NDIS
    Description     = %NdisLwf_Desc%
    AddReg          = Common.Params.reg
  • A filter INF file must specify at least the primary service name of the filter for the CoServices attribute, as the following example shows.

    Copy

    HKR, Ndi,CoServices,0x00010000,"NdisLwf"

    For more information about the CoServices attribute, see Adding Service-Related Values to the Ndi Key.

  • The FilterClass value in the INF file for a filter driver determines its order in a stack of filters. Filter drivers must define the FilterClass key. The class of the driver can be one of the values in the following table.

    Value

    Description

    scheduler

    Packet-scheduling filter service. This class of filter driver is the highest-level driver that can exist above encryption class filters in a driver stack. A packet scheduler detects the 802.1p priority classification that is given to packets by quality of service (QoS)-signaling components and the scheduler sends those packets levels to underlying drivers according to their priority.

    Encryption

    Encryption class filter drivers exist between scheduler and compression class filters.

    Compression

    Compression class filter drivers exist between encryption and vpn class filters.

    Vpn

    vpn class filter drivers exist between compression and load balance filter drivers.

    Loadbalance

    Load-balancing filter service. This class of filter driver exists between packet-scheduling and fail-over drivers. A load balancing filter service balances its workload of packet transfers by distributing the workload over its set of underlying miniport adapters.

    failover

    Fail-over filter service. This class of filter driver exists between load balance and diagnostics drivers.

    Diagnostic

    Diagnostic filter drivers exists below failover drivers in the stack.

    Custom

    Filter drivers in custom class exist below diagnostic drivers.

    Note More than one filter driver of a specific class can exist in a layered stack of modifying filter drivers. For example, two modifying filter drivers of FilterClass "scheduler" can exist in a stack simultaneously. The filter driver that has a later installation timestamp is installed below (that is, closer to the miniport adapter) the filter driver with the earlier timestamp. However, the order of multiple filter drivers with the same class is exactly the same over different miniport adapters on the same computer.

    The following example shows a sample FilterClass .

    Copy

    HKR, Ndi,FilterClass,, compression
  • You must define the following entries in the modifying filter driver INF file to control the driver bindings:

    Copy

    HKR, Ndi\Interfaces,UpperRange,,"noupper"
    HKR, Ndi\Interfaces,LowerRange,,"nolower"
    HKR, Ndi\Interfaces, FilterMediaTypes,,"ethernet"

    For more information about controlling the driver bindings, see Specifying Filter Driver Binding Relationships.

  • A modifying filter INF file should specify common parameter definitions for the driver and parameters that are associated with a specific adapter. The following example shows some common parameter definitions.

    Copy

    [Common.Params.reg]
    
    HKR, FilterDriverParams\DriverParam,  ParamDesc, , "Driverparam for lwf"
    HKR, FilterDriverParams\DriverParam,  default, , "5"
    HKR, FilterDriverParams\DriverParam,  type,  , "int"
    
    HKR, FilterAdapterParams\AdapterParam,  ParamDesc, , "Adapterparam for lwf"
    HKR, FilterAdapterParams\AdapterParam,  default, , "10"
    HKR, FilterAdapterParams\AdapterParam,  type,  , "int"

Send comments about this topic to Microsoft

Build date: 2/9/2011

© 2011 Microsoft. All rights reserved.

NdisAllocateNetBufferMdlAndData分配出来的NET_BUFFER,初始值CurrentMdl指向MdlChain。

CurrentMdlOffset和DataOffset都是Buffer的长度,所以在用之前一定要先初始化。

NDIS 6.0开始用这个结构,就相当于以前的NDIS_PACKET。NET_BUFFER_LIST里面连接的多个NET_BUFFER就是同一TCP连接或UDP里的一系列的包。而NET_BUFFER_LIST之间也就谁也不鸟谁了,可能是完全不搭界的包,向上下层提交的时候也可以以NET_BUFFER_LIST为单位分着来。

一般NDIS接收的包都是一整块内存,发的时候内存是分块的。现在没有了NDIS_BUFFER,直接用MDL了。

NET_BUFFER_1

NET_BUFFER结构里CurrentMdl和MdlChain比较有意思。按我的理解是,比如MdlChain里可以串几个MDL,比如说3个,但我可以让CurrentMdl指向第2个,当发出去或者收进来的时候,都以第2个为开始,相当于MdlChain[0]只是挂在那,它的内容完全完全被忽略。

这张图里的是我随便断下来的一个包,NET_BUFFER->Next是空。也就是只是单独的一个数据包或者说Eth Frame。CurrentMdl和MdlChain指向的是同一个MDL。

CurrentMdlOffset表示包内容在MDL(指示的内存)里的偏移,也就是 包内容起始位置 = MDL’s MappedSystemVa + CurrentMdlOffset。

DataOffset按上面说的那种情况貌似就应该是 包内容起始位置 = MdlChain[0]’s length + CurrentMdl’s MappedSystemVa +CurrentMdlOffset。

NET_BUFFER_2

CurrentMdl里面连着另一个MDL,这个是从发包的时候断下来的,发出去的包基本上都是分层的。

NET_BUFFER->DataLength是数据的长度,在图片里的这种情况里:
DataLength = CurrentMdl->ByteCount – CurrentMdlOffset + NextMdl’s ByteCount

如果CurrentMdl->ByteCount – CurrentMdlOffset 小于DataLength,说明数据不只在一个MDL里,后面还有。

stDataLength不知道干嘛的。

很奇怪, Win7 pdb里的NET_BUFFER结构和WDK文档里的不一样

kd> dt ndis!_NET_BUFFER
   +0×000 Next             : Ptr32 _NET_BUFFER
   +0×004 CurrentMdl       : Ptr32 _MDL
   +0×008 CurrentMdlOffset : Uint4B
   +0×00c DataLength       : Uint4B
   +0×00c stDataLength     : Uint4B
   +0×010 MdlChain         : Ptr32 _MDL
   +0×014 DataOffset       : Uint4B
   +0×000 Link             : _SLIST_HEADER
   +0×018 ChecksumBias     : Uint2B
   +0×01a Reserved         : Uint2B
   +0×01c NdisPoolHandle   : Ptr32 Void
   +0×020 NdisReserved     : [2] Ptr32 Void
   +0×028 ProtocolReserved : [6] Ptr32 Void
   +0×040 MiniportReserved : [4] Ptr32 Void
   +0×050 DataPhysicalAddress : _LARGE_INTEGER
   +0×058 SharedMemoryInfo : Ptr32 _NET_BUFFER_SHARED_MEMORY
   +0×058 ScatterGatherList : Ptr32 _SCATTER_GATHER_LIST