[W7500x]이더넷 링크가 붙지 않아서 질문을 올립니다.


#1

안녕하세요.

W7500P가 정상작동하는지 확인을 하기 위해서 예제를 참고하여 다음과 같은 테스트 소스를 작성하였습니다. 제 생각에는 아래처럼하면 고정 ip를 받는 것이고 문제 없이 링크가 붙어서 통신일 될 것이라고 생각했습니다.

라우터 포트에 연결하여 보니 w7500p을 확인할 없었습니다. 정상적으로 링크가 붙지 않는것 같아서 데스크탑과 같은 네트워크 대역을 갖게 설정한 뒤 1:1로 연결하였지만 링크가 붙지 않는 것 같았습니다.

회로의 문제가 아닐까 하여 엠베드 보드와 다른 회로를 사용해 보았는데도 동일 증상이 발생합니다.

혹시 시간이 되시면 한번 검토해주셔도 되나요?

/*netset.h*/

#ifndef NET_SETTING_H__
#define NET_SETTING_H__


#include "W7500x_wztoe.h"
#include "W7500x_miim.h"

#include "loopback.h"
#include "dhcp.h"
#include "socket.h"

#include "flash.h"


#define SOCK_TCPS	0
#define SOCK_DHCP	2

#define MY_MAX_DHCP_RETRY   3

#define MAC_ADDR_SIZE 6
#define IP_ADDR_SIZE 4


typedef struct netconfig{
	  uint8_t mac_addr[6]; 
    uint8_t src_addr[4];
    uint8_t gw_addr[4];
		uint8_t sub_addr[4];
}NetConfig;


void netboot(void);
void netset(void);
void vDHCPTaskFunction(void* pvParameters);

#endif


/*netset.c*/
#include "netset.h"
#include "flash.h"


#define debug_mode


const uint8_t SIPR[4] = {192,168,42,9};
const uint8_t  GAR[4] = {192,168,42,1};
const uint8_t SUBR[4] = {255,255,255,0};


uint8_t test_buf[2048];
uint32_t my_dhcp_retry = 0;


#ifdef debug_mode
		const uint8_t SHAR[6] = {0x00, 0x08, 0xDC, 0x71, 0x72, 0x77};
#endif



void netboot(void){
	
		#ifdef debug_mode
			DO_IAP(IAP_PROG, DAT0_START_ADDR, (uint8_t*)SHAR, MAC_ADDR_SIZE);
			DO_IAP(IAP_PROG, DAT0_START_ADDR + MAC_ADDR_SIZE, (uint8_t*)SIPR, IP_ADDR_SIZE);
			DO_IAP(IAP_PROG, DAT0_START_ADDR + MAC_ADDR_SIZE + IP_ADDR_SIZE, (uint8_t*)GAR, IP_ADDR_SIZE);
			DO_IAP(IAP_PROG, DAT0_START_ADDR + MAC_ADDR_SIZE + IP_ADDR_SIZE + IP_ADDR_SIZE, (uint8_t*)SUBR, IP_ADDR_SIZE);
		#endif

    PHY_Init();    
    while( link() == 0x0)
			
		netset();
		
//		if((Buffercmp((uint8_t*)SIPR,(((/*volatile */uint8_t *)(DAT0_START_ADDR) + MAC_ADDR_SIZE)),IP_ADDR_SIZE) == PASSED) &&
//			 (Buffercmp((uint8_t*)GAR, (((/*volatile */uint8_t *)(DAT0_START_ADDR) + MAC_ADDR_SIZE + IP_ADDR_SIZE)),IP_ADDR_SIZE) == PASSED) &&
//			 (Buffercmp((uint8_t*)SUBR,(((/*volatile */uint8_t *)(DAT0_START_ADDR) + MAC_ADDR_SIZE + IP_ADDR_SIZE + IP_ADDR_SIZE)),IP_ADDR_SIZE) == PASSED) )
//		{
			//run dhcp task->if 3 time loss, then default netset
			
//		}
			
}

void netset(void){

	NetConfig config;
		
	readflash((uint8_t*)config.mac_addr,(/*volatile */uint8_t *)(DAT0_START_ADDR), MAC_ADDR_SIZE);
	readflash((uint8_t*)config.src_addr,(/*volatile */uint8_t *)(DAT0_START_ADDR + MAC_ADDR_SIZE), IP_ADDR_SIZE);
	readflash((uint8_t*)config.gw_addr, (/*volatile */uint8_t *)(DAT0_START_ADDR + MAC_ADDR_SIZE + IP_ADDR_SIZE), IP_ADDR_SIZE);
	readflash((uint8_t*)config.sub_addr,(/*volatile */uint8_t *)(DAT0_START_ADDR + MAC_ADDR_SIZE + IP_ADDR_SIZE + IP_ADDR_SIZE), IP_ADDR_SIZE);
	
	setSHAR(config.mac_addr);
	setSIPR(config.src_addr);
	setGAR(config.gw_addr);
	setSUBR(config.sub_addr);
	
}

void vDHCPTaskFunction(void* pvParameters){
}

#2

안녕하세요

링크가 붙지않는다는것이 아래 while()문에 묶여있다는뜻이신가요? LINK LED에는 불이 들어오시나요?


#3

안녕하세요. 답변 감사합니다. 와일문에 묶여 있는지 제가 디버깅 툴이 있지를 안아서 확인해보지 못했습니다 link led에는 불이 들어오는데 ping도 가지 않고 연결된 공유기에도 연결되어있지 않게 표시가 됩니다.


#4

안녕하세요

LINK LED에 불이 들어왔다면 네트워크 설정이 제대로 되었는지 다시한번 확인하시기 바랍니다.
칩에 데이터가 정상적으로 read/write가 되는지
네트워크 설정이 원한값으로 되었는지 디버깅하셔야 좋을것 같습니다.


#5

감사합니다. mbed 보드에 라이트되었는지 확인하는 방법이 따로 있나요?
지금 테스트를 위해서 mbed 보드에 깃허브에 올려주신 loopaback 예제를 다운로드해봤는 데도 동일해서요.
예제에서 소스 어드레스와 게이트웨이 어드레스만 연결된 네트워크 설정에 맞춰서 해봤어요


#6

감사합니다. 덕분에 문제를 찾을 수 있었습니다.

DO_IAP로 플레쉬에 저장한 데이터의 주소를 포인터 변수에 담았습니다.

#define debug

typedef struct netconfig{
uint8_t mac_addr[6]; 
uint8_t src_addr[4];
uint8_t gw_addr[4];
uint8_t sub_addr[4];
}NetConfig;

const NetConfig defaultdata = { {0x00, 0x08, 0xDC, 0x01, 0x02, 0x03},{192,168,42,123},{192,168,42,1},{255,255,255,0} };

netset(void){

NetConfig* pconfig

#ifdef debug
DO_IAP(IAP_PROG, DAT0_START_ADDR, (uint8_t*)(&defaultdata), 18);
#endif

pconfig = (NetConfig*)(DAT0_START_ADDR);
setSHAR(pconfig->mac_addr);
setSIPR(pconfig->src_addr);
setGAR(pconfig->gw_addr);
setSUBR(pconfig->sub_addr);

}

간소화한 코드인데 이런식으로 하면 ip를 세팅을 못합니다…

#define debug

typedef struct netconfig{
    uint8_t mac_addr[6]; 
	uint8_t src_addr[4];
	uint8_t gw_addr[4];
	uint8_t sub_addr[4];
}NetConfig;

const NetConfig defaultdata = { {0x00, 0x08, 0xDC, 0x01, 0x02, 0x03},{192,168,42,123},{192,168,42,1},{255,255,255,0} };

netset(void){

	NetConfig* pconfig

    #ifdef debug
    DO_IAP(IAP_PROG, DAT0_START_ADDR, (uint8_t*)(&defaultdata), 18);
	#endif

	pconfig = (NetConfig*)(&defaultdata );
	setSHAR(pconfig->mac_addr);
	setSIPR(pconfig->src_addr);
	setGAR(pconfig->gw_addr);
	setSUBR(pconfig->sub_addr);

}

이런식으로 하면 정상적으로 동작하고요.
지금 내부 플레쉬에 고정ip를 저장해두고서 부팅 시 가져올 수 있다록 하려하는데 읽어오지 못하니 답답합니다.
플래쉬 내부 데이터를 포인터로 접근하지 못하는 건가요?


#7

요즘 mcu에 쓰는 FLASH가 거의 다 NAND겠죠… NOR는 비싸니까요.

제가 겪어본 대부분의 CORTEX-M기반의 MCU들은 NAND FLASH를 포인터로 접근하지 못하고 NVMCTRL이라는 컨트롤러를 이용해서 페이지라는 단위로 접근 할 수 있습니다.

NAND 특성상 바이트 단위로 읽고 쓰기가 불가능합니다. 1바이트를 쓰려고 해도 페이지 단위로 읽어서 1바이트 데이터를 바꾼 다음에 전체 페이지를 다시 써야할 수 밖에 없어요…

WORK FLASH라고 별도의 FLASH 영역을 제공해주지 않는 MCU라면 NVMCTRL을 이용해서 pseudo eeprom layer를 만들고 FLASH 일부분을 eeprom처럼 쓰는 건 가능합니다.


NAND 메모리 구조를 살펴보시기 바랍니다. 포인터로 직접 접근이 안되는 이유를 이해하실 수 있을 것 같습니다.


#8

안녕하세요

우선 플래시 내부데이터를 포인터로 접근가능합니다.
다만 위에 leejin0님이 말씀하셨듯이 바이트 단위로 읽고 쓰기가 불가능합니다.
플래시에 write하기전에 erase 해주시고 SECT단위로 데이터를 쓰시길 추천드립니다.


위에 링크의 플래시 예제 참고하시면 좋을것 같습니다.

올려주신 코드는 좀 더 검토해보도록 하겠습니다.


#9

감사합니다. 덕분에 문제를 잘 해결할 수 있었습니다.

아래 간단하게 플래쉬의 섹터를 부분적으로 바꿀수 있는 예제를 짜봤습니다.

volatile TestStatus TransferStatus = FAILED;

    void Readfalsh(uint8_t* dst_addr, uint8_t* src_addr, uint32_t size){
	uint32_t i;
	for( i = 0; i < size; i++){
		src_addr[i] = dst_addr[i];
	}

}

void Writeflash(uint32_t dst_addr, uint8_t* src_addr, uint32_t size){

	uint8_t buf[SECT_SIZE]={0};
	uint32_t i;
	uint32_t tempaddr;
	uint8_t tempset;


	
	if(dst_addr < DAT1_START_ADDR){
		tempaddr = DAT0_START_ADDR;
		tempset = IAP_ERAS_DAT0;
	}else{
		tempaddr = DAT1_START_ADDR;
		tempset = IAP_ERAS_DAT1;
	}	

	Readfalsh((uint8_t*)tempaddr, (uint8_t*)buf, SECT_SIZE);	

	for(i = 0; i < size; i++){
		buf[dst_addr - tempaddr + i] = src_addr[i];
	}

	DO_IAP(tempset,0,0,0);
	DO_IAP(IAP_PROG, tempaddr, buf, SECT_SIZE);

}

void Eraseflash(uint32_t dst_addr, uint32_t size){
	uint8_t src_addr[SECT_SIZE] = {0};
	Writeflash(dst_addr,src_addr,size);
}

#10

해결되셨다니 다행입니다.
그리고 좋은정보또한 감사합니다.