From 824a3b3ee44f1145e5b6bedec61a7ad5834b151b Mon Sep 17 00:00:00 2001 From: Yilin Sun Date: Sun, 28 May 2023 23:28:29 +0800 Subject: [PATCH] Initial commit Signed-off-by: Yilin Sun --- .clang-format | 12 ++++ .drone.yml | 17 ++++++ .gitignore | 5 ++ CMakeLists.txt | 4 +- LPC804.mex | 37 ++++++++++++ SDK | 1 + board/pin_mux.c | 53 +++++++++++++++++ board/pin_mux.h | 21 +++++++ include/app_i2c_if.h | 6 ++ include/app_reg_if.h | 12 ++++ src/app_i2c_if.c | 132 +++++++++++++++++++++++++++++++++++++++++++ src/app_reg_if.c | 19 +++++++ src/main.c | 10 +++- 13 files changed, 325 insertions(+), 4 deletions(-) create mode 100644 .clang-format create mode 100644 .drone.yml create mode 100644 .gitignore create mode 160000 SDK create mode 100644 include/app_i2c_if.h create mode 100644 include/app_reg_if.h create mode 100644 src/app_i2c_if.c create mode 100644 src/app_reg_if.c diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..214adf0 --- /dev/null +++ b/.clang-format @@ -0,0 +1,12 @@ +BasedOnStyle: Google +IndentWidth: 4 +AlignConsecutiveMacros: Consecutive +AlignConsecutiveDeclarations: Consecutive +AlignConsecutiveAssignments: Consecutive +AllowShortFunctionsOnASingleLine: None +BreakBeforeBraces: Custom +BraceWrapping: + AfterEnum: false + AfterStruct: false + SplitEmptyFunction: false +ColumnLimit: 120 \ No newline at end of file diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 0000000..94e5a4b --- /dev/null +++ b/.drone.yml @@ -0,0 +1,17 @@ +--- +kind: pipeline +type: docker +name: Build + +steps: + - name: Submodules + image: alpine/git + commands: + - git submodule update --init --recursive + + - name: Build + image: "git.minori.work/embedded_sdk/embedded-builder-arm:12.2.mpacbti-rel1" + commands: + - mkdir build && cd build + - cmake -DCMAKE_TOOLCHAIN_FILE=arm-none-eabi.cmake .. + - make diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2da6168 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +/cmake-build-* +/build +/board/*.bak +/.vscode + diff --git a/CMakeLists.txt b/CMakeLists.txt index 57526d9..5d4d26e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.10) -project(mpyate_template) +project(mpyate_firmware) enable_language(CXX) enable_language(ASM) @@ -43,6 +43,8 @@ set(TARGET_SOURCES "board/clock_config.c" "board/peripherals.c" "board/pin_mux.c" + "src/app_i2c_if.c" + "src/app_reg_if.c" "src/main.c" ) diff --git a/LPC804.mex b/LPC804.mex index 64f48c0..9010032 100644 --- a/LPC804.mex +++ b/LPC804.mex @@ -159,6 +159,43 @@ + + Configures pin routing and optionally pin electrical features. + + true + core0 + true + + + + + true + + + + + true + + + + + true + + + + + + + + + + + + + + + + diff --git a/SDK b/SDK new file mode 160000 index 0000000..e468131 --- /dev/null +++ b/SDK @@ -0,0 +1 @@ +Subproject commit e46813114663364b03f7507d3926852fe55b2b58 diff --git a/board/pin_mux.c b/board/pin_mux.c index f9b6a30..08bd069 100644 --- a/board/pin_mux.c +++ b/board/pin_mux.c @@ -36,6 +36,7 @@ void BOARD_InitBootPins(void) BOARD_InitLEDPins(); BOARD_InitADCPins(); BOARD_InitDACPins(); + BOARD_InitI2CPins(); } /* clang-format off */ @@ -204,6 +205,58 @@ void BOARD_InitDACPins(void) /* Disable clock for switch matrix. */ CLOCK_DisableClock(kCLOCK_Swm); } + +/* clang-format off */ +/* + * TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* +BOARD_InitI2CPins: +- options: {callFromInitBoot: 'true', coreID: core0, enableClock: 'true'} +- pin_list: + - {pin_num: '18', peripheral: I2C0, signal: SCL, pin_signal: PIO0_9/ADC_4, mode: inactive} + - {pin_num: '17', peripheral: I2C0, signal: SDA, pin_signal: PIO0_1/ADC_0/ACMP_I2/CLKIN, mode: inactive} + * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS *********** + */ +/* clang-format on */ + +/* FUNCTION ************************************************************************************************************ + * + * Function Name : BOARD_InitI2CPins + * Description : Configures pin routing and optionally pin electrical features. + * + * END ****************************************************************************************************************/ +/* Function assigned for the Cortex-M0P */ +void BOARD_InitI2CPins(void) +{ + /* Enables clock for IOCON.: enable */ + CLOCK_EnableClock(kCLOCK_Iocon); + /* Enables clock for switch matrix.: enable */ + CLOCK_EnableClock(kCLOCK_Swm); + + IOCON->PIO[11] = ((IOCON->PIO[11] & + /* Mask bits to zero which are setting */ + (~(IOCON_PIO_MODE_MASK))) + + /* Selects function mode (on-chip pull-up/pull-down resistor control).: Inactive. Inactive (no + * pull-down/pull-up resistor enabled). */ + | IOCON_PIO_MODE(PIO0_1_MODE_INACTIVE)); + + IOCON->PIO[13] = ((IOCON->PIO[13] & + /* Mask bits to zero which are setting */ + (~(IOCON_PIO_MODE_MASK))) + + /* Selects function mode (on-chip pull-up/pull-down resistor control).: Inactive. Inactive (no + * pull-down/pull-up resistor enabled). */ + | IOCON_PIO_MODE(PIO0_9_MODE_INACTIVE)); + + /* I2C0_SDA connect to P0_1 */ + SWM_SetMovablePinSelect(SWM0, kSWM_I2C0_SDA, kSWM_PortPin_P0_1); + + /* I2C0_SCL connect to P0_9 */ + SWM_SetMovablePinSelect(SWM0, kSWM_I2C0_SCL, kSWM_PortPin_P0_9); + + /* Disable clock for switch matrix. */ + CLOCK_DisableClock(kCLOCK_Swm); +} /*********************************************************************************************************************** * EOF **********************************************************************************************************************/ diff --git a/board/pin_mux.h b/board/pin_mux.h index b68c333..57457d9 100644 --- a/board/pin_mux.h +++ b/board/pin_mux.h @@ -92,6 +92,27 @@ void BOARD_InitADCPins(void); /* Function assigned for the Cortex-M0P */ */ void BOARD_InitDACPins(void); /* Function assigned for the Cortex-M0P */ +/*! + * @brief + * Selects function mode (on-chip pull-up/pull-down resistor control). + * : Inactive. + * Inactive (no pull-down/pull-up resistor enabled). + */ +#define PIO0_1_MODE_INACTIVE 0x00u +/*! + * @brief + * Selects function mode (on-chip pull-up/pull-down resistor control). + * : Inactive. + * Inactive (no pull-down/pull-up resistor enabled). + */ +#define PIO0_9_MODE_INACTIVE 0x00u + +/*! + * @brief Configures pin routing and optionally pin electrical features. + * + */ +void BOARD_InitI2CPins(void); /* Function assigned for the Cortex-M0P */ + #if defined(__cplusplus) } #endif diff --git a/include/app_i2c_if.h b/include/app_i2c_if.h new file mode 100644 index 0000000..d252147 --- /dev/null +++ b/include/app_i2c_if.h @@ -0,0 +1,6 @@ +#ifndef APP_I2C_IF_H +#define APP_I2C_IF_H + +int app_i2c_if_init(void); + +#endif // APP_I2C_IF_H diff --git a/include/app_reg_if.h b/include/app_reg_if.h new file mode 100644 index 0000000..312930a --- /dev/null +++ b/include/app_reg_if.h @@ -0,0 +1,12 @@ +#ifndef APP_REG_IF_H +#define APP_REG_IF_H + +#include +#include + +#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); + +#endif // APP_REG_IF_H diff --git a/src/app_i2c_if.c b/src/app_i2c_if.c new file mode 100644 index 0000000..ec8ee4f --- /dev/null +++ b/src/app_i2c_if.c @@ -0,0 +1,132 @@ +/* Board */ +#include "pin_mux.h" + +/* SDK drivers */ +#include "fsl_clock.h" +#include "fsl_common.h" +#include "fsl_common_arm.h" +#include "fsl_gpio.h" + +/* App */ +#include "app_i2c_if.h" +#include "app_reg_if.h" + +#define APP_I2C_INSTANCE I2C0 +#define APP_I2C_ADDR (0x28U) + +#define APP_I2C_WRITE_LEN (3) +#define APP_I2C_READ_LEN (2) + +uint8_t s_app_i2c_write_ptr; +uint8_t s_app_i2c_write_buffer[APP_I2C_WRITE_LEN]; + +uint8_t s_app_i2c_read_ptr; +uint8_t s_app_i2c_read_reg_addr; +uint8_t s_app_i2c_read_buffer[APP_I2C_READ_LEN]; + +int app_i2c_if_init(void) { + CLOCK_Select(kI2C0_Clk_From_MainClk); + CLOCK_EnableClock(kCLOCK_I2c0); + + RESET_PeripheralReset(kI2C0_RST_N_SHIFT_RSTn); + + APP_I2C_INSTANCE->CLKDIV = 7U; + + APP_I2C_INSTANCE->SLVADR[0] = I2C_SLVADR_SLVADR(APP_I2C_ADDR); // Use slave address 0 + APP_I2C_INSTANCE->SLVQUAL0 = 0UL; // Use the address as-is + + APP_I2C_INSTANCE->INTENCLR = + I2C_INTENCLR_MSTPENDINGCLR(1) | I2C_INTENCLR_MSTARBLOSSCLR(1) | I2C_INTENCLR_MSTSTSTPERRCLR(1) | + I2C_INTENCLR_SLVPENDINGCLR(1) | I2C_INTENCLR_SLVNOTSTRCLR(1) | I2C_INTENCLR_SLVDESELCLR(1) | + I2C_INTENCLR_MONRDYCLR(1) | I2C_INTENCLR_MONIDLECLR(1) | I2C_INTENCLR_EVENTTIMEOUTCLR(1) | + I2C_INTENCLR_SCLTIMEOUTCLR(1); // Disable all interrupts + + APP_I2C_INSTANCE->STAT = I2C_STAT_MSTARBLOSS(1) | I2C_STAT_MSTSTSTPERR(1) | I2C_STAT_SLVDESEL(1) | + I2C_STAT_MONOV(1) | I2C_STAT_MONIDLE(1) | I2C_STAT_EVENTTIMEOUT(1) | + I2C_STAT_SCLTIMEOUT(1); // Clear all interrupt flags + + APP_I2C_INSTANCE->INTENSET = I2C_INTENSET_SLVPENDINGEN(1) | I2C_INTENSET_SLVDESELEN(1); // Enable slave interrupts + + APP_I2C_INSTANCE->CFG = I2C_CFG_SLVEN(1); // Enable Slave mode + + s_app_i2c_write_ptr = 0U; + s_app_i2c_read_ptr = 0U; + + NVIC_SetPriority(I2C0_IRQn, 0); + EnableIRQ(I2C0_IRQn); + + return 0; +} + +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 */ + APP_I2C_INSTANCE->STAT |= flags; + /* Slave requires software servicing */ + if (flags & I2C_STAT_SLVPENDING_MASK) { + uint32_t slave_state = (flags & I2C_STAT_SLVSTATE_MASK); + + if (slave_state == I2C_STAT_SLVSTATE(0)) { + /* A new address cycle has started, slave is selected with address match */ + + /* Ack the address */ + APP_I2C_INSTANCE->SLVCTL = I2C_SLVCTL_SLVCONTINUE(1); + } else if (slave_state == I2C_STAT_SLVSTATE(1)) { + /* Data is ready to be read out */ + if (s_app_i2c_write_ptr == APP_I2C_WRITE_LEN) { + /* Master sent too much data, Nack. */ + APP_I2C_INSTANCE->SLVCTL = I2C_SLVCTL_SLVNACK(1); + } else { + s_app_i2c_write_buffer[s_app_i2c_write_ptr] = APP_I2C_INSTANCE->SLVDAT; + s_app_i2c_write_ptr++; + + APP_I2C_INSTANCE->SLVCTL = I2C_SLVCTL_SLVCONTINUE(1); + } + } else if (slave_state == I2C_STAT_SLVSTATE(2)) { + /* Data needs to be written to host */ + + 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); + + s_app_i2c_read_buffer[0] = reg_data & 0xFFU; + s_app_i2c_read_buffer[1] = (reg_data >> 8U) & 0xFFU; + } + + APP_I2C_INSTANCE->SLVDAT = s_app_i2c_read_buffer[s_app_i2c_read_ptr]; + s_app_i2c_read_ptr++; + } else { + /* Max length reached, start a new register read with self-increased address */ + 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); + + s_app_i2c_read_buffer[0] = reg_data & 0xFFU; + s_app_i2c_read_buffer[1] = (reg_data >> 8U) & 0xFFU; + + APP_I2C_INSTANCE->SLVDAT = s_app_i2c_read_buffer[s_app_i2c_read_ptr]; + s_app_i2c_read_ptr++; + } + + APP_I2C_INSTANCE->SLVCTL = I2C_SLVCTL_SLVCONTINUE(1); + } + } + + if (flags & I2C_STAT_SLVDESEL_MASK) { + /* Slave is de-selected due to another address cycle or STOP event */ + + if (s_app_i2c_write_ptr == APP_I2C_WRITE_LEN) { + /* Complete write, write register. */ + } else if (s_app_i2c_write_ptr == 1) { + /* Select register to read */ + s_app_i2c_read_reg_addr = s_app_i2c_write_buffer[0]; + } + + s_app_i2c_write_ptr = 0U; + s_app_i2c_read_ptr = 0U; + } +} \ No newline at end of file diff --git a/src/app_reg_if.c b/src/app_reg_if.c new file mode 100644 index 0000000..b34f04c --- /dev/null +++ b/src/app_reg_if.c @@ -0,0 +1,19 @@ +#include "app_reg_if.h" + +#define APP_REG_IF_ATTR_RO (1U << 0U) + +uint16_t app_reg_if_read(uint8_t reg) { + switch (reg) { + case APP_REG_IF_REG_ID: + return 0xEACE; + default: + return 0x0000; + } +} + +void app_reg_if_write(uint8_t reg, uint16_t data, bool check_attr) { + switch (reg) { + default: + break; + } +} diff --git a/src/main.c b/src/main.c index c4bd367..400b861 100644 --- a/src/main.c +++ b/src/main.c @@ -1,15 +1,19 @@ +/* Board */ #include "board.h" #include "clock_config.h" -#include "fsl_debug_console.h" #include "pin_mux.h" +/* App */ +#include "app_i2c_if.h" + int main(void) { BOARD_InitBootPins(); BOARD_InitBootClocks(); + app_i2c_if_init(); + for (;;) { - GPIO_PortToggle(BOARD_INITLEDPINS_LED_R_GPIO, BOARD_INITLEDPINS_LED_R_PORT, - BOARD_INITLEDPINS_LED_R_GPIO_PIN_MASK); + GPIO_PortToggle(BOARD_INITLEDPINS_LED_R_GPIO, BOARD_INITLEDPINS_LED_R_PORT, BOARD_INITLEDPINS_LED_R_PIN_MASK); SDK_DelayAtLeastUs(500 * 1000, CLOCK_GetCoreSysClkFreq()); } }