From c52e1a865a29e5d16c0bd9a5a33a49f6e47ba13d Mon Sep 17 00:00:00 2001 From: Yilin Sun Date: Mon, 29 May 2023 23:38:52 +0800 Subject: [PATCH] Added GPIO interface. Signed-off-by: Yilin Sun --- CMakeLists.txt | 2 + LPC804.mex | 41 ++++++++++++++++++++ board/pin_mux.c | 63 ++++++++++++++++++++++++++++++ board/pin_mux.h | 63 ++++++++++++++++++++++++++++++ include/app_gpio.h | 7 ++++ include/app_led.h | 25 ++++++++++++ include/app_periodic_tasks.h | 6 +++ include/app_reg_if.h | 13 ++++++- src/app_gpio.c | 75 ++++++++++++++++++++++++++++++++++++ src/app_i2c_if.c | 10 +++-- src/app_periodic_tasks.c | 38 ++++++++++++++++++ src/app_reg_if.c | 30 +++++++++------ src/main.c | 9 ++++- 13 files changed, 364 insertions(+), 18 deletions(-) create mode 100644 include/app_gpio.h create mode 100644 include/app_led.h create mode 100644 include/app_periodic_tasks.h create mode 100644 src/app_gpio.c create mode 100644 src/app_periodic_tasks.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 5d4d26e..c90dbdd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,6 +44,8 @@ set(TARGET_SOURCES "board/peripherals.c" "board/pin_mux.c" "src/app_i2c_if.c" + "src/app_gpio.c" + "src/app_periodic_tasks.c" "src/app_reg_if.c" "src/main.c" ) diff --git a/LPC804.mex b/LPC804.mex index 9010032..0e0d73a 100644 --- a/LPC804.mex +++ b/LPC804.mex @@ -28,6 +28,10 @@ + + + + @@ -196,6 +200,43 @@ + + Configures pin routing and optionally pin electrical features. + + true + core0 + true + + + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/board/pin_mux.c b/board/pin_mux.c index 08bd069..7ef22c9 100644 --- a/board/pin_mux.c +++ b/board/pin_mux.c @@ -16,6 +16,10 @@ pin_labels: - {pin_num: '30', pin_signal: PIO0_22, label: LED_R, identifier: LED_R} - {pin_num: '31', pin_signal: PIO0_18, label: LED_G, identifier: LED_G} - {pin_num: '32', pin_signal: PIO0_16/ACMP_I4/ADC_3, label: LED_B, identifier: LED_B} +- {pin_num: '16', pin_signal: PIO0_15/ADC_8, label: IO0, identifier: IO0} +- {pin_num: '8', pin_signal: PIO0_11/ADC_6/WKTCLKIN, label: IO1, identifier: IO1} +- {pin_num: '9', pin_signal: PIO0_10/ADC_7, label: IO2, identifier: IO2} +- {pin_num: '15', pin_signal: PIO0_20, label: IO3, identifier: IO3} * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS *********** */ /* clang-format on */ @@ -37,6 +41,7 @@ void BOARD_InitBootPins(void) BOARD_InitADCPins(); BOARD_InitDACPins(); BOARD_InitI2CPins(); + BOARD_InitIOPins(); } /* clang-format off */ @@ -257,6 +262,64 @@ void BOARD_InitI2CPins(void) /* Disable clock for switch matrix. */ CLOCK_DisableClock(kCLOCK_Swm); } + +/* clang-format off */ +/* + * TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* +BOARD_InitIOPins: +- options: {callFromInitBoot: 'true', coreID: core0, enableClock: 'true'} +- pin_list: + - {pin_num: '16', peripheral: GPIO, signal: 'PIO0, 15', pin_signal: PIO0_15/ADC_8, mode: repeater} + - {pin_num: '8', peripheral: GPIO, signal: 'PIO0, 11', pin_signal: PIO0_11/ADC_6/WKTCLKIN, mode: repeater} + - {pin_num: '9', peripheral: GPIO, signal: 'PIO0, 10', pin_signal: PIO0_10/ADC_7, mode: repeater} + - {pin_num: '15', peripheral: GPIO, signal: 'PIO0, 20', pin_signal: PIO0_20, mode: repeater} + * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS *********** + */ +/* clang-format on */ + +/* FUNCTION ************************************************************************************************************ + * + * Function Name : BOARD_InitIOPins + * Description : Configures pin routing and optionally pin electrical features. + * + * END ****************************************************************************************************************/ +/* Function assigned for the Cortex-M0P */ +void BOARD_InitIOPins(void) +{ + /* Enables clock for IOCON.: enable */ + CLOCK_EnableClock(kCLOCK_Iocon); + + IOCON->PIO[8] = ((IOCON->PIO[8] & + /* Mask bits to zero which are setting */ + (~(IOCON_PIO_MODE_MASK))) + + /* Selects function mode (on-chip pull-up/pull-down resistor control).: Repeater. Repeater mode. */ + | IOCON_PIO_MODE(PIO0_10_MODE_REPEATER)); + + IOCON->PIO[7] = ((IOCON->PIO[7] & + /* Mask bits to zero which are setting */ + (~(IOCON_PIO_MODE_MASK))) + + /* Selects function mode (on-chip pull-up/pull-down resistor control).: Repeater. Repeater mode. */ + | IOCON_PIO_MODE(PIO0_11_MODE_REPEATER)); + + IOCON->PIO[10] = ((IOCON->PIO[10] & + /* Mask bits to zero which are setting */ + (~(IOCON_PIO_MODE_MASK))) + + /* Selects function mode (on-chip pull-up/pull-down resistor control).: Repeater. Repeater mode. */ + | IOCON_PIO_MODE(PIO0_15_MODE_REPEATER)); + + IOCON->PIO[22] = ((IOCON->PIO[22] & + /* Mask bits to zero which are setting */ + (~(IOCON_PIO_MODE_MASK))) + + /* Selects function mode (on-chip pull-up/pull-down resistor control).: Repeater. Repeater mode. */ + | IOCON_PIO_MODE(PIO0_20_MODE_REPEATER)); + + /* Disable clock for switch matrix. */ + CLOCK_DisableClock(kCLOCK_Swm); +} /*********************************************************************************************************************** * EOF **********************************************************************************************************************/ diff --git a/board/pin_mux.h b/board/pin_mux.h index 57457d9..92a5fb5 100644 --- a/board/pin_mux.h +++ b/board/pin_mux.h @@ -113,6 +113,69 @@ void BOARD_InitDACPins(void); /* Function assigned for the Cortex-M0P */ */ void BOARD_InitI2CPins(void); /* Function assigned for the Cortex-M0P */ +/*! + * @brief Selects function mode (on-chip pull-up/pull-down resistor control).: Repeater. Repeater mode. */ +#define PIO0_10_MODE_REPEATER 0x03u +/*! + * @brief Selects function mode (on-chip pull-up/pull-down resistor control).: Repeater. Repeater mode. */ +#define PIO0_11_MODE_REPEATER 0x03u +/*! + * @brief Selects function mode (on-chip pull-up/pull-down resistor control).: Repeater. Repeater mode. */ +#define PIO0_15_MODE_REPEATER 0x03u +/*! + * @brief Selects function mode (on-chip pull-up/pull-down resistor control).: Repeater. Repeater mode. */ +#define PIO0_20_MODE_REPEATER 0x03u + +/*! @name PIO0_15 (number 16), IO0 + @{ */ + +/* Symbols to be used with GPIO driver */ +#define BOARD_INITIOPINS_IO0_GPIO GPIO /*!<@brief GPIO peripheral base pointer */ +#define BOARD_INITIOPINS_IO0_GPIO_PIN_MASK (1U << 15U) /*!<@brief GPIO pin mask */ +#define BOARD_INITIOPINS_IO0_PORT 0U /*!<@brief PORT device index: 0 */ +#define BOARD_INITIOPINS_IO0_PIN 15U /*!<@brief PORT pin number */ +#define BOARD_INITIOPINS_IO0_PIN_MASK (1U << 15U) /*!<@brief PORT pin mask */ + /* @} */ + +/*! @name PIO0_11 (number 8), IO1 + @{ */ + +/* Symbols to be used with GPIO driver */ +#define BOARD_INITIOPINS_IO1_GPIO GPIO /*!<@brief GPIO peripheral base pointer */ +#define BOARD_INITIOPINS_IO1_GPIO_PIN_MASK (1U << 11U) /*!<@brief GPIO pin mask */ +#define BOARD_INITIOPINS_IO1_PORT 0U /*!<@brief PORT device index: 0 */ +#define BOARD_INITIOPINS_IO1_PIN 11U /*!<@brief PORT pin number */ +#define BOARD_INITIOPINS_IO1_PIN_MASK (1U << 11U) /*!<@brief PORT pin mask */ + /* @} */ + +/*! @name PIO0_10 (number 9), IO2 + @{ */ + +/* Symbols to be used with GPIO driver */ +#define BOARD_INITIOPINS_IO2_GPIO GPIO /*!<@brief GPIO peripheral base pointer */ +#define BOARD_INITIOPINS_IO2_GPIO_PIN_MASK (1U << 10U) /*!<@brief GPIO pin mask */ +#define BOARD_INITIOPINS_IO2_PORT 0U /*!<@brief PORT device index: 0 */ +#define BOARD_INITIOPINS_IO2_PIN 10U /*!<@brief PORT pin number */ +#define BOARD_INITIOPINS_IO2_PIN_MASK (1U << 10U) /*!<@brief PORT pin mask */ + /* @} */ + +/*! @name PIO0_20 (number 15), IO3 + @{ */ + +/* Symbols to be used with GPIO driver */ +#define BOARD_INITIOPINS_IO3_GPIO GPIO /*!<@brief GPIO peripheral base pointer */ +#define BOARD_INITIOPINS_IO3_GPIO_PIN_MASK (1U << 20U) /*!<@brief GPIO pin mask */ +#define BOARD_INITIOPINS_IO3_PORT 0U /*!<@brief PORT device index: 0 */ +#define BOARD_INITIOPINS_IO3_PIN 20U /*!<@brief PORT pin number */ +#define BOARD_INITIOPINS_IO3_PIN_MASK (1U << 20U) /*!<@brief PORT pin mask */ + /* @} */ + +/*! + * @brief Configures pin routing and optionally pin electrical features. + * + */ +void BOARD_InitIOPins(void); /* Function assigned for the Cortex-M0P */ + #if defined(__cplusplus) } #endif diff --git a/include/app_gpio.h b/include/app_gpio.h new file mode 100644 index 0000000..1e98127 --- /dev/null +++ b/include/app_gpio.h @@ -0,0 +1,7 @@ +#ifndef APP_GPIO_H +#define APP_GPIO_H + +void app_gpio_init(void); +void app_gpio_update(void); + +#endif // APP_GPIO_H diff --git a/include/app_led.h b/include/app_led.h new file mode 100644 index 0000000..655eeb2 --- /dev/null +++ b/include/app_led.h @@ -0,0 +1,25 @@ +#ifndef APP_LED_H +#define APP_LED_H + +#include "fsl_common_arm.h" +#include "pin_mux.h" + +typedef enum { + APP_LED_RED = BOARD_INITLEDPINS_LED_R_PIN, + APP_LED_GREEN = BOARD_INITLEDPINS_LED_G_PIN, + APP_LED_BLUE = BOARD_INITLEDPINS_LED_B_PIN, +} app_led_t; + +static inline void app_led_on(app_led_t led) { + GPIO->B[0][led] = 0U; +} + +static inline void app_led_off(app_led_t led) { + GPIO->B[0][led] = 1U; +} + +static inline void app_led_toggle(app_led_t led) { + GPIO->B[0][led] ^= 1U; +} + +#endif // APP_LED_H diff --git a/include/app_periodic_tasks.h b/include/app_periodic_tasks.h new file mode 100644 index 0000000..c3509af --- /dev/null +++ b/include/app_periodic_tasks.h @@ -0,0 +1,6 @@ +#ifndef APP_PERIODIC_TASKS_H +#define APP_PERIODIC_TASKS_H + +void app_periodic_tasks_init(void); + +#endif // APP_PERIODIC_TASKS_H diff --git a/include/app_reg_if.h b/include/app_reg_if.h index 312930a..d9c10fb 100644 --- a/include/app_reg_if.h +++ b/include/app_reg_if.h @@ -4,9 +4,18 @@ #include #include +#define APP_REG_CFG 0x00U + +#define APP_REG_GPIO_CFG 0x10U +#define APP_REG_GPIO_DATA_OUT 0x11U +#define APP_REG_GPIO_DATA_IN 0x92U + #define APP_REG_IF_REG_ID 0xFFU -uint16_t app_reg_if_read(uint8_t reg); -void app_reg_if_write(uint8_t reg, uint16_t data, bool check_attr); +uint16_t app_reg_if_external_read(uint8_t reg); +void app_reg_if_external_write(uint8_t reg, uint16_t data); + +uint16_t app_reg_if_internal_read(uint8_t reg); +void app_reg_if_internal_write(uint8_t reg, uint16_t data); #endif // APP_REG_IF_H diff --git a/src/app_gpio.c b/src/app_gpio.c new file mode 100644 index 0000000..47bbbf5 --- /dev/null +++ b/src/app_gpio.c @@ -0,0 +1,75 @@ +/* Board */ +#include "pin_mux.h" + +/* SDK drivers */ +#include "fsl_gpio.h" + +/* App */ +#include "app_gpio.h" +#include "app_reg_if.h" + +#define APP_GPIO_PIN_COUNT 4 + +#define APP_GPIO_CFG_OUTPUT_PP 0 +#define APP_GPIO_CFG_OUTPUT_OD 1 +#define APP_GPIO_CFG_INPUT 2 +#define APP_GPIO_CFG_AF 3 + +static const uint8_t s_app_gpio_id_table[APP_GPIO_PIN_COUNT] = { + BOARD_INITIOPINS_IO0_PIN, + BOARD_INITIOPINS_IO1_PIN, + BOARD_INITIOPINS_IO2_PIN, + BOARD_INITIOPINS_IO3_PIN, +}; + +static const uint32_t s_app_gpio_mask_table[APP_GPIO_PIN_COUNT] = { + BOARD_INITIOPINS_IO0_PIN_MASK, + BOARD_INITIOPINS_IO1_PIN_MASK, + BOARD_INITIOPINS_IO2_PIN_MASK, + BOARD_INITIOPINS_IO3_PIN_MASK, +}; + +void app_gpio_init(void) { + GPIO->DIRCLR[0] = (BOARD_INITIOPINS_IO0_PIN_MASK | BOARD_INITIOPINS_IO1_PIN_MASK | BOARD_INITIOPINS_IO2_PIN_MASK | + BOARD_INITIOPINS_IO3_PIN_MASK); + + /* CFG register fields: + * GPIO0_CFG: [1:0] + * GPIO1_CFG: [3:2] + * GPIO2_CFG: [5:4] + * GPIO3_CFG: [7:6] + * + * Values: + * 2'b00: OUTPUT_PP + * 2'b01: OUTPUT_OD + * 2'b10: INPUT + * 2'b11: AF + */ + + app_reg_if_internal_write(APP_REG_GPIO_CFG, 0x00AAU); + app_reg_if_internal_write(APP_REG_GPIO_DATA_IN, 0x0000U); + app_reg_if_internal_write(APP_REG_GPIO_DATA_OUT, 0x0000U); +} + +void app_gpio_update(void) { + uint16_t cfg = app_reg_if_internal_read(APP_REG_GPIO_CFG); + uint16_t out = app_reg_if_internal_read(APP_REG_GPIO_DATA_OUT); + uint16_t in = 0x0000U; + + for (uint8_t i = 0; i < APP_GPIO_PIN_COUNT; i++) { + uint8_t mode = (cfg >> (2 * i)) & 0x03U; + if ((mode & 0x02U) == 0U) { + /* Output mode, either OD or PP */ + GPIO->DIRSET[0] = s_app_gpio_mask_table[i]; + GPIO->B[0][s_app_gpio_id_table[i]] = (out & (1 << i)) ? 1 : 0; + } else if((mode & 0x01U) == 0x00U) { + /* Input mode */ + GPIO->DIRCLR[0] = s_app_gpio_mask_table[i]; + } /* Don't touch: AF mode */ + + /* Update input register no matter what function the pin is, since this data is always available. */ + in |= (GPIO->B[0][s_app_gpio_id_table[i]] << i); + } + + app_reg_if_internal_write(APP_REG_GPIO_DATA_IN, in); +} diff --git a/src/app_i2c_if.c b/src/app_i2c_if.c index ec8ee4f..e3521a8 100644 --- a/src/app_i2c_if.c +++ b/src/app_i2c_if.c @@ -59,7 +59,6 @@ int app_i2c_if_init(void) { } void I2C0_IRQHandler(void) { - GPIO_PinWrite(BOARD_INITLEDPINS_LED_B_GPIO, BOARD_INITLEDPINS_LED_B_PORT, BOARD_INITLEDPINS_LED_B_PIN, 0U); uint32_t flags = APP_I2C_INSTANCE->STAT; /* Clear interrupt flags */ @@ -90,7 +89,7 @@ void I2C0_IRQHandler(void) { if (s_app_i2c_write_ptr < APP_I2C_READ_LEN) { if (s_app_i2c_read_ptr == 0U) { /* First read, read register to buffer */ - uint16_t reg_data = app_reg_if_read(s_app_i2c_read_reg_addr); + uint16_t reg_data = app_reg_if_external_read(s_app_i2c_read_reg_addr); s_app_i2c_read_buffer[0] = reg_data & 0xFFU; s_app_i2c_read_buffer[1] = (reg_data >> 8U) & 0xFFU; @@ -103,7 +102,7 @@ void I2C0_IRQHandler(void) { s_app_i2c_read_reg_addr++; s_app_i2c_read_ptr = 0U; - uint16_t reg_data = app_reg_if_read(s_app_i2c_read_reg_addr); + uint16_t reg_data = app_reg_if_external_read(s_app_i2c_read_reg_addr); s_app_i2c_read_buffer[0] = reg_data & 0xFFU; s_app_i2c_read_buffer[1] = (reg_data >> 8U) & 0xFFU; @@ -121,6 +120,11 @@ void I2C0_IRQHandler(void) { if (s_app_i2c_write_ptr == APP_I2C_WRITE_LEN) { /* Complete write, write register. */ + + uint16_t reg_data = (s_app_i2c_write_buffer[2] << 8U) | s_app_i2c_write_buffer[1]; + + app_reg_if_external_write(s_app_i2c_write_buffer[0], reg_data); + } else if (s_app_i2c_write_ptr == 1) { /* Select register to read */ s_app_i2c_read_reg_addr = s_app_i2c_write_buffer[0]; diff --git a/src/app_periodic_tasks.c b/src/app_periodic_tasks.c new file mode 100644 index 0000000..a2db298 --- /dev/null +++ b/src/app_periodic_tasks.c @@ -0,0 +1,38 @@ +/* Board */ +#include "clock_config.h" + +/* SDK drivers */ +#include "fsl_mrt.h" + +/* App */ +#include "app_gpio.h" +#include "app_periodic_tasks.h" + +#define APP_PERIODIC_RATE 1000 + +void app_periodic_tasks_init(void) { + CLOCK_EnableClock(kCLOCK_Mrt); + + mrt_config_t mrt_cfg = { + .enableMultiTask = false, + }; + + MRT_Init(MRT0, &mrt_cfg); + MRT_SetupChannelMode(MRT0, kMRT_Channel_0, kMRT_RepeatMode); + MRT_EnableInterrupts(MRT0, kMRT_Channel_0, kMRT_TimerInterruptEnable); + + EnableIRQ(MRT0_IRQn); + NVIC_SetPriority(MRT0_IRQn, 2); + + MRT_StartTimer(MRT0, kMRT_Channel_0, (CLOCK_GetCoreSysClkFreq() / APP_PERIODIC_RATE)); +} + +static void app_periodic_task(void) { + app_gpio_update(); +} + +void MRT0_IRQHandler(void) { + app_periodic_task(); + + MRT_ClearStatusFlags(MRT0, kMRT_Channel_0, kMRT_TimerInterruptFlag); +} \ No newline at end of file diff --git a/src/app_reg_if.c b/src/app_reg_if.c index b34f04c..723bade 100644 --- a/src/app_reg_if.c +++ b/src/app_reg_if.c @@ -1,19 +1,25 @@ #include "app_reg_if.h" -#define APP_REG_IF_ATTR_RO (1U << 0U) +#define APP_REG_IF_FILE_SIZE 256 +#define APP_REG_IF_RO_START 0x80U -uint16_t app_reg_if_read(uint8_t reg) { - switch (reg) { - case APP_REG_IF_REG_ID: - return 0xEACE; - default: - return 0x0000; +static uint16_t app_if_reg_file[APP_REG_IF_FILE_SIZE] = { + [APP_REG_IF_REG_ID] = 0xEACE, +}; + +uint16_t app_reg_if_external_read(uint8_t reg) { + return app_if_reg_file[reg]; +} + +void app_reg_if_external_write(uint8_t reg, uint16_t data) { + if (reg < APP_REG_IF_RO_START) { + app_if_reg_file[reg] = data; } } -void app_reg_if_write(uint8_t reg, uint16_t data, bool check_attr) { - switch (reg) { - default: - break; - } +uint16_t app_reg_if_internal_read(uint8_t reg) { + return app_if_reg_file[reg]; +} +void app_reg_if_internal_write(uint8_t reg, uint16_t data) { + app_if_reg_file[reg] = data; } diff --git a/src/main.c b/src/main.c index 400b861..a944a58 100644 --- a/src/main.c +++ b/src/main.c @@ -4,16 +4,23 @@ #include "pin_mux.h" /* App */ +#include "app_gpio.h" #include "app_i2c_if.h" +#include "app_led.h" +#include "app_periodic_tasks.h" int main(void) { BOARD_InitBootPins(); BOARD_InitBootClocks(); + app_gpio_init(); app_i2c_if_init(); + /* Must be the last */ + app_periodic_tasks_init(); + for (;;) { - GPIO_PortToggle(BOARD_INITLEDPINS_LED_R_GPIO, BOARD_INITLEDPINS_LED_R_PORT, BOARD_INITLEDPINS_LED_R_PIN_MASK); + app_led_toggle(APP_LED_RED); SDK_DelayAtLeastUs(500 * 1000, CLOCK_GetCoreSysClkFreq()); } }