OVMS3-idf/components/soc/include/hal/mcpwm_hal.h
michael 538540ce21 mcpwm: add HAL layer support
Also improved the unit tests a bit.
2019-11-25 00:36:30 +08:00

329 lines
13 KiB
C

// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*******************************************************************************
* NOTICE
* The hal is not public api, don't use in application code.
* See readme.md in soc/include/hal/readme.md
******************************************************************************/
// The HAL layer for MCPWM (common part)
/*
* MCPWM HAL usages:
*
* Initialization:
* 1. Fill the parameters in `mcpwm_hal_context_t`.
* 2. Call `mcpwm_hal_init` to initialize the context.
* 3. Call `mcpwm_hal_hw_init` to initialize the hardware.
*
* Basic PWM:
* 1. Update parameters for the timers, comparators and generators.
* 2. Call `mcpwm_hal_timer_update_basic` to update the timer used.
* 3. Call `mcpwm_hal_operator_update_basic` to update all the parameters of a operator.
*
* Alternatively, if only the comparator is updated (duty rate), call
* `mcpwm_hal_operator_update_comparator` to update the comparator parameters; if only the
* generator is updated (output style), call `mcpwm_hal_operator_update_generator` to update the
* generator parameters.
*
* 4. At any time, call `mcpwm_hal_timer_start` to start the timer (so that PWM output will toggle
* according to settings), or call `mcpwm_hal_timer_stop` to stop the timer (so that the PWM output
* will be kept as called).
*
* Timer settings:
* - Sync: Call `mcpwm_hal_timer_enable_sync` to enable the sync for the timer, and call
* `mcpwm_hal_timer_disable_sync` to disable it.
*
* Operator settings:
* - Carrier: Call `mcpwm_hal_operator_enable_carrier` to enable carrier for an operator, and call
* `mcpwm_hal_operator_disable_carrier` to disable it.
*
* - Deadzone: Call `mcpwm_hal_operator_update_deadzone` to update settings of deadzone for an operator.
*
* Fault handling settings:
* 1. Call `mcpwm_hal_fault_init` to initialize an fault signal to be detected.
* 2. Call `mcpwm_hal_operator_update_fault` to update the behavior of an operator when fault is
* detected.
* 3. If the operator selects oneshot mode to handle the fault event, call
* `mcpwm_hal_fault_oneshot_clear` to clear that fault event after the fault is handled properly.
* 4. Call `mcpwm_hal_fault_disable` to deinitialize the fault signal when it's no longer used.
*
* Capture:
* 1. Call `mcpwm_hal_capture_enable` to enable the capture for one capture signal.
* 2. Call `mcpwm_hal_capture_get_result` to get the last captured result.
* 3. Call `mcpwm_hal_capture_disable` to disable the capture for a signal.
*/
#pragma once
#include <esp_err.h>
#include "hal/mcpwm_ll.h"
#define MCPWM_BASE_CLK (2 * APB_CLK_FREQ) //2*APB_CLK_FREQ 160Mhz
/// Configuration of HAL that used only once.
typedef struct {
int host_id; ///< Which MCPWM peripheral to use, 0-1.
} mcpwm_hal_init_config_t;
/// Configuration of each generator (output of operator)
typedef struct {
mcpwm_duty_type_t duty_type; ///< How the generator output
int comparator; ///< for mode `MCPWM_DUTY_MODE_*`, which comparator it refers to.
} mcpwm_hal_generator_config_t;
/// Configuration of each operator
typedef struct {
mcpwm_hal_generator_config_t gen[SOC_MCPWM_GENERATOR_NUM]; ///< Configuration of the generators
float duty[SOC_MCPWM_COMPARATOR_NUM]; ///< Duty rate for each comparator, 10 means 10%.
int timer; ///< The timer this operator is using
} mcpwm_hal_operator_config_t;
/// Configuration of each timer
typedef struct {
uint32_t timer_prescale; ///< The prescale from the MCPWM main clock to the timer clock, TIMER_FREQ=(MCPWM_FREQ/(timer_prescale+1))
uint32_t freq; ///< Frequency desired, will be updated to actual value after the `mcpwm_hal_timer_update_freq` is called.
mcpwm_counter_type_t count_mode; ///< Counting mode
} mcpwm_hal_timer_config_t;
typedef struct {
mcpwm_dev_t *dev; ///< Beginning address of the MCPWM peripheral registers. Call `mcpwm_hal_init` to initialize it.
uint32_t prescale; ///< Prescale from the 160M clock to MCPWM main clock.
mcpwm_hal_timer_config_t timer[SOC_MCPWM_TIMER_NUM]; ///< Configuration of the timers
mcpwm_hal_operator_config_t op[SOC_MCPWM_OP_NUM]; ///< Configuration of the operators
} mcpwm_hal_context_t;
/// Configuration of the carrier
typedef struct {
bool inverted; ///< Whether to invert the output
uint8_t duty; ///< Duty of the carrier, 0-7. Duty rate = duty/8.
uint8_t oneshot_pulse_width; ///< oneshot pulse width, in carrier periods. 0 to disable. 0-15.
uint32_t period; ///< Prescale from the MCPWM main clock to the carrier clock. CARRIER_FREQ=(MCPWM_FREQ/(period+1)/8.)
} mcpwm_hal_carrier_conf_t;
/// Configuration of the deadzone
typedef struct {
mcpwm_deadtime_type_t mode; ///< Deadzone mode, `MCPWM_DEADTIME_BYPASS` to disable.
uint32_t fed; ///< Delay on falling edge. By MCPWM main clock.
uint32_t red; ///< Delay on rising edge. By MCPWM main clock.
} mcpwm_hal_deadzone_conf_t;
/// Configuration of the fault handling for each operator
typedef struct {
uint32_t cbc_enabled_mask; ///< Whether the cycle-by-cycle fault handling is enabled on each fault signal. BIT(n) stands for signal n.
uint32_t ost_enabled_mask; ///< Whether the oneshot fault handling is enabled on each on each fault signal. BIT(n) stands for signal n.
mcpwm_output_action_t action_on_fault[SOC_MCPWM_GENERATOR_NUM]; ///< Action to perform on each generator when any one of the fault signal triggers.
} mcpwm_hal_fault_conf_t;
/// Configuration of the synchronization of each clock
typedef struct {
mcpwm_sync_signal_t sync_sig; ///< Sync signal to use
uint32_t reload_permillage; ///< Reload permillage when the sync is triggered. 100 means the timer will be reload to (period * 100)/1000=10% period value.
} mcpwm_hal_sync_config_t;
/// Configuration of the capture feature on each capture signal
typedef struct {
mcpwm_capture_on_edge_t cap_edge; ///< Whether the edges is captured, bitwise.
uint32_t prescale; ///< Prescale of the input signal.
} mcpwm_hal_capture_config_t;
/**
* @brief Initialize the internal state of the HAL. Call after settings are set and before other functions are called.
*
* @note Since There are several individual parts (timers + operators, captures), this funciton is
* allowed to called several times.
*
* @param hal Context of the HAL layer.
* @param init_config Configuration for the HAL to be used only once.
*/
void mcpwm_hal_init(mcpwm_hal_context_t *hal, const mcpwm_hal_init_config_t *init_config);
/**
* @brief Initialize the hardware, call after `mcpwm_hal_init` and before other functions.
*
* @param hal Context of the HAL layer.
*/
void mcpwm_hal_hw_init(mcpwm_hal_context_t *hal);
/**
* @brief Start a timer
*
* @param hal Context of the HAL layer.
* @param timer Timer to start, 0-2.
*/
void mcpwm_hal_timer_start(mcpwm_hal_context_t *hal, int timer);
/**
* @brief Stop a timer.
*
* @param hal Context of the HAL layer.
* @param timer Timer to stop, 0-2.
*/
void mcpwm_hal_timer_stop(mcpwm_hal_context_t *hal, int timer);
/**
* @brief Update the basic parameters of a timer.
*
* @note This will influence the duty rate and count mode of each operator relies on this timer.
* Call `mcpwm_hal_operator_update_basic` for each of the operator that relies on this timer after
* to update the duty rate and generator output.
*
* @param hal Context of the HAL layer.
* @param timer Timer to update, 0-2.
*/
void mcpwm_hal_timer_update_basic(mcpwm_hal_context_t *hal, int timer);
/**
* @brief Start the synchronization for a timer.
*
* @param hal Context of the HAL layer.
* @param timer Timer to enable, 0-2.
* @param sync_conf Configuration of the sync operation.
*/
void mcpwm_hal_timer_enable_sync(mcpwm_hal_context_t *hal, int timer, const mcpwm_hal_sync_config_t *sync_conf);
/**
* @brief Stop the synchronization for a timer.
*
* @param hal Context of the HAL layer.
* @param timer Timer to disable sync, 0-2.
*/
void mcpwm_hal_timer_disable_sync(mcpwm_hal_context_t *hal, int timer);
/**
* @brief Update the basic settings (duty, output mode) for an operator.
*
* Will call `mcpwm_hal_operator_update_comparator` and `mcpwm_hal_operator_update_generator`
* recursively to update each of their duty and output mode.
*
* @param hal Context of the HAL layer.
* @param op Operator to update, 0-2.
*/
void mcpwm_hal_operator_update_basic(mcpwm_hal_context_t *hal, int op);
/**
* @brief Update a comparator (duty) for an operator.
*
* @param hal Context of the HAL layer.
* @param op Operator to update, 0-2.
* @param cmp Comparator to update, 0-1.
*/
void mcpwm_hal_operator_update_comparator(mcpwm_hal_context_t *hal, int op, int cmp);
/**
* @brief Update a generator (output mode) for an operator.
*
* @param hal Context of the HAL layer.
* @param op Operator to update, 0-2.
* @param cmp Comparator to update, 0-1.
*/
void mcpwm_hal_operator_update_generator(mcpwm_hal_context_t *hal, int op, int gen_num);
/**
* @brief Enable the carrier for an operator.
*
* @param hal Context of the HAL layer.
* @param op Operator to enable carrier, 0-2.
* @param carrier_conf Configuration of the carrier.
*/
void mcpwm_hal_operator_enable_carrier(mcpwm_hal_context_t *hal, int op, const mcpwm_hal_carrier_conf_t *carrier_conf);
/**
* @brief Disable the carrier for an operator.
*
* @param hal Context of the HAL layer.
* @param op Operator to disable carrier, 0-2.
*/
void mcpwm_hal_operator_disable_carrier(mcpwm_hal_context_t *hal, int op);
/**
* @brief Update the deadzone for an operator.
*
* @param hal Context of the HAL layer.
* @param op Operator to update the deadzone, 0-2.
* @param deadzone Configuration of the deadzone. Set member `mode` to `MCPWM_DEADTIME_BYPASS` will bypass the deadzone.
*/
void mcpwm_hal_operator_update_deadzone(mcpwm_hal_context_t *hal, int op, const mcpwm_hal_deadzone_conf_t *deadzone);
/**
* @brief Enable one of the fault signal.
*
* @param hal Context of the HAL layer.
* @param fault_sig The signal to enable, 0-2.
* @param level The active level for the fault signal, true for high and false for low.
*/
void mcpwm_hal_fault_init(mcpwm_hal_context_t *hal, int fault_sig, bool level);
/**
* @brief Configure how the operator behave to the fault signals.
*
* Call after the fault signal is enabled by `mcpwm_hal_fault_init`.
*
* @param hal Context of the HAL layer.
* @param op Operator to configure, 0-2.
* @param fault_conf Configuration of the behavior of the operator when fault. Clear member `cbc_enabled_mask` and `ost_enabled_mask` will disable the fault detection of this operator.
*/
void mcpwm_hal_operator_update_fault(mcpwm_hal_context_t *hal, int op, const mcpwm_hal_fault_conf_t *fault_conf);
/**
* @brief Clear the oneshot fault status for an operator.
*
* @param hal Context of the HAL layer.
* @param op The operator to clear oneshot fault status, 0-2.
*/
void mcpwm_hal_fault_oneshot_clear(mcpwm_hal_context_t *hal, int op);
/**
* @brief Disable one of the fault signal.
*
* @param hal Context of the HAL layer.
* @param fault_sig The fault signal to disable, 0-2.
*/
void mcpwm_hal_fault_disable(mcpwm_hal_context_t *hal, int fault_sig);
/**
* @brief Enable one of the capture signal.
*
* @param hal Context of the HAL layer.
* @param cap_sig Capture signal to enable, 0-2.
* @param conf Configuration on how to capture the signal.
*/
void mcpwm_hal_capture_enable(mcpwm_hal_context_t *hal, int cap_sig, const mcpwm_hal_capture_config_t *conf);
/**
* @brief Get the capture result.
*
* @note The output value will always be updated with the register value, no matter event triggered or not.
*
* @param hal Context of the HAL layer.
* @param cap_sig Signal to get capture result, 0-2.
* @param out_count Output of the captured counter.
* @param out_edge Output of the captured edge.
* @return
* - ESP_OK: if a signal is captured
* - ESP_ERR_NOT_FOUND: if no capture event happened.
*/
esp_err_t mcpwm_hal_capture_get_result(mcpwm_hal_context_t *hal, int cap_sig, uint32_t *out_count,
mcpwm_capture_on_edge_t *out_edge);
/**
* @brief Disable one of the capture signal.
*
* @param hal Context of the HAL layer.
* @param cap_sig The signal to capture, 0-2.
*/
void mcpwm_hal_capture_disable(mcpwm_hal_context_t *hal, int cap_sig);