mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #1130 from stevew817/master
Silicon Labs - Cosmetic: apply mbed coding style to HALpull/1132/head
commit
88d158e43b
|
@ -87,134 +87,134 @@ const PinMap PinMap_PWM[] = {
|
||||||
|
|
||||||
/*************SPI**************/
|
/*************SPI**************/
|
||||||
const PinMap PinMap_SPI_MOSI[] = {
|
const PinMap PinMap_SPI_MOSI[] = {
|
||||||
/* USART0 */
|
/* USART0 */
|
||||||
{PE10, SPI_0, 0},
|
{PE10, SPI_0, 0},
|
||||||
{PE7, SPI_0, 1},
|
{PE7, SPI_0, 1},
|
||||||
{PC11, SPI_0, 2},
|
{PC11, SPI_0, 2},
|
||||||
{PC0, SPI_0, 5},
|
{PC0, SPI_0, 5},
|
||||||
/* USART1 */
|
/* USART1 */
|
||||||
{PD0, SPI_1, 1},
|
{PD0, SPI_1, 1},
|
||||||
{PD7, SPI_1, 2},
|
{PD7, SPI_1, 2},
|
||||||
/* USART2 */
|
/* USART2 */
|
||||||
{PC2, SPI_2, 0},
|
{PC2, SPI_2, 0},
|
||||||
{PB3, SPI_2, 1},
|
{PB3, SPI_2, 1},
|
||||||
/* Not connected */
|
/* Not connected */
|
||||||
{NC , NC , NC}
|
{NC , NC , NC}
|
||||||
};
|
};
|
||||||
|
|
||||||
const PinMap PinMap_SPI_MISO[] = {
|
const PinMap PinMap_SPI_MISO[] = {
|
||||||
/* USART0 */
|
/* USART0 */
|
||||||
{PE11, SPI_0, 0},
|
{PE11, SPI_0, 0},
|
||||||
{PE6, SPI_0, 1},
|
{PE6, SPI_0, 1},
|
||||||
{PC10, SPI_0, 2},
|
{PC10, SPI_0, 2},
|
||||||
{PC1, SPI_0, 5},
|
{PC1, SPI_0, 5},
|
||||||
/* USART1 */
|
/* USART1 */
|
||||||
{PD1, SPI_1, 1},
|
{PD1, SPI_1, 1},
|
||||||
{PD6, SPI_1, 2},
|
{PD6, SPI_1, 2},
|
||||||
/* USART2 */
|
/* USART2 */
|
||||||
{PC3, SPI_2, 0},
|
{PC3, SPI_2, 0},
|
||||||
{PB4, SPI_2, 1},
|
{PB4, SPI_2, 1},
|
||||||
/* Not connected */
|
/* Not connected */
|
||||||
{NC , NC , NC}
|
{NC , NC , NC}
|
||||||
};
|
};
|
||||||
|
|
||||||
const PinMap PinMap_SPI_CLK[] = {
|
const PinMap PinMap_SPI_CLK[] = {
|
||||||
/* USART0 */
|
/* USART0 */
|
||||||
{PE12, SPI_0, 0},
|
{PE12, SPI_0, 0},
|
||||||
{PE5, SPI_0, 1},
|
{PE5, SPI_0, 1},
|
||||||
{PC9, SPI_0, 2},
|
{PC9, SPI_0, 2},
|
||||||
{PB13, SPI_0, 5},
|
{PB13, SPI_0, 5},
|
||||||
/* USART1 */
|
/* USART1 */
|
||||||
{PD2, SPI_1, 1},
|
{PD2, SPI_1, 1},
|
||||||
{PF0, SPI_1, 2},
|
{PF0, SPI_1, 2},
|
||||||
/* USART2 */
|
/* USART2 */
|
||||||
{PC4, SPI_2, 0},
|
{PC4, SPI_2, 0},
|
||||||
{PB5, SPI_2, 1},
|
{PB5, SPI_2, 1},
|
||||||
/* Not connected */
|
/* Not connected */
|
||||||
{NC , NC , NC}
|
{NC , NC , NC}
|
||||||
};
|
};
|
||||||
|
|
||||||
const PinMap PinMap_SPI_CS[] = {
|
const PinMap PinMap_SPI_CS[] = {
|
||||||
/* USART0 */
|
/* USART0 */
|
||||||
{PE13, SPI_0, 0},
|
{PE13, SPI_0, 0},
|
||||||
{PE4, SPI_0, 1},
|
{PE4, SPI_0, 1},
|
||||||
{PC8, SPI_0, 2},
|
{PC8, SPI_0, 2},
|
||||||
{PB14, SPI_0, 5},
|
{PB14, SPI_0, 5},
|
||||||
/* USART1 */
|
/* USART1 */
|
||||||
{PD3, SPI_1, 1},
|
{PD3, SPI_1, 1},
|
||||||
{PF1, SPI_1, 2},
|
{PF1, SPI_1, 2},
|
||||||
/* USART2 */
|
/* USART2 */
|
||||||
{PC5, SPI_2, 0},
|
{PC5, SPI_2, 0},
|
||||||
{PB6, SPI_2, 1},
|
{PB6, SPI_2, 1},
|
||||||
/* Not connected */
|
/* Not connected */
|
||||||
{NC , NC , NC}
|
{NC , NC , NC}
|
||||||
};
|
};
|
||||||
|
|
||||||
/************UART**************/
|
/************UART**************/
|
||||||
const PinMap PinMap_UART_TX[] = {
|
const PinMap PinMap_UART_TX[] = {
|
||||||
/* UART0 */
|
/* UART0 */
|
||||||
{PF6, UART_0, 0},
|
{PF6, UART_0, 0},
|
||||||
{PE0, UART_0, 1},
|
{PE0, UART_0, 1},
|
||||||
/* UART1 */
|
/* UART1 */
|
||||||
{PF10, UART_1, 1},
|
{PF10, UART_1, 1},
|
||||||
{PB9, UART_1, 2},
|
{PB9, UART_1, 2},
|
||||||
{PE2, UART_1, 3},
|
{PE2, UART_1, 3},
|
||||||
/* USART0 */
|
/* USART0 */
|
||||||
{PE10, USART_0, 0},
|
{PE10, USART_0, 0},
|
||||||
{PE7, USART_0, 1},
|
{PE7, USART_0, 1},
|
||||||
{PC11, USART_0, 2},
|
{PC11, USART_0, 2},
|
||||||
{PE13, USART_0, 3},
|
{PE13, USART_0, 3},
|
||||||
{PB7, USART_0, 4},
|
{PB7, USART_0, 4},
|
||||||
/* USART1 */
|
/* USART1 */
|
||||||
{PC0, USART_1, 0},
|
{PC0, USART_1, 0},
|
||||||
{PD0, USART_1, 1},
|
{PD0, USART_1, 1},
|
||||||
{PD7, USART_1, 2},
|
{PD7, USART_1, 2},
|
||||||
/* USART2 */
|
/* USART2 */
|
||||||
{PC2, USART_2, 0},
|
{PC2, USART_2, 0},
|
||||||
{PB3, USART_2, 1},
|
{PB3, USART_2, 1},
|
||||||
/* LEUART0 */
|
/* LEUART0 */
|
||||||
{PD4, LEUART_0, 0},
|
{PD4, LEUART_0, 0},
|
||||||
{PB13, LEUART_0, 1},
|
{PB13, LEUART_0, 1},
|
||||||
{PE14, LEUART_0, 2},
|
{PE14, LEUART_0, 2},
|
||||||
{PF0, LEUART_0, 3},
|
{PF0, LEUART_0, 3},
|
||||||
{PF2, LEUART_0, 4},
|
{PF2, LEUART_0, 4},
|
||||||
/* LEUART1 */
|
/* LEUART1 */
|
||||||
{PC6, LEUART_1, 0},
|
{PC6, LEUART_1, 0},
|
||||||
{PA5, LEUART_1, 1},
|
{PA5, LEUART_1, 1},
|
||||||
/* Not connected */
|
/* Not connected */
|
||||||
{NC , NC , NC}
|
{NC , NC , NC}
|
||||||
};
|
};
|
||||||
|
|
||||||
const PinMap PinMap_UART_RX[] = {
|
const PinMap PinMap_UART_RX[] = {
|
||||||
/* UART0 */
|
/* UART0 */
|
||||||
{PF7, UART_0, 0},
|
{PF7, UART_0, 0},
|
||||||
{PE1, UART_0, 1},
|
{PE1, UART_0, 1},
|
||||||
/* UART1 */
|
/* UART1 */
|
||||||
{PF11, UART_1, 1},
|
{PF11, UART_1, 1},
|
||||||
{PB10, UART_1, 2},
|
{PB10, UART_1, 2},
|
||||||
{PE3, UART_1, 3},
|
{PE3, UART_1, 3},
|
||||||
/* USART0 */
|
/* USART0 */
|
||||||
{PE11, USART_0, 0},
|
{PE11, USART_0, 0},
|
||||||
{PE6, USART_0, 1},
|
{PE6, USART_0, 1},
|
||||||
{PC10, USART_0, 2},
|
{PC10, USART_0, 2},
|
||||||
{PE12, USART_0, 3},
|
{PE12, USART_0, 3},
|
||||||
{PB8, USART_0, 4},
|
{PB8, USART_0, 4},
|
||||||
/* USART1 */
|
/* USART1 */
|
||||||
{PC1, USART_1, 0},
|
{PC1, USART_1, 0},
|
||||||
{PD1, USART_1, 1},
|
{PD1, USART_1, 1},
|
||||||
{PD6, USART_1, 2},
|
{PD6, USART_1, 2},
|
||||||
/* USART2 */
|
/* USART2 */
|
||||||
{PC3, USART_2, 0},
|
{PC3, USART_2, 0},
|
||||||
{PB4, USART_2, 1},
|
{PB4, USART_2, 1},
|
||||||
/* LEUART0 */
|
/* LEUART0 */
|
||||||
{PD5, LEUART_0, 0},
|
{PD5, LEUART_0, 0},
|
||||||
{PB14, LEUART_0, 1},
|
{PB14, LEUART_0, 1},
|
||||||
{PE15, LEUART_0, 2},
|
{PE15, LEUART_0, 2},
|
||||||
{PF1, LEUART_0, 3},
|
{PF1, LEUART_0, 3},
|
||||||
{PA0, LEUART_0, 4},
|
{PA0, LEUART_0, 4},
|
||||||
/* LEUART1 */
|
/* LEUART1 */
|
||||||
{PC7, LEUART_1, 0},
|
{PC7, LEUART_1, 0},
|
||||||
{PA6, LEUART_1, 1},
|
{PA6, LEUART_1, 1},
|
||||||
/* Not connected */
|
/* Not connected */
|
||||||
{NC , NC , NC}
|
{NC , NC , NC}
|
||||||
};
|
};
|
||||||
|
|
|
@ -60,109 +60,109 @@ const PinMap PinMap_PWM[] = {
|
||||||
|
|
||||||
/*************SPI**************/
|
/*************SPI**************/
|
||||||
const PinMap PinMap_SPI_MOSI[] = {
|
const PinMap PinMap_SPI_MOSI[] = {
|
||||||
/* USART0 */
|
/* USART0 */
|
||||||
{PE10, SPI_0, 0},
|
{PE10, SPI_0, 0},
|
||||||
//{NC, SPI_0, 2}, /* SPI_0 loc2 is not bonded */
|
//{NC, SPI_0, 2}, /* SPI_0 loc2 is not bonded */
|
||||||
{PE13, SPI_0, 3},
|
{PE13, SPI_0, 3},
|
||||||
{PB7, SPI_0, 4},
|
{PB7, SPI_0, 4},
|
||||||
|
|
||||||
/* USART1 */
|
/* USART1 */
|
||||||
{PC0, SPI_1, 0},
|
{PC0, SPI_1, 0},
|
||||||
{PD7, SPI_1, 3},
|
{PD7, SPI_1, 3},
|
||||||
{PF2, SPI_1, 4},
|
{PF2, SPI_1, 4},
|
||||||
|
|
||||||
/* Not connected */
|
/* Not connected */
|
||||||
{NC , NC , NC}
|
{NC , NC , NC}
|
||||||
};
|
};
|
||||||
|
|
||||||
const PinMap PinMap_SPI_MISO[] = {
|
const PinMap PinMap_SPI_MISO[] = {
|
||||||
/* USART0 */
|
/* USART0 */
|
||||||
{PE11, SPI_0, 0},
|
{PE11, SPI_0, 0},
|
||||||
{PC10, SPI_0, 2},
|
{PC10, SPI_0, 2},
|
||||||
{PE12, SPI_0, 3},
|
{PE12, SPI_0, 3},
|
||||||
{PB8, SPI_0, 4},
|
{PB8, SPI_0, 4},
|
||||||
|
|
||||||
/* USART1 */
|
/* USART1 */
|
||||||
{PC1, SPI_1, 0},
|
{PC1, SPI_1, 0},
|
||||||
{PD6, SPI_1, 3},
|
{PD6, SPI_1, 3},
|
||||||
{PA0, SPI_1, 4},
|
{PA0, SPI_1, 4},
|
||||||
|
|
||||||
/* Not connected */
|
/* Not connected */
|
||||||
{NC , NC , NC}
|
{NC , NC , NC}
|
||||||
};
|
};
|
||||||
|
|
||||||
const PinMap PinMap_SPI_CLK[] = {
|
const PinMap PinMap_SPI_CLK[] = {
|
||||||
/* USART0 */
|
/* USART0 */
|
||||||
{PE12, SPI_0, 0},
|
{PE12, SPI_0, 0},
|
||||||
{PC9, SPI_0, 2},
|
{PC9, SPI_0, 2},
|
||||||
//{PC15, SPI_0, 3}, /* Conflict with SPI_0 loc4 */
|
//{PC15, SPI_0, 3}, /* Conflict with SPI_0 loc4 */
|
||||||
{PB13, SPI_0, 4},
|
{PB13, SPI_0, 4},
|
||||||
|
|
||||||
/* USART1 */
|
/* USART1 */
|
||||||
{PB7, SPI_1, 0},
|
{PB7, SPI_1, 0},
|
||||||
{PC15, SPI_1, 3},
|
{PC15, SPI_1, 3},
|
||||||
{PB11, SPI_1, 4},
|
{PB11, SPI_1, 4},
|
||||||
|
|
||||||
/* Not connected */
|
/* Not connected */
|
||||||
{NC , NC , NC}
|
{NC , NC , NC}
|
||||||
};
|
};
|
||||||
|
|
||||||
const PinMap PinMap_SPI_CS[] = {
|
const PinMap PinMap_SPI_CS[] = {
|
||||||
/* USART0 */
|
/* USART0 */
|
||||||
{PE13, SPI_0, 0},
|
{PE13, SPI_0, 0},
|
||||||
{PC8, SPI_0, 2},
|
{PC8, SPI_0, 2},
|
||||||
//{PC14, SPI_0, 3}, /* Conflict with SPI_1 loc3 */
|
//{PC14, SPI_0, 3}, /* Conflict with SPI_1 loc3 */
|
||||||
{PB14, SPI_0, 4},
|
{PB14, SPI_0, 4},
|
||||||
|
|
||||||
/* USART1 */
|
/* USART1 */
|
||||||
{PB8, SPI_1, 0},
|
{PB8, SPI_1, 0},
|
||||||
{PC14, SPI_1, 3},
|
{PC14, SPI_1, 3},
|
||||||
|
|
||||||
/* Not connected */
|
/* Not connected */
|
||||||
{NC , NC , NC}
|
{NC , NC , NC}
|
||||||
};
|
};
|
||||||
|
|
||||||
/************UART**************/
|
/************UART**************/
|
||||||
const PinMap PinMap_UART_TX[] = {
|
const PinMap PinMap_UART_TX[] = {
|
||||||
/* USART0 */
|
/* USART0 */
|
||||||
{PE10, USART_0, 0},
|
{PE10, USART_0, 0},
|
||||||
//{NC, USART_0, 2}, /* USART_0 loc2 is not bonded */
|
//{NC, USART_0, 2}, /* USART_0 loc2 is not bonded */
|
||||||
{PE13, USART_0, 3},
|
{PE13, USART_0, 3},
|
||||||
{PB7, USART_0, 4},
|
{PB7, USART_0, 4},
|
||||||
|
|
||||||
/* USART1 */
|
/* USART1 */
|
||||||
{PC0, USART_1, 0},
|
{PC0, USART_1, 0},
|
||||||
{PD7, USART_1, 3},
|
{PD7, USART_1, 3},
|
||||||
{PF2, USART_1, 4},
|
{PF2, USART_1, 4},
|
||||||
|
|
||||||
/* LEUART0 */
|
/* LEUART0 */
|
||||||
{PD4, LEUART_0, 0},
|
{PD4, LEUART_0, 0},
|
||||||
{PB13, LEUART_0, 1},
|
{PB13, LEUART_0, 1},
|
||||||
{PF0, LEUART_0, 3},
|
{PF0, LEUART_0, 3},
|
||||||
{PC14, LEUART_0, 5},
|
{PC14, LEUART_0, 5},
|
||||||
|
|
||||||
/* Not connected */
|
/* Not connected */
|
||||||
{NC , NC , NC}
|
{NC , NC , NC}
|
||||||
};
|
};
|
||||||
|
|
||||||
const PinMap PinMap_UART_RX[] = {
|
const PinMap PinMap_UART_RX[] = {
|
||||||
/* USART0 */
|
/* USART0 */
|
||||||
{PE11, USART_0, 0},
|
{PE11, USART_0, 0},
|
||||||
//{PC10, USART_0, 2},
|
//{PC10, USART_0, 2},
|
||||||
{PE12, USART_0, 3},
|
{PE12, USART_0, 3},
|
||||||
{PB8, USART_0, 4},
|
{PB8, USART_0, 4},
|
||||||
|
|
||||||
/* USART1 */
|
/* USART1 */
|
||||||
{PC1, USART_1, 0},
|
{PC1, USART_1, 0},
|
||||||
{PD6, USART_1, 3},
|
{PD6, USART_1, 3},
|
||||||
{PA0, USART_1, 4},
|
{PA0, USART_1, 4},
|
||||||
|
|
||||||
/* LEUART0 */
|
/* LEUART0 */
|
||||||
{PD5, LEUART_0, 0},
|
{PD5, LEUART_0, 0},
|
||||||
{PB14, LEUART_0, 1},
|
{PB14, LEUART_0, 1},
|
||||||
{PF1, LEUART_0, 3},
|
{PF1, LEUART_0, 3},
|
||||||
{PC15, LEUART_0, 5},
|
{PC15, LEUART_0, 5},
|
||||||
|
|
||||||
/* Not connected */
|
/* Not connected */
|
||||||
{NC , NC , NC}
|
{NC , NC , NC}
|
||||||
};
|
};
|
||||||
|
|
|
@ -87,134 +87,134 @@ const PinMap PinMap_PWM[] = {
|
||||||
|
|
||||||
/*************SPI**************/
|
/*************SPI**************/
|
||||||
const PinMap PinMap_SPI_MOSI[] = {
|
const PinMap PinMap_SPI_MOSI[] = {
|
||||||
/* USART0 */
|
/* USART0 */
|
||||||
{PE10, SPI_0, 0},
|
{PE10, SPI_0, 0},
|
||||||
{PE7, SPI_0, 1},
|
{PE7, SPI_0, 1},
|
||||||
{PC11, SPI_0, 2},
|
{PC11, SPI_0, 2},
|
||||||
{PC0, SPI_0, 5},
|
{PC0, SPI_0, 5},
|
||||||
/* USART1 */
|
/* USART1 */
|
||||||
{PD0, SPI_1, 1},
|
{PD0, SPI_1, 1},
|
||||||
{PD7, SPI_1, 2},
|
{PD7, SPI_1, 2},
|
||||||
/* USART2 */
|
/* USART2 */
|
||||||
{PC2, SPI_2, 0},
|
{PC2, SPI_2, 0},
|
||||||
{PB3, SPI_2, 1},
|
{PB3, SPI_2, 1},
|
||||||
/* Not connected */
|
/* Not connected */
|
||||||
{NC , NC , NC}
|
{NC , NC , NC}
|
||||||
};
|
};
|
||||||
|
|
||||||
const PinMap PinMap_SPI_MISO[] = {
|
const PinMap PinMap_SPI_MISO[] = {
|
||||||
/* USART0 */
|
/* USART0 */
|
||||||
{PE11, SPI_0, 0},
|
{PE11, SPI_0, 0},
|
||||||
{PE6, SPI_0, 1},
|
{PE6, SPI_0, 1},
|
||||||
{PC10, SPI_0, 2},
|
{PC10, SPI_0, 2},
|
||||||
{PC1, SPI_0, 5},
|
{PC1, SPI_0, 5},
|
||||||
/* USART1 */
|
/* USART1 */
|
||||||
{PD1, SPI_1, 1},
|
{PD1, SPI_1, 1},
|
||||||
{PD6, SPI_1, 2},
|
{PD6, SPI_1, 2},
|
||||||
/* USART2 */
|
/* USART2 */
|
||||||
{PC3, SPI_2, 0},
|
{PC3, SPI_2, 0},
|
||||||
{PB4, SPI_2, 1},
|
{PB4, SPI_2, 1},
|
||||||
/* Not connected */
|
/* Not connected */
|
||||||
{NC , NC , NC}
|
{NC , NC , NC}
|
||||||
};
|
};
|
||||||
|
|
||||||
const PinMap PinMap_SPI_CLK[] = {
|
const PinMap PinMap_SPI_CLK[] = {
|
||||||
/* USART0 */
|
/* USART0 */
|
||||||
{PE12, SPI_0, 0},
|
{PE12, SPI_0, 0},
|
||||||
{PE5, SPI_0, 1},
|
{PE5, SPI_0, 1},
|
||||||
{PC9, SPI_0, 2},
|
{PC9, SPI_0, 2},
|
||||||
{PB13, SPI_0, 5},
|
{PB13, SPI_0, 5},
|
||||||
/* USART1 */
|
/* USART1 */
|
||||||
{PD2, SPI_1, 1},
|
{PD2, SPI_1, 1},
|
||||||
{PF0, SPI_1, 2},
|
{PF0, SPI_1, 2},
|
||||||
/* USART2 */
|
/* USART2 */
|
||||||
{PC4, SPI_2, 0},
|
{PC4, SPI_2, 0},
|
||||||
{PB5, SPI_2, 1},
|
{PB5, SPI_2, 1},
|
||||||
/* Not connected */
|
/* Not connected */
|
||||||
{NC , NC , NC}
|
{NC , NC , NC}
|
||||||
};
|
};
|
||||||
|
|
||||||
const PinMap PinMap_SPI_CS[] = {
|
const PinMap PinMap_SPI_CS[] = {
|
||||||
/* USART0 */
|
/* USART0 */
|
||||||
{PE13, SPI_0, 0},
|
{PE13, SPI_0, 0},
|
||||||
{PE4, SPI_0, 1},
|
{PE4, SPI_0, 1},
|
||||||
{PC8, SPI_0, 2},
|
{PC8, SPI_0, 2},
|
||||||
{PB14, SPI_0, 5},
|
{PB14, SPI_0, 5},
|
||||||
/* USART1 */
|
/* USART1 */
|
||||||
{PD3, SPI_1, 1},
|
{PD3, SPI_1, 1},
|
||||||
{PF1, SPI_1, 2},
|
{PF1, SPI_1, 2},
|
||||||
/* USART2 */
|
/* USART2 */
|
||||||
{PC5, SPI_2, 0},
|
{PC5, SPI_2, 0},
|
||||||
{PB6, SPI_2, 1},
|
{PB6, SPI_2, 1},
|
||||||
/* Not connected */
|
/* Not connected */
|
||||||
{NC , NC , NC}
|
{NC , NC , NC}
|
||||||
};
|
};
|
||||||
|
|
||||||
/************UART**************/
|
/************UART**************/
|
||||||
const PinMap PinMap_UART_TX[] = {
|
const PinMap PinMap_UART_TX[] = {
|
||||||
/* UART0 */
|
/* UART0 */
|
||||||
{PF6, UART_0, 0},
|
{PF6, UART_0, 0},
|
||||||
{PE0, UART_0, 1},
|
{PE0, UART_0, 1},
|
||||||
/* UART1 */
|
/* UART1 */
|
||||||
{PF10, UART_1, 1},
|
{PF10, UART_1, 1},
|
||||||
{PB9, UART_1, 2},
|
{PB9, UART_1, 2},
|
||||||
{PE2, UART_1, 3},
|
{PE2, UART_1, 3},
|
||||||
/* USART0 */
|
/* USART0 */
|
||||||
{PE10, USART_0, 0},
|
{PE10, USART_0, 0},
|
||||||
{PE7, USART_0, 1},
|
{PE7, USART_0, 1},
|
||||||
{PC11, USART_0, 2},
|
{PC11, USART_0, 2},
|
||||||
{PE13, USART_0, 3},
|
{PE13, USART_0, 3},
|
||||||
{PB7, USART_0, 4},
|
{PB7, USART_0, 4},
|
||||||
/* USART1 */
|
/* USART1 */
|
||||||
{PC0, USART_1, 0},
|
{PC0, USART_1, 0},
|
||||||
{PD0, USART_1, 1},
|
{PD0, USART_1, 1},
|
||||||
{PD7, USART_1, 2},
|
{PD7, USART_1, 2},
|
||||||
/* USART2 */
|
/* USART2 */
|
||||||
{PC2, USART_2, 0},
|
{PC2, USART_2, 0},
|
||||||
{PB3, USART_2, 1},
|
{PB3, USART_2, 1},
|
||||||
/* LEUART0 */
|
/* LEUART0 */
|
||||||
{PD4, LEUART_0, 0},
|
{PD4, LEUART_0, 0},
|
||||||
{PB13, LEUART_0, 1},
|
{PB13, LEUART_0, 1},
|
||||||
{PE14, LEUART_0, 2},
|
{PE14, LEUART_0, 2},
|
||||||
{PF0, LEUART_0, 3},
|
{PF0, LEUART_0, 3},
|
||||||
{PF2, LEUART_0, 4},
|
{PF2, LEUART_0, 4},
|
||||||
/* LEUART1 */
|
/* LEUART1 */
|
||||||
{PC6, LEUART_1, 0},
|
{PC6, LEUART_1, 0},
|
||||||
{PA5, LEUART_1, 1},
|
{PA5, LEUART_1, 1},
|
||||||
/* Not connected */
|
/* Not connected */
|
||||||
{NC , NC , NC}
|
{NC , NC , NC}
|
||||||
};
|
};
|
||||||
|
|
||||||
const PinMap PinMap_UART_RX[] = {
|
const PinMap PinMap_UART_RX[] = {
|
||||||
/* UART0 */
|
/* UART0 */
|
||||||
{PF7, UART_0, 0},
|
{PF7, UART_0, 0},
|
||||||
{PE1, UART_0, 1},
|
{PE1, UART_0, 1},
|
||||||
/* UART1 */
|
/* UART1 */
|
||||||
{PF11, UART_1, 1},
|
{PF11, UART_1, 1},
|
||||||
{PB10, UART_1, 2},
|
{PB10, UART_1, 2},
|
||||||
{PE3, UART_1, 3},
|
{PE3, UART_1, 3},
|
||||||
/* USART0 */
|
/* USART0 */
|
||||||
{PE11, USART_0, 0},
|
{PE11, USART_0, 0},
|
||||||
{PE6, USART_0, 1},
|
{PE6, USART_0, 1},
|
||||||
{PC10, USART_0, 2},
|
{PC10, USART_0, 2},
|
||||||
{PE12, USART_0, 3},
|
{PE12, USART_0, 3},
|
||||||
{PB8, USART_0, 4},
|
{PB8, USART_0, 4},
|
||||||
/* USART1 */
|
/* USART1 */
|
||||||
{PC1, USART_1, 0},
|
{PC1, USART_1, 0},
|
||||||
{PD1, USART_1, 1},
|
{PD1, USART_1, 1},
|
||||||
{PD6, USART_1, 2},
|
{PD6, USART_1, 2},
|
||||||
/* USART2 */
|
/* USART2 */
|
||||||
{PC3, USART_2, 0},
|
{PC3, USART_2, 0},
|
||||||
{PB4, USART_2, 1},
|
{PB4, USART_2, 1},
|
||||||
/* LEUART0 */
|
/* LEUART0 */
|
||||||
{PD5, LEUART_0, 0},
|
{PD5, LEUART_0, 0},
|
||||||
{PB14, LEUART_0, 1},
|
{PB14, LEUART_0, 1},
|
||||||
{PE15, LEUART_0, 2},
|
{PE15, LEUART_0, 2},
|
||||||
{PF1, LEUART_0, 3},
|
{PF1, LEUART_0, 3},
|
||||||
{PA0, LEUART_0, 4},
|
{PA0, LEUART_0, 4},
|
||||||
/* LEUART1 */
|
/* LEUART1 */
|
||||||
{PC7, LEUART_1, 0},
|
{PC7, LEUART_1, 0},
|
||||||
{PA6, LEUART_1, 1},
|
{PA6, LEUART_1, 1},
|
||||||
/* Not connected */
|
/* Not connected */
|
||||||
{NC , NC , NC}
|
{NC , NC , NC}
|
||||||
};
|
};
|
||||||
|
|
|
@ -92,8 +92,8 @@ typedef enum {
|
||||||
/* mbed modes:
|
/* mbed modes:
|
||||||
* PullUp, PullDown, PullNone, OpenDrain
|
* PullUp, PullDown, PullNone, OpenDrain
|
||||||
*
|
*
|
||||||
* mbed default digital input mode:
|
* mbed default digital input mode:
|
||||||
* PullDefault
|
* PullDefault
|
||||||
*
|
*
|
||||||
* mbed default digital output mode:
|
* mbed default digital output mode:
|
||||||
* PullNone
|
* PullNone
|
||||||
|
|
|
@ -87,134 +87,134 @@ const PinMap PinMap_PWM[] = {
|
||||||
|
|
||||||
/*************SPI**************/
|
/*************SPI**************/
|
||||||
const PinMap PinMap_SPI_MOSI[] = {
|
const PinMap PinMap_SPI_MOSI[] = {
|
||||||
/* USART0 */
|
/* USART0 */
|
||||||
{PE10, SPI_0, 0},
|
{PE10, SPI_0, 0},
|
||||||
{PE7, SPI_0, 1},
|
{PE7, SPI_0, 1},
|
||||||
{PC11, SPI_0, 2},
|
{PC11, SPI_0, 2},
|
||||||
{PC0, SPI_0, 5},
|
{PC0, SPI_0, 5},
|
||||||
/* USART1 */
|
/* USART1 */
|
||||||
{PD0, SPI_1, 1},
|
{PD0, SPI_1, 1},
|
||||||
{PD7, SPI_1, 2},
|
{PD7, SPI_1, 2},
|
||||||
/* USART2 */
|
/* USART2 */
|
||||||
{PC2, SPI_2, 0},
|
{PC2, SPI_2, 0},
|
||||||
{PB3, SPI_2, 1},
|
{PB3, SPI_2, 1},
|
||||||
/* Not connected */
|
/* Not connected */
|
||||||
{NC , NC , NC}
|
{NC , NC , NC}
|
||||||
};
|
};
|
||||||
|
|
||||||
const PinMap PinMap_SPI_MISO[] = {
|
const PinMap PinMap_SPI_MISO[] = {
|
||||||
/* USART0 */
|
/* USART0 */
|
||||||
{PE11, SPI_0, 0},
|
{PE11, SPI_0, 0},
|
||||||
{PE6, SPI_0, 1},
|
{PE6, SPI_0, 1},
|
||||||
{PC10, SPI_0, 2},
|
{PC10, SPI_0, 2},
|
||||||
{PC1, SPI_0, 5},
|
{PC1, SPI_0, 5},
|
||||||
/* USART1 */
|
/* USART1 */
|
||||||
{PD1, SPI_1, 1},
|
{PD1, SPI_1, 1},
|
||||||
{PD6, SPI_1, 2},
|
{PD6, SPI_1, 2},
|
||||||
/* USART2 */
|
/* USART2 */
|
||||||
{PC3, SPI_2, 0},
|
{PC3, SPI_2, 0},
|
||||||
{PB4, SPI_2, 1},
|
{PB4, SPI_2, 1},
|
||||||
/* Not connected */
|
/* Not connected */
|
||||||
{NC , NC , NC}
|
{NC , NC , NC}
|
||||||
};
|
};
|
||||||
|
|
||||||
const PinMap PinMap_SPI_CLK[] = {
|
const PinMap PinMap_SPI_CLK[] = {
|
||||||
/* USART0 */
|
/* USART0 */
|
||||||
{PE12, SPI_0, 0},
|
{PE12, SPI_0, 0},
|
||||||
{PE5, SPI_0, 1},
|
{PE5, SPI_0, 1},
|
||||||
{PC9, SPI_0, 2},
|
{PC9, SPI_0, 2},
|
||||||
{PB13, SPI_0, 5},
|
{PB13, SPI_0, 5},
|
||||||
/* USART1 */
|
/* USART1 */
|
||||||
{PD2, SPI_1, 1},
|
{PD2, SPI_1, 1},
|
||||||
{PF0, SPI_1, 2},
|
{PF0, SPI_1, 2},
|
||||||
/* USART2 */
|
/* USART2 */
|
||||||
{PC4, SPI_2, 0},
|
{PC4, SPI_2, 0},
|
||||||
{PB5, SPI_2, 1},
|
{PB5, SPI_2, 1},
|
||||||
/* Not connected */
|
/* Not connected */
|
||||||
{NC , NC , NC}
|
{NC , NC , NC}
|
||||||
};
|
};
|
||||||
|
|
||||||
const PinMap PinMap_SPI_CS[] = {
|
const PinMap PinMap_SPI_CS[] = {
|
||||||
/* USART0 */
|
/* USART0 */
|
||||||
{PE13, SPI_0, 0},
|
{PE13, SPI_0, 0},
|
||||||
{PE4, SPI_0, 1},
|
{PE4, SPI_0, 1},
|
||||||
{PC8, SPI_0, 2},
|
{PC8, SPI_0, 2},
|
||||||
{PB14, SPI_0, 5},
|
{PB14, SPI_0, 5},
|
||||||
/* USART1 */
|
/* USART1 */
|
||||||
{PD3, SPI_1, 1},
|
{PD3, SPI_1, 1},
|
||||||
{PF1, SPI_1, 2},
|
{PF1, SPI_1, 2},
|
||||||
/* USART2 */
|
/* USART2 */
|
||||||
{PC5, SPI_2, 0},
|
{PC5, SPI_2, 0},
|
||||||
{PB6, SPI_2, 1},
|
{PB6, SPI_2, 1},
|
||||||
/* Not connected */
|
/* Not connected */
|
||||||
{NC , NC , NC}
|
{NC , NC , NC}
|
||||||
};
|
};
|
||||||
|
|
||||||
/************UART**************/
|
/************UART**************/
|
||||||
const PinMap PinMap_UART_TX[] = {
|
const PinMap PinMap_UART_TX[] = {
|
||||||
/* UART0 */
|
/* UART0 */
|
||||||
{PF6, UART_0, 0},
|
{PF6, UART_0, 0},
|
||||||
{PE0, UART_0, 1},
|
{PE0, UART_0, 1},
|
||||||
/* UART1 */
|
/* UART1 */
|
||||||
{PF10, UART_1, 1},
|
{PF10, UART_1, 1},
|
||||||
{PB9, UART_1, 2},
|
{PB9, UART_1, 2},
|
||||||
{PE2, UART_1, 3},
|
{PE2, UART_1, 3},
|
||||||
/* USART0 */
|
/* USART0 */
|
||||||
{PE10, USART_0, 0},
|
{PE10, USART_0, 0},
|
||||||
{PE7, USART_0, 1},
|
{PE7, USART_0, 1},
|
||||||
{PC11, USART_0, 2},
|
{PC11, USART_0, 2},
|
||||||
{PE13, USART_0, 3},
|
{PE13, USART_0, 3},
|
||||||
{PB7, USART_0, 4},
|
{PB7, USART_0, 4},
|
||||||
/* USART1 */
|
/* USART1 */
|
||||||
{PC0, USART_1, 0},
|
{PC0, USART_1, 0},
|
||||||
{PD0, USART_1, 1},
|
{PD0, USART_1, 1},
|
||||||
{PD7, USART_1, 2},
|
{PD7, USART_1, 2},
|
||||||
/* USART2 */
|
/* USART2 */
|
||||||
{PC2, USART_2, 0},
|
{PC2, USART_2, 0},
|
||||||
{PB3, USART_2, 1},
|
{PB3, USART_2, 1},
|
||||||
/* LEUART0 */
|
/* LEUART0 */
|
||||||
{PD4, LEUART_0, 0},
|
{PD4, LEUART_0, 0},
|
||||||
{PB13, LEUART_0, 1},
|
{PB13, LEUART_0, 1},
|
||||||
{PE14, LEUART_0, 2},
|
{PE14, LEUART_0, 2},
|
||||||
{PF0, LEUART_0, 3},
|
{PF0, LEUART_0, 3},
|
||||||
{PF2, LEUART_0, 4},
|
{PF2, LEUART_0, 4},
|
||||||
/* LEUART1 */
|
/* LEUART1 */
|
||||||
{PC6, LEUART_1, 0},
|
{PC6, LEUART_1, 0},
|
||||||
{PA5, LEUART_1, 1},
|
{PA5, LEUART_1, 1},
|
||||||
/* Not connected */
|
/* Not connected */
|
||||||
{NC , NC , NC}
|
{NC , NC , NC}
|
||||||
};
|
};
|
||||||
|
|
||||||
const PinMap PinMap_UART_RX[] = {
|
const PinMap PinMap_UART_RX[] = {
|
||||||
/* UART0 */
|
/* UART0 */
|
||||||
{PF7, UART_0, 0},
|
{PF7, UART_0, 0},
|
||||||
{PE1, UART_0, 1},
|
{PE1, UART_0, 1},
|
||||||
/* UART1 */
|
/* UART1 */
|
||||||
{PF11, UART_1, 1},
|
{PF11, UART_1, 1},
|
||||||
{PB10, UART_1, 2},
|
{PB10, UART_1, 2},
|
||||||
{PE3, UART_1, 3},
|
{PE3, UART_1, 3},
|
||||||
/* USART0 */
|
/* USART0 */
|
||||||
{PE11, USART_0, 0},
|
{PE11, USART_0, 0},
|
||||||
{PE6, USART_0, 1},
|
{PE6, USART_0, 1},
|
||||||
{PC10, USART_0, 2},
|
{PC10, USART_0, 2},
|
||||||
{PE12, USART_0, 3},
|
{PE12, USART_0, 3},
|
||||||
{PB8, USART_0, 4},
|
{PB8, USART_0, 4},
|
||||||
/* USART1 */
|
/* USART1 */
|
||||||
{PC1, USART_1, 0},
|
{PC1, USART_1, 0},
|
||||||
{PD1, USART_1, 1},
|
{PD1, USART_1, 1},
|
||||||
{PD6, USART_1, 2},
|
{PD6, USART_1, 2},
|
||||||
/* USART2 */
|
/* USART2 */
|
||||||
{PC3, USART_2, 0},
|
{PC3, USART_2, 0},
|
||||||
{PB4, USART_2, 1},
|
{PB4, USART_2, 1},
|
||||||
/* LEUART0 */
|
/* LEUART0 */
|
||||||
{PD5, LEUART_0, 0},
|
{PD5, LEUART_0, 0},
|
||||||
{PB14, LEUART_0, 1},
|
{PB14, LEUART_0, 1},
|
||||||
{PE15, LEUART_0, 2},
|
{PE15, LEUART_0, 2},
|
||||||
{PF1, LEUART_0, 3},
|
{PF1, LEUART_0, 3},
|
||||||
{PA0, LEUART_0, 4},
|
{PA0, LEUART_0, 4},
|
||||||
/* LEUART1 */
|
/* LEUART1 */
|
||||||
{PC7, LEUART_1, 0},
|
{PC7, LEUART_1, 0},
|
||||||
{PA6, LEUART_1, 1},
|
{PA6, LEUART_1, 1},
|
||||||
/* Not connected */
|
/* Not connected */
|
||||||
{NC , NC , NC}
|
{NC , NC , NC}
|
||||||
};
|
};
|
||||||
|
|
|
@ -92,8 +92,8 @@ typedef enum {
|
||||||
/* mbed modes:
|
/* mbed modes:
|
||||||
* PullUp, PullDown, PullNone, OpenDrain
|
* PullUp, PullDown, PullNone, OpenDrain
|
||||||
*
|
*
|
||||||
* mbed default digital input mode:
|
* mbed default digital input mode:
|
||||||
* PullDefault
|
* PullDefault
|
||||||
*
|
*
|
||||||
* mbed default digital output mode:
|
* mbed default digital output mode:
|
||||||
* PullNone
|
* PullNone
|
||||||
|
|
|
@ -60,60 +60,60 @@ const PinMap PinMap_PWM[] = {
|
||||||
|
|
||||||
/*************SPI**************/
|
/*************SPI**************/
|
||||||
const PinMap PinMap_SPI_MOSI[] = {
|
const PinMap PinMap_SPI_MOSI[] = {
|
||||||
/* USART1 */
|
/* USART1 */
|
||||||
{PC0, SPI_1, 0},
|
{PC0, SPI_1, 0},
|
||||||
{PD7, SPI_1, 3},
|
{PD7, SPI_1, 3},
|
||||||
/* Not connected */
|
/* Not connected */
|
||||||
{NC , NC , NC}
|
{NC , NC , NC}
|
||||||
};
|
};
|
||||||
|
|
||||||
const PinMap PinMap_SPI_MISO[] = {
|
const PinMap PinMap_SPI_MISO[] = {
|
||||||
/* USART1 */
|
/* USART1 */
|
||||||
{PC1, SPI_1, 0},
|
{PC1, SPI_1, 0},
|
||||||
{PD6, SPI_1, 3},
|
{PD6, SPI_1, 3},
|
||||||
/* Not connected */
|
/* Not connected */
|
||||||
{NC , NC , NC}
|
{NC , NC , NC}
|
||||||
};
|
};
|
||||||
|
|
||||||
const PinMap PinMap_SPI_CLK[] = {
|
const PinMap PinMap_SPI_CLK[] = {
|
||||||
/* USART1 */
|
/* USART1 */
|
||||||
{PB7, SPI_1, 0},
|
{PB7, SPI_1, 0},
|
||||||
{PC15, SPI_1, 3},
|
{PC15, SPI_1, 3},
|
||||||
/* Not connected */
|
/* Not connected */
|
||||||
{NC , NC , NC}
|
{NC , NC , NC}
|
||||||
};
|
};
|
||||||
|
|
||||||
const PinMap PinMap_SPI_CS[] = {
|
const PinMap PinMap_SPI_CS[] = {
|
||||||
/* USART1 */
|
/* USART1 */
|
||||||
{PB8, SPI_1, 0},
|
{PB8, SPI_1, 0},
|
||||||
{PC14, SPI_1, 3},
|
{PC14, SPI_1, 3},
|
||||||
/* Not connected */
|
/* Not connected */
|
||||||
{NC , NC , NC}
|
{NC , NC , NC}
|
||||||
};
|
};
|
||||||
|
|
||||||
/************UART**************/
|
/************UART**************/
|
||||||
const PinMap PinMap_UART_TX[] = {
|
const PinMap PinMap_UART_TX[] = {
|
||||||
/* USART1 */
|
/* USART1 */
|
||||||
{PC0, USART_1, 0},
|
{PC0, USART_1, 0},
|
||||||
{PD7, USART_1, 3},
|
{PD7, USART_1, 3},
|
||||||
/* LEUART0 */
|
/* LEUART0 */
|
||||||
{PD4, LEUART_0, 0},
|
{PD4, LEUART_0, 0},
|
||||||
{PB13, LEUART_0, 1},
|
{PB13, LEUART_0, 1},
|
||||||
{PF0, LEUART_0, 3},
|
{PF0, LEUART_0, 3},
|
||||||
{PF2, LEUART_0, 4},
|
{PF2, LEUART_0, 4},
|
||||||
/* Not connected */
|
/* Not connected */
|
||||||
{NC , NC , NC}
|
{NC , NC , NC}
|
||||||
};
|
};
|
||||||
|
|
||||||
const PinMap PinMap_UART_RX[] = {
|
const PinMap PinMap_UART_RX[] = {
|
||||||
/* USART1 */
|
/* USART1 */
|
||||||
{PC1, USART_1, 0},
|
{PC1, USART_1, 0},
|
||||||
{PD6, USART_1, 3},
|
{PD6, USART_1, 3},
|
||||||
/* LEUART0 */
|
/* LEUART0 */
|
||||||
{PD5, LEUART_0, 0},
|
{PD5, LEUART_0, 0},
|
||||||
{PB14, LEUART_0, 1},
|
{PB14, LEUART_0, 1},
|
||||||
{PF1, LEUART_0, 3},
|
{PF1, LEUART_0, 3},
|
||||||
{PA0, LEUART_0, 4},
|
{PA0, LEUART_0, 4},
|
||||||
/* Not connected */
|
/* Not connected */
|
||||||
{NC , NC , NC}
|
{NC , NC , NC}
|
||||||
};
|
};
|
||||||
|
|
|
@ -42,7 +42,8 @@ void analogout_preinit(dac_t *obj, PinName pin)
|
||||||
MBED_ASSERT((int) obj->channel != NC);
|
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;
|
static uint8_t dac_initialized = 0;
|
||||||
|
|
||||||
/* init in-memory structure */
|
/* init in-memory structure */
|
||||||
|
@ -83,7 +84,8 @@ void analogout_pins_enable(dac_t *obj, uint8_t enable)
|
||||||
//not avail for EFM32
|
//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) {
|
switch (obj->channel) {
|
||||||
case 0:
|
case 0:
|
||||||
obj->dac->CH0DATA = value;
|
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) {
|
switch (obj->channel) {
|
||||||
case 0:
|
case 0:
|
||||||
return obj->dac->CH0DATA;
|
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.
|
/* We multiply the float value with 0xFFF because the DAC has 12-bit resolution.
|
||||||
* Ie. accepts values between 0 and 0xFFF (4096). */
|
* Ie. accepts values between 0 and 0xFFF (4096). */
|
||||||
dac_write(obj, value*0xFFF);
|
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 */
|
/* The DAC has 12 bit resolution, so we remove the 4 least significant bits */
|
||||||
dac_write(obj, value >> 4);
|
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 */
|
/* dac_read returns a number between 0 and 0xFFF. Division gives us a float between 0 and 1 */
|
||||||
return dac_read(obj)/(float)0xFFF;
|
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,
|
/* dac_read returns a number with 12 significant digits,
|
||||||
* so we shift in 0s from right to make it a 16 bit number */
|
* so we shift in 0s from right to make it a 16 bit number */
|
||||||
return dac_read(obj) << 4;
|
return dac_read(obj) << 4;
|
||||||
|
|
|
@ -39,55 +39,51 @@ bool enabled = false;
|
||||||
|
|
||||||
void dma_init(void)
|
void dma_init(void)
|
||||||
{
|
{
|
||||||
if (enabled) return;
|
if (enabled) return;
|
||||||
DMA_Init_TypeDef dmaInit;
|
DMA_Init_TypeDef dmaInit;
|
||||||
|
|
||||||
CMU_ClockEnable(cmuClock_DMA, true);
|
CMU_ClockEnable(cmuClock_DMA, true);
|
||||||
CMU_ClockEnable(cmuClock_HFPER, true);
|
CMU_ClockEnable(cmuClock_HFPER, true);
|
||||||
|
|
||||||
/* Configure general DMA issues */
|
/* Configure general DMA issues */
|
||||||
dmaInit.hprot = 0;
|
dmaInit.hprot = 0;
|
||||||
dmaInit.controlBlock = dmaControlBlock;
|
dmaInit.controlBlock = dmaControlBlock;
|
||||||
DMA_Init(&dmaInit);
|
DMA_Init(&dmaInit);
|
||||||
enabled = true;
|
enabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int dma_channel_allocate(uint32_t capabilities)
|
int dma_channel_allocate(uint32_t capabilities)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
// Check if 2d copy is required
|
// Check if 2d copy is required
|
||||||
if (DMA_CAP_2DCOPY & capabilities)
|
if (DMA_CAP_2DCOPY & capabilities) {
|
||||||
{
|
if (channels & 1) {
|
||||||
if (channels & 1)
|
// Channel already in use
|
||||||
{
|
return DMA_ERROR_OUT_OF_CHANNELS;
|
||||||
// Channel already in use
|
} else {
|
||||||
return DMA_ERROR_OUT_OF_CHANNELS;
|
channels |= 1 << 0;
|
||||||
} else {
|
return 0;
|
||||||
channels |= 1 << 0;
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
}
|
for (i = 1; i < DMA_CHAN_COUNT; i++) {
|
||||||
for (i = 1; i < DMA_CHAN_COUNT; i++)
|
if ((channels & (1 << i)) == 0) {
|
||||||
{
|
// Channel available
|
||||||
if ((channels & (1 << i)) == 0)
|
channels |= 1 << i;
|
||||||
{
|
return i;
|
||||||
// Channel available
|
}
|
||||||
channels |= 1 << i;
|
|
||||||
return i;
|
|
||||||
}
|
}
|
||||||
}
|
// Check if channel 0 is available
|
||||||
// Check if channel 0 is available
|
if ((channels & 1 ) == 0) {
|
||||||
if ((channels & 1 ) == 0) {
|
channels |= 1 << 0;
|
||||||
channels |= 1 << 0;
|
return 0;
|
||||||
return 0;
|
}
|
||||||
}
|
// Couldn't find a channel.
|
||||||
// Couldn't find a channel.
|
return DMA_ERROR_OUT_OF_CHANNELS;
|
||||||
return DMA_ERROR_OUT_OF_CHANNELS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int dma_channel_free(int channelid)
|
int dma_channel_free(int channelid)
|
||||||
{
|
{
|
||||||
channels &= ~(1 << channelid);
|
channels &= ~(1 << channelid);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,9 +46,9 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
DMAUsage dmaUsageState;
|
DMAUsage dmaUsageState;
|
||||||
int dmaChannel;
|
int dmaChannel;
|
||||||
DMA_CB_TypeDef dmaCallback;
|
DMA_CB_TypeDef dmaCallback;
|
||||||
} DMA_OPTIONS_t;
|
} DMA_OPTIONS_t;
|
||||||
|
|
||||||
typedef void (*DMACallback)(void);
|
typedef void (*DMACallback)(void);
|
||||||
|
|
|
@ -37,9 +37,9 @@
|
||||||
#define GPIOINT_MASK2IDX(mask) (countTrailingZeros(mask))
|
#define GPIOINT_MASK2IDX(mask) (countTrailingZeros(mask))
|
||||||
__STATIC_INLINE uint32_t countTrailingZeros(uint32_t mask)
|
__STATIC_INLINE uint32_t countTrailingZeros(uint32_t mask)
|
||||||
{
|
{
|
||||||
uint32_t zeros;
|
uint32_t zeros;
|
||||||
for(zeros=0; (zeros<32) && (0 == (mask&0x1)); zeros++, mask>>=1);
|
for(zeros=0; (zeros<32) && (0 == (mask&0x1)); zeros++, mask>>=1);
|
||||||
return zeros;
|
return zeros;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#error Unsupported architecture.
|
#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)
|
int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id)
|
||||||
{
|
{
|
||||||
/* Init pins */
|
/* Init pins */
|
||||||
gpio_irq_preinit(obj, pin);
|
gpio_irq_preinit(obj, pin);
|
||||||
/* Initialize GPIO interrupt dispatcher */
|
/* Initialize GPIO interrupt dispatcher */
|
||||||
NVIC_ClearPendingIRQ(GPIO_ODD_IRQn);
|
NVIC_ClearPendingIRQ(GPIO_ODD_IRQn);
|
||||||
NVIC_EnableIRQ(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);
|
GPIO_IntConfig(obj->port, obj->pin, obj->risingEdge, obj->fallingEdge, obj->risingEdge || obj->fallingEdge);
|
||||||
if ((GPIO->IEN != 0) && (obj->risingEdge || obj->fallingEdge) && was_disabled) {
|
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)
|
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
|
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)
|
static void GPIOINT_IRQDispatcher(uint32_t iflags)
|
||||||
{
|
{
|
||||||
uint32_t irqIdx;
|
uint32_t irqIdx;
|
||||||
|
|
||||||
/* check for all flags set in IF register */
|
/* check for all flags set in IF register */
|
||||||
while(iflags)
|
while(iflags) {
|
||||||
{
|
irqIdx = GPIOINT_MASK2IDX(iflags);
|
||||||
irqIdx = GPIOINT_MASK2IDX(iflags);
|
|
||||||
|
|
||||||
/* clear flag*/
|
/* clear flag*/
|
||||||
iflags &= ~(1 << irqIdx);
|
iflags &= ~(1 << irqIdx);
|
||||||
|
|
||||||
/* call user callback */
|
/* call user callback */
|
||||||
handle_interrupt_in(irqIdx);
|
handle_interrupt_in(irqIdx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************************//**
|
/***************************************************************************//**
|
||||||
|
@ -188,15 +187,15 @@ static void GPIOINT_IRQDispatcher(uint32_t iflags)
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
void GPIO_EVEN_IRQHandler(void)
|
void GPIO_EVEN_IRQHandler(void)
|
||||||
{
|
{
|
||||||
uint32_t iflags;
|
uint32_t iflags;
|
||||||
|
|
||||||
/* Get all even interrupts. */
|
/* Get all even interrupts. */
|
||||||
iflags = GPIO_IntGetEnabled() & 0x00005555;
|
iflags = GPIO_IntGetEnabled() & 0x00005555;
|
||||||
|
|
||||||
/* Clean only even interrupts. */
|
/* Clean only even interrupts. */
|
||||||
GPIO_IntClear(iflags);
|
GPIO_IntClear(iflags);
|
||||||
|
|
||||||
GPIOINT_IRQDispatcher(iflags);
|
GPIOINT_IRQDispatcher(iflags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -208,15 +207,15 @@ void GPIO_EVEN_IRQHandler(void)
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
void GPIO_ODD_IRQHandler(void)
|
void GPIO_ODD_IRQHandler(void)
|
||||||
{
|
{
|
||||||
uint32_t iflags;
|
uint32_t iflags;
|
||||||
|
|
||||||
/* Get all odd interrupts. */
|
/* Get all odd interrupts. */
|
||||||
iflags = GPIO_IntGetEnabled() & 0x0000AAAA;
|
iflags = GPIO_IntGetEnabled() & 0x0000AAAA;
|
||||||
|
|
||||||
/* Clean only even interrupts. */
|
/* Clean only even interrupts. */
|
||||||
GPIO_IntClear(iflags);
|
GPIO_IntClear(iflags);
|
||||||
|
|
||||||
GPIOINT_IRQDispatcher(iflags);
|
GPIOINT_IRQDispatcher(iflags);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#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;
|
return obj->pin != (PinName)NC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -75,7 +75,7 @@ static CMU_Clock_TypeDef i2c_get_clock(i2c_t *obj)
|
||||||
#endif
|
#endif
|
||||||
#ifdef I2C1
|
#ifdef I2C1
|
||||||
case I2C_1:
|
case I2C_1:
|
||||||
clock = cmuClock_I2C1;
|
clock = cmuClock_I2C1;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
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)
|
void i2c_init(i2c_t *obj, PinName sda, PinName scl)
|
||||||
{
|
{
|
||||||
/* Assign mbed pins */
|
/* Assign mbed pins */
|
||||||
i2c_preinit(obj, sda, scl);
|
i2c_preinit(obj, sda, scl);
|
||||||
|
|
||||||
/* Enable clock for the peripheral */
|
/* Enable clock for the peripheral */
|
||||||
CMU_ClockEnable(i2c_get_clock(obj), true);
|
CMU_ClockEnable(i2c_get_clock(obj), true);
|
||||||
|
|
||||||
/* Initializing the I2C */
|
/* Initializing the I2C */
|
||||||
/* Using default settings */
|
/* Using default settings */
|
||||||
|
@ -222,14 +222,14 @@ int i2c_stop(i2c_t *obj)
|
||||||
/* Returns number of bytes read */
|
/* Returns number of bytes read */
|
||||||
int i2c_read(i2c_t *obj, int address, char *data, int length, int stop)
|
int i2c_read(i2c_t *obj, int address, char *data, int length, int stop)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
i2c_start(obj);
|
i2c_start(obj);
|
||||||
|
|
||||||
retval = i2c_byte_write(obj, (address | 1));
|
retval = i2c_byte_write(obj, (address | 1));
|
||||||
if ((!retval) || (length == 0)) { //Write address with W flag (last bit 1)
|
if ((!retval) || (length == 0)) { //Write address with W flag (last bit 1)
|
||||||
obj->i2c.i2c->CMD = I2C_CMD_STOP | I2C_CMD_ABORT;
|
obj->i2c.i2c->CMD = I2C_CMD_STOP | I2C_CMD_ABORT;
|
||||||
while(obj->i2c.i2c->STATE & I2C_STATE_BUSY); // Wait until the bus is done
|
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
|
return (retval == 0 ? I2C_ERROR_NO_SLAVE : 0); //NACK or error when writing adress. Return 0 as 0 bytes were read
|
||||||
}
|
}
|
||||||
int i = 0;
|
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)
|
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_SLAVE_MASK;
|
||||||
obj->i2c.i2c->CTRL |= _I2C_CTRL_AUTOACK_MASK; //Slave implementation assumes auto acking
|
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_SLAVE_MASK;
|
||||||
obj->i2c.i2c->CTRL &= ~_I2C_CTRL_AUTOACK_MASK; //Master implementation ACKs manually
|
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)
|
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
|
obj->i2c.i2c->IFC = I2C_IF_ADDR; //Clear interrupt
|
||||||
/*0x00 is the address for general write.
|
/*0x00 is the address for general write.
|
||||||
The address the master wrote is in RXDATA now
|
The address the master wrote is in RXDATA now
|
||||||
and reading it also frees the buffer for the next
|
and reading it also frees the buffer for the next
|
||||||
write which can then be acked. */
|
write which can then be acked. */
|
||||||
if(obj->i2c.i2c->RXDATA == 0x00){
|
if(obj->i2c.i2c->RXDATA == 0x00) {
|
||||||
return WriteGeneral; //Read the address;
|
return WriteGeneral; //Read the address;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(obj->i2c.i2c->STATE & I2C_STATE_TRANSMITTER){
|
if(obj->i2c.i2c->STATE & I2C_STATE_TRANSMITTER) {
|
||||||
return ReadAddressed;
|
return ReadAddressed;
|
||||||
}else{
|
} else {
|
||||||
return WriteAddressed;
|
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 handler The I2C IRQ handler to be set
|
||||||
* @param hint DMA hint usage
|
* @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) {
|
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;
|
I2C_TransferReturn_TypeDef retval;
|
||||||
|
if(i2c_active(obj)) return;
|
||||||
if((tx_length == 0) && (rx_length == 0)) 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
|
// Store transfer config
|
||||||
obj->i2c.xfer.addr = address;
|
obj->i2c.xfer.addr = address;
|
||||||
|
|
||||||
// Some combination of tx_length and rx_length will tell us what to do
|
// Some combination of tx_length and rx_length will tell us what to do
|
||||||
if((tx_length > 0) && (rx_length == 0)) {
|
if((tx_length > 0) && (rx_length == 0)) {
|
||||||
obj->i2c.xfer.flags = I2C_FLAG_WRITE;
|
obj->i2c.xfer.flags = I2C_FLAG_WRITE;
|
||||||
//Store buffer info
|
//Store buffer info
|
||||||
obj->i2c.xfer.buf[0].data = tx;
|
obj->i2c.xfer.buf[0].data = tx;
|
||||||
obj->i2c.xfer.buf[0].len = (uint16_t) tx_length;
|
obj->i2c.xfer.buf[0].len = (uint16_t) tx_length;
|
||||||
} else if ((tx_length == 0) && (rx_length > 0)) {
|
} else if ((tx_length == 0) && (rx_length > 0)) {
|
||||||
obj->i2c.xfer.flags = I2C_FLAG_READ;
|
obj->i2c.xfer.flags = I2C_FLAG_READ;
|
||||||
//Store buffer info
|
//Store buffer info
|
||||||
obj->i2c.xfer.buf[0].data = rx;
|
obj->i2c.xfer.buf[0].data = rx;
|
||||||
obj->i2c.xfer.buf[0].len = (uint16_t) rx_length;
|
obj->i2c.xfer.buf[0].len = (uint16_t) rx_length;
|
||||||
} else if ((tx_length > 0) && (rx_length > 0)) {
|
} else if ((tx_length > 0) && (rx_length > 0)) {
|
||||||
obj->i2c.xfer.flags = I2C_FLAG_WRITE_READ;
|
obj->i2c.xfer.flags = I2C_FLAG_WRITE_READ;
|
||||||
//Store buffer info
|
//Store buffer info
|
||||||
obj->i2c.xfer.buf[0].data = tx;
|
obj->i2c.xfer.buf[0].data = tx;
|
||||||
obj->i2c.xfer.buf[0].len = (uint16_t) tx_length;
|
obj->i2c.xfer.buf[0].len = (uint16_t) tx_length;
|
||||||
obj->i2c.xfer.buf[1].data = rx;
|
obj->i2c.xfer.buf[1].data = rx;
|
||||||
obj->i2c.xfer.buf[1].len = (uint16_t) rx_length;
|
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
|
// Store event flags
|
||||||
obj->i2c.events = event;
|
obj->i2c.events = event;
|
||||||
|
|
||||||
// Enable interrupt
|
// Enable interrupt
|
||||||
i2c_enable_interrupt(obj, handler, true);
|
i2c_enable_interrupt(obj, handler, true);
|
||||||
|
|
||||||
// Kick off the transfer
|
// Kick off the transfer
|
||||||
retval = I2C_TransferInit(obj->i2c.i2c, &(obj->i2c.xfer));
|
retval = I2C_TransferInit(obj->i2c.i2c, &(obj->i2c.xfer));
|
||||||
|
|
||||||
if(retval == i2cTransferInProgress) {
|
if(retval == i2cTransferInProgress) {
|
||||||
blockSleepMode(EM1);
|
blockSleepMode(EM1);
|
||||||
}
|
} else {
|
||||||
else {
|
// something happened, and the transfer did not go through
|
||||||
// something happened, and the transfer did not go through
|
// So, we need to clean up
|
||||||
// So, we need to clean up
|
|
||||||
|
|
||||||
// Disable interrupt
|
// Disable interrupt
|
||||||
i2c_enable_interrupt(obj, 0, false);
|
i2c_enable_interrupt(obj, 0, false);
|
||||||
|
|
||||||
// Block until free
|
// Block until free
|
||||||
while(i2c_active(obj));
|
while(i2c_active(obj));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The asynchronous IRQ handler
|
/** The asynchronous IRQ handler
|
||||||
* @param obj The I2C object which holds the transfer information
|
* @param obj The I2C object which holds the transfer information
|
||||||
* @return Returns event flags if a transfer termination condition was met or 0 otherwise.
|
* @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);
|
I2C_TransferReturn_TypeDef status = I2C_Transfer(obj->i2c.i2c);
|
||||||
switch(status) {
|
switch(status) {
|
||||||
case i2cTransferInProgress:
|
case i2cTransferInProgress:
|
||||||
// Still busy transferring, so let it.
|
// Still busy transferring, so let it.
|
||||||
return 0;
|
return 0;
|
||||||
case i2cTransferDone:
|
case i2cTransferDone:
|
||||||
// Transfer has completed
|
// Transfer has completed
|
||||||
|
|
||||||
// Disable interrupt
|
// Disable interrupt
|
||||||
i2c_enable_interrupt(obj, 0, false);
|
i2c_enable_interrupt(obj, 0, false);
|
||||||
|
|
||||||
unblockSleepMode(EM1);
|
unblockSleepMode(EM1);
|
||||||
|
|
||||||
return I2C_EVENT_TRANSFER_COMPLETE & obj->i2c.events;
|
return I2C_EVENT_TRANSFER_COMPLETE & obj->i2c.events;
|
||||||
case i2cTransferNack:
|
case i2cTransferNack:
|
||||||
// A NACK has been received while an ACK was expected. This is usually because the slave did not respond to the address.
|
// A NACK has been received while an ACK was expected. This is usually because the slave did not respond to the address.
|
||||||
// Disable interrupt
|
// Disable interrupt
|
||||||
i2c_enable_interrupt(obj, 0, false);
|
i2c_enable_interrupt(obj, 0, false);
|
||||||
|
|
||||||
unblockSleepMode(EM1);
|
unblockSleepMode(EM1);
|
||||||
|
|
||||||
return I2C_EVENT_ERROR_NO_SLAVE & obj->i2c.events;
|
return I2C_EVENT_ERROR_NO_SLAVE & obj->i2c.events;
|
||||||
default:
|
default:
|
||||||
// An error situation has arisen.
|
// An error situation has arisen.
|
||||||
// Disable interrupt
|
// Disable interrupt
|
||||||
i2c_enable_interrupt(obj, 0, false);
|
i2c_enable_interrupt(obj, 0, false);
|
||||||
|
|
||||||
unblockSleepMode(EM1);
|
unblockSleepMode(EM1);
|
||||||
|
|
||||||
// return error
|
// return error
|
||||||
return I2C_EVENT_ERROR & obj->i2c.events;
|
return I2C_EVENT_ERROR & obj->i2c.events;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Attempts to determine if I2C peripheral is already in use.
|
/** Attempts to determine if I2C peripheral is already in use.
|
||||||
* @param obj The I2C object
|
* @param obj The I2C object
|
||||||
* @return non-zero if the I2C module is active or zero if it is not
|
* @return non-zero if the I2C module is active or zero if it is not
|
||||||
*/
|
*/
|
||||||
uint8_t i2c_active(i2c_t *obj) {
|
uint8_t i2c_active(i2c_t *obj)
|
||||||
return (obj->i2c.i2c->STATE & I2C_STATE_BUSY);
|
{
|
||||||
|
return (obj->i2c.i2c->STATE & I2C_STATE_BUSY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Abort ongoing asynchronous transaction.
|
/** Abort ongoing asynchronous transaction.
|
||||||
* @param obj The I2C object
|
* @param obj The I2C object
|
||||||
*/
|
*/
|
||||||
void i2c_abort_asynch(i2c_t *obj) {
|
void i2c_abort_asynch(i2c_t *obj)
|
||||||
// Do not deactivate I2C twice
|
{
|
||||||
if (!i2c_active(obj)) return;
|
// Do not deactivate I2C twice
|
||||||
|
if (!i2c_active(obj)) return;
|
||||||
|
|
||||||
// Disable interrupt
|
// Disable interrupt
|
||||||
i2c_enable_interrupt(obj, 0, false);
|
i2c_enable_interrupt(obj, 0, false);
|
||||||
|
|
||||||
// Abort
|
// Abort
|
||||||
obj->i2c.i2c->CMD = I2C_CMD_STOP | I2C_CMD_ABORT;
|
obj->i2c.i2c->CMD = I2C_CMD_STOP | I2C_CMD_ABORT;
|
||||||
|
|
||||||
// Block until free
|
// Block until free
|
||||||
while(i2c_active(obj));
|
while(i2c_active(obj));
|
||||||
|
|
||||||
unblockSleepMode(EM1);
|
unblockSleepMode(EM1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //DEVICE_I2C ASYNCH
|
#endif //DEVICE_I2C ASYNCH
|
||||||
|
|
|
@ -27,8 +27,9 @@ void lp_ticker_init()
|
||||||
rtc_set_comp0_handler((uint32_t)lp_ticker_irq_handler);
|
rtc_set_comp0_handler((uint32_t)lp_ticker_irq_handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
void lp_ticker_set_interrupt(timestamp_t timestamp) {
|
void lp_ticker_set_interrupt(timestamp_t timestamp)
|
||||||
uint64_t timestamp_ticks;
|
{
|
||||||
|
uint64_t timestamp_ticks;
|
||||||
uint64_t current_ticks = RTC_CounterGet();
|
uint64_t current_ticks = RTC_CounterGet();
|
||||||
timestamp_t current_time = ((uint64_t)(current_ticks * 1000000) / (LOW_ENERGY_CLOCK_FREQUENCY / RTC_CLOCKDIV_INT));
|
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;
|
if(offset > 0xEFFFFFFF) offset = 100;
|
||||||
|
|
||||||
/* map offset to RTC value */
|
/* map offset to RTC value */
|
||||||
// ticks = offset * RTC frequency div 1000000
|
// ticks = offset * RTC frequency div 1000000
|
||||||
timestamp_ticks = ((uint64_t)offset * (LOW_ENERGY_CLOCK_FREQUENCY / RTC_CLOCKDIV_INT)) / 1000000;
|
timestamp_ticks = ((uint64_t)offset * (LOW_ENERGY_CLOCK_FREQUENCY / RTC_CLOCKDIV_INT)) / 1000000;
|
||||||
timestamp_ticks += current_ticks;
|
timestamp_ticks += current_ticks;
|
||||||
|
|
||||||
/* RTC has 24 bit resolution */
|
/* RTC has 24 bit resolution */
|
||||||
timestamp_ticks &= 0xFFFFFF;
|
timestamp_ticks &= 0xFFFFFF;
|
||||||
|
|
||||||
/* check for RTC limitation */
|
/* check for RTC limitation */
|
||||||
if((timestamp_ticks - RTC_CounterGet()) >= 0x800000) timestamp_ticks = RTC_CounterGet() + 2;
|
if((timestamp_ticks - RTC_CounterGet()) >= 0x800000) timestamp_ticks = RTC_CounterGet() + 2;
|
||||||
|
|
||||||
/* Set callback */
|
/* Set callback */
|
||||||
RTC_FreezeEnable(true);
|
RTC_FreezeEnable(true);
|
||||||
RTC_CompareSet(0, (uint32_t)timestamp_ticks);
|
RTC_CompareSet(0, (uint32_t)timestamp_ticks);
|
||||||
RTC_IntEnable(RTC_IF_COMP0);
|
RTC_IntEnable(RTC_IF_COMP0);
|
||||||
RTC_FreezeEnable(false);
|
RTC_FreezeEnable(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void lp_ticker_disable_interrupt() {
|
inline void lp_ticker_disable_interrupt()
|
||||||
RTC_IntDisable(RTC_IF_COMP0);
|
{
|
||||||
|
RTC_IntDisable(RTC_IF_COMP0);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void lp_ticker_clear_interrupt() {
|
inline void lp_ticker_clear_interrupt()
|
||||||
RTC_IntClear(RTC_IF_COMP0);
|
{
|
||||||
|
RTC_IntClear(RTC_IF_COMP0);
|
||||||
}
|
}
|
||||||
|
|
||||||
timestamp_t lp_ticker_read() {
|
timestamp_t lp_ticker_read()
|
||||||
uint64_t ticks_temp;
|
{
|
||||||
uint64_t ticks = RTC_CounterGet();
|
uint64_t ticks_temp;
|
||||||
|
uint64_t ticks = RTC_CounterGet();
|
||||||
|
|
||||||
/* ticks = counter tick value
|
/* ticks = counter tick value
|
||||||
* timestamp = value in microseconds
|
* timestamp = value in microseconds
|
||||||
* timestamp = ticks * 1.000.000 / RTC frequency
|
* timestamp = ticks * 1.000.000 / RTC frequency
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ticks_temp = (ticks * 1000000) / (LOW_ENERGY_CLOCK_FREQUENCY / RTC_CLOCKDIV_INT);
|
ticks_temp = (ticks * 1000000) / (LOW_ENERGY_CLOCK_FREQUENCY / RTC_CLOCKDIV_INT);
|
||||||
return (timestamp_t) (ticks_temp & 0xFFFFFFFF);
|
return (timestamp_t) (ticks_temp & 0xFFFFFFFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -50,11 +50,11 @@ void mbed_sdk_init()
|
||||||
CMU_ClockSelectSet(cmuClock_LFA, LFXO);
|
CMU_ClockSelectSet(cmuClock_LFA, LFXO);
|
||||||
#endif
|
#endif
|
||||||
#ifdef CMU_LFBCLKSEL_REG
|
#ifdef CMU_LFBCLKSEL_REG
|
||||||
/* cmuClock_LFB (to date) only has LEUART peripherals.
|
/* cmuClock_LFB (to date) only has LEUART peripherals.
|
||||||
* Do NOT set it up here, as LEUARTs might have been initialized
|
* Do NOT set it up here, as LEUARTs might have been initialized
|
||||||
* before this code is called. (Limitation of the override mechanism of ARMCC)
|
* before this code is called. (Limitation of the override mechanism of ARMCC)
|
||||||
*/
|
*/
|
||||||
//TODO: Look for a more elegant fix.
|
//TODO: Look for a more elegant fix.
|
||||||
//CMU_ClockSelectSet(cmuClock_LFB, LFXO);
|
//CMU_ClockSelectSet(cmuClock_LFB, LFXO);
|
||||||
#endif
|
#endif
|
||||||
#ifdef CMU_LFECLKSEL_REG
|
#ifdef CMU_LFECLKSEL_REG
|
||||||
|
@ -92,7 +92,8 @@ void mbed_sdk_init()
|
||||||
gpio_init_out_ex(&bc_enable, EFM_BC_EN, 1);
|
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;
|
uint32_t freq = 14000000, baudrate;
|
||||||
USART_OVS_TypeDef ovs;
|
USART_OVS_TypeDef ovs;
|
||||||
|
|
||||||
|
|
|
@ -129,11 +129,11 @@ struct lp_timer_s {
|
||||||
#if DEVICE_SLEEP
|
#if DEVICE_SLEEP
|
||||||
#define NUM_SLEEP_MODES 5
|
#define NUM_SLEEP_MODES 5
|
||||||
typedef enum {
|
typedef enum {
|
||||||
EM0 = 0,
|
EM0 = 0,
|
||||||
EM1 = 1,
|
EM1 = 1,
|
||||||
EM2 = 2,
|
EM2 = 2,
|
||||||
EM3 = 3,
|
EM3 = 3,
|
||||||
EM4 = 4
|
EM4 = 4
|
||||||
} sleepstate_enum;
|
} sleepstate_enum;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -30,10 +30,10 @@ void pin_mode(PinName pin, PinMode mode)
|
||||||
MBED_ASSERT(pin != NC);
|
MBED_ASSERT(pin != NC);
|
||||||
|
|
||||||
/* Enable GPIO clock if not already done */
|
/* Enable GPIO clock if not already done */
|
||||||
if (!gpio_clock_inited) {
|
if (!gpio_clock_inited) {
|
||||||
CMU_ClockEnable(cmuClock_GPIO, true);
|
CMU_ClockEnable(cmuClock_GPIO, true);
|
||||||
gpio_clock_inited = 1;
|
gpio_clock_inited = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Pin and port index encoded in one uint32.
|
/* Pin and port index encoded in one uint32.
|
||||||
* First four bits represent the pin number
|
* 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)
|
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);
|
port_dir(obj, obj->dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,22 +33,23 @@
|
||||||
static int pwm_clockfreq;
|
static int pwm_clockfreq;
|
||||||
static int pwm_prescaler_div;
|
static int pwm_prescaler_div;
|
||||||
|
|
||||||
uint32_t pwmout_get_channel_route(pwmout_t *obj) {
|
uint32_t pwmout_get_channel_route(pwmout_t *obj)
|
||||||
MBED_ASSERT(obj->channel != (PWMName) NC);
|
{
|
||||||
|
MBED_ASSERT(obj->channel != (PWMName) NC);
|
||||||
|
|
||||||
switch (obj->channel) {
|
switch (obj->channel) {
|
||||||
case PWM_CH0:
|
case PWM_CH0:
|
||||||
return TIMER_ROUTE_CC0PEN;
|
return TIMER_ROUTE_CC0PEN;
|
||||||
break;
|
break;
|
||||||
case PWM_CH1:
|
case PWM_CH1:
|
||||||
return TIMER_ROUTE_CC1PEN;
|
return TIMER_ROUTE_CC1PEN;
|
||||||
break;
|
break;
|
||||||
case PWM_CH2:
|
case PWM_CH2:
|
||||||
return TIMER_ROUTE_CC2PEN;
|
return TIMER_ROUTE_CC2PEN;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pwmout_enable_pins(pwmout_t *obj, uint8_t enable)
|
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)
|
void pwmout_enable(pwmout_t *obj, uint8_t enable)
|
||||||
{
|
{
|
||||||
/* Start with default CC (Compare/Capture) channel parameters */
|
/* Start with default CC (Compare/Capture) channel parameters */
|
||||||
TIMER_InitCC_TypeDef timerCCInit = TIMER_INITCC_DEFAULT;
|
TIMER_InitCC_TypeDef timerCCInit = TIMER_INITCC_DEFAULT;
|
||||||
if (enable) {
|
if (enable) {
|
||||||
/* Set mode to PWM */
|
/* Set mode to PWM */
|
||||||
timerCCInit.mode = timerCCModePWM;
|
timerCCInit.mode = timerCCModePWM;
|
||||||
|
@ -76,33 +77,33 @@ void pwmout_enable(pwmout_t *obj, uint8_t enable)
|
||||||
|
|
||||||
void pwmout_init(pwmout_t *obj, PinName pin)
|
void pwmout_init(pwmout_t *obj, PinName pin)
|
||||||
{
|
{
|
||||||
obj->channel = (PWMName) pinmap_peripheral(pin, PinMap_PWM);
|
obj->channel = (PWMName) pinmap_peripheral(pin, PinMap_PWM);
|
||||||
obj->pin = pin;
|
obj->pin = pin;
|
||||||
MBED_ASSERT(obj->channel != (PWMName) NC);
|
MBED_ASSERT(obj->channel != (PWMName) NC);
|
||||||
|
|
||||||
/* Turn on clock */
|
/* Turn on clock */
|
||||||
CMU_ClockEnable(PWM_TIMER_CLOCK, true);
|
CMU_ClockEnable(PWM_TIMER_CLOCK, true);
|
||||||
|
|
||||||
/* Turn on timer */
|
/* Turn on timer */
|
||||||
if(!(PWM_TIMER->STATUS & TIMER_STATUS_RUNNING)) {
|
if(!(PWM_TIMER->STATUS & TIMER_STATUS_RUNNING)) {
|
||||||
TIMER_Init_TypeDef timerInit = TIMER_INIT_DEFAULT;
|
TIMER_Init_TypeDef timerInit = TIMER_INIT_DEFAULT;
|
||||||
TIMER_Init(PWM_TIMER, &timerInit);
|
TIMER_Init(PWM_TIMER, &timerInit);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enable correct channel */
|
/* Enable correct channel */
|
||||||
uint32_t routeloc = pwmout_get_channel_route(obj);
|
uint32_t routeloc = pwmout_get_channel_route(obj);
|
||||||
if(PWM_TIMER->ROUTE & routeloc) {
|
if(PWM_TIMER->ROUTE & routeloc) {
|
||||||
//This channel was already in use
|
//This channel was already in use
|
||||||
//TODO: gracefully handle this case
|
//TODO: gracefully handle this case
|
||||||
} else {
|
} else {
|
||||||
//This channel was unused up to now
|
//This channel was unused up to now
|
||||||
PWM_TIMER->ROUTE |= routeloc;
|
PWM_TIMER->ROUTE |= routeloc;
|
||||||
blockSleepMode(EM1);
|
blockSleepMode(EM1);
|
||||||
|
|
||||||
//TODO: check if any channel was up already, then don't re-init timer
|
//TODO: check if any channel was up already, then don't re-init timer
|
||||||
pwmout_enable(obj, true);
|
pwmout_enable(obj, true);
|
||||||
pwmout_enable_pins(obj, true);
|
pwmout_enable_pins(obj, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Route correct channel to location 1 */
|
/* Route correct channel to location 1 */
|
||||||
PWM_TIMER->ROUTE &= ~_TIMER_ROUTE_LOCATION_MASK;
|
PWM_TIMER->ROUTE &= ~_TIMER_ROUTE_LOCATION_MASK;
|
||||||
|
@ -115,18 +116,19 @@ void pwmout_init(pwmout_t *obj, PinName pin)
|
||||||
pwmout_period(obj, 0.02);
|
pwmout_period(obj, 0.02);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pwmout_free(pwmout_t *obj) {
|
void pwmout_free(pwmout_t *obj)
|
||||||
uint32_t routeloc = pwmout_get_channel_route(obj);
|
{
|
||||||
if(PWM_TIMER->ROUTE & routeloc) {
|
uint32_t routeloc = pwmout_get_channel_route(obj);
|
||||||
//This channel was in use, so disable
|
if(PWM_TIMER->ROUTE & routeloc) {
|
||||||
PWM_TIMER->ROUTE &= ~routeloc;
|
//This channel was in use, so disable
|
||||||
pwmout_enable_pins(obj, false);
|
PWM_TIMER->ROUTE &= ~routeloc;
|
||||||
unblockSleepMode(EM1);
|
pwmout_enable_pins(obj, false);
|
||||||
|
unblockSleepMode(EM1);
|
||||||
|
|
||||||
//TODO: check if all channels are down, then switch off timer
|
//TODO: check if all channels are down, then switch off timer
|
||||||
} else {
|
} else {
|
||||||
//This channel was disabled already
|
//This channel was disabled already
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pwmout_write(pwmout_t *obj, float value)
|
void pwmout_write(pwmout_t *obj, float value)
|
||||||
|
|
|
@ -37,17 +37,14 @@ void RTC_IRQHandler(void)
|
||||||
{
|
{
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
flags = RTC_IntGet();
|
flags = RTC_IntGet();
|
||||||
if (flags & RTC_IF_OF)
|
if (flags & RTC_IF_OF) {
|
||||||
{
|
|
||||||
RTC_IntClear(RTC_IF_OF);
|
RTC_IntClear(RTC_IF_OF);
|
||||||
/* RTC has overflowed (24 bits). Use time_base as software counter for upper 8 bits. */
|
/* RTC has overflowed (24 bits). Use time_base as software counter for upper 8 bits. */
|
||||||
time_base += 1 << 24;
|
time_base += 1 << 24;
|
||||||
}
|
}
|
||||||
if (flags & RTC_IF_COMP0)
|
if (flags & RTC_IF_COMP0) {
|
||||||
{
|
|
||||||
RTC_IntClear(RTC_IF_COMP0);
|
RTC_IntClear(RTC_IF_COMP0);
|
||||||
if (comp0_handler != NULL)
|
if (comp0_handler != NULL) {
|
||||||
{
|
|
||||||
comp0_handler();
|
comp0_handler();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,8 +66,7 @@ void rtc_init_real(uint32_t flags)
|
||||||
{
|
{
|
||||||
useflags |= flags;
|
useflags |= flags;
|
||||||
|
|
||||||
if (!rtc_inited)
|
if (!rtc_inited) {
|
||||||
{
|
|
||||||
/* Start LFXO and wait until it is stable */
|
/* Start LFXO and wait until it is stable */
|
||||||
CMU_OscillatorEnable(cmuOsc_LFXO, true, true);
|
CMU_OscillatorEnable(cmuOsc_LFXO, true, true);
|
||||||
|
|
||||||
|
@ -114,8 +110,7 @@ void rtc_free_real(uint32_t flags)
|
||||||
flags &= ~flags;
|
flags &= ~flags;
|
||||||
|
|
||||||
/* Disable the RTC if it was inited and is no longer in use by anyone. */
|
/* 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);
|
NVIC_DisableIRQ(RTC_IRQn);
|
||||||
RTC_Reset();
|
RTC_Reset();
|
||||||
CMU_ClockEnable(cmuClock_RTC, false);
|
CMU_ClockEnable(cmuClock_RTC, false);
|
||||||
|
|
|
@ -94,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);}
|
static void usart2_tx_irq() { uart_irq(USART_2, 4, TxIrq); USART_IntClear((USART_TypeDef*)USART_2, USART_IFC_TXC);}
|
||||||
#endif
|
#endif
|
||||||
#ifdef LEUART0
|
#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)) {
|
if(LEUART_IntGetEnabled(LEUART0) && (LEUART_IF_RXDATAV | LEUART_IF_FERR | LEUART_IFC_PERR | LEUART_IF_RXOF)) {
|
||||||
uart_irq(LEUART_0, 5, RxIrq);
|
uart_irq(LEUART_0, 5, RxIrq);
|
||||||
} else {
|
} else {
|
||||||
|
@ -103,7 +104,8 @@ static void leuart0_irq() {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef LEUART1
|
#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)) {
|
if(LEUART_IntGetEnabled(LEUART1) && (LEUART_IF_RXDATAV | LEUART_IF_FERR | LEUART_IFC_PERR | LEUART_IF_RXOF)) {
|
||||||
uart_irq(LEUART_1, 6, RxIrq);
|
uart_irq(LEUART_1, 6, RxIrq);
|
||||||
} else {
|
} else {
|
||||||
|
@ -405,12 +407,12 @@ void serial_enable_pins(serial_t *obj, uint8_t enable)
|
||||||
|
|
||||||
void serial_init(serial_t *obj, PinName tx, PinName rx)
|
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)) {
|
if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
|
||||||
// Set up LEUART clock tree to use high-speed clock)
|
// Set up LEUART clock tree to use high-speed clock)
|
||||||
CMU_ClockSelectSet(cmuClock_LFB, cmuSelect_CORELEDIV2);
|
CMU_ClockSelectSet(cmuClock_LFB, cmuSelect_CORELEDIV2);
|
||||||
CMU_ClockEnable(cmuClock_LFB, true);
|
CMU_ClockEnable(cmuClock_LFB, true);
|
||||||
CMU_ClockSelectSet(serial_get_clock(obj), cmuSelect_CORELEDIV2);
|
CMU_ClockSelectSet(serial_get_clock(obj), cmuSelect_CORELEDIV2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -446,8 +448,8 @@ void serial_init(serial_t *obj, PinName tx, PinName rx)
|
||||||
obj->serial.dmaOptionsTX.dmaChannel = -1;
|
obj->serial.dmaOptionsTX.dmaChannel = -1;
|
||||||
obj->serial.dmaOptionsTX.dmaUsageState = DMA_USAGE_OPPORTUNISTIC;
|
obj->serial.dmaOptionsTX.dmaUsageState = DMA_USAGE_OPPORTUNISTIC;
|
||||||
|
|
||||||
obj->serial.dmaOptionsRX.dmaChannel = -1;
|
obj->serial.dmaOptionsRX.dmaChannel = -1;
|
||||||
obj->serial.dmaOptionsRX.dmaUsageState = DMA_USAGE_OPPORTUNISTIC;
|
obj->serial.dmaOptionsRX.dmaUsageState = DMA_USAGE_OPPORTUNISTIC;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -865,8 +867,8 @@ void serial_pinout_tx(PinName tx)
|
||||||
******************************************/
|
******************************************/
|
||||||
static void serial_dmaTransferComplete(unsigned int channel, bool primary, void *user)
|
static void serial_dmaTransferComplete(unsigned int channel, bool primary, void *user)
|
||||||
{
|
{
|
||||||
/* Store information about which channel triggered because CPP doesn't take arguments */
|
/* Store information about which channel triggered because CPP doesn't take arguments */
|
||||||
serial_dma_irq_fired[channel] = true;
|
serial_dma_irq_fired[channel] = true;
|
||||||
|
|
||||||
/* User pointer should be a thunk to CPP land */
|
/* User pointer should be a thunk to CPP land */
|
||||||
if (user != NULL) {
|
if (user != NULL) {
|
||||||
|
@ -880,100 +882,101 @@ static void serial_dmaTransferComplete(unsigned int channel, bool primary, void
|
||||||
* Sets up the DMA configuration block for the assigned channel
|
* Sets up the DMA configuration block for the assigned channel
|
||||||
* tx_nrx: true if configuring TX, false if configuring RX.
|
* tx_nrx: true if configuring TX, false if configuring RX.
|
||||||
******************************************/
|
******************************************/
|
||||||
static void serial_dmaSetupChannel(serial_t *obj, bool tx_nrx) {
|
static void serial_dmaSetupChannel(serial_t *obj, bool tx_nrx)
|
||||||
DMA_CfgChannel_TypeDef channelConfig;
|
{
|
||||||
|
DMA_CfgChannel_TypeDef channelConfig;
|
||||||
|
|
||||||
if(tx_nrx) {
|
if(tx_nrx) {
|
||||||
//setup TX channel
|
//setup TX channel
|
||||||
channelConfig.highPri = false;
|
channelConfig.highPri = false;
|
||||||
channelConfig.enableInt = true;
|
channelConfig.enableInt = true;
|
||||||
channelConfig.cb = &(obj->serial.dmaOptionsTX.dmaCallback);
|
channelConfig.cb = &(obj->serial.dmaOptionsTX.dmaCallback);
|
||||||
|
|
||||||
switch((uint32_t)(obj->serial.periph.uart)) {
|
switch((uint32_t)(obj->serial.periph.uart)) {
|
||||||
#ifdef UART0
|
#ifdef UART0
|
||||||
case UART_0:
|
case UART_0:
|
||||||
channelConfig.select = DMAREQ_UART0_TXBL;
|
channelConfig.select = DMAREQ_UART0_TXBL;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef UART1
|
#ifdef UART1
|
||||||
case UART_1:
|
case UART_1:
|
||||||
channelConfig.select = DMAREQ_UART1_TXBL;
|
channelConfig.select = DMAREQ_UART1_TXBL;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef USART0
|
#ifdef USART0
|
||||||
case USART_0:
|
case USART_0:
|
||||||
channelConfig.select = DMAREQ_USART0_TXBL;
|
channelConfig.select = DMAREQ_USART0_TXBL;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef USART1
|
#ifdef USART1
|
||||||
case USART_1:
|
case USART_1:
|
||||||
channelConfig.select = DMAREQ_USART1_TXBL;
|
channelConfig.select = DMAREQ_USART1_TXBL;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef USART2
|
#ifdef USART2
|
||||||
case USART_2:
|
case USART_2:
|
||||||
channelConfig.select = DMAREQ_USART2_TXBL;
|
channelConfig.select = DMAREQ_USART2_TXBL;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef LEUART0
|
#ifdef LEUART0
|
||||||
case LEUART_0:
|
case LEUART_0:
|
||||||
channelConfig.select = DMAREQ_LEUART0_TXBL;
|
channelConfig.select = DMAREQ_LEUART0_TXBL;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef LEUART1
|
#ifdef LEUART1
|
||||||
case LEUART_1:
|
case LEUART_1:
|
||||||
channelConfig.select = DMAREQ_LEUART1_TXBL;
|
channelConfig.select = DMAREQ_LEUART1_TXBL;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
DMA_CfgChannel(obj->serial.dmaOptionsTX.dmaChannel, &channelConfig);
|
DMA_CfgChannel(obj->serial.dmaOptionsTX.dmaChannel, &channelConfig);
|
||||||
} else {
|
} else {
|
||||||
//setup RX channel
|
//setup RX channel
|
||||||
channelConfig.highPri = true;
|
channelConfig.highPri = true;
|
||||||
channelConfig.enableInt = true;
|
channelConfig.enableInt = true;
|
||||||
channelConfig.cb = &(obj->serial.dmaOptionsRX.dmaCallback);
|
channelConfig.cb = &(obj->serial.dmaOptionsRX.dmaCallback);
|
||||||
|
|
||||||
switch((uint32_t)(obj->serial.periph.uart)) {
|
switch((uint32_t)(obj->serial.periph.uart)) {
|
||||||
#ifdef UART0
|
#ifdef UART0
|
||||||
case UART_0:
|
case UART_0:
|
||||||
channelConfig.select = DMAREQ_UART0_RXDATAV;
|
channelConfig.select = DMAREQ_UART0_RXDATAV;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef UART1
|
#ifdef UART1
|
||||||
case UART_1:
|
case UART_1:
|
||||||
channelConfig.select = DMAREQ_UART1_RXDATAV;
|
channelConfig.select = DMAREQ_UART1_RXDATAV;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef USART0
|
#ifdef USART0
|
||||||
case USART_0:
|
case USART_0:
|
||||||
channelConfig.select = DMAREQ_USART0_RXDATAV;
|
channelConfig.select = DMAREQ_USART0_RXDATAV;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef USART1
|
#ifdef USART1
|
||||||
case USART_1:
|
case USART_1:
|
||||||
channelConfig.select = DMAREQ_USART1_RXDATAV;
|
channelConfig.select = DMAREQ_USART1_RXDATAV;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef USART2
|
#ifdef USART2
|
||||||
case USART_2:
|
case USART_2:
|
||||||
channelConfig.select = DMAREQ_USART2_RXDATAV;
|
channelConfig.select = DMAREQ_USART2_RXDATAV;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef LEUART0
|
#ifdef LEUART0
|
||||||
case LEUART_0:
|
case LEUART_0:
|
||||||
channelConfig.select = DMAREQ_LEUART0_RXDATAV;
|
channelConfig.select = DMAREQ_LEUART0_RXDATAV;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef LEUART1
|
#ifdef LEUART1
|
||||||
case LEUART_1:
|
case LEUART_1:
|
||||||
channelConfig.select = DMAREQ_LEUART1_RXDATAV;
|
channelConfig.select = DMAREQ_LEUART1_RXDATAV;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
DMA_CfgChannel(obj->serial.dmaOptionsRX.dmaChannel, &channelConfig);
|
DMA_CfgChannel(obj->serial.dmaOptionsRX.dmaChannel, &channelConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -994,57 +997,59 @@ static void serial_dmaSetupChannel(serial_t *obj, bool tx_nrx) {
|
||||||
* Will try to allocate a channel and keep it.
|
* Will try to allocate a channel and keep it.
|
||||||
* If succesfully allocated, state changes to DMA_USAGE_ALLOCATED.
|
* 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) {
|
static void serial_dmaTrySetState(DMA_OPTIONS_t *obj, DMAUsage requestedState, serial_t *serialPtr, bool tx_nrx)
|
||||||
DMAUsage currentState = obj->dmaUsageState;
|
{
|
||||||
int tempDMAChannel = -1;
|
DMAUsage currentState = obj->dmaUsageState;
|
||||||
|
int tempDMAChannel = -1;
|
||||||
|
|
||||||
if ((requestedState == DMA_USAGE_ALWAYS) && (currentState != DMA_USAGE_ALLOCATED)) {
|
if ((requestedState == DMA_USAGE_ALWAYS) && (currentState != DMA_USAGE_ALLOCATED)) {
|
||||||
/* Try to allocate channel */
|
/* Try to allocate channel */
|
||||||
tempDMAChannel = dma_channel_allocate(DMA_CAP_NONE);
|
tempDMAChannel = dma_channel_allocate(DMA_CAP_NONE);
|
||||||
if(tempDMAChannel >= 0) {
|
if(tempDMAChannel >= 0) {
|
||||||
obj->dmaChannel = tempDMAChannel;
|
obj->dmaChannel = tempDMAChannel;
|
||||||
obj->dmaUsageState = DMA_USAGE_ALLOCATED;
|
obj->dmaUsageState = DMA_USAGE_ALLOCATED;
|
||||||
dma_init();
|
dma_init();
|
||||||
serial_dmaSetupChannel(serialPtr, tx_nrx);
|
serial_dmaSetupChannel(serialPtr, tx_nrx);
|
||||||
}
|
}
|
||||||
} else if (requestedState == DMA_USAGE_OPPORTUNISTIC) {
|
} else if (requestedState == DMA_USAGE_OPPORTUNISTIC) {
|
||||||
if (currentState == DMA_USAGE_ALLOCATED) {
|
if (currentState == DMA_USAGE_ALLOCATED) {
|
||||||
/* Channels have already been allocated previously by an ALWAYS state, so after this transfer, we will release them */
|
/* Channels have already been allocated previously by an ALWAYS state, so after this transfer, we will release them */
|
||||||
obj->dmaUsageState = DMA_USAGE_TEMPORARY_ALLOCATED;
|
obj->dmaUsageState = DMA_USAGE_TEMPORARY_ALLOCATED;
|
||||||
} else {
|
} else {
|
||||||
/* Try to allocate channel */
|
/* Try to allocate channel */
|
||||||
tempDMAChannel = dma_channel_allocate(DMA_CAP_NONE);
|
tempDMAChannel = dma_channel_allocate(DMA_CAP_NONE);
|
||||||
if(tempDMAChannel >= 0) {
|
if(tempDMAChannel >= 0) {
|
||||||
obj->dmaChannel = tempDMAChannel;
|
obj->dmaChannel = tempDMAChannel;
|
||||||
obj->dmaUsageState = DMA_USAGE_TEMPORARY_ALLOCATED;
|
obj->dmaUsageState = DMA_USAGE_TEMPORARY_ALLOCATED;
|
||||||
dma_init();
|
dma_init();
|
||||||
serial_dmaSetupChannel(serialPtr, tx_nrx);
|
serial_dmaSetupChannel(serialPtr, tx_nrx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (requestedState == DMA_USAGE_NEVER) {
|
} else if (requestedState == DMA_USAGE_NEVER) {
|
||||||
/* If channel is allocated, get rid of it */
|
/* If channel is allocated, get rid of it */
|
||||||
dma_channel_free(obj->dmaChannel);
|
dma_channel_free(obj->dmaChannel);
|
||||||
obj->dmaChannel = -1;
|
obj->dmaChannel = -1;
|
||||||
obj->dmaUsageState = DMA_USAGE_NEVER;
|
obj->dmaUsageState = DMA_USAGE_NEVER;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void serial_dmaActivate(serial_t *obj, void* cb, void* buffer, int length, bool tx_nrx) {
|
static void serial_dmaActivate(serial_t *obj, void* cb, void* buffer, int length, bool tx_nrx)
|
||||||
DMA_CfgDescr_TypeDef channelConfig;
|
{
|
||||||
|
DMA_CfgDescr_TypeDef channelConfig;
|
||||||
|
|
||||||
if(tx_nrx) {
|
if(tx_nrx) {
|
||||||
// Set DMA callback
|
// Set DMA callback
|
||||||
obj->serial.dmaOptionsTX.dmaCallback.cbFunc = serial_dmaTransferComplete;
|
obj->serial.dmaOptionsTX.dmaCallback.cbFunc = serial_dmaTransferComplete;
|
||||||
obj->serial.dmaOptionsTX.dmaCallback.userPtr = cb;
|
obj->serial.dmaOptionsTX.dmaCallback.userPtr = cb;
|
||||||
|
|
||||||
// Set up configuration structure
|
// Set up configuration structure
|
||||||
channelConfig.dstInc = dmaDataIncNone;
|
channelConfig.dstInc = dmaDataIncNone;
|
||||||
channelConfig.srcInc = dmaDataInc1;
|
channelConfig.srcInc = dmaDataInc1;
|
||||||
channelConfig.size = dmaDataSize1;
|
channelConfig.size = dmaDataSize1;
|
||||||
channelConfig.arbRate = dmaArbitrate1;
|
channelConfig.arbRate = dmaArbitrate1;
|
||||||
channelConfig.hprot = 0;
|
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)) {
|
if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
|
||||||
// Activate TX
|
// Activate TX
|
||||||
|
@ -1065,19 +1070,19 @@ static void serial_dmaActivate(serial_t *obj, void* cb, void* buffer, int length
|
||||||
// Kick off TX DMA
|
// Kick off TX DMA
|
||||||
DMA_ActivateBasic(obj->serial.dmaOptionsTX.dmaChannel, true, false, (void*) &(obj->serial.periph.uart->TXDATA), buffer, length - 1);
|
DMA_ActivateBasic(obj->serial.dmaOptionsTX.dmaChannel, true, false, (void*) &(obj->serial.periph.uart->TXDATA), buffer, length - 1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Set DMA callback
|
// Set DMA callback
|
||||||
obj->serial.dmaOptionsRX.dmaCallback.cbFunc = serial_dmaTransferComplete;
|
obj->serial.dmaOptionsRX.dmaCallback.cbFunc = serial_dmaTransferComplete;
|
||||||
obj->serial.dmaOptionsRX.dmaCallback.userPtr = cb;
|
obj->serial.dmaOptionsRX.dmaCallback.userPtr = cb;
|
||||||
|
|
||||||
// Set up configuration structure
|
// Set up configuration structure
|
||||||
channelConfig.dstInc = dmaDataInc1;
|
channelConfig.dstInc = dmaDataInc1;
|
||||||
channelConfig.srcInc = dmaDataIncNone;
|
channelConfig.srcInc = dmaDataIncNone;
|
||||||
channelConfig.size = dmaDataSize1;
|
channelConfig.size = dmaDataSize1;
|
||||||
channelConfig.arbRate = dmaArbitrate1;
|
channelConfig.arbRate = dmaArbitrate1;
|
||||||
channelConfig.hprot = 0;
|
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)) {
|
if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
|
||||||
// Activate RX
|
// Activate RX
|
||||||
|
@ -1098,7 +1103,7 @@ static void serial_dmaActivate(serial_t *obj, void* cb, void* buffer, int length
|
||||||
// Kick off RX DMA
|
// Kick off RX DMA
|
||||||
DMA_ActivateBasic(obj->serial.dmaOptionsRX.dmaChannel, true, false, buffer, (void*) &(obj->serial.periph.uart->RXDATA), length - 1);
|
DMA_ActivateBasic(obj->serial.dmaOptionsRX.dmaChannel, true, false, buffer, (void*) &(obj->serial.periph.uart->RXDATA), length - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
|
@ -1117,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 event The logical OR of the TX events to configure
|
||||||
* @param enable Set to non-zero to enable events, or zero to disable them
|
* @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) {
|
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;
|
// Shouldn't have to enable TX interrupt here, just need to keep track of the requested events.
|
||||||
else obj->serial.events &= ~event;
|
if(enable) obj->serial.events |= event;
|
||||||
|
else obj->serial.events &= ~event;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1128,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 event The logical OR of the RX events to configure
|
||||||
* @param enable Set to non-zero to enable events, or zero to disable them
|
* @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) {
|
void serial_rx_enable_event(serial_t *obj, int event, uint8_t enable)
|
||||||
if(enable) {
|
{
|
||||||
obj->serial.events |= event;
|
if(enable) {
|
||||||
} else {
|
obj->serial.events |= event;
|
||||||
obj->serial.events &= ~event;
|
} else {
|
||||||
}
|
obj->serial.events &= ~event;
|
||||||
|
}
|
||||||
if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
|
if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
|
||||||
if(event & SERIAL_EVENT_RX_FRAMING_ERROR) {
|
if(event & SERIAL_EVENT_RX_FRAMING_ERROR) {
|
||||||
//FERR interrupt source
|
//FERR interrupt source
|
||||||
|
@ -1187,17 +1194,18 @@ void serial_rx_enable_event(serial_t *obj, int event, uint8_t enable) {
|
||||||
* @param tx The buffer for sending.
|
* @param tx The buffer for sending.
|
||||||
* @param tx_length The number of words to transmit.
|
* @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) {
|
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);
|
// 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.buffer = tx;
|
||||||
obj->tx_buff.length = tx_length;
|
obj->tx_buff.length = tx_length;
|
||||||
obj->tx_buff.pos = 0;
|
obj->tx_buff.pos = 0;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Configure the TX buffer for an asynchronous read serial transaction
|
/** Configure the TX buffer for an asynchronous read serial transaction
|
||||||
|
@ -1206,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 The buffer for receiving.
|
||||||
* @param rx_length The number of words to read.
|
* @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) {
|
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);
|
// 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.buffer = rx;
|
||||||
obj->rx_buff.length = rx_length;
|
obj->rx_buff.length = rx_length;
|
||||||
obj->rx_buff.pos = 0;
|
obj->rx_buff.pos = 0;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Set character to be matched. If an event is enabled, and received character
|
/** Set character to be matched. If an event is enabled, and received character
|
||||||
|
@ -1226,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 obj The serial object
|
||||||
* @param char_match A character in range 0-254
|
* @param char_match A character in range 0-254
|
||||||
*/
|
*/
|
||||||
void serial_set_char_match(serial_t *obj, uint8_t 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.
|
// We only have hardware support for this in LEUART.
|
||||||
if (char_match != SERIAL_RESERVED_CHAR_MATCH) {
|
// When in USART/UART, we can set up a check in the receiving ISR, but not when using DMA.
|
||||||
obj->char_match = char_match;
|
if (char_match != SERIAL_RESERVED_CHAR_MATCH) {
|
||||||
|
obj->char_match = char_match;
|
||||||
|
|
||||||
if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
|
if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
|
||||||
obj->serial.periph.leuart->SIGFRAME = char_match & 0x000000FF;
|
obj->serial.periph.leuart->SIGFRAME = char_match & 0x000000FF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************
|
/************************************
|
||||||
|
@ -1252,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
|
* @param hint A suggestion for how to use DMA with this transfer
|
||||||
* @return Returns number of data transfered, or 0 otherwise
|
* @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) {
|
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);
|
// Check that a buffer has indeed been set up
|
||||||
if(tx_length == 0) return 0;
|
MBED_ASSERT(tx != (void*)0);
|
||||||
|
if(tx_length == 0) return 0;
|
||||||
|
|
||||||
// Set up buffer
|
// Set up buffer
|
||||||
serial_tx_buffer_set(obj, tx, tx_length, tx_width);
|
serial_tx_buffer_set(obj, tx, tx_length, tx_width);
|
||||||
|
|
||||||
// Set up events
|
// Set up events
|
||||||
serial_tx_enable_event(obj, SERIAL_EVENT_TX_ALL, false);
|
serial_tx_enable_event(obj, SERIAL_EVENT_TX_ALL, false);
|
||||||
serial_tx_enable_event(obj, event, true);
|
serial_tx_enable_event(obj, event, true);
|
||||||
|
|
||||||
// Set up sleepmode
|
// Set up sleepmode
|
||||||
blockSleepMode(SERIAL_LEAST_ACTIVE_SLEEPMODE);
|
blockSleepMode(SERIAL_LEAST_ACTIVE_SLEEPMODE);
|
||||||
|
|
||||||
// Determine DMA strategy
|
// Determine DMA strategy
|
||||||
serial_dmaTrySetState(&(obj->serial.dmaOptionsTX), hint, obj, true);
|
serial_dmaTrySetState(&(obj->serial.dmaOptionsTX), hint, obj, true);
|
||||||
|
|
||||||
// If DMA, kick off DMA transfer
|
// If DMA, kick off DMA transfer
|
||||||
if(obj->serial.dmaOptionsTX.dmaChannel >= 0) {
|
if(obj->serial.dmaOptionsTX.dmaChannel >= 0) {
|
||||||
serial_dmaActivate(obj, (void*)handler, obj->tx_buff.buffer, obj->tx_buff.length, true);
|
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, activate interrupt. TXBL will take care of buffer filling through ISR.
|
||||||
else {
|
else {
|
||||||
// Store callback
|
// Store callback
|
||||||
NVIC_ClearPendingIRQ(serial_get_tx_irq_index(obj));
|
NVIC_ClearPendingIRQ(serial_get_tx_irq_index(obj));
|
||||||
NVIC_DisableIRQ(serial_get_tx_irq_index(obj));
|
NVIC_DisableIRQ(serial_get_tx_irq_index(obj));
|
||||||
NVIC_SetPriority(serial_get_tx_irq_index(obj), 1);
|
NVIC_SetPriority(serial_get_tx_irq_index(obj), 1);
|
||||||
NVIC_SetVector(serial_get_tx_irq_index(obj), (uint32_t)handler);
|
NVIC_SetVector(serial_get_tx_irq_index(obj), (uint32_t)handler);
|
||||||
NVIC_EnableIRQ(serial_get_tx_irq_index(obj));
|
NVIC_EnableIRQ(serial_get_tx_irq_index(obj));
|
||||||
|
|
||||||
if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
|
if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
|
||||||
// Activate TX and return
|
// Activate TX and return
|
||||||
|
@ -1302,9 +1313,9 @@ int serial_tx_asynch(serial_t *obj, void *tx, size_t tx_length, uint8_t tx_width
|
||||||
// Enable interrupt
|
// Enable interrupt
|
||||||
USART_IntEnable(obj->serial.periph.uart, USART_IEN_TXBL);
|
USART_IntEnable(obj->serial.periph.uart, USART_IEN_TXBL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Begin asynchronous RX transfer (enable interrupt for data collecting)
|
/** Begin asynchronous RX transfer (enable interrupt for data collecting)
|
||||||
|
@ -1314,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 cb The function to call when an event occurs
|
||||||
* @param hint A suggestion for how to use DMA with this transfer
|
* @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) {
|
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);
|
// Check that a buffer has indeed been set up
|
||||||
if(rx_length == 0) return;
|
MBED_ASSERT(rx != (void*)0);
|
||||||
|
if(rx_length == 0) return;
|
||||||
|
|
||||||
// Set up buffer
|
// Set up buffer
|
||||||
serial_rx_buffer_set(obj, rx, rx_length, rx_width);
|
serial_rx_buffer_set(obj, rx, rx_length, rx_width);
|
||||||
|
|
||||||
// Set up events
|
// Set up events
|
||||||
serial_rx_enable_event(obj, SERIAL_EVENT_RX_ALL, false);
|
serial_rx_enable_event(obj, SERIAL_EVENT_RX_ALL, false);
|
||||||
serial_rx_enable_event(obj, event, true);
|
serial_rx_enable_event(obj, event, true);
|
||||||
serial_set_char_match(obj, char_match);
|
serial_set_char_match(obj, char_match);
|
||||||
|
|
||||||
// Set up sleepmode
|
// Set up sleepmode
|
||||||
blockSleepMode(SERIAL_LEAST_ACTIVE_SLEEPMODE);
|
blockSleepMode(SERIAL_LEAST_ACTIVE_SLEEPMODE);
|
||||||
|
|
||||||
// Determine DMA strategy
|
// 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 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)) {
|
if(!(event & SERIAL_EVENT_RX_CHARACTER_MATCH)) {
|
||||||
serial_dmaTrySetState(&(obj->serial.dmaOptionsRX), hint, obj, false);
|
serial_dmaTrySetState(&(obj->serial.dmaOptionsRX), hint, obj, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If DMA, kick off DMA
|
// If DMA, kick off DMA
|
||||||
if(obj->serial.dmaOptionsRX.dmaChannel >= 0) {
|
if(obj->serial.dmaOptionsRX.dmaChannel >= 0) {
|
||||||
serial_dmaActivate(obj, (void*)handler, obj->rx_buff.buffer, obj->rx_buff.length, false);
|
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, activate interrupt. RXDATAV is responsible for incoming data notification.
|
||||||
else {
|
else {
|
||||||
// Store callback
|
// Store callback
|
||||||
NVIC_ClearPendingIRQ(serial_get_rx_irq_index(obj));
|
NVIC_ClearPendingIRQ(serial_get_rx_irq_index(obj));
|
||||||
NVIC_SetVector(serial_get_rx_irq_index(obj), (uint32_t)handler);
|
NVIC_SetVector(serial_get_rx_irq_index(obj), (uint32_t)handler);
|
||||||
NVIC_EnableIRQ(serial_get_rx_irq_index(obj));
|
NVIC_EnableIRQ(serial_get_rx_irq_index(obj));
|
||||||
|
|
||||||
if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
|
if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
|
||||||
// Activate RX
|
// Activate RX
|
||||||
|
@ -1369,9 +1381,9 @@ void serial_rx_asynch(serial_t *obj, void *rx, size_t rx_length, uint8_t rx_widt
|
||||||
// Enable interrupt
|
// Enable interrupt
|
||||||
USART_IntEnable(obj->serial.periph.uart, USART_IEN_RXDATAV);
|
USART_IntEnable(obj->serial.periph.uart, USART_IEN_RXDATAV);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Attempts to determine if the serial peripheral is already in use for TX
|
/** Attempts to determine if the serial peripheral is already in use for TX
|
||||||
|
@ -1379,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
|
* @param obj The serial object
|
||||||
* @return Non-zero if the TX transaction is ongoing, 0 otherwise
|
* @return Non-zero if the TX transaction is ongoing, 0 otherwise
|
||||||
*/
|
*/
|
||||||
uint8_t serial_tx_active(serial_t *obj) {
|
uint8_t serial_tx_active(serial_t *obj)
|
||||||
switch(obj->serial.dmaOptionsTX.dmaUsageState) {
|
{
|
||||||
case DMA_USAGE_TEMPORARY_ALLOCATED:
|
switch(obj->serial.dmaOptionsTX.dmaUsageState) {
|
||||||
/* Temporary allocation always means its active, as this state gets cleared afterwards */
|
case DMA_USAGE_TEMPORARY_ALLOCATED:
|
||||||
return 1;
|
/* Temporary allocation always means its active, as this state gets cleared afterwards */
|
||||||
case DMA_USAGE_ALLOCATED:
|
return 1;
|
||||||
/* Check whether the allocated DMA channel is active by checking the DMA transfer */
|
case DMA_USAGE_ALLOCATED:
|
||||||
return(DMA_ChannelEnabled(obj->serial.dmaOptionsTX.dmaChannel));
|
/* Check whether the allocated DMA channel is active by checking the DMA transfer */
|
||||||
default:
|
return(DMA_ChannelEnabled(obj->serial.dmaOptionsTX.dmaChannel));
|
||||||
/* Check whether interrupt for serial TX is enabled */
|
default:
|
||||||
|
/* Check whether interrupt for serial TX is enabled */
|
||||||
if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
|
if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
|
||||||
return (obj->serial.periph.leuart->IEN & (LEUART_IEN_TXBL)) ? true : false;
|
return (obj->serial.periph.leuart->IEN & (LEUART_IEN_TXBL)) ? true : false;
|
||||||
} else {
|
} else {
|
||||||
return (obj->serial.periph.uart->IEN & (USART_IEN_TXBL)) ? true : false;
|
return (obj->serial.periph.uart->IEN & (USART_IEN_TXBL)) ? true : false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Attempts to determine if the serial peripheral is already in use for RX
|
/** Attempts to determine if the serial peripheral is already in use for RX
|
||||||
|
@ -1402,22 +1415,23 @@ uint8_t serial_tx_active(serial_t *obj) {
|
||||||
* @param obj The serial object
|
* @param obj The serial object
|
||||||
* @return Non-zero if the RX transaction is ongoing, 0 otherwise
|
* @return Non-zero if the RX transaction is ongoing, 0 otherwise
|
||||||
*/
|
*/
|
||||||
uint8_t serial_rx_active(serial_t *obj) {
|
uint8_t serial_rx_active(serial_t *obj)
|
||||||
switch(obj->serial.dmaOptionsRX.dmaUsageState) {
|
{
|
||||||
case DMA_USAGE_TEMPORARY_ALLOCATED:
|
switch(obj->serial.dmaOptionsRX.dmaUsageState) {
|
||||||
/* Temporary allocation always means its active, as this state gets cleared afterwards */
|
case DMA_USAGE_TEMPORARY_ALLOCATED:
|
||||||
return 1;
|
/* Temporary allocation always means its active, as this state gets cleared afterwards */
|
||||||
case DMA_USAGE_ALLOCATED:
|
return 1;
|
||||||
/* Check whether the allocated DMA channel is active by checking the DMA transfer */
|
case DMA_USAGE_ALLOCATED:
|
||||||
return(DMA_ChannelEnabled(obj->serial.dmaOptionsRX.dmaChannel));
|
/* Check whether the allocated DMA channel is active by checking the DMA transfer */
|
||||||
default:
|
return(DMA_ChannelEnabled(obj->serial.dmaOptionsRX.dmaChannel));
|
||||||
/* Check whether interrupt for serial TX is enabled */
|
default:
|
||||||
|
/* Check whether interrupt for serial TX is enabled */
|
||||||
if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
|
if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
|
||||||
return (obj->serial.periph.leuart->IEN & (LEUART_IEN_RXDATAV)) ? true : false;
|
return (obj->serial.periph.leuart->IEN & (LEUART_IEN_RXDATAV)) ? true : false;
|
||||||
} else {
|
} else {
|
||||||
return (obj->serial.periph.uart->IEN & (USART_IEN_RXDATAV)) ? true : false;
|
return (obj->serial.periph.uart->IEN & (USART_IEN_RXDATAV)) ? true : false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The asynchronous TX handler. Writes to the TX FIFO and checks for events.
|
/** The asynchronous TX handler. Writes to the TX FIFO and checks for events.
|
||||||
|
@ -1426,17 +1440,18 @@ uint8_t serial_rx_active(serial_t *obj) {
|
||||||
* @param obj The serial object
|
* @param obj The serial object
|
||||||
* @return Returns event flags if a TX transfer termination condition was met or 0 otherwise
|
* @return Returns event flags if a TX transfer termination condition was met or 0 otherwise
|
||||||
*/
|
*/
|
||||||
int serial_tx_irq_handler_asynch(serial_t *obj) {
|
int serial_tx_irq_handler_asynch(serial_t *obj)
|
||||||
/* This interrupt handler is called from USART irq */
|
{
|
||||||
uint8_t *buf = obj->tx_buff.buffer;
|
/* This interrupt handler is called from USART irq */
|
||||||
|
uint8_t *buf = obj->tx_buff.buffer;
|
||||||
|
|
||||||
/* Interrupt has another TX source */
|
/* Interrupt has another TX source */
|
||||||
if(obj->tx_buff.pos >= obj->tx_buff.length) {
|
if(obj->tx_buff.pos >= obj->tx_buff.length) {
|
||||||
/* Transfer complete. Switch off interrupt and return event. */
|
/* Transfer complete. Switch off interrupt and return event. */
|
||||||
serial_tx_abort_asynch(obj);
|
serial_tx_abort_asynch(obj);
|
||||||
return SERIAL_EVENT_TX_COMPLETE & obj->serial.events;
|
return SERIAL_EVENT_TX_COMPLETE & obj->serial.events;
|
||||||
} else {
|
} else {
|
||||||
/* There's still data in the buffer that needs to be sent */
|
/* There's still data in the buffer that needs to be sent */
|
||||||
if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
|
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))) {
|
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]);
|
LEUART_Tx(obj->serial.periph.leuart, buf[obj->tx_buff.pos]);
|
||||||
|
@ -1448,8 +1463,8 @@ int serial_tx_irq_handler_asynch(serial_t *obj) {
|
||||||
obj->tx_buff.pos++;
|
obj->tx_buff.pos++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The asynchronous RX handler. Reads from the RX FIFOF and checks for events.
|
/** The asynchronous RX handler. Reads from the RX FIFOF and checks for events.
|
||||||
|
@ -1458,11 +1473,12 @@ int serial_tx_irq_handler_asynch(serial_t *obj) {
|
||||||
* @param obj The serial object
|
* @param obj The serial object
|
||||||
* @return Returns event flags if a RX transfer termination condition was met or 0 otherwise
|
* @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 serial_rx_irq_handler_asynch(serial_t *obj)
|
||||||
int event = 0;
|
{
|
||||||
|
int event = 0;
|
||||||
|
|
||||||
/* This interrupt handler is called from USART irq */
|
/* This interrupt handler is called from USART irq */
|
||||||
uint8_t *buf = (uint8_t*)obj->rx_buff.buffer;
|
uint8_t *buf = (uint8_t*)obj->rx_buff.buffer;
|
||||||
|
|
||||||
if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
|
if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
|
||||||
/* Determine the source of the interrupt */
|
/* Determine the source of the interrupt */
|
||||||
|
@ -1591,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 */
|
/* All events should have generated a return, if no return has happened, no event has been caught */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Unified IRQ handler. Determines the appropriate handler to execute and returns the flags.
|
/** 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.
|
* WARNING: this code should be stateless, as re-entrancy is very possible in interrupt-based mode.
|
||||||
*/
|
*/
|
||||||
int serial_irq_handler_asynch(serial_t *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]) {
|
/* First, check if we're running in DMA mode */
|
||||||
/* Clean up */
|
if(serial_dma_irq_fired[obj->serial.dmaOptionsRX.dmaChannel]) {
|
||||||
serial_dma_irq_fired[obj->serial.dmaOptionsRX.dmaChannel] = false;
|
/* Clean up */
|
||||||
serial_rx_abort_asynch(obj);
|
serial_dma_irq_fired[obj->serial.dmaOptionsRX.dmaChannel] = false;
|
||||||
|
serial_rx_abort_asynch(obj);
|
||||||
|
|
||||||
/* Notify CPP land of RX completion */
|
/* Notify CPP land of RX completion */
|
||||||
return SERIAL_EVENT_RX_COMPLETE & obj->serial.events;
|
return SERIAL_EVENT_RX_COMPLETE & obj->serial.events;
|
||||||
} else if (serial_dma_irq_fired[obj->serial.dmaOptionsTX.dmaChannel]) {
|
} else if (serial_dma_irq_fired[obj->serial.dmaOptionsTX.dmaChannel]) {
|
||||||
/* Clean up */
|
/* Clean up */
|
||||||
serial_dma_irq_fired[obj->serial.dmaOptionsTX.dmaChannel] = false;
|
serial_dma_irq_fired[obj->serial.dmaOptionsTX.dmaChannel] = false;
|
||||||
serial_tx_abort_asynch(obj);
|
serial_tx_abort_asynch(obj);
|
||||||
|
|
||||||
/* Notify CPP land of completion */
|
/* Notify CPP land of completion */
|
||||||
return SERIAL_EVENT_TX_COMPLETE & obj->serial.events;
|
return SERIAL_EVENT_TX_COMPLETE & obj->serial.events;
|
||||||
} else {
|
} else {
|
||||||
/* Check the NVIC to see which interrupt we're running from
|
/* Check the NVIC to see which interrupt we're running from
|
||||||
* Also make sure to prioritize RX */
|
* Also make sure to prioritize RX */
|
||||||
if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
|
if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
|
||||||
//Different method of checking tx vs rx for 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)) {
|
if(LEUART_IntGetEnabled(obj->serial.periph.leuart) & (LEUART_IF_RXDATAV | LEUART_IF_FERR | LEUART_IF_PERR | LEUART_IF_RXOF | LEUART_IF_SIGF)) {
|
||||||
|
@ -1632,10 +1649,10 @@ int serial_irq_handler_asynch(serial_t *obj) {
|
||||||
return serial_tx_irq_handler_asynch(obj);
|
return serial_tx_irq_handler_asynch(obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// All should be done now
|
// All should be done now
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Abort the ongoing TX transaction. It disables the enabled interupt for TX and
|
/** Abort the ongoing TX transaction. It disables the enabled interupt for TX and
|
||||||
|
@ -1643,35 +1660,36 @@ int serial_irq_handler_asynch(serial_t *obj) {
|
||||||
*
|
*
|
||||||
* @param obj The serial object
|
* @param obj The serial object
|
||||||
*/
|
*/
|
||||||
void serial_tx_abort_asynch(serial_t *obj) {
|
void serial_tx_abort_asynch(serial_t *obj)
|
||||||
/* Stop transmitter */
|
{
|
||||||
//obj->serial.periph.uart->CMD |= USART_CMD_TXDIS;
|
/* Stop transmitter */
|
||||||
|
//obj->serial.periph.uart->CMD |= USART_CMD_TXDIS;
|
||||||
|
|
||||||
/* Clean up */
|
/* Clean up */
|
||||||
switch(obj->serial.dmaOptionsTX.dmaUsageState) {
|
switch(obj->serial.dmaOptionsTX.dmaUsageState) {
|
||||||
case DMA_USAGE_ALLOCATED:
|
case DMA_USAGE_ALLOCATED:
|
||||||
/* stop DMA transfer */
|
/* stop DMA transfer */
|
||||||
DMA_ChannelEnable(obj->serial.dmaOptionsTX.dmaChannel, false);
|
DMA_ChannelEnable(obj->serial.dmaOptionsTX.dmaChannel, false);
|
||||||
break;
|
break;
|
||||||
case DMA_USAGE_TEMPORARY_ALLOCATED:
|
case DMA_USAGE_TEMPORARY_ALLOCATED:
|
||||||
/* stop DMA transfer and release channel */
|
/* stop DMA transfer and release channel */
|
||||||
DMA_ChannelEnable(obj->serial.dmaOptionsTX.dmaChannel, false);
|
DMA_ChannelEnable(obj->serial.dmaOptionsTX.dmaChannel, false);
|
||||||
dma_channel_free(obj->serial.dmaOptionsTX.dmaChannel);
|
dma_channel_free(obj->serial.dmaOptionsTX.dmaChannel);
|
||||||
obj->serial.dmaOptionsTX.dmaChannel = -1;
|
obj->serial.dmaOptionsTX.dmaChannel = -1;
|
||||||
obj->serial.dmaOptionsTX.dmaUsageState = DMA_USAGE_OPPORTUNISTIC;
|
obj->serial.dmaOptionsTX.dmaUsageState = DMA_USAGE_OPPORTUNISTIC;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* stop interrupting */
|
/* stop interrupting */
|
||||||
if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
|
if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
|
||||||
LEUART_IntDisable(obj->serial.periph.leuart, LEUART_IEN_TXBL);
|
LEUART_IntDisable(obj->serial.periph.leuart, LEUART_IEN_TXBL);
|
||||||
} else {
|
} else {
|
||||||
USART_IntDisable(obj->serial.periph.uart, USART_IEN_TXBL);
|
USART_IntDisable(obj->serial.periph.uart, USART_IEN_TXBL);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unblock EM2 and below */
|
/* Unblock EM2 and below */
|
||||||
unblockSleepMode(SERIAL_LEAST_ACTIVE_SLEEPMODE);
|
unblockSleepMode(SERIAL_LEAST_ACTIVE_SLEEPMODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Abort the ongoing RX transaction It disables the enabled interrupt for RX and
|
/** Abort the ongoing RX transaction It disables the enabled interrupt for RX and
|
||||||
|
@ -1679,35 +1697,36 @@ void serial_tx_abort_asynch(serial_t *obj) {
|
||||||
*
|
*
|
||||||
* @param obj The serial object
|
* @param obj The serial object
|
||||||
*/
|
*/
|
||||||
void serial_rx_abort_asynch(serial_t *obj) {
|
void serial_rx_abort_asynch(serial_t *obj)
|
||||||
/* Stop receiver */
|
{
|
||||||
obj->serial.periph.uart->CMD |= USART_CMD_RXDIS;
|
/* Stop receiver */
|
||||||
|
obj->serial.periph.uart->CMD |= USART_CMD_RXDIS;
|
||||||
|
|
||||||
/* Clean up */
|
/* Clean up */
|
||||||
switch(obj->serial.dmaOptionsRX.dmaUsageState) {
|
switch(obj->serial.dmaOptionsRX.dmaUsageState) {
|
||||||
case DMA_USAGE_ALLOCATED:
|
case DMA_USAGE_ALLOCATED:
|
||||||
/* stop DMA transfer */
|
/* stop DMA transfer */
|
||||||
DMA_ChannelEnable(obj->serial.dmaOptionsRX.dmaChannel, false);
|
DMA_ChannelEnable(obj->serial.dmaOptionsRX.dmaChannel, false);
|
||||||
break;
|
break;
|
||||||
case DMA_USAGE_TEMPORARY_ALLOCATED:
|
case DMA_USAGE_TEMPORARY_ALLOCATED:
|
||||||
/* stop DMA transfer and release channel */
|
/* stop DMA transfer and release channel */
|
||||||
DMA_ChannelEnable(obj->serial.dmaOptionsRX.dmaChannel, false);
|
DMA_ChannelEnable(obj->serial.dmaOptionsRX.dmaChannel, false);
|
||||||
dma_channel_free(obj->serial.dmaOptionsRX.dmaChannel);
|
dma_channel_free(obj->serial.dmaOptionsRX.dmaChannel);
|
||||||
obj->serial.dmaOptionsRX.dmaChannel = -1;
|
obj->serial.dmaOptionsRX.dmaChannel = -1;
|
||||||
obj->serial.dmaOptionsRX.dmaUsageState = DMA_USAGE_OPPORTUNISTIC;
|
obj->serial.dmaOptionsRX.dmaUsageState = DMA_USAGE_OPPORTUNISTIC;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* stop interrupting */
|
/* stop interrupting */
|
||||||
if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
|
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);
|
LEUART_IntDisable(obj->serial.periph.leuart, LEUART_IEN_RXDATAV | LEUART_IEN_PERR | LEUART_IEN_FERR | LEUART_IEN_RXOF | LEUART_IEN_SIGF);
|
||||||
} else {
|
} else {
|
||||||
USART_IntDisable(obj->serial.periph.uart, USART_IEN_RXDATAV | USART_IEN_PERR | USART_IEN_FERR | USART_IEN_RXOF);
|
USART_IntDisable(obj->serial.periph.uart, USART_IEN_RXDATAV | USART_IEN_PERR | USART_IEN_FERR | USART_IEN_RXOF);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Say that we can stop using this emode */
|
/* Say that we can stop using this emode */
|
||||||
unblockSleepMode(SERIAL_LEAST_ACTIVE_SLEEPMODE);
|
unblockSleepMode(SERIAL_LEAST_ACTIVE_SLEEPMODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //DEVICE_SERIAL_ASYNCH
|
#endif //DEVICE_SERIAL_ASYNCH
|
||||||
|
|
|
@ -34,19 +34,19 @@ uint32_t sleep_block_counter[NUM_SLEEP_MODES] = {0};
|
||||||
*/
|
*/
|
||||||
void sleep(void)
|
void sleep(void)
|
||||||
{
|
{
|
||||||
if (sleep_block_counter[0] > 0) {
|
if (sleep_block_counter[0] > 0) {
|
||||||
// Blocked everything below EM0, so just return
|
// Blocked everything below EM0, so just return
|
||||||
return;
|
return;
|
||||||
} else if (sleep_block_counter[1] > 0) {
|
} else if (sleep_block_counter[1] > 0) {
|
||||||
// Blocked everything below EM1, enter EM1
|
// Blocked everything below EM1, enter EM1
|
||||||
EMU_EnterEM1();
|
EMU_EnterEM1();
|
||||||
} else if (sleep_block_counter[2] > 0) {
|
} else if (sleep_block_counter[2] > 0) {
|
||||||
// Blocked everything below EM2, enter EM2
|
// Blocked everything below EM2, enter EM2
|
||||||
EMU_EnterEM2(true);
|
EMU_EnterEM2(true);
|
||||||
} else if (sleep_block_counter[3] > 0) {
|
} else if (sleep_block_counter[3] > 0) {
|
||||||
// Blocked everything below EM3, enter EM3
|
// Blocked everything below EM3, enter EM3
|
||||||
EMU_EnterEM3(true);
|
EMU_EnterEM3(true);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,9 +76,9 @@ void deepsleep(void)
|
||||||
*/
|
*/
|
||||||
void blockSleepMode(sleepstate_enum minimumMode)
|
void blockSleepMode(sleepstate_enum minimumMode)
|
||||||
{
|
{
|
||||||
INT_Disable();
|
INT_Disable();
|
||||||
sleep_block_counter[minimumMode]++;
|
sleep_block_counter[minimumMode]++;
|
||||||
INT_Enable();
|
INT_Enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Unblock the microcontroller from sleeping below a certain mode
|
/** Unblock the microcontroller from sleeping below a certain mode
|
||||||
|
@ -90,12 +90,11 @@ void blockSleepMode(sleepstate_enum minimumMode)
|
||||||
*/
|
*/
|
||||||
void unblockSleepMode(sleepstate_enum minimumMode)
|
void unblockSleepMode(sleepstate_enum minimumMode)
|
||||||
{
|
{
|
||||||
INT_Disable();
|
INT_Disable();
|
||||||
if(sleep_block_counter[minimumMode] > 0)
|
if(sleep_block_counter[minimumMode] > 0) {
|
||||||
{
|
sleep_block_counter[minimumMode]--;
|
||||||
sleep_block_counter[minimumMode]--;
|
}
|
||||||
}
|
INT_Enable();
|
||||||
INT_Enable();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -35,7 +35,8 @@
|
||||||
static uint16_t fill_word = SPI_FILL_WORD;
|
static uint16_t fill_word = SPI_FILL_WORD;
|
||||||
#define SPI_LEAST_ACTIVE_SLEEPMODE EM1
|
#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) {
|
switch ((int)obj->spi.spi) {
|
||||||
#ifdef USART0
|
#ifdef USART0
|
||||||
case SPI_0:
|
case SPI_0:
|
||||||
|
@ -81,7 +82,8 @@ inline uint8_t spi_get_index(spi_t *obj)
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t spi_get_module(spi_t *obj) {
|
uint8_t spi_get_module(spi_t *obj)
|
||||||
|
{
|
||||||
return spi_get_index(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)
|
void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName clk, PinName cs)
|
||||||
{
|
{
|
||||||
CMU_ClockEnable(cmuClock_HFPER, true);
|
CMU_ClockEnable(cmuClock_HFPER, true);
|
||||||
spi_preinit(obj, mosi, miso, clk, cs);
|
spi_preinit(obj, mosi, miso, clk, cs);
|
||||||
CMU_ClockEnable(spi_get_clock_tree(obj), true);
|
CMU_ClockEnable(spi_get_clock_tree(obj), true);
|
||||||
usart_init(obj, 100000, usartDatabits8, true, usartClockMode0);
|
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);
|
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);
|
NVIC_SetVector(IRQvector, handler);
|
||||||
USART_IntEnable(obj->spi.spi, USART_IEN_RXDATAV);
|
USART_IntEnable(obj->spi.spi, USART_IEN_RXDATAV);
|
||||||
NVIC_EnableIRQ(IRQvector);
|
NVIC_EnableIRQ(IRQvector);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
NVIC_SetVector(IRQvector, handler);
|
NVIC_SetVector(IRQvector, handler);
|
||||||
USART_IntDisable(obj->spi.spi, USART_IEN_RXDATAV);
|
USART_IntDisable(obj->spi.spi, USART_IEN_RXDATAV);
|
||||||
NVIC_DisableIRQ(IRQvector);
|
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)
|
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;
|
uint32_t i;
|
||||||
uint16_t *tx_ptr = (uint16_t *) tx;
|
uint16_t *tx_ptr = (uint16_t *) tx;
|
||||||
|
|
||||||
tx_length *= (bit_width >> 3);
|
tx_length *= (bit_width >> 3);
|
||||||
rx_length *= (bit_width >> 3);
|
rx_length *= (bit_width >> 3);
|
||||||
|
|
||||||
obj->tx_buff.buffer = tx;
|
obj->tx_buff.buffer = tx;
|
||||||
obj->rx_buff.buffer = rx;
|
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;
|
obj->rx_buff.width = bit_width;
|
||||||
|
|
||||||
if((obj->spi.bits == 9) && (tx != 0)) {
|
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
|
// 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++) {
|
for(i = 0; i < (tx_length / 2); i++) {
|
||||||
tx_ptr[i] &= 0x1FF;
|
tx_ptr[i] &= 0x1FF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void spi_buffer_tx_write(spi_t *obj)
|
static void spi_buffer_tx_write(spi_t *obj)
|
||||||
{
|
{
|
||||||
uint32_t data;
|
uint32_t data;
|
||||||
// This routine gets triggered on TXBL (= buffer empty), so check to see if we can write a double value
|
// 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) {
|
if (obj->spi.bits % 9 != 0) {
|
||||||
// No special 9-bit scenario
|
// No special 9-bit scenario
|
||||||
if((obj->tx_buff.pos < obj->tx_buff.length - 1) && ((obj->tx_buff.pos & 0x1) == 0)) {
|
if((obj->tx_buff.pos < obj->tx_buff.length - 1) && ((obj->tx_buff.pos & 0x1) == 0)) {
|
||||||
// write double frame
|
// write double frame
|
||||||
if (obj->tx_buff.buffer == (void *)0) {
|
if (obj->tx_buff.buffer == (void *)0) {
|
||||||
data = SPI_FILL_WORD;
|
data = SPI_FILL_WORD;
|
||||||
} else {
|
} else {
|
||||||
uint16_t *tx = (uint16_t *)(obj->tx_buff.buffer);
|
uint16_t *tx = (uint16_t *)(obj->tx_buff.buffer);
|
||||||
data = tx[obj->tx_buff.pos / 2] & 0xFFFF;
|
data = tx[obj->tx_buff.pos / 2] & 0xFFFF;
|
||||||
}
|
}
|
||||||
obj->tx_buff.pos += 2;
|
obj->tx_buff.pos += 2;
|
||||||
obj->spi.spi->TXDOUBLE = data;
|
obj->spi.spi->TXDOUBLE = data;
|
||||||
} else if (obj->tx_buff.pos < obj->tx_buff.length) {
|
} else if (obj->tx_buff.pos < obj->tx_buff.length) {
|
||||||
// write single frame
|
// write single frame
|
||||||
if (obj->tx_buff.buffer == (void *)0) {
|
if (obj->tx_buff.buffer == (void *)0) {
|
||||||
data = SPI_FILL_WORD & 0xFF;
|
data = SPI_FILL_WORD & 0xFF;
|
||||||
} else {
|
} else {
|
||||||
uint8_t *tx = (uint8_t *)(obj->tx_buff.buffer);
|
uint8_t *tx = (uint8_t *)(obj->tx_buff.buffer);
|
||||||
data = tx[obj->tx_buff.pos] & 0xFF;
|
data = tx[obj->tx_buff.pos] & 0xFF;
|
||||||
}
|
}
|
||||||
obj->tx_buff.pos++;
|
obj->tx_buff.pos++;
|
||||||
obj->spi.spi->TXDATA = data;
|
obj->spi.spi->TXDATA = data;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 9-bit frame
|
// 9-bit frame
|
||||||
if(obj->tx_buff.pos < obj->tx_buff.length - 3) {
|
if(obj->tx_buff.pos < obj->tx_buff.length - 3) {
|
||||||
// write double frame
|
// write double frame
|
||||||
if (obj->tx_buff.buffer == (void *)0) {
|
if (obj->tx_buff.buffer == (void *)0) {
|
||||||
data = ((SPI_FILL_WORD & 0x01FF) << 16) | (SPI_FILL_WORD & 0x1FF);
|
data = ((SPI_FILL_WORD & 0x01FF) << 16) | (SPI_FILL_WORD & 0x1FF);
|
||||||
} else {
|
} else {
|
||||||
uint32_t *tx = (uint32_t *)(obj->tx_buff.buffer);
|
uint32_t *tx = (uint32_t *)(obj->tx_buff.buffer);
|
||||||
data = tx[obj->tx_buff.pos / 4] & 0x01FF01FF;
|
data = tx[obj->tx_buff.pos / 4] & 0x01FF01FF;
|
||||||
}
|
}
|
||||||
obj->tx_buff.pos += 4;
|
obj->tx_buff.pos += 4;
|
||||||
obj->spi.spi->TXDOUBLEX = data;
|
obj->spi.spi->TXDOUBLEX = data;
|
||||||
} else if (obj->tx_buff.pos < obj->tx_buff.length - 1) {
|
} else if (obj->tx_buff.pos < obj->tx_buff.length - 1) {
|
||||||
// write single frame
|
// write single frame
|
||||||
if (obj->tx_buff.buffer == (void *)0) {
|
if (obj->tx_buff.buffer == (void *)0) {
|
||||||
data = SPI_FILL_WORD & 0x01FF;
|
data = SPI_FILL_WORD & 0x01FF;
|
||||||
} else {
|
} else {
|
||||||
uint16_t *tx = (uint16_t *)(obj->tx_buff.buffer);
|
uint16_t *tx = (uint16_t *)(obj->tx_buff.buffer);
|
||||||
data = tx[obj->tx_buff.pos / 2] & 0x01FF;
|
data = tx[obj->tx_buff.pos / 2] & 0x01FF;
|
||||||
}
|
}
|
||||||
obj->tx_buff.pos += 2;
|
obj->tx_buff.pos += 2;
|
||||||
obj->spi.spi->TXDATAX = data;
|
obj->spi.spi->TXDATAX = data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void spi_buffer_rx_read(spi_t *obj)
|
static void spi_buffer_rx_read(spi_t *obj)
|
||||||
{
|
{
|
||||||
if (obj->spi.bits % 9 != 0) {
|
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)) {
|
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
|
// 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
|
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) {
|
if (obj->rx_buff.buffer) {
|
||||||
uint16_t *rx = (uint16_t *)(obj->rx_buff.buffer);
|
uint16_t *rx = (uint16_t *)(obj->rx_buff.buffer);
|
||||||
rx[obj->rx_buff.pos / 2] = data & 0xFFFF;
|
rx[obj->rx_buff.pos / 2] = data & 0xFFFF;
|
||||||
obj->rx_buff.pos += 2;
|
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)) {
|
} 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
|
// Read 8 bits from buffer
|
||||||
while((obj->spi.spi->STATUS & (USART_STATUS_RXDATAV | USART_STATUS_RXFULL)) && (obj->rx_buff.pos < obj->rx_buff.length)) {
|
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
|
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) {
|
if (obj->rx_buff.buffer) {
|
||||||
uint8_t *rx = (uint8_t *)(obj->rx_buff.buffer);
|
uint8_t *rx = (uint8_t *)(obj->rx_buff.buffer);
|
||||||
rx[obj->rx_buff.pos] = data & 0xFF;
|
rx[obj->rx_buff.pos] = data & 0xFF;
|
||||||
obj->rx_buff.pos++;
|
obj->rx_buff.pos++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (obj->spi.spi->STATUS & USART_STATUS_RXFULL) {
|
} else if (obj->spi.spi->STATUS & USART_STATUS_RXFULL) {
|
||||||
// Read from the buffer to lower the interrupt flag
|
// Read from the buffer to lower the interrupt flag
|
||||||
volatile uint32_t data = (uint32_t)obj->spi.spi->RXDOUBLE;
|
volatile uint32_t data = (uint32_t)obj->spi.spi->RXDOUBLE;
|
||||||
} else if (obj->spi.spi->STATUS & USART_STATUS_RXDATAV) {
|
} else if (obj->spi.spi->STATUS & USART_STATUS_RXDATAV) {
|
||||||
// Read from the buffer to lower the interrupt flag
|
// Read from the buffer to lower the interrupt flag
|
||||||
volatile uint32_t data = (uint32_t)obj->spi.spi->RXDATA;
|
volatile uint32_t data = (uint32_t)obj->spi.spi->RXDATA;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Data bits is multiple of 9, so use the extended registers
|
// 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)) {
|
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
|
// 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
|
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) {
|
if (obj->rx_buff.buffer) {
|
||||||
uint16_t *rx = (uint16_t *)(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] = data & 0x000001FF;
|
||||||
rx[(obj->rx_buff.pos / 2) + 1] = (data & 0x01FF0000) >> 16;
|
rx[(obj->rx_buff.pos / 2) + 1] = (data & 0x01FF0000) >> 16;
|
||||||
obj->rx_buff.pos += 4;
|
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)) {
|
} 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
|
// 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)) {
|
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
|
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) {
|
if (obj->rx_buff.buffer) {
|
||||||
uint16_t *rx = (uint16_t *)(obj->rx_buff.buffer);
|
uint16_t *rx = (uint16_t *)(obj->rx_buff.buffer);
|
||||||
rx[obj->rx_buff.pos / 2] = data & 0x01FF;
|
rx[obj->rx_buff.pos / 2] = data & 0x01FF;
|
||||||
obj->rx_buff.pos += 2;
|
obj->rx_buff.pos += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (obj->spi.spi->STATUS & USART_STATUS_RXFULL) {
|
} else if (obj->spi.spi->STATUS & USART_STATUS_RXFULL) {
|
||||||
// Read from the buffer to lower the interrupt flag
|
// Read from the buffer to lower the interrupt flag
|
||||||
volatile uint32_t data = (uint32_t)obj->spi.spi->RXDOUBLEX;
|
volatile uint32_t data = (uint32_t)obj->spi.spi->RXDOUBLEX;
|
||||||
} else if (obj->spi.spi->STATUS & USART_STATUS_RXDATAV) {
|
} else if (obj->spi.spi->STATUS & USART_STATUS_RXDATAV) {
|
||||||
// Read from the buffer to lower the interrupt flag
|
// Read from the buffer to lower the interrupt flag
|
||||||
volatile uint32_t data = (uint32_t)obj->spi.spi->RXDATAX;
|
volatile uint32_t data = (uint32_t)obj->spi.spi->RXDATAX;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int spi_master_write_asynch(spi_t *obj)
|
int spi_master_write_asynch(spi_t *obj)
|
||||||
|
@ -602,7 +603,7 @@ uint32_t spi_event_check(spi_t *obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
if(quit == true) {
|
if(quit == true) {
|
||||||
event |= SPI_EVENT_INTERNAL_TRANSFER_COMPLETE;
|
event |= SPI_EVENT_INTERNAL_TRANSFER_COMPLETE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return event;
|
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.
|
* 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;
|
int dmaChannelIn, dmaChannelOut;
|
||||||
dmaChannelIn = dma_channel_allocate(DMA_CAP_NONE);
|
dmaChannelIn = dma_channel_allocate(DMA_CAP_NONE);
|
||||||
if (dmaChannelIn == DMA_ERROR_OUT_OF_CHANNELS) {
|
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.enableInt = true;
|
||||||
txChnlCfg.cb = &(obj->spi.dmaOptionsTX.dmaCallback);
|
txChnlCfg.cb = &(obj->spi.dmaOptionsTX.dmaCallback);
|
||||||
|
|
||||||
switch ((int)obj->spi.spi) {
|
switch ((int)obj->spi.spi) {
|
||||||
#ifdef USART0
|
#ifdef USART0
|
||||||
case SPI_0:
|
case SPI_0:
|
||||||
rxChnlCfg.select = DMAREQ_USART0_RXDATAV;
|
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.
|
* * 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.
|
* * 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 descriptors */
|
||||||
DMA_CfgDescr_TypeDef rxDescrCfg;
|
DMA_CfgDescr_TypeDef rxDescrCfg;
|
||||||
DMA_CfgDescr_TypeDef txDescrCfg;
|
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;
|
obj->tx_buff.pos = tx_length;
|
||||||
|
|
||||||
if(obj->spi.bits != 9) {
|
if(obj->spi.bits != 9) {
|
||||||
/* Only activate RX DMA if a receive buffer is specified */
|
/* Only activate RX DMA if a receive buffer is specified */
|
||||||
if (rxdata != NULL) {
|
if (rxdata != NULL) {
|
||||||
// Setting up channel descriptor
|
// Setting up channel descriptor
|
||||||
rxDescrCfg.dstInc = dmaDataInc1;
|
rxDescrCfg.dstInc = dmaDataInc1;
|
||||||
rxDescrCfg.srcInc = dmaDataIncNone;
|
rxDescrCfg.srcInc = dmaDataIncNone;
|
||||||
rxDescrCfg.size = dmaDataSize1;
|
rxDescrCfg.size = dmaDataSize1;
|
||||||
rxDescrCfg.arbRate = dmaArbitrate1;
|
rxDescrCfg.arbRate = dmaArbitrate1;
|
||||||
rxDescrCfg.hprot = 0;
|
rxDescrCfg.hprot = 0;
|
||||||
DMA_CfgDescr(obj->spi.dmaOptionsRX.dmaChannel, true, &rxDescrCfg);
|
DMA_CfgDescr(obj->spi.dmaOptionsRX.dmaChannel, true, &rxDescrCfg);
|
||||||
|
|
||||||
// Clear RX registers - Useful if previous command transfered don't
|
// Clear RX registers - Useful if previous command transfered don't
|
||||||
obj->spi.spi->CMD = USART_CMD_CLEARRX;
|
obj->spi.spi->CMD = USART_CMD_CLEARRX;
|
||||||
|
|
||||||
/* Activate RX channel */
|
/* Activate RX channel */
|
||||||
DMA_ActivateBasic(obj->spi.dmaOptionsRX.dmaChannel, true, false, rxdata, (void *)&(obj->spi.spi->RXDATA),
|
DMA_ActivateBasic(obj->spi.dmaOptionsRX.dmaChannel, true, false, rxdata, (void *)&(obj->spi.spi->RXDATA),
|
||||||
rx_length - 1);
|
rx_length - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// buffer with all FFs.
|
// buffer with all FFs.
|
||||||
/* Setting up channel descriptor */
|
/* Setting up channel descriptor */
|
||||||
txDescrCfg.dstInc = dmaDataIncNone;
|
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.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.size = (obj->spi.bits <= 8 ? dmaDataSize1 : dmaDataSize2); //When frame size > 9, we can use TXDOUBLE to save bandwidth
|
||||||
txDescrCfg.arbRate = dmaArbitrate1;
|
txDescrCfg.arbRate = dmaArbitrate1;
|
||||||
txDescrCfg.hprot = 0;
|
txDescrCfg.hprot = 0;
|
||||||
DMA_CfgDescr(obj->spi.dmaOptionsTX.dmaChannel, true, &txDescrCfg);
|
DMA_CfgDescr(obj->spi.dmaOptionsTX.dmaChannel, true, &txDescrCfg);
|
||||||
|
|
||||||
/* Clear TX registers */
|
/* Clear TX registers */
|
||||||
obj->spi.spi->CMD = USART_CMD_CLEARTX;
|
obj->spi.spi->CMD = USART_CMD_CLEARTX;
|
||||||
|
|
||||||
/* Activate TX channel */
|
/* Activate TX channel */
|
||||||
DMA_ActivateBasic( obj->spi.dmaOptionsTX.dmaChannel,
|
DMA_ActivateBasic( obj->spi.dmaOptionsTX.dmaChannel,
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
(obj->spi.bits <= 8 ? (void *)&(obj->spi.spi->TXDATA) : (void *)&(obj->spi.spi->TXDOUBLE)), //When frame size > 9, point to TXDOUBLE
|
(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
|
(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
|
(obj->spi.bits <= 8 ? tx_length - 1 : (tx_length / 2) - 1)); // When using TXDOUBLE, recalculate transfer length
|
||||||
} else {
|
} else {
|
||||||
/* Frame size == 9 */
|
/* Frame size == 9 */
|
||||||
/* Only activate RX DMA if a receive buffer is specified */
|
/* Only activate RX DMA if a receive buffer is specified */
|
||||||
if (rxdata != NULL) {
|
if (rxdata != NULL) {
|
||||||
// Setting up channel descriptor
|
// Setting up channel descriptor
|
||||||
rxDescrCfg.dstInc = dmaDataInc2;
|
rxDescrCfg.dstInc = dmaDataInc2;
|
||||||
rxDescrCfg.srcInc = dmaDataIncNone;
|
rxDescrCfg.srcInc = dmaDataIncNone;
|
||||||
rxDescrCfg.size = dmaDataSize2;
|
rxDescrCfg.size = dmaDataSize2;
|
||||||
rxDescrCfg.arbRate = dmaArbitrate1;
|
rxDescrCfg.arbRate = dmaArbitrate1;
|
||||||
rxDescrCfg.hprot = 0;
|
rxDescrCfg.hprot = 0;
|
||||||
DMA_CfgDescr(obj->spi.dmaOptionsRX.dmaChannel, true, &rxDescrCfg);
|
DMA_CfgDescr(obj->spi.dmaOptionsRX.dmaChannel, true, &rxDescrCfg);
|
||||||
|
|
||||||
// Clear RX registers - Useful if previous command transfered don't
|
// Clear RX registers - Useful if previous command transfered don't
|
||||||
obj->spi.spi->CMD = USART_CMD_CLEARRX;
|
obj->spi.spi->CMD = USART_CMD_CLEARRX;
|
||||||
|
|
||||||
/* Activate RX channel */
|
/* Activate RX channel */
|
||||||
DMA_ActivateBasic(obj->spi.dmaOptionsRX.dmaChannel, true, false, rxdata, (void *)&(obj->spi.spi->RXDATAX),
|
DMA_ActivateBasic(obj->spi.dmaOptionsRX.dmaChannel, true, false, rxdata, (void *)&(obj->spi.spi->RXDATAX),
|
||||||
(rx_length / 2) - 1);
|
(rx_length / 2) - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Setting up channel descriptor */
|
/* Setting up channel descriptor */
|
||||||
txDescrCfg.dstInc = dmaDataIncNone;
|
txDescrCfg.dstInc = dmaDataIncNone;
|
||||||
txDescrCfg.srcInc = (txdata == 0 ? dmaDataIncNone : dmaDataInc2); //Do not increment source pointer when there is no transmit buffer
|
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.size = dmaDataSize2; //When frame size > 9, we can use TXDOUBLE to save bandwidth
|
||||||
txDescrCfg.arbRate = dmaArbitrate1;
|
txDescrCfg.arbRate = dmaArbitrate1;
|
||||||
txDescrCfg.hprot = 0;
|
txDescrCfg.hprot = 0;
|
||||||
DMA_CfgDescr(obj->spi.dmaOptionsTX.dmaChannel, true, &txDescrCfg);
|
DMA_CfgDescr(obj->spi.dmaOptionsTX.dmaChannel, true, &txDescrCfg);
|
||||||
|
|
||||||
/* Clear TX registers */
|
/* Clear TX registers */
|
||||||
obj->spi.spi->CMD = USART_CMD_CLEARTX;
|
obj->spi.spi->CMD = USART_CMD_CLEARTX;
|
||||||
|
|
||||||
/* Activate TX channel */
|
/* Activate TX channel */
|
||||||
DMA_ActivateBasic( obj->spi.dmaOptionsTX.dmaChannel,
|
DMA_ActivateBasic( obj->spi.dmaOptionsTX.dmaChannel,
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
(void *)&(obj->spi.spi->TXDATAX), //When frame size > 9, point to TXDOUBLE
|
(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
|
(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
|
(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.
|
* 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) {
|
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();
|
/* 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 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) {
|
if (hint != DMA_USAGE_NEVER && obj->spi.dmaOptionsTX.dmaUsageState == DMA_USAGE_ALLOCATED) {
|
||||||
/* setup has already been done, so just activate the transfer */
|
/* 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] handler SPI interrupt handler
|
||||||
* @param[in] hint A suggestion for how to use DMA with this transfer
|
* @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) {
|
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;
|
{
|
||||||
|
if( spi_active(obj) ) return;
|
||||||
|
|
||||||
/* update fill word if on 9-bit frame size */
|
/* update fill word if on 9-bit frame size */
|
||||||
if(obj->spi.bits == 9) fill_word = SPI_FILL_WORD & 0x1FF;
|
if(obj->spi.bits == 9) fill_word = SPI_FILL_WORD & 0x1FF;
|
||||||
else fill_word = SPI_FILL_WORD;
|
else fill_word = SPI_FILL_WORD;
|
||||||
|
|
||||||
/* check corner case */
|
/* check corner case */
|
||||||
if(tx_length == 0) {
|
if(tx_length == 0) {
|
||||||
tx_length = rx_length;
|
tx_length = rx_length;
|
||||||
tx = (void*) 0;
|
tx = (void*) 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* First, set the buffer */
|
/* First, set the buffer */
|
||||||
spi_buffer_set(obj, tx, tx_length, rx, rx_length, bit_width);
|
spi_buffer_set(obj, tx, tx_length, rx, rx_length, bit_width);
|
||||||
|
|
||||||
/* Then, enable the events */
|
/* Then, enable the events */
|
||||||
spi_enable_event(obj, SPI_EVENT_ALL, false);
|
spi_enable_event(obj, SPI_EVENT_ALL, false);
|
||||||
spi_enable_event(obj, event, true);
|
spi_enable_event(obj, event, true);
|
||||||
|
|
||||||
/* Be tricky on how we handle increased bit widths in the buffer... Handling on byte-basis */
|
/* Be tricky on how we handle increased bit widths in the buffer... Handling on byte-basis */
|
||||||
// div 8 = shift right 3
|
// div 8 = shift right 3
|
||||||
tx_length = tx_length * (bit_width >> 3);
|
tx_length = tx_length * (bit_width >> 3);
|
||||||
rx_length = rx_length * (bit_width >> 3);
|
rx_length = rx_length * (bit_width >> 3);
|
||||||
|
|
||||||
// Set the sleep mode
|
// Set the sleep mode
|
||||||
blockSleepMode(SPI_LEAST_ACTIVE_SLEEPMODE);
|
blockSleepMode(SPI_LEAST_ACTIVE_SLEEPMODE);
|
||||||
|
|
||||||
/* And kick off the transfer */
|
/* And kick off the transfer */
|
||||||
spi_master_transfer_dma(obj, tx, rx, tx_length, rx_length, (void*)handler, hint);
|
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.
|
* 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 */
|
/* 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 there is an RX transfer ongoing, wait for it to finish */
|
||||||
if (DMA_ChannelEnabled(obj->spi.dmaOptionsRX.dmaChannel)) {
|
if (DMA_ChannelEnabled(obj->spi.dmaOptionsRX.dmaChannel)) {
|
||||||
/* Check if we need to kick off TX transfer again to force more incoming data. */
|
/* Check if we need to kick off TX transfer again to force more incoming data. */
|
||||||
if (!DMA_ChannelEnabled(obj->spi.dmaOptionsTX.dmaChannel) && (obj->tx_buff.pos < obj->rx_buff.length)) {
|
if (!DMA_ChannelEnabled(obj->spi.dmaOptionsTX.dmaChannel) && (obj->tx_buff.pos < obj->rx_buff.length)) {
|
||||||
//Save state of TX transfer amount
|
//Save state of TX transfer amount
|
||||||
int length_diff = obj->rx_buff.length - obj->tx_buff.pos;
|
int length_diff = obj->rx_buff.length - obj->tx_buff.pos;
|
||||||
obj->tx_buff.pos = obj->rx_buff.length;
|
obj->tx_buff.pos = obj->rx_buff.length;
|
||||||
|
|
||||||
//Kick off a new DMA transfer
|
//Kick off a new DMA transfer
|
||||||
DMA_CfgDescr_TypeDef txDescrCfg;
|
DMA_CfgDescr_TypeDef txDescrCfg;
|
||||||
|
|
||||||
if(obj->spi.bits != 9) {
|
if(obj->spi.bits != 9) {
|
||||||
fill_word = SPI_FILL_WORD;
|
fill_word = SPI_FILL_WORD;
|
||||||
/* Setting up channel descriptor */
|
/* Setting up channel descriptor */
|
||||||
txDescrCfg.dstInc = dmaDataIncNone;
|
txDescrCfg.dstInc = dmaDataIncNone;
|
||||||
txDescrCfg.srcInc = dmaDataIncNone; //Do not increment source pointer when there is no transmit buffer
|
txDescrCfg.srcInc = dmaDataIncNone; //Do not increment source pointer when there is no transmit buffer
|
||||||
txDescrCfg.size = (obj->spi.bits <= 8 ? dmaDataSize1 : dmaDataSize2); //When frame size > 9, we can use TXDOUBLE to save bandwidth
|
txDescrCfg.size = (obj->spi.bits <= 8 ? dmaDataSize1 : dmaDataSize2); //When frame size > 9, we can use TXDOUBLE to save bandwidth
|
||||||
txDescrCfg.arbRate = dmaArbitrate1;
|
txDescrCfg.arbRate = dmaArbitrate1;
|
||||||
txDescrCfg.hprot = 0;
|
txDescrCfg.hprot = 0;
|
||||||
DMA_CfgDescr(obj->spi.dmaOptionsTX.dmaChannel, true, &txDescrCfg);
|
DMA_CfgDescr(obj->spi.dmaOptionsTX.dmaChannel, true, &txDescrCfg);
|
||||||
|
|
||||||
/* Activate TX channel */
|
/* Activate TX channel */
|
||||||
DMA_ActivateBasic( obj->spi.dmaOptionsTX.dmaChannel,
|
DMA_ActivateBasic( obj->spi.dmaOptionsTX.dmaChannel,
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
(obj->spi.bits <= 8 ? (void *)&(obj->spi.spi->TXDATA) : (void *)&(obj->spi.spi->TXDOUBLE)), //When frame size > 9, point to TXDOUBLE
|
(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
|
&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
|
(obj->spi.bits <= 8 ? length_diff - 1 : (length_diff / 2) - 1)); // When using TXDOUBLE, recalculate transfer length
|
||||||
} else {
|
} else {
|
||||||
/* Setting up channel descriptor */
|
/* Setting up channel descriptor */
|
||||||
fill_word = SPI_FILL_WORD & 0x1FF;
|
fill_word = SPI_FILL_WORD & 0x1FF;
|
||||||
txDescrCfg.dstInc = dmaDataIncNone;
|
txDescrCfg.dstInc = dmaDataIncNone;
|
||||||
txDescrCfg.srcInc = dmaDataIncNone; //Do not increment source pointer when there is no transmit buffer
|
txDescrCfg.srcInc = dmaDataIncNone; //Do not increment source pointer when there is no transmit buffer
|
||||||
txDescrCfg.size = dmaDataSize2; //When frame size > 9, we can use TXDOUBLE to save bandwidth
|
txDescrCfg.size = dmaDataSize2; //When frame size > 9, we can use TXDOUBLE to save bandwidth
|
||||||
txDescrCfg.arbRate = dmaArbitrate1;
|
txDescrCfg.arbRate = dmaArbitrate1;
|
||||||
txDescrCfg.hprot = 0;
|
txDescrCfg.hprot = 0;
|
||||||
DMA_CfgDescr(obj->spi.dmaOptionsTX.dmaChannel, true, &txDescrCfg);
|
DMA_CfgDescr(obj->spi.dmaOptionsTX.dmaChannel, true, &txDescrCfg);
|
||||||
|
|
||||||
DMA_ActivateBasic( obj->spi.dmaOptionsTX.dmaChannel,
|
DMA_ActivateBasic( obj->spi.dmaOptionsTX.dmaChannel,
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
(void *)&(obj->spi.spi->TXDATAX), //When frame size > 9, point to TXDOUBLE
|
(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
|
&fill_word, // When there is nothing to transmit, point to static fill word
|
||||||
(length_diff / 2) - 1);
|
(length_diff / 2) - 1);
|
||||||
}
|
}
|
||||||
}
|
} else return 0;
|
||||||
else return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If there is still a TX transfer ongoing (tx_length > rx_length), wait for it to finish */
|
/* If there is still a TX transfer ongoing (tx_length > rx_length), wait for it to finish */
|
||||||
if (DMA_ChannelEnabled(obj->spi.dmaOptionsTX.dmaChannel)) {
|
if (DMA_ChannelEnabled(obj->spi.dmaOptionsTX.dmaChannel)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Release the dma channels if they were opportunistically allocated */
|
/* 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
|
* @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 we're not currently transferring, then there's nothing to do here
|
||||||
if(spi_active(obj) != 0) return;
|
if(spi_active(obj) != 0) return;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue