<commit_before>/**
 * \file
 * \brief ChipUartLowLevel class implementation for STM32F4
 *
 * \author Copyright (C) 2016 <NAME> http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include "distortos/chip/ChipUartLowLevel.hpp"

#include "distortos/chip/clocks.hpp"
#include "distortos/chip/CMSIS-proxy.h"
#include "distortos/chip/STM32-USARTv1-bits.h"

#include "distortos/devices/communication/UartBase.hpp"

#include <cerrno>

namespace distortos
{

namespace chip
{

namespace
{

/*---------------------------------------------------------------------------------------------------------------------+
| local objects
+---------------------------------------------------------------------------------------------------------------------*/

#ifdef CONFIG_CHIP_HAS_USART1

/// "enable" bit in RCC registers for USART1
#define RCC_APB2ENR_USART1EN_bb				BITBAND(&RCC->APB2ENR, __builtin_ctzl(RCC_APB2ENR_USART1EN))
/// "reset" bit in RCC registers for USART1
#define RCC_APB2RSTR_USART1RST_bb			BITBAND(&RCC->APB2RSTR, __builtin_ctzl(RCC_APB2RSTR_USART1RST))

#endif	// def CONFIG_CHIP_HAS_USART1

#ifdef CONFIG_CHIP_HAS_USART2

/// "enable" bit in RCC registers for USART2
#define RCC_APB1ENR_USART2EN_bb				BITBAND(&RCC->APB1ENR, __builtin_ctzl(RCC_APB1ENR_USART2EN))
/// "reset" bit in RCC registers for USART2
#define RCC_APB1RSTR_USART2RST_bb			BITBAND(&RCC->APB1RSTR, __builtin_ctzl(RCC_APB1RSTR_USART2RST))

#endif	// def CONFIG_CHIP_HAS_USART2

#ifdef CONFIG_CHIP_HAS_USART3

/// "enable" bit in RCC registers for USART3
#define RCC_APB1ENR_USART3EN_bb				BITBAND(&RCC->APB1ENR, __builtin_ctzl(RCC_APB1ENR_USART3EN))
/// "reset" bit in RCC registers for USART3
#define RCC_APB1RSTR_USART3RST_bb			BITBAND(&RCC->APB1RSTR, __builtin_ctzl(RCC_APB1RSTR_USART3RST))

#endif	// def CONFIG_CHIP_HAS_USART3

#ifdef CONFIG_CHIP_HAS_UART4

/// "enable" bit in RCC registers for UART4
#define RCC_APB1ENR_UART4EN_bb				BITBAND(&RCC->APB1ENR, __builtin_ctzl(RCC_APB1ENR_UART4EN))
/// "reset" bit in RCC registers for UART4
#define RCC_APB1RSTR_UART4RST_bb			BITBAND(&RCC->APB1RSTR, __builtin_ctzl(RCC_APB1RSTR_UART4RST))

#endif	// def CONFIG_CHIP_HAS_UART4

#ifdef CONFIG_CHIP_HAS_UART5

/// "enable" bit in RCC registers for UART5
#define RCC_APB1ENR_UART5EN_bb				BITBAND(&RCC->APB1ENR, __builtin_ctzl(RCC_APB1ENR_UART5EN))
/// "reset" bit in RCC registers for UART5
#define RCC_APB1RSTR_UART5RST_bb			BITBAND(&RCC->APB1RSTR, __builtin_ctzl(RCC_APB1RSTR_UART5RST))

#endif	// def CONFIG_CHIP_HAS_UART5

#ifdef CONFIG_CHIP_HAS_USART6

/// "enable" bit in RCC registers for USART6
#define RCC_APB2ENR_USART6EN_bb				BITBAND(&RCC->APB2ENR, __builtin_ctzl(RCC_APB2ENR_USART6EN))
/// "reset" bit in RCC registers for USART6
#define RCC_APB2RSTR_USART6RST_bb			BITBAND(&RCC->APB2RSTR, __builtin_ctzl(RCC_APB2RSTR_USART6RST))

#endif	// def CONFIG_CHIP_HAS_USART6

#ifdef CONFIG_CHIP_HAS_UART7

/// "enable" bit in RCC registers for UART7
#define RCC_APB1ENR_UART7EN_bb				BITBAND(&RCC->APB1ENR, __builtin_ctzl(RCC_APB1ENR_UART7EN))
/// "reset" bit in RCC registers for UART7
#define RCC_APB1RSTR_UART7RST_bb			BITBAND(&RCC->APB1RSTR, __builtin_ctzl(RCC_APB1RSTR_UART7RST))

#endif	// def CONFIG_CHIP_HAS_UART7

#ifdef CONFIG_CHIP_HAS_UART8

/// "enable" bit in RCC registers for UART8
#define RCC_APB1ENR_UART8EN_bb				BITBAND(&RCC->APB1ENR, __builtin_ctzl(RCC_APB1ENR_UART8EN))
/// "reset" bit in RCC registers for UART8
#define RCC_APB1RSTR_UART8RST_bb			BITBAND(&RCC->APB1RSTR, __builtin_ctzl(RCC_APB1RSTR_UART8RST))

#endif	// def CONFIG_CHIP_HAS_UART8

/*---------------------------------------------------------------------------------------------------------------------+
| local functions
+---------------------------------------------------------------------------------------------------------------------*/

/**
 * \brief Decode value of USART_SR register to devices::UartBase::ErrorSet
 *
 * \param [in] sr is the value of USART_SR register that will be decoded
 *
 * \return devices::UartBase::ErrorSet with errors decoded from \a sr
 */

devices::UartBase::ErrorSet decodeErrors(const uint32_t sr)
{
	devices::UartBase::ErrorSet errorSet {};
	errorSet[devices::UartBase::framingError] = (sr & USART_SR_FE) != 0;
	errorSet[devices::UartBase::noiseError] = (sr & USART_SR_NE) != 0;
	errorSet[devices::UartBase::overrunError] = (sr & USART_SR_ORE) != 0;
	errorSet[devices::UartBase::parityError] = (sr & USART_SR_PE) != 0;
	return errorSet;
}

}	// namespace

/*---------------------------------------------------------------------------------------------------------------------+
| public types
+---------------------------------------------------------------------------------------------------------------------*/

/// parameters for construction of UART low-level drivers
class ChipUartLowLevel::Parameters
{
public:

	static_assert(APB1PERIPH_BASE < APB2PERIPH_BASE && APB2PERIPH_BASE < AHB1PERIPH_BASE,
				"Invalid order of APB1, APB2 and AHB!");

	/**
	 * \brief Parameters's constructor
	 *
	 * \param [in] uart is a pointer to USART_TypeDef with registers
	 * \param [in] rxneieBb is a pointer to bitband alias of RXNEIE bit in USART_CR1 register
	 * \param [in] tcieBb is a pointer to bitband alias of TCIE bit in USART_CR1 register
	 * \param [in] txeieBb is a pointer to bitband alias of TXEIE bit in USART_CR1 register
	 * \param [in] rccEnBb is a pointer to bitband alias of appropriate U[S]ARTxEN bit in RCC register
	 * \param [in] rccRstBb is a pointer to bitband alias of appropriate U[S]ARTxRST bit in RCC register
	 * \param [in] irqNumber is the NVIC's IRQ number of associated U[S]ART
	 *
	 * \note Don't add "const" to values of pointers, don't use references - see
	 * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71113
	 */

	constexpr Parameters(USART_TypeDef* uart, volatile unsigned long* rxneieBb, volatile unsigned long* tcieBb,
			volatile unsigned long* txeieBb, volatile unsigned long* rccEnBb, volatile unsigned long* rccRstBb,
			const IRQn_Type irqNumber) :
					uart_{uart},
					peripheralFrequency_{reinterpret_cast<uint32_t>(uart) < APB2PERIPH_BASE ? apb1Frequency :
							reinterpret_cast<uint32_t>(uart) < AHB1PERIPH_BASE ? apb2Frequency : ahbFrequency},
					rxneieBb_{rxneieBb},
					tcieBb_{tcieBb},
					txeieBb_{txeieBb},
					rccEnBb_{rccEnBb},
					rccRstBb_{rccRstBb},
					irqNumber_{irqNumber}<commit_msg>Add support for AHBPERIPH_BASE to STM32F4-ChipUartLowLevel.cpp<commit_after>/**
 * \file
 * \brief ChipUartLowLevel class implementation for STM32F4
 *
 * \author Copyright (C) 2016 <NAME> http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include "distortos/chip/ChipUartLowLevel.hpp"

#include "distortos/chip/clocks.hpp"
#include "distortos/chip/CMSIS-proxy.h"
#include "distortos/chip/STM32-USARTv1-bits.h"

#include "distortos/devices/communication/UartBase.hpp"

#include <cerrno>

namespace distortos
{

namespace chip
{

namespace
{

/*---------------------------------------------------------------------------------------------------------------------+
| local objects
+---------------------------------------------------------------------------------------------------------------------*/

#ifdef CONFIG_CHIP_HAS_USART1

/// "enable" bit in RCC registers for USART1
#define RCC_APB2ENR_USART1EN_bb				BITBAND(&RCC->APB2ENR, __builtin_ctzl(RCC_APB2ENR_USART1EN))
/// "reset" bit in RCC registers for USART1
#define RCC_APB2RSTR_USART1RST_bb			BITBAND(&RCC->APB2RSTR, __builtin_ctzl(RCC_APB2RSTR_USART1RST))

#endif	// def CONFIG_CHIP_HAS_USART1

#ifdef CONFIG_CHIP_HAS_USART2

/// "enable" bit in RCC registers for USART2
#define RCC_APB1ENR_USART2EN_bb				BITBAND(&RCC->APB1ENR, __builtin_ctzl(RCC_APB1ENR_USART2EN))
/// "reset" bit in RCC registers for USART2
#define RCC_APB1RSTR_USART2RST_bb			BITBAND(&RCC->APB1RSTR, __builtin_ctzl(RCC_APB1RSTR_USART2RST))

#endif	// def CONFIG_CHIP_HAS_USART2

#ifdef CONFIG_CHIP_HAS_USART3

/// "enable" bit in RCC registers for USART3
#define RCC_APB1ENR_USART3EN_bb				BITBAND(&RCC->APB1ENR, __builtin_ctzl(RCC_APB1ENR_USART3EN))
/// "reset" bit in RCC registers for USART3
#define RCC_APB1RSTR_USART3RST_bb			BITBAND(&RCC->APB1RSTR, __builtin_ctzl(RCC_APB1RSTR_USART3RST))

#endif	// def CONFIG_CHIP_HAS_USART3

#ifdef CONFIG_CHIP_HAS_UART4

/// "enable" bit in RCC registers for UART4
#define RCC_APB1ENR_UART4EN_bb				BITBAND(&RCC->APB1ENR, __builtin_ctzl(RCC_APB1ENR_UART4EN))
/// "reset" bit in RCC registers for UART4
#define RCC_APB1RSTR_UART4RST_bb			BITBAND(&RCC->APB1RSTR, __builtin_ctzl(RCC_APB1RSTR_UART4RST))

#endif	// def CONFIG_CHIP_HAS_UART4

#ifdef CONFIG_CHIP_HAS_UART5

/// "enable" bit in RCC registers for UART5
#define RCC_APB1ENR_UART5EN_bb				BITBAND(&RCC->APB1ENR, __builtin_ctzl(RCC_APB1ENR_UART5EN))
/// "reset" bit in RCC registers for UART5
#define RCC_APB1RSTR_UART5RST_bb			BITBAND(&RCC->APB1RSTR, __builtin_ctzl(RCC_APB1RSTR_UART5RST))

#endif	// def CONFIG_CHIP_HAS_UART5

#ifdef CONFIG_CHIP_HAS_USART6

/// "enable" bit in RCC registers for USART6
#define RCC_APB2ENR_USART6EN_bb				BITBAND(&RCC->APB2ENR, __builtin_ctzl(RCC_APB2ENR_USART6EN))
/// "reset" bit in RCC registers for USART6
#define RCC_APB2RSTR_USART6RST_bb			BITBAND(&RCC->APB2RSTR, __builtin_ctzl(RCC_APB2RSTR_USART6RST))

#endif	// def CONFIG_CHIP_HAS_USART6

#ifdef CONFIG_CHIP_HAS_UART7

/// "enable" bit in RCC registers for UART7
#define RCC_APB1ENR_UART7EN_bb				BITBAND(&RCC->APB1ENR, __builtin_ctzl(RCC_APB1ENR_UART7EN))
/// "reset" bit in RCC registers for UART7
#define RCC_APB1RSTR_UART7RST_bb			BITBAND(&RCC->APB1RSTR, __builtin_ctzl(RCC_APB1RSTR_UART7RST))

#endif	// def CONFIG_CHIP_HAS_UART7

#ifdef CONFIG_CHIP_HAS_UART8

/// "enable" bit in RCC registers for UART8
#define RCC_APB1ENR_UART8EN_bb				BITBAND(&RCC->APB1ENR, __builtin_ctzl(RCC_APB1ENR_UART8EN))
/// "reset" bit in RCC registers for UART8
#define RCC_APB1RSTR_UART8RST_bb			BITBAND(&RCC->APB1RSTR, __builtin_ctzl(RCC_APB1RSTR_UART8RST))

#endif	// def CONFIG_CHIP_HAS_UART8

/*---------------------------------------------------------------------------------------------------------------------+
| local functions
+---------------------------------------------------------------------------------------------------------------------*/

/**
 * \brief Decode value of USART_SR register to devices::UartBase::ErrorSet
 *
 * \param [in] sr is the value of USART_SR register that will be decoded
 *
 * \return devices::UartBase::ErrorSet with errors decoded from \a sr
 */

devices::UartBase::ErrorSet decodeErrors(const uint32_t sr)
{
	devices::UartBase::ErrorSet errorSet {};
	errorSet[devices::UartBase::framingError] = (sr & USART_SR_FE) != 0;
	errorSet[devices::UartBase::noiseError] = (sr & USART_SR_NE) != 0;
	errorSet[devices::UartBase::overrunError] = (sr & USART_SR_ORE) != 0;
	errorSet[devices::UartBase::parityError] = (sr & USART_SR_PE) != 0;
	return errorSet;
}

}	// namespace

/*---------------------------------------------------------------------------------------------------------------------+
| public types
+---------------------------------------------------------------------------------------------------------------------*/

/// parameters for construction of UART low-level drivers
class ChipUartLowLevel::Parameters
{
	/// base address of APB1 peripherals
	constexpr static const void* apb1PeripheralsBaseAddress {reinterpret_cast<const void*>(APB1PERIPH_BASE)};
	/// base address of APB2 peripherals
	constexpr static const void* apb2PeripheralsBaseAddress {reinterpret_cast<const void*>(APB2PERIPH_BASE)};
	/// base address of AHB peripherals
#if defined(AHBPERIPH_BASE)
	constexpr static const void* ahbPeripheralsBaseAddress {reinterpret_cast<const void*>(AHBPERIPH_BASE)};
#elif defined(AHB1PERIPH_BASE)
	constexpr static const void* ahbPeripheralsBaseAddress {reinterpret_cast<const void*>(AHB1PERIPH_BASE)};
#else
	#error "Unknown base address of AHB peripherals!"
#endif

	static_assert(apb1PeripheralsBaseAddress < apb2PeripheralsBaseAddress &&
			apb2PeripheralsBaseAddress < ahbPeripheralsBaseAddress, "Invalid order of APB1, APB2 and AHB!");

public:

	/**
	 * \brief Parameters's constructor
	 *
	 * \param [in] uart is a pointer to USART_TypeDef with registers
	 * \param [in] rxneieBb is a pointer to bitband alias of RXNEIE bit in USART_CR1 register
	 * \param [in] tcieBb is a pointer to bitband alias of TCIE bit in USART_CR1 register
	 * \param [in] txeieBb is a pointer to bitband alias of TXEIE bit in USART_CR1 register
	 * \param [in] rccEnBb is a pointer to bitband alias of appropriate U[S]ARTxEN bit in RCC register
	 * \param [in] rccRstBb is a pointer to bitband alias of appropriate U[S]ARTxRST bit in RCC register
	 * \param [in] irqNumber is the NVIC's IRQ number of associated U[S]ART
	 *
	 * \note Don't add "const" to values of pointers, don't use references - see
	 * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71113
	 */

	constexpr Parameters(USART_TypeDef* uart, volatile unsigned long* rxneieBb, volatile unsigned long* tcieBb,
			volatile unsigned long* txeieBb, volatile unsigned long* rccEnBb, volatile unsigned long* rccRstBb,
			const IRQn_Type irqNumber) :
					uart_{uart},
					peripheralFrequency_{uart < apb2PeripheralsBaseAddress ? apb1Frequency :
							uart < ahbPeripheralsBaseAddress ? apb2Frequency : ahbFrequency},
					rxneieBb_{rxneieBb},
					tcieBb_{tcieBb},
					txeieBb_{txeieBb},
					rccEnBb_{rccEnBb},
					rccRstBb_{rccRstBb},
					irqNumber_{irqNumber}
{'fraction_non_alphanumeric': 0.19051389088815315, 'fraction_numerical': 0.022527709802792572, 'mean_word_length': 3.0700058582308145, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 45, 'https://': 2, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '251907', 'n_tokens_mistral': 5371, 'n_tokens_neox': 4978, 'n_words': 1098}