Rewrite I2C register interface.
continuous-integration/drone/push Build is passing Details

Signed-off-by: Yilin Sun <imi415@imi.moe>
This commit is contained in:
Yilin Sun 2023-06-03 16:09:38 +08:00
parent c5fae6db36
commit 626cfa4521
Signed by: imi415
GPG Key ID: 17F01E106F9F5E0A
13 changed files with 251 additions and 119 deletions

View File

@ -43,9 +43,9 @@ set(TARGET_SOURCES
"board/clock_config.c"
"board/peripherals.c"
"board/pin_mux.c"
"src/app_adc.c"
"src/app_i2c_if.c"
"src/app_gpio.c"
"src/app_periodic_tasks.c"
"src/app_reg_if.c"
"src/app_sys_utils.c"
"src/main.c"

10
include/app_adc.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef APP_ADC_H
#define APP_ADC_H
#include "fsl_common_arm.h"
void app_adc_init(void);
uint16_t app_adc_module_reg_read(uint8_t addr);
void app_adc_module_reg_write(uint8_t addr, uint16_t data);
#endif // APP_ADC_H

View File

@ -1,7 +1,10 @@
#ifndef APP_GPIO_H
#define APP_GPIO_H
void app_gpio_init(void);
void app_gpio_update(void);
#include "fsl_common_arm.h"
void app_gpio_init(void);
uint16_t app_gpio_module_reg_read(uint8_t addr);
void app_gpio_module_reg_write(uint8_t addr, uint16_t data);
#endif // APP_GPIO_H

View File

@ -1,6 +0,0 @@
#ifndef APP_PERIODIC_TASKS_H
#define APP_PERIODIC_TASKS_H
void app_periodic_tasks_init(void);
#endif // APP_PERIODIC_TASKS_H

View File

@ -4,18 +4,7 @@
#include <stdbool.h>
#include <stdint.h>
#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_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);
uint16_t app_reg_if_read(uint8_t reg);
void app_reg_if_write(uint8_t reg, uint16_t data);
#endif // APP_REG_IF_H

View File

@ -3,10 +3,8 @@
#include "fsl_common_arm.h"
static inline void app_sys_util_reset(void) {
NVIC_SystemReset();
}
void app_sys_util_update(void);
void app_sys_utils_init(void);
uint16_t app_sys_utils_module_reg_read(uint8_t addr);
void app_sys_utils_module_reg_write(uint8_t addr, uint16_t data);
#endif // APP_SYS_UTILS_H

12
src/app_adc.c Normal file
View File

@ -0,0 +1,12 @@
#include "app_adc.h"
void app_adc_init(void) {
}
uint16_t app_adc_module_reg_read(uint8_t addr) {
return 0x0000U;
}
void app_adc_module_reg_write(uint8_t addr, uint16_t data) {
}

View File

@ -3,11 +3,16 @@
/* SDK drivers */
#include "fsl_gpio.h"
#include "fsl_swm.h"
/* App */
#include "app_gpio.h"
#include "app_reg_if.h"
#define APP_GPIO_REG_OFFSET_CFG (0x00U)
#define APP_GPIO_REG_OFFSET_INPUT (0x01U)
#define APP_GPIO_REG_OFFSET_OUTPUT (0x02U)
#define APP_GPIO_PIN_COUNT 4
#define APP_GPIO_CFG_OUTPUT_PP 0
@ -29,10 +34,51 @@ static const uint32_t s_app_gpio_mask_table[APP_GPIO_PIN_COUNT] = {
BOARD_INITIOPINS_IO3_PIN_MASK,
};
static inline uint16_t app_gpio_read_reg_cfg(void);
static inline uint16_t app_gpio_read_reg_input(void);
static inline uint16_t app_gpio_read_reg_output(void);
static inline void app_gpio_write_reg_cfg(uint16_t data);
static inline void app_gpio_write_reg_output(uint16_t data);
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);
}
uint16_t app_gpio_module_reg_read(uint8_t addr) {
uint16_t ret = 0x5555U;
switch (addr) {
case APP_GPIO_REG_OFFSET_CFG:
ret = app_gpio_read_reg_cfg();
break;
case APP_GPIO_REG_OFFSET_INPUT:
ret = app_gpio_read_reg_input();
break;
case APP_GPIO_REG_OFFSET_OUTPUT:
ret = app_gpio_read_reg_output();
break;
default:
break;
}
return ret;
}
void app_gpio_module_reg_write(uint8_t addr, uint16_t data) {
switch (addr) {
case APP_GPIO_REG_OFFSET_CFG:
app_gpio_write_reg_cfg(data);
break;
case APP_GPIO_REG_OFFSET_OUTPUT:
app_gpio_write_reg_output(data);
break;
default:
break;
}
}
static inline uint16_t app_gpio_read_reg_cfg(void) {
/* CFG register fields:
* GPIO0_CFG: [1:0]
* GPIO1_CFG: [3:2]
@ -43,33 +89,78 @@ void app_gpio_init(void) {
* 2'b00: OUTPUT_PP
* 2'b01: OUTPUT_OD
* 2'b10: INPUT
* 2'b11: AF
* 2'b11: Undefined
*/
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;
uint16_t ret = 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) {
uint32_t dir = GPIO->DIR[0] & (1U << s_app_gpio_id_table[i]);
if (dir == 0UL) {
/* 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);
ret |= (2U << (2 * i));
} else {
/* Output mode */
if ((IOCON->PIO[s_app_gpio_id_table[i]] & IOCON_PIO_OD_MASK) == IOCON_PIO_OD(1)) {
/* OD mode */
ret |= (1U << (2 * i));
}
}
}
app_reg_if_internal_write(APP_REG_GPIO_DATA_IN, in);
return ret;
}
static inline void app_gpio_write_reg_cfg(uint16_t data) {
for (uint8_t i = 0; i < APP_GPIO_PIN_COUNT; i++) {
if (data & (2U << (2 * i))) {
/* Input mode */
GPIO->DIRCLR[0] = (1U << s_app_gpio_id_table[i]);
} else {
/* Output mode */
GPIO->DIRSET[0] = (1U << s_app_gpio_id_table[i]);
if (data & (1U << (2 * i))) {
/* OD mode */
IOCON->PIO[s_app_gpio_id_table[i]] |= IOCON_PIO_OD(1);
} else {
/* PP mode */
IOCON->PIO[s_app_gpio_id_table[i]] &= ~(IOCON_PIO_OD(1));
}
}
}
}
static inline uint16_t app_gpio_read_reg_input(void) {
uint16_t ret = 0x0000U;
for (uint8_t i = 0; i < APP_GPIO_PIN_COUNT; i++) {
if (GPIO->B[s_app_gpio_id_table[i]]) {
ret |= (1U << i);
}
}
return ret;
}
static inline uint16_t app_gpio_read_reg_output(void) {
uint16_t ret = 0x0000U;
for (uint8_t i = 0; i < APP_GPIO_PIN_COUNT; i++) {
if (GPIO->SET[0] & (1U << s_app_gpio_id_table[i])) {
ret |= (1U << i);
}
}
return ret;
}
static inline void app_gpio_write_reg_output(uint16_t data) {
for (uint8_t i = 0; i < APP_GPIO_PIN_COUNT; i++) {
if (data & (1 << i)) {
GPIO->SET[0] = (1U << s_app_gpio_id_table[i]);
} else {
GPIO->CLR[0] = (1U << s_app_gpio_id_table[i]);
}
}
}

View File

@ -89,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_external_read(s_app_i2c_read_reg_addr);
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;
@ -102,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_external_read(s_app_i2c_read_reg_addr);
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;
@ -123,7 +123,7 @@ void I2C0_IRQHandler(void) {
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);
app_reg_if_write(s_app_i2c_write_buffer[0], reg_data);
} else if (s_app_i2c_write_ptr == 1) {
/* Select register to read */

View File

@ -1,40 +0,0 @@
/* Board */
#include "clock_config.h"
/* SDK drivers */
#include "fsl_mrt.h"
/* App */
#include "app_gpio.h"
#include "app_periodic_tasks.h"
#include "app_sys_utils.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_sys_util_update();
app_gpio_update();
}
void MRT0_IRQHandler(void) {
app_periodic_task();
MRT_ClearStatusFlags(MRT0, kMRT_Channel_0, kMRT_TimerInterruptFlag);
}

View File

@ -1,25 +1,49 @@
/* App */
#include "app_adc.h"
#include "app_gpio.h"
#include "app_sys_utils.h"
/* Private */
#include "app_reg_if.h"
#define APP_REG_IF_FILE_SIZE 256
#define APP_REG_IF_RO_START 0x80U
#define MODULE_ID_SYS_UTILS 0
#define MODULE_ID_GPIO 1
#define MODULE_ID_ADC 2
static uint16_t app_if_reg_file[APP_REG_IF_FILE_SIZE] = {
[APP_REG_IF_REG_ID] = 0xEACE,
typedef uint16_t (*module_reg_read_t)(uint8_t offset);
typedef void (*module_reg_write_t)(uint8_t offset, uint16_t data);
typedef struct {
module_reg_read_t read;
module_reg_write_t write;
} module_reg_t;
static const module_reg_t s_module_regs[] = {
[MODULE_ID_SYS_UTILS] =
{
.read = app_sys_utils_module_reg_read,
.write = app_sys_utils_module_reg_write,
},
[MODULE_ID_GPIO] =
{
.read = app_gpio_module_reg_read,
.write = app_gpio_module_reg_write,
},
[MODULE_ID_ADC] =
{
.read = app_adc_module_reg_read,
.write = app_adc_module_reg_write,
},
};
uint16_t app_reg_if_external_read(uint8_t reg) {
return app_if_reg_file[reg];
uint16_t app_reg_if_read(uint8_t reg) {
uint8_t module_id = (reg >> 4U) & 0x0FU;
return s_module_regs[module_id].read(reg & 0x0FU);
}
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) {
uint8_t module_id = (reg >> 4U) & 0x0FU;
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;
s_module_regs[module_id].write((reg & 0x0FU), data);
}

View File

@ -4,17 +4,70 @@
/* Private */
#include "app_sys_utils.h"
#define APP_SYS_OFFSET_CFG (0x00U)
#define APP_SYS_OFFSET_VER (0x0EU)
#define APP_SYS_OFFSET_ID (0x0FU)
#define APP_SYS_CONST_ID (0xEACEU)
#define APP_SYS_CONST_VER (0x0000U)
#define APP_SYS_RST_Pos 15
#define APP_SYS_RST_Msk (1U << APP_SYS_RST_Pos)
void app_sys_util_update(void) {
uint16_t cfg = app_reg_if_internal_read(APP_REG_CFG);
static inline uint16_t app_sys_utils_read_reg_cfg(void);
static inline uint16_t app_sys_utils_read_reg_ver(void);
static inline uint16_t app_sys_utils_read_reg_id(void);
if (cfg & APP_SYS_RST_Msk) {
cfg &= ~(APP_SYS_RST_Msk);
static inline void app_sys_utils_write_reg_cfg(uint16_t data);
app_reg_if_internal_write(APP_REG_CFG, cfg);
void app_sys_utils_init(void) {
/* -- */
}
app_sys_util_reset();
uint16_t app_sys_utils_module_reg_read(uint8_t addr) {
uint16_t ret = 0x5555;
switch (addr) {
case APP_SYS_OFFSET_CFG:
ret = app_sys_utils_read_reg_cfg();
break;
case APP_SYS_OFFSET_VER:
ret = app_sys_utils_read_reg_ver();
break;
case APP_SYS_OFFSET_ID:
ret = app_sys_utils_read_reg_id();
break;
default:
break;
}
}
return ret;
}
void app_sys_utils_module_reg_write(uint8_t addr, uint16_t data) {
switch (addr) {
case APP_SYS_OFFSET_CFG:
app_sys_utils_write_reg_cfg(data);
break;
default:
break;
}
}
static inline uint16_t app_sys_utils_read_reg_cfg(void) {
return 0x0000U;
}
static inline uint16_t app_sys_utils_read_reg_ver(void) {
return APP_SYS_CONST_VER;
}
static inline uint16_t app_sys_utils_read_reg_id(void) {
return APP_SYS_CONST_ID;
}
static inline void app_sys_utils_write_reg_cfg(uint16_t data) {
if (data & APP_SYS_RST_Msk) {
NVIC_SystemReset();
}
}

View File

@ -4,21 +4,19 @@
#include "pin_mux.h"
/* App */
#include "app_adc.h"
#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_adc_init();
app_i2c_if_init();
/* Must be the last */
app_periodic_tasks_init();
for (;;) {
app_led_toggle(APP_LED_RED);
SDK_DelayAtLeastUs(500 * 1000, CLOCK_GetCoreSysClkFreq());