From 35cc40563e66b99210f02b04987284dbf8fbf8b7 Mon Sep 17 00:00:00 2001 From: suman_panchal Date: Wed, 28 Oct 2015 20:56:47 +0530 Subject: [PATCH] Zolertia Z1: Direct memory access using UART. --- cpu/msp430/f2xxx/msp430.c | 47 +++++++++++++++++++++++++------- cpu/msp430/f2xxx/uart0.c | 55 +++++++++++++++++++++++++++++++++++--- platform/z1/contiki-conf.h | 17 +++++------- 3 files changed, 95 insertions(+), 24 deletions(-) diff --git a/cpu/msp430/f2xxx/msp430.c b/cpu/msp430/f2xxx/msp430.c index 8c21986c4..c6552e058 100644 --- a/cpu/msp430/f2xxx/msp430.c +++ b/cpu/msp430/f2xxx/msp430.c @@ -32,8 +32,12 @@ #include "contiki.h" #include "dev/watchdog.h" +/* dco_required set to 1 will cause the CPU not to go into + * sleep modes where the DCO clock stopped */ +int msp430_dco_required; + #if defined(__MSP430__) && defined(__GNUC__) -#define asmv(arg) __asm__ __volatile__(arg) +#define asmv(arg) __asm__ __volatile__ (arg) #endif /*---------------------------------------------------------------------------*/ @@ -42,8 +46,8 @@ void * w_memcpy(void *out, const void *in, size_t n) { uint8_t *src, *dest; - src = (uint8_t *) in; - dest = (uint8_t *) out; + src = (uint8_t *)in; + dest = (uint8_t *)out; while(n-- > 0) { *dest++ = *src++; } @@ -56,7 +60,7 @@ void * w_memset(void *out, int value, size_t n) { uint8_t *dest; - dest = (uint8_t *) out; + dest = (uint8_t *)out; while(n-- > 0) { *dest++ = value & 0xff; } @@ -152,10 +156,30 @@ init_ports(void) /*---------------------------------------------------------------------------*/ /* msp430-ld may align _end incorrectly. Workaround in cpu_init. */ #if defined(__MSP430__) && defined(__GNUC__) -extern int _end; /* Not in sys/unistd.h */ +extern int _end; /* Not in sys/unistd.h */ static char *cur_break = (char *)&_end; #endif +/*---------------------------------------------------------------------------*/ +/* add/remove_lpm_req - for requiring a specific LPM mode. currently Contiki */ +/* jumps to LPM3 to save power, but DMA will not work if DCO is not clocked */ +/* so some modules might need to enter their LPM requirements */ +/* NOTE: currently only works with LPM1 (e.g. DCO) requirements. */ +/*---------------------------------------------------------------------------*/ +void +msp430_add_lpm_req(int req) +{ + if(req <= MSP430_REQUIRE_LPM1) { + msp430_dco_required++; + } +} +void +msp430_remove_lpm_req(int req) +{ + if(req <= MSP430_REQUIRE_LPM1) { + msp430_dco_required--; + } +} void msp430_cpu_init(void) { @@ -164,7 +188,7 @@ msp430_cpu_init(void) init_ports(); /* set DCO to a reasonable default value (8MHz) */ msp430_init_dco(); - /* calibrate the DCO step-by-step */ + /* calibrate the DCO step-by-step */ msp430_sync_dco(); eint(); #if defined(__MSP430__) && defined(__GNUC__) @@ -172,6 +196,7 @@ msp430_cpu_init(void) cur_break++; } #endif + msp430_dco_required = 0; } /*---------------------------------------------------------------------------*/ @@ -191,7 +216,7 @@ splhigh_(void) asmv("mov r2, %0" : "=r" (sr)); asmv("bic %0, r2" : : "i" (GIE)); #endif - return sr & GIE; /* Ignore other sr bits. */ + return sr & GIE; /* Ignore other sr bits. */ } /*---------------------------------------------------------------------------*/ /* @@ -209,7 +234,8 @@ splhigh_(void) /* } */ /*---------------------------------------------------------------------------*/ #ifdef __IAR_SYSTEMS_ICC__ -int __low_level_init(void) +int +__low_level_init(void) { /* turn off watchdog so that C-init will run */ WDTCTL = WDTPW + WDTHOLD; @@ -224,7 +250,8 @@ int __low_level_init(void) #endif /*---------------------------------------------------------------------------*/ void -msp430_sync_dco(void) { +msp430_sync_dco(void) +{ uint16_t oldcapture; int16_t diff; /* DELTA_2 assumes an ACLK of 32768 Hz */ @@ -260,7 +287,7 @@ msp430_sync_dco(void) { if(DCOCTL == 0x00) { /* Did DCO roll over? */ BCSCTL1++; } - /* -> Select next higher RSEL */ + /* -> Select next higher RSEL */ } } diff --git a/cpu/msp430/f2xxx/uart0.c b/cpu/msp430/f2xxx/uart0.c index 249362c0f..79c75f877 100644 --- a/cpu/msp430/f2xxx/uart0.c +++ b/cpu/msp430/f2xxx/uart0.c @@ -51,6 +51,11 @@ static volatile uint8_t transmitting; #define TX_WITH_INTERRUPT 1 #endif /* UART0_CONF_TX_WITH_INTERRUPT */ +#ifdef UART0_CONF_RX_WITH_DMA +#define RX_WITH_DMA UART0_CONF_RX_WITH_DMA +#else /* UART0_CONF_RX_WITH_DMA */ +#define RX_WITH_DMA 1 +#endif /* UART0_CONF_RX_WITH_DMA */ #if TX_WITH_INTERRUPT #define TXBUFSIZE 64 @@ -59,6 +64,30 @@ static struct ringbuf txbuf; static uint8_t txbuf_data[TXBUFSIZE]; #endif /* TX_WITH_INTERRUPT */ +#if RX_WITH_DMA +#define RXBUFSIZE 128 + +static uint8_t rxbuf[RXBUFSIZE]; +static uint16_t last_size; +static struct ctimer rxdma_timer; + +static void +handle_rxdma_timer(void *ptr) +{ + uint16_t size; + size = DMA0SZ; /* Note: loop requires that size is less or eq to RXBUFSIZE */ + while(last_size != size) { + uart0_input_handler((unsigned char)rxbuf[RXBUFSIZE - last_size]); + last_size--; + if(last_size == 0) { + last_size = RXBUFSIZE; + } + } + + ctimer_reset(&rxdma_timer); +} +#endif /* RX_WITH_DMA */ + /*---------------------------------------------------------------------------*/ uint8_t uart0_active(void) @@ -69,6 +98,9 @@ uart0_active(void) void uart0_set_input(int (*input)(unsigned char c)) { +#if RX_WITH_DMA /* This needs to be called after ctimer process is started */ + ctimer_set(&rxdma_timer, CLOCK_SECOND / 64, handle_rxdma_timer, NULL); +#endif uart0_input_handler = input; } /*---------------------------------------------------------------------------*/ @@ -100,7 +132,7 @@ uart0_writeb(unsigned char c) #endif /* TX_WITH_INTERRUPT */ } /*---------------------------------------------------------------------------*/ -#if ! NETSTACK_CONF_WITH_IPV4 /* If NETSTACK_CONF_WITH_IPV4 is defined, putchar() is defined by the SLIP driver */ +#if !NETSTACK_CONF_WITH_IPV4 /* If NETSTACK_CONF_WITH_IPV4 is defined, putchar() is defined by the SLIP driver */ #endif /* ! NETSTACK_CONF_WITH_IPV4 */ /*---------------------------------------------------------------------------*/ /** @@ -135,8 +167,24 @@ uart0_init(unsigned long ubr) ringbuf_init(&txbuf, txbuf_data, sizeof(txbuf_data)); IE2 |= UCA0TXIE; /* Enable UCA0 TX interrupt */ #endif /* TX_WITH_INTERRUPT */ + +#if RX_WITH_DMA + IE2 &= ~UCA0RXIE; /* disable USART0 RX interrupt */ + /* UART0_RX trigger */ + DMACTL0 = DMA0TSEL_3; + + /* source address = UCA0RXBUF */ + DMA0SA = (unsigned int)&UCA0RXBUF; + DMA0DA = (unsigned int)&rxbuf; + DMA0SZ = RXBUFSIZE; + last_size = RXBUFSIZE; + DMA0CTL = DMADT_4 + DMASBDB + DMADSTINCR_3 + DMAEN + DMAREQ; + + msp430_add_lpm_req(MSP430_REQUIRE_LPM1); +#endif /* RX_WITH_DMA */ } /*---------------------------------------------------------------------------*/ +#if !RX_WITH_DMA ISR(USCIAB0RX, uart0_rx_interrupt) { uint8_t c; @@ -148,18 +196,19 @@ ISR(USCIAB0RX, uart0_rx_interrupt) c = UCA0RXBUF; if(uart0_input_handler != NULL) { if(uart0_input_handler(c)) { - LPM4_EXIT; + LPM4_EXIT; } } } ENERGEST_OFF(ENERGEST_TYPE_IRQ); } +#endif /* !RX_WITH_DMA */ /*---------------------------------------------------------------------------*/ #if TX_WITH_INTERRUPT ISR(USCIAB0TX, uart0_tx_interrupt) { ENERGEST_ON(ENERGEST_TYPE_IRQ); - if((IFG2 & UCA0TXIFG)){ + if((IFG2 & UCA0TXIFG)) { if(ringbuf_elements(&txbuf) == 0) { transmitting = 0; diff --git a/platform/z1/contiki-conf.h b/platform/z1/contiki-conf.h index 3f223c0c5..783b3ec8c 100644 --- a/platform/z1/contiki-conf.h +++ b/platform/z1/contiki-conf.h @@ -31,7 +31,6 @@ #ifndef CONTIKI_CONF_H #define CONTIKI_CONF_H - #include "platform-conf.h" #define XMAC_CONF_COMPOWER 1 @@ -58,8 +57,7 @@ #define CXMAC_CONF_ANNOUNCEMENTS 0 #define XMAC_CONF_ANNOUNCEMENTS 0 -#define QUEUEBUF_CONF_NUM 4 - +#define QUEUEBUF_CONF_NUM 4 #else /* NETSTACK_CONF_WITH_IPV6 */ @@ -108,8 +106,7 @@ #define SHELL_VARS_CONF_RAM_BEGIN 0x1100 #define SHELL_VARS_CONF_RAM_END 0x2000 - -#define CFS_CONF_OFFSET_TYPE long +#define CFS_CONF_OFFSET_TYPE long #define PROFILE_CONF_ON 0 #define ENERGEST_CONF_ON 1 @@ -127,8 +124,9 @@ #define PROCESS_CONF_STATS 1 /*#define PROCESS_CONF_FASTPOLL 4*/ +#define UART0_CONF_TX_WITH_INTERRUPT 0 /* So far, printfs without interrupt. */ -#define UART0_CONF_TX_WITH_INTERRUPT 0 // So far, printfs without interrupt. +#define UART0_CONF_RX_WITH_DMA 0 #ifdef NETSTACK_CONF_WITH_IPV6 @@ -144,7 +142,7 @@ /* Handle 10 routes */ #define UIP_CONF_MAX_ROUTES 15 -#define UIP_CONF_ND6_SEND_RA 0 +#define UIP_CONF_ND6_SEND_RA 0 #define UIP_CONF_ND6_REACHABLE_TIME 600000 #define UIP_CONF_ND6_RETRANS_TIMER 10000 @@ -154,7 +152,7 @@ #define UIP_CONF_IPV6_REASSEMBLY 0 #define UIP_CONF_NETIF_MAX_ADDRESSES 3 #define UIP_CONF_IP_FORWARD 0 -#define UIP_CONF_BUFFER_SIZE 140 +#define UIP_CONF_BUFFER_SIZE 140 #define SICSLOWPAN_CONF_COMPRESSION SICSLOWPAN_COMPRESSION_HC06 #ifndef SICSLOWPAN_CONF_FRAG @@ -186,11 +184,8 @@ #define UIP_CONF_TCP_SPLIT 0 - #ifdef PROJECT_CONF_H #include PROJECT_CONF_H #endif /* PROJECT_CONF_H */ - - #endif /* CONTIKI_CONF_H */