/* * */ #include #include #include "bsp.h" #include "w5500.h" #include "socket.h" #include "types.h" #ifdef __DEF_IINCHIP_PPP__ #include "md5.h" #endif static uint8_t rxbuf[W5500BUFLEN+8]={0}; static uint8_t txbuf[W5500BUFLEN+8]={0}; static uint16_t SSIZE[MAX_SOCK_NUM]; /**< Max Tx buffer size by each channel */ static uint16_t RSIZE[MAX_SOCK_NUM]; /**< Max Rx buffer size by each channel */ /********************************************************************/ uint16_t getIINCHIP_RxMAX(uint8_t s) { return RSIZE[s]; } uint16_t getIINCHIP_TxMAX(uint8_t s) { return SSIZE[s]; } void IINCHIP_WRITE( uint32_t addrbsb, uint8_t data) { IINCHIP_ISR_DISABLE(); // Interrupt Service Routine Disable BSP_W5500_Enable(); // CS=0, SPI start txbuf[0] = (uint8_t)( (addrbsb & 0x00FF0000)>>16);// Address byte 1 txbuf[1] = (uint8_t)( (addrbsb & 0x0000FF00)>> 8);// Address byte 2 txbuf[2] = (uint8_t)( (addrbsb & 0x000000F8) | 5); // Data write command and Write data length 1 txbuf[3] = (uint8_t)( data ); // Data write (write 1byte data) BSP_W5500_Write(txbuf,4); BSP_W5500_Disable(); // CS=1, SPI end IINCHIP_ISR_ENABLE(); // Interrupt Service Routine Enable } uint8_t IINCHIP_READ(uint32_t addrbsb) { uint32_t status=0; IINCHIP_ISR_DISABLE(); // Interrupt Service Routine Disable BSP_W5500_Enable(); // CS=0, SPI start txbuf[0] = (uint8_t)( (addrbsb & 0x00FF0000)>>16);// Address byte 1 txbuf[1] = (uint8_t)( (addrbsb & 0x0000FF00)>> 8);// Address byte 2 txbuf[2] = (uint8_t)( (addrbsb & 0x000000F8) | 0x01);// Data read command and Read data length 1 status=BSP_W5500_Write(txbuf,3); status++; /*status=BSP_W5500_Read(rxbuf, 1); status++; SPIx_WriteRead(txbuf[0]); SPIx_WriteRead(txbuf[1]); SPIx_WriteRead(txbuf[2]);*/ status = BSP_W5500_WriteRead(0); rxbuf[0]=status; BSP_W5500_Disable(); // CS=1, SPI end IINCHIP_ISR_ENABLE(); // Interrupt Service Routine Enable return rxbuf[0]; } uint16_t wiz_write_buf(uint32_t addrbsb, uint8_t* buf, uint16_t len) { uint16_t idx = 0; /*uint32_t time1=HAL_GetTick(); uint32_t time2; uint8_t debugbuf[24]={0};*/ if(len == 0) { printf("Unexpected2 length 0\r\n"); } IINCHIP_ISR_DISABLE(); BSP_W5500_Enable(); // CS=0, SPI start txbuf[0] = (uint8_t)( (addrbsb & 0x00FF0000)>>16);// Address byte 1 txbuf[1] = (uint8_t)( (addrbsb & 0x0000FF00)>> 8);// Address byte 2 txbuf[2] = (uint8_t)( (addrbsb & 0x000000F8) + 4);// Data write command and Write data length 1 for(idx = 0; idx < len; idx++) // Write data in loop { txbuf[idx + 3] = (uint8_t)(buf[idx]); } BSP_W5500_Write(txbuf,idx+3); BSP_W5500_Disable(); // CS=1, SPI end IINCHIP_ISR_ENABLE(); // Interrupt Service Routine Enable /*time2=HAL_GetTick(); time1 = sprintf(debugbuf,"%d~%d\r\n",time1,time2); ReportMessage(debugbuf,time1);*/ return len; } uint16_t wiz_read_buf(uint32_t addrbsb, uint8_t* buf,uint16_t len) { //uint16_t idx = 0; //if recv data len is 0, print "Unexpected2 length 0" via com port if(len == 0) { printf("Unexpected2 length 0\r\n"); } BSP_W5500_Enable(); // clear CS=0, SPI enabled txbuf[0] = (uint8_t)( (addrbsb & 0x00FF0000)>>16); // send address to MCU txbuf[1] = (uint8_t)( (addrbsb & 0x0000FF00)>> 8); // txbuf[2] = (uint8_t)( (addrbsb & 0x000000F8)); // Set SPI to read operation BSP_W5500_Write(txbuf,3); BSP_W5500_Read(buf, len); BSP_W5500_Disable(); // set CS=1, SPI disabled return len; } /********************************************************************/ /** @brief This function is for resetting of the iinchip. Initializes the iinchip to work in whether DIRECT or INDIRECT mode */ void iinchip_init(void) { setMR( MR_RST ); #ifdef __DEF_IINCHIP_DBG__ printf("MR value is %02x \r\n",IINCHIP_READ_COMMON(MR)); #endif } /** @brief This function set the transmit & receive buffer size as per the channels is used Note for TMSR and RMSR bits are as follows\n bit 1-0 : memory size of channel #0 \n bit 3-2 : memory size of channel #1 \n bit 5-4 : memory size of channel #2 \n bit 7-6 : memory size of channel #3 \n bit 9-8 : memory size of channel #4 \n bit 11-10 : memory size of channel #5 \n bit 12-12 : memory size of channel #6 \n bit 15-14 : memory size of channel #7 \n Maximum memory size for Tx, Rx in the W5500 is 16K Bytes,\n In the range of 16KBytes, the memory size could be allocated dynamically by each channel.\n Be attentive to sum of memory size shouldn't exceed 8Kbytes\n and to data transmission and receiption from non-allocated channel may cause some problems.\n If the 16KBytes memory is already assigned to centain channel, \n other 3 channels couldn't be used, for there's no available memory.\n If two 4KBytes memory are assigned to two each channels, \n other 2 channels couldn't be used, for there's no available memory.\n */ void sysinit(const uint8_t * tx_size, const uint8_t * rx_size ) { int16_t i; int16_t ssum,rsum; #ifdef __DEF_IINCHIP_DBG__ printf("sysinit()\r\n"); #endif ssum = 0; rsum = 0; for (i = 0 ; i < MAX_SOCK_NUM; i++) // Set the size, masking and base address of Tx & Rx memory by each channel { IINCHIP_WRITE( (Sn_TXMEM_SIZE(i)), tx_size[i]); IINCHIP_WRITE( (Sn_RXMEM_SIZE(i)), rx_size[i]); #ifdef __DEF_IINCHIP_DBG__ printf("tx_size[%d]: %d, Sn_TXMEM_SIZE = %d\r\n",i, tx_size[i], IINCHIP_READ(Sn_TXMEM_SIZE(i))); printf("rx_size[%d]: %d, Sn_RXMEM_SIZE = %d\r\n",i, rx_size[i], IINCHIP_READ(Sn_RXMEM_SIZE(i))); #endif SSIZE[i] = (int16_t)(0); RSIZE[i] = (int16_t)(0); // There are 8 Socket in W5500, and every socket has his own send/recv buffer independently. // Total buffer for all socket is located in the 16KB physical memory and when initializing, each socket has 2KB. // Make sure sum of all the buffer is not larger than 16KB. if (ssum <= 16384) // send buffer of Socket { switch( tx_size[i] ) { case 1: SSIZE[i] = (int16_t)(1024); // i=1, tx_size=1KB break; case 2: SSIZE[i] = (int16_t)(2048); // i=2, tx_size=2KB break; case 4: SSIZE[i] = (int16_t)(4096); // i=4, tx_size=4KB break; case 8: SSIZE[i] = (int16_t)(8192); // i=8, tx_size=8KB break; case 16: SSIZE[i] = (int16_t)(16384); // i=16, tx_size=16KB break; default : RSIZE[i] = (int16_t)(2048); // i=2, tx_size=2KB, default break; } } if (rsum <= 16384) // recv buffer of Socket { switch( rx_size[i] ) { case 1: RSIZE[i] = (int16_t)(1024); // i=1, rx_size=1KB break; case 2: RSIZE[i] = (int16_t)(2048); // i=2, rx_size=2KB break; case 4: RSIZE[i] = (int16_t)(4096); // i=4, rx_size=4KB break; case 8: RSIZE[i] = (int16_t)(8192); // i=8, rx_size=8KB break; case 16: RSIZE[i] = (int16_t)(16384); // i=16, rx_size=16KB break; default : RSIZE[i] = (int16_t)(2048); // i=2, rx_size=2K, default break; } } ssum += SSIZE[i]; rsum += RSIZE[i]; } } /********************************************************************/ /** @brief It sets up mode */ void setMR(uint8_t val) { IINCHIP_WRITE(MR,val); } /** @brief It sets up gateway address */ void setGAR(uint8_t * addr) { wiz_write_buf(GAR0, addr, 4); } /** @brief It sets up SubnetMask address */ void setSUBR(uint8_t * addr) { wiz_write_buf(SUBR0, addr, 4); } /** @brief This function sets up MAC address. **< a pointer to a 6 -byte array responsible to set the MAC address. */ void setSHAR(uint8_t * addr) { wiz_write_buf(SHAR0, addr, 6); } /** @brief This function sets up Source IP address. **< a pointer to a 4 -byte array responsible to set the Source IP address. */ void setSIPR(uint8_t * addr) { wiz_write_buf(SIPR0, addr, 4); } /** @brief This function set the interrupt mask Enable/Disable appropriate Interrupt. ('1' : interrupt enable) If any bit in IMR is set as '0' then there is not interrupt signal though the bit is set in IR register. */ void setIR(uint8_t val) { IINCHIP_WRITE(IR, val); } void clearIR(uint8_t mask) { IINCHIP_WRITE(IR, ~mask | getIR() ); // must be setted 0x10. } void setIMR(uint8_t val) { IINCHIP_WRITE(IMR, val); } void setSIR(uint8_t val) { IINCHIP_WRITE(SIR, val); } void setSIMR(uint8_t val) { IINCHIP_WRITE(SIMR, val); } /** @brief This function sets up Retransmission time. If there is no response from the peer or delay in response then retransmission will be there as per RTR (Retry Time-value Register)setting */ void setRTR(uint16_t timeout) { IINCHIP_WRITE(RTR0,(uint8_t)((timeout & 0xff00) >> 8)); IINCHIP_WRITE(RTR1,(uint8_t)(timeout & 0x00ff)); } /** @brief This function set the number of Retransmission. If there is no response from the peer or delay in response then recorded time as per RTR & RCR register seeting then time out will occur. */ void setRCR(uint8_t retry) { IINCHIP_WRITE(RCR,retry); } void setPHYCFGR(uint8_t val) { IINCHIP_WRITE(PHYCFGR, val); } /********************************************************************/ /** @brief Thess function get registers' value. */ uint8_t getMR( void ) { return IINCHIP_READ(MR); } void getGAR(uint8_t * addr) { wiz_read_buf(GAR0, addr, 4); } void getSUBR(uint8_t * addr) { wiz_read_buf(SUBR0, addr, 4); } void getSHAR(uint8_t * addr) { wiz_read_buf(SHAR0, addr, 6); } void getSIPR(uint8_t * addr) { wiz_read_buf(SIPR0, addr, 4); } uint8_t getIR( void ) { return IINCHIP_READ(IR); } uint8_t getIMR(void) { return IINCHIP_READ(IMR); } uint8_t getSIR( void) { return IINCHIP_READ(SIR); } uint8_t getSIMR(void) { return IINCHIP_READ(SIMR); } uint8_t getPHYCFGR( void) { return IINCHIP_READ(PHYCFGR); } uint8_t getVersion(void) { return IINCHIP_READ(VERSIONR); } /********************************************************************/ uint8_t getSn_MR(SOCKET s) { return IINCHIP_READ(Sn_MR(s)); } void setSn_MR(uint8_t s, uint8_t val) { IINCHIP_WRITE(Sn_MR(s), val); } uint8_t getSn_CR(SOCKET s) { return IINCHIP_READ(Sn_CR(s)); } void setSn_CR(uint8_t s, uint8_t val) { IINCHIP_WRITE(Sn_CR(s), val); } /** @brief get socket interrupt status These below functions are used to read the Interrupt & Soket Status register */ uint8_t getSn_IR(SOCKET s) { return IINCHIP_READ(Sn_IR(s)); } void setSn_IR(uint8_t s, uint8_t val) { IINCHIP_WRITE(Sn_IR(s), val); } uint8_t getSn_IMR(SOCKET s) { return IINCHIP_READ(Sn_IMR(s)); } void setSn_IMR(uint8_t s, uint8_t val) { IINCHIP_WRITE(Sn_IMR(s), val); } /** @brief get socket status */ uint8_t getSn_SR(SOCKET s) { return IINCHIP_READ(Sn_SR(s)); } /** @brief This sets the maximum segment size of TCP in Active Mode), while in Passive Mode this is set by peer */ void setSn_MSS(SOCKET s, uint16_t Sn_MSSR) { IINCHIP_WRITE( Sn_MSSR0(s), (uint8_t)((Sn_MSSR & 0xff00) >> 8)); IINCHIP_WRITE( Sn_MSSR1(s), (uint8_t)(Sn_MSSR & 0x00ff)); } void setSn_TTL(SOCKET s, uint8_t ttl) { IINCHIP_WRITE( Sn_TTL(s) , ttl); } /** @brief get socket TX free buf size This gives free buffer size of transmit buffer. This is the data size that user can transmit. User shuold check this value first and control the size of transmitting data */ uint16_t getSn_TX_FSR(SOCKET s) { uint16_t val=0,val1=0; do { val1 = IINCHIP_READ(Sn_TX_FSR0(s)); val1 = (val1 << 8) + IINCHIP_READ(Sn_TX_FSR1(s)); if (val1 != 0) { val = IINCHIP_READ(Sn_TX_FSR0(s)); val = (val << 8) + IINCHIP_READ(Sn_TX_FSR1(s)); } } while (val != val1); return val; } /** @brief get socket RX recv buf size This gives size of received data in receive buffer. */ uint16_t getSn_RX_RSR(SOCKET s) { uint16_t val=0,val1=0; do { val1 = IINCHIP_READ(Sn_RX_RSR0(s)); // MCU read low byte of Sn_RX_RSR val1 = (val1 << 8) + IINCHIP_READ(Sn_RX_RSR1(s)); //read the high byte of it, and add the low to make whole value if(val1 != 0) // if Sn_RX_RSR is not 0,read it again { val = IINCHIP_READ(Sn_RX_RSR0(s)); val = (val << 8) + IINCHIP_READ(Sn_RX_RSR1(s)); } } while (val != val1); // if two time values do not equal, loop return val; // return the recv buffer size } /** @brief set the tcp keeplive time */ void setkeepalive(SOCKET s) { IINCHIP_WRITE(Sn_KPALVTR(s),0x02); } /** @brief This function is being called by send() and sendto() function also. This function read the Tx write pointer register and after copy the data in buffer update the Tx write pointer register. User should read upper byte first and lower byte later to get proper value. */ void send_data_processing(SOCKET s, uint8_t *data, uint16_t len) { uint16_t ptr =0; uint32_t addrbsb =0; if(len == 0) { //printf("CH: %d Unexpected1 length 0\r\n", s); return; } ptr = IINCHIP_READ( Sn_TX_WR0(s) ); ptr = ((ptr & 0x00ff) << 8) + IINCHIP_READ(Sn_TX_WR1(s)); addrbsb = (uint32_t)(ptr<<8) + (s<<5) + 0x10; wiz_write_buf(addrbsb, data, len); ptr += len; IINCHIP_WRITE( Sn_TX_WR0(s) ,(uint8_t)((ptr & 0xff00) >> 8)); IINCHIP_WRITE( Sn_TX_WR1(s),(uint8_t)(ptr & 0x00ff)); } /** @brief This function is being called by recv() also. This function read the Rx read pointer register and after copy the data from receive buffer update the Rx write pointer register. User should read upper byte first and lower byte later to get proper value. */ void recv_data_processing(SOCKET s, uint8_t *data, uint16_t len) { uint16_t ptr = 0; uint32_t addrbsb = 0; if(len == 0) // if len is 0, return after print message "CH: 0 Unexpected2 length 0". { //printf("CH: %d Unexpected2 length 0\r\n", s); return; } // MCU read the recv data pointer in Sn_RX_RD // Sn_RX_RD saves the first byte address of recv data, if data recved, after data recved, this register is updated. ptr = IINCHIP_READ( Sn_RX_RD0(s) ); ptr = ((ptr & 0x00ff) << 8) + IINCHIP_READ( Sn_RX_RD1(s) ); addrbsb = (uint32_t)(ptr<<8) + (s<<5) + 0x18; // get the absolute address of recv data wiz_read_buf(addrbsb, data, len); // read data to mcu // updata data address ptr += len; // IINCHIP_WRITE( Sn_RX_RD0(s), (uint8_t)((ptr & 0xff00) >> 8)); IINCHIP_WRITE( Sn_RX_RD1(s), (uint8_t)(ptr & 0x00ff)); } /********************************************************************/