📄 init_sam9.c
字号:
//*----------------------------------------------------------------------------
//* ATMEL Microcontroller Software Support - ROUSSET -
//*----------------------------------------------------------------------------
//* The software is delivered "AS IS" without warranty or condition of any
//* kind, either express, implied or statutory. This includes without
//* limitation any warranty or condition with respect to merchantability or
//* fitness for any particular purpose, or against the infringements of
//* intellectual property rights of others.
//*----------------------------------------------------------------------------
//* File Name : init.c
//* Object : Low level initializations written in C
//* Creation : ODi 06/26/2002
//*
//*----------------------------------------------------------------------------
#include "main.h"
#include "dataflash.h"
extern struct _AT91S_CDC pCDC;
extern AT91S_XMODEM xModem;
extern AT91PS_XMODEM AT91F_XMODEM_Open(AT91PS_XMODEM);
/////////////////////////////////////////////////////////////////////////////////////////////////////
// Constants defined for PLL
/////////////////////////////////////////////////////////////////////////////////////////////////////
// Array to determine the PLLB setup for 48MHz USB clock
// PLLB_OUTPUT = FREQ * (MUL+1)/DIV = 96 MHz
// USB_CLOCK = PLLB_OUTPUT/2;
/////////////////////////////////////////////////////////////////////////////////////////////////////
const int PLLB_SETUP[][2] =
{
// Freq DIV MUL
{ 3000000, 1 + ((32 -1) << 16) },
{ 3276800, 3 + ((88 -1) << 16) },
{ 3686400, 1 + ((26 -1) << 16) },
{ 3840000, 1 + ((25 -1) << 16) },
{ 4000000, 1 + ((24 -1) << 16) },
{ 4433619, 3 + ((65 -1) << 16) },
{ 4608000, 5 + ((104 -1) << 16) },
{ 4915200, 2 + ((39 -1) << 16) },
{ 5000000, 5 + ((96 -1) << 16) },
{ 5242880, 3 + ((55 -1) << 16) },
{ 6000000, 1 + ((16 -1) << 16) },
{ 6144000, 5 + ((78 -1) << 16) },
{ 6400000, 1 + ((15 -1) << 16) },
{ 6553600, 3 + ((44 -1) << 16) },
{ 7159090, 5 + ((67 -1) << 16) },
{ 7372800, 1 + ((13 -1) << 16) },
{ 7864320, 5 + ((61 -1) << 16) },
{ 8000000, 1 + ((12 -1) << 16) },
{ 9830400, 9 + ((88 -1) << 16) },
{ 10000000, 5 + ((48 -1) << 16) },
{ 11059200, 3 + ((26 -1) << 16) },
{ 12000000, 1 + (( 8 -1) << 16) },
{ 12288000, 11 + ((86 -1) << 16) },
{ 13000000, 13 + ((96 -1) << 16) },
{ 13560000, 13 + ((92 -1) << 16) },
{ 14318180, 10 + ((67 -1) << 16) },
{ 14745600, 2 + ((13 -1) << 16) },
{ 16000000, 1 + (( 6 -1) << 16) },
{ 16367667, 15 + ((88 -1) << 16) },
{ 17734470, 17 + ((92 -1) << 16) },
{ 18432000, 14 + ((73 -1) << 16) },
{ 20000000, 5 + ((24 -1) << 16) },
{ 24000000, 1 + (( 4 -1) << 16) },
{ 25000000, 25 + ((96 -1) << 16) },
{ 26000000, 13 + ((48 -1) << 16) },
{ 28224000, 5 + ((17 -1) << 16) },
{ 32000000, 1 + (( 3 -1) << 16) },
{ 33000000, 11 + ((32 -1) << 16) },
{ 40000000, 10 + ((24 -1) << 16) },
{ 0 , 0 },
};
//*----------------------------------------------------------------------------
//* \fn AT91F_US_Baudrate
//* \brief Calculate baud_value according to the main clock and the baud rate
//*----------------------------------------------------------------------------
unsigned int AT91F_GetBaudrate (
const unsigned int main_clock, // \arg peripheral clock
const unsigned int baud_rate) // \arg UART baudrate
{
unsigned int baud_value = ((main_clock*10)/(baud_rate * 16));
if ((baud_value % 10) >= 5)
baud_value = (baud_value / 10) + 1;
else
baud_value /= 10;
return baud_value;
}
//*----------------------------------------------------------------------------
//* \fn AT91F_EndOfCalibration
//* \brief Autobaudrate State Machine
//*----------------------------------------------------------------------------
unsigned int AT91F_EndOfCalibration(void)
{
if (AT91C_BASE_DBGU->DBGU_CSR & AT91C_US_RXRDY)
return AT91C_FINAL;
else
return AT91C_INIT;
}
//*----------------------------------------------------------------------------
//* \fn AT91F_LowLevelInit
//* \brief This function performs very low level HW initialization
//*----------------------------------------------------------------------------
void AT91F_LowLevelInit()
{
unsigned int tmp = 0;
int MainClock = 0;
const char* pBuffer = "RomBOOT\n\r>";
/////////////////////////////////////////////////////////////////////////////////////////////////////
// PMC Init Step 3.
// Check the Main Oscillator Frequency and Find Corresponding Quartz
/////////////////////////////////////////////////////////////////////////////////////////////////////
// Wait for MAINRDY flag in PMC_MCFR
tmp = 0;
while(!(AT91C_BASE_CKGR->CKGR_MCFR & AT91C_CKGR_MAINRDY) && (tmp++ < DELAY) );
// Compute MAINCK <=> nb of main clock cycles in 16 slow clock cycles (SLCK = 32768 kHz)
MainClock = (AT91C_BASE_CKGR->CKGR_MCFR & AT91C_CKGR_MAINF) * (32768/16);
// Find the crystal frequency and the PLLB setup in the crystal_freq table (in Hz)
tmp = 0;
while( (PLLB_SETUP[tmp][0] != 0) && (MainClock - PLLB_SETUP[tmp][0] > 0))
tmp++;
// if the crystal frequency doesn't match with the table content
if(PLLB_SETUP[tmp][0] == 0)
return;
// find the correct entry in the table
if ((MainClock - PLLB_SETUP[tmp-1][0]) < (PLLB_SETUP[tmp][0] - MainClock))
tmp --;
// if the crystal value doesn't match
if (PLLB_SETUP[tmp][0] == 0)
return;
/////////////////////////////////////////////////////////////////////////////////////////////////////
// PMC Init Step 4.
// Setting PLL and Divider
/////////////////////////////////////////////////////////////////////////////////////////////////////
#ifdef AT91C340
AT91C_BASE_CKGR->CKGR_PLLBR = AT91C_CKGR_USBDIV_1 | AT91C_CKGR_OUTB_1 | AT91C_CKGR_PLLBCOUNT |\
PLLB_SETUP[tmp][1];
#else
AT91C_BASE_CKGR->CKGR_PLLBR = AT91C_CKGR_USBDIV_1 | AT91C_CKGR_OUTB_0 | AT91C_CKGR_PLLBCOUNT |\
PLLB_SETUP[tmp][1];
#endif
// Wait for PLL stabilization LOCKB bit in PMC_SR
tmp = 0;
while( !(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_LOCKB) && (tmp++ < DELAY) );
/////////////////////////////////////////////////////////////////////////////////////////////////////
// PMC Init Step 5.
// Selection of Master Clock MCK (Processor Clock PCK/2)
/////////////////////////////////////////////////////////////////////////////////////////////////////
// MCK=PCK/2=PLL/2
AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_CSS_PLLB_CLK|AT91C_PMC_PRES_CLK|AT91C_PMC_MDIV_2;
// Wait until the master clock is established
tmp = 0;
while( !(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY) && (tmp++ < DELAY) );
/////////////////////////////////////////////////////////////////////////////////////////////////////
// DBGU Initialisation
/////////////////////////////////////////////////////////////////////////////////////////////////////
// Open PIO for DBGU
AT91f_OpenDbguPIO();
// Disable interrupts
AT91C_BASE_DBGU->DBGU_IDR = (unsigned int) -1;
// Reset receiver and transmitter
AT91C_BASE_DBGU->DBGU_CR = AT91C_US_RSTRX | AT91C_US_RSTTX | AT91C_US_RXDIS | AT91C_US_TXDIS ;
// Define the baud rate divisor register
AT91C_BASE_DBGU->DBGU_BRGR = AT91F_GetBaudrate(AT91C_MASTER_CLOCK, AT91C_BAUDRATE_115200);
// Define the USART mode
AT91C_BASE_DBGU->DBGU_MR = AT91C_DBGU_ASYNC_MODE;
// Enable Transmitter and Receiver
AT91C_BASE_DBGU->DBGU_CR = AT91C_US_TXEN | AT91C_US_RXEN;
// Print Init Buffer
while(*pBuffer != '\0')
{
while (!(AT91C_BASE_DBGU->DBGU_CSR & AT91C_US_TXRDY));
AT91C_BASE_DBGU->DBGU_THR = (*pBuffer++ & 0x1FF);
}
while ( !((AT91C_BASE_DBGU->DBGU_CSR) & AT91C_US_TXEMPTY) );
/////////////////////////////////////////////////////////////////////////////////////////////////////
// SYSC: User Reset Init
/////////////////////////////////////////////////////////////////////////////////////////////////////
// Enable User Reset and set its assertion min to 960 us
AT91C_BASE_RSTC->RSTC_RMR = AT91C_RSTC_URSTEN | (0x4<<8) | (0xA5<<24);
/////////////////////////////////////////////////////////////////////////////////////////////////////
// Xmodem + CDC Open
/////////////////////////////////////////////////////////////////////////////////////////////////////
AT91F_XMODEM_Open(&xModem);
AT91F_CDC_Open(&pCDC, AT91C_BASE_UDP);
}
//*--------------------------------------------------------------------------------------
//* \fn AT91F_Reset_Registers()
//* \brief Set all the registers used to their reset value
//*--------------------------------------------------------------------------------------
void AT91F_Reset_Registers(void)
{
// Close PIO for SPI0
AT91f_CloseSpiPIO();
// Close all peripheral clocks used
AT91C_BASE_PMC->PMC_PCDR = (1 << AT91C_ID_SPI0);
#if defined (AT91SAM9260) || defined (AT91SAM9262)
// Close Smart Media, disable the address range of CS3 in HMATRIX user interface
AT91C_BASE_MATRIX->MATRIX_EBI0 &= ~AT91C_MATRIX_CS3A_SM;
// Close PIOA Clock
#ifdef AT91SAM9260
AT91C_BASE_PMC->PMC_PCDR = ((unsigned int) 1 << AT91C_ID_PIOB);
#else
AT91C_BASE_PMC->PMC_PCDR = ((unsigned int) 1 << AT91C_ID_PIOA);
#endif
AT91f_CloseNandFlashPIO();
#endif
}
//*----------------------------------------------------------------------------
//* \fn AT91F_SpiInit
//* \brief
//*----------------------------------------------------------------------------
void AT91F_SpiInit(void)
{
// Open PIO for SPI0
AT91f_OpenSpiPIO();
// Enables the SPI0 Clock
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_SPI0);
// Reset SPI0
AT91C_BASE_SPI0->SPI_CR = AT91C_SPI_SWRST;
// Configure SPI0 in Master Mode with No CS selected
AT91C_BASE_SPI0->SPI_MR = AT91C_SPI_MSTR | AT91C_SPI_MODFDIS | AT91C_SPI_PCS;
// Configure CS0 (SPI Mode 3)
*(AT91C_SPI0_CSR + 0) = AT91C_SPI_CPOL | (AT91C_SPI_DLYBS & DATAFLASH_TCSS) | (AT91C_SPI_DLYBCT & DATAFLASH_TCHS) | ((AT91C_MASTER_CLOCK / AT91C_SPI_CLK) << 8);
// Choose CS0
AT91C_BASE_SPI0->SPI_MR &= 0xFFF0FFFF;
AT91C_BASE_SPI0->SPI_MR |= ((AT91C_SPI_PCS0_DATAFLASH<<16) & AT91C_SPI_PCS);
// SPI_Enable
AT91C_BASE_SPI0->SPI_CR = AT91C_SPI_SPIEN;
}
//*----------------------------------------------------------------------------
//* \fn AT91F_InitUSB
//* \brief
//*----------------------------------------------------------------------------
void AT91F_InitUSB(void)
{
// Enables the 48MHz USB clock UDPCK
AT91C_BASE_PMC->PMC_SCER = AT91C_PMC_UDP;
// Enables the USB Clock
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_UDP);
// Enable the pull-up
#ifndef AT91SAM9261
AT91C_BASE_UDP->UDP_TXVC = (AT91C_UDP_PUON); // Set PUON and Clear TXVDIS
#else
AT91C_BASE_MATRIX->MATRIX_USBPCR = AT91C_MATRIX_USBPCR_PUON;
#endif
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -