#include #include #include namespace { inline auto port_mode_register (const std::uint32_t port) noexcept -> std::uint32_t; inline auto output_type_register (const std::uint32_t port) noexcept -> std::uint32_t; inline auto output_speed_register (const std::uint32_t port) noexcept -> std::uint32_t; inline auto pull_up_pull_down_register(const std::uint32_t port) noexcept -> std::uint32_t; inline auto input_data_register (const std::uint32_t port) noexcept -> std::uint32_t; inline auto output_data_register (const std::uint32_t port) noexcept -> std::uint32_t; inline auto port_mode_register (const std::uint32_t port) noexcept -> std::uint32_t { return std::uint32_t(port + 0x00UL); } inline auto output_type_register (const std::uint32_t port) noexcept -> std::uint32_t { return std::uint32_t(port + 0x04UL); } inline auto output_speed_register (const std::uint32_t port) noexcept -> std::uint32_t { return std::uint32_t(port + 0x08UL); } inline auto pull_up_pull_down_register(const std::uint32_t port) noexcept -> std::uint32_t { return std::uint32_t(port + 0x0CUL); } inline auto input_data_register (const std::uint32_t port) noexcept -> std::uint32_t { return std::uint32_t(port + 0x10UL); } inline auto output_data_register (const std::uint32_t port) noexcept -> std::uint32_t { return std::uint32_t(port + 0x14UL); } auto set_direction_output(const std::uint32_t port, const std::uint32_t bpos) noexcept -> void; auto set_pin_high (const std::uint32_t port, const std::uint32_t bpos) noexcept -> void; auto set_pin_low (const std::uint32_t port, const std::uint32_t bpos) noexcept -> void; auto read_input_value (const std::uint32_t port, const std::uint32_t bpos) noexcept -> bool; auto set_direction_output(const std::uint32_t port, const std::uint32_t bpos) noexcept -> void { // Set the port pin control bits. // Set for no pull up, no pull down. mcal::reg::dynamic_access::reg_and(pull_up_pull_down_register(port), ~static_cast(UINT32_C(0x03) << (bpos * 2U))); // Select the fastest output speed. mcal::reg::dynamic_access::reg_or(output_speed_register(port), static_cast(UINT32_C(0x03) << (bpos * 2U))); // Set the port pin to push-pull output type. mcal::reg::dynamic_access::bit_clr(output_type_register(port), bpos); // Set the port pin direction to digital output. mcal::reg::dynamic_access::reg_or(port_mode_register(port), static_cast(UINT32_C(0x01) << (bpos * 2U))); } #if 0 auto set_direction_input(const std::uint32_t port, const std::uint32_t bpos) noexcept -> void; auto set_direction_input(const std::uint32_t port, const std::uint32_t bpos) noexcept -> void { // Set the port pin direction to digital input. mcal::reg::dynamic_access::reg_and(port_mode_register(port), ~static_cast(UINT32_C(0x03) << (bpos * 2U))); } #endif auto set_pin_high(const std::uint32_t port, const std::uint32_t bpos) noexcept -> void { // Set the port output value to high. mcal::reg::dynamic_access::bit_set(output_data_register(port), bpos); } auto set_pin_low(const std::uint32_t port, const std::uint32_t bpos) noexcept -> void { // Set the port output value to low. mcal::reg::dynamic_access::bit_clr(output_data_register(port), bpos); } auto read_input_value(const std::uint32_t port, const std::uint32_t bpos) noexcept -> bool { // Read the port input value. // According to the microcontroller handbook: // "These bits are read-only and can be accessed in *word* mode only, ..." // We, therefore, access this register with a 16-bit address-type // template parameter. return mcal::reg::dynamic_access::bit_get ( static_cast(input_data_register(port)), static_cast(bpos) ); } } extern "C" void Dio_Init(const Dio_ConfigType*) { set_direction_output(mcal::reg::gpioa_base, static_cast(UINT8_C(5))); set_direction_output(mcal::reg::gpioc_base, static_cast(UINT8_C(8))); } extern "C" void Dio_WriteChannel(Dio_ChannelType ChannelId, Dio_LevelType Level) { (Level != STD_LOW ? set_pin_high(mcal::reg::gpioa_base + std::uint32_t((ChannelId >> 8U) * 0x0400U), ChannelId & 0xFU) : set_pin_low (mcal::reg::gpioa_base + std::uint32_t((ChannelId >> 8U) * 0x0400U), ChannelId & 0xFU)); } extern "C" Dio_LevelType Dio_ReadChannel(Dio_ChannelType ChannelId) { const auto pin_is_high = read_input_value(mcal::reg::gpioa_base + std::uint32_t((ChannelId >> 8U) * 0x0400U), ChannelId & 0xFU); return static_cast ( // AXIVION Next Line AutosarC++19_03-A5.16.1: AUTOSAR permitted pin_is_high ? static_cast(STD_HIGH) : static_cast(STD_LOW) ); }