diff options
author | Harald Welte <laforge@osmocom.org> | 2019-12-21 16:46:53 +0100 |
---|---|---|
committer | Harald Welte <laforge@osmocom.org> | 2019-12-21 16:46:53 +0100 |
commit | c590c19cc6cd8bd020f56faff70b15603be81935 (patch) | |
tree | d0b96da86b59084cdcd750b97be84bd5591f71d3 /sam | |
parent | 1bd94ad07d0afbfe16565efdf7b9fcfc69942fc1 (diff) |
e1: Major update: use double-buffering for SSC rx/tx; USB receive works
Diffstat (limited to 'sam')
-rw-r--r-- | sam/applications/sam_e1/e1_ssc_tc.c | 139 | ||||
-rw-r--r-- | sam/applications/sam_e1/e1_ssc_tc.h | 9 | ||||
-rw-r--r-- | sam/applications/sam_e1/main.c | 123 |
3 files changed, 138 insertions, 133 deletions
diff --git a/sam/applications/sam_e1/e1_ssc_tc.c b/sam/applications/sam_e1/e1_ssc_tc.c index 4b0370a2..9e6e8701 100644 --- a/sam/applications/sam_e1/e1_ssc_tc.c +++ b/sam/applications/sam_e1/e1_ssc_tc.c @@ -3,36 +3,13 @@ #include <string.h> #include <asf.h> #include "conf_board.h" +#include "e1_ssc_tc.h" -/* enable Transmit support */ -#define TX_ENABLE - -static int g_ssc_num_overruns; -static Pdc* g_pdc; - - -/* 1024 bytes covers 32 frames of 32bytes (256bits) each. - * At frame rate of 8000 Hz, this means 1024 bytes represent 4ms */ -#define BUFFER_SIZE 1024 - -static uint8_t g_pdc_ssc_buffer0[BUFFER_SIZE]; -static pdc_packet_t g_pdc_ssc_rx_packet0 = { - .ul_addr = &g_pdc_ssc_buffer0, - .ul_size = BUFFER_SIZE/4, /* 32bit transfers, so 4 bytes per transfer */ -}; -static uint8_t g_pdc_ssc_buffer1[BUFFER_SIZE]; -static pdc_packet_t g_pdc_ssc_rx_packet1 = { - .ul_addr = &g_pdc_ssc_buffer1, - .ul_size = BUFFER_SIZE/4, /* 32bit transfers, so 4 bytes per transfer */ -}; - -static uint8_t g_pdc_ssc_buffer2[BUFFER_SIZE]; -static pdc_packet_t g_pdc_ssc_tx_packet = { - .ul_addr = &g_pdc_ssc_buffer2, - .ul_size = BUFFER_SIZE/4, /* 32bit transfers, so 4 bytes per transfer */ -}; - +#include <osmocom/core/utils.h> +/*********************************************************************** + * Timer/Counter block for FRAME generation + ***********************************************************************/ /* We use one timer/counter block to generate an artificial frame signal from the * received/recovered clock, which we then feed into the SSC for bit/octet-alignment */ @@ -41,7 +18,7 @@ static pdc_packet_t g_pdc_ssc_tx_packet = { #define TC_ALIGN TC1 /* instance 1 */ #define TC_CHANNEL_ALIGN 1 /* TC1 on instance 1 */ -void e1_tc_align_init() +void e1_tc_align_init(void) { printf("%s\n\r", __func__); sysclk_enable_peripheral_clock(ID_TC_ALIGN); @@ -70,27 +47,103 @@ void e1_tc_align_init() tc_start(TC_ALIGN, TC_CHANNEL_ALIGN); } -uint32_t e1_tc_align_read() +uint32_t e1_tc_align_read(void) { return tc_read_cv(TC_ALIGN, TC_CHANNEL_ALIGN); } +void e1_tc_align_set(uint8_t pos) +{ + tc_write_ra(TC_ALIGN, TC_CHANNEL_ALIGN, pos); + tc_write_rb(TC_ALIGN, TC_CHANNEL_ALIGN, (pos+16)%256); + tc_start(TC_ALIGN, TC_CHANNEL_ALIGN); +} + + + +/*********************************************************************** + * SSC code (using PDC) + ***********************************************************************/ + +/* enable Transmit support */ +#define TX_ENABLE + +static int g_ssc_num_overruns; +static Pdc* g_pdc; + + +/* 1024 bytes covers 32 frames of 32bytes (256bits) each. + * At frame rate of 8000 Hz, this means 1024 bytes represent 4ms */ +#define BUFFER_SIZE 1024 +#define NUM_RX_BUF_SSC 2 +#define NUM_TX_BUF_SSC 2 + +struct ssc_buffer { + uint8_t buffer[BUFFER_SIZE]; + pdc_packet_t packet; +}; + +static int g_pdc_ssc_cur_rx_idx = 0; +static struct ssc_buffer g_pdc_ssc_rx_buffer[NUM_RX_BUF_SSC]; +static int g_pdc_ssc_cur_tx_idx = 0; +static struct ssc_buffer g_pdc_ssc_tx_buffer[NUM_TX_BUF_SSC]; + +static void ssc_buffer_init(struct ssc_buffer *buf, unsigned int num) +{ + unsigned int i; + for (i = 0; i < num; i++) { + buf[i].packet.ul_addr = (uint32_t) &buf[i].buffer; + buf[i].packet.ul_size = sizeof(buf[i].buffer)/4; + } +} + +static void usb_iso_in_cb(udd_ep_status_t status, iram_size_t nb_transfered, udd_ep_id_t ep) +{ + if (status != UDD_EP_TRANSFER_OK) + printf("U%d", status); +} + /* Interrupt handler for SSC. Linker magic binds this function based on name (startup_sam4s.c) */ void SSC_Handler(void) { uint32_t status = ssc_get_status(SSC); + if (status & SSC_SR_ENDRX) { + struct ssc_buffer *sb_cur = &g_pdc_ssc_rx_buffer[g_pdc_ssc_cur_rx_idx]; + int next_rx_idx = (g_pdc_ssc_cur_rx_idx + 1) % NUM_RX_BUF_SSC; + bool rc; + /* refill only the 'next' DMA buffer; PDC has copied previous next to current */ + pdc_rx_init(g_pdc, NULL, &g_pdc_ssc_rx_buffer[next_rx_idx].packet); + //printf("E%d", g_pdc_ssc_cur_rx_idx); + /* FIXME: hand over to USB ISO IN */ + rc = udi_vendor_iso_in_run(sb_cur->buffer, sizeof(sb_cur->buffer), usb_iso_in_cb); + if (rc == false) printf("x"); + g_pdc_ssc_cur_rx_idx = next_rx_idx; + } if (status & SSC_SR_RXBUFF) { - //printf("R"); - pdc_rx_init(g_pdc, &g_pdc_ssc_rx_packet1, NULL); /* FIXME: swap buffers */ + /* this means both current and next buffer have ended. Shouldn't happen, + * as due to double buffering we always refill the next buffer in ENDRX */ + printf("RXBUFF!\r\n"); + /* re-start from scratch */ + g_pdc_ssc_cur_rx_idx = 0; + pdc_rx_init(g_pdc, &g_pdc_ssc_rx_buffer[0].packet, &g_pdc_ssc_rx_buffer[1].packet); } #ifdef TX_ENABLE + if (status & SSC_SR_ENDTX) { + int next_tx_idx = (g_pdc_ssc_cur_tx_idx + 1) % NUM_TX_BUF_SSC; + pdc_tx_init(g_pdc, NULL, &g_pdc_ssc_tx_buffer[next_tx_idx].packet); + //printf("e%d", g_pdc_ssc_cur_tx_idx); + g_pdc_ssc_cur_tx_idx = next_tx_idx; + } if (status & SSC_SR_TXBUFE) { - pdc_tx_init(g_pdc, &g_pdc_ssc_tx_packet, NULL); + printf("TXBUFE!\r\n"); + g_pdc_ssc_cur_tx_idx = 0; + pdc_tx_init(g_pdc, &g_pdc_ssc_tx_buffer[0].packet, &g_pdc_ssc_tx_buffer[1].packet); } #endif if (status & SSC_SR_OVRUN) { g_ssc_num_overruns++; + printf("OVRUN!\r\n"); } } @@ -108,7 +161,7 @@ static void fill_tx_buf(uint8_t *buf, unsigned int size) } } -void e1_init_gpio() +void e1_init_gpio(void) { printf("%s\n\r", __func__); @@ -136,11 +189,15 @@ void e1_init_gpio() pio_configure_pin(PIO_PA13_IDX, PIO_PERIPH_A); /* LIU_MOSI */ } -void e1_ssc_init() +void e1_ssc_init(void) { g_pdc = ssc_get_pdc_base(SSC); printf("%s\n\r", __func__); - fill_tx_buf(g_pdc_ssc_buffer2, sizeof(g_pdc_ssc_buffer2)); + ssc_buffer_init(g_pdc_ssc_rx_buffer, ARRAY_SIZE(g_pdc_ssc_rx_buffer)); + ssc_buffer_init(g_pdc_ssc_tx_buffer, ARRAY_SIZE(g_pdc_ssc_tx_buffer)); + + for (int i = 0; i < ARRAY_SIZE(g_pdc_ssc_tx_buffer); i++) + fill_tx_buf(g_pdc_ssc_tx_buffer[i].buffer, sizeof(g_pdc_ssc_tx_buffer[i].buffer)); sysclk_enable_peripheral_clock(ID_SSC); @@ -197,10 +254,10 @@ void e1_ssc_init() #endif /* set up Peripheral DMA controller */ - //pdc_rx_init(g_pdc, &g_pdc_ssc_rx_packet0, &g_pdc_ssc_rx_packet1); - pdc_rx_init(g_pdc, &g_pdc_ssc_rx_packet0, NULL); + g_pdc_ssc_cur_rx_idx = 0; + pdc_rx_init(g_pdc, &g_pdc_ssc_rx_buffer[0].packet, &g_pdc_ssc_rx_buffer[1].packet); #ifdef TX_ENABLE - pdc_tx_init(g_pdc, &g_pdc_ssc_tx_packet, NULL); + pdc_tx_init(g_pdc, &g_pdc_ssc_tx_buffer[0].packet, &g_pdc_ssc_tx_buffer[1].packet); #endif pdc_enable_transfer(g_pdc, PERIPH_PTCR_RXTEN #ifdef TX_ENABLE @@ -216,9 +273,9 @@ void e1_ssc_init() NVIC_EnableIRQ(SSC_IRQn); /* enable SSC interrupts */ - ssc_enable_interrupt(SSC, SSC_IER_RXBUFF + ssc_enable_interrupt(SSC, SSC_IER_RXBUFF | SSC_IER_ENDRX | SSC_IER_OVRUN #ifdef TX_ENABLE - | SSC_IER_TXBUFE + | SSC_IER_TXBUFE | SSC_IER_ENDTX #endif ); diff --git a/sam/applications/sam_e1/e1_ssc_tc.h b/sam/applications/sam_e1/e1_ssc_tc.h index ac573a7e..6052cd56 100644 --- a/sam/applications/sam_e1/e1_ssc_tc.h +++ b/sam/applications/sam_e1/e1_ssc_tc.h @@ -1,5 +1,8 @@ #pragma once -void e1_init_gpio(); -void e1_tc_align_init(); -void e1_ssc_init(); +void e1_tc_align_init(void); +uint32_t e1_tc_align_read(void); +void e1_tc_align_set(uint8_t pos); + +void e1_init_gpio(void); +void e1_ssc_init(void); diff --git a/sam/applications/sam_e1/main.c b/sam/applications/sam_e1/main.c index f6472360..b31409c2 100644 --- a/sam/applications/sam_e1/main.c +++ b/sam/applications/sam_e1/main.c @@ -1,95 +1,11 @@ -/** - * \file - * - * \brief Low Power Application. - * - * Copyright (c) 2012-2016 Atmel Corporation. All rights reserved. - * - * \asf_license_start - * - * \page License - * - * 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. The name of Atmel may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * 4. This software may only be redistributed and used in connection with an - * Atmel microcontroller product. - * - * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE - * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. - * - * \asf_license_stop - * - */ - -/** - * \mainpage Low Power Application - * - * \section Purpose - * - * This example shows all the different low power modes with several types - * of wake-up sources. And the consumption of the core in different power - * modes can be measured. - * - * \section Requirements - * - * This package can be used with SAM evaluation kits. - * - * \section Description - * - * The program will display a menu on console. It allows users to change the - * configuration and enter into a different power mode, and then measure the - * power consumption. - * - * For Eks, an amperemeter has to be plugged on the board instead of the - * VDDx jumper. - * - * Note that for better consumption measurement: - * - Run program out of flash without ICE connected. - * - * \section Usage - * - * -# Build the program and download it into the evaluation board. - * -# On the computer, open and configure a terminal application - * (e.g., HyperTerminal on Microsoft Windows) with these settings: - * - 115200 bauds - * - 8 bits of data - * - No parity - * - 1 stop bit - * - No flow control - * -# Start the application. - */ -/* - * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a> - */ - #include <asf.h> #include "stdio_serial.h" #include "conf_board.h" #include "conf_clock.h" #include "conf_uart_serial.h" #include "conf_usb.h" -#include "low_power_board.h" #include "e1_ssc_tc.h" +#include "low_power_board.h" #include "idt82v2081_asf.h" #include "microvty.h" @@ -147,6 +63,8 @@ /** Current MCK in Hz */ uint32_t g_ul_current_mck; +volatile uint32_t g_ul_ms_ticks; + /** Button pressed flag */ volatile uint32_t g_ul_button_pressed = 0; @@ -404,6 +322,24 @@ DEFUN(vty_idt_write, idt_write_cmd, "idt-write", "Write to SPI register") printf("IDT82 Register 0x%02lx: Written 0x%02lx\r\n", reg, val); } +DEFUN(vty_tca_write, tca_write_cmd, "tc-align-write", "Write to TC Align register") +{ + long val; + + if (argc < 2) { + printf("You must specify the value\r\n"); + return; + } + val = strtol(argv[1], NULL, 0); + + if (val < 0 || val > 256) { + printf("Value out of range <0..255>\r\n"); + return; + } + + e1_tc_align_set(val); +} + static void main_vbus_action(bool b_high) { @@ -413,6 +349,11 @@ static void main_vbus_action(bool b_high) udc_detach(); } +void SysTick_Handler(void) +{ + g_ul_ms_ticks++; +} + /** * \brief Low power application entry point. * @@ -424,6 +365,10 @@ int main(void) sysclk_init(); g_ul_current_mck = sysclk_get_cpu_hz(); board_init(); + SysTick_Config(sysclk_get_cpu_hz() / 1000); + + udc_start(); + udc_detach(); /* Initialize the console uart */ configure_console(); @@ -432,15 +377,15 @@ int main(void) microvty_register(&idt_read_cmd); microvty_register(&idt_write_cmd); microvty_register(&tc_dump_cv_cmd); - - /* Output example information */ - puts(STRING_HEADER); + microvty_register(&tca_write_cmd); /* Set default clock and re-configure UART */ set_default_working_clock(); reconfigure_console(g_ul_current_mck, CONF_UART_BAUDRATE); - udc_start(); + /* Output example information */ + puts(STRING_HEADER); + if (!udc_include_vbus_monitoring()) main_vbus_action(true); |