1 /***************************************************************************//**
2 * \file cybt_platform_freertos.c
3 *
4 * \brief
5 * Implementation for BT porting interface on FreeRTOS
6 *
7 ********************************************************************************
8 * \copyright
9 * Copyright 2018-2019 Cypress Semiconductor Corporation
10 * SPDX-License-Identifier: Apache-2.0
11 *
12 * Licensed under the Apache License, Version 2.0 (the "License");
13 * you may not use this file except in compliance with the License.
14 * You may obtain a copy of the License at
15 *
16 * http://www.apache.org/licenses/LICENSE-2.0
17 *
18 * Unless required by applicable law or agreed to in writing, software
19 * distributed under the License is distributed on an "AS IS" BASIS,
20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 * See the License for the specific language governing permissions and
22 * limitations under the License.
23 *******************************************************************************/
24 #include "cyabs_rtos.h"
25 #include "cyhal_lptimer.h"
26 #include "cycfg.h"
27 #include "cybt_platform_task.h"
28 #include "cybt_platform_interface.h"
29 #include "cybt_platform_trace.h"
30 #include "cybt_platform_internal.h"
31
32 /******************************************************************************
33 * Constants
34 ******************************************************************************/
35 #define NOT_IN_ISR (false)
36 #define IN_ISR (true)
37 #define ENABLE_EVENT (true)
38 #define DISABLE_EVENT (false)
39
40 /*****************************************************************************
41 * Type Definitions
42 *****************************************************************************/
43
44
45 /******************************************************************************
46 * Variables Definitions
47 ******************************************************************************/
48 #ifdef DISABLE_LPTIMER
49 static cy_timer_t stack_timer;
50 #else
51 static cyhal_lptimer_t stack_timer;
52 #endif
53
54 /******************************************************************************
55 * Function Declarations
56 ******************************************************************************/
57 extern cybt_result_t cybt_platform_msg_to_bt_task(const uint16_t msg, bool is_from_isr);
58
59 /******************************************************************************
60 * Function Definitions
61 ******************************************************************************/
cybt_platform_get_tick_count_us(void)62 uint64_t cybt_platform_get_tick_count_us(void)
63 {
64 #ifdef DISABLE_LPTIMER
65 static cy_time_t last_time_in_ms = 0;
66 static uint64_t abs_time_cnt_in_us_hi = 0;
67 cy_time_t cur_time_in_ms;
68 uint64_t cur_time_in_ms64 = 0;
69 uint64_t cur_time_in_us64 = 0;
70
71 cy_rtos_get_time(&cur_time_in_ms);
72
73 if(cur_time_in_ms < last_time_in_ms)
74 {
75 abs_time_cnt_in_us_hi += 0x100000000;
76 }
77
78 last_time_in_ms = cur_time_in_ms;
79
80 cur_time_in_ms64 = cur_time_in_ms + abs_time_cnt_in_us_hi;
81 cur_time_in_us64 = (cur_time_in_ms64 * 1000);
82 return (cur_time_in_us64);
83 #else
84 static uint64_t abs_tick_cnt_hi = 0;
85 static uint32_t last_tick_cnt = 0;
86 static uint64_t lptick_remainder = 0;
87
88 uint32_t cur_time_in_lpticks = 0;
89 uint64_t cur_time_in_lpticks64 = 0;
90 uint64_t cur_time_in_us = 0;
91 uint64_t temp_cnt64 = 0;
92
93 cur_time_in_lpticks = cyhal_lptimer_read(&stack_timer);
94
95 if (cur_time_in_lpticks < last_tick_cnt)
96 {
97 abs_tick_cnt_hi += 0x100000000;
98 }
99
100 last_tick_cnt = cur_time_in_lpticks;
101 cur_time_in_lpticks64 = cur_time_in_lpticks + abs_tick_cnt_hi;
102
103 // convert tick to us
104 temp_cnt64 = cur_time_in_lpticks64 * 1000000;
105 cur_time_in_us = temp_cnt64 / CY_CFG_SYSCLK_CLKLF_FREQ_HZ;
106
107 lptick_remainder += temp_cnt64 - (cur_time_in_us * CY_CFG_SYSCLK_CLKLF_FREQ_HZ);
108 if(lptick_remainder > CY_CFG_SYSCLK_CLKLF_FREQ_HZ)
109 {
110 cur_time_in_us += 1;
111 lptick_remainder -= CY_CFG_SYSCLK_CLKLF_FREQ_HZ;
112 }
113
114 return cur_time_in_us;
115 #endif
116 }
117
cybt_platform_set_next_timeout(uint64_t abs_tick_us_to_expire)118 void cybt_platform_set_next_timeout(uint64_t abs_tick_us_to_expire)
119 {
120 uint64_t curr_time_in_us = cybt_platform_get_tick_count_us();
121 uint64_t time_to_expire_in_us = abs_tick_us_to_expire - curr_time_in_us;
122
123 if(abs_tick_us_to_expire <= curr_time_in_us)
124 {
125 cybt_platform_msg_to_bt_task(BT_EVT_TIMEOUT, NOT_IN_ISR);
126 return;
127 }
128 #ifdef DISABLE_LPTIMER
129 {
130 cy_rslt_t result;
131 cy_time_t next_timeout = (cy_time_t)(time_to_expire_in_us/1000);
132
133 /* No need to stop this timer, internally FREE-RTOS restarting the timer
134 * Leaving reminder (~1ms), Its ok verified */
135 result = cy_rtos_start_timer(&stack_timer, next_timeout);
136 if(CY_RSLT_SUCCESS != result)
137 {
138 MAIN_TRACE_DEBUG("timer failed to start %u\n", next_timeout);
139 }
140 }
141 #else
142 {
143 uint32_t time_to_expire_in_lpticks;
144
145 // convert us to tick
146 time_to_expire_in_lpticks = ((time_to_expire_in_us * CY_CFG_SYSCLK_CLKLF_FREQ_HZ) + 1000000 - 1) / 1000000;
147
148 cyhal_lptimer_enable_event(&stack_timer, CYHAL_LPTIMER_COMPARE_MATCH, CYHAL_ISR_PRIORITY_DEFAULT, ENABLE_EVENT);
149 cyhal_lptimer_set_delay(&stack_timer, time_to_expire_in_lpticks);
150 }
151 #endif
152 }
153
154 #ifndef DISABLE_LPTIMER
platform_stack_lptimer_cback(void * callback_arg,cyhal_lptimer_event_t event)155 static void platform_stack_lptimer_cback(void *callback_arg, cyhal_lptimer_event_t event)
156 #else
157 static void platform_stack_timer_callback(cy_timer_callback_arg_t arg)
158 #endif
159 {
160 #ifdef DISABLE_LPTIMER
161 /* Will be called from TmrSVC rtos thread context and not from ISR context */
162 cybt_platform_msg_to_bt_task(BT_EVT_TIMEOUT, NOT_IN_ISR);
163 #else
164 cyhal_lptimer_enable_event(&stack_timer, CYHAL_LPTIMER_COMPARE_MATCH, CYHAL_ISR_PRIORITY_DEFAULT, DISABLE_EVENT);
165 cybt_platform_msg_to_bt_task(BT_EVT_TIMEOUT, IN_ISR);
166 #endif
167 }
168
cybt_platform_stack_timer_init(void)169 void cybt_platform_stack_timer_init(void)
170 {
171 #ifdef DISABLE_LPTIMER
172 cy_rtos_init_timer(&stack_timer, CY_TIMER_TYPE_ONCE, platform_stack_timer_callback, (cy_timer_callback_arg_t)NULL);
173 #else
174 cyhal_lptimer_init(&stack_timer);
175 cyhal_lptimer_enable_event(&stack_timer, CYHAL_LPTIMER_COMPARE_MATCH, CYHAL_ISR_PRIORITY_DEFAULT, DISABLE_EVENT);
176 cyhal_lptimer_register_callback(&stack_timer, &platform_stack_lptimer_cback, NULL);
177 #endif
178 }
179
cybt_platform_stack_timer_deinit(void)180 void cybt_platform_stack_timer_deinit(void)
181 {
182 #ifdef DISABLE_LPTIMER
183 cy_rtos_deinit_timer(&stack_timer);
184 #else
185 cyhal_lptimer_free(&stack_timer);
186 #endif
187 }
188