/* * Copyright 2012 by Embedded Technologies s.r.o * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * For additional information see http://www.ethernut.de/ */ #include #include #include #include #include /*! * \brief Handle I/O controls for the debug device. * * \param dev Identifies the device that receives the device-control * request. * \param req Requested control function. * \param conf Points to a buffer that contains any data required for * the given control function or receives data from that * function. * * \return 0 on success, -1 if the function fails or is not available. */ static int IOCtl(NUTDEVICE * dev, int req, void *conf) { return -1; } /*! * \brief Send a single character to debug device. * * The function will automatically prepend any newline character * (ASCII 10) with a carriage return character (ASCII 13). * * \param ch The character to send. */ static void Put(uintptr_t devnum, char ch) { /* Prepend NL with CR. */ if (ch == '\n') { Put(devnum, '\r'); } /* Wait until space is available in the FIFO */ while (!(MCF_UART_USR(devnum) & MCF_UART_USR_TXRDY)) ; /* Send the character */ MCF_UART_UTB(devnum) = (uint8_t) ch; } /*! * \brief Send a buffer contents to the debug device. * * This function is called by the low level input routines of the * \ref xrCrtLowio "C runtime library", using the _NUTDEVICE::dev_read * entry. * * Applications must not call this function, but use the stdio * functions instead. * * The debug driver is not interrupt driven and has no internal buffer * and no timeout control. Thus, it can be safely used in interrupt routines. * Of course, this will significantly decrease interrupt latency and overall * system performance. * * \param fp Identifies the device to send to. This may be used by * the driver to retrieve the \ref NUTDEVICE pointer. * \param buffer Pointer to the data to be written. * \param len Number of characters to write. If 0, then the caller * requests to flush the drivers internal output buffer. * In this case the pointer to the data is ignored. * * \return The number of characters written, which is the same as the * number of characters specified. */ static int Write(NUTFILE * fp, const void *buffer, int len) { int c = len; const char *cp = (const char *) buffer; uintptr_t devnum = fp->nf_dev->dev_base; while (c--) { Put(devnum, *cp++); } return len; } /*! * \brief Read bytes from file * * \return Number of characters read. */ static int Read(NUTFILE * nf, void *buffer, int len) { return 0; } /*! * \brief Open debug device. * * \return Pointer to a static NUTFILE structure. */ static NUTFILE *Open(NUTDEVICE * dev, const char *name, int mode, int acc) { NUTFILE *fp = (NUTFILE *) (dev->dev_dcb); fp->nf_dev = dev; fp->nf_fcb = NULL; return fp; } /*! * \brief Close debug device. * * \param fp Pointer to a \ref _NUTFILE structure, obtained by a * previous call to ZeroDebugOpen(). * * \return Always 0. */ static int Close(NUTFILE * fp) { /* Nothing to do for this simple driver. */ return 0; } /*! * \brief Initialize debug device. * * This function is called by NutRegisterDevice(), using the * _NUTDEVICE::dev_init entry. * * Applications must not call this function, they must call * NutRegisterDevice() instead. * * \param dev Pointer to the device information structure. * * \return Always 0. */ static int Init(NUTDEVICE * dev) { uint8_t devnum = dev->dev_base; uint32_t sysclk = NutGetCpuClock(); int baud = 115200; register uint16_t ubgs; /* Enable UART Port on GPIO */ switch (devnum) { #ifdef UART0_TXD_PIN case 0: GpioPinConfigSet(UART0_TXD_PORT, UART0_TXD_PIN, UART0_TXD_PERIPHERAL); GpioPinConfigSet(UART0_RXD_PORT, UART0_RXD_PIN, UART0_RXD_PERIPHERAL); break; #endif #ifdef UART1_TXD_PIN case 1: GpioPinConfigSet(UART1_TXD_PORT, UART1_TXD_PIN, UART1_TXD_PERIPHERAL); GpioPinConfigSet(UART1_RXD_PORT, UART1_RXD_PIN, UART1_RXD_PERIPHERAL); break; #endif #ifdef UART2_TXD_PIN case 2: GpioPinConfigSet(UART2_TXD_PORT, UART2_TXD_PIN, UART2_TXD_PERIPHERAL); GpioPinConfigSet(UART2_RXD_PORT, UART2_RXD_PIN, UART2_RXD_PERIPHERAL); break; #endif default: return 0; } /* Reset Transmitter */ MCF_UART_UCR(devnum) = MCF_UART_UCR_RESET_TX; /* Reset Receiver */ MCF_UART_UCR(devnum) = MCF_UART_UCR_RESET_RX; /* Reset Mode Register */ MCF_UART_UCR(devnum) = MCF_UART_UCR_RESET_MR; /* No parity, 8-bits per character */ MCF_UART_UMR(devnum) = MCF_UART_UMR_PM_NONE | MCF_UART_UMR_BC_8; /* Normal mode(No echo or loopback), 1 stop bit */ MCF_UART_UMR(devnum) = MCF_UART_UMR_CM_NORMAL | MCF_UART_UMR_SB_STOP_BITS_1; /* Select Rx and Tx clocks */ MCF_UART_UCSR(devnum) = MCF_UART_UCSR_RCS_SYS_CLK | MCF_UART_UCSR_TCS_SYS_CLK; /* Calculate baud settings */ ubgs = (uint16_t)(sysclk / (baud * 32)); MCF_UART_UBG1(devnum) = (uint8_t)((ubgs & 0xFF00) >> 8); MCF_UART_UBG2(devnum) = (uint8_t)(ubgs & 0x00FF); /* Enable receiver and transmitter */ MCF_UART_UCR(devnum) = MCF_UART_UCR_TX_ENABLED | MCF_UART_UCR_RX_ENABLED; return 0; } /* * While most drivers allocate this structure from the heap during * the open call and release it during close, this driver uses a * static structure. Therefore, concurrent open calls are not * allowed. */ static NUTFILE dbgfile; /*! * \brief Debug device information structure. * * Usually, the device structure is the only public symbol that may be * referenced by the application code using * * \code * #include * * { * ... * NutRegisterDevice(&devDebug0, 0, 0); * ... * } * \endcode * * If not referenced, the driver code (and this structure) will not be * included in the final binary. * * The name of the structure may differ among platforms. Portable * applications should avoid it and instead make use of dev/board.h. * * \code * #include * * { * ... * NutRegisterDevice(&DEV_DEBUG, 0, 0); * ... * } * \endcode * * While output is supported by default, input may be not. If input is * required, applications may replace \ref DEV_DEBUG by \ref DEV_CONSOLE. * In this case the debug driver is selected only, if it has input * capability (see \ref NUT_DEV_DEBUG_READ). Otherwise an interrupt * driven UART driver will be used. * * Note, that this polling driver has certain advantages * - very low memory usage * - allows stdio output functions in interrupt context * - allows stdio output functions in early system stage * - no internal buffering, output is synchronous * - atomic output with multiple threads * * but also some disadvantages * - concurrent threads are blocked during output * - most or all UART settings are hard coded * - may not work with non-ASCII (binary) data * - often only output is supported, not input * - only one instance (open) is allowed * * When used with Harvard architectures, additional functions may * be offered to access data in program space. */ #ifdef UART0_TXD_PIN NUTDEVICE devDebug0 = { NULL, /*!< _NUTDEVICE::dev_next, must be NULL */ { 'u', 'a', 'r', 't', '0', 0, 0, 0, 0 }, /*!< _NUTDEVICE::dev_name, use for all UART0 drivers. */ IFTYP_CHAR, /*!< _NUTDEVICE::dev_type, probably not used, may be 0. */ 0, /*!< _NUTDEVICE::dev_base, device number = 2(COM2). */ 0, /*!< _NUTDEVICE::dev_irq, not used by this driver. */ NULL, /*!< _NUTDEVICE::dev_icb, not used by this driver. */ &dbgfile, /*!< _NUTDEVICE::dev_dcb, stores the \ref NUTFILE handle. */ Init, /*!< _NUTDEVICE::dev_init. */ IOCtl, /*!< _NUTDEVICE::dev_ioctl. */ Read, /*!< _NUTDEVICE::dev_read, optional, may be NULL. */ Write, /*!< _NUTDEVICE::dev_write. */ Open, /*!< _NUTDEVICE::dev_open. */ Close, /*!< _NUTDEVICE::dev_close. */ NULL, /*!< _NUTDEVICE::dev_size, optional, may be NULL. */ NULL, /*!< _NUTDEVICE::dev_select, optional, may be NULL */ }; #endif #ifdef UART1_TXD_PIN NUTDEVICE devDebug1 = { NULL, /*!< _NUTDEVICE::dev_next, must be NULL */ { 'u', 'a', 'r', 't', '1', 0, 0, 0, 0 }, /*!< _NUTDEVICE::dev_name, use for all UART0 drivers. */ IFTYP_CHAR, /*!< _NUTDEVICE::dev_type, probably not used, may be 0. */ 1, /*!< _NUTDEVICE::dev_base, device number = 2(COM2). */ 0, /*!< _NUTDEVICE::dev_irq, not used by this driver. */ NULL, /*!< _NUTDEVICE::dev_icb, not used by this driver. */ &dbgfile, /*!< _NUTDEVICE::dev_dcb, stores the \ref NUTFILE handle. */ Init, /*!< _NUTDEVICE::dev_init. */ IOCtl, /*!< _NUTDEVICE::dev_ioctl. */ Read, /*!< _NUTDEVICE::dev_read, optional, may be NULL. */ Write, /*!< _NUTDEVICE::dev_write. */ Open, /*!< _NUTDEVICE::dev_open. */ Close, /*!< _NUTDEVICE::dev_close. */ NULL, /*!< _NUTDEVICE::dev_size, optional, may be NULL. */ NULL, /*!< _NUTDEVICE::dev_select, optional, may be NULL */ }; #endif #ifdef UART2_TXD_PIN NUTDEVICE devDebug2 = { NULL, /*!< _NUTDEVICE::dev_next, must be NULL */ { 'u', 'a', 'r', 't', '2', 0, 0, 0, 0 }, /*!< _NUTDEVICE::dev_name, use for all UART0 drivers. */ IFTYP_CHAR, /*!< _NUTDEVICE::dev_type, probably not used, may be 0. */ 2, /*!< _NUTDEVICE::dev_base, device number = 2(COM2). */ 0, /*!< _NUTDEVICE::dev_irq, not used by this driver. */ NULL, /*!< _NUTDEVICE::dev_icb, not used by this driver. */ &dbgfile, /*!< _NUTDEVICE::dev_dcb, stores the \ref NUTFILE handle. */ Init, /*!< _NUTDEVICE::dev_init. */ IOCtl, /*!< _NUTDEVICE::dev_ioctl. */ Read, /*!< _NUTDEVICE::dev_read, optional, may be NULL. */ Write, /*!< _NUTDEVICE::dev_write. */ Open, /*!< _NUTDEVICE::dev_open. */ Close, /*!< _NUTDEVICE::dev_close. */ NULL /*!< _NUTDEVICE::dev_size, optional, may be NULL. */ NULL, /*!< _NUTDEVICE::dev_select, optional, may be NULL */ }; #endif