diff --git a/arch/arm/src/imxrt/Kconfig b/arch/arm/src/imxrt/Kconfig index cf5d387096..66d21210e6 100644 --- a/arch/arm/src/imxrt/Kconfig +++ b/arch/arm/src/imxrt/Kconfig @@ -1025,6 +1025,10 @@ config ENC1_HNE endif # ENC1_HIP +config ENC1_XIE + bool "INDEX signal position capture" + default n + config ENC1_XIP bool "INDEX signal initializes position counter" default n @@ -1100,6 +1104,10 @@ config ENC2_HNE endif # ENC2_HIP +config ENC2_XIE + bool "INDEX signal position capture" + default n + config ENC2_XIP bool "INDEX signal initializes position counter" default n @@ -1177,6 +1185,10 @@ config ENC3_HNE endif # ENC3_HIP +config ENC3_XIE + bool "INDEX signal position capture" + default n + config ENC3_XIP bool "INDEX signal initializes position counter" default n @@ -1252,6 +1264,10 @@ config ENC4_HNE endif # ENC4_HIP +config ENC4_XIE + bool "INDEX signal position capture" + default n + config ENC4_XIP bool "INDEX signal initializes position counter" default n diff --git a/arch/arm/src/imxrt/imxrt_enc.c b/arch/arm/src/imxrt/imxrt_enc.c index a0a9a53ea0..ae1abe3553 100644 --- a/arch/arm/src/imxrt/imxrt_enc.c +++ b/arch/arm/src/imxrt/imxrt_enc.c @@ -80,6 +80,10 @@ # define CONFIG_ENC1_HNE 0 #endif +#ifndef CONFIG_ENC1_XIE +# define CONFIG_ENC1_XIE 0 +#endif + #ifndef CONFIG_ENC1_XIP # define CONFIG_ENC1_XIP 0 #endif @@ -121,6 +125,10 @@ # define CONFIG_ENC2_HNE 0 #endif +#ifndef CONFIG_ENC2_XIE +# define CONFIG_ENC2_XIE 0 +#endif + #ifndef CONFIG_ENC2_XIP # define CONFIG_ENC2_XIP 0 #endif @@ -162,6 +170,10 @@ # define CONFIG_ENC3_HNE 0 #endif +#ifndef CONFIG_ENC3_XIE +# define CONFIG_ENC3_XIE 0 +#endif + #ifndef CONFIG_ENC3_XIP # define CONFIG_ENC3_XIP 0 #endif @@ -203,6 +215,10 @@ # define CONFIG_ENC4_HNE 0 #endif +#ifndef CONFIG_ENC4_XIE +# define CONFIG_ENC4_XIE 0 +#endif + #ifndef CONFIG_ENC4_XIP # define CONFIG_ENC4_XIP 0 #endif @@ -236,6 +252,7 @@ #define XNE_SHIFT (3) #define REV_SHIFT (4) #define MOD_SHIFT (5) +#define XIE_SHIFT (6) /**************************************************************************** * Private Types @@ -246,6 +263,7 @@ struct imxrt_qeconfig_s { uint32_t base; /* Register base address */ + uint32_t irq; /* Encoder interrupt */ uint32_t init_val; /* Value to initialize position counters to */ uint32_t modulus; /* Modulus to use when modulo counting is enabled */ uint16_t in_filt_per; /* Period for input filter sampling in # of periph @@ -258,13 +276,18 @@ struct imxrt_qeconfig_s * will reinitialize the position counter. Bits 4-0: * [MOD, REV, XNE, XIP, HNE, HIP] */ - #ifdef CONFIG_DEBUG_SENSORS bool tst_dir_adv; /* Whether to generate down/up test signals */ uint8_t tst_period; /* Period of PHASE pulses in # of periph clock cycles */ #endif }; +struct imxrt_qedata_s +{ + int32_t index_pos; /* Last position of index occurance */ + uint32_t index_cnt; /* Number of index occurance */ +}; + /* ENC Device Private Data */ struct imxrt_enc_lowerhalf_s @@ -277,10 +300,11 @@ struct imxrt_enc_lowerhalf_s /* IMXRT driver-specific fields: */ - const struct imxrt_qeconfig_s *config; /* static configuration */ - sem_t sem_excl; /* Mutual exclusion semaphore to - * ensure atomic 32-bit reads. - */ + FAR const struct imxrt_qeconfig_s *config; /* static configuration */ + struct qe_index_s *data; + sem_t sem_excl; /* Mutual exclusion semaphore to + * ensure atomic 32-bit reads. + */ }; /**************************************************************************** @@ -312,6 +336,8 @@ static void imxrt_enc_modulo_enable(struct imxrt_enc_lowerhalf_s *priv, uint32_t modulus); static void imxrt_enc_modulo_disable(struct imxrt_enc_lowerhalf_s *priv); +static int imxrt_enc_index(int irq, void *context, FAR void *arg); + #ifdef CONFIG_DEBUG_SENSORS static int imxrt_enc_test_gen(struct imxrt_enc_lowerhalf_s *priv, uint16_t value); @@ -350,12 +376,14 @@ static const struct qe_ops_s g_qecallbacks = static const struct imxrt_qeconfig_s imxrt_enc1_config = { .base = IMXRT_ENC1_BASE, + .irq = IMXRT_IRQ_ENC1, .init_val = CONFIG_ENC1_INITVAL, .modulus = CONFIG_ENC1_MODULUS, .in_filt_per = CONFIG_ENC1_FILTPER, .in_filt_cnt = CONFIG_ENC1_FILTCNT, .init_flags = CONFIG_ENC1_HIP << HIP_SHIFT | CONFIG_ENC1_HNE << HNE_SHIFT | + CONFIG_ENC1_XIE << XIE_SHIFT | CONFIG_ENC1_XIP << XIP_SHIFT | CONFIG_ENC1_XNE << XNE_SHIFT | CONFIG_ENC1_DIR << REV_SHIFT | @@ -367,10 +395,18 @@ static const struct imxrt_qeconfig_s imxrt_enc1_config = #endif }; +static struct qe_index_s imxrt_enc1_data = +{ + .qenc_pos = 0, + .indx_pos = 0, + .indx_cnt = 0, +}; + static struct imxrt_enc_lowerhalf_s imxrt_enc1_priv = { - .ops = &g_qecallbacks, + .ops = &g_qecallbacks, .config = &imxrt_enc1_config, + .data = &imxrt_enc1_data, }; #endif @@ -378,12 +414,14 @@ static struct imxrt_enc_lowerhalf_s imxrt_enc1_priv = static const struct imxrt_qeconfig_s imxrt_enc2_config = { .base = IMXRT_ENC2_BASE, + .irq = IMXRT_IRQ_ENC2, .init_val = CONFIG_ENC2_INITVAL, .modulus = CONFIG_ENC2_MODULUS, .in_filt_per = CONFIG_ENC2_FILTPER, .in_filt_cnt = CONFIG_ENC2_FILTCNT, .init_flags = CONFIG_ENC2_HIP << HIP_SHIFT | CONFIG_ENC2_HNE << HNE_SHIFT | + CONFIG_ENC2_XIE << XIE_SHIFT | CONFIG_ENC2_XIP << XIP_SHIFT | CONFIG_ENC2_XNE << XNE_SHIFT | CONFIG_ENC2_DIR << REV_SHIFT | @@ -395,10 +433,18 @@ static const struct imxrt_qeconfig_s imxrt_enc2_config = #endif }; +static struct qe_index_s imxrt_enc2_data = +{ + .qenc_pos = 0, + .indx_pos = 0, + .indx_cnt = 0, +}; + static struct imxrt_enc_lowerhalf_s imxrt_enc2_priv = { .ops = &g_qecallbacks, .config = &imxrt_enc2_config, + .data = &imxrt_enc2_data, }; #endif @@ -406,12 +452,14 @@ static struct imxrt_enc_lowerhalf_s imxrt_enc2_priv = static const struct imxrt_qeconfig_s imxrt_enc3_config = { .base = IMXRT_ENC3_BASE, + .irq = IMXRT_IRQ_ENC3, .init_val = CONFIG_ENC3_INITVAL, .modulus = CONFIG_ENC3_MODULUS, .in_filt_per = CONFIG_ENC3_FILTPER, .in_filt_cnt = CONFIG_ENC3_FILTCNT, .init_flags = CONFIG_ENC3_HIP << HIP_SHIFT | CONFIG_ENC3_HNE << HNE_SHIFT | + CONFIG_ENC3_XIE << XIE_SHIFT | CONFIG_ENC3_XIP << XIP_SHIFT | CONFIG_ENC3_XNE << XNE_SHIFT | CONFIG_ENC3_DIR << REV_SHIFT | @@ -423,10 +471,18 @@ static const struct imxrt_qeconfig_s imxrt_enc3_config = #endif }; +static struct qe_index_s imxrt_enc3_data = +{ + .qenc_pos = 0, + .indx_pos = 0, + .indx_cnt = 0, +}; + static struct imxrt_enc_lowerhalf_s imxrt_enc3_priv = { .ops = &g_qecallbacks, .config = &imxrt_enc3_config, + .data = &imxrt_enc3_data, }; #endif @@ -434,12 +490,14 @@ static struct imxrt_enc_lowerhalf_s imxrt_enc3_priv = static const struct imxrt_qeconfig_s imxrt_enc4_config = { .base = IMXRT_ENC4_BASE, + .irq = IMXRT_IRQ_ENC4, .init_val = CONFIG_ENC4_INITVAL, .modulus = CONFIG_ENC4_MODULUS, .in_filt_per = CONFIG_ENC4_FILTPER, .in_filt_cnt = CONFIG_ENC4_FILTCNT, .init_flags = CONFIG_ENC4_HIP << HIP_SHIFT | CONFIG_ENC4_HNE << HNE_SHIFT | + CONFIG_ENC4_XIE << XIE_SHIFT | CONFIG_ENC4_XIP << XIP_SHIFT | CONFIG_ENC4_XNE << XNE_SHIFT | CONFIG_ENC4_DIR << REV_SHIFT | @@ -451,10 +509,18 @@ static const struct imxrt_qeconfig_s imxrt_enc4_config = #endif }; +static struct qe_index_s imxrt_enc4_data = +{ + .qenc_pos = 0, + .indx_pos = 0, + .indx_cnt = 0, +}; + static struct imxrt_enc_lowerhalf_s imxrt_enc4_priv = { .ops = &g_qecallbacks, .config = &imxrt_enc4_config, + .data = &imxrt_enc4_data, }; #endif @@ -640,6 +706,15 @@ static int imxrt_enc_reconfig(struct imxrt_enc_lowerhalf_s *priv, clear |= ENC_CTRL_HNE; } + if ((args >> XIE_SHIFT) & 1) + { + set |= ENC_CTRL_XIE; + } + else + { + clear |= ENC_CTRL_XIE; + } + if ((args >> XIP_SHIFT) & 1) { set |= ENC_CTRL_XIP; @@ -752,6 +827,41 @@ static void imxrt_enc_modulo_disable(struct imxrt_enc_lowerhalf_s *priv) imxrt_enc_modifyreg16(priv, IMXRT_ENC_CTRL2_OFFSET, ENC_CTRL2_MOD, 0); } +/**************************************************************************** + * Name: imxrt_enc_index + * + * Description: + * Get the index position and increments index count. + * + ****************************************************************************/ + +static int imxrt_enc_index(int irq, void *context, FAR void *arg) +{ + FAR struct imxrt_enc_lowerhalf_s *priv = + (FAR struct imxrt_enc_lowerhalf_s *)arg; + FAR const struct imxrt_qeconfig_s *config = priv->config; + FAR struct qe_index_s *data = priv->data; + uint16_t regval = getreg16(config->base + IMXRT_ENC_CTRL_OFFSET); + + if ((regval & ENC_CTRL_XIRQ) != 0) + { + /* Clear the interrupt */ + + regval |= ENC_CTRL_XIRQ; + putreg16(regval, config->base + IMXRT_ENC_CTRL_OFFSET); + + /* Get index position */ + + imxrt_position(arg, &data->indx_pos); + + /* Increment index count */ + + priv->data->indx_cnt += 1; + } + + return OK; +} + #ifdef CONFIG_DEBUG_SENSORS /**************************************************************************** @@ -867,6 +977,18 @@ static int imxrt_setup(struct qe_lowerhalf_s *lower) imxrt_enc_putreg16(priv, IMXRT_ENC_TST_OFFSET, regval); #endif + if ((config->init_flags && XIE_SHIFT) == 1) + { + ret = irq_attach(config->irq, imxrt_enc_index, priv); + if (ret < 0) + { + snerr("ERROR: irq_attach failed: %d\n", ret); + return ret; + } + + up_enable_irq(config->irq); + } + /* Control and Control 2 register */ regval = ENC_CTRL_SWIP; @@ -874,6 +996,7 @@ static int imxrt_setup(struct qe_lowerhalf_s *lower) regval |= ((config->init_flags >> HIP_SHIFT) & 1) ? ENC_CTRL_HIP : 0; regval |= ((config->init_flags >> HNE_SHIFT) & 1) ? ENC_CTRL_HNE : 0; regval |= ((config->init_flags >> XIP_SHIFT) & 1) ? ENC_CTRL_XIP : 0; + regval |= ((config->init_flags >> XIE_SHIFT) & 1) ? ENC_CTRL_XIE : 0; regval |= ((config->init_flags >> XNE_SHIFT) & 1) ? ENC_CTRL_XNE : 0; imxrt_enc_putreg16(priv, IMXRT_ENC_CTRL_OFFSET, regval); @@ -913,6 +1036,15 @@ static int imxrt_shutdown(struct qe_lowerhalf_s *lower) imxrt_enc_putreg16(priv, IMXRT_ENC_TST_OFFSET, 0); #endif + /* Disable interrupts if used */ + + if ((priv->config->init_flags && XIE_SHIFT) == 1) + { + up_disable_irq(priv->config->irq); + + irq_detach(priv->config->irq); + } + imxrt_enc_putreg16(priv, IMXRT_ENC_FILT_OFFSET, 0); imxrt_enc_putreg16(priv, IMXRT_ENC_LINIT_OFFSET, 0); imxrt_enc_putreg16(priv, IMXRT_ENC_UINIT_OFFSET, 0); @@ -1027,6 +1159,7 @@ static int imxrt_ioctl(struct qe_lowerhalf_s *lower, int cmd, unsigned long arg) { struct imxrt_enc_lowerhalf_s *priv = (struct imxrt_enc_lowerhalf_s *)lower; + FAR struct qe_index_s *data = priv->data; switch (cmd) { /* QEIOC_POSDIFF: @@ -1055,6 +1188,10 @@ static int imxrt_ioctl(struct qe_lowerhalf_s *lower, int cmd, case QEIOC_RESETATMAX: imxrt_enc_modulo_disable(priv); break; + case QEIOC_GETINDEX: + imxrt_position(lower, &data->qenc_pos); + *((struct qe_index_s *)arg) = *data; + break; #ifdef CONFIG_DEBUG_SENSORS case QEIOC_TEST_GEN: