Merge pull request #14911 from OTAkeys/pr/can_stm32_deepsleep_opt

stm32/can: add option to enable deep-sleep per device
This commit is contained in:
benpicco 2021-02-22 22:52:46 +01:00 committed by GitHub
commit d014f5e6d0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 29 additions and 11 deletions

View File

@ -65,6 +65,7 @@ static const can_conf_t candev_conf[] = {
.rx1_irqn = CAN1_RX1_IRQn, .rx1_irqn = CAN1_RX1_IRQn,
.sce_irqn = CAN1_SCE_IRQn, .sce_irqn = CAN1_SCE_IRQn,
#endif #endif
.en_deep_sleep_wake_up = true,
.ttcm = 0, .ttcm = 0,
.abom = 1, .abom = 1,
.awum = 1, .awum = 1,
@ -85,6 +86,7 @@ static const can_conf_t candev_conf[] = {
#ifndef CPU_FAM_STM32F1 #ifndef CPU_FAM_STM32F1
.af = GPIO_AF9, .af = GPIO_AF9,
#endif #endif
.en_deep_sleep_wake_up = true,
.tx_irqn = CAN2_TX_IRQn, .tx_irqn = CAN2_TX_IRQn,
.rx0_irqn = CAN2_RX0_IRQn, .rx0_irqn = CAN2_RX0_IRQn,
.rx1_irqn = CAN2_RX1_IRQn, .rx1_irqn = CAN2_RX1_IRQn,
@ -108,6 +110,7 @@ static const can_conf_t candev_conf[] = {
.rx_pin = GPIO_PIN(PORT_B, 3), .rx_pin = GPIO_PIN(PORT_B, 3),
.tx_pin = GPIO_PIN(PORT_B, 4), .tx_pin = GPIO_PIN(PORT_B, 4),
.af = GPIO_AF11, .af = GPIO_AF11,
.en_deep_sleep_wake_up = true,
.tx_irqn = CAN3_TX_IRQn, .tx_irqn = CAN3_TX_IRQn,
.rx0_irqn = CAN3_RX0_IRQn, .rx0_irqn = CAN3_RX0_IRQn,
.rx1_irqn = CAN3_RX1_IRQn, .rx1_irqn = CAN3_RX1_IRQn,

View File

@ -100,6 +100,7 @@ typedef struct {
#ifndef CPU_FAM_STM32F1 #ifndef CPU_FAM_STM32F1
gpio_af_t af; /**< Alternate pin function to use */ gpio_af_t af; /**< Alternate pin function to use */
#endif #endif
bool en_deep_sleep_wake_up; /**< Enable deep-sleep wake-up interrupt */
#if CANDEV_STM32_CHAN_NUMOF > 1 || defined(DOXYGEN) #if CANDEV_STM32_CHAN_NUMOF > 1 || defined(DOXYGEN)
CAN_TypeDef *can_master; /**< Master CAN device */ CAN_TypeDef *can_master; /**< Master CAN device */
uint32_t master_rcc_mask; /**< Master device RCC mask */ uint32_t master_rcc_mask; /**< Master device RCC mask */

View File

@ -644,8 +644,10 @@ static void turn_off(can_t *dev)
#endif #endif
} }
_status[chan] = STATUS_SLEEP; _status[chan] = STATUS_SLEEP;
periph_clk_dis(APB1, dev->conf->rcc_mask); if (dev->conf->en_deep_sleep_wake_up) {
enable_int(dev, 0); periph_clk_dis(APB1, dev->conf->rcc_mask);
enable_int(dev, 0);
}
} }
} }
else { else {
@ -658,20 +660,26 @@ static void turn_off(can_t *dev)
#endif #endif
/* Fall through */ /* Fall through */
case STATUS_NOT_USED: case STATUS_NOT_USED:
periph_clk_dis(APB1, dev->conf->master_rcc_mask); if (dev->conf->en_deep_sleep_wake_up) {
periph_clk_dis(APB1, dev->conf->master_rcc_mask);
}
break; break;
} }
periph_clk_dis(APB1, dev->conf->rcc_mask); if (dev->conf->en_deep_sleep_wake_up) {
periph_clk_dis(APB1, dev->conf->rcc_mask);
}
if (_status[get_channel(dev->conf->can)] != STATUS_SLEEP) { if (_status[get_channel(dev->conf->can)] != STATUS_SLEEP) {
#ifdef STM32_PM_STOP #ifdef STM32_PM_STOP
pm_unblock(STM32_PM_STOP); pm_unblock(STM32_PM_STOP);
#endif #endif
} }
_status[get_channel(dev->conf->can)] = STATUS_SLEEP; _status[get_channel(dev->conf->can)] = STATUS_SLEEP;
if (_status[master_chan] == STATUS_SLEEP) { if (dev->conf->en_deep_sleep_wake_up) {
enable_int(dev, 1); if (_status[master_chan] == STATUS_SLEEP) {
enable_int(dev, 1);
}
enable_int(dev, 0);
} }
enable_int(dev, 0);
} }
#else #else
if (_status[get_channel(dev->conf->can)] != STATUS_SLEEP) { if (_status[get_channel(dev->conf->can)] != STATUS_SLEEP) {
@ -680,8 +688,10 @@ static void turn_off(can_t *dev)
#endif #endif
} }
_status[get_channel(dev->conf->can)] = STATUS_SLEEP; _status[get_channel(dev->conf->can)] = STATUS_SLEEP;
periph_clk_dis(APB1, dev->conf->rcc_mask); if (dev->conf->en_deep_sleep_wake_up) {
gpio_init_int(dev->rx_pin, GPIO_IN, GPIO_FALLING, _wkup_cb, dev); periph_clk_dis(APB1, dev->conf->rcc_mask);
gpio_init_int(dev->rx_pin, GPIO_IN, GPIO_FALLING, _wkup_cb, dev);
}
#endif #endif
irq_restore(irq); irq_restore(irq);
} }
@ -697,7 +707,9 @@ static void turn_on(can_t *dev)
switch (_status[master_chan]) { switch (_status[master_chan]) {
case STATUS_SLEEP: case STATUS_SLEEP:
_status[master_chan] = STATUS_READY_FOR_SLEEP; _status[master_chan] = STATUS_READY_FOR_SLEEP;
disable_int(dev, 1); if (dev->conf->en_deep_sleep_wake_up) {
disable_int(dev, 1);
}
#ifdef STM32_PM_STOP #ifdef STM32_PM_STOP
pm_block(STM32_PM_STOP); pm_block(STM32_PM_STOP);
#endif #endif
@ -712,7 +724,9 @@ static void turn_on(can_t *dev)
#ifdef STM32_PM_STOP #ifdef STM32_PM_STOP
pm_block(STM32_PM_STOP); pm_block(STM32_PM_STOP);
#endif #endif
disable_int(dev, 0); if (dev->conf->en_deep_sleep_wake_up) {
disable_int(dev, 0);
}
periph_clk_en(APB1, dev->conf->rcc_mask); periph_clk_en(APB1, dev->conf->rcc_mask);
} }
_status[get_channel(dev->conf->can)] = STATUS_ON; _status[get_channel(dev->conf->can)] = STATUS_ON;