Boen_Shi 8be2866433 feat(base): 初始化 MSPM0 开发环境
- 添加头文件和配置文件支持
- 更新.gitignore忽略编译和IDE相关文件
- 添加基础的bsp代码
2026-07-16 14:45:26 +08:00

340 lines
12 KiB
C

/*
* Copyright (c) 2020, Texas Instruments Incorporated
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <ti/driverlib/dl_uart_extend.h>
#include <ti/driverlib/dl_uart_main.h>
#if defined(__MSPM0_HAS_UART_MAIN__) || defined(__MSPM0_HAS_UART_EXTD__)
void DL_UART_init(UART_Regs *uart, const DL_UART_Config *config)
{
DL_UART_disable(uart);
DL_Common_updateReg(&uart->CTL0,
(uint32_t) config->mode | (uint32_t) config->direction |
(uint32_t) config->flowControl,
UART_CTL0_RXE_MASK | UART_CTL0_TXE_MASK | UART_CTL0_MODE_MASK |
UART_CTL0_RTSEN_MASK | UART_CTL0_CTSEN_MASK | UART_CTL0_FEN_MASK);
DL_Common_updateReg(&uart->LCRH,
(uint32_t) config->parity | (uint32_t) config->wordLength |
(uint32_t) config->stopBits,
UART_LCRH_PEN_ENABLE | UART_LCRH_EPS_MASK | UART_LCRH_SPS_MASK |
UART_LCRH_WLEN_MASK | UART_LCRH_STP2_MASK);
}
void DL_UART_setClockConfig(UART_Regs *uart, const DL_UART_ClockConfig *config)
{
uart->CLKSEL = (uint32_t) config->clockSel;
uart->CLKDIV = (uint32_t) config->divideRatio;
}
void DL_UART_getClockConfig(const UART_Regs *uart, DL_UART_ClockConfig *config)
{
config->clockSel = (DL_UART_CLOCK) uart->CLKSEL;
config->divideRatio = (DL_UART_CLOCK_DIVIDE_RATIO) uart->CLKDIV;
}
void DL_UART_configBaudRate(
UART_Regs *uart, uint32_t clockFreq, uint32_t baudRate)
{
uint32_t divisor;
/*
* The baud rate divisor, brd, is calculated with the following formula:
* brd = ibrd.fbrd = clockOutput / (OVS * baudRate)
* where ibrd is the integer part, fbrd is the fractional part.
* Since fbrd is 6 bits, multiply brd by 64:
* 64 * brd = (clockOutput * 64) / (16 * baudRate)
* = (clockOutput * 4) / baudRate
* add 1/2 to round the least significant bit of fbrd:
* 64 * brd + 1/2 = (clockOutput * 8 / (2 * baudRate) + 1/2
* divisor = 64*brd+1/2 = [(clockOutput * 8)/ baudRate + 1] / 2
*
* The lower 6 bits is fbrd, upper part is ibrd
* Note: If ibrd is 0, FBRD will be ignored and no data will be
* transferred.
*/
/* Calculate baud rate divisor based on OVS: */
if ((baudRate * (uint32_t) 8) > clockFreq) {
DL_UART_setOversampling(uart, DL_UART_OVERSAMPLING_RATE_3X);
divisor = ((clockFreq * (uint32_t) 64) / (baudRate * (uint32_t) 3)) +
((uint32_t) 1 / (uint32_t) 2);
} else if ((baudRate * (uint32_t) 16) > clockFreq) {
DL_UART_setOversampling(uart, DL_UART_OVERSAMPLING_RATE_8X);
baudRate = baudRate / (uint32_t) 2;
divisor = (((clockFreq * (uint32_t) 8) / baudRate) + (uint32_t) 1) /
(uint32_t) 2;
} else {
DL_UART_setOversampling(uart, DL_UART_OVERSAMPLING_RATE_16X);
divisor = (((clockFreq * (uint32_t) 8) / baudRate) + (uint32_t) 1) /
(uint32_t) 2;
}
/* Set the integer and fractional parts of the baud rate divisor */
DL_UART_setBaudRateDivisor(
uart, divisor >> (uint32_t) 6, divisor & (uint32_t) 0x3F);
}
// TODO: Verify parameters and units
/**
* @brief Set the IrDA configurations
*
* Calculates the baud rate divisor given the clock output of the UART clock
* source and the target baud rate. This API also enables IrDA mode.
*
* @param[in] uart Pointer to the register overlay for the peripheral
* @param[in] polarity The receive input polarity.
* One of @DL_UART_IRDA_POLARITY.
* @param[in] pulseLength The length of the IrDA transmit pulse.
* @param[in] irdaClk The clock used for the transmit pulse.
* One of @DL_UART_IRDA_CLOCK.
*/
void DL_UART_configIrDAMode(UART_Regs *uart, DL_UART_IRDA_POLARITY polarity,
uint32_t pulseLength, DL_UART_IRDA_CLOCK irdaClk)
{
DL_Common_updateReg(&uart->IRCTL,
(uint32_t) polarity | UART_IRCTL_IREN_ENABLE,
UART_IRCTL_IRRXPL_MASK | UART_IRCTL_IREN_MASK);
DL_UART_setIrDAPulseLength(uart, pulseLength, irdaClk);
}
void DL_UART_setIrDAPulseLength(
UART_Regs *uart, uint32_t pulseLength, DL_UART_IRDA_CLOCK irdaClk)
{
uint32_t IRTXPL;
if (pulseLength == DL_UART_PULSE_WIDTH_3_16_BIT_PERIOD) {
// Set IRTXCLK = 0 = BITCLK16 and IRTXPL = 5
DL_Common_updateReg(&uart->IRCTL, 0x14,
UART_IRCTL_IRTXCLK_MASK | UART_IRCTL_IRTXPL_MASK);
} else {
IRTXPL =
pulseLength * (uint32_t) 2 * (uint32_t) irdaClk - (uint32_t) 1;
DL_Common_updateReg(&uart->IRCTL, IRTXPL,
UART_IRCTL_IRTXCLK_MASK | UART_IRCTL_IRTXPL_MASK);
}
}
uint8_t DL_UART_receiveDataBlocking(const UART_Regs *uart)
{
while (DL_UART_isRXFIFOEmpty(uart)) {
};
return DL_UART_receiveData(uart);
}
void DL_UART_transmitDataBlocking(UART_Regs *uart, uint8_t data)
{
while (DL_UART_isTXFIFOFull(uart)) {
};
DL_UART_transmitData(uart, data);
}
bool DL_UART_receiveDataCheck(const UART_Regs *uart, uint8_t *buffer)
{
bool status;
if (DL_UART_isRXFIFOEmpty(uart)) {
status = false;
} else {
*buffer = DL_UART_receiveData(uart);
status = true;
}
return status;
}
bool DL_UART_transmitDataCheck(UART_Regs *uart, uint8_t data)
{
bool status;
if (DL_UART_isTXFIFOFull(uart)) {
status = false;
} else {
DL_UART_transmitData(uart, data);
status = true;
}
return status;
}
uint32_t DL_UART_drainRXFIFO(
const UART_Regs *uart, uint8_t *buffer, uint32_t maxCount)
{
uint32_t i;
for (i = 0; i < maxCount; i++) {
if (!DL_UART_isRXFIFOEmpty(uart)) {
buffer[i] = DL_UART_receiveData(uart);
} else {
break;
}
}
return i;
}
uint32_t DL_UART_fillTXFIFO(
UART_Regs *uart, const uint8_t *buffer, uint32_t count)
{
uint32_t i;
for (i = 0; i < count; i++) {
if (!DL_UART_isTXFIFOFull(uart)) {
DL_UART_transmitData(uart, buffer[i]);
} else {
break;
}
}
return i;
}
#ifdef __MSPM0_HAS_UART_MAIN__
bool DL_UART_Main_saveConfiguration(
const UART_Regs *uart, DL_UART_Main_backupConfig *ptr)
{
bool stateSaved = !ptr->backupRdy;
if (stateSaved) {
ptr->controlWord = uart->CTL0;
ptr->clockSel = uart->CLKSEL;
ptr->divideRatio = uart->CLKDIV;
ptr->interruptFifoLevelSelectWord = uart->IFLS;
ptr->ibrd = uart->IBRD;
ptr->fbrd = uart->FBRD;
ptr->lineControlRegisterWord = uart->LCRH;
ptr->glitchFilterControlWord = uart->GFCTL;
ptr->interruptMask0 = uart->CPU_INT.IMASK;
ptr->interruptMask1 = uart->DMA_TRIG_RX.IMASK;
ptr->interruptMask2 = uart->DMA_TRIG_TX.IMASK;
ptr->backupRdy = true;
}
return stateSaved;
}
bool DL_UART_Main_restoreConfiguration(
UART_Regs *uart, DL_UART_Main_backupConfig *ptr)
{
bool stateRestored = ptr->backupRdy;
if (stateRestored) {
/* Set CTL0.ENABLE=0 during initialization */
uart->CTL0 = ptr->controlWord & ~(UART_CTL0_ENABLE_MASK);
uart->CLKSEL = ptr->clockSel;
uart->CLKDIV = ptr->divideRatio;
uart->IFLS = ptr->interruptFifoLevelSelectWord;
uart->IBRD = ptr->ibrd;
uart->FBRD = ptr->fbrd;
uart->LCRH = ptr->lineControlRegisterWord;
uart->GFCTL = ptr->glitchFilterControlWord;
uart->CPU_INT.IMASK = ptr->interruptMask0;
uart->DMA_TRIG_RX.IMASK = ptr->interruptMask1;
uart->DMA_TRIG_TX.IMASK = ptr->interruptMask2;
/* Re-enable UART if it was originally enabled */
if ((ptr->controlWord & UART_CTL0_ENABLE_MASK) ==
UART_CTL0_ENABLE_MASK) {
DL_UART_enable(uart);
}
ptr->backupRdy = false;
}
return stateRestored;
}
#endif /* __MSPM0_HAS_UART_MAIN__ */
#ifdef __MSPM0_HAS_UART_EXTD__
bool DL_UART_Extend_saveConfiguration(
const UART_Regs *uart, DL_UART_Extend_backupConfig *ptr)
{
bool stateSaved = !ptr->backupRdy;
if (stateSaved) {
ptr->controlWord = uart->CTL0;
ptr->clockSel = uart->CLKSEL;
ptr->divideRatio = uart->CLKDIV;
ptr->interruptFifoLevelSelectWord = uart->IFLS;
ptr->ibrd = uart->IBRD;
ptr->fbrd = uart->FBRD;
ptr->lineControlRegisterWord = uart->LCRH;
ptr->glitchFilterControlWord = uart->GFCTL;
ptr->linControlWord = uart->LINCTL;
ptr->irdaControlWord = uart->IRCTL;
ptr->addressMask = uart->AMASK;
ptr->address = uart->ADDR;
ptr->interruptMask0 = uart->CPU_INT.IMASK;
ptr->interruptMask1 = uart->DMA_TRIG_RX.IMASK;
ptr->interruptMask2 = uart->DMA_TRIG_TX.IMASK;
ptr->backupRdy = true;
}
return stateSaved;
}
bool DL_UART_Extend_restoreConfiguration(
UART_Regs *uart, DL_UART_Extend_backupConfig *ptr)
{
bool stateRestored = ptr->backupRdy;
if (stateRestored) {
/* Set CTL0.ENABLE=0 during initialization */
uart->CTL0 = ptr->controlWord & ~(UART_CTL0_ENABLE_MASK);
uart->CLKSEL = ptr->clockSel;
uart->CLKDIV = ptr->divideRatio;
uart->IFLS = ptr->interruptFifoLevelSelectWord;
uart->IBRD = ptr->ibrd;
uart->FBRD = ptr->fbrd;
uart->LCRH = ptr->lineControlRegisterWord;
uart->GFCTL = ptr->glitchFilterControlWord;
uart->LCRH = ptr->lineControlRegisterWord;
uart->IRCTL = ptr->irdaControlWord;
uart->AMASK = ptr->addressMask;
uart->ADDR = ptr->address;
uart->CPU_INT.IMASK = ptr->interruptMask0;
uart->DMA_TRIG_RX.IMASK = ptr->interruptMask1;
uart->DMA_TRIG_TX.IMASK = ptr->interruptMask2;
/* Re-enable UART if it was originally enabled */
if ((ptr->controlWord & UART_CTL0_ENABLE_MASK) ==
UART_CTL0_ENABLE_MASK) {
DL_UART_enable(uart);
}
ptr->backupRdy = false;
}
return stateRestored;
}
#endif /* __MSPM0_HAS_UART_EXTD__ */
#endif /* __MSPM0_HAS_UART_MAIN__ || __MSPM0_HAS_UART_EXTD__ */