/** * \brief Find best MCK divisor * * Finds the best MCK divisor given the timer frequency and MCK. The result * is guaranteed to satisfy the following equation: * \code * (MCK / (DIV * 65536)) <= freq <= (MCK / DIV) * \endcode * with DIV being the highest possible value. * * \param freq Desired timer freq. * \param div Divisor value. * \param tc_clks TCCLKS field value for divisor. * * \return 1 if a proper divisor has been found, otherwise 0. */ uint32_t tc_find_mck_divisor (uint32_t freq, uint32_t * div, uint32_t * tc_clks) { const uint32_t periph_clock = pmc_get_peripheral_clock(ID_TC0); const uint32_t available_freqs[5] = {periph_clock >> 1, periph_clock >> 3, periph_clock >> 5, periph_clock >> 7, 32768}; int i = 0; for (i = 0; i < 5; ++i) { uint32_t tmp = freq << 1; if (tmp > available_freqs[i]) break; } i = (i == 5 ? i-1 : i); /* Store results */ if (div) { *div = periph_clock / available_freqs[i]; } if (tc_clks) { *tc_clks = i; } return 1; }
static bool _gmac_configure_mdc_clock(Gmac *gmac) { uint32_t mck, clk; mck = pmc_get_peripheral_clock(get_gmac_id_from_addr(gmac)); /* Disable RX/TX */ gmac->GMAC_NCR &= ~(GMAC_NCR_RXEN | GMAC_NCR_TXEN); /* Find divider */ if (mck <= 20000000) { clk = GMAC_NCFGR_CLK_MCK_8; // MCK/8 } else if (mck <= 40000000) { clk = GMAC_NCFGR_CLK_MCK_16; // MCK/16 } else if (mck <= 80000000) { clk = GMAC_NCFGR_CLK_MCK_32; // MCK/32 } else if (mck <= 120000000) { clk = GMAC_NCFGR_CLK_MCK_48; // MCK/48 } else if (mck <= 160000000) { clk = GMAC_NCFGR_CLK_MCK_64; // MCK/64 } else if (mck <= 240000000) { clk = GMAC_NCFGR_CLK_MCK_96; // MCK/96 } else { trace_error("MCK too high, cannot configure MDC clock.\r\n"); return false; } /* configure MDC clock divider and enable RX/TX */ gmac->GMAC_NCFGR = (gmac->GMAC_NCFGR & ~GMAC_NCFGR_CLK_Msk) | clk; gmac->GMAC_NCR |= (GMAC_NCR_RXEN | GMAC_NCR_TXEN); return true; }
void tc_trigger_on_freq(Tc* tc, uint32_t channel_num, uint32_t freq) { uint32_t div = 0; uint32_t tcclks = 0; uint32_t tc_id = get_tc_id_from_addr(tc); TcChannel* channel = &tc->TC_CHANNEL[channel_num]; tc_find_mck_divisor(freq, &div, &tcclks); tc_configure(tc, channel_num, tcclks | TC_CMR_CPCTRG); channel->TC_RC = (pmc_get_peripheral_clock(tc_id) / div) / freq; }
/* * Initializes the UART with the given parameters, and enables both the * transmitter and the receiver. The mode parameter contains the value of the * UART_MR register. * Value UART_STANDARD can be used for mode to get the most common configuration * (i.e. aysnchronous, 8bits, no parity, 1 stop bit, no flow control). * \param mode Operating mode to configure. * \param baudrate Desired baudrate (e.g. 115200). * \param mck Frequency of the system master clock in Hz. */ void uart_configure(Uart* pUart, uint32_t mode, uint32_t baudrate) { uint32_t uart_id = get_uart_id_from_addr(pUart); // Reset & disable receiver and transmitter, disable interrupts pUart->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX | UART_CR_RXDIS | UART_CR_TXDIS | UART_CR_RSTSTA; pUart->UART_IDR = 0xFFFFFFFF; // Configure baud rate pUart->UART_BRGR = pmc_get_peripheral_clock(uart_id) / (baudrate * 16); // Configure mode register pUart->UART_MR = mode; // Enable receiver and transmitter pUart->UART_CR = UART_CR_RXEN | UART_CR_TXEN; }
/** * \brief Configures an DBGU peripheral with the specified parameters. * * \param dgbu Pointer to the DBGU peripheral to configure * \param baudrate Baudrate at which the DBGU should operate (in Hz). * \param clock Frequency of the system master clock (in Hz). */ void dbgu_configure(Dbgu* dbgu, uint32_t mode, uint32_t baudrate) { assert(dbgu == DBGU); /* Reset and disable receiver & transmitter */ dbgu->DBGU_CR = DBGU_CR_RSTRX | DBGU_CR_RSTTX; dbgu->DBGU_IDR = 0xFFFFFFFF; dbgu->DBGU_SR; /* Configure mode */ dbgu->DBGU_MR = mode; /* Configure baudrate */ dbgu->DBGU_BRGR = ROUND_INT_DIV(pmc_get_peripheral_clock(ID_DBGU) / 16, baudrate); /* Enable receiver and transmitter */ dbgu->DBGU_CR = DBGU_CR_RXEN | DBGU_CR_TXEN; }
uint32_t qspi_set_baudrate(Qspi *qspi, uint32_t baudrate) { uint32_t mck, scr, scbr; if (!baudrate) return 0; /* Serial Clock Baudrate */ mck = pmc_get_peripheral_clock(get_qspi_id_from_addr(qspi)); scbr = (mck + baudrate - 1) / baudrate; if (scbr > 0) scbr--; /* Update the Serial Clock Register */ scr = qspi->QSPI_SCR; scr &= ~QSPI_SCR_SCBR_Msk; scr |= QSPI_SCR_SCBR(scbr); qspi->QSPI_SCR = scr; return mck / (scbr + 1); }
/** * \brief Configures a SSC peripheral.If the divided clock is not used, the master * clock frequency can be set to 0. * \note The emitter and transmitter are disabled by this function. * \param ssc Pointer to an SSC instance. * \param bitRate bit rate. * \param masterClock master clock. */ void SSC_Configure(Ssc * ssc, uint32_t bitRate, uint32_t masterClock) { uint32_t id; uint32_t clock; id = (ssc == SSC0) ? ID_SSC0 : ID_SSC1; clock = pmc_get_peripheral_clock(id); /* Reset, disable receiver & transmitter */ ssc->SSC_CR = SSC_CR_RXDIS | SSC_CR_TXDIS | SSC_CR_SWRST; /* Configure clock frequency */ if (bitRate != 0) { ssc->SSC_CMR = clock / (2 * bitRate); } else { ssc->SSC_CMR = 0; } /* Enable SSC peripheral clock */ //pmc_enable_peripheral(id); }