⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mcfmbus.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 2 页
字号:
                    break;                                case EVENT_ARB_LOST:                    mcfmbus_error(bus, I2C_ARBITRATION_LOST);                    next_state(bus, STATE_IDLE);                    mcfmbus_machine(bus, EVENT_NEXTMSG);                    break;                                default:                    mcfmbus_machine_error(bus, event);                    break;            }            break;                     case STATE_SENDING:            switch (event)            {                case EVENT_ACK:                    if (bus->byte == bus->cmsg->len)                    {                        next_state(bus, STATE_IDLE);                        mcfmbus_machine(bus, EVENT_NEXTMSG);                    }                    else                    {                        mcfmbus_send(bus, bus->cmsg->buf[bus->byte++]);                        next_state(bus, STATE_SENDING);                    }                    break;                                    case EVENT_NACK:                    if (bus->byte == 0)                    {                        mcfmbus_error(bus, I2C_NO_DEVICE);                    }                    else                    {                        mcfmbus_error(bus, I2C_NO_ACKNOWLEDGE);                    }                    next_state(bus, STATE_IDLE);                    mcfmbus_machine(bus, EVENT_NEXTMSG);                    break;                                    case EVENT_ARB_LOST:                    mcfmbus_error(bus, I2C_ARBITRATION_LOST);                    next_state(bus, STATE_IDLE);                    mcfmbus_machine(bus, EVENT_NEXTMSG);                    break;                                default:                    mcfmbus_machine_error(bus, event);                    break;                                }            break;                        case STATE_RECEIVING:            switch (event)            {                case EVENT_DATA_RECV:                    if (bus->cmsg->len - bus->byte <= 2)                    {                        mcfmbus_send_nack(bus);                        if (bus->cmsg->len - bus->byte <= 1)                        {                            if (bus->cmsg - bus->msg + 1 == bus->nmsg)                                mcfmbus_stop(bus);                            else                                mcfmbus_rstart(bus);                        }                    }                    else                    {                        mcfmbus_send_ack(bus);                    }                    bus->cmsg->buf[bus->byte++] = *MCF5206E_MBDR(bus->base);                    if (bus->cmsg->len == bus->byte)                    {                        next_state(bus,STATE_IDLE);                        mcfmbus_machine(bus, EVENT_NEXTMSG);                    }                    else                    {                        next_state(bus,STATE_RECEIVING);                    }                    break;                case EVENT_ARB_LOST:                    mcfmbus_error(bus, I2C_ARBITRATION_LOST);                    next_state(bus, STATE_IDLE);                    mcfmbus_machine(bus, EVENT_NEXTMSG);                    break;                default:                    mcfmbus_machine_error(bus, event);                    break;            }            break;    }}/* mcfmbus_interrupt_handler -- *     MBUS module interrupt handler routine * * PARAMETERS: *     vector - interrupt vector number (not used) * * RETURNS: *     none */rtems_isrmcfmbus_interrupt_handler(rtems_vector_number vector){    i2c_event event;    event = mcfmbus_get_event(mbus);    mcfmbus_machine(mbus, event);}/* mcfmbus_poll -- *     MBUS module poll routine; used to poll events when I2C driver *     operates in poll-driven mode. * * PARAMETERS: *     none * * RETURNS: *     none */voidmcfmbus_poll(mcfmbus *bus){    i2c_event event;    event = mcfmbus_get_event(bus);    if (event != EVENT_NONE)        mcfmbus_machine(bus, event);}/* mcfmbus_select_clock_divider -- *     Select divider for system clock which is used for I2C bus clock *     generation. Not each divider can be selected for I2C bus; this *     function select nearest larger or equal divider. * * PARAMETERS: *     i2c_bus - pointer to the bus descriptor structure *     divider - system frequency divider for I2C serial clock. * RETURNS: *     RTEMS_SUCCESSFUL, if operation performed successfully, or *     RTEMS error code when failed. */rtems_status_codemcfmbus_select_clock_divider(mcfmbus *i2c_bus, int divider){    int i;    int mbc;    struct {        int divider;        int mbc;    } dividers[] ={        { 20,   0x20 }, { 22,   0x21 }, { 24,   0x22 }, { 26,   0x23 },         { 28,   0x00 }, { 30,   0x01 }, { 32,   0x25 }, { 34,   0x02 },        { 36,   0x26 }, { 40,   0x03 }, { 44,   0x04 }, { 48,   0x05 },        { 56,   0x06 }, { 64,   0x2a }, { 68,   0x07 }, { 72,   0x2B },        { 80,   0x08 }, { 88,   0x09 }, { 96,   0x2D }, { 104,  0x0A },        { 112,  0x2E }, { 128,  0x0B }, { 144,  0x0C }, { 160,  0x0D },        { 192,  0x0E }, { 224,  0x32 }, { 240,  0x0F }, { 256,  0x33 },        { 288,  0x10 }, { 320,  0x11 }, { 384,  0x12 }, { 448,  0x36 },        { 480,  0x13 }, { 512,  0x37 }, { 576,  0x14 }, { 640,  0x15 },        { 768,  0x16 }, { 896,  0x3A }, { 960,  0x17 }, { 1024, 0x3B },        { 1152, 0x18 }, { 1280, 0x19 }, { 1536, 0x1A }, { 1792, 0x3E },        { 1920, 0x1B }, { 2048, 0x3F }, { 2304, 0x1C }, { 2560, 0x1D },        { 3072, 0x1E }, { 3840, 0x1F }    };    if (i2c_bus == NULL)        return RTEMS_INVALID_ADDRESS;        for (i = 0, mbc = -1; i < sizeof(dividers)/sizeof(dividers[0]); i++)    {        mbc = dividers[i].mbc;        if (dividers[i].divider >= divider)        {            break;        }    }    *MCF5206E_MFDR(i2c_bus->base) = mbc;    return RTEMS_SUCCESSFUL;}/* mcfmbus_initialize -- *     Initialize ColdFire MBUS I2C bus controller. * * PARAMETERS: *     i2c_bus - pointer to the bus descriptor structure *     base    - ColdFire internal peripherial base address * * RETURNS: *     RTEMS_SUCCESSFUL, or RTEMS error code when initialization failed. */rtems_status_codemcfmbus_initialize(mcfmbus *i2c_bus, rtems_unsigned32 base){    rtems_interrupt_level level;    rtems_status_code sc;    if (mbus != NULL) /* Check if already initialized */        return RTEMS_RESOURCE_IN_USE;            if (i2c_bus == NULL)        return RTEMS_INVALID_ADDRESS;        i2c_bus->base = base;    i2c_bus->state = STATE_IDLE;    i2c_bus->msg = NULL;    i2c_bus->cmsg = NULL;    i2c_bus->nmsg = 0;    i2c_bus->byte = 0;        sc = rtems_interrupt_catch(        mcfmbus_interrupt_handler,         24 + ((*MCF5206E_ICR(base, MCF5206E_INTR_MBUS) & MCF5206E_ICR_IL) >>                                   MCF5206E_ICR_IL_S),        &i2c_bus->oldisr    );    if (sc != RTEMS_SUCCESSFUL)        return sc;    mbus = i2c_bus;    rtems_interrupt_disable(level);    *MCF5206E_IMR(base) &= ~MCF5206E_INTR_BIT(MCF5206E_INTR_MBUS);    *MCF5206E_MBCR(base) = 0;    *MCF5206E_MBSR(base) = 0;    *MCF5206E_MBDR(base) = 0x1F; /* Maximum possible divider is 3840 */    *MCF5206E_MBCR(base) = MCF5206E_MBCR_MEN | MCF5206E_MBCR_MIEN;    rtems_interrupt_enable(level);        return RTEMS_SUCCESSFUL;}/* mcfmbus_i2c_transfer -- *     Initiate multiple-messages transfer over I2C bus via ColdFire MBUS *     controller. * * PARAMETERS: *     bus - pointer to MBUS controller descriptor *     nmsg - number of messages *     msg - pointer to messages array *     done - function which is called when transfer is finished *     done_arg - arbitrary argument passed to done funciton * * RETURNS: *     RTEMS_SUCCESSFUL if transfer initiated successfully, or error *     code when failed. */rtems_status_codemcfmbus_i2c_transfer(mcfmbus *bus, int nmsg, i2c_message *msg,                     i2c_transfer_done done, rtems_unsigned32 done_arg){    if (bus != mbus)        return RTEMS_NOT_CONFIGURED;        bus->done = done;    bus->done_arg = done_arg;    bus->cmsg = bus->msg = msg;    bus->nmsg = nmsg;    bus->byte = 0;    bus->state = STATE_IDLE;    mcfmbus_machine(bus, EVENT_TRANSFER);    return RTEMS_SUCCESSFUL;}/* mcfmbus_i2c_done -- *     Close ColdFire MBUS I2C bus controller and release all resources. * * PARAMETERS: *     bus - pointer to MBUS controller descriptor * * RETURNS: *     RTEMS_SUCCESSFUL, if transfer initiated successfully, or error *     code when failed. */rtems_status_codemcfmbus_i2c_done(mcfmbus *i2c_bus){    rtems_status_code sc;    rtems_unsigned32 base;    if (mbus == NULL)        return RTEMS_NOT_CONFIGURED;        if (mbus != i2c_bus)        return RTEMS_INVALID_ADDRESS;        base = i2c_bus->base;        *MCF5206E_IMR(base) |= MCF5206E_INTR_BIT(MCF5206E_INTR_MBUS);    *MCF5206E_MBCR(base) = 0;    sc = rtems_interrupt_catch(        i2c_bus->oldisr,        24 + ((*MCF5206E_ICR(base, MCF5206E_INTR_MBUS) & MCF5206E_ICR_IL) >>                                   MCF5206E_ICR_IL_S),        NULL    );    return sc;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -