From b0bc340ad67bb8a900e8e35fc775c889110a1b1c Mon Sep 17 00:00:00 2001 From: Owen L - SFE Date: Thu, 30 Jan 2020 10:55:09 -0700 Subject: [PATCH 1/9] whitespace --- .../TARGET_Apollo3/device/objects_uart.h | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/objects_uart.h b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/objects_uart.h index 8dd68a5b82d..9821a35091b 100644 --- a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/objects_uart.h +++ b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/objects_uart.h @@ -23,34 +23,34 @@ SOFTWARE. #define MBED_OBJECTS_UART_H #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif -typedef uint32_t ap3_uart_pad_t; -typedef uint32_t ap3_uart_inst_t; - -typedef enum{ - AP3_UART_TX = 0x00, - AP3_UART_RX, - AP3_UART_RTS, - AP3_UART_CTS, -} ap3_uart_pad_type_e; - -typedef struct _ap3_uart_pad_map_elem_t{ - ap3_uart_pad_t pad; - uint8_t funcsel; -} ap3_uart_pad_map_elem_t; - - - - -typedef struct serial_s { - ap3_uart_inst_t inst; // UART module instance - void* handle; // UART handle - am_hal_uart_config_t cfg; // UART configuration - -} serial_t; - + typedef uint32_t ap3_uart_pad_t; + typedef uint32_t ap3_uart_inst_t; + + typedef enum + { + AP3_UART_TX = 0x00, + AP3_UART_RX, + AP3_UART_RTS, + AP3_UART_CTS, + } ap3_uart_pad_type_e; + + typedef struct _ap3_uart_pad_map_elem_t + { + ap3_uart_pad_t pad; + uint8_t funcsel; + } ap3_uart_pad_map_elem_t; + + typedef struct serial_s + { + ap3_uart_inst_t inst; // UART module instance + void *handle; // UART handle + am_hal_uart_config_t cfg; // UART configuration + + } serial_t; #ifdef __cplusplus } From bb7d06facf11e3596bbf619cb7ca6b07ce13a033 Mon Sep 17 00:00:00 2001 From: Owen L - SFE Date: Thu, 30 Jan 2020 10:58:50 -0700 Subject: [PATCH 2/9] remove typedef on serial_s While the SERAIL API allows you to define this it would appear that the ASYNCH_SERIAL API defines its own serial_t, which simply includes a serial_s member that is user-defined. --- .../TARGET_Ambiq_Micro/TARGET_Apollo3/device/objects_uart.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/objects_uart.h b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/objects_uart.h index 9821a35091b..9c97b66204e 100644 --- a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/objects_uart.h +++ b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/objects_uart.h @@ -44,13 +44,12 @@ extern "C" uint8_t funcsel; } ap3_uart_pad_map_elem_t; - typedef struct serial_s + struct serial_s { ap3_uart_inst_t inst; // UART module instance void *handle; // UART handle am_hal_uart_config_t cfg; // UART configuration - - } serial_t; + }; #ifdef __cplusplus } From 6d3bfa580aca44f9f3e8ba51abccec6c40402ad7 Mon Sep 17 00:00:00 2001 From: Owen L - SFE Date: Thu, 30 Jan 2020 14:45:08 -0700 Subject: [PATCH 3/9] initial effort --- .../TARGET_AMA3B1KK/device/PeripheralNames.h | 37 -- .../TARGET_AMA3B1KK/device/PeripheralPins.c | 145 +++++ .../TARGET_Apollo3/device/PeripheralNames.h | 34 ++ .../TARGET_Apollo3/device/PeripheralPins.h | 73 +++ .../TARGET_Apollo3/device/objects_uart.h | 7 +- .../TARGET_Apollo3/device/serial_api.c | 529 ++++++++++++++++++ targets/targets.json | 2 +- 7 files changed, 786 insertions(+), 41 deletions(-) delete mode 100644 targets/TARGET_Ambiq_Micro/TARGET_Apollo3/TARGET_AMA3B1KK/device/PeripheralNames.h create mode 100644 targets/TARGET_Ambiq_Micro/TARGET_Apollo3/TARGET_AMA3B1KK/device/PeripheralPins.c create mode 100644 targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/PeripheralNames.h create mode 100644 targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/PeripheralPins.h create mode 100644 targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/serial_api.c diff --git a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/TARGET_AMA3B1KK/device/PeripheralNames.h b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/TARGET_AMA3B1KK/device/PeripheralNames.h deleted file mode 100644 index 461a61eebc6..00000000000 --- a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/TARGET_AMA3B1KK/device/PeripheralNames.h +++ /dev/null @@ -1,37 +0,0 @@ -/* -Copyright (c) 2019 SparkFun Electronics - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ -#ifndef MBED_PERIPHERALNAMES_H -#define MBED_PERIPHERALNAMES_H - -#include "device.h" - -#ifdef __cplusplus -extern "C" { -#endif - - - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/TARGET_AMA3B1KK/device/PeripheralPins.c b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/TARGET_AMA3B1KK/device/PeripheralPins.c new file mode 100644 index 00000000000..9bef584ad40 --- /dev/null +++ b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/TARGET_AMA3B1KK/device/PeripheralPins.c @@ -0,0 +1,145 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "PeripheralPins.h" + +/************RTC***************/ +const PinMap PinMap_RTC[] = { + {NC, 0, 0}, +}; + +/************ADC***************/ +const PinMap PinMap_ADC[] = { + {NC, NC, 0}}; + +/************DAC***************/ +const PinMap PinMap_DAC[] = { + {NC, NC, 0}}; + +/************I2C***************/ +const PinMap PinMap_I2C_SDA[] = { + {NC, NC, 0}}; + +const PinMap PinMap_I2C_SCL[] = { + {NC, NC, 0}}; + +/************UART***************/ +const PinMap PinMap_UART_TX[] = { + {1, UART_0, AM_HAL_PIN_1_UART0TX}, + {7, UART_0, AM_HAL_PIN_7_UART0TX}, + {16, UART_0, AM_HAL_PIN_16_UART0TX}, + {20, UART_0, AM_HAL_PIN_20_UART0TX}, + {22, UART_0, AM_HAL_PIN_22_UART0TX}, + {26, UART_0, AM_HAL_PIN_26_UART0TX}, + {28, UART_0, AM_HAL_PIN_28_UART0TX}, + {30, UART_0, AM_HAL_PIN_30_UART0TX}, + {39, UART_0, AM_HAL_PIN_39_UART0TX}, + {41, UART_0, AM_HAL_PIN_41_UART0TX}, + {48, UART_0, AM_HAL_PIN_48_UART0TX}, + {8, UART_1, AM_HAL_PIN_8_UART1TX}, + {12, UART_1, AM_HAL_PIN_12_UART1TX}, + {14, UART_1, AM_HAL_PIN_14_UART1TX}, + {18, UART_1, AM_HAL_PIN_18_UART1TX}, + {20, UART_1, AM_HAL_PIN_20_UART1TX}, + {24, UART_1, AM_HAL_PIN_24_UART1TX}, + {35, UART_1, AM_HAL_PIN_35_UART1TX}, + {37, UART_1, AM_HAL_PIN_37_UART1TX}, + {39, UART_1, AM_HAL_PIN_39_UART1TX}, + {42, UART_1, AM_HAL_PIN_42_UART1TX}, + {46, UART_1, AM_HAL_PIN_46_UART1TX}, + {NC, NC, 0}}; + +const PinMap PinMap_UART_RX[] = { + {2, UART_0, AM_HAL_PIN_2_UART0RX}, + {4, UART_0, AM_HAL_PIN_4_UART0RX}, + {11, UART_0, AM_HAL_PIN_11_UART0RX}, + {17, UART_0, AM_HAL_PIN_17_UART0RX}, + {21, UART_0, AM_HAL_PIN_21_UART0RX}, + {23, UART_0, AM_HAL_PIN_23_UART0RX}, + {27, UART_0, AM_HAL_PIN_27_UART0RX}, + {29, UART_0, AM_HAL_PIN_29_UART0RX}, + {31, UART_0, AM_HAL_PIN_31_UART0RX}, + {34, UART_0, AM_HAL_PIN_34_UART0RX}, + {40, UART_0, AM_HAL_PIN_40_UART0RX}, + {45, UART_0, AM_HAL_PIN_45_UART0RX}, + {49, UART_0, AM_HAL_PIN_49_UART0RX}, + {9, UART_1, AM_HAL_PIN_9_UART1RX}, + {13, UART_1, AM_HAL_PIN_13_UART1RX}, + {15, UART_1, AM_HAL_PIN_15_UART1RX}, + {19, UART_1, AM_HAL_PIN_19_UART1RX}, + {21, UART_1, AM_HAL_PIN_21_UART1RX}, + {25, UART_1, AM_HAL_PIN_25_UART1RX}, + {36, UART_1, AM_HAL_PIN_36_UART1RX}, + {38, UART_1, AM_HAL_PIN_38_UART1RX}, + {40, UART_1, AM_HAL_PIN_40_UART1RX}, + {43, UART_1, AM_HAL_PIN_43_UART1RX}, + {47, UART_1, AM_HAL_PIN_47_UART1RX}, + {NC, NC, 0}}; + +const PinMap PinMap_UART_RTS[] = { + {3, UART_0, AM_HAL_PIN_3_UART0RTS}, + {5, UART_0, AM_HAL_PIN_5_UART0RTS}, + {13, UART_0, AM_HAL_PIN_13_UART0RTS}, + {18, UART_0, AM_HAL_PIN_18_UART0RTS}, + {34, UART_0, AM_HAL_PIN_34_UART0RTS}, + {35, UART_0, AM_HAL_PIN_35_UART0RTS}, + {37, UART_0, AM_HAL_PIN_37_UART0RTS}, + {41, UART_0, AM_HAL_PIN_41_UART0RTS}, + {10, UART_1, AM_HAL_PIN_10_UART1RTS}, + {16, UART_1, AM_HAL_PIN_16_UART1RTS}, + {20, UART_1, AM_HAL_PIN_20_UART1RTS}, + {30, UART_1, AM_HAL_PIN_30_UART1RTS}, + {31, UART_1, AM_HAL_PIN_31_UART1RTS}, + {34, UART_1, AM_HAL_PIN_34_UART1RTS}, + {41, UART_1, AM_HAL_PIN_41_UART1RTS}, + {44, UART_1, AM_HAL_PIN_44_UART1RTS}, + {NC, NC, 0}}; + +const PinMap PinMap_UART_CTS[] = { + {4, UART_0, AM_HAL_PIN_4_UART0CTS}, + {6, UART_0, AM_HAL_PIN_6_UART0CTS}, + {12, UART_0, AM_HAL_PIN_12_UART0CTS}, + {24, UART_0, AM_HAL_PIN_24_UART0CTS}, + {29, UART_0, AM_HAL_PIN_29_UART0CTS}, + {33, UART_0, AM_HAL_PIN_33_UART0CTS}, + {26, UART_0, AM_HAL_PIN_36_UART0CTS}, + {38, UART_0, AM_HAL_PIN_38_UART0CTS}, + {11, UART_1, AM_HAL_PIN_11_UART1CTS}, + {17, UART_1, AM_HAL_PIN_17_UART1CTS}, + {21, UART_1, AM_HAL_PIN_21_UART1CTS}, + {26, UART_1, AM_HAL_PIN_26_UART1CTS}, + {29, UART_1, AM_HAL_PIN_29_UART1CTS}, + {32, UART_1, AM_HAL_PIN_32_UART1CTS}, + {36, UART_1, AM_HAL_PIN_36_UART1CTS}, + {45, UART_1, AM_HAL_PIN_45_UART1CTS}, + {NC, NC, 0}}; + +/************SPI***************/ +const PinMap PinMap_SPI_SCLK[] = { + {NC, NC, 0}}; + +const PinMap PinMap_SPI_MOSI[] = { + {NC, NC, 0}}; + +const PinMap PinMap_SPI_MISO[] = { + {NC, NC, 0}}; + +const PinMap PinMap_SPI_SSEL[] = { + {NC, NC, 0}}; + +/************PWM***************/ +const PinMap PinMap_PWM[] = { + {NC, NC, 0}}; diff --git a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/PeripheralNames.h b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/PeripheralNames.h new file mode 100644 index 00000000000..fc746cf0de6 --- /dev/null +++ b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/PeripheralNames.h @@ -0,0 +1,34 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBED_PERIPHERALNAMES_H +#define MBED_PERIPHERALNAMES_H + +#include "cmsis.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + UART_0 = 0, + UART_1, +} UARTName; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/PeripheralPins.h b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/PeripheralPins.h new file mode 100644 index 00000000000..dabf69f78b4 --- /dev/null +++ b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/PeripheralPins.h @@ -0,0 +1,73 @@ +/* + * mbed Microcontroller Library + * Copyright (c) 2017-2018 Future Electronics + * Copyright (c) 2018-2019 Cypress Semiconductor Corporation + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MBED_PERIPHERALPINS_H +#define MBED_PERIPHERALPINS_H + +#include "pinmap.h" +#include "PeripheralNames.h" + +//*** I2C *** +#if DEVICE_I2C +extern const PinMap PinMap_I2C_SDA[]; +extern const PinMap PinMap_I2C_SCL[]; +#endif + +//*** PWM *** +#if DEVICE_PWMOUT +extern const PinMap PinMap_PWM_OUT[]; +#endif + +//*** SERIAL *** +#if DEVICE_SERIAL +extern const PinMap PinMap_UART_TX[]; +extern const PinMap PinMap_UART_RX[]; +extern const PinMap PinMap_UART_RTS[]; +extern const PinMap PinMap_UART_CTS[]; +#endif + +//*** SPI *** +#if DEVICE_SPI +extern const PinMap PinMap_SPI_MOSI[]; +extern const PinMap PinMap_SPI_MISO[]; +extern const PinMap PinMap_SPI_SCLK[]; +extern const PinMap PinMap_SPI_SSEL[]; +#endif + +//*** ADC *** +#if DEVICE_ANALOGIN +extern const PinMap PinMap_ADC[]; +#endif + +//*** DAC *** +#if DEVICE_ANALOGOUT +extern const PinMap PinMap_DAC[]; +#endif + +//*** QSPI *** +#if DEVICE_QSPI +extern const PinMap PinMap_QSPI_SCLK[]; +extern const PinMap PinMap_QSPI_SSEL[]; +extern const PinMap PinMap_QSPI_DATA0[]; +extern const PinMap PinMap_QSPI_DATA1[]; +extern const PinMap PinMap_QSPI_DATA2[]; +extern const PinMap PinMap_QSPI_DATA3[]; +#endif + +#endif diff --git a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/objects_uart.h b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/objects_uart.h index 9c97b66204e..71241de4215 100644 --- a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/objects_uart.h +++ b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/objects_uart.h @@ -46,9 +46,10 @@ extern "C" struct serial_s { - ap3_uart_inst_t inst; // UART module instance - void *handle; // UART handle - am_hal_uart_config_t cfg; // UART configuration + ap3_uart_inst_t inst; // UART module instance + void *handle; // UART handle + am_hal_uart_config_t cfg; // UART configuration + volatile uint32_t tx_idle; // UART tx idle indication }; #ifdef __cplusplus diff --git a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/serial_api.c b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/serial_api.c new file mode 100644 index 00000000000..b79a76e20f7 --- /dev/null +++ b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/serial_api.c @@ -0,0 +1,529 @@ + +/** \addtogroup hal */ +/** @{*/ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if DEVICE_SERIAL + +#include "serial_api.h" + +#include "PeripheralPins.h" + +// interrupt variables +static uart_irq_handler irq_handler; +static uint32_t serial_irq_ids[AM_REG_UART_NUM_MODULES]; + +/** + * \defgroup hal_GeneralSerial Serial Configuration Functions + * + * # Defined behavior + * * ::serial_init initializes the ::serial_t + * * ::serial_init sets the default parameters for serial peripheral (9600 bps, 8N1 format) + * * ::serial_init configures the specified pins + * * ::serial_free releases the serial peripheral + * * ::serial_baud configures the baud rate + * * at least 9600 bps the baud rate must be supported + * * ::serial_format configures the transmission format (number of bits, parity and the number of stop bits) + * * at least 8N1 format must be supported + * * ::serial_irq_handler registers the interrupt handler which will be invoked when the interrupt fires. + * * ::serial_irq_set enables or disables the serial RX or TX IRQ. + * * If `RxIrq` is enabled by ::serial_irq_set, ::serial_irq_handler will be invoked whenever + * Receive Data Register Full IRQ is generated. + * * If `TxIrq` is enabled by ::serial_irq_set, ::serial_irq_handler will be invoked whenever + * Transmit Data Register Empty IRQ is generated. + * * If the interrupt condition holds true, when the interrupt is enabled with ::serial_irq_set, + * the ::serial_irq_handler is called instantly. + * * ::serial_getc returns the character from serial buffer. + * * ::serial_getc is a blocking call (waits for the character). + * * ::serial_putc sends a character. + * * ::serial_putc is a blocking call (waits for a peripheral to be available). + * * ::serial_readable returns non-zero value if a character can be read, 0 otherwise. + * * ::serial_writable returns non-zero value if a character can be written, 0 otherwise. + * * ::serial_clear clears the ::serial_t RX/TX buffers + * * ::serial_break_set sets the break signal. + * * ::serial_break_clear clears the break signal. + * * ::serial_pinout_tx configures the TX pin as an output (to be used in half-duplex mode). + * * ::serial_set_flow_control configures serial flow control. + * * ::serial_set_flow_control sets flow control in the hardware if a serial peripheral supports it, + * otherwise software emulation is used. + * * ::serial_tx_asynch starts the serial asynchronous transfer. + * * ::serial_tx_asynch writes `tx_length` bytes from the `tx` to the bus. + * * ::serial_tx_asynch must support 8 data bits + * * The callback given to ::serial_tx_asynch is invoked when the transfer completes. + * * ::serial_tx_asynch specifies the logical OR of events to be registered. + * * The ::serial_tx_asynch function may use the `DMAUsage` hint to select the appropriate async algorithm. + * * ::serial_rx_asynch starts the serial asynchronous transfer. + * * ::serial_rx_asynch reads `rx_length` bytes to the `rx` buffer. + * * ::serial_rx_asynch must support 8 data bits + * * The callback given to ::serial_rx_asynch is invoked when the transfer completes. + * * ::serial_rx_asynch specifies the logical OR of events to be registered. + * * The ::serial_rx_asynch function may use the `DMAUsage` hint to select the appropriate async algorithm. + * * ::serial_rx_asynch specifies a character in range 0-254 to be matched, 255 is a reserved value. + * * If SERIAL_EVENT_RX_CHARACTER_MATCH event is not registered, the `char_match` is ignored. + * * The SERIAL_EVENT_RX_CHARACTER_MATCH event is set in the callback when SERIAL_EVENT_RX_CHARACTER_MATCH event is + * registered AND `char_match` is present in the received data. + * * ::serial_tx_active returns non-zero if the TX transaction is ongoing, 0 otherwise. + * * ::serial_rx_active returns non-zero if the RX transaction is ongoing, 0 otherwise. + * * ::serial_irq_handler_asynch returns event flags if a transfer termination condition was met, otherwise returns 0. + * * ::serial_irq_handler_asynch takes no longer than one packet transfer time (packet_bits / baudrate) to execute. + * * ::serial_tx_abort_asynch aborts the ongoing TX transaction. + * * ::serial_tx_abort_asynch disables the enabled interupt for TX. + * * ::serial_tx_abort_asynch flushes the TX hardware buffer if TX FIFO is used. + * * ::serial_rx_abort_asynch aborts the ongoing RX transaction. + * * ::serial_rx_abort_asynch disables the enabled interupt for RX. + * * ::serial_rx_abort_asynch flushes the TX hardware buffer if RX FIFO is used. + * * Correct operation guaranteed when interrupt latency is shorter than one packet transfer time (packet_bits / baudrate) + * if the flow control is not used. + * * Correct operation guaranteed regardless of interrupt latency if the flow control is used. + * + * # Undefined behavior + * * Calling ::serial_init multiple times on the same `serial_t` without ::serial_free. + * * Passing invalid pin to ::serial_init, ::serial_pinout_tx. + * * Calling any function other than ::serial_init on am uninitialized or freed `serial_t`. + * * Passing an invalid pointer as `obj` to any function. + * * Passing an invalid pointer as `handler` to ::serial_irq_handler, ::serial_tx_asynch, ::serial_rx_asynch. + * * Calling ::serial_tx_abort while no async TX transfer is being processed. + * * Calling ::serial_rx_abort while no async RX transfer is being processed. + * * Devices behavior is undefined when the interrupt latency is longer than one packet transfer time + * (packet_bits / baudrate) if the flow control is not used. + * @{ + */ + +/** + * \defgroup hal_GeneralSerial_tests Serial hal tests + * The Serial HAL tests ensure driver conformance to defined behavior. + * + * To run the Serial hal tests use the command: + * + * mbed test -t -m -n tests-mbed_hal_fpga_ci_test_shield-uart + * + */ + +/** Initialize the serial peripheral. It sets the default parameters for serial + * peripheral, and configures its specifieds pins. + * + * @param obj The serial object + * @param tx The TX pin name + * @param rx The RX pin name + */ +void serial_init(serial_t *obj, PinName tx, PinName rx) +{ + // determine the UART to use + UARTName uart_tx = (UARTName)pinmap_peripheral(tx, PinMap_UART_TX); + UARTName uart_rx = (UARTName)pinmap_peripheral(rx, PinMap_UART_RX); + UARTName uart = (UARTName)pinmap_merge(uart_tx, uart_rx); + obj->serial.inst = (uint32_t)uart; + MBED_ASSERT((int)uart != NC); + + // associate buffers + // todo: decide which buffers to use + obj->serial.cfg.pui8RxBuffer = NULL; + obj->serial.cfg.pui8TxBuffer = NULL; + obj->serial.cfg.ui32RxBufferSize = 0; + obj->serial.cfg.ui32TxBufferSize = 0; + + // pinout the chosen uart + pinmap_pinout(tx, PinMap_UART_TX); + pinmap_pinout(rx, PinMap_UART_RX); + + // start UART instance + MBED_ASSERT(am_hal_uart_initialize(obj->serial.inst, &(obj->serial.handle)) == AM_HAL_STATUS_SUCCESS); + MBED_ASSERT(am_hal_uart_power_control(obj->serial.handle, AM_HAL_SYSCTRL_WAKE, false) == AM_HAL_STATUS_SUCCESS); + MBED_ASSERT(am_hal_uart_configure(obj->serial.handle, &(obj->serial.cfg)) == AM_HAL_STATUS_SUCCESS); + + // enable UART interrupts for this instance + NVIC_EnableIRQ((IRQn_Type)(UART0_IRQn + obj->serial.inst)); + am_hal_uart_interrupt_enable(obj->serial.handle, (AM_HAL_UART_INT_RX | AM_HAL_UART_INT_TX)); + + // service interrupts to determine idle state + am_hal_uart_interrupt_service(obj->serial.handle, 0, (uint32_t *)obj->serial.tx_idle); + + // set default baud rate and format + serial_baud(obj, 9600); + serial_format(obj, 8, ParityNone, 1); +} + +/** Release the serial peripheral, not currently invoked. It requires further + * resource management. + * + * @param obj The serial object + */ +void serial_free(serial_t *obj) +{ + // nothing to do unless resources are allocated for members of the serial_s serial member of obj + // assuming mbed handles obj and its members +} + +/** Configure the baud rate + * + * @param obj The serial object + * @param baudrate The baud rate to be configured + */ +void serial_baud(serial_t *obj, int baudrate) +{ + obj->serial.cfg.ui32BaudRate = (uint32_t)baudrate; + MBED_ASSERT(am_hal_uart_configure(obj->serial.handle, &(obj->serial.cfg)) == AM_HAL_STATUS_SUCCESS); +} + +/** Configure the format. Set the number of bits, parity and the number of stop bits + * + * @param obj The serial object + * @param data_bits The number of data bits + * @param parity The parity + * @param stop_bits The number of stop bits + */ +void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_bits) +{ + uint32_t am_hal_parity = AM_HAL_UART_PARITY_NONE; + switch (parity) + { + case ParityNone: + am_hal_parity = AM_HAL_UART_PARITY_NONE; + break; + case ParityOdd: + am_hal_parity = AM_HAL_UART_PARITY_ODD; + break; + case ParityEven: + am_hal_parity = AM_HAL_UART_PARITY_EVEN; + break; + default: // fall-through intentional after default + case ParityForced1: + case ParityForced0: + MBED_ASSERT(0); + break; + } + + obj->serial.cfg.ui32DataBits = (uint32_t)data_bits; + obj->serial.cfg.ui32Parity = (uint32_t)am_hal_parity; + obj->serial.cfg.ui32StopBits = (uint32_t)stop_bits; + MBED_ASSERT(am_hal_uart_configure(obj->serial.handle, &(obj->serial.cfg)) == AM_HAL_STATUS_SUCCESS); +} + +/** The serial interrupt handler registration + * + * @param obj The serial object + * @param handler The interrupt handler which will be invoked when the interrupt fires + * @param id The SerialBase object + */ +void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id) +{ + irq_handler = handler; + serial_irq_ids[obj->serial.inst] = id; + // todo: revisit with Kyle +} + +/** Configure serial interrupt. This function is used for word-approach + * + * @param obj The serial object + * @param irq The serial IRQ type (RX or TX) + * @param enable Set to non-zero to enable events, or zero to disable them + */ +void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable) +{ + // todo: revisit with Kyle +} + +/** Get character. This is a blocking call, waiting for a character + * + * @param obj The serial object + */ +int serial_getc(serial_t *obj) +{ + // todo: handle data_bits > 8 + uint8_t rx_c = 0x00; + uint32_t bytes_read = 0x00; + static am_hal_uart_transfer_t am_hal_uart_xfer_read_single = + { + .ui32Direction = AM_HAL_UART_READ, + .pui8Data = (uint8_t *)&rx_c, + .ui32NumBytes = 1, + .ui32TimeoutMs = 0, + .pui32BytesTransferred = &bytes_read, + }; + + do + { + am_hal_uart_transfer(obj->serial.handle, &am_hal_uart_xfer_read_single); + } while (bytes_read == 0); + + return (int)rx_c; +} + +/** Send a character. This is a blocking call, waiting for a peripheral to be available + * for writing + * + * @param obj The serial object + * @param c The character to be sent + */ +void serial_putc(serial_t *obj, int c) +{ + uint32_t bytes_sent = 0; + am_hal_uart_transfer_t am_hal_uart_xfer_write_single = + { + .ui32Direction = AM_HAL_UART_WRITE, + .pui8Data = (uint8_t *)(&c), + .ui32NumBytes = 1, + .ui32TimeoutMs = 0, + .pui32BytesTransferred = &bytes_sent, + }; + + do + { + while (!(obj->serial.tx_idle)) + { + }; // wait for tx to become idle + + am_hal_uart_transfer(_handle, &sUartWrite); + + } while (bytes_sent == 0); +} + +/** Check if the serial peripheral is readable + * + * @param obj The serial object + * @return Non-zero value if a character can be read, 0 if nothing to read + */ +int serial_readable(serial_t *obj) +{ + // todo: +} + +/** Check if the serial peripheral is writable + * + * @param obj The serial object + * @return Non-zero value if a character can be written, 0 otherwise. + */ +int serial_writable(serial_t *obj) +{ + // todo: +} + +/** Clear the serial peripheral + * + * @param obj The serial object + */ +void serial_clear(serial_t *obj) +{ + // todo: +} + +/** Set the break + * + * @param obj The serial object + */ +void serial_break_set(serial_t *obj) +{ + // todo: +} + +/** Clear the break + * + * @param obj The serial object + */ +void serial_break_clear(serial_t *obj) +{ + // todo: +} + +/** Configure the TX pin for UART function. + * + * @param tx The pin name used for TX + */ +void serial_pinout_tx(PinName tx) + +#if DEVICE_SERIAL_FC + /** Configure the serial for the flow control. It sets flow control in the hardware + * if a serial peripheral supports it, otherwise software emulation is used. + * + * @param obj The serial object + * @param type The type of the flow control. Look at the available FlowControl types. + * @param rxflow The TX pin name + * @param txflow The RX pin name + */ + void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, PinName txflow) +{ + // todo: +} + +/** Configure the serial for the flow control. It sets flow control in the hardware + * if a serial peripheral supports it, otherwise software emulation is used. + * + * @param obj The serial object + * @param type The type of the flow control. Look at the available FlowControl types. + * @param pinmap Pointer to structure which holds static pinmap + */ +void serial_set_flow_control_direct(serial_t *obj, FlowControl type, const serial_fc_pinmap_t *pinmap) +{ + // todo: +} +#endif + +/** Get the pins that support Serial TX + * + * Return a PinMap array of pins that support Serial TX. The + * array is terminated with {NC, NC, 0}. + * + * @return PinMap array + */ +const PinMap *serial_tx_pinmap(void) +{ + return PinMap_UART_TX; +} + +/** Get the pins that support Serial RX + * + * Return a PinMap array of pins that support Serial RX. The + * array is terminated with {NC, NC, 0}. + * + * @return PinMap array + */ +const PinMap *serial_rx_pinmap(void) +{ + return PinMap_UART_TX; +} + +#if DEVICE_SERIAL_FC +/** Get the pins that support Serial CTS + * + * Return a PinMap array of pins that support Serial CTS. The + * array is terminated with {NC, NC, 0}. + * + * @return PinMap array + */ +const PinMap *serial_cts_pinmap(void) +{ + return PinMap_UART_CTS; +} + +/** Get the pins that support Serial RTS + * + * Return a PinMap array of pins that support Serial RTS. The + * array is terminated with {NC, NC, 0}. + * + * @return PinMap array + */ +const PinMap *serial_rts_pinmap(void) +{ + return PinMap_UART_RTS; +} +#endif + +#if DEVICE_SERIAL_ASYNCH + +/**@}*/ + +/** + * \defgroup hal_AsynchSerial Asynchronous Serial Hardware Abstraction Layer + * @{ + */ + +/** Begin asynchronous TX transfer. The used buffer is specified in the serial object, + * tx_buff + * + * @param obj The serial object + * @param tx The transmit buffer + * @param tx_length The number of bytes to transmit + * @param tx_width Deprecated argument + * @param handler The serial handler + * @param event The logical OR of events to be registered + * @param hint A suggestion for how to use DMA with this transfer + * @return Returns number of data transfered, otherwise returns 0 + */ +int serial_tx_asynch(serial_t *obj, const void *tx, size_t tx_length, uint8_t tx_width, uint32_t handler, uint32_t event, DMAUsage hint) +{ + // todo: +} + +/** Begin asynchronous RX transfer (enable interrupt for data collecting) + * The used buffer is specified in the serial object - rx_buff + * + * @param obj The serial object + * @param rx The receive buffer + * @param rx_length The number of bytes to receive + * @param rx_width Deprecated argument + * @param handler The serial handler + * @param event The logical OR of events to be registered + * @param char_match A character in range 0-254 to be matched + * @param hint A suggestion for how to use DMA with this transfer + */ +void serial_rx_asynch(serial_t *obj, void *rx, size_t rx_length, uint8_t rx_width, uint32_t handler, uint32_t event, uint8_t char_match, DMAUsage hint) +{ + // todo: +} + +/** Attempts to determine if the serial peripheral is already in use for TX + * + * @param obj The serial object + * @return Non-zero if the RX transaction is ongoing, 0 otherwise + */ +uint8_t serial_tx_active(serial_t *obj) +{ + // todo: +} + +/** Attempts to determine if the serial peripheral is already in use for RX + * + * @param obj The serial object + * @return Non-zero if the RX transaction is ongoing, 0 otherwise + */ +uint8_t serial_rx_active(serial_t *obj) +{ + // todo: +} + +/** The asynchronous TX and RX handler. + * + * @param obj The serial object + * @return Returns event flags if an RX transfer termination condition was met; otherwise returns 0 + */ +int serial_irq_handler_asynch(serial_t *obj) +{ + // todo: +} + +/** Abort the ongoing TX transaction. It disables the enabled interupt for TX and + * flushes the TX hardware buffer if TX FIFO is used + * + * @param obj The serial object + */ +void serial_tx_abort_asynch(serial_t *obj) +{ + // todo: +} + +/** Abort the ongoing RX transaction. It disables the enabled interrupt for RX and + * flushes the RX hardware buffer if RX FIFO is used + * + * @param obj The serial object + */ +void serial_rx_abort_asynch(serial_t *obj) +{ + // todo: +} + +/**@}*/ + +#endif + +#ifdef __cplusplus +} +#endif + +#endif + +/** @}*/ diff --git a/targets/targets.json b/targets/targets.json index a4cd264c2bf..a4ad2eee476 100644 --- a/targets/targets.json +++ b/targets/targets.json @@ -9846,7 +9846,7 @@ "supported_toolchains": ["GCC_ARM"], "public": false, "extra_labels": ["Ambiq_Micro", "Apollo3"], - "device_has": ["MPU", "USTICKER"], + "device_has": ["MPU", "USTICKER", "SERIAL_ASYNCH"], "macros": [] }, "AMA3B1KK": { From ce41cfdbf8efe7a917902090922d725fa6c6322f Mon Sep 17 00:00:00 2001 From: Owen L - SFE Date: Thu, 30 Jan 2020 10:55:09 -0700 Subject: [PATCH 4/9] whitespace --- .../TARGET_Apollo3/device/objects_uart.h | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/objects_uart.h b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/objects_uart.h index 8dd68a5b82d..9821a35091b 100644 --- a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/objects_uart.h +++ b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/objects_uart.h @@ -23,34 +23,34 @@ SOFTWARE. #define MBED_OBJECTS_UART_H #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif -typedef uint32_t ap3_uart_pad_t; -typedef uint32_t ap3_uart_inst_t; - -typedef enum{ - AP3_UART_TX = 0x00, - AP3_UART_RX, - AP3_UART_RTS, - AP3_UART_CTS, -} ap3_uart_pad_type_e; - -typedef struct _ap3_uart_pad_map_elem_t{ - ap3_uart_pad_t pad; - uint8_t funcsel; -} ap3_uart_pad_map_elem_t; - - - - -typedef struct serial_s { - ap3_uart_inst_t inst; // UART module instance - void* handle; // UART handle - am_hal_uart_config_t cfg; // UART configuration - -} serial_t; - + typedef uint32_t ap3_uart_pad_t; + typedef uint32_t ap3_uart_inst_t; + + typedef enum + { + AP3_UART_TX = 0x00, + AP3_UART_RX, + AP3_UART_RTS, + AP3_UART_CTS, + } ap3_uart_pad_type_e; + + typedef struct _ap3_uart_pad_map_elem_t + { + ap3_uart_pad_t pad; + uint8_t funcsel; + } ap3_uart_pad_map_elem_t; + + typedef struct serial_s + { + ap3_uart_inst_t inst; // UART module instance + void *handle; // UART handle + am_hal_uart_config_t cfg; // UART configuration + + } serial_t; #ifdef __cplusplus } From b171bdd9f46f49ea2e850008da3e67261f70cb37 Mon Sep 17 00:00:00 2001 From: Owen L - SFE Date: Thu, 30 Jan 2020 10:58:50 -0700 Subject: [PATCH 5/9] remove typedef on serial_s While the SERAIL API allows you to define this it would appear that the ASYNCH_SERIAL API defines its own serial_t, which simply includes a serial_s member that is user-defined. --- .../TARGET_Ambiq_Micro/TARGET_Apollo3/device/objects_uart.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/objects_uart.h b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/objects_uart.h index 9821a35091b..9c97b66204e 100644 --- a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/objects_uart.h +++ b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/objects_uart.h @@ -44,13 +44,12 @@ extern "C" uint8_t funcsel; } ap3_uart_pad_map_elem_t; - typedef struct serial_s + struct serial_s { ap3_uart_inst_t inst; // UART module instance void *handle; // UART handle am_hal_uart_config_t cfg; // UART configuration - - } serial_t; + }; #ifdef __cplusplus } From c58f226619e3d5508f0f68f7aef025f449d1391e Mon Sep 17 00:00:00 2001 From: Owen L - SFE Date: Thu, 30 Jan 2020 14:45:08 -0700 Subject: [PATCH 6/9] initial effort --- .../TARGET_AMA3B1KK/device/PeripheralNames.h | 37 -- .../TARGET_AMA3B1KK/device/PeripheralPins.c | 145 +++++ .../TARGET_Apollo3/device/PeripheralNames.h | 34 ++ .../TARGET_Apollo3/device/PeripheralPins.h | 73 +++ .../TARGET_Apollo3/device/objects_uart.h | 7 +- .../TARGET_Apollo3/device/serial_api.c | 529 ++++++++++++++++++ 6 files changed, 785 insertions(+), 40 deletions(-) delete mode 100644 targets/TARGET_Ambiq_Micro/TARGET_Apollo3/TARGET_AMA3B1KK/device/PeripheralNames.h create mode 100644 targets/TARGET_Ambiq_Micro/TARGET_Apollo3/TARGET_AMA3B1KK/device/PeripheralPins.c create mode 100644 targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/PeripheralNames.h create mode 100644 targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/PeripheralPins.h create mode 100644 targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/serial_api.c diff --git a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/TARGET_AMA3B1KK/device/PeripheralNames.h b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/TARGET_AMA3B1KK/device/PeripheralNames.h deleted file mode 100644 index 461a61eebc6..00000000000 --- a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/TARGET_AMA3B1KK/device/PeripheralNames.h +++ /dev/null @@ -1,37 +0,0 @@ -/* -Copyright (c) 2019 SparkFun Electronics - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ -#ifndef MBED_PERIPHERALNAMES_H -#define MBED_PERIPHERALNAMES_H - -#include "device.h" - -#ifdef __cplusplus -extern "C" { -#endif - - - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/TARGET_AMA3B1KK/device/PeripheralPins.c b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/TARGET_AMA3B1KK/device/PeripheralPins.c new file mode 100644 index 00000000000..9bef584ad40 --- /dev/null +++ b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/TARGET_AMA3B1KK/device/PeripheralPins.c @@ -0,0 +1,145 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "PeripheralPins.h" + +/************RTC***************/ +const PinMap PinMap_RTC[] = { + {NC, 0, 0}, +}; + +/************ADC***************/ +const PinMap PinMap_ADC[] = { + {NC, NC, 0}}; + +/************DAC***************/ +const PinMap PinMap_DAC[] = { + {NC, NC, 0}}; + +/************I2C***************/ +const PinMap PinMap_I2C_SDA[] = { + {NC, NC, 0}}; + +const PinMap PinMap_I2C_SCL[] = { + {NC, NC, 0}}; + +/************UART***************/ +const PinMap PinMap_UART_TX[] = { + {1, UART_0, AM_HAL_PIN_1_UART0TX}, + {7, UART_0, AM_HAL_PIN_7_UART0TX}, + {16, UART_0, AM_HAL_PIN_16_UART0TX}, + {20, UART_0, AM_HAL_PIN_20_UART0TX}, + {22, UART_0, AM_HAL_PIN_22_UART0TX}, + {26, UART_0, AM_HAL_PIN_26_UART0TX}, + {28, UART_0, AM_HAL_PIN_28_UART0TX}, + {30, UART_0, AM_HAL_PIN_30_UART0TX}, + {39, UART_0, AM_HAL_PIN_39_UART0TX}, + {41, UART_0, AM_HAL_PIN_41_UART0TX}, + {48, UART_0, AM_HAL_PIN_48_UART0TX}, + {8, UART_1, AM_HAL_PIN_8_UART1TX}, + {12, UART_1, AM_HAL_PIN_12_UART1TX}, + {14, UART_1, AM_HAL_PIN_14_UART1TX}, + {18, UART_1, AM_HAL_PIN_18_UART1TX}, + {20, UART_1, AM_HAL_PIN_20_UART1TX}, + {24, UART_1, AM_HAL_PIN_24_UART1TX}, + {35, UART_1, AM_HAL_PIN_35_UART1TX}, + {37, UART_1, AM_HAL_PIN_37_UART1TX}, + {39, UART_1, AM_HAL_PIN_39_UART1TX}, + {42, UART_1, AM_HAL_PIN_42_UART1TX}, + {46, UART_1, AM_HAL_PIN_46_UART1TX}, + {NC, NC, 0}}; + +const PinMap PinMap_UART_RX[] = { + {2, UART_0, AM_HAL_PIN_2_UART0RX}, + {4, UART_0, AM_HAL_PIN_4_UART0RX}, + {11, UART_0, AM_HAL_PIN_11_UART0RX}, + {17, UART_0, AM_HAL_PIN_17_UART0RX}, + {21, UART_0, AM_HAL_PIN_21_UART0RX}, + {23, UART_0, AM_HAL_PIN_23_UART0RX}, + {27, UART_0, AM_HAL_PIN_27_UART0RX}, + {29, UART_0, AM_HAL_PIN_29_UART0RX}, + {31, UART_0, AM_HAL_PIN_31_UART0RX}, + {34, UART_0, AM_HAL_PIN_34_UART0RX}, + {40, UART_0, AM_HAL_PIN_40_UART0RX}, + {45, UART_0, AM_HAL_PIN_45_UART0RX}, + {49, UART_0, AM_HAL_PIN_49_UART0RX}, + {9, UART_1, AM_HAL_PIN_9_UART1RX}, + {13, UART_1, AM_HAL_PIN_13_UART1RX}, + {15, UART_1, AM_HAL_PIN_15_UART1RX}, + {19, UART_1, AM_HAL_PIN_19_UART1RX}, + {21, UART_1, AM_HAL_PIN_21_UART1RX}, + {25, UART_1, AM_HAL_PIN_25_UART1RX}, + {36, UART_1, AM_HAL_PIN_36_UART1RX}, + {38, UART_1, AM_HAL_PIN_38_UART1RX}, + {40, UART_1, AM_HAL_PIN_40_UART1RX}, + {43, UART_1, AM_HAL_PIN_43_UART1RX}, + {47, UART_1, AM_HAL_PIN_47_UART1RX}, + {NC, NC, 0}}; + +const PinMap PinMap_UART_RTS[] = { + {3, UART_0, AM_HAL_PIN_3_UART0RTS}, + {5, UART_0, AM_HAL_PIN_5_UART0RTS}, + {13, UART_0, AM_HAL_PIN_13_UART0RTS}, + {18, UART_0, AM_HAL_PIN_18_UART0RTS}, + {34, UART_0, AM_HAL_PIN_34_UART0RTS}, + {35, UART_0, AM_HAL_PIN_35_UART0RTS}, + {37, UART_0, AM_HAL_PIN_37_UART0RTS}, + {41, UART_0, AM_HAL_PIN_41_UART0RTS}, + {10, UART_1, AM_HAL_PIN_10_UART1RTS}, + {16, UART_1, AM_HAL_PIN_16_UART1RTS}, + {20, UART_1, AM_HAL_PIN_20_UART1RTS}, + {30, UART_1, AM_HAL_PIN_30_UART1RTS}, + {31, UART_1, AM_HAL_PIN_31_UART1RTS}, + {34, UART_1, AM_HAL_PIN_34_UART1RTS}, + {41, UART_1, AM_HAL_PIN_41_UART1RTS}, + {44, UART_1, AM_HAL_PIN_44_UART1RTS}, + {NC, NC, 0}}; + +const PinMap PinMap_UART_CTS[] = { + {4, UART_0, AM_HAL_PIN_4_UART0CTS}, + {6, UART_0, AM_HAL_PIN_6_UART0CTS}, + {12, UART_0, AM_HAL_PIN_12_UART0CTS}, + {24, UART_0, AM_HAL_PIN_24_UART0CTS}, + {29, UART_0, AM_HAL_PIN_29_UART0CTS}, + {33, UART_0, AM_HAL_PIN_33_UART0CTS}, + {26, UART_0, AM_HAL_PIN_36_UART0CTS}, + {38, UART_0, AM_HAL_PIN_38_UART0CTS}, + {11, UART_1, AM_HAL_PIN_11_UART1CTS}, + {17, UART_1, AM_HAL_PIN_17_UART1CTS}, + {21, UART_1, AM_HAL_PIN_21_UART1CTS}, + {26, UART_1, AM_HAL_PIN_26_UART1CTS}, + {29, UART_1, AM_HAL_PIN_29_UART1CTS}, + {32, UART_1, AM_HAL_PIN_32_UART1CTS}, + {36, UART_1, AM_HAL_PIN_36_UART1CTS}, + {45, UART_1, AM_HAL_PIN_45_UART1CTS}, + {NC, NC, 0}}; + +/************SPI***************/ +const PinMap PinMap_SPI_SCLK[] = { + {NC, NC, 0}}; + +const PinMap PinMap_SPI_MOSI[] = { + {NC, NC, 0}}; + +const PinMap PinMap_SPI_MISO[] = { + {NC, NC, 0}}; + +const PinMap PinMap_SPI_SSEL[] = { + {NC, NC, 0}}; + +/************PWM***************/ +const PinMap PinMap_PWM[] = { + {NC, NC, 0}}; diff --git a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/PeripheralNames.h b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/PeripheralNames.h new file mode 100644 index 00000000000..fc746cf0de6 --- /dev/null +++ b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/PeripheralNames.h @@ -0,0 +1,34 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBED_PERIPHERALNAMES_H +#define MBED_PERIPHERALNAMES_H + +#include "cmsis.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + UART_0 = 0, + UART_1, +} UARTName; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/PeripheralPins.h b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/PeripheralPins.h new file mode 100644 index 00000000000..dabf69f78b4 --- /dev/null +++ b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/PeripheralPins.h @@ -0,0 +1,73 @@ +/* + * mbed Microcontroller Library + * Copyright (c) 2017-2018 Future Electronics + * Copyright (c) 2018-2019 Cypress Semiconductor Corporation + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MBED_PERIPHERALPINS_H +#define MBED_PERIPHERALPINS_H + +#include "pinmap.h" +#include "PeripheralNames.h" + +//*** I2C *** +#if DEVICE_I2C +extern const PinMap PinMap_I2C_SDA[]; +extern const PinMap PinMap_I2C_SCL[]; +#endif + +//*** PWM *** +#if DEVICE_PWMOUT +extern const PinMap PinMap_PWM_OUT[]; +#endif + +//*** SERIAL *** +#if DEVICE_SERIAL +extern const PinMap PinMap_UART_TX[]; +extern const PinMap PinMap_UART_RX[]; +extern const PinMap PinMap_UART_RTS[]; +extern const PinMap PinMap_UART_CTS[]; +#endif + +//*** SPI *** +#if DEVICE_SPI +extern const PinMap PinMap_SPI_MOSI[]; +extern const PinMap PinMap_SPI_MISO[]; +extern const PinMap PinMap_SPI_SCLK[]; +extern const PinMap PinMap_SPI_SSEL[]; +#endif + +//*** ADC *** +#if DEVICE_ANALOGIN +extern const PinMap PinMap_ADC[]; +#endif + +//*** DAC *** +#if DEVICE_ANALOGOUT +extern const PinMap PinMap_DAC[]; +#endif + +//*** QSPI *** +#if DEVICE_QSPI +extern const PinMap PinMap_QSPI_SCLK[]; +extern const PinMap PinMap_QSPI_SSEL[]; +extern const PinMap PinMap_QSPI_DATA0[]; +extern const PinMap PinMap_QSPI_DATA1[]; +extern const PinMap PinMap_QSPI_DATA2[]; +extern const PinMap PinMap_QSPI_DATA3[]; +#endif + +#endif diff --git a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/objects_uart.h b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/objects_uart.h index 9c97b66204e..71241de4215 100644 --- a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/objects_uart.h +++ b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/objects_uart.h @@ -46,9 +46,10 @@ extern "C" struct serial_s { - ap3_uart_inst_t inst; // UART module instance - void *handle; // UART handle - am_hal_uart_config_t cfg; // UART configuration + ap3_uart_inst_t inst; // UART module instance + void *handle; // UART handle + am_hal_uart_config_t cfg; // UART configuration + volatile uint32_t tx_idle; // UART tx idle indication }; #ifdef __cplusplus diff --git a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/serial_api.c b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/serial_api.c new file mode 100644 index 00000000000..b79a76e20f7 --- /dev/null +++ b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/serial_api.c @@ -0,0 +1,529 @@ + +/** \addtogroup hal */ +/** @{*/ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if DEVICE_SERIAL + +#include "serial_api.h" + +#include "PeripheralPins.h" + +// interrupt variables +static uart_irq_handler irq_handler; +static uint32_t serial_irq_ids[AM_REG_UART_NUM_MODULES]; + +/** + * \defgroup hal_GeneralSerial Serial Configuration Functions + * + * # Defined behavior + * * ::serial_init initializes the ::serial_t + * * ::serial_init sets the default parameters for serial peripheral (9600 bps, 8N1 format) + * * ::serial_init configures the specified pins + * * ::serial_free releases the serial peripheral + * * ::serial_baud configures the baud rate + * * at least 9600 bps the baud rate must be supported + * * ::serial_format configures the transmission format (number of bits, parity and the number of stop bits) + * * at least 8N1 format must be supported + * * ::serial_irq_handler registers the interrupt handler which will be invoked when the interrupt fires. + * * ::serial_irq_set enables or disables the serial RX or TX IRQ. + * * If `RxIrq` is enabled by ::serial_irq_set, ::serial_irq_handler will be invoked whenever + * Receive Data Register Full IRQ is generated. + * * If `TxIrq` is enabled by ::serial_irq_set, ::serial_irq_handler will be invoked whenever + * Transmit Data Register Empty IRQ is generated. + * * If the interrupt condition holds true, when the interrupt is enabled with ::serial_irq_set, + * the ::serial_irq_handler is called instantly. + * * ::serial_getc returns the character from serial buffer. + * * ::serial_getc is a blocking call (waits for the character). + * * ::serial_putc sends a character. + * * ::serial_putc is a blocking call (waits for a peripheral to be available). + * * ::serial_readable returns non-zero value if a character can be read, 0 otherwise. + * * ::serial_writable returns non-zero value if a character can be written, 0 otherwise. + * * ::serial_clear clears the ::serial_t RX/TX buffers + * * ::serial_break_set sets the break signal. + * * ::serial_break_clear clears the break signal. + * * ::serial_pinout_tx configures the TX pin as an output (to be used in half-duplex mode). + * * ::serial_set_flow_control configures serial flow control. + * * ::serial_set_flow_control sets flow control in the hardware if a serial peripheral supports it, + * otherwise software emulation is used. + * * ::serial_tx_asynch starts the serial asynchronous transfer. + * * ::serial_tx_asynch writes `tx_length` bytes from the `tx` to the bus. + * * ::serial_tx_asynch must support 8 data bits + * * The callback given to ::serial_tx_asynch is invoked when the transfer completes. + * * ::serial_tx_asynch specifies the logical OR of events to be registered. + * * The ::serial_tx_asynch function may use the `DMAUsage` hint to select the appropriate async algorithm. + * * ::serial_rx_asynch starts the serial asynchronous transfer. + * * ::serial_rx_asynch reads `rx_length` bytes to the `rx` buffer. + * * ::serial_rx_asynch must support 8 data bits + * * The callback given to ::serial_rx_asynch is invoked when the transfer completes. + * * ::serial_rx_asynch specifies the logical OR of events to be registered. + * * The ::serial_rx_asynch function may use the `DMAUsage` hint to select the appropriate async algorithm. + * * ::serial_rx_asynch specifies a character in range 0-254 to be matched, 255 is a reserved value. + * * If SERIAL_EVENT_RX_CHARACTER_MATCH event is not registered, the `char_match` is ignored. + * * The SERIAL_EVENT_RX_CHARACTER_MATCH event is set in the callback when SERIAL_EVENT_RX_CHARACTER_MATCH event is + * registered AND `char_match` is present in the received data. + * * ::serial_tx_active returns non-zero if the TX transaction is ongoing, 0 otherwise. + * * ::serial_rx_active returns non-zero if the RX transaction is ongoing, 0 otherwise. + * * ::serial_irq_handler_asynch returns event flags if a transfer termination condition was met, otherwise returns 0. + * * ::serial_irq_handler_asynch takes no longer than one packet transfer time (packet_bits / baudrate) to execute. + * * ::serial_tx_abort_asynch aborts the ongoing TX transaction. + * * ::serial_tx_abort_asynch disables the enabled interupt for TX. + * * ::serial_tx_abort_asynch flushes the TX hardware buffer if TX FIFO is used. + * * ::serial_rx_abort_asynch aborts the ongoing RX transaction. + * * ::serial_rx_abort_asynch disables the enabled interupt for RX. + * * ::serial_rx_abort_asynch flushes the TX hardware buffer if RX FIFO is used. + * * Correct operation guaranteed when interrupt latency is shorter than one packet transfer time (packet_bits / baudrate) + * if the flow control is not used. + * * Correct operation guaranteed regardless of interrupt latency if the flow control is used. + * + * # Undefined behavior + * * Calling ::serial_init multiple times on the same `serial_t` without ::serial_free. + * * Passing invalid pin to ::serial_init, ::serial_pinout_tx. + * * Calling any function other than ::serial_init on am uninitialized or freed `serial_t`. + * * Passing an invalid pointer as `obj` to any function. + * * Passing an invalid pointer as `handler` to ::serial_irq_handler, ::serial_tx_asynch, ::serial_rx_asynch. + * * Calling ::serial_tx_abort while no async TX transfer is being processed. + * * Calling ::serial_rx_abort while no async RX transfer is being processed. + * * Devices behavior is undefined when the interrupt latency is longer than one packet transfer time + * (packet_bits / baudrate) if the flow control is not used. + * @{ + */ + +/** + * \defgroup hal_GeneralSerial_tests Serial hal tests + * The Serial HAL tests ensure driver conformance to defined behavior. + * + * To run the Serial hal tests use the command: + * + * mbed test -t -m -n tests-mbed_hal_fpga_ci_test_shield-uart + * + */ + +/** Initialize the serial peripheral. It sets the default parameters for serial + * peripheral, and configures its specifieds pins. + * + * @param obj The serial object + * @param tx The TX pin name + * @param rx The RX pin name + */ +void serial_init(serial_t *obj, PinName tx, PinName rx) +{ + // determine the UART to use + UARTName uart_tx = (UARTName)pinmap_peripheral(tx, PinMap_UART_TX); + UARTName uart_rx = (UARTName)pinmap_peripheral(rx, PinMap_UART_RX); + UARTName uart = (UARTName)pinmap_merge(uart_tx, uart_rx); + obj->serial.inst = (uint32_t)uart; + MBED_ASSERT((int)uart != NC); + + // associate buffers + // todo: decide which buffers to use + obj->serial.cfg.pui8RxBuffer = NULL; + obj->serial.cfg.pui8TxBuffer = NULL; + obj->serial.cfg.ui32RxBufferSize = 0; + obj->serial.cfg.ui32TxBufferSize = 0; + + // pinout the chosen uart + pinmap_pinout(tx, PinMap_UART_TX); + pinmap_pinout(rx, PinMap_UART_RX); + + // start UART instance + MBED_ASSERT(am_hal_uart_initialize(obj->serial.inst, &(obj->serial.handle)) == AM_HAL_STATUS_SUCCESS); + MBED_ASSERT(am_hal_uart_power_control(obj->serial.handle, AM_HAL_SYSCTRL_WAKE, false) == AM_HAL_STATUS_SUCCESS); + MBED_ASSERT(am_hal_uart_configure(obj->serial.handle, &(obj->serial.cfg)) == AM_HAL_STATUS_SUCCESS); + + // enable UART interrupts for this instance + NVIC_EnableIRQ((IRQn_Type)(UART0_IRQn + obj->serial.inst)); + am_hal_uart_interrupt_enable(obj->serial.handle, (AM_HAL_UART_INT_RX | AM_HAL_UART_INT_TX)); + + // service interrupts to determine idle state + am_hal_uart_interrupt_service(obj->serial.handle, 0, (uint32_t *)obj->serial.tx_idle); + + // set default baud rate and format + serial_baud(obj, 9600); + serial_format(obj, 8, ParityNone, 1); +} + +/** Release the serial peripheral, not currently invoked. It requires further + * resource management. + * + * @param obj The serial object + */ +void serial_free(serial_t *obj) +{ + // nothing to do unless resources are allocated for members of the serial_s serial member of obj + // assuming mbed handles obj and its members +} + +/** Configure the baud rate + * + * @param obj The serial object + * @param baudrate The baud rate to be configured + */ +void serial_baud(serial_t *obj, int baudrate) +{ + obj->serial.cfg.ui32BaudRate = (uint32_t)baudrate; + MBED_ASSERT(am_hal_uart_configure(obj->serial.handle, &(obj->serial.cfg)) == AM_HAL_STATUS_SUCCESS); +} + +/** Configure the format. Set the number of bits, parity and the number of stop bits + * + * @param obj The serial object + * @param data_bits The number of data bits + * @param parity The parity + * @param stop_bits The number of stop bits + */ +void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_bits) +{ + uint32_t am_hal_parity = AM_HAL_UART_PARITY_NONE; + switch (parity) + { + case ParityNone: + am_hal_parity = AM_HAL_UART_PARITY_NONE; + break; + case ParityOdd: + am_hal_parity = AM_HAL_UART_PARITY_ODD; + break; + case ParityEven: + am_hal_parity = AM_HAL_UART_PARITY_EVEN; + break; + default: // fall-through intentional after default + case ParityForced1: + case ParityForced0: + MBED_ASSERT(0); + break; + } + + obj->serial.cfg.ui32DataBits = (uint32_t)data_bits; + obj->serial.cfg.ui32Parity = (uint32_t)am_hal_parity; + obj->serial.cfg.ui32StopBits = (uint32_t)stop_bits; + MBED_ASSERT(am_hal_uart_configure(obj->serial.handle, &(obj->serial.cfg)) == AM_HAL_STATUS_SUCCESS); +} + +/** The serial interrupt handler registration + * + * @param obj The serial object + * @param handler The interrupt handler which will be invoked when the interrupt fires + * @param id The SerialBase object + */ +void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id) +{ + irq_handler = handler; + serial_irq_ids[obj->serial.inst] = id; + // todo: revisit with Kyle +} + +/** Configure serial interrupt. This function is used for word-approach + * + * @param obj The serial object + * @param irq The serial IRQ type (RX or TX) + * @param enable Set to non-zero to enable events, or zero to disable them + */ +void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable) +{ + // todo: revisit with Kyle +} + +/** Get character. This is a blocking call, waiting for a character + * + * @param obj The serial object + */ +int serial_getc(serial_t *obj) +{ + // todo: handle data_bits > 8 + uint8_t rx_c = 0x00; + uint32_t bytes_read = 0x00; + static am_hal_uart_transfer_t am_hal_uart_xfer_read_single = + { + .ui32Direction = AM_HAL_UART_READ, + .pui8Data = (uint8_t *)&rx_c, + .ui32NumBytes = 1, + .ui32TimeoutMs = 0, + .pui32BytesTransferred = &bytes_read, + }; + + do + { + am_hal_uart_transfer(obj->serial.handle, &am_hal_uart_xfer_read_single); + } while (bytes_read == 0); + + return (int)rx_c; +} + +/** Send a character. This is a blocking call, waiting for a peripheral to be available + * for writing + * + * @param obj The serial object + * @param c The character to be sent + */ +void serial_putc(serial_t *obj, int c) +{ + uint32_t bytes_sent = 0; + am_hal_uart_transfer_t am_hal_uart_xfer_write_single = + { + .ui32Direction = AM_HAL_UART_WRITE, + .pui8Data = (uint8_t *)(&c), + .ui32NumBytes = 1, + .ui32TimeoutMs = 0, + .pui32BytesTransferred = &bytes_sent, + }; + + do + { + while (!(obj->serial.tx_idle)) + { + }; // wait for tx to become idle + + am_hal_uart_transfer(_handle, &sUartWrite); + + } while (bytes_sent == 0); +} + +/** Check if the serial peripheral is readable + * + * @param obj The serial object + * @return Non-zero value if a character can be read, 0 if nothing to read + */ +int serial_readable(serial_t *obj) +{ + // todo: +} + +/** Check if the serial peripheral is writable + * + * @param obj The serial object + * @return Non-zero value if a character can be written, 0 otherwise. + */ +int serial_writable(serial_t *obj) +{ + // todo: +} + +/** Clear the serial peripheral + * + * @param obj The serial object + */ +void serial_clear(serial_t *obj) +{ + // todo: +} + +/** Set the break + * + * @param obj The serial object + */ +void serial_break_set(serial_t *obj) +{ + // todo: +} + +/** Clear the break + * + * @param obj The serial object + */ +void serial_break_clear(serial_t *obj) +{ + // todo: +} + +/** Configure the TX pin for UART function. + * + * @param tx The pin name used for TX + */ +void serial_pinout_tx(PinName tx) + +#if DEVICE_SERIAL_FC + /** Configure the serial for the flow control. It sets flow control in the hardware + * if a serial peripheral supports it, otherwise software emulation is used. + * + * @param obj The serial object + * @param type The type of the flow control. Look at the available FlowControl types. + * @param rxflow The TX pin name + * @param txflow The RX pin name + */ + void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, PinName txflow) +{ + // todo: +} + +/** Configure the serial for the flow control. It sets flow control in the hardware + * if a serial peripheral supports it, otherwise software emulation is used. + * + * @param obj The serial object + * @param type The type of the flow control. Look at the available FlowControl types. + * @param pinmap Pointer to structure which holds static pinmap + */ +void serial_set_flow_control_direct(serial_t *obj, FlowControl type, const serial_fc_pinmap_t *pinmap) +{ + // todo: +} +#endif + +/** Get the pins that support Serial TX + * + * Return a PinMap array of pins that support Serial TX. The + * array is terminated with {NC, NC, 0}. + * + * @return PinMap array + */ +const PinMap *serial_tx_pinmap(void) +{ + return PinMap_UART_TX; +} + +/** Get the pins that support Serial RX + * + * Return a PinMap array of pins that support Serial RX. The + * array is terminated with {NC, NC, 0}. + * + * @return PinMap array + */ +const PinMap *serial_rx_pinmap(void) +{ + return PinMap_UART_TX; +} + +#if DEVICE_SERIAL_FC +/** Get the pins that support Serial CTS + * + * Return a PinMap array of pins that support Serial CTS. The + * array is terminated with {NC, NC, 0}. + * + * @return PinMap array + */ +const PinMap *serial_cts_pinmap(void) +{ + return PinMap_UART_CTS; +} + +/** Get the pins that support Serial RTS + * + * Return a PinMap array of pins that support Serial RTS. The + * array is terminated with {NC, NC, 0}. + * + * @return PinMap array + */ +const PinMap *serial_rts_pinmap(void) +{ + return PinMap_UART_RTS; +} +#endif + +#if DEVICE_SERIAL_ASYNCH + +/**@}*/ + +/** + * \defgroup hal_AsynchSerial Asynchronous Serial Hardware Abstraction Layer + * @{ + */ + +/** Begin asynchronous TX transfer. The used buffer is specified in the serial object, + * tx_buff + * + * @param obj The serial object + * @param tx The transmit buffer + * @param tx_length The number of bytes to transmit + * @param tx_width Deprecated argument + * @param handler The serial handler + * @param event The logical OR of events to be registered + * @param hint A suggestion for how to use DMA with this transfer + * @return Returns number of data transfered, otherwise returns 0 + */ +int serial_tx_asynch(serial_t *obj, const void *tx, size_t tx_length, uint8_t tx_width, uint32_t handler, uint32_t event, DMAUsage hint) +{ + // todo: +} + +/** Begin asynchronous RX transfer (enable interrupt for data collecting) + * The used buffer is specified in the serial object - rx_buff + * + * @param obj The serial object + * @param rx The receive buffer + * @param rx_length The number of bytes to receive + * @param rx_width Deprecated argument + * @param handler The serial handler + * @param event The logical OR of events to be registered + * @param char_match A character in range 0-254 to be matched + * @param hint A suggestion for how to use DMA with this transfer + */ +void serial_rx_asynch(serial_t *obj, void *rx, size_t rx_length, uint8_t rx_width, uint32_t handler, uint32_t event, uint8_t char_match, DMAUsage hint) +{ + // todo: +} + +/** Attempts to determine if the serial peripheral is already in use for TX + * + * @param obj The serial object + * @return Non-zero if the RX transaction is ongoing, 0 otherwise + */ +uint8_t serial_tx_active(serial_t *obj) +{ + // todo: +} + +/** Attempts to determine if the serial peripheral is already in use for RX + * + * @param obj The serial object + * @return Non-zero if the RX transaction is ongoing, 0 otherwise + */ +uint8_t serial_rx_active(serial_t *obj) +{ + // todo: +} + +/** The asynchronous TX and RX handler. + * + * @param obj The serial object + * @return Returns event flags if an RX transfer termination condition was met; otherwise returns 0 + */ +int serial_irq_handler_asynch(serial_t *obj) +{ + // todo: +} + +/** Abort the ongoing TX transaction. It disables the enabled interupt for TX and + * flushes the TX hardware buffer if TX FIFO is used + * + * @param obj The serial object + */ +void serial_tx_abort_asynch(serial_t *obj) +{ + // todo: +} + +/** Abort the ongoing RX transaction. It disables the enabled interrupt for RX and + * flushes the RX hardware buffer if RX FIFO is used + * + * @param obj The serial object + */ +void serial_rx_abort_asynch(serial_t *obj) +{ + // todo: +} + +/**@}*/ + +#endif + +#ifdef __cplusplus +} +#endif + +#endif + +/** @}*/ From 2641b734259b7e4c2d35c7be45aeb26eca88f2d6 Mon Sep 17 00:00:00 2001 From: Kyle Wenner Date: Mon, 3 Feb 2020 12:44:18 -0700 Subject: [PATCH 7/9] basics of serial working for apollo3 mbed --- .../PinNames.h | 71 +++-- .../TARGET_AMA3B1KK/device/startup_gcc.c | 284 +++++++++--------- .../TARGET_Apollo3/device/PeripheralNames.h | 14 +- .../TARGET_Apollo3/device/objects_uart.h | 25 +- .../TARGET_Apollo3/device/pinmap.c | 66 ++++ .../TARGET_Apollo3/device/serial_api.c | 267 ++++++++++++---- 6 files changed, 485 insertions(+), 242 deletions(-) create mode 100644 targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/pinmap.c diff --git a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/TARGET_AMA3B1KK/TARGET_SparkFun_Artemis_Module/TARGET_SparkFun_RedBoard_Artemis_ATP/PinNames.h b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/TARGET_AMA3B1KK/TARGET_SparkFun_Artemis_Module/TARGET_SparkFun_RedBoard_Artemis_ATP/PinNames.h index e1efed3261a..a7a7364e079 100644 --- a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/TARGET_AMA3B1KK/TARGET_SparkFun_Artemis_Module/TARGET_SparkFun_RedBoard_Artemis_ATP/PinNames.h +++ b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/TARGET_AMA3B1KK/TARGET_SparkFun_Artemis_Module/TARGET_SparkFun_RedBoard_Artemis_ATP/PinNames.h @@ -25,41 +25,46 @@ SOFTWARE. #include "device.h" #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif -#define NC_VAL (int)0xFFFFFFFF - -typedef enum { - // Digital naming - D16 = 16, - D31 = 31, - D45 = 45, - D44 = 44, - - // Analog naming - A16 = D16, - A31 = D31, - - // LEDs - LED_BLUE = AM_BSP_GPIO_LED_BLUE, - - // mbed original LED naming - LED1 = AM_BSP_GPIO_LED0, - - // Qwiic - QWIIC_SCL = 39, - QWIIC_SDA = 40, - - // UART - SERIAL_TX = 48, - SERIAL_RX = 49, - USBTX = SERIAL_TX, - USBRX = SERIAL_RX, - - // Not connected - NC = NC_VAL -} PinName; +#define NC_VAL (uint32_t)0xFFFFFFFF + + typedef enum + { + // Digital naming + D16 = 16, + D31 = 31, + D45 = 45, + D44 = 44, + + // Analog naming + A16 = D16, + A31 = D31, + + // LEDs + LED_BLUE = AM_BSP_GPIO_LED_BLUE, + + // mbed original LED naming + LED1 = AM_BSP_GPIO_LED0, + + // Qwiic + QWIIC_SCL = 39, + QWIIC_SDA = 40, + + // UART + SERIAL_TX = 48, + SERIAL_RX = 49, + USBTX = SERIAL_TX, + USBRX = SERIAL_RX, + + // Not connected + NC = NC_VAL + } PinName; + +#define STDIO_UART_TX USBTX +#define STDIO_UART_RX USBRX #ifdef __cplusplus } diff --git a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/TARGET_AMA3B1KK/device/startup_gcc.c b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/TARGET_AMA3B1KK/device/startup_gcc.c index 2d5f8c29ac1..0e7ae34e427 100644 --- a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/TARGET_AMA3B1KK/device/startup_gcc.c +++ b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/TARGET_AMA3B1KK/device/startup_gcc.c @@ -10,24 +10,24 @@ // // Copyright (c) 2019, Ambiq Micro // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: -// +// // 1. Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. -// +// // 2. 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. -// +// // 3. Neither the name of the copyright holder nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. -// +// // Third party software included in this distribution is subject to the // additional license terms as defined in the /docs/licenses directory. -// +// // 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 @@ -52,52 +52,52 @@ // Forward declaration of interrupt handlers. // //***************************************************************************** -extern void Reset_Handler(void) __attribute ((naked)); -extern void NMI_Handler(void) __attribute ((weak)); -extern void HardFault_Handler(void) __attribute ((weak)); -extern void MemManage_Handler(void) __attribute ((weak, alias ("HardFault_Handler"))); -extern void BusFault_Handler(void) __attribute ((weak, alias ("HardFault_Handler"))); -extern void UsageFault_Handler(void) __attribute ((weak, alias ("HardFault_Handler"))); -extern void SecureFault_Handler(void) __attribute ((weak)); -extern void SVC_Handler(void) __attribute ((weak, alias ("am_default_isr"))); -extern void DebugMon_Handler(void) __attribute ((weak, alias ("am_default_isr"))); -extern void PendSV_Handler(void) __attribute ((weak, alias ("am_default_isr"))); -extern void SysTick_Handler(void) __attribute ((weak, alias ("am_default_isr"))); +extern void Reset_Handler(void) __attribute((naked)); +extern void NMI_Handler(void) __attribute((weak)); +extern void HardFault_Handler(void) __attribute((weak)); +extern void MemManage_Handler(void) __attribute((weak, alias("HardFault_Handler"))); +extern void BusFault_Handler(void) __attribute((weak, alias("HardFault_Handler"))); +extern void UsageFault_Handler(void) __attribute((weak, alias("HardFault_Handler"))); +extern void SecureFault_Handler(void) __attribute((weak)); +extern void SVC_Handler(void) __attribute((weak, alias("am_default_isr"))); +extern void DebugMon_Handler(void) __attribute((weak, alias("am_default_isr"))); +extern void PendSV_Handler(void) __attribute((weak, alias("am_default_isr"))); +extern void SysTick_Handler(void) __attribute((weak, alias("am_default_isr"))); -extern void am_brownout_isr(void) __attribute ((weak, alias ("am_default_isr"))); -extern void am_watchdog_isr(void) __attribute ((weak, alias ("am_default_isr"))); -extern void am_rtc_isr(void) __attribute ((weak, alias ("am_default_isr"))); -extern void am_vcomp_isr(void) __attribute ((weak, alias ("am_default_isr"))); -extern void am_ioslave_ios_isr(void) __attribute ((weak, alias ("am_default_isr"))); -extern void am_ioslave_acc_isr(void) __attribute ((weak, alias ("am_default_isr"))); -extern void am_iomaster0_isr(void) __attribute ((weak, alias ("am_default_isr"))); -extern void am_iomaster1_isr(void) __attribute ((weak, alias ("am_default_isr"))); -extern void am_iomaster2_isr(void) __attribute ((weak, alias ("am_default_isr"))); -extern void am_iomaster3_isr(void) __attribute ((weak, alias ("am_default_isr"))); -extern void am_iomaster4_isr(void) __attribute ((weak, alias ("am_default_isr"))); -extern void am_iomaster5_isr(void) __attribute ((weak, alias ("am_default_isr"))); -extern void am_ble_isr(void) __attribute ((weak, alias ("am_default_isr"))); -extern void am_gpio_isr(void) __attribute ((weak, alias ("am_default_isr"))); -extern void am_ctimer_isr(void) __attribute ((weak, alias ("am_default_isr"))); -extern void am_uart_isr(void) __attribute ((weak, alias ("am_default_isr"))); -extern void am_uart1_isr(void) __attribute ((weak, alias ("am_default_isr"))); -extern void am_scard_isr(void) __attribute ((weak, alias ("am_default_isr"))); -extern void am_adc_isr(void) __attribute ((weak, alias ("am_default_isr"))); -extern void am_pdm0_isr(void) __attribute ((weak, alias ("am_default_isr"))); -extern void am_mspi0_isr(void) __attribute ((weak, alias ("am_default_isr"))); -extern void am_software0_isr(void) __attribute ((weak, alias ("am_default_isr"))); -extern void am_stimer_isr(void) __attribute ((weak, alias ("am_default_isr"))); -extern void am_stimer_cmpr0_isr(void) __attribute ((weak, alias ("am_default_isr"))); -extern void am_stimer_cmpr1_isr(void) __attribute ((weak, alias ("am_default_isr"))); -extern void am_stimer_cmpr2_isr(void) __attribute ((weak, alias ("am_default_isr"))); -extern void am_stimer_cmpr3_isr(void) __attribute ((weak, alias ("am_default_isr"))); -extern void am_stimer_cmpr4_isr(void) __attribute ((weak, alias ("am_default_isr"))); -extern void am_stimer_cmpr5_isr(void) __attribute ((weak, alias ("am_default_isr"))); -extern void am_stimer_cmpr6_isr(void) __attribute ((weak, alias ("am_default_isr"))); -extern void am_stimer_cmpr7_isr(void) __attribute ((weak, alias ("am_default_isr"))); -extern void am_clkgen_isr(void) __attribute ((weak, alias ("am_default_isr"))); +extern void am_brownout_isr(void) __attribute((weak, alias("am_default_isr"))); +extern void am_watchdog_isr(void) __attribute((weak, alias("am_default_isr"))); +extern void am_rtc_isr(void) __attribute((weak, alias("am_default_isr"))); +extern void am_vcomp_isr(void) __attribute((weak, alias("am_default_isr"))); +extern void am_ioslave_ios_isr(void) __attribute((weak, alias("am_default_isr"))); +extern void am_ioslave_acc_isr(void) __attribute((weak, alias("am_default_isr"))); +extern void am_iomaster0_isr(void) __attribute((weak, alias("am_default_isr"))); +extern void am_iomaster1_isr(void) __attribute((weak, alias("am_default_isr"))); +extern void am_iomaster2_isr(void) __attribute((weak, alias("am_default_isr"))); +extern void am_iomaster3_isr(void) __attribute((weak, alias("am_default_isr"))); +extern void am_iomaster4_isr(void) __attribute((weak, alias("am_default_isr"))); +extern void am_iomaster5_isr(void) __attribute((weak, alias("am_default_isr"))); +extern void am_ble_isr(void) __attribute((weak, alias("am_default_isr"))); +extern void am_gpio_isr(void) __attribute((weak, alias("am_default_isr"))); +extern void am_ctimer_isr(void) __attribute((weak, alias("am_default_isr"))); +extern void am_uart_isr(void) __attribute((weak, alias("am_default_isr"))); +extern void am_uart1_isr(void) __attribute((weak, alias("am_default_isr"))); +extern void am_scard_isr(void) __attribute((weak, alias("am_default_isr"))); +extern void am_adc_isr(void) __attribute((weak, alias("am_default_isr"))); +extern void am_pdm0_isr(void) __attribute((weak, alias("am_default_isr"))); +extern void am_mspi0_isr(void) __attribute((weak, alias("am_default_isr"))); +extern void am_software0_isr(void) __attribute((weak, alias("am_default_isr"))); +extern void am_stimer_isr(void) __attribute((weak, alias("am_default_isr"))); +extern void am_stimer_cmpr0_isr(void) __attribute((weak, alias("am_default_isr"))); +extern void am_stimer_cmpr1_isr(void) __attribute((weak, alias("am_default_isr"))); +extern void am_stimer_cmpr2_isr(void) __attribute((weak, alias("am_default_isr"))); +extern void am_stimer_cmpr3_isr(void) __attribute((weak, alias("am_default_isr"))); +extern void am_stimer_cmpr4_isr(void) __attribute((weak, alias("am_default_isr"))); +extern void am_stimer_cmpr5_isr(void) __attribute((weak, alias("am_default_isr"))); +extern void am_stimer_cmpr6_isr(void) __attribute((weak, alias("am_default_isr"))); +extern void am_stimer_cmpr7_isr(void) __attribute((weak, alias("am_default_isr"))); +extern void am_clkgen_isr(void) __attribute((weak, alias("am_default_isr"))); -extern void am_default_isr(void) __attribute ((weak)); +extern void am_default_isr(void) __attribute((weak)); // // Entry Point for mbed boot sequence // extern void __main(void); @@ -111,9 +111,9 @@ extern void mbed_init(void); //***************************************************************************** extern int main(void); -// '__stack' accesses the linker-provided address for the start of the stack +// '__stack' accesses the linker-provided address for the start of the stack // (which is a high address - stack goes top to bottom) -extern void* __stack; +extern void *__stack; //***************************************************************************** // @@ -125,61 +125,60 @@ extern void* __stack; // Therefore, we'll explicitly use am_fault_isr in the table for those vectors. // //***************************************************************************** -__attribute__ ((section(".isr_vector"))) -void (* const g_am_pfnVectors[])(void) = -{ - (void (*)(void))(&__stack), // The initial stack pointer (provided by linker script) - Reset_Handler, // The reset handler - NMI_Handler, // The NMI handler - HardFault_Handler, // The hard fault handler - MemManage_Handler, // The MemManage_Handler - BusFault_Handler, // The BusFault_Handler - UsageFault_Handler, // The UsageFault_Handler - SecureFault_Handler, // The SecureFault_Handler - 0, // Reserved - 0, // Reserved - 0, // Reserved - SVC_Handler, // SVCall handler - DebugMon_Handler, // Debug monitor handler - 0, // Reserved - PendSV_Handler, // The PendSV handler - SysTick_Handler, // The SysTick handler +__attribute__((section(".isr_vector"))) void (*const g_am_pfnVectors[])(void) = + { + (void (*)(void))(&__stack), // The initial stack pointer (provided by linker script) + Reset_Handler, // The reset handler + NMI_Handler, // The NMI handler + HardFault_Handler, // The hard fault handler + MemManage_Handler, // The MemManage_Handler + BusFault_Handler, // The BusFault_Handler + UsageFault_Handler, // The UsageFault_Handler + SecureFault_Handler, // The SecureFault_Handler + 0, // Reserved + 0, // Reserved + 0, // Reserved + SVC_Handler, // SVCall handler + DebugMon_Handler, // Debug monitor handler + 0, // Reserved + PendSV_Handler, // The PendSV handler + SysTick_Handler, // The SysTick handler - // - // Peripheral Interrupts - // - am_brownout_isr, // 0: Brownout (rstgen) - am_watchdog_isr, // 1: Watchdog - am_rtc_isr, // 2: RTC - am_vcomp_isr, // 3: Voltage Comparator - am_ioslave_ios_isr, // 4: I/O Slave general - am_ioslave_acc_isr, // 5: I/O Slave access - am_iomaster0_isr, // 6: I/O Master 0 - am_iomaster1_isr, // 7: I/O Master 1 - am_iomaster2_isr, // 8: I/O Master 2 - am_iomaster3_isr, // 9: I/O Master 3 - am_iomaster4_isr, // 10: I/O Master 4 - am_iomaster5_isr, // 11: I/O Master 5 - am_ble_isr, // 12: BLEIF - am_gpio_isr, // 13: GPIO - am_ctimer_isr, // 14: CTIMER - am_uart_isr, // 15: UART0 - am_uart1_isr, // 16: UART1 - am_scard_isr, // 17: SCARD - am_adc_isr, // 18: ADC - am_pdm0_isr, // 19: PDM - am_mspi0_isr, // 20: MSPI0 - am_software0_isr, // 21: SOFTWARE0 - am_stimer_isr, // 22: SYSTEM TIMER - am_stimer_cmpr0_isr, // 23: SYSTEM TIMER COMPARE0 - am_stimer_cmpr1_isr, // 24: SYSTEM TIMER COMPARE1 - am_stimer_cmpr2_isr, // 25: SYSTEM TIMER COMPARE2 - am_stimer_cmpr3_isr, // 26: SYSTEM TIMER COMPARE3 - am_stimer_cmpr4_isr, // 27: SYSTEM TIMER COMPARE4 - am_stimer_cmpr5_isr, // 28: SYSTEM TIMER COMPARE5 - am_stimer_cmpr6_isr, // 29: SYSTEM TIMER COMPARE6 - am_stimer_cmpr7_isr, // 30: SYSTEM TIMER COMPARE7 - am_clkgen_isr, // 31: CLKGEN + // + // Peripheral Interrupts + // + am_brownout_isr, // 0: Brownout (rstgen) + am_watchdog_isr, // 1: Watchdog + am_rtc_isr, // 2: RTC + am_vcomp_isr, // 3: Voltage Comparator + am_ioslave_ios_isr, // 4: I/O Slave general + am_ioslave_acc_isr, // 5: I/O Slave access + am_iomaster0_isr, // 6: I/O Master 0 + am_iomaster1_isr, // 7: I/O Master 1 + am_iomaster2_isr, // 8: I/O Master 2 + am_iomaster3_isr, // 9: I/O Master 3 + am_iomaster4_isr, // 10: I/O Master 4 + am_iomaster5_isr, // 11: I/O Master 5 + am_ble_isr, // 12: BLEIF + am_gpio_isr, // 13: GPIO + am_ctimer_isr, // 14: CTIMER + am_uart_isr, // 15: UART0 + am_uart1_isr, // 16: UART1 + am_scard_isr, // 17: SCARD + am_adc_isr, // 18: ADC + am_pdm0_isr, // 19: PDM + am_mspi0_isr, // 20: MSPI0 + am_software0_isr, // 21: SOFTWARE0 + am_stimer_isr, // 22: SYSTEM TIMER + am_stimer_cmpr0_isr, // 23: SYSTEM TIMER COMPARE0 + am_stimer_cmpr1_isr, // 24: SYSTEM TIMER COMPARE1 + am_stimer_cmpr2_isr, // 25: SYSTEM TIMER COMPARE2 + am_stimer_cmpr3_isr, // 26: SYSTEM TIMER COMPARE3 + am_stimer_cmpr4_isr, // 27: SYSTEM TIMER COMPARE4 + am_stimer_cmpr5_isr, // 28: SYSTEM TIMER COMPARE5 + am_stimer_cmpr6_isr, // 29: SYSTEM TIMER COMPARE6 + am_stimer_cmpr7_isr, // 30: SYSTEM TIMER COMPARE7 + am_clkgen_isr, // 31: CLKGEN }; //****************************************************************************** @@ -195,25 +194,25 @@ void (* const g_am_pfnVectors[])(void) = // (16 core + 48 periph) such that code begins at offset 0x100. // //****************************************************************************** -__attribute__ ((section(".ble_patch"))) +__attribute__((section(".ble_patch"))) uint32_t const __Patchable[] = -{ - 0, // 32 - 0, // 33 - 0, // 34 - 0, // 35 - 0, // 36 - 0, // 37 - 0, // 38 - 0, // 39 - 0, // 40 - 0, // 41 - 0, // 42 - 0, // 43 - 0, // 44 - 0, // 45 - 0, // 46 - 0, // 47 + { + 0, // 32 + 0, // 33 + 0, // 34 + 0, // 35 + 0, // 36 + 0, // 37 + 0, // 38 + 0, // 39 + 0, // 40 + 0, // 41 + 0, // 42 + 0, // 43 + 0, // 44 + 0, // 45 + 0, // 46 + 0, // 47 }; // //***************************************************************************** @@ -237,8 +236,7 @@ uint32_t const __Patchable[] = // //***************************************************************************** #if defined(__GNUC_STDC_INLINE__) -void -Reset_Handler(void) +void Reset_Handler(void) { // // Set the vector table pointer. @@ -247,15 +245,15 @@ Reset_Handler(void) " ldr r1, =g_am_pfnVectors\n" " str r1, [r0]"); -// // -// // Set the stack pointer. -// // + // // + // // Set the stack pointer. + // // __asm(" ldr sp, [r1]"); #ifndef NOFPU -// // -// // Enable the FPU. -// // + // // + // // Enable the FPU. + // // __asm("ldr r0, =0xE000ED88\n" "ldr r1,[r0]\n" "orr r1,#(0xF << 20)\n" @@ -268,7 +266,6 @@ Reset_Handler(void) // SystemInit(); // _start(); - // // Copy the data segment initializers from flash to SRAM. // @@ -282,12 +279,12 @@ Reset_Handler(void) " str r3, [r1], #4\n" " b copy_loop\n" "copy_end:\n"); - + // // // // Zero fill the bss segment. // // - __asm( "LDR R0, =_start\n" - "BX R0\n"); + __asm("LDR R0, =_start\n" + "BX R0\n"); // // If main returns then execute a break point instruction // @@ -304,13 +301,12 @@ Reset_Handler(void) // by a debugger. // //***************************************************************************** -void -NMI_Handler(void) +void NMI_Handler(void) { // // Go into an infinite loop. // - while(1) + while (1) { } } @@ -322,13 +318,12 @@ NMI_Handler(void) // for examination by a debugger. // //***************************************************************************** -void -HardFault_Handler(void) +void HardFault_Handler(void) { // // Go into an infinite loop. // - while(1) + while (1) { } } @@ -340,13 +335,12 @@ HardFault_Handler(void) // for examination by a debugger. // //***************************************************************************** -void -am_default_isr(void) +void am_default_isr(void) { // // Go into an infinite loop. // - while(1) + while (1) { } } diff --git a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/PeripheralNames.h b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/PeripheralNames.h index fc746cf0de6..dde40670d5a 100644 --- a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/PeripheralNames.h +++ b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/PeripheralNames.h @@ -19,13 +19,17 @@ #include "cmsis.h" #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif -typedef enum { - UART_0 = 0, - UART_1, -} UARTName; +#define STDIO_UART UART_0 + + typedef enum + { + UART_0 = 0, + UART_1, + } UARTName; #ifdef __cplusplus } diff --git a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/objects_uart.h b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/objects_uart.h index 71241de4215..dbb69c082fd 100644 --- a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/objects_uart.h +++ b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/objects_uart.h @@ -44,13 +44,30 @@ extern "C" uint8_t funcsel; } ap3_uart_pad_map_elem_t; + typedef struct _ap3_uart_control_t + { + ap3_uart_inst_t inst; // UART module instance + void *handle; // UART handle + am_hal_uart_config_t cfg; // UART configuration + uint32_t serial_irq_id; // + } ap3_uart_control_t; + +#if DEVICE_SERIAL_ASYNCH struct serial_s { - ap3_uart_inst_t inst; // UART module instance - void *handle; // UART handle - am_hal_uart_config_t cfg; // UART configuration - volatile uint32_t tx_idle; // UART tx idle indication + ap3_uart_control_t *uart_control; }; +#else +struct serial_u +{ + ap3_uart_control_t *uart_control; +}; + +struct serial_s +{ + struct serial_u serial; +}; +#endif // DEVICE_SERIAL_ASYNCH #ifdef __cplusplus } diff --git a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/pinmap.c b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/pinmap.c new file mode 100644 index 00000000000..d25d440b595 --- /dev/null +++ b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/pinmap.c @@ -0,0 +1,66 @@ +#include "mbed_assert.h" +#include "pinmap.h" +#include "mbed_error.h" + +#include "am_mcu_apollo.h" + +void pin_function(PinName pin, int function) +{ + // am_hal_gpio_pincfg_t cfg = {0}; + // cfg.uFuncSel = function; + // am_hal_gpio_pinconfig((uint32_t)(pin), cfg); // apply configuration + +#define PADREG_FLD_FNSEL_S 3 + + uint32_t ui32Padreg; + uint32_t ui32Funcsel; + + MBED_ASSERT(pin < AM_HAL_GPIO_MAX_PADS); + + // + // Initialize the PADREG accumulator variables. + // + ui32Padreg = 0; + + // Get the requested function + ui32Funcsel = (uint32_t)function; + + ui32Padreg |= ui32Funcsel << PADREG_FLD_FNSEL_S; + + // + // At this point, the configuration variable ui32Padreg, + // values is set (at bit position 0) and ready to write + // to its respective register bitfields. + // + uint32_t ui32PadregAddr; + uint32_t ui32PadClearMask; + uint32_t ui32PadShft; + + ui32PadregAddr = AM_REGADDR(GPIO, PADREGA) + (pin & ~0x3); + + ui32PadShft = ((pin & 0x3) << 3); + ui32PadClearMask = ~((uint32_t)0x38 << ui32PadShft); + + // Get the new values into their rightful bit positions. + ui32Padreg <<= ui32PadShft; + + AM_CRITICAL_BEGIN + + GPIO->PADKEY = GPIO_PADKEY_PADKEY_Key; + + AM_REGVAL(ui32PadregAddr) = (AM_REGVAL(ui32PadregAddr) & ui32PadClearMask) | ui32Padreg; + + GPIO->PADKEY = 0; + + AM_CRITICAL_END +} + +void pin_mode(PinName pin, PinMode mode) +{ + MBED_ASSERT(0); + // gpio_t obj = { + // .pad = (ap3_gpio_pad_t)pin, + // .cfg = {0}, + // }; + // gpio_mode(gpio_t * obj, PinMode mode) +} diff --git a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/serial_api.c b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/serial_api.c index b79a76e20f7..092b1e9beaa 100644 --- a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/serial_api.c +++ b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/serial_api.c @@ -22,11 +22,22 @@ #include "serial_api.h" +#include "mbed_assert.h" #include "PeripheralPins.h" +// globals? +int stdio_uart_inited = 0; +serial_t stdio_uart; +bool value = false; + // interrupt variables static uart_irq_handler irq_handler; -static uint32_t serial_irq_ids[AM_REG_UART_NUM_MODULES]; +static ap3_uart_control_t ap3_uart_control[AM_REG_UART_NUM_MODULES]; + +// forward declarations +extern void am_uart_isr(void); +extern void am_uart1_isr(void); +void uart_configure_pin_function(PinName pin, UARTName uart, const PinMap *map); /** * \defgroup hal_GeneralSerial Serial Configuration Functions @@ -124,34 +135,31 @@ static uint32_t serial_irq_ids[AM_REG_UART_NUM_MODULES]; void serial_init(serial_t *obj, PinName tx, PinName rx) { // determine the UART to use - UARTName uart_tx = (UARTName)pinmap_peripheral(tx, PinMap_UART_TX); - UARTName uart_rx = (UARTName)pinmap_peripheral(rx, PinMap_UART_RX); + UARTName uart_tx = (UARTName)pinmap_peripheral(tx, serial_tx_pinmap()); + UARTName uart_rx = (UARTName)pinmap_peripheral(rx, serial_rx_pinmap()); UARTName uart = (UARTName)pinmap_merge(uart_tx, uart_rx); - obj->serial.inst = (uint32_t)uart; - MBED_ASSERT((int)uart != NC); - - // associate buffers - // todo: decide which buffers to use - obj->serial.cfg.pui8RxBuffer = NULL; - obj->serial.cfg.pui8TxBuffer = NULL; - obj->serial.cfg.ui32RxBufferSize = 0; - obj->serial.cfg.ui32TxBufferSize = 0; + MBED_ASSERT((uint32_t)uart != NC); + obj->serial.uart_control = &ap3_uart_control[uart]; + obj->serial.uart_control->inst = uart; - // pinout the chosen uart - pinmap_pinout(tx, PinMap_UART_TX); - pinmap_pinout(rx, PinMap_UART_RX); + // ensure that HAL queueing is disabled (we want to use the FIFOs directly) + obj->serial.uart_control->cfg.pui8RxBuffer = NULL; + obj->serial.uart_control->cfg.pui8TxBuffer = NULL; + obj->serial.uart_control->cfg.ui32RxBufferSize = 0; + obj->serial.uart_control->cfg.ui32TxBufferSize = 0; - // start UART instance - MBED_ASSERT(am_hal_uart_initialize(obj->serial.inst, &(obj->serial.handle)) == AM_HAL_STATUS_SUCCESS); - MBED_ASSERT(am_hal_uart_power_control(obj->serial.handle, AM_HAL_SYSCTRL_WAKE, false) == AM_HAL_STATUS_SUCCESS); - MBED_ASSERT(am_hal_uart_configure(obj->serial.handle, &(obj->serial.cfg)) == AM_HAL_STATUS_SUCCESS); + // memset(obj->serial.uart_control->cfg, 0x00, sizeof(am_hal_uart_config_t)); // ensure config begins zeroed - // enable UART interrupts for this instance - NVIC_EnableIRQ((IRQn_Type)(UART0_IRQn + obj->serial.inst)); - am_hal_uart_interrupt_enable(obj->serial.handle, (AM_HAL_UART_INT_RX | AM_HAL_UART_INT_TX)); + // // pinout the chosen uart // todo: better???? + // pinmap_pinout(tx, serial_tx_pinmap()); + // pinmap_pinout(rx, serial_rx_pinmap()); + uart_configure_pin_function(tx, uart, serial_tx_pinmap()); + uart_configure_pin_function(rx, uart, serial_rx_pinmap()); - // service interrupts to determine idle state - am_hal_uart_interrupt_service(obj->serial.handle, 0, (uint32_t *)obj->serial.tx_idle); + // start UART instance + MBED_ASSERT(am_hal_uart_initialize(uart, &(obj->serial.uart_control->handle)) == AM_HAL_STATUS_SUCCESS); + MBED_ASSERT(am_hal_uart_power_control(obj->serial.uart_control->handle, AM_HAL_SYSCTRL_WAKE, false) == AM_HAL_STATUS_SUCCESS); + MBED_ASSERT(am_hal_uart_configure(obj->serial.uart_control->handle, &(obj->serial.uart_control->cfg)) == AM_HAL_STATUS_SUCCESS); // set default baud rate and format serial_baud(obj, 9600); @@ -176,8 +184,8 @@ void serial_free(serial_t *obj) */ void serial_baud(serial_t *obj, int baudrate) { - obj->serial.cfg.ui32BaudRate = (uint32_t)baudrate; - MBED_ASSERT(am_hal_uart_configure(obj->serial.handle, &(obj->serial.cfg)) == AM_HAL_STATUS_SUCCESS); + obj->serial.uart_control->cfg.ui32BaudRate = (uint32_t)baudrate; + MBED_ASSERT(am_hal_uart_configure(obj->serial.uart_control->handle, &(obj->serial.uart_control->cfg)) == AM_HAL_STATUS_SUCCESS); } /** Configure the format. Set the number of bits, parity and the number of stop bits @@ -189,6 +197,26 @@ void serial_baud(serial_t *obj, int baudrate) */ void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_bits) { + uint32_t am_hal_data_bits = 0; + switch (data_bits) + { + case 5: + am_hal_data_bits = AM_HAL_UART_DATA_BITS_5; + break; + case 6: + am_hal_data_bits = AM_HAL_UART_DATA_BITS_6; + break; + case 7: + am_hal_data_bits = AM_HAL_UART_DATA_BITS_7; + break; + case 8: + am_hal_data_bits = AM_HAL_UART_DATA_BITS_8; + break; + default: + MBED_ASSERT(0); + break; + } + uint32_t am_hal_parity = AM_HAL_UART_PARITY_NONE; switch (parity) { @@ -208,10 +236,23 @@ void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_b break; } - obj->serial.cfg.ui32DataBits = (uint32_t)data_bits; - obj->serial.cfg.ui32Parity = (uint32_t)am_hal_parity; - obj->serial.cfg.ui32StopBits = (uint32_t)stop_bits; - MBED_ASSERT(am_hal_uart_configure(obj->serial.handle, &(obj->serial.cfg)) == AM_HAL_STATUS_SUCCESS); + uint32_t am_hal_stop_bits = 0; + switch (stop_bits) + { + case 1: + am_hal_stop_bits = AM_HAL_UART_ONE_STOP_BIT; + break; + case 2: + am_hal_stop_bits = AM_HAL_UART_TWO_STOP_BITS; + break; + default: + MBED_ASSERT(0); + } + + obj->serial.uart_control->cfg.ui32DataBits = (uint32_t)am_hal_data_bits; + obj->serial.uart_control->cfg.ui32Parity = (uint32_t)am_hal_parity; + obj->serial.uart_control->cfg.ui32StopBits = (uint32_t)am_hal_stop_bits; + MBED_ASSERT(am_hal_uart_configure(obj->serial.uart_control->handle, &(obj->serial.uart_control->cfg)) == AM_HAL_STATUS_SUCCESS); } /** The serial interrupt handler registration @@ -223,7 +264,7 @@ void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_b void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id) { irq_handler = handler; - serial_irq_ids[obj->serial.inst] = id; + obj->serial.uart_control->serial_irq_id = id; // todo: revisit with Kyle } @@ -235,7 +276,21 @@ void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id) */ void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable) { - // todo: revisit with Kyle + MBED_ASSERT(obj->serial.uart_control != NULL); + + am_hal_uart_interrupt_enable(obj->serial.uart_control->handle, (AM_HAL_UART_INT_RX | AM_HAL_UART_INT_TX | AM_HAL_UART_INT_TXCMP)); + + switch (obj->serial.uart_control->inst) + { + case 0: + NVIC_SetVector((IRQn_Type)UART0_IRQn, (uint32_t)am_uart_isr); + break; + case 1: + NVIC_SetVector((IRQn_Type)UART1_IRQn, (uint32_t)am_uart1_isr); + break; + } + + NVIC_EnableIRQ((IRQn_Type)(UART0_IRQn + obj->serial.uart_control->inst)); } /** Get character. This is a blocking call, waiting for a character @@ -244,21 +299,22 @@ void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable) */ int serial_getc(serial_t *obj) { - // todo: handle data_bits > 8 + MBED_ASSERT(obj->serial.uart_control != NULL); + uint8_t rx_c = 0x00; - uint32_t bytes_read = 0x00; - static am_hal_uart_transfer_t am_hal_uart_xfer_read_single = + volatile uint32_t bytes_read = 0x00; + am_hal_uart_transfer_t am_hal_uart_xfer_read_single = { .ui32Direction = AM_HAL_UART_READ, .pui8Data = (uint8_t *)&rx_c, .ui32NumBytes = 1, .ui32TimeoutMs = 0, - .pui32BytesTransferred = &bytes_read, + .pui32BytesTransferred = (uint32_t *)&bytes_read, }; do { - am_hal_uart_transfer(obj->serial.handle, &am_hal_uart_xfer_read_single); + am_hal_uart_transfer(obj->serial.uart_control->handle, &am_hal_uart_xfer_read_single); } while (bytes_read == 0); return (int)rx_c; @@ -272,24 +328,21 @@ int serial_getc(serial_t *obj) */ void serial_putc(serial_t *obj, int c) { - uint32_t bytes_sent = 0; + MBED_ASSERT(obj->serial.uart_control != NULL); + + volatile uint32_t bytes_sent = 0; am_hal_uart_transfer_t am_hal_uart_xfer_write_single = { .ui32Direction = AM_HAL_UART_WRITE, .pui8Data = (uint8_t *)(&c), .ui32NumBytes = 1, .ui32TimeoutMs = 0, - .pui32BytesTransferred = &bytes_sent, + .pui32BytesTransferred = (uint32_t *)&bytes_sent, }; do { - while (!(obj->serial.tx_idle)) - { - }; // wait for tx to become idle - - am_hal_uart_transfer(_handle, &sUartWrite); - + am_hal_uart_transfer(obj->serial.uart_control->handle, &am_hal_uart_xfer_write_single); } while (bytes_sent == 0); } @@ -300,7 +353,8 @@ void serial_putc(serial_t *obj, int c) */ int serial_readable(serial_t *obj) { - // todo: + MBED_ASSERT(obj->serial.uart_control != NULL); + return !(UARTn(obj->serial.uart_control->inst)->FR_b.RXFE); } /** Check if the serial peripheral is writable @@ -310,7 +364,8 @@ int serial_readable(serial_t *obj) */ int serial_writable(serial_t *obj) { - // todo: + MBED_ASSERT(obj->serial.uart_control != NULL); + return !(UARTn(obj->serial.uart_control->inst)->FR_b.TXFF); } /** Clear the serial peripheral @@ -319,7 +374,7 @@ int serial_writable(serial_t *obj) */ void serial_clear(serial_t *obj) { - // todo: + MBED_ASSERT(0); // todo: WTF is this? } /** Set the break @@ -328,7 +383,8 @@ void serial_clear(serial_t *obj) */ void serial_break_set(serial_t *obj) { - // todo: + MBED_ASSERT(obj->serial.uart_control != NULL); + UARTn(obj->serial.uart_control->inst)->LCRH |= UART0_LCRH_BRK_Msk; } /** Clear the break @@ -337,7 +393,8 @@ void serial_break_set(serial_t *obj) */ void serial_break_clear(serial_t *obj) { - // todo: + MBED_ASSERT(obj->serial.uart_control != NULL); + UARTn(obj->serial.uart_control->inst)->LCRH &= ~UART0_LCRH_BRK_Msk; } /** Configure the TX pin for UART function. @@ -345,9 +402,12 @@ void serial_break_clear(serial_t *obj) * @param tx The pin name used for TX */ void serial_pinout_tx(PinName tx) +{ + MBED_ASSERT(0); // todo: (this seems like a vestigial function) +} #if DEVICE_SERIAL_FC - /** Configure the serial for the flow control. It sets flow control in the hardware +/** Configure the serial for the flow control. It sets flow control in the hardware * if a serial peripheral supports it, otherwise software emulation is used. * * @param obj The serial object @@ -355,7 +415,7 @@ void serial_pinout_tx(PinName tx) * @param rxflow The TX pin name * @param txflow The RX pin name */ - void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, PinName txflow) +void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, PinName txflow) { // todo: } @@ -394,7 +454,7 @@ const PinMap *serial_tx_pinmap(void) */ const PinMap *serial_rx_pinmap(void) { - return PinMap_UART_TX; + return PinMap_UART_RX; } #if DEVICE_SERIAL_FC @@ -446,7 +506,21 @@ const PinMap *serial_rts_pinmap(void) */ int serial_tx_asynch(serial_t *obj, const void *tx, size_t tx_length, uint8_t tx_width, uint32_t handler, uint32_t event, DMAUsage hint) { - // todo: + MBED_ASSERT(obj->serial.uart_control != NULL); + uint32_t bytes_written = 0; + + am_hal_uart_transfer_t am_hal_uart_xfer_write = + { + .ui32Direction = AM_HAL_UART_WRITE, + .pui8Data = (uint8_t *)obj->tx_buff.buffer, + .ui32NumBytes = tx_length, // todo: consider maybe this? (uint32_t)obj->tx_buff.length, + .ui32TimeoutMs = 0, + .pui32BytesTransferred = &bytes_written, + }; + + am_hal_uart_transfer(obj->serial.uart_control->handle, &am_hal_uart_xfer_write); + + return (int)bytes_written; } /** Begin asynchronous RX transfer (enable interrupt for data collecting) @@ -463,7 +537,20 @@ int serial_tx_asynch(serial_t *obj, const void *tx, size_t tx_length, uint8_t tx */ void serial_rx_asynch(serial_t *obj, void *rx, size_t rx_length, uint8_t rx_width, uint32_t handler, uint32_t event, uint8_t char_match, DMAUsage hint) { - // todo: + // todo: revisit + MBED_ASSERT(obj->serial.uart_control != NULL); + uint32_t bytes_read = 0; + + am_hal_uart_transfer_t am_hal_uart_xfer_read = + { + .ui32Direction = AM_HAL_UART_READ, + .pui8Data = (uint8_t *)obj->rx_buff.buffer, + .ui32NumBytes = rx_length, // todo: consider this (uint32_t)obj->rx_buff.length, + .ui32TimeoutMs = 0, + .pui32BytesTransferred = &bytes_read, + }; + + am_hal_uart_transfer(obj->serial.uart_control->handle, &am_hal_uart_xfer_read); } /** Attempts to determine if the serial peripheral is already in use for TX @@ -520,6 +607,76 @@ void serial_rx_abort_asynch(serial_t *obj) #endif +static inline void uart_irq(uint32_t instance) +{ + void *handle = ap3_uart_control[instance].handle; + MBED_ASSERT(handle != NULL); + + // check flags + uint32_t status = 0x00; + MBED_ASSERT(am_hal_uart_interrupt_status_get(handle, &status, true) == AM_HAL_STATUS_SUCCESS); + MBED_ASSERT(am_hal_uart_interrupt_clear(handle, status) == AM_HAL_STATUS_SUCCESS); + + if (ap3_uart_control[instance].serial_irq_id != 0) + { + if (status & AM_HAL_UART_INT_TXCMP) + { // for transmit complete + if (irq_handler) + { + irq_handler(ap3_uart_control[instance].serial_irq_id, TxIrq); + } + } + if (status & AM_HAL_UART_INT_RX) + { // for receive complete + if (irq_handler) + { + irq_handler(ap3_uart_control[instance].serial_irq_id, RxIrq); + } + } + } +} + +extern void am_uart_isr(void) +{ + // void* handle = &(g_am_hal_uart_states[0]) // bad - breaks barrier between AMHAL and mbed + // value = !value; + // (value) ? am_hal_gpio_output_set(16) : am_hal_gpio_output_clear(16); + + am_hal_gpio_output_set(16); + + uart_irq(UART_0); +} + +extern void am_uart1_isr(void) +{ + // void* handle = &(g_am_hal_uart_states[1]) // bad - breaks barrier between AMHAL and mbed + uart_irq(UART_1); +} + +void uart_configure_pin_function(PinName pin, UARTName uart, const PinMap *map) +{ + while (map->pin != NC) + { + if (map->peripheral == uart) + { + if (map->pin == pin) + { + // pin_function(pin, map->function); + + am_hal_gpio_pincfg_t cfg = + { + .uFuncSel = map->function, + // .eDriveStrength = (tx) ? AM_HAL_GPIO_PIN_DRIVESTRENGTH_2MA : 0, + }; + + am_hal_gpio_pinconfig(pin, cfg); + break; + } + } + map++; + } +} + #ifdef __cplusplus } #endif From 52c4383d1127e515622f2615209de96f7b5841e1 Mon Sep 17 00:00:00 2001 From: Kyle Wenner Date: Tue, 4 Feb 2020 13:32:57 -0700 Subject: [PATCH 8/9] initial commit for gpio irq, ambiq apollo3 --- .mbedignore | 1 - .../TARGET_Apollo3/device/apollo3.h | 3 + .../TARGET_Apollo3/device/gpio_api.c | 4 +- .../TARGET_Apollo3/device/gpio_irq_api.c | 230 ++++++++++++++++++ .../TARGET_Apollo3/device/objects_gpio.h | 180 ++++++++------ targets/targets.json | 2 +- 6 files changed, 341 insertions(+), 79 deletions(-) create mode 100644 targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/gpio_irq_api.c diff --git a/.mbedignore b/.mbedignore index 35bdb4e68fd..e69de29bb2d 100644 --- a/.mbedignore +++ b/.mbedignore @@ -1 +0,0 @@ -features/ \ No newline at end of file diff --git a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/apollo3.h b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/apollo3.h index 57a9ec27cc1..a0cb1efbde9 100644 --- a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/apollo3.h +++ b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/apollo3.h @@ -147,6 +147,9 @@ typedef enum { #define __IOM __IO #endif +#ifdef OVERFLOW +#undef OVERFLOW +#endif /* ======================================== Start of section using anonymous unions ======================================== */ #if defined (__CC_ARM) diff --git a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/gpio_api.c b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/gpio_api.c index 8bdc0715a73..ac6339b16f8 100644 --- a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/gpio_api.c +++ b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/gpio_api.c @@ -102,11 +102,11 @@ void gpio_dir(gpio_t *obj, PinDirection direction){ MBED_ASSERT(gpio_is_connected(obj)); MBED_ASSERT(direction < (PinDirection)PIN_DIR_ELEMENTS); - if( direction & (PinDirection)PIN_INPUT ){ + if( direction == (PinDirection)PIN_INPUT ){ obj->cfg.eGPInput = AM_HAL_GPIO_PIN_INPUT_ENABLE; obj->cfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_DISABLE; } - else if ( direction & (PinDirection)PIN_OUTPUT ){ + else if ( direction == (PinDirection)PIN_OUTPUT ){ obj->cfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL; obj->cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA; obj->cfg.eGPInput = AM_HAL_GPIO_PIN_INPUT_ENABLE; diff --git a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/gpio_irq_api.c b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/gpio_irq_api.c new file mode 100644 index 00000000000..f7c33559e5c --- /dev/null +++ b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/gpio_irq_api.c @@ -0,0 +1,230 @@ +#include "gpio_irq_api.h" +#include "objects.h" + +#if DEVICE_INTERRUPTIN + +#ifdef __cplusplus +extern "C" +{ +#endif + + uint32_t ap3_gpio_enable_interrupts(uint32_t ui32Pin, am_hal_gpio_intdir_e eIntDir); + + /** GPIO IRQ HAL structure. gpio_irq_s is declared in the target's HAL + */ + typedef struct gpio_irq_s gpio_irq_t; + + typedef void (*gpio_irq_handler)(uint32_t id, gpio_irq_event event); + extern void am_gpio_isr(void); + static ap3_gpio_irq_control_t gpio_irq_control[AP3_GPIO_MAX_PADS]; + + /** + * \defgroup hal_gpioirq GPIO IRQ HAL functions + * + * # Defined behavior + * * ::gpio_irq_init initializes the GPIO IRQ pin + * * ::gpio_irq_init attaches the interrupt handler + * * ::gpio_irq_free releases the GPIO IRQ pin + * * ::gpio_irq_set enables/disables pin IRQ event + * * ::gpio_irq_enable enables GPIO IRQ + * * ::gpio_irq_disable disables GPIO IRQ + * + * # Undefined behavior + * * Calling other function before ::gpio_irq_init + * + * @{ + */ + + /** Initialize the GPIO IRQ pin + * + * @param obj The GPIO object to initialize + * @param pin The GPIO pin name + * @param handler The handler to be attached to GPIO IRQ + * @param id The object ID (id != 0, 0 is reserved) + * @return -1 if pin is NC, 0 otherwise + */ + int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id) + { + //grab the correct irq control object + ap3_gpio_irq_control_t control = gpio_irq_control[pin]; + + //Register locally + control.pad = pin; + control.handler = handler; + control.id = id; + control.events = IRQ_NONE; + + //Attach to object + obj->control = &control; + + //Make sure the interrupt is set to none to reflect the new events value + ap3_gpio_enable_interrupts(control.pad, AM_HAL_GPIO_PIN_INTDIR_NONE); + + //Enable GPIO IRQ's in the NVIC + NVIC_SetVector((IRQn_Type)GPIO_IRQn, (uint32_t)am_gpio_isr); + NVIC_EnableIRQ((IRQn_Type)GPIO_IRQn); + return 0; + } + + void am_gpio_isr(void) + { + //call the handler for the interrupt + uint64_t gpio_int_mask = 0x00; + am_hal_gpio_interrupt_status_get(true, &gpio_int_mask); + uint32_t pinNum = 0; + while (gpio_int_mask) + { + if (gpio_int_mask |= 0x0000000000000001) + { + am_hal_gpio_interrupt_clear(AM_HAL_GPIO_BIT(pinNum)); + ap3_gpio_irq_control_t irq_ctrl = gpio_irq_control[pinNum]; + ((gpio_irq_handler)irq_ctrl.handler)(irq_ctrl.id, irq_ctrl.events); + } + gpio_int_mask >>= 1; + pinNum++; + } + } + + /** Release the GPIO IRQ PIN + * + * @param obj The gpio object + */ + void gpio_irq_free(gpio_irq_t *obj) + { + } + + /** Enable/disable pin IRQ event + * + * @param obj The GPIO object + * @param event The GPIO IRQ event + * @param enable The enable flag + */ + void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable) + { + //Clear state + obj->control->events &= (~event); + if (enable) + { + //Reset if enabled + obj->control->events |= event; + } + + // Map enabled events to a value the reflects the ambiq hal/register values + am_hal_gpio_intdir_e ap3_int_dir = 0x00; + switch (obj->control->events) + { + case IRQ_NONE: + ap3_int_dir = AM_HAL_GPIO_PIN_INTDIR_NONE; + break; + case IRQ_RISE: + ap3_int_dir = AM_HAL_GPIO_PIN_INTDIR_LO2HI; + break; + case IRQ_FALL: + ap3_int_dir = AM_HAL_GPIO_PIN_INTDIR_HI2LO; + break; + case (IRQ_RISE | IRQ_FALL): + ap3_int_dir = AM_HAL_GPIO_PIN_INTDIR_BOTH; + break; + } + + ap3_gpio_enable_interrupts(obj->control->pad, ap3_int_dir); + } + + /** Enable GPIO IRQ + * + * This is target dependent, as it might enable the entire port or just a pin + * @param obj The GPIO object + */ + void gpio_irq_enable(gpio_irq_t *obj) + { + am_hal_gpio_interrupt_clear(AM_HAL_GPIO_BIT(obj->control->pad)); + am_hal_gpio_interrupt_enable(AM_HAL_GPIO_BIT(obj->control->pad)); + } + + /** Disable GPIO IRQ + * + * This is target dependent, as it might disable the entire port or just a pin + * @param obj The GPIO object + */ + void gpio_irq_disable(gpio_irq_t *obj) + { + am_hal_gpio_interrupt_clear(AM_HAL_GPIO_BIT(obj->control->pad)); + am_hal_gpio_interrupt_disable(AM_HAL_GPIO_BIT(obj->control->pad)); + } + + /**@}*/ + uint32_t ap3_gpio_enable_interrupts(uint32_t ui32Pin, am_hal_gpio_intdir_e eIntDir) + { + uint32_t ui32Padreg, ui32AltPadCfg, ui32GPCfg; + uint32_t ui32Funcsel, ui32PowerSw; + bool bClearEnable = false; + +#ifndef AM_HAL_DISABLE_API_VALIDATION + if (ui32Pin >= AM_HAL_GPIO_MAX_PADS) + { + return AM_HAL_STATUS_INVALID_ARG; + } +#endif // AM_HAL_DISABLE_API_VALIDATION + + // + // Initialize the PADREG accumulator variables. + // + ui32GPCfg = ui32Padreg = ui32AltPadCfg = 0; + + // + // Map the requested interrupt direction settings into the Apollo3 + // GPIOCFG register field, which is a 4-bit field: + // [INTD(1):OUTCFG(2):INCFG(1)]. + // Bit0 of eIntDir maps to GPIOCFG.INTD (b3). + // Bit1 of eIntDir maps to GPIOCFG.INCFG (b0). + // + ui32GPCfg |= (((eIntDir >> 0) & 0x1) << GPIOCFG_FLD_INTD_S) | (((eIntDir >> 1) & 0x1) << GPIOCFG_FLD_INCFG_S); + + // + // At this point, the configuration variable, ui32GpioCfg + // value is set (at bit position 0) and ready to write + // to their respective register bitfields. + // + uint32_t ui32GPCfgAddr; + uint32_t ui32GPCfgClearMask; + uint32_t ui32GPCfgShft; + + ui32GPCfgShft = ((ui32Pin & 0x7) << 2); + + ui32GPCfgAddr = AM_REGADDR(GPIO, CFGA) + ((ui32Pin >> 1) & ~0x3); + + ui32GPCfgClearMask = ~((uint32_t)0xF << ui32GPCfgShft); + + // + // Get the new values into their rightful bit positions. + // + ui32GPCfg <<= ui32GPCfgShft; + + AM_CRITICAL_BEGIN + + if (bClearEnable) + { + // + // We're configuring a mode that requires clearing the Enable bit. + // + am_hal_gpio_output_tristate_disable(ui32Pin); + } + + GPIO->PADKEY = GPIO_PADKEY_PADKEY_Key; + + // Here's where the magic happens + AM_REGVAL(ui32GPCfgAddr) = (AM_REGVAL(ui32GPCfgAddr) & ui32GPCfgClearMask) | ui32GPCfg; + + GPIO->PADKEY = 0; + + AM_CRITICAL_END + + return AM_HAL_STATUS_SUCCESS; + + } // am_hal_gpio_pinconfig() + +#ifdef __cplusplus +} +#endif +/** @}*/ +#endif //DEVICE_INTERRUPTIN \ No newline at end of file diff --git a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/objects_gpio.h b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/objects_gpio.h index b28308b4f3a..d684372fcb9 100644 --- a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/objects_gpio.h +++ b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/objects_gpio.h @@ -23,85 +23,115 @@ SOFTWARE. #define MBED_OBJECTS_GPIO_H #include "am_hal_gpio.h" +#include "PinNames.h" #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif -typedef uint32_t ap3_gpio_pad_t; - -typedef enum { - PIN_INPUT = 0x00, - PIN_OUTPUT, - - PIN_DIR_ELEMENTS -} PinDirection; - -enum sPinMode { - sPowerSwNone = 0x00, - sPowerSwVDD, - sPowerSwVSS, - sPullNone, - sPullUp, - sPullDown, - sDriveStrength2mA, - sDriveStrength4mA, - sDriveStrength8mA, - sDriveStrength12mA, - sOutDisable, - sOutPushPull, - sOutOpenDrain, - sOutTristate, - sInAuto, - sInNone, - sInEnable, - sReadPin, - sReadZero, - - sPinModeElements -}; - -#define PinModeEntry(e) e = (1 << s ## e) - -typedef enum { - PinModeEntry(PowerSwNone), - PinModeEntry(PowerSwVDD), - PinModeEntry(PowerSwVSS), - PowerSwDefault = PowerSwNone, - - PinModeEntry(PullNone), - PinModeEntry(PullUp), - PinModeEntry(PullDown), - PullDefault = PullNone, - - PinModeEntry(DriveStrength2mA), - PinModeEntry(DriveStrength4mA), - PinModeEntry(DriveStrength8mA), - PinModeEntry(DriveStrength12mA), - DriveStrengthDefault = DriveStrength12mA, - - PinModeEntry(OutDisable), - PinModeEntry(OutPushPull), - PinModeEntry(OutOpenDrain), - PinModeEntry(OutTristate), - OutDefault = OutPushPull, - - PinModeEntry(InAuto), - PinModeEntry(InNone), - PinModeEntry(InEnable), - InDefault = InEnable, - - PinModeEntry(ReadPin), - PinModeEntry(ReadZero), - ReadDefault = ReadPin, - - PinModeEntry(PinModeElements) -} PinMode; - -typedef struct _gpio_t { - ap3_gpio_pad_t pad; - am_hal_gpio_pincfg_t cfg; -} gpio_t; + typedef uint32_t ap3_gpio_pad_t; + + typedef enum + { + PIN_INPUT = 0x00, + PIN_OUTPUT, + + PIN_DIR_ELEMENTS + } PinDirection; + + enum sPinMode + { + sPowerSwNone = 0x00, + sPowerSwVDD, + sPowerSwVSS, + sPullNone, + sPullUp, + sPullDown, + sDriveStrength2mA, + sDriveStrength4mA, + sDriveStrength8mA, + sDriveStrength12mA, + sOutDisable, + sOutPushPull, + sOutOpenDrain, + sOutTristate, + sInAuto, + sInNone, + sInEnable, + sReadPin, + sReadZero, + + sPinModeElements + }; + +#define PinModeEntry(e) e = (1 << s##e) + + typedef enum + { + PinModeEntry(PowerSwNone), + PinModeEntry(PowerSwVDD), + PinModeEntry(PowerSwVSS), + PowerSwDefault = PowerSwNone, + + PinModeEntry(PullNone), + PinModeEntry(PullUp), + PinModeEntry(PullDown), + PullDefault = PullNone, + + PinModeEntry(DriveStrength2mA), + PinModeEntry(DriveStrength4mA), + PinModeEntry(DriveStrength8mA), + PinModeEntry(DriveStrength12mA), + DriveStrengthDefault = DriveStrength12mA, + + PinModeEntry(OutDisable), + PinModeEntry(OutPushPull), + PinModeEntry(OutOpenDrain), + PinModeEntry(OutTristate), + OutDefault = OutPushPull, + + PinModeEntry(InAuto), + PinModeEntry(InNone), + PinModeEntry(InEnable), + InDefault = InEnable, + + PinModeEntry(ReadPin), + PinModeEntry(ReadZero), + ReadDefault = ReadPin, + + PinModeEntry(PinModeElements) + } PinMode; + + typedef struct _gpio_t + { + ap3_gpio_pad_t pad; + am_hal_gpio_pincfg_t cfg; + } gpio_t; + + typedef struct ap3_gpio_irq_control_t + { + ap3_gpio_pad_t pad; + uint32_t id; + void *handler; + uint8_t events; + } ap3_gpio_irq_control_t; + + typedef struct gpio_irq_s + { + ap3_gpio_irq_control_t *control; + } gpio_irq_s; + +#define AP3_GPIO_MAX_PADS (50) +#define PADREG_FLD_76_S 6 +#define PADREG_FLD_FNSEL_S 3 +#define PADREG_FLD_DRVSTR_S 2 +#define PADREG_FLD_INPEN_S 1 +#define PADREG_FLD_PULLUP_S 0 + +#define GPIOCFG_FLD_INTD_S 3 +#define GPIOCFG_FLD_OUTCFG_S 1 +#define GPIOCFG_FLD_INCFG_S 0 #ifdef __cplusplus } diff --git a/targets/targets.json b/targets/targets.json index a0f73cb4291..d58c40754ce 100644 --- a/targets/targets.json +++ b/targets/targets.json @@ -9846,7 +9846,7 @@ "supported_toolchains": ["GCC_ARM"], "public": false, "extra_labels": ["Ambiq_Micro", "Apollo3"], - "device_has": ["MPU", "USTICKER", "SERIAL"], + "device_has": ["MPU", "USTICKER", "SERIAL", "INTERRUPTIN"], "macros": [] }, "AMA3B1KK": { From cb97958fb3c14c2dbae97f69d1b9edbfd99512fc Mon Sep 17 00:00:00 2001 From: Kyle Wenner Date: Fri, 14 Feb 2020 14:53:53 -0700 Subject: [PATCH 9/9] GPIO Interrupts working, ambiq apollo3 mbed port --- .../TARGET_Apollo3/device/apollo3.h | 4 - .../TARGET_Apollo3/device/cmsis.h | 2 +- .../TARGET_Apollo3/device/gpio_api.c | 166 ++- .../TARGET_Apollo3/device/gpio_irq_api.c | 20 +- .../TARGET_Apollo3/device/objects_gpio.h | 2 + .../TARGET_Apollo3/device/serial_api.c | 2 +- .../mcu/apollo3/am_mcu_apollo.h | 22 +- .../mcu/apollo3/hal/am_hal_gpio.c | 943 +++++++++----- .../mcu/apollo3/hal/am_hal_gpio.h | 1110 ++++++++--------- 9 files changed, 1337 insertions(+), 934 deletions(-) diff --git a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/apollo3.h b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/apollo3.h index a0cb1efbde9..3a35c0fc3db 100644 --- a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/apollo3.h +++ b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/apollo3.h @@ -147,10 +147,6 @@ typedef enum { #define __IOM __IO #endif -#ifdef OVERFLOW -#undef OVERFLOW -#endif - /* ======================================== Start of section using anonymous unions ======================================== */ #if defined (__CC_ARM) #pragma push diff --git a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/cmsis.h b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/cmsis.h index a60785cc523..d87cc6d7044 100644 --- a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/cmsis.h +++ b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/cmsis.h @@ -7,7 +7,7 @@ #ifndef MBED_CMSIS_H #define MBED_CMSIS_H -#include "apollo3.h" +#include "am_mcu_apollo.h" #include "cmsis_nvic.h" #endif diff --git a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/gpio_api.c b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/gpio_api.c index ac6339b16f8..61748ef1504 100644 --- a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/gpio_api.c +++ b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/gpio_api.c @@ -28,7 +28,8 @@ SOFTWARE. * @param pin The pin to be set as GPIO * @return The GPIO port mask for this pin **/ -uint32_t gpio_set(PinName pin){ +uint32_t gpio_set(PinName pin) +{ MBED_ASSERT(pin != (PinName)NC); return (uint32_t)AM_HAL_GPIO_BIT(pin); } @@ -38,7 +39,8 @@ uint32_t gpio_set(PinName pin){ * @return 0 if object was initialized with NC * @return non-zero if object was initialized with a valid PinName **/ -int gpio_is_connected(const gpio_t *obj){ +int gpio_is_connected(const gpio_t *obj) +{ MBED_ASSERT(obj != NULL); return (int)(((PinName)obj->pad == (PinName)NC) ? 0 : 1); } @@ -48,49 +50,127 @@ int gpio_is_connected(const gpio_t *obj){ * @param obj The GPIO object to initialize * @param pin The GPIO pin to initialize (may be NC) */ -void gpio_init(gpio_t *obj, PinName pin){ +void gpio_init(gpio_t *obj, PinName pin) +{ MBED_ASSERT(obj != NULL); obj->pad = (ap3_uart_pad_t)pin; return; } - /** Set the input pin mode * * @param obj The GPIO object (must be connected) * @param mode The pin mode to be set */ -void gpio_mode(gpio_t *obj, PinMode mode){ +void gpio_mode(gpio_t *obj, PinMode mode) +{ MBED_ASSERT(gpio_is_connected(obj)); MBED_ASSERT(mode < (PinMode)PinModeElements); + am_hal_gpio_pincfg_allow_t pinConfigBools; - obj->cfg.uFuncSel = 3; // gpio + obj->cfg.uFuncSel = AP3_PINCFG_FUNCSEL_GPIO; // gpio - if( mode & (PinMode)PowerSwNone ){ obj->cfg.ePowerSw = AM_HAL_GPIO_PIN_POWERSW_NONE; } - if( mode & (PinMode)PowerSwVDD ){ obj->cfg.ePowerSw = AM_HAL_GPIO_PIN_POWERSW_VDD; } - if( mode & (PinMode)PowerSwVSS ){ obj->cfg.ePowerSw = AM_HAL_GPIO_PIN_POWERSW_VSS; } + if (mode & (PinMode)PowerSwNone) + { + obj->cfg.ePowerSw = AM_HAL_GPIO_PIN_POWERSW_NONE; + pinConfigBools.powerSw = true; + } + if (mode & (PinMode)PowerSwVDD) + { + obj->cfg.ePowerSw = AM_HAL_GPIO_PIN_POWERSW_VDD; + pinConfigBools.powerSw = true; + } + if (mode & (PinMode)PowerSwVSS) + { + obj->cfg.ePowerSw = AM_HAL_GPIO_PIN_POWERSW_VSS; + pinConfigBools.powerSw = true; + } - if( mode & (PinMode)PullNone ){ obj->cfg.ePullup = AM_HAL_GPIO_PIN_PULLUP_NONE; } - if( mode & (PinMode)PullUp ){ obj->cfg.ePullup = AM_HAL_GPIO_PIN_PULLUP_WEAK; } - if( mode & (PinMode)PullDown ){ obj->cfg.ePullup = AM_HAL_GPIO_PIN_PULLDOWN; } + if (mode & (PinMode)PullNone) + { + obj->cfg.ePullup = AM_HAL_GPIO_PIN_PULLUP_NONE; + pinConfigBools.pullup = true; + } + if (mode & (PinMode)PullUp) + { + obj->cfg.ePullup = AM_HAL_GPIO_PIN_PULLUP_WEAK; + pinConfigBools.pullup = true; + } + if (mode & (PinMode)PullDown) + { + obj->cfg.ePullup = AM_HAL_GPIO_PIN_PULLDOWN; + pinConfigBools.pullup = true; + } - if( mode & (PinMode)DriveStrength2mA ){ obj->cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_2MA; } - if( mode & (PinMode)DriveStrength4mA ){ obj->cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_4MA; } - if( mode & (PinMode)DriveStrength8mA ){ obj->cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_8MA; } - if( mode & (PinMode)DriveStrength12mA ){ obj->cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA; } + if (mode & (PinMode)DriveStrength2mA) + { + obj->cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_2MA; + pinConfigBools.driveStrength = true; + } + if (mode & (PinMode)DriveStrength4mA) + { + obj->cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_4MA; + pinConfigBools.driveStrength = true; + } + if (mode & (PinMode)DriveStrength8mA) + { + obj->cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_8MA; + pinConfigBools.driveStrength = true; + } + if (mode & (PinMode)DriveStrength12mA) + { + obj->cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA; + pinConfigBools.driveStrength = true; + } - if( mode & (PinMode)OutDisable ){ obj->cfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_DISABLE; } - if( mode & (PinMode)OutPushPull ){ obj->cfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL; } - if( mode & (PinMode)OutOpenDrain ){ obj->cfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_OPENDRAIN; } - if( mode & (PinMode)OutTristate ){ obj->cfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_TRISTATE; } + if (mode & (PinMode)OutDisable) + { + obj->cfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_DISABLE; + pinConfigBools.gpOutcfg = true; + } + if (mode & (PinMode)OutPushPull) + { + obj->cfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL; + pinConfigBools.gpOutcfg = true; + } + if (mode & (PinMode)OutOpenDrain) + { + obj->cfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_OPENDRAIN; + pinConfigBools.gpOutcfg = true; + } + if (mode & (PinMode)OutTristate) + { + obj->cfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_TRISTATE; + pinConfigBools.gpOutcfg = true; + } - if( mode & (PinMode)InAuto ){ obj->cfg.eGPInput = AM_HAL_GPIO_PIN_INPUT_AUTO; } - if( mode & (PinMode)InNone ){ obj->cfg.eGPInput = AM_HAL_GPIO_PIN_INPUT_NONE; } - if( mode & (PinMode)InEnable ){ obj->cfg.eGPInput = AM_HAL_GPIO_PIN_INPUT_ENABLE; } + if (mode & (PinMode)InAuto) + { + obj->cfg.eGPInput = AM_HAL_GPIO_PIN_INPUT_AUTO; + pinConfigBools.gpInput = true; + } + if (mode & (PinMode)InNone) + { + obj->cfg.eGPInput = AM_HAL_GPIO_PIN_INPUT_NONE; + pinConfigBools.gpInput = true; + } + if (mode & (PinMode)InEnable) + { + obj->cfg.eGPInput = AM_HAL_GPIO_PIN_INPUT_ENABLE; + pinConfigBools.gpInput = true; + } - if( mode & (PinMode)ReadPin ){ obj->cfg.eGPRdZero = AM_HAL_GPIO_PIN_RDZERO_READPIN; } - if( mode & (PinMode)ReadZero ){ obj->cfg.eGPRdZero = AM_HAL_GPIO_PIN_RDZERO_ZERO; } + if (mode & (PinMode)ReadPin) + { + obj->cfg.eGPRdZero = AM_HAL_GPIO_PIN_RDZERO_READPIN; + pinConfigBools.gprdZero = true; + } + if (mode & (PinMode)ReadZero) + { + obj->cfg.eGPRdZero = AM_HAL_GPIO_PIN_RDZERO_ZERO; + pinConfigBools.gprdZero = true; + } - am_hal_gpio_pinconfig((uint32_t)(obj->pad), obj->cfg); // apply configuration + ap3_hal_gpio_pinconfig_partial((uint32_t)(obj->pad), obj->cfg, pinConfigBools); //padRegMsk.byte, GPConfigMsk.byte, padAltCfgMsk.byte); // apply configuration } /** Set the pin direction @@ -98,24 +178,33 @@ void gpio_mode(gpio_t *obj, PinMode mode){ * @param obj The GPIO object (must be connected) * @param direction The pin direction to be set */ -void gpio_dir(gpio_t *obj, PinDirection direction){ +void gpio_dir(gpio_t *obj, PinDirection direction) +{ MBED_ASSERT(gpio_is_connected(obj)); MBED_ASSERT(direction < (PinDirection)PIN_DIR_ELEMENTS); + am_hal_gpio_pincfg_allow_t pinConfigBools; - if( direction == (PinDirection)PIN_INPUT ){ + if (direction == (PinDirection)PIN_INPUT) + { obj->cfg.eGPInput = AM_HAL_GPIO_PIN_INPUT_ENABLE; + pinConfigBools.gpInput = true; obj->cfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_DISABLE; + pinConfigBools.gpOutcfg = true; } - else if ( direction == (PinDirection)PIN_OUTPUT ){ + else if (direction == (PinDirection)PIN_OUTPUT) + { obj->cfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL; + pinConfigBools.gpOutcfg = false; obj->cfg.eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA; - obj->cfg.eGPInput = AM_HAL_GPIO_PIN_INPUT_ENABLE; - obj->cfg.eGPRdZero = AM_HAL_GPIO_PIN_RDZERO_READPIN; - }else{ + obj->cfg.eGPInput = AM_HAL_GPIO_PIN_INPUT_NONE; + pinConfigBools.gpInput = false; + } + else + { MBED_ASSERT(false); } - am_hal_gpio_pinconfig((uint32_t)(obj->pad), obj->cfg); // apply configuration + ap3_hal_gpio_pinconfig_partial((uint32_t)(obj->pad), obj->cfg, pinConfigBools); //padRegMsk.byte, GPConfigMsk.byte, padAltCfgMsk.byte); // apply configuration } /** Set the output value @@ -123,7 +212,8 @@ void gpio_dir(gpio_t *obj, PinDirection direction){ * @param obj The GPIO object (must be connected) * @param value The value to be set */ -void gpio_write(gpio_t *obj, int value){ +void gpio_write(gpio_t *obj, int value) +{ MBED_ASSERT(gpio_is_connected(obj)); (value) ? am_hal_gpio_output_set(obj->pad) : am_hal_gpio_output_clear(obj->pad); } @@ -133,7 +223,8 @@ void gpio_write(gpio_t *obj, int value){ * @param obj The GPIO object (must be connected) * @return An integer value 1 or 0 */ -int gpio_read(gpio_t *obj){ +int gpio_read(gpio_t *obj) +{ MBED_ASSERT(gpio_is_connected(obj)); uint32_t ui32BaseAddr = (obj->pad) / 8; uint32_t ui32BaseShift = (((obj->pad) % 8) * 4) + 1; @@ -153,7 +244,8 @@ int gpio_read(gpio_t *obj){ * * @return PinMap array */ -const PinMap *gpio_pinmap(void){ +const PinMap *gpio_pinmap(void) +{ MBED_ASSERT(false); return NULL; -} +} \ No newline at end of file diff --git a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/gpio_irq_api.c b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/gpio_irq_api.c index f7c33559e5c..9a80811d4b4 100644 --- a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/gpio_irq_api.c +++ b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/gpio_irq_api.c @@ -9,7 +9,6 @@ extern "C" #endif uint32_t ap3_gpio_enable_interrupts(uint32_t ui32Pin, am_hal_gpio_intdir_e eIntDir); - /** GPIO IRQ HAL structure. gpio_irq_s is declared in the target's HAL */ typedef struct gpio_irq_s gpio_irq_t; @@ -46,21 +45,22 @@ extern "C" int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id) { //grab the correct irq control object - ap3_gpio_irq_control_t control = gpio_irq_control[pin]; + ap3_gpio_irq_control_t *control = &gpio_irq_control[pin]; //Register locally - control.pad = pin; - control.handler = handler; - control.id = id; - control.events = IRQ_NONE; + control->pad = pin; + control->handler = handler; + control->id = id; + control->events = IRQ_NONE; //Attach to object - obj->control = &control; + obj->control = control; //Make sure the interrupt is set to none to reflect the new events value - ap3_gpio_enable_interrupts(control.pad, AM_HAL_GPIO_PIN_INTDIR_NONE); + ap3_gpio_enable_interrupts(control->pad, AM_HAL_GPIO_PIN_INTDIR_NONE); //Enable GPIO IRQ's in the NVIC + gpio_irq_enable(obj); NVIC_SetVector((IRQn_Type)GPIO_IRQn, (uint32_t)am_gpio_isr); NVIC_EnableIRQ((IRQn_Type)GPIO_IRQn); return 0; @@ -74,7 +74,7 @@ extern "C" uint32_t pinNum = 0; while (gpio_int_mask) { - if (gpio_int_mask |= 0x0000000000000001) + if (gpio_int_mask & 0x0000000000000001) { am_hal_gpio_interrupt_clear(AM_HAL_GPIO_BIT(pinNum)); ap3_gpio_irq_control_t irq_ctrl = gpio_irq_control[pinNum]; @@ -155,6 +155,8 @@ extern "C" /**@}*/ uint32_t ap3_gpio_enable_interrupts(uint32_t ui32Pin, am_hal_gpio_intdir_e eIntDir) { + //GPConfigReg_t GPCfgMask = {.bit.INCFG = 1, .bit.INTD = 1}; + // uint32_t ap3_hal_gpio_pinconfig_partial(ui32Pin, bfGpioCfg, 0, uint8_t GPCfgMask, 0); uint32_t ui32Padreg, ui32AltPadCfg, ui32GPCfg; uint32_t ui32Funcsel, ui32PowerSw; bool bClearEnable = false; diff --git a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/objects_gpio.h b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/objects_gpio.h index d684372fcb9..df62e62ecf7 100644 --- a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/objects_gpio.h +++ b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/objects_gpio.h @@ -122,6 +122,8 @@ extern "C" ap3_gpio_irq_control_t *control; } gpio_irq_s; +#define AP3_PINCFG_FUNCSEL_GPIO 3 + #define AP3_GPIO_MAX_PADS (50) #define PADREG_FLD_76_S 6 #define PADREG_FLD_FNSEL_S 3 diff --git a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/serial_api.c b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/serial_api.c index 092b1e9beaa..dafd262879f 100644 --- a/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/serial_api.c +++ b/targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/serial_api.c @@ -133,7 +133,7 @@ void uart_configure_pin_function(PinName pin, UARTName uart, const PinMap *map); * @param rx The RX pin name */ void serial_init(serial_t *obj, PinName tx, PinName rx) -{ +{ //TODO: we should be able to call this multiple times // determine the UART to use UARTName uart_tx = (UARTName)pinmap_peripheral(tx, serial_tx_pinmap()); UARTName uart_rx = (UARTName)pinmap_peripheral(rx, serial_rx_pinmap()); diff --git a/targets/TARGET_Ambiq_Micro/mcu/apollo3/am_mcu_apollo.h b/targets/TARGET_Ambiq_Micro/mcu/apollo3/am_mcu_apollo.h index 105d76f4ce9..1e3209aa1eb 100644 --- a/targets/TARGET_Ambiq_Micro/mcu/apollo3/am_mcu_apollo.h +++ b/targets/TARGET_Ambiq_Micro/mcu/apollo3/am_mcu_apollo.h @@ -18,24 +18,24 @@ // // Copyright (c) 2019, Ambiq Micro // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: -// +// // 1. Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. -// +// // 2. 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. -// +// // 3. Neither the name of the copyright holder nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. -// +// // Third party software included in this distribution is subject to the // additional license terms as defined in the /docs/licenses directory. -// +// // 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 @@ -59,7 +59,7 @@ // Define AM_CMSIS_REGS to indicate that CMSIS registers are supported. // //***************************************************************************** -#define AM_CMSIS_REGS 1 +#define AM_CMSIS_REGS 1 //***************************************************************************** // @@ -71,11 +71,14 @@ #include #include #if AM_CMSIS_REGS +#ifdef OVERFLOW +#undef OVERFLOW +#endif // OVERRFLOW #include "apollo3.h" #else // AM_CMSIS_REGS #ifdef __IAR_SYSTEMS_ICC__ -#include "intrinsics.h" // __CLZ() and other intrinsics -#endif // AM_CMSIS_REGS +#include "intrinsics.h" // __CLZ() and other intrinsics +#endif // AM_CMSIS_REGS #endif //***************************************************************************** @@ -152,4 +155,3 @@ #include "hal/am_hal_wdt.h" #endif // AM_MCU_APOLLO_H - diff --git a/targets/TARGET_Ambiq_Micro/mcu/apollo3/hal/am_hal_gpio.c b/targets/TARGET_Ambiq_Micro/mcu/apollo3/hal/am_hal_gpio.c index 4fb86487b77..8532a210544 100644 --- a/targets/TARGET_Ambiq_Micro/mcu/apollo3/hal/am_hal_gpio.c +++ b/targets/TARGET_Ambiq_Micro/mcu/apollo3/hal/am_hal_gpio.c @@ -15,24 +15,24 @@ // // Copyright (c) 2019, Ambiq Micro // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: -// +// // 1. Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. -// +// // 2. 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. -// +// // 3. Neither the name of the copyright holder nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. -// +// // Third party software included in this distribution is subject to the // additional license terms as defined in the /docs/licenses directory. -// +// // 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 @@ -59,15 +59,15 @@ // // Generally define GPIO PADREG and GPIOCFG bitfields // -#define PADREG_FLD_76_S 6 -#define PADREG_FLD_FNSEL_S 3 -#define PADREG_FLD_DRVSTR_S 2 -#define PADREG_FLD_INPEN_S 1 -#define PADREG_FLD_PULLUP_S 0 +#define PADREG_FLD_76_S 6 +#define PADREG_FLD_FNSEL_S 3 +#define PADREG_FLD_DRVSTR_S 2 +#define PADREG_FLD_INPEN_S 1 +#define PADREG_FLD_PULLUP_S 0 -#define GPIOCFG_FLD_INTD_S 3 -#define GPIOCFG_FLD_OUTCFG_S 1 -#define GPIOCFG_FLD_INCFG_S 0 +#define GPIOCFG_FLD_INTD_S 3 +#define GPIOCFG_FLD_OUTCFG_S 1 +#define GPIOCFG_FLD_INCFG_S 0 //***************************************************************************** // @@ -78,26 +78,23 @@ // Define some common GPIO configurations. //***************************************************************************** const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_DISABLE = -{ - .uFuncSel = 3, - .eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_2MA, - .eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_DISABLE -}; + { + .uFuncSel = 3, + .eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_2MA, + .eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_DISABLE}; const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_TRISTATE = -{ - .uFuncSel = 3, - .eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_2MA, - .eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_TRISTATE -}; + { + .uFuncSel = 3, + .eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_2MA, + .eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_TRISTATE}; const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_INPUT = -{ - .uFuncSel = 3, - .eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_DISABLE, - .eGPInput = AM_HAL_GPIO_PIN_INPUT_ENABLE, - .eGPRdZero = AM_HAL_GPIO_PIN_RDZERO_READPIN -}; + { + .uFuncSel = 3, + .eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_DISABLE, + .eGPInput = AM_HAL_GPIO_PIN_INPUT_ENABLE, + .eGPRdZero = AM_HAL_GPIO_PIN_RDZERO_READPIN}; // // Input with various pullups (weak, 1.5K, 6K, 12K, 24K) @@ -106,89 +103,79 @@ const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_INPUT = // The "weak" value is used for almost every other pad except pin 20. // const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_INPUT_PULLUP = -{ - .uFuncSel = 3, - .eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_DISABLE, - .eGPInput = AM_HAL_GPIO_PIN_INPUT_ENABLE, - .eGPRdZero = AM_HAL_GPIO_PIN_RDZERO_READPIN, - .ePullup = AM_HAL_GPIO_PIN_PULLUP_WEAK -}; + { + .uFuncSel = 3, + .eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_DISABLE, + .eGPInput = AM_HAL_GPIO_PIN_INPUT_ENABLE, + .eGPRdZero = AM_HAL_GPIO_PIN_RDZERO_READPIN, + .ePullup = AM_HAL_GPIO_PIN_PULLUP_WEAK}; const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_INPUT_PULLUP_1_5 = -{ - .uFuncSel = 3, - .eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_DISABLE, - .eGPInput = AM_HAL_GPIO_PIN_INPUT_ENABLE, - .eGPRdZero = AM_HAL_GPIO_PIN_RDZERO_READPIN, - .ePullup = AM_HAL_GPIO_PIN_PULLUP_1_5K -}; + { + .uFuncSel = 3, + .eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_DISABLE, + .eGPInput = AM_HAL_GPIO_PIN_INPUT_ENABLE, + .eGPRdZero = AM_HAL_GPIO_PIN_RDZERO_READPIN, + .ePullup = AM_HAL_GPIO_PIN_PULLUP_1_5K}; const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_INPUT_PULLUP_6 = -{ - .uFuncSel = 3, - .eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_DISABLE, - .eGPInput = AM_HAL_GPIO_PIN_INPUT_ENABLE, - .eGPRdZero = AM_HAL_GPIO_PIN_RDZERO_READPIN, - .ePullup = AM_HAL_GPIO_PIN_PULLUP_6K -}; + { + .uFuncSel = 3, + .eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_DISABLE, + .eGPInput = AM_HAL_GPIO_PIN_INPUT_ENABLE, + .eGPRdZero = AM_HAL_GPIO_PIN_RDZERO_READPIN, + .ePullup = AM_HAL_GPIO_PIN_PULLUP_6K}; const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_INPUT_PULLUP_12 = -{ - .uFuncSel = 3, - .eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_DISABLE, - .eGPInput = AM_HAL_GPIO_PIN_INPUT_ENABLE, - .eGPRdZero = AM_HAL_GPIO_PIN_RDZERO_READPIN, - .ePullup = AM_HAL_GPIO_PIN_PULLUP_12K -}; + { + .uFuncSel = 3, + .eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_DISABLE, + .eGPInput = AM_HAL_GPIO_PIN_INPUT_ENABLE, + .eGPRdZero = AM_HAL_GPIO_PIN_RDZERO_READPIN, + .ePullup = AM_HAL_GPIO_PIN_PULLUP_12K}; const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_INPUT_PULLUP_24 = -{ - .uFuncSel = 3, - .eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_DISABLE, - .eGPInput = AM_HAL_GPIO_PIN_INPUT_ENABLE, - .eGPRdZero = AM_HAL_GPIO_PIN_RDZERO_READPIN, - .ePullup = AM_HAL_GPIO_PIN_PULLUP_24K -}; + { + .uFuncSel = 3, + .eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_DISABLE, + .eGPInput = AM_HAL_GPIO_PIN_INPUT_ENABLE, + .eGPRdZero = AM_HAL_GPIO_PIN_RDZERO_READPIN, + .ePullup = AM_HAL_GPIO_PIN_PULLUP_24K}; // // Variations of output (drive strengths, read, etc) // const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_OUTPUT = -{ - .uFuncSel = 3, - .eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_2MA, - .eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL -}; + { + .uFuncSel = 3, + .eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_2MA, + .eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL}; const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_OUTPUT_4 = -{ - .uFuncSel = 3, - .eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_4MA, - .eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL -}; + { + .uFuncSel = 3, + .eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_4MA, + .eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL}; const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_OUTPUT_8 = -{ - .uFuncSel = 3, - .eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_8MA, - .eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL -}; + { + .uFuncSel = 3, + .eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_8MA, + .eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL}; const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_OUTPUT_12 = -{ - .uFuncSel = 3, - .eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA, - .eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL -}; + { + .uFuncSel = 3, + .eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA, + .eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL}; const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_OUTPUT_WITH_READ = -{ - .uFuncSel = 3, - .eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_2MA, - .eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL, - .eGPInput = AM_HAL_GPIO_PIN_INPUT_ENABLE, - .eGPRdZero = AM_HAL_GPIO_PIN_RDZERO_READPIN -}; + { + .uFuncSel = 3, + .eDriveStrength = AM_HAL_GPIO_PIN_DRIVESTRENGTH_2MA, + .eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL, + .eGPInput = AM_HAL_GPIO_PIN_INPUT_ENABLE, + .eGPRdZero = AM_HAL_GPIO_PIN_RDZERO_READPIN}; //***************************************************************************** // @@ -198,14 +185,14 @@ const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_OUTPUT_WITH_READ = // //***************************************************************************** static const uint8_t -g_ui8Inpen[AM_HAL_GPIO_MAX_PADS] = -{ - //0 1 2 3 4 5 6 7 8 9 - 0x23, 0x23, 0x27, 0x62, 0xA1, 0x03, 0x87, 0x10, 0x03, 0x53, // Pins 0-9 - 0x00, 0xE1, 0x51, 0x81, 0x41, 0x55, 0x05, 0xC4, 0x80, 0x40, // Pins 10-19 - 0x01, 0xB1, 0x40, 0x41, 0x14, 0x31, 0xA0, 0x31, 0x00, 0xF1, // Pins 20-29 - 0x80, 0x11, 0x91, 0x21, 0xC1, 0x11, 0xE5, 0x11, 0x45, 0x30, // Pins 30-39 - 0x37, 0x00, 0x30, 0x31, 0x00, 0x71, 0x00, 0x40, 0x30, 0x31 // Pins 40-49 + g_ui8Inpen[AM_HAL_GPIO_MAX_PADS] = + { + //0 1 2 3 4 5 6 7 8 9 + 0x23, 0x23, 0x27, 0x62, 0xA1, 0x03, 0x87, 0x10, 0x03, 0x53, // Pins 0-9 + 0x00, 0xE1, 0x51, 0x81, 0x41, 0x55, 0x05, 0xC4, 0x80, 0x40, // Pins 10-19 + 0x01, 0xB1, 0x40, 0x41, 0x14, 0x31, 0xA0, 0x31, 0x00, 0xF1, // Pins 20-29 + 0x80, 0x11, 0x91, 0x21, 0xC1, 0x11, 0xE5, 0x11, 0x45, 0x30, // Pins 30-39 + 0x37, 0x00, 0x30, 0x31, 0x00, 0x71, 0x00, 0x40, 0x30, 0x31 // Pins 40-49 }; //***************************************************************************** @@ -214,20 +201,20 @@ g_ui8Inpen[AM_HAL_GPIO_MAX_PADS] = // This lookup table specifies capabilities of each pad for PADREG bits 7:6. // //***************************************************************************** -#define CAP_PUP 0x01 // PULLUP -#define CAP_PDN 0x08 // PULLDOWN (pin 20 only) -#define CAP_VDD 0x02 // VDD PWR (power source) -#define CAP_VSS 0x04 // VSS PWR (ground sink) -#define CAP_RSV 0x80 // bits 7:6 are reserved for this pin +#define CAP_PUP 0x01 // PULLUP +#define CAP_PDN 0x08 // PULLDOWN (pin 20 only) +#define CAP_VDD 0x02 // VDD PWR (power source) +#define CAP_VSS 0x04 // VSS PWR (ground sink) +#define CAP_RSV 0x80 // bits 7:6 are reserved for this pin static const uint8_t -g_ui8Bit76Capabilities[AM_HAL_GPIO_MAX_PADS] = -{ - //0 1 2 3 4 5 6 7 8 9 - CAP_PUP, CAP_PUP, CAP_RSV, CAP_VDD, CAP_RSV, CAP_PUP, CAP_PUP, CAP_RSV, CAP_PUP, CAP_PUP, // Pins 0-9 - CAP_RSV, CAP_RSV, CAP_RSV, CAP_RSV, CAP_RSV, CAP_RSV, CAP_RSV, CAP_RSV, CAP_RSV, CAP_RSV, // Pins 10-19 - CAP_PDN, CAP_RSV, CAP_RSV, CAP_RSV, CAP_RSV, CAP_PUP, CAP_RSV, CAP_PUP, CAP_RSV, CAP_RSV, // Pins 20-29 - CAP_RSV, CAP_RSV, CAP_RSV, CAP_RSV, CAP_RSV, CAP_RSV, CAP_VDD, CAP_VSS, CAP_RSV, CAP_PUP, // Pins 30-39 - CAP_PUP, CAP_VSS, CAP_PUP, CAP_PUP, CAP_RSV, CAP_RSV, CAP_RSV, CAP_RSV, CAP_PUP, CAP_PUP // Pins 40-49 + g_ui8Bit76Capabilities[AM_HAL_GPIO_MAX_PADS] = + { + //0 1 2 3 4 5 6 7 8 9 + CAP_PUP, CAP_PUP, CAP_RSV, CAP_VDD, CAP_RSV, CAP_PUP, CAP_PUP, CAP_RSV, CAP_PUP, CAP_PUP, // Pins 0-9 + CAP_RSV, CAP_RSV, CAP_RSV, CAP_RSV, CAP_RSV, CAP_RSV, CAP_RSV, CAP_RSV, CAP_RSV, CAP_RSV, // Pins 10-19 + CAP_PDN, CAP_RSV, CAP_RSV, CAP_RSV, CAP_RSV, CAP_PUP, CAP_RSV, CAP_PUP, CAP_RSV, CAP_RSV, // Pins 20-29 + CAP_RSV, CAP_RSV, CAP_RSV, CAP_RSV, CAP_RSV, CAP_RSV, CAP_VDD, CAP_VSS, CAP_RSV, CAP_PUP, // Pins 30-39 + CAP_PUP, CAP_VSS, CAP_PUP, CAP_PUP, CAP_RSV, CAP_RSV, CAP_RSV, CAP_RSV, CAP_PUP, CAP_PUP // Pins 40-49 }; //***************************************************************************** @@ -253,14 +240,14 @@ g_ui8Bit76Capabilities[AM_HAL_GPIO_MAX_PADS] = // //***************************************************************************** static const uint8_t -g_ui8nCEpins[AM_HAL_GPIO_MAX_PADS] = -{ - // 0 1 2 3 4 5 6 7 8 9 - 0x07, 0x07, 0x07, 0x02, 0x02, 0x08, 0x08, 0x00, 0x02, 0x02, // Pads 0-9 - 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // Pads 10-19 - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // Pads 20-29 - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08, // Pads 30-39 - 0x08, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 // Pads 40-49 + g_ui8nCEpins[AM_HAL_GPIO_MAX_PADS] = + { + // 0 1 2 3 4 5 6 7 8 9 + 0x07, 0x07, 0x07, 0x02, 0x02, 0x08, 0x08, 0x00, 0x02, 0x02, // Pads 0-9 + 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // Pads 10-19 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // Pads 20-29 + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08, // Pads 30-39 + 0x08, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 // Pads 40-49 }; //***************************************************************************** @@ -275,59 +262,59 @@ g_ui8nCEpins[AM_HAL_GPIO_MAX_PADS] = // //***************************************************************************** static const uint8_t -g_ui8NCEtable[AM_HAL_GPIO_MAX_PADS][4] = -{ - // 0 1 2 3 = OUTCFG - {0x32, 0x42, 0x52, 0x13}, // NCE0 - {0x02, 0x12, 0x22, 0x60}, // NCE1 - {0x33, 0x43, 0x53, 0x21}, // NCE2 - {0x30, 0x40, 0x50, 0x20}, // NCE3 - {0x31, 0x41, 0x51, 0x11}, // NCE4 - {0xFF, 0xFF, 0xFF, 0xFF}, // NCE5 - {0xFF, 0xFF, 0xFF, 0xFF}, // NCE6 - {0x31, 0x41, 0x51, 0x60}, // NCE7 - {0x30, 0x40, 0x50, 0x00}, // NCE8 - {0x33, 0x43, 0x53, 0x23}, // NCE9 - {0x32, 0x42, 0x52, 0x60}, // NCE10 - {0x00, 0x10, 0x20, 0x30}, // NCE11 - {0x30, 0x40, 0x50, 0x61}, // NCE12 - {0x31, 0x41, 0x51, 0x01}, // NCE13 - {0x02, 0x12, 0x22, 0x42}, // NCE14 - {0x03, 0x13, 0x23, 0x60}, // NCE15 - {0x00, 0x10, 0x20, 0x50}, // NCE16 - {0x01, 0x11, 0x21, 0x41}, // NCE17 - {0x02, 0x12, 0x22, 0x32}, // NCE18 - {0x03, 0x13, 0x33, 0x60}, // NCE19 - {0x31, 0x41, 0x51, 0x21}, // NCE20 - {0x32, 0x42, 0x52, 0x22}, // NCE21 - {0x33, 0x43, 0x53, 0x03}, // NCE22 - {0x00, 0x10, 0x20, 0x40}, // NCE23 - {0x01, 0x11, 0x21, 0x51}, // NCE24 - {0x32, 0x42, 0x52, 0x02}, // NCE25 - {0x33, 0x43, 0x53, 0x13}, // NCE26 - {0x30, 0x40, 0x50, 0x10}, // NCE27 - {0x31, 0x41, 0x51, 0x60}, // NCE28 - {0x32, 0x42, 0x52, 0x12}, // NCE29 - {0x33, 0x43, 0x53, 0x03}, // NCE30 - {0x00, 0x10, 0x20, 0x40}, // NCE31 - {0x01, 0x11, 0x21, 0x61}, // NCE32 - {0x02, 0x12, 0x22, 0x52}, // NCE33 - {0x03, 0x13, 0x23, 0x33}, // NCE34 - {0x00, 0x10, 0x20, 0x30}, // NCE35 - {0x31, 0x41, 0x51, 0x61}, // NCE36 - {0x32, 0x42, 0x52, 0x02}, // NCE37 - {0x03, 0x13, 0x33, 0x53}, // NCE38 - {0xFF, 0xFF, 0xFF, 0xFF}, // NCE39 - {0xFF, 0xFF, 0xFF, 0xFF}, // NCE40 - {0x01, 0x11, 0x21, 0x61}, // NCE41 - {0x00, 0x10, 0x20, 0x50}, // NCE42 - {0x01, 0x11, 0x21, 0x61}, // NCE43 - {0x02, 0x12, 0x22, 0x52}, // NCE44 - {0x33, 0x43, 0x53, 0x13}, // NCE45 - {0x30, 0x40, 0x50, 0x61}, // NCE46 - {0x01, 0x11, 0x21, 0x31}, // NCE47 - {0x02, 0x12, 0x22, 0x32}, // NCE48 - {0x03, 0x13, 0x23, 0x43} // NCE49 + g_ui8NCEtable[AM_HAL_GPIO_MAX_PADS][4] = + { + // 0 1 2 3 = OUTCFG + {0x32, 0x42, 0x52, 0x13}, // NCE0 + {0x02, 0x12, 0x22, 0x60}, // NCE1 + {0x33, 0x43, 0x53, 0x21}, // NCE2 + {0x30, 0x40, 0x50, 0x20}, // NCE3 + {0x31, 0x41, 0x51, 0x11}, // NCE4 + {0xFF, 0xFF, 0xFF, 0xFF}, // NCE5 + {0xFF, 0xFF, 0xFF, 0xFF}, // NCE6 + {0x31, 0x41, 0x51, 0x60}, // NCE7 + {0x30, 0x40, 0x50, 0x00}, // NCE8 + {0x33, 0x43, 0x53, 0x23}, // NCE9 + {0x32, 0x42, 0x52, 0x60}, // NCE10 + {0x00, 0x10, 0x20, 0x30}, // NCE11 + {0x30, 0x40, 0x50, 0x61}, // NCE12 + {0x31, 0x41, 0x51, 0x01}, // NCE13 + {0x02, 0x12, 0x22, 0x42}, // NCE14 + {0x03, 0x13, 0x23, 0x60}, // NCE15 + {0x00, 0x10, 0x20, 0x50}, // NCE16 + {0x01, 0x11, 0x21, 0x41}, // NCE17 + {0x02, 0x12, 0x22, 0x32}, // NCE18 + {0x03, 0x13, 0x33, 0x60}, // NCE19 + {0x31, 0x41, 0x51, 0x21}, // NCE20 + {0x32, 0x42, 0x52, 0x22}, // NCE21 + {0x33, 0x43, 0x53, 0x03}, // NCE22 + {0x00, 0x10, 0x20, 0x40}, // NCE23 + {0x01, 0x11, 0x21, 0x51}, // NCE24 + {0x32, 0x42, 0x52, 0x02}, // NCE25 + {0x33, 0x43, 0x53, 0x13}, // NCE26 + {0x30, 0x40, 0x50, 0x10}, // NCE27 + {0x31, 0x41, 0x51, 0x60}, // NCE28 + {0x32, 0x42, 0x52, 0x12}, // NCE29 + {0x33, 0x43, 0x53, 0x03}, // NCE30 + {0x00, 0x10, 0x20, 0x40}, // NCE31 + {0x01, 0x11, 0x21, 0x61}, // NCE32 + {0x02, 0x12, 0x22, 0x52}, // NCE33 + {0x03, 0x13, 0x23, 0x33}, // NCE34 + {0x00, 0x10, 0x20, 0x30}, // NCE35 + {0x31, 0x41, 0x51, 0x61}, // NCE36 + {0x32, 0x42, 0x52, 0x02}, // NCE37 + {0x03, 0x13, 0x33, 0x53}, // NCE38 + {0xFF, 0xFF, 0xFF, 0xFF}, // NCE39 + {0xFF, 0xFF, 0xFF, 0xFF}, // NCE40 + {0x01, 0x11, 0x21, 0x61}, // NCE41 + {0x00, 0x10, 0x20, 0x50}, // NCE42 + {0x01, 0x11, 0x21, 0x61}, // NCE43 + {0x02, 0x12, 0x22, 0x52}, // NCE44 + {0x33, 0x43, 0x53, 0x13}, // NCE45 + {0x30, 0x40, 0x50, 0x61}, // NCE46 + {0x01, 0x11, 0x21, 0x31}, // NCE47 + {0x02, 0x12, 0x22, 0x32}, // NCE48 + {0x03, 0x13, 0x23, 0x43} // NCE49 }; //***************************************************************************** @@ -337,6 +324,9 @@ g_ui8NCEtable[AM_HAL_GPIO_MAX_PADS][4] = //***************************************************************************** static am_hal_gpio_handler_t gpio_ppfnHandlers[AM_HAL_GPIO_MAX_PADS]; +//Hello +void ap3_gpio_get_pinconfig_bitmasks(am_hal_gpio_pincfg_allow_t sAllowableChanges, uint8_t *padRegMask, uint8_t *GPCfgMask, uint8_t *altPadCfgMask); + //***************************************************************************** // // Helper functions @@ -353,8 +343,8 @@ pincfg_equ(void *cfg1, void *cfg2) // We're assuming that am_hal_gpio_pincfg_t boils down to a uint32_t, // which is its intent. // - ui32A = *((uint32_t*)cfg1); - ui32B = *((uint32_t*)cfg2); + ui32A = *((uint32_t *)cfg1); + ui32B = *((uint32_t *)cfg2); return ui32A == ui32B ? true : false; @@ -364,7 +354,7 @@ static uint32_t num_bits64(uint64_t ui64bitmask) { uint32_t ux = 0; - while ( ui64bitmask ) + while (ui64bitmask) { ux += ui64bitmask & 1; ui64bitmask >>= 1; @@ -372,7 +362,6 @@ num_bits64(uint64_t ui64bitmask) return ux; } // num_bits64() - //***************************************************************************** // //! @brief Configure an Apollo3 pin. @@ -396,7 +385,7 @@ am_hal_gpio_pinconfig(uint32_t ui32Pin, am_hal_gpio_pincfg_t bfGpioCfg) bool bClearEnable = false; #ifndef AM_HAL_DISABLE_API_VALIDATION - if ( ui32Pin >= AM_HAL_GPIO_MAX_PADS ) + if (ui32Pin >= AM_HAL_GPIO_MAX_PADS) { return AM_HAL_STATUS_INVALID_ARG; } @@ -418,7 +407,7 @@ am_hal_gpio_pinconfig(uint32_t ui32Pin, am_hal_gpio_pincfg_t bfGpioCfg) // // Check for invalid configuration requests. // - if ( bfGpioCfg.ePullup != AM_HAL_GPIO_PIN_PULLUP_NONE ) + if (bfGpioCfg.ePullup != AM_HAL_GPIO_PIN_PULLUP_NONE) { // // This setting is needed for all pullup settings including @@ -429,31 +418,30 @@ am_hal_gpio_pinconfig(uint32_t ui32Pin, am_hal_gpio_pincfg_t bfGpioCfg) // // Check for specific pullup or pulldown settings. // - if ( (bfGpioCfg.ePullup >= AM_HAL_GPIO_PIN_PULLUP_1_5K) && - (bfGpioCfg.ePullup <= AM_HAL_GPIO_PIN_PULLUP_24K) ) + if ((bfGpioCfg.ePullup >= AM_HAL_GPIO_PIN_PULLUP_1_5K) && + (bfGpioCfg.ePullup <= AM_HAL_GPIO_PIN_PULLUP_24K)) { - ui32Padreg |= ((bfGpioCfg.ePullup - AM_HAL_GPIO_PIN_PULLUP_1_5K) << - PADREG_FLD_76_S); + ui32Padreg |= ((bfGpioCfg.ePullup - AM_HAL_GPIO_PIN_PULLUP_1_5K) << PADREG_FLD_76_S); #ifndef AM_HAL_DISABLE_API_VALIDATION - if ( !(g_ui8Bit76Capabilities[ui32Pin] & CAP_PUP) ) + if (!(g_ui8Bit76Capabilities[ui32Pin] & CAP_PUP)) { return AM_HAL_GPIO_ERR_PULLUP; } } - else if ( bfGpioCfg.ePullup == AM_HAL_GPIO_PIN_PULLDOWN ) + else if (bfGpioCfg.ePullup == AM_HAL_GPIO_PIN_PULLDOWN) { - if ( ui32Pin != 20 ) + if (ui32Pin != 20) { return AM_HAL_GPIO_ERR_PULLDOWN; } } - else if ( bfGpioCfg.ePullup == AM_HAL_GPIO_PIN_PULLUP_WEAK ) + else if (bfGpioCfg.ePullup == AM_HAL_GPIO_PIN_PULLUP_WEAK) { // // All pads except 20 support a weak pullup, for which we only need // to set PADnPULL and clear 7:6 (already done at this point). // - if ( ui32Pin == 20 ) + if (ui32Pin == 20) { return AM_HAL_GPIO_ERR_PULLUP; } @@ -464,15 +452,15 @@ am_hal_gpio_pinconfig(uint32_t ui32Pin, am_hal_gpio_pincfg_t bfGpioCfg) // // Check if requesting a power switch pin // - if ( ui32PowerSw != AM_HAL_GPIO_PIN_POWERSW_NONE ) + if (ui32PowerSw != AM_HAL_GPIO_PIN_POWERSW_NONE) { - if ( (ui32PowerSw == AM_HAL_GPIO_PIN_POWERSW_VDD) && - (g_ui8Bit76Capabilities[ui32Pin] & CAP_VDD) ) + if ((ui32PowerSw == AM_HAL_GPIO_PIN_POWERSW_VDD) && + (g_ui8Bit76Capabilities[ui32Pin] & CAP_VDD)) { ui32Padreg |= 0x1 << PADREG_FLD_76_S; } - else if ( (ui32PowerSw == AM_HAL_GPIO_PIN_POWERSW_VSS) && - (g_ui8Bit76Capabilities[ui32Pin] & CAP_VSS) ) + else if ((ui32PowerSw == AM_HAL_GPIO_PIN_POWERSW_VSS) && + (g_ui8Bit76Capabilities[ui32Pin] & CAP_VSS)) { ui32Padreg |= 0x2 << PADREG_FLD_76_S; } @@ -490,7 +478,7 @@ am_hal_gpio_pinconfig(uint32_t ui32Pin, am_hal_gpio_pincfg_t bfGpioCfg) // // Configure ui32GpCfg based on whether nCE requested. // - if ( g_ui8nCEpins[ui32Pin] == ui32Funcsel ) + if (g_ui8nCEpins[ui32Pin] == ui32Funcsel) { uint32_t ui32Outcfg; uint8_t ui8CEtbl; @@ -502,9 +490,9 @@ am_hal_gpio_pinconfig(uint32_t ui32Pin, am_hal_gpio_pincfg_t bfGpioCfg) // Valid uNCE values are 0-3 (uNCE is a 2-bit field). // Valid uIOMnum are 0-6 (0-5 for IOMs, 6 for MSPI, 7 is invalid). // - if ( bfGpioCfg.uIOMnum > IOMNUM_MAX ) + if (bfGpioCfg.uIOMnum > IOMNUM_MAX) { - return AM_HAL_GPIO_ERR_INVCE; // Invalid CE specified + return AM_HAL_GPIO_ERR_INVCE; // Invalid CE specified } #endif // AM_HAL_DISABLE_API_VALIDATION @@ -513,24 +501,24 @@ am_hal_gpio_pinconfig(uint32_t ui32Pin, am_hal_gpio_pincfg_t bfGpioCfg) // the OUTCFG value by looking for that value in the pin row. // ui8CEtbl = (bfGpioCfg.uIOMnum << 4) | bfGpioCfg.uNCE; - for ( ui32Outcfg = 0; ui32Outcfg < 4; ui32Outcfg++ ) + for (ui32Outcfg = 0; ui32Outcfg < 4; ui32Outcfg++) { - if ( g_ui8NCEtable[ui32Pin][ui32Outcfg] == ui8CEtbl ) + if (g_ui8NCEtable[ui32Pin][ui32Outcfg] == ui8CEtbl) { break; } } #ifndef AM_HAL_DISABLE_API_VALIDATION - if ( ui32Outcfg >= 4 ) + if (ui32Outcfg >= 4) { return AM_HAL_GPIO_ERR_INVCEPIN; } #endif // AM_HAL_DISABLE_API_VALIDATION - ui32GPCfg |= (ui32Outcfg << GPIOCFG_FLD_OUTCFG_S) | - (bfGpioCfg.eCEpol << GPIOCFG_FLD_INTD_S) | - (0 << GPIOCFG_FLD_INCFG_S); + ui32GPCfg |= (ui32Outcfg << GPIOCFG_FLD_OUTCFG_S) | + (bfGpioCfg.eCEpol << GPIOCFG_FLD_INTD_S) | + (0 << GPIOCFG_FLD_INCFG_S); } else { @@ -547,12 +535,12 @@ am_hal_gpio_pinconfig(uint32_t ui32Pin, am_hal_gpio_pincfg_t bfGpioCfg) // Bit0 of eIntDir maps to GPIOCFG.INTD (b3). // Bit1 of eIntDir maps to GPIOCFG.INCFG (b0). // - ui32GPCfg |= (bfGpioCfg.eGPOutcfg << GPIOCFG_FLD_OUTCFG_S) | - (((bfGpioCfg.eIntDir >> 0) & 0x1) << GPIOCFG_FLD_INTD_S) | + ui32GPCfg |= (bfGpioCfg.eGPOutcfg << GPIOCFG_FLD_OUTCFG_S) | + (((bfGpioCfg.eIntDir >> 0) & 0x1) << GPIOCFG_FLD_INTD_S) | (((bfGpioCfg.eIntDir >> 1) & 0x1) << GPIOCFG_FLD_INCFG_S); - if ( (bfGpioCfg.eGPOutcfg == AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL) || - pincfg_equ(&bfGpioCfg, (void*)&g_AM_HAL_GPIO_DISABLE) ) + if ((bfGpioCfg.eGPOutcfg == AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL) || + pincfg_equ(&bfGpioCfg, (void *)&g_AM_HAL_GPIO_DISABLE)) { // // For pushpull configurations, we must be sure to clear the ENABLE @@ -576,34 +564,34 @@ am_hal_gpio_pinconfig(uint32_t ui32Pin, am_hal_gpio_pincfg_t bfGpioCfg) // If eIntDir is provided, eGPRdZero is ignored and can only be // achieved via the AM_HAL_GPIO_PIN_INTDIR_NONE setting. // - if ( bfGpioCfg.eIntDir == 0 ) + if (bfGpioCfg.eIntDir == 0) { ui32GPCfg &= ~(1 << GPIOCFG_FLD_INCFG_S); ui32GPCfg |= (bfGpioCfg.eGPRdZero << GPIOCFG_FLD_INCFG_S); } } - switch ( bfGpioCfg.eDriveStrength ) + switch (bfGpioCfg.eDriveStrength) { - // DRIVESTRENGTH is a 2-bit field. - // bit0 maps to bit2 of a PADREG field. - // bit1 maps to bit0 of an ALTPADCFG field. - case AM_HAL_GPIO_PIN_DRIVESTRENGTH_2MA: - ui32Padreg |= (0 << PADREG_FLD_DRVSTR_S); - ui32AltPadCfg |= (0 << 0); - break; - case AM_HAL_GPIO_PIN_DRIVESTRENGTH_4MA: - ui32Padreg |= (1 << PADREG_FLD_DRVSTR_S); - ui32AltPadCfg |= (0 << 0); - break; - case AM_HAL_GPIO_PIN_DRIVESTRENGTH_8MA: - ui32Padreg |= (0 << PADREG_FLD_DRVSTR_S); - ui32AltPadCfg |= (1 << 0); - break; - case AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA: - ui32Padreg |= (1 << PADREG_FLD_DRVSTR_S); - ui32AltPadCfg |= (1 << 0); - break; + // DRIVESTRENGTH is a 2-bit field. + // bit0 maps to bit2 of a PADREG field. + // bit1 maps to bit0 of an ALTPADCFG field. + case AM_HAL_GPIO_PIN_DRIVESTRENGTH_2MA: + ui32Padreg |= (0 << PADREG_FLD_DRVSTR_S); + ui32AltPadCfg |= (0 << 0); + break; + case AM_HAL_GPIO_PIN_DRIVESTRENGTH_4MA: + ui32Padreg |= (1 << PADREG_FLD_DRVSTR_S); + ui32AltPadCfg |= (0 << 0); + break; + case AM_HAL_GPIO_PIN_DRIVESTRENGTH_8MA: + ui32Padreg |= (0 << PADREG_FLD_DRVSTR_S); + ui32AltPadCfg |= (1 << 0); + break; + case AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA: + ui32Padreg |= (1 << PADREG_FLD_DRVSTR_S); + ui32AltPadCfg |= (1 << 0); + break; } // @@ -615,25 +603,25 @@ am_hal_gpio_pinconfig(uint32_t ui32Pin, am_hal_gpio_pincfg_t bfGpioCfg) uint32_t ui32GPCfgClearMask, ui32PadClearMask; uint32_t ui32GPCfgShft, ui32PadShft; - ui32GPCfgAddr = AM_REGADDR(GPIO, CFGA) + ((ui32Pin >> 1) & ~0x3); - ui32PadregAddr = AM_REGADDR(GPIO, PADREGA) + (ui32Pin & ~0x3); - ui32AltpadAddr = AM_REGADDR(GPIO, ALTPADCFGA) + (ui32Pin & ~0x3); + ui32GPCfgAddr = AM_REGADDR(GPIO, CFGA) + ((ui32Pin >> 1) & ~0x3); + ui32PadregAddr = AM_REGADDR(GPIO, PADREGA) + (ui32Pin & ~0x3); + ui32AltpadAddr = AM_REGADDR(GPIO, ALTPADCFGA) + (ui32Pin & ~0x3); - ui32GPCfgShft = ((ui32Pin & 0x7) << 2); - ui32PadShft = ((ui32Pin & 0x3) << 3); - ui32GPCfgClearMask = ~((uint32_t)0xF << ui32GPCfgShft); - ui32PadClearMask = ~((uint32_t)0xFF << ui32PadShft); + ui32GPCfgShft = ((ui32Pin & 0x7) << 2); + ui32PadShft = ((ui32Pin & 0x3) << 3); + ui32GPCfgClearMask = ~((uint32_t)0xF << ui32GPCfgShft); + ui32PadClearMask = ~((uint32_t)0xFF << ui32PadShft); // // Get the new values into their rightful bit positions. // - ui32Padreg <<= ui32PadShft; + ui32Padreg <<= ui32PadShft; ui32AltPadCfg <<= ui32PadShft; - ui32GPCfg <<= ui32GPCfgShft; + ui32GPCfg <<= ui32GPCfgShft; AM_CRITICAL_BEGIN - if ( bClearEnable ) + if (bClearEnable) { // // We're configuring a mode that requires clearing the Enable bit. @@ -643,9 +631,9 @@ am_hal_gpio_pinconfig(uint32_t ui32Pin, am_hal_gpio_pincfg_t bfGpioCfg) GPIO->PADKEY = GPIO_PADKEY_PADKEY_Key; - AM_REGVAL(ui32PadregAddr) = (AM_REGVAL(ui32PadregAddr) & ui32PadClearMask) | ui32Padreg; - AM_REGVAL(ui32GPCfgAddr) = (AM_REGVAL(ui32GPCfgAddr) & ui32GPCfgClearMask) | ui32GPCfg; - AM_REGVAL(ui32AltpadAddr) = (AM_REGVAL(ui32AltpadAddr) & ui32PadClearMask) | ui32AltPadCfg; + AM_REGVAL(ui32PadregAddr) = (AM_REGVAL(ui32PadregAddr) & ui32PadClearMask) | ui32Padreg; + AM_REGVAL(ui32GPCfgAddr) = (AM_REGVAL(ui32GPCfgAddr) & ui32GPCfgClearMask) | ui32GPCfg; + AM_REGVAL(ui32AltpadAddr) = (AM_REGVAL(ui32AltpadAddr) & ui32PadClearMask) | ui32AltPadCfg; GPIO->PADKEY = 0; @@ -686,9 +674,9 @@ am_hal_gpio_fast_pinconfig(uint64_t ui64PinMask, uint32_t ux, ui32pinnum, ui32retval, ui32Mask; #ifndef AM_HAL_DISABLE_API_VALIDATION - if ( (ui64PinMask & ~(((uint64_t)1 << AM_HAL_GPIO_MAX_PADS) - 1)) || - (num_bits64(ui64PinMask) > 8) || - (bfGpioCfg.eGPOutcfg == AM_HAL_GPIO_PIN_OUTCFG_TRISTATE) ) + if ((ui64PinMask & ~(((uint64_t)1 << AM_HAL_GPIO_MAX_PADS) - 1)) || + (num_bits64(ui64PinMask) > 8) || + (bfGpioCfg.eGPOutcfg == AM_HAL_GPIO_PIN_OUTCFG_TRISTATE)) { return AM_HAL_STATUS_INVALID_ARG; } @@ -701,9 +689,9 @@ am_hal_gpio_fast_pinconfig(uint64_t ui64PinMask, ui32Mask = 0; ui32pinnum = 0; ux = 0; - while ( ui64PinMask ) + while (ui64PinMask) { - if ( ui64PinMask & 0x1 ) + if (ui64PinMask & 0x1) { // // It is assumed that the caller will have disabled Fast GPIO and @@ -714,7 +702,7 @@ am_hal_gpio_fast_pinconfig(uint64_t ui64PinMask, // Configure the pin. // ui32retval = am_hal_gpio_pinconfig(ui32pinnum, bfGpioCfg); - if ( ui32retval ) + if (ui32retval) { return ui32retval; } @@ -726,12 +714,12 @@ am_hal_gpio_fast_pinconfig(uint64_t ui64PinMask, // am_hal_gpio_fastgpio_enable(ui32pinnum); - if ( ui32Masks ) + if (ui32Masks) { - ui32Masks[ux + 0] = _VAL2FLD(APBDMA_BBSETCLEAR_SET, ui32Mask); + ui32Masks[ux + 0] = _VAL2FLD(APBDMA_BBSETCLEAR_SET, ui32Mask); ui32Masks[ux + 1] = _VAL2FLD(APBDMA_BBSETCLEAR_CLEAR, ui32Mask); } - ux += 2; // Get next indexes + ux += 2; // Get next indexes } ui32pinnum++; ui64PinMask >>= 1; @@ -767,12 +755,12 @@ am_hal_gpio_state_read(uint32_t ui32Pin, uint32_t ui32BaseAddr, ui32Shift; #ifndef AM_HAL_DISABLE_API_VALIDATION - if ( pui32ReadState == NULL ) + if (pui32ReadState == NULL) { return AM_HAL_STATUS_INVALID_ARG; } - if ( ui32Pin >= AM_HAL_GPIO_MAX_PADS ) + if (ui32Pin >= AM_HAL_GPIO_MAX_PADS) { *pui32ReadState = ui32ReadValue; return AM_HAL_STATUS_OUT_OF_RANGE; @@ -782,30 +770,30 @@ am_hal_gpio_state_read(uint32_t ui32Pin, // // Compute base address + offset of 0 or 4. // - ui32BaseAddr = ((ui32Pin & 0x20) >> 3); // 0 or 4 - ui32Shift = ui32Pin & 0x1F; + ui32BaseAddr = ((ui32Pin & 0x20) >> 3); // 0 or 4 + ui32Shift = ui32Pin & 0x1F; - switch ( eReadType ) + switch (eReadType) { - case AM_HAL_GPIO_INPUT_READ: - // - // Assumes eIntDir != AM_HAL_GPIO_PIN_INTDIR_NONE && - // eIntDir != AM_HAL_GPIO_PIN_INTDIR_BOTH - // If either of those configs are set, returns 0. - // - ui32ReadValue = AM_REGVAL(AM_REGADDR(GPIO, RDA) + ui32BaseAddr); - ui32ReadValue = (ui32ReadValue >> ui32Shift) & 0x01; - break; - case AM_HAL_GPIO_OUTPUT_READ: - ui32ReadValue = AM_REGVAL(AM_REGADDR(GPIO, WTA) + ui32BaseAddr); - ui32ReadValue = (ui32ReadValue >> ui32Shift) & 0x01; - break; - case AM_HAL_GPIO_ENABLE_READ: - ui32ReadValue = AM_REGVAL(AM_REGADDR(GPIO, ENA) + ui32BaseAddr); - ui32ReadValue = (ui32ReadValue >> ui32Shift) & 0x01; - break; - default: - return AM_HAL_STATUS_INVALID_ARG; + case AM_HAL_GPIO_INPUT_READ: + // + // Assumes eIntDir != AM_HAL_GPIO_PIN_INTDIR_NONE && + // eIntDir != AM_HAL_GPIO_PIN_INTDIR_BOTH + // If either of those configs are set, returns 0. + // + ui32ReadValue = AM_REGVAL(AM_REGADDR(GPIO, RDA) + ui32BaseAddr); + ui32ReadValue = (ui32ReadValue >> ui32Shift) & 0x01; + break; + case AM_HAL_GPIO_OUTPUT_READ: + ui32ReadValue = AM_REGVAL(AM_REGADDR(GPIO, WTA) + ui32BaseAddr); + ui32ReadValue = (ui32ReadValue >> ui32Shift) & 0x01; + break; + case AM_HAL_GPIO_ENABLE_READ: + ui32ReadValue = AM_REGVAL(AM_REGADDR(GPIO, ENA) + ui32BaseAddr); + ui32ReadValue = (ui32ReadValue >> ui32Shift) & 0x01; + break; + default: + return AM_HAL_STATUS_INVALID_ARG; } *pui32ReadState = ui32ReadValue; @@ -840,46 +828,46 @@ am_hal_gpio_state_write(uint32_t ui32Pin, am_hal_gpio_write_type_e eWriteType) uint32_t ui32Return = AM_HAL_STATUS_SUCCESS; #ifndef AM_HAL_DISABLE_API_VALIDATION - if ( ui32Pin >= AM_HAL_GPIO_MAX_PADS ) + if (ui32Pin >= AM_HAL_GPIO_MAX_PADS) { return AM_HAL_STATUS_OUT_OF_RANGE; } - if ( eWriteType > AM_HAL_GPIO_OUTPUT_TRISTATE_TOGGLE ) + if (eWriteType > AM_HAL_GPIO_OUTPUT_TRISTATE_TOGGLE) { return AM_HAL_STATUS_INVALID_ARG; } #endif // AM_HAL_DISABLE_API_VALIDATION ui32Mask = (uint32_t)0x1 << (ui32Pin % 32); - ui32Off = (ui32Pin & 0x20) >> 3; // 0 or 4 + ui32Off = (ui32Pin & 0x20) >> 3; // 0 or 4 AM_CRITICAL_BEGIN; - switch ( eWriteType ) + switch (eWriteType) { - case AM_HAL_GPIO_OUTPUT_SET: // Write a one to a GPIO. - AM_REGVAL(AM_REGADDR(GPIO, WTSA) + ui32Off) = ui32Mask; - break; - case AM_HAL_GPIO_OUTPUT_CLEAR: // Write a zero to a GPIO. - AM_REGVAL(AM_REGADDR(GPIO, WTCA) + ui32Off) = ui32Mask; - break; - case AM_HAL_GPIO_OUTPUT_TOGGLE: // Toggle the GPIO value. - AM_REGVAL(AM_REGADDR(GPIO, WTA) + ui32Off) ^= ui32Mask; - break; - case AM_HAL_GPIO_OUTPUT_TRISTATE_ENABLE: // Enable a tri-state GPIO. - AM_REGVAL(AM_REGADDR(GPIO, ENSA) + ui32Off) = ui32Mask; - break; - case AM_HAL_GPIO_OUTPUT_TRISTATE_DISABLE: // Disable a tri-state GPIO. - AM_REGVAL(AM_REGADDR(GPIO, ENCA) + ui32Off) = ui32Mask; - break; - case AM_HAL_GPIO_OUTPUT_TRISTATE_TOGGLE: // Toggle a tri-state GPIO. - AM_REGVAL(AM_REGADDR(GPIO, ENCA) + ui32Off) ^= ui32Mask; - break; - default: - // Type values were validated on entry. - // We can't return from here because we're in a critical section. - ui32Return = AM_HAL_STATUS_INVALID_ARG; - break; + case AM_HAL_GPIO_OUTPUT_SET: // Write a one to a GPIO. + AM_REGVAL(AM_REGADDR(GPIO, WTSA) + ui32Off) = ui32Mask; + break; + case AM_HAL_GPIO_OUTPUT_CLEAR: // Write a zero to a GPIO. + AM_REGVAL(AM_REGADDR(GPIO, WTCA) + ui32Off) = ui32Mask; + break; + case AM_HAL_GPIO_OUTPUT_TOGGLE: // Toggle the GPIO value. + AM_REGVAL(AM_REGADDR(GPIO, WTA) + ui32Off) ^= ui32Mask; + break; + case AM_HAL_GPIO_OUTPUT_TRISTATE_ENABLE: // Enable a tri-state GPIO. + AM_REGVAL(AM_REGADDR(GPIO, ENSA) + ui32Off) = ui32Mask; + break; + case AM_HAL_GPIO_OUTPUT_TRISTATE_DISABLE: // Disable a tri-state GPIO. + AM_REGVAL(AM_REGADDR(GPIO, ENCA) + ui32Off) = ui32Mask; + break; + case AM_HAL_GPIO_OUTPUT_TRISTATE_TOGGLE: // Toggle a tri-state GPIO. + AM_REGVAL(AM_REGADDR(GPIO, ENCA) + ui32Off) ^= ui32Mask; + break; + default: + // Type values were validated on entry. + // We can't return from here because we're in a critical section. + ui32Return = AM_HAL_STATUS_INVALID_ARG; + break; } AM_CRITICAL_END; @@ -899,7 +887,7 @@ am_hal_gpio_interrupt_enable(uint64_t ui64InterruptMask) // // Check parameters // - if ( ui64InterruptMask & ~(((uint64_t)1 << AM_HAL_GPIO_MAX_PADS) - 1) ) + if (ui64InterruptMask & ~(((uint64_t)1 << AM_HAL_GPIO_MAX_PADS) - 1)) { return AM_HAL_STATUS_OUT_OF_RANGE; } @@ -934,7 +922,7 @@ am_hal_gpio_interrupt_disable(uint64_t ui64InterruptMask) // // Check parameters // - if ( ui64InterruptMask & ~(((uint64_t)1 << AM_HAL_GPIO_MAX_PADS) - 1) ) + if (ui64InterruptMask & ~(((uint64_t)1 << AM_HAL_GPIO_MAX_PADS) - 1)) { return AM_HAL_STATUS_OUT_OF_RANGE; } @@ -969,7 +957,7 @@ am_hal_gpio_interrupt_clear(uint64_t ui64InterruptMask) // // Check parameters // - if ( ui64InterruptMask & ~(((uint64_t)1 << AM_HAL_GPIO_MAX_PADS) - 1) ) + if (ui64InterruptMask & ~(((uint64_t)1 << AM_HAL_GPIO_MAX_PADS) - 1)) { return AM_HAL_STATUS_OUT_OF_RANGE; } @@ -1004,7 +992,7 @@ am_hal_gpio_interrupt_status_get(bool bEnabledOnly, uint64_t *pui64IntStatus) uint64_t ui64RetVal, ui64Mask; #ifndef AM_HAL_DISABLE_API_VALIDATION - if ( pui64IntStatus == NULL ) + if (pui64IntStatus == NULL) { return AM_HAL_STATUS_INVALID_ARG; } @@ -1013,20 +1001,20 @@ am_hal_gpio_interrupt_status_get(bool bEnabledOnly, uint64_t *pui64IntStatus) // // Initialize variable outside critical section // - ui64Mask = 0xFFFFFFFFFFFFFFFF; + ui64Mask = 0xFFFFFFFFFFFFFFFF; // // Combine upper or lower GPIO words into one 64 bit return value. // AM_CRITICAL_BEGIN - ui64RetVal = ((uint64_t)GPIO->INT1STAT) << 32; + ui64RetVal = ((uint64_t)GPIO->INT1STAT) << 32; ui64RetVal |= ((uint64_t)GPIO->INT0STAT) << 0; - if ( bEnabledOnly ) + if (bEnabledOnly) { - ui64Mask = ((uint64_t)GPIO->INT1EN) << 32; - ui64Mask |= ((uint64_t)GPIO->INT0EN) << 0; + ui64Mask = ((uint64_t)GPIO->INT1EN) << 32; + ui64Mask |= ((uint64_t)GPIO->INT0EN) << 0; } ui64RetVal &= ui64Mask; @@ -1055,12 +1043,12 @@ am_hal_gpio_interrupt_register(uint32_t ui32GPIONumber, // // Check parameters // - if ( ui32GPIONumber >= AM_HAL_GPIO_MAX_PADS ) + if (ui32GPIONumber >= AM_HAL_GPIO_MAX_PADS) { return AM_HAL_STATUS_OUT_OF_RANGE; } - if ( pfnHandler == NULL ) + if (pfnHandler == NULL) { return AM_HAL_STATUS_INVALID_ARG; } @@ -1095,12 +1083,12 @@ am_hal_gpio_interrupt_service(uint64_t ui64Status) // // Check parameters // - if ( ui64Status & ~(((uint64_t)1 << AM_HAL_GPIO_MAX_PADS) - 1) ) + if (ui64Status & ~(((uint64_t)1 << AM_HAL_GPIO_MAX_PADS) - 1)) { return AM_HAL_STATUS_OUT_OF_RANGE; } - if ( ui64Status == 0 ) + if (ui64Status == 0) { return AM_HAL_STATUS_FAIL; } @@ -1113,14 +1101,14 @@ am_hal_gpio_interrupt_service(uint64_t ui64Status) // (The order of handling upper or lower bits is somewhat arbitrary.) // ui32Cnt = 0; - while ( ui32Cnt < 33 ) + while (ui32Cnt < 33) { // // Get upper or lower status word. // ui32Status = (uint32_t)(ui64Status >> ui32Cnt); - while ( ui32Status ) + while (ui32Status) { // // We need to FFS (Find First Set). We can easily zero-base FFS @@ -1145,7 +1133,7 @@ am_hal_gpio_interrupt_service(uint64_t ui64Status) // registered for this particular bit. // pfnHandler = gpio_ppfnHandlers[ui32Cnt + ui32FFS]; - if ( pfnHandler ) + if (pfnHandler) { // // If we found an interrupt handler routine, call it now. @@ -1171,6 +1159,327 @@ am_hal_gpio_interrupt_service(uint64_t ui64Status) } // am_hal_gpio_interrupt_service() +//***************************************************************************** +// +//! @brief Configure an Apollo3 pin. +//! +//! @param ui32Pin - pin number to be configured. +//! @param ui32Config - Contains multiple descriptor fields. +//! +//! This function configures a pin according to the parameters in ui32Config. +//! All parameters are validated, and the given pin is configured according +//! to the designated parameters. +//! +//! @return Status. +// +//***************************************************************************** +uint32_t ap3_hal_gpio_pinconfig_partial(uint32_t ui32Pin, am_hal_gpio_pincfg_t bfGpioCfg, am_hal_gpio_pincfg_allow_t sAllowableChanges) //am_hal_gpio_pincfg_t bfGpioCfgMsk) +{ + uint32_t ui32Padreg, ui32AltPadCfg, ui32GPCfg; + uint32_t ui32Funcsel, ui32PowerSw; + uint8_t padRegMask = 0, GPCfgMask = 0, altPadCfgMask = 0; + bool bClearEnable = false; + +#ifndef AM_HAL_DISABLE_API_VALIDATION + if (ui32Pin >= AM_HAL_GPIO_MAX_PADS) + { + return AM_HAL_STATUS_INVALID_ARG; + } +#endif // AM_HAL_DISABLE_API_VALIDATION + ap3_gpio_get_pinconfig_bitmasks(sAllowableChanges, &padRegMask, &GPCfgMask, &altPadCfgMask); + // + // Initialize the PADREG accumulator variables. + // + ui32GPCfg = ui32Padreg = ui32AltPadCfg = 0; + + // + // Get the requested function and/or power switch. + // + ui32Funcsel = bfGpioCfg.uFuncSel; + ui32PowerSw = bfGpioCfg.ePowerSw; + + ui32Padreg |= ui32Funcsel << PADREG_FLD_FNSEL_S; + + // + // Check for invalid configuration requests. + // + if (bfGpioCfg.ePullup != AM_HAL_GPIO_PIN_PULLUP_NONE) + { + // + // This setting is needed for all pullup settings including + // AM_HAL_GPIO_PIN_PULLUP_WEAK and AM_HAL_GPIO_PIN_PULLDOWN. + // + ui32Padreg |= (0x1 << PADREG_FLD_PULLUP_S); + + // + // Check for specific pullup or pulldown settings. + // + if ((bfGpioCfg.ePullup >= AM_HAL_GPIO_PIN_PULLUP_1_5K) && + (bfGpioCfg.ePullup <= AM_HAL_GPIO_PIN_PULLUP_24K)) + { + ui32Padreg |= ((bfGpioCfg.ePullup - AM_HAL_GPIO_PIN_PULLUP_1_5K) << PADREG_FLD_76_S); +#ifndef AM_HAL_DISABLE_API_VALIDATION + if (!(g_ui8Bit76Capabilities[ui32Pin] & CAP_PUP)) + { + return AM_HAL_GPIO_ERR_PULLUP; + } + } + else if (bfGpioCfg.ePullup == AM_HAL_GPIO_PIN_PULLDOWN) + { + if (ui32Pin != 20) + { + return AM_HAL_GPIO_ERR_PULLDOWN; + } + } + else if (bfGpioCfg.ePullup == AM_HAL_GPIO_PIN_PULLUP_WEAK) + { + // + // All pads except 20 support a weak pullup, for which we only need + // to set PADnPULL and clear 7:6 (already done at this point). + // + if (ui32Pin == 20) + { + return AM_HAL_GPIO_ERR_PULLUP; + } +#endif // AM_HAL_DISABLE_API_VALIDATION + } + } + + // + // Check if requesting a power switch pin + // + if (ui32PowerSw != AM_HAL_GPIO_PIN_POWERSW_NONE) + { + if ((ui32PowerSw == AM_HAL_GPIO_PIN_POWERSW_VDD) && + (g_ui8Bit76Capabilities[ui32Pin] & CAP_VDD)) + { + ui32Padreg |= 0x1 << PADREG_FLD_76_S; + } + else if ((ui32PowerSw == AM_HAL_GPIO_PIN_POWERSW_VSS) && + (g_ui8Bit76Capabilities[ui32Pin] & CAP_VSS)) + { + ui32Padreg |= 0x2 << PADREG_FLD_76_S; + } + else + { + return AM_HAL_GPIO_ERR_PWRSW; + } + } + + // + // Depending on the selected pin and FNSEL, determine if INPEN needs to be set. + // + ui32Padreg |= (g_ui8Inpen[ui32Pin] & (1 << ui32Funcsel)) ? (1 << PADREG_FLD_INPEN_S) : 0; + + // + // Configure ui32GpCfg based on whether nCE requested. + // + if (g_ui8nCEpins[ui32Pin] == ui32Funcsel) + { + uint32_t ui32Outcfg; + uint8_t ui8CEtbl; + +#ifndef AM_HAL_DISABLE_API_VALIDATION + // + // User is configuring a nCE. Verify the requested settings and set the + // polarity and OUTCFG values (INCFG is not used here and should be 0). + // Valid uNCE values are 0-3 (uNCE is a 2-bit field). + // Valid uIOMnum are 0-6 (0-5 for IOMs, 6 for MSPI, 7 is invalid). + // + if (bfGpioCfg.uIOMnum > IOMNUM_MAX) + { + return AM_HAL_GPIO_ERR_INVCE; // Invalid CE specified + } +#endif // AM_HAL_DISABLE_API_VALIDATION + + // + // Construct the entry we expect to find in the table. We can determine + // the OUTCFG value by looking for that value in the pin row. + // + ui8CEtbl = (bfGpioCfg.uIOMnum << 4) | bfGpioCfg.uNCE; + for (ui32Outcfg = 0; ui32Outcfg < 4; ui32Outcfg++) + { + if (g_ui8NCEtable[ui32Pin][ui32Outcfg] == ui8CEtbl) + { + break; + } + } + +#ifndef AM_HAL_DISABLE_API_VALIDATION + if (ui32Outcfg >= 4) + { + return AM_HAL_GPIO_ERR_INVCEPIN; + } +#endif // AM_HAL_DISABLE_API_VALIDATION + + ui32GPCfg |= (ui32Outcfg << GPIOCFG_FLD_OUTCFG_S) | + (bfGpioCfg.eCEpol << GPIOCFG_FLD_INTD_S) | + (0 << GPIOCFG_FLD_INCFG_S); + } + else + { + // + // It's not nCE, it's one of the other funcsels. + // Start by setting the value of the requested GPIO input. + // + ui32Padreg |= (bfGpioCfg.eGPInput << PADREG_FLD_INPEN_S); + + // + // Map the requested interrupt direction settings into the Apollo3 + // GPIOCFG register field, which is a 4-bit field: + // [INTD(1):OUTCFG(2):INCFG(1)]. + // Bit0 of eIntDir maps to GPIOCFG.INTD (b3). + // Bit1 of eIntDir maps to GPIOCFG.INCFG (b0). + // + ui32GPCfg |= (bfGpioCfg.eGPOutcfg << GPIOCFG_FLD_OUTCFG_S) | + (((bfGpioCfg.eIntDir >> 0) & 0x1) << GPIOCFG_FLD_INTD_S) | + (((bfGpioCfg.eIntDir >> 1) & 0x1) << GPIOCFG_FLD_INCFG_S); + + if ((bfGpioCfg.eGPOutcfg == AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL) || + pincfg_equ(&bfGpioCfg, (void *)&g_AM_HAL_GPIO_DISABLE)) + { + // + // For pushpull configurations, we must be sure to clear the ENABLE + // bit. In pushpull, these bits turn on FAST GPIO. For regular + // GPIO, they must be clear. + // + bClearEnable = true; + } + + // + // There is some overlap between eGPRdZero and eIntDir as both settings + // utilize the overloaded INCFG bit. + // Therefore the two fields should be used in a mutually exclusive + // manner. For flexibility however they are not disallowed because + // their functionality is dependent on FUNCSEL and whether interrupts + // are used. + // + // In the vein of mutual exclusion, eGPRdZero is primarily intended for + // use when GPIO interrupts are not in use and can be used when no + // eIntDir setting is provided. + // If eIntDir is provided, eGPRdZero is ignored and can only be + // achieved via the AM_HAL_GPIO_PIN_INTDIR_NONE setting. + // + if (bfGpioCfg.eIntDir == 0) + { + ui32GPCfg &= ~(1 << GPIOCFG_FLD_INCFG_S); + ui32GPCfg |= (bfGpioCfg.eGPRdZero << GPIOCFG_FLD_INCFG_S); + } + } + + switch (bfGpioCfg.eDriveStrength) + { + // DRIVESTRENGTH is a 2-bit field. + // bit0 maps to bit2 of a PADREG field. + // bit1 maps to bit0 of an ALTPADCFG field. + case AM_HAL_GPIO_PIN_DRIVESTRENGTH_2MA: + ui32Padreg |= (0 << PADREG_FLD_DRVSTR_S); + ui32AltPadCfg |= (0 << 0); + break; + case AM_HAL_GPIO_PIN_DRIVESTRENGTH_4MA: + ui32Padreg |= (1 << PADREG_FLD_DRVSTR_S); + ui32AltPadCfg |= (0 << 0); + break; + case AM_HAL_GPIO_PIN_DRIVESTRENGTH_8MA: + ui32Padreg |= (0 << PADREG_FLD_DRVSTR_S); + ui32AltPadCfg |= (1 << 0); + break; + case AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA: + ui32Padreg |= (1 << PADREG_FLD_DRVSTR_S); + ui32AltPadCfg |= (1 << 0); + break; + } + + // + // At this point, the 3 configuration variables, ui32GPCfg, ui32Padreg, + // and ui32AltPadCfg values are set (at bit position 0) and ready to write + // to their respective register bitfields. + // + uint32_t ui32GPCfgAddr, ui32PadregAddr, ui32AltpadAddr; + uint32_t ui32GPCfgClearMask, ui32PadClearMask, ui32AltPadClearMask; + uint32_t ui32GPCfgShft, ui32PadShft; + + ui32GPCfgAddr = AM_REGADDR(GPIO, CFGA) + ((ui32Pin >> 1) & ~0x3); + ui32PadregAddr = AM_REGADDR(GPIO, PADREGA) + (ui32Pin & ~0x3); + ui32AltpadAddr = AM_REGADDR(GPIO, ALTPADCFGA) + (ui32Pin & ~0x3); + + ui32GPCfgShft = ((ui32Pin & 0x7) << 2); + ui32PadShft = ((ui32Pin & 0x3) << 3); + ui32GPCfgClearMask = ~((uint32_t)GPCfgMask << ui32GPCfgShft); + ui32PadClearMask = ~((uint32_t)padRegMask << ui32PadShft); + ui32AltPadClearMask = ~((uint32_t)altPadCfgMask << ui32PadShft); + + // + // Get the new values into their rightful bit positions. + // + ui32Padreg = (ui32Padreg & (uint32_t)padRegMask) << ui32PadShft; + ui32AltPadCfg = (ui32AltPadCfg & (uint32_t)altPadCfgMask) << ui32PadShft; + ui32GPCfg = (ui32GPCfg & (uint32_t)GPCfgMask) << ui32GPCfgShft; + + AM_CRITICAL_BEGIN + + if (bClearEnable) + { + // + // We're configuring a mode that requires clearing the Enable bit. + // + am_hal_gpio_output_tristate_disable(ui32Pin); + } + + GPIO->PADKEY = GPIO_PADKEY_PADKEY_Key; + + AM_REGVAL(ui32PadregAddr) = (AM_REGVAL(ui32PadregAddr) & ui32PadClearMask) | ui32Padreg; + AM_REGVAL(ui32GPCfgAddr) = (AM_REGVAL(ui32GPCfgAddr) & ui32GPCfgClearMask) | ui32GPCfg; + AM_REGVAL(ui32AltpadAddr) = (AM_REGVAL(ui32AltpadAddr) & ui32AltPadClearMask) | ui32AltPadCfg; + + GPIO->PADKEY = 0; + + AM_CRITICAL_END + + return AM_HAL_STATUS_SUCCESS; + +} //ap3_hal_gpio_pinconfig_partial + +void ap3_gpio_get_pinconfig_bitmasks(am_hal_gpio_pincfg_allow_t sAllowableChanges, uint8_t *padRegMask, uint8_t *GPCfgMask, uint8_t *altPadCfgMask) +{ + *padRegMask = 0; + *GPCfgMask = 0; + *altPadCfgMask = 0; + + if (sAllowableChanges.funcSel) + { + *padRegMask |= 0x38; //bits 3-5 PadReg + } + if (sAllowableChanges.powerSw) + { + *padRegMask |= 0xC0; //bits 6 and 7 PadReg + } + if (sAllowableChanges.pullup) + { + *padRegMask |= 0xC1; //bits 6 and 7 and 0 PadReg + } + if (sAllowableChanges.driveStrength) + { + *padRegMask |= 0x04; //bit 2 PadReg + *altPadCfgMask |= 0x10; //bit 4 AltPadReg + } + if (sAllowableChanges.gpOutcfg) + { + *GPCfgMask |= 0x06; //bits 1 and 2 CFGReg + } + if (sAllowableChanges.gpInput) + { + *padRegMask |= 0x02; //bit 1 PadReg + } + if (sAllowableChanges.intDir) + { + *GPCfgMask |= 0x09; //bit 0 and 3 CFGReg + } + if (sAllowableChanges.gprdZero) + { + *GPCfgMask |= 0x01; //bit 0 CFGReg + } +} //***************************************************************************** // diff --git a/targets/TARGET_Ambiq_Micro/mcu/apollo3/hal/am_hal_gpio.h b/targets/TARGET_Ambiq_Micro/mcu/apollo3/hal/am_hal_gpio.h index ff68aba54ef..ea14e767793 100644 --- a/targets/TARGET_Ambiq_Micro/mcu/apollo3/hal/am_hal_gpio.h +++ b/targets/TARGET_Ambiq_Micro/mcu/apollo3/hal/am_hal_gpio.h @@ -15,24 +15,24 @@ // // Copyright (c) 2019, Ambiq Micro // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: -// +// // 1. Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. -// +// // 2. 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. -// +// // 3. Neither the name of the copyright holder nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. -// +// // Third party software included in this distribution is subject to the // additional license terms as defined in the /docs/licenses directory. -// +// // 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 @@ -50,7 +50,7 @@ //***************************************************************************** #ifndef AM_HAL_GPIO_H -#define AM_HAL_GPIO_H 1 +#define AM_HAL_GPIO_H 1 #ifdef __cplusplus extern "C" @@ -60,207 +60,217 @@ extern "C" // // Designate this peripheral. // -#define AM_APOLLO3_GPIO 1 +#define AM_APOLLO3_GPIO 1 // // Maximum number of GPIOs on this device // -#define AM_HAL_GPIO_MAX_PADS (50) +#define AM_HAL_GPIO_MAX_PADS (50) // // Macro to assist with defining a GPIO bit given a GPIO number. // -#define AM_HAL_GPIO_BIT(n) (((uint64_t) 0x1) << n) - -//***************************************************************************** -//! -//! Read types for am_hal_gpio_state_read(). -//! -//***************************************************************************** -typedef enum -{ - AM_HAL_GPIO_INPUT_READ, - AM_HAL_GPIO_OUTPUT_READ, - AM_HAL_GPIO_ENABLE_READ -} am_hal_gpio_read_type_e; - -//***************************************************************************** -//! -//! Write types for am_hal_gpio_state_write(). -//! -//***************************************************************************** -typedef enum -{ - AM_HAL_GPIO_OUTPUT_CLEAR, - AM_HAL_GPIO_OUTPUT_SET, - AM_HAL_GPIO_OUTPUT_TOGGLE, - AM_HAL_GPIO_OUTPUT_TRISTATE_DISABLE, - AM_HAL_GPIO_OUTPUT_TRISTATE_ENABLE, - AM_HAL_GPIO_OUTPUT_TRISTATE_TOGGLE -} am_hal_gpio_write_type_e; - - -//***************************************************************************** -//! -//! Types for ui32GpioCfg bitfields in am_hal_gpio_pinconfig(). -//! -//***************************************************************************** -//! -//! Power Switch configuration: am_hal_gpio_pincfg_t.ePowerSw enums -//! -typedef enum -{ - AM_HAL_GPIO_PIN_POWERSW_NONE, - AM_HAL_GPIO_PIN_POWERSW_VDD, - AM_HAL_GPIO_PIN_POWERSW_VSS, - AM_HAL_GPIO_PIN_POWERSW_INVALID, -} am_hal_gpio_powersw_e; - -//! -//! Pullup configuration: am_hal_gpio_pincfg_t.ePullup enums -//! -typedef enum -{ - // - //! Define pullup enums. - //! The 1.5K - 24K pullup values are valid for select I2C enabled pads. - //! For Apollo3 these pins are 0-1,5-6,8-9,25,27,39-40,42-43,48-49. - //! The "weak" value is used for almost every other pad except pin 20. - // - AM_HAL_GPIO_PIN_PULLUP_NONE = 0x00, - AM_HAL_GPIO_PIN_PULLUP_WEAK, - AM_HAL_GPIO_PIN_PULLUP_1_5K, - AM_HAL_GPIO_PIN_PULLUP_6K, - AM_HAL_GPIO_PIN_PULLUP_12K, - AM_HAL_GPIO_PIN_PULLUP_24K, - AM_HAL_GPIO_PIN_PULLDOWN -} am_hal_gpio_pullup_e; - -//! -//! Pad Drive Strength configuration: am_hal_gpio_pincfg_t.eDriveStrength enums -//! -typedef enum -{ - // - //! DRIVESTRENGTH is a 2-bit field. - //! bit0 maps to bit2 of a PADREG field. - //! bit1 maps to bit0 of an ALTPADCFG field. - // - AM_HAL_GPIO_PIN_DRIVESTRENGTH_2MA = 0x0, - AM_HAL_GPIO_PIN_DRIVESTRENGTH_4MA = 0x1, - AM_HAL_GPIO_PIN_DRIVESTRENGTH_8MA = 0x2, - AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA = 0x3 -} am_hal_gpio_drivestrength_e; - -//! -//! OUTCFG pad configuration: am_hal_gpio_pincfg_t.eGPOutcfg enums -//! Applies only to GPIO configured pins. -//! Ultimately maps to GPIOCFG.OUTCFG, bits [2:1]. -//! -typedef enum -{ - AM_HAL_GPIO_PIN_OUTCFG_DISABLE = 0x0, - AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL = 0x1, - AM_HAL_GPIO_PIN_OUTCFG_OPENDRAIN = 0x2, - AM_HAL_GPIO_PIN_OUTCFG_TRISTATE = 0x3 -} am_hal_gpio_outcfg_e; - -//! -//! GPIO input configuration: am_hal_gpio_pincfg_t.eGPInput enums -//! Applies only to GPIO configured pins! -//! Ultimately maps to PADREG.INPEN, bit1. -//! -typedef enum -{ - AM_HAL_GPIO_PIN_INPUT_AUTO = 0x0, - AM_HAL_GPIO_PIN_INPUT_NONE = 0x0, - AM_HAL_GPIO_PIN_INPUT_ENABLE = 0x1 -} am_hal_gpio_input_e; - -//! -//! GPIO interrupt direction configuration: am_hal_gpio_pincfg_t.eIntDir enums -//! Note: Setting INTDIR_NONE has the side-effect of disabling being able to -//! read a pin - the pin will always read back as 0. -//! -typedef enum -{ - // Bit1 of these values maps to GPIOCFG.INCFG (b0). - // Bit0 of these values maps to GPIOCFG.INTD (b3). - AM_HAL_GPIO_PIN_INTDIR_LO2HI = 0x0, - AM_HAL_GPIO_PIN_INTDIR_HI2LO = 0x1, - AM_HAL_GPIO_PIN_INTDIR_NONE = 0x2, - AM_HAL_GPIO_PIN_INTDIR_BOTH = 0x3 -} am_hal_gpio_intdir_e; - -//! -//! am_hal_gpio_pincfg_t.eGPRdZero -//! For GPIO configurations (funcsel=3), the pin value can be read or 0 can be -//! forced as the read value. -//! -typedef enum -{ - AM_HAL_GPIO_PIN_RDZERO_READPIN = 0x0, - AM_HAL_GPIO_PIN_RDZERO_ZERO = 0x1 -} am_hal_gpio_readen_e; - -//! -//! nCE polarity configuration: am_hal_gpio_pincfg_t.eCEpol enums -//! -typedef enum -{ - AM_HAL_GPIO_PIN_CEPOL_ACTIVELOW = 0x0, - AM_HAL_GPIO_PIN_CEPOL_ACTIVEHIGH = 0x1 -} am_hal_gpio_cepol_e; - - -// -// Apollo3 usage of bits [7:6] of a PADREG field: -// PULLUPs are available on pins: 0,1,5,6,8,9,25,27,39,40,42,43,48,49 -// RESERVED on pins: 2,4,7,10-24,26,28-35,38,44-47 -// VDD PWR on pins: 3, 36 (b7=0, b6=1) -// VSS PWR on pins: 37,41 (b7=1, b6=0) -// - -//! -//! Define the am_hal_gpio_pinconfig() bitfield structure. -//! uFuncSel a value of 0-7 corresponding to the FNCSEL field of PADREG. -//! ePowerSw: Select pins can be set as a power source or sink. -//! ePullup: Select pins can enable a pullup of varying values. -//! eDriveStrength: Select pins can be set for varying drive strengths. -//! eGPOutcfg: GPIO pin only, corresponds to GPIOCFG.OUTCFG field. -//! eGPInput: GPIO pin only, corresponds to PADREG.INPEN. -//! eGPRdZero: GPIO read zero. Corresponds to GPIOCFG.INCFG. -//! eIntDir: Interrupt direction, l2h, h2l, both, none. -//! eGPRdZero: Read the pin value, or always read the pin as zero. -//! uIOMnum: nCE pin IOMnumber (0-5, or 6 for MSPI) -//! nNCE: Selects the SPI channel (CE) number (0-3) -//! eCEpol: CE polarity. -//! -typedef struct -{ - uint32_t uFuncSel : 3; // [2:0] Function select (FUNCSEL) - uint32_t ePowerSw : 2; // [4:3] Pin is a power switch source (VCC) or sink (VSS) - uint32_t ePullup : 3; // [7:5] Pin will enable a pullup resistor - uint32_t eDriveStrength : 2; // [9:8] Pad strength designator - uint32_t eGPOutcfg : 2; // [11:10] OUTCFG (GPIO config only) - uint32_t eGPInput : 1; // [12:12] GPIO Input (GPIO config only) - uint32_t eIntDir : 2; // [14:13] Interrupt direction - uint32_t eGPRdZero : 1; // [15:15] GPIO read as zero +#define AM_HAL_GPIO_BIT(n) (((uint64_t)0x1) << n) + + //***************************************************************************** + //! + //! Read types for am_hal_gpio_state_read(). + //! + //***************************************************************************** + typedef enum + { + AM_HAL_GPIO_INPUT_READ, + AM_HAL_GPIO_OUTPUT_READ, + AM_HAL_GPIO_ENABLE_READ + } am_hal_gpio_read_type_e; + + //***************************************************************************** + //! + //! Write types for am_hal_gpio_state_write(). + //! + //***************************************************************************** + typedef enum + { + AM_HAL_GPIO_OUTPUT_CLEAR, + AM_HAL_GPIO_OUTPUT_SET, + AM_HAL_GPIO_OUTPUT_TOGGLE, + AM_HAL_GPIO_OUTPUT_TRISTATE_DISABLE, + AM_HAL_GPIO_OUTPUT_TRISTATE_ENABLE, + AM_HAL_GPIO_OUTPUT_TRISTATE_TOGGLE + } am_hal_gpio_write_type_e; + + //***************************************************************************** + //! + //! Types for ui32GpioCfg bitfields in am_hal_gpio_pinconfig(). + //! + //***************************************************************************** + //! + //! Power Switch configuration: am_hal_gpio_pincfg_t.ePowerSw enums + //! + typedef enum + { + AM_HAL_GPIO_PIN_POWERSW_NONE, + AM_HAL_GPIO_PIN_POWERSW_VDD, + AM_HAL_GPIO_PIN_POWERSW_VSS, + AM_HAL_GPIO_PIN_POWERSW_INVALID, + } am_hal_gpio_powersw_e; + + //! + //! Pullup configuration: am_hal_gpio_pincfg_t.ePullup enums + //! + typedef enum + { + // + //! Define pullup enums. + //! The 1.5K - 24K pullup values are valid for select I2C enabled pads. + //! For Apollo3 these pins are 0-1,5-6,8-9,25,27,39-40,42-43,48-49. + //! The "weak" value is used for almost every other pad except pin 20. + // + AM_HAL_GPIO_PIN_PULLUP_NONE = 0x00, + AM_HAL_GPIO_PIN_PULLUP_WEAK, + AM_HAL_GPIO_PIN_PULLUP_1_5K, + AM_HAL_GPIO_PIN_PULLUP_6K, + AM_HAL_GPIO_PIN_PULLUP_12K, + AM_HAL_GPIO_PIN_PULLUP_24K, + AM_HAL_GPIO_PIN_PULLDOWN + } am_hal_gpio_pullup_e; + + //! + //! Pad Drive Strength configuration: am_hal_gpio_pincfg_t.eDriveStrength enums + //! + typedef enum + { + // + //! DRIVESTRENGTH is a 2-bit field. + //! bit0 maps to bit2 of a PADREG field. + //! bit1 maps to bit0 of an ALTPADCFG field. + // + AM_HAL_GPIO_PIN_DRIVESTRENGTH_2MA = 0x0, + AM_HAL_GPIO_PIN_DRIVESTRENGTH_4MA = 0x1, + AM_HAL_GPIO_PIN_DRIVESTRENGTH_8MA = 0x2, + AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA = 0x3 + } am_hal_gpio_drivestrength_e; + + //! + //! OUTCFG pad configuration: am_hal_gpio_pincfg_t.eGPOutcfg enums + //! Applies only to GPIO configured pins. + //! Ultimately maps to GPIOCFG.OUTCFG, bits [2:1]. + //! + typedef enum + { + AM_HAL_GPIO_PIN_OUTCFG_DISABLE = 0x0, + AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL = 0x1, + AM_HAL_GPIO_PIN_OUTCFG_OPENDRAIN = 0x2, + AM_HAL_GPIO_PIN_OUTCFG_TRISTATE = 0x3 + } am_hal_gpio_outcfg_e; + + //! + //! GPIO input configuration: am_hal_gpio_pincfg_t.eGPInput enums + //! Applies only to GPIO configured pins! + //! Ultimately maps to PADREG.INPEN, bit1. + //! + typedef enum + { + AM_HAL_GPIO_PIN_INPUT_AUTO = 0x0, + AM_HAL_GPIO_PIN_INPUT_NONE = 0x0, + AM_HAL_GPIO_PIN_INPUT_ENABLE = 0x1 + } am_hal_gpio_input_e; + + //! + //! GPIO interrupt direction configuration: am_hal_gpio_pincfg_t.eIntDir enums + //! Note: Setting INTDIR_NONE has the side-effect of disabling being able to + //! read a pin - the pin will always read back as 0. + //! + typedef enum + { + // Bit1 of these values maps to GPIOCFG.INCFG (b0). + // Bit0 of these values maps to GPIOCFG.INTD (b3). + AM_HAL_GPIO_PIN_INTDIR_LO2HI = 0x0, + AM_HAL_GPIO_PIN_INTDIR_HI2LO = 0x1, + AM_HAL_GPIO_PIN_INTDIR_NONE = 0x2, + AM_HAL_GPIO_PIN_INTDIR_BOTH = 0x3 + } am_hal_gpio_intdir_e; + + //! + //! am_hal_gpio_pincfg_t.eGPRdZero + //! For GPIO configurations (funcsel=3), the pin value can be read or 0 can be + //! forced as the read value. + //! + typedef enum + { + AM_HAL_GPIO_PIN_RDZERO_READPIN = 0x0, + AM_HAL_GPIO_PIN_RDZERO_ZERO = 0x1 + } am_hal_gpio_readen_e; + + //! + //! nCE polarity configuration: am_hal_gpio_pincfg_t.eCEpol enums + //! + typedef enum + { + AM_HAL_GPIO_PIN_CEPOL_ACTIVELOW = 0x0, + AM_HAL_GPIO_PIN_CEPOL_ACTIVEHIGH = 0x1 + } am_hal_gpio_cepol_e; // - // The following descriptors designate the chip enable features of the - // pin being configured. If not a CE, these descriptors are ignored. - // uIOMnum is 0-5 for the IOMs, or 6 for MSPI, 7 is invalid. + // Apollo3 usage of bits [7:6] of a PADREG field: + // PULLUPs are available on pins: 0,1,5,6,8,9,25,27,39,40,42,43,48,49 + // RESERVED on pins: 2,4,7,10-24,26,28-35,38,44-47 + // VDD PWR on pins: 3, 36 (b7=0, b6=1) + // VSS PWR on pins: 37,41 (b7=1, b6=0) // - uint32_t uIOMnum : 3; // [18:16] IOM number (0-5), 6 for MSPI - uint32_t uNCE : 2; // [20:19] NCE number (0-3). - uint32_t eCEpol : 1; // [21:21] NCE polarity. - - uint32_t uRsvd22 : 10; // [31:22] -} am_hal_gpio_pincfg_t; -#define IOMNUM_MSPI 6 -#define IOMNUM_MAX IOMNUM_MSPI + //! + //! Define the am_hal_gpio_pinconfig() bitfield structure. + //! uFuncSel a value of 0-7 corresponding to the FNCSEL field of PADREG. + //! ePowerSw: Select pins can be set as a power source or sink. + //! ePullup: Select pins can enable a pullup of varying values. + //! eDriveStrength: Select pins can be set for varying drive strengths. + //! eGPOutcfg: GPIO pin only, corresponds to GPIOCFG.OUTCFG field. + //! eGPInput: GPIO pin only, corresponds to PADREG.INPEN. + //! eGPRdZero: GPIO read zero. Corresponds to GPIOCFG.INCFG. + //! eIntDir: Interrupt direction, l2h, h2l, both, none. + //! eGPRdZero: Read the pin value, or always read the pin as zero. + //! uIOMnum: nCE pin IOMnumber (0-5, or 6 for MSPI) + //! nNCE: Selects the SPI channel (CE) number (0-3) + //! eCEpol: CE polarity. + //! + typedef struct + { + uint32_t uFuncSel : 3; // [2:0] Function select (FUNCSEL) + uint32_t ePowerSw : 2; // [4:3] Pin is a power switch source (VCC) or sink (VSS) + uint32_t ePullup : 3; // [7:5] Pin will enable a pullup resistor + uint32_t eDriveStrength : 2; // [9:8] Pad strength designator + uint32_t eGPOutcfg : 2; // [11:10] OUTCFG (GPIO config only) + uint32_t eGPInput : 1; // [12:12] GPIO Input (GPIO config only) + uint32_t eIntDir : 2; // [14:13] Interrupt direction + uint32_t eGPRdZero : 1; // [15:15] GPIO read as zero + + // + // The following descriptors designate the chip enable features of the + // pin being configured. If not a CE, these descriptors are ignored. + // uIOMnum is 0-5 for the IOMs, or 6 for MSPI, 7 is invalid. + // + uint32_t uIOMnum : 3; // [18:16] IOM number (0-5), 6 for MSPI + uint32_t uNCE : 2; // [20:19] NCE number (0-3). + uint32_t eCEpol : 1; // [21:21] NCE polarity. + + uint32_t uRsvd22 : 10; // [31:22] + } am_hal_gpio_pincfg_t; + + typedef struct + { + uint8_t funcSel : 1; + uint8_t powerSw : 1; + uint8_t pullup : 1; + uint8_t driveStrength : 1; + uint8_t gpOutcfg : 1; + uint8_t gpInput : 1; + uint8_t intDir : 1; + uint8_t gprdZero : 1; + } am_hal_gpio_pincfg_allow_t; + +#define IOMNUM_MSPI 6 +#define IOMNUM_MAX IOMNUM_MSPI // // Define shift and width values for the above bitfields. @@ -269,315 +279,316 @@ typedef struct // GCC, the bitfields are all exactly as defined in the above structure. // - These defines should be used sparingly. // -#define UFUNCSEL_S 0 -#define EPOWERSW_S 3 -#define EPULLUP_S 5 -#define EDRVSTR_S 8 -#define EGPOUTCFG_S 10 -#define EGPINPUT_S 12 -#define EINTDIR_S 13 -#define UIOMNUM_S 16 -#define UNCE_S 19 -#define ECEPOL_S 21 - -#define UFUNCSEL_W 3 -#define EPOWERSW_W 2 -#define EPULLUP_W 3 -#define EDRVSTR_W 2 -#define EGPOUTCFG_W 2 -#define EGPINPUT_W 1 -#define EINTDIR_W 2 -#define UIOMNUM_W 3 -#define UNCE_W 2 -#define ECEPOL_W 1 - -//! -//! Define GPIO error codes that are returned by am_hal_gpio_pinconfig(). -//! -enum am_hal_gpio_pincfgerr -{ - AM_HAL_GPIO_ERR_PULLUP = (AM_HAL_STATUS_MODULE_SPECIFIC_START + 0x100), - AM_HAL_GPIO_ERR_PULLDOWN, - AM_HAL_GPIO_ERR_PWRSW, - AM_HAL_GPIO_ERR_INVCE, - AM_HAL_GPIO_ERR_INVCEPIN, - AM_HAL_GPIO_ERR_PULLUPENUM -}; - -//***************************************************************************** -// -// Globals -// -//***************************************************************************** -//***************************************************************************** -// Define some common GPIO pin configurations. -//***************************************************************************** -//! Basics -extern const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_DISABLE; -extern const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_TRISTATE; - -//! Input variations -extern const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_INPUT; -//! Input with various pullups (weak, 1.5K, 6K, 12K, 24K) -extern const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_INPUT_PULLUP; -extern const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_INPUT_PULLUP_1_5; -extern const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_INPUT_PULLUP_6; -extern const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_INPUT_PULLUP_12; -extern const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_INPUT_PULLUP_24; - -//! Output variations -extern const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_OUTPUT; -extern const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_OUTPUT_4; -extern const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_OUTPUT_8; -extern const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_OUTPUT_12; -extern const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_OUTPUT_WITH_READ; - -//***************************************************************************** -// -// Function pointer type for GPIO interrupt handlers. -// -//***************************************************************************** -typedef void (*am_hal_gpio_handler_t)(void); +#define UFUNCSEL_S 0 +#define EPOWERSW_S 3 +#define EPULLUP_S 5 +#define EDRVSTR_S 8 +#define EGPOUTCFG_S 10 +#define EGPINPUT_S 12 +#define EINTDIR_S 13 +#define UIOMNUM_S 16 +#define UNCE_S 19 +#define ECEPOL_S 21 + +#define UFUNCSEL_W 3 +#define EPOWERSW_W 2 +#define EPULLUP_W 3 +#define EDRVSTR_W 2 +#define EGPOUTCFG_W 2 +#define EGPINPUT_W 1 +#define EINTDIR_W 2 +#define UIOMNUM_W 3 +#define UNCE_W 2 +#define ECEPOL_W 1 + + //! + //! Define GPIO error codes that are returned by am_hal_gpio_pinconfig(). + //! + enum am_hal_gpio_pincfgerr + { + AM_HAL_GPIO_ERR_PULLUP = (AM_HAL_STATUS_MODULE_SPECIFIC_START + 0x100), + AM_HAL_GPIO_ERR_PULLDOWN, + AM_HAL_GPIO_ERR_PWRSW, + AM_HAL_GPIO_ERR_INVCE, + AM_HAL_GPIO_ERR_INVCEPIN, + AM_HAL_GPIO_ERR_PULLUPENUM + }; + + //***************************************************************************** + // + // Globals + // + //***************************************************************************** + //***************************************************************************** + // Define some common GPIO pin configurations. + //***************************************************************************** + //! Basics + extern const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_DISABLE; + extern const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_TRISTATE; + + //! Input variations + extern const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_INPUT; + //! Input with various pullups (weak, 1.5K, 6K, 12K, 24K) + extern const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_INPUT_PULLUP; + extern const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_INPUT_PULLUP_1_5; + extern const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_INPUT_PULLUP_6; + extern const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_INPUT_PULLUP_12; + extern const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_INPUT_PULLUP_24; + + //! Output variations + extern const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_OUTPUT; + extern const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_OUTPUT_4; + extern const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_OUTPUT_8; + extern const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_OUTPUT_12; + extern const am_hal_gpio_pincfg_t g_AM_HAL_GPIO_OUTPUT_WITH_READ; + + //***************************************************************************** + // + // Function pointer type for GPIO interrupt handlers. + // + //***************************************************************************** + typedef void (*am_hal_gpio_handler_t)(void); -//***************************************************************************** -// -//! @brief Configure an Apollo3 pin. -//! -//! @param ui32Pin - pin number to be configured. -//! @param ui32GpioCfg - Contains multiple descriptor fields. -//! -//! This function configures a pin according to the descriptor parameters as -//! passed in sPinCfg. All parameters are validated with regard to each -//! other and according to the requested function. Once the parameters and -//! settings have been confirmed, the pin is configured accordingly. -//! -//! @return Status. -// -//***************************************************************************** -extern uint32_t am_hal_gpio_pinconfig(uint32_t ui32Pin, - am_hal_gpio_pincfg_t sPincfg); + //***************************************************************************** + // + //! @brief Configure an Apollo3 pin. + //! + //! @param ui32Pin - pin number to be configured. + //! @param ui32GpioCfg - Contains multiple descriptor fields. + //! + //! This function configures a pin according to the descriptor parameters as + //! passed in sPinCfg. All parameters are validated with regard to each + //! other and according to the requested function. Once the parameters and + //! settings have been confirmed, the pin is configured accordingly. + //! + //! @return Status. + // + //***************************************************************************** + extern uint32_t am_hal_gpio_pinconfig(uint32_t ui32Pin, + am_hal_gpio_pincfg_t sPincfg); -//***************************************************************************** -// -//! @brief Configure specified pins for FAST GPIO operation. -//! -//! @param ui64PinMask - a mask specifying up to 8 pins to be configured and -//! used for FAST GPIO (only bits 0-49 are valid). -//! @param bfGpioCfg - The GPIO configuration (same as am_hal_gpio_pinconfig()). -//! All of the pins specified by ui64PinMask will be set to this -//! configuration. -//! @param ui32Masks - If NULL, not used. Otherwise if provided, an array to -//! receive two 32-bit values, per pin, of the SET and CLEAR -//! masks that can be used for the BBSETCLEAR register. -//! The two 32-bit values will be placed at incremental indexes. -//! For example, say pin numbers 5 and 19 are indicated in the -//! mask, and an array pointer is provided in ui32Masks. This -//! array must be allocated by the caller to be at least 4 wds. -//! ui32Masks[0] = the set mask used for pin 5. -//! ui32Masks[1] = the clear mask used for pin 5. -//! ui32Masks[2] = the set mask used for pin 19. -//! ui32Masks[3] = the clear mask used for pin 19. -//! -//! @return Status. -//! -//! Fast GPIO helper macros: -//! am_hal_gpio_fastgpio_set(n) - Sets the value for pin number 'n'. -//! am_hal_gpio_fastgpio_clr(n) - Clear the value for pin number 'n'. -//! -//! am_hal_gpio_fastgpio_enable(n) - Enable Fast GPIO on pin 'n'. -//! am_hal_gpio_fastgpio_disable(n) - Disable Fast GPIO on pin 'n'. -//! -//! Note - The enable and disable macros assume the pin has already been -//! configured. Once disabled, the state of the pin will revert to the -//! state of the normal GPIO configuration for that pin. -//! -//! NOTES on pin configuration: -//! - To avoid glitches on the pin, it is strongly recommended that before -// calling am_hal_gpio_fast_pinconfig() that am_hal_gpio_fastgpio_disable() -//! first be called to make sure that Fast GPIO is disabled before config. -//! - If the state of the pin is important, preset the value of the pin to the -//! desired value BEFORE calling am_hal_gpio_fast_pinconfig(). The set and -//! clear macros shown above can be used for this purpose. -//! -//! NOTES on general use of Fast GPIO: -//! Fast GPIO input or output will not work if the pin is configured as -//! tristate. The overloaded OUTPUT ENABLE control is used for enabling both -//! modes, so Apollo3 logic specifically disallows Fast GPIO input or output -//! when the pin is configured for tristate mode. -//! Fast GPIO input can be used for pushpull, opendrain, or disable modes. -//! -//! Fast GPIO pin groupings: -//! The FaST GPIO pins are grouped across a matrix of pins. Each -//! row of pins is controlled by a single data bit. -//! -//! Referring to the below chart: -//! If pin 35 were configured for Fast GPIO output, it would be set -//! when bit3 of BBSETCLEAR.SET was written with a 1. -//! It would be cleared when bit3 of BBSETCLEAR.CLEAR was written with 1. -//! -//! Note that if all the pins in a row were configured for Fast GPIO output, -//! all the pins would respond to set/clear. -//! -//! Input works in a similar fashion. -//! -//! BIT PIN controlled -//! --- --------------------------- -//! 0 0 8 16 24 32 40 48 -//! 1 1 9 17 25 33 41 49 -//! 2 2 10 18 26 34 42 -//! 3 3 11 19 27 35 43 -//! 4 4 12 20 28 36 44 -//! 5 5 13 21 29 37 45 -//! 6 6 14 22 30 38 46 -//! 7 7 15 23 31 39 47 -//! -// -//***************************************************************************** -extern uint32_t am_hal_gpio_fast_pinconfig(uint64_t ui64PinMask, - am_hal_gpio_pincfg_t bfGpioCfg, - uint32_t ui32Masks[]); + //***************************************************************************** + // + //! @brief Configure specified pins for FAST GPIO operation. + //! + //! @param ui64PinMask - a mask specifying up to 8 pins to be configured and + //! used for FAST GPIO (only bits 0-49 are valid). + //! @param bfGpioCfg - The GPIO configuration (same as am_hal_gpio_pinconfig()). + //! All of the pins specified by ui64PinMask will be set to this + //! configuration. + //! @param ui32Masks - If NULL, not used. Otherwise if provided, an array to + //! receive two 32-bit values, per pin, of the SET and CLEAR + //! masks that can be used for the BBSETCLEAR register. + //! The two 32-bit values will be placed at incremental indexes. + //! For example, say pin numbers 5 and 19 are indicated in the + //! mask, and an array pointer is provided in ui32Masks. This + //! array must be allocated by the caller to be at least 4 wds. + //! ui32Masks[0] = the set mask used for pin 5. + //! ui32Masks[1] = the clear mask used for pin 5. + //! ui32Masks[2] = the set mask used for pin 19. + //! ui32Masks[3] = the clear mask used for pin 19. + //! + //! @return Status. + //! + //! Fast GPIO helper macros: + //! am_hal_gpio_fastgpio_set(n) - Sets the value for pin number 'n'. + //! am_hal_gpio_fastgpio_clr(n) - Clear the value for pin number 'n'. + //! + //! am_hal_gpio_fastgpio_enable(n) - Enable Fast GPIO on pin 'n'. + //! am_hal_gpio_fastgpio_disable(n) - Disable Fast GPIO on pin 'n'. + //! + //! Note - The enable and disable macros assume the pin has already been + //! configured. Once disabled, the state of the pin will revert to the + //! state of the normal GPIO configuration for that pin. + //! + //! NOTES on pin configuration: + //! - To avoid glitches on the pin, it is strongly recommended that before + // calling am_hal_gpio_fast_pinconfig() that am_hal_gpio_fastgpio_disable() + //! first be called to make sure that Fast GPIO is disabled before config. + //! - If the state of the pin is important, preset the value of the pin to the + //! desired value BEFORE calling am_hal_gpio_fast_pinconfig(). The set and + //! clear macros shown above can be used for this purpose. + //! + //! NOTES on general use of Fast GPIO: + //! Fast GPIO input or output will not work if the pin is configured as + //! tristate. The overloaded OUTPUT ENABLE control is used for enabling both + //! modes, so Apollo3 logic specifically disallows Fast GPIO input or output + //! when the pin is configured for tristate mode. + //! Fast GPIO input can be used for pushpull, opendrain, or disable modes. + //! + //! Fast GPIO pin groupings: + //! The FaST GPIO pins are grouped across a matrix of pins. Each + //! row of pins is controlled by a single data bit. + //! + //! Referring to the below chart: + //! If pin 35 were configured for Fast GPIO output, it would be set + //! when bit3 of BBSETCLEAR.SET was written with a 1. + //! It would be cleared when bit3 of BBSETCLEAR.CLEAR was written with 1. + //! + //! Note that if all the pins in a row were configured for Fast GPIO output, + //! all the pins would respond to set/clear. + //! + //! Input works in a similar fashion. + //! + //! BIT PIN controlled + //! --- --------------------------- + //! 0 0 8 16 24 32 40 48 + //! 1 1 9 17 25 33 41 49 + //! 2 2 10 18 26 34 42 + //! 3 3 11 19 27 35 43 + //! 4 4 12 20 28 36 44 + //! 5 5 13 21 29 37 45 + //! 6 6 14 22 30 38 46 + //! 7 7 15 23 31 39 47 + //! + // + //***************************************************************************** + extern uint32_t am_hal_gpio_fast_pinconfig(uint64_t ui64PinMask, + am_hal_gpio_pincfg_t bfGpioCfg, + uint32_t ui32Masks[]); -//***************************************************************************** -// -//! @brief Read GPIO. -//! -//! @param ui32Pin - pin number to be read. -//! @param eReadType - State type to read. One of: -//! AM_HAL_GPIO_INPUT_READ -//! AM_HAL_GPIO_OUTPUT_READ -//! AM_HAL_GPIO_ENABLE_READ -//! -//! This function reads a pin state as given by eReadType. -//! -//! @return Status. -// -//***************************************************************************** -extern uint32_t am_hal_gpio_state_read(uint32_t ui32Pin, - am_hal_gpio_read_type_e eReadType, - uint32_t *pu32RetVal); + //***************************************************************************** + // + //! @brief Read GPIO. + //! + //! @param ui32Pin - pin number to be read. + //! @param eReadType - State type to read. One of: + //! AM_HAL_GPIO_INPUT_READ + //! AM_HAL_GPIO_OUTPUT_READ + //! AM_HAL_GPIO_ENABLE_READ + //! + //! This function reads a pin state as given by eReadType. + //! + //! @return Status. + // + //***************************************************************************** + extern uint32_t am_hal_gpio_state_read(uint32_t ui32Pin, + am_hal_gpio_read_type_e eReadType, + uint32_t *pu32RetVal); -//***************************************************************************** -// -//! @brief Write GPIO. -//! -//! @param ui32Pin - pin number to be read. -//! -//! @param eWriteType - State type to write. One of: -//! AM_HAL_GPIO_OUTPUT_SET - Write a one to a GPIO. -//! AM_HAL_GPIO_OUTPUT_CLEAR - Write a zero to a GPIO. -//! AM_HAL_GPIO_OUTPUT_TOGGLE - Toggle the GPIO value. -//! The following two apply when output is set for TriState (OUTCFG==3). -//! AM_HAL_GPIO_OUTPUT_TRISTATE_ENABLE - Enable a tri-state GPIO. -//! AM_HAL_GPIO_OUTPUT_TRISTATE_DISABLE - Disable a tri-state GPIO. -//! -//! This function writes a GPIO value. -//! -//! @return Status. -//! Fails if the pad is not configured for GPIO (PADFNCSEL != 3). -// -//***************************************************************************** -extern uint32_t am_hal_gpio_state_write(uint32_t ui32Pin, - am_hal_gpio_write_type_e eWriteType); + //***************************************************************************** + // + //! @brief Write GPIO. + //! + //! @param ui32Pin - pin number to be read. + //! + //! @param eWriteType - State type to write. One of: + //! AM_HAL_GPIO_OUTPUT_SET - Write a one to a GPIO. + //! AM_HAL_GPIO_OUTPUT_CLEAR - Write a zero to a GPIO. + //! AM_HAL_GPIO_OUTPUT_TOGGLE - Toggle the GPIO value. + //! The following two apply when output is set for TriState (OUTCFG==3). + //! AM_HAL_GPIO_OUTPUT_TRISTATE_ENABLE - Enable a tri-state GPIO. + //! AM_HAL_GPIO_OUTPUT_TRISTATE_DISABLE - Disable a tri-state GPIO. + //! + //! This function writes a GPIO value. + //! + //! @return Status. + //! Fails if the pad is not configured for GPIO (PADFNCSEL != 3). + // + //***************************************************************************** + extern uint32_t am_hal_gpio_state_write(uint32_t ui32Pin, + am_hal_gpio_write_type_e eWriteType); -//***************************************************************************** -// -//! @brief Enable GPIO interrupts. -//! -//! @param ui64InterruptMask - Mask of GPIO interrupts to enable. -//! Only bits 0-49 are valid in the mask. -//! -//! @return Status. -//! Fails if any bit above bit49 is set in ui64InterruptMask. -// -//***************************************************************************** -extern uint32_t am_hal_gpio_interrupt_enable(uint64_t ui64InterruptMask); + //***************************************************************************** + // + //! @brief Enable GPIO interrupts. + //! + //! @param ui64InterruptMask - Mask of GPIO interrupts to enable. + //! Only bits 0-49 are valid in the mask. + //! + //! @return Status. + //! Fails if any bit above bit49 is set in ui64InterruptMask. + // + //***************************************************************************** + extern uint32_t am_hal_gpio_interrupt_enable(uint64_t ui64InterruptMask); -//***************************************************************************** -// -//! @brief Disable GPIO interrupts. -//! -//! @param ui64InterruptMask - Mask of GPIO interrupts to disable. -//! Only bits 0-49 are valid in the mask. -//! -//! @return Status. -//! Fails if any bit above bit49 is set in ui64InterruptMask. -// -//***************************************************************************** -extern uint32_t am_hal_gpio_interrupt_disable(uint64_t ui64InterruptMask); + //***************************************************************************** + // + //! @brief Disable GPIO interrupts. + //! + //! @param ui64InterruptMask - Mask of GPIO interrupts to disable. + //! Only bits 0-49 are valid in the mask. + //! + //! @return Status. + //! Fails if any bit above bit49 is set in ui64InterruptMask. + // + //***************************************************************************** + extern uint32_t am_hal_gpio_interrupt_disable(uint64_t ui64InterruptMask); -//***************************************************************************** -// -//! @brief Clear GPIO interrupts. -//! -//! @param ui64InterruptMask - Mask of GPIO interrupts to be cleared. -//! Only bits 0-49 are valid in the mask. -//! -//! @return Status. -//! Fails if any bit above bit49 is set in ui64InterruptMask. -// -//***************************************************************************** -extern uint32_t am_hal_gpio_interrupt_clear(uint64_t ui64InterruptMask); + //***************************************************************************** + // + //! @brief Clear GPIO interrupts. + //! + //! @param ui64InterruptMask - Mask of GPIO interrupts to be cleared. + //! Only bits 0-49 are valid in the mask. + //! + //! @return Status. + //! Fails if any bit above bit49 is set in ui64InterruptMask. + // + //***************************************************************************** + extern uint32_t am_hal_gpio_interrupt_clear(uint64_t ui64InterruptMask); -//***************************************************************************** -// -//! @brief Get GPIO interrupt status. -//! -//! @param bEnabledOnly - Return status only for currently enabled interrupts. -//! -//! @param pui64IntStatus - 64-bit variable to return a bitmask of the status -//! of the interrupts. -//! -//! @return Status. -//! Fails if pui64IntStatus is NULL. -// -//***************************************************************************** -extern uint32_t am_hal_gpio_interrupt_status_get(bool bEnabledOnly, - uint64_t *pui64IntStatus); + //***************************************************************************** + // + //! @brief Get GPIO interrupt status. + //! + //! @param bEnabledOnly - Return status only for currently enabled interrupts. + //! + //! @param pui64IntStatus - 64-bit variable to return a bitmask of the status + //! of the interrupts. + //! + //! @return Status. + //! Fails if pui64IntStatus is NULL. + // + //***************************************************************************** + extern uint32_t am_hal_gpio_interrupt_status_get(bool bEnabledOnly, + uint64_t *pui64IntStatus); -//***************************************************************************** -// -//! @brief GPIO interrupt service routine registration. -//! -//! @param ui32GPIONumber - GPIO number (0-49) to be registered. -//! -//! @param pfnHandler - Function pointer to the callback. -//! -//! @return Status. -//! Fails if pfnHandler is NULL or ui32GPIONumber > 49. -// -//***************************************************************************** -extern uint32_t am_hal_gpio_interrupt_register(uint32_t ui32GPIONumber, - am_hal_gpio_handler_t pfnHandler); + //***************************************************************************** + // + //! @brief GPIO interrupt service routine registration. + //! + //! @param ui32GPIONumber - GPIO number (0-49) to be registered. + //! + //! @param pfnHandler - Function pointer to the callback. + //! + //! @return Status. + //! Fails if pfnHandler is NULL or ui32GPIONumber > 49. + // + //***************************************************************************** + extern uint32_t am_hal_gpio_interrupt_register(uint32_t ui32GPIONumber, + am_hal_gpio_handler_t pfnHandler); -//***************************************************************************** -// -// GPIO interrupt service routine. -//! @brief GPIO interrupt service routine registration. -//! -//! @param ui64Status - Mask of the interrupt(s) to be serviced. This mask is -//! typically obtained via a call to am_hal_gpio_interrupt_status_get(). -//! -//! The intended use is that the application first registers a handler for a -//! particular GPIO via am_hal_gpio_interrupt_register(), and to supply the -//! main ISR, am_gpio_isr(). -//! -//! On a GPIO interrupt, am_gpio_isr() calls am_hal_gpio_interrupt_status_get() -//! and provides the return value to this function. -//! -//! In the event that multiple GPIO interrupts are active, the corresponding -//! interrupt handlers will be called in numerical order by GPIO number -//! starting with the lowest GPIO number. -//! -//! @return Status. -//! AM_HAL_STATUS_INVALID_OPERATION if no handler had been registered -//! for any of the GPIOs that caused the interrupt. -//! AM_HAL_STATUS_OUT_OF_RANGE if any bit above bit49 is set. -//! AM_HAL_STATUS_FAIL if ui64Status is 0. -//! AM_HAL_STATUS_SUCCESS otherwise. -// -//***************************************************************************** -extern uint32_t am_hal_gpio_interrupt_service(uint64_t ui64Status); + //***************************************************************************** + // + // GPIO interrupt service routine. + //! @brief GPIO interrupt service routine registration. + //! + //! @param ui64Status - Mask of the interrupt(s) to be serviced. This mask is + //! typically obtained via a call to am_hal_gpio_interrupt_status_get(). + //! + //! The intended use is that the application first registers a handler for a + //! particular GPIO via am_hal_gpio_interrupt_register(), and to supply the + //! main ISR, am_gpio_isr(). + //! + //! On a GPIO interrupt, am_gpio_isr() calls am_hal_gpio_interrupt_status_get() + //! and provides the return value to this function. + //! + //! In the event that multiple GPIO interrupts are active, the corresponding + //! interrupt handlers will be called in numerical order by GPIO number + //! starting with the lowest GPIO number. + //! + //! @return Status. + //! AM_HAL_STATUS_INVALID_OPERATION if no handler had been registered + //! for any of the GPIOs that caused the interrupt. + //! AM_HAL_STATUS_OUT_OF_RANGE if any bit above bit49 is set. + //! AM_HAL_STATUS_FAIL if ui64Status is 0. + //! AM_HAL_STATUS_SUCCESS otherwise. + // + //***************************************************************************** + extern uint32_t am_hal_gpio_interrupt_service(uint64_t ui64Status); + uint32_t ap3_hal_gpio_pinconfig_partial(uint32_t ui32Pin, am_hal_gpio_pincfg_t bfGpioCfg, am_hal_gpio_pincfg_allow_t sAllowableChanges); //;uint8_t padRegMask, uint8_t GPCfgMask, uint8_t altPadCfgMask); //***************************************************************************** // @@ -604,21 +615,20 @@ extern uint32_t am_hal_gpio_interrupt_service(uint64_t ui64Status); //! // //***************************************************************************** -#define am_hal_gpio_input_read(n) ( \ - (AM_REGVAL( (AM_REGADDR(GPIO, RDA) + (((uint32_t)(n) & 0x20) >> 3)) ) >> /* Read appropriate register */ \ - ((uint32_t)(n) & 0x1F) ) & /* Shift by appropriate number of bits */ \ - ((uint32_t)0x1) ) /* Mask out the LSB */ - -#define am_hal_gpio_output_read(n) ( \ - (AM_REGVAL( (AM_REGADDR(GPIO, WTA) + (((uint32_t)(n) & 0x20) >> 3)) ) >> /* Read appropriate register */ \ - ((uint32_t)(n) & 0x1F) ) & /* Shift by appropriate number of bits */ \ - ((uint32_t)0x1) ) /* Mask out the LSB */ +#define am_hal_gpio_input_read(n) ( \ + (AM_REGVAL((AM_REGADDR(GPIO, RDA) + (((uint32_t)(n)&0x20) >> 3))) >> /* Read appropriate register */ \ + ((uint32_t)(n)&0x1F)) & /* Shift by appropriate number of bits */ \ + ((uint32_t)0x1)) /* Mask out the LSB */ -#define am_hal_gpio_enable_read(n) ( \ - (AM_REGVAL( (AM_REGADDR(GPIO, ENA) + (((uint32_t)(n) & 0x20) >> 3)) ) >> /* Read appropriate register */ \ - ((uint32_t)(n) & 0x1F) ) & /* Shift by appropriate number of bits */ \ - ((uint32_t)0x1) ) /* Mask out the LSB */ +#define am_hal_gpio_output_read(n) ( \ + (AM_REGVAL((AM_REGADDR(GPIO, WTA) + (((uint32_t)(n)&0x20) >> 3))) >> /* Read appropriate register */ \ + ((uint32_t)(n)&0x1F)) & /* Shift by appropriate number of bits */ \ + ((uint32_t)0x1)) /* Mask out the LSB */ +#define am_hal_gpio_enable_read(n) ( \ + (AM_REGVAL((AM_REGADDR(GPIO, ENA) + (((uint32_t)(n)&0x20) >> 3))) >> /* Read appropriate register */ \ + ((uint32_t)(n)&0x1F)) & /* Shift by appropriate number of bits */ \ + ((uint32_t)0x1)) /* Mask out the LSB */ //***************************************************************************** // @@ -649,51 +659,42 @@ extern uint32_t am_hal_gpio_interrupt_service(uint64_t ui64Status); // // Note - these macros use byte-oriented addressing. // -#define am_hal_gpio_output_clear(n) \ - ((*((volatile uint32_t *) \ - ((AM_REGADDR(GPIO, WTCA) + (((uint32_t)(n) & 0x20) >> 3))))) = \ - ((uint32_t) 0x1 << ((uint32_t)(n) % 32))) - -#define am_hal_gpio_output_set(n) \ - ((*((volatile uint32_t *) \ - ((AM_REGADDR(GPIO, WTSA) + (((uint32_t)(n) & 0x20) >> 3))))) = \ - ((uint32_t) 0x1 << ((uint32_t)(n) % 32))) - -#define am_hal_gpio_output_toggle(n) \ - if ( 1 ) \ - { \ - AM_CRITICAL_BEGIN \ - ((*((volatile uint32_t *) \ - ((AM_REGADDR(GPIO, WTA) + (((uint32_t)(n) & 0x20) >> 3))))) ^= \ - ((uint32_t) 0x1 << ((uint32_t)(n) % 32))); \ - AM_CRITICAL_END \ - } +#define am_hal_gpio_output_clear(n) \ + ((*((volatile uint32_t *)((AM_REGADDR(GPIO, WTCA) + (((uint32_t)(n)&0x20) >> 3))))) = \ + ((uint32_t)0x1 << ((uint32_t)(n) % 32))) + +#define am_hal_gpio_output_set(n) \ + ((*((volatile uint32_t *)((AM_REGADDR(GPIO, WTSA) + (((uint32_t)(n)&0x20) >> 3))))) = \ + ((uint32_t)0x1 << ((uint32_t)(n) % 32))) -#define am_hal_gpio_output_tristate_disable(n) \ - ((*((volatile uint32_t *) \ - ((AM_REGADDR(GPIO, ENCA) + (((uint32_t)(n) & 0x20) >> 3))))) = \ - ((uint32_t) 0x1 << ((uint32_t)(n) % 32))) - -#define am_hal_gpio_output_tristate_enable(n) \ - ((*((volatile uint32_t *) \ - ((AM_REGADDR(GPIO, ENSA) + (((uint32_t)(n) & 0x20) >> 3))))) = \ - ((uint32_t) 0x1 << ((uint32_t)(n) % 32))) - -#define am_hal_gpio_output_tristate_toggle(n) \ - if ( 1 ) \ - { \ - AM_CRITICAL_BEGIN \ - ((*((volatile uint32_t *) \ - ((AM_REGADDR(GPIO, ENA) + (((uint32_t)(n) & 0x20) >> 3))))) ^= \ - ((uint32_t) 0x1 << ((uint32_t)(n) % 32))); \ - AM_CRITICAL_END \ +#define am_hal_gpio_output_toggle(n) \ + if (1) \ + { \ + AM_CRITICAL_BEGIN((*((volatile uint32_t *)((AM_REGADDR(GPIO, WTA) + (((uint32_t)(n)&0x20) >> 3))))) ^= \ + ((uint32_t)0x1 << ((uint32_t)(n) % 32))); \ + AM_CRITICAL_END \ } +#define am_hal_gpio_output_tristate_disable(n) \ + ((*((volatile uint32_t *)((AM_REGADDR(GPIO, ENCA) + (((uint32_t)(n)&0x20) >> 3))))) = \ + ((uint32_t)0x1 << ((uint32_t)(n) % 32))) + +#define am_hal_gpio_output_tristate_enable(n) \ + ((*((volatile uint32_t *)((AM_REGADDR(GPIO, ENSA) + (((uint32_t)(n)&0x20) >> 3))))) = \ + ((uint32_t)0x1 << ((uint32_t)(n) % 32))) + +#define am_hal_gpio_output_tristate_toggle(n) \ + if (1) \ + { \ + AM_CRITICAL_BEGIN((*((volatile uint32_t *)((AM_REGADDR(GPIO, ENA) + (((uint32_t)(n)&0x20) >> 3))))) ^= \ + ((uint32_t)0x1 << ((uint32_t)(n) % 32))); \ + AM_CRITICAL_END \ + } // // Define Fast GPIO enable and disable. // -#define am_hal_gpio_fastgpio_enable(n) am_hal_gpio_output_tristate_enable(n) +#define am_hal_gpio_fastgpio_enable(n) am_hal_gpio_output_tristate_enable(n) #define am_hal_gpio_fastgpio_disable(n) am_hal_gpio_output_tristate_disable(n) // @@ -702,21 +703,20 @@ extern uint32_t am_hal_gpio_interrupt_service(uint64_t ui64Status); // Note - these macros are most efficient if 'n' is a constant value, and // of course when compiled with -O3. // -#define am_hal_gpio_fastgpio_read(n) ((APBDMA->BBINPUT >> (n & 0x7)) & 0x1) -#define am_hal_gpio_fastgpio_set(n) (APBDMA->BBSETCLEAR = _VAL2FLD(APBDMA_BBSETCLEAR_SET, (1 << (n & 0x7)))) -#define am_hal_gpio_fastgpio_clr(n) (APBDMA->BBSETCLEAR = _VAL2FLD(APBDMA_BBSETCLEAR_CLEAR, (1 << (n & 0x7)))) -#define am_hal_gpio_fastgpio_setmsk(m) (APBDMA->BBSETCLEAR = _VAL2FLD(APBDMA_BBSETCLEAR_SET, m)) -#define am_hal_gpio_fastgpio_clrmsk(m) (APBDMA->BBSETCLEAR = _VAL2FLD(APBDMA_BBSETCLEAR_CLEAR, m)) -#define am_hal_gpio_fastgpio_wrval(val) (APBDMA->BBSETCLEAR = \ - (_VAL2FLD(APBDMA_BBSETCLEAR_SET, val) | \ - _VAL2FLD(APBDMA_BBSETCLEAR_CLEAR, val ^ 0xFF))) - +#define am_hal_gpio_fastgpio_read(n) ((APBDMA->BBINPUT >> (n & 0x7)) & 0x1) +#define am_hal_gpio_fastgpio_set(n) (APBDMA->BBSETCLEAR = _VAL2FLD(APBDMA_BBSETCLEAR_SET, (1 << (n & 0x7)))) +#define am_hal_gpio_fastgpio_clr(n) (APBDMA->BBSETCLEAR = _VAL2FLD(APBDMA_BBSETCLEAR_CLEAR, (1 << (n & 0x7)))) +#define am_hal_gpio_fastgpio_setmsk(m) (APBDMA->BBSETCLEAR = _VAL2FLD(APBDMA_BBSETCLEAR_SET, m)) +#define am_hal_gpio_fastgpio_clrmsk(m) (APBDMA->BBSETCLEAR = _VAL2FLD(APBDMA_BBSETCLEAR_CLEAR, m)) +#define am_hal_gpio_fastgpio_wrval(val) (APBDMA->BBSETCLEAR = \ + (_VAL2FLD(APBDMA_BBSETCLEAR_SET, val) | \ + _VAL2FLD(APBDMA_BBSETCLEAR_CLEAR, val ^ 0xFF))) #ifdef __cplusplus } #endif -#endif // AM_HAL_GPIO_H +#endif // AM_HAL_GPIO_H //***************************************************************************** //