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
이 댓글을 비밀 댓글로

W7500 mbed porting Guide ( 3/6 )

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

W7500 mbed SDK Porting Guide

Serial Porting

예제 코드

#include "mbed.h"

int main()
{
    Serial pc(USBTX, USBRX);

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

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

수정할 필요 없는 코드

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

  • api/Serial.h
  • api/SerialBase.h
  • common/Serial.cpp
  • common/SerialBase.cpp

targets/hal/TARGET_WIZNET/TARGET_W7500x/TARGET_WIZwiki_W7500/PeripheralPins.c

  • UART 사용 시 필요한 RX, TX Pin 정보를 저장
  • 상위 어플리케이션에서는 PA_14라는 Pin 정보만 줘도 아래 PinMap으로 UART0의 TX Pin을 설정 할 수 있음
//*** SERIAL ***
const PinMap PinMap_UART_TX[] = {
    {PA_14, UART_0, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_PULLUP, Px_AFSR_AF0)},
    {PC_2,  UART_1, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_PULLUP, Px_AFSR_AF0)},
    {NC,    NC,     0}
};

const PinMap PinMap_UART_RX[] = {
    {PA_13, UART_0, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_PULLUP, Px_AFSR_AF0)},
    {PC_3,  UART_1, WIZ_PIN_DATA(WIZ_MODE_AF, WIZ_GPIO_PULLUP, Px_AFSR_AF0)},
    {NC,    NC,     0}
};

targets/hal/TARGET_WIZNET/TARGET_W7500x/serial_api.c

  • Serial 객체 생성 및 사용 시, Serial.cpp와 SerialBase.cpp를 통해 아래 코드 수행
static void init_uart(serial_t *obj)
{
    UART = (UART_TypeDef *)(obj->uart);
    UART_InitStructure.UART_BaudRate            = obj->baudrate;
    UART_InitStructure.UART_WordLength          = obj->databits;
    UART_InitStructure.UART_StopBits            = obj->stopbits;
    UART_InitStructure.UART_Parity              = obj->parity;
    UART_InitStructure.UART_HardwareFlowControl = UART_HardwareFlowControl_None;


    if (obj->pin_rx == NC) {
        UART_InitStructure.UART_Mode = UART_Mode_Tx;
    } else if (obj->pin_tx == NC) {
        UART_InitStructure.UART_Mode = UART_Mode_Rx;
    } else {
        UART_InitStructure.UART_Mode = (UART_Mode_Rx | UART_Mode_Tx);
    }

    UART_Init(UART,&UART_InitStructure);
}

void serial_init(serial_t *obj, PinName tx, PinName rx)
{
    // Determine the UART to use (UART_1, UART_2, ...)
    UARTName uart_tx = (UARTName)pinmap_peripheral(tx, PinMap_UART_TX);
    UARTName uart_rx = (UARTName)pinmap_peripheral(rx, PinMap_UART_RX);

    // Get the peripheral name (UART_1, UART_2, ...) from the pin and assign it to the object
    obj->uart = (UARTName)pinmap_merge(uart_tx, uart_rx);

    MBED_ASSERT(obj->uart != (UARTName)NC);

    // Enable USART clock
    if (obj->uart == UART_0) {
        obj->index = 0;
    }

    if (obj->uart == UART_1) {
        obj->index = 1;
    }

    // Configure the UART pins
    pinmap_pinout(tx, PinMap_UART_TX);
    pinmap_pinout(rx, PinMap_UART_RX);
    if (tx != NC) {
        pin_mode(tx, PullUp);
    }
    if (rx != NC) {
        pin_mode(rx, PullUp);
    }

    // Configure UART
    obj->baudrate = 9600;
    obj->databits = UART_WordLength_8b;
    obj->stopbits = UART_StopBits_1;
    obj->parity   = UART_Parity_No;

    obj->pin_tx = tx;
    obj->pin_rx = rx;


    init_uart(obj);

    // For stdio management
    if (obj->uart == STDIO_UART) {
        stdio_uart_inited = 1;
        memcpy(&stdio_uart, obj, sizeof(serial_t));
    }
}

void serial_baud(serial_t *obj, int baudrate)
{
    obj->baudrate = baudrate;
    init_uart(obj);
}

void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_bits)
{
    if (data_bits == 7) {
        obj->databits = UART_WordLength_7b;
    } else {
        obj->databits = UART_WordLength_8b;
    }

    switch (parity) {
        case ParityOdd:
        case ParityForced0:
            obj->parity = UART_Parity_Odd;
            break;
        case ParityEven:
        case ParityForced1:
            obj->parity = UART_Parity_Even;
            break;
        default: // ParityNone
            obj->parity = UART_Parity_No;
            break;
    }

    if (stop_bits == 2) {
        obj->stopbits = UART_StopBits_2;
    } else {
        obj->stopbits = UART_StopBits_1;
    }

    init_uart(obj);
}


/******************************************************************************
 * READ/WRITE
 ******************************************************************************/

int serial_getc(serial_t *obj)
{
    UART_TypeDef *uart = (UART_TypeDef *)(obj->uart);
//    while(!serial_readable(obj));
    while(uart->FR & UART_FR_RXFE);

    return (uart->DR & 0xFF);
}

void serial_putc(serial_t *obj, int c)
{
    UART_TypeDef *uart = (UART_TypeDef *)(obj->uart);

    uart->DR = (uint32_t)(c & (uint16_t)0xFF);
    while(uart->FR & UART_FR_BUSY);
}

int serial_readable(serial_t *obj)
{
    int status;
    UART_TypeDef *uart = (UART_TypeDef *)(obj->uart);
    // Check if data is received
    status = ((uart->FR & UART_FR_RXFE) ? 0: 1);
    return status;
}

int serial_writable(serial_t *obj)
{
    int status;
    UART_TypeDef *uart = (UART_TypeDef *)(obj->uart);
    // Check if data is transmitted
    status = ((uart->FR & UART_FR_BUSY) ? 0: 1);
    return status;
}
저작자 표시
신고

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

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
mbed rpc interfacing with Python  (0) 2015.10.08
이 댓글을 비밀 댓글로

W7500 mbed porting Guide ( 2/6 )

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

W7500 mbed SDK Porting Guide

GPIO Porting

예제 코드

#include "mbed.h"

////MBED Example 1 LED CONTROL AND Serial Output
int main()
{
    DigitalOut myled(LED1);

    myled = 0;
    while(1){
        myled = 1; // LED is ON
        wait(1); // 1 sec
        myled = 0; // LED is OFF
        wait(1); // 1 sec
    }
}

수정할 필요 없는 코드

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

  • api/DigitalOut.h
  • common/gpio.c
  • hal/gpio_api.h

targets/hal/TARGET_WIZNET/TARGET_W7500x/TARGET_WIZwiki_W7500/PortNames.h

typedef enum {
    PortA = 0,
    PortB = 1,
    PortC = 2,
    PortD = 3,
} PortName;

targets/hal/TARGET_WIZNET/TARGET_W7500x/TARGET_WIZwiki_W7500/PinNames.h

  • W7500 Chip의 Pin 정보를 mbed SDK를 위한 형태로 변경
  • PinName 규칙 (AF[9:8] + PORT[5:4] + PIN[3:0])
    • ex) PC_10 = 0x32A, // 0xx:U_TXD2, 1xx:GPIOC_10, 2xx:PWM2, 3xx:AIN5
// See W7500x_hal_gpio.h for values of MODE, PUPD and AFNUM
#define WIZ_PIN_DATA(MODE, PUPD, AFNUM)  ((int)(((AFNUM) << 8) | ((PUPD) << 4) | ((MODE) << 0)))
#define WIZ_PIN_MODE(X)       (((X) >> 0) & 0x0F)
#define WIZ_PIN_PUPD(X)       (((X) >> 4) & 0x0F)
#define WIZ_PIN_AFNUM(X)      (((X) >> 8) & 0x0F)
#define WIZ_MODE_INPUT              (0)
#define WIZ_MODE_OUTPUT             (1)
#define WIZ_MODE_AF                 (2)

#define WIZ_GPIO_NOPULL             (0)   /*!< No Pull-up or Pull-down activation  */
#define WIZ_GPIO_PULLDOWN           (1)   /*!< Pull-down activation                */
#define WIZ_GPIO_PULLUP             (2)   /*!< Pull-up activation                  */
#define WIZ_GPIO_OPEN_DRAIN         (3)   /*!< Open Drain activation               */


#define WIZ_AFNUM(X)(((uint32_t)(X) >> 8) & 0xF)    // AF number   (0=AF0, 1=AF1, 2=AF2, 3=AF3)
#define WIZ_PORT(X) (((uint32_t)(X) >> 4) & 0xF)    // port number (0=A, 1=B, 2=C, 3=D)
#define WIZ_PIN(X)  ((uint32_t)(X) & 0xF)           // pin number


typedef enum {
    PIN_INPUT,
    PIN_OUTPUT
} PinDirection;


typedef enum {
    // W7500x Pin Names (AF[9:8] + PORT[5:4] + PIN[3:0])

    PA_0  = 0x000,
    PA_1  = 0x001,
    PA_2  = 0x002,
    PA_3  = 0x003,
    PA_4  = 0x004,
    PA_5  = 0x005,
    PA_6  = 0x006,
    PA_7  = 0x007,
    PA_8  = 0x008,
    PA_9  = 0x009,
    PA_10 = 0x00A,
    PA_11 = 0x00B,
    PA_12 = 0x00C,
    PA_13 = 0x00D,
    PA_14 = 0x00E,
    PA_15 = 0x00F,

    PB_0  = 0x010, //SSEL1/SD_SEL
    PB_1  = 0x011, //SCLK1/SD_CLK
    PB_2  = 0x012, //MISO1/SD_MISO
    PB_3  = 0x013, //MOSI1/SD_MOSI
    PB_4  = 0x014,
    PB_5  = 0x015,
    PB_6  = 0x016,
    PB_7  = 0x017,
    PB_8  = 0x018,
    PB_9  = 0x019,
    PB_10 = 0x01A,
    PB_11 = 0x01B,
    PB_12 = 0x01C,
    PB_13 = 0x01D,
    PB_14 = 0x01E,
    PB_15 = 0x01F,

    PC_0  = 0x120,  // 0xx:U_CTS1, 1xx:GPIOC_0, 2xx:PWM0
    PC_1  = 0x121,  // 0xx:U_RTS1, 1xx:GPIOC_1, 2xx:PWM1
    PC_2  = 0x022,
    PC_3  = 0x023,
    PC_4  = 0x124,  // 0xx:SDA1, 1xx:GPIOC_4, 2xx:PWM4
    PC_5  = 0x025,
    PC_6  = 0x026,
    PC_7  = 0x027,
    PC_8  = 0x128,  // 0xx:PWM0,   1xx:GPIOC_8,  2xx:SCL0,  3xx:AIN7
    PC_9  = 0x129,  // 0xx:PWM1,   1xx:GPIOC_9,  2xx:SDA0,  3xx:AIN6

    PC_10 = 0x32A,  // 0xx:U_TXD2, 1xx:GPIOC_10, 2xx:PWM2,  3xx:AIN5
    PC_11 = 0x32B,  // 0xx:U_RXD2, 1xx:GPIOC_11, 2xx:PWM3,  3xx:AIN4
    PC_12 = 0x32C,  // 0xx:AIN3,   1xx:GPIOC_12, 2xx:SSEL0, 3xx:AIN3
    PC_13 = 0x32D,  // 0xx:AIN2,   1xx:GPIOC_13, 2xx:SCLK0, 3xx:AIN2
    PC_14 = 0x32E,  // 0xx:AIN1,   1xx:GPIOC_14, 2xx:MISO0, 3xx:AIN1
    PC_15 = 0x32F,  // 0xx:AIN0,   1xx:GPIOC_15, 2xx:MOSI0, 3xx:AIN0

    PD_0  = 0x030,
    PD_1  = 0x031,
    PD_2  = 0x032,
    PD_3  = 0x033,
    PD_4  = 0x034,


    // Arduino connector namings
    A0          = PC_15,            // AIN0
    A1          = PC_14,            // AIN1
    A2          = PC_13,            // AIN2
    A3          = PC_12,            // AIN3
    A4          = PC_11,            // AIN4
    A5          = PC_10,            // AIN5
    D0          = PA_14,            // U_TXD0
    D1          = PA_13,            // U_RXD0
    D2          = PC_1,            // GPIOC_1, EXTI
    D3          = PC_0,            // GPIOC_0, EXTI
    D4          = PA_2,            // GPIOA_2,
    D5          = PA_1,            // GPIOA_1,
    D6          = PA_0,            // GPIOA_0,
    D7          = PC_6,            // GPIOC_6, EXTI
    D8          = PC_7,            // GPIOC_7, EXTI
    D9          = PC_4,            // GPIOC_4, EXTI
    D10         = PA_5,            // SSEL0
    D11         = PA_8,            // MOSI0
    D12         = PA_7,            // MISO0
    D13         = PA_6,            // SCLK0
    D14         = PA_10,            // SDA0
    D15         = PA_9,            // SCL0

    // Generic signals namings
    LED_RED      = PC_8,
    LED_GREEN    = PC_9,
    LED_BLUE     = PC_5,

    LED1        = LED_RED,
    LED2        = LED_GREEN,
    LED3        = LED_BLUE,
//    USER_BUTTON = PC_13,
    SERIAL_TX   = PC_2,            // U_TXD1
    SERIAL_RX   = PC_3,            // U_RXD1
    USBTX       = SERIAL_TX,
    USBRX       = SERIAL_RX,
    I2C_SCL     = PA_9,         // SCL0
    I2C_SDA     = PA_10,        // SDA0
    SPI_MOSI    = PA_8,         // MISO0
    SPI_MISO    = PA_7,         // MOSI0
    SPI_SCK     = PA_9,         // SCL0
    SPI_CS      = PA_5,         // SSEL0
    SD_SEL      = PB_0,         // SSEL1
    SD_CLK      = PB_1,         // SCL1
    SD_MISO     = PB_2,         // MOSI1
    SD_MOSI     = PB_3,         // MISO1
//    PWM_OUT     = PC_7,

    // Not connected
    NC = (int)0xFFFFFFFF
} PinName;

targets/hal/TARGET_WIZNET/TARGET_W7500x/gpio_object.h

  • PinNames.h에 정의한 Pin 정보들을 이용하여 GPIO pin을 read, write 하기 위한 Function 구현
typedef struct {
    PinName  pin;
    uint32_t mask;

    __IO uint32_t *reg_data_in;
} gpio_t;


extern uint32_t Get_GPIO_BaseAddress(uint32_t port_idx);


static inline void gpio_write(gpio_t *obj, int value) {
    MBED_ASSERT(obj->pin != (PinName)NC);

    uint32_t port_index = WIZ_PORT(obj->pin);
    uint32_t pin_index  = WIZ_PIN(obj->pin);

    uint32_t gpio_add = Get_GPIO_BaseAddress(port_index);
    GPIO_TypeDef *gpio = (GPIO_TypeDef *)gpio_add;

    if (value)
    {
        HAL_GPIO_SetBits(gpio,(0x01 << pin_index));
    }
    else
    {
        HAL_GPIO_ResetBits(gpio,(0x01 << pin_index));
    }
}

static inline int gpio_read(gpio_t *obj) {
    MBED_ASSERT(obj->pin != (PinName)NC);

    return ((*obj->reg_data_in & obj->mask) ? 1 : 0);
}

static inline int gpio_is_connected(const gpio_t *obj) {
    return obj->pin != (PinName)NC;
}

targets/hal/TARGET_WIZNET/TARGET_W7500x/pinmap.c

  • Pin들을 설정하기 위한 함수 구현
    • Output,Input,Alternative Fuction을 설정 할 수 있음.
    • Pin Mode 설정을 위한 함수 구현 —> Pull up, Pull down, Open Drain
  • 실질적인 pin을 Control 하기 위한 기능들이 구현되어 있음
// GPIO mode look-up table
// It have to same with PinMode index in "PinNames.h"
static const uint32_t gpio_pupd[4] = {
    GPIO_NO_PUPD,           //  PullNone
    GPIO_PuPd_DOWN,         //  PullDown
    GPIO_PuPd_UP,           //  PullUp
    GPIO_OD                 //  OpenDrain
};

uint32_t Get_GPIO_BaseAddress(uint32_t port_idx)
{
    uint32_t gpio_add = 0;
    switch(port_idx)    {
        case PortA:
            gpio_add = GPIOA_BASE;
            break;
        case PortB:
            gpio_add = GPIOB_BASE;
            break;
        case PortC:
            gpio_add = GPIOC_BASE;
            break;
        case PortD:
            gpio_add = GPIOD_BASE;
            break;
        default:
            error("Pinmap error: wrong port number.");
            break;
    }
    return gpio_add;
}


/**
 * Configure pin (input, output, alternate function or analog) + output speed + AF
 */

void pin_function(PinName pin, int data) {
    MBED_ASSERT(pin != (PinName)NC);
    // Get the pin informations
    uint32_t mode  = WIZ_PIN_MODE(data);
    uint32_t pupd  = WIZ_PIN_PUPD(data);
    uint32_t afnum;

    if( mode == WIZ_MODE_AF )
        afnum = WIZ_PIN_AFNUM(data);
    else
        afnum = WIZ_AFNUM(pin);

    uint32_t port_index = WIZ_PORT(pin);
    uint32_t pin_index  = WIZ_PIN(pin);


    uint32_t gpio_add = Get_GPIO_BaseAddress(port_index);
    GPIO_TypeDef *gpio = (GPIO_TypeDef *)gpio_add;

    // Configure Alternate Function
    // Warning: Must be done before the GPIO is initialized
    switch (afnum) {
        case 0:
            HAL_PAD_AFConfig(port_index,(uint32_t)(1 << pin_index),Px_AFSR_AF0);
            break;
        case 1:
            HAL_PAD_AFConfig(port_index,(uint32_t)(1 << pin_index),Px_AFSR_AF1);
            break;
        case 2:
            HAL_PAD_AFConfig(port_index,(uint32_t)(1 << pin_index),Px_AFSR_AF2);
            break;
        case 3:
            HAL_PAD_AFConfig(port_index,(uint32_t)(1 << pin_index),Px_AFSR_AF3);
            break;
        default:
            break;
    }

    if(mode == WIZ_MODE_AF)
        return;

    // Configure GPIO
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin       = (uint32_t)(1 << pin_index);
    GPIO_InitStructure.GPIO_Mode      = mode;
    GPIO_InitStructure.GPIO_Pad       = gpio_pupd[pupd];
    HAL_GPIO_Init(gpio, &GPIO_InitStructure);
}

/**
 * Configure pin pull-up/pull-down
 */
void pin_mode(PinName pin, PinMode pupd)
{
    MBED_ASSERT(pin != (PinName)NC);

    P_Port_Def *px_pcr;

    uint32_t port_index = WIZ_PORT(pin);

    switch(port_index)    {
        case PortA:
            px_pcr = PA_PCR;
            break;
        case PortB:
            px_pcr = PB_PCR;
            break;
        case PortC:
            px_pcr = PC_PCR;
            break;
        case PortD:
            px_pcr = (P_Port_Def*)PD_PCR;
            break;
        default:
            error("Pinmap error: wrong port number.");
            return;
    }

    px_pcr->Port[port_index] &= ~(Px_PCR_PUPD_DOWN|Px_PCR_PUPD_UP|Px_PCR_DS_HIGH| \
                                  Px_PCR_OD | Px_PCR_IE | Px_PCR_CS_SUMMIT);
    px_pcr->Port[port_index] |= gpio_pupd[pupd];
}

targets/hal/TARGET_WIZNET/TARGET_W7500x/gpio_api.c

  • pinmap.c에 구현한 함수를 이용하여 gpio 설정을 변경
extern uint32_t Get_GPIO_BaseAddress(uint32_t port_idx);

uint32_t gpio_set(PinName pin)
{
    MBED_ASSERT(pin != (PinName)NC);

    pin_function(pin, WIZ_PIN_DATA(WIZ_MODE_INPUT, WIZ_GPIO_NOPULL, 0));

    return (uint32_t)(1 << ((uint32_t)pin & 0xF)); // Return the pin mask
}

void gpio_init(gpio_t *obj, PinName pin)
{
    obj->pin = pin;
    if (pin == (PinName)NC) {
        return;
    }

    uint32_t port_index = WIZ_PORT(pin);

    GPIO_TypeDef *gpio = (GPIO_TypeDef *)Get_GPIO_BaseAddress(port_index);

    // Fill GPIO object structure for future use
    obj->mask    = gpio_set(pin);
    obj->reg_data_in    = &gpio->DATA;
}

void gpio_mode(gpio_t *obj, PinMode mode)
{
    pin_mode(obj->pin, mode);
}

void gpio_dir(gpio_t *obj, PinDirection direction)
{
    MBED_ASSERT(obj->pin != (PinName)NC);
    if (direction == PIN_OUTPUT) {
        pin_function(obj->pin, WIZ_PIN_DATA(WIZ_MODE_OUTPUT, WIZ_GPIO_NOPULL, 0));
    } else { // PIN_INPUT
        pin_function(obj->pin, WIZ_PIN_DATA(WIZ_MODE_INPUT, WIZ_GPIO_NOPULL, 0));
    }
}
저작자 표시
신고

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

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
mbed rpc interfacing with Python  (0) 2015.10.08
mbed RPC Library porting guide for WIZwiki-W7500  (0) 2015.10.08
이 댓글을 비밀 댓글로

W7500 mbed porting Guide ( 1/6 )

Posted by 카이젠8501 카이젠8501
2015.10.08 14:58 IT 개발/mbed

W7500 mbed porting Guide

현재 회사에서 W7500 Peripheral Library Firmware 구현과 mbed에 등록하기 위한 Porting 작없을 진행하고 있다.
본 포스팅에서는 W7500을 mbed에 등록하기 위한 Porting 작업을 진행하는 방법과 기술적인 이슈들을 정리 한다.

mbed SDK Porting 개요

mbed Porting의 궁극적인 목적은 mbed에서 제공하는 아래와 같은 코드를 W7500에서 동작 할 수 있도록 Interface Code를 구현하는 것이다.

#include "mbed.h"

////MBED Example 1 LED CONTROL AND Serial Output
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
    }
}

mbed SDK Porting을 위한 코드 및 자세한 정보는 아래 주소에서 얻을 수 있다.
http://developer.mbed.org/handbook/mbed-SDK-porting

mbed SDK 폴더 구조

mbed SDK의 폴더 구조는 크게 api, common, hal, targets 으로 구분 된다. 각 폴더에 대한 간략한 설명은 아래와 같다.

api

api 폴더에는 아래 그림과 같은 파일들이 존재 하며, 각 파일들은 User가 Application을 구현 할 때 필요한 API 들의 프로토타입들이 존재 한다.

선택 영역_017.png

common

api 폴더에서 선언한 프로토타입들을 구현한 파일들이 존재 한다.
common 폴더의 구현부에서 Chip에 종속적인 함수들을 호출 할 때는 Hal 폴더에 정의된 함수들을 이용한다.

선택 영역_018.png

hal

Chip에 종속적인 기능을 사용 하기 위한 Interface API들의 프로토타입들이 존재 하며, common 폴더의 함수들은 hal에 정의되어 있는 함수들을 이용하여 Chip에 종속적인 기능을 이용한다.

선택 영역_019.png

targets

targets 폴더는 cmsis와 hal로 나뉜다.

targets/cmsis

targets/cmsis는 chip을 구동하기 위해 필요한 startup code와 linker script 들이 존재 하며, verdor에 따라서는 Chip을 제어하기 위한 Library Code 들을 보관 한다.

선택 영역_024.png

targets/hal

hal 폴더에서 정의한 프로토타입들의 실제 구현 코드들을 보관하며, common 폴더의 함수들이 Chip에 종속적인 기능을 사용하기 위해서는 targets/hal 폴더에 정의된 함수들을 호출한다.

선택 영역_026.png

저작자 표시
신고

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

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
mbed rpc interfacing with Python  (0) 2015.10.08
mbed RPC Library porting guide for WIZwiki-W7500  (0) 2015.10.08
mbed RPC  (0) 2015.10.08
이 댓글을 비밀 댓글로

mbed RPC Library porting guide for WIZwiki-W7500

Posted by 카이젠8501 카이젠8501
2015.10.08 14:42 IT 개발/mbed

mbed RPC Library porting guide for WIZwiki-W7500

Used library in this project

Modified Point

mbed rpc를 사용하기 위한 Interface는 RPC over Serial과 RPC over HTTP로 나눌 수 있다. 본 예제에서는 HTTP를 이용하여 RPC를 사용하며, mbed platform 에는 HTTPServer가 구동되고 있다. mbed rpc를 위한 Interface에 대한 자세한 정보는 Link를 참고 하기 바란다.

WIZnetInterface

HTTPServer Library에서 아래와 같은 코드를 사용하는데, WIZnetInterface에는 init()함수가 없음 —> WIZnetLibrary에 init() 함수 추가

HTTPServer/HTTPServer.cpp ( Line 50~56 )

INFO("Initializing network\n");
if (m_pEthernet->init() != 0) {
    ERR("Failed to initialize the ethernet interface !");
    delete m_pEthernet;
    m_pEthernet = NULL;
    return false;
}

mbed-rpc

공식 mbed-rpc Library에서 WIZwiki-W7500의 Pin들을 사용할 수 있도록 아래와 같이 코드를 추가 하였다.

mbed-rpc/parse_pins.cpp

#elif defined(TARGET_WIZwiki_W7500)
    if (str[0] == 'P' && str[2] == '_') {   // Px_n
        uint32_t port = str[1] - 'A';
        uint32_t pin  = str[3] - '0';       // Px_n
        uint32_t pin2 = str[4] - '0';       // Px_nn

        if (pin2 <= 9) {
            pin = pin * 10 + pin2;
        }
        return port_pin((PortName)port, pin);
#endif

WIZwiki-W7500의 Port와 Pin들은 아래와 같은 규칙으로 정의 되어 있으므로, parse_pins.cpp 에서는 PA_0와 같은 String Data를 받아 0x000과 같은 Int Data로 변환하는 동작을 수행한다.

// In PinNames.h

// W7500x PORT[5:4] + PIN[3:0])
PA_0  = 0x000,
PA_1  = 0x001,
PA_2  = 0x002,
...
PB_9  = 0x019,
PB_10 = 0x01A,
PB_11 = 0x01B,
...
PC_0  = 0x020,
PC_1  = 0x021,
PC_2  = 0x022,
...
// In PortNames.h

typedef enum {
    PortA = 0,
    PortB = 1,
    PortC = 2,
    PortD = 3,
} PortName;

mbed rpc library에 WIZwiki-W7500을 위한 코드를 추가한 후, mbed official repository에 pull request를 보내서 코드 업데이트를 요청 하였다.

Run Simple Example

#include "mbed.h"
#include "EthernetInterface.h"
#include "HTTPServer.h"
#include "mbed_rpc.h"

RpcDigitalOut led1(LED1,"led1");

EthernetInterface eth;  
HTTPServer svr;

int main() {
  //Turn the LEDs off
  uint8_t mac_addr[6] = {0x00, 0x08, 0xDC, 0x00, 0x00, 0x00}; 
  led1.write(1);

  RPC::add_rpc_class<RpcDigitalOut>();

  printf("Setting up...\n");
  eth.init(mac_addr);
  int ethErr = eth.connect();
  if(ethErr < 0)
  {
    printf("Error %d in setup.\n", ethErr);
    return -1;
  }

  svr.addHandler<HTTPRpcRequestHandler>("/rpc");

  //attach server to port 80
  svr.start(80, &eth);

  printf("Listening...\n");

  Timer tm;
  tm.start();
  //Listen indefinitely
  while(true)
  {
    svr.poll();
    if(tm.read()>.5)
    {
      tm.start();
    }
  }
}
  • 6 : 제어를 원하는 GPIO의 RPC Name 지정
  • 19~20 : ethernet interface 초기화 및 DHCP 수행
  • 27 : HTTPRpcRequestHandler 등록
  • 30 : HTTP Server Start ( TCP Server로 80포트 리슨)


저작자 표시
신고

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

W7500 mbed porting Guide ( 1/6 )  (0) 2015.10.08
mbed rpc interfacing with Python  (0) 2015.10.08
mbed RPC Library porting guide for WIZwiki-W7500  (0) 2015.10.08
mbed RPC  (0) 2015.10.08
[FRDM-KL25Z]WIZ550 ioShield-A Porting Guide  (0) 2014.08.20
Eclipse에서 mbed repository 연동 하기  (0) 2014.06.15
이 댓글을 비밀 댓글로