📄 tlc16c550.c
字号:
tv = *(u_char *) (dev->dev_base + ACE_LCTL_OFS); tv &= (u_char) ~ (LCTL_WS0_MSK | LCTL_WS1_MSK); tv |= (bv & (LCTL_WS0_MSK | LCTL_WS1_MSK)); *(u_char *) (dev->dev_base + ACE_LCTL_OFS) = tv; } AceEnable(devnum); break; case ACE_GETDATABITS: *lvp = *(u_char *) (dev->dev_base + ACE_LCTL_OFS) & (LCTL_WS0_MSK | LCTL_WS1_MSK); break; case ACE_SETPARITY: AceDisable(devnum); if (bv <= 4) { switch (bv) { case 1: // odd parity bv = LCTL_PEN_MSK; break; case 2: // event parity bv = LCTL_PEN_MSK | LCTL_PRE_MSK; break; case 3: // space bv = LCTL_PEN_MSK; break; case 4: // mark bv = LCTL_PEN_MSK | LCTL_PRS_MSK; default: // no parity bv = 0; break; } tv = *(u_char *) (dev->dev_base + ACE_LCTL_OFS); tv &= (u_char) ~ (LCTL_PEN_MSK | LCTL_PRE_MSK | LCTL_PRS_MSK); tv |= bv; *(u_char *) (dev->dev_base + ACE_LCTL_OFS) = tv; } AceEnable(devnum); break; case ACE_GETPARITY: tv = *(u_char *) (dev->dev_base + ACE_LCTL_OFS) & (LCTL_PEN_MSK | LCTL_PRE_MSK | LCTL_PRS_MSK); switch (tv) { case 0: *lvp = 0; // no parity break; case LCTL_PEN_MSK: *lvp = 1; // odd parity break; case LCTL_PEN_MSK | LCTL_PRE_MSK: *lvp = 2; // event parity break; case LCTL_PEN_MSK | LCTL_PRS_MSK: *lvp = 4; // mark parity break; } break; case ACE_SETSTOPBITS: AceDisable(devnum); if (bv == 1 || bv == 2) { tv = *(u_char *) (dev->dev_base + ACE_LCTL_OFS); tv &= (u_char) ~ (LCTL_STB_MSK); tv |= (bv == 2) ? LCTL_STB_MSK : 0; *(u_char *) (dev->dev_base + ACE_LCTL_OFS) = tv; } AceEnable(devnum); break; case ACE_GETSTOPBITS: tv = *(u_char *) (dev->dev_base + ACE_LCTL_OFS); *lvp = (tv & LCTL_STB_MSK) ? 2 : 1; break; case ACE_SETFIFO: AceDisable(devnum); dcb->dcb_wfifo = 16; switch (bv) { case 1: tv = FCTL_ENABLE | FCTL_LEVEL_1; break; case 4: tv = FCTL_ENABLE | FCTL_LEVEL_4; break; case 8: tv = FCTL_ENABLE | FCTL_LEVEL_8; break; case 14: tv = FCTL_ENABLE | FCTL_LEVEL_14; break; default: bv = 0; tv = 0; dcb->dcb_wfifo = 1; break; } *(u_char *) (dev->dev_base + ACE_FCTL_OFS) = tv; /* if enabling then must write the level after */ *(u_char *) (dev->dev_base + ACE_FCTL_OFS) = tv; dcb->dcb_rfifo = bv; /* must signal any active and waiting writer, discard pending data */ ifs = dev->dev_icb; ifs->if_tx_act = 0; ifs->if_tx_idx = ifs->if_wr_idx; NutEventPostAsync(&(dcb->dcb_tx_rdy)); AceEnable(devnum); break; case ACE_GETFIFO: *lvp = (u_long) (dcb->dcb_rfifo); break; case ACE_GETSTATUS: AceGetStatus(dev, lvp); break; case ACE_SETSTATUS: rc = -1; break; case ACE_SETREADTIMEOUT: dcb->dcb_rtimeout = lv; break; case ACE_GETREADTIMEOUT: *lvp = dcb->dcb_rtimeout; break; case ACE_SETWRITETIMEOUT: dcb->dcb_wtimeout = lv; break; case ACE_GETWRITETIMEOUT: *lvp = dcb->dcb_wtimeout; break; case ACE_SETLOCALECHO: if (bv) dcb->dcb_modeflags |= ACE_MF_LOCALECHO; else dcb->dcb_modeflags &= ~ACE_MF_LOCALECHO; break; case ACE_GETLOCALECHO: *lvp = (dcb->dcb_modeflags & ACE_MF_LOCALECHO) ? 1 : 0; break; case ACE_SETFLOWCONTROL: if (bv) dcb->dcb_modeflags |= ACE_MF_LOCALECHO; else dcb->dcb_modeflags &= ~ACE_MF_LOCALECHO; break; case ACE_GETFLOWCONTROL: break; case ACE_SETCOOKEDMODE: if (bv) dcb->dcb_modeflags |= ACE_MF_COOKEDMODE; else dcb->dcb_modeflags &= ~ACE_MF_COOKEDMODE; break; case ACE_GETCOOKEDMODE: *lvp = (dcb->dcb_modeflags & ACE_MF_COOKEDMODE) ? 1 : 0; break; default: rc = -1; break; } return rc;}/*! * \brief Initialize on chip ACE device. * * Prepares the device for subsequent reading or writing. * Enables ACE transmitter and receiver interrupts. * * \param dev Identifies the device to initialize. * * \return 0 on success, -1 otherwise. */int AceInit(NUTDEVICE * dev){ IFSTREAM *ifs; ACEDCB *dcb; u_long baudrate = 9600; u_long databits = 8; u_long parity = 0; u_long stopbits = 1; IRQ_HANDLER *irq; u_char *pnPort; u_char nMask; /* * We only support character devices for on-chip ACEs. */ if (dev->dev_type != IFTYP_STREAM) { return -1; } /* * Initialize interface control block. */ ifs = dev->dev_icb; memset(ifs, 0, sizeof(IFSTREAM)); ifs->if_input = AceInput; ifs->if_output = AceOutput; ifs->if_flush = AceFlush; /* * Initialize driver control block. */ dcb = dev->dev_dcb; memset(dcb, 0, sizeof(ACEDCB)); dcb->dcb_modeflags = ACE_MF_NOBUFFER; dcb->dcb_rfifo = 0; dcb->dcb_wfifo = 1; dcb->dev_next = NULL; /* * Register interrupt handler. */ if (dev->dev_base) { /* if any ACE is already assigned to this interrupt */ if (atIrqDcb[dev->dev_irq] != NULL) { /* put ourself on the end of the list */ (atIrqDcb[dev->dev_irq])->dev_next = dev; } else { // get the appropriate irq handler irq = (IRQ_HANDLER *) pgm_read_word(&(atIrqDefs[dev->dev_irq].pvIrq)); if (NutRegisterIrqHandler(irq, AceIrqHandler, dev)) { return -1; } // enable the interrupts pnPort = (u_char *) pgm_read_word(&(atIrqDefs[dev->dev_irq].pnIrqMskPort)); nMask = pgm_read_byte(&(atIrqDefs[dev->dev_irq].nMask)); *pnPort |= nMask; } /* remember dcb of the recently initialized device */ atIrqDcb[dev->dev_irq] = dcb; } /* * Set baudrate and handshake default. This will also * enable the ACE functions. */ AceIOCtl(dev, ACE_SETSPEED, (void *) &baudrate); AceIOCtl(dev, ACE_SETDATABITS, (void *) &databits); AceIOCtl(dev, ACE_SETPARITY, (void *) &parity); AceIOCtl(dev, ACE_SETSTOPBITS, (void *) &stopbits); sbi(EIMSK, dev->dev_irq); /* dev->dev_irq to IRQ_INTx map should be used for a clean implementation but it looks like an overhead */ AceEnable(dev->dev_base); return 0;}/*! * \brief Read from device. */int AceRead(NUTFILE * fp, void *buffer, int size){ int rc; NUTDEVICE *dev; IFSTREAM *ifs; ACEDCB *dcb; u_char elmode; u_char ch; u_char *cp = buffer; dev = fp->nf_dev; ifs = (IFSTREAM *) dev->dev_icb; dcb = dev->dev_dcb; if (dcb->dcb_modeflags & ACE_MF_COOKEDMODE) elmode = 1; else elmode = 0; /* * Call without data pointer discards receive buffer. */ if (buffer == 0) { ifs->if_rd_idx = ifs->if_rx_idx; return 0; } /* * Get characters from receive buffer. */ for (rc = 0; rc < size;) { /* if nothing has been received yet */ if (ifs->if_rd_idx == ifs->if_rx_idx) { /* while incomming buffer is empty */ while (ifs->if_rd_idx == ifs->if_rx_idx) { /* wait (timeout) for incomming data */ if (AceInput(dev)) { /* if a timeout */ return 0; } } } ch = ifs->if_rx_buf[ifs->if_rd_idx++]; if (elmode && (ch == '\r' || ch == '\n')) { if ((ifs->if_last_eol == 0) || (ifs->if_last_eol == ch)) { ifs->if_last_eol = ch; *cp++ = '\n'; rc++; } } else { ifs->if_last_eol = 0; *cp++ = ch; rc++; } } return rc;}/*! * \brief Write to device. */int AcePut(NUTDEVICE * dev, CONST void *buffer, int len, int pflg){ int rc; IFSTREAM *ifs; ACEDCB *dcb; CONST u_char *cp; u_char lbmode; u_char elmode; u_char ch; ifs = dev->dev_icb; dcb = dev->dev_dcb; if (dcb->dcb_modeflags & ACE_MF_LINEBUFFER) lbmode = 1; else lbmode = 0; if (dcb->dcb_modeflags & ACE_MF_COOKEDMODE) elmode = 1; else elmode = 0; /* * Call without data pointer starts transmission. */ if (buffer == 0) { rc = AceFlush(dev); return rc; } /* * Put characters in transmit buffer. */ cp = buffer; for (rc = 0; rc < len;) { if ((u_char) (ifs->if_wr_idx + 1) == ifs->if_tx_idx) { if (AceFlush(dev)) { return -1; } } ch = pflg ? PRG_RDB(cp) : *cp; if (elmode == 1 && ch == '\n') { elmode = 2; if (lbmode == 1) lbmode = 2; ch = '\r'; } else { if (elmode == 2) elmode = 1; cp++; rc++; } ifs->if_tx_buf[ifs->if_wr_idx++] = ch; } if (lbmode > 1 || (dcb->dcb_modeflags & ACE_MF_NOBUFFER) != 0) { if (AceFlush(dev)) rc = -1; } return rc;}int AceWrite(NUTFILE * fp, CONST void *buffer, int len){ return AcePut(fp->nf_dev, buffer, len, 0);}int AceWrite_P(NUTFILE * fp, PGM_P buffer, int len){ return AcePut(fp->nf_dev, (CONST char *) buffer, len, 1);}/*! * \brief Open a device or file. */NUTFILE *AceOpen(NUTDEVICE * dev, CONST char *name, int mode, int acc){ NUTFILE *fp = NutHeapAlloc(sizeof(NUTFILE)); ACEDCB *dcb; if (fp == 0) return NUTFILE_EOF; dcb = dev->dev_dcb; if (mode & _O_BINARY) dcb->dcb_modeflags &= ~ACE_MF_COOKEDMODE; else dcb->dcb_modeflags |= ACE_MF_COOKEDMODE; fp->nf_next = 0; fp->nf_dev = dev; fp->nf_fcb = 0; return fp;}/*! * \brief Close a device or file. */int AceClose(NUTFILE * fp){ NutHeapFree(fp); return 0;}/*! * \brief Request file size. */long AceSize(NUTFILE * fp){ NUTDEVICE *dev; IFSTREAM *ifs; dev = fp->nf_dev; ifs = (IFSTREAM *) dev->dev_icb; return ((u_char) (ifs->if_rx_idx - ifs->if_rd_idx));}/*@}*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -