mirror of https://github.com/ARMmbed/mbed-os.git
Merge branch 'master' of https://github.com/mbedmicro/mbed
commit
b8909ae27d
|
@ -85,6 +85,10 @@
|
|||
#define EPINT_IN (EP4IN)
|
||||
#define EPINT_OUT_callback EP3_OUT_callback
|
||||
#define EPINT_IN_callback EP4_IN_callback
|
||||
/* Isochronous endpoints */
|
||||
/* NOT SUPPORTED - use invalid endpoint number to prevent built errors */
|
||||
#define EPISO_OUT (EP0OUT)
|
||||
#define EPISO_IN (EP0IN)
|
||||
|
||||
#define MAX_PACKET_SIZE_EPBULK (64)
|
||||
#define MAX_PACKET_SIZE_EPINT (64)
|
||||
|
|
|
@ -60,7 +60,7 @@ public:
|
|||
Ticker() : TimerEvent() {
|
||||
}
|
||||
|
||||
Ticker(const ticker_data_t *const data) : TimerEvent(data) {
|
||||
Ticker(const ticker_data_t *data) : TimerEvent(data) {
|
||||
}
|
||||
|
||||
/** Attach a function to be called by the Ticker, specifiying the interval in seconds
|
||||
|
|
|
@ -46,7 +46,7 @@ class Timer {
|
|||
|
||||
public:
|
||||
Timer();
|
||||
Timer(const ticker_data_t *const data);
|
||||
Timer(const ticker_data_t *data);
|
||||
|
||||
/** Start the timer
|
||||
*/
|
||||
|
@ -83,7 +83,7 @@ protected:
|
|||
int _running; // whether the timer is running
|
||||
unsigned int _start; // the start time of the latest slice
|
||||
int _time; // any accumulated time from previous slices
|
||||
const ticker_data_t *const _ticker_data;
|
||||
const ticker_data_t *_ticker_data;
|
||||
};
|
||||
|
||||
} // namespace mbed
|
||||
|
|
|
@ -47,7 +47,7 @@ protected:
|
|||
|
||||
ticker_event_t event;
|
||||
|
||||
const ticker_data_t *const _ticker_data;
|
||||
const ticker_data_t *_ticker_data;
|
||||
};
|
||||
|
||||
} // namespace mbed
|
||||
|
|
|
@ -23,7 +23,7 @@ Timer::Timer() : _running(), _start(), _time(), _ticker_data(get_us_ticker_data(
|
|||
reset();
|
||||
}
|
||||
|
||||
Timer::Timer(const ticker_data_t *const data) : _running(), _start(), _time(), _ticker_data(data) {
|
||||
Timer::Timer(const ticker_data_t *data) : _running(), _start(), _time(), _ticker_data(data) {
|
||||
reset();
|
||||
}
|
||||
|
||||
|
|
|
@ -170,10 +170,10 @@ typedef enum {
|
|||
AOUT_CO = (0xF << PORT_SHIFT) | 2,
|
||||
AOUT_DO = (0xF << PORT_SHIFT) | 3,
|
||||
|
||||
LED_GREEN = P7_4,
|
||||
LED_RED = P7_0,
|
||||
LED_YELLOW = P6_6,
|
||||
LED_BLUE = P7_6,
|
||||
LED_GREEN = P6_6,
|
||||
LED_RED = P7_1,
|
||||
LED_YELLOW = P7_0,
|
||||
LED_BLUE = P6_7,
|
||||
|
||||
// mbed original LED naming
|
||||
LED1 = LED_RED,
|
||||
|
|
|
@ -115,7 +115,7 @@ void spi_format(spi_t *obj, int bits, int mode, int slave)
|
|||
void spi_frequency(spi_t *obj, int hz)
|
||||
{
|
||||
// Maximum frequency is half the system frequency
|
||||
MBED_ASSERT((unsigned int)hz < (SystemCoreClock / 2));
|
||||
MBED_ASSERT((unsigned int)hz <= (SystemCoreClock / 2));
|
||||
unsigned clocks = ((SystemCoreClock/2)/(hz));
|
||||
|
||||
// Figure out the divider ratio
|
||||
|
|
|
@ -115,7 +115,7 @@ void spi_format(spi_t *obj, int bits, int mode, int slave)
|
|||
void spi_frequency(spi_t *obj, int hz)
|
||||
{
|
||||
// Maximum frequency is half the system frequency
|
||||
MBED_ASSERT((unsigned int)hz < (SystemCoreClock / 2));
|
||||
MBED_ASSERT((unsigned int)hz <= (SystemCoreClock / 2));
|
||||
unsigned clocks = ((SystemCoreClock/2)/(hz));
|
||||
|
||||
// Figure out the divider ratio
|
||||
|
|
|
@ -87,134 +87,134 @@ const PinMap PinMap_PWM[] = {
|
|||
|
||||
/*************SPI**************/
|
||||
const PinMap PinMap_SPI_MOSI[] = {
|
||||
/* USART0 */
|
||||
{PE10, SPI_0, 0},
|
||||
{PE7, SPI_0, 1},
|
||||
{PC11, SPI_0, 2},
|
||||
{PC0, SPI_0, 5},
|
||||
/* USART1 */
|
||||
{PD0, SPI_1, 1},
|
||||
{PD7, SPI_1, 2},
|
||||
/* USART2 */
|
||||
{PC2, SPI_2, 0},
|
||||
{PB3, SPI_2, 1},
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
/* USART0 */
|
||||
{PE10, SPI_0, 0},
|
||||
{PE7, SPI_0, 1},
|
||||
{PC11, SPI_0, 2},
|
||||
{PC0, SPI_0, 5},
|
||||
/* USART1 */
|
||||
{PD0, SPI_1, 1},
|
||||
{PD7, SPI_1, 2},
|
||||
/* USART2 */
|
||||
{PC2, SPI_2, 0},
|
||||
{PB3, SPI_2, 1},
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
};
|
||||
|
||||
const PinMap PinMap_SPI_MISO[] = {
|
||||
/* USART0 */
|
||||
{PE11, SPI_0, 0},
|
||||
{PE6, SPI_0, 1},
|
||||
{PC10, SPI_0, 2},
|
||||
{PC1, SPI_0, 5},
|
||||
/* USART1 */
|
||||
{PD1, SPI_1, 1},
|
||||
{PD6, SPI_1, 2},
|
||||
/* USART2 */
|
||||
{PC3, SPI_2, 0},
|
||||
{PB4, SPI_2, 1},
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
/* USART0 */
|
||||
{PE11, SPI_0, 0},
|
||||
{PE6, SPI_0, 1},
|
||||
{PC10, SPI_0, 2},
|
||||
{PC1, SPI_0, 5},
|
||||
/* USART1 */
|
||||
{PD1, SPI_1, 1},
|
||||
{PD6, SPI_1, 2},
|
||||
/* USART2 */
|
||||
{PC3, SPI_2, 0},
|
||||
{PB4, SPI_2, 1},
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
};
|
||||
|
||||
const PinMap PinMap_SPI_CLK[] = {
|
||||
/* USART0 */
|
||||
{PE12, SPI_0, 0},
|
||||
{PE5, SPI_0, 1},
|
||||
{PC9, SPI_0, 2},
|
||||
{PB13, SPI_0, 5},
|
||||
/* USART1 */
|
||||
{PD2, SPI_1, 1},
|
||||
{PF0, SPI_1, 2},
|
||||
/* USART2 */
|
||||
{PC4, SPI_2, 0},
|
||||
{PB5, SPI_2, 1},
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
/* USART0 */
|
||||
{PE12, SPI_0, 0},
|
||||
{PE5, SPI_0, 1},
|
||||
{PC9, SPI_0, 2},
|
||||
{PB13, SPI_0, 5},
|
||||
/* USART1 */
|
||||
{PD2, SPI_1, 1},
|
||||
{PF0, SPI_1, 2},
|
||||
/* USART2 */
|
||||
{PC4, SPI_2, 0},
|
||||
{PB5, SPI_2, 1},
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
};
|
||||
|
||||
const PinMap PinMap_SPI_CS[] = {
|
||||
/* USART0 */
|
||||
{PE13, SPI_0, 0},
|
||||
{PE4, SPI_0, 1},
|
||||
{PC8, SPI_0, 2},
|
||||
{PB14, SPI_0, 5},
|
||||
/* USART1 */
|
||||
{PD3, SPI_1, 1},
|
||||
{PF1, SPI_1, 2},
|
||||
/* USART2 */
|
||||
{PC5, SPI_2, 0},
|
||||
{PB6, SPI_2, 1},
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
/* USART0 */
|
||||
{PE13, SPI_0, 0},
|
||||
{PE4, SPI_0, 1},
|
||||
{PC8, SPI_0, 2},
|
||||
{PB14, SPI_0, 5},
|
||||
/* USART1 */
|
||||
{PD3, SPI_1, 1},
|
||||
{PF1, SPI_1, 2},
|
||||
/* USART2 */
|
||||
{PC5, SPI_2, 0},
|
||||
{PB6, SPI_2, 1},
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
};
|
||||
|
||||
/************UART**************/
|
||||
const PinMap PinMap_UART_TX[] = {
|
||||
/* UART0 */
|
||||
{PF6, UART_0, 0},
|
||||
{PE0, UART_0, 1},
|
||||
/* UART1 */
|
||||
{PF10, UART_1, 1},
|
||||
{PB9, UART_1, 2},
|
||||
{PE2, UART_1, 3},
|
||||
/* USART0 */
|
||||
{PE10, USART_0, 0},
|
||||
{PE7, USART_0, 1},
|
||||
{PC11, USART_0, 2},
|
||||
{PE13, USART_0, 3},
|
||||
{PB7, USART_0, 4},
|
||||
/* USART1 */
|
||||
{PC0, USART_1, 0},
|
||||
{PD0, USART_1, 1},
|
||||
{PD7, USART_1, 2},
|
||||
/* USART2 */
|
||||
{PC2, USART_2, 0},
|
||||
{PB3, USART_2, 1},
|
||||
/* LEUART0 */
|
||||
{PD4, LEUART_0, 0},
|
||||
{PB13, LEUART_0, 1},
|
||||
{PE14, LEUART_0, 2},
|
||||
{PF0, LEUART_0, 3},
|
||||
{PF2, LEUART_0, 4},
|
||||
/* LEUART1 */
|
||||
{PC6, LEUART_1, 0},
|
||||
{PA5, LEUART_1, 1},
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
/* UART0 */
|
||||
{PF6, UART_0, 0},
|
||||
{PE0, UART_0, 1},
|
||||
/* UART1 */
|
||||
{PF10, UART_1, 1},
|
||||
{PB9, UART_1, 2},
|
||||
{PE2, UART_1, 3},
|
||||
/* USART0 */
|
||||
{PE10, USART_0, 0},
|
||||
{PE7, USART_0, 1},
|
||||
{PC11, USART_0, 2},
|
||||
{PE13, USART_0, 3},
|
||||
{PB7, USART_0, 4},
|
||||
/* USART1 */
|
||||
{PC0, USART_1, 0},
|
||||
{PD0, USART_1, 1},
|
||||
{PD7, USART_1, 2},
|
||||
/* USART2 */
|
||||
{PC2, USART_2, 0},
|
||||
{PB3, USART_2, 1},
|
||||
/* LEUART0 */
|
||||
{PD4, LEUART_0, 0},
|
||||
{PB13, LEUART_0, 1},
|
||||
{PE14, LEUART_0, 2},
|
||||
{PF0, LEUART_0, 3},
|
||||
{PF2, LEUART_0, 4},
|
||||
/* LEUART1 */
|
||||
{PC6, LEUART_1, 0},
|
||||
{PA5, LEUART_1, 1},
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
};
|
||||
|
||||
const PinMap PinMap_UART_RX[] = {
|
||||
/* UART0 */
|
||||
{PF7, UART_0, 0},
|
||||
{PE1, UART_0, 1},
|
||||
/* UART1 */
|
||||
{PF11, UART_1, 1},
|
||||
{PB10, UART_1, 2},
|
||||
{PE3, UART_1, 3},
|
||||
/* USART0 */
|
||||
{PE11, USART_0, 0},
|
||||
{PE6, USART_0, 1},
|
||||
{PC10, USART_0, 2},
|
||||
{PE12, USART_0, 3},
|
||||
{PB8, USART_0, 4},
|
||||
/* USART1 */
|
||||
{PC1, USART_1, 0},
|
||||
{PD1, USART_1, 1},
|
||||
{PD6, USART_1, 2},
|
||||
/* USART2 */
|
||||
{PC3, USART_2, 0},
|
||||
{PB4, USART_2, 1},
|
||||
/* LEUART0 */
|
||||
{PD5, LEUART_0, 0},
|
||||
{PB14, LEUART_0, 1},
|
||||
{PE15, LEUART_0, 2},
|
||||
{PF1, LEUART_0, 3},
|
||||
{PA0, LEUART_0, 4},
|
||||
/* LEUART1 */
|
||||
{PC7, LEUART_1, 0},
|
||||
{PA6, LEUART_1, 1},
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
/* UART0 */
|
||||
{PF7, UART_0, 0},
|
||||
{PE1, UART_0, 1},
|
||||
/* UART1 */
|
||||
{PF11, UART_1, 1},
|
||||
{PB10, UART_1, 2},
|
||||
{PE3, UART_1, 3},
|
||||
/* USART0 */
|
||||
{PE11, USART_0, 0},
|
||||
{PE6, USART_0, 1},
|
||||
{PC10, USART_0, 2},
|
||||
{PE12, USART_0, 3},
|
||||
{PB8, USART_0, 4},
|
||||
/* USART1 */
|
||||
{PC1, USART_1, 0},
|
||||
{PD1, USART_1, 1},
|
||||
{PD6, USART_1, 2},
|
||||
/* USART2 */
|
||||
{PC3, USART_2, 0},
|
||||
{PB4, USART_2, 1},
|
||||
/* LEUART0 */
|
||||
{PD5, LEUART_0, 0},
|
||||
{PB14, LEUART_0, 1},
|
||||
{PE15, LEUART_0, 2},
|
||||
{PF1, LEUART_0, 3},
|
||||
{PA0, LEUART_0, 4},
|
||||
/* LEUART1 */
|
||||
{PC7, LEUART_1, 0},
|
||||
{PA6, LEUART_1, 1},
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
};
|
||||
|
|
|
@ -60,109 +60,109 @@ const PinMap PinMap_PWM[] = {
|
|||
|
||||
/*************SPI**************/
|
||||
const PinMap PinMap_SPI_MOSI[] = {
|
||||
/* USART0 */
|
||||
{PE10, SPI_0, 0},
|
||||
//{NC, SPI_0, 2}, /* SPI_0 loc2 is not bonded */
|
||||
{PE13, SPI_0, 3},
|
||||
{PB7, SPI_0, 4},
|
||||
/* USART0 */
|
||||
{PE10, SPI_0, 0},
|
||||
//{NC, SPI_0, 2}, /* SPI_0 loc2 is not bonded */
|
||||
{PE13, SPI_0, 3},
|
||||
{PB7, SPI_0, 4},
|
||||
|
||||
/* USART1 */
|
||||
{PC0, SPI_1, 0},
|
||||
{PD7, SPI_1, 3},
|
||||
{PF2, SPI_1, 4},
|
||||
/* USART1 */
|
||||
{PC0, SPI_1, 0},
|
||||
{PD7, SPI_1, 3},
|
||||
{PF2, SPI_1, 4},
|
||||
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
};
|
||||
|
||||
const PinMap PinMap_SPI_MISO[] = {
|
||||
/* USART0 */
|
||||
{PE11, SPI_0, 0},
|
||||
{PC10, SPI_0, 2},
|
||||
{PE12, SPI_0, 3},
|
||||
{PB8, SPI_0, 4},
|
||||
/* USART0 */
|
||||
{PE11, SPI_0, 0},
|
||||
{PC10, SPI_0, 2},
|
||||
{PE12, SPI_0, 3},
|
||||
{PB8, SPI_0, 4},
|
||||
|
||||
/* USART1 */
|
||||
{PC1, SPI_1, 0},
|
||||
{PD6, SPI_1, 3},
|
||||
{PA0, SPI_1, 4},
|
||||
/* USART1 */
|
||||
{PC1, SPI_1, 0},
|
||||
{PD6, SPI_1, 3},
|
||||
{PA0, SPI_1, 4},
|
||||
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
};
|
||||
|
||||
const PinMap PinMap_SPI_CLK[] = {
|
||||
/* USART0 */
|
||||
{PE12, SPI_0, 0},
|
||||
{PC9, SPI_0, 2},
|
||||
//{PC15, SPI_0, 3}, /* Conflict with SPI_0 loc4 */
|
||||
{PB13, SPI_0, 4},
|
||||
/* USART0 */
|
||||
{PE12, SPI_0, 0},
|
||||
{PC9, SPI_0, 2},
|
||||
//{PC15, SPI_0, 3}, /* Conflict with SPI_0 loc4 */
|
||||
{PB13, SPI_0, 4},
|
||||
|
||||
/* USART1 */
|
||||
{PB7, SPI_1, 0},
|
||||
{PC15, SPI_1, 3},
|
||||
{PB11, SPI_1, 4},
|
||||
/* USART1 */
|
||||
{PB7, SPI_1, 0},
|
||||
{PC15, SPI_1, 3},
|
||||
{PB11, SPI_1, 4},
|
||||
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
};
|
||||
|
||||
const PinMap PinMap_SPI_CS[] = {
|
||||
/* USART0 */
|
||||
{PE13, SPI_0, 0},
|
||||
{PC8, SPI_0, 2},
|
||||
//{PC14, SPI_0, 3}, /* Conflict with SPI_1 loc3 */
|
||||
{PB14, SPI_0, 4},
|
||||
/* USART0 */
|
||||
{PE13, SPI_0, 0},
|
||||
{PC8, SPI_0, 2},
|
||||
//{PC14, SPI_0, 3}, /* Conflict with SPI_1 loc3 */
|
||||
{PB14, SPI_0, 4},
|
||||
|
||||
/* USART1 */
|
||||
{PB8, SPI_1, 0},
|
||||
{PC14, SPI_1, 3},
|
||||
/* USART1 */
|
||||
{PB8, SPI_1, 0},
|
||||
{PC14, SPI_1, 3},
|
||||
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
};
|
||||
|
||||
/************UART**************/
|
||||
const PinMap PinMap_UART_TX[] = {
|
||||
/* USART0 */
|
||||
{PE10, USART_0, 0},
|
||||
//{NC, USART_0, 2}, /* USART_0 loc2 is not bonded */
|
||||
{PE13, USART_0, 3},
|
||||
{PB7, USART_0, 4},
|
||||
/* USART0 */
|
||||
{PE10, USART_0, 0},
|
||||
//{NC, USART_0, 2}, /* USART_0 loc2 is not bonded */
|
||||
{PE13, USART_0, 3},
|
||||
{PB7, USART_0, 4},
|
||||
|
||||
/* USART1 */
|
||||
{PC0, USART_1, 0},
|
||||
{PD7, USART_1, 3},
|
||||
{PF2, USART_1, 4},
|
||||
/* USART1 */
|
||||
{PC0, USART_1, 0},
|
||||
{PD7, USART_1, 3},
|
||||
{PF2, USART_1, 4},
|
||||
|
||||
/* LEUART0 */
|
||||
{PD4, LEUART_0, 0},
|
||||
{PB13, LEUART_0, 1},
|
||||
{PF0, LEUART_0, 3},
|
||||
{PC14, LEUART_0, 5},
|
||||
/* LEUART0 */
|
||||
{PD4, LEUART_0, 0},
|
||||
{PB13, LEUART_0, 1},
|
||||
{PF0, LEUART_0, 3},
|
||||
{PC14, LEUART_0, 5},
|
||||
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
};
|
||||
|
||||
const PinMap PinMap_UART_RX[] = {
|
||||
/* USART0 */
|
||||
{PE11, USART_0, 0},
|
||||
//{PC10, USART_0, 2},
|
||||
{PE12, USART_0, 3},
|
||||
{PB8, USART_0, 4},
|
||||
/* USART0 */
|
||||
{PE11, USART_0, 0},
|
||||
//{PC10, USART_0, 2},
|
||||
{PE12, USART_0, 3},
|
||||
{PB8, USART_0, 4},
|
||||
|
||||
/* USART1 */
|
||||
{PC1, USART_1, 0},
|
||||
{PD6, USART_1, 3},
|
||||
{PA0, USART_1, 4},
|
||||
/* USART1 */
|
||||
{PC1, USART_1, 0},
|
||||
{PD6, USART_1, 3},
|
||||
{PA0, USART_1, 4},
|
||||
|
||||
/* LEUART0 */
|
||||
{PD5, LEUART_0, 0},
|
||||
{PB14, LEUART_0, 1},
|
||||
{PF1, LEUART_0, 3},
|
||||
{PC15, LEUART_0, 5},
|
||||
/* LEUART0 */
|
||||
{PD5, LEUART_0, 0},
|
||||
{PB14, LEUART_0, 1},
|
||||
{PF1, LEUART_0, 3},
|
||||
{PC15, LEUART_0, 5},
|
||||
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
};
|
||||
|
|
|
@ -87,134 +87,134 @@ const PinMap PinMap_PWM[] = {
|
|||
|
||||
/*************SPI**************/
|
||||
const PinMap PinMap_SPI_MOSI[] = {
|
||||
/* USART0 */
|
||||
{PE10, SPI_0, 0},
|
||||
{PE7, SPI_0, 1},
|
||||
{PC11, SPI_0, 2},
|
||||
{PC0, SPI_0, 5},
|
||||
/* USART1 */
|
||||
{PD0, SPI_1, 1},
|
||||
{PD7, SPI_1, 2},
|
||||
/* USART2 */
|
||||
{PC2, SPI_2, 0},
|
||||
{PB3, SPI_2, 1},
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
/* USART0 */
|
||||
{PE10, SPI_0, 0},
|
||||
{PE7, SPI_0, 1},
|
||||
{PC11, SPI_0, 2},
|
||||
{PC0, SPI_0, 5},
|
||||
/* USART1 */
|
||||
{PD0, SPI_1, 1},
|
||||
{PD7, SPI_1, 2},
|
||||
/* USART2 */
|
||||
{PC2, SPI_2, 0},
|
||||
{PB3, SPI_2, 1},
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
};
|
||||
|
||||
const PinMap PinMap_SPI_MISO[] = {
|
||||
/* USART0 */
|
||||
{PE11, SPI_0, 0},
|
||||
{PE6, SPI_0, 1},
|
||||
{PC10, SPI_0, 2},
|
||||
{PC1, SPI_0, 5},
|
||||
/* USART1 */
|
||||
{PD1, SPI_1, 1},
|
||||
{PD6, SPI_1, 2},
|
||||
/* USART2 */
|
||||
{PC3, SPI_2, 0},
|
||||
{PB4, SPI_2, 1},
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
/* USART0 */
|
||||
{PE11, SPI_0, 0},
|
||||
{PE6, SPI_0, 1},
|
||||
{PC10, SPI_0, 2},
|
||||
{PC1, SPI_0, 5},
|
||||
/* USART1 */
|
||||
{PD1, SPI_1, 1},
|
||||
{PD6, SPI_1, 2},
|
||||
/* USART2 */
|
||||
{PC3, SPI_2, 0},
|
||||
{PB4, SPI_2, 1},
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
};
|
||||
|
||||
const PinMap PinMap_SPI_CLK[] = {
|
||||
/* USART0 */
|
||||
{PE12, SPI_0, 0},
|
||||
{PE5, SPI_0, 1},
|
||||
{PC9, SPI_0, 2},
|
||||
{PB13, SPI_0, 5},
|
||||
/* USART1 */
|
||||
{PD2, SPI_1, 1},
|
||||
{PF0, SPI_1, 2},
|
||||
/* USART2 */
|
||||
{PC4, SPI_2, 0},
|
||||
{PB5, SPI_2, 1},
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
/* USART0 */
|
||||
{PE12, SPI_0, 0},
|
||||
{PE5, SPI_0, 1},
|
||||
{PC9, SPI_0, 2},
|
||||
{PB13, SPI_0, 5},
|
||||
/* USART1 */
|
||||
{PD2, SPI_1, 1},
|
||||
{PF0, SPI_1, 2},
|
||||
/* USART2 */
|
||||
{PC4, SPI_2, 0},
|
||||
{PB5, SPI_2, 1},
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
};
|
||||
|
||||
const PinMap PinMap_SPI_CS[] = {
|
||||
/* USART0 */
|
||||
{PE13, SPI_0, 0},
|
||||
{PE4, SPI_0, 1},
|
||||
{PC8, SPI_0, 2},
|
||||
{PB14, SPI_0, 5},
|
||||
/* USART1 */
|
||||
{PD3, SPI_1, 1},
|
||||
{PF1, SPI_1, 2},
|
||||
/* USART2 */
|
||||
{PC5, SPI_2, 0},
|
||||
{PB6, SPI_2, 1},
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
/* USART0 */
|
||||
{PE13, SPI_0, 0},
|
||||
{PE4, SPI_0, 1},
|
||||
{PC8, SPI_0, 2},
|
||||
{PB14, SPI_0, 5},
|
||||
/* USART1 */
|
||||
{PD3, SPI_1, 1},
|
||||
{PF1, SPI_1, 2},
|
||||
/* USART2 */
|
||||
{PC5, SPI_2, 0},
|
||||
{PB6, SPI_2, 1},
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
};
|
||||
|
||||
/************UART**************/
|
||||
const PinMap PinMap_UART_TX[] = {
|
||||
/* UART0 */
|
||||
{PF6, UART_0, 0},
|
||||
{PE0, UART_0, 1},
|
||||
/* UART1 */
|
||||
{PF10, UART_1, 1},
|
||||
{PB9, UART_1, 2},
|
||||
{PE2, UART_1, 3},
|
||||
/* USART0 */
|
||||
{PE10, USART_0, 0},
|
||||
{PE7, USART_0, 1},
|
||||
{PC11, USART_0, 2},
|
||||
{PE13, USART_0, 3},
|
||||
{PB7, USART_0, 4},
|
||||
/* USART1 */
|
||||
{PC0, USART_1, 0},
|
||||
{PD0, USART_1, 1},
|
||||
{PD7, USART_1, 2},
|
||||
/* USART2 */
|
||||
{PC2, USART_2, 0},
|
||||
{PB3, USART_2, 1},
|
||||
/* LEUART0 */
|
||||
{PD4, LEUART_0, 0},
|
||||
{PB13, LEUART_0, 1},
|
||||
{PE14, LEUART_0, 2},
|
||||
{PF0, LEUART_0, 3},
|
||||
{PF2, LEUART_0, 4},
|
||||
/* LEUART1 */
|
||||
{PC6, LEUART_1, 0},
|
||||
{PA5, LEUART_1, 1},
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
/* UART0 */
|
||||
{PF6, UART_0, 0},
|
||||
{PE0, UART_0, 1},
|
||||
/* UART1 */
|
||||
{PF10, UART_1, 1},
|
||||
{PB9, UART_1, 2},
|
||||
{PE2, UART_1, 3},
|
||||
/* USART0 */
|
||||
{PE10, USART_0, 0},
|
||||
{PE7, USART_0, 1},
|
||||
{PC11, USART_0, 2},
|
||||
{PE13, USART_0, 3},
|
||||
{PB7, USART_0, 4},
|
||||
/* USART1 */
|
||||
{PC0, USART_1, 0},
|
||||
{PD0, USART_1, 1},
|
||||
{PD7, USART_1, 2},
|
||||
/* USART2 */
|
||||
{PC2, USART_2, 0},
|
||||
{PB3, USART_2, 1},
|
||||
/* LEUART0 */
|
||||
{PD4, LEUART_0, 0},
|
||||
{PB13, LEUART_0, 1},
|
||||
{PE14, LEUART_0, 2},
|
||||
{PF0, LEUART_0, 3},
|
||||
{PF2, LEUART_0, 4},
|
||||
/* LEUART1 */
|
||||
{PC6, LEUART_1, 0},
|
||||
{PA5, LEUART_1, 1},
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
};
|
||||
|
||||
const PinMap PinMap_UART_RX[] = {
|
||||
/* UART0 */
|
||||
{PF7, UART_0, 0},
|
||||
{PE1, UART_0, 1},
|
||||
/* UART1 */
|
||||
{PF11, UART_1, 1},
|
||||
{PB10, UART_1, 2},
|
||||
{PE3, UART_1, 3},
|
||||
/* USART0 */
|
||||
{PE11, USART_0, 0},
|
||||
{PE6, USART_0, 1},
|
||||
{PC10, USART_0, 2},
|
||||
{PE12, USART_0, 3},
|
||||
{PB8, USART_0, 4},
|
||||
/* USART1 */
|
||||
{PC1, USART_1, 0},
|
||||
{PD1, USART_1, 1},
|
||||
{PD6, USART_1, 2},
|
||||
/* USART2 */
|
||||
{PC3, USART_2, 0},
|
||||
{PB4, USART_2, 1},
|
||||
/* LEUART0 */
|
||||
{PD5, LEUART_0, 0},
|
||||
{PB14, LEUART_0, 1},
|
||||
{PE15, LEUART_0, 2},
|
||||
{PF1, LEUART_0, 3},
|
||||
{PA0, LEUART_0, 4},
|
||||
/* LEUART1 */
|
||||
{PC7, LEUART_1, 0},
|
||||
{PA6, LEUART_1, 1},
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
/* UART0 */
|
||||
{PF7, UART_0, 0},
|
||||
{PE1, UART_0, 1},
|
||||
/* UART1 */
|
||||
{PF11, UART_1, 1},
|
||||
{PB10, UART_1, 2},
|
||||
{PE3, UART_1, 3},
|
||||
/* USART0 */
|
||||
{PE11, USART_0, 0},
|
||||
{PE6, USART_0, 1},
|
||||
{PC10, USART_0, 2},
|
||||
{PE12, USART_0, 3},
|
||||
{PB8, USART_0, 4},
|
||||
/* USART1 */
|
||||
{PC1, USART_1, 0},
|
||||
{PD1, USART_1, 1},
|
||||
{PD6, USART_1, 2},
|
||||
/* USART2 */
|
||||
{PC3, USART_2, 0},
|
||||
{PB4, USART_2, 1},
|
||||
/* LEUART0 */
|
||||
{PD5, LEUART_0, 0},
|
||||
{PB14, LEUART_0, 1},
|
||||
{PE15, LEUART_0, 2},
|
||||
{PF1, LEUART_0, 3},
|
||||
{PA0, LEUART_0, 4},
|
||||
/* LEUART1 */
|
||||
{PC7, LEUART_1, 0},
|
||||
{PA6, LEUART_1, 1},
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
};
|
||||
|
|
|
@ -92,8 +92,8 @@ typedef enum {
|
|||
/* mbed modes:
|
||||
* PullUp, PullDown, PullNone, OpenDrain
|
||||
*
|
||||
* mbed default digital input mode:
|
||||
* PullDefault
|
||||
* mbed default digital input mode:
|
||||
* PullDefault
|
||||
*
|
||||
* mbed default digital output mode:
|
||||
* PullNone
|
||||
|
|
|
@ -87,134 +87,134 @@ const PinMap PinMap_PWM[] = {
|
|||
|
||||
/*************SPI**************/
|
||||
const PinMap PinMap_SPI_MOSI[] = {
|
||||
/* USART0 */
|
||||
{PE10, SPI_0, 0},
|
||||
{PE7, SPI_0, 1},
|
||||
{PC11, SPI_0, 2},
|
||||
{PC0, SPI_0, 5},
|
||||
/* USART1 */
|
||||
{PD0, SPI_1, 1},
|
||||
{PD7, SPI_1, 2},
|
||||
/* USART2 */
|
||||
{PC2, SPI_2, 0},
|
||||
{PB3, SPI_2, 1},
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
/* USART0 */
|
||||
{PE10, SPI_0, 0},
|
||||
{PE7, SPI_0, 1},
|
||||
{PC11, SPI_0, 2},
|
||||
{PC0, SPI_0, 5},
|
||||
/* USART1 */
|
||||
{PD0, SPI_1, 1},
|
||||
{PD7, SPI_1, 2},
|
||||
/* USART2 */
|
||||
{PC2, SPI_2, 0},
|
||||
{PB3, SPI_2, 1},
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
};
|
||||
|
||||
const PinMap PinMap_SPI_MISO[] = {
|
||||
/* USART0 */
|
||||
{PE11, SPI_0, 0},
|
||||
{PE6, SPI_0, 1},
|
||||
{PC10, SPI_0, 2},
|
||||
{PC1, SPI_0, 5},
|
||||
/* USART1 */
|
||||
{PD1, SPI_1, 1},
|
||||
{PD6, SPI_1, 2},
|
||||
/* USART2 */
|
||||
{PC3, SPI_2, 0},
|
||||
{PB4, SPI_2, 1},
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
/* USART0 */
|
||||
{PE11, SPI_0, 0},
|
||||
{PE6, SPI_0, 1},
|
||||
{PC10, SPI_0, 2},
|
||||
{PC1, SPI_0, 5},
|
||||
/* USART1 */
|
||||
{PD1, SPI_1, 1},
|
||||
{PD6, SPI_1, 2},
|
||||
/* USART2 */
|
||||
{PC3, SPI_2, 0},
|
||||
{PB4, SPI_2, 1},
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
};
|
||||
|
||||
const PinMap PinMap_SPI_CLK[] = {
|
||||
/* USART0 */
|
||||
{PE12, SPI_0, 0},
|
||||
{PE5, SPI_0, 1},
|
||||
{PC9, SPI_0, 2},
|
||||
{PB13, SPI_0, 5},
|
||||
/* USART1 */
|
||||
{PD2, SPI_1, 1},
|
||||
{PF0, SPI_1, 2},
|
||||
/* USART2 */
|
||||
{PC4, SPI_2, 0},
|
||||
{PB5, SPI_2, 1},
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
/* USART0 */
|
||||
{PE12, SPI_0, 0},
|
||||
{PE5, SPI_0, 1},
|
||||
{PC9, SPI_0, 2},
|
||||
{PB13, SPI_0, 5},
|
||||
/* USART1 */
|
||||
{PD2, SPI_1, 1},
|
||||
{PF0, SPI_1, 2},
|
||||
/* USART2 */
|
||||
{PC4, SPI_2, 0},
|
||||
{PB5, SPI_2, 1},
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
};
|
||||
|
||||
const PinMap PinMap_SPI_CS[] = {
|
||||
/* USART0 */
|
||||
{PE13, SPI_0, 0},
|
||||
{PE4, SPI_0, 1},
|
||||
{PC8, SPI_0, 2},
|
||||
{PB14, SPI_0, 5},
|
||||
/* USART1 */
|
||||
{PD3, SPI_1, 1},
|
||||
{PF1, SPI_1, 2},
|
||||
/* USART2 */
|
||||
{PC5, SPI_2, 0},
|
||||
{PB6, SPI_2, 1},
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
/* USART0 */
|
||||
{PE13, SPI_0, 0},
|
||||
{PE4, SPI_0, 1},
|
||||
{PC8, SPI_0, 2},
|
||||
{PB14, SPI_0, 5},
|
||||
/* USART1 */
|
||||
{PD3, SPI_1, 1},
|
||||
{PF1, SPI_1, 2},
|
||||
/* USART2 */
|
||||
{PC5, SPI_2, 0},
|
||||
{PB6, SPI_2, 1},
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
};
|
||||
|
||||
/************UART**************/
|
||||
const PinMap PinMap_UART_TX[] = {
|
||||
/* UART0 */
|
||||
{PF6, UART_0, 0},
|
||||
{PE0, UART_0, 1},
|
||||
/* UART1 */
|
||||
{PF10, UART_1, 1},
|
||||
{PB9, UART_1, 2},
|
||||
{PE2, UART_1, 3},
|
||||
/* USART0 */
|
||||
{PE10, USART_0, 0},
|
||||
{PE7, USART_0, 1},
|
||||
{PC11, USART_0, 2},
|
||||
{PE13, USART_0, 3},
|
||||
{PB7, USART_0, 4},
|
||||
/* USART1 */
|
||||
{PC0, USART_1, 0},
|
||||
{PD0, USART_1, 1},
|
||||
{PD7, USART_1, 2},
|
||||
/* USART2 */
|
||||
{PC2, USART_2, 0},
|
||||
{PB3, USART_2, 1},
|
||||
/* LEUART0 */
|
||||
{PD4, LEUART_0, 0},
|
||||
{PB13, LEUART_0, 1},
|
||||
{PE14, LEUART_0, 2},
|
||||
{PF0, LEUART_0, 3},
|
||||
{PF2, LEUART_0, 4},
|
||||
/* LEUART1 */
|
||||
{PC6, LEUART_1, 0},
|
||||
{PA5, LEUART_1, 1},
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
/* UART0 */
|
||||
{PF6, UART_0, 0},
|
||||
{PE0, UART_0, 1},
|
||||
/* UART1 */
|
||||
{PF10, UART_1, 1},
|
||||
{PB9, UART_1, 2},
|
||||
{PE2, UART_1, 3},
|
||||
/* USART0 */
|
||||
{PE10, USART_0, 0},
|
||||
{PE7, USART_0, 1},
|
||||
{PC11, USART_0, 2},
|
||||
{PE13, USART_0, 3},
|
||||
{PB7, USART_0, 4},
|
||||
/* USART1 */
|
||||
{PC0, USART_1, 0},
|
||||
{PD0, USART_1, 1},
|
||||
{PD7, USART_1, 2},
|
||||
/* USART2 */
|
||||
{PC2, USART_2, 0},
|
||||
{PB3, USART_2, 1},
|
||||
/* LEUART0 */
|
||||
{PD4, LEUART_0, 0},
|
||||
{PB13, LEUART_0, 1},
|
||||
{PE14, LEUART_0, 2},
|
||||
{PF0, LEUART_0, 3},
|
||||
{PF2, LEUART_0, 4},
|
||||
/* LEUART1 */
|
||||
{PC6, LEUART_1, 0},
|
||||
{PA5, LEUART_1, 1},
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
};
|
||||
|
||||
const PinMap PinMap_UART_RX[] = {
|
||||
/* UART0 */
|
||||
{PF7, UART_0, 0},
|
||||
{PE1, UART_0, 1},
|
||||
/* UART1 */
|
||||
{PF11, UART_1, 1},
|
||||
{PB10, UART_1, 2},
|
||||
{PE3, UART_1, 3},
|
||||
/* USART0 */
|
||||
{PE11, USART_0, 0},
|
||||
{PE6, USART_0, 1},
|
||||
{PC10, USART_0, 2},
|
||||
{PE12, USART_0, 3},
|
||||
{PB8, USART_0, 4},
|
||||
/* USART1 */
|
||||
{PC1, USART_1, 0},
|
||||
{PD1, USART_1, 1},
|
||||
{PD6, USART_1, 2},
|
||||
/* USART2 */
|
||||
{PC3, USART_2, 0},
|
||||
{PB4, USART_2, 1},
|
||||
/* LEUART0 */
|
||||
{PD5, LEUART_0, 0},
|
||||
{PB14, LEUART_0, 1},
|
||||
{PE15, LEUART_0, 2},
|
||||
{PF1, LEUART_0, 3},
|
||||
{PA0, LEUART_0, 4},
|
||||
/* LEUART1 */
|
||||
{PC7, LEUART_1, 0},
|
||||
{PA6, LEUART_1, 1},
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
/* UART0 */
|
||||
{PF7, UART_0, 0},
|
||||
{PE1, UART_0, 1},
|
||||
/* UART1 */
|
||||
{PF11, UART_1, 1},
|
||||
{PB10, UART_1, 2},
|
||||
{PE3, UART_1, 3},
|
||||
/* USART0 */
|
||||
{PE11, USART_0, 0},
|
||||
{PE6, USART_0, 1},
|
||||
{PC10, USART_0, 2},
|
||||
{PE12, USART_0, 3},
|
||||
{PB8, USART_0, 4},
|
||||
/* USART1 */
|
||||
{PC1, USART_1, 0},
|
||||
{PD1, USART_1, 1},
|
||||
{PD6, USART_1, 2},
|
||||
/* USART2 */
|
||||
{PC3, USART_2, 0},
|
||||
{PB4, USART_2, 1},
|
||||
/* LEUART0 */
|
||||
{PD5, LEUART_0, 0},
|
||||
{PB14, LEUART_0, 1},
|
||||
{PE15, LEUART_0, 2},
|
||||
{PF1, LEUART_0, 3},
|
||||
{PA0, LEUART_0, 4},
|
||||
/* LEUART1 */
|
||||
{PC7, LEUART_1, 0},
|
||||
{PA6, LEUART_1, 1},
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
};
|
||||
|
|
|
@ -92,8 +92,8 @@ typedef enum {
|
|||
/* mbed modes:
|
||||
* PullUp, PullDown, PullNone, OpenDrain
|
||||
*
|
||||
* mbed default digital input mode:
|
||||
* PullDefault
|
||||
* mbed default digital input mode:
|
||||
* PullDefault
|
||||
*
|
||||
* mbed default digital output mode:
|
||||
* PullNone
|
||||
|
|
|
@ -60,60 +60,60 @@ const PinMap PinMap_PWM[] = {
|
|||
|
||||
/*************SPI**************/
|
||||
const PinMap PinMap_SPI_MOSI[] = {
|
||||
/* USART1 */
|
||||
{PC0, SPI_1, 0},
|
||||
{PD7, SPI_1, 3},
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
/* USART1 */
|
||||
{PC0, SPI_1, 0},
|
||||
{PD7, SPI_1, 3},
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
};
|
||||
|
||||
const PinMap PinMap_SPI_MISO[] = {
|
||||
/* USART1 */
|
||||
{PC1, SPI_1, 0},
|
||||
{PD6, SPI_1, 3},
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
/* USART1 */
|
||||
{PC1, SPI_1, 0},
|
||||
{PD6, SPI_1, 3},
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
};
|
||||
|
||||
const PinMap PinMap_SPI_CLK[] = {
|
||||
/* USART1 */
|
||||
{PB7, SPI_1, 0},
|
||||
{PC15, SPI_1, 3},
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
/* USART1 */
|
||||
{PB7, SPI_1, 0},
|
||||
{PC15, SPI_1, 3},
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
};
|
||||
|
||||
const PinMap PinMap_SPI_CS[] = {
|
||||
/* USART1 */
|
||||
{PB8, SPI_1, 0},
|
||||
{PC14, SPI_1, 3},
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
/* USART1 */
|
||||
{PB8, SPI_1, 0},
|
||||
{PC14, SPI_1, 3},
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
};
|
||||
|
||||
/************UART**************/
|
||||
const PinMap PinMap_UART_TX[] = {
|
||||
/* USART1 */
|
||||
{PC0, USART_1, 0},
|
||||
{PD7, USART_1, 3},
|
||||
/* LEUART0 */
|
||||
{PD4, LEUART_0, 0},
|
||||
{PB13, LEUART_0, 1},
|
||||
{PF0, LEUART_0, 3},
|
||||
{PF2, LEUART_0, 4},
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
/* USART1 */
|
||||
{PC0, USART_1, 0},
|
||||
{PD7, USART_1, 3},
|
||||
/* LEUART0 */
|
||||
{PD4, LEUART_0, 0},
|
||||
{PB13, LEUART_0, 1},
|
||||
{PF0, LEUART_0, 3},
|
||||
{PF2, LEUART_0, 4},
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
};
|
||||
|
||||
const PinMap PinMap_UART_RX[] = {
|
||||
/* USART1 */
|
||||
{PC1, USART_1, 0},
|
||||
{PD6, USART_1, 3},
|
||||
/* LEUART0 */
|
||||
{PD5, LEUART_0, 0},
|
||||
{PB14, LEUART_0, 1},
|
||||
{PF1, LEUART_0, 3},
|
||||
{PA0, LEUART_0, 4},
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
/* USART1 */
|
||||
{PC1, USART_1, 0},
|
||||
{PD6, USART_1, 3},
|
||||
/* LEUART0 */
|
||||
{PD5, LEUART_0, 0},
|
||||
{PB14, LEUART_0, 1},
|
||||
{PF1, LEUART_0, 3},
|
||||
{PA0, LEUART_0, 4},
|
||||
/* Not connected */
|
||||
{NC , NC , NC}
|
||||
};
|
||||
|
|
|
@ -42,7 +42,8 @@ void analogout_preinit(dac_t *obj, PinName pin)
|
|||
MBED_ASSERT((int) obj->channel != NC);
|
||||
}
|
||||
|
||||
void analogout_init(dac_t *obj, PinName pin) {
|
||||
void analogout_init(dac_t *obj, PinName pin)
|
||||
{
|
||||
static uint8_t dac_initialized = 0;
|
||||
|
||||
/* init in-memory structure */
|
||||
|
@ -83,7 +84,8 @@ void analogout_pins_enable(dac_t *obj, uint8_t enable)
|
|||
//not avail for EFM32
|
||||
}
|
||||
|
||||
static inline void dac_write(dac_t *obj, int value) {
|
||||
static inline void dac_write(dac_t *obj, int value)
|
||||
{
|
||||
switch (obj->channel) {
|
||||
case 0:
|
||||
obj->dac->CH0DATA = value;
|
||||
|
@ -94,7 +96,8 @@ static inline void dac_write(dac_t *obj, int value) {
|
|||
}
|
||||
}
|
||||
|
||||
static inline int dac_read(dac_t *obj) {
|
||||
static inline int dac_read(dac_t *obj)
|
||||
{
|
||||
switch (obj->channel) {
|
||||
case 0:
|
||||
return obj->dac->CH0DATA;
|
||||
|
@ -109,23 +112,27 @@ static inline int dac_read(dac_t *obj) {
|
|||
}
|
||||
}
|
||||
|
||||
void analogout_write(dac_t *obj, float value) {
|
||||
void analogout_write(dac_t *obj, float value)
|
||||
{
|
||||
/* We multiply the float value with 0xFFF because the DAC has 12-bit resolution.
|
||||
* Ie. accepts values between 0 and 0xFFF (4096). */
|
||||
dac_write(obj, value*0xFFF);
|
||||
}
|
||||
|
||||
void analogout_write_u16(dac_t *obj, uint16_t value) {
|
||||
void analogout_write_u16(dac_t *obj, uint16_t value)
|
||||
{
|
||||
/* The DAC has 12 bit resolution, so we remove the 4 least significant bits */
|
||||
dac_write(obj, value >> 4);
|
||||
}
|
||||
|
||||
float analogout_read(dac_t *obj) {
|
||||
float analogout_read(dac_t *obj)
|
||||
{
|
||||
/* dac_read returns a number between 0 and 0xFFF. Division gives us a float between 0 and 1 */
|
||||
return dac_read(obj)/(float)0xFFF;
|
||||
}
|
||||
|
||||
uint16_t analogout_read_u16(dac_t *obj) {
|
||||
uint16_t analogout_read_u16(dac_t *obj)
|
||||
{
|
||||
/* dac_read returns a number with 12 significant digits,
|
||||
* so we shift in 0s from right to make it a 16 bit number */
|
||||
return dac_read(obj) << 4;
|
||||
|
|
|
@ -39,55 +39,51 @@ bool enabled = false;
|
|||
|
||||
void dma_init(void)
|
||||
{
|
||||
if (enabled) return;
|
||||
DMA_Init_TypeDef dmaInit;
|
||||
if (enabled) return;
|
||||
DMA_Init_TypeDef dmaInit;
|
||||
|
||||
CMU_ClockEnable(cmuClock_DMA, true);
|
||||
CMU_ClockEnable(cmuClock_HFPER, true);
|
||||
CMU_ClockEnable(cmuClock_DMA, true);
|
||||
CMU_ClockEnable(cmuClock_HFPER, true);
|
||||
|
||||
/* Configure general DMA issues */
|
||||
dmaInit.hprot = 0;
|
||||
dmaInit.controlBlock = dmaControlBlock;
|
||||
DMA_Init(&dmaInit);
|
||||
enabled = true;
|
||||
/* Configure general DMA issues */
|
||||
dmaInit.hprot = 0;
|
||||
dmaInit.controlBlock = dmaControlBlock;
|
||||
DMA_Init(&dmaInit);
|
||||
enabled = true;
|
||||
}
|
||||
|
||||
int dma_channel_allocate(uint32_t capabilities)
|
||||
{
|
||||
int i;
|
||||
// Check if 2d copy is required
|
||||
if (DMA_CAP_2DCOPY & capabilities)
|
||||
{
|
||||
if (channels & 1)
|
||||
{
|
||||
// Channel already in use
|
||||
return DMA_ERROR_OUT_OF_CHANNELS;
|
||||
} else {
|
||||
channels |= 1 << 0;
|
||||
return 0;
|
||||
int i;
|
||||
// Check if 2d copy is required
|
||||
if (DMA_CAP_2DCOPY & capabilities) {
|
||||
if (channels & 1) {
|
||||
// Channel already in use
|
||||
return DMA_ERROR_OUT_OF_CHANNELS;
|
||||
} else {
|
||||
channels |= 1 << 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i = 1; i < DMA_CHAN_COUNT; i++)
|
||||
{
|
||||
if ((channels & (1 << i)) == 0)
|
||||
{
|
||||
// Channel available
|
||||
channels |= 1 << i;
|
||||
return i;
|
||||
for (i = 1; i < DMA_CHAN_COUNT; i++) {
|
||||
if ((channels & (1 << i)) == 0) {
|
||||
// Channel available
|
||||
channels |= 1 << i;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Check if channel 0 is available
|
||||
if ((channels & 1 ) == 0) {
|
||||
channels |= 1 << 0;
|
||||
return 0;
|
||||
}
|
||||
// Couldn't find a channel.
|
||||
return DMA_ERROR_OUT_OF_CHANNELS;
|
||||
// Check if channel 0 is available
|
||||
if ((channels & 1 ) == 0) {
|
||||
channels |= 1 << 0;
|
||||
return 0;
|
||||
}
|
||||
// Couldn't find a channel.
|
||||
return DMA_ERROR_OUT_OF_CHANNELS;
|
||||
}
|
||||
|
||||
int dma_channel_free(int channelid)
|
||||
{
|
||||
channels &= ~(1 << channelid);
|
||||
return 0;
|
||||
channels &= ~(1 << channelid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -46,9 +46,9 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
typedef struct {
|
||||
DMAUsage dmaUsageState;
|
||||
int dmaChannel;
|
||||
DMA_CB_TypeDef dmaCallback;
|
||||
DMAUsage dmaUsageState;
|
||||
int dmaChannel;
|
||||
DMA_CB_TypeDef dmaCallback;
|
||||
} DMA_OPTIONS_t;
|
||||
|
||||
typedef void (*DMACallback)(void);
|
||||
|
|
|
@ -37,9 +37,9 @@
|
|||
#define GPIOINT_MASK2IDX(mask) (countTrailingZeros(mask))
|
||||
__STATIC_INLINE uint32_t countTrailingZeros(uint32_t mask)
|
||||
{
|
||||
uint32_t zeros;
|
||||
for(zeros=0; (zeros<32) && (0 == (mask&0x1)); zeros++, mask>>=1);
|
||||
return zeros;
|
||||
uint32_t zeros;
|
||||
for(zeros=0; (zeros<32) && (0 == (mask&0x1)); zeros++, mask>>=1);
|
||||
return zeros;
|
||||
}
|
||||
#else
|
||||
#error Unsupported architecture.
|
||||
|
@ -85,8 +85,8 @@ void gpio_irq_preinit(gpio_irq_t *obj, PinName pin)
|
|||
|
||||
int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id)
|
||||
{
|
||||
/* Init pins */
|
||||
gpio_irq_preinit(obj, pin);
|
||||
/* Init pins */
|
||||
gpio_irq_preinit(obj, pin);
|
||||
/* Initialize GPIO interrupt dispatcher */
|
||||
NVIC_ClearPendingIRQ(GPIO_ODD_IRQn);
|
||||
NVIC_EnableIRQ(GPIO_ODD_IRQn);
|
||||
|
@ -134,13 +134,13 @@ void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
|
|||
|
||||
GPIO_IntConfig(obj->port, obj->pin, obj->risingEdge, obj->fallingEdge, obj->risingEdge || obj->fallingEdge);
|
||||
if ((GPIO->IEN != 0) && (obj->risingEdge || obj->fallingEdge) && was_disabled) {
|
||||
blockSleepMode(GPIO_LEAST_ACTIVE_SLEEPMODE);
|
||||
blockSleepMode(GPIO_LEAST_ACTIVE_SLEEPMODE);
|
||||
}
|
||||
}
|
||||
|
||||
inline void gpio_irq_enable(gpio_irq_t *obj)
|
||||
{
|
||||
if(GPIO->IEN == 0) blockSleepMode(GPIO_LEAST_ACTIVE_SLEEPMODE);
|
||||
if(GPIO->IEN == 0) blockSleepMode(GPIO_LEAST_ACTIVE_SLEEPMODE);
|
||||
GPIO_IntEnable(1 << obj->pin); // pin mask for pins to enable
|
||||
}
|
||||
|
||||
|
@ -165,19 +165,18 @@ inline void gpio_irq_disable(gpio_irq_t *obj)
|
|||
******************************************************************************/
|
||||
static void GPIOINT_IRQDispatcher(uint32_t iflags)
|
||||
{
|
||||
uint32_t irqIdx;
|
||||
uint32_t irqIdx;
|
||||
|
||||
/* check for all flags set in IF register */
|
||||
while(iflags)
|
||||
{
|
||||
irqIdx = GPIOINT_MASK2IDX(iflags);
|
||||
/* check for all flags set in IF register */
|
||||
while(iflags) {
|
||||
irqIdx = GPIOINT_MASK2IDX(iflags);
|
||||
|
||||
/* clear flag*/
|
||||
iflags &= ~(1 << irqIdx);
|
||||
/* clear flag*/
|
||||
iflags &= ~(1 << irqIdx);
|
||||
|
||||
/* call user callback */
|
||||
handle_interrupt_in(irqIdx);
|
||||
}
|
||||
/* call user callback */
|
||||
handle_interrupt_in(irqIdx);
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
|
@ -188,15 +187,15 @@ static void GPIOINT_IRQDispatcher(uint32_t iflags)
|
|||
******************************************************************************/
|
||||
void GPIO_EVEN_IRQHandler(void)
|
||||
{
|
||||
uint32_t iflags;
|
||||
uint32_t iflags;
|
||||
|
||||
/* Get all even interrupts. */
|
||||
iflags = GPIO_IntGetEnabled() & 0x00005555;
|
||||
/* Get all even interrupts. */
|
||||
iflags = GPIO_IntGetEnabled() & 0x00005555;
|
||||
|
||||
/* Clean only even interrupts. */
|
||||
GPIO_IntClear(iflags);
|
||||
/* Clean only even interrupts. */
|
||||
GPIO_IntClear(iflags);
|
||||
|
||||
GPIOINT_IRQDispatcher(iflags);
|
||||
GPIOINT_IRQDispatcher(iflags);
|
||||
}
|
||||
|
||||
|
||||
|
@ -208,15 +207,15 @@ void GPIO_EVEN_IRQHandler(void)
|
|||
******************************************************************************/
|
||||
void GPIO_ODD_IRQHandler(void)
|
||||
{
|
||||
uint32_t iflags;
|
||||
uint32_t iflags;
|
||||
|
||||
/* Get all odd interrupts. */
|
||||
iflags = GPIO_IntGetEnabled() & 0x0000AAAA;
|
||||
/* Get all odd interrupts. */
|
||||
iflags = GPIO_IntGetEnabled() & 0x0000AAAA;
|
||||
|
||||
/* Clean only even interrupts. */
|
||||
GPIO_IntClear(iflags);
|
||||
/* Clean only even interrupts. */
|
||||
GPIO_IntClear(iflags);
|
||||
|
||||
GPIOINT_IRQDispatcher(iflags);
|
||||
GPIOINT_IRQDispatcher(iflags);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -49,7 +49,8 @@ static inline int gpio_read(gpio_t *obj)
|
|||
}
|
||||
}
|
||||
|
||||
static inline int gpio_is_connected(const gpio_t *obj) {
|
||||
static inline int gpio_is_connected(const gpio_t *obj)
|
||||
{
|
||||
return obj->pin != (PinName)NC;
|
||||
}
|
||||
|
||||
|
|
|
@ -75,7 +75,7 @@ static CMU_Clock_TypeDef i2c_get_clock(i2c_t *obj)
|
|||
#endif
|
||||
#ifdef I2C1
|
||||
case I2C_1:
|
||||
clock = cmuClock_I2C1;
|
||||
clock = cmuClock_I2C1;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
|
@ -104,10 +104,10 @@ void i2c_preinit(i2c_t *obj, PinName sda, PinName scl)
|
|||
void i2c_init(i2c_t *obj, PinName sda, PinName scl)
|
||||
{
|
||||
/* Assign mbed pins */
|
||||
i2c_preinit(obj, sda, scl);
|
||||
i2c_preinit(obj, sda, scl);
|
||||
|
||||
/* Enable clock for the peripheral */
|
||||
CMU_ClockEnable(i2c_get_clock(obj), true);
|
||||
/* Enable clock for the peripheral */
|
||||
CMU_ClockEnable(i2c_get_clock(obj), true);
|
||||
|
||||
/* Initializing the I2C */
|
||||
/* Using default settings */
|
||||
|
@ -222,14 +222,14 @@ int i2c_stop(i2c_t *obj)
|
|||
/* Returns number of bytes read */
|
||||
int i2c_read(i2c_t *obj, int address, char *data, int length, int stop)
|
||||
{
|
||||
int retval;
|
||||
int retval;
|
||||
|
||||
i2c_start(obj);
|
||||
|
||||
retval = i2c_byte_write(obj, (address | 1));
|
||||
if ((!retval) || (length == 0)) { //Write address with W flag (last bit 1)
|
||||
obj->i2c.i2c->CMD = I2C_CMD_STOP | I2C_CMD_ABORT;
|
||||
while(obj->i2c.i2c->STATE & I2C_STATE_BUSY); // Wait until the bus is done
|
||||
obj->i2c.i2c->CMD = I2C_CMD_STOP | I2C_CMD_ABORT;
|
||||
while(obj->i2c.i2c->STATE & I2C_STATE_BUSY); // Wait until the bus is done
|
||||
return (retval == 0 ? I2C_ERROR_NO_SLAVE : 0); //NACK or error when writing adress. Return 0 as 0 bytes were read
|
||||
}
|
||||
int i = 0;
|
||||
|
@ -344,10 +344,10 @@ int block_and_wait_for_ack(I2C_TypeDef *i2c)
|
|||
|
||||
void i2c_slave_mode(i2c_t *obj, int enable_slave)
|
||||
{
|
||||
if(enable_slave){
|
||||
if(enable_slave) {
|
||||
obj->i2c.i2c->CTRL |= _I2C_CTRL_SLAVE_MASK;
|
||||
obj->i2c.i2c->CTRL |= _I2C_CTRL_AUTOACK_MASK; //Slave implementation assumes auto acking
|
||||
}else{
|
||||
} else {
|
||||
obj->i2c.i2c->CTRL &= ~_I2C_CTRL_SLAVE_MASK;
|
||||
obj->i2c.i2c->CTRL &= ~_I2C_CTRL_AUTOACK_MASK; //Master implementation ACKs manually
|
||||
}
|
||||
|
@ -356,19 +356,19 @@ void i2c_slave_mode(i2c_t *obj, int enable_slave)
|
|||
int i2c_slave_receive(i2c_t *obj)
|
||||
{
|
||||
|
||||
if(obj->i2c.i2c->IF & I2C_IF_ADDR){
|
||||
if(obj->i2c.i2c->IF & I2C_IF_ADDR) {
|
||||
obj->i2c.i2c->IFC = I2C_IF_ADDR; //Clear interrupt
|
||||
/*0x00 is the address for general write.
|
||||
The address the master wrote is in RXDATA now
|
||||
and reading it also frees the buffer for the next
|
||||
write which can then be acked. */
|
||||
if(obj->i2c.i2c->RXDATA == 0x00){
|
||||
if(obj->i2c.i2c->RXDATA == 0x00) {
|
||||
return WriteGeneral; //Read the address;
|
||||
}
|
||||
|
||||
if(obj->i2c.i2c->STATE & I2C_STATE_TRANSMITTER){
|
||||
if(obj->i2c.i2c->STATE & I2C_STATE_TRANSMITTER) {
|
||||
return ReadAddressed;
|
||||
}else{
|
||||
} else {
|
||||
return WriteAddressed;
|
||||
}
|
||||
}
|
||||
|
@ -426,128 +426,131 @@ void i2c_slave_address(i2c_t *obj, int idx, uint32_t address, uint32_t mask)
|
|||
* @param handler The I2C IRQ handler to be set
|
||||
* @param hint DMA hint usage
|
||||
*/
|
||||
void i2c_transfer_asynch(i2c_t *obj, void *tx, size_t tx_length, void *rx, size_t rx_length, uint32_t address, uint32_t stop, uint32_t handler, uint32_t event, DMAUsage hint) {
|
||||
I2C_TransferReturn_TypeDef retval;
|
||||
if(i2c_active(obj)) return;
|
||||
void i2c_transfer_asynch(i2c_t *obj, void *tx, size_t tx_length, void *rx, size_t rx_length, uint32_t address, uint32_t stop, uint32_t handler, uint32_t event, DMAUsage hint)
|
||||
{
|
||||
I2C_TransferReturn_TypeDef retval;
|
||||
if(i2c_active(obj)) return;
|
||||
if((tx_length == 0) && (rx_length == 0)) return;
|
||||
// For now, we are assuming a solely interrupt-driven implementation.
|
||||
// For now, we are assuming a solely interrupt-driven implementation.
|
||||
|
||||
// Store transfer config
|
||||
obj->i2c.xfer.addr = address;
|
||||
// Store transfer config
|
||||
obj->i2c.xfer.addr = address;
|
||||
|
||||
// Some combination of tx_length and rx_length will tell us what to do
|
||||
if((tx_length > 0) && (rx_length == 0)) {
|
||||
obj->i2c.xfer.flags = I2C_FLAG_WRITE;
|
||||
//Store buffer info
|
||||
obj->i2c.xfer.buf[0].data = tx;
|
||||
obj->i2c.xfer.buf[0].len = (uint16_t) tx_length;
|
||||
} else if ((tx_length == 0) && (rx_length > 0)) {
|
||||
obj->i2c.xfer.flags = I2C_FLAG_READ;
|
||||
//Store buffer info
|
||||
obj->i2c.xfer.buf[0].data = rx;
|
||||
obj->i2c.xfer.buf[0].len = (uint16_t) rx_length;
|
||||
} else if ((tx_length > 0) && (rx_length > 0)) {
|
||||
obj->i2c.xfer.flags = I2C_FLAG_WRITE_READ;
|
||||
//Store buffer info
|
||||
obj->i2c.xfer.buf[0].data = tx;
|
||||
obj->i2c.xfer.buf[0].len = (uint16_t) tx_length;
|
||||
obj->i2c.xfer.buf[1].data = rx;
|
||||
obj->i2c.xfer.buf[1].len = (uint16_t) rx_length;
|
||||
}
|
||||
// Some combination of tx_length and rx_length will tell us what to do
|
||||
if((tx_length > 0) && (rx_length == 0)) {
|
||||
obj->i2c.xfer.flags = I2C_FLAG_WRITE;
|
||||
//Store buffer info
|
||||
obj->i2c.xfer.buf[0].data = tx;
|
||||
obj->i2c.xfer.buf[0].len = (uint16_t) tx_length;
|
||||
} else if ((tx_length == 0) && (rx_length > 0)) {
|
||||
obj->i2c.xfer.flags = I2C_FLAG_READ;
|
||||
//Store buffer info
|
||||
obj->i2c.xfer.buf[0].data = rx;
|
||||
obj->i2c.xfer.buf[0].len = (uint16_t) rx_length;
|
||||
} else if ((tx_length > 0) && (rx_length > 0)) {
|
||||
obj->i2c.xfer.flags = I2C_FLAG_WRITE_READ;
|
||||
//Store buffer info
|
||||
obj->i2c.xfer.buf[0].data = tx;
|
||||
obj->i2c.xfer.buf[0].len = (uint16_t) tx_length;
|
||||
obj->i2c.xfer.buf[1].data = rx;
|
||||
obj->i2c.xfer.buf[1].len = (uint16_t) rx_length;
|
||||
}
|
||||
|
||||
if(address > 255) obj->i2c.xfer.flags |= I2C_FLAG_10BIT_ADDR;
|
||||
if(address > 255) obj->i2c.xfer.flags |= I2C_FLAG_10BIT_ADDR;
|
||||
|
||||
// Store event flags
|
||||
obj->i2c.events = event;
|
||||
// Store event flags
|
||||
obj->i2c.events = event;
|
||||
|
||||
// Enable interrupt
|
||||
i2c_enable_interrupt(obj, handler, true);
|
||||
// Enable interrupt
|
||||
i2c_enable_interrupt(obj, handler, true);
|
||||
|
||||
// Kick off the transfer
|
||||
retval = I2C_TransferInit(obj->i2c.i2c, &(obj->i2c.xfer));
|
||||
// Kick off the transfer
|
||||
retval = I2C_TransferInit(obj->i2c.i2c, &(obj->i2c.xfer));
|
||||
|
||||
if(retval == i2cTransferInProgress) {
|
||||
blockSleepMode(EM1);
|
||||
}
|
||||
else {
|
||||
// something happened, and the transfer did not go through
|
||||
// So, we need to clean up
|
||||
if(retval == i2cTransferInProgress) {
|
||||
blockSleepMode(EM1);
|
||||
} else {
|
||||
// something happened, and the transfer did not go through
|
||||
// So, we need to clean up
|
||||
|
||||
// Disable interrupt
|
||||
i2c_enable_interrupt(obj, 0, false);
|
||||
// Disable interrupt
|
||||
i2c_enable_interrupt(obj, 0, false);
|
||||
|
||||
// Block until free
|
||||
while(i2c_active(obj));
|
||||
}
|
||||
// Block until free
|
||||
while(i2c_active(obj));
|
||||
}
|
||||
}
|
||||
|
||||
/** The asynchronous IRQ handler
|
||||
* @param obj The I2C object which holds the transfer information
|
||||
* @return Returns event flags if a transfer termination condition was met or 0 otherwise.
|
||||
*/
|
||||
uint32_t i2c_irq_handler_asynch(i2c_t *obj) {
|
||||
uint32_t i2c_irq_handler_asynch(i2c_t *obj)
|
||||
{
|
||||
|
||||
// For now, we are assuming a solely interrupt-driven implementation.
|
||||
// For now, we are assuming a solely interrupt-driven implementation.
|
||||
|
||||
I2C_TransferReturn_TypeDef status = I2C_Transfer(obj->i2c.i2c);
|
||||
switch(status) {
|
||||
case i2cTransferInProgress:
|
||||
// Still busy transferring, so let it.
|
||||
return 0;
|
||||
case i2cTransferDone:
|
||||
// Transfer has completed
|
||||
I2C_TransferReturn_TypeDef status = I2C_Transfer(obj->i2c.i2c);
|
||||
switch(status) {
|
||||
case i2cTransferInProgress:
|
||||
// Still busy transferring, so let it.
|
||||
return 0;
|
||||
case i2cTransferDone:
|
||||
// Transfer has completed
|
||||
|
||||
// Disable interrupt
|
||||
i2c_enable_interrupt(obj, 0, false);
|
||||
// Disable interrupt
|
||||
i2c_enable_interrupt(obj, 0, false);
|
||||
|
||||
unblockSleepMode(EM1);
|
||||
unblockSleepMode(EM1);
|
||||
|
||||
return I2C_EVENT_TRANSFER_COMPLETE & obj->i2c.events;
|
||||
case i2cTransferNack:
|
||||
// A NACK has been received while an ACK was expected. This is usually because the slave did not respond to the address.
|
||||
// Disable interrupt
|
||||
i2c_enable_interrupt(obj, 0, false);
|
||||
return I2C_EVENT_TRANSFER_COMPLETE & obj->i2c.events;
|
||||
case i2cTransferNack:
|
||||
// A NACK has been received while an ACK was expected. This is usually because the slave did not respond to the address.
|
||||
// Disable interrupt
|
||||
i2c_enable_interrupt(obj, 0, false);
|
||||
|
||||
unblockSleepMode(EM1);
|
||||
unblockSleepMode(EM1);
|
||||
|
||||
return I2C_EVENT_ERROR_NO_SLAVE & obj->i2c.events;
|
||||
default:
|
||||
// An error situation has arisen.
|
||||
// Disable interrupt
|
||||
i2c_enable_interrupt(obj, 0, false);
|
||||
return I2C_EVENT_ERROR_NO_SLAVE & obj->i2c.events;
|
||||
default:
|
||||
// An error situation has arisen.
|
||||
// Disable interrupt
|
||||
i2c_enable_interrupt(obj, 0, false);
|
||||
|
||||
unblockSleepMode(EM1);
|
||||
unblockSleepMode(EM1);
|
||||
|
||||
// return error
|
||||
return I2C_EVENT_ERROR & obj->i2c.events;
|
||||
}
|
||||
// return error
|
||||
return I2C_EVENT_ERROR & obj->i2c.events;
|
||||
}
|
||||
}
|
||||
|
||||
/** Attempts to determine if I2C peripheral is already in use.
|
||||
* @param obj The I2C object
|
||||
* @return non-zero if the I2C module is active or zero if it is not
|
||||
*/
|
||||
uint8_t i2c_active(i2c_t *obj) {
|
||||
return (obj->i2c.i2c->STATE & I2C_STATE_BUSY);
|
||||
uint8_t i2c_active(i2c_t *obj)
|
||||
{
|
||||
return (obj->i2c.i2c->STATE & I2C_STATE_BUSY);
|
||||
}
|
||||
|
||||
/** Abort ongoing asynchronous transaction.
|
||||
* @param obj The I2C object
|
||||
*/
|
||||
void i2c_abort_asynch(i2c_t *obj) {
|
||||
// Do not deactivate I2C twice
|
||||
if (!i2c_active(obj)) return;
|
||||
void i2c_abort_asynch(i2c_t *obj)
|
||||
{
|
||||
// Do not deactivate I2C twice
|
||||
if (!i2c_active(obj)) return;
|
||||
|
||||
// Disable interrupt
|
||||
i2c_enable_interrupt(obj, 0, false);
|
||||
// Disable interrupt
|
||||
i2c_enable_interrupt(obj, 0, false);
|
||||
|
||||
// Abort
|
||||
obj->i2c.i2c->CMD = I2C_CMD_STOP | I2C_CMD_ABORT;
|
||||
// Abort
|
||||
obj->i2c.i2c->CMD = I2C_CMD_STOP | I2C_CMD_ABORT;
|
||||
|
||||
// Block until free
|
||||
while(i2c_active(obj));
|
||||
// Block until free
|
||||
while(i2c_active(obj));
|
||||
|
||||
unblockSleepMode(EM1);
|
||||
unblockSleepMode(EM1);
|
||||
}
|
||||
|
||||
#endif //DEVICE_I2C ASYNCH
|
||||
|
|
|
@ -27,8 +27,9 @@ void lp_ticker_init()
|
|||
rtc_set_comp0_handler((uint32_t)lp_ticker_irq_handler);
|
||||
}
|
||||
|
||||
void lp_ticker_set_interrupt(timestamp_t timestamp) {
|
||||
uint64_t timestamp_ticks;
|
||||
void lp_ticker_set_interrupt(timestamp_t timestamp)
|
||||
{
|
||||
uint64_t timestamp_ticks;
|
||||
uint64_t current_ticks = RTC_CounterGet();
|
||||
timestamp_t current_time = ((uint64_t)(current_ticks * 1000000) / (LOW_ENERGY_CLOCK_FREQUENCY / RTC_CLOCKDIV_INT));
|
||||
|
||||
|
@ -38,42 +39,45 @@ void lp_ticker_set_interrupt(timestamp_t timestamp) {
|
|||
if(offset > 0xEFFFFFFF) offset = 100;
|
||||
|
||||
/* map offset to RTC value */
|
||||
// ticks = offset * RTC frequency div 1000000
|
||||
timestamp_ticks = ((uint64_t)offset * (LOW_ENERGY_CLOCK_FREQUENCY / RTC_CLOCKDIV_INT)) / 1000000;
|
||||
// ticks = offset * RTC frequency div 1000000
|
||||
timestamp_ticks = ((uint64_t)offset * (LOW_ENERGY_CLOCK_FREQUENCY / RTC_CLOCKDIV_INT)) / 1000000;
|
||||
timestamp_ticks += current_ticks;
|
||||
|
||||
/* RTC has 24 bit resolution */
|
||||
timestamp_ticks &= 0xFFFFFF;
|
||||
/* RTC has 24 bit resolution */
|
||||
timestamp_ticks &= 0xFFFFFF;
|
||||
|
||||
/* check for RTC limitation */
|
||||
if((timestamp_ticks - RTC_CounterGet()) >= 0x800000) timestamp_ticks = RTC_CounterGet() + 2;
|
||||
|
||||
/* Set callback */
|
||||
RTC_FreezeEnable(true);
|
||||
RTC_CompareSet(0, (uint32_t)timestamp_ticks);
|
||||
RTC_IntEnable(RTC_IF_COMP0);
|
||||
RTC_FreezeEnable(false);
|
||||
/* Set callback */
|
||||
RTC_FreezeEnable(true);
|
||||
RTC_CompareSet(0, (uint32_t)timestamp_ticks);
|
||||
RTC_IntEnable(RTC_IF_COMP0);
|
||||
RTC_FreezeEnable(false);
|
||||
}
|
||||
|
||||
inline void lp_ticker_disable_interrupt() {
|
||||
RTC_IntDisable(RTC_IF_COMP0);
|
||||
inline void lp_ticker_disable_interrupt()
|
||||
{
|
||||
RTC_IntDisable(RTC_IF_COMP0);
|
||||
}
|
||||
|
||||
inline void lp_ticker_clear_interrupt() {
|
||||
RTC_IntClear(RTC_IF_COMP0);
|
||||
inline void lp_ticker_clear_interrupt()
|
||||
{
|
||||
RTC_IntClear(RTC_IF_COMP0);
|
||||
}
|
||||
|
||||
timestamp_t lp_ticker_read() {
|
||||
uint64_t ticks_temp;
|
||||
uint64_t ticks = RTC_CounterGet();
|
||||
timestamp_t lp_ticker_read()
|
||||
{
|
||||
uint64_t ticks_temp;
|
||||
uint64_t ticks = RTC_CounterGet();
|
||||
|
||||
/* ticks = counter tick value
|
||||
* timestamp = value in microseconds
|
||||
* timestamp = ticks * 1.000.000 / RTC frequency
|
||||
*/
|
||||
/* ticks = counter tick value
|
||||
* timestamp = value in microseconds
|
||||
* timestamp = ticks * 1.000.000 / RTC frequency
|
||||
*/
|
||||
|
||||
ticks_temp = (ticks * 1000000) / (LOW_ENERGY_CLOCK_FREQUENCY / RTC_CLOCKDIV_INT);
|
||||
return (timestamp_t) (ticks_temp & 0xFFFFFFFF);
|
||||
ticks_temp = (ticks * 1000000) / (LOW_ENERGY_CLOCK_FREQUENCY / RTC_CLOCKDIV_INT);
|
||||
return (timestamp_t) (ticks_temp & 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -50,11 +50,11 @@ void mbed_sdk_init()
|
|||
CMU_ClockSelectSet(cmuClock_LFA, LFXO);
|
||||
#endif
|
||||
#ifdef CMU_LFBCLKSEL_REG
|
||||
/* cmuClock_LFB (to date) only has LEUART peripherals.
|
||||
* Do NOT set it up here, as LEUARTs might have been initialized
|
||||
* before this code is called. (Limitation of the override mechanism of ARMCC)
|
||||
*/
|
||||
//TODO: Look for a more elegant fix.
|
||||
/* cmuClock_LFB (to date) only has LEUART peripherals.
|
||||
* Do NOT set it up here, as LEUARTs might have been initialized
|
||||
* before this code is called. (Limitation of the override mechanism of ARMCC)
|
||||
*/
|
||||
//TODO: Look for a more elegant fix.
|
||||
//CMU_ClockSelectSet(cmuClock_LFB, LFXO);
|
||||
#endif
|
||||
#ifdef CMU_LFECLKSEL_REG
|
||||
|
@ -92,7 +92,8 @@ void mbed_sdk_init()
|
|||
gpio_init_out_ex(&bc_enable, EFM_BC_EN, 1);
|
||||
}
|
||||
|
||||
void check_usart_clock(USART_TypeDef* usart, uint32_t clockmask) {
|
||||
void check_usart_clock(USART_TypeDef* usart, uint32_t clockmask)
|
||||
{
|
||||
uint32_t freq = 14000000, baudrate;
|
||||
USART_OVS_TypeDef ovs;
|
||||
|
||||
|
|
|
@ -129,11 +129,11 @@ struct lp_timer_s {
|
|||
#if DEVICE_SLEEP
|
||||
#define NUM_SLEEP_MODES 5
|
||||
typedef enum {
|
||||
EM0 = 0,
|
||||
EM1 = 1,
|
||||
EM2 = 2,
|
||||
EM3 = 3,
|
||||
EM4 = 4
|
||||
EM0 = 0,
|
||||
EM1 = 1,
|
||||
EM2 = 2,
|
||||
EM3 = 3,
|
||||
EM4 = 4
|
||||
} sleepstate_enum;
|
||||
#endif
|
||||
|
||||
|
|
|
@ -30,10 +30,10 @@ void pin_mode(PinName pin, PinMode mode)
|
|||
MBED_ASSERT(pin != NC);
|
||||
|
||||
/* Enable GPIO clock if not already done */
|
||||
if (!gpio_clock_inited) {
|
||||
CMU_ClockEnable(cmuClock_GPIO, true);
|
||||
gpio_clock_inited = 1;
|
||||
}
|
||||
if (!gpio_clock_inited) {
|
||||
CMU_ClockEnable(cmuClock_GPIO, true);
|
||||
gpio_clock_inited = 1;
|
||||
}
|
||||
|
||||
/* Pin and port index encoded in one uint32.
|
||||
* First four bits represent the pin number
|
||||
|
|
|
@ -44,7 +44,7 @@ void port_preinit(port_t *obj, PortName port, int mask, PinDirection dir)
|
|||
|
||||
void port_init(port_t *obj, PortName port, int mask, PinDirection dir)
|
||||
{
|
||||
port_preinit(obj, port, mask, dir);
|
||||
port_preinit(obj, port, mask, dir);
|
||||
port_dir(obj, obj->dir);
|
||||
}
|
||||
|
||||
|
|
|
@ -33,22 +33,23 @@
|
|||
static int pwm_clockfreq;
|
||||
static int pwm_prescaler_div;
|
||||
|
||||
uint32_t pwmout_get_channel_route(pwmout_t *obj) {
|
||||
MBED_ASSERT(obj->channel != (PWMName) NC);
|
||||
uint32_t pwmout_get_channel_route(pwmout_t *obj)
|
||||
{
|
||||
MBED_ASSERT(obj->channel != (PWMName) NC);
|
||||
|
||||
switch (obj->channel) {
|
||||
case PWM_CH0:
|
||||
return TIMER_ROUTE_CC0PEN;
|
||||
break;
|
||||
case PWM_CH1:
|
||||
return TIMER_ROUTE_CC1PEN;
|
||||
break;
|
||||
case PWM_CH2:
|
||||
return TIMER_ROUTE_CC2PEN;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
switch (obj->channel) {
|
||||
case PWM_CH0:
|
||||
return TIMER_ROUTE_CC0PEN;
|
||||
break;
|
||||
case PWM_CH1:
|
||||
return TIMER_ROUTE_CC1PEN;
|
||||
break;
|
||||
case PWM_CH2:
|
||||
return TIMER_ROUTE_CC2PEN;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void pwmout_enable_pins(pwmout_t *obj, uint8_t enable)
|
||||
|
@ -63,8 +64,8 @@ void pwmout_enable_pins(pwmout_t *obj, uint8_t enable)
|
|||
|
||||
void pwmout_enable(pwmout_t *obj, uint8_t enable)
|
||||
{
|
||||
/* Start with default CC (Compare/Capture) channel parameters */
|
||||
TIMER_InitCC_TypeDef timerCCInit = TIMER_INITCC_DEFAULT;
|
||||
/* Start with default CC (Compare/Capture) channel parameters */
|
||||
TIMER_InitCC_TypeDef timerCCInit = TIMER_INITCC_DEFAULT;
|
||||
if (enable) {
|
||||
/* Set mode to PWM */
|
||||
timerCCInit.mode = timerCCModePWM;
|
||||
|
@ -76,33 +77,33 @@ void pwmout_enable(pwmout_t *obj, uint8_t enable)
|
|||
|
||||
void pwmout_init(pwmout_t *obj, PinName pin)
|
||||
{
|
||||
obj->channel = (PWMName) pinmap_peripheral(pin, PinMap_PWM);
|
||||
obj->pin = pin;
|
||||
MBED_ASSERT(obj->channel != (PWMName) NC);
|
||||
obj->channel = (PWMName) pinmap_peripheral(pin, PinMap_PWM);
|
||||
obj->pin = pin;
|
||||
MBED_ASSERT(obj->channel != (PWMName) NC);
|
||||
|
||||
/* Turn on clock */
|
||||
CMU_ClockEnable(PWM_TIMER_CLOCK, true);
|
||||
/* Turn on clock */
|
||||
CMU_ClockEnable(PWM_TIMER_CLOCK, true);
|
||||
|
||||
/* Turn on timer */
|
||||
if(!(PWM_TIMER->STATUS & TIMER_STATUS_RUNNING)) {
|
||||
TIMER_Init_TypeDef timerInit = TIMER_INIT_DEFAULT;
|
||||
TIMER_Init(PWM_TIMER, &timerInit);
|
||||
}
|
||||
/* Turn on timer */
|
||||
if(!(PWM_TIMER->STATUS & TIMER_STATUS_RUNNING)) {
|
||||
TIMER_Init_TypeDef timerInit = TIMER_INIT_DEFAULT;
|
||||
TIMER_Init(PWM_TIMER, &timerInit);
|
||||
}
|
||||
|
||||
/* Enable correct channel */
|
||||
uint32_t routeloc = pwmout_get_channel_route(obj);
|
||||
if(PWM_TIMER->ROUTE & routeloc) {
|
||||
//This channel was already in use
|
||||
//TODO: gracefully handle this case
|
||||
} else {
|
||||
//This channel was unused up to now
|
||||
PWM_TIMER->ROUTE |= routeloc;
|
||||
blockSleepMode(EM1);
|
||||
uint32_t routeloc = pwmout_get_channel_route(obj);
|
||||
if(PWM_TIMER->ROUTE & routeloc) {
|
||||
//This channel was already in use
|
||||
//TODO: gracefully handle this case
|
||||
} else {
|
||||
//This channel was unused up to now
|
||||
PWM_TIMER->ROUTE |= routeloc;
|
||||
blockSleepMode(EM1);
|
||||
|
||||
//TODO: check if any channel was up already, then don't re-init timer
|
||||
pwmout_enable(obj, true);
|
||||
pwmout_enable_pins(obj, true);
|
||||
}
|
||||
//TODO: check if any channel was up already, then don't re-init timer
|
||||
pwmout_enable(obj, true);
|
||||
pwmout_enable_pins(obj, true);
|
||||
}
|
||||
|
||||
/* Route correct channel to location 1 */
|
||||
PWM_TIMER->ROUTE &= ~_TIMER_ROUTE_LOCATION_MASK;
|
||||
|
@ -115,18 +116,19 @@ void pwmout_init(pwmout_t *obj, PinName pin)
|
|||
pwmout_period(obj, 0.02);
|
||||
}
|
||||
|
||||
void pwmout_free(pwmout_t *obj) {
|
||||
uint32_t routeloc = pwmout_get_channel_route(obj);
|
||||
if(PWM_TIMER->ROUTE & routeloc) {
|
||||
//This channel was in use, so disable
|
||||
PWM_TIMER->ROUTE &= ~routeloc;
|
||||
pwmout_enable_pins(obj, false);
|
||||
unblockSleepMode(EM1);
|
||||
void pwmout_free(pwmout_t *obj)
|
||||
{
|
||||
uint32_t routeloc = pwmout_get_channel_route(obj);
|
||||
if(PWM_TIMER->ROUTE & routeloc) {
|
||||
//This channel was in use, so disable
|
||||
PWM_TIMER->ROUTE &= ~routeloc;
|
||||
pwmout_enable_pins(obj, false);
|
||||
unblockSleepMode(EM1);
|
||||
|
||||
//TODO: check if all channels are down, then switch off timer
|
||||
} else {
|
||||
//This channel was disabled already
|
||||
}
|
||||
//TODO: check if all channels are down, then switch off timer
|
||||
} else {
|
||||
//This channel was disabled already
|
||||
}
|
||||
}
|
||||
|
||||
void pwmout_write(pwmout_t *obj, float value)
|
||||
|
|
|
@ -37,17 +37,14 @@ void RTC_IRQHandler(void)
|
|||
{
|
||||
uint32_t flags;
|
||||
flags = RTC_IntGet();
|
||||
if (flags & RTC_IF_OF)
|
||||
{
|
||||
if (flags & RTC_IF_OF) {
|
||||
RTC_IntClear(RTC_IF_OF);
|
||||
/* RTC has overflowed (24 bits). Use time_base as software counter for upper 8 bits. */
|
||||
time_base += 1 << 24;
|
||||
}
|
||||
if (flags & RTC_IF_COMP0)
|
||||
{
|
||||
if (flags & RTC_IF_COMP0) {
|
||||
RTC_IntClear(RTC_IF_COMP0);
|
||||
if (comp0_handler != NULL)
|
||||
{
|
||||
if (comp0_handler != NULL) {
|
||||
comp0_handler();
|
||||
}
|
||||
}
|
||||
|
@ -69,8 +66,7 @@ void rtc_init_real(uint32_t flags)
|
|||
{
|
||||
useflags |= flags;
|
||||
|
||||
if (!rtc_inited)
|
||||
{
|
||||
if (!rtc_inited) {
|
||||
/* Start LFXO and wait until it is stable */
|
||||
CMU_OscillatorEnable(cmuOsc_LFXO, true, true);
|
||||
|
||||
|
@ -114,8 +110,7 @@ void rtc_free_real(uint32_t flags)
|
|||
flags &= ~flags;
|
||||
|
||||
/* Disable the RTC if it was inited and is no longer in use by anyone. */
|
||||
if (rtc_inited && (flags == 0))
|
||||
{
|
||||
if (rtc_inited && (flags == 0)) {
|
||||
NVIC_DisableIRQ(RTC_IRQn);
|
||||
RTC_Reset();
|
||||
CMU_ClockEnable(cmuClock_RTC, false);
|
||||
|
|
|
@ -66,6 +66,8 @@ serial_t stdio_uart;
|
|||
|
||||
static void uart_irq(UARTName, int, SerialIrq);
|
||||
uint8_t serial_get_index(serial_t *obj);
|
||||
void serial_enable(serial_t *obj, uint8_t enable);
|
||||
void serial_enable_pins(serial_t *obj, uint8_t enable);
|
||||
IRQn_Type serial_get_rx_irq_index(serial_t *obj);
|
||||
IRQn_Type serial_get_tx_irq_index(serial_t *obj);
|
||||
CMU_Clock_TypeDef serial_get_clock(serial_t *obj);
|
||||
|
@ -92,7 +94,8 @@ static void usart2_rx_irq() { uart_irq(USART_2, 4, RxIrq); }
|
|||
static void usart2_tx_irq() { uart_irq(USART_2, 4, TxIrq); USART_IntClear((USART_TypeDef*)USART_2, USART_IFC_TXC);}
|
||||
#endif
|
||||
#ifdef LEUART0
|
||||
static void leuart0_irq() {
|
||||
static void leuart0_irq()
|
||||
{
|
||||
if(LEUART_IntGetEnabled(LEUART0) && (LEUART_IF_RXDATAV | LEUART_IF_FERR | LEUART_IFC_PERR | LEUART_IF_RXOF)) {
|
||||
uart_irq(LEUART_0, 5, RxIrq);
|
||||
} else {
|
||||
|
@ -101,7 +104,8 @@ static void leuart0_irq() {
|
|||
}
|
||||
#endif
|
||||
#ifdef LEUART1
|
||||
static void leuart1_irq() {
|
||||
static void leuart1_irq()
|
||||
{
|
||||
if(LEUART_IntGetEnabled(LEUART1) && (LEUART_IF_RXDATAV | LEUART_IF_FERR | LEUART_IFC_PERR | LEUART_IF_RXOF)) {
|
||||
uart_irq(LEUART_1, 6, RxIrq);
|
||||
} else {
|
||||
|
@ -403,12 +407,12 @@ void serial_enable_pins(serial_t *obj, uint8_t enable)
|
|||
|
||||
void serial_init(serial_t *obj, PinName tx, PinName rx)
|
||||
{
|
||||
serial_preinit(obj, tx, rx);
|
||||
serial_preinit(obj, tx, rx);
|
||||
|
||||
if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
|
||||
// Set up LEUART clock tree to use high-speed clock)
|
||||
CMU_ClockSelectSet(cmuClock_LFB, cmuSelect_CORELEDIV2);
|
||||
CMU_ClockEnable(cmuClock_LFB, true);
|
||||
CMU_ClockEnable(cmuClock_LFB, true);
|
||||
CMU_ClockSelectSet(serial_get_clock(obj), cmuSelect_CORELEDIV2);
|
||||
}
|
||||
|
||||
|
@ -435,24 +439,17 @@ void serial_init(serial_t *obj, PinName tx, PinName rx)
|
|||
if (obj->serial.periph.uart == (USART_TypeDef*)STDIO_UART ) {
|
||||
stdio_uart_inited = 1;
|
||||
memcpy(&stdio_uart, obj, sizeof(serial_t));
|
||||
|
||||
/* enable TX and RX by default for STDIO */
|
||||
if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
|
||||
obj->serial.periph.leuart->CMD = LEUART_CMD_TXEN | LEUART_CMD_RXEN;
|
||||
} else {
|
||||
obj->serial.periph.uart->CMD = USART_CMD_TXEN | USART_CMD_RXEN;
|
||||
}
|
||||
}
|
||||
|
||||
serial_enable_pins(obj, true);
|
||||
|
||||
serial_enable(obj, true);
|
||||
|
||||
|
||||
obj->serial.dmaOptionsTX.dmaChannel = -1;
|
||||
obj->serial.dmaOptionsTX.dmaUsageState = DMA_USAGE_OPPORTUNISTIC;
|
||||
|
||||
obj->serial.dmaOptionsRX.dmaChannel = -1;
|
||||
obj->serial.dmaOptionsRX.dmaUsageState = DMA_USAGE_OPPORTUNISTIC;
|
||||
obj->serial.dmaOptionsRX.dmaChannel = -1;
|
||||
obj->serial.dmaOptionsRX.dmaUsageState = DMA_USAGE_OPPORTUNISTIC;
|
||||
|
||||
}
|
||||
|
||||
|
@ -870,8 +867,8 @@ void serial_pinout_tx(PinName tx)
|
|||
******************************************/
|
||||
static void serial_dmaTransferComplete(unsigned int channel, bool primary, void *user)
|
||||
{
|
||||
/* Store information about which channel triggered because CPP doesn't take arguments */
|
||||
serial_dma_irq_fired[channel] = true;
|
||||
/* Store information about which channel triggered because CPP doesn't take arguments */
|
||||
serial_dma_irq_fired[channel] = true;
|
||||
|
||||
/* User pointer should be a thunk to CPP land */
|
||||
if (user != NULL) {
|
||||
|
@ -885,100 +882,101 @@ static void serial_dmaTransferComplete(unsigned int channel, bool primary, void
|
|||
* Sets up the DMA configuration block for the assigned channel
|
||||
* tx_nrx: true if configuring TX, false if configuring RX.
|
||||
******************************************/
|
||||
static void serial_dmaSetupChannel(serial_t *obj, bool tx_nrx) {
|
||||
DMA_CfgChannel_TypeDef channelConfig;
|
||||
static void serial_dmaSetupChannel(serial_t *obj, bool tx_nrx)
|
||||
{
|
||||
DMA_CfgChannel_TypeDef channelConfig;
|
||||
|
||||
if(tx_nrx) {
|
||||
//setup TX channel
|
||||
channelConfig.highPri = false;
|
||||
channelConfig.enableInt = true;
|
||||
channelConfig.cb = &(obj->serial.dmaOptionsTX.dmaCallback);
|
||||
if(tx_nrx) {
|
||||
//setup TX channel
|
||||
channelConfig.highPri = false;
|
||||
channelConfig.enableInt = true;
|
||||
channelConfig.cb = &(obj->serial.dmaOptionsTX.dmaCallback);
|
||||
|
||||
switch((uint32_t)(obj->serial.periph.uart)) {
|
||||
switch((uint32_t)(obj->serial.periph.uart)) {
|
||||
#ifdef UART0
|
||||
case UART_0:
|
||||
channelConfig.select = DMAREQ_UART0_TXBL;
|
||||
break;
|
||||
case UART_0:
|
||||
channelConfig.select = DMAREQ_UART0_TXBL;
|
||||
break;
|
||||
#endif
|
||||
#ifdef UART1
|
||||
case UART_1:
|
||||
channelConfig.select = DMAREQ_UART1_TXBL;
|
||||
break;
|
||||
case UART_1:
|
||||
channelConfig.select = DMAREQ_UART1_TXBL;
|
||||
break;
|
||||
#endif
|
||||
#ifdef USART0
|
||||
case USART_0:
|
||||
channelConfig.select = DMAREQ_USART0_TXBL;
|
||||
break;
|
||||
case USART_0:
|
||||
channelConfig.select = DMAREQ_USART0_TXBL;
|
||||
break;
|
||||
#endif
|
||||
#ifdef USART1
|
||||
case USART_1:
|
||||
channelConfig.select = DMAREQ_USART1_TXBL;
|
||||
break;
|
||||
case USART_1:
|
||||
channelConfig.select = DMAREQ_USART1_TXBL;
|
||||
break;
|
||||
#endif
|
||||
#ifdef USART2
|
||||
case USART_2:
|
||||
channelConfig.select = DMAREQ_USART2_TXBL;
|
||||
break;
|
||||
case USART_2:
|
||||
channelConfig.select = DMAREQ_USART2_TXBL;
|
||||
break;
|
||||
#endif
|
||||
#ifdef LEUART0
|
||||
case LEUART_0:
|
||||
channelConfig.select = DMAREQ_LEUART0_TXBL;
|
||||
break;
|
||||
case LEUART_0:
|
||||
channelConfig.select = DMAREQ_LEUART0_TXBL;
|
||||
break;
|
||||
#endif
|
||||
#ifdef LEUART1
|
||||
case LEUART_1:
|
||||
channelConfig.select = DMAREQ_LEUART1_TXBL;
|
||||
break;
|
||||
case LEUART_1:
|
||||
channelConfig.select = DMAREQ_LEUART1_TXBL;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
DMA_CfgChannel(obj->serial.dmaOptionsTX.dmaChannel, &channelConfig);
|
||||
} else {
|
||||
//setup RX channel
|
||||
channelConfig.highPri = true;
|
||||
channelConfig.enableInt = true;
|
||||
channelConfig.cb = &(obj->serial.dmaOptionsRX.dmaCallback);
|
||||
DMA_CfgChannel(obj->serial.dmaOptionsTX.dmaChannel, &channelConfig);
|
||||
} else {
|
||||
//setup RX channel
|
||||
channelConfig.highPri = true;
|
||||
channelConfig.enableInt = true;
|
||||
channelConfig.cb = &(obj->serial.dmaOptionsRX.dmaCallback);
|
||||
|
||||
switch((uint32_t)(obj->serial.periph.uart)) {
|
||||
switch((uint32_t)(obj->serial.periph.uart)) {
|
||||
#ifdef UART0
|
||||
case UART_0:
|
||||
channelConfig.select = DMAREQ_UART0_RXDATAV;
|
||||
break;
|
||||
case UART_0:
|
||||
channelConfig.select = DMAREQ_UART0_RXDATAV;
|
||||
break;
|
||||
#endif
|
||||
#ifdef UART1
|
||||
case UART_1:
|
||||
channelConfig.select = DMAREQ_UART1_RXDATAV;
|
||||
break;
|
||||
case UART_1:
|
||||
channelConfig.select = DMAREQ_UART1_RXDATAV;
|
||||
break;
|
||||
#endif
|
||||
#ifdef USART0
|
||||
case USART_0:
|
||||
channelConfig.select = DMAREQ_USART0_RXDATAV;
|
||||
break;
|
||||
case USART_0:
|
||||
channelConfig.select = DMAREQ_USART0_RXDATAV;
|
||||
break;
|
||||
#endif
|
||||
#ifdef USART1
|
||||
case USART_1:
|
||||
channelConfig.select = DMAREQ_USART1_RXDATAV;
|
||||
break;
|
||||
case USART_1:
|
||||
channelConfig.select = DMAREQ_USART1_RXDATAV;
|
||||
break;
|
||||
#endif
|
||||
#ifdef USART2
|
||||
case USART_2:
|
||||
channelConfig.select = DMAREQ_USART2_RXDATAV;
|
||||
break;
|
||||
case USART_2:
|
||||
channelConfig.select = DMAREQ_USART2_RXDATAV;
|
||||
break;
|
||||
#endif
|
||||
#ifdef LEUART0
|
||||
case LEUART_0:
|
||||
channelConfig.select = DMAREQ_LEUART0_RXDATAV;
|
||||
break;
|
||||
case LEUART_0:
|
||||
channelConfig.select = DMAREQ_LEUART0_RXDATAV;
|
||||
break;
|
||||
#endif
|
||||
#ifdef LEUART1
|
||||
case LEUART_1:
|
||||
channelConfig.select = DMAREQ_LEUART1_RXDATAV;
|
||||
break;
|
||||
case LEUART_1:
|
||||
channelConfig.select = DMAREQ_LEUART1_RXDATAV;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
DMA_CfgChannel(obj->serial.dmaOptionsRX.dmaChannel, &channelConfig);
|
||||
}
|
||||
DMA_CfgChannel(obj->serial.dmaOptionsRX.dmaChannel, &channelConfig);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -999,57 +997,59 @@ static void serial_dmaSetupChannel(serial_t *obj, bool tx_nrx) {
|
|||
* Will try to allocate a channel and keep it.
|
||||
* If succesfully allocated, state changes to DMA_USAGE_ALLOCATED.
|
||||
******************************************/
|
||||
static void serial_dmaTrySetState(DMA_OPTIONS_t *obj, DMAUsage requestedState, serial_t *serialPtr, bool tx_nrx) {
|
||||
DMAUsage currentState = obj->dmaUsageState;
|
||||
int tempDMAChannel = -1;
|
||||
static void serial_dmaTrySetState(DMA_OPTIONS_t *obj, DMAUsage requestedState, serial_t *serialPtr, bool tx_nrx)
|
||||
{
|
||||
DMAUsage currentState = obj->dmaUsageState;
|
||||
int tempDMAChannel = -1;
|
||||
|
||||
if ((requestedState == DMA_USAGE_ALWAYS) && (currentState != DMA_USAGE_ALLOCATED)) {
|
||||
/* Try to allocate channel */
|
||||
tempDMAChannel = dma_channel_allocate(DMA_CAP_NONE);
|
||||
if(tempDMAChannel >= 0) {
|
||||
obj->dmaChannel = tempDMAChannel;
|
||||
obj->dmaUsageState = DMA_USAGE_ALLOCATED;
|
||||
dma_init();
|
||||
serial_dmaSetupChannel(serialPtr, tx_nrx);
|
||||
}
|
||||
} else if (requestedState == DMA_USAGE_OPPORTUNISTIC) {
|
||||
if (currentState == DMA_USAGE_ALLOCATED) {
|
||||
/* Channels have already been allocated previously by an ALWAYS state, so after this transfer, we will release them */
|
||||
obj->dmaUsageState = DMA_USAGE_TEMPORARY_ALLOCATED;
|
||||
} else {
|
||||
/* Try to allocate channel */
|
||||
tempDMAChannel = dma_channel_allocate(DMA_CAP_NONE);
|
||||
if(tempDMAChannel >= 0) {
|
||||
obj->dmaChannel = tempDMAChannel;
|
||||
obj->dmaUsageState = DMA_USAGE_TEMPORARY_ALLOCATED;
|
||||
dma_init();
|
||||
serial_dmaSetupChannel(serialPtr, tx_nrx);
|
||||
}
|
||||
}
|
||||
} else if (requestedState == DMA_USAGE_NEVER) {
|
||||
/* If channel is allocated, get rid of it */
|
||||
dma_channel_free(obj->dmaChannel);
|
||||
obj->dmaChannel = -1;
|
||||
obj->dmaUsageState = DMA_USAGE_NEVER;
|
||||
}
|
||||
if ((requestedState == DMA_USAGE_ALWAYS) && (currentState != DMA_USAGE_ALLOCATED)) {
|
||||
/* Try to allocate channel */
|
||||
tempDMAChannel = dma_channel_allocate(DMA_CAP_NONE);
|
||||
if(tempDMAChannel >= 0) {
|
||||
obj->dmaChannel = tempDMAChannel;
|
||||
obj->dmaUsageState = DMA_USAGE_ALLOCATED;
|
||||
dma_init();
|
||||
serial_dmaSetupChannel(serialPtr, tx_nrx);
|
||||
}
|
||||
} else if (requestedState == DMA_USAGE_OPPORTUNISTIC) {
|
||||
if (currentState == DMA_USAGE_ALLOCATED) {
|
||||
/* Channels have already been allocated previously by an ALWAYS state, so after this transfer, we will release them */
|
||||
obj->dmaUsageState = DMA_USAGE_TEMPORARY_ALLOCATED;
|
||||
} else {
|
||||
/* Try to allocate channel */
|
||||
tempDMAChannel = dma_channel_allocate(DMA_CAP_NONE);
|
||||
if(tempDMAChannel >= 0) {
|
||||
obj->dmaChannel = tempDMAChannel;
|
||||
obj->dmaUsageState = DMA_USAGE_TEMPORARY_ALLOCATED;
|
||||
dma_init();
|
||||
serial_dmaSetupChannel(serialPtr, tx_nrx);
|
||||
}
|
||||
}
|
||||
} else if (requestedState == DMA_USAGE_NEVER) {
|
||||
/* If channel is allocated, get rid of it */
|
||||
dma_channel_free(obj->dmaChannel);
|
||||
obj->dmaChannel = -1;
|
||||
obj->dmaUsageState = DMA_USAGE_NEVER;
|
||||
}
|
||||
}
|
||||
|
||||
static void serial_dmaActivate(serial_t *obj, void* cb, void* buffer, int length, bool tx_nrx) {
|
||||
DMA_CfgDescr_TypeDef channelConfig;
|
||||
static void serial_dmaActivate(serial_t *obj, void* cb, void* buffer, int length, bool tx_nrx)
|
||||
{
|
||||
DMA_CfgDescr_TypeDef channelConfig;
|
||||
|
||||
if(tx_nrx) {
|
||||
// Set DMA callback
|
||||
obj->serial.dmaOptionsTX.dmaCallback.cbFunc = serial_dmaTransferComplete;
|
||||
obj->serial.dmaOptionsTX.dmaCallback.userPtr = cb;
|
||||
if(tx_nrx) {
|
||||
// Set DMA callback
|
||||
obj->serial.dmaOptionsTX.dmaCallback.cbFunc = serial_dmaTransferComplete;
|
||||
obj->serial.dmaOptionsTX.dmaCallback.userPtr = cb;
|
||||
|
||||
// Set up configuration structure
|
||||
channelConfig.dstInc = dmaDataIncNone;
|
||||
channelConfig.srcInc = dmaDataInc1;
|
||||
channelConfig.size = dmaDataSize1;
|
||||
channelConfig.arbRate = dmaArbitrate1;
|
||||
channelConfig.hprot = 0;
|
||||
// Set up configuration structure
|
||||
channelConfig.dstInc = dmaDataIncNone;
|
||||
channelConfig.srcInc = dmaDataInc1;
|
||||
channelConfig.size = dmaDataSize1;
|
||||
channelConfig.arbRate = dmaArbitrate1;
|
||||
channelConfig.hprot = 0;
|
||||
|
||||
DMA_CfgDescr(obj->serial.dmaOptionsTX.dmaChannel, true, &channelConfig);
|
||||
DMA_CfgDescr(obj->serial.dmaOptionsTX.dmaChannel, true, &channelConfig);
|
||||
|
||||
if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
|
||||
// Activate TX
|
||||
|
@ -1070,19 +1070,19 @@ static void serial_dmaActivate(serial_t *obj, void* cb, void* buffer, int length
|
|||
// Kick off TX DMA
|
||||
DMA_ActivateBasic(obj->serial.dmaOptionsTX.dmaChannel, true, false, (void*) &(obj->serial.periph.uart->TXDATA), buffer, length - 1);
|
||||
}
|
||||
} else {
|
||||
// Set DMA callback
|
||||
obj->serial.dmaOptionsRX.dmaCallback.cbFunc = serial_dmaTransferComplete;
|
||||
obj->serial.dmaOptionsRX.dmaCallback.userPtr = cb;
|
||||
} else {
|
||||
// Set DMA callback
|
||||
obj->serial.dmaOptionsRX.dmaCallback.cbFunc = serial_dmaTransferComplete;
|
||||
obj->serial.dmaOptionsRX.dmaCallback.userPtr = cb;
|
||||
|
||||
// Set up configuration structure
|
||||
channelConfig.dstInc = dmaDataInc1;
|
||||
channelConfig.srcInc = dmaDataIncNone;
|
||||
channelConfig.size = dmaDataSize1;
|
||||
channelConfig.arbRate = dmaArbitrate1;
|
||||
channelConfig.hprot = 0;
|
||||
// Set up configuration structure
|
||||
channelConfig.dstInc = dmaDataInc1;
|
||||
channelConfig.srcInc = dmaDataIncNone;
|
||||
channelConfig.size = dmaDataSize1;
|
||||
channelConfig.arbRate = dmaArbitrate1;
|
||||
channelConfig.hprot = 0;
|
||||
|
||||
DMA_CfgDescr(obj->serial.dmaOptionsRX.dmaChannel, true, &channelConfig);
|
||||
DMA_CfgDescr(obj->serial.dmaOptionsRX.dmaChannel, true, &channelConfig);
|
||||
|
||||
if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
|
||||
// Activate RX
|
||||
|
@ -1103,7 +1103,7 @@ static void serial_dmaActivate(serial_t *obj, void* cb, void* buffer, int length
|
|||
// Kick off RX DMA
|
||||
DMA_ActivateBasic(obj->serial.dmaOptionsRX.dmaChannel, true, false, buffer, (void*) &(obj->serial.periph.uart->RXDATA), length - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************************
|
||||
|
@ -1122,10 +1122,11 @@ static void serial_dmaActivate(serial_t *obj, void* cb, void* buffer, int length
|
|||
* @param event The logical OR of the TX events to configure
|
||||
* @param enable Set to non-zero to enable events, or zero to disable them
|
||||
*/
|
||||
void serial_tx_enable_event(serial_t *obj, int event, uint8_t enable) {
|
||||
// Shouldn't have to enable TX interrupt here, just need to keep track of the requested events.
|
||||
if(enable) obj->serial.events |= event;
|
||||
else obj->serial.events &= ~event;
|
||||
void serial_tx_enable_event(serial_t *obj, int event, uint8_t enable)
|
||||
{
|
||||
// Shouldn't have to enable TX interrupt here, just need to keep track of the requested events.
|
||||
if(enable) obj->serial.events |= event;
|
||||
else obj->serial.events &= ~event;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1133,12 +1134,13 @@ void serial_tx_enable_event(serial_t *obj, int event, uint8_t enable) {
|
|||
* @param event The logical OR of the RX events to configure
|
||||
* @param enable Set to non-zero to enable events, or zero to disable them
|
||||
*/
|
||||
void serial_rx_enable_event(serial_t *obj, int event, uint8_t enable) {
|
||||
if(enable) {
|
||||
obj->serial.events |= event;
|
||||
} else {
|
||||
obj->serial.events &= ~event;
|
||||
}
|
||||
void serial_rx_enable_event(serial_t *obj, int event, uint8_t enable)
|
||||
{
|
||||
if(enable) {
|
||||
obj->serial.events |= event;
|
||||
} else {
|
||||
obj->serial.events &= ~event;
|
||||
}
|
||||
if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
|
||||
if(event & SERIAL_EVENT_RX_FRAMING_ERROR) {
|
||||
//FERR interrupt source
|
||||
|
@ -1192,17 +1194,18 @@ void serial_rx_enable_event(serial_t *obj, int event, uint8_t enable) {
|
|||
* @param tx The buffer for sending.
|
||||
* @param tx_length The number of words to transmit.
|
||||
*/
|
||||
void serial_tx_buffer_set(serial_t *obj, void *tx, int tx_length, uint8_t width) {
|
||||
// We only support byte buffers for now
|
||||
MBED_ASSERT(width == 8);
|
||||
void serial_tx_buffer_set(serial_t *obj, void *tx, int tx_length, uint8_t width)
|
||||
{
|
||||
// We only support byte buffers for now
|
||||
MBED_ASSERT(width == 8);
|
||||
|
||||
if(serial_tx_active(obj)) return;
|
||||
if(serial_tx_active(obj)) return;
|
||||
|
||||
obj->tx_buff.buffer = tx;
|
||||
obj->tx_buff.length = tx_length;
|
||||
obj->tx_buff.pos = 0;
|
||||
obj->tx_buff.buffer = tx;
|
||||
obj->tx_buff.length = tx_length;
|
||||
obj->tx_buff.pos = 0;
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
/** Configure the TX buffer for an asynchronous read serial transaction
|
||||
|
@ -1211,17 +1214,18 @@ void serial_tx_buffer_set(serial_t *obj, void *tx, int tx_length, uint8_t width)
|
|||
* @param rx The buffer for receiving.
|
||||
* @param rx_length The number of words to read.
|
||||
*/
|
||||
void serial_rx_buffer_set(serial_t *obj, void *rx, int rx_length, uint8_t width) {
|
||||
// We only support byte buffers for now
|
||||
MBED_ASSERT(width == 8);
|
||||
void serial_rx_buffer_set(serial_t *obj, void *rx, int rx_length, uint8_t width)
|
||||
{
|
||||
// We only support byte buffers for now
|
||||
MBED_ASSERT(width == 8);
|
||||
|
||||
if(serial_rx_active(obj)) return;
|
||||
if(serial_rx_active(obj)) return;
|
||||
|
||||
obj->rx_buff.buffer = rx;
|
||||
obj->rx_buff.length = rx_length;
|
||||
obj->rx_buff.pos = 0;
|
||||
obj->rx_buff.buffer = rx;
|
||||
obj->rx_buff.length = rx_length;
|
||||
obj->rx_buff.pos = 0;
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
/** Set character to be matched. If an event is enabled, and received character
|
||||
|
@ -1231,18 +1235,19 @@ void serial_rx_buffer_set(serial_t *obj, void *rx, int rx_length, uint8_t width)
|
|||
* @param obj The serial object
|
||||
* @param char_match A character in range 0-254
|
||||
*/
|
||||
void serial_set_char_match(serial_t *obj, uint8_t char_match) {
|
||||
// We only have hardware support for this in LEUART.
|
||||
// When in USART/UART, we can set up a check in the receiving ISR, but not when using DMA.
|
||||
if (char_match != SERIAL_RESERVED_CHAR_MATCH) {
|
||||
obj->char_match = char_match;
|
||||
void serial_set_char_match(serial_t *obj, uint8_t char_match)
|
||||
{
|
||||
// We only have hardware support for this in LEUART.
|
||||
// When in USART/UART, we can set up a check in the receiving ISR, but not when using DMA.
|
||||
if (char_match != SERIAL_RESERVED_CHAR_MATCH) {
|
||||
obj->char_match = char_match;
|
||||
|
||||
if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
|
||||
obj->serial.periph.leuart->SIGFRAME = char_match & 0x000000FF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
/************************************
|
||||
|
@ -1257,36 +1262,37 @@ void serial_set_char_match(serial_t *obj, uint8_t char_match) {
|
|||
* @param hint A suggestion for how to use DMA with this transfer
|
||||
* @return Returns number of data transfered, or 0 otherwise
|
||||
*/
|
||||
int serial_tx_asynch(serial_t *obj, void *tx, size_t tx_length, uint8_t tx_width, uint32_t handler, uint32_t event, DMAUsage hint) {
|
||||
// Check that a buffer has indeed been set up
|
||||
MBED_ASSERT(tx != (void*)0);
|
||||
if(tx_length == 0) return 0;
|
||||
int serial_tx_asynch(serial_t *obj, void *tx, size_t tx_length, uint8_t tx_width, uint32_t handler, uint32_t event, DMAUsage hint)
|
||||
{
|
||||
// Check that a buffer has indeed been set up
|
||||
MBED_ASSERT(tx != (void*)0);
|
||||
if(tx_length == 0) return 0;
|
||||
|
||||
// Set up buffer
|
||||
serial_tx_buffer_set(obj, tx, tx_length, tx_width);
|
||||
// Set up buffer
|
||||
serial_tx_buffer_set(obj, tx, tx_length, tx_width);
|
||||
|
||||
// Set up events
|
||||
serial_tx_enable_event(obj, SERIAL_EVENT_TX_ALL, false);
|
||||
serial_tx_enable_event(obj, event, true);
|
||||
// Set up events
|
||||
serial_tx_enable_event(obj, SERIAL_EVENT_TX_ALL, false);
|
||||
serial_tx_enable_event(obj, event, true);
|
||||
|
||||
// Set up sleepmode
|
||||
blockSleepMode(SERIAL_LEAST_ACTIVE_SLEEPMODE);
|
||||
// Set up sleepmode
|
||||
blockSleepMode(SERIAL_LEAST_ACTIVE_SLEEPMODE);
|
||||
|
||||
// Determine DMA strategy
|
||||
serial_dmaTrySetState(&(obj->serial.dmaOptionsTX), hint, obj, true);
|
||||
// Determine DMA strategy
|
||||
serial_dmaTrySetState(&(obj->serial.dmaOptionsTX), hint, obj, true);
|
||||
|
||||
// If DMA, kick off DMA transfer
|
||||
if(obj->serial.dmaOptionsTX.dmaChannel >= 0) {
|
||||
serial_dmaActivate(obj, (void*)handler, obj->tx_buff.buffer, obj->tx_buff.length, true);
|
||||
}
|
||||
// Else, activate interrupt. TXBL will take care of buffer filling through ISR.
|
||||
else {
|
||||
// Store callback
|
||||
NVIC_ClearPendingIRQ(serial_get_tx_irq_index(obj));
|
||||
NVIC_DisableIRQ(serial_get_tx_irq_index(obj));
|
||||
NVIC_SetPriority(serial_get_tx_irq_index(obj), 1);
|
||||
NVIC_SetVector(serial_get_tx_irq_index(obj), (uint32_t)handler);
|
||||
NVIC_EnableIRQ(serial_get_tx_irq_index(obj));
|
||||
// If DMA, kick off DMA transfer
|
||||
if(obj->serial.dmaOptionsTX.dmaChannel >= 0) {
|
||||
serial_dmaActivate(obj, (void*)handler, obj->tx_buff.buffer, obj->tx_buff.length, true);
|
||||
}
|
||||
// Else, activate interrupt. TXBL will take care of buffer filling through ISR.
|
||||
else {
|
||||
// Store callback
|
||||
NVIC_ClearPendingIRQ(serial_get_tx_irq_index(obj));
|
||||
NVIC_DisableIRQ(serial_get_tx_irq_index(obj));
|
||||
NVIC_SetPriority(serial_get_tx_irq_index(obj), 1);
|
||||
NVIC_SetVector(serial_get_tx_irq_index(obj), (uint32_t)handler);
|
||||
NVIC_EnableIRQ(serial_get_tx_irq_index(obj));
|
||||
|
||||
if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
|
||||
// Activate TX and return
|
||||
|
@ -1307,9 +1313,9 @@ int serial_tx_asynch(serial_t *obj, void *tx, size_t tx_length, uint8_t tx_width
|
|||
// Enable interrupt
|
||||
USART_IntEnable(obj->serial.periph.uart, USART_IEN_TXBL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Begin asynchronous RX transfer (enable interrupt for data collecting)
|
||||
|
@ -1319,38 +1325,39 @@ int serial_tx_asynch(serial_t *obj, void *tx, size_t tx_length, uint8_t tx_width
|
|||
* @param cb The function to call when an event occurs
|
||||
* @param hint A suggestion for how to use DMA with this transfer
|
||||
*/
|
||||
void serial_rx_asynch(serial_t *obj, void *rx, size_t rx_length, uint8_t rx_width, uint32_t handler, uint32_t event, uint8_t char_match, DMAUsage hint) {
|
||||
// Check that a buffer has indeed been set up
|
||||
MBED_ASSERT(rx != (void*)0);
|
||||
if(rx_length == 0) return;
|
||||
void serial_rx_asynch(serial_t *obj, void *rx, size_t rx_length, uint8_t rx_width, uint32_t handler, uint32_t event, uint8_t char_match, DMAUsage hint)
|
||||
{
|
||||
// Check that a buffer has indeed been set up
|
||||
MBED_ASSERT(rx != (void*)0);
|
||||
if(rx_length == 0) return;
|
||||
|
||||
// Set up buffer
|
||||
serial_rx_buffer_set(obj, rx, rx_length, rx_width);
|
||||
// Set up buffer
|
||||
serial_rx_buffer_set(obj, rx, rx_length, rx_width);
|
||||
|
||||
// Set up events
|
||||
serial_rx_enable_event(obj, SERIAL_EVENT_RX_ALL, false);
|
||||
serial_rx_enable_event(obj, event, true);
|
||||
serial_set_char_match(obj, char_match);
|
||||
// Set up events
|
||||
serial_rx_enable_event(obj, SERIAL_EVENT_RX_ALL, false);
|
||||
serial_rx_enable_event(obj, event, true);
|
||||
serial_set_char_match(obj, char_match);
|
||||
|
||||
// Set up sleepmode
|
||||
blockSleepMode(SERIAL_LEAST_ACTIVE_SLEEPMODE);
|
||||
// Set up sleepmode
|
||||
blockSleepMode(SERIAL_LEAST_ACTIVE_SLEEPMODE);
|
||||
|
||||
// Determine DMA strategy
|
||||
// If character match is enabled, we can't use DMA, sadly. We could when using LEUART though, but that support is not in here yet.
|
||||
if(!(event & SERIAL_EVENT_RX_CHARACTER_MATCH)) {
|
||||
serial_dmaTrySetState(&(obj->serial.dmaOptionsRX), hint, obj, false);
|
||||
}
|
||||
// Determine DMA strategy
|
||||
// If character match is enabled, we can't use DMA, sadly. We could when using LEUART though, but that support is not in here yet.
|
||||
if(!(event & SERIAL_EVENT_RX_CHARACTER_MATCH)) {
|
||||
serial_dmaTrySetState(&(obj->serial.dmaOptionsRX), hint, obj, false);
|
||||
}
|
||||
|
||||
// If DMA, kick off DMA
|
||||
if(obj->serial.dmaOptionsRX.dmaChannel >= 0) {
|
||||
serial_dmaActivate(obj, (void*)handler, obj->rx_buff.buffer, obj->rx_buff.length, false);
|
||||
}
|
||||
// Else, activate interrupt. RXDATAV is responsible for incoming data notification.
|
||||
else {
|
||||
// Store callback
|
||||
NVIC_ClearPendingIRQ(serial_get_rx_irq_index(obj));
|
||||
NVIC_SetVector(serial_get_rx_irq_index(obj), (uint32_t)handler);
|
||||
NVIC_EnableIRQ(serial_get_rx_irq_index(obj));
|
||||
// If DMA, kick off DMA
|
||||
if(obj->serial.dmaOptionsRX.dmaChannel >= 0) {
|
||||
serial_dmaActivate(obj, (void*)handler, obj->rx_buff.buffer, obj->rx_buff.length, false);
|
||||
}
|
||||
// Else, activate interrupt. RXDATAV is responsible for incoming data notification.
|
||||
else {
|
||||
// Store callback
|
||||
NVIC_ClearPendingIRQ(serial_get_rx_irq_index(obj));
|
||||
NVIC_SetVector(serial_get_rx_irq_index(obj), (uint32_t)handler);
|
||||
NVIC_EnableIRQ(serial_get_rx_irq_index(obj));
|
||||
|
||||
if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
|
||||
// Activate RX
|
||||
|
@ -1374,9 +1381,9 @@ void serial_rx_asynch(serial_t *obj, void *rx, size_t rx_length, uint8_t rx_widt
|
|||
// Enable interrupt
|
||||
USART_IntEnable(obj->serial.periph.uart, USART_IEN_RXDATAV);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
/** Attempts to determine if the serial peripheral is already in use for TX
|
||||
|
@ -1384,22 +1391,23 @@ void serial_rx_asynch(serial_t *obj, void *rx, size_t rx_length, uint8_t rx_widt
|
|||
* @param obj The serial object
|
||||
* @return Non-zero if the TX transaction is ongoing, 0 otherwise
|
||||
*/
|
||||
uint8_t serial_tx_active(serial_t *obj) {
|
||||
switch(obj->serial.dmaOptionsTX.dmaUsageState) {
|
||||
case DMA_USAGE_TEMPORARY_ALLOCATED:
|
||||
/* Temporary allocation always means its active, as this state gets cleared afterwards */
|
||||
return 1;
|
||||
case DMA_USAGE_ALLOCATED:
|
||||
/* Check whether the allocated DMA channel is active by checking the DMA transfer */
|
||||
return(DMA_ChannelEnabled(obj->serial.dmaOptionsTX.dmaChannel));
|
||||
default:
|
||||
/* Check whether interrupt for serial TX is enabled */
|
||||
uint8_t serial_tx_active(serial_t *obj)
|
||||
{
|
||||
switch(obj->serial.dmaOptionsTX.dmaUsageState) {
|
||||
case DMA_USAGE_TEMPORARY_ALLOCATED:
|
||||
/* Temporary allocation always means its active, as this state gets cleared afterwards */
|
||||
return 1;
|
||||
case DMA_USAGE_ALLOCATED:
|
||||
/* Check whether the allocated DMA channel is active by checking the DMA transfer */
|
||||
return(DMA_ChannelEnabled(obj->serial.dmaOptionsTX.dmaChannel));
|
||||
default:
|
||||
/* Check whether interrupt for serial TX is enabled */
|
||||
if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
|
||||
return (obj->serial.periph.leuart->IEN & (LEUART_IEN_TXBL)) ? true : false;
|
||||
} else {
|
||||
return (obj->serial.periph.uart->IEN & (USART_IEN_TXBL)) ? true : false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Attempts to determine if the serial peripheral is already in use for RX
|
||||
|
@ -1407,22 +1415,23 @@ uint8_t serial_tx_active(serial_t *obj) {
|
|||
* @param obj The serial object
|
||||
* @return Non-zero if the RX transaction is ongoing, 0 otherwise
|
||||
*/
|
||||
uint8_t serial_rx_active(serial_t *obj) {
|
||||
switch(obj->serial.dmaOptionsRX.dmaUsageState) {
|
||||
case DMA_USAGE_TEMPORARY_ALLOCATED:
|
||||
/* Temporary allocation always means its active, as this state gets cleared afterwards */
|
||||
return 1;
|
||||
case DMA_USAGE_ALLOCATED:
|
||||
/* Check whether the allocated DMA channel is active by checking the DMA transfer */
|
||||
return(DMA_ChannelEnabled(obj->serial.dmaOptionsRX.dmaChannel));
|
||||
default:
|
||||
/* Check whether interrupt for serial TX is enabled */
|
||||
uint8_t serial_rx_active(serial_t *obj)
|
||||
{
|
||||
switch(obj->serial.dmaOptionsRX.dmaUsageState) {
|
||||
case DMA_USAGE_TEMPORARY_ALLOCATED:
|
||||
/* Temporary allocation always means its active, as this state gets cleared afterwards */
|
||||
return 1;
|
||||
case DMA_USAGE_ALLOCATED:
|
||||
/* Check whether the allocated DMA channel is active by checking the DMA transfer */
|
||||
return(DMA_ChannelEnabled(obj->serial.dmaOptionsRX.dmaChannel));
|
||||
default:
|
||||
/* Check whether interrupt for serial TX is enabled */
|
||||
if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
|
||||
return (obj->serial.periph.leuart->IEN & (LEUART_IEN_RXDATAV)) ? true : false;
|
||||
} else {
|
||||
return (obj->serial.periph.uart->IEN & (USART_IEN_RXDATAV)) ? true : false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** The asynchronous TX handler. Writes to the TX FIFO and checks for events.
|
||||
|
@ -1431,17 +1440,18 @@ uint8_t serial_rx_active(serial_t *obj) {
|
|||
* @param obj The serial object
|
||||
* @return Returns event flags if a TX transfer termination condition was met or 0 otherwise
|
||||
*/
|
||||
int serial_tx_irq_handler_asynch(serial_t *obj) {
|
||||
/* This interrupt handler is called from USART irq */
|
||||
uint8_t *buf = obj->tx_buff.buffer;
|
||||
int serial_tx_irq_handler_asynch(serial_t *obj)
|
||||
{
|
||||
/* This interrupt handler is called from USART irq */
|
||||
uint8_t *buf = obj->tx_buff.buffer;
|
||||
|
||||
/* Interrupt has another TX source */
|
||||
if(obj->tx_buff.pos >= obj->tx_buff.length) {
|
||||
/* Transfer complete. Switch off interrupt and return event. */
|
||||
serial_tx_abort_asynch(obj);
|
||||
return SERIAL_EVENT_TX_COMPLETE & obj->serial.events;
|
||||
} else {
|
||||
/* There's still data in the buffer that needs to be sent */
|
||||
/* Interrupt has another TX source */
|
||||
if(obj->tx_buff.pos >= obj->tx_buff.length) {
|
||||
/* Transfer complete. Switch off interrupt and return event. */
|
||||
serial_tx_abort_asynch(obj);
|
||||
return SERIAL_EVENT_TX_COMPLETE & obj->serial.events;
|
||||
} else {
|
||||
/* There's still data in the buffer that needs to be sent */
|
||||
if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
|
||||
while((LEUART_StatusGet(obj->serial.periph.leuart) & LEUART_STATUS_TXBL) && (obj->tx_buff.pos <= (obj->tx_buff.length - 1))) {
|
||||
LEUART_Tx(obj->serial.periph.leuart, buf[obj->tx_buff.pos]);
|
||||
|
@ -1453,8 +1463,8 @@ int serial_tx_irq_handler_asynch(serial_t *obj) {
|
|||
obj->tx_buff.pos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** The asynchronous RX handler. Reads from the RX FIFOF and checks for events.
|
||||
|
@ -1463,11 +1473,12 @@ int serial_tx_irq_handler_asynch(serial_t *obj) {
|
|||
* @param obj The serial object
|
||||
* @return Returns event flags if a RX transfer termination condition was met or 0 otherwise
|
||||
*/
|
||||
int serial_rx_irq_handler_asynch(serial_t *obj) {
|
||||
int event = 0;
|
||||
int serial_rx_irq_handler_asynch(serial_t *obj)
|
||||
{
|
||||
int event = 0;
|
||||
|
||||
/* This interrupt handler is called from USART irq */
|
||||
uint8_t *buf = (uint8_t*)obj->rx_buff.buffer;
|
||||
/* This interrupt handler is called from USART irq */
|
||||
uint8_t *buf = (uint8_t*)obj->rx_buff.buffer;
|
||||
|
||||
if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
|
||||
/* Determine the source of the interrupt */
|
||||
|
@ -1596,33 +1607,34 @@ int serial_rx_irq_handler_asynch(serial_t *obj) {
|
|||
}
|
||||
}
|
||||
|
||||
/* All events should have generated a return, if no return has happened, no event has been caught */
|
||||
return 0;
|
||||
/* All events should have generated a return, if no return has happened, no event has been caught */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Unified IRQ handler. Determines the appropriate handler to execute and returns the flags.
|
||||
*
|
||||
* WARNING: this code should be stateless, as re-entrancy is very possible in interrupt-based mode.
|
||||
*/
|
||||
int serial_irq_handler_asynch(serial_t *obj) {
|
||||
/* First, check if we're running in DMA mode */
|
||||
if(serial_dma_irq_fired[obj->serial.dmaOptionsRX.dmaChannel]) {
|
||||
/* Clean up */
|
||||
serial_dma_irq_fired[obj->serial.dmaOptionsRX.dmaChannel] = false;
|
||||
serial_rx_abort_asynch(obj);
|
||||
int serial_irq_handler_asynch(serial_t *obj)
|
||||
{
|
||||
/* First, check if we're running in DMA mode */
|
||||
if(serial_dma_irq_fired[obj->serial.dmaOptionsRX.dmaChannel]) {
|
||||
/* Clean up */
|
||||
serial_dma_irq_fired[obj->serial.dmaOptionsRX.dmaChannel] = false;
|
||||
serial_rx_abort_asynch(obj);
|
||||
|
||||
/* Notify CPP land of RX completion */
|
||||
return SERIAL_EVENT_RX_COMPLETE & obj->serial.events;
|
||||
} else if (serial_dma_irq_fired[obj->serial.dmaOptionsTX.dmaChannel]) {
|
||||
/* Clean up */
|
||||
serial_dma_irq_fired[obj->serial.dmaOptionsTX.dmaChannel] = false;
|
||||
serial_tx_abort_asynch(obj);
|
||||
/* Notify CPP land of RX completion */
|
||||
return SERIAL_EVENT_RX_COMPLETE & obj->serial.events;
|
||||
} else if (serial_dma_irq_fired[obj->serial.dmaOptionsTX.dmaChannel]) {
|
||||
/* Clean up */
|
||||
serial_dma_irq_fired[obj->serial.dmaOptionsTX.dmaChannel] = false;
|
||||
serial_tx_abort_asynch(obj);
|
||||
|
||||
/* Notify CPP land of completion */
|
||||
return SERIAL_EVENT_TX_COMPLETE & obj->serial.events;
|
||||
} else {
|
||||
/* Check the NVIC to see which interrupt we're running from
|
||||
* Also make sure to prioritize RX */
|
||||
/* Notify CPP land of completion */
|
||||
return SERIAL_EVENT_TX_COMPLETE & obj->serial.events;
|
||||
} else {
|
||||
/* Check the NVIC to see which interrupt we're running from
|
||||
* Also make sure to prioritize RX */
|
||||
if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
|
||||
//Different method of checking tx vs rx for LEUART
|
||||
if(LEUART_IntGetEnabled(obj->serial.periph.leuart) & (LEUART_IF_RXDATAV | LEUART_IF_FERR | LEUART_IF_PERR | LEUART_IF_RXOF | LEUART_IF_SIGF)) {
|
||||
|
@ -1637,10 +1649,10 @@ int serial_irq_handler_asynch(serial_t *obj) {
|
|||
return serial_tx_irq_handler_asynch(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// All should be done now
|
||||
return 0;
|
||||
// All should be done now
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Abort the ongoing TX transaction. It disables the enabled interupt for TX and
|
||||
|
@ -1648,35 +1660,36 @@ int serial_irq_handler_asynch(serial_t *obj) {
|
|||
*
|
||||
* @param obj The serial object
|
||||
*/
|
||||
void serial_tx_abort_asynch(serial_t *obj) {
|
||||
/* Stop transmitter */
|
||||
//obj->serial.periph.uart->CMD |= USART_CMD_TXDIS;
|
||||
void serial_tx_abort_asynch(serial_t *obj)
|
||||
{
|
||||
/* Stop transmitter */
|
||||
//obj->serial.periph.uart->CMD |= USART_CMD_TXDIS;
|
||||
|
||||
/* Clean up */
|
||||
switch(obj->serial.dmaOptionsTX.dmaUsageState) {
|
||||
case DMA_USAGE_ALLOCATED:
|
||||
/* stop DMA transfer */
|
||||
DMA_ChannelEnable(obj->serial.dmaOptionsTX.dmaChannel, false);
|
||||
break;
|
||||
case DMA_USAGE_TEMPORARY_ALLOCATED:
|
||||
/* stop DMA transfer and release channel */
|
||||
DMA_ChannelEnable(obj->serial.dmaOptionsTX.dmaChannel, false);
|
||||
dma_channel_free(obj->serial.dmaOptionsTX.dmaChannel);
|
||||
obj->serial.dmaOptionsTX.dmaChannel = -1;
|
||||
obj->serial.dmaOptionsTX.dmaUsageState = DMA_USAGE_OPPORTUNISTIC;
|
||||
break;
|
||||
default:
|
||||
/* stop interrupting */
|
||||
if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
|
||||
LEUART_IntDisable(obj->serial.periph.leuart, LEUART_IEN_TXBL);
|
||||
} else {
|
||||
USART_IntDisable(obj->serial.periph.uart, USART_IEN_TXBL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* Clean up */
|
||||
switch(obj->serial.dmaOptionsTX.dmaUsageState) {
|
||||
case DMA_USAGE_ALLOCATED:
|
||||
/* stop DMA transfer */
|
||||
DMA_ChannelEnable(obj->serial.dmaOptionsTX.dmaChannel, false);
|
||||
break;
|
||||
case DMA_USAGE_TEMPORARY_ALLOCATED:
|
||||
/* stop DMA transfer and release channel */
|
||||
DMA_ChannelEnable(obj->serial.dmaOptionsTX.dmaChannel, false);
|
||||
dma_channel_free(obj->serial.dmaOptionsTX.dmaChannel);
|
||||
obj->serial.dmaOptionsTX.dmaChannel = -1;
|
||||
obj->serial.dmaOptionsTX.dmaUsageState = DMA_USAGE_OPPORTUNISTIC;
|
||||
break;
|
||||
default:
|
||||
/* stop interrupting */
|
||||
if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
|
||||
LEUART_IntDisable(obj->serial.periph.leuart, LEUART_IEN_TXBL);
|
||||
} else {
|
||||
USART_IntDisable(obj->serial.periph.uart, USART_IEN_TXBL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Unblock EM2 and below */
|
||||
unblockSleepMode(SERIAL_LEAST_ACTIVE_SLEEPMODE);
|
||||
/* Unblock EM2 and below */
|
||||
unblockSleepMode(SERIAL_LEAST_ACTIVE_SLEEPMODE);
|
||||
}
|
||||
|
||||
/** Abort the ongoing RX transaction It disables the enabled interrupt for RX and
|
||||
|
@ -1684,35 +1697,36 @@ void serial_tx_abort_asynch(serial_t *obj) {
|
|||
*
|
||||
* @param obj The serial object
|
||||
*/
|
||||
void serial_rx_abort_asynch(serial_t *obj) {
|
||||
/* Stop receiver */
|
||||
obj->serial.periph.uart->CMD |= USART_CMD_RXDIS;
|
||||
void serial_rx_abort_asynch(serial_t *obj)
|
||||
{
|
||||
/* Stop receiver */
|
||||
obj->serial.periph.uart->CMD |= USART_CMD_RXDIS;
|
||||
|
||||
/* Clean up */
|
||||
switch(obj->serial.dmaOptionsRX.dmaUsageState) {
|
||||
case DMA_USAGE_ALLOCATED:
|
||||
/* stop DMA transfer */
|
||||
DMA_ChannelEnable(obj->serial.dmaOptionsRX.dmaChannel, false);
|
||||
break;
|
||||
case DMA_USAGE_TEMPORARY_ALLOCATED:
|
||||
/* stop DMA transfer and release channel */
|
||||
DMA_ChannelEnable(obj->serial.dmaOptionsRX.dmaChannel, false);
|
||||
dma_channel_free(obj->serial.dmaOptionsRX.dmaChannel);
|
||||
obj->serial.dmaOptionsRX.dmaChannel = -1;
|
||||
obj->serial.dmaOptionsRX.dmaUsageState = DMA_USAGE_OPPORTUNISTIC;
|
||||
break;
|
||||
default:
|
||||
/* stop interrupting */
|
||||
if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
|
||||
LEUART_IntDisable(obj->serial.periph.leuart, LEUART_IEN_RXDATAV | LEUART_IEN_PERR | LEUART_IEN_FERR | LEUART_IEN_RXOF | LEUART_IEN_SIGF);
|
||||
} else {
|
||||
USART_IntDisable(obj->serial.periph.uart, USART_IEN_RXDATAV | USART_IEN_PERR | USART_IEN_FERR | USART_IEN_RXOF);
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* Clean up */
|
||||
switch(obj->serial.dmaOptionsRX.dmaUsageState) {
|
||||
case DMA_USAGE_ALLOCATED:
|
||||
/* stop DMA transfer */
|
||||
DMA_ChannelEnable(obj->serial.dmaOptionsRX.dmaChannel, false);
|
||||
break;
|
||||
case DMA_USAGE_TEMPORARY_ALLOCATED:
|
||||
/* stop DMA transfer and release channel */
|
||||
DMA_ChannelEnable(obj->serial.dmaOptionsRX.dmaChannel, false);
|
||||
dma_channel_free(obj->serial.dmaOptionsRX.dmaChannel);
|
||||
obj->serial.dmaOptionsRX.dmaChannel = -1;
|
||||
obj->serial.dmaOptionsRX.dmaUsageState = DMA_USAGE_OPPORTUNISTIC;
|
||||
break;
|
||||
default:
|
||||
/* stop interrupting */
|
||||
if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
|
||||
LEUART_IntDisable(obj->serial.periph.leuart, LEUART_IEN_RXDATAV | LEUART_IEN_PERR | LEUART_IEN_FERR | LEUART_IEN_RXOF | LEUART_IEN_SIGF);
|
||||
} else {
|
||||
USART_IntDisable(obj->serial.periph.uart, USART_IEN_RXDATAV | USART_IEN_PERR | USART_IEN_FERR | USART_IEN_RXOF);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Say that we can stop using this emode */
|
||||
unblockSleepMode(SERIAL_LEAST_ACTIVE_SLEEPMODE);
|
||||
/* Say that we can stop using this emode */
|
||||
unblockSleepMode(SERIAL_LEAST_ACTIVE_SLEEPMODE);
|
||||
}
|
||||
|
||||
#endif //DEVICE_SERIAL_ASYNCH
|
||||
|
|
|
@ -34,19 +34,19 @@ uint32_t sleep_block_counter[NUM_SLEEP_MODES] = {0};
|
|||
*/
|
||||
void sleep(void)
|
||||
{
|
||||
if (sleep_block_counter[0] > 0) {
|
||||
// Blocked everything below EM0, so just return
|
||||
return;
|
||||
} else if (sleep_block_counter[1] > 0) {
|
||||
// Blocked everything below EM1, enter EM1
|
||||
EMU_EnterEM1();
|
||||
} else if (sleep_block_counter[2] > 0) {
|
||||
// Blocked everything below EM2, enter EM2
|
||||
EMU_EnterEM2(true);
|
||||
} else if (sleep_block_counter[3] > 0) {
|
||||
// Blocked everything below EM3, enter EM3
|
||||
EMU_EnterEM3(true);
|
||||
}
|
||||
if (sleep_block_counter[0] > 0) {
|
||||
// Blocked everything below EM0, so just return
|
||||
return;
|
||||
} else if (sleep_block_counter[1] > 0) {
|
||||
// Blocked everything below EM1, enter EM1
|
||||
EMU_EnterEM1();
|
||||
} else if (sleep_block_counter[2] > 0) {
|
||||
// Blocked everything below EM2, enter EM2
|
||||
EMU_EnterEM2(true);
|
||||
} else if (sleep_block_counter[3] > 0) {
|
||||
// Blocked everything below EM3, enter EM3
|
||||
EMU_EnterEM3(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -76,9 +76,9 @@ void deepsleep(void)
|
|||
*/
|
||||
void blockSleepMode(sleepstate_enum minimumMode)
|
||||
{
|
||||
INT_Disable();
|
||||
sleep_block_counter[minimumMode]++;
|
||||
INT_Enable();
|
||||
INT_Disable();
|
||||
sleep_block_counter[minimumMode]++;
|
||||
INT_Enable();
|
||||
}
|
||||
|
||||
/** Unblock the microcontroller from sleeping below a certain mode
|
||||
|
@ -90,12 +90,11 @@ void blockSleepMode(sleepstate_enum minimumMode)
|
|||
*/
|
||||
void unblockSleepMode(sleepstate_enum minimumMode)
|
||||
{
|
||||
INT_Disable();
|
||||
if(sleep_block_counter[minimumMode] > 0)
|
||||
{
|
||||
sleep_block_counter[minimumMode]--;
|
||||
}
|
||||
INT_Enable();
|
||||
INT_Disable();
|
||||
if(sleep_block_counter[minimumMode] > 0) {
|
||||
sleep_block_counter[minimumMode]--;
|
||||
}
|
||||
INT_Enable();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -35,7 +35,8 @@
|
|||
static uint16_t fill_word = SPI_FILL_WORD;
|
||||
#define SPI_LEAST_ACTIVE_SLEEPMODE EM1
|
||||
|
||||
inline CMU_Clock_TypeDef spi_get_clock_tree(spi_t *obj) {
|
||||
inline CMU_Clock_TypeDef spi_get_clock_tree(spi_t *obj)
|
||||
{
|
||||
switch ((int)obj->spi.spi) {
|
||||
#ifdef USART0
|
||||
case SPI_0:
|
||||
|
@ -81,7 +82,8 @@ inline uint8_t spi_get_index(spi_t *obj)
|
|||
return index;
|
||||
}
|
||||
|
||||
uint8_t spi_get_module(spi_t *obj) {
|
||||
uint8_t spi_get_module(spi_t *obj)
|
||||
{
|
||||
return spi_get_index(obj);
|
||||
}
|
||||
|
||||
|
@ -200,12 +202,12 @@ void spi_enable(spi_t *obj, uint8_t enable)
|
|||
|
||||
void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName clk, PinName cs)
|
||||
{
|
||||
CMU_ClockEnable(cmuClock_HFPER, true);
|
||||
spi_preinit(obj, mosi, miso, clk, cs);
|
||||
CMU_ClockEnable(spi_get_clock_tree(obj), true);
|
||||
usart_init(obj, 100000, usartDatabits8, true, usartClockMode0);
|
||||
CMU_ClockEnable(cmuClock_HFPER, true);
|
||||
spi_preinit(obj, mosi, miso, clk, cs);
|
||||
CMU_ClockEnable(spi_get_clock_tree(obj), true);
|
||||
usart_init(obj, 100000, usartDatabits8, true, usartClockMode0);
|
||||
|
||||
spi_enable_pins(obj, true, mosi, miso, clk, cs);
|
||||
spi_enable_pins(obj, true, mosi, miso, clk, cs);
|
||||
spi_enable(obj, true);
|
||||
}
|
||||
|
||||
|
@ -254,8 +256,7 @@ void spi_enable_interrupt(spi_t *obj, uint32_t handler, uint8_t enable)
|
|||
NVIC_SetVector(IRQvector, handler);
|
||||
USART_IntEnable(obj->spi.spi, USART_IEN_RXDATAV);
|
||||
NVIC_EnableIRQ(IRQvector);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
NVIC_SetVector(IRQvector, handler);
|
||||
USART_IntDisable(obj->spi.spi, USART_IEN_RXDATAV);
|
||||
NVIC_DisableIRQ(IRQvector);
|
||||
|
@ -400,11 +401,11 @@ uint8_t spi_active(spi_t *obj)
|
|||
|
||||
void spi_buffer_set(spi_t *obj, void *tx, uint32_t tx_length, void *rx, uint32_t rx_length, uint8_t bit_width)
|
||||
{
|
||||
uint32_t i;
|
||||
uint16_t *tx_ptr = (uint16_t *) tx;
|
||||
uint32_t i;
|
||||
uint16_t *tx_ptr = (uint16_t *) tx;
|
||||
|
||||
tx_length *= (bit_width >> 3);
|
||||
rx_length *= (bit_width >> 3);
|
||||
tx_length *= (bit_width >> 3);
|
||||
rx_length *= (bit_width >> 3);
|
||||
|
||||
obj->tx_buff.buffer = tx;
|
||||
obj->rx_buff.buffer = rx;
|
||||
|
@ -416,123 +417,123 @@ void spi_buffer_set(spi_t *obj, void *tx, uint32_t tx_length, void *rx, uint32_t
|
|||
obj->rx_buff.width = bit_width;
|
||||
|
||||
if((obj->spi.bits == 9) && (tx != 0)) {
|
||||
// Make sure we don't have inadvertent non-zero bits outside 9-bit frames which could trigger unwanted operation
|
||||
for(i = 0; i < (tx_length / 2); i++) {
|
||||
tx_ptr[i] &= 0x1FF;
|
||||
}
|
||||
// Make sure we don't have inadvertent non-zero bits outside 9-bit frames which could trigger unwanted operation
|
||||
for(i = 0; i < (tx_length / 2); i++) {
|
||||
tx_ptr[i] &= 0x1FF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void spi_buffer_tx_write(spi_t *obj)
|
||||
{
|
||||
uint32_t data;
|
||||
// This routine gets triggered on TXBL (= buffer empty), so check to see if we can write a double value
|
||||
if (obj->spi.bits % 9 != 0) {
|
||||
// No special 9-bit scenario
|
||||
if((obj->tx_buff.pos < obj->tx_buff.length - 1) && ((obj->tx_buff.pos & 0x1) == 0)) {
|
||||
// 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 / 2] & 0xFFFF;
|
||||
}
|
||||
obj->tx_buff.pos += 2;
|
||||
obj->spi.spi->TXDOUBLE = data;
|
||||
} else if (obj->tx_buff.pos < obj->tx_buff.length) {
|
||||
// write single frame
|
||||
if (obj->tx_buff.buffer == (void *)0) {
|
||||
data = SPI_FILL_WORD & 0xFF;
|
||||
} else {
|
||||
uint8_t *tx = (uint8_t *)(obj->tx_buff.buffer);
|
||||
data = tx[obj->tx_buff.pos] & 0xFF;
|
||||
}
|
||||
obj->tx_buff.pos++;
|
||||
obj->spi.spi->TXDATA = data;
|
||||
}
|
||||
} else {
|
||||
// 9-bit frame
|
||||
if(obj->tx_buff.pos < obj->tx_buff.length - 3) {
|
||||
// write double frame
|
||||
if (obj->tx_buff.buffer == (void *)0) {
|
||||
data = ((SPI_FILL_WORD & 0x01FF) << 16) | (SPI_FILL_WORD & 0x1FF);
|
||||
} else {
|
||||
uint32_t *tx = (uint32_t *)(obj->tx_buff.buffer);
|
||||
data = tx[obj->tx_buff.pos / 4] & 0x01FF01FF;
|
||||
}
|
||||
obj->tx_buff.pos += 4;
|
||||
obj->spi.spi->TXDOUBLEX = data;
|
||||
} else if (obj->tx_buff.pos < obj->tx_buff.length - 1) {
|
||||
// write single frame
|
||||
if (obj->tx_buff.buffer == (void *)0) {
|
||||
data = SPI_FILL_WORD & 0x01FF;
|
||||
} else {
|
||||
uint16_t *tx = (uint16_t *)(obj->tx_buff.buffer);
|
||||
data = tx[obj->tx_buff.pos / 2] & 0x01FF;
|
||||
}
|
||||
obj->tx_buff.pos += 2;
|
||||
obj->spi.spi->TXDATAX = data;
|
||||
}
|
||||
}
|
||||
uint32_t data;
|
||||
// This routine gets triggered on TXBL (= buffer empty), so check to see if we can write a double value
|
||||
if (obj->spi.bits % 9 != 0) {
|
||||
// No special 9-bit scenario
|
||||
if((obj->tx_buff.pos < obj->tx_buff.length - 1) && ((obj->tx_buff.pos & 0x1) == 0)) {
|
||||
// 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 / 2] & 0xFFFF;
|
||||
}
|
||||
obj->tx_buff.pos += 2;
|
||||
obj->spi.spi->TXDOUBLE = data;
|
||||
} else if (obj->tx_buff.pos < obj->tx_buff.length) {
|
||||
// write single frame
|
||||
if (obj->tx_buff.buffer == (void *)0) {
|
||||
data = SPI_FILL_WORD & 0xFF;
|
||||
} else {
|
||||
uint8_t *tx = (uint8_t *)(obj->tx_buff.buffer);
|
||||
data = tx[obj->tx_buff.pos] & 0xFF;
|
||||
}
|
||||
obj->tx_buff.pos++;
|
||||
obj->spi.spi->TXDATA = data;
|
||||
}
|
||||
} else {
|
||||
// 9-bit frame
|
||||
if(obj->tx_buff.pos < obj->tx_buff.length - 3) {
|
||||
// write double frame
|
||||
if (obj->tx_buff.buffer == (void *)0) {
|
||||
data = ((SPI_FILL_WORD & 0x01FF) << 16) | (SPI_FILL_WORD & 0x1FF);
|
||||
} else {
|
||||
uint32_t *tx = (uint32_t *)(obj->tx_buff.buffer);
|
||||
data = tx[obj->tx_buff.pos / 4] & 0x01FF01FF;
|
||||
}
|
||||
obj->tx_buff.pos += 4;
|
||||
obj->spi.spi->TXDOUBLEX = data;
|
||||
} else if (obj->tx_buff.pos < obj->tx_buff.length - 1) {
|
||||
// write single frame
|
||||
if (obj->tx_buff.buffer == (void *)0) {
|
||||
data = SPI_FILL_WORD & 0x01FF;
|
||||
} else {
|
||||
uint16_t *tx = (uint16_t *)(obj->tx_buff.buffer);
|
||||
data = tx[obj->tx_buff.pos / 2] & 0x01FF;
|
||||
}
|
||||
obj->tx_buff.pos += 2;
|
||||
obj->spi.spi->TXDATAX = data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void spi_buffer_rx_read(spi_t *obj)
|
||||
{
|
||||
if (obj->spi.bits % 9 != 0) {
|
||||
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
|
||||
uint32_t data = (uint32_t)obj->spi.spi->RXDOUBLE; //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 & 0xFFFF;
|
||||
obj->rx_buff.pos += 2;
|
||||
}
|
||||
} else if ((obj->spi.spi->STATUS & (USART_STATUS_RXDATAV | USART_STATUS_RXFULL)) && (obj->rx_buff.pos < obj->rx_buff.length)) {
|
||||
// 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 ((obj->spi.spi->STATUS & USART_STATUS_RXFULL) && (obj->rx_buff.pos < obj->rx_buff.length - 3) && ((obj->rx_buff.pos % 4) == 0)) {
|
||||
// Read max 18 bits from buffer to speed things up
|
||||
uint32_t data = (uint32_t)obj->spi.spi->RXDOUBLEX; //read the data but store only if rx is set and will not overflow
|
||||
if (obj->rx_buff.buffer) {
|
||||
uint16_t *rx = (uint16_t *)(obj->rx_buff.buffer);
|
||||
rx[obj->rx_buff.pos / 2] = data & 0x000001FF;
|
||||
rx[(obj->rx_buff.pos / 2) + 1] = (data & 0x01FF0000) >> 16;
|
||||
obj->rx_buff.pos += 4;
|
||||
}
|
||||
} else if ((obj->spi.spi->STATUS & (USART_STATUS_RXDATAV | USART_STATUS_RXFULL)) && (obj->rx_buff.pos < obj->rx_buff.length - 1)) {
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
if (obj->spi.bits % 9 != 0) {
|
||||
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
|
||||
uint32_t data = (uint32_t)obj->spi.spi->RXDOUBLE; //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 & 0xFFFF;
|
||||
obj->rx_buff.pos += 2;
|
||||
}
|
||||
} else if ((obj->spi.spi->STATUS & (USART_STATUS_RXDATAV | USART_STATUS_RXFULL)) && (obj->rx_buff.pos < obj->rx_buff.length)) {
|
||||
// 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 ((obj->spi.spi->STATUS & USART_STATUS_RXFULL) && (obj->rx_buff.pos < obj->rx_buff.length - 3) && ((obj->rx_buff.pos % 4) == 0)) {
|
||||
// Read max 18 bits from buffer to speed things up
|
||||
uint32_t data = (uint32_t)obj->spi.spi->RXDOUBLEX; //read the data but store only if rx is set and will not overflow
|
||||
if (obj->rx_buff.buffer) {
|
||||
uint16_t *rx = (uint16_t *)(obj->rx_buff.buffer);
|
||||
rx[obj->rx_buff.pos / 2] = data & 0x000001FF;
|
||||
rx[(obj->rx_buff.pos / 2) + 1] = (data & 0x01FF0000) >> 16;
|
||||
obj->rx_buff.pos += 4;
|
||||
}
|
||||
} else if ((obj->spi.spi->STATUS & (USART_STATUS_RXDATAV | USART_STATUS_RXFULL)) && (obj->rx_buff.pos < obj->rx_buff.length - 1)) {
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int spi_master_write_asynch(spi_t *obj)
|
||||
|
@ -602,7 +603,7 @@ uint32_t spi_event_check(spi_t *obj)
|
|||
}
|
||||
|
||||
if(quit == true) {
|
||||
event |= SPI_EVENT_INTERNAL_TRANSFER_COMPLETE;
|
||||
event |= SPI_EVENT_INTERNAL_TRANSFER_COMPLETE;
|
||||
}
|
||||
|
||||
return event;
|
||||
|
@ -633,7 +634,8 @@ void transferComplete(unsigned int channel, bool primary, void *user)
|
|||
*
|
||||
* return value: whether the channels were acquired successfully (true) or not.
|
||||
******************************************/
|
||||
bool spi_allocate_dma(spi_t *obj) {
|
||||
bool spi_allocate_dma(spi_t *obj)
|
||||
{
|
||||
int dmaChannelIn, dmaChannelOut;
|
||||
dmaChannelIn = dma_channel_allocate(DMA_CAP_NONE);
|
||||
if (dmaChannelIn == DMA_ERROR_OUT_OF_CHANNELS) {
|
||||
|
@ -722,7 +724,7 @@ static void spi_master_dma_channel_setup(spi_t *obj, void* callback)
|
|||
txChnlCfg.enableInt = true;
|
||||
txChnlCfg.cb = &(obj->spi.dmaOptionsTX.dmaCallback);
|
||||
|
||||
switch ((int)obj->spi.spi) {
|
||||
switch ((int)obj->spi.spi) {
|
||||
#ifdef USART0
|
||||
case SPI_0:
|
||||
rxChnlCfg.select = DMAREQ_USART0_RXDATAV;
|
||||
|
@ -759,7 +761,8 @@ static void spi_master_dma_channel_setup(spi_t *obj, void* callback)
|
|||
* * tx_length: how many bytes will get sent.
|
||||
* * rx_length: how many bytes will get received. If > tx_length, TX will get padded with n lower bits of SPI_FILL_WORD.
|
||||
******************************************/
|
||||
static void spi_activate_dma(spi_t *obj, void* rxdata, void* txdata, int tx_length, int rx_length) {
|
||||
static void spi_activate_dma(spi_t *obj, void* rxdata, void* txdata, int tx_length, int rx_length)
|
||||
{
|
||||
/* DMA descriptors */
|
||||
DMA_CfgDescr_TypeDef rxDescrCfg;
|
||||
DMA_CfgDescr_TypeDef txDescrCfg;
|
||||
|
@ -768,81 +771,81 @@ static void spi_activate_dma(spi_t *obj, void* rxdata, void* txdata, int tx_leng
|
|||
obj->tx_buff.pos = tx_length;
|
||||
|
||||
if(obj->spi.bits != 9) {
|
||||
/* Only activate RX DMA if a receive buffer is specified */
|
||||
if (rxdata != NULL) {
|
||||
// Setting up channel descriptor
|
||||
rxDescrCfg.dstInc = dmaDataInc1;
|
||||
rxDescrCfg.srcInc = dmaDataIncNone;
|
||||
rxDescrCfg.size = dmaDataSize1;
|
||||
rxDescrCfg.arbRate = dmaArbitrate1;
|
||||
rxDescrCfg.hprot = 0;
|
||||
DMA_CfgDescr(obj->spi.dmaOptionsRX.dmaChannel, true, &rxDescrCfg);
|
||||
/* Only activate RX DMA if a receive buffer is specified */
|
||||
if (rxdata != NULL) {
|
||||
// Setting up channel descriptor
|
||||
rxDescrCfg.dstInc = dmaDataInc1;
|
||||
rxDescrCfg.srcInc = dmaDataIncNone;
|
||||
rxDescrCfg.size = dmaDataSize1;
|
||||
rxDescrCfg.arbRate = dmaArbitrate1;
|
||||
rxDescrCfg.hprot = 0;
|
||||
DMA_CfgDescr(obj->spi.dmaOptionsRX.dmaChannel, true, &rxDescrCfg);
|
||||
|
||||
// Clear RX registers - Useful if previous command transfered don't
|
||||
obj->spi.spi->CMD = USART_CMD_CLEARRX;
|
||||
// Clear RX registers - Useful if previous command transfered don't
|
||||
obj->spi.spi->CMD = USART_CMD_CLEARRX;
|
||||
|
||||
/* Activate RX channel */
|
||||
DMA_ActivateBasic(obj->spi.dmaOptionsRX.dmaChannel, true, false, rxdata, (void *)&(obj->spi.spi->RXDATA),
|
||||
rx_length - 1);
|
||||
}
|
||||
/* 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);
|
||||
// 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);
|
||||
|
||||
/* Clear TX registers */
|
||||
obj->spi.spi->CMD = USART_CMD_CLEARTX;
|
||||
/* Clear TX registers */
|
||||
obj->spi.spi->CMD = USART_CMD_CLEARTX;
|
||||
|
||||
/* 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 : txdata), // When there is nothing to transmit, point to static fill word
|
||||
(obj->spi.bits <= 8 ? tx_length - 1 : (tx_length / 2) - 1)); // When using TXDOUBLE, recalculate transfer length
|
||||
/* 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 : txdata), // When there is nothing to transmit, point to static fill word
|
||||
(obj->spi.bits <= 8 ? tx_length - 1 : (tx_length / 2) - 1)); // When using TXDOUBLE, recalculate transfer length
|
||||
} 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.srcInc = dmaDataIncNone;
|
||||
rxDescrCfg.size = dmaDataSize2;
|
||||
rxDescrCfg.arbRate = dmaArbitrate1;
|
||||
rxDescrCfg.hprot = 0;
|
||||
DMA_CfgDescr(obj->spi.dmaOptionsRX.dmaChannel, true, &rxDescrCfg);
|
||||
/* Frame size == 9 */
|
||||
/* Only activate RX DMA if a receive buffer is specified */
|
||||
if (rxdata != NULL) {
|
||||
// Setting up channel descriptor
|
||||
rxDescrCfg.dstInc = dmaDataInc2;
|
||||
rxDescrCfg.srcInc = dmaDataIncNone;
|
||||
rxDescrCfg.size = dmaDataSize2;
|
||||
rxDescrCfg.arbRate = dmaArbitrate1;
|
||||
rxDescrCfg.hprot = 0;
|
||||
DMA_CfgDescr(obj->spi.dmaOptionsRX.dmaChannel, true, &rxDescrCfg);
|
||||
|
||||
// Clear RX registers - Useful if previous command transfered don't
|
||||
obj->spi.spi->CMD = USART_CMD_CLEARRX;
|
||||
// Clear RX registers - Useful if previous command transfered don't
|
||||
obj->spi.spi->CMD = USART_CMD_CLEARRX;
|
||||
|
||||
/* Activate RX channel */
|
||||
DMA_ActivateBasic(obj->spi.dmaOptionsRX.dmaChannel, true, false, rxdata, (void *)&(obj->spi.spi->RXDATAX),
|
||||
(rx_length / 2) - 1);
|
||||
}
|
||||
/* Activate RX channel */
|
||||
DMA_ActivateBasic(obj->spi.dmaOptionsRX.dmaChannel, true, false, rxdata, (void *)&(obj->spi.spi->RXDATAX),
|
||||
(rx_length / 2) - 1);
|
||||
}
|
||||
|
||||
/* Setting up channel descriptor */
|
||||
txDescrCfg.dstInc = dmaDataIncNone;
|
||||
txDescrCfg.srcInc = (txdata == 0 ? dmaDataIncNone : dmaDataInc2); //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);
|
||||
/* Setting up channel descriptor */
|
||||
txDescrCfg.dstInc = dmaDataIncNone;
|
||||
txDescrCfg.srcInc = (txdata == 0 ? dmaDataIncNone : dmaDataInc2); //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);
|
||||
|
||||
/* Clear TX registers */
|
||||
obj->spi.spi->CMD = USART_CMD_CLEARTX;
|
||||
/* Clear TX registers */
|
||||
obj->spi.spi->CMD = USART_CMD_CLEARTX;
|
||||
|
||||
/* 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 : txdata), // When there is nothing to transmit, point to static fill word
|
||||
(tx_length / 2) - 1); // When using TXDOUBLE, recalculate transfer length
|
||||
/* 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 : txdata), // When there is nothing to transmit, point to static fill word
|
||||
(tx_length / 2) - 1); // When using TXDOUBLE, recalculate transfer length
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -863,9 +866,10 @@ static void spi_activate_dma(spi_t *obj, void* rxdata, void* txdata, int tx_leng
|
|||
* If the previous transfer has kept the channel, that channel will continue to get used.
|
||||
*
|
||||
********************************************************************/
|
||||
void spi_master_transfer_dma(spi_t *obj, void *txdata, void *rxdata, int tx_length, int rx_length, void* cb, DMAUsage hint) {
|
||||
/* Init DMA here to include it in the power figure */
|
||||
dma_init();
|
||||
void spi_master_transfer_dma(spi_t *obj, void *txdata, void *rxdata, int tx_length, int rx_length, void* cb, DMAUsage hint)
|
||||
{
|
||||
/* Init DMA here to include it in the power figure */
|
||||
dma_init();
|
||||
/* If the DMA channels are already allocated, we can assume they have been setup already */
|
||||
if (hint != DMA_USAGE_NEVER && obj->spi.dmaOptionsTX.dmaUsageState == DMA_USAGE_ALLOCATED) {
|
||||
/* setup has already been done, so just activate the transfer */
|
||||
|
@ -910,36 +914,37 @@ void spi_master_transfer_dma(spi_t *obj, void *txdata, void *rxdata, int tx_leng
|
|||
* @param[in] handler SPI interrupt handler
|
||||
* @param[in] hint A suggestion for how to use DMA with this transfer
|
||||
*/
|
||||
void spi_master_transfer(spi_t *obj, void *tx, size_t tx_length, void *rx, size_t rx_length, uint8_t bit_width, uint32_t handler, uint32_t event, DMAUsage hint) {
|
||||
if( spi_active(obj) ) return;
|
||||
void spi_master_transfer(spi_t *obj, void *tx, size_t tx_length, void *rx, size_t rx_length, uint8_t bit_width, uint32_t handler, uint32_t event, DMAUsage hint)
|
||||
{
|
||||
if( spi_active(obj) ) return;
|
||||
|
||||
/* update fill word if on 9-bit frame size */
|
||||
if(obj->spi.bits == 9) fill_word = SPI_FILL_WORD & 0x1FF;
|
||||
else fill_word = SPI_FILL_WORD;
|
||||
/* update fill word if on 9-bit frame size */
|
||||
if(obj->spi.bits == 9) fill_word = SPI_FILL_WORD & 0x1FF;
|
||||
else fill_word = SPI_FILL_WORD;
|
||||
|
||||
/* check corner case */
|
||||
if(tx_length == 0) {
|
||||
tx_length = rx_length;
|
||||
tx = (void*) 0;
|
||||
}
|
||||
/* check corner case */
|
||||
if(tx_length == 0) {
|
||||
tx_length = rx_length;
|
||||
tx = (void*) 0;
|
||||
}
|
||||
|
||||
/* First, set the buffer */
|
||||
spi_buffer_set(obj, tx, tx_length, rx, rx_length, bit_width);
|
||||
/* First, set the buffer */
|
||||
spi_buffer_set(obj, tx, tx_length, rx, rx_length, bit_width);
|
||||
|
||||
/* Then, enable the events */
|
||||
spi_enable_event(obj, SPI_EVENT_ALL, false);
|
||||
spi_enable_event(obj, event, true);
|
||||
/* Then, enable the events */
|
||||
spi_enable_event(obj, SPI_EVENT_ALL, false);
|
||||
spi_enable_event(obj, event, true);
|
||||
|
||||
/* Be tricky on how we handle increased bit widths in the buffer... Handling on byte-basis */
|
||||
// div 8 = shift right 3
|
||||
tx_length = tx_length * (bit_width >> 3);
|
||||
rx_length = rx_length * (bit_width >> 3);
|
||||
/* Be tricky on how we handle increased bit widths in the buffer... Handling on byte-basis */
|
||||
// div 8 = shift right 3
|
||||
tx_length = tx_length * (bit_width >> 3);
|
||||
rx_length = rx_length * (bit_width >> 3);
|
||||
|
||||
// Set the sleep mode
|
||||
blockSleepMode(SPI_LEAST_ACTIVE_SLEEPMODE);
|
||||
// Set the sleep mode
|
||||
blockSleepMode(SPI_LEAST_ACTIVE_SLEEPMODE);
|
||||
|
||||
/* And kick off the transfer */
|
||||
spi_master_transfer_dma(obj, tx, rx, tx_length, rx_length, (void*)handler, hint);
|
||||
/* And kick off the transfer */
|
||||
spi_master_transfer_dma(obj, tx, rx, tx_length, rx_length, (void*)handler, hint);
|
||||
}
|
||||
|
||||
|
||||
|
@ -953,7 +958,8 @@ void spi_master_transfer(spi_t *obj, void *tx, size_t tx_length, void *rx, size_
|
|||
* return: event mask. Currently only 0 or SPI_EVENT_COMPLETE upon transfer completion.
|
||||
*
|
||||
********************************************************************/
|
||||
uint32_t spi_irq_handler_asynch(spi_t* obj) {
|
||||
uint32_t spi_irq_handler_asynch(spi_t* obj)
|
||||
{
|
||||
|
||||
/* Determine whether the current scenario is DMA or IRQ, and act accordingly */
|
||||
|
||||
|
@ -962,56 +968,55 @@ uint32_t spi_irq_handler_asynch(spi_t* obj) {
|
|||
|
||||
/* If there is an RX transfer ongoing, wait for it to finish */
|
||||
if (DMA_ChannelEnabled(obj->spi.dmaOptionsRX.dmaChannel)) {
|
||||
/* 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)) {
|
||||
//Save state of TX transfer amount
|
||||
int length_diff = obj->rx_buff.length - obj->tx_buff.pos;
|
||||
obj->tx_buff.pos = obj->rx_buff.length;
|
||||
/* 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)) {
|
||||
//Save state of TX transfer amount
|
||||
int length_diff = obj->rx_buff.length - obj->tx_buff.pos;
|
||||
obj->tx_buff.pos = obj->rx_buff.length;
|
||||
|
||||
//Kick off a new DMA transfer
|
||||
DMA_CfgDescr_TypeDef txDescrCfg;
|
||||
//Kick off a new DMA transfer
|
||||
DMA_CfgDescr_TypeDef txDescrCfg;
|
||||
|
||||
if(obj->spi.bits != 9) {
|
||||
fill_word = SPI_FILL_WORD;
|
||||
/* Setting up channel descriptor */
|
||||
txDescrCfg.dstInc = dmaDataIncNone;
|
||||
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.arbRate = dmaArbitrate1;
|
||||
txDescrCfg.hprot = 0;
|
||||
DMA_CfgDescr(obj->spi.dmaOptionsTX.dmaChannel, true, &txDescrCfg);
|
||||
if(obj->spi.bits != 9) {
|
||||
fill_word = SPI_FILL_WORD;
|
||||
/* Setting up channel descriptor */
|
||||
txDescrCfg.dstInc = dmaDataIncNone;
|
||||
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.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
|
||||
&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 {
|
||||
/* Setting up channel descriptor */
|
||||
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);
|
||||
/* 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
|
||||
&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 {
|
||||
/* Setting up channel descriptor */
|
||||
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;
|
||||
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 */
|
||||
if (DMA_ChannelEnabled(obj->spi.dmaOptionsTX.dmaChannel)) {
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Release the dma channels if they were opportunistically allocated */
|
||||
|
@ -1054,7 +1059,8 @@ uint32_t spi_irq_handler_asynch(spi_t* obj) {
|
|||
*
|
||||
* @param obj The SPI peripheral to stop
|
||||
*/
|
||||
void spi_abort_asynch(spi_t *obj) {
|
||||
void spi_abort_asynch(spi_t *obj)
|
||||
{
|
||||
// If we're not currently transferring, then there's nothing to do here
|
||||
if(spi_active(obj) != 0) return;
|
||||
|
||||
|
|
Loading…
Reference in New Issue