mirror of https://github.com/ARMmbed/mbed-os.git
commit
a3a4c78ea0
|
@ -1581,7 +1581,8 @@
|
||||||
"extra_labels": ["Silicon_Labs", "EFM32"],
|
"extra_labels": ["Silicon_Labs", "EFM32"],
|
||||||
"supported_toolchains": ["GCC_ARM", "ARM", "uARM"],
|
"supported_toolchains": ["GCC_ARM", "ARM", "uARM"],
|
||||||
"progen": {"target": "efm32gg-stk"},
|
"progen": {"target": "efm32gg-stk"},
|
||||||
"device_has": ["ANALOGIN", "ANALOGOUT", "ERROR_PATTERN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"]
|
"device_has": ["ANALOGIN", "ANALOGOUT", "ERROR_PATTERN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"],
|
||||||
|
"forced_reset_timeout": 2
|
||||||
},
|
},
|
||||||
"EFM32LG_STK3600": {
|
"EFM32LG_STK3600": {
|
||||||
"inherits": ["Target"],
|
"inherits": ["Target"],
|
||||||
|
@ -1590,7 +1591,8 @@
|
||||||
"extra_labels": ["Silicon_Labs", "EFM32"],
|
"extra_labels": ["Silicon_Labs", "EFM32"],
|
||||||
"supported_toolchains": ["GCC_ARM", "ARM", "uARM"],
|
"supported_toolchains": ["GCC_ARM", "ARM", "uARM"],
|
||||||
"progen": {"target": "efm32lg-stk"},
|
"progen": {"target": "efm32lg-stk"},
|
||||||
"device_has": ["ANALOGIN", "ANALOGOUT", "ERROR_PATTERN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"]
|
"device_has": ["ANALOGIN", "ANALOGOUT", "ERROR_PATTERN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"],
|
||||||
|
"forced_reset_timeout": 2
|
||||||
},
|
},
|
||||||
"EFM32WG_STK3800": {
|
"EFM32WG_STK3800": {
|
||||||
"inherits": ["Target"],
|
"inherits": ["Target"],
|
||||||
|
@ -1599,7 +1601,8 @@
|
||||||
"extra_labels": ["Silicon_Labs", "EFM32"],
|
"extra_labels": ["Silicon_Labs", "EFM32"],
|
||||||
"supported_toolchains": ["GCC_ARM", "ARM", "uARM"],
|
"supported_toolchains": ["GCC_ARM", "ARM", "uARM"],
|
||||||
"progen": {"target": "efm32wg-stk"},
|
"progen": {"target": "efm32wg-stk"},
|
||||||
"device_has": ["ANALOGIN", "ANALOGOUT", "ERROR_PATTERN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"]
|
"device_has": ["ANALOGIN", "ANALOGOUT", "ERROR_PATTERN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"],
|
||||||
|
"forced_reset_timeout": 2
|
||||||
},
|
},
|
||||||
"EFM32ZG_STK3200": {
|
"EFM32ZG_STK3200": {
|
||||||
"inherits": ["Target"],
|
"inherits": ["Target"],
|
||||||
|
@ -1612,7 +1615,8 @@
|
||||||
"target": "efm32zg-stk"
|
"target": "efm32zg-stk"
|
||||||
},
|
},
|
||||||
"device_has": ["ANALOGIN", "ERROR_PATTERN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"],
|
"device_has": ["ANALOGIN", "ERROR_PATTERN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"],
|
||||||
"default_build": "small"
|
"default_build": "small",
|
||||||
|
"forced_reset_timeout": 2
|
||||||
},
|
},
|
||||||
"EFM32HG_STK3400": {
|
"EFM32HG_STK3400": {
|
||||||
"inherits": ["Target"],
|
"inherits": ["Target"],
|
||||||
|
@ -1625,7 +1629,8 @@
|
||||||
"target": "efm32hg-stk"
|
"target": "efm32hg-stk"
|
||||||
},
|
},
|
||||||
"device_has": ["ANALOGIN", "ERROR_PATTERN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"],
|
"device_has": ["ANALOGIN", "ERROR_PATTERN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"],
|
||||||
"default_build": "small"
|
"default_build": "small",
|
||||||
|
"forced_reset_timeout": 2
|
||||||
},
|
},
|
||||||
"EFM32PG_STK3401": {
|
"EFM32PG_STK3401": {
|
||||||
"inherits": ["Target"],
|
"inherits": ["Target"],
|
||||||
|
@ -1634,7 +1639,8 @@
|
||||||
"extra_labels": ["Silicon_Labs", "EFM32"],
|
"extra_labels": ["Silicon_Labs", "EFM32"],
|
||||||
"supported_toolchains": ["GCC_ARM", "ARM", "uARM", "IAR"],
|
"supported_toolchains": ["GCC_ARM", "ARM", "uARM", "IAR"],
|
||||||
"progen": {"target": "efm32pg-stk"},
|
"progen": {"target": "efm32pg-stk"},
|
||||||
"device_has": ["ANALOGIN", "ERROR_PATTERN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"]
|
"device_has": ["ANALOGIN", "ERROR_PATTERN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES"],
|
||||||
|
"forced_reset_timeout": 2
|
||||||
},
|
},
|
||||||
"WIZWIKI_W7500": {
|
"WIZWIKI_W7500": {
|
||||||
"supported_form_factors": ["ARDUINO"],
|
"supported_form_factors": ["ARDUINO"],
|
||||||
|
|
|
@ -86,9 +86,15 @@ const PinMap PinMap_I2C_SDA[] = {
|
||||||
|
|
||||||
/************PWM***************/
|
/************PWM***************/
|
||||||
const PinMap PinMap_PWM[] = {
|
const PinMap PinMap_PWM[] = {
|
||||||
{PA12, PWM_CH0, 0},
|
{PA8, PWM_CH0, 0},
|
||||||
{PA13, PWM_CH1, 0},
|
{PA9, PWM_CH1, 0},
|
||||||
{PA14, PWM_CH2, 0},
|
{PA10, PWM_CH2, 0},
|
||||||
|
{PA12, PWM_CH0, 1},
|
||||||
|
{PA13, PWM_CH1, 1},
|
||||||
|
{PA14, PWM_CH2, 1},
|
||||||
|
{PC8, PWM_CH0, 2},
|
||||||
|
{PC9, PWM_CH1, 2},
|
||||||
|
{PC10, PWM_CH2, 2},
|
||||||
{NC , NC , 0}
|
{NC , NC , 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -62,6 +62,9 @@ const PinMap PinMap_PWM[] = {
|
||||||
{PA0, PWM_CH0, 0},
|
{PA0, PWM_CH0, 0},
|
||||||
{PA1, PWM_CH1, 0},
|
{PA1, PWM_CH1, 0},
|
||||||
{PA2, PWM_CH2, 0},
|
{PA2, PWM_CH2, 0},
|
||||||
|
{PF0, PWM_CH0, 5},
|
||||||
|
{PF1, PWM_CH1, 5},
|
||||||
|
{PF2, PWM_CH2, 5},
|
||||||
{NC , NC , NC}
|
{NC , NC , NC}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -86,9 +86,15 @@ const PinMap PinMap_I2C_SDA[] = {
|
||||||
|
|
||||||
/************PWM***************/
|
/************PWM***************/
|
||||||
const PinMap PinMap_PWM[] = {
|
const PinMap PinMap_PWM[] = {
|
||||||
{PA12, PWM_CH0, 0},
|
{PA8, PWM_CH0, 0},
|
||||||
{PA13, PWM_CH1, 0},
|
{PA9, PWM_CH1, 0},
|
||||||
{PA14, PWM_CH2, 0},
|
{PA10, PWM_CH2, 0},
|
||||||
|
{PA12, PWM_CH0, 1},
|
||||||
|
{PA13, PWM_CH1, 1},
|
||||||
|
{PA14, PWM_CH2, 1},
|
||||||
|
{PC8, PWM_CH0, 2},
|
||||||
|
{PC9, PWM_CH1, 2},
|
||||||
|
{PC10, PWM_CH2, 2},
|
||||||
{NC , NC , 0}
|
{NC , NC , 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -86,9 +86,15 @@ const PinMap PinMap_I2C_SDA[] = {
|
||||||
|
|
||||||
/************PWM***************/
|
/************PWM***************/
|
||||||
const PinMap PinMap_PWM[] = {
|
const PinMap PinMap_PWM[] = {
|
||||||
{PA12, PWM_CH0, 0},
|
{PA8, PWM_CH0, 0},
|
||||||
{PA13, PWM_CH1, 0},
|
{PA9, PWM_CH1, 0},
|
||||||
{PA14, PWM_CH2, 0},
|
{PA10, PWM_CH2, 0},
|
||||||
|
{PA12, PWM_CH0, 1},
|
||||||
|
{PA13, PWM_CH1, 1},
|
||||||
|
{PA14, PWM_CH2, 1},
|
||||||
|
{PC8, PWM_CH0, 2},
|
||||||
|
{PC9, PWM_CH1, 2},
|
||||||
|
{PC10, PWM_CH2, 2},
|
||||||
{NC , NC , 0}
|
{NC , NC , 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,378 @@
|
||||||
|
/***************************************************************************//**
|
||||||
|
* @file main.cpp
|
||||||
|
*******************************************************************************
|
||||||
|
* @section License
|
||||||
|
* <b>(C) Copyright 2016 Silicon Labs, http://www.silabs.com</b>
|
||||||
|
*******************************************************************************
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
* not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "mbed.h"
|
||||||
|
|
||||||
|
#include "greentea-client/test_env.h"
|
||||||
|
#include "unity/unity.h"
|
||||||
|
#include "utest/utest.h"
|
||||||
|
|
||||||
|
#include "em_cmu.h"
|
||||||
|
#include "em_gpio.h"
|
||||||
|
#include "em_prs.h"
|
||||||
|
#include "em_timer.h"
|
||||||
|
|
||||||
|
#define SHORT_TRANSFER_FRAMES 16
|
||||||
|
#define LONG_TRANSFER_FRAMES 1842
|
||||||
|
|
||||||
|
#if defined(TARGET_EFM32GG_STK3700) || defined(TARGET_EFM32LG_STK3600) || defined(TARGET_EFM32WG_STK3800)
|
||||||
|
|
||||||
|
#define TEST 1
|
||||||
|
|
||||||
|
#define TEST_UART USART1
|
||||||
|
#define MOSI_PIN PD0
|
||||||
|
#define MISO_PIN PD1
|
||||||
|
#define CLK_PIN PD2
|
||||||
|
#define CS_PIN PD3
|
||||||
|
|
||||||
|
#define GPIO_PORT gpioPortD
|
||||||
|
#define GPIO_PIN_TX 0
|
||||||
|
#define GPIO_PIN_CLK 2
|
||||||
|
#define GPIO_PRS_SRC_TX PRS_CH_CTRL_SOURCESEL_GPIOL
|
||||||
|
#define GPIO_PRS_SIG_TX PRS_CH_CTRL_SIGSEL_GPIOPIN0
|
||||||
|
#define GPIO_PRS_SRC_CLK PRS_CH_CTRL_SOURCESEL_GPIOL
|
||||||
|
#define GPIO_PRS_SIG_CLK PRS_CH_CTRL_SIGSEL_GPIOPIN2
|
||||||
|
|
||||||
|
#define TEST_TIMER TIMER1
|
||||||
|
#define TEST_TIMER_CLOCK cmuClock_TIMER1
|
||||||
|
|
||||||
|
#elif defined(TARGET_EFM32PG_STK3401)
|
||||||
|
|
||||||
|
#define TEST 1
|
||||||
|
|
||||||
|
#define TEST_UART USART1
|
||||||
|
#define MOSI_PIN PC6
|
||||||
|
#define MISO_PIN PC7
|
||||||
|
#define CLK_PIN PC8
|
||||||
|
#define CS_PIN PC9
|
||||||
|
|
||||||
|
#define GPIO_PORT gpioPortC
|
||||||
|
#define GPIO_PIN_TX 6
|
||||||
|
#define GPIO_PIN_CLK 8
|
||||||
|
#define GPIO_PRS_SRC_TX PRS_CH_CTRL_SOURCESEL_GPIOL
|
||||||
|
#define GPIO_PRS_SIG_TX PRS_CH_CTRL_SIGSEL_GPIOPIN6
|
||||||
|
#define GPIO_PRS_SRC_CLK PRS_CH_CTRL_SOURCESEL_GPIOH
|
||||||
|
#define GPIO_PRS_SIG_CLK PRS_CH_CTRL_SIGSEL_GPIOPIN8
|
||||||
|
|
||||||
|
#define TEST_TIMER TIMER1
|
||||||
|
#define TEST_TIMER_CLOCK cmuClock_TIMER1
|
||||||
|
|
||||||
|
#else
|
||||||
|
#define TEST 0
|
||||||
|
#warning "Test config not defined; skipping test"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
using namespace utest::v1;
|
||||||
|
|
||||||
|
#if TEST
|
||||||
|
DigitalOut cs(CS_PIN);
|
||||||
|
static volatile bool complete;
|
||||||
|
event_callback_t cb;
|
||||||
|
|
||||||
|
static uint8_t short_data_8[SHORT_TRANSFER_FRAMES];
|
||||||
|
static uint16_t short_data_16[SHORT_TRANSFER_FRAMES];
|
||||||
|
static uint32_t short_data_32[SHORT_TRANSFER_FRAMES];
|
||||||
|
|
||||||
|
static uint8_t short_data_8_rx[SHORT_TRANSFER_FRAMES];
|
||||||
|
static uint16_t short_data_16_rx[SHORT_TRANSFER_FRAMES];
|
||||||
|
static uint32_t short_data_32_rx[SHORT_TRANSFER_FRAMES];
|
||||||
|
|
||||||
|
static uint8_t long_data_8[LONG_TRANSFER_FRAMES];
|
||||||
|
static uint16_t long_data_16[LONG_TRANSFER_FRAMES];
|
||||||
|
|
||||||
|
static uint8_t long_data_8_rx[LONG_TRANSFER_FRAMES];
|
||||||
|
static uint16_t long_data_16_rx[LONG_TRANSFER_FRAMES];
|
||||||
|
|
||||||
|
void callbackFunction(int flags) {
|
||||||
|
complete = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_timer() {
|
||||||
|
CMU_ClockEnable(cmuClock_PRS, true);
|
||||||
|
CMU_ClockEnable(cmuClock_GPIO, true);
|
||||||
|
CMU_ClockEnable(TEST_TIMER_CLOCK, true);
|
||||||
|
|
||||||
|
// Setup USART TX pin as PRS producer
|
||||||
|
GPIO_IntConfig(GPIO_PORT, GPIO_PIN_TX, false, false, false);
|
||||||
|
PRS_SourceSignalSet(0,
|
||||||
|
GPIO_PRS_SRC_TX,
|
||||||
|
GPIO_PRS_SIG_TX,
|
||||||
|
prsEdgeOff);
|
||||||
|
|
||||||
|
// Setup USART CLK pin as PRS producer
|
||||||
|
GPIO_IntConfig(GPIO_PORT, GPIO_PIN_CLK, false, false, false);
|
||||||
|
PRS_SourceSignalSet(1,
|
||||||
|
GPIO_PRS_SRC_CLK,
|
||||||
|
GPIO_PRS_SIG_CLK,
|
||||||
|
prsEdgeOff);
|
||||||
|
|
||||||
|
// Setup timer to count on PRS pulses
|
||||||
|
TIMER_Init_TypeDef timInit = TIMER_INIT_DEFAULT;
|
||||||
|
timInit.enable = false;
|
||||||
|
timInit.clkSel = timerClkSelCC1;
|
||||||
|
|
||||||
|
TIMER_InitCC_TypeDef timInitCC = TIMER_INITCC_DEFAULT;
|
||||||
|
timInitCC.prsInput = true;
|
||||||
|
timInitCC.prsSel = timerPRSSELCh1;
|
||||||
|
|
||||||
|
TIMER_Init(TEST_TIMER, &timInit);
|
||||||
|
TIMER_InitCC(TEST_TIMER, 1, &timInitCC);
|
||||||
|
|
||||||
|
TIMER_Enable(TEST_TIMER, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void init_arrays(T * tx, T * rx, int len, uint32_t mask) {
|
||||||
|
for (uint32_t i = 0; i < len; i++) {
|
||||||
|
if (tx) {
|
||||||
|
tx[i] = i & mask;
|
||||||
|
}
|
||||||
|
if (rx) {
|
||||||
|
rx[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void test_transfer(int bits, int polarity, int freq, DMAUsage dma, T * data_tx, T * data_rx, int len) {
|
||||||
|
SPI spi(MOSI_PIN, MISO_PIN, CLK_PIN);
|
||||||
|
|
||||||
|
spi.format(bits, polarity);
|
||||||
|
spi.frequency(freq);
|
||||||
|
|
||||||
|
spi.set_dma_usage(dma);
|
||||||
|
|
||||||
|
// Clear RX buffer, setup tx pattern
|
||||||
|
init_arrays(data_tx, data_rx, len, (1 << bits) - 1);
|
||||||
|
|
||||||
|
// Set up PRS loopback of TX data to RX
|
||||||
|
TEST_UART->INPUT = USART_INPUT_RXPRS | USART_INPUT_RXPRSSEL_PRSCH0;
|
||||||
|
|
||||||
|
complete = false;
|
||||||
|
TIMER1->CNT = 0;
|
||||||
|
cs = 0;
|
||||||
|
spi.transfer(data_tx, len, data_rx, data_rx ? len : 0, cb);
|
||||||
|
|
||||||
|
while (!complete);
|
||||||
|
|
||||||
|
uint32_t xferred = TIMER1->CNT;
|
||||||
|
cs = 1;
|
||||||
|
|
||||||
|
// Check that all bits were sent
|
||||||
|
TEST_ASSERT_EQUAL(bits*len, xferred);
|
||||||
|
|
||||||
|
// Check that all data was received correctly
|
||||||
|
if (data_rx) {
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
TEST_ASSERT_EQUAL(data_tx[i], data_rx[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
// Short single transfers
|
||||||
|
|
||||||
|
void test_5bit_8bit_0_1mhz_short_transfer() {
|
||||||
|
test_transfer(5, 0, 1000000, DMA_USAGE_NEVER, short_data_8, short_data_8_rx, SHORT_TRANSFER_FRAMES);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_5bit_8bit_0_1mhz_short_dma_transfer() {
|
||||||
|
test_transfer(5, 0, 1000000, DMA_USAGE_OPPORTUNISTIC, short_data_8, short_data_8_rx, SHORT_TRANSFER_FRAMES);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_5bit_16bit_0_1mhz_short_transfer() {
|
||||||
|
test_transfer(5, 0, 1000000, DMA_USAGE_NEVER, short_data_16, short_data_16_rx, SHORT_TRANSFER_FRAMES);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_5bit_16bit_0_1mhz_short_dma_transfer() {
|
||||||
|
test_transfer(5, 0, 1000000, DMA_USAGE_OPPORTUNISTIC, short_data_16, short_data_16_rx, SHORT_TRANSFER_FRAMES);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_8bit_8bit_0_1mhz_short_transfer() {
|
||||||
|
test_transfer(8, 0, 1000000, DMA_USAGE_NEVER, short_data_8, short_data_8_rx, SHORT_TRANSFER_FRAMES);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_8bit_8bit_0_1mhz_short_dma_transfer() {
|
||||||
|
test_transfer(8, 0, 1000000, DMA_USAGE_OPPORTUNISTIC, short_data_8, short_data_8_rx, SHORT_TRANSFER_FRAMES);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_8bit_16bit_0_1mhz_short_transfer() {
|
||||||
|
test_transfer(8, 0, 1000000, DMA_USAGE_NEVER, short_data_16, short_data_16_rx, SHORT_TRANSFER_FRAMES);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_8bit_16bit_0_1mhz_short_dma_transfer() {
|
||||||
|
test_transfer(8, 0, 1000000, DMA_USAGE_OPPORTUNISTIC, short_data_16, short_data_16_rx, SHORT_TRANSFER_FRAMES);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
// Short extended/double transfers
|
||||||
|
|
||||||
|
void test_9bit_16bit_0_1mhz_short_transfer() {
|
||||||
|
test_transfer(9, 0, 1000000, DMA_USAGE_NEVER, short_data_16, short_data_16_rx, SHORT_TRANSFER_FRAMES);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_9bit_16bit_0_1mhz_short_dma_transfer() {
|
||||||
|
test_transfer(9, 0, 1000000, DMA_USAGE_OPPORTUNISTIC, short_data_16, short_data_16_rx, SHORT_TRANSFER_FRAMES);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_9bit_32bit_0_1mhz_short_transfer() {
|
||||||
|
test_transfer(9, 0, 1000000, DMA_USAGE_NEVER, short_data_32, short_data_32_rx, SHORT_TRANSFER_FRAMES);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_9bit_32bit_0_1mhz_short_dma_transfer() {
|
||||||
|
test_transfer(9, 0, 1000000, DMA_USAGE_OPPORTUNISTIC, short_data_32, short_data_32_rx, SHORT_TRANSFER_FRAMES);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_16bit_16bit_0_1mhz_short_transfer() {
|
||||||
|
test_transfer(16, 0, 1000000, DMA_USAGE_NEVER, short_data_16, short_data_16_rx, SHORT_TRANSFER_FRAMES);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_16bit_16bit_0_1mhz_short_dma_transfer() {
|
||||||
|
test_transfer(16, 0, 1000000, DMA_USAGE_OPPORTUNISTIC, short_data_16, short_data_16_rx, SHORT_TRANSFER_FRAMES);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_16bit_32bit_0_1mhz_short_transfer() {
|
||||||
|
test_transfer(16, 0, 1000000, DMA_USAGE_NEVER, short_data_32, short_data_32_rx, SHORT_TRANSFER_FRAMES);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_16bit_32bit_0_1mhz_short_dma_transfer() {
|
||||||
|
test_transfer(16, 0, 1000000, DMA_USAGE_OPPORTUNISTIC, short_data_32, short_data_32_rx, SHORT_TRANSFER_FRAMES);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
// Long single transfers
|
||||||
|
|
||||||
|
void test_5bit_8bit_0_1mhz_long_transfer() {
|
||||||
|
test_transfer(5, 0, 1000000, DMA_USAGE_NEVER, long_data_8, long_data_8_rx, LONG_TRANSFER_FRAMES);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_5bit_8bit_0_1mhz_long_dma_transfer() {
|
||||||
|
test_transfer(5, 0, 1000000, DMA_USAGE_OPPORTUNISTIC, long_data_8, long_data_8_rx, LONG_TRANSFER_FRAMES);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_5bit_16bit_0_1mhz_long_transfer() {
|
||||||
|
test_transfer(5, 0, 1000000, DMA_USAGE_NEVER, long_data_16, long_data_16_rx, LONG_TRANSFER_FRAMES);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_5bit_16bit_0_1mhz_long_dma_transfer() {
|
||||||
|
test_transfer(5, 0, 1000000, DMA_USAGE_OPPORTUNISTIC, long_data_16, long_data_16_rx, LONG_TRANSFER_FRAMES);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_8bit_8bit_0_1mhz_long_transfer() {
|
||||||
|
test_transfer(8, 0, 1000000, DMA_USAGE_NEVER, long_data_8, long_data_8_rx, LONG_TRANSFER_FRAMES);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_8bit_8bit_0_1mhz_long_dma_transfer() {
|
||||||
|
test_transfer(8, 0, 1000000, DMA_USAGE_OPPORTUNISTIC, long_data_8, long_data_8_rx, LONG_TRANSFER_FRAMES);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_8bit_16bit_0_1mhz_long_transfer() {
|
||||||
|
test_transfer(8, 0, 1000000, DMA_USAGE_NEVER, long_data_16, long_data_16_rx, LONG_TRANSFER_FRAMES);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_8bit_16bit_0_1mhz_long_dma_transfer() {
|
||||||
|
test_transfer(8, 0, 1000000, DMA_USAGE_OPPORTUNISTIC, long_data_16, long_data_16_rx, LONG_TRANSFER_FRAMES);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
// Long extended/double transfers
|
||||||
|
|
||||||
|
void test_9bit_16bit_0_1mhz_long_transfer() {
|
||||||
|
test_transfer(9, 0, 1000000, DMA_USAGE_NEVER, long_data_16, long_data_16_rx, LONG_TRANSFER_FRAMES);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_9bit_16bit_0_1mhz_long_dma_transfer() {
|
||||||
|
test_transfer(9, 0, 1000000, DMA_USAGE_OPPORTUNISTIC, long_data_16, long_data_16_rx, LONG_TRANSFER_FRAMES);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_16bit_16bit_0_1mhz_long_transfer() {
|
||||||
|
test_transfer(16, 0, 1000000, DMA_USAGE_NEVER, long_data_16, long_data_16_rx, LONG_TRANSFER_FRAMES);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_16bit_16bit_0_1mhz_long_dma_transfer() {
|
||||||
|
test_transfer(16, 0, 1000000, DMA_USAGE_OPPORTUNISTIC, long_data_16, long_data_16_rx, LONG_TRANSFER_FRAMES);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
#else
|
||||||
|
void test_dummy() {
|
||||||
|
TEST_IGNORE_MESSAGE("This test is not compatible with this target.");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
utest::v1::status_t greentea_failure_handler(const Case *const source, const failure_t reason) {
|
||||||
|
greentea_case_failure_abort_handler(source, reason);
|
||||||
|
return STATUS_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Case cases[] = {
|
||||||
|
#if TEST
|
||||||
|
Case("5-bit frames with 8-bit data, 1 MHz (short)", test_5bit_8bit_0_1mhz_short_transfer, greentea_failure_handler),
|
||||||
|
Case("5-bit frames with 8-bit data, 1 MHz, DMA (short)", test_5bit_8bit_0_1mhz_short_dma_transfer, greentea_failure_handler),
|
||||||
|
Case("5-bit frames with 16-bit data, 1 MHz (short)", test_5bit_16bit_0_1mhz_short_transfer, greentea_failure_handler),
|
||||||
|
Case("5-bit frames with 16-bit data, 1 MHz, DMA (short)", test_5bit_16bit_0_1mhz_short_dma_transfer, greentea_failure_handler),
|
||||||
|
Case("8-bit frames with 8-bit data, 1 MHz (short)", test_8bit_8bit_0_1mhz_short_transfer, greentea_failure_handler),
|
||||||
|
Case("8-bit frames with 8-bit data, 1 MHz, DMA (short)", test_8bit_8bit_0_1mhz_short_dma_transfer, greentea_failure_handler),
|
||||||
|
Case("8-bit frames with 16-bit data, 1 MHz (short)", test_8bit_16bit_0_1mhz_short_transfer, greentea_failure_handler),
|
||||||
|
Case("8-bit frames with 16-bit data, 1 MHz, DMA (short)", test_8bit_16bit_0_1mhz_short_dma_transfer, greentea_failure_handler),
|
||||||
|
Case("9-bit frames with 16-bit data, 1 MHz (short)", test_9bit_16bit_0_1mhz_short_transfer, greentea_failure_handler),
|
||||||
|
Case("9-bit frames with 16-bit data, 1 MHz, DMA (short)", test_9bit_16bit_0_1mhz_short_dma_transfer, greentea_failure_handler),
|
||||||
|
Case("9-bit frames with 32-bit data, 1 MHz (short)", test_9bit_32bit_0_1mhz_short_transfer, greentea_failure_handler),
|
||||||
|
Case("9-bit frames with 32-bit data, 1 MHz, DMA (short)", test_9bit_32bit_0_1mhz_short_dma_transfer, greentea_failure_handler),
|
||||||
|
Case("16-bit frames with 16-bit data, 1 MHz (short)", test_16bit_16bit_0_1mhz_short_transfer, greentea_failure_handler),
|
||||||
|
Case("16-bit frames with 16-bit data, 1 MHz, DMA (short)", test_16bit_16bit_0_1mhz_short_dma_transfer, greentea_failure_handler),
|
||||||
|
Case("16-bit frames with 32-bit data, 1 MHz (short)", test_16bit_32bit_0_1mhz_short_transfer, greentea_failure_handler),
|
||||||
|
Case("16-bit frames with 32-bit data, 1 MHz, DMA (short)", test_16bit_32bit_0_1mhz_short_dma_transfer, greentea_failure_handler),
|
||||||
|
|
||||||
|
Case("5-bit frames with 8-bit data, 1 MHz (long)", test_5bit_8bit_0_1mhz_long_transfer, greentea_failure_handler),
|
||||||
|
Case("5-bit frames with 8-bit data, 1 MHz, DMA (long)", test_5bit_8bit_0_1mhz_long_dma_transfer, greentea_failure_handler),
|
||||||
|
Case("5-bit frames with 16-bit data, 1 MHz (long)", test_5bit_16bit_0_1mhz_long_transfer, greentea_failure_handler),
|
||||||
|
Case("5-bit frames with 16-bit data, 1 MHz, DMA (long)", test_5bit_16bit_0_1mhz_long_dma_transfer, greentea_failure_handler),
|
||||||
|
Case("8-bit frames with 8-bit data, 1 MHz (long)", test_8bit_8bit_0_1mhz_long_transfer, greentea_failure_handler),
|
||||||
|
Case("8-bit frames with 8-bit data, 1 MHz, DMA (long)", test_8bit_8bit_0_1mhz_long_dma_transfer, greentea_failure_handler),
|
||||||
|
Case("8-bit frames with 16-bit data, 1 MHz (long)", test_8bit_16bit_0_1mhz_long_transfer, greentea_failure_handler),
|
||||||
|
Case("8-bit frames with 16-bit data, 1 MHz, DMA (long)", test_8bit_16bit_0_1mhz_long_dma_transfer, greentea_failure_handler),
|
||||||
|
Case("9-bit frames with 16-bit data, 1 MHz (long)", test_9bit_16bit_0_1mhz_long_transfer, greentea_failure_handler),
|
||||||
|
Case("9-bit frames with 16-bit data, 1 MHz, DMA (long)", test_9bit_16bit_0_1mhz_long_dma_transfer, greentea_failure_handler),
|
||||||
|
Case("16-bit frames with 16-bit data, 1 MHz (long)", test_16bit_16bit_0_1mhz_long_transfer, greentea_failure_handler),
|
||||||
|
Case("16-bit frames with 16-bit data, 1 MHz, DMA (long)", test_16bit_16bit_0_1mhz_long_dma_transfer, greentea_failure_handler),
|
||||||
|
#else
|
||||||
|
Case("Dummy case", test_dummy, greentea_failure_handler)
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
utest::v1::status_t greentea_test_setup(const size_t number_of_cases) {
|
||||||
|
GREENTEA_SETUP(25, "default_auto");
|
||||||
|
return greentea_test_setup_handler(number_of_cases);
|
||||||
|
}
|
||||||
|
|
||||||
|
Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
#if TEST
|
||||||
|
cs = 1;
|
||||||
|
cb.attach(callbackFunction);
|
||||||
|
init_timer();
|
||||||
|
#endif
|
||||||
|
Harness::run(specification);
|
||||||
|
}
|
|
@ -25,7 +25,6 @@
|
||||||
#include "dma_api_HAL.h"
|
#include "dma_api_HAL.h"
|
||||||
#include "em_device.h"
|
#include "em_device.h"
|
||||||
#include "em_cmu.h"
|
#include "em_cmu.h"
|
||||||
#include "em_int.h"
|
|
||||||
|
|
||||||
#ifdef DMA_PRESENT
|
#ifdef DMA_PRESENT
|
||||||
#include "em_dma.h"
|
#include "em_dma.h"
|
||||||
|
@ -198,7 +197,6 @@ bool LDMAx_ChannelEnabled( int ch )
|
||||||
EFM_ASSERT(ch < DMA_CHAN_COUNT);
|
EFM_ASSERT(ch < DMA_CHAN_COUNT);
|
||||||
uint32_t chMask = 1 << ch;
|
uint32_t chMask = 1 << ch;
|
||||||
return (bool)(LDMA->CHEN & chMask);
|
return (bool)(LDMA->CHEN & chMask);
|
||||||
INT_Disable();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* LDMA_PRESENT */
|
#endif /* LDMA_PRESENT */
|
||||||
|
|
|
@ -96,8 +96,10 @@ int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32
|
||||||
// Init pins
|
// Init pins
|
||||||
gpio_irq_preinit(obj, pin);
|
gpio_irq_preinit(obj, pin);
|
||||||
// Initialize GPIO interrupt dispatcher
|
// Initialize GPIO interrupt dispatcher
|
||||||
|
NVIC_SetVector(GPIO_ODD_IRQn, (uint32_t)GPIO_ODD_IRQHandler);
|
||||||
NVIC_ClearPendingIRQ(GPIO_ODD_IRQn);
|
NVIC_ClearPendingIRQ(GPIO_ODD_IRQn);
|
||||||
NVIC_EnableIRQ(GPIO_ODD_IRQn);
|
NVIC_EnableIRQ(GPIO_ODD_IRQn);
|
||||||
|
NVIC_SetVector(GPIO_EVEN_IRQn, (uint32_t)GPIO_EVEN_IRQHandler);
|
||||||
NVIC_ClearPendingIRQ(GPIO_EVEN_IRQn);
|
NVIC_ClearPendingIRQ(GPIO_EVEN_IRQn);
|
||||||
NVIC_EnableIRQ(GPIO_EVEN_IRQn);
|
NVIC_EnableIRQ(GPIO_EVEN_IRQn);
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
#include "rtc_api_HAL.h"
|
#include "rtc_api_HAL.h"
|
||||||
#include "lp_ticker_api.h"
|
#include "lp_ticker_api.h"
|
||||||
|
|
||||||
#include "em_int.h"
|
#include "critical.h"
|
||||||
#if (defined RTCC_COUNT) && (RTCC_COUNT > 0)
|
#if (defined RTCC_COUNT) && (RTCC_COUNT > 0)
|
||||||
#include "em_rtcc.h"
|
#include "em_rtcc.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -38,21 +38,21 @@ static int rtc_reserved = 0;
|
||||||
void lp_ticker_init()
|
void lp_ticker_init()
|
||||||
{
|
{
|
||||||
if(!rtc_reserved) {
|
if(!rtc_reserved) {
|
||||||
INT_Disable();
|
core_util_critical_section_enter();
|
||||||
rtc_init_real(RTC_INIT_LPTIMER);
|
rtc_init_real(RTC_INIT_LPTIMER);
|
||||||
rtc_set_comp0_handler((uint32_t)lp_ticker_irq_handler);
|
rtc_set_comp0_handler((uint32_t)lp_ticker_irq_handler);
|
||||||
rtc_reserved = 1;
|
rtc_reserved = 1;
|
||||||
INT_Enable();
|
core_util_critical_section_exit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void lp_ticker_free()
|
void lp_ticker_free()
|
||||||
{
|
{
|
||||||
if(rtc_reserved) {
|
if(rtc_reserved) {
|
||||||
INT_Disable();
|
core_util_critical_section_enter();
|
||||||
rtc_free_real(RTC_INIT_LPTIMER);
|
rtc_free_real(RTC_INIT_LPTIMER);
|
||||||
rtc_reserved = 0;
|
rtc_reserved = 0;
|
||||||
INT_Enable();
|
core_util_critical_section_exit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
#include "em_gpio.h"
|
#include "em_gpio.h"
|
||||||
#include "em_timer.h"
|
#include "em_timer.h"
|
||||||
|
|
||||||
static int pwm_prescaler_div;
|
static uint32_t pwm_prescaler_div;
|
||||||
|
|
||||||
float pwmout_calculate_duty(uint32_t width_cycles, uint32_t period_cycles);
|
float pwmout_calculate_duty(uint32_t width_cycles, uint32_t period_cycles);
|
||||||
void pwmout_write_channel(uint32_t channel, float value);
|
void pwmout_write_channel(uint32_t channel, float value);
|
||||||
|
@ -132,7 +132,7 @@ bool pwmout_all_inactive(void) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if(PWM_TIMER->ROUTE == PWM_ROUTE) {
|
if(PWM_TIMER->ROUTE & (TIMER_ROUTE_CC0PEN | TIMER_ROUTE_CC1PEN | TIMER_ROUTE_CC2PEN)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -211,7 +211,11 @@ void pwmout_init(pwmout_t *obj, PinName pin)
|
||||||
#else
|
#else
|
||||||
// On P1, the route location is statically defined for the entire timer.
|
// On P1, the route location is statically defined for the entire timer.
|
||||||
PWM_TIMER->ROUTE &= ~_TIMER_ROUTE_LOCATION_MASK;
|
PWM_TIMER->ROUTE &= ~_TIMER_ROUTE_LOCATION_MASK;
|
||||||
PWM_TIMER->ROUTE |= PWM_ROUTE;
|
if(pwmout_all_inactive()) {
|
||||||
|
PWM_TIMER->ROUTE |= pinmap_find_function(pin,PinMap_PWM) << _TIMER_ROUTE_LOCATION_SHIFT;
|
||||||
|
} else {
|
||||||
|
MBED_ASSERT((pinmap_find_function(pin,PinMap_PWM) << _TIMER_ROUTE_LOCATION_SHIFT) == (PWM_TIMER->ROUTE & _TIMER_ROUTE_LOCATION_MASK));
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Set default 20ms frequency and 0ms pulse width
|
// Set default 20ms frequency and 0ms pulse width
|
||||||
|
@ -281,7 +285,7 @@ void pwmout_period(pwmout_t *obj, float seconds)
|
||||||
// This gives us max resolution for a given period
|
// This gives us max resolution for a given period
|
||||||
|
|
||||||
//The value of the top register if prescaler is set to 0
|
//The value of the top register if prescaler is set to 0
|
||||||
int cycles = REFERENCE_FREQUENCY * seconds;
|
uint32_t cycles = (uint32_t)REFERENCE_FREQUENCY * seconds;
|
||||||
pwm_prescaler_div = 0;
|
pwm_prescaler_div = 0;
|
||||||
|
|
||||||
//The top register is only 16 bits, so we keep dividing till we are below 0xFFFF
|
//The top register is only 16 bits, so we keep dividing till we are below 0xFFFF
|
||||||
|
|
|
@ -71,7 +71,8 @@ void RTC_IRQHandler(void)
|
||||||
|
|
||||||
uint32_t rtc_get_32bit(void)
|
uint32_t rtc_get_32bit(void)
|
||||||
{
|
{
|
||||||
return (RTC_CounterGet() + (time_extend << RTC_NUM_BITS));
|
uint32_t pending = (RTC_IntGet() & RTC_IF_OF) ? 1 : 0;
|
||||||
|
return (RTC_CounterGet() + ((time_extend + pending) << RTC_NUM_BITS));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t rtc_get_full(void)
|
uint64_t rtc_get_full(void)
|
||||||
|
@ -104,8 +105,8 @@ void rtc_init_real(uint32_t flags)
|
||||||
|
|
||||||
/* Enable Interrupt from RTC */
|
/* Enable Interrupt from RTC */
|
||||||
RTC_IntEnable(RTC_IEN_OF);
|
RTC_IntEnable(RTC_IEN_OF);
|
||||||
NVIC_EnableIRQ(RTC_IRQn);
|
|
||||||
NVIC_SetVector(RTC_IRQn, (uint32_t)RTC_IRQHandler);
|
NVIC_SetVector(RTC_IRQn, (uint32_t)RTC_IRQHandler);
|
||||||
|
NVIC_EnableIRQ(RTC_IRQn);
|
||||||
|
|
||||||
/* Initialize */
|
/* Initialize */
|
||||||
RTC_Init(&init);
|
RTC_Init(&init);
|
||||||
|
@ -198,8 +199,8 @@ void rtc_init_real(uint32_t flags)
|
||||||
|
|
||||||
/* Enable Interrupt from RTC */
|
/* Enable Interrupt from RTC */
|
||||||
RTCC_IntEnable(RTCC_IEN_OF);
|
RTCC_IntEnable(RTCC_IEN_OF);
|
||||||
NVIC_EnableIRQ(RTCC_IRQn);
|
|
||||||
NVIC_SetVector(RTCC_IRQn, (uint32_t)RTCC_IRQHandler);
|
NVIC_SetVector(RTCC_IRQn, (uint32_t)RTCC_IRQHandler);
|
||||||
|
NVIC_EnableIRQ(RTCC_IRQn);
|
||||||
|
|
||||||
/* Initialize */
|
/* Initialize */
|
||||||
RTCC_Init(&init);
|
RTCC_Init(&init);
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
#include "sleepmodes.h"
|
#include "sleepmodes.h"
|
||||||
#include "cmsis.h"
|
#include "cmsis.h"
|
||||||
#include "em_emu.h"
|
#include "em_emu.h"
|
||||||
#include "em_int.h"
|
#include "critical.h"
|
||||||
|
|
||||||
uint32_t sleep_block_counter[NUM_SLEEP_MODES] = {0};
|
uint32_t sleep_block_counter[NUM_SLEEP_MODES] = {0};
|
||||||
|
|
||||||
|
@ -80,9 +80,9 @@ void deepsleep(void)
|
||||||
*/
|
*/
|
||||||
void blockSleepMode(sleepstate_enum minimumMode)
|
void blockSleepMode(sleepstate_enum minimumMode)
|
||||||
{
|
{
|
||||||
INT_Disable();
|
core_util_critical_section_enter();
|
||||||
sleep_block_counter[minimumMode]++;
|
sleep_block_counter[minimumMode]++;
|
||||||
INT_Enable();
|
core_util_critical_section_exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Unblock the microcontroller from sleeping below a certain mode
|
/** Unblock the microcontroller from sleeping below a certain mode
|
||||||
|
@ -94,11 +94,11 @@ void blockSleepMode(sleepstate_enum minimumMode)
|
||||||
*/
|
*/
|
||||||
void unblockSleepMode(sleepstate_enum minimumMode)
|
void unblockSleepMode(sleepstate_enum minimumMode)
|
||||||
{
|
{
|
||||||
INT_Disable();
|
core_util_critical_section_enter();
|
||||||
if(sleep_block_counter[minimumMode] > 0) {
|
if(sleep_block_counter[minimumMode] > 0) {
|
||||||
sleep_block_counter[minimumMode]--;
|
sleep_block_counter[minimumMode]--;
|
||||||
}
|
}
|
||||||
INT_Enable();
|
core_util_critical_section_exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -471,91 +471,60 @@ void spi_buffer_set(spi_t *obj, const void *tx, uint32_t tx_length, void *rx, ui
|
||||||
|
|
||||||
static void spi_buffer_tx_write(spi_t *obj)
|
static void spi_buffer_tx_write(spi_t *obj)
|
||||||
{
|
{
|
||||||
uint32_t data;
|
uint32_t data = 0;
|
||||||
if(obj->spi.bits >= 9) {
|
|
||||||
// write double frame
|
|
||||||
if (obj->tx_buff.buffer == (void *)0) {
|
|
||||||
data = SPI_FILL_WORD;
|
|
||||||
} else {
|
|
||||||
uint16_t *tx = (uint16_t *)(obj->tx_buff.buffer);
|
|
||||||
data = tx[obj->tx_buff.pos] & 0xFFFF;
|
|
||||||
}
|
|
||||||
obj->tx_buff.pos += 1;
|
|
||||||
if(obj->spi.bits == 9){
|
|
||||||
obj->spi.spi->TXDATAX = data;
|
|
||||||
}else {
|
|
||||||
obj->spi.spi->TXDOUBLE = data;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (obj->tx_buff.pos < obj->tx_buff.length) {
|
// Interpret buffer according to declared width
|
||||||
// write single frame
|
if (!obj->tx_buff.buffer) {
|
||||||
if (obj->tx_buff.buffer == (void *)0) {
|
data = SPI_FILL_WORD;
|
||||||
data = SPI_FILL_WORD & 0xFF;
|
} else if (obj->tx_buff.width == 32) {
|
||||||
} else {
|
uint32_t * tx = (uint32_t *)obj->tx_buff.buffer;
|
||||||
uint8_t *tx = (uint8_t *)(obj->tx_buff.buffer);
|
data = tx[obj->tx_buff.pos];
|
||||||
data = tx[obj->tx_buff.pos] & 0xFF;
|
} else if (obj->tx_buff.width == 16) {
|
||||||
}
|
uint16_t * tx = (uint16_t *)obj->tx_buff.buffer;
|
||||||
obj->tx_buff.pos++;
|
data = tx[obj->tx_buff.pos];
|
||||||
|
} else {
|
||||||
|
uint8_t * tx = (uint8_t *)obj->tx_buff.buffer;
|
||||||
|
data = tx[obj->tx_buff.pos];
|
||||||
|
}
|
||||||
|
obj->tx_buff.pos++;
|
||||||
|
|
||||||
|
// Send buffer
|
||||||
|
if (obj->spi.bits > 9) {
|
||||||
|
obj->spi.spi->TXDOUBLE = data;
|
||||||
|
} else if (obj->spi.bits == 9) {
|
||||||
|
obj->spi.spi->TXDATAX = data;
|
||||||
|
} else {
|
||||||
obj->spi.spi->TXDATA = data;
|
obj->spi.spi->TXDATA = data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void spi_buffer_rx_read(spi_t *obj)
|
static void spi_buffer_rx_read(spi_t *obj)
|
||||||
{
|
{
|
||||||
if (obj->spi.bits % 9 != 0) {
|
uint32_t data;
|
||||||
if ((obj->spi.spi->STATUS & USART_STATUS_RXFULL) && (obj->rx_buff.pos < obj->rx_buff.length - 1) && ((obj->rx_buff.pos % 2) == 0)) {
|
|
||||||
// Read max 16 bits from buffer to speed things up
|
if (obj->spi.spi->STATUS & USART_STATUS_RXDATAV) {
|
||||||
uint32_t data = (uint32_t)obj->spi.spi->RXDOUBLE; //read the data but store only if rx is set and not full
|
// Read from the FIFO
|
||||||
if (obj->rx_buff.buffer) {
|
if (obj->spi.bits > 9) {
|
||||||
uint16_t *rx = (uint16_t *)(obj->rx_buff.buffer);
|
data = obj->spi.spi->RXDOUBLE;
|
||||||
rx[obj->rx_buff.pos / 2] = data & 0xFFFF;
|
} else if (obj->spi.bits == 9) {
|
||||||
obj->rx_buff.pos += 2;
|
data = obj->spi.spi->RXDATAX;
|
||||||
}
|
} else {
|
||||||
} else if ((obj->spi.spi->STATUS & (USART_STATUS_RXDATAV | USART_STATUS_RXFULL)) && (obj->rx_buff.pos < obj->rx_buff.length)) {
|
data = obj->spi.spi->RXDATA;
|
||||||
// Read 8 bits from buffer
|
|
||||||
while((obj->spi.spi->STATUS & (USART_STATUS_RXDATAV | USART_STATUS_RXFULL)) && (obj->rx_buff.pos < obj->rx_buff.length)) {
|
|
||||||
uint32_t data = (uint32_t)obj->spi.spi->RXDATA; //read the data but store only if rx is set and not full
|
|
||||||
if (obj->rx_buff.buffer) {
|
|
||||||
uint8_t *rx = (uint8_t *)(obj->rx_buff.buffer);
|
|
||||||
rx[obj->rx_buff.pos] = data & 0xFF;
|
|
||||||
obj->rx_buff.pos++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (obj->spi.spi->STATUS & USART_STATUS_RXFULL) {
|
|
||||||
// Read from the buffer to lower the interrupt flag
|
|
||||||
volatile uint32_t data = (uint32_t)obj->spi.spi->RXDOUBLE;
|
|
||||||
} else if (obj->spi.spi->STATUS & USART_STATUS_RXDATAV) {
|
|
||||||
// Read from the buffer to lower the interrupt flag
|
|
||||||
volatile uint32_t data = (uint32_t)obj->spi.spi->RXDATA;
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// Data bits is multiple of 9, so use the extended registers
|
// If there is room in the buffer, store the data
|
||||||
if ((obj->spi.spi->STATUS & USART_STATUS_RXFULL) && (obj->rx_buff.pos < obj->rx_buff.length - 3) && ((obj->rx_buff.pos % 4) == 0)) {
|
if (obj->rx_buff.buffer && obj->rx_buff.pos < obj->rx_buff.length) {
|
||||||
// Read max 18 bits from buffer to speed things up
|
if (obj->rx_buff.width == 32) {
|
||||||
uint32_t data = (uint32_t)obj->spi.spi->RXDOUBLEX; //read the data but store only if rx is set and will not overflow
|
uint32_t * rx = (uint32_t *)(obj->rx_buff.buffer);
|
||||||
if (obj->rx_buff.buffer) {
|
rx[obj->rx_buff.pos] = data;
|
||||||
uint16_t *rx = (uint16_t *)(obj->rx_buff.buffer);
|
} else if (obj->rx_buff.width == 16) {
|
||||||
rx[obj->rx_buff.pos / 2] = data & 0x000001FF;
|
uint16_t * rx = (uint16_t *)(obj->rx_buff.buffer);
|
||||||
rx[(obj->rx_buff.pos / 2) + 1] = (data & 0x01FF0000) >> 16;
|
rx[obj->rx_buff.pos] = data;
|
||||||
obj->rx_buff.pos += 4;
|
} else {
|
||||||
|
uint8_t * rx = (uint8_t *)(obj->rx_buff.buffer);
|
||||||
|
rx[obj->rx_buff.pos] = data;
|
||||||
}
|
}
|
||||||
} else if ((obj->spi.spi->STATUS & (USART_STATUS_RXDATAV | USART_STATUS_RXFULL)) && (obj->rx_buff.pos < obj->rx_buff.length - 1)) {
|
obj->rx_buff.pos++;
|
||||||
// Read 9 bits from buffer
|
|
||||||
while((obj->spi.spi->STATUS & (USART_STATUS_RXDATAV | USART_STATUS_RXFULL)) && (obj->rx_buff.pos < obj->rx_buff.length - 1)) {
|
|
||||||
uint32_t data = (uint32_t)obj->spi.spi->RXDATAX; //read the data but store only if rx is set and not full
|
|
||||||
if (obj->rx_buff.buffer) {
|
|
||||||
uint16_t *rx = (uint16_t *)(obj->rx_buff.buffer);
|
|
||||||
rx[obj->rx_buff.pos / 2] = data & 0x01FF;
|
|
||||||
obj->rx_buff.pos += 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (obj->spi.spi->STATUS & USART_STATUS_RXFULL) {
|
|
||||||
// Read from the buffer to lower the interrupt flag
|
|
||||||
volatile uint32_t data = (uint32_t)obj->spi.spi->RXDOUBLEX;
|
|
||||||
} else if (obj->spi.spi->STATUS & USART_STATUS_RXDATAV) {
|
|
||||||
// Read from the buffer to lower the interrupt flag
|
|
||||||
volatile uint32_t data = (uint32_t)obj->spi.spi->RXDATAX;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -813,58 +782,6 @@ static void spi_activate_dma(spi_t *obj, void* rxdata, const void* txdata, int t
|
||||||
{
|
{
|
||||||
LDMA_PeripheralSignal_t dma_periph;
|
LDMA_PeripheralSignal_t dma_periph;
|
||||||
|
|
||||||
if( txdata ) {
|
|
||||||
volatile void *target_addr;
|
|
||||||
|
|
||||||
/* Select TX target address. 9 bit frame length requires to use extended register.
|
|
||||||
10 bit and larger frame requires to use TXDOUBLE register. */
|
|
||||||
switch((int)obj->spi.spi) {
|
|
||||||
case USART_0:
|
|
||||||
dma_periph = ldmaPeripheralSignal_USART0_TXBL;
|
|
||||||
if(obj->spi.bits <= 8){
|
|
||||||
target_addr = &USART0->TXDATA;
|
|
||||||
}else if(obj->spi.bits == 9){
|
|
||||||
target_addr = &USART0->TXDATAX;
|
|
||||||
}else{
|
|
||||||
target_addr = &USART0->TXDOUBLE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case USART_1:
|
|
||||||
dma_periph = ldmaPeripheralSignal_USART1_TXBL;
|
|
||||||
if(obj->spi.bits <= 8){
|
|
||||||
target_addr = &USART1->TXDATA;
|
|
||||||
}else if(obj->spi.bits == 9){
|
|
||||||
target_addr = &USART1->TXDATAX;
|
|
||||||
}else{
|
|
||||||
target_addr = &USART1->TXDOUBLE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
EFM_ASSERT(0);
|
|
||||||
while(1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check the transmit lenght, and split long transfers to smaller ones*/
|
|
||||||
int max_length = 1024;
|
|
||||||
#ifdef _LDMA_CH_CTRL_XFERCNT_MASK
|
|
||||||
max_length = (_LDMA_CH_CTRL_XFERCNT_MASK>>_LDMA_CH_CTRL_XFERCNT_SHIFT)+1;
|
|
||||||
#endif
|
|
||||||
if(tx_length>max_length){
|
|
||||||
tx_length = max_length;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Save amount of TX done by DMA */
|
|
||||||
obj->tx_buff.pos += tx_length;
|
|
||||||
|
|
||||||
LDMA_TransferCfg_t xferConf = LDMA_TRANSFER_CFG_PERIPHERAL(dma_periph);
|
|
||||||
LDMA_Descriptor_t desc = LDMA_DESCRIPTOR_SINGLE_M2P_BYTE(txdata, target_addr, tx_length);
|
|
||||||
if(obj->spi.bits >= 9){
|
|
||||||
desc.xfer.size = ldmaCtrlSizeHalf;
|
|
||||||
}
|
|
||||||
LDMAx_StartTransfer(obj->spi.dmaOptionsTX.dmaChannel, &xferConf, &desc, serial_dmaTransferComplete,obj->spi.dmaOptionsRX.dmaCallback.userPtr);
|
|
||||||
|
|
||||||
}
|
|
||||||
if(rxdata) {
|
if(rxdata) {
|
||||||
volatile const void *source_addr;
|
volatile const void *source_addr;
|
||||||
/* Select RX source address. 9 bit frame length requires to use extended register.
|
/* Select RX source address. 9 bit frame length requires to use extended register.
|
||||||
|
@ -872,23 +789,9 @@ static void spi_activate_dma(spi_t *obj, void* rxdata, const void* txdata, int t
|
||||||
switch((int)obj->spi.spi) {
|
switch((int)obj->spi.spi) {
|
||||||
case USART_0:
|
case USART_0:
|
||||||
dma_periph = ldmaPeripheralSignal_USART0_RXDATAV;
|
dma_periph = ldmaPeripheralSignal_USART0_RXDATAV;
|
||||||
if(obj->spi.bits <= 8){
|
|
||||||
source_addr = &USART0->RXDATA;
|
|
||||||
}else if(obj->spi.bits == 9){
|
|
||||||
source_addr = &USART0->RXDATAX;
|
|
||||||
}else{
|
|
||||||
source_addr = &USART0->RXDOUBLE;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case USART_1:
|
case USART_1:
|
||||||
dma_periph = ldmaPeripheralSignal_USART1_RXDATAV;
|
dma_periph = ldmaPeripheralSignal_USART1_RXDATAV;
|
||||||
if(obj->spi.bits <= 8){
|
|
||||||
source_addr = &USART1->RXDATA;
|
|
||||||
}else if(obj->spi.bits == 9){
|
|
||||||
source_addr = &USART1->RXDATAX;
|
|
||||||
}else{
|
|
||||||
source_addr = &USART1->RXDOUBLE;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
EFM_ASSERT(0);
|
EFM_ASSERT(0);
|
||||||
|
@ -896,13 +799,104 @@ static void spi_activate_dma(spi_t *obj, void* rxdata, const void* txdata, int t
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (obj->spi.bits <= 8) {
|
||||||
|
source_addr = &obj->spi.spi->RXDATA;
|
||||||
|
} else if (obj->spi.bits == 9) {
|
||||||
|
source_addr = &obj->spi.spi->RXDATAX;
|
||||||
|
} else {
|
||||||
|
source_addr = &obj->spi.spi->RXDOUBLE;
|
||||||
|
}
|
||||||
|
|
||||||
LDMA_TransferCfg_t xferConf = LDMA_TRANSFER_CFG_PERIPHERAL(dma_periph);
|
LDMA_TransferCfg_t xferConf = LDMA_TRANSFER_CFG_PERIPHERAL(dma_periph);
|
||||||
LDMA_Descriptor_t desc = LDMA_DESCRIPTOR_SINGLE_P2M_BYTE(source_addr, rxdata, rx_length);
|
LDMA_Descriptor_t desc = LDMA_DESCRIPTOR_SINGLE_P2M_BYTE(source_addr, rxdata, rx_length);
|
||||||
|
|
||||||
if(obj->spi.bits >= 9){
|
if(obj->spi.bits >= 9){
|
||||||
desc.xfer.size = ldmaCtrlSizeHalf;
|
desc.xfer.size = ldmaCtrlSizeHalf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (obj->tx_buff.width == 32) {
|
||||||
|
if (obj->spi.bits >= 9) {
|
||||||
|
desc.xfer.dstInc = ldmaCtrlDstIncTwo;
|
||||||
|
} else {
|
||||||
|
desc.xfer.dstInc = ldmaCtrlDstIncFour;
|
||||||
|
}
|
||||||
|
} else if (obj->tx_buff.width == 16) {
|
||||||
|
if (obj->spi.bits >= 9) {
|
||||||
|
desc.xfer.dstInc = ldmaCtrlDstIncOne;
|
||||||
|
} else {
|
||||||
|
desc.xfer.dstInc = ldmaCtrlDstIncTwo;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
desc.xfer.dstInc = ldmaCtrlDstIncOne;
|
||||||
|
}
|
||||||
|
|
||||||
LDMAx_StartTransfer(obj->spi.dmaOptionsRX.dmaChannel, &xferConf, &desc, serial_dmaTransferComplete,obj->spi.dmaOptionsRX.dmaCallback.userPtr);
|
LDMAx_StartTransfer(obj->spi.dmaOptionsRX.dmaChannel, &xferConf, &desc, serial_dmaTransferComplete,obj->spi.dmaOptionsRX.dmaCallback.userPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
volatile void *target_addr;
|
||||||
|
|
||||||
|
/* Select TX target address. 9 bit frame length requires to use extended register.
|
||||||
|
10 bit and larger frame requires to use TXDOUBLE register. */
|
||||||
|
switch ((int)obj->spi.spi) {
|
||||||
|
case USART_0:
|
||||||
|
dma_periph = ldmaPeripheralSignal_USART0_TXBL;
|
||||||
|
break;
|
||||||
|
case USART_1:
|
||||||
|
dma_periph = ldmaPeripheralSignal_USART1_TXBL;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
EFM_ASSERT(0);
|
||||||
|
while(1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj->spi.bits <= 8) {
|
||||||
|
target_addr = &obj->spi.spi->TXDATA;
|
||||||
|
} else if (obj->spi.bits == 9) {
|
||||||
|
target_addr = &obj->spi.spi->TXDATAX;
|
||||||
|
} else {
|
||||||
|
target_addr = &obj->spi.spi->TXDOUBLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check the transmit length, and split long transfers to smaller ones */
|
||||||
|
int max_length = 1024;
|
||||||
|
#ifdef _LDMA_CH_CTRL_XFERCNT_MASK
|
||||||
|
max_length = (_LDMA_CH_CTRL_XFERCNT_MASK>>_LDMA_CH_CTRL_XFERCNT_SHIFT)+1;
|
||||||
|
#endif
|
||||||
|
if (tx_length > max_length) {
|
||||||
|
tx_length = max_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Save amount of TX done by DMA */
|
||||||
|
obj->tx_buff.pos += tx_length;
|
||||||
|
|
||||||
|
LDMA_TransferCfg_t xferConf = LDMA_TRANSFER_CFG_PERIPHERAL(dma_periph);
|
||||||
|
LDMA_Descriptor_t desc = LDMA_DESCRIPTOR_SINGLE_M2P_BYTE((txdata ? txdata : &fill_word), target_addr, tx_length);
|
||||||
|
|
||||||
|
if (obj->spi.bits >= 9) {
|
||||||
|
desc.xfer.size = ldmaCtrlSizeHalf;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!txdata) {
|
||||||
|
desc.xfer.srcInc = ldmaCtrlSrcIncNone;
|
||||||
|
} else if (obj->tx_buff.width == 32) {
|
||||||
|
if (obj->spi.bits >= 9) {
|
||||||
|
desc.xfer.srcInc = ldmaCtrlSrcIncTwo;
|
||||||
|
} else {
|
||||||
|
desc.xfer.srcInc = ldmaCtrlSrcIncFour;
|
||||||
|
}
|
||||||
|
} else if (obj->tx_buff.width == 16) {
|
||||||
|
if (obj->spi.bits >= 9) {
|
||||||
|
desc.xfer.srcInc = ldmaCtrlSrcIncOne;
|
||||||
|
} else {
|
||||||
|
desc.xfer.srcInc = ldmaCtrlSrcIncTwo;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
desc.xfer.srcInc = ldmaCtrlSrcIncOne;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Kick off DMA TX
|
||||||
|
LDMAx_StartTransfer(obj->spi.dmaOptionsTX.dmaChannel, &xferConf, &desc, serial_dmaTransferComplete,obj->spi.dmaOptionsTX.dmaCallback.userPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
@ -922,90 +916,90 @@ static void spi_activate_dma(spi_t *obj, void* rxdata, const void* txdata, int t
|
||||||
DMA_CfgDescr_TypeDef rxDescrCfg;
|
DMA_CfgDescr_TypeDef rxDescrCfg;
|
||||||
DMA_CfgDescr_TypeDef txDescrCfg;
|
DMA_CfgDescr_TypeDef txDescrCfg;
|
||||||
|
|
||||||
/* Split up transfers if the tx length is larger than what the DMA supports. */
|
/* Split up transfers if the length is larger than what the DMA supports. */
|
||||||
const int DMA_MAX_TRANSFER = (_DMA_CTRL_N_MINUS_1_MASK >> _DMA_CTRL_N_MINUS_1_SHIFT);
|
const int DMA_MAX_TRANSFER = (_DMA_CTRL_N_MINUS_1_MASK >> _DMA_CTRL_N_MINUS_1_SHIFT);
|
||||||
|
|
||||||
if (tx_length > DMA_MAX_TRANSFER) {
|
if (tx_length > DMA_MAX_TRANSFER) {
|
||||||
uint32_t max_length = DMA_MAX_TRANSFER;
|
tx_length = DMA_MAX_TRANSFER;
|
||||||
|
}
|
||||||
/* Make sure only an even amount of bytes are transferred
|
if (rx_length > DMA_MAX_TRANSFER) {
|
||||||
if the width is larger than 8 bits. */
|
rx_length = DMA_MAX_TRANSFER;
|
||||||
if (obj->spi.bits > 8) {
|
|
||||||
max_length = DMA_MAX_TRANSFER - (DMA_MAX_TRANSFER & 0x01);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Update length for current transfer. */
|
|
||||||
tx_length = max_length;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save amount of TX done by DMA */
|
/* Save amount of TX done by DMA */
|
||||||
obj->tx_buff.pos += tx_length;
|
obj->tx_buff.pos += tx_length;
|
||||||
|
obj->rx_buff.pos += rx_length;
|
||||||
|
|
||||||
if(obj->spi.bits != 9) {
|
/* Only activate RX DMA if a receive buffer is specified */
|
||||||
/* Only activate RX DMA if a receive buffer is specified */
|
if (rxdata != NULL) {
|
||||||
if (rxdata != NULL) {
|
// Setting up channel descriptor
|
||||||
// Setting up channel descriptor
|
if (obj->rx_buff.width == 32) {
|
||||||
rxDescrCfg.dstInc = dmaDataInc1;
|
rxDescrCfg.dstInc = dmaDataInc4;
|
||||||
rxDescrCfg.srcInc = dmaDataIncNone;
|
} else if (obj->rx_buff.width == 16) {
|
||||||
rxDescrCfg.size = dmaDataSize1;
|
|
||||||
rxDescrCfg.arbRate = dmaArbitrate1;
|
|
||||||
rxDescrCfg.hprot = 0;
|
|
||||||
DMA_CfgDescr(obj->spi.dmaOptionsRX.dmaChannel, true, &rxDescrCfg);
|
|
||||||
|
|
||||||
/* Activate RX channel */
|
|
||||||
DMA_ActivateBasic(obj->spi.dmaOptionsRX.dmaChannel, true, false, rxdata, (void *)&(obj->spi.spi->RXDATA),
|
|
||||||
rx_length - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// buffer with all FFs.
|
|
||||||
/* Setting up channel descriptor */
|
|
||||||
txDescrCfg.dstInc = dmaDataIncNone;
|
|
||||||
txDescrCfg.srcInc = (txdata == 0 ? dmaDataIncNone : (obj->spi.bits <= 8 ? dmaDataInc1 : dmaDataInc2)); //Do not increment source pointer when there is no transmit buffer
|
|
||||||
txDescrCfg.size = (obj->spi.bits <= 8 ? dmaDataSize1 : dmaDataSize2); //When frame size > 9, we can use TXDOUBLE to save bandwidth
|
|
||||||
txDescrCfg.arbRate = dmaArbitrate1;
|
|
||||||
txDescrCfg.hprot = 0;
|
|
||||||
DMA_CfgDescr(obj->spi.dmaOptionsTX.dmaChannel, true, &txDescrCfg);
|
|
||||||
|
|
||||||
/* Activate TX channel */
|
|
||||||
DMA_ActivateBasic( obj->spi.dmaOptionsTX.dmaChannel,
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
(obj->spi.bits <= 8 ? (void *)&(obj->spi.spi->TXDATA) : (void *)&(obj->spi.spi->TXDOUBLE)), //When frame size > 9, point to TXDOUBLE
|
|
||||||
(txdata == 0 ? &fill_word : (void *)txdata), // When there is nothing to transmit, point to static fill word
|
|
||||||
(tx_length - 1));
|
|
||||||
} else {
|
|
||||||
/* Frame size == 9 */
|
|
||||||
/* Only activate RX DMA if a receive buffer is specified */
|
|
||||||
if (rxdata != NULL) {
|
|
||||||
// Setting up channel descriptor
|
|
||||||
rxDescrCfg.dstInc = dmaDataInc2;
|
rxDescrCfg.dstInc = dmaDataInc2;
|
||||||
rxDescrCfg.srcInc = dmaDataIncNone;
|
} else {
|
||||||
rxDescrCfg.size = dmaDataSize2;
|
rxDescrCfg.dstInc = dmaDataInc1;
|
||||||
rxDescrCfg.arbRate = dmaArbitrate1;
|
}
|
||||||
rxDescrCfg.hprot = 0;
|
rxDescrCfg.srcInc = dmaDataIncNone;
|
||||||
DMA_CfgDescr(obj->spi.dmaOptionsRX.dmaChannel, true, &rxDescrCfg);
|
rxDescrCfg.size = (obj->spi.bits <= 8 ? dmaDataSize1 : dmaDataSize2); //When frame size >= 9, use RXDOUBLE
|
||||||
|
rxDescrCfg.arbRate = dmaArbitrate1;
|
||||||
|
rxDescrCfg.hprot = 0;
|
||||||
|
DMA_CfgDescr(obj->spi.dmaOptionsRX.dmaChannel, true, &rxDescrCfg);
|
||||||
|
|
||||||
/* Activate RX channel */
|
void * rx_reg;
|
||||||
DMA_ActivateBasic(obj->spi.dmaOptionsRX.dmaChannel, true, false, rxdata, (void *)&(obj->spi.spi->RXDATAX),
|
if (obj->spi.bits > 9) {
|
||||||
(rx_length / 2) - 1);
|
rx_reg = (void *)&obj->spi.spi->RXDOUBLE;
|
||||||
|
} else if (obj->spi.bits == 9) {
|
||||||
|
rx_reg = (void *)&obj->spi.spi->RXDATAX;
|
||||||
|
} else {
|
||||||
|
rx_reg = (void *)&obj->spi.spi->RXDATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Setting up channel descriptor */
|
/* Activate RX channel */
|
||||||
txDescrCfg.dstInc = dmaDataIncNone;
|
DMA_ActivateBasic(obj->spi.dmaOptionsRX.dmaChannel,
|
||||||
txDescrCfg.srcInc = (txdata == 0 ? dmaDataIncNone : dmaDataInc2); //Do not increment source pointer when there is no transmit buffer
|
true,
|
||||||
txDescrCfg.size = dmaDataSize2; //When frame size > 9, we can use TXDOUBLE to save bandwidth
|
false,
|
||||||
txDescrCfg.arbRate = dmaArbitrate1;
|
rxdata,
|
||||||
txDescrCfg.hprot = 0;
|
rx_reg,
|
||||||
DMA_CfgDescr(obj->spi.dmaOptionsTX.dmaChannel, true, &txDescrCfg);
|
rx_length - 1);
|
||||||
|
|
||||||
/* Activate TX channel */
|
|
||||||
DMA_ActivateBasic( obj->spi.dmaOptionsTX.dmaChannel,
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
(void *)&(obj->spi.spi->TXDATAX), //When frame size > 9, point to TXDOUBLE
|
|
||||||
(txdata == 0 ? &fill_word : (void *)txdata), // When there is nothing to transmit, point to static fill word
|
|
||||||
(tx_length - 1));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// buffer with all FFs.
|
||||||
|
/* Setting up channel descriptor */
|
||||||
|
txDescrCfg.dstInc = dmaDataIncNone;
|
||||||
|
if (txdata == 0) {
|
||||||
|
// Don't increment source when there is no transmit buffer
|
||||||
|
txDescrCfg.srcInc = dmaDataIncNone;
|
||||||
|
} else {
|
||||||
|
if (obj->tx_buff.width == 32) {
|
||||||
|
txDescrCfg.srcInc = dmaDataInc4;
|
||||||
|
} else if (obj->tx_buff.width == 16) {
|
||||||
|
txDescrCfg.srcInc = dmaDataInc2;
|
||||||
|
} else {
|
||||||
|
txDescrCfg.srcInc = dmaDataInc1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
txDescrCfg.size = (obj->spi.bits <= 8 ? dmaDataSize1 : dmaDataSize2); //When frame size >= 9, use TXDOUBLE
|
||||||
|
txDescrCfg.arbRate = dmaArbitrate1;
|
||||||
|
txDescrCfg.hprot = 0;
|
||||||
|
DMA_CfgDescr(obj->spi.dmaOptionsTX.dmaChannel, true, &txDescrCfg);
|
||||||
|
|
||||||
|
void * tx_reg;
|
||||||
|
if (obj->spi.bits > 9) {
|
||||||
|
tx_reg = (void *)&obj->spi.spi->TXDOUBLE;
|
||||||
|
} else if (obj->spi.bits == 9) {
|
||||||
|
tx_reg = (void *)&obj->spi.spi->TXDATAX;
|
||||||
|
} else {
|
||||||
|
tx_reg = (void *)&obj->spi.spi->TXDATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Activate TX channel */
|
||||||
|
DMA_ActivateBasic(obj->spi.dmaOptionsTX.dmaChannel,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
tx_reg,
|
||||||
|
(txdata == 0 ? &fill_word : (void *)txdata), // When there is nothing to transmit, point to static fill word
|
||||||
|
(tx_length - 1));
|
||||||
}
|
}
|
||||||
#endif //LDMA_PRESENT
|
#endif //LDMA_PRESENT
|
||||||
/********************************************************************
|
/********************************************************************
|
||||||
|
@ -1191,67 +1185,84 @@ uint32_t spi_irq_handler_asynch(spi_t* obj)
|
||||||
|
|
||||||
/* If there is still data in the TX buffer, setup a new transfer. */
|
/* If there is still data in the TX buffer, setup a new transfer. */
|
||||||
if (obj->tx_buff.pos < obj->tx_buff.length) {
|
if (obj->tx_buff.pos < obj->tx_buff.length) {
|
||||||
|
/* If there is still a TX transfer ongoing, let it finish
|
||||||
|
* before (if necessary) kicking off a new transfer */
|
||||||
|
if (DMA_ChannelEnabled(obj->spi.dmaOptionsTX.dmaChannel)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
/* Find position and remaining length without modifying tx_buff. */
|
/* Find position and remaining length without modifying tx_buff. */
|
||||||
void* tx_pointer = (char*)obj->tx_buff.buffer + obj->tx_buff.pos;
|
void * tx_pointer;
|
||||||
|
if (obj->tx_buff.width == 32) {
|
||||||
|
tx_pointer = ((uint32_t *)obj->tx_buff.buffer) + obj->tx_buff.pos;
|
||||||
|
} else if (obj->tx_buff.width == 16) {
|
||||||
|
tx_pointer = ((uint16_t *)obj->tx_buff.buffer) + obj->tx_buff.pos;
|
||||||
|
} else {
|
||||||
|
tx_pointer = ((uint8_t *)obj->tx_buff.buffer) + obj->tx_buff.pos;
|
||||||
|
}
|
||||||
uint32_t tx_length = obj->tx_buff.length - obj->tx_buff.pos;
|
uint32_t tx_length = obj->tx_buff.length - obj->tx_buff.pos;
|
||||||
|
|
||||||
|
/* Refresh RX transfer too if it exists */
|
||||||
|
void * rx_pointer = NULL;
|
||||||
|
if (obj->rx_buff.pos < obj->rx_buff.length) {
|
||||||
|
if (obj->rx_buff.width == 32) {
|
||||||
|
rx_pointer = ((uint32_t *)obj->rx_buff.buffer) + obj->rx_buff.pos;
|
||||||
|
} else if (obj->rx_buff.width == 16) {
|
||||||
|
rx_pointer = ((uint16_t *)obj->rx_buff.buffer) + obj->rx_buff.pos;
|
||||||
|
} else {
|
||||||
|
rx_pointer = ((uint8_t *)obj->rx_buff.buffer) + obj->rx_buff.pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uint32_t rx_length = obj->rx_buff.length - obj->rx_buff.pos;
|
||||||
|
|
||||||
|
/* Wait for the previous transfer to complete. */
|
||||||
|
while(!(obj->spi.spi->STATUS & USART_STATUS_TXC));
|
||||||
|
|
||||||
/* Begin transfer. Rely on spi_activate_dma to split up the transfer further. */
|
/* Begin transfer. Rely on spi_activate_dma to split up the transfer further. */
|
||||||
spi_activate_dma(obj, obj->rx_buff.buffer, tx_pointer, tx_length, obj->rx_buff.length);
|
spi_activate_dma(obj, rx_pointer, tx_pointer, tx_length, rx_length);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If there is an RX transfer ongoing, wait for it to finish */
|
/* If an RX transfer is ongoing, continue processing RX data */
|
||||||
if (DMA_ChannelEnabled(obj->spi.dmaOptionsRX.dmaChannel)) {
|
if (DMA_ChannelEnabled(obj->spi.dmaOptionsRX.dmaChannel)) {
|
||||||
/* Check if we need to kick off TX transfer again to force more incoming data. */
|
/* Check if we need to kick off TX transfer again to force more incoming data. */
|
||||||
if (!DMA_ChannelEnabled(obj->spi.dmaOptionsTX.dmaChannel) && (obj->tx_buff.pos < obj->rx_buff.length)) {
|
if (!DMA_ChannelEnabled(obj->spi.dmaOptionsTX.dmaChannel) && (obj->rx_buff.pos < obj->rx_buff.length)) {
|
||||||
//Save state of TX transfer amount
|
//Save state of TX transfer amount
|
||||||
int length_diff = obj->rx_buff.length - obj->tx_buff.pos;
|
int length_diff = obj->rx_buff.length - obj->rx_buff.pos;
|
||||||
obj->tx_buff.pos = obj->rx_buff.length;
|
obj->tx_buff.pos = obj->rx_buff.length;
|
||||||
|
|
||||||
//Kick off a new DMA transfer
|
//Kick off a new DMA transfer
|
||||||
DMA_CfgDescr_TypeDef txDescrCfg;
|
DMA_CfgDescr_TypeDef txDescrCfg;
|
||||||
|
|
||||||
if(obj->spi.bits != 9) {
|
fill_word = SPI_FILL_WORD;
|
||||||
fill_word = SPI_FILL_WORD;
|
/* Setting up channel descriptor */
|
||||||
/* Setting up channel descriptor */
|
txDescrCfg.dstInc = dmaDataIncNone;
|
||||||
txDescrCfg.dstInc = dmaDataIncNone;
|
txDescrCfg.srcInc = dmaDataIncNone; //Do not increment source pointer when there is no transmit buffer
|
||||||
txDescrCfg.srcInc = dmaDataIncNone; //Do not increment source pointer when there is no transmit buffer
|
txDescrCfg.size = (obj->spi.bits <= 8 ? dmaDataSize1 : dmaDataSize2); //When frame size > 9, we can use TXDOUBLE to save bandwidth
|
||||||
txDescrCfg.size = (obj->spi.bits <= 8 ? dmaDataSize1 : dmaDataSize2); //When frame size > 9, we can use TXDOUBLE to save bandwidth
|
txDescrCfg.arbRate = dmaArbitrate1;
|
||||||
txDescrCfg.arbRate = dmaArbitrate1;
|
txDescrCfg.hprot = 0;
|
||||||
txDescrCfg.hprot = 0;
|
DMA_CfgDescr(obj->spi.dmaOptionsTX.dmaChannel, true, &txDescrCfg);
|
||||||
DMA_CfgDescr(obj->spi.dmaOptionsTX.dmaChannel, true, &txDescrCfg);
|
|
||||||
|
|
||||||
/* Activate TX channel */
|
void * tx_reg;
|
||||||
DMA_ActivateBasic( obj->spi.dmaOptionsTX.dmaChannel,
|
if (obj->spi.bits > 9) {
|
||||||
true,
|
tx_reg = (void *)&obj->spi.spi->TXDOUBLE;
|
||||||
false,
|
} else if (obj->spi.bits == 9) {
|
||||||
(obj->spi.bits <= 8 ? (void *)&(obj->spi.spi->TXDATA) : (void *)&(obj->spi.spi->TXDOUBLE)), //When frame size > 9, point to TXDOUBLE
|
tx_reg = (void *)&obj->spi.spi->TXDATAX;
|
||||||
&fill_word, // When there is nothing to transmit, point to static fill word
|
|
||||||
(obj->spi.bits <= 8 ? length_diff - 1 : (length_diff / 2) - 1)); // When using TXDOUBLE, recalculate transfer length
|
|
||||||
} else {
|
} else {
|
||||||
/* Setting up channel descriptor */
|
tx_reg = (void *)&obj->spi.spi->TXDATA;
|
||||||
fill_word = SPI_FILL_WORD & 0x1FF;
|
|
||||||
txDescrCfg.dstInc = dmaDataIncNone;
|
|
||||||
txDescrCfg.srcInc = dmaDataIncNone; //Do not increment source pointer when there is no transmit buffer
|
|
||||||
txDescrCfg.size = dmaDataSize2; //When frame size > 9, we can use TXDOUBLE to save bandwidth
|
|
||||||
txDescrCfg.arbRate = dmaArbitrate1;
|
|
||||||
txDescrCfg.hprot = 0;
|
|
||||||
DMA_CfgDescr(obj->spi.dmaOptionsTX.dmaChannel, true, &txDescrCfg);
|
|
||||||
|
|
||||||
DMA_ActivateBasic( obj->spi.dmaOptionsTX.dmaChannel,
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
(void *)&(obj->spi.spi->TXDATAX), //When frame size > 9, point to TXDOUBLE
|
|
||||||
&fill_word, // When there is nothing to transmit, point to static fill word
|
|
||||||
(length_diff / 2) - 1);
|
|
||||||
}
|
}
|
||||||
} else return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If there is still a TX transfer ongoing (tx_length > rx_length), wait for it to finish */
|
/* Activate TX channel */
|
||||||
if (DMA_ChannelEnabled(obj->spi.dmaOptionsTX.dmaChannel)) {
|
DMA_ActivateBasic(obj->spi.dmaOptionsTX.dmaChannel,
|
||||||
return 0;
|
true,
|
||||||
|
false,
|
||||||
|
tx_reg, //When frame size > 9, point to TXDOUBLE
|
||||||
|
&fill_word, // When there is nothing to transmit, point to static fill word
|
||||||
|
length_diff - 1);
|
||||||
|
} else {
|
||||||
|
/* Nothing to do */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Release the dma channels if they were opportunistically allocated */
|
/* Release the dma channels if they were opportunistically allocated */
|
||||||
|
@ -1261,7 +1272,7 @@ uint32_t spi_irq_handler_asynch(spi_t* obj)
|
||||||
obj->spi.dmaOptionsTX.dmaUsageState = DMA_USAGE_OPPORTUNISTIC;
|
obj->spi.dmaOptionsTX.dmaUsageState = DMA_USAGE_OPPORTUNISTIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait transmit to complete, before user code is indicated*/
|
/* Wait for transmit to complete, before user code is indicated */
|
||||||
while(!(obj->spi.spi->STATUS & USART_STATUS_TXC));
|
while(!(obj->spi.spi->STATUS & USART_STATUS_TXC));
|
||||||
unblockSleepMode(SPI_LEAST_ACTIVE_SLEEPMODE);
|
unblockSleepMode(SPI_LEAST_ACTIVE_SLEEPMODE);
|
||||||
|
|
||||||
|
@ -1282,6 +1293,8 @@ uint32_t spi_irq_handler_asynch(spi_t* obj)
|
||||||
/* disable interrupts */
|
/* disable interrupts */
|
||||||
spi_enable_interrupt(obj, (uint32_t)NULL, false);
|
spi_enable_interrupt(obj, (uint32_t)NULL, false);
|
||||||
|
|
||||||
|
/* Wait for transmit to complete, before user code is indicated */
|
||||||
|
while(!(obj->spi.spi->STATUS & USART_STATUS_TXC));
|
||||||
unblockSleepMode(SPI_LEAST_ACTIVE_SLEEPMODE);
|
unblockSleepMode(SPI_LEAST_ACTIVE_SLEEPMODE);
|
||||||
|
|
||||||
/* Return the event back to userland */
|
/* Return the event back to userland */
|
||||||
|
|
Loading…
Reference in New Issue