Čeština / English
Login

SVN Repository / Prohlížení

Aktuální adresář: FITkit / trunk / mcu / libs / enc28j60 /

enc28j60_spi_tx.c

   1  /*******************************************************************************
   2  
   3     Copyright (C) 2010 Brno University of Technology,
   4                        Faculty of Information Technology
   5     Author(s): Martin Musil <xmusil34 AT fit.vutbr.cz>
   6  
   7     LICENSE TERMS
   8  
   9     Redistribution and use in source and binary forms, with or without
  10     modification, are permitted provided that the following conditions
  11     are met:
  12     1. Redistributions of source code must retain the above copyright
  13        notice, this list of conditions and the following disclaimer.
  14     2. Redistributions in binary form must reproduce the above copyright
  15        notice, this list of conditions and the following disclaimer in
  16        the documentation and/or other materials provided with the
  17        distribution.
  18     3. All advertising materials mentioning features or use of this software
  19        or firmware must display the following acknowledgement:
  20  
  21          This product includes software developed by the University of
  22          Technology, Faculty of Information Technology, Brno and its
  23          contributors.
  24  
  25     4. Neither the name of the Company nor the names of its contributors
  26        may be used to endorse or promote products derived from this
  27        software without specific prior written permission.
  28  
  29     This software or firmware is provided ``as is'', and any express or implied
  30     warranties, including, but not limited to, the implied warranties of
  31     merchantability and fitness for a particular purpose are disclaimed.
  32     In no event shall the company or contributors be liable for any
  33     direct, indirect, incidental, special, exemplary, or consequential
  34     damages (including, but not limited to, procurement of substitute
  35     goods or services; loss of use, data, or profits; or business
  36     interruption) however caused and on any theory of liability, whether
  37     in contract, strict liability, or tort (including negligence or
  38     otherwise) arising in any way out of the use of this software, even
  39     if advised of the possibility of such damage.
  40  
  41     $Id$
  42  
  43  *******************************************************************************/
  44  
  45  #include "enc28j60_spi_tx.h"
  46  #include "enc28j60_spi.h"
  47  #include "fspi.h"
  48  
  49  //hlavni ukazatele pro praci s buffery
  50  unsigned int tx_ptr;
  51  unsigned int tx_end_ptr;
  52  unsigned int TXST;
  53  unsigned int TXND;
  54  
  55  //promenna, znaci aktualni buffer
  56  unsigned char act_tx;
  57  
  58  //zamek bufferu
  59  #define LOCKED 1
  60  #define UNLOCKED 0
  61  char tx1_lock = UNLOCKED;
  62  char tx2_lock = UNLOCKED;
  63  char tx3_lock = UNLOCKED;
  64  
  65  //promenne pro ulozeni protokolu, ktery se pres ne odesila
  66  char tx1_protocol;
  67  char tx2_protocol;
  68  char tx3_protocol;
  69  
  70  //ukazatele pro jednotlive buffery, slouzi pro uchovavani hodnot behem prepinani
  71  unsigned int tx1_ptr;
  72  unsigned int tx2_ptr;
  73  unsigned int tx3_ptr;
  74  
  75  unsigned int tx1_end_ptr;
  76  unsigned int tx2_end_ptr;
  77  unsigned int tx3_end_ptr;
  78  
  79  //vnitrni pomocne funkce
  80  char tx_protocol(unsigned char protocol);
  81  
  82  
  83  //************************************************
  84  //odesilaci buffer
  85  //************************************************
  86  
  87  /**
  88  
  89   **/
  90  char tx_init(unsigned char protocol){
  91  
  92  	int timer = TIMEOUT;					//timeout
  93  
  94  	//kontrola dokonceni odesilani predchoziho paketu
  95  	while((read_reg8(ECON1,NO_DUMMY) & ECON1_TXRTS) && (timer-- > 0) );
  96  
  97  	if(timer == 0)						//timeout vyprsel
  98  		return -1;
  99  
 100  	//buffer pro UDP pakety
 101  	if(protocol == UDP_PROTO){
 102  
 103  		if(tx1_lock == LOCKED){					//tx1 ma zamek,aby nedoslo k nahodnemu prepsani jeste
 104  			return -1;							//neodeslaneho obsahu bufferu jinym. napr. pri odesilani
 105  		}										//paketu z obsluhy preruseni
 106  
 107  		tx1_lock = LOCKED;
 108  		tx_save(act_tx);
 109  
 110  		TXST = TX1ST;							//restart ukazatelu na zacatek a konec vyhrazene pameti
 111  		TXND = TX1ND;
 112  		act_tx = TX1;							//bufferem je TX1
 113  
 114  		select_bank(0);
 115  
 116  		write_reg16(ETXST,TXST);				// zapsani ukazatele na zacatek bufferu do ENC28
 117  		write_reg16(ETXND,TXST);
 118  
 119  		tx_ptr = TX1ST;							//inicializace ukazatele do bufferu
 120  		tx1_ptr	= TX1ST;						//nastaveni pomocnych ukazatelu (jsou pro
 121  		tx1_end_ptr	= TX1ST;					// uchovani hodnot behem prepinani funkcemi tx_save a tx_load)
 122  		tx1_protocol = protocol;
 123  
 124  		return tx_protocol(protocol);
 125  	}
 126  
 127  	//buffer pro TCP pakety
 128  	else if(protocol == TCP_PROTO){
 129  
 130  		if(tx3_lock == LOCKED){					//tx3 ma zamek, zde u TCP slouzi k tomu, aby nebylo mozne
 131  			return -1;							//odesilat dalsi paket, dokud predchozi nebyl odeslan
 132  		}										//   zamek odemyka stavovy automat TCP spojeni
 133  		tx3_lock = LOCKED;
 134  
 135  		tx_save(act_tx);
 136  
 137  		TXST = TX3ST;							//restart ukazatelu na zacatek a konec vyhrazene pameti
 138  		TXND = TX3ND;
 139  		act_tx = TX3;							//bufferem je TX3
 140  
 141  		select_bank(0);
 142  
 143  		write_reg16(ETXST,TXST);				// zapsani ukazatele na zacatek bufferu do ENC28
 144  		write_reg16(ETXND,TXST);
 145  
 146  		tx_ptr = TX3ST;							//inicializace ukazatele do bufferu
 147  		tx3_ptr	= TX3ST;						//nastaveni pomocnych ukazatelu (jsou pro
 148  		tx3_end_ptr	= TX3ST;					// uchovani hodnot behem prepinani funkcemi tx_save a tx_load)
 149  		tx3_protocol = protocol;
 150  
 151  		return tx_protocol(protocol);
 152  	}
 153  
 154  	//buffer pro automaticke odpovedi a ARP dotazy
 155  	else if((protocol == ICMP_PROTO) | (protocol == TCP_PROTO_HEADER_ONLY)){
 156  
 157  		if(tx2_lock == LOCKED){					//tx2 ma zamek,aby nedoslo k nahodnemu prepsani jeste
 158  			return -1;							//neodeslaneho obsahu bufferu jinym. napr. pri odesilani
 159  		}										//paketu z obsluhy preruseni
 160  
 161  		tx2_lock = LOCKED;
 162  		tx_save(act_tx);
 163  
 164  		TXST = TX2ST;							//restart ukazatelu na zacatek a konec vyhrazene pameti
 165  		TXND = TX2ND;
 166  		act_tx = TX2;							//bufferem je TX2
 167  
 168  		select_bank(0);
 169  
 170  		write_reg16(ETXST,TXST);				// zapsani ukazatele na zacatek bufferu do ENC28
 171  		write_reg16(ETXND,TXST);				// --||-- konec
 172  
 173  		tx_ptr = TX2ST;							//inicializace ukazatele do bufferu
 174  		tx2_ptr = TX2ST;						//nastaveni pomocnych ukazatelu (jsou pro
 175  		tx2_end_ptr = TX2ST;					// uchovani hodnot behem prepinani funkcemi tx_save a tx_load)
 176  		tx2_protocol = protocol;
 177  
 178  		return tx_protocol(protocol);
 179  	}
 180  	else if((protocol == ARP_PROTO)){
 181  
 182  		tx_save(act_tx);
 183  
 184  		TXST = TX4ST;							//restart ukazatelu na zacatek a konec vyhrazene pameti
 185  		TXND = TX4ND;
 186  		act_tx = TX4;							//bufferem je TX4
 187  
 188  		select_bank(0);
 189  
 190  		write_reg16(ETXST,TXST);				// zapsani ukazatele na zacatek bufferu do ENC28
 191  		write_reg16(ETXND,TXST);				// --||-- konec
 192  
 193  		tx_ptr = TX4ST;							//inicializace ukazatele do bufferu
 194  
 195  		return tx_protocol(protocol);
 196  	}
 197  
 198  
 199  return -1;
 200  }
 201  
 202  /*Fce pro preskoceni mista pro hlavicky podle pouziteho protokolu*/
 203  char tx_protocol(unsigned char protocol){
 204  
 205  	switch(protocol){
 206  		case TCP_PROTO_HEADER_ONLY:
 207  		case TCP_PROTO:
 208  			tx_ptr = TXST + CTRL_LEN + ETH_HEADER_LEN + IP_HEADER_LEN + TCP_HEADER_LEN;
 209  			break;
 210  		case UDP_PROTO:
 211  			tx_ptr = TXST + CTRL_LEN + ETH_HEADER_LEN + IP_HEADER_LEN + UDP_HEADER_LEN;
 212  			break;
 213  		case ICMP_PROTO:
 214  			tx_ptr = TXST + CTRL_LEN + ETH_HEADER_LEN + IP_HEADER_LEN + ICMP_HEADER_LEN;
 215  			break;
 216  		case ARP_PROTO:
 217  			tx_ptr = TXST + CTRL_LEN + ETH_HEADER_LEN;
 218  			break;
 219  		default:
 220  			return -1;
 221  	}
 222  
 223  	select_bank(0);
 224  	write_reg16(EWRPT,tx_ptr);							//posun na zacatek datove casti
 225  
 226  return 0;
 227  }
 228  
 229  /**
 230  
 231  
 232   **/
 233  void tx_rewind(){
 234  
 235  	switch(act_tx){
 236  		case TX1:
 237  			tx_protocol(tx1_protocol);
 238  			break;
 239  		case TX2:
 240  			tx_protocol(tx2_protocol);
 241  			break;
 242  		case TX3:
 243  			tx_protocol(tx3_protocol);
 244  			break;
 245  	}
 246  }
 247  
 248  
 249  
 250  /**
 251  
 252   **/
 253  void tx_seek(unsigned char header){
 254  	switch(header){
 255  		case CTRL:
 256  			tx_ptr = TXST;
 257  			break;
 258  		case ETH_HEADER:
 259  			tx_ptr = TXST + CTRL_LEN;
 260  			break;
 261  		case IP_HEADER:
 262  			tx_ptr = TXST + CTRL_LEN + ETH_HEADER_LEN;
 263  			break;
 264  		case ICMP_HEADER:
 265  		case TCP_HEADER:
 266  		case UDP_HEADER:
 267  			tx_ptr = TXST + CTRL_LEN + ETH_HEADER_LEN + IP_HEADER_LEN;
 268  			break;
 269  	}
 270  
 271  	select_bank(0);
 272  	write_reg16(EWRPT,tx_ptr);
 273  return;
 274  }
 275  
 276  /**
 277  
 278  
 279  
 280   **/
 281  inline void tx_close(){
 282  	select_bank(0);
 283  	tx_end_ptr = tx_ptr;
 284  	write_reg16(ETXND,tx_end_ptr-1);		//tx_end_ptr ukazatel ukazuje na misto, kde jeste neni nic zapsano, proto -1
 285  }											//ETXND musi ukazovat na posledni bajt dat
 286  
 287  
 288  /**
 289  
 290   **/
 291  void tx_save(unsigned char buffer){
 292  
 293  		//ulozeni stavu predchoziho bufferu
 294  		switch(buffer){
 295  			case TX1:
 296  				tx1_ptr = tx_ptr;		//ulozeni stavu TX1
 297  				tx1_end_ptr	= tx_end_ptr;
 298  				break;
 299  
 300  			case TX2:
 301  				tx2_ptr = tx_ptr;		//ulozeni stavu TX2
 302  				tx2_end_ptr	= tx_end_ptr;
 303  				break;
 304  
 305  			case TX3:
 306  				tx3_ptr = tx_ptr;		//ulozeni stavu TX3
 307  				tx3_end_ptr	= tx_end_ptr;
 308  				break;
 309  		}
 310  return;
 311  }
 312  
 313  
 314  /**
 315  
 316   **/
 317  void tx_load(unsigned char buffer){
 318  
 319  		switch(buffer){
 320  			case TX1:
 321  				TXST = TX1ST;			//obnoveni stavu pro TX1
 322  				TXND = TX1ND;
 323  				tx_ptr = tx1_ptr;
 324  				tx_end_ptr = tx1_end_ptr;
 325  				act_tx = TX1;
 326  				break;
 327  
 328  			case TX2:
 329  				TXST = TX2ST;			//obnoveni stavu pro TX2
 330  				TXND = TX2ND;
 331  				tx_ptr = tx2_ptr;
 332  				tx_end_ptr = tx2_end_ptr;
 333  				act_tx = TX2;
 334  				break;
 335  
 336  			case TX3:
 337  				TXST = TX3ST;			//obnoveni stavu pro TX3
 338  				TXND = TX3ND;
 339  				tx_ptr = tx3_ptr;
 340  				tx_end_ptr = tx3_end_ptr;
 341  				act_tx = TX3;
 342  				break;
 343  		}
 344  
 345  	write_reg16(EWRPT,tx_ptr);		// nastaveni ukazatele pro zapis
 346  	write_reg16(ETXST,TXST);		// zapsani ukazatele na zacatek bufferu do ENC28
 347  	write_reg16(ETXND,tx_end_ptr-1);		//tx_end_ptr ukazatel ukazuje na misto, kde jeste neni nic zapsano, proto -1
 348  											//ETXND musi ukazovat na posledni bajt dat
 349  
 350  return;
 351  }
 352  
 353  /**
 354  
 355   **/
 356  unsigned char tx_act(){
 357  
 358  	return act_tx;
 359  }
 360  
 361  /**
 362  
 363   **/
 364  unsigned char tx_putc(char c){
 365  
 366  	if(tx_ptr > TXND)
 367  		return 0;
 368  	else{
 369  		spi_putc(c);
 370  		tx_ptr++;
 371  		return 1;
 372  	}
 373  }
 374  
 375  /**
 376  
 377   **/
 378  unsigned int tx_write(void* ptr, unsigned int length){
 379  
 380  	int remaining = tx_left();
 381  
 382  	if(tx_ptr > TXND)
 383  		return 0;
 384  	else if(length >= remaining){
 385  		spi_write(ptr, remaining);
 386  		tx_ptr += remaining;
 387  		return remaining;
 388  	}
 389  	else{
 390  		spi_write(ptr, length);
 391  		tx_ptr += length;
 392  		return length;
 393  	}
 394  return 0;
 395  }
 396  
 397  /**
 398  
 399   **/
 400  unsigned int tx_fill(unsigned char value, unsigned int length){
 401  
 402  	int remaining = tx_left();
 403  
 404  	if(tx_ptr > TXND)
 405  		return 0;
 406  	else if(length >= remaining){
 407  		spi_fill(value, remaining);
 408  		tx_ptr += remaining;
 409  		return remaining;
 410  	}
 411  	else{
 412  		spi_fill(value, length);
 413  		tx_ptr += length;
 414  		return length;
 415  	}
 416  return 0;
 417  }
 418  
 419  /**
 420  
 421  
 422   **/
 423  unsigned int tx_skip(unsigned int length){
 424  
 425  	int remaining = tx_left();
 426  
 427  	if(tx_ptr > TXND)
 428  		return 0;
 429  	else if(length >= remaining){
 430  		tx_ptr += remaining;
 431  		write_reg16(EWRPT,tx_ptr);
 432  		return remaining;
 433  	}
 434  	else{
 435  		tx_ptr += length;
 436  		write_reg16(EWRPT,tx_ptr);
 437  		return length;
 438  	}
 439  return 0;
 440  }
 441  
 442  /**
 443  
 444   **/
 445  char tx_send(){
 446  
 447  	int timer = TIMEOUT;					//timeout
 448  
 449  	while(( (read_reg8(ECON1,NO_DUMMY) & ECON1_TXRTS) > 0) & (timer-- > 0) );	//kontrola odeslani predchoziho paketu
 450  
 451  
 452  	if(timer == 0){						//timeout vyprsel
 453  		if(act_tx == TX1){				//odemknuti TX1 po nevydarenem odeslani
 454  			tx_unlock(TX1);
 455  		}
 456  		else if(act_tx == TX2){
 457  			tx_unlock(TX2);
 458  		}
 459  		return -1;
 460  	}
 461  
 462  	// prepsani registru s nastavenim  paddingu,crc... sam od sebe se nejak "maze"
 463  	//mozna hw zavada vybranyho kousku
 464  	select_bank(2);
 465  	write_reg8(MACON3,MACON3_PADCFG0 | MACON3_TXCRCEN | MACON3_FULDPX);
 466  
 467  	bf_set(ECON1,ECON1_TXRTS);
 468  
 469  	if(act_tx == TX1){					//odemknuti TX1
 470  		tx_unlock(TX1);
 471  	}
 472  	else if(act_tx == TX2){
 473  		tx_unlock(TX2);
 474  	}
 475  return 0;
 476  }
 477  
 478  
 479  /**
 480  
 481   **/
 482  inline unsigned int tx_left(){
 483  
 484  return TXND - tx_ptr +1;	//kompenzace, TXND je posledni bajt zpravy, tx_ptr tam musi umoznit zapisovat
 485  }
 486  
 487  /**
 488  
 489   **/
 490  inline unsigned int tx_data_len(){
 491  
 492  return tx_end_ptr - tx_ptr;
 493  }
 494  
 495  /**
 496  
 497   **/
 498  unsigned int tx_checksum(){
 499  
 500  	//vyuziti vnitrniho DMA radice v ENC28J60 pro spocitani checksumu
 501  	select_bank(0);
 502  	write_reg16(EDMAST,tx_ptr);
 503  	write_reg16(EDMAND,tx_end_ptr -1);
 504  	bf_clear(EIR,EIR_DMAIF);
 505  
 506  	bf_set(ECON1,ECON1_CSUMEN | ECON1_DMAST);
 507  
 508  	while((read_reg8(EIR,NO_DUMMY) & EIR_DMAIF ) == 0);
 509  
 510  	return read_reg16(EDMACS,NO_DUMMY);
 511  
 512  }
 513  
 514  
 515  /**
 516  
 517   **/
 518  inline void tx_unlock(unsigned char buffer){
 519  
 520  	if(buffer == TX1)
 521  		tx1_lock = UNLOCKED;
 522  	else if(buffer == TX2)
 523  		tx2_lock = UNLOCKED;
 524  	else if(buffer == TX3)
 525  		tx3_lock = UNLOCKED;
 526  
 527  return;
 528  }
 529  
Zobrazeno: 597158x Naposledy: 27.1.2022 15:48:03