打印
[ZLG-ARM]

在easyARM2200上成功移植eCos

[复制链接]
2181|10
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
3B1105|  楼主 | 2010-6-23 20:50 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
沙发
6019实验室| | 2010-6-23 20:51 | 只看该作者
移植中的问题现在移植过程中还有一个难题,就是8019的移植。找到的ecos下8019的补丁代码是在PC下的代码。虽然有人声称移植成功,但它给出的具体方法好像并不适用于ARM,特别好像不适用于ZLG平台。我正在研究,希望大家给点意见。

使用特权

评论回复
板凳
huzixian| | 2010-6-23 20:52 | 只看该作者
请教楼主楼主有没有测试uart0,1的驱动?不是hal的串行驱动,是dev和io层的,
我测试下来uart0是ok的,uart1用中断方式驱动死活不行。后来查出是lpc
的bug在搞鬼,要改就要改dev中的16x5x通用驱动。没办法,只好uart0用上层
驱动,uart1用hal驱动,反正用起来也一样,等lpc修正了bug再说。
不知楼主是怎么解决这个问题的,希望可以多多交流:)

使用特权

评论回复
地板
3B1105|  楼主 | 2010-6-23 20:53 | 只看该作者
还是不行看来不是硬件问题。
sgwu大哥能把变体抽象层(如果改动的话)和平台抽象层代码给我看看吗?

使用特权

评论回复
5
米其林r| | 2010-6-23 20:54 | 只看该作者
用 NE2000 的驱动,稍微修改读写就可以了。晚上放44B0上移植参考。

使用特权

评论回复
6
六楼的窗户| | 2010-6-23 20:54 | 只看该作者
郁闷郁闷还是改驱动吧,和16x5x包脱离关系。
怎么这个问题就我碰到?

使用特权

评论回复
7
3B1105|  楼主 | 2010-6-23 20:55 | 只看该作者
问题找到了首先可以肯定,ecos源码(www.ecoscentric.com下载的最新snapshot)中的lpc2xxx串口驱动程序是绝对有问题的。该驱动基于16550标准驱动,lpc的uart寄存器位置也符合16550工业规范,不同在于THRE中断的产生。在不满足初始条件时THRE中断不置位,而所有数据发送都在中断处理例程中进行,造成根本不能发送数据。所以该驱动在联合hal串口驱动使用时比较正常,单独使用就不行。结果表现为至多有一个串口能正常工作。

这个问题以前在编写ucos的中断方式串口驱动就发现了,解决办法是在每次发送开始时,从队列取出第一个字节发送到UxTHR,其他数据在中断例程中传送。而现在要用这个方法解决问题势必要改动io层的串口驱动,这是不大规范的做法。

所以,希望在lpc上使用ecos的朋友能一起讨论讨论:)

使用特权

评论回复
8
linux1| | 2010-6-23 20:57 | 只看该作者
写了一个串口驱动,解决了问题半天赶工的,程序本身还很粗糙。但是能用(包括查询方式和中断方式)
#include <pkgconf/hal.h>
#include <pkgconf/infra.h>
#include <pkgconf/system.h>
#include <pkgconf/io_serial.h>
#include <pkgconf/io.h>
#include <pkgconf/kernel.h>

#include <cyg/io/io.h>
#include <cyg/hal/hal_io.h>
#include <cyg/hal/hal_intr.h>
#include <cyg/io/devtab.h>
#include <cyg/io/serial.h>
#include <cyg/infra/diag.h>
#include <cyg/infra/cyg_type.h>

#ifdef CYGPKG_IO_SERIAL_ARM_LPC2XXX

const unsigned int select_baud[] = {
    9999,
    50,
    75,
    110,
    134.5,
    150,
    200,
    300,
    600,
    1200,
    1800,
    2400,
    3600,
    4800,
    7200,
    9600,
    14400,
    19200,
    38400,
    57600,
    115200,
    230400
};

typedef struct lpc2xxx_serial_info {
    int            int_num;
    cyg_interrupt  serial_interrupt;
    cyg_handle_t   serial_interrupt_handle;
} lpc2xxx_serial_info;

static bool lpc2xxx_serial_init(struct cyg_devtab_entry *tab);

static Cyg_ErrNo lpc2xxx_serial_lookup(struct cyg_devtab_entry **tab,
                                    struct cyg_devtab_entry *sub_tab,
                                    const char *name);
static Cyg_ErrNo lpc2xxx_serial_set_config(serial_channel *chan, cyg_uint32 key,
                                        const void *xbuf, cyg_uint32 *len);

static void lpc2xxx_serial_start_xmit(serial_channel *chan);
static void lpc2xxx_serial_stop_xmit(serial_channel *chan);

static cyg_uint32 lpc2xxx_serial_ISR(cyg_vector_t vector, cyg_addrword_t data);
static void       lpc2xxx_serial_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data);

static bool lpc2xxx_serial_putc_interrupt(serial_channel *chan, unsigned char c);
static unsigned char lpc2xxx_serial_getc_interrupt(serial_channel *chan);

static bool lpc2xxx_serial_putc_polled(serial_channel *chan, unsigned char c);
static unsigned char lpc2xxx_serial_getc_polled(serial_channel *chan);

#if (CYGNUM_IO_SERIAL_ARM_LPC2XXX_SERIAL0_BUFSIZE > 0)
static SERIAL_FUNS(lpc2xxx_serial_funs_interrupt,
                   lpc2xxx_serial_putc_interrupt,
                   lpc2xxx_serial_getc_interrupt,
                   lpc2xxx_serial_set_config,
                   lpc2xxx_serial_start_xmit,
                   lpc2xxx_serial_stop_xmit
                   );
#endif

#if (CYGNUM_IO_SERIAL_ARM_LPC2XXX_SERIAL0_BUFSIZE == 0)
static SERIAL_FUNS(lpc2xxx_serial_funs_polled,
                   lpc2xxx_serial_putc_polled,
                   lpc2xxx_serial_getc_polled,
                   lpc2xxx_serial_set_config,
                   lpc2xxx_serial_start_xmit,
                   lpc2xxx_serial_stop_xmit
                   );
#endif

static lpc2xxx_serial_info lpc2xxx_serial_info0 = {
    int_num : CYGNUM_HAL_INTERRUPT_UART1
};

#if CYGNUM_IO_SERIAL_ARM_LPC2XXX_SERIAL0_BUFSIZE > 0
static unsigned char lpc2xxx_serial_out_buf0[CYGNUM_IO_SERIAL_ARM_LPC2XXX_SERIAL0_BUFSIZE];
static unsigned char lpc2xxx_serial_in_buf0[CYGNUM_IO_SERIAL_ARM_LPC2XXX_SERIAL0_BUFSIZE];

static SERIAL_CHANNEL_USING_INTERRUPTS(lpc2xxx_serial_channel0,
                                       lpc2xxx_serial_funs_interrupt,
                                       lpc2xxx_serial_info0,
                                       CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_ARM_LPC2XXX_SERIAL0_BAUD),
                                       CYG_SERIAL_STOP_DEFAULT,
                                       CYG_SERIAL_PARITY_DEFAULT,
                                       CYG_SERIAL_WORD_LENGTH_DEFAULT,
                                       CYG_SERIAL_FLAGS_DEFAULT,
                                       &lpc2xxx_serial_out_buf0[0], sizeof(lpc2xxx_serial_out_buf0),
                                       &lpc2xxx_serial_in_buf0[0], sizeof(lpc2xxx_serial_in_buf0)
                                       );
#else
static SERIAL_CHANNEL(lpc2xxx_serial_channel0,
                      lpc2xxx_serial_funs_polled,
                      lpc2xxx_serial_info0,
                      CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_ARM_LPC2XXX_SERIAL0_BAUD),
                      CYG_SERIAL_STOP_DEFAULT,
                      CYG_SERIAL_PARITY_DEFAULT,
                      CYG_SERIAL_WORD_LENGTH_DEFAULT,
                      CYG_SERIAL_FLAGS_DEFAULT
    );
#endif

DEVTAB_ENTRY(lpc2xxx_serial_io0,
             CYGDAT_IO_SERIAL_ARM_LPC2XXX_SERIAL0_NAME,
             0,
             &cyg_io_serial_devio,
             lpc2xxx_serial_init,
             lpc2xxx_serial_lookup,
             &lpc2xxx_serial_channel0
             );


static bool
lpc2xxx_serial_config_port(serial_channel *chan, cyg_serial_info_t *new_config)
{
    unsigned int baud_rate = select_baud[new_config->baud];
    unsigned short baud_divisor = CYG_HAL_ARM_LPC2XXX_BAUD_GENERATOR(baud_rate);
   
    HAL_WRITE_UINT8(LPC2XXX_U1IER, 0x00);
    HAL_WRITE_UINT8(LPC2XXX_U1LCR, 0x83);
    HAL_WRITE_UINT8(LPC2XXX_U1DLM, baud_divisor >> 8);
    HAL_WRITE_UINT8(LPC2XXX_U1DLL, baud_divisor & 0xFF);
    HAL_WRITE_UINT8(LPC2XXX_U1LCR, 0x03);
    HAL_WRITE_UINT8(LPC2XXX_U1FCR, 0x07);
    HAL_WRITE_UINT8(LPC2XXX_U1IER, 0x01);

    if (new_config != &chan->config) {
        chan->config = *new_config;
    }

    return true;
}

static bool
lpc2xxx_serial_init(struct cyg_devtab_entry *tab)
{
    serial_channel * const chan = (serial_channel *) tab->priv;
    lpc2xxx_serial_info * const lpc2xxx_chan = (lpc2xxx_serial_info *) chan->dev_priv;

    (chan->callbacks->serial_init)(chan);
    if (chan->out_cbuf.len != 0) {
        cyg_drv_interrupt_create(lpc2xxx_chan->int_num,
                                 4,
                                 (cyg_addrword_t)chan,
                                 lpc2xxx_serial_ISR,
                                 lpc2xxx_serial_DSR,
                                 &lpc2xxx_chan->serial_interrupt_handle,
                                 &lpc2xxx_chan->serial_interrupt);
        cyg_drv_interrupt_attach(lpc2xxx_chan->serial_interrupt_handle);
        cyg_drv_interrupt_unmask(lpc2xxx_chan->int_num);
    }
    lpc2xxx_serial_config_port(chan, &chan->config);
    return true;
}

static Cyg_ErrNo
lpc2xxx_serial_lookup(struct cyg_devtab_entry **tab,
                  struct cyg_devtab_entry *sub_tab,
                  const char *name)
{
    serial_channel * const chan = (serial_channel *) (*tab)->priv;

    (chan->callbacks->serial_init)(chan);
    return ENOERR;
}

static bool
lpc2xxx_serial_putc_interrupt(serial_channel *chan, unsigned char c)
{
    cyg_uint8 uart_lsr;

    HAL_READ_UINT8(LPC2XXX_U1LSR, uart_lsr);
    if (uart_lsr & 0x20) {
        HAL_WRITE_UINT8(LPC2XXX_U1THR, c);
        return true;
    }
    return false;
}

static bool
lpc2xxx_serial_putc_polled(serial_channel *chan, unsigned char c)
{
    cyg_uint8 uart_lsr;
   
    HAL_WRITE_UINT8(LPC2XXX_U1THR, c);
    while (1) {
        HAL_READ_UINT8(LPC2XXX_U1LSR, uart_lsr);
        if (uart_lsr & 0x40) break;
    }
    return true;
}

static unsigned char
lpc2xxx_serial_getc_interrupt(serial_channel *chan)
{
    cyg_uint8 c;

    HAL_READ_UINT8(LPC2XXX_U1RBR, c);
    return (unsigned char) c;
}

static unsigned char
lpc2xxx_serial_getc_polled(serial_channel *chan)
{
    cyg_uint8 c;
    cyg_uint8 uart_lsr;
   
    while (1) {
        HAL_READ_UINT8(LPC2XXX_U1LSR, uart_lsr);
        if (uart_lsr & 0x01) break;
    }
    HAL_READ_UINT8(LPC2XXX_U1RBR, c);
   
    return (unsigned char) c;
}

static Cyg_ErrNo
lpc2xxx_serial_set_config(serial_channel *chan, cyg_uint32 key,
                       const void *xbuf, cyg_uint32 *len)
{
    switch (key) {
    case CYG_IO_SET_CONFIG_SERIAL_INFO:
    {
        cyg_serial_info_t *config = (cyg_serial_info_t *)xbuf;
        if ( *len < sizeof(cyg_serial_info_t) ) {
            return -EINVAL;
        }
        *len = sizeof(cyg_serial_info_t);
        if ( true != lpc2xxx_serial_config_port(chan, config) )
            return -EINVAL;
    }
    break;
    default:
        return -EINVAL;
    }
    return ENOERR;
}

static void
lpc2xxx_serial_start_xmit(serial_channel *chan)
{
    cbuf_t *cbuf = &chan->out_cbuf;
    serial_funs *funs = chan->funs;
    cyg_uint8 uart_lsr;
    cyg_uint8 uart_ier;
    cyg_uint8 c;
   
    c = cbuf->data[cbuf->get];
    HAL_WRITE_UINT8(LPC2XXX_U1THR, c);
    while (1) {
        HAL_READ_UINT8(LPC2XXX_U1LSR, uart_lsr);
        if (uart_lsr & 0x20) break;
    }
    cbuf->get++;
    if (cbuf->get == cbuf->len) cbuf->get = 0;
    cbuf->nb--;

    HAL_READ_UINT8(LPC2XXX_U1IER, uart_ier);
    uart_ier |= 0x02;
    HAL_WRITE_UINT8(LPC2XXX_U1IER, uart_ier);
}

static void
lpc2xxx_serial_stop_xmit(serial_channel *chan)
{
    cyg_uint8 uart_ier;

    HAL_READ_UINT8(LPC2XXX_U1IER, uart_ier);
    uart_ier &= ~0x02;
    HAL_WRITE_UINT8(LPC2XXX_U1IER, uart_ier);
}

static cyg_uint32
lpc2xxx_serial_ISR(cyg_vector_t vector, cyg_addrword_t data)
{
    serial_channel *chan = (serial_channel *)data;
    lpc2xxx_serial_info *lpc2xxx_chan = (lpc2xxx_serial_info *)chan->dev_priv;
    cyg_drv_interrupt_mask(lpc2xxx_chan->int_num);
    cyg_drv_interrupt_acknowledge(lpc2xxx_chan->int_num);
    return CYG_ISR_CALL_DSR;
}

static void      
lpc2xxx_serial_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
{
    serial_channel *chan = (serial_channel *)data;
    lpc2xxx_serial_info *lpc2xxx_chan = (lpc2xxx_serial_info *)chan->dev_priv;
    cyg_uint8 uart_iir;

    HAL_READ_UINT8(LPC2XXX_U1IIR, uart_iir);
    while ((uart_iir & 01) == 0) {
        switch (uart_iir & 0x0E) {
        case 0x04:
        case 0x0C:
        {
            cyg_uint8 uart_lsr;
            unsigned char c;
            HAL_READ_UINT8(LPC2XXX_U1LSR, uart_lsr);
            while(uart_lsr & 0x01) {
                HAL_READ_UINT8(LPC2XXX_U1RBR, c);
                (chan->callbacks->rcv_char)(chan, c);
                HAL_READ_UINT8(LPC2XXX_U1LSR, uart_lsr);
            }
            break;
        }
        case 0x02:
            (chan->callbacks->xmt_char)(chan);
            break;
        }

        HAL_READ_UINT8(LPC2XXX_U1IIR, uart_iir);
    }

    cyg_drv_interrupt_unmask(lpc2xxx_chan->int_num);
}

#endif

使用特权

评论回复
9
北京户口| | 2010-6-23 20:58 | 只看该作者
在2106 2132 2214上测试通过中断方式开始发送时使用了查询,浪费了一点cpu

使用特权

评论回复
10
LPC300| | 2010-6-23 20:59 | 只看该作者
能参考一下吗我想用TCP做个数据传输,看周立功自带的相应太慢,能参考一下你移植的吗?
我的邮箱
calvinwx@163.com

使用特权

评论回复
11
清风一士| | 2010-8-10 12:58 | 只看该作者
我在板子上试过,还是比较不错的。就是坛子上托太多,好多不是纯粹为讨论技术而来的

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

315

主题

1645

帖子

4

粉丝