diff --git a/lib/include/isr.h b/lib/include/isr.h index e8f5fa867..3377d8d85 100644 --- a/lib/include/isr.h +++ b/lib/include/isr.h @@ -163,6 +163,7 @@ extern void kbi7_isr(void) __attribute__((weak)); extern void cal_isr(void) __attribute__((weak)); extern void uart1_isr(void) __attribute__((weak)); +extern void uart2_isr(void) __attribute__((weak)); extern void maca_isr(void) __attribute__((weak)); diff --git a/lib/include/mc1322x.h b/lib/include/mc1322x.h index e6437e0de..3cec5af32 100644 --- a/lib/include/mc1322x.h +++ b/lib/include/mc1322x.h @@ -44,7 +44,7 @@ #include "kbi.h" #include "maca.h" #include "packet.h" -#include "uart1.h" +#include "uart.h" #include "utils.h" #include "asm.h" diff --git a/lib/include/uart1.h b/lib/include/uart.h similarity index 63% rename from lib/include/uart1.h rename to lib/include/uart.h index d80eac65d..ad738649f 100644 --- a/lib/include/uart1.h +++ b/lib/include/uart.h @@ -33,11 +33,94 @@ * */ -#ifndef UART1_H -#define UART1_H +#ifndef UART_H +#define UART_H #include +/* Timer registers are all 16-bit wide with 16-bit access only */ +#define UART1_BASE (0x80005000) +#define UART2_BASE (0x8000B000) + +struct UART_struct { + union { + uint32_t CON; + struct UART_CON { + uint32_t :16; + uint32_t TST:1; + uint32_t MRXR:1; + uint32_t MTXR:1; + uint32_t FCE:1; + uint32_t FCP:1; + uint32_t XTIM:1; + uint32_t :2; + uint32_t TXOENB:1; + uint32_t CONTX:1; + uint32_t SB:1; + uint32_t ST2:1; + uint32_t EP:1; + uint32_t PEN:1; + uint32_t RXE:1; + uint32_t TXE:1; + } CONbits; + }; + union { + uint32_t STAT; + struct UART_STAT { + uint32_t :24; + uint32_t TXRDY:1; + uint32_t RXRDY:1; + uint32_t RUE:1; + uint32_t ROE:1; + uint32_t TOE:1; + uint32_t FE:1; + uint32_t PE:1; + uint32_t SE:1; + } USTATbits; + }; + union { + uint32_t DATA; + struct UART_DATA { + uint32_t :24; + uint32_t DATA:8; + } DATAbits; + }; + union { + uint32_t RXCON; + struct UART_URXCON { + uint32_t :26; + uint32_t LVL:6; + } RXCONbits; + }; + union { + uint32_t TXCON; + struct UART_TXCON { + uint32_t :26; + uint32_t LVL:6; + } TXCONbits; + }; + union { + uint32_t CTS; + struct UART_CTS { + uint32_t :27; + uint32_t LVL:5; + } CTSbits; + }; + union { + uint32_t BR; + struct UART_BR { + uint32_t INC:16; + uint32_t MOD:16; + } BRbits; + }; +}; + +static volatile struct UART_struct * const UART1 = (void *) (UART1_BASE); +static volatile struct UART_struct * const UART2 = (void *) (UART2_BASE); + +/* Old uart definitions, for compatibility */ +#ifndef REG_NO_COMPAT + #define UCON (0) /* UCON bits */ #define UCON_SAMP 10 @@ -51,9 +134,6 @@ #define UCTS (0x14) #define UBRCNT (0x18) -#define UART1_BASE (0x80005000) -#define UART2_BASE (0x8000b000) - #define UART1_UCON ((volatile uint32_t *) ( UART1_BASE + UCON )) #define UART1_USTAT ((volatile uint32_t *) ( UART1_BASE + USTAT )) #define UART1_UDATA ((volatile uint32_t *) ( UART1_BASE + UDATA )) @@ -70,11 +150,16 @@ #define UART2_UCTS ((volatile uint32_t *) ( UART2_BASE + UCTS )) #define UART2_UBRCNT ((volatile uint32_t *) ( UART2_BASE + UBRCNT )) +#endif /* REG_NO_COMPAT */ + extern volatile uint32_t u1_head, u1_tail; void uart1_putc(char c); #define uart1_can_get() (*UART1_URXCON > 0) uint8_t uart1_getc(void); - +extern volatile uint32_t u2_head, u2_tail; +void uart2_putc(char c); +#define uart2_can_get() (*UART2_URXCON > 0) +uint8_t uart2_getc(void); #endif diff --git a/lib/uart2.c b/lib/uart2.c new file mode 100644 index 000000000..3b9f310f0 --- /dev/null +++ b/lib/uart2.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2010, Mariano Alvira and other contributors + * to the MC1322x project (http://mc1322x.devl.org) + * All rights reserved. + * + * 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 Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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. + * + * This file is part of libmc1322x: see http://mc1322x.devl.org + * for details. + * + * + */ + +#include +#include + +volatile char u2_tx_buf[64]; +volatile uint32_t u2_head, u2_tail; + +void uart2_isr(void) { + while( *UART1_UTXCON != 0 ) { + if (u2_head == u2_tail) { + disable_irq(UART2); + return; + } + *UART2_UDATA = u2_tx_buf[u2_tail]; + u2_tail++; + if (u2_tail >= sizeof(u2_tx_buf)) + u2_tail = 0; + } +} + +void uart2_putc(char c) { + /* disable UART2 since */ + /* UART2 isr modifies u2_head and u2_tail */ + disable_irq(UART2); + + if( (u2_head == u2_tail) && + (*UART2_UTXCON != 0)) { + *UART2_UDATA = c; + } else { + u2_tx_buf[u2_head] = c; + u2_head += 1; + if (u2_head >= sizeof(u2_tx_buf)) + u2_head = 0; + if (u2_head == u2_tail) { /* drop chars when no room */ + if (u2_head) { u2_head -=1; } else { u2_head = sizeof(u2_tx_buf); } + } + enable_irq(UART1); + } +} + +uint8_t uart2_getc(void) { + while(uart2_can_get() == 0) { continue; } + return *UART2_UDATA; +} diff --git a/src/default_lowlevel.c b/src/default_lowlevel.c index 35750314a..ca87ec7c4 100644 --- a/src/default_lowlevel.c +++ b/src/default_lowlevel.c @@ -34,6 +34,7 @@ */ #include +#include void default_vreg_init(void) { volatile uint32_t i; @@ -44,16 +45,17 @@ void default_vreg_init(void) { *CRM_VREG_CNTL = 0x00000ff8; /* start the regulators */ } -void uart1_init(uint16_t inc, uint16_t mod, uint8_t samp) { - +void uart1_init(volatile uint16_t inc, volatile uint16_t mod, volatile uint8_t samp) { + /* UART must be disabled to set the baudrate */ - *UART1_UCON = 0; - *UART1_UBRCNT = ( inc << 16 ) | mod; + UART1->CON = 0; + + UART1->BR = ( inc << 16 ) | mod; /* TX and CTS as outputs */ GPIO->PAD_DIR_SET.GPIO_14 = 1; GPIO->PAD_DIR_SET.GPIO_16 = 1; - + /* RX and RTS as inputs */ GPIO->PAD_DIR_RESET.GPIO_15 = 1; GPIO->PAD_DIR_RESET.GPIO_17 = 1; @@ -62,16 +64,17 @@ void uart1_init(uint16_t inc, uint16_t mod, uint8_t samp) { /* you must enable the peripheral first BEFORE setting the function in GPIO_FUNC_SEL */ /* From the datasheet: "The peripheral function will control operation of the pad IF */ /* THE PERIPHERAL IS ENABLED. */ - *UART1_UCON = (1 << 0) | (1 << 1); /* enable receive, transmit */ + UART1->CON = (1 << 0) | (1 << 1); /* enable receive, transmit */ if(samp == UCON_SAMP_16X) set_bit(*UART1_UCON,UCON_SAMP); - /* set GPIO15-14 to UART (UART1 TX and RX)*/ + /* set GPIO15-14 to UART (UART1 TX and RX)*/ GPIO->FUNC_SEL.GPIO_14 = 1; GPIO->FUNC_SEL.GPIO_15 = 1; /* interrupt when there are this number or more bytes free in the TX buffer*/ - *UART1_UTXCON = 16; + UART1->TXCON = 16; + UART1->RXCON = 16; u1_head = 0; u1_tail = 0; @@ -80,3 +83,34 @@ void uart1_init(uint16_t inc, uint16_t mod, uint8_t samp) { /* enable UART1 interrupts in the interrupt controller */ enable_irq(UART1); } + +void uart2_init(volatile uint16_t inc, volatile uint16_t mod, volatile uint8_t samp) { + + /* UART must be disabled to set the baudrate */ + UART2->CON = 0; + UART2->BR = ( inc << 16 ) | mod; + + /* see Section 11.5.1.2 Alternate Modes */ + /* you must enable the peripheral first BEFORE setting the function in GPIO_FUNC_SEL */ + /* From the datasheet: "The peripheral function will control operation of the pad IF */ + /* THE PERIPHERAL IS ENABLED. Can override with U2_ENABLE_DEFAULT. */ + UART2->CON = (1 << 0) | (1 << 1); /* enable receive, transmit */ + + if(samp == UCON_SAMP_16X) + set_bit(*UART2_UCON, samp); + + /* set GPIO18-19 to UART (UART2 TX and RX)*/ + GPIO->FUNC_SEL.GPIO_18 = 1; + GPIO->FUNC_SEL.GPIO_19 = 1; + + /* interrupt when there are this number or more bytes free in the TX buffer*/ + UART2->TXCON = 16; + UART2->RXCON = 16; + + u2_head = 0; u2_tail = 0; + + /* tx and rx interrupts are enabled in the UART by default */ + /* see status register bits 13 and 14 */ + /* enable UART2 interrupts in the interrupt controller */ + enable_irq(UART2); +} diff --git a/src/default_lowlevel.h b/src/default_lowlevel.h index e91ec949b..20fc43e66 100644 --- a/src/default_lowlevel.h +++ b/src/default_lowlevel.h @@ -42,6 +42,7 @@ void default_vreg_init(void); void uart1_init(uint16_t inc, uint16_t mod, uint8_t samp); +void uart2_init(uint16_t inc, uint16_t mod, uint8_t samp); void irq_register_timer_handler(int timer, void (*isr)(void)); diff --git a/src/isr.c b/src/isr.c index fc17659ed..ccc2f1091 100644 --- a/src/isr.c +++ b/src/isr.c @@ -73,6 +73,9 @@ void irq(void) if(bit_is_set(pending, INT_NUM_UART1)) { if(uart1_isr != 0) { uart1_isr(); } } + if(bit_is_set(pending, INT_NUM_UART2)) { + if(uart2_isr != 0) { uart2_isr(); } + } if(bit_is_set(pending, INT_NUM_CRM)) { if(rtc_wu_evt() && (rtc_isr != 0)) { rtc_isr(); } if(kbi_evnt(4) && (kbi4_isr != 0)) { kbi4_isr(); } diff --git a/tests/Makefile b/tests/Makefile index 09e928385..1611c0640 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -8,6 +8,7 @@ COBJS := tests.o put.o # all of the target programs to build TARGETS := blink-red blink-green blink-blue blink-white blink-allio \ uart1-loopback \ + u1u2-loopback \ tmr tmr-ints \ sleep \ printf \ diff --git a/tests/u1u2-loopback.c b/tests/u1u2-loopback.c new file mode 100644 index 000000000..4f7262e17 --- /dev/null +++ b/tests/u1u2-loopback.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2010, Mariano Alvira and other contributors + * to the MC1322x project (http://mc1322x.devl.org) + * All rights reserved. + * + * 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 Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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. + * + * This file is part of libmc1322x: see http://mc1322x.devl.org + * for details. + * + * + */ + +#include +#include + +#include "tests.h" +#include "config.h" + +void main(void) { + + uart1_init(INC,MOD,SAMP); + uart2_init(INC,MOD,SAMP); + + while(1) { + if(uart1_can_get()) { + /* Receive buffer isn't empty */ + /* read a byte and write it to the transmit buffer */ + uart2_putc(uart1_getc()); + } + if(uart2_can_get()) { + uart1_putc(uart2_getc()); + } + } + +}