[전동 Skateboard 만들기]#3 Wi-Fi 모듈 연결 및 Control 어플 구현

Posted by 카이젠8501 카이젠8501
2015.11.03 09:58 IT 개발/DIY 프로젝트

[전동 Skateboard 만들기]#3 Wi-Fi 모듈 연결 및 Control 어플 구현

Hardware of Wi-Fi Receiver

Wi-Fi 수신기는 스마트폰에서 데이터를 수신하여 스케이트 보드의 속도를 조절하는 장치이며, 하드웨어 구성은 아래와 같다.

20151029_143029

아래 사진은 완성된 하드웨어 사진이다. 배터리나 다른 보드들과의 circuit short를 방지하기 위해 절연 테이트를 부착하여 조금 부족해 보이지만 동작에는 문제가 없다.

오른쪽에 3핀, 2핀이 나와 있는데, 위에 3핀은 PWM,3.3V VCC,GND 핀이고, 아래 2핀은 배터리에서 받아 올 5V VCC, GND 핀이다.

20151030_082315

Wi-Fi Receiver Firmware

Source Code

Wi-Fi Receiver firmware는 아래 그림과 같은 구조로 동작된다. 스마트폰에서 Speed Up 명령을 주면 Wi-Fi Receiver는 속도를 5% 올리고 Speed Down 명령을 주면 속도를 5% 내린다.

20151030_084225

예외 상황에서는 아래 그림과 같이 Motor를 정지 한다. 단 Motor가 정지 되어도 가속도 때문에 스케이트 보드는 계속 움직일 수는 있다.

20151030_085505

Wi-Fi 수신기에 대한 소스코드는 아래 경로에서 다운로드 할 수 있다.
https://developer.mbed.org/users/kaizen/code/Wifi_Electric_Skateboard/

#include "mbed.h"
#include "Servo.h"
#include "WizFi250Interface.h"

#define SECURE WizFi250::SEC_WPA2_MIXED
#define SSID "Kaizen_Skate"
#define PASS "qwertyuiop"

#define SERVER_PORT    5000
#define STOP_MOTOR     50


#if defined(TARGET_WIZwiki_W7500P)
    WizFi250Interface wizfi250(PC_2,PC_3,PC_13,PC_14,PC_12,NC,115200);
    Serial pc(USBTX, USBRX);
    Servo motor_speed(PC_8);      // it used to percentage value ( 0 ~ 1 )
    DigitalOut green_led(LED2);    
    DigitalOut red_led(LED1);
    DigitalOut blue_led(LED3);
#endif

#define START_MSG       "START"
#define END_MSG         "END\n"
#define CONTROL_UP      "UPXX"
#define CONTROL_DOWN    "DOWN"
#define CONTROL_CRUISER "CRUI"
#define CONTROL_STOP    "STOP"

#define STATUS_CMD_OK   "OKXX"
#define STATUS_CMD_FAIL "FAIL"

#define CONTROL_MSG_SIZE    19

// Control Pkt Format : START,CONTROL,SPEED_VALUE,END
//                      START,UPXX,500,END
// Status Pkt Format : START,CONTROL,SPEED_VALUE,STATUS,END

struct control_pkt{
    char start_msg[6];
    char control_msg[5];
    char speed_msg[4];
    char end_msg[4];
};
void parse(char buffer[], int *j, char *string);

int main() {    
    int recv_cnt,j;
    volatile float speed_value = 0.5;
    char recv_control_msg[100];
    char status_msg[100];
    control_pkt control;

    pc.baud(115200);
    green_led = 1; red_led = 1; blue_led = 1;

    wizfi250.init();
    wizfi250.setAntMode(WizFi250::PCB);
    wizfi250.setAddress("192.168.100.2","255.255.255.0","192.168.100.1");
    if ( wizfi250.connect(SECURE, SSID, PASS, WizFi250::WM_AP))
    {
        red_led = 0;
        return -1;
    }
    printf("IP Address is %s\r\n", wizfi250.getIPAddress());
    green_led = 0; red_led = 0; blue_led = 0;

    TCPSocketServer server;
    TCPSocketConnection client;

    while(true)
    {
        if( client.is_connected() == false )
        {
            green_led = 1; red_led = 1; blue_led = 0;            
            client.close();
            server.close();

            if(speed_value == 0.5)
            {
                server.bind(SERVER_PORT);
                server.listen();

                printf("\nWait for new connection...\r\n");
                server.accept(client);
                client.set_blocking(false, 1500);
            }
            else if(speed_value <= 0.4)
            {
                printf("Speed decrease +\r\n");

                speed_value = 0.5;
                motor_speed = speed_value;
            }
            else
            {
                printf("Speed decrease -\r\n");
                speed_value = 0.5;  motor_speed = speed_value;
            }
        }
        else
        {
            motor_speed = speed_value;

            green_led = 0; red_led = 1; blue_led = 1;
            //recv_cnt = client.receive_all((char*)recv_control_msg, sizeof(control)-1);
            recv_cnt = client.receive_all((char*)recv_control_msg, sizeof(control));

            j=0;
            parse(recv_control_msg, &j, control.start_msg);
            parse(recv_control_msg, &j, control.control_msg);
            parse(recv_control_msg, &j, control.speed_msg);
            parse(recv_control_msg, &j, control.end_msg);

            if(recv_cnt > 0)
            {
                if( (strncmp(control.start_msg,START_MSG,sizeof(control.start_msg)) != 0) || 
                    (strncmp(control.end_msg,END_MSG,sizeof(control.end_msg)) != 0) )
                {
                    printf("TEST Error\r\n");
                    sprintf(status_msg,"%s,%03d,%s,%s\n",START_MSG,int(speed_value*100),STATUS_CMD_FAIL,END_MSG);
                    client.send_all((char*)status_msg,strlen(status_msg));
                    continue;
                }

                if( strncmp(control.control_msg,CONTROL_UP,sizeof(control.control_msg)) == 0 )
                {
                    speed_value += 0.05; 
                    motor_speed = speed_value;
                    printf("TEST UP %f\r\n",speed_value); 
                }
                else if( strncmp(control.control_msg,CONTROL_DOWN,sizeof(control.control_msg)) == 0)
                {
                    speed_value -= 0.05; 
                    motor_speed = speed_value;
                    printf("TEST DOWN %f\r\n",speed_value);
                }
                else if( strncmp(control.control_msg,CONTROL_CRUISER,sizeof(control.control_msg)) == 0)
                {
                    printf("TEST CRUISER\r\n"); 
                    speed_value = (float)(atoi(control.speed_msg)) / 100;
                    motor_speed = speed_value;
                }
                else if( strncmp(control.control_msg,CONTROL_STOP,sizeof(control.control_msg)) == 0)
                {
                    printf("TEST STOP\r\n"); 
                    speed_value = 0.5;
                    motor_speed = speed_value;
                }
                else
                {
                    printf("TEST Error 1-2\r\n");
                    sprintf(status_msg,"%s,%03d,%s,%s\n",START_MSG,int(speed_value*100),STATUS_CMD_FAIL,END_MSG);
                    client.send_all((char*)status_msg,strlen(status_msg));
                    continue;
                }

                sprintf(status_msg,"%s,%03d,%s,%s\n",START_MSG,int(speed_value*100),STATUS_CMD_OK,END_MSG);
                client.send_all((char*)status_msg,strlen(status_msg));
            }
            else
            {
                sprintf(status_msg,"%s,%03d,%s,%s\n",START_MSG,int(speed_value*100),STATUS_CMD_OK,END_MSG);
                client.send_all((char*)status_msg,strlen(status_msg));
            }
        }
    }// while
}

void parse(char buffer[], int *j, char *string) {
//extracts next location string data item from buffer
    int i=0;
    for (i=0; i<=strlen(buffer); i++) {  //TOTAL SIZE OF RETURNED DATA
        if ((buffer[*j+i] == ',')||(buffer[*j+i] == '\0' )) { //IF comma or end of string
            //comma is the string field delimiter
            string[i]=0; //SETS END OF SRTRING TO 0
            *j=*j+i+1; //UPDATES to 1 after comma seperated value
            break;
        } else string[i]=buffer[*j+i]; //Keep adding to the string
    }
}

스마트폰 어플

Screenshot_2015-10-29-16-20-25

Source Code

https://github.com/kaizen8501/WiFi_Skateboard

Demo Video


저작자 표시
신고
이 댓글을 비밀 댓글로
    • ㅇㅇ
    • 2016.12.17 21:51 신고
    너무 어렵다.........
    • 안녕하세요^^

      어느 부분이 어려우신지 말씀해 주시면 제가 아는 한도 내에서 자세히 설명 해 드리도록 하겠습니다^^

전동 Skateboard 만들기 #2

Posted by 카이젠8501 카이젠8501
2015.11.03 09:57 IT 개발/DIY 프로젝트

전동 Skateboard 만들기 #2

Mortor Test

Hardware 구성

다들 아시겠지만, 서보모터는 MCU의 PWM 파형을 이용하여 구동한다. PWM 파형을 제어하기 위해 Cortex-M0 계열의 WIZwiki-W7500ECO 보드를 이용하였으며, 하드웨어 구성은 아래 그림과 같다.

20151029_143257

Test Software

Software는 mbed 환경에서 구현하였다. 서보 모터를 제어하기 위해, mbed에서는 Servo 라이브러리를 제공하며 사용방법은 아래 주소를 참고 하기 바란다. (Servo Library)

내 스케이트 보드에 장착되어 있는 보드의 모터에 어떤 값을 입력하였을 때, 전진하고 후진하는지 알아 보기 위해 아래와 같은 테스트 코드를 작성하였다. mbed Servo는 0 ~ 1 사이의 값으로 PWM 파형을 생성하며, 스케이트 보드에 장착된 모터는 0.4 ~ 0.55 값에서 중립 상태를 보인다.

#include "mbed.h"
#include "Servo.h"

int main() {    
    uint8_t ch;
    volatile float speed_value = 0.5;

    Servo myservo(PC_8);
    Serial pc(USBTX,USBRX);

    pc.baud(115200);
    wait(1);
    pc.printf("TEST Start\r\n");

    while(1)
    {
        pc.printf("speed : %f\r\n",speed_value);
        myservo = speed_value;

        ch = pc.getc();

        if(ch == 'u')
        {
            speed_value += 0.001;
        }
        else if(ch == 'd')
        {
            speed_value -= 0.001;
        }

        else if(ch == 's')
        {
            myservo = 0.5;
            wait(0.5);

            speed_value = 0.41;
            myservo = speed_value;
            wait(5);

            speed_value = 0.5;
            myservo = speed_value;

        }
    }
}

위 코드는 https://developer.mbed.org/users/kaizen/code/Servo_HelloWorld/에서 확인 및 다운로드 할 수 있다.


저작자 표시
신고
이 댓글을 비밀 댓글로

FreeRTOS기반의 W7500 UART CLI(Command Line Interpreter) 구현하기

Posted by 카이젠8501 카이젠8501
2015.10.08 15:19 IT 개발/Cortex

FreeRTOS기반의 W7500 UART CLI(Command Line Interpreter) 구현하기

CLI(Command Line Interpreter)

CLI, Command line interface) 또는 명령어 인터페이스는 텍스트 터미널을 통해 사용자와 컴퓨터가 상호 작용하는 방식을 뜻한다. 즉, 작업 명령은 사용자가 컴퓨터 키보드 등을 통해 문자열의 형태로 입력하며, 컴퓨터로부터의 출력 역시 문자열의 형태로 주어진다.

참고 : https://ko.wikipedia.org/wiki/%EB%AA%85%EB%A0%B9_%EC%A4%84_%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4

Repository of Project

Repository에 접속한 후, Download ZIP혹은 Clone in Desktop 버튼을 클릭하면 해당 프로젝트를 사용 할 수 있다.

20150922_215621

Explain key point function of this project

serial.c

serial.c는 W7500에서 FreeRTOS 기반에서 UART를 사용하기 위한 Driver Code이다.

Serial 초기화(xSerialPortInitMinimal())과정에서 Rx Data를 관리하기 위한 xRxedChars Queue와 Tx Data를 관리하기 위한 xCharsForTx Queue를 생성한다.

UART Rx Interrupt가 발생하면, xRxedChars Queue에 보관하고 xSerialGetChar() 시에 Queue에서 Data를 꺼내서 사용한다.

xComPortHandle xSerialPortInitMinimal( unsigned long ulWantedBaud, unsigned portBASE_TYPE uxQueueLength )
{
xComPortHandle xReturn;
    /* Create the queues used to hold Rx/Tx characters. */
    xRxedChars = xQueueCreate( uxQueueLength, ( unsigned portBASE_TYPE ) sizeof( signed char ) );
    xCharsForTx = xQueueCreate( uxQueueLength + 1, ( unsigned portBASE_TYPE ) sizeof( signed char ) );

    /* If the queue/semaphore was created correctly then setup the serial port
    hardware. */
    if( ( xRxedChars != serINVALID_QUEUE ) && ( xCharsForTx != serINVALID_QUEUE ) )
    {
        S_UART_Init(115200);

        S_UART_ITConfig(S_UART_CTRL_RXI,ENABLE);
        NVIC_EnableIRQ(UART2_IRQn);

        xReturn = (xComPortHandle)UART2;
    }
    else
    {
        xReturn = ( xComPortHandle ) 0;
    }

    /* This demo file only supports a single port but we have to return
    something to comply with the standard demo header file. */
    return xReturn;
}

void UART2_Handler( void )
{
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
char cChar;

    if( S_UART_GetITStatus(S_UART_INTSTATUS_RXI) != RESET ) {
        S_UART_ClearITPendingBit(S_UART_INTSTATUS_RXI);
        cChar = S_UART_ReceiveData();
        xQueueSendFromISR( xRxedChars, &cChar, &xHigherPriorityTaskWoken );
    }    
    portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );
}
signed portBASE_TYPE xSerialGetChar( xComPortHandle pxPort, signed char *pcRxedChar, TickType_t xBlockTime )
{
    /* The port handle is not required as this driver only supports one port. */
    ( void ) pxPort;

    /* Get the next character from the buffer.  Return false if no characters
    are available, or arrive before xBlockTime expires. */
    if( xQueueReceive( xRxedChars, pcRxedChar, xBlockTime ) )
    {
        return pdTRUE;
    }
    else
    {
        return pdFALSE;
    }
}
/*-----------------------------------------------------------*/

void vSerialPutString( xComPortHandle pxPort, const signed char * const pcString, unsigned short usStringLength )
{
signed char *pxNext;

    /* A couple of parameters that this port does not use. */
    ( void ) usStringLength;
    ( void ) pxPort;

    /* NOTE: This implementation does not handle the queue being full as no
    block time is used! */

    /* The port handle is not required as this driver only supports UART1. */
    ( void ) pxPort;

    /* Send each character in the string, one at a time. */
    pxNext = ( signed char * ) pcString;
    while( *pxNext )
    {
        xSerialPutChar( pxPort, *pxNext, serNO_BLOCK );
        pxNext++;
    }
}
/*-----------------------------------------------------------*/

signed portBASE_TYPE xSerialPutChar( xComPortHandle pxPort, signed char cOutChar, TickType_t xBlockTime )
{
signed portBASE_TYPE xReturn;
char cChar;
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;

    if( xQueueSend( xCharsForTx, &cOutChar, xBlockTime ) == pdPASS )
    {
        xReturn = pdPASS;
        if( xQueueReceiveFromISR( xCharsForTx, &cChar, &xHigherPriorityTaskWoken ) == pdTRUE )
        {
            /* A character was retrieved from the queue so can be sent to the
            THR now. */
            S_UART_SendData( cChar );
        }        
    }
    else
    {
        xReturn = pdFAIL;
    }

    return xReturn;
}

UARTCommandConsole.c, FreeRTOS_CLI.c

UART로 입력된 명령을 Parsing 해서 지정된 Task를 호출하는 기능을 수행한다.
prvUARTCommandConsoleTask() 함수는 Uart Data가 “\r\n” 개행 문자가 나올 때 까지 문자열을 보관한 후, FreeRTOS_CLIProcessCommand()함수를 실행시켜 등록되어 있는 Command인지 확인하고 해당 Task를 호출하는 기능을 수행한다.

CLI-commands.c

Command 이름과 수행해야 하는 Task, Parameter 수를 CLI_Command_definition_t 타입에 저장 한후, FreeRTOS_CLIRegisterCommand()를 이용하여 Command들을 등록한다.
본 예제에서는 SetNetConfig와 GetNetConfig를 등록해서 사용한다.

static const CLI_Command_Definition_t xSetNetConfig =
{
    "set-net",
    "set-network <ip-addr> <subnet> <gateway>:\r\n",
    prvSetNetworkConfigCommand, /* The function to run. */
    3 /* Three parameters are expected, which can take any value. */
};

static const CLI_Command_Definition_t xGetNetConfig =
{
    "get-net",
    "get-network\r\n",
    prvGetNetworkConfigCommand, /* The function to run. */
    0
};

void vRegisterCLICommands(void)
{
    /* Register all the command line commands defined immediately above. */
    FreeRTOS_CLIRegisterCommand(&xSetNetConfig);
    FreeRTOS_CLIRegisterCommand(&xGetNetConfig);

}

위에서 등록한 명령에 대한 Task의 구현부분이다.
prvSetNetworkConfigCommand는 set-net 이라는 명령이 들어오면 수행되며, W7500의 IP주소, Subnet Mask, Gateway 주소를 변경하는 기능을 수행한다.
prvGetNetworkConfigCommand는 get-net 이라는 명령이 들어오면 수행되며, W7500의 Network 정보를 Serial로 출력하는 기능을 한다.

static BaseType_t prvSetNetworkConfigCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString )
{
const char *pcParameter;
char ip[16]={0};
char subnet[16]={0};
char gateway[16]={0};

BaseType_t xParameterStringLength, xReturn;

    /* Remove compile time warnings about unused parameters, and check the
    write buffer is not NULL.  NOTE - for simplicity, this example assumes the
    write buffer length is adequate, so does not check for buffer overflows. */
    ( void ) pcCommandString;
    ( void ) xWriteBufferLen;
    configASSERT( pcWriteBuffer );

    pcParameter = FreeRTOS_CLIGetParameter(pcCommandString, 1, &xParameterStringLength);
    strncat(ip, pcParameter, xParameterStringLength);
    setSIPR( str_to_ip_array(ip) );

    pcParameter = FreeRTOS_CLIGetParameter(pcCommandString, 2, &xParameterStringLength);
    strncat(subnet, pcParameter, xParameterStringLength);
    setSUBR( str_to_ip_array(subnet) ) ;

    pcParameter = FreeRTOS_CLIGetParameter(pcCommandString, 3, &xParameterStringLength);
    strncat(gateway, pcParameter, xParameterStringLength);
    setGAR( str_to_ip_array(gateway) );

    sprintf(pcWriteBuffer,SUCCESS_MESSAGE); 

    xReturn = pdFALSE;
    return xReturn;
}

static BaseType_t prvGetNetworkConfigCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString )
{
BaseType_t xReturn;
uint8_t tmp[8];
static int paramCount = 0;

    /* Remove compile time warnings about unused parameters, and check the
    write buffer is not NULL.  NOTE - for simplicity, this example assumes the
    write buffer length is adequate, so does not check for buffer overflows. */
    ( void ) pcCommandString;
    ( void ) xWriteBufferLen;
    configASSERT( pcWriteBuffer );


    switch(paramCount)
    {
        case 0:
            getSHAR(tmp);
            sprintf(pcWriteBuffer,"MAC ADDRESS : %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\r\n",tmp[0],tmp[1],tmp[2],tmp[3],tmp[4],tmp[5]); 
            xReturn = pdPASS;
            paramCount++;
            break;
        case 1:
            getSIPR(tmp);
            sprintf(pcWriteBuffer,"IP ADDRESS  : %d.%d.%d.%d\r\n",tmp[0],tmp[1],tmp[2],tmp[3]); 
            xReturn = pdPASS;
            paramCount++;
            break;
        case 2:
            getGAR(tmp);
            sprintf(pcWriteBuffer,"GW ADDRESS  : %d.%d.%d.%d\r\n",tmp[0],tmp[1],tmp[2],tmp[3]); 
            xReturn = pdPASS;
            paramCount++;
            break;
        case 3:
            getSUBR(tmp);
            sprintf(pcWriteBuffer,"SN MASK    : %d.%d.%d.%d\r\n",tmp[0],tmp[1],tmp[2],tmp[3]); 
            xReturn = pdPASS;
            paramCount++;
            break;
        default:
            paramCount=0;
            xReturn = pdFALSE;
            break;
    }

    return xReturn;
}

Demo

Demo를 위한 절차는 아래와 같다.

  1. get-net 명령을 이용하여 WIZwiki-W7500ECO Board의 Default Network 정보를 출력한다. PC에서 Ping을 보내서 IP 주소가 유효한지 확인한다.
  2. set-net 명령을 이용하여 IP주소를 192.168.77.50으로 변경한다. 변경 후 동일하게 PC에서 Ping을 보내, IP 주소가 유효한지 확인한다.


20150922_223157

Future Work

  1. W7500을 제어하기 위한 Command 보강
  2. FreeRTOS에서 W7500의 Network 기능을 사용하기 위한 Socket Porting


저작자 표시
신고
이 댓글을 비밀 댓글로
    • 2016.08.30 21:04
    비밀댓글입니다
  1. 안녕하세요^^
    메일로 답변 드렸습니다. 진행 하시다가 추가로 궁금하신 내용 있으면 문의 주세요^^

FreeRTOS Porting Guide(2/4)

Posted by 카이젠8501 카이젠8501
2015.10.08 15:16 IT 개발/Cortex

FreeRTOS

Download FreeRTOS

FreeRTOS사이트에 접속하면, FreeRTOS에 관한 정보와 문서, 소스 코드를 다운 받을 수 있다.

Folder Structure

FreeRTOS를 다운로드 받으면, 크게 Free-RTOS-Plus 폴더와 FreeRTOS 폴더를 확인 할 수 있다.
자세한 내용은 http://www.freertos.org/a00017.html를 참고 하기 바란다.

20150922_193631

먼저 FreeRTOS 폴더를 확인해 보면 Demo 폴더와 Source 폴더로 구성되어 있으며, Demo 폴더에는 FreeRTOS 커널 기반의 예제 데모 프로젝트가 존재 한다.

20150922_193652

Source 폴더에는 FreeRTOS Kenel 구현 파일들이 존재하며, Portable 폴더에는 프로세스별, IDE별 FreeRTOS Port를 정의한 파일이 존재 한다.

20150922_193732

본 장에서는 Cortex M0계열의 W7500 프로세서를 이용하여 FreeRTOS를 구동하므로, portable/RVDS/ARM_CM0 폴더에 있는 port.c와 portmacro.h를 사용하려고 한다.
추가로 FreeRTOS의 Memory Management를 위해 portable/MemMang 폴더에 있는 파일들을 프로젝트에 추가 해야 한다. Memory Management에 대한 자세한 설명은 http://www.freertos.org/a00111.html를 참고 하기 바란다.

WIZwiki-W7500ECO FreeRTOS Porting

본 장에서는 WIZwiki-W7500ECO Board에 FreeRTOS를 Porting 하는 방법에 대해 설명한다. 본 장에서 구동하는 예제는 WIZwiki-W7500ECO Board의 LED1을 20ms 마다 Blink 하는 프로그램이다.

Step 1 : Download W7500 Library and Example

https://github.com/Wiznet/W7500에 접속한 후, W7500 Library Code를 다운로드 한다.

20150922_201106

Step 2 : Create Keil Project for W7500

W7500-master\W7500x_Library_Examples\Projects\Peripheral_Examples 에 프로젝트를 위한 폴더를 생성한 후, 적당한 프로젝트 파일 하나는 복사한다. 나는 OS\FreeRTOS 폴더를 생성 한 후, GPIO\Blink_LED 안에 있는 파일들을 OS\FreeRTOS 폴더에 복사해서 사용하였다. 원래는 새로운 프로젝트를 만들어서 사용하는 것이 정석이나, WIZnet에서 이미 만들어 놓은 프로젝트의 설정 값들을 그대로 사용하기 위해 위와 같은 방법으로 프로젝트를 생성 하였다.

OS\FreeRTOS\MDK 폴더의 W7500x_GPIO_Blink_LED.uvproj를 열면 아래 그림과 같이 W7500의 GPIO를 On/Off 하는 예제를 확인 할 수 있다.

Include Path 설정법

본 예제는 GPIO\Blink_LED와 폴더 Depth가 동일하기 때문에 Keil 프로젝트의 설정 변경 없이 그대로 사용할 수 있다. 하지만 폴더 Depth를 기존 프로젝트들과 다르게 만들었을 경우, 컴파일이 안되는 문제가 발생 할 수 있다. 이런 경우, 아래 방법을 이용하여 Include Path를 설정하면 문제를 해결 할 수 있다.

[Project]-[Options for Target] 선택 후, [C/C++]탭의 Include Paths에 아래 폴더들의 경로를 지정한다.

  • \Libraries\CMSIS\Device\WIZnet\W7500\Include
  • \Libraries\W7500x_stdPeriph_Driver\inc
  • \Libraries\CMSIS\Include
  • ..\

20150922_202318

20150922_202539

Step 3 : Porting FreeRTOS

Step1에서 다운로드 받은 FreeRTOS 파일을 Step 2의 OS\FreeRTOS\ 폴더에 아래 그림과 같이 복사한다.
FreeRTOS 폴더에는 아래 그림에 있는 내용만 남겨 놓고 다른 폴더들은 다 삭제 하기 바란다.

20150922_203751

위 과정을 완료 후, Keil 프로젝트에 FreeRTOS 그룹을 만들고 아래 파일들은 추가 한다.

  • OS\FreeRTOS\FreeRTOS\croutine.c
  • OS\FreeRTOS\FreeRTOS\list.c
  • OS\FreeRTOS\FreeRTOS\queue.c
  • OS\FreeRTOS\FreeRTOS\tasks.c
  • OS\FreeRTOS\FreeRTOS\timers.c
  • OS\FreeRTOS\FreeRTOS\portable\MemMang\heap_2.c
  • OS\FreeRTOS\FreeRTOS\portable\RVDS\ARM_CM0\port.c

20150922_204021

Create FreeRTOSConfig.h

#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H

/*-----------------------------------------------------------
 * Application specific definitions.
 *
 * These definitions should be adjusted for your particular hardware and
 * application requirements.
 *
 * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
 * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
 *
 * See http://www.freertos.org/a00110.html.
 *----------------------------------------------------------*/

/* Prevent C code being included by the IAR assembler. */
#ifndef __IASMARM__
    #include <stdint.h>
    extern uint32_t SystemCoreClock;
#endif

#define configUSE_PREEMPTION            1
#define configUSE_IDLE_HOOK                0
#define configUSE_TICK_HOOK                0
#define configCPU_CLOCK_HZ                ( SystemCoreClock )
#define configTICK_RATE_HZ                ( ( TickType_t ) 1000 )
#define configMAX_PRIORITIES            ( 5 )
#define configMINIMAL_STACK_SIZE        ( ( unsigned short ) 128 )
#define configTOTAL_HEAP_SIZE            ( ( size_t ) ( 10 * 1024 ) )
#define configMAX_TASK_NAME_LEN            ( 16 )

#define configUSE_TRACE_FACILITY    0
#define configUSE_16_BIT_TICKS        0
#define configIDLE_SHOULD_YIELD        1
#define configUSE_MUTEXES                1

/* Co-routine definitions. */
#define configUSE_CO_ROUTINES             0
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )

/* Software timer definitions. */
#define configUSE_TIMERS                1
#define configTIMER_TASK_PRIORITY        ( 2 )
#define configTIMER_QUEUE_LENGTH        5
#define configTIMER_TASK_STACK_DEPTH    ( 80 )

/* Set the following definitions to 1 to include the API function, or zero
to exclude the API function. */
#define INCLUDE_vTaskPrioritySet        1
#define INCLUDE_uxTaskPriorityGet        1
#define INCLUDE_vTaskDelete                1
#define INCLUDE_vTaskCleanUpResources    1
#define INCLUDE_vTaskSuspend            1
#define INCLUDE_vTaskDelayUntil            1
#define INCLUDE_vTaskDelay                1
#define INCLUDE_eTaskGetState            1

/* Normal assert() semantics without relying on the provision of an assert.h
header file. */
#define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for( ;; ); }

/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
standard names - or at least those used in the unmodified vector table. */
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler

/* Bump up the priority of recmuCONTROLLING_TASK_PRIORITY to prevent false
positive errors being reported considering the priority of other tasks in the
system. */
#define recmuCONTROLLING_TASK_PRIORITY ( configMAX_PRIORITIES - 1 )

#endif
/* Kernel includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"

#include "W7500x_gpio.h"


/* Priorities at which the tasks are created. */
#define mainQUEUE_RECEIVE_TASK_PRIORITY    ( tskIDLE_PRIORITY + 2 )
#define mainQUEUE_SEND_TASK_PRIORITY        ( tskIDLE_PRIORITY + 1 )

/* The rate at which data is sent to the queue.  The 200ms value is converted
to ticks using the portTICK_PERIOD_MS constant. */
#define mainQUEUE_SEND_FREQUENCY_MS            ( 200 / portTICK_PERIOD_MS )

/* The number of items the queue can hold.  This is 1 as the receive task
will remove items as they are added, meaning the send task should always find
the queue empty. */
#define mainQUEUE_LENGTH                    ( 1 )

/* Values passed to the two tasks just to check the task parameter
functionality. */
#define mainQUEUE_SEND_PARAMETER            ( 0x1111UL )
#define mainQUEUE_RECEIVE_PARAMETER            ( 0x22UL )

/* The number of the LED that is toggled. */
#define mainLED_TO_TOGGLE                    ( 0 )

/*
 * The tasks as described in the comments at the top of this file.
 */
static void prvQueueReceiveTask( void *pvParameters );
static void prvQueueSendTask( void *pvParameters );

/*
 * Called by main() to create the simply blinky style application if
 * mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is set to 1.
 */
void main_blinky( void );

void vParTestToggleLED( unsigned long ulLED );

/*
 * The hardware only has a single LED.  Simply toggle it.
 */
extern void vMainToggleLED( void );

/* The queue used by both tasks. */
static QueueHandle_t xQueue = NULL;


void main_blinky( void )
{
    /* Create the queue. */
    xQueue = xQueueCreate( mainQUEUE_LENGTH, sizeof( unsigned long ) );

    if( xQueue != NULL )
    {
        /* Start the two tasks as described in the comments at the top of this
        file. */
        xTaskCreate( prvQueueReceiveTask,                    /* The function that implements the task. */
                    "Rx",                                     /* The text name assigned to the task - for debug only as it is not used by the kernel. */
                    configMINIMAL_STACK_SIZE,                 /* The size of the stack to allocate to the task. */
                    ( void * ) mainQUEUE_RECEIVE_PARAMETER, /* The parameter passed to the task - just to check the functionality. */
                    mainQUEUE_RECEIVE_TASK_PRIORITY,         /* The priority assigned to the task. */
                    NULL );                                    /* The task handle is not required, so NULL is passed. */

        xTaskCreate( prvQueueSendTask, "TX", configMINIMAL_STACK_SIZE, ( void * ) mainQUEUE_SEND_PARAMETER, mainQUEUE_SEND_TASK_PRIORITY, NULL );

        /* Start the tasks and timer running. */
        vTaskStartScheduler();
    }

    /* If all is well, the scheduler will now be running, and the following
    line will never be reached.  If the following line does execute, then
    there was insufficient FreeRTOS heap memory available for the idle and/or
    timer tasks    to be created.  See the memory management section on the
    FreeRTOS web site for more details. */
    for( ;; );
}

static void prvQueueSendTask( void *pvParameters )
{
    TickType_t xNextWakeTime;
    const unsigned long ulValueToSend = 100UL;

    /* Check the task parameter is as expected. */
    configASSERT( ( ( unsigned long ) pvParameters ) == mainQUEUE_SEND_PARAMETER );

    /* Initialise xNextWakeTime - this only needs to be done once. */
    xNextWakeTime = xTaskGetTickCount();

    for( ;; )
    {
        /* Place this task in the blocked state until it is time to run again.
        The block time is specified in ticks, the constant used converts ticks
        to ms.  While in the Blocked state this task will not consume any CPU
        time. */
        vTaskDelayUntil( &xNextWakeTime, mainQUEUE_SEND_FREQUENCY_MS );

        /* Send to the queue - causing the queue receive task to unblock and
        toggle the LED.  0 is used as the block time so the sending operation
        will not block - it shouldn't need to block as the queue should always
        be empty at this point in the code. */
        xQueueSend( xQueue, &ulValueToSend, 0U );
    }
}

static void prvQueueReceiveTask( void *pvParameters )
{
    unsigned long ulReceivedValue;

    /* Check the task parameter is as expected. */
    configASSERT( ( ( unsigned long ) pvParameters ) == mainQUEUE_RECEIVE_PARAMETER );

    for( ;; )
    {
        /* Wait until something arrives in the queue - this task will block
        indefinitely provided INCLUDE_vTaskSuspend is set to 1 in
        FreeRTOSConfig.h. */
        xQueueReceive( xQueue, &ulReceivedValue, portMAX_DELAY );

        /*  To get here something must have been received from the queue, but
        is it the expected value?  If it is, toggle the LED. */
        if( ulReceivedValue == 100UL )
        {
            vParTestToggleLED( mainLED_TO_TOGGLE );
            ulReceivedValue = 0U;
        }
    }
}

void vParTestToggleLED( unsigned long ulLED )
{
    if( GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_1) == Bit_SET )
        GPIO_ResetBits(GPIOA, GPIO_Pin_1);
    else
        GPIO_SetBits(GPIOA, GPIO_Pin_1);
}

Modified main.c

/**
  ******************************************************************************
  * @file    Uart/Printf/main.c 
  * @author  IOP Team
  * @version V1.0.0
  * @date    01-May-2015
  * @brief   Main program body
  ******************************************************************************
  * @attention
  *
  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
  * TIME. AS A RESULT, WIZnet SHALL NOT BE HELD LIABLE FOR ANY
  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
  *
  * <h2><center>&copy; COPYRIGHT 2015 WIZnet Co.,Ltd.</center></h2>
  ******************************************************************************
  */ 

/* Includes ------------------------------------------------------------------*/
#include <stdio.h>
#include "W7500x_uart.h"
#include "W7500x_gpio.h"

#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "queue.h"

extern void main_blinky( void );
/*
 * Initialise the LED ports, and create a timer that periodically toggles an LED
 * just to provide a visual indication that the program is running.
 */


int main()
{
    GPIO_InitTypeDef GPIO_InitDef;
    SystemInit();
    SystemCoreClockUpdate();

    GPIO_InitDef.GPIO_Pin = ( GPIO_Pin_1 | GPIO_Pin_2) ; // Set to Pin_1 (LED1) & Pin_2 (LED2)
    GPIO_InitDef.GPIO_Mode = GPIO_Mode_OUT; // Set to Mode Output
    GPIO_Init(GPIOA, &GPIO_InitDef);
    PAD_AFConfig(PAD_PA,(GPIO_Pin_1|GPIO_Pin_2), PAD_AF1); // PAD Config - LED used 2nd Function    

    main_blinky();

    for(;;);
}


void vApplicationMallocFailedHook( void )
{
    /* vApplicationMallocFailedHook() will only be called if
    configUSE_MALLOC_FAILED_HOOK is set to 1 in FreeRTOSConfig.h.  It is a hook
    function that will get called if a call to pvPortMalloc() fails.
    pvPortMalloc() is called internally by the kernel whenever a task, queue,
    timer or semaphore is created.  It is also called by various parts of the
    demo application.  If heap_1.c or heap_2.c are used, then the size of the
    heap available to pvPortMalloc() is defined by configTOTAL_HEAP_SIZE in
    FreeRTOSConfig.h, and the xPortGetFreeHeapSize() API function can be used
    to query the size of free heap space that remains (although it does not
    provide information on how the remaining heap might be fragmented). */
    taskDISABLE_INTERRUPTS();
    for( ;; );
}
/*-----------------------------------------------------------*/

void vApplicationIdleHook( void )
{
    /* vApplicationIdleHook() will only be called if configUSE_IDLE_HOOK is set
    to 1 in FreeRTOSConfig.h.  It will be called on each iteration of the idle
    task.  It is essential that code added to this hook function never attempts
    to block in any way (for example, call xQueueReceive() with a block time
    specified, or call vTaskDelay()).  If the application makes use of the
    vTaskDelete() API function (as this demo application does) then it is also
    important that vApplicationIdleHook() is permitted to return to its calling
    function, because it is the responsibility of the idle task to clean up
    memory allocated by the kernel to any task that has since been deleted. */
}
/*-----------------------------------------------------------*/

void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName )
{
    ( void ) pcTaskName;
    ( void ) pxTask;

    /* Run time stack overflow checking is performed if
    configCHECK_FOR_STACK_OVERFLOW is defined to 1 or 2.  This hook
    function is called if a stack overflow is detected. */
    taskDISABLE_INTERRUPTS();
    for( ;; );
}
/*-----------------------------------------------------------*/

void vApplicationTickHook( void )
{
    /* This function will be called by each tick interrupt if
    configUSE_TICK_HOOK is set to 1 in FreeRTOSConfig.h.  User code can be
    added here, but the tick hook is called from an interrupt context, so
    code must not attempt to block, and only the interrupt safe FreeRTOS API
    functions can be used (those that end in FromISR()).  The code in this
    tick hook implementation is for demonstration only - it has no real
    purpose.  It just gives a semaphore every 50ms.  The semaphore unblocks a
    task that then toggles an LED.  Additionally, the call to
    vQueueSetAccessQueueSetFromISR() is part of the "standard demo tasks"
    functionality. */

    /* The semaphore and associated task are not created when the simple blinky
    demo is used. */

}
/*-----------------------------------------------------------*/

Fixed Error

Error: L6200E: Symbol PendSV_Handler multiply defined (by port.o and w7500x_it.o).
Error: L6200E: Symbol SysTick_Handler multiply defined (by port.o and w7500x_it.o).

위 Error는 PendSV_Handler와 SysTick_Handler 함수가 중복되어 있어서 발생한 Error이다. 이를 해결하기 위해서는 W7500x_it.c를 아래와 같이 수정하면 된다.

__weak void PendSV_Handler(void)
{}
__weak void SysTick_Handler(void)
{}

Step 4 : Execute Example

https://youtu.be/aXhDnW_doLs

저작자 표시
신고
이 댓글을 비밀 댓글로

W7500 TCP Network Speed Test using WIZwiki-W7500ECO

Posted by 카이젠8501 카이젠8501
2015.10.08 15:13 IT 개발/기타

W7500 TCP Network Speed Test using WIZwiki-W7500ECO

WIZwiki-W7500ECO

WIZnet WIZwiki Platform based on WIZnet’s MCU. WIZnet WIZwiki-W7500eco is a WIZwiki platform board based on W7500. The IOP4IoT W7500 chip is one-chip solution which integrates an ARM Cortex-M0, 128KB Flash and hardwired TCP/IP core for various embedded application platform especially internet of things. If you use WIZwiki-W7500eco, you will be able to easily develop a prototype.

wizwiki-w7500eco3dtop

Test Scenario

  • WIZwiki-W7500ECO

    • Run TCP Echo Server which receive data and then send to tcp client.
  • PC

    • Run TCP client using my test tool.
    • It can be used for simple tcp test and check tcp speed.

To check TCP speed of WIZwiki-W7500, I upload TCP echo server binary to WIZwiki-W7500ECO.
I send data which is 1Mbytes to WIZwiki-W7500ECO using my test tool and then test tool will receive data from WIZwiki-W7500ECO for checking TCP communication speed.

20150826_220148

Test Result

Test Condition 1

There are change points for this test.

  • Change System Clock ( 20MHz, 48MHz )
  • Change RAM buffer ( 2048, 4096, 8192 )

20150826_184249

Comment about Test Condition 1

WIZwiki-W7500ECO TCP Speed depended upon it’s system clock. After test, I got result as below.

  • Buffer size of variable in the code didn’t make much difference to the speed.
  • When using 20MHz of WIZwiki-W7500ECO’s system clock, average speed is 4.7Mbps.
  • When using 48MHz of WIZwiki-W7500ECO’s system clock, average speed is 8.5Mbps.

Test Condition 2

W7500 has one 16KB TX memory for Socket n TX Buffer Blocks and one 16KB RX memory for Socket n RX buffer Blocks.

16KB TX memory is initially allocated in 2KB size for each Socket TX Buffer Block (2KB X 8 = 16KB). The initial allocated 2KB size of Socket n TX Buffer can be re-allocated by using ‘Socket n TX Buffer Size Register (Sn_TXBUF_SIZE)’. Once all Sn_TXBUF_SIZE registers have been configured, Socket TX Buffer is allocated with the configured size of 16KB TX Memory and is assigned sequentially from Socket 0 to Socket 7. Its physical memory address is automatically determined in 16KB TX memory. Therefore, the total sum of Sn_TXBUF_SIZE should not exceed 16 in case of error in data transmission.

wztoe_memory_map

There are chage point for second test.

  • Change Socket RX/TX Buffer of W7500 ( 2048, 8192, 16,384 )

20150827_083215

Comment about Test Condition 2

  • Socket TX/RX buffer size didn’t make much difference to the speed.
  • When using 2Kbytes of Socket buffer, average speed is 8.116Mbps
  • When using 8Kbytes of Socket buffer, average speed is 9.099Mbps
  • When using 16Bytes of Socket buffer, average speed is 9.142Mbps


저작자 표시
신고
이 댓글을 비밀 댓글로
    • 이청열
    • 2017.01.23 15:35 신고
    좋은 글 감사합니다.

    혹 PC에서 실행한 Test Toll을 어디서 구할 수 없나요?
    • 안녕하세요.^^
      아래 주소에 가시면 실행파일을 다운로드 하실 수 있습니다.
      https://github.com/kaizen8501/IPV6_TestTool/blob/master/Release/S2E_TestTool(20150828).exe

      코드가 필요하시다면 아래 주소를 참고 하시기 바랍니다.
      https://github.com/kaizen8501/IPV6_TestTool

      출처: http://kaizen8501.tistory.com/108#comment11622035 [카이젠의 임베디드 DIY 공작소]

How to use pyOCD for new target MCU like W7500

Posted by 카이젠8501 카이젠8501
2015.10.08 15:11 IT 개발/mbed

How to use pyOCD for new target MCU like W7500

What about pyOCD

pyOCD is an Open Source python 2.7 based library for programming and debugging ARM Cortex-M microcontrollers using CMSIS-DAP. Linux, OSX and Windows are supported.

You can use the following interfaces:

  1. From a python interpretor:

    • halt, step, resume execution
    • read/write memory
    • read/write block memory
    • read-write core register
    • set/remove hardware breakpoints
    • flash new binary
    • reset
  2. From a GDB client, you have all the features provided by gdb:

    • load a .elf file
    • read/write memory
    • read/write core register
    • set/remove hardware breakpoints
    • high level stepping

Fork mbedmicro/pyOCD repository and Installation

There are repository for pyOCD by mbedmicro.

After then I issued this command for pyOCD installation.
You can install from source by cloning the git repository and running

$ python setup.py install

For more information about pyOCD installation, Refer to this URL.

Added information and flash algorithm for W7500

I added flash algorithm and information for W7500 to python code of pyOCD project.

There are my commit log for adding W7500 target.

Self Test

After to add my target MCU as W7500, I did test using test script made by mbedmicro.
If this test finished successfully, I think my target MCU is added normally.

This test script include read/write/erase test and register read/write test.

$ cd pyOCD/test/
$ sudo python automated_test.py
------ TEST RESULTS ------
Target         Test           Result         Time           

w7500          Basic Test     Pass           5.34418797493  
w7500          Speed Test     Pass           27.8010311127  
w7500          Cortex Test    Pass           6.81142616272  
w7500          Flash Test     Pass           131.791074038  

Test Time: 171.747846127
All tests passed


저작자 표시
신고
Tags
이 댓글을 비밀 댓글로

WIZwiki_W7500 CMSIS-DAP Porting

Posted by 카이젠8501 카이젠8501
2015.10.08 15:10 IT 개발/mbed

WIZwiki_W7500 CMSIS-DAP Porting

WIZwiki_W7500 Board를 개발하는 중, W7500 Chip이 Reset 되지 않는 문제를 발견하였다.
이 문제로 인해, WIZwki_W7500에 아래와 같은 문제가 발생 했다.

  • Firmware Upload 시, SWD_ERROR 발생
    • Firmware Upload 전, Target Chip(W7500)을 Reset 하는데, Reset 후 W7500이 Booting 되지 않아서 발생한 문제
  • mbed self test에서 Fail되는 현상
    • mbed test bench에서 Firmware Upload 후 CMSIS-DAP을 Reset 하는데 이 때 W7500이 Booting 되지 않아서 발생한 문제

Modified point for Software

기존 CMSIS-DAP의 Reference 대로 LPC11U35의 P1_19번 핀으로 Wizwiki Board의 Switch Reset을 Monitoring 한다.

www.life4iot.com_003

CMSIS-DAP이 Power on Reset 될 때, Target Board(W7500)이 Booting이 완료 될 때 까지 Reset을 시도 한다.

www.life4iot.com_002

www.life4iot.com_001

mbed single test result

위와 같이 CMSIS-DAP 코드를 수정해서 mbed self test를 통과 할 수 있었다.

Building library CMSIS (WIZwiki_W7500, uARM)
Building library MBED (WIZwiki_W7500, uARM)
Building project DETECT (WIZwiki_W7500, uARM)
Executing 'python host_test.py -d H:\ -f "F:\WiznetGit_Repository\W7500_Miscellaneous\mbed-master\build\test\WIZwiki_W7500\uARM\DTCT_1\detect.bin" -p COM12 -t 10 -C 1.5 -m WIZwiki_W7500'
Test::Output::Start
MBED: Instrumentation: "COM12" and disk: "H:\"
HOST: Copy image onto target...
HOST: Initialize serial port...
.......port ready!
HOST: Reset target...
HOST: Property 'timeout' = '10'
HOST: Property 'host_test_name' = 'detect_auto'
HOST: Property 'description' = 'Simple detect test'
HOST: Property 'test_id' = 'DTCT_1'
HOST: Start test...
{{start}}
HOST: Detecting target name...
MBED: Target 'WIZwiki_W7500'
HOST: MUT Target name 'WIZwiki_W7500', expected 'WIZwiki_W7500'... [OK]
MBED: Test ID 'DTCT_1'
MBED: UUID '8ded4549-9396-4b12-b4e1-d90801203d2f'


{{success}}

{{end}}
Test::Output::Finish
TargetTest::WIZwiki_W7500::uARM::DTCT_1::Simple detect test [OK] in 1.46 of 10 sec
Building project DEV_NULL (WIZwiki_W7500, uARM)
Executing 'python host_test.py -d H:\ -f "F:\WiznetGit_Repository\W7500_Miscellaneous\mbed-master\build\test\WIZwiki_W7500\uARM\EXAMPLE_1\dev_null.bin" -p COM12 -t 10 -C 1.5 -m WIZwiki_W7500'
Test::Output::Start
MBED: Instrumentation: "COM12" and disk: "H:\"
HOST: Copy image onto target...
HOST: Initialize serial port...
........port ready!
HOST: Reset target...
HOST: Property 'timeout' = '20'
HOST: Property 'host_test_name' = 'dev_null_auto'
HOST: Property 'description' = 'stdout redirected to dev null'
HOST: Property 'test_id' = 'EXAMPLE_1'
HOST: Start test...
Received 0 bytes: 


{{success}}

{{end}}
Test::Output::Finish
TargetTest::WIZwiki_W7500::uARM::EXAMPLE_1::/dev/null [OK] in 4.45 of 20 sec
Building project HELLO (WIZwiki_W7500, uARM)
Executing 'python host_test.py -d H:\ -f "F:\WiznetGit_Repository\W7500_Miscellaneous\mbed-master\build\test\WIZwiki_W7500\uARM\MBED_10\hello.bin" -p COM12 -t 10 -C 1.5 -m WIZwiki_W7500'
Test::Output::Start
MBED: Instrumentation: "COM12" and disk: "H:\"
HOST: Copy image onto target...
HOST: Initialize serial port...
........port ready!
HOST: Reset target...
HOST: Property 'timeout' = '5'
HOST: Property 'host_test_name' = 'hello_auto'
HOST: Property 'description' = 'Hello World'
HOST: Property 'test_id' = 'MBED_10'
HOST: Start test...
Read 13 bytes:
Hello World


{{success}}

{{end}}
Test::Output::Finish
TargetTest::WIZwiki_W7500::uARM::MBED_10::Hello World [OK] in 1.34 of 5 sec
Building project TICKER (WIZwiki_W7500, uARM)
Executing 'python host_test.py -d H:\ -f "F:\WiznetGit_Repository\W7500_Miscellaneous\mbed-master\build\test\WIZwiki_W7500\uARM\MBED_11\ticker.bin" -p COM12 -t 20 -C 1.5 -m WIZwiki_W7500'
Test::Output::Start
MBED: Instrumentation: "COM12" and disk: "H:\"
HOST: Copy image onto target...
HOST: Initialize serial port...
........port ready!
HOST: Reset target...
HOST: Property 'timeout' = '15'
HOST: Property 'host_test_name' = 'wait_us_auto'
HOST: Property 'description' = 'Ticker Int'
HOST: Property 'test_id' = 'MBED_11'
HOST: Start test...
* in 1.00 sec (0.00) [OK]
* in 0.98 sec (0.02) [OK]
* in 1.00 sec (0.00) [OK]
* in 1.00 sec (0.00) [OK]
* in 1.00 sec (0.00) [OK]
* in 0.98 sec (0.02) [OK]
* in 1.00 sec (0.00) [OK]
* in 1.00 sec (0.00) [OK]
* in 0.98 sec (0.02) [OK]
* in 1.00 sec (0.00) [OK]
Consecutive OK timer reads: 10
Completed in 9.94 sec


{{success}}

{{end}}
Test::Output::Finish
TargetTest::WIZwiki_W7500::uARM::MBED_11::Ticker Int [OK] in 12.29 of 15 sec
Building project CPP (WIZwiki_W7500, uARM)
Executing 'python host_test.py -d H:\ -f "F:\WiznetGit_Repository\W7500_Miscellaneous\mbed-master\build\test\WIZwiki_W7500\uARM\MBED_12\cpp.bin" -p COM12 -t 10 -C 1.5 -m WIZwiki_W7500'
Test::Output::Start
MBED: Instrumentation: "COM12" and disk: "H:\"
HOST: Copy image onto target...
HOST: Initialize serial port...
........port ready!
HOST: Reset target...
HOST: Unknown property: Static::init
HOST: Property 'timeout' = '10'
HOST: Property 'host_test_name' = 'default_auto'
HOST: Property 'description' = 'C++'
HOST: Property 'test_id' = 'MBED_12'
HOST: Start test...
Static::stack_test
Stack::init
Stack::hello
Stack::destroy
Static::check_init: OK
Heap::init
Heap::hello
Heap::check_init: OK
Heap::destroy
{{success}}
{{end}}
Test::Output::Finish
TargetTest::WIZwiki_W7500::uARM::MBED_12::C++ [OK] in 2.40 of 10 sec
Building project RTC (WIZwiki_W7500, uARM)
Executing 'python host_test.py -d H:\ -f "F:\WiznetGit_Repository\W7500_Miscellaneous\mbed-master\build\test\WIZwiki_W7500\uARM\MBED_16\rtc.bin" -p COM12 -t 15 -C 1.5 -m WIZwiki_W7500'
Test::Output::Start
MBED: Instrumentation: "COM12" and disk: "H:\"
HOST: Copy image onto target...
HOST: Initialize serial port...
........port ready!
HOST: Reset target...
HOST: Property 'timeout' = '20'
HOST: Property 'host_test_name' = 'rtc_auto'
HOST: Property 'description' = 'RTC'
HOST: Property 'test_id' = 'MBED_16'
HOST: Start test...
MBED: [0] [1970-01-01 00:00:00 AM]
HOST: [0] [1970-01-01 00:00:00 AM] received time +0 sec after 0.05 sec... FAIL
MBED: [0] [1970-01-01 00:00:00 AM]
HOST: [0] [1970-01-01 00:00:00 AM] received time +0 sec after 1.03 sec... FAIL
MBED: [0] [1970-01-01 00:00:00 AM]
HOST: [0] [1970-01-01 00:00:00 AM] received time +0 sec after 1.03 sec... FAIL
MBED: [0] [1970-01-01 00:00:00 AM]
HOST: [0] [1970-01-01 00:00:00 AM] received time +0 sec after 1.03 sec... FAIL
MBED: [0] [1970-01-01 00:00:00 AM]
HOST: [0] [1970-01-01 00:00:00 AM] received time +0 sec after 1.04 sec... FAIL


{{failure}}

{{end}}
Test::Output::Finish
TargetTest::WIZwiki_W7500::uARM::MBED_16::RTC [FAIL] in 5.51 of 20 sec
Building project STDIO (WIZwiki_W7500, uARM)
Executing 'python host_test.py -d H:\ -f "F:\WiznetGit_Repository\W7500_Miscellaneous\mbed-master\build\test\WIZwiki_W7500\uARM\MBED_2\stdio.bin" -p COM12 -t 20 -C 1.5 -m WIZwiki_W7500'
Test::Output::Start
MBED: Instrumentation: "COM12" and disk: "H:\"
HOST: Copy image onto target...
HOST: Initialize serial port...
........port ready!
HOST: Reset target...
HOST: Property 'timeout' = '20'
HOST: Property 'host_test_name' = 'stdio_auto'
HOST: Property 'description' = 'stdio'
HOST: Property 'test_id' = 'MBED_2'
HOST: Start test...
{{start}}

HOST: Generated number: 17349
MBED: Your value was: 17349
HOST: Number 17349 read after 0.031 sec ... [OK]
HOST: Generated number: 12660
MBED: Your value was: 12660
HOST: Number 12660 read after 0.047 sec ... [OK]
HOST: Generated number: -72654
MBED: Your value was: -72654
HOST: Number -72654 read after 0.031 sec ... [OK]
HOST: Generated number: 30812
MBED: Your value was: 30812
HOST: Number 30812 read after 0.047 sec ... [OK]
HOST: Generated number: 84634
MBED: Your value was: 84634
HOST: Number 84634 read after 0.031 sec ... [OK]
HOST: Generated number: -88020
MBED: Your value was: -88020
HOST: Number -88020 read after 0.047 sec ... [OK]
HOST: Generated number: 24709
MBED: Your value was: 24709
HOST: Number 24709 read after 0.031 sec ... [OK]
HOST: Generated number: 6023
MBED: Your value was: 6023
HOST: Number 6023 read after 0.047 sec ... [OK]
HOST: Generated number: 37272
MBED: Your value was: 37272
HOST: Number 37272 read after 0.031 sec ... [OK]
HOST: Generated number: -46512
MBED: Your value was: -46512
HOST: Number -46512 read after 0.047 sec ... [OK]


{{success}}

{{end}}
Test::Output::Finish
TargetTest::WIZwiki_W7500::uARM::MBED_2::stdio [OK] in 1.74 of 20 sec
Building project TICKER_2 (WIZwiki_W7500, uARM)
Executing 'python host_test.py -d H:\ -f "F:\WiznetGit_Repository\W7500_Miscellaneous\mbed-master\build\test\WIZwiki_W7500\uARM\MBED_23\ticker_2.bin" -p COM12 -t 15 -C 1.5 -m WIZwiki_W7500'
Test::Output::Start
MBED: Instrumentation: "COM12" and disk: "H:\"
HOST: Copy image onto target...
HOST: Initialize serial port...
........port ready!
HOST: Reset target...
HOST: Property 'timeout' = '15'
HOST: Property 'host_test_name' = 'wait_us_auto'
HOST: Property 'description' = 'Ticker Int us'
HOST: Property 'test_id' = 'MBED_23'
HOST: Start test...
* in 0.98 sec (0.02) [OK]
* in 1.00 sec (0.00) [OK]
* in 1.00 sec (0.00) [OK]
* in 0.98 sec (0.02) [OK]
* in 1.00 sec (0.00) [OK]
* in 1.00 sec (0.00) [OK]
* in 0.98 sec (0.02) [OK]
* in 1.00 sec (0.00) [OK]
* in 1.00 sec (0.00) [OK]
* in 0.98 sec (0.02) [OK]
Consecutive OK timer reads: 10
Completed in 9.92 sec


{{success}}

{{end}}
Test::Output::Finish
TargetTest::WIZwiki_W7500::uARM::MBED_23::Ticker Int us [OK] in 12.30 of 15 sec
Building project TIMEOUT (WIZwiki_W7500, uARM)
Executing 'python host_test.py -d H:\ -f "F:\WiznetGit_Repository\W7500_Miscellaneous\mbed-master\build\test\WIZwiki_W7500\uARM\MBED_24\timeout.bin" -p COM12 -t 15 -C 1.5 -m WIZwiki_W7500'
Test::Output::Start
MBED: Instrumentation: "COM12" and disk: "H:\"
HOST: Copy image onto target...
HOST: Initialize serial port...
........port ready!
HOST: Reset target...
HOST: Property 'timeout' = '15'
HOST: Property 'host_test_name' = 'wait_us_auto'
HOST: Property 'description' = 'Timeout Int us'
HOST: Property 'test_id' = 'MBED_24'
HOST: Start test...
* in 1.03 sec (0.03) [OK]
* in 1.04 sec (0.04) [OK]
* in 1.05 sec (0.05) [OK]
* in 1.03 sec (0.03) [OK]
* in 1.05 sec (0.05) [OK]
* in 1.04 sec (0.04) [OK]
* in 1.05 sec (0.05) [OK]
* in 1.03 sec (0.03) [OK]
* in 1.05 sec (0.05) [OK]
* in 1.05 sec (0.05) [OK]
Consecutive OK timer reads: 10
Completed in 10.41 sec


{{success}}

{{end}}
Test::Output::Finish
TargetTest::WIZwiki_W7500::uARM::MBED_24::Timeout Int us [OK] in 12.80 of 15 sec
Building project TIME_US (WIZwiki_W7500, uARM)
Executing 'python host_test.py -d H:\ -f "F:\WiznetGit_Repository\W7500_Miscellaneous\mbed-master\build\test\WIZwiki_W7500\uARM\MBED_25\time_us.bin" -p COM12 -t 15 -C 1.5 -m WIZwiki_W7500'
Test::Output::Start
MBED: Instrumentation: "COM12" and disk: "H:\"
HOST: Copy image onto target...
HOST: Initialize serial port...
........port ready!
HOST: Reset target...
HOST: Property 'timeout' = '15'
HOST: Property 'host_test_name' = 'wait_us_auto'
HOST: Property 'description' = 'Time us'
HOST: Property 'test_id' = 'MBED_25'
HOST: Start test...
* in 1.00 sec (0.00) [OK]
* in 1.00 sec (0.00) [OK]
* in 1.00 sec (0.00) [OK]
* in 1.00 sec (0.00) [OK]
* in 1.00 sec (0.00) [OK]
* in 1.00 sec (0.00) [OK]
* in 1.00 sec (0.00) [OK]
* in 1.00 sec (0.00) [OK]
* in 1.00 sec (0.00) [OK]
* in 1.00 sec (0.00) [OK]
Consecutive OK timer reads: 10
Completed in 9.98 sec


{{success}}

{{end}}
Test::Output::Finish
TargetTest::WIZwiki_W7500::uARM::MBED_25::Time us [OK] in 12.33 of 15 sec
Building project DIV (WIZwiki_W7500, uARM)
Executing 'python host_test.py -d H:\ -f "F:\WiznetGit_Repository\W7500_Miscellaneous\mbed-master\build\test\WIZwiki_W7500\uARM\MBED_26\div.bin" -p COM12 -t 10 -C 1.5 -m WIZwiki_W7500'
Test::Output::Start
MBED: Instrumentation: "COM12" and disk: "H:\"
HOST: Copy image onto target...
HOST: Initialize serial port...
...port ready!
HOST: Reset target...
HOST: Property 'timeout' = '20'
HOST: Property 'host_test_name' = 'default_auto'
HOST: Property 'description' = 'Integer constant division'
HOST: Property 'test_id' = 'MBED_26'
HOST: Start test...
64bit: 0x7FFFFFFF8: expected 0x55555555 got 0x55555555 ... [OK]

64bit: 0x17FFFFFFE8: expected 0xFFFFFFFF got 0xFFFFFFFF ... [OK]

{{success}}
{{end}}
Test::Output::Finish
TargetTest::WIZwiki_W7500::uARM::MBED_26::Integer constant division [OK] in 2.40 of 20 sec
Building project TICKER_3 (WIZwiki_W7500, uARM)
Executing 'python host_test.py -d H:\ -f "F:\WiznetGit_Repository\W7500_Miscellaneous\mbed-master\build\test\WIZwiki_W7500\uARM\MBED_34\ticker_3.bin" -p COM12 -t 15 -C 1.5 -m WIZwiki_W7500'
Test::Output::Start
MBED: Instrumentation: "COM12" and disk: "H:\"
HOST: Copy image onto target...
HOST: Initialize serial port...
...port ready!
HOST: Reset target...
HOST: Property 'timeout' = '20'
HOST: Property 'host_test_name' = 'default_auto'
HOST: Property 'description' = 'Integer constant division'
HOST: Property 'test_id' = 'MBED_26'
HOST: Start test...
64bit: 0x7FFFFFFF8: expected 0x55555555 got 0x55555555 ... [OK]

64bit: 0x17FFFFFFE8: expected 0xFFFFFFFF got 0xFFFFFFFF ... [OK]

{{success}}
{{end}}
Test::Output::Finish
TargetTest::WIZwiki_W7500::uARM::MBED_34::Ticker Two callbacks [OK] in 2.39 of 20 sec
Building project BASIC (WIZwiki_W7500, uARM)
Executing 'python host_test.py -d H:\ -f "F:\WiznetGit_Repository\W7500_Miscellaneous\mbed-master\build\test\WIZwiki_W7500\uARM\MBED_A1\basic.bin" -p COM12 -t 10 -C 1.5 -m WIZwiki_W7500'
Test::Output::Start
MBED: Instrumentation: "COM12" and disk: "H:\"
HOST: Copy image onto target...
HOST: Initialize serial port...
........port ready!
HOST: Reset target...
HOST: Property 'timeout' = '20'
HOST: Property 'host_test_name' = 'default_auto'
HOST: Property 'description' = 'Basic'
HOST: Property 'test_id' = 'MBED_A1'
HOST: Start test...
{{success}}
{{end}}
Test::Output::Finish
TargetTest::WIZwiki_W7500::uARM::MBED_A1::Basic [OK] in 2.48 of 20 sec
Building project CALL_BEFORE_MAIN (WIZwiki_W7500, uARM)
Executing 'python host_test.py -d H:\ -f "F:\WiznetGit_Repository\W7500_Miscellaneous\mbed-master\build\test\WIZwiki_W7500\uARM\MBED_A21\call_before_main.bin" -p COM12 -t 10 -C 1.5 -m WIZwiki_W7500'
Test::Output::Start
MBED: Instrumentation: "COM12" and disk: "H:\"
HOST: Copy image onto target...
HOST: Initialize serial port...
........port ready!
HOST: Reset target...
HOST: Unknown property: MBED: mbed_main() call before main()
HOST: Property 'timeout' = '20'
HOST: Property 'host_test_name' = 'default_auto'
HOST: Property 'description' = 'Call function mbed_main before main'
HOST: Property 'test_id' = 'MBED_A21'
HOST: Start test...
MBED: main() starts now!

{{success}}
{{end}}
Test::Output::Finish
TargetTest::WIZwiki_W7500::uARM::MBED_A21::Call function before main (mbed_main) [OK] in 2.45 of 20 sec
Building project ECHO (WIZwiki_W7500, uARM)
Executing 'python host_test.py -d H:\ -f "F:\WiznetGit_Repository\W7500_Miscellaneous\mbed-master\build\test\WIZwiki_W7500\uARM\MBED_A9\echo.bin" -p COM12 -t 10 -C 1.5 -m WIZwiki_W7500'
Test::Output::Start
MBED: Instrumentation: "COM12" and disk: "H:\"
HOST: Copy image onto target...
HOST: Initialize serial port...
........port ready!
HOST: Reset target...
HOST: Property 'timeout' = '20'
HOST: Property 'host_test_name' = 'echo'
HOST: Property 'description' = 'Serial Echo at 115200'
HOST: Property 'test_id' = 'MBED_A9'
HOST: Start test...
...port ready!
HOST: Starting the ECHO test
..................................................

{{success}}

{{end}}
Test::Output::Finish
TargetTest::WIZwiki_W7500::uARM::MBED_A9::Serial Echo at 115200 [OK] in 2.66 of 20 sec
Building project BUS_OUT (WIZwiki_W7500, uARM)
Executing 'python host_test.py -d H:\ -f "F:\WiznetGit_Repository\W7500_Miscellaneous\mbed-master\build\test\WIZwiki_W7500\uARM\MBED_BUSOUT\bus_out.bin" -p COM12 -t 15 -C 1.5 -m WIZwiki_W7500'
Test::Output::Start
MBED: Instrumentation: "COM12" and disk: "H:\"
HOST: Copy image onto target...
HOST: Initialize serial port...
........port ready!
HOST: Reset target...
HOST: Start test...
MBED: BusIn mask: 0xF

MBED: BusIn LED mask: 0xF

MBED: BusOut.bit[0] is connected

MBED: BusOut.bit[1] is connected

MBED: BusOut.bit[2] is connected

MBED: BusOut.bit[3] is connected

MBED: Blinking LEDs: 

AaBbCcDd

{{success}}
{{end}}
Test::Output::Finish
TargetTest::WIZwiki_W7500::uARM::MBED_BUSOUT::BusOut [OK] in 3.29 of 15 sec
Test summary:
+--------+---------------+-----------+-------------+---------------------------------------+--------------------+---------------+-------+
| Result | Target        | Toolchain | Test ID     | Test Description                      | Elapsed Time (sec) | Timeout (sec) | Loops |
+--------+---------------+-----------+-------------+---------------------------------------+--------------------+---------------+-------+
| OK     | WIZwiki_W7500 | uARM      | DTCT_1      | Simple detect test                    |        1.46        |       10      |  1/1  |
| OK     | WIZwiki_W7500 | uARM      | EXAMPLE_1   | /dev/null                             |        4.45        |       20      |  1/1  |
| OK     | WIZwiki_W7500 | uARM      | MBED_10     | Hello World                           |        1.34        |       5       |  1/1  |
| OK     | WIZwiki_W7500 | uARM      | MBED_11     | Ticker Int                            |       12.29        |       15      |  1/1  |
| OK     | WIZwiki_W7500 | uARM      | MBED_12     | C++                                   |        2.4         |       10      |  1/1  |
| FAIL   | WIZwiki_W7500 | uARM      | MBED_16     | RTC                                   |        5.51        |       20      |  0/1  |
| OK     | WIZwiki_W7500 | uARM      | MBED_2      | stdio                                 |        1.74        |       20      |  1/1  |
| OK     | WIZwiki_W7500 | uARM      | MBED_23     | Ticker Int us                         |        12.3        |       15      |  1/1  |
| OK     | WIZwiki_W7500 | uARM      | MBED_24     | Timeout Int us                        |        12.8        |       15      |  1/1  |
| OK     | WIZwiki_W7500 | uARM      | MBED_25     | Time us                               |       12.33        |       15      |  1/1  |
| OK     | WIZwiki_W7500 | uARM      | MBED_26     | Integer constant division             |        2.4         |       20      |  1/1  |
| OK     | WIZwiki_W7500 | uARM      | MBED_34     | Ticker Two callbacks                  |        2.39        |       20      |  1/1  |
| OK     | WIZwiki_W7500 | uARM      | MBED_A1     | Basic                                 |        2.48        |       20      |  1/1  |
| OK     | WIZwiki_W7500 | uARM      | MBED_A21    | Call function before main (mbed_main) |        2.45        |       20      |  1/1  |
| OK     | WIZwiki_W7500 | uARM      | MBED_A9     | Serial Echo at 115200                 |        2.66        |       20      |  1/1  |
| OK     | WIZwiki_W7500 | uARM      | MBED_BUSOUT | BusOut                                |        3.29        |       15      |  1/1  |
+--------+---------------+-----------+-------------+---------------------------------------+--------------------+---------------+-------+
Result: 1 FAIL / 15 OK

Completed in 182.77 sec

Build successes:
  * uARM::WIZwiki_W7500


저작자 표시
신고
이 댓글을 비밀 댓글로

W7500 mbed SDK Porting Guide (6/6)

Posted by 카이젠8501 카이젠8501
2015.10.08 15:04 IT 개발/mbed

W7500 mbed SDK Porting Guide

ADC Porting

예제 코드

#include "mbed.h"

int main() {

    Serial pc(USBTX, USBRX); // tx, rx
    pc.baud(115200);
    AnalogIn ain(A0); //is ADC0_0: must be channel 0 of ADC0 or ADC1

    pc.printf("Starting program...\r\n");

    while(1)
    {
        pc.printf("percentage: 3.3f\r\n", ain.read() * 100.0f);
        pc.printf("normalized: 0x%04X\r\n", ain.read_u16());
        wait(1);
    }
}

수정할 필요 없는 코드

api 폴더, common 폴더, hal 폴더에 있는 내용을 수정하면 호환성 문제가 발생 할 수 있으므로 수정하지 않는 것을 권한다.

  • api/AnalogIn.h

targets/hal/TARGET_WIZNET/TARGET_W7500x/analogin_api.c

특이사항
  • WIZWiki Board의 ADC Pin은 ADC_CH0, ADC_CH1, ADC_CH2, ADC_CH3, ADC_CH4, ADC_CH5만 사용함
  • analogin_read 함수는 출력되는 analog 값을 0 ~ 1 사이의 값으로 modulation 함
  • analgoin_read_u16 함수는 출력되는 analog 값을 16bit로 읽어 옴

ADC_TypeDef * AdcHandle;

int adc_inited = 0;

void analogin_init(analogin_t *obj, PinName pin)
{
    // Get the peripheral name from the pin and assign it to the object
    obj->adc = (ADCName)pinmap_peripheral(pin, PinMap_ADC);

    MBED_ASSERT(obj->adc != (ADCName)NC);

    // Configure GPIO
    pinmap_pinout(pin, PinMap_ADC);

    // Save pin number for the read function
    obj->pin = pin;

    // The ADC initialization is done once
    if (adc_inited == 0) {
        adc_inited = 1;

        ADC_Init();
    }
}

static inline uint16_t adc_read(analogin_t *obj)
{
    ADC_CH adc_ch;

    switch (obj->pin) {
        case PC_15:
            adc_ch = ADC_CH0;
            break;
        case PC_14:
            adc_ch = ADC_CH1;
            break;
        case PC_13:
            adc_ch = ADC_CH2;
            break;
        case PC_12:
            adc_ch = ADC_CH3;
            break;
        case PC_11:
            adc_ch = ADC_CH4;
            break;
        case PC_10:
            adc_ch = ADC_CH5;
            break;
        default:
            return 0;
    }

    ADC_ChannelSelect(adc_ch);
    ADC_Start();

    // Wait end of conversion and get value
    while(ADC_IsInterrupt());
    return ADC_ReadData();
}

uint16_t analogin_read_u16(analogin_t *obj)
{
    uint16_t value = adc_read(obj);
    // 12-bit to 16-bit conversion
    return value;
}

float analogin_read(analogin_t *obj)
{
    uint16_t value = adc_read(obj);

    return (float)value * (1.0f / (float)0xFFF); // 12 bits range
}


저작자 표시
신고

'IT 개발 > mbed' 카테고리의 다른 글

How to use pyOCD for new target MCU like W7500  (0) 2015.10.08
WIZwiki_W7500 CMSIS-DAP Porting  (0) 2015.10.08
W7500 mbed SDK Porting Guide (6/6)  (0) 2015.10.08
W7500 mbed SDK Porting Guide (5/6)  (0) 2015.10.08
W7500 mbed SDK Porting Guide (4/6)  (0) 2015.10.08
W7500 mbed porting Guide ( 3/6 )  (0) 2015.10.08
이 댓글을 비밀 댓글로

W7500 mbed SDK Porting Guide (5/6)

Posted by 카이젠8501 카이젠8501
2015.10.08 15:03 IT 개발/mbed

W7500 mbed SDK Porting Guide

I2C Master Porting

예제 코드

선택 영역_027.png

int main() {
    int address = 0xA0;
    char tx_data[27] = {0x00, 0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,
                        0x08, 0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x10,
                        0x10, 0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18};
    char rx_data[22]={0};

    I2C i2c(I2C_SDA, I2C_SCL);

    i2c.start();
    i2c.write(address,tx_data,9);

    wait(1);

    i2c.start();
    i2c.write(address,0x00,1,true);

    i2c.read(address,rx_data,27);

    for(int i=0;i<22;i++)
    {
        //pc.printf("Data[%d]: %x\r\n",i, rx_data[i]);
    }
}

수정할 필요 없는 코드

api 폴더, common 폴더, hal 폴더에 있는 내용을 수정하면 호환성 문제가 발생 할 수 있으므로 수정하지 않는 것을 권한다.

  • api/I2C.h
  • common/I2C.cpp

targets/hal/TARGET_WIZNET/TARGET_W7500x/i2c_api.c

  • i2c 초기화 및 frequency 설정을 위한 함수
void i2c_init(i2c_t *obj, PinName sda, PinName scl)
{
    // Determine the I2C to use
    I2CName i2c_sda = (I2CName)pinmap_peripheral(sda, PinMap_I2C_SDA);
    I2CName i2c_scl = (I2CName)pinmap_peripheral(scl, PinMap_I2C_SCL);

    obj->i2c = (I2CName)pinmap_merge(i2c_sda, i2c_scl);
    MBED_ASSERT(obj->i2c != (I2CName)NC);

    // Enable I2C1 clock and pinout if not done
    if ((obj->i2c == I2C_0) && !i2c0_inited) {
        i2c0_inited = 1;
        // Configure I2C pins
        pinmap_pinout(sda, PinMap_I2C_SDA);
        pinmap_pinout(scl, PinMap_I2C_SCL);
        pin_mode(sda, OpenDrain);
        pin_mode(scl, OpenDrain);
    }

    // Enable I2C2 clock and pinout if not done
    if ((obj->i2c == I2C_1) && !i2c1_inited) {
        i2c1_inited = 1;
        // Configure I2C pins
        pinmap_pinout(sda, PinMap_I2C_SDA);
        pinmap_pinout(scl, PinMap_I2C_SCL);
        pin_mode(sda, OpenDrain);
        pin_mode(scl, OpenDrain);
    }

    // Reset to clear pending flags if any
    i2c_reset(obj);

    // I2C configuration
    i2c_frequency(obj, 100000); // 100 kHz per default
    obj->is_setAddress = 0;
}

void i2c_frequency(i2c_t *obj, int hz)
{
    MBED_ASSERT((hz == 100000) || (hz == 400000) || (hz == 1000000));
    I2cHandle = (I2C_TypeDef *)(obj->i2c);

    // wait before init
    I2C_ConfigStruct conf;

    conf.mode = I2C_Master;
    conf.master.timeout = LONG_TIMEOUT;

    // Common settings: I2C clock = 48 MHz, Analog filter = ON, Digital filter coefficient = 0
    switch (hz) {
        case 100000:
            conf.master.prescale  = 0x61;      // Standard mode with Rise Time = 400ns and Fall Time = 100ns
            break;
        case 400000:
            break;
        case 1000000:
            break;
        default:
            break;
    }

    // I2C configuration
    I2C_Init(I2cHandle, conf);
}
특이사항
  • W7500 I2C 구조적인 차이로 i2c_start 시, i2c start signal을 내보내지 않음.
    • W7500은 I2C start signal을 설정하기 전에 Slave Address를 미리 저장하고 있어야 함.
  • 위 문제를 해결하기 위해, read/write 함수에서 Slave Address의 유/무를 확인하여 I2C Start Signal을 송신 함.
inline int i2c_start(i2c_t *obj)
{
    obj->is_setAddress = 0;

    return 0;
}

inline int i2c_stop(i2c_t *obj)
{
    I2cHandle = (I2C_TypeDef *)(obj->i2c);

    // Generate the STOP condition
    I2C_Stop(I2cHandle);
    I2C_Reset(I2cHandle);
    obj->is_setAddress = 0;

    return 0;
}

int i2c_read(i2c_t *obj, int address, char *data, int length, int stop)
{
    I2cHandle = (I2C_TypeDef *)(obj->i2c);
    int count;
    int value;

    if(!obj->is_setAddress)
    {
       if( I2C_Start(I2cHandle, address, I2C_READ_SA7) == ERROR )
        {
            return -1;
        }
       obj->is_setAddress = 1;
       obj->ADDRESS = address;
    }
    else
    {
        I2C_Restart_Structure(I2cHandle, address, I2C_READ_SA7);
        obj->ADDRESS = address;
    }

    // Read all bytes
    for (count = 0; count < (length-1); count++) {
        if( (value = i2c_byte_read(obj, 0)) == -1) return value;
        data[count] = (char)value;
    }

    if(stop){
        if( (value = i2c_byte_read(obj, 1)) == -1) return value;
        data[count] = (char)value;
    }
    else{
        if( (value = i2c_byte_read(obj, 0)) == -1) return value;
        data[count] = (char)value;
    }

    return count;
}

int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop)
{
    I2cHandle = (I2C_TypeDef *)(obj->i2c);
    int count;

    if(!obj->is_setAddress)
    {
       if( I2C_Start(I2cHandle, address, I2C_WRITE_SA7) == ERROR )
        {
            return -1;
        }
       obj->is_setAddress = 1;
       obj->ADDRESS = address;
    }
    else
    {
        I2C_Restart_Structure(I2cHandle, address, I2C_WRITE_SA7);
        obj->ADDRESS = address;
    }

    for (count = 0; count < length; count++) {
        i2c_byte_write(obj, data[count]);
    }

    // If not repeated start, send stop
    if (stop) {
        i2c_stop(obj);
    }

    return count;
}

int i2c_byte_read(i2c_t *obj, int last)
{
    I2cHandle = (I2C_TypeDef *)(obj->i2c);

    return I2C_ReceiveData(I2cHandle, last);
}

int i2c_byte_write(i2c_t *obj, int data)
{
    I2cHandle = (I2C_TypeDef *)(obj->i2c);
    return I2C_SendDataAck(I2cHandle,(uint8_t)data);
}

void i2c_reset(i2c_t *obj)
{
    I2cHandle = (I2C_TypeDef *)(obj->i2c);

    I2C_Reset(I2cHandle);
}


저작자 표시
신고

'IT 개발 > mbed' 카테고리의 다른 글

WIZwiki_W7500 CMSIS-DAP Porting  (0) 2015.10.08
W7500 mbed SDK Porting Guide (6/6)  (0) 2015.10.08
W7500 mbed SDK Porting Guide (5/6)  (0) 2015.10.08
W7500 mbed SDK Porting Guide (4/6)  (0) 2015.10.08
W7500 mbed porting Guide ( 3/6 )  (0) 2015.10.08
W7500 mbed porting Guide ( 2/6 )  (0) 2015.10.08
이 댓글을 비밀 댓글로

W7500 mbed SDK Porting Guide (4/6)

Posted by 카이젠8501 카이젠8501
2015.10.08 15:02 IT 개발/mbed

W7500 mbed SDK Porting Guide

wait Dealy Porting

예제 코드

#include "mbed.h"

int main()
{
    Serial pc(USBTX, USBRX);
    DigitalOut myled(LED1);

    pc.baud(115200);
    pc.printf("TEST Start\r\n");

    myled = 0;
    while(1){
        pc.printf("LED ON\r\n");
        myled = 1; // LED is ON
        wait(1); // 1 sec
        pc.printf("LED OFF\r\n");
        myled = 0; // LED is OFF
        wait(1); // 1 sec
    }
}

수정할 필요 없는 코드

api 폴더, common 폴더, hal 폴더에 있는 내용을 수정하면 호환성 문제가 발생 할 수 있으므로 수정하지 않는 것을 권한다.
GPIO Porting시 사용하는 아래 파일들은 수정할 필요가 없다.

  • api/wait_api.h
  • common/wait_api.c

common/wait_api.c

  • 아래 함수를 수정 할 필요는 없으나 wait 함수 동작을 위해 함수 구현부를 정리 하였다.
  • wait_us()에서는 PWM의 Counter 값을 읽고 함수가 시작했을 때의 Counter 값의 차이가 원하는 Delay 시간이 될 때 까지 Polling으로 기다림
void wait(float s) {
    wait_us(s * 1000000.0f);
}

void wait_ms(int ms) {
    wait_us(ms * 1000);
}

void wait_us(int us) {

    uint32_t start = us_ticker_read();
    while ((us_ticker_read() - start) < (uint32_t)us);
}

targets/hal/TARGET_WIZNET/TARGET_W7500x/us_ticker.c

  • 1us의 counter를 사용하기 위해 PWM을 아래와 같이 설정 함
// 32-bit timer selection
#define TIM_MST PWM_CH7

//static TIM_HandleTypeDef TimMasterHandle;
static PWM_TimerModeInitTypeDef TimMasterHandle;
static int us_ticker_inited = 0;

void us_ticker_init(void)
{
    if (us_ticker_inited) return;
    us_ticker_inited = 1;

    TimMasterHandle.PWM_CHn_PR = (GetSystemClock() / 1000000) -1;
    TimMasterHandle.PWM_CHn_LR = 0xFFFFFFFF;
    TimMasterHandle.PWM_CHn_PDMR = 1;

    PWM_TimerModeInit(TIM_MST, &TimMasterHandle);
    PWM_CHn_Start(TIM_MST);
}

uint32_t us_ticker_read()
{
    if (!us_ticker_inited) us_ticker_init();

    return TIM_MST->TCR;
}


저작자 표시
신고

'IT 개발 > mbed' 카테고리의 다른 글

W7500 mbed SDK Porting Guide (6/6)  (0) 2015.10.08
W7500 mbed SDK Porting Guide (5/6)  (0) 2015.10.08
W7500 mbed SDK Porting Guide (4/6)  (0) 2015.10.08
W7500 mbed porting Guide ( 3/6 )  (0) 2015.10.08
W7500 mbed porting Guide ( 2/6 )  (0) 2015.10.08
W7500 mbed porting Guide ( 1/6 )  (0) 2015.10.08
이 댓글을 비밀 댓글로