Arduino IDE에서 W5500 테스트에서 전송률이 낮아서 MounRiver 에서 W5500 테스트를 해 보자
우선 프로젝트를 생성하고 ioLibrary Driver를 다운 받아 복사 한다.
CH32V307의 SPI 설정 함수를 작성한다.
void SPI_FullDuplex_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure = {0};
SPI_InitTypeDef SPI_InitStructure = {0};
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_SPI1, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA, GPIO_Pin_2);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(SPI1, &SPI_InitStructure);
SPI_Cmd(SPI1, ENABLE);
}
void GPIO_INIT(void)
{
GPIO_InitTypeDef GPIO_InitStructure = {0};
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_SetBits(GPIOB, GPIO_Pin_4);
}
CH32V307에서 W5500 CS핀은 PB4에 할당되어 있으므로 설정해 준다.
#define W5200_CS_PORT GPIOB
#define W5200_CS_BIT BIT4
#define IINCHIP_CSoff() GPIO_ResetBits(W5200_CS_PORT, W5200_CS_BIT)
#define IINCHIP_CSon() GPIO_SetBits(W5200_CS_PORT, W5200_CS_BIT)
W5500 라이브러리에서 사용할 SPI_WriteReadByte, SPI_WriteBuf, SPI_ReadBuf 함수를 CH32V307에 맞도록 수정해 준다.
unsigned char SPI_WriteReadByte(unsigned char Data)
{
volatile unsigned int spi_cnt = 0;
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET)
{
spi_cnt++;
if(spi_cnt > SPIx_TIMEOUT_MAX)
return 0;
}
SPI_I2S_SendData(SPI1, Data);
spi_cnt = 0;
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET)
{
spi_cnt++;
if(spi_cnt > SPIx_TIMEOUT_MAX)
return 0;
}
return SPI_I2S_ReceiveData(SPI1);
}
unsigned char SPI_WriteBuf(unsigned char *pDataBuf, unsigned int Size)
{
#if _USE_SPI_DMA
#else
for(int i=0;i<Size;i++)
{
SPI_WriteReadByte(pDataBuf[i]);
}
#endif
return i;
}
unsigned char SPI_ReadBuf(unsigned char *pDataBuf, unsigned int Size)
{
uint8_t receivedbyte = 0;
#if _USE_SPI_DMA
#else
for(int i=0;i<Size;i++)
{
pDataBuf[i] = SPI_WriteReadByte(0xff);
}
#endif
return receivedbyte;
}
W5500으로 TCP 루프백 테스트를 할수 있는 main 함수를 작성한다.
#include "wiznet_test.h"
#define SOCK_TCPS0 0
uint8_t gDATABUF[DATA_BUF_SIZE];
int main(void)
{
SystemCoreClockUpdate();
Delay_Init();
USART_Printf_Init(115200);
printf("SystemClk:%d\r\n", SystemCoreClock);
printf( "ChipID:%08x\r\n", DBGMCU_GetCHIPID() );
GPIO_INIT();
SPI_FullDuplex_Init();
W5500_Init();
Display_Net_Info();
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
loopback_tcps(SOCK_TCPS0, gDATABUF, 5001);
}
}
CH32V307 에서 W5500의 TCP전송률을 측정하면 동작은 하지만 속도를 높이면 정상 동작 하지 않는다.
SPI 클럭을 SPI_BaudRatePrescaler_32 이하로 설정하면 정상 동작 하지 않는다.
CH32V003, CH32V035 에서는 잘 동작 하는데… CH32V307만 안된다.
그럴리가…
삽질 끝에 해결책을 찾았다.
CH32V035에서 단서를 찾았다. SPI초기화 부분에서 PA2를 출력으로 설정하는 부분이 있었는데.. 그냥 독립적인 GPIO라 그냥 두고 테스트 했는데 이부분이 문제가 되었다.
이 부분을 삭제하고 나니 정상 동작한다. 왜그렇지? 중국칩의 한계인가?
그냥 독립적인 GPIO인데…
좀더 정확한 원인을 찾을 필요가 있을것 같다
void SPI_FullDuplex_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure = {0};
SPI_InitTypeDef SPI_InitStructure = {0};
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_SPI1, ENABLE);
/*
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA, GPIO_Pin_2);
*/
:
이제 SPI CLK 18Mhz 에서 정상 동작 한다.
#define SYSCLK_FREQ_144MHz_HSE 144000000
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;
이때 10Mbps로 측정된다.
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
로 설정하면 SPI클럭이 36Mhz가 되는데… 그러면 W5500이 정상동작 하지 않는다.
이부분은 W6100으로 테스트 해 볼 필요가 있을것 같다.
그렇다면 메인 클럭을 120Mhz로 설정해 보자
#define SYSCLK_FREQ_120MHz_HSE 120000000
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
SPI클럭이 30Mhz로 설정이 되었다. 이때 TCP 전송률은 14Mbps 정도로 측정된다.
W5500의 FIFO 크기를 키워보면 좀더 속도가 향상된다. 다른 MCU들 처럼 아주 크게 빨라지지는 않는것 같다.
비슷한 클럭 주파수의 중국산 GD32F303 에서 W5500의 TCP Throughput 측정 테스트 과 비교해 보면 성능면에서 떨어지는것 같다.
SPI DMA로 다시 테스트 해봐야 겠다.