Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ruanhaishen
Nodemcu Firmware
Commits
669543bb
Commit
669543bb
authored
Feb 17, 2016
by
philip
Browse files
Hardware timer support and convert the PWM module to use it
parent
1afa72d5
Changes
10
Hide whitespace changes
Inline
Side-by-side
.gitignore
View file @
669543bb
sdk/
cache/
user_config.h
Makefile
View file @
669543bb
...
...
@@ -131,6 +131,10 @@ CCFLAGS += \
-mtext-section-literals
# -Wall
ifneq
($(wildcard $(TOP_DIR)/user_config.h),)
INCLUDES
:=
$(INCLUDES)
-include
"
$(TOP_DIR)
/user_config.h"
endif
CFLAGS
=
$(CCFLAGS)
$(DEFINES)
$(EXTRA_CCFLAGS)
$(STD_CFLAGS)
$(INCLUDES)
DFLAGS
=
$(CCFLAGS)
$(DDEFINES)
$(EXTRA_CCFLAGS)
$(STD_CFLAGS)
$(INCLUDES)
...
...
app/driver/pwm.c
View file @
669543bb
...
...
@@ -14,6 +14,7 @@
#include "os_type.h"
#include "osapi.h"
#include "gpio.h"
#include "hw_timer.h"
#include "user_interface.h"
#include "driver/pwm.h"
...
...
@@ -21,6 +22,19 @@
// #define PWM_DBG os_printf
#define PWM_DBG
// Enabling the next line will cause the interrupt handler to toggle
// this output pin during processing so that the timing is obvious
//
// #define PWM_DBG_PIN 13 // GPIO7
#ifdef PWM_DBG_PIN
#define PWM_DBG_PIN_HIGH() GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, 1 << PWM_DBG_PIN)
#define PWM_DBG_PIN_LOW() GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, 1 << PWM_DBG_PIN)
#else
#define PWM_DBG_PIN_HIGH()
#define PWM_DBG_PIN_LOW()
#endif
LOCAL
struct
pwm_single_param
pwm_single_toggle
[
2
][
PWM_CHANNEL
+
1
];
LOCAL
struct
pwm_single_param
*
pwm_single
;
...
...
@@ -32,7 +46,13 @@ LOCAL int8 pwm_out_io_num[PWM_CHANNEL] = {-1, -1, -1, -1, -1, -1};
LOCAL
uint8
pwm_channel_toggle
[
2
];
LOCAL
uint8
*
pwm_channel
;
// Toggle flips between 1 and 0 when we make updates so that the interrupt code
// cn switch cleanly between the two states. The cinterrupt handler uses either
// the pwm_single_toggle[0] or pwm_single_toggle[1]
// pwm_toggle indicates which state should be used on the *next* timer interrupt
// freq boundary.
LOCAL
uint8
pwm_toggle
=
1
;
LOCAL
volatile
uint8
pwm_current_toggle
=
1
;
LOCAL
uint8
pwm_timer_down
=
1
;
LOCAL
uint8
pwm_current_channel
=
0
;
...
...
@@ -41,27 +61,8 @@ LOCAL uint16 pwm_gpio = 0;
LOCAL
uint8
pwm_channel_num
=
0
;
//XXX: 0xffffffff/(80000000/16)=35A
#define US_TO_RTC_TIMER_TICKS(t) \
((t) ? \
(((t) > 0x35A) ? \
(((t)>>2) * ((APB_CLK_FREQ>>4)/250000) + ((t)&0x3) * ((APB_CLK_FREQ>>4)/1000000)) : \
(((t) *(APB_CLK_FREQ>>4)) / 1000000)) : \
0)
//FRC1
#define FRC1_ENABLE_TIMER BIT7
typedef
enum
{
DIVDED_BY_1
=
0
,
DIVDED_BY_16
=
4
,
DIVDED_BY_256
=
8
,
}
TIMER_PREDIVED_MODE
;
typedef
enum
{
TM_LEVEL_INT
=
1
,
TM_EDGE_INT
=
0
,
}
TIMER_INT_MODE
;
LOCAL
void
ICACHE_RAM_ATTR
pwm_tim1_intr_handler
(
os_param_t
p
);
#define TIMER_OWNER ((os_param_t) 'P')
LOCAL
void
ICACHE_FLASH_ATTR
pwm_insert_sort
(
struct
pwm_single_param
pwm
[],
uint8
n
)
...
...
@@ -74,7 +75,6 @@ pwm_insert_sort(struct pwm_single_param pwm[], uint8 n)
struct
pwm_single_param
tmp
;
os_memcpy
(
&
tmp
,
&
pwm
[
i
],
sizeof
(
struct
pwm_single_param
));
os_memcpy
(
&
pwm
[
i
],
&
pwm
[
i
-
1
],
sizeof
(
struct
pwm_single_param
));
while
(
tmp
.
h_time
<
pwm
[
j
].
h_time
)
{
os_memcpy
(
&
pwm
[
j
+
1
],
&
pwm
[
j
],
sizeof
(
struct
pwm_single_param
));
...
...
@@ -89,18 +89,8 @@ pwm_insert_sort(struct pwm_single_param pwm[], uint8 n)
}
}
LOCAL
volatile
uint8
critical
=
0
;
#define LOCK_PWM(c) do { \
while( (c)==1 ); \
(c) = 1; \
} while (0)
#define UNLOCK_PWM(c) do { \
(c) = 0; \
} while (0)
void
ICACHE_FLASH_ATTR
// Returns FALSE if we cannot start
bool
ICACHE_FLASH_ATTR
pwm_start
(
void
)
{
uint8
i
,
j
;
...
...
@@ -109,10 +99,19 @@ pwm_start(void)
PWM_DBG
(
"pwm_out_io_num[0]:%d,[1]:%d,[2]:%d
\n
"
,
pwm_out_io_num
[
0
],
pwm_out_io_num
[
1
],
pwm_out_io_num
[
2
]);
PWM_DBG
(
"pwm.period:%d,pwm.duty[0]:%d,[1]:%d,[2]:%d
\n
"
,
pwm
.
period
,
pwm
.
duty
[
0
],
pwm
.
duty
[
1
],
pwm
.
duty
[
2
]);
LOCK_PWM
(
critical
);
// enter critical
// First we need to make sure that the interrupt handler is running
// out of the same set of params as we expect
while
(
!
pwm_timer_down
&&
pwm_toggle
!=
pwm_current_toggle
)
{
os_delay_us
(
100
);
}
if
(
pwm_timer_down
)
{
pwm_toggle
=
pwm_current_toggle
;
}
uint8_t
new_toggle
=
pwm_toggle
^
0x01
;
struct
pwm_single_param
*
local_single
=
pwm_single_toggle
[
pwm
_toggle
^
0x01
];
uint8
*
local_channel
=
&
pwm_channel_toggle
[
pwm
_toggle
^
0x01
];
struct
pwm_single_param
*
local_single
=
pwm_single_toggle
[
new
_toggle
];
uint8
*
local_channel
=
&
pwm_channel_toggle
[
new
_toggle
];
// step 1: init PWM_CHANNEL+1 channels param
for
(
i
=
0
;
i
<
pwm_channel_num
;
i
++
)
{
...
...
@@ -132,9 +131,10 @@ pwm_start(void)
*
local_channel
=
pwm_channel_num
+
1
;
PWM_DBG
(
"1channel:%d,single[0]:%d,[1]:%d,[2]:%d,[3]:%d
\n
"
,
*
local_channel
,
local_single
[
0
].
h_time
,
local_single
[
1
].
h_time
,
local_single
[
2
].
h_time
,
local_single
[
3
].
h_time
);
// step 3: combine same duty channels
// step 3: combine same duty channels (or nearly the same duty). If there is
// under 2 us between pwm outputs, then treat them as the same.
for
(
i
=
pwm_channel_num
;
i
>
0
;
i
--
)
{
if
(
local_single
[
i
].
h_time
=
=
local_single
[
i
-
1
].
h_time
)
{
if
(
local_single
[
i
].
h_time
<
=
local_single
[
i
-
1
].
h_time
+
US_TO_RTC_TIMER_TICKS
(
2
)
)
{
local_single
[
i
-
1
].
gpio_set
|=
local_single
[
i
].
gpio_set
;
local_single
[
i
-
1
].
gpio_clear
|=
local_single
[
i
].
gpio_clear
;
...
...
@@ -166,28 +166,43 @@ pwm_start(void)
(
*
local_channel
)
--
;
}
// Make the new ones active
pwm_toggle
=
new_toggle
;
// if timer is down, need to set gpio and start timer
if
(
pwm_timer_down
==
1
)
{
pwm_channel
=
local_channel
;
pwm_single
=
local_single
;
pwm_current_toggle
=
pwm_toggle
;
// start
gpio_output_set
(
local_single
[
0
].
gpio_set
,
local_single
[
0
].
gpio_clear
,
pwm_gpio
,
0
);
// yeah, if all channels' duty is 0 or 255, don't need to start timer, otherwise start...
if
(
*
local_channel
!=
1
)
{
pwm_timer_down
=
0
;
RTC_REG_WRITE
(
FRC1_LOAD_ADDRESS
,
local_single
[
0
].
h_time
);
}
}
if
(
pwm_toggle
==
1
)
{
pwm_toggle
=
0
;
PWM_DBG
(
"Need to setup timer
\n
"
);
if
(
!
platform_hw_timer_init
(
TIMER_OWNER
,
NMI_SOURCE
,
FALSE
))
{
return
FALSE
;
}
pwm_timer_down
=
0
;
platform_hw_timer_set_func
(
TIMER_OWNER
,
pwm_tim1_intr_handler
,
0
);
platform_hw_timer_arm_ticks
(
TIMER_OWNER
,
local_single
[
0
].
h_time
);
}
else
{
PWM_DBG
(
"Timer left idle
\n
"
);
platform_hw_timer_close
(
TIMER_OWNER
);
}
}
else
{
pwm_toggle
=
1
;
// ensure that all outputs are outputs
gpio_output_set
(
0
,
0
,
pwm_gpio
,
0
);
}
UNLOCK_PWM
(
critical
);
// leave critical
#ifdef PWM_DBG_PIN
// Enable as output
gpio_output_set
(
0
,
0
,
1
<<
PWM_DBG_PIN
,
0
);
#endif
PWM_DBG
(
"3channel:%d,single[0]:%d,[1]:%d,[2]:%d,[3]:%d
\n
"
,
*
local_channel
,
local_single
[
0
].
h_time
,
local_single
[
1
].
h_time
,
local_single
[
2
].
h_time
,
local_single
[
3
].
h_time
);
return
TRUE
;
}
/******************************************************************************
...
...
@@ -210,7 +225,6 @@ pwm_set_duty(uint16 duty, uint8 channel)
if
(
i
==
pwm_channel_num
)
// non found
return
;
LOCK_PWM
(
critical
);
// enter critical
if
(
duty
<
1
)
{
pwm
.
duty
[
channel
]
=
0
;
}
else
if
(
duty
>=
PWM_DEPTH
)
{
...
...
@@ -218,7 +232,6 @@ pwm_set_duty(uint16 duty, uint8 channel)
}
else
{
pwm
.
duty
[
channel
]
=
duty
;
}
UNLOCK_PWM
(
critical
);
// leave critical
}
/******************************************************************************
...
...
@@ -230,7 +243,6 @@ pwm_set_duty(uint16 duty, uint8 channel)
void
ICACHE_FLASH_ATTR
pwm_set_freq
(
uint16
freq
,
uint8
channel
)
{
LOCK_PWM
(
critical
);
// enter critical
if
(
freq
>
PWM_FREQ_MAX
)
{
pwm
.
freq
=
PWM_FREQ_MAX
;
}
else
if
(
freq
<
1
)
{
...
...
@@ -240,7 +252,6 @@ pwm_set_freq(uint16 freq, uint8 channel)
}
pwm
.
period
=
PWM_1S
/
pwm
.
freq
;
UNLOCK_PWM
(
critical
);
// leave critical
}
/******************************************************************************
...
...
@@ -306,36 +317,57 @@ pwm_get_freq(uint8 channel)
* Returns : NONE
*******************************************************************************/
LOCAL
void
ICACHE_RAM_ATTR
pwm_tim1_intr_handler
(
void
*
p
)
pwm_tim1_intr_handler
(
os_param_t
p
)
{
(
void
)
p
;
uint8
local_toggle
=
pwm_toggle
;
// pwm_toggle may change outside
RTC_CLR_REG_MASK
(
FRC1_INT_ADDRESS
,
FRC1_INT_CLR_MASK
);
(
void
)
p
;
if
(
pwm_current_channel
>=
(
*
pwm_channel
-
1
))
{
// *pwm_channel may change outside
pwm_single
=
pwm_single_toggle
[
local_toggle
];
pwm_channel
=
&
pwm_channel_toggle
[
local_toggle
];
PWM_DBG_PIN_HIGH
();
gpio_output_set
(
pwm_single
[
*
pwm_channel
-
1
].
gpio_set
,
pwm_single
[
*
pwm_channel
-
1
].
gpio_clear
,
pwm_gpio
,
0
);
int
offset
=
0
;
pwm_current_channel
=
0
;
while
(
1
)
{
if
(
pwm_current_channel
>=
(
*
pwm_channel
-
1
))
{
pwm_single
=
pwm_single_toggle
[
pwm_toggle
];
pwm_channel
=
&
pwm_channel_toggle
[
pwm_toggle
];
pwm_current_toggle
=
pwm_toggle
;
if
(
*
pwm_channel
!=
1
)
{
RTC_REG_WRITE
(
FRC1_LOAD_ADDRESS
,
pwm_single
[
pwm_current_channel
].
h_time
);
}
else
{
pwm_timer_down
=
1
;
}
gpio_output_set
(
pwm_single
[
*
pwm_channel
-
1
].
gpio_set
,
pwm_single
[
*
pwm_channel
-
1
].
gpio_clear
,
0
,
0
);
pwm_current_channel
=
0
;
if
(
*
pwm_channel
==
1
)
{
pwm_timer_down
=
1
;
break
;
}
}
else
{
gpio_output_set
(
pwm_single
[
pwm_current_channel
].
gpio_set
,
pwm_single
[
pwm_current_channel
].
gpio_clear
,
pwm_gpio
,
0
);
gpio_output_set
(
pwm_single
[
pwm_current_channel
].
gpio_set
,
pwm_single
[
pwm_current_channel
].
gpio_clear
,
0
,
0
);
pwm_current_channel
++
;
}
pwm_current_channel
++
;
RTC_REG_WRITE
(
FRC1_LOAD_ADDRESS
,
pwm_single
[
pwm_current_channel
].
h_time
);
int
next_time
=
pwm_single
[
pwm_current_channel
].
h_time
;
// Delay now holds the time (in ticks) since when the last timer expiry was
PWM_DBG_PIN_LOW
();
int
delay
=
platform_hw_timer_get_delay_ticks
(
TIMER_OWNER
)
+
4
-
offset
;
offset
+=
next_time
;
next_time
=
next_time
-
delay
;
if
(
next_time
>
US_TO_RTC_TIMER_TICKS
(
4
))
{
PWM_DBG_PIN_HIGH
();
platform_hw_timer_arm_ticks
(
TIMER_OWNER
,
next_time
);
break
;
}
PWM_DBG_PIN_HIGH
();
}
PWM_DBG_PIN_LOW
();
}
/******************************************************************************
...
...
@@ -343,19 +375,13 @@ pwm_tim1_intr_handler(void *p)
* Description : pwm gpio, params and timer initialization
* Parameters : uint16 freq : pwm freq param
* uint16 *duty : each channel's duty
* Returns :
NONE
* Returns :
void
*******************************************************************************/
void
ICACHE_FLASH_ATTR
pwm_init
(
uint16
freq
,
uint16
*
duty
)
{
uint8
i
;
RTC_REG_WRITE
(
FRC1_CTRL_ADDRESS
,
//FRC2_AUTO_RELOAD|
DIVDED_BY_16
|
FRC1_ENABLE_TIMER
|
TM_EDGE_INT
);
RTC_REG_WRITE
(
FRC1_LOAD_ADDRESS
,
0
);
// PIN_FUNC_SELECT(PWM_0_OUT_IO_MUX, PWM_0_OUT_IO_FUNC);
// PIN_FUNC_SELECT(PWM_1_OUT_IO_MUX, PWM_1_OUT_IO_FUNC);
// PIN_FUNC_SELECT(PWM_2_OUT_IO_MUX, PWM_2_OUT_IO_FUNC);
...
...
@@ -373,10 +399,8 @@ pwm_init(uint16 freq, uint16 *duty)
// pwm_set_freq_duty(freq, duty);
pwm_start
();
ETS_FRC_TIMER1_INTR_ATTACH
(
pwm_tim1_intr_handler
,
NULL
);
TM1_EDGE_INT_ENABLE
();
ETS_FRC1_INTR_ENABLE
();
PWM_DBG
(
"pwm_init returning
\n
"
);
}
bool
ICACHE_FLASH_ATTR
...
...
@@ -390,14 +414,12 @@ pwm_add(uint8 channel){
if
(
pwm_out_io_num
[
i
]
==
channel
)
// already exist
return
true
;
if
(
pwm_out_io_num
[
i
]
==
-
1
){
// empty exist
LOCK_PWM
(
critical
);
// enter critical
pwm_out_io_num
[
i
]
=
channel
;
pwm
.
duty
[
i
]
=
0
;
pwm_gpio
|=
(
1
<<
pin_num
[
channel
]);
PIN_FUNC_SELECT
(
pin_mux
[
channel
],
pin_func
[
channel
]);
GPIO_REG_WRITE
(
GPIO_PIN_ADDR
(
GPIO_ID_PIN
(
pin_num
[
channel
])),
GPIO_REG_READ
(
GPIO_PIN_ADDR
(
GPIO_ID_PIN
(
pin_num
[
channel
])))
&
(
~
GPIO_PIN_PAD_DRIVER_SET
(
GPIO_PAD_DRIVER_ENABLE
)));
//disable open drain;
pwm_channel_num
++
;
UNLOCK_PWM
(
critical
);
// leave critical
return
true
;
}
}
...
...
@@ -413,7 +435,6 @@ pwm_delete(uint8 channel){
uint8
i
,
j
;
for
(
i
=
0
;
i
<
pwm_channel_num
;
i
++
){
if
(
pwm_out_io_num
[
i
]
==
channel
){
// exist
LOCK_PWM
(
critical
);
// enter critical
pwm_out_io_num
[
i
]
=
-
1
;
pwm_gpio
&=
~
(
1
<<
pin_num
[
channel
]);
//clear the bit
for
(
j
=
i
;
j
<
pwm_channel_num
-
1
;
j
++
){
...
...
@@ -423,7 +444,6 @@ pwm_delete(uint8 channel){
pwm_out_io_num
[
pwm_channel_num
-
1
]
=
-
1
;
pwm
.
duty
[
pwm_channel_num
-
1
]
=
0
;
pwm_channel_num
--
;
UNLOCK_PWM
(
critical
);
// leave critical
return
true
;
}
}
...
...
app/include/driver/pwm.h
View file @
669543bb
...
...
@@ -33,7 +33,7 @@ struct pwm_param {
// #define PWM_2_OUT_IO_FUNC FUNC_GPIO13
void
pwm_init
(
uint16
freq
,
uint16
*
duty
);
void
pwm_start
(
void
);
bool
pwm_start
(
void
);
void
pwm_set_duty
(
uint16
duty
,
uint8
channel
);
uint16
pwm_get_duty
(
uint8
channel
);
...
...
app/modules/pwm.c
View file @
669543bb
...
...
@@ -47,7 +47,9 @@ static int lpwm_start( lua_State* L )
unsigned
id
;
id
=
luaL_checkinteger
(
L
,
1
);
MOD_CHECK_ID
(
pwm
,
id
);
platform_pwm_start
(
id
);
if
(
!
platform_pwm_start
(
id
))
{
return
luaL_error
(
L
,
"Unable to start PWM output"
);
}
return
0
;
}
...
...
app/platform/hw_timer.c
0 → 100644
View file @
669543bb
/******************************************************************************
* Copyright 2013-2014 Espressif Systems (Wuxi)
*
* FileName: hw_timer.c
*
* Description: hw_timer driver
*
* Modification history:
* 2014/5/1, v1.0 create this file.
*
* Adapted for NodeMCU 2016
*
* The owner parameter should be a unique value per module using this API
* It could be a pointer to a bit of data or code
* e.g. #define OWNER ((os_param_t) module_init)
* where module_init is a function. For builtin modules, it might be
* a small numeric value that is known not to clash.
*******************************************************************************/
#include "ets_sys.h"
#include "os_type.h"
#include "osapi.h"
#include "hw_timer.h"
#define FRC1_ENABLE_TIMER BIT7
#define FRC1_AUTO_LOAD BIT6
//TIMER PREDIVIDED MODE
typedef
enum
{
DIVIDED_BY_1
=
0
,
//timer clock
DIVIDED_BY_16
=
4
,
//divided by 16
DIVIDED_BY_256
=
8
,
//divided by 256
}
TIMER_PREDIVIDED_MODE
;
typedef
enum
{
//timer interrupt mode
TM_LEVEL_INT
=
1
,
// level interrupt
TM_EDGE_INT
=
0
,
//edge interrupt
}
TIMER_INT_MODE
;
static
os_param_t
the_owner
;
static
os_param_t
callback_arg
;
static
void
(
*
user_hw_timer_cb
)(
os_param_t
);
#define VERIFY_OWNER(owner) if (owner != the_owner) { if (the_owner) { return 0; } the_owner = owner; }
/******************************************************************************
* FunctionName : platform_hw_timer_arm_ticks
* Description : set a trigger timer delay for this timer.
* Parameters : os_param_t owner
* uint32 ticks :
* Returns : true if it worked
*******************************************************************************/
bool
ICACHE_RAM_ATTR
platform_hw_timer_arm_ticks
(
os_param_t
owner
,
uint32_t
ticks
)
{
VERIFY_OWNER
(
owner
);
RTC_REG_WRITE
(
FRC1_LOAD_ADDRESS
,
ticks
);
return
1
;
}
/******************************************************************************
* FunctionName : platform_hw_timer_arm_us
* Description : set a trigger timer delay for this timer.
* Parameters : os_param_t owner
* uint32 microseconds :
* in autoload mode
* 50 ~ 0x7fffff; for FRC1 source.
* 100 ~ 0x7fffff; for NMI source.
* in non autoload mode:
* 10 ~ 0x7fffff;
* Returns : true if it worked
*******************************************************************************/
bool
ICACHE_RAM_ATTR
platform_hw_timer_arm_us
(
os_param_t
owner
,
uint32_t
microseconds
)
{
VERIFY_OWNER
(
owner
);
RTC_REG_WRITE
(
FRC1_LOAD_ADDRESS
,
US_TO_RTC_TIMER_TICKS
(
microseconds
));
return
1
;
}
/******************************************************************************
* FunctionName : platform_hw_timer_set_func
* Description : set the func, when trigger timer is up.
* Parameters : os_param_t owner
* void (* user_hw_timer_cb_set)(os_param_t):
timer callback function
* os_param_t arg
* Returns : true if it worked
*******************************************************************************/
bool
platform_hw_timer_set_func
(
os_param_t
owner
,
void
(
*
user_hw_timer_cb_set
)(
os_param_t
),
os_param_t
arg
)
{
VERIFY_OWNER
(
owner
);
callback_arg
=
arg
;
user_hw_timer_cb
=
user_hw_timer_cb_set
;
return
1
;
}
static
void
ICACHE_RAM_ATTR
hw_timer_isr_cb
(
void
*
arg
)
{
if
(
user_hw_timer_cb
!=
NULL
)
{
(
*
(
user_hw_timer_cb
))(
callback_arg
);
}
}
static
void
ICACHE_RAM_ATTR
hw_timer_nmi_cb
(
void
)
{
if
(
user_hw_timer_cb
!=
NULL
)
{
(
*
(
user_hw_timer_cb
))(
callback_arg
);
}
}
/******************************************************************************
* FunctionName : platform_hw_timer_get_delay_ticks
* Description : figure out how long since th last timer interrupt
* Parameters : os_param_t owner
* Returns : the number of ticks
*******************************************************************************/
uint32_t
ICACHE_RAM_ATTR
platform_hw_timer_get_delay_ticks
(
os_param_t
owner
)
{
VERIFY_OWNER
(
owner
);
return
(
-
RTC_REG_READ
(
FRC1_COUNT_ADDRESS
))
&
((
1
<<
23
)
-
1
);
}
/******************************************************************************
* FunctionName : platform_hw_timer_init
* Description : initialize the hardware isr timer
* Parameters : os_param_t owner
* FRC1_TIMER_SOURCE_TYPE source_type:
* FRC1_SOURCE, timer use frc1 isr as isr source.
* NMI_SOURCE, timer use nmi isr as isr source.
* bool autoload:
* 0, not autoload,
* 1, autoload mode,
* Returns : true if it worked
*******************************************************************************/
bool
platform_hw_timer_init
(
os_param_t
owner
,
FRC1_TIMER_SOURCE_TYPE
source_type
,
bool
autoload
)
{
VERIFY_OWNER
(
owner
);
if
(
autoload
)
{
RTC_REG_WRITE
(
FRC1_CTRL_ADDRESS
,
FRC1_AUTO_LOAD
|
DIVIDED_BY_16
|
FRC1_ENABLE_TIMER
|
TM_EDGE_INT
);
}
else
{
RTC_REG_WRITE
(
FRC1_CTRL_ADDRESS
,
DIVIDED_BY_16
|
FRC1_ENABLE_TIMER
|
TM_EDGE_INT
);
}
if
(
source_type
==
NMI_SOURCE
)
{
ETS_FRC_TIMER1_NMI_INTR_ATTACH
(
hw_timer_nmi_cb
);
}
else
{
ETS_FRC_TIMER1_INTR_ATTACH
(
hw_timer_isr_cb
,
NULL
);
}
TM1_EDGE_INT_ENABLE
();
ETS_FRC1_INTR_ENABLE
();
return
1
;
}
/******************************************************************************
* FunctionName : platform_hw_timer_close
* Description : ends use of the hardware isr timer
* Parameters : os_param_t owner
* Returns : true if it worked
*******************************************************************************/
bool
ICACHE_RAM_ATTR
platform_hw_timer_close
(
os_param_t
owner
)
{
VERIFY_OWNER
(
owner
);
/* Set no reload mode */
RTC_REG_WRITE
(
FRC1_CTRL_ADDRESS
,
DIVIDED_BY_16
|
TM_EDGE_INT
);
TM1_EDGE_INT_DISABLE
();
ETS_FRC1_INTR_DISABLE
();
user_hw_timer_cb
=
NULL
;
the_owner
=
0
;
return
1
;
}
app/platform/hw_timer.h
0 → 100644
View file @
669543bb
#ifndef _HW_TIMER_H
#define _HW_TIMER_H
#if APB_CLK_FREQ == 80 * 1000000
// 80 MHz divided by 16 is 5 MHz count rate.
#define US_TO_RTC_TIMER_TICKS(t) ((t) * 5)
#else
#define US_TO_RTC_TIMER_TICKS(t) \
((t) ? \
(((t) > 0x35A) ? \
(((t)>>2) * ((APB_CLK_FREQ>>4)/250000) + ((t)&0x3) * ((APB_CLK_FREQ>>4)/1000000)) : \
(((t) *(APB_CLK_FREQ>>4)) / 1000000)) : \
0)
#endif
typedef
enum
{
FRC1_SOURCE
=
0
,
NMI_SOURCE
=
1
,
}
FRC1_TIMER_SOURCE_TYPE
;
bool
ICACHE_RAM_ATTR
platform_hw_timer_arm_ticks
(
os_param_t
owner
,
uint32_t
ticks
);
bool
ICACHE_RAM_ATTR
platform_hw_timer_arm_us
(
os_param_t
owner
,
uint32_t
microseconds
);
bool
platform_hw_timer_set_func
(
os_param_t
owner
,
void
(
*
user_hw_timer_cb_set
)(
os_param_t
),
os_param_t
arg
);
bool
platform_hw_timer_init
(
os_param_t
owner
,
FRC1_TIMER_SOURCE_TYPE
source_type
,
bool
autoload
);
bool
ICACHE_RAM_ATTR
platform_hw_timer_close
(
os_param_t
owner
);
uint32_t
ICACHE_RAM_ATTR
platform_hw_timer_get_delay_ticks
(
os_param_t
owner
);
#endif
app/platform/platform.c
View file @
669543bb
...
...
@@ -402,7 +402,9 @@ uint32_t platform_pwm_setup( unsigned pin, uint32_t frequency, unsigned duty )
return
0
;
}
clock
=
platform_pwm_get_clock
(
pin
);
pwm_start
();
if
(
!
pwm_start
())
{
return
0
;
}
return
clock
;
}
...
...
@@ -416,16 +418,18 @@ void platform_pwm_close( unsigned pin )
}
}
void
platform_pwm_start
(
unsigned
pin
)
bool
platform_pwm_start
(
unsigned
pin
)
{
// NODE_DBG("Function platform_pwm_start() is called.\n");
if
(
pin
<
NUM_PWM
)
{
if
(
!
pwm_exist
(
pin
))
return
;
return
FALSE
;
pwm_set_duty
(
DUTY
(
pwms_duty
[
pin
]),
pin
);
pwm_start
();
return
pwm_start
();
}
return
FALSE
;
}
void
platform_pwm_stop
(
unsigned
pin
)
...
...
app/platform/platform.h
View file @
669543bb
...
...
@@ -166,7 +166,7 @@ void platform_uart_alt( int set );
static
inline
int
platform_pwm_exists
(
unsigned
id
)
{
return
((
id
<
NUM_PWM
)
&&
(
id
>
0
));
}
uint32_t
platform_pwm_setup
(
unsigned
id
,
uint32_t
frequency
,
unsigned
duty
);
void
platform_pwm_close
(
unsigned
id
);
void
platform_pwm_start
(
unsigned
id
);
bool
platform_pwm_start
(
unsigned
id
);
void
platform_pwm_stop
(
unsigned
id
);
uint32_t
platform_pwm_set_clock
(
unsigned
id
,
uint32_t
data
);
uint32_t
platform_pwm_get_clock
(
unsigned
id
);
...
...
sdk-overrides/include/osapi.h
View file @
669543bb
...
...
@@ -8,6 +8,8 @@ int atoi(const char *nptr);
int
os_printf
(
const
char
*
format
,
...)
__attribute__
((
format
(
printf
,
1
,
2
)));
int
os_printf_plus
(
const
char
*
format
,
...)
__attribute__
((
format
(
printf
,
1
,
2
)));
void
NmiTimSetFunc
(
void
(
*
func
)(
void
));
#include_next "osapi.h"
#endif
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment