STM32H7 보드에서 W5300 의 TCP 전송율 테스트를 해 보자.
STM32H7 칩 내부에 Ethernet MAC가 포함되어 있어 이더넷 통신이 가능하지만 Ethernet 전송율이 34Mbps 정도로 그렇게 빠르지 않다.
STM32F439보드에서 W5300을 이용하면 이더넷 전송율을 90Mbps 이상 나오므로 STM32H7에서는 좀더 여유롭지 않을까..
STM32H7 보드에 W5300은 NE1(PD7)에 연결되어 있고 PC3에 리셋이 할당되어 있다.
기존에 테스트 했던 예제를 이용하여 STM32H7 에서는 정상동작을 하지 않는다.
getMR() = 0201
W5300 memory initialization failed
Mac address: 01:68:01:68:01:68
IP address : 1.104.1.104
SM Mask : 1.104.1.104
Gate way : 1.104.1.104
DNS Server : 0.0.0.0
일단 W5300의 레지스터에 값을 쓰고 읽어 보는 테스트를 해 보자
while (1)
{
IINCHIP_WRITE(SHAR, 0x1234);
IINCHIP_WRITE(SHAR+2, 0x5678);
IINCHIP_WRITE(SHAR+4, 0x9abc);
HAL_Delay(10);
printf("%x, ", IINCHIP_READ(SHAR));
printf("%x, ", IINCHIP_READ(SHAR+2));
printf("%x", IINCHIP_READ(SHAR+4));
printf("\r\n");
HAL_Delay(1000);
마지막 값만 읽어 오는것 같다.
1a90, 1a90, 1a10
1a90, 1a90, 1a90
1a90, 1a90, 1a90
오실로 스코프 확인 결과 CS 한번에 Write 신호가 연속을 나온다.
그리고 동일한 주소에 데이터를 쓰면 무시되는 현상이 발행하는데 문제의 원인은 M7으로 오면서 변경된 고속의 버스 아키텍츠 때문이라고 한다.
해결 방법은 메모리스왑을 통해서 저속메모리 영역으로 옮겨야 하는데 MCP_Config() 함수에서 가능하다.
CORTEX_M7 탭에서 MCP를 초기화 하자.
이렇게 생성된 코드를 이용하여 테스트 해 보면
void MPU_Config(void)
{
/// Enable the MPU
MPU_Region_InitTypeDef MPU_InitStruct;
HAL_MPU_Disable();
MPU_InitStruct.Enable=MPU_REGION_ENABLE;
MPU_InitStruct.BaseAddress = 0x60000000;
MPU_InitStruct.Size = MPU_REGION_SIZE_64KB;
MPU_InitStruct.AccessPermission=MPU_REGION_FULL_ACCESS;
MPU_InitStruct.TypeExtField=MPU_TEX_LEVEL0;
MPU_InitStruct.IsCacheable=MPU_ACCESS_NOT_CACHEABLE;
MPU_InitStruct.IsBufferable=MPU_ACCESS_BUFFERABLE;
MPU_InitStruct.IsShareable=MPU_ACCESS_SHAREABLE;
MPU_InitStruct.Number=MPU_REGION_NUMBER0;
MPU_InitStruct.SubRegionDisable=0x00;
MPU_InitStruct.DisableExec=MPU_INSTRUCTION_ACCESS_ENABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
}
CS 신호 하나에 Write 신호가 하나씩 정상적으로 출력되는것을 확인 할 수 있다.
W5300의 TCP 루프백 테스트를 해보자. 전송율이 15Mbps로 상당히 느리다.
왜 이런 현상이 발생할까?
STM32F4 W5300 TCP 전송률 테스트에서 처럼 코드를 옵티마이즈 해 보자
void WIZCHIP_WRITE(uint32_t AddrSel, uint16_t wb )
{
#if _USE_W5300_OPTIMIZE
_W5300_DATA(AddrSel) = wb;
#else
WIZCHIP.IF.BUS._write_data(AddrSel, wb);
:
}
35Mbps로 좀더 빨라 졌다.
STM32H7의 ICache, DCache 를 설정해 보자
int main(void)
{
/* USER CODE BEGIN 1 */
unsigned int data;
SCB_EnableICache();
SCB_EnableDCache();
MPU_Config();
60Mbps 정도로 빨라졌다.
STM32H7의 FMC 타이밍을 최대한 줄여 볼까?
조금 빨라지지만 에러가 자주 발생한다.
FMC_NORSRAM_TimingTypeDef Timing = {0};
FMC_SDRAM_TimingTypeDef SdramTiming = {0};
hsram1.Instance = FMC_NORSRAM_DEVICE;
hsram1.Extended = FMC_NORSRAM_EXTENDED_DEVICE;
hsram1.Init.NSBank = FMC_NORSRAM_BANK1;
hsram1.Init.DataAddressMux = FMC_DATA_ADDRESS_MUX_DISABLE;
hsram1.Init.MemoryType = FMC_MEMORY_TYPE_SRAM;
hsram1.Init.MemoryDataWidth = FMC_NORSRAM_MEM_BUS_WIDTH_16;
hsram1.Init.BurstAccessMode = FMC_BURST_ACCESS_MODE_DISABLE;
hsram1.Init.WaitSignalPolarity = FMC_WAIT_SIGNAL_POLARITY_LOW;
hsram1.Init.WaitSignalActive = FMC_WAIT_TIMING_BEFORE_WS;
hsram1.Init.WriteOperation = FMC_WRITE_OPERATION_ENABLE;
hsram1.Init.WaitSignal = FMC_WAIT_SIGNAL_DISABLE;
hsram1.Init.ExtendedMode = FMC_EXTENDED_MODE_DISABLE;
hsram1.Init.AsynchronousWait = FMC_ASYNCHRONOUS_WAIT_DISABLE;
hsram1.Init.WriteBurst = FMC_WRITE_BURST_DISABLE;
hsram1.Init.ContinuousClock = FMC_CONTINUOUS_CLOCK_SYNC_ONLY;
hsram1.Init.WriteFifo = FMC_WRITE_FIFO_DISABLE;
hsram1.Init.PageSize = FMC_PAGE_SIZE_NONE;
/* Timing */
Timing.AddressSetupTime = 4;
Timing.AddressHoldTime = 4;
Timing.DataSetupTime = 10;
Timing.BusTurnAroundDuration = 4;
Timing.CLKDivision = 17;
Timing.DataLatency = 16;
Timing.AccessMode = FMC_ACCESS_MODE_A;
/* ExtTiming */
if (HAL_SRAM_Init(&hsram1, &Timing, NULL) != HAL_OK)
{
Error_Handler( );
}
아무리 설정해 봐도 기존의 STM32F439 보드에서 측정되었던 전송율은 나오지 않는다.
FMC 영역을 속도가 느린 메모리로 스왑해서 발생한 것인가?
Wizet에서 제공하는 최신 라이브러라가 아닌 STM32F439 보드에서 테스트 했던 라이브러리를 이용해 보자
void ProcessTCPS(SOCKET s, uint16 port)
{
unsigned long len;
uint16 mode = 0;
//ESTABLISH?
switch(getSn_SSR(s))
{
case SOCK_ESTABLISHED:
if(getSn_IR(s) & Sn_IR_CON) // check Sn_IR_CON bit
{
setSn_IR(s,Sn_IR_CON); // clear Sn_IR_CON
}
//수신된 데이터가 있으면
if((len=getSn_RX_RSR(s)) > 0) // check the size of received data
{
//수신받은 데이터 만큼 수신하고
len = recv(s, data_buf, len);
//루프백 테스트
send(s,data_buf,1);
}
break;
//초기화시
case SOCK_INIT:
//TCP CLIENT로 부터 접속대기
listen(s);
status = 1;
break;
// PASSIVE CLOSED
case SOCK_CLOSE_WAIT:
disconnect(s);
break;
// Socket CLOSED일 경우
case SOCK_CLOSED:
close(s);
//새롭게 Socket Open
socket(s,Sn_MR_TCP,port,mode);
status = 0;
break;
default:
break;
}
}
80Mbps 정도까지는 측정이 된다.
STM32H7 FMC 타이밍을 좀더 줄여 보자
Timing.AddressSetupTime = 3;
Timing.AddressHoldTime = 3;
Timing.DataSetupTime = 10;
Timing.BusTurnAroundDuration = 4;
Timing.CLKDivision = 17;
Timing.DataLatency = 16;
옛날 라이브러리는 타이밍을 줄여도 에러는 발생하지 않지만 85Mbps 이상 전송율이 올라가지 않는다.
영혼 까지 끌어 모아 테스트 해보았지만 눈물겹다.
STM32H7에서 더 빨라 졌을거라 예상 했는데...
STM32H7에서 W5300을 이용여 iperf로 TCP Throughput 테스트를 해보자
95Mbps 정도로 거의 최대 전송율이 나온다.
단방향 전송에서 최대 전송율이 나오는것으로 만족해야 할것 같다.