Skip to content

Commit

Permalink
Merge pull request #13489 from rajkan01/hal_directory_restructuring
Browse files Browse the repository at this point in the history
Refactor hal directory
  • Loading branch information
0xc0170 committed Sep 2, 2020
2 parents 29f54fe + fafa0c4 commit 9073a48
Show file tree
Hide file tree
Showing 147 changed files with 1,050 additions and 5 deletions.
4 changes: 2 additions & 2 deletions .codecheckignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
^storage/filesystem/littlefsv2/littlefs/
^features/unsupported/
^hal/storage_abstraction
^hal/tests/TESTS/mbed_hal/trng/pithy
^hal/tests/TESTS/mbed_hal/trng/pithy
^platform/cxxsupport
^platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV
^platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM
Expand All @@ -25,8 +27,6 @@
^rtos/source/TARGET_CORTEX/rtx4
^rtos/source/TARGET_CORTEX/rtx5
^targets
^TESTS/mbed_hal/trng/pithy
^TESTS/mbed_hal/trng/pithy
^tools
^UNITTESTS
^storage/blockdevice/tests/UNITTESTS
Expand Down
1 change: 1 addition & 0 deletions UNITTESTS/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ set(unittest-includes-base
"${PROJECT_SOURCE_DIR}/../drivers/include/drivers"
"${PROJECT_SOURCE_DIR}/../drivers/include/drivers/internal"
"${PROJECT_SOURCE_DIR}/../hal"
"${PROJECT_SOURCE_DIR}/../hal/include"
"${PROJECT_SOURCE_DIR}/../events/include"
"${PROJECT_SOURCE_DIR}/../events/include/events/internal"
"${PROJECT_SOURCE_DIR}/../events/source"
Expand Down
2 changes: 1 addition & 1 deletion UNITTESTS/stubs/us_ticker_stub.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@


#include "stdlib.h"
#include "us_ticker_api.h"
#include "hal/us_ticker_api.h"

const ticker_data_t *get_us_ticker_data(void)
{
Expand Down
2 changes: 1 addition & 1 deletion UNITTESTS/stubs/watchdog_api_stub.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "watchdog_api.h"
#include "hal/watchdog_api.h"

#if DEVICE_WATCHDOG

Expand Down
2 changes: 1 addition & 1 deletion UNITTESTS/target_h/PinNames.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,6 @@ typedef enum {
#ifdef __cplusplus
}
#endif
#include "pinmap.h"
#include "hal/pinmap.h"

#endif
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
181 changes: 181 additions & 0 deletions hal/tests/TESTS/host_tests/reset_reason.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
"""
Copyright (c) 2018-2019 Arm Limited and affiliates.
SPDX-License-Identifier: Apache-2.0
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.
"""
import time
from mbed_host_tests import BaseHostTest

DEFAULT_SYNC_DELAY = 4.0

MSG_VALUE_WATCHDOG_PRESENT = 1
MSG_VALUE_DUMMY = '0'
MSG_VALUE_RESET_REASON_GET = 'get'
MSG_VALUE_RESET_REASON_CLEAR = 'clear'
MSG_VALUE_DEVICE_RESET_NVIC = 'nvic'
MSG_VALUE_DEVICE_RESET_WATCHDOG = 'watchdog'

MSG_KEY_DEVICE_READY = 'ready'
MSG_KEY_RESET_REASON_RAW = 'reason_raw'
MSG_KEY_RESET_REASON = 'reason'
MSG_KEY_DEVICE_RESET = 'reset'
MSG_KEY_SYNC = '__sync'
MSG_KEY_RESET_COMPLETE = 'reset_complete'

RESET_REASONS = {
'POWER_ON': '0',
'PIN_RESET': '1',
'BROWN_OUT': '2',
'SOFTWARE': '3',
'WATCHDOG': '4',
'LOCKUP': '5',
'WAKE_LOW_POWER': '6',
'ACCESS_ERROR': '7',
'BOOT_ERROR': '8',
'MULTIPLE': '9',
'PLATFORM': '10',
'UNKNOWN': '11'
}


def raise_if_different(expected, actual, text=''):
"""Raise a RuntimeError if actual is different than expected."""
if expected != actual:
raise RuntimeError('{}Got {!r}, expected {!r}'
.format(text, actual, expected))


class ResetReasonTest(BaseHostTest):
"""Test for the Reset Reason HAL API.
Given a device supporting a Reset Reason API.
When the device is restarted using various methods.
Then the device returns a correct reset reason for every restart.
"""

def __init__(self):
super(ResetReasonTest, self).__init__()
self.device_reasons = None
self.device_has_watchdog = None
self.raw_reset_reasons = set()
self.sync_delay = DEFAULT_SYNC_DELAY
self.test_steps_sequence = self.test_steps()
# Advance the coroutine to it's first yield statement.
self.test_steps_sequence.send(None)

def setup(self):
sync_delay = self.get_config_item('forced_reset_timeout')
self.sync_delay = sync_delay if sync_delay is not None else DEFAULT_SYNC_DELAY
self.register_callback(MSG_KEY_DEVICE_READY, self.cb_device_ready)
self.register_callback(MSG_KEY_RESET_REASON_RAW, self.cb_reset_reason_raw)
self.register_callback(MSG_KEY_RESET_REASON, self.cb_reset_reason)
self.register_callback(MSG_KEY_DEVICE_RESET, self.cb_reset_reason)
self.register_callback(MSG_KEY_RESET_COMPLETE, self.cb_reset_reason)

def cb_device_ready(self, key, value, timestamp):
"""Request a raw value of the reset_reason register.
Additionally, save the device's reset_reason capabilities
and the watchdog status on the first call.
"""
if self.device_reasons is None:
reasons, wdg_status = (int(i, base=16) for i in value.split(','))
self.device_has_watchdog = (wdg_status == MSG_VALUE_WATCHDOG_PRESENT)
self.device_reasons = [k for k, v in RESET_REASONS.items() if (reasons & 1 << int(v))]
self.send_kv(MSG_KEY_RESET_REASON_RAW, MSG_VALUE_RESET_REASON_GET)

def cb_reset_reason_raw(self, key, value, timestamp):
"""Verify that the raw reset_reason register value is unique.
Fail the test suite if the raw reset_reason value is not unique.
Request a platform independent reset_reason otherwise.
"""
if value in self.raw_reset_reasons:
self.log('TEST FAILED: The raw reset reason is not unique. '
'{!r} is already present in {!r}.'
.format(value, self.raw_reset_reasons))
self.notify_complete(False)
else:
self.raw_reset_reasons.add(value)
self.send_kv(MSG_KEY_RESET_REASON, MSG_VALUE_RESET_REASON_GET)

def cb_reset_reason(self, key, value, timestamp):
"""Feed the test_steps coroutine with reset_reason value.
Pass the test suite if the coroutine yields True.
Fail the test suite if the iterator stops or raises a RuntimeError.
"""
try:
if self.test_steps_sequence.send(value):
self.notify_complete(True)
except (StopIteration, RuntimeError) as exc:
self.log('TEST FAILED: {}'.format(exc))
self.notify_complete(False)

def test_steps(self):
"""Generate a sequence of test steps.
This coroutine calls yield to wait for the input from the device
(the reset_reason). If the device gives the wrong response, the
generator raises a RuntimeError exception and fails the test.
"""
# Ignore the first reason.
__ignored_reset_reason = yield
self.raw_reset_reasons.clear()
self.send_kv(MSG_KEY_RESET_REASON, MSG_VALUE_RESET_REASON_CLEAR)
__ignored_clear_ack = yield

# Request a NVIC_SystemReset() call.
expected_reason = 'SOFTWARE'
if expected_reason not in self.device_reasons:
self.log('Skipping the {} reset reason -- not supported.'.format(expected_reason))
else:
# Request a NVIC_SystemReset() call.
self.send_kv(MSG_KEY_DEVICE_RESET, MSG_VALUE_DEVICE_RESET_NVIC)
__ignored_reset_ack = yield
time.sleep(self.sync_delay)
self.send_kv(MSG_KEY_SYNC, MSG_VALUE_DUMMY)
reset_reason = yield
raise_if_different(RESET_REASONS[expected_reason], reset_reason, 'Wrong reset reason. ')
self.send_kv(MSG_KEY_RESET_REASON, MSG_VALUE_RESET_REASON_CLEAR)
__ignored_clear_ack = yield

# Reset the device using DAP.
expected_reason = 'PIN_RESET'
if expected_reason not in self.device_reasons:
self.log('Skipping the {} reset reason -- not supported.'.format(expected_reason))
else:
self.reset()
__ignored_reset_ack = yield # 'reset_complete'
time.sleep(self.sync_delay)
self.send_kv(MSG_KEY_SYNC, MSG_VALUE_DUMMY)
reset_reason = yield
raise_if_different(RESET_REASONS[expected_reason], reset_reason, 'Wrong reset reason. ')
self.send_kv(MSG_KEY_RESET_REASON, MSG_VALUE_RESET_REASON_CLEAR)
__ignored_clear_ack = yield

# Start a watchdog timer and wait for it to reset the device.
expected_reason = 'WATCHDOG'
if expected_reason not in self.device_reasons or not self.device_has_watchdog:
self.log('Skipping the {} reset reason -- not supported.'.format(expected_reason))
else:
self.send_kv(MSG_KEY_DEVICE_RESET, MSG_VALUE_DEVICE_RESET_WATCHDOG)
__ignored_reset_ack = yield
time.sleep(self.sync_delay)
self.send_kv(MSG_KEY_SYNC, MSG_VALUE_DUMMY)
reset_reason = yield
raise_if_different(RESET_REASONS[expected_reason], reset_reason, 'Wrong reset reason. ')

# The sequence is correct -- test passed.
yield True
140 changes: 140 additions & 0 deletions hal/tests/TESTS/host_tests/rtc_calc_auto.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
"""
Copyright (c) 2011-2020, Arm Limited and affiliates
SPDX-License-Identifier: Apache-2.0
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.
"""

from mbed_host_tests import BaseHostTest
import time
import calendar
import datetime

class RTC_time_calc_test(BaseHostTest):
"""
This is the host part of the test to verify if:
- _rtc_mktime function converts a calendar time into time since UNIX epoch as a time_t,
- _rtc_localtime function converts a given time in seconds since epoch into calendar time.
The same algoritm to generate next calendar time to be tested is used by both parts of the test.
We will check if correct time since UNIX epoch is calculated for the first and the last day
of each month and across valid years.
Mbed part of the test sends calculated time since UNIX epoch.
This part validates given value and responds to indicate pass or fail.
Additionally it sends also encoded day of week and day of year which
will be needed to verify _rtc_localtime.
Support for both types of RTC devices is provided:
- RTCs which handles all leap years in the mentioned year range correctly. Leap year is determined by checking if
the year counter value is divisible by 400, 100, and 4. No problem here.
- RTCs which handles leap years correctly up to 2100. The RTC does a simple bit comparison to see if the two
lowest order bits of the year counter are zero. In this case 2100 year will be considered
incorrectly as a leap year, so the last valid point in time will be 28.02.2100 23:59:59 and next day will be
29.02.2100 (invalid). So after 28.02.2100 the day counter will be off by a day.
"""

edge_date = datetime.datetime(2100, 2, 28, 0, 0, 0)

# Test the following years:
# - first - 1970
# - example not leap year (not divisible by 4)
# - example leap year (divisible by 4 and by 100 and by 400)
# - example leap year (divisible by 4 and not by 100)
# - example not leap year (divisible by 4 and by 100)
# - last fully supported - 2105
years = [1970, 1971, 2000, 2096, 2100, 2105]
year_id = 0



full_leap_year_support = False

RTC_FULL_LEAP_YEAR_SUPPORT = 0
RTC_PARTIAL_LEAP_YEAR_SUPPORT = 1

def _set_leap_year_support(self, key, value, timestamp):
if (int(value) == self.RTC_FULL_LEAP_YEAR_SUPPORT):
self.full_leap_year_support = True
else:
self.full_leap_year_support = False

self.first = True
self.date = datetime.datetime(1970, 1, 1, 23, 0, 0)
self.year_id = 0

def _verify_timestamp(self, key, value, timestamp):
# week day in python is counted from sunday(0) and on mbed side week day is counted from monday(0).
# year day in python is counted from 1 and on mbed side year day is counted from 0.
week_day = ((self.date.timetuple().tm_wday + 1) % 7)
year_day = self.date.timetuple().tm_yday - 1

# Fix for RTC which not have full leap year support.
if (not self.full_leap_year_support):
if self.date >= self.edge_date:
# After 28.02.2100 we should be one day off - add this day and store original
date_org = self.date
self.date += datetime.timedelta(days = 1)

# Adjust week day.
week_day = ((self.date.timetuple().tm_wday + 1) % 7)

# Adjust year day.
if (self.date.year == 2100):
year_day = self.date.timetuple().tm_yday - 1
else:
year_day = date_org.timetuple().tm_yday - 1

# Last day in year
if (self.date.month == 1 and self.date.day == 1):
if (self.date.year == 2101):
# Exception for year 2100 - ivalid handled by RTC without full leap year support
year_day = 365
else:
year_day = date_org.timetuple().tm_yday - 1

t = (self.date.year , self.date.month, self.date.day, self.date.hour, self.date.minute, self.date.second, 0, 0, 0)

expected_timestamp = calendar.timegm(t)
actual_timestamp = int(value) & 0xffffffff # convert to unsigned int

# encode week day and year day in the response
response = (week_day << 16) | year_day

if (actual_timestamp == expected_timestamp):
# response contains encoded week day and year day
self.send_kv("passed", str(response))
else:
self.send_kv("failed", 0)
print("expected = %d, result = %d" % (expected_timestamp , actual_timestamp))

# calculate next date
if (self.first):
days_range = calendar.monthrange(self.date.year, self.date.month)
self.date = self.date.replace(day = days_range[1], minute = 59, second = 59)
self.first = not self.first
else:
self.date += datetime.timedelta(days = 1)
if (self.date.month == 1):
self.year_id += 1
if (len(self.years) == self.year_id):
# All years were processed, no need to calc next date
return
self.date = self.date.replace(year = self.years[self.year_id])
self.date = self.date.replace(day = 1, minute = 0, second = 0)
self.first = not self.first

def setup(self):
self.register_callback('timestamp', self._verify_timestamp)
self.register_callback('leap_year_setup', self._set_leap_year_support)

0 comments on commit 9073a48

Please sign in to comment.