---
title: "[W5100S] ioLibrary 포팅시 레지스터 엑세스에 대하여"
url: "https://maker.wiznet.io/forum/13205"
markdown_url: "https://maker.wiznet.io/forum/13205/md"
type: "Forum topic"
category: "Ethernet Chips"
author: "infoic"
created: "2019-02-11T11:15:20+09:00"
last_activity: "2019-02-18T09:50:46+09:00"
language: "ko"
views: 1107
replies: 8
source: "WIZnet Makers forum (https://maker.wiznet.io/forum/)"
---

# [W5100S] ioLibrary 포팅시 레지스터 엑세스에 대하여

## Question

Asked by infoic on 2019-02-11 in Ethernet Chips.

포팅중에 w5100s의 레지스터를 엑세스하는 코드에서 의문이 있어서 문의드립니다.
저는 indirect 모드를 사용하려는데,
코드를 보니 아래처럼 정의되어 있는데,
#if (*WIZCHIP_IO_MODE* & *WIZCHIP_IO_MODE_SPI*)
#define getMR() WIZCHIP_READ(MR)
#else
#define getMR() (*(uint8_t*)MR)
#endif

그렇다면 indirect 모드에서는
#define getMR() (*(uint8_t*)MR)
인데, 제가 보기에는 이코드는 direct모드의 코드로 보이는데 ??
주소에서 바로 값을 읽어오는 위의 코드는 direct모드가 아닌가요?
indirect 모드에서는 주소를 보내고 MR값을 읽어와야 하는게 아닌가요?

## Replies

### Reply 1 by irina, 2019-02-12

안녕하세요.

말씀하신대로 Indirect mode를 사용할 경우,

```
     ADDR  :   01       10        11
     DATA  : ADDR_H    ADDR_L    DATA
```

와 같이 동작을 합니다.

단, MR의 경우는 조금 다르다고 볼수 있습니다.
MR의 경우 ADDR의 00이 MR의 주소를 나타냅니다.
→ 이는 W5100를 사용하고 있는 사용자들이 W5100S로 변경하기 원할때, 별도의 firmware작업없이 사용할수 있게 만들어졌기때문입니다.

아래의 그림은 W5100의 DataSheet에서 발췌한것입니다.
![image](https://maker.wiznet.io/forum_uploads/wiznet/original/2X/c/c99ce8a0fa4ec83ff366d87b6748ad68e19608da.png)

해당하는 부분은 Datasheet에 추가 설명해 놓겠습니다.

감사합니다.
irina

### Reply 2 by infoic, 2019-02-12 (in reply to reply 1)

신속한 답변에 감사합니다.
그런데, 제 질문의 의도가 제대로 전달되지 않은것 같습니다.

#define setMR(mr) (*((uint8_t*)MR) = mr) 이므로,

setMR(0x80) 은 아래처럼 해석됩니다.

(*((uint8_t*)(0x60000000 + (0x0000))) = 0x80)

즉, 0x60000000 번지에 0x80을 쓰게 됩니다.

결국, 이 번지는 대부분의 마이컴에서는 기술되지 않은 부분이어서 익셉션이 발생하게 될꺼라는 질문이었습니다.

제가 무슨 착각을 하고있는건가요?? ^^;;

결론적으로, 아래 코드가 indir 모드에서는 제대로 동작하지 않는게 아닌가 하는 질문입니다.

> /**
>
> - @ingroup Common_register_access_function_W5100S
>
> - @brief Set Mode Register
>
> - @param (uint8_t)mr The value to be set.
>
> - @sa getMR()
>   */
>   #if (*WIZCHIP_IO_MODE* & *WIZCHIP_IO_MODE_SPI*)
>   #define setMR(mr) WIZCHIP_WRITE(MR,mr)
>   #else
>   #define setMR(mr) (*((uint8_t*)MR) = mr)
>   #endif
>
> /**
>
> - @ingroup Common_register_access_function_W5100S
>
> - @brief Get @ref MR.
>
> - @return uint8_t. The value of Mode register.
>
> - @sa setMR()
>   */
>   #if (*WIZCHIP_IO_MODE* & *WIZCHIP_IO_MODE_SPI*)
>   #define getMR() WIZCHIP_READ(MR)
>   #else
>   #define getMR() (*(uint8_t*)MR)
>   #endif

### Reply 3 by irina, 2019-02-12

안녕하세요.

![](https://avatars.discourse-cdn.com/v4/letter/i/c6cbf5/48.png) infoic:

> #define setMR(mr) ( *((uint8_t* )MR) = mr) 이므로,
>
> setMR(0x80) 은 아래처럼 해석됩니다.
>
> ( *((uint8_t* )(0x60000000 + (0x0000))) = 0x80)
>
> 즉, 0x60000000 번지에 0x80을 쓰게 됩니다.

말씀해 주시는 부분이 맞습니다.

Indirect mode를 사용할 경우, 아래의 주소를 사용하기 때문에, 말씀하신대로 0x6000_0000이 맞습니다

```
#define _WIZCHIP_IO_BASE_	0x60000000	// for 5100S IND
#define IDM_OR             ((_WIZCHIP_IO_BASE  + 0x0000))
#define IDM_AR0            ((_WIZCHIP_IO_BASE_ + 0x0001))
#define IDM_AR1            ((_WIZCHIP_IO_BASE_ + 0x0002))
#define IDM_DR             ((_WIZCHIP_IO_BASE_ + 0x0003))
```

여기에서 아셔야 할점은, W5100와 W5100S에서의 IDM_OR은 실제 MR 을 나타내는 주소입니다.
이전에도 말씀드렸듯이 W5100에서 W5100S을 변경하고자하는 고객을 위해 설계된부분이고,
W5100에서는 Direct mode에서 indirect mode로 변경시 IDM_OR의 한 bit를 세팅해주면 변경이 되었습니다.
이 부분에 관해서는 W5100S에서 해당 비트는 사용하지 않지만, W5100사용자들을 위해 0x6000_0000에 값을 쓰거나 읽게 되면, MR register에 접근을 하게 됩니다.

이부분은 테스트 완료 된 부분이기때문에, 익센셥이 발생하지 않습니다.

![](https://avatars.discourse-cdn.com/v4/letter/i/c6cbf5/48.png) infoic:

> 결국, 이 번지는 대부분의 마이컴에서는 기술되지 않은 부분이어서 익셉션이 발생하게 될꺼라는 질문이었습니다.

기술되지 않은 부분이란 어떤걸 얘기하시는건지…
Indirect mode 일때,*WIZCHIP_IO_BASE* 의 값은 MCU 마다 다른 부분입니다.
Wiznet에서 제공하는 예제의 MCU에서 는 해당 address를 사용하기 때문에, 0x6000_0000에 Base address로 세팅되어있는 것입니다.

다른 MCU를 사용하신다면, MCU에 맞는 주소를 설정하셔서 사용하셔야합니다.

감사합니다.
irina

### Reply 4 by infoic, 2019-02-12

아… 이제 말씀하시는 의미를 알겠습니다.

즉, W5100s에서 AD0,1은 (외부메모리 인터페이스에 사용되는) 어드레스 버스신호선(보통 AD[31:0])의 최하위 2비트를 W5100s에 연결하는 경우를 말씀하시는 거군요.

예, 맞습니다.
이 경우에는 정성동작하겠네요.
(그런데, 이렇게 사용하는 유저는 별로 없을 듯…)

저도 CORTEX-M0의 GPIO를 AD0,1에 연결해서 사용합니다.
이경우에는 0x6000_0000은 사용되지 않는 영역이므로 메모리 익셉션이 발생하게 됩니다.(확인했습니다)
저와 같은 경우에는 ioLibrary의 함수를 그대로 사용하면 않되겠네요.
수정이 필요하겠네요.

혹시 수정할 점에 대하여 도움될 코드가 있으면 좋겠는데…
하여튼 감사합니다.

이제야 왜 아래처럼 선언했는지 이해가 됩니다.

#define *WIZCHIP_IO_BASE* 0x60000000 // for 5100S IND
#define IDM_OR ((_WIZCHIP_IO_BASE + 0x0000))
#define IDM_AR0 ((*WIZCHIP_IO_BASE* + 0x0001))
#define IDM_AR1 ((*WIZCHIP_IO_BASE* + 0x0002))
#define IDM_DR ((*WIZCHIP_IO_BASE* + 0x0003))

### Reply 5 by irina, 2019-02-12

ioLibrary 를 사용하여 쓰실경우
WIZCHIP_IO_BASE의 값을 사용가능한 memory 주소로 매핑하신다면 어렵지 않게 사용하실수 있을것 같습니다.

감사합니다.
irina

### Reply 6 by infoic, 2019-02-15

예 감사합니다.

> wizchip_setnetinfo(&info);
> wizchip_settimeout(&nettime);
> wizchip_init(txsize, rxsize);

위 코드를 실행한 후
다시 netinfo를 읽어보니 정상적으로 읽어지는 것을 확인했습니다.

그런데, 또 문제가 발생했습니다.ㅠㅠ

int8_t close(uint8_t sn) 에서

> setSn_CR(sn,Sn_CR_CLOSE);
> /* wait to process the command… */
> while( getSn_CR(sn) );

이부분에서 Sn_CR 값이 0으로 되질 않습니다.

참고로,
ADDR0,ADDR1 은 GPIO를 사용하고 있습니다.

혹시나 해서 PCB도 다시 조립해 봤지만 마찬가지 였습니다.
어느 부분을 검토해 봐야 할까요?
조언을 부탁드립니다.

### Reply 7 by irina, 2019-02-18 (in reply to reply 6)

![](https://avatars.discourse-cdn.com/v4/letter/i/c6cbf5/48.png) infoic:

> Sn_CR_CLOSE

안녕하세요 .
Sn_CR의 경우 로직상
자동으로 Clear되도록 설계되어있습니다.

어떤 동작을 한후 Sn_CR의 값이 0이 되지 않는건가요?
예를 들어 connect 함수에서 동작하지 않는다…
사용하는 SOCKET의 Sn_CR이 맞는지 확인해야할것 같습니다.

감사합니다.
irina 드림.

### Reply 8 by infoic, 2019-02-18

실행한 프로그램을 순서대로 코드를 나열하면 아래와 같습니다.

> pin_low(RST);
> // 여기 약간의 다른 코드가 있고,
> pin_high(RST);
>
> Wait_10us(200 * 100);

위처럼 리셋 작업을 한 후

> uint8_t txsize[4] = {2, 2, 2, 2};
> uint8_t rxsize[4] = {2, 2, 2, 2};
>
> reg_wizchip_cris_cbfunc(enable_irq, disable_irq);
> reg_wizchip_cs_cbfunc(cs_low, cs_high);
> reg_wizchip_bus_cbfunc(bus_readdata, bus_writedata);
>
> wiz_NetInfo info = {
> .dhcp=NETINFO_STATIC
> };
>
> // MAC ADDRESS
> for (i = 0 ; i &lt; 6; i++) {
> info.mac[5-i] = (param.mac >> (i * 8)) & 0xFF;
> }
> // Local IP ADDRESS
> for (i = 0 ; i &lt; 4; i++) {
> info.ip[3-i] = (param.ip >> (i * 8)) & 0xFF;
> }
> // Subnet Mask ADDRESS
> for (i = 0 ; i &lt; 4; i++) {
> info.sn[3-i] = (param.subnet >> (i * 8)) & 0xFF;
> }
> // GateWay ADDRESS
> for (i = 0 ; i &lt; 4; i++) {
> info.gw[3-i] = (param.gateway >> (i * 8)) & 0xFF;
> }
>
> wiz_NetTimeout nettime = {
> .retry_cnt = param.retryCount,
> .time_100us = param.retryTime
> };
>
> wizchip_setnetinfo(&info);
> wizchip_settimeout(&nettime);
> wizchip_init(txsize, rxsize);

위에서 처럼 초기화 했습니다.
ip, subnet,gw는 정상적으로 써졌다는것을 확인했습니다.

> TcpServer(0, 8698);

마지막으로 위처럼 TcpServer를 실행했는데,
여기서부터는 ioLibrary내의 코드이므로 잘 알고 계실것으로 생각되는데,

> socket(s,Sn_MR_TCP,port,0x00);

을 호출하고,
또 socket()에서는

> close(sn);
> 을 호출 하지요.

또, close() 에서는

> setSn_CR(sn,Sn_CR_CLOSE);
> /* wait to process the command… */
> while( getSn_CR(sn) );

위의 코드가 있습니다.
여기서 while 문에서 무한루프를 돕니다.
값을 확인해보면 0으로 리셋되지 않고 Sn_CR_CLOSE가 그대로 있 습니다.

---

Source: https://maker.wiznet.io/forum/13205
