WIZnet Developer Forum

[W7500] mbed Flash Memory 관련 문의

W7500 mbed 컴파일러로 개발하고 있는 개발자입니다.

인터넷 접근이 너무 간단해서 많이 놀랐네요~~
지금 저희가 flash memory에 사용자 환경(Setup)값을 저장하고 싶습니다.
Keil 버전용 Firmware에서 DO_IAP 함수를 이용하여 DATA0, DATA1영역에 접근할 수 있구요.
문제는 보드 Reset버튼 재부팅시 플래쉬메모리 영역에 값들이 지워지는걸 확인했습니다.
혹시 플래쉬영역 일부를 저희가 임의로 사용할 수 있는지요?
없다면 칩을 별도로 추가해야 되는지요??
답변 부탁 드리겠습니다.

W7500 flash Link를 확인해보셨나요?
정확한 현상을 파악하기 위해 질문 드리자면, IAP_PROG로 저장을 하셨는데, 리셋시 초기화된다는 말씀이신가요?

일반적인 Flash이기 때문에, 사용법은 일반적인 내용과 동일합니다.
주로 메모리 관리를 위해 DATA0 과 DATA1만을 저장용으로 이용하시는 것이 좋습니다.

넵 맞습니다. IAP_PROG로 저장하였으며 초기 부팅시 저장된 값을 확인하는 소스코드를 추가하여 확인하였습니다.
mbed 에서 Test 중입니다.

사용하신 소스코드를 공유해주실 수 있을까요?

#include "mbed.h"
#include "EthernetInterface.h"


#define ECHO_SERVER_PORT   15000
//#define ENABLE_DHCP



/********************************************************************************/
//  Define
/********************************************************************************/
#define IAP_ENTRY                                       0x1FFF1001            // Because Thum code
#define IAP_ERAS                                        0x010
#define IAP_ERAS_DAT0                                   (IAP_ERAS + 0)
#define IAP_ERAS_DAT1                                   (IAP_ERAS + 1)
#define IAP_ERAS_SECT                                   (IAP_ERAS + 2)              
#define IAP_ERAS_BLCK                                   (IAP_ERAS + 3)  
#define IAP_ERAS_CHIP                                   (IAP_ERAS + 4)  
#define IAP_ERAS_MASS                                   (IAP_ERAS + 5)  
#define IAP_PROG                                        0x022
#define DAT0_START_ADDR                                 0x0003FE00
#define DAT1_START_ADDR                                 0x0003FF00
#define CODE_TEST_ADDR                                  0x0001FF00
#define BLOCK_SIZE                                      4096
#define SECT_SIZE                                       256


typedef enum 
{ 
    FAILED = 0,
    PASSED = !FAILED
    
} TestStatus;


/********************************************************************************/
// Function Prototype Define
/********************************************************************************/
void Buffercmp(uint8_t* pBuffer1, uint8_t* pBuffer2, uint16_t BufferLength);
void DO_IAP( uint32_t id, uint32_t dst_addr, uint8_t* src_addr, uint32_t size);



////////////////////////////////////////////////////////////////////////////////
//                      Init Global Valiable                                  //
////////////////////////////////////////////////////////////////////////////////
DigitalOut RLED(PC_8);
DigitalOut GLED(PC_9);
DigitalOut BLED(PC_5);
Serial Sensor(PA_13, PA_14);


uint8_t save_buff[SECT_SIZE];


uint8_t gMac_addr[6]    = {0x00, 0x08, 0xDC, 0x00, 0x01, 0x02};
char gIp_addr[]         = {"192.168.0.105"};
char gMask[]            = {"255.255.255.0"};
char gGateway_addr[]    = {"192.168.0.1"};
////////////////////////////////////////////////////////////////////////////////



int main (void)
{
    int nCnt = 0;
    //TestStatus result;
    printf("Wait a second...\r\n");
    
    memset(save_buff, 0x00, SECT_SIZE);
    // Make Init Symbol Flash Write
    save_buff[nCnt++] = 'M';
    save_buff[nCnt++] = 'T';
    save_buff[nCnt++] = 'E';
    save_buff[nCnt++] = 'C';
    
    //DO_IAP(IAP_ERAS_DAT0, DAT0_START_ADDR, 0, 0);
    //DO_IAP(IAP_PROG, DAT0_START_ADDR, save_buff, SECT_SIZE);
    Buffercmp((uint8_t*)&save_buff[0], ((uint8_t *)(DAT0_START_ADDR)), SECT_SIZE);
    printf("%s\r\n", save_buff);
                    
    EthernetInterface eth;
    
 #ifdef ENABLE_DHCP
    printf("DHCP IP Mode\r\n");
    eth.init(gMac_addr); //Use DHCP
    eth.connect();
    printf("Server IP Address is %s\r\n", eth.getIPAddress());
 #else
    printf("Static IP Mode\r\n");
    eth.init(gMac_addr, gIp_addr, gMask, gGateway_addr);    
 #endif/* ENABLE_DHCP */
    
    TCPSocketServer server;
    server.bind(ECHO_SERVER_PORT);
    server.listen();
    
    RLED = 0;
    GLED = 1;
    BLED = 0;
    wait(0.2);
        
    while (true) 
    {
        printf("Wait for new connection...\r\n");
        TCPSocketConnection client;
        server.accept(client);
        client.set_blocking(false, 15000); // Timeout after (1.5)s
        
        printf("Connection from: %s\r\n", client.get_address());
        char buffer[256];
        
        RLED = 0;
        GLED = 0;
        BLED = 1;
        
        while (true) {
            
            int n = client.receive(buffer, sizeof(buffer));
            if (n <= 0) break;
            
            // print received message to terminal
            buffer[n] = '\0';
            printf("Received message from Client :'%s'\r\n",buffer);
            
            // reverse the message
            char temp;
            for(int f = 0, l = n-1; f<l; f++,l--){
                temp = buffer[f];
                buffer[f] = buffer[l];
                buffer[l] = temp;
                }
            
            // print reversed message to terminal
            printf("Sending message to Client: '%s'\r\n",buffer);
            
            // Echo received message back to client
            client.send_all(buffer, n);
            if (n <= 0) break;
        }
        client.close();
        RLED = 0;
        GLED = 1;
        BLED = 0;
    }
}



/********************************************************************************/
// This is DO_IAP.
/********************************************************************************/
void DO_IAP( uint32_t id, uint32_t dst_addr, uint8_t* src_addr, uint32_t size)
{
    // Disable interrupts before calling IAP
    __disable_irq();
    
    // Call IAP Function
    ((void(*)(uint32_t,uint32_t,uint8_t*,uint32_t))IAP_ENTRY)( id,dst_addr,src_addr,size);

    // Enable interrupts
    __enable_irq();
}



/********************************************************************************/
// This is Buffercmp.
/********************************************************************************/
void Buffercmp(uint8_t* pBuffer1, uint8_t* pBuffer2, uint16_t BufferLength)
{
    while(BufferLength--)
    {   
        (*pBuffer1) = (*pBuffer2);
    
        pBuffer1++;
        pBuffer2++;
    }
}

코드상에서는 DO_IAP를 사용하지 않으신데,
이전 코드에서 사용하시고, 현재 코드로 테스트하신 건가요?

일단 아래 코드를 한번 참조해 보시길 바랍니다.

#include "mbed.h"

#define IAP_ENTRY           0x1FFF1001            
#define IAP_ERAS            0x010
#define IAP_ERAS_DAT0       (IAP_ERAS + 0)
#define IAP_ERAS_SECT       (IAP_ERAS + 2)              
#define IAP_ERAS_BLCK       (IAP_ERAS + 3)  
#define IAP_ERAS_CHIP       (IAP_ERAS + 4)  
#define IAP_ERAS_MASS       (IAP_ERAS + 5)  
#define IAP_PROG            0x022
#define DAT0_START_ADDR     0x0003FE00
#define BLOCK_SIZE          4096
#define SECT_SIZE           256


struct data{
    char something1[5];
    int something2;
} test;

void DO_IAP( uint32_t id, uint32_t dst_addr, uint8_t* src_addr, uint32_t size);

Serial pc(USBTX,USBRX);

int main()
{ 
    uint8_t save_buff[BLOCK_SIZE];

    pc.baud(115200);

    /* Set dummy data */
    strcpy(test.something1, "abcd");
    test.something2 = 1000;
    memcpy(save_buff, (const char*)&test, sizeof(data) );
    
    /* Load stored data */
    memcpy(save_buff,(uint8_t *)(DAT0_START_ADDR),sizeof(data));
    data *p = (data*)save_buff;
    pc.printf("Something1: %s, Something2: %d \r\n",p->something1, p->something2);
    
    /* Store different data */
    strcpy(test.something1 ,"hello");
    test.something2 = 20000;
    memcpy(save_buff, (const char*)&test, sizeof(data) );
    
    DO_IAP(IAP_ERAS_DAT0,0,0,0);
    DO_IAP(IAP_PROG,DAT0_START_ADDR,save_buff,SECT_SIZE);
}

void DO_IAP( uint32_t id, uint32_t dst_addr, uint8_t* src_addr, uint32_t size)
{
    uint32_t temp_interrupt;

    // Backup Interrupt Set Pending Register
    temp_interrupt = (NVIC->ISPR[0]);
    (NVIC->ISPR[0]) = (uint32_t)0xFFFFFFFF;
    
    // Call IAP Function
    ((void(*)(uint32_t,uint32_t,uint8_t*,uint32_t))IAP_ENTRY)( id,dst_addr,src_addr,size);

    // Restore Interrupt Set Pending Register
    (NVIC->ISPR[0]) = temp_interrupt;
}

제가 보내준 소스 DO_IAP에서 __disable_irq(); / __enable_irq(); Keil에서만 해당되는
코드인가 보군요!! Error 안나길레 ~~!!

보내주신 DO_IAP함수를 사용하니 잘 되는걸 확인하였습니다.
답변 고맙습니다.

아 혹시 mbed 컴파일 환경에서 Timer Interrupt를 구현할 수 있는 소스가 있으시다면
공유해주시면 고맙겠습니다.
Keil 환경으로 Code를 꾸미고 있는데 mbed환경이 너무 좋아서 위 Timer Interrupt 소스만
있다면 계속 mbed 컴파일로 진행해도 될거 같아서 입니다.
그럼 부탁 드립니다.

W7500에 대한 mbed용 Timer Interrupt 예제는 보유하고 있지 않습니다.
우선, mbed의 기본적인 룰에 따라 포팅 되어 있는 것이기 때문에, mbed의 사용법을 따라서 코드 작성하시면 될 것 같습니다.
마찬가지로, mbed 내에서 검색을 통해 유사한 소스코드를 활용하시는것도 하나의 방법이 되겠습니다.

간단하게 찾아본 결과, mbed Timers and interrupts를 참조하시면 도움이 되시리라 판단됩니다.

넵 고맙습니다. 참고하겠습니다.
그럼 수고하세요~

1 Like

Copyright © 2017 WIZnet Co., Ltd. All Rights Reserved.