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

📄 rx.c

📁 ARM入门的好帮手.包含了从简单到相对较复杂的程序.
💻 C
字号:
/*-*-C-*- * * $Revision: 1.9.6.7 $ *   $Author: rivimey $ *     $Date: 1998/03/03 13:46:47 $ * * Copyright Advanced RISC Machines Limited, 1995. * All Rights Reserved. * *   Project: ANGEL * *     Title:  Character reception engine */#include <stdarg.h>             /* ANSI varargs support */#include "angel.h"              /* Angel system definitions */#include "endian.h"             /* Endian independant memory access macros */#include "crc.h"                /* crc generation definitions and headers */#include "rxtx.h"#include "channels.h"#include "buffers.h"#ifdef TARGET#include "devdriv.h"#endif#include "logging.h"static re_status unexp_stx(struct re_state *rxstate);static re_status unexp_etx(struct re_state *rxstate);/* bitfield for the rx_engine state */typedef enum rx_state_flag{    RST_STX,    RST_TYP,    RST_LEN,    RST_DAT,    RST_CRC,    RST_ETX,    RST_ESC = (0x1 << 0x3)}rx_state_flag;void Angel_RxEngineInit(const struct re_config *rxconfig,                   struct re_state *rxstate){    rxstate->rx_state = RST_STX;    rxstate->field_c = 0;    rxstate->index = 0;    rxstate->crc = 0;    rxstate->error = RE_OKAY;    rxstate->config = rxconfig;}re_status Angel_RxEngine(unsigned char new_ch, unsigned char ovr, struct data_packet *packet,               struct re_state *rxstate){    /*     * TODO: add the flow control bits in     * Note: We test for the data field in a seperate case so we can     * completely avoid entering the switch for most chars     */    /*     * If overrun signalled, forget this packet and move on to the next.     */    if (ovr)    {        LogWarning(LOG_RX, ( "RxEngine: overflow; reset to STX\n"));        rxstate->field_c = 0;        rxstate->rx_state = RST_STX;        rxstate->error = RE_OVR;        return RS_BAD_PKT;    }    /* see if we're expecting a escaped char */    if ((rxstate->rx_state & RST_ESC) == RST_ESC)    {        /* unescape the char and unset the flag */        new_ch &= ~serial_ESCAPE;        LogTrace1("rxe-echar-%2x ", new_ch);        rxstate->rx_state &= ~RST_ESC;    }    else if (new_ch < 32)    {        if ((1 << new_ch) & rxstate->config->fc_set)        {            LogInfo(LOG_RX, ("RxEngine: xon/xoff\n"));#if 0 && defined(TARGET)  /* disabled for the present -- ric */            rxstate->config->fc_callback(new_ch, rxstate->config->fc_data);#endif        }        else if ((1 << new_ch) & rxstate->config->esc_set)        {            /* see if the incoming char is a special one */            if (new_ch == rxstate->config->esc)            {                LogTrace("rxe-esc ");                rxstate->rx_state |= RST_ESC;                return RS_IN_PKT;            }            else            {                /*                 * must be a normal packet so do some unexpected etx/stx checking                 * we haven't been told to escape or received an escape so unless                 * we are expecting an stx or etx then we can take the unexpected                  * stx/etx trap                 */                if ((new_ch == (rxstate->config->stx)) && (rxstate->rx_state != RST_STX))                    return unexp_stx(rxstate);                if ((new_ch == (rxstate->config->etx)) && (rxstate->rx_state != RST_ETX))                    return unexp_etx(rxstate);            }        }    }        if (rxstate->rx_state == RST_DAT)    {        /*         * do this to speed up the common case, no real penalty for         * other cases          */        LogTrace1("rxe-dat-%2x", new_ch);        rxstate->crc = crc32(&new_ch, 1, rxstate->crc);        (packet->data)[rxstate->index++] = (unsigned int)new_ch & 0xff;        if (rxstate->index == packet->len)            rxstate->rx_state = RST_CRC;        return RS_IN_PKT;    }    /*     * Now that the common case is out of the way we can test for everything     * else without worrying quite so much about the speed, changing the     * order to len,crc,stx,etx,typ might gain a tiny bit of speed but lets     * leave that for the moment     */    switch (rxstate->rx_state)    {        case RST_STX:            if (new_ch == rxstate->config->stx)            {                rxstate->rx_state = RST_TYP;                rxstate->error = RE_OKAY;                rxstate->crc = startCRC32;                rxstate->index = 0;                return RS_IN_PKT;            }            else            {                rxstate->error = RE_OKAY;                return RS_WAIT_PKT;            }        case RST_TYP:            packet->type = (DevChanID) new_ch;            rxstate->rx_state = RST_LEN;            rxstate->error = RE_OKAY;            rxstate->field_c = 0;  /* set up here for the length that follows */            LogTrace1("rxe-type-%2x ", packet->type);            rxstate->crc = crc32(&new_ch, 1, rxstate->crc);            return RS_IN_PKT;        case RST_LEN:            rxstate->crc = crc32(&new_ch, 1, rxstate->crc);            if (rxstate->field_c++ == 0)            {                /* first length byte */                packet->len = ((unsigned int)new_ch) << 8;                return RS_IN_PKT;            }            else            {                /* got the whole legth */                packet->len |= new_ch;                LogTrace1("rxe-len-%4x\n", packet->len);                /* check that the length is ok */                if (packet->len == 0)                {                    /* empty pkt */                    rxstate->field_c = 0;                    rxstate->rx_state = RST_CRC;                    return RS_IN_PKT;                }                else                {                    if (packet->data == NULL)                    {                        /* need to alloc the data buffer */                        if (!rxstate->config->ba_callback(                                            packet, rxstate->config->ba_data))                        {                            LogWarning(LOG_RX, ("RxEngine: Couldn't alloc %d byte buffer; "                                                  "dropping packet\n", packet->len));                            rxstate->rx_state = RST_STX;                            rxstate->error = RE_INTERNAL;                            return RS_NO_BUF;                        }                    }                    if (packet->len > packet->buf_len)                    {                        /* pkt bigger than buffer */                        rxstate->field_c = 0;                        rxstate->rx_state = RST_STX;                        rxstate->error = RE_LEN;                        return RS_BAD_PKT;                    }                    else                    {                        /* packet ok */                        rxstate->field_c = 0;                        rxstate->rx_state = RST_DAT;                        return RS_IN_PKT;                    }                }            }        case RST_DAT:            /* dummy case (dealt with earlier) */            LogWarning(LOG_RX, ( "ERROR: hit RST_dat in switch\n"));            rxstate->rx_state = RST_STX;            rxstate->error = RE_INTERNAL;            return RS_BAD_PKT;        case RST_CRC:            if (rxstate->field_c == 0)                packet->crc = 0;            packet->crc |= (new_ch & 0xFF) << ((3 - rxstate->field_c) * 8);            rxstate->field_c++;            if (rxstate->field_c == 4)            {                /* last crc field */                rxstate->field_c = 0;                rxstate->rx_state = RST_ETX;                LogTrace1("rxe-rcrc-%8x ", packet->crc);            }            return RS_IN_PKT;        case RST_ETX:            if (new_ch == rxstate->config->etx)            {                /* check crc */                if (rxstate->crc == packet->crc)                {                    /* crc ok */                    rxstate->rx_state = RST_STX;                    rxstate->field_c = 0;                    return RS_GOOD_PKT;                }                else                {                    LogWarning(LOG_RX, ( "Bad crc (0x%x), rx calculates it should be 0x%x\n",                                         packet->crc, rxstate->crc));                    rxstate->rx_state = RST_STX;                    rxstate->error = RE_CRC;                    return RS_BAD_PKT;                }            }            else if (new_ch == rxstate->config->stx)                return unexp_stx(rxstate);            else            {                rxstate->rx_state = RST_STX;                rxstate->error = RE_NETX;                return RS_BAD_PKT;            }        default:            LogWarning(LOG_RX, ( "ERROR fell through rxengine\n"));            rxstate->rx_state = RST_STX;            rxstate->error = RE_INTERNAL;            return RS_BAD_PKT;    }}static re_status unexp_stx(struct re_state *rxstate){    LogWarning(LOG_RX, ( "Unexpected stx\n"));    rxstate->crc = startCRC32;    rxstate->index = 0;    rxstate->rx_state = RST_TYP;    rxstate->error = RE_U_STX;    rxstate->field_c = 0;    return RS_BAD_PKT;}static re_status unexp_etx(struct re_state *rxstate){    LogWarning(LOG_RX, ( "Unexpected etx, rxstate: index= 0x%x, field_c=0x%x, state=0x%x\n",                         rxstate->index, rxstate->field_c, rxstate->rx_state));    rxstate->crc = 0;    rxstate->index = 0;    rxstate->rx_state = RST_STX;    rxstate->error = RE_U_ETX;    rxstate->field_c = 0;    return RS_BAD_PKT;}/* * This can be used as the buffer allocation callback for the rx engine, * and makes use of angel_DD_GetBuffer() [in devdrv.h].  * * Saves duplicating this callback function in every device driver that * uses the rx engine. * * Note that this REQUIRES that the device id is installed as cb_data * in the rx engine config structure for the driver. */bool angel_DD_RxEng_BufferAlloc(struct data_packet * packet, void *cb_data){#ifdef TARGET    DeviceID devid = (DeviceID) cb_data;#else    IGNORE(cb_data);#endif    if (packet->type < DC_NUM_CHANNELS)    {        /* request a buffer down from the channels layer */#ifdef TARGET        packet->data = angel_DD_GetBuffer(devid, packet->type,                                          packet->len);#else        packet->data = malloc(packet->len);#endif        if (packet->data == NULL)            return FALSE;        else        {            packet->buf_len = packet->len;            return TRUE;        }    }    else    {        /* bad type field */        return FALSE;    }}/* EOF rx.c */

⌨️ 快捷键说明

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