Skip to content

Commit

Permalink
Merge branch 'contrib/github_pr_10402_v4.4' into 'release/v4.4'
Browse files Browse the repository at this point in the history
ledc: move callback to IRAM as it's called from an ISR (GitHub PR) (v4.4)

See merge request espressif/esp-idf!22593
  • Loading branch information
jack0c committed Mar 20, 2023
2 parents 3c8bc22 + 022a697 commit 48b3f23
Show file tree
Hide file tree
Showing 4 changed files with 12 additions and 4 deletions.
10 changes: 9 additions & 1 deletion components/driver/ledc.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "esp_rom_gpio.h"
#include "esp_rom_sys.h"
#include "soc/clk_ctrl_os.h"
#include "soc/soc_memory_types.h"

static const char* LEDC_TAG = "ledc";

Expand Down Expand Up @@ -1079,8 +1080,15 @@ esp_err_t ledc_cb_register(ledc_mode_t speed_mode, ledc_channel_t channel, ledc_
{
LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode");
LEDC_ARG_CHECK(channel < LEDC_CHANNEL_MAX, "channel");
LEDC_ARG_CHECK(cbs, "callback");
LEDC_CHECK(p_ledc_obj[speed_mode] != NULL, LEDC_NOT_INIT, ESP_ERR_INVALID_STATE);
LEDC_CHECK(ledc_fade_channel_init_check(speed_mode, channel) == ESP_OK , LEDC_FADE_INIT_ERROR_STR, ESP_FAIL);
LEDC_CHECK(ledc_fade_channel_init_check(speed_mode, channel) == ESP_OK, LEDC_FADE_INIT_ERROR_STR, ESP_FAIL);
if (cbs->fade_cb && !esp_ptr_in_iram(cbs->fade_cb)) {
ESP_LOGW(LEDC_TAG, "fade callback not in IRAM");
}
if (user_arg && !esp_ptr_internal(user_arg)) {
ESP_LOGW(LEDC_TAG, "user context not in internal RAM");
}
s_ledc_fade_rec[speed_mode][channel]->ledc_fade_callback = cbs->fade_cb;
s_ledc_fade_rec[speed_mode][channel]->cb_user_arg = user_arg;
return ESP_OK;
Expand Down
2 changes: 1 addition & 1 deletion docs/en/api-reference/peripherals/ledc.rst
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ The LEDC hardware provides the means to gradually transition from one duty cycle

Start fading with :cpp:func:`ledc_fade_start`. A fade can be operated in blocking or non-blocking mode, please check :cpp:enum:`ledc_fade_mode_t` for the difference between the two available fade modes. Note that with either fade mode, the next fade or fixed-duty update will not take effect until the last fade finishes.

To get a notification about the completion of a fade operation, a fade end callback function can be registered for each channel by calling :cpp:func:`ledc_cb_register` after the fade service being installed. The fade end callback prototype is defined in :cpp:type:`ledc_cb_t`, where you should return a boolean value from the callback function, indicating whether a high priority task is woken up by this callback function.
To get a notification about the completion of a fade operation, a fade end callback function can be registered for each channel by calling :cpp:func:`ledc_cb_register` after the fade service being installed. The fade end callback prototype is defined in :cpp:type:`ledc_cb_t`, where you should return a boolean value from the callback function, indicating whether a high priority task is woken up by this callback function. It is worth mentioning, the callback and the function invoked by itself should be placed in IRAM, as the interrupt service routine is in IRAM. :cpp:func:`ledc_cb_register` will print a warning message if it finds the addresses of callback and user context are incorrect.

If not required anymore, fading and an associated interrupt can be disabled with :cpp:func:`ledc_fade_func_uninstall`.

Expand Down
2 changes: 1 addition & 1 deletion docs/zh_CN/api-reference/peripherals/ledc.rst
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ LED PWM 控制器硬件可逐渐改变占空比的数值。要使用此功能,

最后需要调用 :cpp:func:`ledc_fade_start` 开启渐变。渐变可以在阻塞或非阻塞模式下运行,具体区别请查看 :cpp:enum:`ledc_fade_mode_t`。需要特别注意的是,不管在哪种模式下,下一次渐变或单次占空比配置的指令生效都必须等到前一次渐变结束。

此外,在使能渐变后,每个通道都可以额外通过调用 :cpp:func:`ledc_cb_register` 注册一个回调函数用以获得渐变完成的事件通知。回调函数的原型被定义在 :cpp:type:`ledc_cb_t`。每个回调函数都应当返回一个布尔值给驱动的中断处理函数,用以表示是否有高优先级任务被其唤醒。
此外,在使能渐变后,每个通道都可以额外通过调用 :cpp:func:`ledc_cb_register` 注册一个回调函数用以获得渐变完成的事件通知。回调函数的原型被定义在 :cpp:type:`ledc_cb_t`。每个回调函数都应当返回一个布尔值给驱动的中断处理函数,用以表示是否有高优先级任务被其唤醒。此外,值得注意的是,由于驱动的中断处理函数被放在了 IRAM 中, 回调函数和其调用的函数也需要被放在 IRAM 中。 :cpp:func:`ledc_cb_register` 会检查回调函数及函数上下文的指针地址是否在正确的存储区域。

如不需要渐变和渐变中断,可用函数 :cpp:func:`ledc_fade_func_uninstall` 关闭。

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
* Use callback only if you are aware it is being called inside an ISR
* Otherwise, you can use a semaphore to unblock tasks
*/
static bool cb_ledc_fade_end_event(const ledc_cb_param_t *param, void *user_arg)
static IRAM_ATTR bool cb_ledc_fade_end_event(const ledc_cb_param_t *param, void *user_arg)
{
portBASE_TYPE taskAwoken = pdFALSE;

Expand Down

0 comments on commit 48b3f23

Please sign in to comment.