XMC4xxx: Add USIC baudrate calculation.
This commit is contained in:
parent
ae32905fe8
commit
5df421488c
@ -70,10 +70,21 @@ void xmc4_clock_configure(void);
|
||||
* Name: xmc4_get_coreclock
|
||||
*
|
||||
* Description:
|
||||
* Return the current core clock frequency.
|
||||
* Return the current core clock frequency, fCPU.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
uint32_t xmc4_get_coreclock(void);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: xmc4_get_periphclock
|
||||
*
|
||||
* Description:
|
||||
* The peripheral clock is either fCPU or fCPU/2, depending on the state
|
||||
* of the peripheral divider.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
uint32_t xmc4_get_periphclock(void);
|
||||
|
||||
#endif /* __ARCH_ARM_SRC_XMC4_XMC4_CLOCKCONFIG_H */
|
||||
|
@ -101,36 +101,36 @@ uint32_t xmc4_get_coreclock(void)
|
||||
temp = BOARD_XTAL_FREQUENCY;
|
||||
}
|
||||
|
||||
/* Check if PLL is locked */
|
||||
/* Check if PLL is locked */
|
||||
|
||||
regval = getreg32(XMC4_SCU_PLLSTAT);
|
||||
if ((regval & SCU_PLLSTAT_VCOLOCK) != 0)
|
||||
{
|
||||
/* PLL normal mode */
|
||||
regval = getreg32(XMC4_SCU_PLLSTAT);
|
||||
if ((regval & SCU_PLLSTAT_VCOLOCK) != 0)
|
||||
{
|
||||
/* PLL normal mode */
|
||||
|
||||
regval = getreg32(XMC4_SCU_PLLCON1);
|
||||
pdiv = ((regval & SCU_PLLCON1_PDIV_MASK) >> SCU_PLLCON1_PDIV_SHIFT) + 1;
|
||||
ndiv = ((regval & SCU_PLLCON1_NDIV_MASK) >> SCU_PLLCON1_NDIV_SHIFT) + 1;
|
||||
kdiv = ((regval & SCU_PLLCON1_K2DIV_MASK) >> SCU_PLLCON1_K2DIV_SHIFT) + 1;
|
||||
regval = getreg32(XMC4_SCU_PLLCON1);
|
||||
pdiv = ((regval & SCU_PLLCON1_PDIV_MASK) >> SCU_PLLCON1_PDIV_SHIFT) + 1;
|
||||
ndiv = ((regval & SCU_PLLCON1_NDIV_MASK) >> SCU_PLLCON1_NDIV_SHIFT) + 1;
|
||||
kdiv = ((regval & SCU_PLLCON1_K2DIV_MASK) >> SCU_PLLCON1_K2DIV_SHIFT) + 1;
|
||||
|
||||
temp = (temp / (pdiv * kdiv)) * ndiv;
|
||||
temp = (temp / (pdiv * kdiv)) * ndiv;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* PLL prescalar mode */
|
||||
|
||||
regval = getreg32(XMC4_SCU_PLLCON1);
|
||||
kdiv = ((regval & SCU_PLLCON1_K1DIV_MASK) >> SCU_PLLCON1_K1DIV_SHIFT) + 1;
|
||||
|
||||
temp = (temp / kdiv);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* PLL prescalar mode */
|
||||
|
||||
regval = getreg32(XMC4_SCU_PLLCON1);
|
||||
kdiv = ((regval & SCU_PLLCON1_K1DIV_MASK) >> SCU_PLLCON1_K1DIV_SHIFT) + 1;
|
||||
|
||||
temp = (temp / kdiv);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* fOFI is clock source for fSYS */
|
||||
{
|
||||
/* fOFI is clock source for fSYS */
|
||||
|
||||
temp = OFI_FREQUENCY;
|
||||
}
|
||||
temp = OFI_FREQUENCY;
|
||||
}
|
||||
|
||||
/* Divide by SYSDIV to get fSYS */
|
||||
|
||||
@ -148,3 +148,35 @@ uint32_t xmc4_get_coreclock(void)
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: xmc4_get_periphclock
|
||||
*
|
||||
* Description:
|
||||
* The peripheral clock is either fCPU or fCPU/2, depending on the state
|
||||
* of the peripheral divider.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
uint32_t xmc4_get_periphclock(void)
|
||||
{
|
||||
uint32_t periphclock;
|
||||
|
||||
/* Get the CPU clock frequency. Unless it is divided down, this also the
|
||||
* peripheral clock frequency.
|
||||
*/
|
||||
|
||||
periphclock = xmc4_get_coreclock();
|
||||
|
||||
/* Get the peripheral clock divider */
|
||||
|
||||
periphclock = getreg32(XMC4_SCU_PBCLKCR);
|
||||
if ((periphclock & SCU_PBCLKCR_PBDIV) != 0)
|
||||
{
|
||||
/* The peripheral clock is fCPU/2 */
|
||||
|
||||
periphclock <<= 1;
|
||||
}
|
||||
|
||||
return periphclock;
|
||||
}
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <arch/irq.h>
|
||||
#include <arch/board/board.h>
|
||||
@ -50,6 +51,7 @@
|
||||
#include "xmc4_config.h"
|
||||
#include "chip/xmc4_usic.h"
|
||||
#include "chip/xmc4_pinmux.h"
|
||||
#include "xmc4_usic.h"
|
||||
#include "xmc4_lowputc.h"
|
||||
|
||||
/****************************************************************************
|
||||
@ -60,42 +62,42 @@
|
||||
|
||||
#if defined(HAVE_UART_CONSOLE)
|
||||
# if defined(CONFIG_UART0_SERIAL_CONSOLE)
|
||||
# define CONSOLE_BASE XMC4_USIC0_CH0_BASE
|
||||
# define CONSOLE_CHAN USIC0_CHAN0
|
||||
# define CONSOLE_FREQ BOARD_CORECLK_FREQ
|
||||
# define CONSOLE_BAUD CONFIG_UART0_BAUD
|
||||
# define CONSOLE_BITS CONFIG_UART0_BITS
|
||||
# define CONSOLE_2STOP CONFIG_UART0_2STOP
|
||||
# define CONSOLE_PARITY CONFIG_UART0_PARITY
|
||||
# elif defined(CONFIG_UART1_SERIAL_CONSOLE)
|
||||
# define CONSOLE_BASE XMC4_USIC0_CH1_BASE
|
||||
# define CONSOLE_CHAN USIC0_CHAN1
|
||||
# define CONSOLE_FREQ BOARD_CORECLK_FREQ
|
||||
# define CONSOLE_BAUD CONFIG_UART1_BAUD
|
||||
# define CONSOLE_BITS CONFIG_UART1_BITS
|
||||
# define CONSOLE_2STOP CONFIG_UART1_2STOP
|
||||
# define CONSOLE_PARITY CONFIG_UART1_PARITY
|
||||
# elif defined(CONFIG_UART2_SERIAL_CONSOLE)
|
||||
# define CONSOLE_BASE XMC4_USIC1_CH0_BASE
|
||||
# define CONSOLE_CHAN USIC1_CHAN0
|
||||
# define CONSOLE_FREQ BOARD_BUS_FREQ
|
||||
# define CONSOLE_BAUD CONFIG_UART2_BAUD
|
||||
# define CONSOLE_BITS CONFIG_UART2_BITS
|
||||
# define CONSOLE_2STOP CONFIG_UART2_2STOP
|
||||
# define CONSOLE_PARITY CONFIG_UART2_PARITY
|
||||
# elif defined(CONFIG_UART3_SERIAL_CONSOLE)
|
||||
# define CONSOLE_BASE XMC4_USIC1_CH1_BASE
|
||||
# define CONSOLE_CHAN USIC1_CHAN1
|
||||
# define CONSOLE_FREQ BOARD_BUS_FREQ
|
||||
# define CONSOLE_BAUD CONFIG_UART3_BAUD
|
||||
# define CONSOLE_BITS CONFIG_UART3_BITS
|
||||
# define CONSOLE_2STOP CONFIG_UART3_2STOP
|
||||
# define CONSOLE_PARITY CONFIG_UART3_PARITY
|
||||
# elif defined(CONFIG_UART4_SERIAL_CONSOLE)
|
||||
# define CONSOLE_BASE XMC4_USIC2_CH0_BASE
|
||||
# define CONSOLE_CHAN USIC2_CHAN0
|
||||
# define CONSOLE_FREQ BOARD_BUS_FREQ
|
||||
# define CONSOLE_BAUD CONFIG_UART4_BAUD
|
||||
# define CONSOLE_BITS CONFIG_UART4_BITS
|
||||
# define CONSOLE_2STOP CONFIG_UART4_2STOP
|
||||
# define CONSOLE_PARITY CONFIG_UART4_PARITY
|
||||
# elif defined(CONFIG_UART5_SERIAL_CONSOLE)
|
||||
# define CONSOLE_BASE XMC4_USIC2_CH1_BASE
|
||||
# define CONSOLE_CHAN USIC2_CHAN1
|
||||
# define CONSOLE_FREQ BOARD_BUS_FREQ
|
||||
# define CONSOLE_BAUD CONFIG_UART5_BAUD
|
||||
# define CONSOLE_BITS CONFIG_UART5_BITS
|
||||
@ -107,7 +109,7 @@
|
||||
#endif /* HAVE_UART_CONSOLE */
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
@ -169,7 +171,7 @@ void xmc4_lowsetup(void)
|
||||
* when the serial driver is opened.
|
||||
*/
|
||||
|
||||
xmc4_uart_configure(CONSOLE_BASE, CONSOLE_BAUD, CONSOLE_FREQ, \
|
||||
xmc4_uart_configure(CONSOLE_CHAN, CONSOLE_BAUD, CONSOLE_FREQ, \
|
||||
CONSOLE_PARITY, CONSOLE_BITS, CONSOLE_2STOP);
|
||||
#endif /* HAVE_UART_DEVICE */
|
||||
}
|
||||
@ -210,11 +212,12 @@ int xmc4_uart_configure(enum usic_channel_e channel, uint32_t baud,
|
||||
unsigned int nbits, unsigned int stop2)
|
||||
{
|
||||
uintptr_t base;
|
||||
uint32_t oversampling;
|
||||
int ret;
|
||||
|
||||
/* Get the base address of the USIC registers associated with this channel */
|
||||
|
||||
base = uintptr_t xmc4_channel_baseaddress(channel);
|
||||
base = xmc4_channel_baseaddress(channel);
|
||||
if (base == 0)
|
||||
{
|
||||
return -EINVAL;
|
||||
@ -228,6 +231,8 @@ int xmc4_uart_configure(enum usic_channel_e channel, uint32_t baud,
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = xmc4_uisc_baudrate(channel, baud, oversampling);
|
||||
|
||||
/* Configure number of bits, stop bits and parity */
|
||||
#warning Missing logic
|
||||
|
||||
|
@ -31,6 +31,20 @@
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* May include some logic from sample code provided by Infineon:
|
||||
*
|
||||
* Copyright (C) 2011-2015 Infineon Technologies AG. All rights reserved.
|
||||
*
|
||||
* Infineon Technologies AG (Infineon) is supplying this software for use with
|
||||
* Infineon's microcontrollers. This file can be freely distributed within
|
||||
* development tools that are supporting such microcontrollers.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED AS IS. NO WARRANTIES, WHETHER EXPRESS, IMPLIED
|
||||
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
|
||||
* INFINEON SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
|
||||
* OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
@ -42,12 +56,14 @@
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <arch/xmc4/chip.h>
|
||||
|
||||
#include "up_arch.h"
|
||||
#include "chip/xmc4_usic.h"
|
||||
#include "chip/xmc4_scu.h"
|
||||
#include "xmc4_clockconfig.h"
|
||||
#include "xmc4_usic.h"
|
||||
|
||||
/****************************************************************************
|
||||
@ -226,7 +242,7 @@ int xmc4_disable_usic(enum usic_e usic)
|
||||
|
||||
uintptr_t xmc4_channel_baseaddress(enum usic_channel_e channel)
|
||||
{
|
||||
if ((usigned int)channel < (2 * XM4C_NUSICS))
|
||||
if ((unsigned int)channel < (2 * XMC4_NUSIC))
|
||||
{
|
||||
return g_channel_baseaddress[channel];
|
||||
}
|
||||
@ -264,7 +280,7 @@ int xmc4_enable_usic_channel(enum usic_channel_e channel)
|
||||
|
||||
/* Enable the USIC module */
|
||||
|
||||
xmc4_enable_usic(xmc4_channel2usic(channel));
|
||||
ret = xmc4_enable_usic(xmc4_channel2usic(channel));
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
@ -330,7 +346,7 @@ int xmc4_disable_usic_channel(enum usic_channel_e channel)
|
||||
/* Get the base address of other channel for this USIC module */
|
||||
|
||||
other = xmc4_channel_baseaddress(channel ^ 1);
|
||||
DEBUASSERT(other != 0);
|
||||
DEBUGASSERT(other != 0);
|
||||
|
||||
/* Check if the other channel has also been disabled */
|
||||
|
||||
@ -343,4 +359,89 @@ int xmc4_disable_usic_channel(enum usic_channel_e channel)
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: xmc4_uisc_baudrate
|
||||
*
|
||||
* Description:
|
||||
* Set the USIC baudrate for the USIC channel
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) is returned on success; A negated errno value is returned to
|
||||
* indicate the nature of any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int xmc4_uisc_baudrate(enum usic_channel_e channel, uint32_t baud,
|
||||
uint32_t oversampling)
|
||||
{
|
||||
uintptr_t base;
|
||||
uint32_t periphclock;
|
||||
uint32_t clkdiv;
|
||||
uint32_t clkdiv_min;
|
||||
uint32_t pdiv;
|
||||
uint32_t pdiv_int;
|
||||
uint32_t pdiv_int_min;
|
||||
uint32_t pdiv_frac;
|
||||
uint32_t pdiv_frac_min;
|
||||
uint32_t regval;
|
||||
int ret;
|
||||
|
||||
/* Get the base address of the registers for this channel */
|
||||
|
||||
base = xmc4_channel_baseaddress(channel);
|
||||
if (base == 0)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* The baud and peripheral clock are divided by 100 to be able to use only
|
||||
* 32-bit arithmetic.
|
||||
*/
|
||||
|
||||
if (baud >= 100 && oversampling != 0)
|
||||
{
|
||||
periphclock = xmc4_get_periphclock() / 100;
|
||||
baud = baud / 100;
|
||||
|
||||
clkdiv_min = 1;
|
||||
pdiv_int_min = 1;
|
||||
pdiv_frac_min = 0x3ff;
|
||||
|
||||
for (clkdiv = 1023; clkdiv > 0; --clkdiv)
|
||||
{
|
||||
pdiv = ((periphclock * clkdiv) / (baud * oversampling));
|
||||
pdiv_int = pdiv >> 10;
|
||||
pdiv_frac = pdiv & 0x3ff;
|
||||
|
||||
if (pdiv_int < 1024 && pdiv_frac < pdiv_frac_min)
|
||||
{
|
||||
pdiv_frac_min = pdiv_frac;
|
||||
pdiv_int_min = pdiv_int;
|
||||
clkdiv_min = clkdiv;
|
||||
}
|
||||
}
|
||||
|
||||
/* Select and setup the fractional divider */
|
||||
|
||||
regval = USIC_FDR_DM_FRACTIONAL | (clkdiv_min << USIC_FDR_STEP_SHIFT);
|
||||
putreg32(regval, base + XMC4_USIC_FDR_OFFSET);
|
||||
|
||||
/* Setup and enable the baud rate generator */
|
||||
|
||||
regval = getreg32(base + XMC4_USIC_BRG_OFFSET);
|
||||
regval &= ~(USIC_BRG_DCTQ_MASK | USIC_BRG_PDIV_MASK | USIC_BRG_PCTQ_MASK | USIC_BRG_PPPEN);
|
||||
regval |= (USIC_BRG_DCTQ(oversampling - 1) | USIC_BRG_PDIV(pdiv_int_min - 1));
|
||||
putreg32(regval, base + XMC4_USIC_BRG_OFFSET);
|
||||
|
||||
ret = OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = -ERANGE;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -167,4 +167,19 @@ int xmc4_enable_usic_channel(enum usic_channel_e channel);
|
||||
|
||||
int xmc4_disable_usic_channel(enum usic_channel_e channel);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: xmc4_uisc_baudrate
|
||||
*
|
||||
* Description:
|
||||
* Set the USIC baudrate for the USIC channel
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) is returned on success; A negated errno value is returned to
|
||||
* indicate the nature of any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int xmc4_uisc_baudrate(enum usic_channel_e channel, uint32_t baud,
|
||||
uint32_t oversampling);
|
||||
|
||||
#endif /* __ARCH_ARM_SRC_XMC4_XMC4_USIC_H */
|
||||
|
Loading…
Reference in New Issue
Block a user